History

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

[airlied: add two missing Kconfig] drm-misc-next for v5.18: UAPI Changes: - Fix invalid IN_FORMATS blob when plane->format_mod_supported is NULL. Cross-subsystem Changes: - Assorted dt bindings updates. - Fix vga16fb vga checking on x86. - Fix extra semicolon in rwsem.h's _down_write_nest_lock. - Assorted small fixes to agp and fbdev drivers. - Fix oops in creating a udmabuf with 0 pages. - Hot-unplug firmware fb devices on forced removal - Reqquest memory region in simplefb and simpledrm, and don't make the ioresource as busy. Core Changes: - Mock a drm_plane in drm-plane-helper selftest. - Assorted bug fixes to device logging, dbi. - Use DP helper for sink count in mst. - Assorted documentation fixes. - Assorted small fixes. - Move DP headers to drm/dp, and add a drm dp helper module. - Move the buddy allocator from i915 to common drm. - Add simple pci and platform module init macros to remove a lot of boilerplate from some drivers. - Support microsoft extension for HMDs and specialized monitors. - Improve edid parser's deep color handling. - Add type 7 timing support to edid parser. - Add a weak backpointer to the ttm_bo from ttm_resource - Add 3 eDP panels. Driver Changes: - Add support for HDMI and JZ4780 to ingenic. - Add support for higher DP/eDP bitrates to nouveau. - Assorted driver fixes to tilcdc, vmwgfx, sn65dsi83, meson, stm, panfrost, v3d, gma500, vc4, virtio, mgag200, ast, radeon, amdgpu, nouveau, various bridge drivers. - Convert and revert exynos dsi support to bridge driver. - Add vcc supply regulator support for sn65dsi83. - More conversion of bridge/chipone-icn6211 to atomic. - Remove conflicting fb's from stm, and add support for new hw version. - Add device link in parade-ps8640 to fix suspend/resume. - Update Boe-tv110c9m init sequence. - Add wide screen support to AST2600. - Fix omapdrm implicit dma_buf fencing. - Add support for multiple overlay planes to vkms. - Convert bridge/anx7625 to atomic, add HDCP support, add eld support for audio, and fix HPD. - Add driver for ChromeOS privacy screen. - Handover display from firmware to vc4 more gracefully, and support nomodeset. - Add flexible and ycbcr pixel formats to stm/ltdc. - Convert exynos mipi dsi to atomic. - Add initial dual core group GPUs support to panfrost. - No longer add exclusive fence in amdgpu as shared fence. - Add CSC and full range supoprt to vc4. - Shutdown the display on system shutdown and unbind. - Add Multi-Inno Technology MI0700S4T-6 simple panel. Signed-off-by: Dave Airlie <airlied@redhat.com>

Dave Airlie committed 4 years ago

Commit 53dbee42 parents 26291c5 a5d092d233 files · +5377 −2613Browse files

Unified · Split

233 files
  1. Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml +1 −0
  2. Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml +4 −1
  3. Documentation/devicetree/bindings/display/panel/panel-simple.yaml +2 −0
  4. Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml +9 −2
  5. Documentation/gpu/drm-internals.rst +6 −0
  6. Documentation/gpu/drm-kms-helpers.rst +13 −13
  7. Documentation/gpu/drm-kms.rst +3 −3
  8. Documentation/gpu/drm-mm.rst +1 −1
  9. Documentation/gpu/todo.rst +15 −0
  10. Documentation/gpu/vkms.rst +0 −2
  11. drivers/char/agp/ati-agp.c +6 −2
  12. drivers/char/agp/backend.c +2 −0
  13. drivers/char/agp/frontend.c +3 −1
  14. drivers/char/agp/nvidia-agp.c +2 −1
  15. drivers/char/agp/sworks-agp.c +1 −4
  16. drivers/char/agp/via-agp.c +0 −3
  17. drivers/dma-buf/dma-resv.c +17 −29
  18. drivers/dma-buf/st-dma-resv.c +5 −21
  19. drivers/dma-buf/udmabuf.c +4 −0
  20. drivers/firmware/sysfb_simplefb.c +1 −1
  21. drivers/gpu/drm/Kconfig +15 −0
  22. drivers/gpu/drm/Makefile +6 −8
  23. drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +2 −2
  24. drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +1 −4
  25. drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +4 −2
  26. drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +0 −6
  27. drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +4 −1
  28. drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +1 −1
  29. drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +2 −2
  30. drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c +2 −1
  31. drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +5 −5
  32. drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +4 −1
  33. drivers/gpu/drm/amd/amdgpu/atombios_dp.c +1 −1
  34. drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +2 −2
  35. drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +1 −1
  36. drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +2 −2
  37. drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c +1 −1
  38. drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +1 −1
  39. drivers/gpu/drm/amd/display/dc/os_types.h +1 −1
  40. drivers/gpu/drm/amd/display/include/dpcd_defs.h +1 −1
  41. drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +1 −1
  42. drivers/gpu/drm/arm/display/komeda/d71/d71_component.c +6 −6
  43. drivers/gpu/drm/arm/display/komeda/komeda_drv.c +2 −1
  44. drivers/gpu/drm/arm/hdlcd_drv.c +2 −1
  45. drivers/gpu/drm/arm/malidp_drv.c +2 −1
  46. drivers/gpu/drm/ast/ast_drv.c +2 −16
  47. drivers/gpu/drm/ast/ast_main.c +2 −0
  48. drivers/gpu/drm/ast/ast_mode.c +4 −1
  49. drivers/gpu/drm/bridge/Kconfig +5 −0
  50. drivers/gpu/drm/bridge/adv7511/adv7511.h +1 −0
  51. drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +23 −8
  52. drivers/gpu/drm/bridge/adv7511/adv7533.c +1 −1
  53. drivers/gpu/drm/bridge/analogix/Kconfig +2 −0
  54. drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +1 −1
  55. drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +1 −1
  56. drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c +1 −1
  57. drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +2 −2
  58. drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +1 −1
  59. drivers/gpu/drm/bridge/analogix/anx7625.c +421 −19
  60. drivers/gpu/drm/bridge/analogix/anx7625.h +73 −7
  61. drivers/gpu/drm/bridge/cadence/Kconfig +1 −0
  62. drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +10 −10
  63. drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h +1 −1
  64. drivers/gpu/drm/bridge/chipone-icn6211.c +26 −13
  65. drivers/gpu/drm/bridge/ite-it66121.c +0 −3
  66. drivers/gpu/drm/bridge/lontium-lt9611.c +2 −2
  67. drivers/gpu/drm/bridge/lontium-lt9611uxc.c +2 −2
  68. drivers/gpu/drm/bridge/nwl-dsi.c +3 −5
  69. drivers/gpu/drm/bridge/parade-ps8640.c +28 −5
  70. drivers/gpu/drm/bridge/sii902x.c +99 −30
  71. drivers/gpu/drm/bridge/sil-sii8620.c +1 −1
  72. drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +8 −8
  73. drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +17 −8
  74. drivers/gpu/drm/bridge/tc358767.c +1 −1
  75. drivers/gpu/drm/bridge/tc358775.c +2 −2
  76. drivers/gpu/drm/bridge/ti-sn65dsi83.c +43 −10
  77. drivers/gpu/drm/bridge/ti-sn65dsi86.c +2 −2
  78. drivers/gpu/drm/dp/Makefile +9 −0
  79. drivers/gpu/drm/dp/drm_dp.c +3 −3
  80. drivers/gpu/drm/dp/drm_dp_aux_bus.c +2 −2
  81. drivers/gpu/drm/dp/drm_dp_aux_dev.c +3 −3
  82. drivers/gpu/drm/dp/drm_dp_cec.c +1 −1
  83. drivers/gpu/drm/dp/drm_dp_dual_mode_helper.c +1 −1
  84. drivers/gpu/drm/dp/drm_dp_helper_internal.h +33 −0
  85. drivers/gpu/drm/dp/drm_dp_helper_mod.c +22 −0
  86. drivers/gpu/drm/dp/drm_dp_mst_topology.c +4 −4
  87. drivers/gpu/drm/dp/drm_dp_mst_topology_internal.h +1 −1
  88. drivers/gpu/drm/drm_buddy.c +535 −0
  89. drivers/gpu/drm/drm_color_mgmt.c +4 −0
  90. drivers/gpu/drm/drm_crtc_helper_internal.h +0 −27
  91. drivers/gpu/drm/drm_dsc.c +1 −1
  92. drivers/gpu/drm/drm_edid.c +68 −36
  93. drivers/gpu/drm/drm_kms_helper_common.c +0 −14
  94. drivers/gpu/drm/drm_plane.c +2 −7
  95. drivers/gpu/drm/drm_privacy_screen.c +4 −1
  96. drivers/gpu/drm/drm_privacy_screen_x86.c +17 −0
  97. drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +1 −2
  98. drivers/gpu/drm/exynos/Kconfig +1 −0
  99. drivers/gpu/drm/exynos/exynos_drm_dsi.c +12 −1
  100. drivers/gpu/drm/gma500/cdv_intel_dp.c +4 −10
  101. drivers/gpu/drm/gma500/gma_display.c +2 −4
  102. drivers/gpu/drm/gma500/intel_bios.c +1 −1
  103. drivers/gpu/drm/gma500/mmu.c +4 −4
  104. drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +2 −1
  105. drivers/gpu/drm/i915/Kconfig +2 −0
  106. drivers/gpu/drm/i915/Makefile +0 −1
  107. drivers/gpu/drm/i915/display/intel_bios.c +1 −1
  108. drivers/gpu/drm/i915/display/intel_display.c +1 −1
  109. drivers/gpu/drm/i915/display/intel_display_types.h +2 −2
  110. drivers/gpu/drm/i915/display/intel_dp.c +1 −1
  111. drivers/gpu/drm/i915/display/intel_dp_hdcp.c +2 −2
  112. drivers/gpu/drm/i915/display/intel_dp_link_training.h +1 −1
  113. drivers/gpu/drm/i915/display/intel_hdmi.c +3 −3
  114. drivers/gpu/drm/i915/display/intel_lspcon.c +2 −2
  115. drivers/gpu/drm/i915/i915_buddy.c +0 −466
  116. drivers/gpu/drm/i915/i915_buddy.h +0 −143
  117. drivers/gpu/drm/i915/i915_module.c +0 −3
  118. drivers/gpu/drm/i915/i915_scatterlist.c +5 −6
  119. drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +20 −17
  120. drivers/gpu/drm/i915/i915_ttm_buddy_manager.h +2 −2
  121. drivers/gpu/drm/i915/selftests/i915_buddy.c +0 −787
  122. drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +0 −1
  123. drivers/gpu/drm/i915/selftests/intel_memory_region.c +7 −6
  124. drivers/gpu/drm/imx/dcss/dcss-drv.c +2 −1
  125. drivers/gpu/drm/ingenic/ingenic-drm-drv.c +59 −3
  126. drivers/gpu/drm/ingenic/ingenic-drm.h +38 −0
  127. drivers/gpu/drm/meson/meson_drv.c +13 −12
  128. drivers/gpu/drm/meson/meson_osd_afbcd.c +27 −14
  129. drivers/gpu/drm/meson/meson_osd_afbcd.h +1 −0
  130. drivers/gpu/drm/mgag200/mgag200_mode.c +4 −1
  131. drivers/gpu/drm/msm/Kconfig +1 −0
  132. drivers/gpu/drm/msm/dp/dp_audio.c +1 −1
  133. drivers/gpu/drm/msm/dp/dp_aux.h +1 −1
  134. drivers/gpu/drm/msm/dp/dp_catalog.c +1 −1
  135. drivers/gpu/drm/msm/dp/dp_ctrl.c +1 −1
  136. drivers/gpu/drm/msm/edp/edp.h +77 −0
  137. drivers/gpu/drm/msm/edp/edp_ctrl.c +1373 −0
  138. drivers/gpu/drm/mxsfb/mxsfb_drv.c +9 −0
  139. drivers/gpu/drm/nouveau/Kconfig +1 −0
  140. drivers/gpu/drm/nouveau/dispnv50/disp.c +1 −1
  141. drivers/gpu/drm/nouveau/nouveau_connector.h +1 −1
  142. drivers/gpu/drm/nouveau/nouveau_dp.c +16 −1
  143. drivers/gpu/drm/nouveau/nouveau_encoder.h +2 −2
  144. drivers/gpu/drm/nouveau/nouveau_mem.c +2 −1
  145. drivers/gpu/drm/nouveau/nouveau_mem.h +2 −1
  146. drivers/gpu/drm/nouveau/nouveau_ttm.c +7 −6
  147. drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +224 −93
  148. drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h +29 −6
  149. drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +12 −1
  150. drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c +4 −0
  151. drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +13 −1
  152. drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +15 −3
  153. drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c +5 −4
  154. drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +1 −0
  155. drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +4 −4
  156. drivers/gpu/drm/panel/panel-edp.c +19 −2
  157. drivers/gpu/drm/panel/panel-samsung-atna33xc20.c +2 −2
  158. drivers/gpu/drm/panel/panel-simple.c +33 −0
  159. drivers/gpu/drm/panfrost/panfrost_features.h +7 −205
  160. drivers/gpu/drm/panfrost/panfrost_gpu.c +26 −6
  161. drivers/gpu/drm/radeon/atombios_dp.c +1 −1
  162. drivers/gpu/drm/radeon/radeon_connectors.c +2 −2
  163. drivers/gpu/drm/radeon/radeon_dp_mst.c +1 −1
  164. drivers/gpu/drm/radeon/radeon_mode.h +2 −2
  165. drivers/gpu/drm/radeon/radeon_ttm.c +2 −2
  166. drivers/gpu/drm/rockchip/Kconfig +2 −0
  167. drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +2 −2
  168. drivers/gpu/drm/rockchip/cdn-dp-core.c +1 −1
  169. drivers/gpu/drm/rockchip/cdn-dp-core.h +1 −1
  170. drivers/gpu/drm/rockchip/rockchip_lvds.c +1 −1
  171. drivers/gpu/drm/rockchip/rockchip_rgb.c +1 −1
  172. drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c +5 −3
  173. drivers/gpu/drm/selftests/test-drm_plane_helper.c +4 −0
  174. drivers/gpu/drm/stm/drv.c +5 −0
  175. drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +106 −8
  176. drivers/gpu/drm/stm/ltdc.c +647 −163
  177. drivers/gpu/drm/stm/ltdc.h +10 −2
  178. drivers/gpu/drm/tegra/Kconfig +1 −0
  179. drivers/gpu/drm/tegra/dp.c +1 −1
  180. drivers/gpu/drm/tegra/dpaux.c +1 −1
  181. drivers/gpu/drm/tegra/sor.c +1 −1
  182. drivers/gpu/drm/tilcdc/tilcdc_drv.c +1 −3
  183. drivers/gpu/drm/tiny/bochs.c +2 −18
  184. drivers/gpu/drm/tiny/cirrus.c +2 −15
  185. drivers/gpu/drm/tiny/simpledrm.c +17 −5
  186. drivers/gpu/drm/ttm/ttm_bo_util.c +5 −2
  187. drivers/gpu/drm/ttm/ttm_range_manager.c +3 −1
  188. drivers/gpu/drm/ttm/ttm_resource.c +35 −0
  189. drivers/gpu/drm/ttm/ttm_sys_manager.c +2 −1
  190. drivers/gpu/drm/v3d/v3d_drv.c +6 −2
  191. drivers/gpu/drm/vc4/vc4_bo.c +0 −2
  192. drivers/gpu/drm/vc4/vc4_drv.c +29 −4
  193. drivers/gpu/drm/vc4/vc4_hdmi.c +78 −54
  194. drivers/gpu/drm/vc4/vc4_hdmi.h +3 −2
  195. drivers/gpu/drm/vc4/vc4_regs.h +3 −0
  196. drivers/gpu/drm/virtio/virtgpu_gem.c +3 −0
  197. drivers/gpu/drm/vkms/vkms_drv.h +2 −0
  198. drivers/gpu/drm/vkms/vkms_output.c +22 −7
  199. drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +3 −1
  200. drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c +2 −1
  201. drivers/gpu/drm/xlnx/Kconfig +1 −0
  202. drivers/gpu/drm/xlnx/zynqmp_dp.c +1 −1
  203. drivers/platform/chrome/Kconfig +11 −0
  204. drivers/platform/chrome/Makefile +1 −0
  205. drivers/platform/chrome/chromeos_privacy_screen.c +153 −0
  206. drivers/platform/x86/thinkpad_acpi.c +1 −1
  207. drivers/video/fbdev/asiliantfb.c +1 −1
  208. drivers/video/fbdev/core/fbmem.c +26 −3
  209. drivers/video/fbdev/s3c-fb.c +1 −1
  210. drivers/video/fbdev/simplefb.c +45 −20
  211. drivers/video/fbdev/vga16fb.c +5 −0
  212. include/drm/bridge/dw_mipi_dsi.h +3 −1
  213. include/drm/dp/drm_dp_aux_bus.h +0 −0
  214. include/drm/dp/drm_dp_dual_mode_helper.h +0 −0
  215. include/drm/dp/drm_dp_helper.h +2 −5
  216. include/drm/dp/drm_dp_mst_helper.h +1 −1
  217. include/drm/drm_buddy.h +150 −0
  218. include/drm/drm_connector.h +12 −6
  219. include/drm/drm_crtc.h +10 −0
  220. include/drm/drm_dsc.h +1 −1
  221. include/drm/drm_edid.h +2 −2
  222. include/drm/drm_mipi_dbi.h +1 −1
  223. include/drm/drm_modeset_lock.h +1 −0
  224. include/drm/drm_module.h +125 −0
  225. include/drm/drm_plane.h +1 −1
  226. include/drm/drm_privacy_screen_driver.h +12 −1
  227. include/drm/ttm/ttm_resource.h +16 −7
  228. include/linux/dma-buf-map.h +2 −2
  229. include/linux/dma-resv.h +2 −2
  230. include/linux/fb.h +1 −0
  231. include/linux/rwsem.h +1 −1
  232. include/soc/bcm2835/raspberrypi-firmware.h +1 −0
  233. include/uapi/drm/panfrost_drm.h +2 −2
Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml+1−0
@@ -39,6 +39,7 @@ properties: · 38 unmodified lines
39 - const: lvds-encoder # Generic LVDS encoder compatible fallback39 - const: lvds-encoder # Generic LVDS encoder compatible fallback
40 - items:40 - items:
41 - enum:41 - enum:
42 - ti,ds90cf364a # For the DS90CF364A FPD-Link LVDS Receiver
42 - ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver43 - ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver
43 - const: lvds-decoder # Generic LVDS decoders compatible fallback44 - const: lvds-decoder # Generic LVDS decoders compatible fallback
44 - enum:45 - enum:
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml+4−1
@@ -32,6 +32,9 @@ properties: · 31 unmodified lines
32 maxItems: 132 maxItems: 1
33 description: GPIO specifier for bridge_en pin (active high).33 description: GPIO specifier for bridge_en pin (active high).
34 34
35 vcc-supply:
36 description: A 1.8V power supply (see regulator/regulator.yaml).
37
35 ports:38 ports:
36 $ref: /schemas/graph.yaml#/properties/ports39 $ref: /schemas/graph.yaml#/properties/ports
37 40
@@ -91,7 +94,6 @@ properties: · 53 unmodified lines
91required:94required:
92 - compatible95 - compatible
93 - reg96 - reg
94 - enable-gpios
95 - ports97 - ports
96 98
97allOf:99allOf:
@@ -133,6 +135,7 @@ examples: · 35 unmodified lines
133 reg = <0x2d>;135 reg = <0x2d>;
134 136
135 enable-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;137 enable-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
138 vcc-supply = <&reg_sn65dsi83_1v8>;
136 139
137 ports {140 ports {
138 #address-cells = <1>;141 #address-cells = <1>;
Documentation/devicetree/bindings/display/panel/panel-simple.yaml+2−0
@@ -222,6 +222,8 @@ properties: · 221 unmodified lines
222 - logictechno,lttd800480070-l6wh-rt222 - logictechno,lttd800480070-l6wh-rt
223 # Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel223 # Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
224 - mitsubishi,aa070mc01-ca1224 - mitsubishi,aa070mc01-ca1
225 # Multi-Inno Technology Co.,Ltd MI0700S4T-6 7" 800x480 TFT Resistive Touch Module
226 - multi-inno,mi0700s4t-6
225 # Multi-Inno Technology Co.,Ltd MI1010AIT-1CP 10.1" 1280x800 LVDS IPS Cap Touch Mod.227 # Multi-Inno Technology Co.,Ltd MI1010AIT-1CP 10.1" 1280x800 LVDS IPS Cap Touch Mod.
226 - multi-inno,mi1010ait-1cp228 - multi-inno,mi1010ait-1cp
227 # NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel229 # NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel
Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml+9−2
@@ -4,7 +4,12 @@ · 3 unmodified lines
4$id: http://devicetree.org/schemas/display/panel/sony,acx424akp.yaml#4$id: http://devicetree.org/schemas/display/panel/sony,acx424akp.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#5$schema: http://devicetree.org/meta-schemas/core.yaml#
6 6
7title: Sony ACX424AKP 4" 480x864 AMOLED panel7title: Sony ACX424AKP/ACX424AKM 4" 480x864/480x854 AMOLED panel
8
9description: The Sony ACX424AKP and ACX424AKM are panels built around
10 the Novatek NT35560 display controller. The only difference is that
11 the AKM is configured to use 10 pixels less in the Y axis than the
12 AKP.
8 13
9maintainers:14maintainers:
10 - Linus Walleij <linus.walleij@linaro.org>15 - Linus Walleij <linus.walleij@linaro.org>
@@ -14,7 +19,9 @@ allOf: · 3 unmodified lines
14 19
15properties:20properties:
16 compatible:21 compatible:
17 const: sony,acx424akp22 enum:
23 - sony,acx424akp
24 - sony,acx424akm
18 reg: true25 reg: true
19 reset-gpios: true26 reset-gpios: true
20 vddi-supply:27 vddi-supply:
Documentation/gpu/drm-internals.rst+6−0
@@ -75,6 +75,12 @@ update it, its value is mostly useless. The DRM core prints it to the · 74 unmodified lines
75kernel log at initialization time and passes it to userspace through the75kernel log at initialization time and passes it to userspace through the
76DRM_IOCTL_VERSION ioctl.76DRM_IOCTL_VERSION ioctl.
77 77
78Module Initialization
79---------------------
80
81.. kernel-doc:: include/drm/drm_module.h
82 :doc: overview
83
78Managing Ownership of the Framebuffer Aperture84Managing Ownership of the Framebuffer Aperture
79----------------------------------------------85----------------------------------------------
80 86
Documentation/gpu/drm-kms-helpers.rst+13−13
@@ -232,34 +232,34 @@ HDCP Helper Functions Reference · 231 unmodified lines
232Display Port Helper Functions Reference232Display Port Helper Functions Reference
233=======================================233=======================================
234 234
235.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c235.. kernel-doc:: drivers/gpu/drm/dp/drm_dp.c
236 :doc: dp helpers236 :doc: dp helpers
237 237
238.. kernel-doc:: include/drm/drm_dp_helper.h238.. kernel-doc:: include/drm/dp/drm_dp_helper.h
239 :internal:239 :internal:
240 240
241.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c241.. kernel-doc:: drivers/gpu/drm/dp/drm_dp.c
242 :export:242 :export:
243 243
244Display Port CEC Helper Functions Reference244Display Port CEC Helper Functions Reference
245===========================================245===========================================
246 246
247.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c247.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_cec.c
248 :doc: dp cec helpers248 :doc: dp cec helpers
249 249
250.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c250.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_cec.c
251 :export:251 :export:
252 252
253Display Port Dual Mode Adaptor Helper Functions Reference253Display Port Dual Mode Adaptor Helper Functions Reference
254=========================================================254=========================================================
255 255
256.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c256.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_dual_mode_helper.c
257 :doc: dp dual mode helpers257 :doc: dp dual mode helpers
258 258
259.. kernel-doc:: include/drm/drm_dp_dual_mode_helper.h259.. kernel-doc:: include/drm/dp/drm_dp_dual_mode_helper.h
260 :internal:260 :internal:
261 261
262.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c262.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_dual_mode_helper.c
263 :export:263 :export:
264 264
265Display Port MST Helpers265Display Port MST Helpers
@@ -268,19 +268,19 @@ Display Port MST Helpers · 2 unmodified lines
268Overview268Overview
269--------269--------
270 270
271.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c271.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
272 :doc: dp mst helper272 :doc: dp mst helper
273 273
274.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c274.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
275 :doc: Branch device and port refcounting275 :doc: Branch device and port refcounting
276 276
277Functions Reference277Functions Reference
278-------------------278-------------------
279 279
280.. kernel-doc:: include/drm/drm_dp_mst_helper.h280.. kernel-doc:: include/drm/dp/drm_dp_mst_helper.h
281 :internal:281 :internal:
282 282
283.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c283.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
284 :export:284 :export:
285 285
286Topology Lifetime Internals286Topology Lifetime Internals
@@ -289,7 +289,7 @@ Topology Lifetime Internals · 2 unmodified lines
289These functions aren't exported to drivers, but are documented here to help make289These functions aren't exported to drivers, but are documented here to help make
290the MST topology helpers easier to understand290the MST topology helpers easier to understand
291 291
292.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c292.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
293 :functions: drm_dp_mst_topology_try_get_mstb drm_dp_mst_topology_get_mstb293 :functions: drm_dp_mst_topology_try_get_mstb drm_dp_mst_topology_get_mstb
294 drm_dp_mst_topology_put_mstb294 drm_dp_mst_topology_put_mstb
295 drm_dp_mst_topology_try_get_port drm_dp_mst_topology_get_port295 drm_dp_mst_topology_try_get_port drm_dp_mst_topology_get_port
Documentation/gpu/drm-kms.rst+3−3
@@ -423,12 +423,12 @@ Connector Functions Reference · 422 unmodified lines
423Writeback Connectors423Writeback Connectors
424--------------------424--------------------
425 425
426.. kernel-doc:: include/drm/drm_writeback.h
427 :internal:
428
429.. kernel-doc:: drivers/gpu/drm/drm_writeback.c426.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
430 :doc: overview427 :doc: overview
431 428
429.. kernel-doc:: include/drm/drm_writeback.h
430 :internal:
431
432.. kernel-doc:: drivers/gpu/drm/drm_writeback.c432.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
433 :export:433 :export:
434 434
Documentation/gpu/drm-mm.rst+1−1
@@ -8,7 +8,7 @@ the very dynamic nature of many of that data, managing graphics memory · 7 unmodified lines
8efficiently is thus crucial for the graphics stack and plays a central8efficiently is thus crucial for the graphics stack and plays a central
9role in the DRM infrastructure.9role in the DRM infrastructure.
10 10
11The DRM core includes two memory managers, namely Translation Table Maps11The DRM core includes two memory managers, namely Translation Table Manager
12(TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory12(TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory
13manager to be developed and tried to be a one-size-fits-them all13manager to be developed and tried to be a one-size-fits-them all
14solution. It provides a single userspace API to accommodate the need of14solution. It provides a single userspace API to accommodate the need of
Documentation/gpu/todo.rst+15−0
@@ -467,6 +467,21 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de> · 466 unmodified lines
467 467
468Level: Intermediate468Level: Intermediate
469 469
470Request memory regions in all drivers
471-------------------------------------
472
473Go through all drivers and add code to request the memory regions that the
474driver uses. This requires adding calls to request_mem_region(),
475pci_request_region() or similar functions. Use helpers for managed cleanup
476where possible.
477
478Drivers are pretty bad at doing this and there used to be conflicts among
479DRM and fbdev drivers. Still, it's the correct thing to do.
480
481Contact: Thomas Zimmermann <tzimmermann@suse.de>
482
483Level: Starter
484
470 485
471Core refactorings486Core refactorings
472=================487=================
Documentation/gpu/vkms.rst+0−2
@@ -124,8 +124,6 @@ Add Plane Features · 123 unmodified lines
124 124
125There's lots of plane features we could add support for:125There's lots of plane features we could add support for:
126 126
127- Multiple overlay planes. [Good to get started]
128
129- Clearing primary plane: clear primary plane before plane composition (at the127- Clearing primary plane: clear primary plane before plane composition (at the
130 start) for correctness of pixel blend ops. It also guarantees alpha channel128 start) for correctness of pixel blend ops. It also guarantees alpha channel
131 is cleared in the target buffer for stable crc. [Good to get started]129 is cleared in the target buffer for stable crc. [Good to get started]
drivers/char/agp/ati-agp.c+6−2
@@ -55,7 +55,7 @@ static struct _ati_generic_private { · 54 unmodified lines
55 55
56static int ati_create_page_map(struct ati_page_map *page_map)56static int ati_create_page_map(struct ati_page_map *page_map)
57{57{
58 int i, err = 0;58 int i, err;
59 59
60 page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL);60 page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL);
61 if (page_map->real == NULL)61 if (page_map->real == NULL)
@@ -63,6 +63,10 @@ static int ati_create_page_map(struct ati_page_map *page_map) · 1 unmodified line
63 63
64 set_memory_uc((unsigned long)page_map->real, 1);64 set_memory_uc((unsigned long)page_map->real, 1);
65 err = map_page_into_agp(virt_to_page(page_map->real));65 err = map_page_into_agp(virt_to_page(page_map->real));
66 if (err) {
67 free_page((unsigned long)page_map->real);
68 return err;
69 }
66 page_map->remapped = page_map->real;70 page_map->remapped = page_map->real;
67 71
68 for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {72 for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
@@ -303,7 +307,7 @@ static int ati_insert_memory(struct agp_memory * mem, · 234 unmodified lines
303 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {307 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
304 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;308 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
305 cur_gatt = GET_GATT(addr);309 cur_gatt = GET_GATT(addr);
306 writel(agp_bridge->driver->mask_memory(agp_bridge, 310 writel(agp_bridge->driver->mask_memory(agp_bridge,
307 page_to_phys(mem->pages[i]),311 page_to_phys(mem->pages[i]),
308 mem->type),312 mem->type),
309 cur_gatt+GET_GATT_OFF(addr));313 cur_gatt+GET_GATT_OFF(addr));
drivers/char/agp/backend.c+2−0
@@ -62,6 +62,7 @@ EXPORT_SYMBOL(agp_find_bridge); · 61 unmodified lines
62 62
63/**63/**
64 * agp_backend_acquire - attempt to acquire an agp backend.64 * agp_backend_acquire - attempt to acquire an agp backend.
65 * @pdev: the PCI device
65 *66 *
66 */67 */
67struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)68struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)
@@ -83,6 +84,7 @@ EXPORT_SYMBOL(agp_backend_acquire); · 15 unmodified lines
83 84
84/**85/**
85 * agp_backend_release - release the lock on the agp backend.86 * agp_backend_release - release the lock on the agp backend.
87 * @bridge: the AGP backend to release
86 *88 *
87 * The caller must insure that the graphics aperture translation table89 * The caller must insure that the graphics aperture translation table
88 * is read for use by another entity.90 * is read for use by another entity.
drivers/char/agp/frontend.c+3−1
@@ -39,7 +39,9 @@ · 38 unmodified lines
39#include <linux/fs.h>39#include <linux/fs.h>
40#include <linux/sched.h>40#include <linux/sched.h>
41#include <linux/uaccess.h>41#include <linux/uaccess.h>
42
42#include "agp.h"43#include "agp.h"
44#include "compat_ioctl.h"
43 45
44struct agp_front_data agp_fe;46struct agp_front_data agp_fe;
45 47
@@ -1017,7 +1019,7 @@ static long agp_ioctl(struct file *file, · 971 unmodified lines
1017 case AGPIOC_UNBIND:1019 case AGPIOC_UNBIND:
1018 ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);1020 ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
1019 break;1021 break;
1020 1022
1021 case AGPIOC_CHIPSET_FLUSH:1023 case AGPIOC_CHIPSET_FLUSH:
1022 break;1024 break;
1023 }1025 }
drivers/char/agp/nvidia-agp.c+2−1
@@ -261,7 +261,8 @@ static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type · 260 unmodified lines
261static void nvidia_tlbflush(struct agp_memory *mem)261static void nvidia_tlbflush(struct agp_memory *mem)
262{262{
263 unsigned long end;263 unsigned long end;
264 u32 wbc_reg, temp;264 u32 wbc_reg;
265 u32 __maybe_unused temp;
265 int i;266 int i;
266 267
267 /* flush chipset */268 /* flush chipset */
drivers/char/agp/sworks-agp.c+1−4
@@ -262,13 +262,10 @@ static void serverworks_tlbflush(struct agp_memory *temp) · 261 unmodified lines
262 262
263static int serverworks_configure(void)263static int serverworks_configure(void)
264{264{
265 struct aper_size_info_lvl2 *current_size;
266 u32 temp;265 u32 temp;
267 u8 enable_reg;266 u8 enable_reg;
268 u16 cap_reg;267 u16 cap_reg;
269 268
270 current_size = A_SIZE_LVL2(agp_bridge->current_size);
271
272 /* Get the memory mapped registers */269 /* Get the memory mapped registers */
273 pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp);270 pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp);
274 temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);271 temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
@@ -350,7 +347,7 @@ static int serverworks_insert_memory(struct agp_memory *mem, · 75 unmodified lines
350 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {347 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
351 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;348 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
352 cur_gatt = SVRWRKS_GET_GATT(addr);349 cur_gatt = SVRWRKS_GET_GATT(addr);
353 writel(agp_bridge->driver->mask_memory(agp_bridge, 350 writel(agp_bridge->driver->mask_memory(agp_bridge,
354 page_to_phys(mem->pages[i]), mem->type),351 page_to_phys(mem->pages[i]), mem->type),
355 cur_gatt+GET_GATT_OFF(addr));352 cur_gatt+GET_GATT_OFF(addr));
356 }353 }
drivers/char/agp/via-agp.c+0−3
@@ -128,9 +128,6 @@ static int via_fetch_size_agp3(void) · 127 unmodified lines
128static int via_configure_agp3(void)128static int via_configure_agp3(void)
129{129{
130 u32 temp;130 u32 temp;
131 struct aper_size_info_16 *current_size;
132
133 current_size = A_SIZE_16(agp_bridge->current_size);
134 131
135 /* address to map to */132 /* address to map to */
136 agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,133 agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
drivers/dma-buf/dma-resv.c+17−29
@@ -542,57 +542,45 @@ EXPORT_SYMBOL(dma_resv_copy_fences); · 541 unmodified lines
542 * dma_resv_get_fences - Get an object's shared and exclusive542 * dma_resv_get_fences - Get an object's shared and exclusive
543 * fences without update side lock held543 * fences without update side lock held
544 * @obj: the reservation object544 * @obj: the reservation object
545 * @fence_excl: the returned exclusive fence (or NULL)545 * @write: true if we should return all fences
546 * @shared_count: the number of shared fences returned546 * @num_fences: the number of fences returned
547 * @shared: the array of shared fence ptrs returned (array is krealloc'd to547 * @fences: the array of fence ptrs returned (array is krealloc'd to the
548 * the required size, and must be freed by caller)548 * required size, and must be freed by caller)
549 *549 *
550 * Retrieve all fences from the reservation object. If the pointer for the550 * Retrieve all fences from the reservation object.
551 * exclusive fence is not specified the fence is put into the array of the551 * Returns either zero or -ENOMEM.
552 * shared fences as well. Returns either zero or -ENOMEM.
553 */552 */
554int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **fence_excl,553int dma_resv_get_fences(struct dma_resv *obj, bool write,
555 unsigned int *shared_count, struct dma_fence ***shared)554 unsigned int *num_fences, struct dma_fence ***fences)
556{555{
557 struct dma_resv_iter cursor;556 struct dma_resv_iter cursor;
558 struct dma_fence *fence;557 struct dma_fence *fence;
559 558
560 *shared_count = 0;559 *num_fences = 0;
561 *shared = NULL;560 *fences = NULL;
562 561
563 if (fence_excl)562 dma_resv_iter_begin(&cursor, obj, write);
564 *fence_excl = NULL;
565
566 dma_resv_iter_begin(&cursor, obj, true);
567 dma_resv_for_each_fence_unlocked(&cursor, fence) {563 dma_resv_for_each_fence_unlocked(&cursor, fence) {
568 564
569 if (dma_resv_iter_is_restarted(&cursor)) {565 if (dma_resv_iter_is_restarted(&cursor)) {
570 unsigned int count;566 unsigned int count;
571 567
572 while (*shared_count)568 while (*num_fences)
573 dma_fence_put((*shared)[--(*shared_count)]);569 dma_fence_put((*fences)[--(*num_fences)]);
574
575 if (fence_excl)
576 dma_fence_put(*fence_excl);
577 570
578 count = cursor.shared_count;571 count = cursor.shared_count + 1;
579 count += fence_excl ? 0 : 1;
580 572
581 /* Eventually re-allocate the array */573 /* Eventually re-allocate the array */
582 *shared = krealloc_array(*shared, count,574 *fences = krealloc_array(*fences, count,
583 sizeof(void *),575 sizeof(void *),
584 GFP_KERNEL);576 GFP_KERNEL);
585 if (count && !*shared) {577 if (count && !*fences) {
586 dma_resv_iter_end(&cursor);578 dma_resv_iter_end(&cursor);
587 return -ENOMEM;579 return -ENOMEM;
588 }580 }
589 }581 }
590 582
591 dma_fence_get(fence);583 (*fences)[(*num_fences)++] = dma_fence_get(fence);
592 if (dma_resv_iter_is_exclusive(&cursor) && fence_excl)
593 *fence_excl = fence;
594 else
595 (*shared)[(*shared_count)++] = fence;
596 }584 }
597 dma_resv_iter_end(&cursor);585 dma_resv_iter_end(&cursor);
598 586
drivers/dma-buf/st-dma-resv.c+5−21
@@ -275,7 +275,7 @@ static int test_shared_for_each_unlocked(void *arg) · 274 unmodified lines
275 275
276static int test_get_fences(void *arg, bool shared)276static int test_get_fences(void *arg, bool shared)
277{277{
278 struct dma_fence *f, *excl = NULL, **fences = NULL;278 struct dma_fence *f, **fences = NULL;
279 struct dma_resv resv;279 struct dma_resv resv;
280 int r, i;280 int r, i;
281 281
@@ -304,35 +304,19 @@ static int test_get_fences(void *arg, bool shared) · 22 unmodified lines
304 }304 }
305 dma_resv_unlock(&resv);305 dma_resv_unlock(&resv);
306 306
307 r = dma_resv_get_fences(&resv, &excl, &i, &fences);307 r = dma_resv_get_fences(&resv, shared, &i, &fences);
308 if (r) {308 if (r) {
309 pr_err("get_fences failed\n");309 pr_err("get_fences failed\n");
310 goto err_free;310 goto err_free;
311 }311 }
312 312
313 if (shared) {313 if (i != 1 || fences[0] != f) {
314 if (excl != NULL) {314 pr_err("get_fences returned unexpected fence\n");
315 pr_err("get_fences returned unexpected excl fence\n");315 goto err_free;
316 goto err_free;
317 }
318 if (i != 1 || fences[0] != f) {
319 pr_err("get_fences returned unexpected shared fence\n");
320 goto err_free;
321 }
322 } else {
323 if (excl != f) {
324 pr_err("get_fences returned unexpected excl fence\n");
325 goto err_free;
326 }
327 if (i != 0) {
328 pr_err("get_fences returned unexpected shared fence\n");
329 goto err_free;
330 }
331 }316 }
332 317
333 dma_fence_signal(f);318 dma_fence_signal(f);
334err_free:319err_free:
335 dma_fence_put(excl);
336 while (i--)320 while (i--)
337 dma_fence_put(fences[i]);321 dma_fence_put(fences[i]);
338 kfree(fences);322 kfree(fences);
drivers/dma-buf/udmabuf.c+4−0
@@ -190,6 +190,10 @@ static long udmabuf_create(struct miscdevice *device, · 189 unmodified lines
190 if (ubuf->pagecount > pglimit)190 if (ubuf->pagecount > pglimit)
191 goto err;191 goto err;
192 }192 }
193
194 if (!ubuf->pagecount)
195 goto err;
196
193 ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),197 ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
194 GFP_KERNEL);198 GFP_KERNEL);
195 if (!ubuf->pages) {199 if (!ubuf->pages) {
drivers/firmware/sysfb_simplefb.c+1−1
@@ -99,7 +99,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si, · 98 unmodified lines
99 99
100 /* setup IORESOURCE_MEM as framebuffer memory */100 /* setup IORESOURCE_MEM as framebuffer memory */
101 memset(&res, 0, sizeof(res));101 memset(&res, 0, sizeof(res));
102 res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;102 res.flags = IORESOURCE_MEM;
103 res.name = simplefb_resname;103 res.name = simplefb_resname;
104 res.start = base;104 res.start = base;
105 res.end = res.start + length - 1;105 res.end = res.start + length - 1;
drivers/gpu/drm/Kconfig+15−0
@@ -68,6 +68,7 @@ config DRM_DEBUG_SELFTEST · 67 unmodified lines
68 depends on DRM68 depends on DRM
69 depends on DEBUG_KERNEL69 depends on DEBUG_KERNEL
70 select PRIME_NUMBERS70 select PRIME_NUMBERS
71 select DRM_DP_HELPER
71 select DRM_LIB_RANDOM72 select DRM_LIB_RANDOM
72 select DRM_KMS_HELPER73 select DRM_KMS_HELPER
73 select DRM_EXPORT_FOR_TESTS if m74 select DRM_EXPORT_FOR_TESTS if m
@@ -80,6 +81,12 @@ config DRM_DEBUG_SELFTEST · 6 unmodified lines
80 81
81 If in doubt, say "N".82 If in doubt, say "N".
82 83
84config DRM_DP_HELPER
85 tristate
86 depends on DRM
87 help
88 DRM helpers for DisplayPort.
89
83config DRM_KMS_HELPER90config DRM_KMS_HELPER
84 tristate91 tristate
85 depends on DRM92 depends on DRM
@@ -198,6 +205,12 @@ config DRM_TTM · 112 unmodified lines
198 GPU memory types. Will be enabled automatically if a device driver205 GPU memory types. Will be enabled automatically if a device driver
199 uses it.206 uses it.
200 207
208config DRM_BUDDY
209 tristate
210 depends on DRM
211 help
212 A page based buddy allocator
213
201config DRM_VRAM_HELPER214config DRM_VRAM_HELPER
202 tristate215 tristate
203 depends on DRM216 depends on DRM
@@ -236,6 +249,7 @@ config DRM_RADEON · 32 unmodified lines
236 depends on DRM && PCI && MMU249 depends on DRM && PCI && MMU
237 depends on AGP || !AGP250 depends on AGP || !AGP
238 select FW_LOADER251 select FW_LOADER
252 select DRM_DP_HELPER
239 select DRM_KMS_HELPER253 select DRM_KMS_HELPER
240 select DRM_TTM254 select DRM_TTM
241 select DRM_TTM_HELPER255 select DRM_TTM_HELPER
@@ -256,6 +270,7 @@ config DRM_AMDGPU · 14 unmodified lines
256 tristate "AMD GPU"270 tristate "AMD GPU"
257 depends on DRM && PCI && MMU271 depends on DRM && PCI && MMU
258 select FW_LOADER272 select FW_LOADER
273 select DRM_DP_HELPER
259 select DRM_KMS_HELPER274 select DRM_KMS_HELPER
260 select DRM_SCHED275 select DRM_SCHED
261 select DRM_TTM276 select DRM_TTM
drivers/gpu/drm/Makefile+6−8
@@ -31,8 +31,6 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o · 30 unmodified lines
31drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o31drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
32drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o32drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o
33 33
34obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
35
36obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o34obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
37 35
38drm_cma_helper-y := drm_gem_cma_helper.o36drm_cma_helper-y := drm_gem_cma_helper.o
@@ -42,27 +40,26 @@ obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o · 3 unmodified lines
42drm_shmem_helper-y := drm_gem_shmem_helper.o40drm_shmem_helper-y := drm_gem_shmem_helper.o
43obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o41obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
44 42
43obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
44
45drm_vram_helper-y := drm_gem_vram_helper.o45drm_vram_helper-y := drm_gem_vram_helper.o
46obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o46obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
47 47
48drm_ttm_helper-y := drm_gem_ttm_helper.o48drm_ttm_helper-y := drm_gem_ttm_helper.o
49obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o49obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
50 50
51drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \51drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o \
52 drm_dsc.o drm_encoder_slave.o drm_flip_work.o drm_hdcp.o \52 drm_dsc.o drm_encoder_slave.o drm_flip_work.o drm_hdcp.o \
53 drm_probe_helper.o \53 drm_probe_helper.o \
54 drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \54 drm_plane_helper.o drm_atomic_helper.o \
55 drm_kms_helper_common.o drm_dp_dual_mode_helper.o \55 drm_kms_helper_common.o \
56 drm_simple_kms_helper.o drm_modeset_helper.o \56 drm_simple_kms_helper.o drm_modeset_helper.o \
57 drm_scdc_helper.o drm_gem_atomic_helper.o \57 drm_scdc_helper.o drm_gem_atomic_helper.o \
58 drm_gem_framebuffer_helper.o \58 drm_gem_framebuffer_helper.o \
59 drm_atomic_state_helper.o drm_damage_helper.o \59 drm_atomic_state_helper.o drm_damage_helper.o \
60 drm_format_helper.o drm_self_refresh_helper.o drm_rect.o60 drm_format_helper.o drm_self_refresh_helper.o drm_rect.o
61
62drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o61drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
63drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o62drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
64drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
65drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
66 63
67obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o64obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
68obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/65obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
@@ -72,6 +69,7 @@ obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o · 3 unmodified lines
72obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o69obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
73obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o70obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
74obj-y += arm/71obj-y += arm/
72obj-y += dp/
75obj-$(CONFIG_DRM_TTM) += ttm/73obj-$(CONFIG_DRM_TTM) += ttm/
76obj-$(CONFIG_DRM_SCHED) += scheduler/74obj-$(CONFIG_DRM_SCHED) += scheduler/
77obj-$(CONFIG_DRM_TDFX) += tdfx/75obj-$(CONFIG_DRM_TDFX) += tdfx/
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c+2−2
@@ -26,7 +26,7 @@ · 25 unmodified lines
26 26
27#include <drm/drm_edid.h>27#include <drm/drm_edid.h>
28#include <drm/drm_fb_helper.h>28#include <drm/drm_fb_helper.h>
29#include <drm/drm_dp_helper.h>29#include <drm/dp/drm_dp_helper.h>
30#include <drm/drm_probe_helper.h>30#include <drm/drm_probe_helper.h>
31#include <drm/amdgpu_drm.h>31#include <drm/amdgpu_drm.h>
32#include "amdgpu.h"32#include "amdgpu.h"
@@ -175,7 +175,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector) · 142 unmodified lines
175 175
176 /* Check if bpc is within clock limit. Try to degrade gracefully otherwise */176 /* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
177 if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {177 if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
178 if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&178 if ((connector->display_info.edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) &&
179 (mode_clock * 5/4 <= max_tmds_clock))179 (mode_clock * 5/4 <= max_tmds_clock))
180 bpc = 10;180 bpc = 10;
181 else181 else
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c+1−4
@@ -1274,14 +1274,11 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, · 1273 unmodified lines
1274 /*1274 /*
1275 * Work around dma_resv shortcommings by wrapping up the1275 * Work around dma_resv shortcommings by wrapping up the
1276 * submission in a dma_fence_chain and add it as exclusive1276 * submission in a dma_fence_chain and add it as exclusive
1277 * fence, but first add the submission as shared fence to make1277 * fence.
1278 * sure that shared fences never signal before the exclusive
1279 * one.
1280 */1278 */
1281 dma_fence_chain_init(chain, dma_resv_excl_fence(resv),1279 dma_fence_chain_init(chain, dma_resv_excl_fence(resv),
1282 dma_fence_get(p->fence), 1);1280 dma_fence_get(p->fence), 1);
1283 1281
1284 dma_resv_add_shared_fence(resv, p->fence);
1285 rcu_assign_pointer(resv->fence_excl, &chain->base);1282 rcu_assign_pointer(resv->fence_excl, &chain->base);
1286 e->chain = NULL;1283 e->chain = NULL;
1287 }1284 }
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c+4−2
@@ -200,8 +200,10 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, · 199 unmodified lines
200 goto unpin;200 goto unpin;
201 }201 }
202 202
203 r = dma_resv_get_fences(new_abo->tbo.base.resv, NULL,203 /* TODO: Unify this with other drivers */
204 &work->shared_count, &work->shared);204 r = dma_resv_get_fences(new_abo->tbo.base.resv, true,
205 &work->shared_count,
206 &work->shared);
205 if (unlikely(r != 0)) {207 if (unlikely(r != 0)) {
206 DRM_ERROR("failed to get fences for buffer\n");208 DRM_ERROR("failed to get fences for buffer\n");
207 goto unpin;209 goto unpin;
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c+0−6
@@ -226,12 +226,6 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, · 225 unmodified lines
226 if (!amdgpu_vm_ready(vm))226 if (!amdgpu_vm_ready(vm))
227 goto out_unlock;227 goto out_unlock;
228 228
229 fence = dma_resv_excl_fence(bo->tbo.base.resv);
230 if (fence) {
231 amdgpu_bo_fence(bo, fence, true);
232 fence = NULL;
233 }
234
235 r = amdgpu_vm_clear_freed(adev, vm, &fence);229 r = amdgpu_vm_clear_freed(adev, vm, &fence);
236 if (r || !fence)230 if (r || !fence)
237 goto out_unlock;231 goto out_unlock;
drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c+4−1
@@ -167,6 +167,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, · 166 unmodified lines
167 return 0;167 return 0;
168 168
169err_free:169err_free:
170 ttm_resource_fini(man, &node->base.base);
170 kfree(node);171 kfree(node);
171 172
172err_out:173err_out:
@@ -198,6 +199,7 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, · 25 unmodified lines
198 if (!(res->placement & TTM_PL_FLAG_TEMPORARY))199 if (!(res->placement & TTM_PL_FLAG_TEMPORARY))
199 atomic64_sub(res->num_pages, &mgr->used);200 atomic64_sub(res->num_pages, &mgr->used);
200 201
202 ttm_resource_fini(man, res);
201 kfree(node);203 kfree(node);
202}204}
203 205
@@ -286,7 +288,8 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) · 82 unmodified lines
286 man->use_tt = true;288 man->use_tt = true;
287 man->func = &amdgpu_gtt_mgr_func;289 man->func = &amdgpu_gtt_mgr_func;
288 290
289 ttm_resource_manager_init(man, gtt_size >> PAGE_SHIFT);291 ttm_resource_manager_init(man, &adev->mman.bdev,
292 gtt_size >> PAGE_SHIFT);
290 293
291 start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS;294 start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS;
292 size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;295 size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c+1−1
@@ -112,7 +112,7 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv, · 111 unmodified lines
112 unsigned count;112 unsigned count;
113 int r;113 int r;
114 114
115 r = dma_resv_get_fences(resv, NULL, &count, &fences);115 r = dma_resv_get_fences(resv, true, &count, &fences);
116 if (r)116 if (r)
117 goto fallback;117 goto fallback;
118 118
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h+2−2
@@ -33,7 +33,7 @@ · 32 unmodified lines
33#include <drm/drm_crtc.h>33#include <drm/drm_crtc.h>
34#include <drm/drm_edid.h>34#include <drm/drm_edid.h>
35#include <drm/drm_encoder.h>35#include <drm/drm_encoder.h>
36#include <drm/drm_dp_helper.h>36#include <drm/dp/drm_dp_helper.h>
37#include <drm/drm_fixed.h>37#include <drm/drm_fixed.h>
38#include <drm/drm_crtc_helper.h>38#include <drm/drm_crtc_helper.h>
39#include <drm/drm_fb_helper.h>39#include <drm/drm_fb_helper.h>
@@ -44,7 +44,7 @@ · 4 unmodified lines
44#include <linux/hrtimer.h>44#include <linux/hrtimer.h>
45#include "amdgpu_irq.h"45#include "amdgpu_irq.h"
46 46
47#include <drm/drm_dp_mst_helper.h>47#include <drm/dp/drm_dp_mst_helper.h>
48#include "modules/inc/mod_freesync.h"48#include "modules/inc/mod_freesync.h"
49#include "amdgpu_dm_irq_params.h"49#include "amdgpu_dm_irq_params.h"
50 50
drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c+2−1
@@ -95,6 +95,7 @@ static void amdgpu_preempt_mgr_del(struct ttm_resource_manager *man, · 94 unmodified lines
95 struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);95 struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
96 96
97 atomic64_sub(res->num_pages, &mgr->used);97 atomic64_sub(res->num_pages, &mgr->used);
98 ttm_resource_fini(man, res);
98 kfree(res);99 kfree(res);
99}100}
100 101
@@ -152,7 +153,7 @@ int amdgpu_preempt_mgr_init(struct amdgpu_device *adev) · 51 unmodified lines
152 man->use_tt = true;153 man->use_tt = true;
153 man->func = &amdgpu_preempt_mgr_func;154 man->func = &amdgpu_preempt_mgr_func;
154 155
155 ttm_resource_manager_init(man, (1 << 30));156 ttm_resource_manager_init(man, &adev->mman.bdev, (1 << 30));
156 157
157 atomic64_set(&mgr->used, 0);158 atomic64_set(&mgr->used, 0);
158 159
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c+5−5
@@ -2087,7 +2087,7 @@ static int amdgpu_mm_vram_table_show(struct seq_file *m, void *unused) · 2086 unmodified lines
2087 TTM_PL_VRAM);2087 TTM_PL_VRAM);
2088 struct drm_printer p = drm_seq_file_printer(m);2088 struct drm_printer p = drm_seq_file_printer(m);
2089 2089
2090 man->func->debug(man, &p);2090 ttm_resource_manager_debug(man, &p);
2091 return 0;2091 return 0;
2092}2092}
2093 2093
@@ -2105,7 +2105,7 @@ static int amdgpu_mm_tt_table_show(struct seq_file *m, void *unused) · 11 unmodified lines
2105 TTM_PL_TT);2105 TTM_PL_TT);
2106 struct drm_printer p = drm_seq_file_printer(m);2106 struct drm_printer p = drm_seq_file_printer(m);
2107 2107
2108 man->func->debug(man, &p);2108 ttm_resource_manager_debug(man, &p);
2109 return 0;2109 return 0;
2110}2110}
2111 2111
@@ -2116,7 +2116,7 @@ static int amdgpu_mm_gds_table_show(struct seq_file *m, void *unused) · 4 unmodified lines
2116 AMDGPU_PL_GDS);2116 AMDGPU_PL_GDS);
2117 struct drm_printer p = drm_seq_file_printer(m);2117 struct drm_printer p = drm_seq_file_printer(m);
2118 2118
2119 man->func->debug(man, &p);2119 ttm_resource_manager_debug(man, &p);
2120 return 0;2120 return 0;
2121}2121}
2122 2122
@@ -2127,7 +2127,7 @@ static int amdgpu_mm_gws_table_show(struct seq_file *m, void *unused) · 4 unmodified lines
2127 AMDGPU_PL_GWS);2127 AMDGPU_PL_GWS);
2128 struct drm_printer p = drm_seq_file_printer(m);2128 struct drm_printer p = drm_seq_file_printer(m);
2129 2129
2130 man->func->debug(man, &p);2130 ttm_resource_manager_debug(man, &p);
2131 return 0;2131 return 0;
2132}2132}
2133 2133
@@ -2138,7 +2138,7 @@ static int amdgpu_mm_oa_table_show(struct seq_file *m, void *unused) · 4 unmodified lines
2138 AMDGPU_PL_OA);2138 AMDGPU_PL_OA);
2139 struct drm_printer p = drm_seq_file_printer(m);2139 struct drm_printer p = drm_seq_file_printer(m);
2140 2140
2141 man->func->debug(man, &p);2141 ttm_resource_manager_debug(man, &p);
2142 return 0;2142 return 0;
2143}2143}
2144 2144
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c+4−1
@@ -472,6 +472,7 @@ error_free: · 471 unmodified lines
472 while (i--)472 while (i--)
473 drm_mm_remove_node(&node->mm_nodes[i]);473 drm_mm_remove_node(&node->mm_nodes[i]);
474 spin_unlock(&mgr->lock);474 spin_unlock(&mgr->lock);
475 ttm_resource_fini(man, &node->base);
475 kvfree(node);476 kvfree(node);
476 477
477error_sub:478error_sub:
@@ -511,6 +512,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man, · 33 unmodified lines
511 atomic64_sub(usage, &mgr->usage);512 atomic64_sub(usage, &mgr->usage);
512 atomic64_sub(vis_usage, &mgr->vis_usage);513 atomic64_sub(vis_usage, &mgr->vis_usage);
513 514
515 ttm_resource_fini(man, res);
514 kvfree(node);516 kvfree(node);
515}517}
516 518
@@ -689,7 +691,8 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) · 172 unmodified lines
689 struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;691 struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
690 struct ttm_resource_manager *man = &mgr->manager;692 struct ttm_resource_manager *man = &mgr->manager;
691 693
692 ttm_resource_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT);694 ttm_resource_manager_init(man, &adev->mman.bdev,
695 adev->gmc.real_vram_size >> PAGE_SHIFT);
693 696
694 man->func = &amdgpu_vram_mgr_func;697 man->func = &amdgpu_vram_mgr_func;
695 698
drivers/gpu/drm/amd/amdgpu/atombios_dp.c+1−1
@@ -34,7 +34,7 @@ · 33 unmodified lines
34#include "atombios_dp.h"34#include "atombios_dp.h"
35#include "amdgpu_connectors.h"35#include "amdgpu_connectors.h"
36#include "amdgpu_atombios.h"36#include "amdgpu_atombios.h"
37#include <drm/drm_dp_helper.h>37#include <drm/dp/drm_dp_helper.h>
38 38
39/* move these to drm_dp_helper.c/h */39/* move these to drm_dp_helper.c/h */
40#define DP_LINK_CONFIGURATION_SIZE 940#define DP_LINK_CONFIGURATION_SIZE 9
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c+2−2
@@ -76,7 +76,7 @@ · 75 unmodified lines
76#include <drm/drm_atomic.h>76#include <drm/drm_atomic.h>
77#include <drm/drm_atomic_uapi.h>77#include <drm/drm_atomic_uapi.h>
78#include <drm/drm_atomic_helper.h>78#include <drm/drm_atomic_helper.h>
79#include <drm/drm_dp_mst_helper.h>79#include <drm/dp/drm_dp_mst_helper.h>
80#include <drm/drm_fb_helper.h>80#include <drm/drm_fb_helper.h>
81#include <drm/drm_fourcc.h>81#include <drm/drm_fourcc.h>
82#include <drm/drm_edid.h>82#include <drm/drm_edid.h>
@@ -5856,7 +5856,7 @@ static void fill_stream_properties_from_drm_display_mode( · 5773 unmodified lines
5856 else if (drm_mode_is_420_also(info, mode_in)5856 else if (drm_mode_is_420_also(info, mode_in)
5857 && aconnector->force_yuv420_output)5857 && aconnector->force_yuv420_output)
5858 timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;5858 timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
5859 else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)5859 else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444)
5860 && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)5860 && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
5861 timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;5861 timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
5862 else5862 else
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h+1−1
@@ -29,7 +29,7 @@ · 28 unmodified lines
29#include <drm/drm_atomic.h>29#include <drm/drm_atomic.h>
30#include <drm/drm_connector.h>30#include <drm/drm_connector.h>
31#include <drm/drm_crtc.h>31#include <drm/drm_crtc.h>
32#include <drm/drm_dp_mst_helper.h>32#include <drm/dp/drm_dp_mst_helper.h>
33#include <drm/drm_plane.h>33#include <drm/drm_plane.h>
34 34
35/*35/*
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c+2−2
@@ -25,8 +25,8 @@ · 24 unmodified lines
25 25
26#include <drm/drm_atomic.h>26#include <drm/drm_atomic.h>
27#include <drm/drm_atomic_helper.h>27#include <drm/drm_atomic_helper.h>
28#include <drm/drm_dp_mst_helper.h>28#include <drm/dp/drm_dp_mst_helper.h>
29#include <drm/drm_dp_helper.h>29#include <drm/dp/drm_dp_helper.h>
30#include "dm_services.h"30#include "dm_services.h"
31#include "amdgpu.h"31#include "amdgpu.h"
32#include "amdgpu_dm.h"32#include "amdgpu_dm.h"
drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c+1−1
@@ -27,7 +27,7 @@ · 26 unmodified lines
27#include <dc_link.h>27#include <dc_link.h>
28#include <inc/link_hwss.h>28#include <inc/link_hwss.h>
29#include <inc/link_dpcd.h>29#include <inc/link_dpcd.h>
30#include "drm/drm_dp_helper.h"30#include <drm/dp/drm_dp_helper.h>
31#include <dc_dp_types.h>31#include <dc_dp_types.h>
32#include "dm_helpers.h"32#include "dm_helpers.h"
33 33
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c+1−1
@@ -25,7 +25,7 @@ · 24 unmodified lines
25#include <drm/drm_dsc.h>25#include <drm/drm_dsc.h>
26#include "dc_hw_types.h"26#include "dc_hw_types.h"
27#include "dsc.h"27#include "dsc.h"
28#include <drm/drm_dp_helper.h>28#include <drm/dp/drm_dp_helper.h>
29#include "dc.h"29#include "dc.h"
30#include "rc_calc.h"30#include "rc_calc.h"
31#include "fixed31_32.h"31#include "fixed31_32.h"
drivers/gpu/drm/amd/display/dc/os_types.h+1−1
@@ -36,7 +36,7 @@ · 35 unmodified lines
36#include <asm/byteorder.h>36#include <asm/byteorder.h>
37 37
38#include <drm/drm_print.h>38#include <drm/drm_print.h>
39#include <drm/drm_dp_helper.h>39#include <drm/dp/drm_dp_helper.h>
40 40
41#include "cgs_common.h"41#include "cgs_common.h"
42 42
drivers/gpu/drm/amd/display/include/dpcd_defs.h+1−1
@@ -26,7 +26,7 @@ · 25 unmodified lines
26#ifndef __DAL_DPCD_DEFS_H__26#ifndef __DAL_DPCD_DEFS_H__
27#define __DAL_DPCD_DEFS_H__27#define __DAL_DPCD_DEFS_H__
28 28
29#include <drm/drm_dp_helper.h>29#include <drm/dp/drm_dp_helper.h>
30#ifndef DP_SINK_HW_REVISION_START // can remove this once the define gets into linux drm_dp_helper.h30#ifndef DP_SINK_HW_REVISION_START // can remove this once the define gets into linux drm_dp_helper.h
31#define DP_SINK_HW_REVISION_START 0x40931#define DP_SINK_HW_REVISION_START 0x409
32#endif32#endif
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h+1−1
@@ -30,7 +30,7 @@ · 29 unmodified lines
30#include "hdcp_log.h"30#include "hdcp_log.h"
31 31
32#include <drm/drm_hdcp.h>32#include <drm/drm_hdcp.h>
33#include <drm/drm_dp_helper.h>33#include <drm/dp/drm_dp_helper.h>
34 34
35enum mod_hdcp_trans_input_result {35enum mod_hdcp_trans_input_result {
36 UNKNOWN = 0,36 UNKNOWN = 0,
drivers/gpu/drm/arm/display/komeda/d71/d71_component.c+6−6
@@ -1078,11 +1078,11 @@ static void d71_improc_update(struct komeda_component *c, · 1077 unmodified lines
1078 mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;1078 mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;
1079 1079
1080 /* config color format */1080 /* config color format */
1081 if (st->color_format == DRM_COLOR_FORMAT_YCRCB420)1081 if (st->color_format == DRM_COLOR_FORMAT_YCBCR420)
1082 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;1082 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;
1083 else if (st->color_format == DRM_COLOR_FORMAT_YCRCB422)1083 else if (st->color_format == DRM_COLOR_FORMAT_YCBCR422)
1084 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422;1084 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422;
1085 else if (st->color_format == DRM_COLOR_FORMAT_YCRCB444)1085 else if (st->color_format == DRM_COLOR_FORMAT_YCBCR444)
1086 ctrl |= IPS_CTRL_YUV;1086 ctrl |= IPS_CTRL_YUV;
1087 1087
1088 malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);1088 malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
@@ -1144,11 +1144,11 @@ static int d71_improc_init(struct d71_dev *d71, · 55 unmodified lines
1144 improc = to_improc(c);1144 improc = to_improc(c);
1145 improc->supported_color_depths = BIT(8) | BIT(10);1145 improc->supported_color_depths = BIT(8) | BIT(10);
1146 improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |1146 improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
1147 DRM_COLOR_FORMAT_YCRCB444 |1147 DRM_COLOR_FORMAT_YCBCR444 |
1148 DRM_COLOR_FORMAT_YCRCB422;1148 DRM_COLOR_FORMAT_YCBCR422;
1149 value = malidp_read32(reg, BLK_INFO);1149 value = malidp_read32(reg, BLK_INFO);
1150 if (value & IPS_INFO_CHD420)1150 if (value & IPS_INFO_CHD420)
1151 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420;1151 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCBCR420;
1152 1152
1153 improc->supports_csc = true;1153 improc->supports_csc = true;
1154 improc->supports_gamma = true;1154 improc->supports_gamma = true;
drivers/gpu/drm/arm/display/komeda/komeda_drv.c+2−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/platform_device.h>9#include <linux/platform_device.h>
10#include <linux/component.h>10#include <linux/component.h>
11#include <linux/pm_runtime.h>11#include <linux/pm_runtime.h>
12#include <drm/drm_module.h>
12#include <drm/drm_of.h>13#include <drm/drm_of.h>
13#include "komeda_dev.h"14#include "komeda_dev.h"
14#include "komeda_kms.h"15#include "komeda_kms.h"
@@ -198,7 +199,7 @@ static struct platform_driver komeda_platform_driver = { · 183 unmodified lines
198 },199 },
199};200};
200 201
201module_platform_driver(komeda_platform_driver);202drm_module_platform_driver(komeda_platform_driver);
202 203
203MODULE_AUTHOR("James.Qian.Wang <james.qian.wang@arm.com>");204MODULE_AUTHOR("James.Qian.Wang <james.qian.wang@arm.com>");
204MODULE_DESCRIPTION("Komeda KMS driver");205MODULE_DESCRIPTION("Komeda KMS driver");
drivers/gpu/drm/arm/hdlcd_drv.c+2−1
@@ -30,6 +30,7 @@ · 29 unmodified lines
30#include <drm/drm_gem_cma_helper.h>30#include <drm/drm_gem_cma_helper.h>
31#include <drm/drm_gem_framebuffer_helper.h>31#include <drm/drm_gem_framebuffer_helper.h>
32#include <drm/drm_modeset_helper.h>32#include <drm/drm_modeset_helper.h>
33#include <drm/drm_module.h>
33#include <drm/drm_of.h>34#include <drm/drm_of.h>
34#include <drm/drm_probe_helper.h>35#include <drm/drm_probe_helper.h>
35#include <drm/drm_vblank.h>36#include <drm/drm_vblank.h>
@@ -434,7 +435,7 @@ static struct platform_driver hdlcd_platform_driver = { · 398 unmodified lines
434 },435 },
435};436};
436 437
437module_platform_driver(hdlcd_platform_driver);438drm_module_platform_driver(hdlcd_platform_driver);
438 439
439MODULE_AUTHOR("Liviu Dudau");440MODULE_AUTHOR("Liviu Dudau");
440MODULE_DESCRIPTION("ARM HDLCD DRM driver");441MODULE_DESCRIPTION("ARM HDLCD DRM driver");
drivers/gpu/drm/arm/malidp_drv.c+2−1
@@ -25,6 +25,7 @@ · 24 unmodified lines
25#include <drm/drm_gem_cma_helper.h>25#include <drm/drm_gem_cma_helper.h>
26#include <drm/drm_gem_framebuffer_helper.h>26#include <drm/drm_gem_framebuffer_helper.h>
27#include <drm/drm_modeset_helper.h>27#include <drm/drm_modeset_helper.h>
28#include <drm/drm_module.h>
28#include <drm/drm_of.h>29#include <drm/drm_of.h>
29#include <drm/drm_probe_helper.h>30#include <drm/drm_probe_helper.h>
30#include <drm/drm_vblank.h>31#include <drm/drm_vblank.h>
@@ -1008,7 +1009,7 @@ static struct platform_driver malidp_platform_driver = { · 977 unmodified lines
1008 },1009 },
1009};1010};
1010 1011
1011module_platform_driver(malidp_platform_driver);1012drm_module_platform_driver(malidp_platform_driver);
1012 1013
1013MODULE_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");1014MODULE_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");
1014MODULE_DESCRIPTION("ARM Mali DP DRM driver");1015MODULE_DESCRIPTION("ARM Mali DP DRM driver");
drivers/gpu/drm/ast/ast_drv.c+2−16
@@ -34,6 +34,7 @@ · 33 unmodified lines
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_vram_helper.h>
37#include <drm/drm_module.h>
37#include <drm/drm_probe_helper.h>38#include <drm/drm_probe_helper.h>
38 39
39#include "ast_drv.h"40#include "ast_drv.h"
@@ -230,22 +231,7 @@ static struct pci_driver ast_pci_driver = { · 190 unmodified lines
230 .driver.pm = &ast_pm_ops,231 .driver.pm = &ast_pm_ops,
231};232};
232 233
233static int __init ast_init(void)234drm_module_pci_driver_if_modeset(ast_pci_driver, ast_modeset);
234{
235 if (drm_firmware_drivers_only() && ast_modeset == -1)
236 return -EINVAL;
237
238 if (ast_modeset == 0)
239 return -EINVAL;
240 return pci_register_driver(&ast_pci_driver);
241}
242static void __exit ast_exit(void)
243{
244 pci_unregister_driver(&ast_pci_driver);
245}
246
247module_init(ast_init);
248module_exit(ast_exit);
249 235
250MODULE_AUTHOR(DRIVER_AUTHOR);236MODULE_AUTHOR(DRIVER_AUTHOR);
251MODULE_DESCRIPTION(DRIVER_DESC);237MODULE_DESCRIPTION(DRIVER_DESC);
drivers/gpu/drm/ast/ast_main.c+2−0
@@ -209,6 +209,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) · 208 unmodified lines
209 if (ast->chip == AST2500 &&209 if (ast->chip == AST2500 &&
210 scu_rev == 0x100) /* ast2510 */210 scu_rev == 0x100) /* ast2510 */
211 ast->support_wide_screen = true;211 ast->support_wide_screen = true;
212 if (ast->chip == AST2600) /* ast2600 */
213 ast->support_wide_screen = true;
212 }214 }
213 break;215 break;
214 }216 }
drivers/gpu/drm/ast/ast_mode.c+4−1
@@ -471,7 +471,10 @@ static void ast_set_color_reg(struct ast_private *ast, · 470 unmodified lines
471static void ast_set_crtthd_reg(struct ast_private *ast)471static void ast_set_crtthd_reg(struct ast_private *ast)
472{472{
473 /* Set Threshold */473 /* Set Threshold */
474 if (ast->chip == AST2300 || ast->chip == AST2400 ||474 if (ast->chip == AST2600) {
475 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0xe0);
476 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0xa0);
477 } else if (ast->chip == AST2300 || ast->chip == AST2400 ||
475 ast->chip == AST2500) {478 ast->chip == AST2500) {
476 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);479 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
477 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);480 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
drivers/gpu/drm/bridge/Kconfig+5−0
@@ -30,6 +30,7 @@ config DRM_CDNS_DSI · 29 unmodified lines
30config DRM_CHIPONE_ICN621130config DRM_CHIPONE_ICN6211
31 tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"31 tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
32 depends on OF32 depends on OF
33 depends on DRM_KMS_HELPER
33 select DRM_MIPI_DSI34 select DRM_MIPI_DSI
34 select DRM_PANEL_BRIDGE35 select DRM_PANEL_BRIDGE
35 help36 help
@@ -183,6 +184,7 @@ config DRM_PARADE_PS8640 · 147 unmodified lines
183 tristate "Parade PS8640 MIPI DSI to eDP Converter"184 tristate "Parade PS8640 MIPI DSI to eDP Converter"
184 depends on OF185 depends on OF
185 select DRM_DP_AUX_BUS186 select DRM_DP_AUX_BUS
187 select DRM_DP_HELPER
186 select DRM_KMS_HELPER188 select DRM_KMS_HELPER
187 select DRM_MIPI_DSI189 select DRM_MIPI_DSI
188 select DRM_PANEL190 select DRM_PANEL
@@ -253,6 +255,7 @@ config DRM_TOSHIBA_TC358764 · 64 unmodified lines
253config DRM_TOSHIBA_TC358767255config DRM_TOSHIBA_TC358767
254 tristate "Toshiba TC358767 eDP bridge"256 tristate "Toshiba TC358767 eDP bridge"
255 depends on OF257 depends on OF
258 select DRM_DP_HELPER
256 select DRM_KMS_HELPER259 select DRM_KMS_HELPER
257 select REGMAP_I2C260 select REGMAP_I2C
258 select DRM_PANEL261 select DRM_PANEL
@@ -272,6 +275,7 @@ config DRM_TOSHIBA_TC358768 · 13 unmodified lines
272config DRM_TOSHIBA_TC358775275config DRM_TOSHIBA_TC358775
273 tristate "Toshiba TC358775 DSI/LVDS bridge"276 tristate "Toshiba TC358775 DSI/LVDS bridge"
274 depends on OF277 depends on OF
278 select DRM_DP_HELPER
275 select DRM_KMS_HELPER279 select DRM_KMS_HELPER
276 select REGMAP_I2C280 select REGMAP_I2C
277 select DRM_PANEL281 select DRM_PANEL
@@ -299,6 +303,7 @@ config DRM_TI_SN65DSI83 · 21 unmodified lines
299config DRM_TI_SN65DSI86303config DRM_TI_SN65DSI86
300 tristate "TI SN65DSI86 DSI to eDP bridge"304 tristate "TI SN65DSI86 DSI to eDP bridge"
301 depends on OF305 depends on OF
306 select DRM_DP_HELPER
302 select DRM_KMS_HELPER307 select DRM_KMS_HELPER
303 select REGMAP_I2C308 select REGMAP_I2C
304 select DRM_PANEL309 select DRM_PANEL
drivers/gpu/drm/bridge/adv7511/adv7511.h+1−0
@@ -169,6 +169,7 @@ · 168 unmodified lines
169#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)169#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)
170#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0)170#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0)
171 171
172#define ADV7535_REG_POWER2_HPD_OVERRIDE BIT(6)
172#define ADV7511_REG_POWER2_HPD_SRC_MASK 0xc0173#define ADV7511_REG_POWER2_HPD_SRC_MASK 0xc0
173#define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00174#define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00
174#define ADV7511_REG_POWER2_HPD_SRC_HPD 0x40175#define ADV7511_REG_POWER2_HPD_SRC_HPD 0x40
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c+23−8
@@ -223,7 +223,7 @@ static void adv7511_set_config_csc(struct adv7511 *adv7511, · 222 unmodified lines
223 config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;223 config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
224 224
225 if ((connector->display_info.color_formats &225 if ((connector->display_info.color_formats &
226 DRM_COLOR_FORMAT_YCRCB422) &&226 DRM_COLOR_FORMAT_YCBCR422) &&
227 config.hdmi_mode) {227 config.hdmi_mode) {
228 config.csc_enable = false;228 config.csc_enable = false;
229 config.avi_infoframe.colorspace =229 config.avi_infoframe.colorspace =
@@ -351,11 +351,17 @@ static void __adv7511_power_on(struct adv7511 *adv7511) · 121 unmodified lines
351 * from standby or are enabled. When the HPD goes low the adv7511 is351 * from standby or are enabled. When the HPD goes low the adv7511 is
352 * reset and the outputs are disabled which might cause the monitor to352 * reset and the outputs are disabled which might cause the monitor to
353 * go to standby again. To avoid this we ignore the HPD pin for the353 * go to standby again. To avoid this we ignore the HPD pin for the
354 * first few seconds after enabling the output.354 * first few seconds after enabling the output. On the other hand
355 * adv7535 require to enable HPD Override bit for proper HPD.
355 */356 */
356 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,357 if (adv7511->type == ADV7535)
357 ADV7511_REG_POWER2_HPD_SRC_MASK,358 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
358 ADV7511_REG_POWER2_HPD_SRC_NONE);359 ADV7535_REG_POWER2_HPD_OVERRIDE,
360 ADV7535_REG_POWER2_HPD_OVERRIDE);
361 else
362 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
363 ADV7511_REG_POWER2_HPD_SRC_MASK,
364 ADV7511_REG_POWER2_HPD_SRC_NONE);
359}365}
360 366
361static void adv7511_power_on(struct adv7511 *adv7511)367static void adv7511_power_on(struct adv7511 *adv7511)
@@ -375,6 +381,10 @@ static void adv7511_power_on(struct adv7511 *adv7511) · 13 unmodified lines
375static void __adv7511_power_off(struct adv7511 *adv7511)381static void __adv7511_power_off(struct adv7511 *adv7511)
376{382{
377 /* TODO: setup additional power down modes */383 /* TODO: setup additional power down modes */
384 if (adv7511->type == ADV7535)
385 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
386 ADV7535_REG_POWER2_HPD_OVERRIDE, 0);
387
378 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,388 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
379 ADV7511_POWER_POWER_DOWN,389 ADV7511_POWER_POWER_DOWN,
380 ADV7511_POWER_POWER_DOWN);390 ADV7511_POWER_POWER_DOWN);
@@ -672,9 +682,14 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector) · 291 unmodified lines
672 status = connector_status_disconnected;682 status = connector_status_disconnected;
673 } else {683 } else {
674 /* Renable HPD sensing */684 /* Renable HPD sensing */
675 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,685 if (adv7511->type == ADV7535)
676 ADV7511_REG_POWER2_HPD_SRC_MASK,686 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
677 ADV7511_REG_POWER2_HPD_SRC_BOTH);687 ADV7535_REG_POWER2_HPD_OVERRIDE,
688 ADV7535_REG_POWER2_HPD_OVERRIDE);
689 else
690 regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
691 ADV7511_REG_POWER2_HPD_SRC_MASK,
692 ADV7511_REG_POWER2_HPD_SRC_BOTH);
678 }693 }
679 694
680 adv7511->status = status;695 adv7511->status = status;
drivers/gpu/drm/bridge/adv7511/adv7533.c+1−1
@@ -29,7 +29,7 @@ static void adv7511_dsi_config_timing_gen(struct adv7511 *adv) · 28 unmodified lines
29 struct mipi_dsi_device *dsi = adv->dsi;29 struct mipi_dsi_device *dsi = adv->dsi;
30 struct drm_display_mode *mode = &adv->curr_mode;30 struct drm_display_mode *mode = &adv->curr_mode;
31 unsigned int hsw, hfp, hbp, vsw, vfp, vbp;31 unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
32 u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */32 static const u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
33 33
34 hsw = mode->hsync_end - mode->hsync_start;34 hsw = mode->hsync_end - mode->hsync_start;
35 hfp = mode->hsync_start - mode->hdisplay;35 hfp = mode->hsync_start - mode->hdisplay;
drivers/gpu/drm/bridge/analogix/Kconfig+2−0
@@ -3,6 +3,7 @@ config DRM_ANALOGIX_ANX6345 · 2 unmodified lines
3 tristate "Analogix ANX6345 bridge"3 tristate "Analogix ANX6345 bridge"
4 depends on OF4 depends on OF
5 select DRM_ANALOGIX_DP5 select DRM_ANALOGIX_DP
6 select DRM_DP_HELPER
6 select DRM_KMS_HELPER7 select DRM_KMS_HELPER
7 select REGMAP_I2C8 select REGMAP_I2C
8 help9 help
@@ -14,6 +15,7 @@ config DRM_ANALOGIX_ANX6345 · 5 unmodified lines
14config DRM_ANALOGIX_ANX78XX15config DRM_ANALOGIX_ANX78XX
15 tristate "Analogix ANX78XX bridge"16 tristate "Analogix ANX78XX bridge"
16 select DRM_ANALOGIX_DP17 select DRM_ANALOGIX_DP
18 select DRM_DP_HELPER
17 select DRM_KMS_HELPER19 select DRM_KMS_HELPER
18 select REGMAP_I2C20 select REGMAP_I2C
19 help21 help
drivers/gpu/drm/bridge/analogix/analogix-anx6345.c+1−1
@@ -22,7 +22,7 @@ · 21 unmodified lines
22#include <drm/drm_bridge.h>22#include <drm/drm_bridge.h>
23#include <drm/drm_crtc.h>23#include <drm/drm_crtc.h>
24#include <drm/drm_crtc_helper.h>24#include <drm/drm_crtc_helper.h>
25#include <drm/drm_dp_helper.h>25#include <drm/dp/drm_dp_helper.h>
26#include <drm/drm_edid.h>26#include <drm/drm_edid.h>
27#include <drm/drm_of.h>27#include <drm/drm_of.h>
28#include <drm/drm_panel.h>28#include <drm/drm_panel.h>
drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c+1−1
@@ -21,7 +21,7 @@ · 20 unmodified lines
21#include <drm/drm_atomic_helper.h>21#include <drm/drm_atomic_helper.h>
22#include <drm/drm_bridge.h>22#include <drm/drm_bridge.h>
23#include <drm/drm_crtc.h>23#include <drm/drm_crtc.h>
24#include <drm/drm_dp_helper.h>24#include <drm/dp/drm_dp_helper.h>
25#include <drm/drm_edid.h>25#include <drm/drm_edid.h>
26#include <drm/drm_print.h>26#include <drm/drm_print.h>
27#include <drm/drm_probe_helper.h>27#include <drm/drm_probe_helper.h>
drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c+1−1
@@ -8,7 +8,7 @@ · 7 unmodified lines
8#include <linux/regmap.h>8#include <linux/regmap.h>
9 9
10#include <drm/drm.h>10#include <drm/drm.h>
11#include <drm/drm_dp_helper.h>11#include <drm/dp/drm_dp_helper.h>
12#include <drm/drm_print.h>12#include <drm/drm_print.h>
13 13
14#include "analogix-i2c-dptx.h"14#include "analogix-i2c-dptx.h"
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c+2−2
@@ -1537,9 +1537,9 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, · 1536 unmodified lines
1537 video->color_depth = COLOR_8;1537 video->color_depth = COLOR_8;
1538 break;1538 break;
1539 }1539 }
1540 if (display_info->color_formats & DRM_COLOR_FORMAT_YCRCB444)1540 if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
1541 video->color_space = COLOR_YCBCR444;1541 video->color_space = COLOR_YCBCR444;
1542 else if (display_info->color_formats & DRM_COLOR_FORMAT_YCRCB422)1542 else if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
1543 video->color_space = COLOR_YCBCR422;1543 video->color_space = COLOR_YCBCR422;
1544 else1544 else
1545 video->color_space = COLOR_RGB;1545 video->color_space = COLOR_RGB;
drivers/gpu/drm/bridge/analogix/analogix_dp_core.h+1−1
@@ -10,7 +10,7 @@ · 9 unmodified lines
10#define _ANALOGIX_DP_CORE_H10#define _ANALOGIX_DP_CORE_H
11 11
12#include <drm/drm_crtc.h>12#include <drm/drm_crtc.h>
13#include <drm/drm_dp_helper.h>13#include <drm/dp/drm_dp_helper.h>
14 14
15#define DP_TIMEOUT_LOOP_COUNT 10015#define DP_TIMEOUT_LOOP_COUNT 100
16#define MAX_CR_LOOP 516#define MAX_CR_LOOP 5
drivers/gpu/drm/bridge/analogix/anx7625.c+421−19
@@ -24,8 +24,9 @@ · 23 unmodified lines
24#include <drm/drm_atomic_helper.h>24#include <drm/drm_atomic_helper.h>
25#include <drm/drm_bridge.h>25#include <drm/drm_bridge.h>
26#include <drm/drm_crtc_helper.h>26#include <drm/drm_crtc_helper.h>
27#include <drm/drm_dp_helper.h>27#include <drm/dp/drm_dp_helper.h>
28#include <drm/drm_edid.h>28#include <drm/drm_edid.h>
29#include <drm/drm_hdcp.h>
29#include <drm/drm_mipi_dsi.h>30#include <drm/drm_mipi_dsi.h>
30#include <drm/drm_of.h>31#include <drm/drm_of.h>
31#include <drm/drm_panel.h>32#include <drm/drm_panel.h>
@@ -213,6 +214,65 @@ static int wait_aux_op_finish(struct anx7625_data *ctx) · 181 unmodified lines
213 return 0;214 return 0;
214}215}
215 216
217static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
218 u32 address, u8 len, u8 *buf)
219{
220 struct device *dev = &ctx->client->dev;
221 int ret;
222 u8 addrh, addrm, addrl;
223 u8 cmd;
224
225 if (len > MAX_DPCD_BUFFER_SIZE) {
226 dev_err(dev, "exceed aux buffer len.\n");
227 return -EINVAL;
228 }
229
230 addrl = address & 0xFF;
231 addrm = (address >> 8) & 0xFF;
232 addrh = (address >> 16) & 0xFF;
233
234 cmd = DPCD_CMD(len, DPCD_READ);
235 cmd = ((len - 1) << 4) | 0x09;
236
237 /* Set command and length */
238 ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
239 AP_AUX_COMMAND, cmd);
240
241 /* Set aux access address */
242 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
243 AP_AUX_ADDR_7_0, addrl);
244 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
245 AP_AUX_ADDR_15_8, addrm);
246 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
247 AP_AUX_ADDR_19_16, addrh);
248
249 /* Enable aux access */
250 ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
251 AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
252
253 if (ret < 0) {
254 dev_err(dev, "cannot access aux related register.\n");
255 return -EIO;
256 }
257
258 usleep_range(2000, 2100);
259
260 ret = wait_aux_op_finish(ctx);
261 if (ret) {
262 dev_err(dev, "aux IO error: wait aux op finish.\n");
263 return ret;
264 }
265
266 ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
267 AP_AUX_BUFF_START, len, buf);
268 if (ret < 0) {
269 dev_err(dev, "read dpcd register failed\n");
270 return -EIO;
271 }
272
273 return 0;
274}
275
216static int anx7625_video_mute_control(struct anx7625_data *ctx,276static int anx7625_video_mute_control(struct anx7625_data *ctx,
217 u8 status)277 u8 status)
218{278{
@@ -669,6 +729,165 @@ static int anx7625_dpi_config(struct anx7625_data *ctx) · 450 unmodified lines
669 return ret;729 return ret;
670}730}
671 731
732static int anx7625_read_flash_status(struct anx7625_data *ctx)
733{
734 return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
735}
736
737static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
738{
739 int ret, val;
740 struct device *dev = &ctx->client->dev;
741 u8 ident[FLASH_BUF_LEN];
742
743 ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
744 FLASH_ADDR_HIGH, 0x91);
745 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
746 FLASH_ADDR_LOW, 0xA0);
747 if (ret < 0) {
748 dev_err(dev, "IO error : set key flash address.\n");
749 return ret;
750 }
751
752 ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
753 FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
754 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
755 FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
756 if (ret < 0) {
757 dev_err(dev, "IO error : set key flash len.\n");
758 return ret;
759 }
760
761 ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
762 R_FLASH_RW_CTRL, FLASH_READ);
763 ret |= readx_poll_timeout(anx7625_read_flash_status,
764 ctx, val,
765 ((val & FLASH_DONE) || (val < 0)),
766 2000,
767 2000 * 150);
768 if (ret) {
769 dev_err(dev, "flash read access fail!\n");
770 return -EIO;
771 }
772
773 ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
774 FLASH_BUF_BASE_ADDR,
775 FLASH_BUF_LEN, ident);
776 if (ret < 0) {
777 dev_err(dev, "read flash data fail!\n");
778 return -EIO;
779 }
780
781 if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
782 return -EINVAL;
783
784 return 0;
785}
786
787static int anx7625_hdcp_key_load(struct anx7625_data *ctx)
788{
789 int ret;
790 struct device *dev = &ctx->client->dev;
791
792 /* Select HDCP 1.4 KEY */
793 ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
794 R_BOOT_RETRY, 0x12);
795 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
796 FLASH_ADDR_HIGH, HDCP14KEY_START_ADDR >> 8);
797 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
798 FLASH_ADDR_LOW, HDCP14KEY_START_ADDR & 0xFF);
799 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
800 R_RAM_LEN_H, HDCP14KEY_SIZE >> 12);
801 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
802 R_RAM_LEN_L, HDCP14KEY_SIZE >> 4);
803
804 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
805 R_RAM_ADDR_H, 0);
806 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
807 R_RAM_ADDR_L, 0);
808 /* Enable HDCP 1.4 KEY load */
809 ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
810 R_RAM_CTRL, DECRYPT_EN | LOAD_START);
811 dev_dbg(dev, "load HDCP 1.4 key done\n");
812 return ret;
813}
814
815static int anx7625_hdcp_disable(struct anx7625_data *ctx)
816{
817 int ret;
818 struct device *dev = &ctx->client->dev;
819
820 dev_dbg(dev, "disable HDCP 1.4\n");
821
822 /* Disable HDCP */
823 ret = anx7625_write_and(ctx, ctx->i2c.rx_p1_client, 0xee, 0x9f);
824 /* Try auth flag */
825 ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
826 /* Interrupt for DRM */
827 ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
828 if (ret < 0)
829 dev_err(dev, "fail to disable HDCP\n");
830
831 return anx7625_write_and(ctx, ctx->i2c.tx_p0_client,
832 TX_HDCP_CTRL0, ~HARD_AUTH_EN & 0xFF);
833}
834
835static int anx7625_hdcp_enable(struct anx7625_data *ctx)
836{
837 u8 bcap;
838 int ret;
839 struct device *dev = &ctx->client->dev;
840
841 ret = anx7625_hdcp_key_probe(ctx);
842 if (ret) {
843 dev_dbg(dev, "no key found, not to do hdcp\n");
844 return ret;
845 }
846
847 /* Read downstream capability */
848 anx7625_aux_dpcd_read(ctx, 0x68028, 1, &bcap);
849 if (!(bcap & 0x01)) {
850 pr_warn("downstream not support HDCP 1.4, cap(%x).\n", bcap);
851 return 0;
852 }
853
854 dev_dbg(dev, "enable HDCP 1.4\n");
855
856 /* First clear HDCP state */
857 ret = anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
858 TX_HDCP_CTRL0,
859 KSVLIST_VLD | BKSV_SRM_PASS | RE_AUTHEN);
860 usleep_range(1000, 1100);
861 /* Second clear HDCP state */
862 ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
863 TX_HDCP_CTRL0,
864 KSVLIST_VLD | BKSV_SRM_PASS | RE_AUTHEN);
865
866 /* Set time for waiting KSVR */
867 ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
868 SP_TX_WAIT_KSVR_TIME, 0xc8);
869 /* Set time for waiting R0 */
870 ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
871 SP_TX_WAIT_R0_TIME, 0xb0);
872 ret |= anx7625_hdcp_key_load(ctx);
873 if (ret) {
874 pr_warn("prepare HDCP key failed.\n");
875 return ret;
876 }
877
878 ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
879
880 /* Try auth flag */
881 ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
882 /* Interrupt for DRM */
883 ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
884 if (ret < 0)
885 dev_err(dev, "fail to enable HDCP\n");
886
887 return anx7625_write_or(ctx, ctx->i2c.tx_p0_client,
888 TX_HDCP_CTRL0, HARD_AUTH_EN);
889}
890
672static void anx7625_dp_start(struct anx7625_data *ctx)891static void anx7625_dp_start(struct anx7625_data *ctx)
673{892{
674 int ret;893 int ret;
@@ -679,6 +898,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx) · 4 unmodified lines
679 return;898 return;
680 }899 }
681 900
901 /* Disable HDCP */
902 anx7625_write_and(ctx, ctx->i2c.rx_p1_client, 0xee, 0x9f);
903
682 if (ctx->pdata.is_dpi)904 if (ctx->pdata.is_dpi)
683 ret = anx7625_dpi_config(ctx);905 ret = anx7625_dpi_config(ctx);
684 else906 else
@@ -686,6 +908,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx) · 1 unmodified line
686 908
687 if (ret < 0)909 if (ret < 0)
688 DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");910 DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
911
912 ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
913
914 ctx->dp_en = 1;
689}915}
690 916
691static void anx7625_dp_stop(struct anx7625_data *ctx)917static void anx7625_dp_stop(struct anx7625_data *ctx)
@@ -705,6 +931,10 @@ static void anx7625_dp_stop(struct anx7625_data *ctx) · 13 unmodified lines
705 ret |= anx7625_video_mute_control(ctx, 1);931 ret |= anx7625_video_mute_control(ctx, 1);
706 if (ret < 0)932 if (ret < 0)
707 DRM_DEV_ERROR(dev, "IO error : mute video fail\n");933 DRM_DEV_ERROR(dev, "IO error : mute video fail\n");
934
935 ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
936
937 ctx->dp_en = 0;
708}938}
709 939
710static int sp_tx_rst_aux(struct anx7625_data *ctx)940static int sp_tx_rst_aux(struct anx7625_data *ctx)
@@ -1098,9 +1328,18 @@ static void anx7625_init_gpio(struct anx7625_data *platform) · 387 unmodified lines
1098 /* Gpio for chip power enable */1328 /* Gpio for chip power enable */
1099 platform->pdata.gpio_p_on =1329 platform->pdata.gpio_p_on =
1100 devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);1330 devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
1331 if (IS_ERR_OR_NULL(platform->pdata.gpio_p_on)) {
1332 DRM_DEV_DEBUG_DRIVER(dev, "no enable gpio found\n");
1333 platform->pdata.gpio_p_on = NULL;
1334 }
1335
1101 /* Gpio for chip reset */1336 /* Gpio for chip reset */
1102 platform->pdata.gpio_reset =1337 platform->pdata.gpio_reset =
1103 devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);1338 devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
1339 if (IS_ERR_OR_NULL(platform->pdata.gpio_reset)) {
1340 DRM_DEV_DEBUG_DRIVER(dev, "no reset gpio found\n");
1341 platform->pdata.gpio_reset = NULL;
1342 }
1104 1343
1105 if (platform->pdata.gpio_p_on && platform->pdata.gpio_reset) {1344 if (platform->pdata.gpio_p_on && platform->pdata.gpio_reset) {
1106 platform->pdata.low_power_mode = 1;1345 platform->pdata.low_power_mode = 1;
@@ -1601,9 +1840,27 @@ static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data, · 494 unmodified lines
1601 return 0;1840 return 0;
1602}1841}
1603 1842
1843static int anx7625_audio_get_eld(struct device *dev, void *data,
1844 u8 *buf, size_t len)
1845{
1846 struct anx7625_data *ctx = dev_get_drvdata(dev);
1847
1848 if (!ctx->connector) {
1849 dev_err(dev, "connector not initial\n");
1850 return -EINVAL;
1851 }
1852
1853 dev_dbg(dev, "audio copy eld\n");
1854 memcpy(buf, ctx->connector->eld,
1855 min(sizeof(ctx->connector->eld), len));
1856
1857 return 0;
1858}
1859
1604static const struct hdmi_codec_ops anx7625_codec_ops = {1860static const struct hdmi_codec_ops anx7625_codec_ops = {
1605 .hw_params = anx7625_audio_hw_params,1861 .hw_params = anx7625_audio_hw_params,
1606 .audio_shutdown = anx7625_audio_shutdown,1862 .audio_shutdown = anx7625_audio_shutdown,
1863 .get_eld = anx7625_audio_get_eld,
1607 .get_dai_id = anx7625_hdmi_i2s_get_dai_id,1864 .get_dai_id = anx7625_hdmi_i2s_get_dai_id,
1608 .hook_plugged_cb = anx7625_audio_hook_plugged_cb,1865 .hook_plugged_cb = anx7625_audio_hook_plugged_cb,
1609};1866};
@@ -1660,7 +1917,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx) · 50 unmodified lines
1660 host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);1917 host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);
1661 if (!host) {1918 if (!host) {
1662 DRM_DEV_ERROR(dev, "fail to find dsi host.\n");1919 DRM_DEV_ERROR(dev, "fail to find dsi host.\n");
1663 return -EINVAL;1920 return -EPROBE_DEFER;
1664 }1921 }
1665 1922
1666 dsi = devm_mipi_dsi_device_register_full(dev, host, &info);1923 dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
@@ -1688,6 +1945,83 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx) · 21 unmodified lines
1688 return 0;1945 return 0;
1689}1946}
1690 1947
1948static void hdcp_check_work_func(struct work_struct *work)
1949{
1950 u8 status;
1951 struct delayed_work *dwork;
1952 struct anx7625_data *ctx;
1953 struct device *dev;
1954 struct drm_device *drm_dev;
1955
1956 dwork = to_delayed_work(work);
1957 ctx = container_of(dwork, struct anx7625_data, hdcp_work);
1958 dev = &ctx->client->dev;
1959
1960 if (!ctx->connector) {
1961 dev_err(dev, "HDCP connector is null!");
1962 return;
1963 }
1964
1965 drm_dev = ctx->connector->dev;
1966 drm_modeset_lock(&drm_dev->mode_config.connection_mutex, NULL);
1967 mutex_lock(&ctx->hdcp_wq_lock);
1968
1969 status = anx7625_reg_read(ctx, ctx->i2c.tx_p0_client, 0);
1970 dev_dbg(dev, "sink HDCP status check: %.02x\n", status);
1971 if (status & BIT(1)) {
1972 ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_ENABLED;
1973 drm_hdcp_update_content_protection(ctx->connector,
1974 ctx->hdcp_cp);
1975 dev_dbg(dev, "update CP to ENABLE\n");
1976 }
1977
1978 mutex_unlock(&ctx->hdcp_wq_lock);
1979 drm_modeset_unlock(&drm_dev->mode_config.connection_mutex);
1980}
1981
1982static int anx7625_connector_atomic_check(struct anx7625_data *ctx,
1983 struct drm_connector_state *state)
1984{
1985 struct device *dev = &ctx->client->dev;
1986 int cp;
1987
1988 dev_dbg(dev, "hdcp state check\n");
1989 cp = state->content_protection;
1990
1991 if (cp == ctx->hdcp_cp)
1992 return 0;
1993
1994 if (cp == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
1995 if (ctx->dp_en) {
1996 dev_dbg(dev, "enable HDCP\n");
1997 anx7625_hdcp_enable(ctx);
1998
1999 queue_delayed_work(ctx->hdcp_workqueue,
2000 &ctx->hdcp_work,
2001 msecs_to_jiffies(2000));
2002 }
2003 }
2004
2005 if (cp == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
2006 if (ctx->hdcp_cp != DRM_MODE_CONTENT_PROTECTION_ENABLED) {
2007 dev_err(dev, "current CP is not ENABLED\n");
2008 return -EINVAL;
2009 }
2010 anx7625_hdcp_disable(ctx);
2011 ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
2012 drm_hdcp_update_content_protection(ctx->connector,
2013 ctx->hdcp_cp);
2014 dev_dbg(dev, "update CP to UNDESIRE\n");
2015 }
2016
2017 if (cp == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
2018 dev_err(dev, "Userspace illegal set to PROTECTION ENABLE\n");
2019 return -EINVAL;
2020 }
2021
2022 return 0;
2023}
2024
1691static int anx7625_bridge_attach(struct drm_bridge *bridge,2025static int anx7625_bridge_attach(struct drm_bridge *bridge,
1692 enum drm_bridge_attach_flags flags)2026 enum drm_bridge_attach_flags flags)
1693{2027{
@@ -1902,25 +2236,57 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge, · 208 unmodified lines
1902 return true;2236 return true;
1903}2237}
1904 2238
1905static void anx7625_bridge_enable(struct drm_bridge *bridge)2239static int anx7625_bridge_atomic_check(struct drm_bridge *bridge,
2240 struct drm_bridge_state *bridge_state,
2241 struct drm_crtc_state *crtc_state,
2242 struct drm_connector_state *conn_state)
2243{
2244 struct anx7625_data *ctx = bridge_to_anx7625(bridge);
2245 struct device *dev = &ctx->client->dev;
2246
2247 dev_dbg(dev, "drm bridge atomic check\n");
2248
2249 anx7625_bridge_mode_fixup(bridge, &crtc_state->mode,
2250 &crtc_state->adjusted_mode);
2251
2252 return anx7625_connector_atomic_check(ctx, conn_state);
2253}
2254
2255static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
2256 struct drm_bridge_state *state)
1906{2257{
1907 struct anx7625_data *ctx = bridge_to_anx7625(bridge);2258 struct anx7625_data *ctx = bridge_to_anx7625(bridge);
1908 struct device *dev = &ctx->client->dev;2259 struct device *dev = &ctx->client->dev;
2260 struct drm_connector *connector;
1909 2261
1910 DRM_DEV_DEBUG_DRIVER(dev, "drm enable\n");2262 dev_dbg(dev, "drm atomic enable\n");
2263
2264 if (!bridge->encoder) {
2265 dev_err(dev, "Parent encoder object not found");
2266 return;
2267 }
2268
2269 connector = drm_atomic_get_new_connector_for_encoder(state->base.state,
2270 bridge->encoder);
2271 if (!connector)
2272 return;
2273
2274 ctx->connector = connector;
1911 2275
1912 pm_runtime_get_sync(dev);2276 pm_runtime_get_sync(dev);
1913 2277
1914 anx7625_dp_start(ctx);2278 anx7625_dp_start(ctx);
1915}2279}
1916 2280
1917static void anx7625_bridge_disable(struct drm_bridge *bridge)2281static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge,
2282 struct drm_bridge_state *old)
1918{2283{
1919 struct anx7625_data *ctx = bridge_to_anx7625(bridge);2284 struct anx7625_data *ctx = bridge_to_anx7625(bridge);
1920 struct device *dev = &ctx->client->dev;2285 struct device *dev = &ctx->client->dev;
1921 2286
1922 DRM_DEV_DEBUG_DRIVER(dev, "drm disable\n");2287 dev_dbg(dev, "drm atomic disable\n");
1923 2288
2289 ctx->connector = NULL;
1924 anx7625_dp_stop(ctx);2290 anx7625_dp_stop(ctx);
1925 2291
1926 pm_runtime_put_sync(dev);2292 pm_runtime_put_sync(dev);
@@ -1950,11 +2316,14 @@ static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge, · 23 unmodified lines
1950 2316
1951static const struct drm_bridge_funcs anx7625_bridge_funcs = {2317static const struct drm_bridge_funcs anx7625_bridge_funcs = {
1952 .attach = anx7625_bridge_attach,2318 .attach = anx7625_bridge_attach,
1953 .disable = anx7625_bridge_disable,
1954 .mode_valid = anx7625_bridge_mode_valid,2319 .mode_valid = anx7625_bridge_mode_valid,
1955 .mode_set = anx7625_bridge_mode_set,2320 .mode_set = anx7625_bridge_mode_set,
1956 .mode_fixup = anx7625_bridge_mode_fixup,2321 .atomic_check = anx7625_bridge_atomic_check,
1957 .enable = anx7625_bridge_enable,2322 .atomic_enable = anx7625_bridge_atomic_enable,
2323 .atomic_disable = anx7625_bridge_atomic_disable,
2324 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
2325 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
2326 .atomic_reset = drm_atomic_helper_bridge_reset,
1958 .detect = anx7625_bridge_detect,2327 .detect = anx7625_bridge_detect,
1959 .get_edid = anx7625_bridge_get_edid,2328 .get_edid = anx7625_bridge_get_edid,
1960};2329};
@@ -1962,40 +2331,54 @@ static const struct drm_bridge_funcs anx7625_bridge_funcs = { · 1 unmodified line
1962static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,2331static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
1963 struct i2c_client *client)2332 struct i2c_client *client)
1964{2333{
2334 int err = 0;
2335
1965 ctx->i2c.tx_p0_client = i2c_new_dummy_device(client->adapter,2336 ctx->i2c.tx_p0_client = i2c_new_dummy_device(client->adapter,
1966 TX_P0_ADDR >> 1);2337 TX_P0_ADDR >> 1);
1967 if (!ctx->i2c.tx_p0_client)2338 if (IS_ERR(ctx->i2c.tx_p0_client))
1968 return -ENOMEM;2339 return PTR_ERR(ctx->i2c.tx_p0_client);
1969 2340
1970 ctx->i2c.tx_p1_client = i2c_new_dummy_device(client->adapter,2341 ctx->i2c.tx_p1_client = i2c_new_dummy_device(client->adapter,
1971 TX_P1_ADDR >> 1);2342 TX_P1_ADDR >> 1);
1972 if (!ctx->i2c.tx_p1_client)2343 if (IS_ERR(ctx->i2c.tx_p1_client)) {
2344 err = PTR_ERR(ctx->i2c.tx_p1_client);
1973 goto free_tx_p0;2345 goto free_tx_p0;
2346 }
1974 2347
1975 ctx->i2c.tx_p2_client = i2c_new_dummy_device(client->adapter,2348 ctx->i2c.tx_p2_client = i2c_new_dummy_device(client->adapter,
1976 TX_P2_ADDR >> 1);2349 TX_P2_ADDR >> 1);
1977 if (!ctx->i2c.tx_p2_client)2350 if (IS_ERR(ctx->i2c.tx_p2_client)) {
2351 err = PTR_ERR(ctx->i2c.tx_p2_client);
1978 goto free_tx_p1;2352 goto free_tx_p1;
2353 }
1979 2354
1980 ctx->i2c.rx_p0_client = i2c_new_dummy_device(client->adapter,2355 ctx->i2c.rx_p0_client = i2c_new_dummy_device(client->adapter,
1981 RX_P0_ADDR >> 1);2356 RX_P0_ADDR >> 1);
1982 if (!ctx->i2c.rx_p0_client)2357 if (IS_ERR(ctx->i2c.rx_p0_client)) {
2358 err = PTR_ERR(ctx->i2c.rx_p0_client);
1983 goto free_tx_p2;2359 goto free_tx_p2;
2360 }
1984 2361
1985 ctx->i2c.rx_p1_client = i2c_new_dummy_device(client->adapter,2362 ctx->i2c.rx_p1_client = i2c_new_dummy_device(client->adapter,
1986 RX_P1_ADDR >> 1);2363 RX_P1_ADDR >> 1);
1987 if (!ctx->i2c.rx_p1_client)2364 if (IS_ERR(ctx->i2c.rx_p1_client)) {
2365 err = PTR_ERR(ctx->i2c.rx_p1_client);
1988 goto free_rx_p0;2366 goto free_rx_p0;
2367 }
1989 2368
1990 ctx->i2c.rx_p2_client = i2c_new_dummy_device(client->adapter,2369 ctx->i2c.rx_p2_client = i2c_new_dummy_device(client->adapter,
1991 RX_P2_ADDR >> 1);2370 RX_P2_ADDR >> 1);
1992 if (!ctx->i2c.rx_p2_client)2371 if (IS_ERR(ctx->i2c.rx_p2_client)) {
2372 err = PTR_ERR(ctx->i2c.rx_p2_client);
1993 goto free_rx_p1;2373 goto free_rx_p1;
2374 }
1994 2375
1995 ctx->i2c.tcpc_client = i2c_new_dummy_device(client->adapter,2376 ctx->i2c.tcpc_client = i2c_new_dummy_device(client->adapter,
1996 TCPC_INTERFACE_ADDR >> 1);2377 TCPC_INTERFACE_ADDR >> 1);
1997 if (!ctx->i2c.tcpc_client)2378 if (IS_ERR(ctx->i2c.tcpc_client)) {
2379 err = PTR_ERR(ctx->i2c.tcpc_client);
1998 goto free_rx_p2;2380 goto free_rx_p2;
2381 }
1999 2382
2000 return 0;2383 return 0;
2001 2384
@@ -2012,7 +2395,7 @@ free_tx_p1: · 10 unmodified lines
2012free_tx_p0:2395free_tx_p0:
2013 i2c_unregister_device(ctx->i2c.tx_p0_client);2396 i2c_unregister_device(ctx->i2c.tx_p0_client);
2014 2397
2015 return -ENOMEM;2398 return err;
2016}2399}
2017 2400
2018static void anx7625_unregister_i2c_dummy_clients(struct anx7625_data *ctx)2401static void anx7625_unregister_i2c_dummy_clients(struct anx7625_data *ctx)
@@ -2134,6 +2517,15 @@ static int anx7625_i2c_probe(struct i2c_client *client, · 115 unmodified lines
2134 anx7625_init_gpio(platform);2517 anx7625_init_gpio(platform);
2135 2518
2136 mutex_init(&platform->lock);2519 mutex_init(&platform->lock);
2520 mutex_init(&platform->hdcp_wq_lock);
2521
2522 INIT_DELAYED_WORK(&platform->hdcp_work, hdcp_check_work_func);
2523 platform->hdcp_workqueue = create_workqueue("hdcp workqueue");
2524 if (!platform->hdcp_workqueue) {
2525 dev_err(dev, "fail to create work queue\n");
2526 ret = -ENOMEM;
2527 goto free_platform;
2528 }
2137 2529
2138 platform->pdata.intp_irq = client->irq;2530 platform->pdata.intp_irq = client->irq;
2139 if (platform->pdata.intp_irq) {2531 if (platform->pdata.intp_irq) {
@@ -2143,7 +2535,7 @@ static int anx7625_i2c_probe(struct i2c_client *client, · 3 unmodified lines
2143 if (!platform->workqueue) {2535 if (!platform->workqueue) {
2144 DRM_DEV_ERROR(dev, "fail to create work queue\n");2536 DRM_DEV_ERROR(dev, "fail to create work queue\n");
2145 ret = -ENOMEM;2537 ret = -ENOMEM;
2146 goto free_platform;2538 goto free_hdcp_wq;
2147 }2539 }
2148 2540
2149 ret = devm_request_threaded_irq(dev, platform->pdata.intp_irq,2541 ret = devm_request_threaded_irq(dev, platform->pdata.intp_irq,
@@ -2213,6 +2605,10 @@ free_wq: · 63 unmodified lines
2213 if (platform->workqueue)2605 if (platform->workqueue)
2214 destroy_workqueue(platform->workqueue);2606 destroy_workqueue(platform->workqueue);
2215 2607
2608free_hdcp_wq:
2609 if (platform->hdcp_workqueue)
2610 destroy_workqueue(platform->hdcp_workqueue);
2611
2216free_platform:2612free_platform:
2217 kfree(platform);2613 kfree(platform);
2218 2614
@@ -2228,6 +2624,12 @@ static int anx7625_i2c_remove(struct i2c_client *client) · 9 unmodified lines
2228 if (platform->pdata.intp_irq)2624 if (platform->pdata.intp_irq)
2229 destroy_workqueue(platform->workqueue);2625 destroy_workqueue(platform->workqueue);
2230 2626
2627 if (platform->hdcp_workqueue) {
2628 cancel_delayed_work(&platform->hdcp_work);
2629 flush_workqueue(platform->workqueue);
2630 destroy_workqueue(platform->workqueue);
2631 }
2632
2231 if (!platform->pdata.low_power_mode)2633 if (!platform->pdata.low_power_mode)
2232 pm_runtime_put_sync_suspend(&client->dev);2634 pm_runtime_put_sync_suspend(&client->dev);
2233 2635
drivers/gpu/drm/bridge/analogix/anx7625.h+73−7
@@ -59,10 +59,23 @@ · 58 unmodified lines
59 59
60/***************************************************************/60/***************************************************************/
61/* Register definition of device address 0x70 */61/* Register definition of device address 0x70 */
62#define I2C_ADDR_70_DPTX 0x7062#define TX_HDCP_CTRL0 0x01
63 63#define STORE_AN BIT(7)
64#define SP_TX_LINK_BW_SET_REG 0xA064#define RX_REPEATER BIT(6)
65#define SP_TX_LANE_COUNT_SET_REG 0xA165#define RE_AUTHEN BIT(5)
66#define SW_AUTH_OK BIT(4)
67#define HARD_AUTH_EN BIT(3)
68#define ENC_EN BIT(2)
69#define BKSV_SRM_PASS BIT(1)
70#define KSVLIST_VLD BIT(0)
71
72#define SP_TX_WAIT_R0_TIME 0x40
73#define SP_TX_WAIT_KSVR_TIME 0x42
74#define SP_TX_SYS_CTRL1_REG 0x80
75#define HDCP2TX_FW_EN BIT(4)
76
77#define SP_TX_LINK_BW_SET_REG 0xA0
78#define SP_TX_LANE_COUNT_SET_REG 0xA1
66 79
67#define M_VID_0 0xC080#define M_VID_0 0xC0
68#define M_VID_1 0xC181#define M_VID_1 0xC1
@@ -71,6 +84,12 @@ · 2 unmodified lines
71#define N_VID_1 0xC484#define N_VID_1 0xC4
72#define N_VID_2 0xC585#define N_VID_2 0xC5
73 86
87#define KEY_START_ADDR 0x9000
88#define KEY_RESERVED 416
89
90#define HDCP14KEY_START_ADDR (KEY_START_ADDR + KEY_RESERVED)
91#define HDCP14KEY_SIZE 624
92
74/***************************************************************/93/***************************************************************/
75/* Register definition of device address 0x72 */94/* Register definition of device address 0x72 */
76#define AUX_RST 0x0495#define AUX_RST 0x04
@@ -155,9 +174,43 @@ · 78 unmodified lines
155 174
156#define I2C_ADDR_7E_FLASH_CONTROLLER 0x7E175#define I2C_ADDR_7E_FLASH_CONTROLLER 0x7E
157 176
177#define R_BOOT_RETRY 0x00
178#define R_RAM_ADDR_H 0x01
179#define R_RAM_ADDR_L 0x02
180#define R_RAM_LEN_H 0x03
181#define R_RAM_LEN_L 0x04
158#define FLASH_LOAD_STA 0x05182#define FLASH_LOAD_STA 0x05
159#define FLASH_LOAD_STA_CHK BIT(7)183#define FLASH_LOAD_STA_CHK BIT(7)
160 184
185#define R_RAM_CTRL 0x05
186/* bit positions */
187#define FLASH_DONE BIT(7)
188#define BOOT_LOAD_DONE BIT(6)
189#define CRC_OK BIT(5)
190#define LOAD_DONE BIT(4)
191#define O_RW_DONE BIT(3)
192#define FUSE_BUSY BIT(2)
193#define DECRYPT_EN BIT(1)
194#define LOAD_START BIT(0)
195
196#define FLASH_ADDR_HIGH 0x0F
197#define FLASH_ADDR_LOW 0x10
198#define FLASH_LEN_HIGH 0x31
199#define FLASH_LEN_LOW 0x32
200#define R_FLASH_RW_CTRL 0x33
201/* bit positions */
202#define READ_DELAY_SELECT BIT(7)
203#define GENERAL_INSTRUCTION_EN BIT(6)
204#define FLASH_ERASE_EN BIT(5)
205#define RDID_READ_EN BIT(4)
206#define REMS_READ_EN BIT(3)
207#define WRITE_STATUS_EN BIT(2)
208#define FLASH_READ BIT(1)
209#define FLASH_WRITE BIT(0)
210
211#define FLASH_BUF_BASE_ADDR 0x60
212#define FLASH_BUF_LEN 0x20
213
161#define XTAL_FRQ_SEL 0x3F214#define XTAL_FRQ_SEL 0x3F
162/* bit field positions */215/* bit field positions */
163#define XTAL_FRQ_SEL_POS 5216#define XTAL_FRQ_SEL_POS 5
@@ -184,10 +237,15 @@ · 20 unmodified lines
184#define AP_AUX_CTRL_ADDRONLY 0x20237#define AP_AUX_CTRL_ADDRONLY 0x20
185 238
186#define AP_AUX_BUFF_START 0x15239#define AP_AUX_BUFF_START 0x15
187#define PIXEL_CLOCK_L 0x25240#define PIXEL_CLOCK_L 0x25
188#define PIXEL_CLOCK_H 0x26241#define PIXEL_CLOCK_H 0x26
242
243#define AP_AUX_COMMAND 0x27 /* com+len */
244#define LENGTH_SHIFT 4
245#define DPCD_READ 0x09
246#define DPCD_WRITE 0x08
247#define DPCD_CMD(len, cmd) ((((len) - 1) << LENGTH_SHIFT) | (cmd))
189 248
190#define AP_AUX_COMMAND 0x27 /* com+len */
191/* Bit 0&1: 3D video structure */249/* Bit 0&1: 3D video structure */
192/* 0x01: frame packing, 0x02:Line alternative, 0x03:Side-by-side(full) */250/* 0x01: frame packing, 0x02:Line alternative, 0x03:Side-by-side(full) */
193#define AP_AV_STATUS 0x28251#define AP_AV_STATUS 0x28
@@ -392,21 +450,29 @@ struct anx7625_data { · 198 unmodified lines
392 struct platform_device *audio_pdev;450 struct platform_device *audio_pdev;
393 int hpd_status;451 int hpd_status;
394 int hpd_high_cnt;452 int hpd_high_cnt;
453 int dp_en;
454 int hdcp_cp;
395 /* Lock for work queue */455 /* Lock for work queue */
396 struct mutex lock;456 struct mutex lock;
397 struct i2c_client *client;457 struct i2c_client *client;
398 struct anx7625_i2c_client i2c;458 struct anx7625_i2c_client i2c;
399 struct i2c_client *last_client;459 struct i2c_client *last_client;
460 struct timer_list hdcp_timer;
400 struct s_edid_data slimport_edid_p;461 struct s_edid_data slimport_edid_p;
401 struct device *codec_dev;462 struct device *codec_dev;
402 hdmi_codec_plugged_cb plugged_cb;463 hdmi_codec_plugged_cb plugged_cb;
403 struct work_struct work;464 struct work_struct work;
404 struct workqueue_struct *workqueue;465 struct workqueue_struct *workqueue;
466 struct delayed_work hdcp_work;
467 struct workqueue_struct *hdcp_workqueue;
468 /* Lock for hdcp work queue */
469 struct mutex hdcp_wq_lock;
405 char edid_block;470 char edid_block;
406 struct display_timing dt;471 struct display_timing dt;
407 u8 display_timing_valid;472 u8 display_timing_valid;
408 struct drm_bridge bridge;473 struct drm_bridge bridge;
409 u8 bridge_attached;474 u8 bridge_attached;
475 struct drm_connector *connector;
410 struct mipi_dsi_device *dsi;476 struct mipi_dsi_device *dsi;
411};477};
412 478
drivers/gpu/drm/bridge/cadence/Kconfig+1−0
@@ -1,6 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2config DRM_CDNS_MHDP85462config DRM_CDNS_MHDP8546
3 tristate "Cadence DPI/DP bridge"3 tristate "Cadence DPI/DP bridge"
4 select DRM_DP_HELPER
4 select DRM_KMS_HELPER5 select DRM_KMS_HELPER
5 select DRM_PANEL_BRIDGE6 select DRM_PANEL_BRIDGE
6 depends on OF7 depends on OF
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c+10−10
@@ -41,7 +41,7 @@ · 40 unmodified lines
41#include <drm/drm_bridge.h>41#include <drm/drm_bridge.h>
42#include <drm/drm_connector.h>42#include <drm/drm_connector.h>
43#include <drm/drm_crtc_helper.h>43#include <drm/drm_crtc_helper.h>
44#include <drm/drm_dp_helper.h>44#include <drm/dp/drm_dp_helper.h>
45#include <drm/drm_hdcp.h>45#include <drm/drm_hdcp.h>
46#include <drm/drm_modeset_helper_vtables.h>46#include <drm/drm_modeset_helper_vtables.h>
47#include <drm/drm_print.h>47#include <drm/drm_print.h>
@@ -1553,13 +1553,13 @@ static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt) · 1505 unmodified lines
1553 1553
1554 switch (fmt->color_format) {1554 switch (fmt->color_format) {
1555 case DRM_COLOR_FORMAT_RGB444:1555 case DRM_COLOR_FORMAT_RGB444:
1556 case DRM_COLOR_FORMAT_YCRCB444:1556 case DRM_COLOR_FORMAT_YCBCR444:
1557 bpp = fmt->bpc * 3;1557 bpp = fmt->bpc * 3;
1558 break;1558 break;
1559 case DRM_COLOR_FORMAT_YCRCB422:1559 case DRM_COLOR_FORMAT_YCBCR422:
1560 bpp = fmt->bpc * 2;1560 bpp = fmt->bpc * 2;
1561 break;1561 break;
1562 case DRM_COLOR_FORMAT_YCRCB420:1562 case DRM_COLOR_FORMAT_YCBCR420:
1563 bpp = fmt->bpc * 3 / 2;1563 bpp = fmt->bpc * 3 / 2;
1564 break;1564 break;
1565 default:1565 default:
@@ -1767,8 +1767,8 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, · 201 unmodified lines
1767 * If YCBCR supported and stream not SD, use ITU7091767 * If YCBCR supported and stream not SD, use ITU709
1768 * Need to handle ITU version with YCBCR420 when supported1768 * Need to handle ITU version with YCBCR420 when supported
1769 */1769 */
1770 if ((pxlfmt == DRM_COLOR_FORMAT_YCRCB444 ||1770 if ((pxlfmt == DRM_COLOR_FORMAT_YCBCR444 ||
1771 pxlfmt == DRM_COLOR_FORMAT_YCRCB422) && mode->crtc_vdisplay >= 720)1771 pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
1772 misc0 = DP_YCBCR_COEFFICIENTS_ITU709;1772 misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
1773 1773
1774 bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);1774 bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
@@ -1778,15 +1778,15 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, · 3 unmodified lines
1778 pxl_repr = CDNS_DP_FRAMER_RGB << CDNS_DP_FRAMER_PXL_FORMAT;1778 pxl_repr = CDNS_DP_FRAMER_RGB << CDNS_DP_FRAMER_PXL_FORMAT;
1779 misc0 |= DP_COLOR_FORMAT_RGB;1779 misc0 |= DP_COLOR_FORMAT_RGB;
1780 break;1780 break;
1781 case DRM_COLOR_FORMAT_YCRCB444:1781 case DRM_COLOR_FORMAT_YCBCR444:
1782 pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT;1782 pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT;
1783 misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA;1783 misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA;
1784 break;1784 break;
1785 case DRM_COLOR_FORMAT_YCRCB422:1785 case DRM_COLOR_FORMAT_YCBCR422:
1786 pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT;1786 pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT;
1787 misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA;1787 misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA;
1788 break;1788 break;
1789 case DRM_COLOR_FORMAT_YCRCB420:1789 case DRM_COLOR_FORMAT_YCBCR420:
1790 pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT;1790 pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT;
1791 break;1791 break;
1792 default:1792 default:
@@ -1882,7 +1882,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, · 89 unmodified lines
1882 if (mhdp->display_fmt.y_only)1882 if (mhdp->display_fmt.y_only)
1883 misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY;1883 misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY;
1884 /* Use VSC SDP for Y420 */1884 /* Use VSC SDP for Y420 */
1885 if (pxlfmt == DRM_COLOR_FORMAT_YCRCB420)1885 if (pxlfmt == DRM_COLOR_FORMAT_YCBCR420)
1886 misc1 = CDNS_DP_TEST_VSC_SDP;1886 misc1 = CDNS_DP_TEST_VSC_SDP;
1887 1887
1888 cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id),1888 cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id),
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h+1−1
@@ -17,7 +17,7 @@ · 16 unmodified lines
17 17
18#include <drm/drm_bridge.h>18#include <drm/drm_bridge.h>
19#include <drm/drm_connector.h>19#include <drm/drm_connector.h>
20#include <drm/drm_dp_helper.h>20#include <drm/dp/drm_dp_helper.h>
21 21
22struct clk;22struct clk;
23struct device;23struct device;
drivers/gpu/drm/bridge/chipone-icn6211.c+26−13
@@ -4,6 +4,7 @@ · 3 unmodified lines
4 * Author: Jagan Teki <jagan@amarulasolutions.com>4 * Author: Jagan Teki <jagan@amarulasolutions.com>
5 */5 */
6 6
7#include <drm/drm_atomic_helper.h>
7#include <drm/drm_of.h>8#include <drm/drm_of.h>
8#include <drm/drm_print.h>9#include <drm/drm_print.h>
9#include <drm/drm_mipi_dsi.h>10#include <drm/drm_mipi_dsi.h>
@@ -30,6 +31,7 @@ · 20 unmodified lines
30struct chipone {31struct chipone {
31 struct device *dev;32 struct device *dev;
32 struct drm_bridge bridge;33 struct drm_bridge bridge;
34 struct drm_display_mode mode;
33 struct drm_bridge *panel_bridge;35 struct drm_bridge *panel_bridge;
34 struct gpio_desc *enable_gpio;36 struct gpio_desc *enable_gpio;
35 struct regulator *vdd1;37 struct regulator *vdd1;
@@ -42,11 +44,6 @@ static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge) · 6 unmodified lines
42 return container_of(bridge, struct chipone, bridge);44 return container_of(bridge, struct chipone, bridge);
43}45}
44 46
45static struct drm_display_mode *bridge_to_mode(struct drm_bridge *bridge)
46{
47 return &bridge->encoder->crtc->state->adjusted_mode;
48}
49
50static inline int chipone_dsi_write(struct chipone *icn, const void *seq,47static inline int chipone_dsi_write(struct chipone *icn, const void *seq,
51 size_t len)48 size_t len)
52{49{
@@ -61,10 +58,11 @@ static inline int chipone_dsi_write(struct chipone *icn, const void *seq, · 8 unmodified lines
61 chipone_dsi_write(icn, d, ARRAY_SIZE(d)); \58 chipone_dsi_write(icn, d, ARRAY_SIZE(d)); \
62 }59 }
63 60
64static void chipone_enable(struct drm_bridge *bridge)61static void chipone_atomic_enable(struct drm_bridge *bridge,
62 struct drm_bridge_state *old_bridge_state)
65{63{
66 struct chipone *icn = bridge_to_chipone(bridge);64 struct chipone *icn = bridge_to_chipone(bridge);
67 struct drm_display_mode *mode = bridge_to_mode(bridge);65 struct drm_display_mode *mode = &icn->mode;
68 66
69 ICN6211_DSI(icn, 0x7a, 0xc1);67 ICN6211_DSI(icn, 0x7a, 0xc1);
70 68
@@ -114,7 +112,8 @@ static void chipone_enable(struct drm_bridge *bridge) · 43 unmodified lines
114 usleep_range(10000, 11000);112 usleep_range(10000, 11000);
115}113}
116 114
117static void chipone_pre_enable(struct drm_bridge *bridge)115static void chipone_atomic_pre_enable(struct drm_bridge *bridge,
116 struct drm_bridge_state *old_bridge_state)
118{117{
119 struct chipone *icn = bridge_to_chipone(bridge);118 struct chipone *icn = bridge_to_chipone(bridge);
120 int ret;119 int ret;
@@ -145,7 +144,8 @@ static void chipone_pre_enable(struct drm_bridge *bridge) · 24 unmodified lines
145 usleep_range(10000, 11000);144 usleep_range(10000, 11000);
146}145}
147 146
148static void chipone_post_disable(struct drm_bridge *bridge)147static void chipone_atomic_post_disable(struct drm_bridge *bridge,
148 struct drm_bridge_state *old_bridge_state)
149{149{
150 struct chipone *icn = bridge_to_chipone(bridge);150 struct chipone *icn = bridge_to_chipone(bridge);
151 151
@@ -161,6 +161,15 @@ static void chipone_post_disable(struct drm_bridge *bridge) · 9 unmodified lines
161 gpiod_set_value(icn->enable_gpio, 0);161 gpiod_set_value(icn->enable_gpio, 0);
162}162}
163 163
164static void chipone_mode_set(struct drm_bridge *bridge,
165 const struct drm_display_mode *mode,
166 const struct drm_display_mode *adjusted_mode)
167{
168 struct chipone *icn = bridge_to_chipone(bridge);
169
170 drm_mode_copy(&icn->mode, adjusted_mode);
171}
172
164static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags)173static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags)
165{174{
166 struct chipone *icn = bridge_to_chipone(bridge);175 struct chipone *icn = bridge_to_chipone(bridge);
@@ -169,10 +178,14 @@ static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flag · 2 unmodified lines
169}178}
170 179
171static const struct drm_bridge_funcs chipone_bridge_funcs = {180static const struct drm_bridge_funcs chipone_bridge_funcs = {
172 .attach = chipone_attach,181 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
173 .post_disable = chipone_post_disable,182 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
174 .pre_enable = chipone_pre_enable,183 .atomic_reset = drm_atomic_helper_bridge_reset,
175 .enable = chipone_enable,184 .atomic_pre_enable = chipone_atomic_pre_enable,
185 .atomic_enable = chipone_atomic_enable,
186 .atomic_post_disable = chipone_atomic_post_disable,
187 .mode_set = chipone_mode_set,
188 .attach = chipone_attach,
176};189};
177 190
178static int chipone_parse_dt(struct chipone *icn)191static int chipone_parse_dt(struct chipone *icn)
drivers/gpu/drm/bridge/ite-it66121.c+0−3
@@ -936,9 +936,6 @@ static int it66121_probe(struct i2c_client *client, · 935 unmodified lines
936 return -EPROBE_DEFER;936 return -EPROBE_DEFER;
937 }937 }
938 938
939 if (!ctx->next_bridge)
940 return -EPROBE_DEFER;
941
942 i2c_set_clientdata(client, ctx);939 i2c_set_clientdata(client, ctx);
943 mutex_init(&ctx->lock);940 mutex_init(&ctx->lock);
944 941
drivers/gpu/drm/bridge/lontium-lt9611.c+2−2
@@ -1090,7 +1090,7 @@ static int lt9611_probe(struct i2c_client *client, · 1089 unmodified lines
1090 if (!lt9611)1090 if (!lt9611)
1091 return -ENOMEM;1091 return -ENOMEM;
1092 1092
1093 lt9611->dev = &client->dev;1093 lt9611->dev = dev;
1094 lt9611->client = client;1094 lt9611->client = client;
1095 lt9611->sleep = false;1095 lt9611->sleep = false;
1096 1096
@@ -1100,7 +1100,7 @@ static int lt9611_probe(struct i2c_client *client, · 3 unmodified lines
1100 return PTR_ERR(lt9611->regmap);1100 return PTR_ERR(lt9611->regmap);
1101 }1101 }
1102 1102
1103 ret = lt9611_parse_dt(&client->dev, lt9611);1103 ret = lt9611_parse_dt(dev, lt9611);
1104 if (ret) {1104 if (ret) {
1105 dev_err(dev, "failed to parse device tree\n");1105 dev_err(dev, "failed to parse device tree\n");
1106 return ret;1106 return ret;
drivers/gpu/drm/bridge/lontium-lt9611uxc.c+2−2
@@ -860,7 +860,7 @@ static int lt9611uxc_probe(struct i2c_client *client, · 859 unmodified lines
860 if (!lt9611uxc)860 if (!lt9611uxc)
861 return -ENOMEM;861 return -ENOMEM;
862 862
863 lt9611uxc->dev = &client->dev;863 lt9611uxc->dev = dev;
864 lt9611uxc->client = client;864 lt9611uxc->client = client;
865 mutex_init(&lt9611uxc->ocm_lock);865 mutex_init(&lt9611uxc->ocm_lock);
866 866
@@ -870,7 +870,7 @@ static int lt9611uxc_probe(struct i2c_client *client, · 3 unmodified lines
870 return PTR_ERR(lt9611uxc->regmap);870 return PTR_ERR(lt9611uxc->regmap);
871 }871 }
872 872
873 ret = lt9611uxc_parse_dt(&client->dev, lt9611uxc);873 ret = lt9611uxc_parse_dt(dev, lt9611uxc);
874 if (ret) {874 if (ret) {
875 dev_err(dev, "failed to parse device tree\n");875 dev_err(dev, "failed to parse device tree\n");
876 return ret;876 return ret;
drivers/gpu/drm/bridge/nwl-dsi.c+3−5
@@ -65,7 +65,6 @@ struct nwl_dsi_transfer { · 64 unmodified lines
65struct nwl_dsi {65struct nwl_dsi {
66 struct drm_bridge bridge;66 struct drm_bridge bridge;
67 struct mipi_dsi_host dsi_host;67 struct mipi_dsi_host dsi_host;
68 struct drm_bridge *panel_bridge;
69 struct device *dev;68 struct device *dev;
70 struct phy *phy;69 struct phy *phy;
71 union phy_configure_opts phy_cfg;70 union phy_configure_opts phy_cfg;
@@ -924,13 +923,11 @@ static int nwl_dsi_bridge_attach(struct drm_bridge *bridge, · 852 unmodified lines
924 if (IS_ERR(panel_bridge))923 if (IS_ERR(panel_bridge))
925 return PTR_ERR(panel_bridge);924 return PTR_ERR(panel_bridge);
926 }925 }
927 dsi->panel_bridge = panel_bridge;
928 926
929 if (!dsi->panel_bridge)927 if (!panel_bridge)
930 return -EPROBE_DEFER;928 return -EPROBE_DEFER;
931 929
932 return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,930 return drm_bridge_attach(bridge->encoder, panel_bridge, bridge, flags);
933 flags);
934}931}
935 932
936static void nwl_dsi_bridge_detach(struct drm_bridge *bridge)933static void nwl_dsi_bridge_detach(struct drm_bridge *bridge)
@@ -1206,6 +1203,7 @@ static int nwl_dsi_probe(struct platform_device *pdev) · 269 unmodified lines
1206 1203
1207 ret = nwl_dsi_select_input(dsi);1204 ret = nwl_dsi_select_input(dsi);
1208 if (ret < 0) {1205 if (ret < 0) {
1206 pm_runtime_disable(dev);
1209 mipi_dsi_host_unregister(&dsi->dsi_host);1207 mipi_dsi_host_unregister(&dsi->dsi_host);
1210 return ret;1208 return ret;
1211 }1209 }
drivers/gpu/drm/bridge/parade-ps8640.c+28−5
@@ -14,8 +14,8 @@ · 13 unmodified lines
14#include <linux/regulator/consumer.h>14#include <linux/regulator/consumer.h>
15 15
16#include <drm/drm_bridge.h>16#include <drm/drm_bridge.h>
17#include <drm/drm_dp_aux_bus.h>17#include <drm/dp/drm_dp_aux_bus.h>
18#include <drm/drm_dp_helper.h>18#include <drm/dp/drm_dp_helper.h>
19#include <drm/drm_mipi_dsi.h>19#include <drm/drm_mipi_dsi.h>
20#include <drm/drm_of.h>20#include <drm/drm_of.h>
21#include <drm/drm_panel.h>21#include <drm/drm_panel.h>
@@ -102,6 +102,7 @@ struct ps8640 { · 80 unmodified lines
102 struct regulator_bulk_data supplies[2];102 struct regulator_bulk_data supplies[2];
103 struct gpio_desc *gpio_reset;103 struct gpio_desc *gpio_reset;
104 struct gpio_desc *gpio_powerdown;104 struct gpio_desc *gpio_powerdown;
105 struct device_link *link;
105 bool pre_enabled;106 bool pre_enabled;
106};107};
107 108
@@ -456,14 +457,36 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge, · 348 unmodified lines
456 return ret;457 return ret;
457 }458 }
458 459
460 ps_bridge->link = device_link_add(bridge->dev->dev, dev, DL_FLAG_STATELESS);
461 if (!ps_bridge->link) {
462 dev_err(dev, "failed to create device link");
463 ret = -EINVAL;
464 goto err_devlink;
465 }
466
459 /* Attach the panel-bridge to the dsi bridge */467 /* Attach the panel-bridge to the dsi bridge */
460 return drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge,468 ret = drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge,
461 &ps_bridge->bridge, flags);469 &ps_bridge->bridge, flags);
470 if (ret)
471 goto err_bridge_attach;
472
473 return 0;
474
475err_bridge_attach:
476 device_link_del(ps_bridge->link);
477err_devlink:
478 drm_dp_aux_unregister(&ps_bridge->aux);
479
480 return ret;
462}481}
463 482
464static void ps8640_bridge_detach(struct drm_bridge *bridge)483static void ps8640_bridge_detach(struct drm_bridge *bridge)
465{484{
466 drm_dp_aux_unregister(&bridge_to_ps8640(bridge)->aux);485 struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
486
487 drm_dp_aux_unregister(&ps_bridge->aux);
488 if (ps_bridge->link)
489 device_link_del(ps_bridge->link);
467}490}
468 491
469static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge,492static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge,
drivers/gpu/drm/bridge/sii902x.c+99−30
@@ -166,10 +166,12 @@ struct sii902x { · 165 unmodified lines
166 struct i2c_client *i2c;166 struct i2c_client *i2c;
167 struct regmap *regmap;167 struct regmap *regmap;
168 struct drm_bridge bridge;168 struct drm_bridge bridge;
169 struct drm_bridge *next_bridge;
169 struct drm_connector connector;170 struct drm_connector connector;
170 struct gpio_desc *reset_gpio;171 struct gpio_desc *reset_gpio;
171 struct i2c_mux_core *i2cmux;172 struct i2c_mux_core *i2cmux;
172 struct regulator_bulk_data supplies[2];173 struct regulator_bulk_data supplies[2];
174 bool sink_is_hdmi;
173 /*175 /*
174 * Mutex protects audio and video functions from interfering176 * Mutex protects audio and video functions from interfering
175 * each other, by keeping their i2c command sequences atomic.177 * each other, by keeping their i2c command sequences atomic.
@@ -245,10 +247,8 @@ static void sii902x_reset(struct sii902x *sii902x) · 69 unmodified lines
245 gpiod_set_value(sii902x->reset_gpio, 0);247 gpiod_set_value(sii902x->reset_gpio, 0);
246}248}
247 249
248static enum drm_connector_status250static enum drm_connector_status sii902x_detect(struct sii902x *sii902x)
249sii902x_connector_detect(struct drm_connector *connector, bool force)
250{251{
251 struct sii902x *sii902x = connector_to_sii902x(connector);
252 unsigned int status;252 unsigned int status;
253 253
254 mutex_lock(&sii902x->mutex);254 mutex_lock(&sii902x->mutex);
@@ -261,6 +261,14 @@ sii902x_connector_detect(struct drm_connector *connector, bool force) · 6 unmodified lines
261 connector_status_connected : connector_status_disconnected;261 connector_status_connected : connector_status_disconnected;
262}262}
263 263
264static enum drm_connector_status
265sii902x_connector_detect(struct drm_connector *connector, bool force)
266{
267 struct sii902x *sii902x = connector_to_sii902x(connector);
268
269 return sii902x_detect(sii902x);
270}
271
264static const struct drm_connector_funcs sii902x_connector_funcs = {272static const struct drm_connector_funcs sii902x_connector_funcs = {
265 .detect = sii902x_connector_detect,273 .detect = sii902x_connector_detect,
266 .fill_modes = drm_helper_probe_single_connector_modes,274 .fill_modes = drm_helper_probe_single_connector_modes,
@@ -270,42 +278,40 @@ static const struct drm_connector_funcs sii902x_connector_funcs = { · 3 unmodified lines
270 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,278 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
271};279};
272 280
273static int sii902x_get_modes(struct drm_connector *connector)281static struct edid *sii902x_get_edid(struct sii902x *sii902x,
282 struct drm_connector *connector)
274{283{
275 struct sii902x *sii902x = connector_to_sii902x(connector);
276 u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
277 u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
278 struct edid *edid;284 struct edid *edid;
279 int num = 0, ret;
280 285
281 mutex_lock(&sii902x->mutex);286 mutex_lock(&sii902x->mutex);
282 287
283 edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);288 edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
284 drm_connector_update_edid_property(connector, edid);
285 if (edid) {289 if (edid) {
286 if (drm_detect_hdmi_monitor(edid))290 if (drm_detect_hdmi_monitor(edid))
287 output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;291 sii902x->sink_is_hdmi = true;
288 292 else
289 num = drm_add_edid_modes(connector, edid);293 sii902x->sink_is_hdmi = false;
290 kfree(edid);
291 }294 }
292 295
293 ret = drm_display_info_set_bus_formats(&connector->display_info,296 mutex_unlock(&sii902x->mutex);
294 &bus_format, 1);
295 if (ret)
296 goto error_out;
297 297
298 ret = regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,298 return edid;
299 SII902X_SYS_CTRL_OUTPUT_MODE, output_mode);299}
300 if (ret)
301 goto error_out;
302 300
303 ret = num;301static int sii902x_get_modes(struct drm_connector *connector)
302{
303 struct sii902x *sii902x = connector_to_sii902x(connector);
304 struct edid *edid;
305 int num = 0;
304 306
305error_out:307 edid = sii902x_get_edid(sii902x, connector);
306 mutex_unlock(&sii902x->mutex);308 drm_connector_update_edid_property(connector, edid);
309 if (edid) {
310 num = drm_add_edid_modes(connector, edid);
311 kfree(edid);
312 }
307 313
308 return ret;314 return num;
309}315}
310 316
311static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,317static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
@@ -354,12 +360,16 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge, · 42 unmodified lines
354 const struct drm_display_mode *adj)360 const struct drm_display_mode *adj)
355{361{
356 struct sii902x *sii902x = bridge_to_sii902x(bridge);362 struct sii902x *sii902x = bridge_to_sii902x(bridge);
363 u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
357 struct regmap *regmap = sii902x->regmap;364 struct regmap *regmap = sii902x->regmap;
358 u8 buf[HDMI_INFOFRAME_SIZE(AVI)];365 u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
359 struct hdmi_avi_infoframe frame;366 struct hdmi_avi_infoframe frame;
360 u16 pixel_clock_10kHz = adj->clock / 10;367 u16 pixel_clock_10kHz = adj->clock / 10;
361 int ret;368 int ret;
362 369
370 if (sii902x->sink_is_hdmi)
371 output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
372
363 buf[0] = pixel_clock_10kHz & 0xff;373 buf[0] = pixel_clock_10kHz & 0xff;
364 buf[1] = pixel_clock_10kHz >> 8;374 buf[1] = pixel_clock_10kHz >> 8;
365 buf[2] = drm_mode_vrefresh(adj);375 buf[2] = drm_mode_vrefresh(adj);
@@ -375,6 +385,11 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge, · 9 unmodified lines
375 385
376 mutex_lock(&sii902x->mutex);386 mutex_lock(&sii902x->mutex);
377 387
388 ret = regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
389 SII902X_SYS_CTRL_OUTPUT_MODE, output_mode);
390 if (ret)
391 goto out;
392
378 ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10);393 ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10);
379 if (ret)394 if (ret)
380 goto out;395 goto out;
@@ -405,13 +420,13 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge, · 24 unmodified lines
405 enum drm_bridge_attach_flags flags)420 enum drm_bridge_attach_flags flags)
406{421{
407 struct sii902x *sii902x = bridge_to_sii902x(bridge);422 struct sii902x *sii902x = bridge_to_sii902x(bridge);
423 u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
408 struct drm_device *drm = bridge->dev;424 struct drm_device *drm = bridge->dev;
409 int ret;425 int ret;
410 426
411 if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {427 if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
412 DRM_ERROR("Fix bridge driver to make connector optional!");428 return drm_bridge_attach(bridge->encoder, sii902x->next_bridge,
413 return -EINVAL;429 bridge, flags);
414 }
415 430
416 drm_connector_helper_add(&sii902x->connector,431 drm_connector_helper_add(&sii902x->connector,
417 &sii902x_connector_helper_funcs);432 &sii902x_connector_helper_funcs);
@@ -433,16 +448,38 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge, · 15 unmodified lines
433 else448 else
434 sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;449 sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
435 450
451 ret = drm_display_info_set_bus_formats(&sii902x->connector.display_info,
452 &bus_format, 1);
453 if (ret)
454 return ret;
455
436 drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);456 drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
437 457
438 return 0;458 return 0;
439}459}
440 460
461static enum drm_connector_status sii902x_bridge_detect(struct drm_bridge *bridge)
462{
463 struct sii902x *sii902x = bridge_to_sii902x(bridge);
464
465 return sii902x_detect(sii902x);
466}
467
468static struct edid *sii902x_bridge_get_edid(struct drm_bridge *bridge,
469 struct drm_connector *connector)
470{
471 struct sii902x *sii902x = bridge_to_sii902x(bridge);
472
473 return sii902x_get_edid(sii902x, connector);
474}
475
441static const struct drm_bridge_funcs sii902x_bridge_funcs = {476static const struct drm_bridge_funcs sii902x_bridge_funcs = {
442 .attach = sii902x_bridge_attach,477 .attach = sii902x_bridge_attach,
443 .mode_set = sii902x_bridge_mode_set,478 .mode_set = sii902x_bridge_mode_set,
444 .disable = sii902x_bridge_disable,479 .disable = sii902x_bridge_disable,
445 .enable = sii902x_bridge_enable,480 .enable = sii902x_bridge_enable,
481 .detect = sii902x_bridge_detect,
482 .get_edid = sii902x_bridge_get_edid,
446};483};
447 484
448static int sii902x_mute(struct sii902x *sii902x, bool mute)485static int sii902x_mute(struct sii902x *sii902x, bool mute)
@@ -829,8 +866,12 @@ static irqreturn_t sii902x_interrupt(int irq, void *data) · 380 unmodified lines
829 866
830 mutex_unlock(&sii902x->mutex);867 mutex_unlock(&sii902x->mutex);
831 868
832 if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)869 if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev) {
833 drm_helper_hpd_irq_event(sii902x->bridge.dev);870 drm_helper_hpd_irq_event(sii902x->bridge.dev);
871 drm_bridge_hpd_notify(&sii902x->bridge, (status & SII902X_PLUGGED_STATUS)
872 ? connector_status_connected
873 : connector_status_disconnected);
874 }
834 875
835 return IRQ_HANDLED;876 return IRQ_HANDLED;
836}877}
@@ -1001,6 +1042,11 @@ static int sii902x_init(struct sii902x *sii902x) · 164 unmodified lines
1001 sii902x->bridge.funcs = &sii902x_bridge_funcs;1042 sii902x->bridge.funcs = &sii902x_bridge_funcs;
1002 sii902x->bridge.of_node = dev->of_node;1043 sii902x->bridge.of_node = dev->of_node;
1003 sii902x->bridge.timings = &default_sii902x_timings;1044 sii902x->bridge.timings = &default_sii902x_timings;
1045 sii902x->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
1046
1047 if (sii902x->i2c->irq > 0)
1048 sii902x->bridge.ops |= DRM_BRIDGE_OP_HPD;
1049
1004 drm_bridge_add(&sii902x->bridge);1050 drm_bridge_add(&sii902x->bridge);
1005 1051
1006 sii902x_audio_codec_init(sii902x, dev);1052 sii902x_audio_codec_init(sii902x, dev);
@@ -1022,6 +1068,7 @@ static int sii902x_probe(struct i2c_client *client, · 15 unmodified lines
1022 const struct i2c_device_id *id)1068 const struct i2c_device_id *id)
1023{1069{
1024 struct device *dev = &client->dev;1070 struct device *dev = &client->dev;
1071 struct device_node *endpoint;
1025 struct sii902x *sii902x;1072 struct sii902x *sii902x;
1026 int ret;1073 int ret;
1027 1074
@@ -1049,6 +1096,28 @@ static int sii902x_probe(struct i2c_client *client, · 21 unmodified lines
1049 return PTR_ERR(sii902x->reset_gpio);1096 return PTR_ERR(sii902x->reset_gpio);
1050 }1097 }
1051 1098
1099 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
1100 if (endpoint) {
1101 struct device_node *remote = of_graph_get_remote_port_parent(endpoint);
1102
1103 of_node_put(endpoint);
1104 if (!remote) {
1105 dev_err(dev, "Endpoint in port@1 unconnected\n");
1106 return -ENODEV;
1107 }
1108
1109 if (!of_device_is_available(remote)) {
1110 dev_err(dev, "port@1 remote device is disabled\n");
1111 of_node_put(remote);
1112 return -ENODEV;
1113 }
1114
1115 sii902x->next_bridge = of_drm_find_bridge(remote);
1116 of_node_put(remote);
1117 if (!sii902x->next_bridge)
1118 return -EPROBE_DEFER;
1119 }
1120
1052 mutex_init(&sii902x->mutex);1121 mutex_init(&sii902x->mutex);
1053 1122
1054 sii902x->supplies[0].supply = "iovcc";1123 sii902x->supplies[0].supply = "iovcc";
drivers/gpu/drm/bridge/sil-sii8620.c+1−1
@@ -2120,7 +2120,7 @@ static void sii8620_init_rcp_input_dev(struct sii8620 *ctx) · 2119 unmodified lines
2120 if (ret) {2120 if (ret) {
2121 dev_err(ctx->dev, "Failed to register RC device\n");2121 dev_err(ctx->dev, "Failed to register RC device\n");
2122 ctx->error = ret;2122 ctx->error = ret;
2123 rc_free_device(ctx->rc_dev);2123 rc_free_device(rc_dev);
2124 return;2124 return;
2125 }2125 }
2126 ctx->rc_dev = rc_dev;2126 ctx->rc_dev = rc_dev;
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c+8−8
@@ -2540,7 +2540,7 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, · 2539 unmodified lines
2540 struct drm_display_mode *mode = &crtc_state->mode;2540 struct drm_display_mode *mode = &crtc_state->mode;
2541 u8 max_bpc = conn_state->max_requested_bpc;2541 u8 max_bpc = conn_state->max_requested_bpc;
2542 bool is_hdmi2_sink = info->hdmi.scdc.supported ||2542 bool is_hdmi2_sink = info->hdmi.scdc.supported ||
2543 (info->color_formats & DRM_COLOR_FORMAT_YCRCB420);2543 (info->color_formats & DRM_COLOR_FORMAT_YCBCR420);
2544 u32 *output_fmts;2544 u32 *output_fmts;
2545 unsigned int i = 0;2545 unsigned int i = 0;
2546 2546
@@ -2594,36 +2594,36 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, · 47 unmodified lines
2594 */2594 */
2595 2595
2596 if (max_bpc >= 16 && info->bpc == 16) {2596 if (max_bpc >= 16 && info->bpc == 16) {
2597 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)2597 if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
2598 output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;2598 output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
2599 2599
2600 output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;2600 output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
2601 }2601 }
2602 2602
2603 if (max_bpc >= 12 && info->bpc >= 12) {2603 if (max_bpc >= 12 && info->bpc >= 12) {
2604 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)2604 if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
2605 output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;2605 output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;
2606 2606
2607 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)2607 if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
2608 output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;2608 output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;
2609 2609
2610 output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;2610 output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
2611 }2611 }
2612 2612
2613 if (max_bpc >= 10 && info->bpc >= 10) {2613 if (max_bpc >= 10 && info->bpc >= 10) {
2614 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)2614 if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
2615 output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;2615 output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;
2616 2616
2617 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)2617 if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
2618 output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;2618 output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;
2619 2619
2620 output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;2620 output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;
2621 }2621 }
2622 2622
2623 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)2623 if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
2624 output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;2624 output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;
2625 2625
2626 if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)2626 if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
2627 output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;2627 output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
2628 2628
2629 /* Default 8bit RGB fallback */2629 /* Default 8bit RGB fallback */
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c+17−8
@@ -871,7 +871,8 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi) · 870 unmodified lines
871 dsi_write(dsi, DSI_INT_MSK1, 0);871 dsi_write(dsi, DSI_INT_MSK1, 0);
872}872}
873 873
874static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)874static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge,
875 struct drm_bridge_state *old_bridge_state)
875{876{
876 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);877 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
877 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;878 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
@@ -978,7 +979,8 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge, · 100 unmodified lines
978 dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);979 dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);
979}980}
980 981
981static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)982static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
983 struct drm_bridge_state *old_bridge_state)
982{984{
983 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);985 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
984 986
@@ -998,7 +1000,10 @@ dw_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, · 13 unmodified lines
998 enum drm_mode_status mode_status = MODE_OK;1000 enum drm_mode_status mode_status = MODE_OK;
999 1001
1000 if (pdata->mode_valid)1002 if (pdata->mode_valid)
1001 mode_status = pdata->mode_valid(pdata->priv_data, mode);1003 mode_status = pdata->mode_valid(pdata->priv_data, mode,
1004 dsi->mode_flags,
1005 dw_mipi_dsi_get_lanes(dsi),
1006 dsi->format);
1002 1007
1003 return mode_status;1008 return mode_status;
1004}1009}
@@ -1032,11 +1037,14 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge, · 27 unmodified lines
1032}1037}
1033 1038
1034static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {1039static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
1035 .mode_set = dw_mipi_dsi_bridge_mode_set,1040 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
1036 .enable = dw_mipi_dsi_bridge_enable,1041 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
1037 .post_disable = dw_mipi_dsi_bridge_post_disable,1042 .atomic_reset = drm_atomic_helper_bridge_reset,
1038 .mode_valid = dw_mipi_dsi_bridge_mode_valid,1043 .atomic_enable = dw_mipi_dsi_bridge_atomic_enable,
1039 .attach = dw_mipi_dsi_bridge_attach,1044 .atomic_post_disable = dw_mipi_dsi_bridge_post_atomic_disable,
1045 .mode_set = dw_mipi_dsi_bridge_mode_set,
1046 .mode_valid = dw_mipi_dsi_bridge_mode_valid,
1047 .attach = dw_mipi_dsi_bridge_attach,
1040};1048};
1041 1049
1042#ifdef CONFIG_DEBUG_FS1050#ifdef CONFIG_DEBUG_FS
@@ -1199,6 +1207,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, · 156 unmodified lines
1199 ret = mipi_dsi_host_register(&dsi->dsi_host);1207 ret = mipi_dsi_host_register(&dsi->dsi_host);
1200 if (ret) {1208 if (ret) {
1201 dev_err(dev, "Failed to register MIPI host: %d\n", ret);1209 dev_err(dev, "Failed to register MIPI host: %d\n", ret);
1210 pm_runtime_disable(dev);
1202 dw_mipi_dsi_debugfs_remove(dsi);1211 dw_mipi_dsi_debugfs_remove(dsi);
1203 return ERR_PTR(ret);1212 return ERR_PTR(ret);
1204 }1213 }
drivers/gpu/drm/bridge/tc358767.c+1−1
@@ -27,7 +27,7 @@ · 26 unmodified lines
27 27
28#include <drm/drm_atomic_helper.h>28#include <drm/drm_atomic_helper.h>
29#include <drm/drm_bridge.h>29#include <drm/drm_bridge.h>
30#include <drm/drm_dp_helper.h>30#include <drm/dp/drm_dp_helper.h>
31#include <drm/drm_edid.h>31#include <drm/drm_edid.h>
32#include <drm/drm_of.h>32#include <drm/drm_of.h>
33#include <drm/drm_panel.h>33#include <drm/drm_panel.h>
drivers/gpu/drm/bridge/tc358775.c+2−2
@@ -22,7 +22,7 @@ · 21 unmodified lines
22#include <drm/drm_atomic_helper.h>22#include <drm/drm_atomic_helper.h>
23#include <drm/drm_bridge.h>23#include <drm/drm_bridge.h>
24#include <drm/drm_crtc_helper.h>24#include <drm/drm_crtc_helper.h>
25#include <drm/drm_dp_helper.h>25#include <drm/dp/drm_dp_helper.h>
26#include <drm/drm_mipi_dsi.h>26#include <drm/drm_mipi_dsi.h>
27#include <drm/drm_of.h>27#include <drm/drm_of.h>
28#include <drm/drm_panel.h>28#include <drm/drm_panel.h>
@@ -241,7 +241,7 @@ static inline u32 TC358775_LVCFG_PCLKDIV(uint32_t val) · 212 unmodified lines
241}241}
242 242
243#define TC358775_LVCFG_LVDLINK__MASK 0x00000002243#define TC358775_LVCFG_LVDLINK__MASK 0x00000002
244#define TC358775_LVCFG_LVDLINK__SHIFT 0244#define TC358775_LVCFG_LVDLINK__SHIFT 1
245static inline u32 TC358775_LVCFG_LVDLINK(uint32_t val)245static inline u32 TC358775_LVCFG_LVDLINK(uint32_t val)
246{246{
247 return ((val) << TC358775_LVCFG_LVDLINK__SHIFT) &247 return ((val) << TC358775_LVCFG_LVDLINK__SHIFT) &
drivers/gpu/drm/bridge/ti-sn65dsi83.c+43−10
@@ -33,6 +33,7 @@ · 32 unmodified lines
33#include <linux/of_device.h>33#include <linux/of_device.h>
34#include <linux/of_graph.h>34#include <linux/of_graph.h>
35#include <linux/regmap.h>35#include <linux/regmap.h>
36#include <linux/regulator/consumer.h>
36 37
37#include <drm/drm_atomic_helper.h>38#include <drm/drm_atomic_helper.h>
38#include <drm/drm_bridge.h>39#include <drm/drm_bridge.h>
@@ -143,6 +144,7 @@ struct sn65dsi83 { · 104 unmodified lines
143 struct mipi_dsi_device *dsi;144 struct mipi_dsi_device *dsi;
144 struct drm_bridge *panel_bridge;145 struct drm_bridge *panel_bridge;
145 struct gpio_desc *enable_gpio;146 struct gpio_desc *enable_gpio;
147 struct regulator *vcc;
146 int dsi_lanes;148 int dsi_lanes;
147 bool lvds_dual_link;149 bool lvds_dual_link;
148 bool lvds_dual_link_even_odd_swap;150 bool lvds_dual_link_even_odd_swap;
@@ -337,6 +339,12 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, · 188 unmodified lines
337 u16 val;339 u16 val;
338 int ret;340 int ret;
339 341
342 ret = regulator_enable(ctx->vcc);
343 if (ret) {
344 dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret);
345 return;
346 }
347
340 /* Deassert reset */348 /* Deassert reset */
341 gpiod_set_value(ctx->enable_gpio, 1);349 gpiod_set_value(ctx->enable_gpio, 1);
342 usleep_range(1000, 1100);350 usleep_range(1000, 1100);
@@ -486,11 +494,16 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge, · 143 unmodified lines
486 struct drm_bridge_state *old_bridge_state)494 struct drm_bridge_state *old_bridge_state)
487{495{
488 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);496 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
497 int ret;
489 498
490 /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */499 /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
491 gpiod_set_value(ctx->enable_gpio, 0);500 gpiod_set_value(ctx->enable_gpio, 0);
492 usleep_range(10000, 11000);501 usleep_range(10000, 11000);
493 502
503 ret = regulator_disable(ctx->vcc);
504 if (ret)
505 dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret);
506
494 regcache_mark_dirty(ctx->regmap);507 regcache_mark_dirty(ctx->regmap);
495}508}
496 509
@@ -560,10 +573,14 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model) · 63 unmodified lines
560 ctx->host_node = of_graph_get_remote_port_parent(endpoint);573 ctx->host_node = of_graph_get_remote_port_parent(endpoint);
561 of_node_put(endpoint);574 of_node_put(endpoint);
562 575
563 if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4)576 if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4) {
564 return -EINVAL;577 ret = -EINVAL;
565 if (!ctx->host_node)578 goto err_put_node;
566 return -ENODEV;579 }
580 if (!ctx->host_node) {
581 ret = -ENODEV;
582 goto err_put_node;
583 }
567 584
568 ctx->lvds_dual_link = false;585 ctx->lvds_dual_link = false;
569 ctx->lvds_dual_link_even_odd_swap = false;586 ctx->lvds_dual_link_even_odd_swap = false;
@@ -590,16 +607,27 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model) · 20 unmodified lines
590 607
591 ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge);608 ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge);
592 if (ret < 0)609 if (ret < 0)
593 return ret;610 goto err_put_node;
594 if (panel) {611 if (panel) {
595 panel_bridge = devm_drm_panel_bridge_add(dev, panel);612 panel_bridge = devm_drm_panel_bridge_add(dev, panel);
596 if (IS_ERR(panel_bridge))613 if (IS_ERR(panel_bridge)) {
597 return PTR_ERR(panel_bridge);614 ret = PTR_ERR(panel_bridge);
615 goto err_put_node;
616 }
598 }617 }
599 618
600 ctx->panel_bridge = panel_bridge;619 ctx->panel_bridge = panel_bridge;
601 620
621 ctx->vcc = devm_regulator_get(dev, "vcc");
622 if (IS_ERR(ctx->vcc))
623 return dev_err_probe(dev, PTR_ERR(ctx->vcc),
624 "Failed to get supply 'vcc'\n");
625
602 return 0;626 return 0;
627
628err_put_node:
629 of_node_put(ctx->host_node);
630 return ret;
603}631}
604 632
605static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)633static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)
@@ -662,7 +690,8 @@ static int sn65dsi83_probe(struct i2c_client *client, · 56 unmodified lines
662 }690 }
663 691
664 /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */692 /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
665 ctx->enable_gpio = devm_gpiod_get(ctx->dev, "enable", GPIOD_OUT_LOW);693 ctx->enable_gpio = devm_gpiod_get_optional(ctx->dev, "enable",
694 GPIOD_OUT_LOW);
666 if (IS_ERR(ctx->enable_gpio))695 if (IS_ERR(ctx->enable_gpio))
667 return PTR_ERR(ctx->enable_gpio);696 return PTR_ERR(ctx->enable_gpio);
668 697
@@ -673,8 +702,10 @@ static int sn65dsi83_probe(struct i2c_client *client, · 4 unmodified lines
673 return ret;702 return ret;
674 703
675 ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config);704 ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config);
676 if (IS_ERR(ctx->regmap))705 if (IS_ERR(ctx->regmap)) {
677 return PTR_ERR(ctx->regmap);706 ret = PTR_ERR(ctx->regmap);
707 goto err_put_node;
708 }
678 709
679 dev_set_drvdata(dev, ctx);710 dev_set_drvdata(dev, ctx);
680 i2c_set_clientdata(client, ctx);711 i2c_set_clientdata(client, ctx);
@@ -691,6 +722,8 @@ static int sn65dsi83_probe(struct i2c_client *client, · 10 unmodified lines
691 722
692err_remove_bridge:723err_remove_bridge:
693 drm_bridge_remove(&ctx->bridge);724 drm_bridge_remove(&ctx->bridge);
725err_put_node:
726 of_node_put(ctx->host_node);
694 return ret;727 return ret;
695}728}
696 729
drivers/gpu/drm/bridge/ti-sn65dsi86.c+2−2
@@ -26,8 +26,8 @@ · 25 unmodified lines
26#include <drm/drm_atomic.h>26#include <drm/drm_atomic.h>
27#include <drm/drm_atomic_helper.h>27#include <drm/drm_atomic_helper.h>
28#include <drm/drm_bridge.h>28#include <drm/drm_bridge.h>
29#include <drm/drm_dp_aux_bus.h>29#include <drm/dp/drm_dp_aux_bus.h>
30#include <drm/drm_dp_helper.h>30#include <drm/dp/drm_dp_helper.h>
31#include <drm/drm_mipi_dsi.h>31#include <drm/drm_mipi_dsi.h>
32#include <drm/drm_of.h>32#include <drm/drm_of.h>
33#include <drm/drm_panel.h>33#include <drm/drm_panel.h>
drivers/gpu/drm/dp/Makefile+9−0
@@ -0,0 +1,9 @@
1# SPDX-License-Identifier: MIT
2
3obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
4
5drm_dp_helper-y := drm_dp.o drm_dp_dual_mode_helper.o drm_dp_helper_mod.o drm_dp_mst_topology.o
6drm_dp_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
7drm_dp_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
8
9obj-$(CONFIG_DRM_DP_HELPER) += drm_dp_helper.o
drivers/gpu/drm/dp/drm_dp.crenamed from drivers/gpu/drm/drm_dp_helper.c+3−3
@@ -29,13 +29,13 @@ · 28 unmodified lines
29#include <linux/sched.h>29#include <linux/sched.h>
30#include <linux/seq_file.h>30#include <linux/seq_file.h>
31 31
32#include <drm/drm_dp_helper.h>32#include <drm/dp/drm_dp_helper.h>
33#include <drm/drm_print.h>33#include <drm/drm_print.h>
34#include <drm/drm_vblank.h>34#include <drm/drm_vblank.h>
35#include <drm/drm_dp_mst_helper.h>35#include <drm/dp/drm_dp_mst_helper.h>
36#include <drm/drm_panel.h>36#include <drm/drm_panel.h>
37 37
38#include "drm_crtc_helper_internal.h"38#include "drm_dp_helper_internal.h"
39 39
40struct dp_aux_backlight {40struct dp_aux_backlight {
41 struct backlight_device *base;41 struct backlight_device *base;
drivers/gpu/drm/dp/drm_dp_aux_bus.crenamed from drivers/gpu/drm/drm_dp_aux_bus.c+2−2
@@ -19,8 +19,8 @@ · 18 unmodified lines
19#include <linux/pm_domain.h>19#include <linux/pm_domain.h>
20#include <linux/pm_runtime.h>20#include <linux/pm_runtime.h>
21 21
22#include <drm/drm_dp_aux_bus.h>22#include <drm/dp/drm_dp_aux_bus.h>
23#include <drm/drm_dp_helper.h>23#include <drm/dp/drm_dp_helper.h>
24 24
25/**25/**
26 * dp_aux_ep_match() - The match function for the dp_aux_bus.26 * dp_aux_ep_match() - The match function for the dp_aux_bus.
drivers/gpu/drm/dp/drm_dp_aux_dev.crenamed from drivers/gpu/drm/drm_dp_aux_dev.c+3−3
@@ -36,11 +36,11 @@ · 35 unmodified lines
36#include <linux/uio.h>36#include <linux/uio.h>
37 37
38#include <drm/drm_crtc.h>38#include <drm/drm_crtc.h>
39#include <drm/drm_dp_helper.h>39#include <drm/dp/drm_dp_helper.h>
40#include <drm/drm_dp_mst_helper.h>40#include <drm/dp/drm_dp_mst_helper.h>
41#include <drm/drm_print.h>41#include <drm/drm_print.h>
42 42
43#include "drm_crtc_helper_internal.h"43#include "drm_dp_helper_internal.h"
44 44
45struct drm_dp_aux_dev {45struct drm_dp_aux_dev {
46 unsigned index;46 unsigned index;
drivers/gpu/drm/dp/drm_dp_cec.crenamed from drivers/gpu/drm/drm_dp_cec.c+1−1
@@ -13,7 +13,7 @@ · 12 unmodified lines
13 13
14#include <drm/drm_connector.h>14#include <drm/drm_connector.h>
15#include <drm/drm_device.h>15#include <drm/drm_device.h>
16#include <drm/drm_dp_helper.h>16#include <drm/dp/drm_dp_helper.h>
17 17
18/*18/*
19 * Unfortunately it turns out that we have a chicken-and-egg situation19 * Unfortunately it turns out that we have a chicken-and-egg situation
drivers/gpu/drm/dp/drm_dp_dual_mode_helper.crenamed from drivers/gpu/drm/drm_dp_dual_mode_helper.c+1−1
@@ -28,7 +28,7 @@ · 27 unmodified lines
28#include <linux/string.h>28#include <linux/string.h>
29 29
30#include <drm/drm_device.h>30#include <drm/drm_device.h>
31#include <drm/drm_dp_dual_mode_helper.h>31#include <drm/dp/drm_dp_dual_mode_helper.h>
32#include <drm/drm_print.h>32#include <drm/drm_print.h>
33 33
34/**34/**
drivers/gpu/drm/dp/drm_dp_helper_internal.h+33−0
@@ -0,0 +1,33 @@
1/* SPDX-License-Identifier: MIT */
2
3#ifndef DRM_DP_HELPER_INTERNAL_H
4#define DRM_DP_HELPER_INTERNAL_H
5
6struct drm_dp_aux;
7
8#ifdef CONFIG_DRM_DP_AUX_CHARDEV
9int drm_dp_aux_dev_init(void);
10void drm_dp_aux_dev_exit(void);
11int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
12void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
13#else
14static inline int drm_dp_aux_dev_init(void)
15{
16 return 0;
17}
18
19static inline void drm_dp_aux_dev_exit(void)
20{
21}
22
23static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
24{
25 return 0;
26}
27
28static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
29{
30}
31#endif
32
33#endif
drivers/gpu/drm/dp/drm_dp_helper_mod.c+22−0
@@ -0,0 +1,22 @@
1// SPDX-License-Identifier: MIT
2
3#include <linux/module.h>
4
5#include "drm_dp_helper_internal.h"
6
7MODULE_DESCRIPTION("DRM DisplayPort helper");
8MODULE_LICENSE("GPL and additional rights");
9
10static int __init drm_dp_helper_module_init(void)
11{
12 return drm_dp_aux_dev_init();
13}
14
15static void __exit drm_dp_helper_module_exit(void)
16{
17 /* Call exit functions from specific dp helpers here */
18 drm_dp_aux_dev_exit();
19}
20
21module_init(drm_dp_helper_module_init);
22module_exit(drm_dp_helper_module_exit);
drivers/gpu/drm/dp/drm_dp_mst_topology.crenamed from drivers/gpu/drm/drm_dp_mst_topology.c+4−4
@@ -38,14 +38,14 @@ · 37 unmodified lines
38#include <linux/math64.h>38#include <linux/math64.h>
39#endif39#endif
40 40
41#include <drm/dp/drm_dp_mst_helper.h>
41#include <drm/drm_atomic.h>42#include <drm/drm_atomic.h>
42#include <drm/drm_atomic_helper.h>43#include <drm/drm_atomic_helper.h>
43#include <drm/drm_dp_mst_helper.h>
44#include <drm/drm_drv.h>44#include <drm/drm_drv.h>
45#include <drm/drm_print.h>45#include <drm/drm_print.h>
46#include <drm/drm_probe_helper.h>46#include <drm/drm_probe_helper.h>
47 47
48#include "drm_crtc_helper_internal.h"48#include "drm_dp_helper_internal.h"
49#include "drm_dp_mst_topology_internal.h"49#include "drm_dp_mst_topology_internal.h"
50 50
51/**51/**
@@ -4196,7 +4196,7 @@ int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handl · 4144 unmodified lines
4196 int ret = 0;4196 int ret = 0;
4197 int sc;4197 int sc;
4198 *handled = false;4198 *handled = false;
4199 sc = esi[0] & 0x3f;4199 sc = DP_GET_SINK_COUNT(esi[0]);
4200 4200
4201 if (sc != mgr->sink_count) {4201 if (sc != mgr->sink_count) {
4202 mgr->sink_count = sc;4202 mgr->sink_count = sc;
@@ -4811,7 +4811,7 @@ static void drm_dp_mst_dump_mstb(struct seq_file *m, · 608 unmodified lines
4811 4811
4812 seq_printf(m, "%smstb - [%p]: num_ports: %d\n", prefix, mstb, mstb->num_ports);4812 seq_printf(m, "%smstb - [%p]: num_ports: %d\n", prefix, mstb, mstb->num_ports);
4813 list_for_each_entry(port, &mstb->ports, next) {4813 list_for_each_entry(port, &mstb->ports, next) {
4814 seq_printf(m, "%sport %d - [%p] (%s - %s): ddps: %d, ldps: %d, sdp: %d/%d, fec: %s, conn: %p\n", 4814 seq_printf(m, "%sport %d - [%p] (%s - %s): ddps: %d, ldps: %d, sdp: %d/%d, fec: %s, conn: %p\n",
4815 prefix,4815 prefix,
4816 port->port_num,4816 port->port_num,
4817 port,4817 port,
drivers/gpu/drm/dp/drm_dp_mst_topology_internal.hrenamed from drivers/gpu/drm/drm_dp_mst_topology_internal.h+1−1
@@ -10,7 +10,7 @@ · 9 unmodified lines
10#ifndef _DRM_DP_MST_HELPER_INTERNAL_H_10#ifndef _DRM_DP_MST_HELPER_INTERNAL_H_
11#define _DRM_DP_MST_HELPER_INTERNAL_H_11#define _DRM_DP_MST_HELPER_INTERNAL_H_
12 12
13#include <drm/drm_dp_mst_helper.h>13#include <drm/dp/drm_dp_mst_helper.h>
14 14
15void15void
16drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,16drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
drivers/gpu/drm/drm_buddy.c+535−0
@@ -0,0 +1,535 @@
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2021 Intel Corporation
4 */
5
6#include <linux/kmemleak.h>
7#include <linux/module.h>
8#include <linux/sizes.h>
9
10#include <drm/drm_buddy.h>
11
12static struct kmem_cache *slab_blocks;
13
14static struct drm_buddy_block *drm_block_alloc(struct drm_buddy *mm,
15 struct drm_buddy_block *parent,
16 unsigned int order,
17 u64 offset)
18{
19 struct drm_buddy_block *block;
20
21 BUG_ON(order > DRM_BUDDY_MAX_ORDER);
22
23 block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
24 if (!block)
25 return NULL;
26
27 block->header = offset;
28 block->header |= order;
29 block->parent = parent;
30
31 BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED);
32 return block;
33}
34
35static void drm_block_free(struct drm_buddy *mm,
36 struct drm_buddy_block *block)
37{
38 kmem_cache_free(slab_blocks, block);
39}
40
41static void mark_allocated(struct drm_buddy_block *block)
42{
43 block->header &= ~DRM_BUDDY_HEADER_STATE;
44 block->header |= DRM_BUDDY_ALLOCATED;
45
46 list_del(&block->link);
47}
48
49static void mark_free(struct drm_buddy *mm,
50 struct drm_buddy_block *block)
51{
52 block->header &= ~DRM_BUDDY_HEADER_STATE;
53 block->header |= DRM_BUDDY_FREE;
54
55 list_add(&block->link,
56 &mm->free_list[drm_buddy_block_order(block)]);
57}
58
59static void mark_split(struct drm_buddy_block *block)
60{
61 block->header &= ~DRM_BUDDY_HEADER_STATE;
62 block->header |= DRM_BUDDY_SPLIT;
63
64 list_del(&block->link);
65}
66
67/**
68 * drm_buddy_init - init memory manager
69 *
70 * @mm: DRM buddy manager to initialize
71 * @size: size in bytes to manage
72 * @chunk_size: minimum page size in bytes for our allocations
73 *
74 * Initializes the memory manager and its resources.
75 *
76 * Returns:
77 * 0 on success, error code on failure.
78 */
79int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)
80{
81 unsigned int i;
82 u64 offset;
83
84 if (size < chunk_size)
85 return -EINVAL;
86
87 if (chunk_size < PAGE_SIZE)
88 return -EINVAL;
89
90 if (!is_power_of_2(chunk_size))
91 return -EINVAL;
92
93 size = round_down(size, chunk_size);
94
95 mm->size = size;
96 mm->avail = size;
97 mm->chunk_size = chunk_size;
98 mm->max_order = ilog2(size) - ilog2(chunk_size);
99
100 BUG_ON(mm->max_order > DRM_BUDDY_MAX_ORDER);
101
102 mm->free_list = kmalloc_array(mm->max_order + 1,
103 sizeof(struct list_head),
104 GFP_KERNEL);
105 if (!mm->free_list)
106 return -ENOMEM;
107
108 for (i = 0; i <= mm->max_order; ++i)
109 INIT_LIST_HEAD(&mm->free_list[i]);
110
111 mm->n_roots = hweight64(size);
112
113 mm->roots = kmalloc_array(mm->n_roots,
114 sizeof(struct drm_buddy_block *),
115 GFP_KERNEL);
116 if (!mm->roots)
117 goto out_free_list;
118
119 offset = 0;
120 i = 0;
121
122 /*
123 * Split into power-of-two blocks, in case we are given a size that is
124 * not itself a power-of-two.
125 */
126 do {
127 struct drm_buddy_block *root;
128 unsigned int order;
129 u64 root_size;
130
131 root_size = rounddown_pow_of_two(size);
132 order = ilog2(root_size) - ilog2(chunk_size);
133
134 root = drm_block_alloc(mm, NULL, order, offset);
135 if (!root)
136 goto out_free_roots;
137
138 mark_free(mm, root);
139
140 BUG_ON(i > mm->max_order);
141 BUG_ON(drm_buddy_block_size(mm, root) < chunk_size);
142
143 mm->roots[i] = root;
144
145 offset += root_size;
146 size -= root_size;
147 i++;
148 } while (size);
149
150 return 0;
151
152out_free_roots:
153 while (i--)
154 drm_block_free(mm, mm->roots[i]);
155 kfree(mm->roots);
156out_free_list:
157 kfree(mm->free_list);
158 return -ENOMEM;
159}
160EXPORT_SYMBOL(drm_buddy_init);
161
162/**
163 * drm_buddy_fini - tear down the memory manager
164 *
165 * @mm: DRM buddy manager to free
166 *
167 * Cleanup memory manager resources and the freelist
168 */
169void drm_buddy_fini(struct drm_buddy *mm)
170{
171 int i;
172
173 for (i = 0; i < mm->n_roots; ++i) {
174 WARN_ON(!drm_buddy_block_is_free(mm->roots[i]));
175 drm_block_free(mm, mm->roots[i]);
176 }
177
178 WARN_ON(mm->avail != mm->size);
179
180 kfree(mm->roots);
181 kfree(mm->free_list);
182}
183EXPORT_SYMBOL(drm_buddy_fini);
184
185static int split_block(struct drm_buddy *mm,
186 struct drm_buddy_block *block)
187{
188 unsigned int block_order = drm_buddy_block_order(block) - 1;
189 u64 offset = drm_buddy_block_offset(block);
190
191 BUG_ON(!drm_buddy_block_is_free(block));
192 BUG_ON(!drm_buddy_block_order(block));
193
194 block->left = drm_block_alloc(mm, block, block_order, offset);
195 if (!block->left)
196 return -ENOMEM;
197
198 block->right = drm_block_alloc(mm, block, block_order,
199 offset + (mm->chunk_size << block_order));
200 if (!block->right) {
201 drm_block_free(mm, block->left);
202 return -ENOMEM;
203 }
204
205 mark_free(mm, block->left);
206 mark_free(mm, block->right);
207
208 mark_split(block);
209
210 return 0;
211}
212
213static struct drm_buddy_block *
214get_buddy(struct drm_buddy_block *block)
215{
216 struct drm_buddy_block *parent;
217
218 parent = block->parent;
219 if (!parent)
220 return NULL;
221
222 if (parent->left == block)
223 return parent->right;
224
225 return parent->left;
226}
227
228static void __drm_buddy_free(struct drm_buddy *mm,
229 struct drm_buddy_block *block)
230{
231 struct drm_buddy_block *parent;
232
233 while ((parent = block->parent)) {
234 struct drm_buddy_block *buddy;
235
236 buddy = get_buddy(block);
237
238 if (!drm_buddy_block_is_free(buddy))
239 break;
240
241 list_del(&buddy->link);
242
243 drm_block_free(mm, block);
244 drm_block_free(mm, buddy);
245
246 block = parent;
247 }
248
249 mark_free(mm, block);
250}
251
252/**
253 * drm_buddy_free_block - free a block
254 *
255 * @mm: DRM buddy manager
256 * @block: block to be freed
257 */
258void drm_buddy_free_block(struct drm_buddy *mm,
259 struct drm_buddy_block *block)
260{
261 BUG_ON(!drm_buddy_block_is_allocated(block));
262 mm->avail += drm_buddy_block_size(mm, block);
263 __drm_buddy_free(mm, block);
264}
265EXPORT_SYMBOL(drm_buddy_free_block);
266
267/**
268 * drm_buddy_free_list - free blocks
269 *
270 * @mm: DRM buddy manager
271 * @objects: input list head to free blocks
272 */
273void drm_buddy_free_list(struct drm_buddy *mm, struct list_head *objects)
274{
275 struct drm_buddy_block *block, *on;
276
277 list_for_each_entry_safe(block, on, objects, link) {
278 drm_buddy_free_block(mm, block);
279 cond_resched();
280 }
281 INIT_LIST_HEAD(objects);
282}
283EXPORT_SYMBOL(drm_buddy_free_list);
284
285/**
286 * drm_buddy_alloc_blocks - allocate power-of-two blocks
287 *
288 * @mm: DRM buddy manager to allocate from
289 * @order: size of the allocation
290 *
291 * The order value here translates to:
292 *
293 * 0 = 2^0 * mm->chunk_size
294 * 1 = 2^1 * mm->chunk_size
295 * 2 = 2^2 * mm->chunk_size
296 *
297 * Returns:
298 * allocated ptr to the &drm_buddy_block on success
299 */
300struct drm_buddy_block *
301drm_buddy_alloc_blocks(struct drm_buddy *mm, unsigned int order)
302{
303 struct drm_buddy_block *block = NULL;
304 unsigned int i;
305 int err;
306
307 for (i = order; i <= mm->max_order; ++i) {
308 block = list_first_entry_or_null(&mm->free_list[i],
309 struct drm_buddy_block,
310 link);
311 if (block)
312 break;
313 }
314
315 if (!block)
316 return ERR_PTR(-ENOSPC);
317
318 BUG_ON(!drm_buddy_block_is_free(block));
319
320 while (i != order) {
321 err = split_block(mm, block);
322 if (unlikely(err))
323 goto out_free;
324
325 /* Go low */
326 block = block->left;
327 i--;
328 }
329
330 mark_allocated(block);
331 mm->avail -= drm_buddy_block_size(mm, block);
332 kmemleak_update_trace(block);
333 return block;
334
335out_free:
336 if (i != order)
337 __drm_buddy_free(mm, block);
338 return ERR_PTR(err);
339}
340EXPORT_SYMBOL(drm_buddy_alloc_blocks);
341
342static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
343{
344 return s1 <= e2 && e1 >= s2;
345}
346
347static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
348{
349 return s1 <= s2 && e1 >= e2;
350}
351
352/**
353 * drm_buddy_alloc_range - allocate range
354 *
355 * @mm: DRM buddy manager to allocate from
356 * @blocks: output list head to add allocated blocks
357 * @start: start of the allowed range for this block
358 * @size: size of the allocation
359 *
360 * Intended for pre-allocating portions of the address space, for example to
361 * reserve a block for the initial framebuffer or similar, hence the expectation
362 * here is that drm_buddy_alloc_blocks() is still the main vehicle for
363 * allocations, so if that's not the case then the drm_mm range allocator is
364 * probably a much better fit, and so you should probably go use that instead.
365 *
366 * Note that it's safe to chain together multiple alloc_ranges
367 * with the same blocks list
368 *
369 * Returns:
370 * 0 on success, error code on failure.
371 */
372int drm_buddy_alloc_range(struct drm_buddy *mm,
373 struct list_head *blocks,
374 u64 start, u64 size)
375{
376 struct drm_buddy_block *block;
377 struct drm_buddy_block *buddy;
378 LIST_HEAD(allocated);
379 LIST_HEAD(dfs);
380 u64 end;
381 int err;
382 int i;
383
384 if (size < mm->chunk_size)
385 return -EINVAL;
386
387 if (!IS_ALIGNED(size | start, mm->chunk_size))
388 return -EINVAL;
389
390 if (range_overflows(start, size, mm->size))
391 return -EINVAL;
392
393 for (i = 0; i < mm->n_roots; ++i)
394 list_add_tail(&mm->roots[i]->tmp_link, &dfs);
395
396 end = start + size - 1;
397
398 do {
399 u64 block_start;
400 u64 block_end;
401
402 block = list_first_entry_or_null(&dfs,
403 struct drm_buddy_block,
404 tmp_link);
405 if (!block)
406 break;
407
408 list_del(&block->tmp_link);
409
410 block_start = drm_buddy_block_offset(block);
411 block_end = block_start + drm_buddy_block_size(mm, block) - 1;
412
413 if (!overlaps(start, end, block_start, block_end))
414 continue;
415
416 if (drm_buddy_block_is_allocated(block)) {
417 err = -ENOSPC;
418 goto err_free;
419 }
420
421 if (contains(start, end, block_start, block_end)) {
422 if (!drm_buddy_block_is_free(block)) {
423 err = -ENOSPC;
424 goto err_free;
425 }
426
427 mark_allocated(block);
428 mm->avail -= drm_buddy_block_size(mm, block);
429 list_add_tail(&block->link, &allocated);
430 continue;
431 }
432
433 if (!drm_buddy_block_is_split(block)) {
434 err = split_block(mm, block);
435 if (unlikely(err))
436 goto err_undo;
437 }
438
439 list_add(&block->right->tmp_link, &dfs);
440 list_add(&block->left->tmp_link, &dfs);
441 } while (1);
442
443 list_splice_tail(&allocated, blocks);
444 return 0;
445
446err_undo:
447 /*
448 * We really don't want to leave around a bunch of split blocks, since
449 * bigger is better, so make sure we merge everything back before we
450 * free the allocated blocks.
451 */
452 buddy = get_buddy(block);
453 if (buddy &&
454 (drm_buddy_block_is_free(block) &&
455 drm_buddy_block_is_free(buddy)))
456 __drm_buddy_free(mm, block);
457
458err_free:
459 drm_buddy_free_list(mm, &allocated);
460 return err;
461}
462EXPORT_SYMBOL(drm_buddy_alloc_range);
463
464/**
465 * drm_buddy_block_print - print block information
466 *
467 * @mm: DRM buddy manager
468 * @block: DRM buddy block
469 * @p: DRM printer to use
470 */
471void drm_buddy_block_print(struct drm_buddy *mm,
472 struct drm_buddy_block *block,
473 struct drm_printer *p)
474{
475 u64 start = drm_buddy_block_offset(block);
476 u64 size = drm_buddy_block_size(mm, block);
477
478 drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size);
479}
480EXPORT_SYMBOL(drm_buddy_block_print);
481
482/**
483 * drm_buddy_print - print allocator state
484 *
485 * @mm: DRM buddy manager
486 * @p: DRM printer to use
487 */
488void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p)
489{
490 int order;
491
492 drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB\n",
493 mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20);
494
495 for (order = mm->max_order; order >= 0; order--) {
496 struct drm_buddy_block *block;
497 u64 count = 0, free;
498
499 list_for_each_entry(block, &mm->free_list[order], link) {
500 BUG_ON(!drm_buddy_block_is_free(block));
501 count++;
502 }
503
504 drm_printf(p, "order-%d ", order);
505
506 free = count * (mm->chunk_size << order);
507 if (free < SZ_1M)
508 drm_printf(p, "free: %lluKiB", free >> 10);
509 else
510 drm_printf(p, "free: %lluMiB", free >> 20);
511
512 drm_printf(p, ", pages: %llu\n", count);
513 }
514}
515EXPORT_SYMBOL(drm_buddy_print);
516
517static void drm_buddy_module_exit(void)
518{
519 kmem_cache_destroy(slab_blocks);
520}
521
522static int __init drm_buddy_module_init(void)
523{
524 slab_blocks = KMEM_CACHE(drm_buddy_block, 0);
525 if (!slab_blocks)
526 return -ENOMEM;
527
528 return 0;
529}
530
531module_init(drm_buddy_module_init);
532module_exit(drm_buddy_module_exit);
533
534MODULE_DESCRIPTION("DRM Buddy Allocator");
535MODULE_LICENSE("Dual MIT/GPL");
drivers/gpu/drm/drm_color_mgmt.c+4−0
@@ -82,6 +82,10 @@ · 81 unmodified lines
82 * driver boot-up state too. Drivers can access this blob through82 * driver boot-up state too. Drivers can access this blob through
83 * &drm_crtc_state.gamma_lut.83 * &drm_crtc_state.gamma_lut.
84 *84 *
85 * Note that for mostly historical reasons stemming from Xorg heritage,
86 * this is also used to store the color map (also sometimes color lut, CLUT
87 * or color palette) for indexed formats like DRM_FORMAT_C8.
88 *
85 * “GAMMA_LUT_SIZE”:89 * “GAMMA_LUT_SIZE”:
86 * Unsigned range property to give the size of the lookup table to be set90 * Unsigned range property to give the size of the lookup table to be set
87 * on the GAMMA_LUT property (the size depends on the underlying hardware).91 * on the GAMMA_LUT property (the size depends on the underlying hardware).
drivers/gpu/drm/drm_crtc_helper_internal.h+0−27
@@ -28,36 +28,9 @@ · 27 unmodified lines
28 28
29#include <drm/drm_connector.h>29#include <drm/drm_connector.h>
30#include <drm/drm_crtc.h>30#include <drm/drm_crtc.h>
31#include <drm/drm_dp_helper.h>
32#include <drm/drm_encoder.h>31#include <drm/drm_encoder.h>
33#include <drm/drm_modes.h>32#include <drm/drm_modes.h>
34 33
35/* drm_dp_aux_dev.c */
36#ifdef CONFIG_DRM_DP_AUX_CHARDEV
37int drm_dp_aux_dev_init(void);
38void drm_dp_aux_dev_exit(void);
39int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
40void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
41#else
42static inline int drm_dp_aux_dev_init(void)
43{
44 return 0;
45}
46
47static inline void drm_dp_aux_dev_exit(void)
48{
49}
50
51static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
52{
53 return 0;
54}
55
56static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
57{
58}
59#endif
60
61/* drm_probe_helper.c */34/* drm_probe_helper.c */
62enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,35enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
63 const struct drm_display_mode *mode);36 const struct drm_display_mode *mode);
drivers/gpu/drm/drm_dsc.c+1−1
@@ -12,7 +12,7 @@ · 11 unmodified lines
12#include <linux/errno.h>12#include <linux/errno.h>
13#include <linux/byteorder/generic.h>13#include <linux/byteorder/generic.h>
14#include <drm/drm_print.h>14#include <drm/drm_print.h>
15#include <drm/drm_dp_helper.h>15#include <drm/dp/drm_dp_helper.h>
16#include <drm/drm_dsc.h>16#include <drm/drm_dsc.h>
17 17
18/**18/**
drivers/gpu/drm/drm_edid.c+68−36
@@ -93,6 +93,8 @@ static int oui(u8 first, u8 second, u8 third) · 92 unmodified lines
93/* Non desktop display (i.e. HMD) */93/* Non desktop display (i.e. HMD) */
94#define EDID_QUIRK_NON_DESKTOP (1 << 12)94#define EDID_QUIRK_NON_DESKTOP (1 << 12)
95 95
96#define MICROSOFT_IEEE_OUI 0xca125c
97
96struct detailed_mode_closure {98struct detailed_mode_closure {
97 struct drm_connector *connector;99 struct drm_connector *connector;
98 struct edid *edid;100 struct edid *edid;
@@ -212,9 +214,7 @@ static const struct edid_quirk { · 113 unmodified lines
212 214
213 /* Windows Mixed Reality Headsets */215 /* Windows Mixed Reality Headsets */
214 EDID_QUIRK('A', 'C', 'R', 0x7fce, EDID_QUIRK_NON_DESKTOP),216 EDID_QUIRK('A', 'C', 'R', 0x7fce, EDID_QUIRK_NON_DESKTOP),
215 EDID_QUIRK('H', 'P', 'N', 0x3515, EDID_QUIRK_NON_DESKTOP),
216 EDID_QUIRK('L', 'E', 'N', 0x0408, EDID_QUIRK_NON_DESKTOP),217 EDID_QUIRK('L', 'E', 'N', 0x0408, EDID_QUIRK_NON_DESKTOP),
217 EDID_QUIRK('L', 'E', 'N', 0xb800, EDID_QUIRK_NON_DESKTOP),
218 EDID_QUIRK('F', 'U', 'J', 0x1970, EDID_QUIRK_NON_DESKTOP),218 EDID_QUIRK('F', 'U', 'J', 0x1970, EDID_QUIRK_NON_DESKTOP),
219 EDID_QUIRK('D', 'E', 'L', 0x7fce, EDID_QUIRK_NON_DESKTOP),219 EDID_QUIRK('D', 'E', 'L', 0x7fce, EDID_QUIRK_NON_DESKTOP),
220 EDID_QUIRK('S', 'E', 'C', 0x144a, EDID_QUIRK_NON_DESKTOP),220 EDID_QUIRK('S', 'E', 'C', 0x144a, EDID_QUIRK_NON_DESKTOP),
@@ -3776,7 +3776,7 @@ static int do_y420vdb_modes(struct drm_connector *connector, · 3555 unmodified lines
3776 }3776 }
3777 3777
3778 if (modes > 0)3778 if (modes > 0)
3779 info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;3779 info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
3780 return modes;3780 return modes;
3781}3781}
3782 3782
@@ -4222,6 +4222,17 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db) · 439 unmodified lines
4222 return oui(db[3], db[2], db[1]) == HDMI_FORUM_IEEE_OUI;4222 return oui(db[3], db[2], db[1]) == HDMI_FORUM_IEEE_OUI;
4223}4223}
4224 4224
4225static bool cea_db_is_microsoft_vsdb(const u8 *db)
4226{
4227 if (cea_db_tag(db) != VENDOR_BLOCK)
4228 return false;
4229
4230 if (cea_db_payload_len(db) != 21)
4231 return false;
4232
4233 return oui(db[3], db[2], db[1]) == MICROSOFT_IEEE_OUI;
4234}
4235
4225static bool cea_db_is_vcdb(const u8 *db)4236static bool cea_db_is_vcdb(const u8 *db)
4226{4237{
4227 if (cea_db_tag(db) != USE_EXTENDED_TAG)4238 if (cea_db_tag(db) != USE_EXTENDED_TAG)
@@ -4279,7 +4290,7 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector, · 51 unmodified lines
4279 if (map_len == 0) {4290 if (map_len == 0) {
4280 /* All CEA modes support ycbcr420 sampling also.*/4291 /* All CEA modes support ycbcr420 sampling also.*/
4281 hdmi->y420_cmdb_map = U64_MAX;4292 hdmi->y420_cmdb_map = U64_MAX;
4282 info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;4293 info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
4283 return;4294 return;
4284 }4295 }
4285 4296
@@ -4302,7 +4313,7 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector, · 16 unmodified lines
4302 map |= (u64)db[2 + count] << (8 * count);4313 map |= (u64)db[2 + count] << (8 * count);
4303 4314
4304 if (map)4315 if (map)
4305 info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;4316 info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
4306 4317
4307 hdmi->y420_cmdb_map = map;4318 hdmi->y420_cmdb_map = map;
4308}4319}
@@ -5075,21 +5086,21 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, · 766 unmodified lines
5075 5086
5076 if (hdmi[6] & DRM_EDID_HDMI_DC_30) {5087 if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
5077 dc_bpc = 10;5088 dc_bpc = 10;
5078 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30;5089 info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_30;
5079 DRM_DEBUG("%s: HDMI sink does deep color 30.\n",5090 DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
5080 connector->name);5091 connector->name);
5081 }5092 }
5082 5093
5083 if (hdmi[6] & DRM_EDID_HDMI_DC_36) {5094 if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
5084 dc_bpc = 12;5095 dc_bpc = 12;
5085 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36;5096 info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_36;
5086 DRM_DEBUG("%s: HDMI sink does deep color 36.\n",5097 DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
5087 connector->name);5098 connector->name);
5088 }5099 }
5089 5100
5090 if (hdmi[6] & DRM_EDID_HDMI_DC_48) {5101 if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
5091 dc_bpc = 16;5102 dc_bpc = 16;
5092 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48;5103 info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_48;
5093 DRM_DEBUG("%s: HDMI sink does deep color 48.\n",5104 DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
5094 connector->name);5105 connector->name);
5095 }5106 }
@@ -5104,16 +5115,9 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, · 8 unmodified lines
5104 connector->name, dc_bpc);5115 connector->name, dc_bpc);
5105 info->bpc = dc_bpc;5116 info->bpc = dc_bpc;
5106 5117
5107 /*
5108 * Deep color support mandates RGB444 support for all video
5109 * modes and forbids YCRCB422 support for all video modes per
5110 * HDMI 1.3 spec.
5111 */
5112 info->color_formats = DRM_COLOR_FORMAT_RGB444;
5113
5114 /* YCRCB444 is optional according to spec. */5118 /* YCRCB444 is optional according to spec. */
5115 if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {5119 if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
5116 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;5120 info->edid_hdmi_ycbcr444_dc_modes = info->edid_hdmi_rgb444_dc_modes;
5117 DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",5121 DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
5118 connector->name);5122 connector->name);
5119 }5123 }
@@ -5149,6 +5153,25 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db) · 29 unmodified lines
5149 drm_parse_hdmi_deep_color_info(connector, db);5153 drm_parse_hdmi_deep_color_info(connector, db);
5150}5154}
5151 5155
5156/*
5157 * See EDID extension for head-mounted and specialized monitors, specified at:
5158 * https://docs.microsoft.com/en-us/windows-hardware/drivers/display/specialized-monitors-edid-extension
5159 */
5160static void drm_parse_microsoft_vsdb(struct drm_connector *connector,
5161 const u8 *db)
5162{
5163 struct drm_display_info *info = &connector->display_info;
5164 u8 version = db[4];
5165 bool desktop_usage = db[5] & BIT(6);
5166
5167 /* Version 1 and 2 for HMDs, version 3 flags desktop usage explicitly */
5168 if (version == 1 || version == 2 || (version == 3 && !desktop_usage))
5169 info->non_desktop = true;
5170
5171 drm_dbg_kms(connector->dev, "HMD or specialized display VSDB version %u: 0x%02x\n",
5172 version, db[5]);
5173}
5174
5152static void drm_parse_cea_ext(struct drm_connector *connector,5175static void drm_parse_cea_ext(struct drm_connector *connector,
5153 const struct edid *edid)5176 const struct edid *edid)
5154{5177{
@@ -5165,9 +5188,9 @@ static void drm_parse_cea_ext(struct drm_connector *connector, · 10 unmodified lines
5165 /* The existence of a CEA block should imply RGB support */5188 /* The existence of a CEA block should imply RGB support */
5166 info->color_formats = DRM_COLOR_FORMAT_RGB444;5189 info->color_formats = DRM_COLOR_FORMAT_RGB444;
5167 if (edid_ext[3] & EDID_CEA_YCRCB444)5190 if (edid_ext[3] & EDID_CEA_YCRCB444)
5168 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;5191 info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
5169 if (edid_ext[3] & EDID_CEA_YCRCB422)5192 if (edid_ext[3] & EDID_CEA_YCRCB422)
5170 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;5193 info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
5171 5194
5172 if (cea_db_offsets(edid_ext, &start, &end))5195 if (cea_db_offsets(edid_ext, &start, &end))
5173 return;5196 return;
@@ -5179,6 +5202,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector, · 5 unmodified lines
5179 drm_parse_hdmi_vsdb_video(connector, db);5202 drm_parse_hdmi_vsdb_video(connector, db);
5180 if (cea_db_is_hdmi_forum_vsdb(db))5203 if (cea_db_is_hdmi_forum_vsdb(db))
5181 drm_parse_hdmi_forum_vsdb(connector, db);5204 drm_parse_hdmi_forum_vsdb(connector, db);
5205 if (cea_db_is_microsoft_vsdb(db))
5206 drm_parse_microsoft_vsdb(connector, db);
5182 if (cea_db_is_y420cmdb(db))5207 if (cea_db_is_y420cmdb(db))
5183 drm_parse_y420cmdb_bitmap(connector, db);5208 drm_parse_y420cmdb_bitmap(connector, db);
5184 if (cea_db_is_vcdb(db))5209 if (cea_db_is_vcdb(db))
@@ -5333,17 +5358,13 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi · 148 unmodified lines
5333 info->width_mm = edid->width_cm * 10;5358 info->width_mm = edid->width_cm * 10;
5334 info->height_mm = edid->height_cm * 10;5359 info->height_mm = edid->height_cm * 10;
5335 5360
5336 info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
5337
5338 drm_get_monitor_range(connector, edid);5361 drm_get_monitor_range(connector, edid);
5339 5362
5340 DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
5341
5342 if (edid->revision < 3)5363 if (edid->revision < 3)
5343 return quirks;5364 goto out;
5344 5365
5345 if (!(edid->input & DRM_EDID_INPUT_DIGITAL))5366 if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
5346 return quirks;5367 goto out;
5347 5368
5348 drm_parse_cea_ext(connector, edid);5369 drm_parse_cea_ext(connector, edid);
5349 5370
@@ -5363,7 +5384,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi · 13 unmodified lines
5363 5384
5364 /* Only defined for 1.4 with digital displays */5385 /* Only defined for 1.4 with digital displays */
5365 if (edid->revision < 4)5386 if (edid->revision < 4)
5366 return quirks;5387 goto out;
5367 5388
5368 switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {5389 switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
5369 case DRM_EDID_DIGITAL_DEPTH_6:5390 case DRM_EDID_DIGITAL_DEPTH_6:
@@ -5395,17 +5416,25 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi · 25 unmodified lines
5395 5416
5396 info->color_formats |= DRM_COLOR_FORMAT_RGB444;5417 info->color_formats |= DRM_COLOR_FORMAT_RGB444;
5397 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)5418 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
5398 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;5419 info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
5399 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)5420 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
5400 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;5421 info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
5401 5422
5402 drm_update_mso(connector, edid);5423 drm_update_mso(connector, edid);
5403 5424
5425out:
5426 if (quirks & EDID_QUIRK_NON_DESKTOP) {
5427 drm_dbg_kms(connector->dev, "Non-desktop display%s\n",
5428 info->non_desktop ? " (redundant quirk)" : "");
5429 info->non_desktop = true;
5430 }
5431
5404 return quirks;5432 return quirks;
5405}5433}
5406 5434
5407static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,5435static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,
5408 struct displayid_detailed_timings_1 *timings)5436 struct displayid_detailed_timings_1 *timings,
5437 bool type_7)
5409{5438{
5410 struct drm_display_mode *mode;5439 struct drm_display_mode *mode;
5411 unsigned pixel_clock = (timings->pixel_clock[0] |5440 unsigned pixel_clock = (timings->pixel_clock[0] |
@@ -5426,7 +5455,8 @@ static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *d · 14 unmodified lines
5426 if (!mode)5455 if (!mode)
5427 return NULL;5456 return NULL;
5428 5457
5429 mode->clock = pixel_clock * 10;5458 /* resolution is kHz for type VII, and 10 kHz for type I */
5459 mode->clock = type_7 ? pixel_clock : pixel_clock * 10;
5430 mode->hdisplay = hactive;5460 mode->hdisplay = hactive;
5431 mode->hsync_start = mode->hdisplay + hsync;5461 mode->hsync_start = mode->hdisplay + hsync;
5432 mode->hsync_end = mode->hsync_start + hsync_width;5462 mode->hsync_end = mode->hsync_start + hsync_width;
@@ -5457,6 +5487,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector, · 24 unmodified lines
5457 int num_timings;5487 int num_timings;
5458 struct drm_display_mode *newmode;5488 struct drm_display_mode *newmode;
5459 int num_modes = 0;5489 int num_modes = 0;
5490 bool type_7 = block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING;
5460 /* blocks must be multiple of 20 bytes length */5491 /* blocks must be multiple of 20 bytes length */
5461 if (block->num_bytes % 20)5492 if (block->num_bytes % 20)
5462 return 0;5493 return 0;
@@ -5465,7 +5496,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector, · 2 unmodified lines
5465 for (i = 0; i < num_timings; i++) {5496 for (i = 0; i < num_timings; i++) {
5466 struct displayid_detailed_timings_1 *timings = &det->timings[i];5497 struct displayid_detailed_timings_1 *timings = &det->timings[i];
5467 5498
5468 newmode = drm_mode_displayid_detailed(connector->dev, timings);5499 newmode = drm_mode_displayid_detailed(connector->dev, timings, type_7);
5469 if (!newmode)5500 if (!newmode)
5470 continue;5501 continue;
5471 5502
@@ -5484,7 +5515,8 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, · 12 unmodified lines
5484 5515
5485 displayid_iter_edid_begin(edid, &iter);5516 displayid_iter_edid_begin(edid, &iter);
5486 displayid_iter_for_each(block, &iter) {5517 displayid_iter_for_each(block, &iter) {
5487 if (block->tag == DATA_BLOCK_TYPE_1_DETAILED_TIMING)5518 if (block->tag == DATA_BLOCK_TYPE_1_DETAILED_TIMING ||
5519 block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING)
5488 num_modes += add_displayid_detailed_1_modes(connector, block);5520 num_modes += add_displayid_detailed_1_modes(connector, block);
5489 }5521 }
5490 displayid_iter_end(&iter);5522 displayid_iter_end(&iter);
@@ -5652,7 +5684,7 @@ static bool is_hdmi2_sink(const struct drm_connector *connector) · 161 unmodified lines
5652 return true;5684 return true;
5653 5685
5654 return connector->display_info.hdmi.scdc.supported ||5686 return connector->display_info.hdmi.scdc.supported ||
5655 connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;5687 connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR420;
5656}5688}
5657 5689
5658static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)5690static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)
@@ -5891,13 +5923,13 @@ static const u32 hdmi_colorimetry_val[] = { · 232 unmodified lines
5891#undef ACE5923#undef ACE
5892 5924
5893/**5925/**
5894 * drm_hdmi_avi_infoframe_colorspace() - fill the HDMI AVI infoframe5926 * drm_hdmi_avi_infoframe_colorimetry() - fill the HDMI AVI infoframe
5895 * colorspace information5927 * colorimetry information
5896 * @frame: HDMI AVI infoframe5928 * @frame: HDMI AVI infoframe
5897 * @conn_state: connector state5929 * @conn_state: connector state
5898 */5930 */
5899void5931void
5900drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,5932drm_hdmi_avi_infoframe_colorimetry(struct hdmi_avi_infoframe *frame,
5901 const struct drm_connector_state *conn_state)5933 const struct drm_connector_state *conn_state)
5902{5934{
5903 u32 colorimetry_val;5935 u32 colorimetry_val;
@@ -5916,7 +5948,7 @@ drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, · 12 unmodified lines
5916 frame->extended_colorimetry = (colorimetry_val >> 2) &5948 frame->extended_colorimetry = (colorimetry_val >> 2) &
5917 EXTENDED_COLORIMETRY_MASK;5949 EXTENDED_COLORIMETRY_MASK;
5918}5950}
5919EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorspace);5951EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorimetry);
5920 5952
5921/**5953/**
5922 * drm_hdmi_avi_infoframe_quant_range() - fill the HDMI AVI infoframe5954 * drm_hdmi_avi_infoframe_quant_range() - fill the HDMI AVI infoframe
drivers/gpu/drm/drm_kms_helper_common.c+0−14
@@ -61,17 +61,3 @@ MODULE_PARM_DESC(edid_firmware, · 60 unmodified lines
61 "DEPRECATED. Use drm.edid_firmware module parameter instead.");61 "DEPRECATED. Use drm.edid_firmware module parameter instead.");
62 62
63#endif63#endif
64
65static int __init drm_kms_helper_init(void)
66{
67 return drm_dp_aux_dev_init();
68}
69
70static void __exit drm_kms_helper_exit(void)
71{
72 /* Call exit functions from specific kms helpers here */
73 drm_dp_aux_dev_exit();
74}
75
76module_init(drm_kms_helper_init);
77module_exit(drm_kms_helper_exit);
drivers/gpu/drm/drm_plane.c+2−7
@@ -202,17 +202,13 @@ static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane · 201 unmodified lines
202 202
203 memcpy(formats_ptr(blob_data), plane->format_types, formats_size);203 memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
204 204
205 /* If we can't determine support, just bail */
206 if (!plane->funcs->format_mod_supported)
207 goto done;
208
209 mod = modifiers_ptr(blob_data);205 mod = modifiers_ptr(blob_data);
210 for (i = 0; i < plane->modifier_count; i++) {206 for (i = 0; i < plane->modifier_count; i++) {
211 for (j = 0; j < plane->format_count; j++) {207 for (j = 0; j < plane->format_count; j++) {
212 if (plane->funcs->format_mod_supported(plane,208 if (!plane->funcs->format_mod_supported ||
209 plane->funcs->format_mod_supported(plane,
213 plane->format_types[j],210 plane->format_types[j],
214 plane->modifiers[i])) {211 plane->modifiers[i])) {
215
216 mod->formats |= 1ULL << j;212 mod->formats |= 1ULL << j;
217 }213 }
218 }214 }
@@ -223,7 +219,6 @@ static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane · 4 unmodified lines
223 mod++;219 mod++;
224 }220 }
225 221
226done:
227 drm_object_attach_property(&plane->base, config->modifiers_property,222 drm_object_attach_property(&plane->base, config->modifiers_property,
228 blob->base.id);223 blob->base.id);
229 224
drivers/gpu/drm/drm_privacy_screen.c+4−1
@@ -387,7 +387,8 @@ static void drm_privacy_screen_device_release(struct device *dev) · 386 unmodified lines
387 * * An ERR_PTR(errno) on failure.387 * * An ERR_PTR(errno) on failure.
388 */388 */
389struct drm_privacy_screen *drm_privacy_screen_register(389struct drm_privacy_screen *drm_privacy_screen_register(
390 struct device *parent, const struct drm_privacy_screen_ops *ops)390 struct device *parent, const struct drm_privacy_screen_ops *ops,
391 void *data)
391{392{
392 struct drm_privacy_screen *priv;393 struct drm_privacy_screen *priv;
393 int ret;394 int ret;
@@ -404,6 +405,7 @@ struct drm_privacy_screen *drm_privacy_screen_register( · 10 unmodified lines
404 priv->dev.parent = parent;405 priv->dev.parent = parent;
405 priv->dev.release = drm_privacy_screen_device_release;406 priv->dev.release = drm_privacy_screen_device_release;
406 dev_set_name(&priv->dev, "privacy_screen-%s", dev_name(parent));407 dev_set_name(&priv->dev, "privacy_screen-%s", dev_name(parent));
408 priv->drvdata = data;
407 priv->ops = ops;409 priv->ops = ops;
408 410
409 priv->ops->get_hw_state(priv);411 priv->ops->get_hw_state(priv);
@@ -439,6 +441,7 @@ void drm_privacy_screen_unregister(struct drm_privacy_screen *priv) · 29 unmodified lines
439 mutex_unlock(&drm_privacy_screen_devs_lock);441 mutex_unlock(&drm_privacy_screen_devs_lock);
440 442
441 mutex_lock(&priv->lock);443 mutex_lock(&priv->lock);
444 priv->drvdata = NULL;
442 priv->ops = NULL;445 priv->ops = NULL;
443 mutex_unlock(&priv->lock);446 mutex_unlock(&priv->lock);
444 447
drivers/gpu/drm/drm_privacy_screen_x86.c+17−0
@@ -50,6 +50,13 @@ static bool __init detect_thinkpad_privacy_screen(void) · 49 unmodified lines
50}50}
51#endif51#endif
52 52
53#if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN)
54static bool __init detect_chromeos_privacy_screen(void)
55{
56 return acpi_dev_present("GOOG0010", NULL, -1);
57}
58#endif
59
53static const struct arch_init_data arch_init_data[] __initconst = {60static const struct arch_init_data arch_init_data[] __initconst = {
54#if IS_ENABLED(CONFIG_THINKPAD_ACPI)61#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
55 {62 {
@@ -61,6 +68,16 @@ static const struct arch_init_data arch_init_data[] __initconst = { · 5 unmodified lines
61 .detect = detect_thinkpad_privacy_screen,68 .detect = detect_thinkpad_privacy_screen,
62 },69 },
63#endif70#endif
71#if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN)
72 {
73 .lookup = {
74 .dev_id = NULL,
75 .con_id = NULL,
76 .provider = "privacy_screen-GOOG0010:00",
77 },
78 .detect = detect_chromeos_privacy_screen,
79 },
80#endif
64};81};
65 82
66void __init drm_privacy_screen_lookup_init(void)83void __init drm_privacy_screen_lookup_init(void)
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c+1−2
@@ -189,8 +189,7 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit) · 188 unmodified lines
189 continue;189 continue;
190 190
191 if (bo->flags & ETNA_SUBMIT_BO_WRITE) {191 if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
192 ret = dma_resv_get_fences(robj, NULL,192 ret = dma_resv_get_fences(robj, true, &bo->nr_shared,
193 &bo->nr_shared,
194 &bo->shared);193 &bo->shared);
195 if (ret)194 if (ret)
196 return ret;195 return ret;
drivers/gpu/drm/exynos/Kconfig+1−0
@@ -66,6 +66,7 @@ config DRM_EXYNOS_DP · 65 unmodified lines
66 bool "Exynos specific extensions for Analogix DP driver"66 bool "Exynos specific extensions for Analogix DP driver"
67 depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON67 depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
68 select DRM_ANALOGIX_DP68 select DRM_ANALOGIX_DP
69 select DRM_DP_HELPER
69 default DRM_EXYNOS70 default DRM_EXYNOS
70 select DRM_PANEL71 select DRM_PANEL
71 help72 help
drivers/gpu/drm/exynos/exynos_drm_dsi.c+12−1
@@ -258,6 +258,7 @@ struct exynos_dsi { · 257 unmodified lines
258 struct list_head bridge_chain;258 struct list_head bridge_chain;
259 struct drm_bridge *out_bridge;259 struct drm_bridge *out_bridge;
260 struct device *dev;260 struct device *dev;
261 struct drm_display_mode mode;
261 262
262 void __iomem *reg_base;263 void __iomem *reg_base;
263 struct phy *phy;264 struct phy *phy;
@@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) · 617 unmodified lines
881 882
882static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)883static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
883{884{
884 struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;885 struct drm_display_mode *m = &dsi->mode;
885 unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;886 unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
886 u32 reg;887 u32 reg;
887 888
@@ -1446,6 +1447,15 @@ static void exynos_dsi_disable(struct drm_encoder *encoder) · 558 unmodified lines
1446 pm_runtime_put_sync(dsi->dev);1447 pm_runtime_put_sync(dsi->dev);
1447}1448}
1448 1449
1450static void exynos_dsi_mode_set(struct drm_encoder *encoder,
1451 struct drm_display_mode *mode,
1452 struct drm_display_mode *adjusted_mode)
1453{
1454 struct exynos_dsi *dsi = encoder_to_dsi(encoder);
1455
1456 drm_mode_copy(&dsi->mode, adjusted_mode);
1457}
1458
1449static enum drm_connector_status1459static enum drm_connector_status
1450exynos_dsi_detect(struct drm_connector *connector, bool force)1460exynos_dsi_detect(struct drm_connector *connector, bool force)
1451{1461{
@@ -1513,6 +1523,7 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder) · 61 unmodified lines
1513static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {1523static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
1514 .enable = exynos_dsi_enable,1524 .enable = exynos_dsi_enable,
1515 .disable = exynos_dsi_disable,1525 .disable = exynos_dsi_disable,
1526 .mode_set = exynos_dsi_mode_set,
1516};1527};
1517 1528
1518MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);1529MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
drivers/gpu/drm/gma500/cdv_intel_dp.c+4−10
@@ -31,7 +31,7 @@ · 30 unmodified lines
31 31
32#include <drm/drm_crtc.h>32#include <drm/drm_crtc.h>
33#include <drm/drm_crtc_helper.h>33#include <drm/drm_crtc_helper.h>
34#include <drm/drm_dp_helper.h>34#include <drm/dp/drm_dp_helper.h>
35#include <drm/drm_simple_kms_helper.h>35#include <drm/drm_simple_kms_helper.h>
36 36
37#include "gma_display.h"37#include "gma_display.h"
@@ -82,7 +82,6 @@ i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) · 44 unmodified lines
82{82{
83 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;83 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
84 int mode = MODE_I2C_START;84 int mode = MODE_I2C_START;
85 int ret;
86 85
87 if (reading)86 if (reading)
88 mode |= MODE_I2C_READ;87 mode |= MODE_I2C_READ;
@@ -90,8 +89,7 @@ i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) · 1 unmodified line
90 mode |= MODE_I2C_WRITE;89 mode |= MODE_I2C_WRITE;
91 algo_data->address = address;90 algo_data->address = address;
92 algo_data->running = true;91 algo_data->running = true;
93 ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);92 return i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
94 return ret;
95}93}
96 94
97/*95/*
@@ -122,13 +120,11 @@ static int · 24 unmodified lines
122i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)120i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
123{121{
124 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;122 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
125 int ret;
126 123
127 if (!algo_data->running)124 if (!algo_data->running)
128 return -EIO;125 return -EIO;
129 126
130 ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);127 return i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
131 return ret;
132}128}
133 129
134/*130/*
@@ -139,13 +135,11 @@ static int · 4 unmodified lines
139i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)135i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
140{136{
141 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;137 struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
142 int ret;
143 138
144 if (!algo_data->running)139 if (!algo_data->running)
145 return -EIO;140 return -EIO;
146 141
147 ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);142 return i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
148 return ret;
149}143}
150 144
151static int145static int
drivers/gpu/drm/gma500/gma_display.c+2−4
@@ -335,7 +335,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc, · 334 unmodified lines
335 struct psb_gem_object *pobj;335 struct psb_gem_object *pobj;
336 struct psb_gem_object *cursor_pobj = gma_crtc->cursor_pobj;336 struct psb_gem_object *cursor_pobj = gma_crtc->cursor_pobj;
337 struct drm_gem_object *obj;337 struct drm_gem_object *obj;
338 void *tmp_dst, *tmp_src;338 void *tmp_dst;
339 int ret = 0, i, cursor_pages;339 int ret = 0, i, cursor_pages;
340 340
341 /* If we didn't get a handle then turn the cursor off */341 /* If we didn't get a handle then turn the cursor off */
@@ -400,9 +400,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc, · 58 unmodified lines
400 /* Copy the cursor to cursor mem */400 /* Copy the cursor to cursor mem */
401 tmp_dst = dev_priv->vram_addr + cursor_pobj->offset;401 tmp_dst = dev_priv->vram_addr + cursor_pobj->offset;
402 for (i = 0; i < cursor_pages; i++) {402 for (i = 0; i < cursor_pages; i++) {
403 tmp_src = kmap(pobj->pages[i]);403 memcpy_from_page(tmp_dst, pobj->pages[i], 0, PAGE_SIZE);
404 memcpy(tmp_dst, tmp_src, PAGE_SIZE);
405 kunmap(pobj->pages[i]);
406 tmp_dst += PAGE_SIZE;404 tmp_dst += PAGE_SIZE;
407 }405 }
408 406
drivers/gpu/drm/gma500/intel_bios.c+1−1
@@ -6,7 +6,7 @@ · 5 unmodified lines
6 * Eric Anholt <eric@anholt.net>6 * Eric Anholt <eric@anholt.net>
7 */7 */
8#include <drm/drm.h>8#include <drm/drm.h>
9#include <drm/drm_dp_helper.h>9#include <drm/dp/drm_dp_helper.h>
10 10
11#include "intel_bios.h"11#include "intel_bios.h"
12#include "psb_drv.h"12#include "psb_drv.h"
drivers/gpu/drm/gma500/mmu.c+4−4
@@ -184,17 +184,17 @@ struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, · 183 unmodified lines
184 pd->invalid_pte = 0;184 pd->invalid_pte = 0;
185 }185 }
186 186
187 v = kmap(pd->dummy_pt);187 v = kmap_local_page(pd->dummy_pt);
188 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)188 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
189 v[i] = pd->invalid_pte;189 v[i] = pd->invalid_pte;
190 190
191 kunmap(pd->dummy_pt);191 kunmap_local(v);
192 192
193 v = kmap(pd->p);193 v = kmap_local_page(pd->p);
194 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)194 for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
195 v[i] = pd->invalid_pde;195 v[i] = pd->invalid_pde;
196 196
197 kunmap(pd->p);197 kunmap_local(v);
198 198
199 clear_page(kmap(pd->dummy_page));199 clear_page(kmap(pd->dummy_page));
200 kunmap(pd->dummy_page);200 kunmap(pd->dummy_page);
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c+2−1
@@ -20,6 +20,7 @@ · 19 unmodified lines
20#include <drm/drm_gem_framebuffer_helper.h>20#include <drm/drm_gem_framebuffer_helper.h>
21#include <drm/drm_gem_vram_helper.h>21#include <drm/drm_gem_vram_helper.h>
22#include <drm/drm_managed.h>22#include <drm/drm_managed.h>
23#include <drm/drm_module.h>
23#include <drm/drm_vblank.h>24#include <drm/drm_vblank.h>
24 25
25#include "hibmc_drm_drv.h"26#include "hibmc_drm_drv.h"
@@ -379,7 +380,7 @@ static struct pci_driver hibmc_pci_driver = { · 353 unmodified lines
379 .driver.pm = &hibmc_pm_ops,380 .driver.pm = &hibmc_pm_ops,
380};381};
381 382
382module_pci_driver(hibmc_pci_driver);383drm_module_pci_driver(hibmc_pci_driver);
383 384
384MODULE_DEVICE_TABLE(pci, hibmc_pci_table);385MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
385MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");386MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
drivers/gpu/drm/i915/Kconfig+2−0
@@ -9,6 +9,7 @@ config DRM_I915 · 8 unmodified lines
9 # the shmem_readpage() which depends upon tmpfs9 # the shmem_readpage() which depends upon tmpfs
10 select SHMEM10 select SHMEM
11 select TMPFS11 select TMPFS
12 select DRM_DP_HELPER
12 select DRM_KMS_HELPER13 select DRM_KMS_HELPER
13 select DRM_PANEL14 select DRM_PANEL
14 select DRM_MIPI_DSI15 select DRM_MIPI_DSI
@@ -27,6 +28,7 @@ config DRM_I915 · 12 unmodified lines
27 select CEC_CORE if CEC_NOTIFIER28 select CEC_CORE if CEC_NOTIFIER
28 select VMAP_PFN29 select VMAP_PFN
29 select DRM_TTM30 select DRM_TTM
31 select DRM_BUDDY
30 help32 help
31 Choose this option if you have a system that has "Intel Graphics33 Choose this option if you have a system that has "Intel Graphics
32 Media Accelerator" or "HD Graphics" integrated graphics,34 Media Accelerator" or "HD Graphics" integrated graphics,
drivers/gpu/drm/i915/Makefile+0−1
@@ -161,7 +161,6 @@ gem-y += \ · 160 unmodified lines
161i915-y += \161i915-y += \
162 $(gem-y) \162 $(gem-y) \
163 i915_active.o \163 i915_active.o \
164 i915_buddy.o \
165 i915_cmd_parser.o \164 i915_cmd_parser.o \
166 i915_deps.o \165 i915_deps.o \
167 i915_gem_evict.o \166 i915_gem_evict.o \
drivers/gpu/drm/i915/display/intel_bios.c+1−1
@@ -25,7 +25,7 @@ · 24 unmodified lines
25 *25 *
26 */26 */
27 27
28#include <drm/drm_dp_helper.h>28#include <drm/dp/drm_dp_helper.h>
29 29
30#include "display/intel_display.h"30#include "display/intel_display.h"
31#include "display/intel_display_types.h"31#include "display/intel_display_types.h"
drivers/gpu/drm/i915/display/intel_display.c+1−1
@@ -38,7 +38,7 @@ · 37 unmodified lines
38#include <drm/drm_atomic_helper.h>38#include <drm/drm_atomic_helper.h>
39#include <drm/drm_atomic_uapi.h>39#include <drm/drm_atomic_uapi.h>
40#include <drm/drm_damage_helper.h>40#include <drm/drm_damage_helper.h>
41#include <drm/drm_dp_helper.h>41#include <drm/dp/drm_dp_helper.h>
42#include <drm/drm_edid.h>42#include <drm/drm_edid.h>
43#include <drm/drm_fourcc.h>43#include <drm/drm_fourcc.h>
44#include <drm/drm_plane_helper.h>44#include <drm/drm_plane_helper.h>
drivers/gpu/drm/i915/display/intel_display_types.h+2−2
@@ -32,10 +32,10 @@ · 31 unmodified lines
32#include <linux/pwm.h>32#include <linux/pwm.h>
33#include <linux/sched/clock.h>33#include <linux/sched/clock.h>
34 34
35#include <drm/dp/drm_dp_dual_mode_helper.h>
36#include <drm/dp/drm_dp_mst_helper.h>
35#include <drm/drm_atomic.h>37#include <drm/drm_atomic.h>
36#include <drm/drm_crtc.h>38#include <drm/drm_crtc.h>
37#include <drm/drm_dp_dual_mode_helper.h>
38#include <drm/drm_dp_mst_helper.h>
39#include <drm/drm_dsc.h>39#include <drm/drm_dsc.h>
40#include <drm/drm_encoder.h>40#include <drm/drm_encoder.h>
41#include <drm/drm_fb_helper.h>41#include <drm/drm_fb_helper.h>
drivers/gpu/drm/i915/display/intel_dp.c+1−1
@@ -36,7 +36,7 @@ · 35 unmodified lines
36 36
37#include <drm/drm_atomic_helper.h>37#include <drm/drm_atomic_helper.h>
38#include <drm/drm_crtc.h>38#include <drm/drm_crtc.h>
39#include <drm/drm_dp_helper.h>39#include <drm/dp/drm_dp_helper.h>
40#include <drm/drm_edid.h>40#include <drm/drm_edid.h>
41#include <drm/drm_probe_helper.h>41#include <drm/drm_probe_helper.h>
42 42
drivers/gpu/drm/i915/display/intel_dp_hdcp.c+2−2
@@ -6,8 +6,8 @@ · 5 unmodified lines
6 * Sean Paul <seanpaul@chromium.org>6 * Sean Paul <seanpaul@chromium.org>
7 */7 */
8 8
9#include <drm/drm_dp_helper.h>9#include <drm/dp/drm_dp_helper.h>
10#include <drm/drm_dp_mst_helper.h>10#include <drm/dp/drm_dp_mst_helper.h>
11#include <drm/drm_hdcp.h>11#include <drm/drm_hdcp.h>
12#include <drm/drm_print.h>12#include <drm/drm_print.h>
13 13
drivers/gpu/drm/i915/display/intel_dp_link_training.h+1−1
@@ -6,7 +6,7 @@ · 5 unmodified lines
6#ifndef __INTEL_DP_LINK_TRAINING_H__6#ifndef __INTEL_DP_LINK_TRAINING_H__
7#define __INTEL_DP_LINK_TRAINING_H__7#define __INTEL_DP_LINK_TRAINING_H__
8 8
9#include <drm/drm_dp_helper.h>9#include <drm/dp/drm_dp_helper.h>
10 10
11struct intel_crtc_state;11struct intel_crtc_state;
12struct intel_dp;12struct intel_dp;
drivers/gpu/drm/i915/display/intel_hdmi.c+3−3
@@ -730,7 +730,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, · 729 unmodified lines
730 else730 else
731 frame->colorspace = HDMI_COLORSPACE_RGB;731 frame->colorspace = HDMI_COLORSPACE_RGB;
732 732
733 drm_hdmi_avi_infoframe_colorspace(frame, conn_state);733 drm_hdmi_avi_infoframe_colorimetry(frame, conn_state);
734 734
735 /* nonsense combination */735 /* nonsense combination */
736 drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&736 drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&
@@ -1912,7 +1912,7 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector, · 1175 unmodified lines
1912 if (ycbcr420_output)1912 if (ycbcr420_output)
1913 return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36;1913 return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36;
1914 else1914 else
1915 return info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36;1915 return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36;
1916 case 10:1916 case 10:
1917 if (!has_hdmi_sink)1917 if (!has_hdmi_sink)
1918 return false;1918 return false;
@@ -1920,7 +1920,7 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector, · 1 unmodified line
1920 if (ycbcr420_output)1920 if (ycbcr420_output)
1921 return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30;1921 return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30;
1922 else1922 else
1923 return info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30;1923 return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30;
1924 case 8:1924 case 8:
1925 return true;1925 return true;
1926 default:1926 default:
drivers/gpu/drm/i915/display/intel_lspcon.c+2−2
@@ -24,7 +24,7 @@ · 23 unmodified lines
24 */24 */
25 25
26#include <drm/drm_atomic_helper.h>26#include <drm/drm_atomic_helper.h>
27#include <drm/drm_dp_dual_mode_helper.h>27#include <drm/dp/drm_dp_dual_mode_helper.h>
28#include <drm/drm_edid.h>28#include <drm/drm_edid.h>
29 29
30#include "intel_de.h"30#include "intel_de.h"
@@ -537,7 +537,7 @@ void lspcon_set_infoframes(struct intel_encoder *encoder, · 506 unmodified lines
537 frame.avi.colorspace = HDMI_COLORSPACE_RGB;537 frame.avi.colorspace = HDMI_COLORSPACE_RGB;
538 538
539 /* Set the Colorspace as per the HDMI spec */539 /* Set the Colorspace as per the HDMI spec */
540 drm_hdmi_avi_infoframe_colorspace(&frame.avi, conn_state);540 drm_hdmi_avi_infoframe_colorimetry(&frame.avi, conn_state);
541 541
542 /* nonsense combination */542 /* nonsense combination */
543 drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&543 drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&
drivers/gpu/drm/i915/i915_buddy.c+0−466
@@ -1,466 +0,0 @@
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2021 Intel Corporation
4 */
5
6#include <linux/kmemleak.h>
7#include <linux/sizes.h>
8
9#include "i915_buddy.h"
10
11#include "i915_gem.h"
12#include "i915_utils.h"
13
14static struct kmem_cache *slab_blocks;
15
16static struct i915_buddy_block *i915_block_alloc(struct i915_buddy_mm *mm,
17 struct i915_buddy_block *parent,
18 unsigned int order,
19 u64 offset)
20{
21 struct i915_buddy_block *block;
22
23 GEM_BUG_ON(order > I915_BUDDY_MAX_ORDER);
24
25 block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
26 if (!block)
27 return NULL;
28
29 block->header = offset;
30 block->header |= order;
31 block->parent = parent;
32
33 GEM_BUG_ON(block->header & I915_BUDDY_HEADER_UNUSED);
34 return block;
35}
36
37static void i915_block_free(struct i915_buddy_mm *mm,
38 struct i915_buddy_block *block)
39{
40 kmem_cache_free(slab_blocks, block);
41}
42
43static void mark_allocated(struct i915_buddy_block *block)
44{
45 block->header &= ~I915_BUDDY_HEADER_STATE;
46 block->header |= I915_BUDDY_ALLOCATED;
47
48 list_del(&block->link);
49}
50
51static void mark_free(struct i915_buddy_mm *mm,
52 struct i915_buddy_block *block)
53{
54 block->header &= ~I915_BUDDY_HEADER_STATE;
55 block->header |= I915_BUDDY_FREE;
56
57 list_add(&block->link,
58 &mm->free_list[i915_buddy_block_order(block)]);
59}
60
61static void mark_split(struct i915_buddy_block *block)
62{
63 block->header &= ~I915_BUDDY_HEADER_STATE;
64 block->header |= I915_BUDDY_SPLIT;
65
66 list_del(&block->link);
67}
68
69int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size)
70{
71 unsigned int i;
72 u64 offset;
73
74 if (size < chunk_size)
75 return -EINVAL;
76
77 if (chunk_size < PAGE_SIZE)
78 return -EINVAL;
79
80 if (!is_power_of_2(chunk_size))
81 return -EINVAL;
82
83 size = round_down(size, chunk_size);
84
85 mm->size = size;
86 mm->avail = size;
87 mm->chunk_size = chunk_size;
88 mm->max_order = ilog2(size) - ilog2(chunk_size);
89
90 GEM_BUG_ON(mm->max_order > I915_BUDDY_MAX_ORDER);
91
92 mm->free_list = kmalloc_array(mm->max_order + 1,
93 sizeof(struct list_head),
94 GFP_KERNEL);
95 if (!mm->free_list)
96 return -ENOMEM;
97
98 for (i = 0; i <= mm->max_order; ++i)
99 INIT_LIST_HEAD(&mm->free_list[i]);
100
101 mm->n_roots = hweight64(size);
102
103 mm->roots = kmalloc_array(mm->n_roots,
104 sizeof(struct i915_buddy_block *),
105 GFP_KERNEL);
106 if (!mm->roots)
107 goto out_free_list;
108
109 offset = 0;
110 i = 0;
111
112 /*
113 * Split into power-of-two blocks, in case we are given a size that is
114 * not itself a power-of-two.
115 */
116 do {
117 struct i915_buddy_block *root;
118 unsigned int order;
119 u64 root_size;
120
121 root_size = rounddown_pow_of_two(size);
122 order = ilog2(root_size) - ilog2(chunk_size);
123
124 root = i915_block_alloc(mm, NULL, order, offset);
125 if (!root)
126 goto out_free_roots;
127
128 mark_free(mm, root);
129
130 GEM_BUG_ON(i > mm->max_order);
131 GEM_BUG_ON(i915_buddy_block_size(mm, root) < chunk_size);
132
133 mm->roots[i] = root;
134
135 offset += root_size;
136 size -= root_size;
137 i++;
138 } while (size);
139
140 return 0;
141
142out_free_roots:
143 while (i--)
144 i915_block_free(mm, mm->roots[i]);
145 kfree(mm->roots);
146out_free_list:
147 kfree(mm->free_list);
148 return -ENOMEM;
149}
150
151void i915_buddy_fini(struct i915_buddy_mm *mm)
152{
153 int i;
154
155 for (i = 0; i < mm->n_roots; ++i) {
156 GEM_WARN_ON(!i915_buddy_block_is_free(mm->roots[i]));
157 i915_block_free(mm, mm->roots[i]);
158 }
159
160 GEM_WARN_ON(mm->avail != mm->size);
161
162 kfree(mm->roots);
163 kfree(mm->free_list);
164}
165
166static int split_block(struct i915_buddy_mm *mm,
167 struct i915_buddy_block *block)
168{
169 unsigned int block_order = i915_buddy_block_order(block) - 1;
170 u64 offset = i915_buddy_block_offset(block);
171
172 GEM_BUG_ON(!i915_buddy_block_is_free(block));
173 GEM_BUG_ON(!i915_buddy_block_order(block));
174
175 block->left = i915_block_alloc(mm, block, block_order, offset);
176 if (!block->left)
177 return -ENOMEM;
178
179 block->right = i915_block_alloc(mm, block, block_order,
180 offset + (mm->chunk_size << block_order));
181 if (!block->right) {
182 i915_block_free(mm, block->left);
183 return -ENOMEM;
184 }
185
186 mark_free(mm, block->left);
187 mark_free(mm, block->right);
188
189 mark_split(block);
190
191 return 0;
192}
193
194static struct i915_buddy_block *
195get_buddy(struct i915_buddy_block *block)
196{
197 struct i915_buddy_block *parent;
198
199 parent = block->parent;
200 if (!parent)
201 return NULL;
202
203 if (parent->left == block)
204 return parent->right;
205
206 return parent->left;
207}
208
209static void __i915_buddy_free(struct i915_buddy_mm *mm,
210 struct i915_buddy_block *block)
211{
212 struct i915_buddy_block *parent;
213
214 while ((parent = block->parent)) {
215 struct i915_buddy_block *buddy;
216
217 buddy = get_buddy(block);
218
219 if (!i915_buddy_block_is_free(buddy))
220 break;
221
222 list_del(&buddy->link);
223
224 i915_block_free(mm, block);
225 i915_block_free(mm, buddy);
226
227 block = parent;
228 }
229
230 mark_free(mm, block);
231}
232
233void i915_buddy_free(struct i915_buddy_mm *mm,
234 struct i915_buddy_block *block)
235{
236 GEM_BUG_ON(!i915_buddy_block_is_allocated(block));
237 mm->avail += i915_buddy_block_size(mm, block);
238 __i915_buddy_free(mm, block);
239}
240
241void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects)
242{
243 struct i915_buddy_block *block, *on;
244
245 list_for_each_entry_safe(block, on, objects, link) {
246 i915_buddy_free(mm, block);
247 cond_resched();
248 }
249 INIT_LIST_HEAD(objects);
250}
251
252/*
253 * Allocate power-of-two block. The order value here translates to:
254 *
255 * 0 = 2^0 * mm->chunk_size
256 * 1 = 2^1 * mm->chunk_size
257 * 2 = 2^2 * mm->chunk_size
258 * ...
259 */
260struct i915_buddy_block *
261i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order)
262{
263 struct i915_buddy_block *block = NULL;
264 unsigned int i;
265 int err;
266
267 for (i = order; i <= mm->max_order; ++i) {
268 block = list_first_entry_or_null(&mm->free_list[i],
269 struct i915_buddy_block,
270 link);
271 if (block)
272 break;
273 }
274
275 if (!block)
276 return ERR_PTR(-ENOSPC);
277
278 GEM_BUG_ON(!i915_buddy_block_is_free(block));
279
280 while (i != order) {
281 err = split_block(mm, block);
282 if (unlikely(err))
283 goto out_free;
284
285 /* Go low */
286 block = block->left;
287 i--;
288 }
289
290 mark_allocated(block);
291 mm->avail -= i915_buddy_block_size(mm, block);
292 kmemleak_update_trace(block);
293 return block;
294
295out_free:
296 if (i != order)
297 __i915_buddy_free(mm, block);
298 return ERR_PTR(err);
299}
300
301static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
302{
303 return s1 <= e2 && e1 >= s2;
304}
305
306static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
307{
308 return s1 <= s2 && e1 >= e2;
309}
310
311/*
312 * Allocate range. Note that it's safe to chain together multiple alloc_ranges
313 * with the same blocks list.
314 *
315 * Intended for pre-allocating portions of the address space, for example to
316 * reserve a block for the initial framebuffer or similar, hence the expectation
317 * here is that i915_buddy_alloc() is still the main vehicle for
318 * allocations, so if that's not the case then the drm_mm range allocator is
319 * probably a much better fit, and so you should probably go use that instead.
320 */
321int i915_buddy_alloc_range(struct i915_buddy_mm *mm,
322 struct list_head *blocks,
323 u64 start, u64 size)
324{
325 struct i915_buddy_block *block;
326 struct i915_buddy_block *buddy;
327 LIST_HEAD(allocated);
328 LIST_HEAD(dfs);
329 u64 end;
330 int err;
331 int i;
332
333 if (size < mm->chunk_size)
334 return -EINVAL;
335
336 if (!IS_ALIGNED(size | start, mm->chunk_size))
337 return -EINVAL;
338
339 if (range_overflows(start, size, mm->size))
340 return -EINVAL;
341
342 for (i = 0; i < mm->n_roots; ++i)
343 list_add_tail(&mm->roots[i]->tmp_link, &dfs);
344
345 end = start + size - 1;
346
347 do {
348 u64 block_start;
349 u64 block_end;
350
351 block = list_first_entry_or_null(&dfs,
352 struct i915_buddy_block,
353 tmp_link);
354 if (!block)
355 break;
356
357 list_del(&block->tmp_link);
358
359 block_start = i915_buddy_block_offset(block);
360 block_end = block_start + i915_buddy_block_size(mm, block) - 1;
361
362 if (!overlaps(start, end, block_start, block_end))
363 continue;
364
365 if (i915_buddy_block_is_allocated(block)) {
366 err = -ENOSPC;
367 goto err_free;
368 }
369
370 if (contains(start, end, block_start, block_end)) {
371 if (!i915_buddy_block_is_free(block)) {
372 err = -ENOSPC;
373 goto err_free;
374 }
375
376 mark_allocated(block);
377 mm->avail -= i915_buddy_block_size(mm, block);
378 list_add_tail(&block->link, &allocated);
379 continue;
380 }
381
382 if (!i915_buddy_block_is_split(block)) {
383 err = split_block(mm, block);
384 if (unlikely(err))
385 goto err_undo;
386 }
387
388 list_add(&block->right->tmp_link, &dfs);
389 list_add(&block->left->tmp_link, &dfs);
390 } while (1);
391
392 list_splice_tail(&allocated, blocks);
393 return 0;
394
395err_undo:
396 /*
397 * We really don't want to leave around a bunch of split blocks, since
398 * bigger is better, so make sure we merge everything back before we
399 * free the allocated blocks.
400 */
401 buddy = get_buddy(block);
402 if (buddy &&
403 (i915_buddy_block_is_free(block) &&
404 i915_buddy_block_is_free(buddy)))
405 __i915_buddy_free(mm, block);
406
407err_free:
408 i915_buddy_free_list(mm, &allocated);
409 return err;
410}
411
412void i915_buddy_block_print(struct i915_buddy_mm *mm,
413 struct i915_buddy_block *block,
414 struct drm_printer *p)
415{
416 u64 start = i915_buddy_block_offset(block);
417 u64 size = i915_buddy_block_size(mm, block);
418
419 drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size);
420}
421
422void i915_buddy_print(struct i915_buddy_mm *mm, struct drm_printer *p)
423{
424 int order;
425
426 drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB\n",
427 mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20);
428
429 for (order = mm->max_order; order >= 0; order--) {
430 struct i915_buddy_block *block;
431 u64 count = 0, free;
432
433 list_for_each_entry(block, &mm->free_list[order], link) {
434 GEM_BUG_ON(!i915_buddy_block_is_free(block));
435 count++;
436 }
437
438 drm_printf(p, "order-%d ", order);
439
440 free = count * (mm->chunk_size << order);
441 if (free < SZ_1M)
442 drm_printf(p, "free: %lluKiB", free >> 10);
443 else
444 drm_printf(p, "free: %lluMiB", free >> 20);
445
446 drm_printf(p, ", pages: %llu\n", count);
447 }
448}
449
450#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
451#include "selftests/i915_buddy.c"
452#endif
453
454void i915_buddy_module_exit(void)
455{
456 kmem_cache_destroy(slab_blocks);
457}
458
459int __init i915_buddy_module_init(void)
460{
461 slab_blocks = KMEM_CACHE(i915_buddy_block, 0);
462 if (!slab_blocks)
463 return -ENOMEM;
464
465 return 0;
466}
drivers/gpu/drm/i915/i915_buddy.h+0−143
@@ -1,143 +0,0 @@
1/* SPDX-License-Identifier: MIT */
2/*
3 * Copyright © 2021 Intel Corporation
4 */
5
6#ifndef __I915_BUDDY_H__
7#define __I915_BUDDY_H__
8
9#include <linux/bitops.h>
10#include <linux/list.h>
11#include <linux/slab.h>
12
13#include <drm/drm_print.h>
14
15struct i915_buddy_block {
16#define I915_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
17#define I915_BUDDY_HEADER_STATE GENMASK_ULL(11, 10)
18#define I915_BUDDY_ALLOCATED (1 << 10)
19#define I915_BUDDY_FREE (2 << 10)
20#define I915_BUDDY_SPLIT (3 << 10)
21/* Free to be used, if needed in the future */
22#define I915_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6)
23#define I915_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0)
24 u64 header;
25
26 struct i915_buddy_block *left;
27 struct i915_buddy_block *right;
28 struct i915_buddy_block *parent;
29
30 void *private; /* owned by creator */
31
32 /*
33 * While the block is allocated by the user through i915_buddy_alloc*,
34 * the user has ownership of the link, for example to maintain within
35 * a list, if so desired. As soon as the block is freed with
36 * i915_buddy_free* ownership is given back to the mm.
37 */
38 struct list_head link;
39 struct list_head tmp_link;
40};
41
42/* Order-zero must be at least PAGE_SIZE */
43#define I915_BUDDY_MAX_ORDER (63 - PAGE_SHIFT)
44
45/*
46 * Binary Buddy System.
47 *
48 * Locking should be handled by the user, a simple mutex around
49 * i915_buddy_alloc* and i915_buddy_free* should suffice.
50 */
51struct i915_buddy_mm {
52 /* Maintain a free list for each order. */
53 struct list_head *free_list;
54
55 /*
56 * Maintain explicit binary tree(s) to track the allocation of the
57 * address space. This gives us a simple way of finding a buddy block
58 * and performing the potentially recursive merge step when freeing a
59 * block. Nodes are either allocated or free, in which case they will
60 * also exist on the respective free list.
61 */
62 struct i915_buddy_block **roots;
63
64 /*
65 * Anything from here is public, and remains static for the lifetime of
66 * the mm. Everything above is considered do-not-touch.
67 */
68 unsigned int n_roots;
69 unsigned int max_order;
70
71 /* Must be at least PAGE_SIZE */
72 u64 chunk_size;
73 u64 size;
74 u64 avail;
75};
76
77static inline u64
78i915_buddy_block_offset(struct i915_buddy_block *block)
79{
80 return block->header & I915_BUDDY_HEADER_OFFSET;
81}
82
83static inline unsigned int
84i915_buddy_block_order(struct i915_buddy_block *block)
85{
86 return block->header & I915_BUDDY_HEADER_ORDER;
87}
88
89static inline unsigned int
90i915_buddy_block_state(struct i915_buddy_block *block)
91{
92 return block->header & I915_BUDDY_HEADER_STATE;
93}
94
95static inline bool
96i915_buddy_block_is_allocated(struct i915_buddy_block *block)
97{
98 return i915_buddy_block_state(block) == I915_BUDDY_ALLOCATED;
99}
100
101static inline bool
102i915_buddy_block_is_free(struct i915_buddy_block *block)
103{
104 return i915_buddy_block_state(block) == I915_BUDDY_FREE;
105}
106
107static inline bool
108i915_buddy_block_is_split(struct i915_buddy_block *block)
109{
110 return i915_buddy_block_state(block) == I915_BUDDY_SPLIT;
111}
112
113static inline u64
114i915_buddy_block_size(struct i915_buddy_mm *mm,
115 struct i915_buddy_block *block)
116{
117 return mm->chunk_size << i915_buddy_block_order(block);
118}
119
120int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size);
121
122void i915_buddy_fini(struct i915_buddy_mm *mm);
123
124struct i915_buddy_block *
125i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order);
126
127int i915_buddy_alloc_range(struct i915_buddy_mm *mm,
128 struct list_head *blocks,
129 u64 start, u64 size);
130
131void i915_buddy_free(struct i915_buddy_mm *mm, struct i915_buddy_block *block);
132
133void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects);
134
135void i915_buddy_print(struct i915_buddy_mm *mm, struct drm_printer *p);
136void i915_buddy_block_print(struct i915_buddy_mm *mm,
137 struct i915_buddy_block *block,
138 struct drm_printer *p);
139
140void i915_buddy_module_exit(void);
141int i915_buddy_module_init(void);
142
143#endif
drivers/gpu/drm/i915/i915_module.c+0−3
@@ -9,7 +9,6 @@ · 8 unmodified lines
9#include "gem/i915_gem_context.h"9#include "gem/i915_gem_context.h"
10#include "gem/i915_gem_object.h"10#include "gem/i915_gem_object.h"
11#include "i915_active.h"11#include "i915_active.h"
12#include "i915_buddy.h"
13#include "i915_params.h"12#include "i915_params.h"
14#include "i915_pci.h"13#include "i915_pci.h"
15#include "i915_perf.h"14#include "i915_perf.h"
@@ -50,8 +49,6 @@ static const struct { · 34 unmodified lines
50 { .init = i915_check_nomodeset },49 { .init = i915_check_nomodeset },
51 { .init = i915_active_module_init,50 { .init = i915_active_module_init,
52 .exit = i915_active_module_exit },51 .exit = i915_active_module_exit },
53 { .init = i915_buddy_module_init,
54 .exit = i915_buddy_module_exit },
55 { .init = i915_context_module_init,52 { .init = i915_context_module_init,
56 .exit = i915_context_module_exit },53 .exit = i915_context_module_exit },
57 { .init = i915_gem_context_module_init,54 { .init = i915_gem_context_module_init,
drivers/gpu/drm/i915/i915_scatterlist.c+5−6
@@ -5,10 +5,9 @@ · 4 unmodified lines
5 */5 */
6 6
7#include "i915_scatterlist.h"7#include "i915_scatterlist.h"
8
9#include "i915_buddy.h"
10#include "i915_ttm_buddy_manager.h"8#include "i915_ttm_buddy_manager.h"
11 9
10#include <drm/drm_buddy.h>
12#include <drm/drm_mm.h>11#include <drm/drm_mm.h>
13 12
14#include <linux/slab.h>13#include <linux/slab.h>
@@ -153,9 +152,9 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res, · 138 unmodified lines
153 struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);152 struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
154 const u64 size = res->num_pages << PAGE_SHIFT;153 const u64 size = res->num_pages << PAGE_SHIFT;
155 const u64 max_segment = rounddown(UINT_MAX, PAGE_SIZE);154 const u64 max_segment = rounddown(UINT_MAX, PAGE_SIZE);
156 struct i915_buddy_mm *mm = bman_res->mm;155 struct drm_buddy *mm = bman_res->mm;
157 struct list_head *blocks = &bman_res->blocks;156 struct list_head *blocks = &bman_res->blocks;
158 struct i915_buddy_block *block;157 struct drm_buddy_block *block;
159 struct i915_refct_sgt *rsgt;158 struct i915_refct_sgt *rsgt;
160 struct scatterlist *sg;159 struct scatterlist *sg;
161 struct sg_table *st;160 struct sg_table *st;
@@ -181,8 +180,8 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res, · 19 unmodified lines
181 list_for_each_entry(block, blocks, link) {180 list_for_each_entry(block, blocks, link) {
182 u64 block_size, offset;181 u64 block_size, offset;
183 182
184 block_size = min_t(u64, size, i915_buddy_block_size(mm, block));183 block_size = min_t(u64, size, drm_buddy_block_size(mm, block));
185 offset = i915_buddy_block_offset(block);184 offset = drm_buddy_block_offset(block);
186 185
187 while (block_size) {186 while (block_size) {
188 u64 len;187 u64 len;
drivers/gpu/drm/i915/i915_ttm_buddy_manager.c+20−17
@@ -8,14 +8,15 @@ · 7 unmodified lines
8#include <drm/ttm/ttm_bo_driver.h>8#include <drm/ttm/ttm_bo_driver.h>
9#include <drm/ttm/ttm_placement.h>9#include <drm/ttm/ttm_placement.h>
10 10
11#include <drm/drm_buddy.h>
12
11#include "i915_ttm_buddy_manager.h"13#include "i915_ttm_buddy_manager.h"
12 14
13#include "i915_buddy.h"
14#include "i915_gem.h"15#include "i915_gem.h"
15 16
16struct i915_ttm_buddy_manager {17struct i915_ttm_buddy_manager {
17 struct ttm_resource_manager manager;18 struct ttm_resource_manager manager;
18 struct i915_buddy_mm mm;19 struct drm_buddy mm;
19 struct list_head reserved;20 struct list_head reserved;
20 struct mutex lock;21 struct mutex lock;
21 u64 default_page_size;22 u64 default_page_size;
@@ -34,7 +35,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, · 12 unmodified lines
34{35{
35 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);36 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
36 struct i915_ttm_buddy_resource *bman_res;37 struct i915_ttm_buddy_resource *bman_res;
37 struct i915_buddy_mm *mm = &bman->mm;38 struct drm_buddy *mm = &bman->mm;
38 unsigned long n_pages;39 unsigned long n_pages;
39 unsigned int min_order;40 unsigned int min_order;
40 u64 min_page_size;41 u64 min_page_size;
@@ -73,7 +74,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, · 32 unmodified lines
73 n_pages = size >> ilog2(mm->chunk_size);74 n_pages = size >> ilog2(mm->chunk_size);
74 75
75 do {76 do {
76 struct i915_buddy_block *block;77 struct drm_buddy_block *block;
77 unsigned int order;78 unsigned int order;
78 79
79 order = fls(n_pages) - 1;80 order = fls(n_pages) - 1;
@@ -82,7 +83,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, · 2 unmodified lines
82 83
83 do {84 do {
84 mutex_lock(&bman->lock);85 mutex_lock(&bman->lock);
85 block = i915_buddy_alloc(mm, order);86 block = drm_buddy_alloc_blocks(mm, order);
86 mutex_unlock(&bman->lock);87 mutex_unlock(&bman->lock);
87 if (!IS_ERR(block))88 if (!IS_ERR(block))
88 break;89 break;
@@ -106,9 +107,10 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, · 17 unmodified lines
106 107
107err_free_blocks:108err_free_blocks:
108 mutex_lock(&bman->lock);109 mutex_lock(&bman->lock);
109 i915_buddy_free_list(mm, &bman_res->blocks);110 drm_buddy_free_list(mm, &bman_res->blocks);
110 mutex_unlock(&bman->lock);111 mutex_unlock(&bman->lock);
111err_free_res:112err_free_res:
113 ttm_resource_fini(man, &bman_res->base);
112 kfree(bman_res);114 kfree(bman_res);
113 return err;115 return err;
114}116}
@@ -120,9 +122,10 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man, · 5 unmodified lines
120 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);122 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
121 123
122 mutex_lock(&bman->lock);124 mutex_lock(&bman->lock);
123 i915_buddy_free_list(&bman->mm, &bman_res->blocks);125 drm_buddy_free_list(&bman->mm, &bman_res->blocks);
124 mutex_unlock(&bman->lock);126 mutex_unlock(&bman->lock);
125 127
128 ttm_resource_fini(man, res);
126 kfree(bman_res);129 kfree(bman_res);
127}130}
128 131
@@ -130,17 +133,17 @@ static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, · 1 unmodified line
130 struct drm_printer *printer)133 struct drm_printer *printer)
131{134{
132 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);135 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
133 struct i915_buddy_block *block;136 struct drm_buddy_block *block;
134 137
135 mutex_lock(&bman->lock);138 mutex_lock(&bman->lock);
136 drm_printf(printer, "default_page_size: %lluKiB\n",139 drm_printf(printer, "default_page_size: %lluKiB\n",
137 bman->default_page_size >> 10);140 bman->default_page_size >> 10);
138 141
139 i915_buddy_print(&bman->mm, printer);142 drm_buddy_print(&bman->mm, printer);
140 143
141 drm_printf(printer, "reserved:\n");144 drm_printf(printer, "reserved:\n");
142 list_for_each_entry(block, &bman->reserved, link)145 list_for_each_entry(block, &bman->reserved, link)
143 i915_buddy_block_print(&bman->mm, block, printer);146 drm_buddy_block_print(&bman->mm, block, printer);
144 mutex_unlock(&bman->lock);147 mutex_unlock(&bman->lock);
145}148}
146 149
@@ -190,7 +193,7 @@ int i915_ttm_buddy_man_init(struct ttm_device *bdev, · 43 unmodified lines
190 if (!bman)193 if (!bman)
191 return -ENOMEM;194 return -ENOMEM;
192 195
193 err = i915_buddy_init(&bman->mm, size, chunk_size);196 err = drm_buddy_init(&bman->mm, size, chunk_size);
194 if (err)197 if (err)
195 goto err_free_bman;198 goto err_free_bman;
196 199
@@ -202,7 +205,7 @@ int i915_ttm_buddy_man_init(struct ttm_device *bdev, · 5 unmodified lines
202 man = &bman->manager;205 man = &bman->manager;
203 man->use_tt = use_tt;206 man->use_tt = use_tt;
204 man->func = &i915_ttm_buddy_manager_func;207 man->func = &i915_ttm_buddy_manager_func;
205 ttm_resource_manager_init(man, bman->mm.size >> PAGE_SHIFT);208 ttm_resource_manager_init(man, bdev, bman->mm.size >> PAGE_SHIFT);
206 209
207 ttm_resource_manager_set_used(man, true);210 ttm_resource_manager_set_used(man, true);
208 ttm_set_driver_manager(bdev, type, man);211 ttm_set_driver_manager(bdev, type, man);
@@ -228,7 +231,7 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type) · 19 unmodified lines
228{231{
229 struct ttm_resource_manager *man = ttm_manager_type(bdev, type);232 struct ttm_resource_manager *man = ttm_manager_type(bdev, type);
230 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);233 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
231 struct i915_buddy_mm *mm = &bman->mm;234 struct drm_buddy *mm = &bman->mm;
232 int ret;235 int ret;
233 236
234 ttm_resource_manager_set_used(man, false);237 ttm_resource_manager_set_used(man, false);
@@ -240,8 +243,8 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type) · 5 unmodified lines
240 ttm_set_driver_manager(bdev, type, NULL);243 ttm_set_driver_manager(bdev, type, NULL);
241 244
242 mutex_lock(&bman->lock);245 mutex_lock(&bman->lock);
243 i915_buddy_free_list(mm, &bman->reserved);246 drm_buddy_free_list(mm, &bman->reserved);
244 i915_buddy_fini(mm);247 drm_buddy_fini(mm);
245 mutex_unlock(&bman->lock);248 mutex_unlock(&bman->lock);
246 249
247 ttm_resource_manager_cleanup(man);250 ttm_resource_manager_cleanup(man);
@@ -264,11 +267,11 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man, · 16 unmodified lines
264 u64 start, u64 size)267 u64 start, u64 size)
265{268{
266 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);269 struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
267 struct i915_buddy_mm *mm = &bman->mm;270 struct drm_buddy *mm = &bman->mm;
268 int ret;271 int ret;
269 272
270 mutex_lock(&bman->lock);273 mutex_lock(&bman->lock);
271 ret = i915_buddy_alloc_range(mm, &bman->reserved, start, size);274 ret = drm_buddy_alloc_range(mm, &bman->reserved, start, size);
272 mutex_unlock(&bman->lock);275 mutex_unlock(&bman->lock);
273 276
274 return ret;277 return ret;
drivers/gpu/drm/i915/i915_ttm_buddy_manager.h+2−2
@@ -13,7 +13,7 @@ · 12 unmodified lines
13 13
14struct ttm_device;14struct ttm_device;
15struct ttm_resource_manager;15struct ttm_resource_manager;
16struct i915_buddy_mm;16struct drm_buddy;
17 17
18/**18/**
19 * struct i915_ttm_buddy_resource19 * struct i915_ttm_buddy_resource
@@ -28,7 +28,7 @@ struct i915_buddy_mm; · 8 unmodified lines
28struct i915_ttm_buddy_resource {28struct i915_ttm_buddy_resource {
29 struct ttm_resource base;29 struct ttm_resource base;
30 struct list_head blocks;30 struct list_head blocks;
31 struct i915_buddy_mm *mm;31 struct drm_buddy *mm;
32};32};
33 33
34/**34/**
drivers/gpu/drm/i915/selftests/i915_buddy.c+0−787
@@ -1,787 +0,0 @@
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2019 Intel Corporation
4 */
5
6#include <linux/prime_numbers.h>
7
8#include "../i915_selftest.h"
9#include "i915_random.h"
10
11static void __igt_dump_block(struct i915_buddy_mm *mm,
12 struct i915_buddy_block *block,
13 bool buddy)
14{
15 pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
16 block->header,
17 i915_buddy_block_state(block),
18 i915_buddy_block_order(block),
19 i915_buddy_block_offset(block),
20 i915_buddy_block_size(mm, block),
21 yesno(!block->parent),
22 yesno(buddy));
23}
24
25static void igt_dump_block(struct i915_buddy_mm *mm,
26 struct i915_buddy_block *block)
27{
28 struct i915_buddy_block *buddy;
29
30 __igt_dump_block(mm, block, false);
31
32 buddy = get_buddy(block);
33 if (buddy)
34 __igt_dump_block(mm, buddy, true);
35}
36
37static int igt_check_block(struct i915_buddy_mm *mm,
38 struct i915_buddy_block *block)
39{
40 struct i915_buddy_block *buddy;
41 unsigned int block_state;
42 u64 block_size;
43 u64 offset;
44 int err = 0;
45
46 block_state = i915_buddy_block_state(block);
47
48 if (block_state != I915_BUDDY_ALLOCATED &&
49 block_state != I915_BUDDY_FREE &&
50 block_state != I915_BUDDY_SPLIT) {
51 pr_err("block state mismatch\n");
52 err = -EINVAL;
53 }
54
55 block_size = i915_buddy_block_size(mm, block);
56 offset = i915_buddy_block_offset(block);
57
58 if (block_size < mm->chunk_size) {
59 pr_err("block size smaller than min size\n");
60 err = -EINVAL;
61 }
62
63 if (!is_power_of_2(block_size)) {
64 pr_err("block size not power of two\n");
65 err = -EINVAL;
66 }
67
68 if (!IS_ALIGNED(block_size, mm->chunk_size)) {
69 pr_err("block size not aligned to min size\n");
70 err = -EINVAL;
71 }
72
73 if (!IS_ALIGNED(offset, mm->chunk_size)) {
74 pr_err("block offset not aligned to min size\n");
75 err = -EINVAL;
76 }
77
78 if (!IS_ALIGNED(offset, block_size)) {
79 pr_err("block offset not aligned to block size\n");
80 err = -EINVAL;
81 }
82
83 buddy = get_buddy(block);
84
85 if (!buddy && block->parent) {
86 pr_err("buddy has gone fishing\n");
87 err = -EINVAL;
88 }
89
90 if (buddy) {
91 if (i915_buddy_block_offset(buddy) != (offset ^ block_size)) {
92 pr_err("buddy has wrong offset\n");
93 err = -EINVAL;
94 }
95
96 if (i915_buddy_block_size(mm, buddy) != block_size) {
97 pr_err("buddy size mismatch\n");
98 err = -EINVAL;
99 }
100
101 if (i915_buddy_block_state(buddy) == block_state &&
102 block_state == I915_BUDDY_FREE) {
103 pr_err("block and its buddy are free\n");
104 err = -EINVAL;
105 }
106 }
107
108 return err;
109}
110
111static int igt_check_blocks(struct i915_buddy_mm *mm,
112 struct list_head *blocks,
113 u64 expected_size,
114 bool is_contiguous)
115{
116 struct i915_buddy_block *block;
117 struct i915_buddy_block *prev;
118 u64 total;
119 int err = 0;
120
121 block = NULL;
122 prev = NULL;
123 total = 0;
124
125 list_for_each_entry(block, blocks, link) {
126 err = igt_check_block(mm, block);
127
128 if (!i915_buddy_block_is_allocated(block)) {
129 pr_err("block not allocated\n"),
130 err = -EINVAL;
131 }
132
133 if (is_contiguous && prev) {
134 u64 prev_block_size;
135 u64 prev_offset;
136 u64 offset;
137
138 prev_offset = i915_buddy_block_offset(prev);
139 prev_block_size = i915_buddy_block_size(mm, prev);
140 offset = i915_buddy_block_offset(block);
141
142 if (offset != (prev_offset + prev_block_size)) {
143 pr_err("block offset mismatch\n");
144 err = -EINVAL;
145 }
146 }
147
148 if (err)
149 break;
150
151 total += i915_buddy_block_size(mm, block);
152 prev = block;
153 }
154
155 if (!err) {
156 if (total != expected_size) {
157 pr_err("size mismatch, expected=%llx, found=%llx\n",
158 expected_size, total);
159 err = -EINVAL;
160 }
161 return err;
162 }
163
164 if (prev) {
165 pr_err("prev block, dump:\n");
166 igt_dump_block(mm, prev);
167 }
168
169 pr_err("bad block, dump:\n");
170 igt_dump_block(mm, block);
171
172 return err;
173}
174
175static int igt_check_mm(struct i915_buddy_mm *mm)
176{
177 struct i915_buddy_block *root;
178 struct i915_buddy_block *prev;
179 unsigned int i;
180 u64 total;
181 int err = 0;
182
183 if (!mm->n_roots) {
184 pr_err("n_roots is zero\n");
185 return -EINVAL;
186 }
187
188 if (mm->n_roots != hweight64(mm->size)) {
189 pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
190 mm->n_roots, hweight64(mm->size));
191 return -EINVAL;
192 }
193
194 root = NULL;
195 prev = NULL;
196 total = 0;
197
198 for (i = 0; i < mm->n_roots; ++i) {
199 struct i915_buddy_block *block;
200 unsigned int order;
201
202 root = mm->roots[i];
203 if (!root) {
204 pr_err("root(%u) is NULL\n", i);
205 err = -EINVAL;
206 break;
207 }
208
209 err = igt_check_block(mm, root);
210
211 if (!i915_buddy_block_is_free(root)) {
212 pr_err("root not free\n");
213 err = -EINVAL;
214 }
215
216 order = i915_buddy_block_order(root);
217
218 if (!i) {
219 if (order != mm->max_order) {
220 pr_err("max order root missing\n");
221 err = -EINVAL;
222 }
223 }
224
225 if (prev) {
226 u64 prev_block_size;
227 u64 prev_offset;
228 u64 offset;
229
230 prev_offset = i915_buddy_block_offset(prev);
231 prev_block_size = i915_buddy_block_size(mm, prev);
232 offset = i915_buddy_block_offset(root);
233
234 if (offset != (prev_offset + prev_block_size)) {
235 pr_err("root offset mismatch\n");
236 err = -EINVAL;
237 }
238 }
239
240 block = list_first_entry_or_null(&mm->free_list[order],
241 struct i915_buddy_block,
242 link);
243 if (block != root) {
244 pr_err("root mismatch at order=%u\n", order);
245 err = -EINVAL;
246 }
247
248 if (err)
249 break;
250
251 prev = root;
252 total += i915_buddy_block_size(mm, root);
253 }
254
255 if (!err) {
256 if (total != mm->size) {
257 pr_err("expected mm size=%llx, found=%llx\n", mm->size,
258 total);
259 err = -EINVAL;
260 }
261 return err;
262 }
263
264 if (prev) {
265 pr_err("prev root(%u), dump:\n", i - 1);
266 igt_dump_block(mm, prev);
267 }
268
269 if (root) {
270 pr_err("bad root(%u), dump:\n", i);
271 igt_dump_block(mm, root);
272 }
273
274 return err;
275}
276
277static void igt_mm_config(u64 *size, u64 *chunk_size)
278{
279 I915_RND_STATE(prng);
280 u32 s, ms;
281
282 /* Nothing fancy, just try to get an interesting bit pattern */
283
284 prandom_seed_state(&prng, i915_selftest.random_seed);
285
286 /* Let size be a random number of pages up to 8 GB (2M pages) */
287 s = 1 + i915_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
288 /* Let the chunk size be a random power of 2 less than size */
289 ms = BIT(i915_prandom_u32_max_state(ilog2(s), &prng));
290 /* Round size down to the chunk size */
291 s &= -ms;
292
293 /* Convert from pages to bytes */
294 *chunk_size = (u64)ms << 12;
295 *size = (u64)s << 12;
296}
297
298static int igt_buddy_alloc_smoke(void *arg)
299{
300 struct i915_buddy_mm mm;
301 IGT_TIMEOUT(end_time);
302 I915_RND_STATE(prng);
303 u64 chunk_size;
304 u64 mm_size;
305 int *order;
306 int err, i;
307
308 igt_mm_config(&mm_size, &chunk_size);
309
310 pr_info("buddy_init with size=%llx, chunk_size=%llx\n", mm_size, chunk_size);
311
312 err = i915_buddy_init(&mm, mm_size, chunk_size);
313 if (err) {
314 pr_err("buddy_init failed(%d)\n", err);
315 return err;
316 }
317
318 order = i915_random_order(mm.max_order + 1, &prng);
319 if (!order)
320 goto out_fini;
321
322 for (i = 0; i <= mm.max_order; ++i) {
323 struct i915_buddy_block *block;
324 int max_order = order[i];
325 bool timeout = false;
326 LIST_HEAD(blocks);
327 int order;
328 u64 total;
329
330 err = igt_check_mm(&mm);
331 if (err) {
332 pr_err("pre-mm check failed, abort\n");
333 break;
334 }
335
336 pr_info("filling from max_order=%u\n", max_order);
337
338 order = max_order;
339 total = 0;
340
341 do {
342retry:
343 block = i915_buddy_alloc(&mm, order);
344 if (IS_ERR(block)) {
345 err = PTR_ERR(block);
346 if (err == -ENOMEM) {
347 pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
348 order);
349 } else {
350 if (order--) {
351 err = 0;
352 goto retry;
353 }
354
355 pr_err("buddy_alloc with order=%d failed(%d)\n",
356 order, err);
357 }
358
359 break;
360 }
361
362 list_add_tail(&block->link, &blocks);
363
364 if (i915_buddy_block_order(block) != order) {
365 pr_err("buddy_alloc order mismatch\n");
366 err = -EINVAL;
367 break;
368 }
369
370 total += i915_buddy_block_size(&mm, block);
371
372 if (__igt_timeout(end_time, NULL)) {
373 timeout = true;
374 break;
375 }
376 } while (total < mm.size);
377
378 if (!err)
379 err = igt_check_blocks(&mm, &blocks, total, false);
380
381 i915_buddy_free_list(&mm, &blocks);
382
383 if (!err) {
384 err = igt_check_mm(&mm);
385 if (err)
386 pr_err("post-mm check failed\n");
387 }
388
389 if (err || timeout)
390 break;
391
392 cond_resched();
393 }
394
395 if (err == -ENOMEM)
396 err = 0;
397
398 kfree(order);
399out_fini:
400 i915_buddy_fini(&mm);
401
402 return err;
403}
404
405static int igt_buddy_alloc_pessimistic(void *arg)
406{
407 const unsigned int max_order = 16;
408 struct i915_buddy_block *block, *bn;
409 struct i915_buddy_mm mm;
410 unsigned int order;
411 LIST_HEAD(blocks);
412 int err;
413
414 /*
415 * Create a pot-sized mm, then allocate one of each possible
416 * order within. This should leave the mm with exactly one
417 * page left.
418 */
419
420 err = i915_buddy_init(&mm, PAGE_SIZE << max_order, PAGE_SIZE);
421 if (err) {
422 pr_err("buddy_init failed(%d)\n", err);
423 return err;
424 }
425 GEM_BUG_ON(mm.max_order != max_order);
426
427 for (order = 0; order < max_order; order++) {
428 block = i915_buddy_alloc(&mm, order);
429 if (IS_ERR(block)) {
430 pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
431 order);
432 err = PTR_ERR(block);
433 goto err;
434 }
435
436 list_add_tail(&block->link, &blocks);
437 }
438
439 /* And now the last remaining block available */
440 block = i915_buddy_alloc(&mm, 0);
441 if (IS_ERR(block)) {
442 pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
443 err = PTR_ERR(block);
444 goto err;
445 }
446 list_add_tail(&block->link, &blocks);
447
448 /* Should be completely full! */
449 for (order = max_order; order--; ) {
450 block = i915_buddy_alloc(&mm, order);
451 if (!IS_ERR(block)) {
452 pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
453 order);
454 list_add_tail(&block->link, &blocks);
455 err = -EINVAL;
456 goto err;
457 }
458 }
459
460 block = list_last_entry(&blocks, typeof(*block), link);
461 list_del(&block->link);
462 i915_buddy_free(&mm, block);
463
464 /* As we free in increasing size, we make available larger blocks */
465 order = 1;
466 list_for_each_entry_safe(block, bn, &blocks, link) {
467 list_del(&block->link);
468 i915_buddy_free(&mm, block);
469
470 block = i915_buddy_alloc(&mm, order);
471 if (IS_ERR(block)) {
472 pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
473 order);
474 err = PTR_ERR(block);
475 goto err;
476 }
477 i915_buddy_free(&mm, block);
478 order++;
479 }
480
481 /* To confirm, now the whole mm should be available */
482 block = i915_buddy_alloc(&mm, max_order);
483 if (IS_ERR(block)) {
484 pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
485 max_order);
486 err = PTR_ERR(block);
487 goto err;
488 }
489 i915_buddy_free(&mm, block);
490
491err:
492 i915_buddy_free_list(&mm, &blocks);
493 i915_buddy_fini(&mm);
494 return err;
495}
496
497static int igt_buddy_alloc_optimistic(void *arg)
498{
499 const int max_order = 16;
500 struct i915_buddy_block *block;
501 struct i915_buddy_mm mm;
502 LIST_HEAD(blocks);
503 int order;
504 int err;
505
506 /*
507 * Create a mm with one block of each order available, and
508 * try to allocate them all.
509 */
510
511 err = i915_buddy_init(&mm,
512 PAGE_SIZE * ((1 << (max_order + 1)) - 1),
513 PAGE_SIZE);
514 if (err) {
515 pr_err("buddy_init failed(%d)\n", err);
516 return err;
517 }
518 GEM_BUG_ON(mm.max_order != max_order);
519
520 for (order = 0; order <= max_order; order++) {
521 block = i915_buddy_alloc(&mm, order);
522 if (IS_ERR(block)) {
523 pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
524 order);
525 err = PTR_ERR(block);
526 goto err;
527 }
528
529 list_add_tail(&block->link, &blocks);
530 }
531
532 /* Should be completely full! */
533 block = i915_buddy_alloc(&mm, 0);
534 if (!IS_ERR(block)) {
535 pr_info("buddy_alloc unexpectedly succeeded, it should be full!");
536 list_add_tail(&block->link, &blocks);
537 err = -EINVAL;
538 goto err;
539 }
540
541err:
542 i915_buddy_free_list(&mm, &blocks);
543 i915_buddy_fini(&mm);
544 return err;
545}
546
547static int igt_buddy_alloc_pathological(void *arg)
548{
549 const int max_order = 16;
550 struct i915_buddy_block *block;
551 struct i915_buddy_mm mm;
552 LIST_HEAD(blocks);
553 LIST_HEAD(holes);
554 int order, top;
555 int err;
556
557 /*
558 * Create a pot-sized mm, then allocate one of each possible
559 * order within. This should leave the mm with exactly one
560 * page left. Free the largest block, then whittle down again.
561 * Eventually we will have a fully 50% fragmented mm.
562 */
563
564 err = i915_buddy_init(&mm, PAGE_SIZE << max_order, PAGE_SIZE);
565 if (err) {
566 pr_err("buddy_init failed(%d)\n", err);
567 return err;
568 }
569 GEM_BUG_ON(mm.max_order != max_order);
570
571 for (top = max_order; top; top--) {
572 /* Make room by freeing the largest allocated block */
573 block = list_first_entry_or_null(&blocks, typeof(*block), link);
574 if (block) {
575 list_del(&block->link);
576 i915_buddy_free(&mm, block);
577 }
578
579 for (order = top; order--; ) {
580 block = i915_buddy_alloc(&mm, order);
581 if (IS_ERR(block)) {
582 pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
583 order, top);
584 err = PTR_ERR(block);
585 goto err;
586 }
587 list_add_tail(&block->link, &blocks);
588 }
589
590 /* There should be one final page for this sub-allocation */
591 block = i915_buddy_alloc(&mm, 0);
592 if (IS_ERR(block)) {
593 pr_info("buddy_alloc hit -ENOMEM for hole\n");
594 err = PTR_ERR(block);
595 goto err;
596 }
597 list_add_tail(&block->link, &holes);
598
599 block = i915_buddy_alloc(&mm, top);
600 if (!IS_ERR(block)) {
601 pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
602 top, max_order);
603 list_add_tail(&block->link, &blocks);
604 err = -EINVAL;
605 goto err;
606 }
607 }
608
609 i915_buddy_free_list(&mm, &holes);
610
611 /* Nothing larger than blocks of chunk_size now available */
612 for (order = 1; order <= max_order; order++) {
613 block = i915_buddy_alloc(&mm, order);
614 if (!IS_ERR(block)) {
615 pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
616 order);
617 list_add_tail(&block->link, &blocks);
618 err = -EINVAL;
619 goto err;
620 }
621 }
622
623err:
624 list_splice_tail(&holes, &blocks);
625 i915_buddy_free_list(&mm, &blocks);
626 i915_buddy_fini(&mm);
627 return err;
628}
629
630static int igt_buddy_alloc_range(void *arg)
631{
632 struct i915_buddy_mm mm;
633 unsigned long page_num;
634 LIST_HEAD(blocks);
635 u64 chunk_size;
636 u64 offset;
637 u64 size;
638 u64 rem;
639 int err;
640
641 igt_mm_config(&size, &chunk_size);
642
643 pr_info("buddy_init with size=%llx, chunk_size=%llx\n", size, chunk_size);
644
645 err = i915_buddy_init(&mm, size, chunk_size);
646 if (err) {
647 pr_err("buddy_init failed(%d)\n", err);
648 return err;
649 }
650
651 err = igt_check_mm(&mm);
652 if (err) {
653 pr_err("pre-mm check failed, abort, abort, abort!\n");
654 goto err_fini;
655 }
656
657 rem = mm.size;
658 offset = 0;
659
660 for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
661 struct i915_buddy_block *block;
662 LIST_HEAD(tmp);
663
664 size = min(page_num * mm.chunk_size, rem);
665
666 err = i915_buddy_alloc_range(&mm, &tmp, offset, size);
667 if (err) {
668 if (err == -ENOMEM) {
669 pr_info("alloc_range hit -ENOMEM with size=%llx\n",
670 size);
671 } else {
672 pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
673 offset, size, err);
674 }
675
676 break;
677 }
678
679 block = list_first_entry_or_null(&tmp,
680 struct i915_buddy_block,
681 link);
682 if (!block) {
683 pr_err("alloc_range has no blocks\n");
684 err = -EINVAL;
685 break;
686 }
687
688 if (i915_buddy_block_offset(block) != offset) {
689 pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
690 i915_buddy_block_offset(block), offset);
691 err = -EINVAL;
692 }
693
694 if (!err)
695 err = igt_check_blocks(&mm, &tmp, size, true);
696
697 list_splice_tail(&tmp, &blocks);
698
699 if (err)
700 break;
701
702 offset += size;
703
704 rem -= size;
705 if (!rem)
706 break;
707
708 cond_resched();
709 }
710
711 if (err == -ENOMEM)
712 err = 0;
713
714 i915_buddy_free_list(&mm, &blocks);
715
716 if (!err) {
717 err = igt_check_mm(&mm);
718 if (err)
719 pr_err("post-mm check failed\n");
720 }
721
722err_fini:
723 i915_buddy_fini(&mm);
724
725 return err;
726}
727
728static int igt_buddy_alloc_limit(void *arg)
729{
730 struct i915_buddy_block *block;
731 struct i915_buddy_mm mm;
732 const u64 size = U64_MAX;
733 int err;
734
735 err = i915_buddy_init(&mm, size, PAGE_SIZE);
736 if (err)
737 return err;
738
739 if (mm.max_order != I915_BUDDY_MAX_ORDER) {
740 pr_err("mm.max_order(%d) != %d\n",
741 mm.max_order, I915_BUDDY_MAX_ORDER);
742 err = -EINVAL;
743 goto out_fini;
744 }
745
746 block = i915_buddy_alloc(&mm, mm.max_order);
747 if (IS_ERR(block)) {
748 err = PTR_ERR(block);
749 goto out_fini;
750 }
751
752 if (i915_buddy_block_order(block) != mm.max_order) {
753 pr_err("block order(%d) != %d\n",
754 i915_buddy_block_order(block), mm.max_order);
755 err = -EINVAL;
756 goto out_free;
757 }
758
759 if (i915_buddy_block_size(&mm, block) !=
760 BIT_ULL(mm.max_order) * PAGE_SIZE) {
761 pr_err("block size(%llu) != %llu\n",
762 i915_buddy_block_size(&mm, block),
763 BIT_ULL(mm.max_order) * PAGE_SIZE);
764 err = -EINVAL;
765 goto out_free;
766 }
767
768out_free:
769 i915_buddy_free(&mm, block);
770out_fini:
771 i915_buddy_fini(&mm);
772 return err;
773}
774
775int i915_buddy_mock_selftests(void)
776{
777 static const struct i915_subtest tests[] = {
778 SUBTEST(igt_buddy_alloc_pessimistic),
779 SUBTEST(igt_buddy_alloc_optimistic),
780 SUBTEST(igt_buddy_alloc_pathological),
781 SUBTEST(igt_buddy_alloc_smoke),
782 SUBTEST(igt_buddy_alloc_range),
783 SUBTEST(igt_buddy_alloc_limit),
784 };
785
786 return i915_subtests(tests, NULL);
787}
drivers/gpu/drm/i915/selftests/i915_mock_selftests.h+0−1
@@ -33,4 +33,3 @@ selftest(evict, i915_gem_evict_mock_selftests) · 32 unmodified lines
33selftest(gtt, i915_gem_gtt_mock_selftests)33selftest(gtt, i915_gem_gtt_mock_selftests)
34selftest(hugepages, i915_gem_huge_page_mock_selftests)34selftest(hugepages, i915_gem_huge_page_mock_selftests)
35selftest(memory_region, intel_memory_region_mock_selftests)35selftest(memory_region, intel_memory_region_mock_selftests)
36selftest(buddy, i915_buddy_mock_selftests)
drivers/gpu/drm/i915/selftests/intel_memory_region.c+7−6
@@ -6,6 +6,8 @@ · 5 unmodified lines
6#include <linux/prime_numbers.h>6#include <linux/prime_numbers.h>
7#include <linux/sort.h>7#include <linux/sort.h>
8 8
9#include <drm/drm_buddy.h>
10
9#include "../i915_selftest.h"11#include "../i915_selftest.h"
10 12
11#include "mock_drm.h"13#include "mock_drm.h"
@@ -20,7 +22,6 @@ · 8 unmodified lines
20#include "gt/intel_engine_pm.h"22#include "gt/intel_engine_pm.h"
21#include "gt/intel_engine_user.h"23#include "gt/intel_engine_user.h"
22#include "gt/intel_gt.h"24#include "gt/intel_gt.h"
23#include "i915_buddy.h"
24#include "gt/intel_migrate.h"25#include "gt/intel_migrate.h"
25#include "i915_memcpy.h"26#include "i915_memcpy.h"
26#include "i915_ttm_buddy_manager.h"27#include "i915_ttm_buddy_manager.h"
@@ -369,7 +370,7 @@ static int igt_mock_splintered_region(void *arg) · 342 unmodified lines
369 struct drm_i915_private *i915 = mem->i915;370 struct drm_i915_private *i915 = mem->i915;
370 struct i915_ttm_buddy_resource *res;371 struct i915_ttm_buddy_resource *res;
371 struct drm_i915_gem_object *obj;372 struct drm_i915_gem_object *obj;
372 struct i915_buddy_mm *mm;373 struct drm_buddy *mm;
373 unsigned int expected_order;374 unsigned int expected_order;
374 LIST_HEAD(objects);375 LIST_HEAD(objects);
375 u64 size;376 u64 size;
@@ -454,8 +455,8 @@ static int igt_mock_max_segment(void *arg) · 78 unmodified lines
454 struct drm_i915_private *i915 = mem->i915;455 struct drm_i915_private *i915 = mem->i915;
455 struct i915_ttm_buddy_resource *res;456 struct i915_ttm_buddy_resource *res;
456 struct drm_i915_gem_object *obj;457 struct drm_i915_gem_object *obj;
457 struct i915_buddy_block *block;458 struct drm_buddy_block *block;
458 struct i915_buddy_mm *mm;459 struct drm_buddy *mm;
459 struct list_head *blocks;460 struct list_head *blocks;
460 struct scatterlist *sg;461 struct scatterlist *sg;
461 LIST_HEAD(objects);462 LIST_HEAD(objects);
@@ -485,8 +486,8 @@ static int igt_mock_max_segment(void *arg) · 23 unmodified lines
485 mm = res->mm;486 mm = res->mm;
486 size = 0;487 size = 0;
487 list_for_each_entry(block, blocks, link) {488 list_for_each_entry(block, blocks, link) {
488 if (i915_buddy_block_size(mm, block) > size)489 if (drm_buddy_block_size(mm, block) > size)
489 size = i915_buddy_block_size(mm, block);490 size = drm_buddy_block_size(mm, block);
490 }491 }
491 if (size < max_segment) {492 if (size < max_segment) {
492 pr_err("%s: Failed to create a huge contiguous block [> %u], largest block %lld\n",493 pr_err("%s: Failed to create a huge contiguous block [> %u], largest block %lld\n",
drivers/gpu/drm/imx/dcss/dcss-drv.c+2−1
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#include <linux/module.h>6#include <linux/module.h>
7#include <linux/kernel.h>7#include <linux/kernel.h>
8#include <linux/platform_device.h>8#include <linux/platform_device.h>
9#include <drm/drm_module.h>
9#include <drm/drm_of.h>10#include <drm/drm_of.h>
10 11
11#include "dcss-dev.h"12#include "dcss-dev.h"
@@ -131,7 +132,7 @@ static struct platform_driver dcss_platform_driver = { · 119 unmodified lines
131 },132 },
132};133};
133 134
134module_platform_driver(dcss_platform_driver);135drm_module_platform_driver(dcss_platform_driver);
135 136
136MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@nxp.com>");137MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@nxp.com>");
137MODULE_DESCRIPTION("DCSS driver for i.MX8MQ");138MODULE_DESCRIPTION("DCSS driver for i.MX8MQ");
drivers/gpu/drm/ingenic/ingenic-drm-drv.c+59−3
@@ -6,6 +6,7 @@ · 5 unmodified lines
6 6
7#include "ingenic-drm.h"7#include "ingenic-drm.h"
8 8
9#include <linux/bitfield.h>
9#include <linux/component.h>10#include <linux/component.h>
10#include <linux/clk.h>11#include <linux/clk.h>
11#include <linux/dma-mapping.h>12#include <linux/dma-mapping.h>
@@ -49,6 +50,11 @@ struct ingenic_dma_hwdesc { · 37 unmodified lines
49 u32 addr;50 u32 addr;
50 u32 id;51 u32 id;
51 u32 cmd;52 u32 cmd;
53 /* extended hw descriptor for jz4780 */
54 u32 offsize;
55 u32 pagewidth;
56 u32 cpos;
57 u32 dessize;
52} __aligned(16);58} __aligned(16);
53 59
54struct ingenic_dma_hwdescs {60struct ingenic_dma_hwdescs {
@@ -60,6 +66,7 @@ struct jz_soc_info { · 5 unmodified lines
60 bool needs_dev_clk;66 bool needs_dev_clk;
61 bool has_osd;67 bool has_osd;
62 bool map_noncoherent;68 bool map_noncoherent;
69 bool use_extended_hwdesc;
63 unsigned int max_width, max_height;70 unsigned int max_width, max_height;
64 const u32 *formats_f0, *formats_f1;71 const u32 *formats_f0, *formats_f1;
65 unsigned int num_formats_f0, num_formats_f1;72 unsigned int num_formats_f0, num_formats_f1;
@@ -173,7 +180,6 @@ static const struct regmap_config ingenic_drm_regmap_config = { · 107 unmodified lines
173 .val_bits = 32,180 .val_bits = 32,
174 .reg_stride = 4,181 .reg_stride = 4,
175 182
176 .max_register = JZ_REG_LCD_SIZE1,
177 .writeable_reg = ingenic_drm_writeable_reg,183 .writeable_reg = ingenic_drm_writeable_reg,
178};184};
179 185
@@ -447,6 +453,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, · 267 unmodified lines
447 if (!crtc)453 if (!crtc)
448 return 0;454 return 0;
449 455
456 if (plane == &priv->f0)
457 return -EINVAL;
458
450 crtc_state = drm_atomic_get_existing_crtc_state(state,459 crtc_state = drm_atomic_get_existing_crtc_state(state,
451 crtc);460 crtc);
452 if (WARN_ON(!crtc_state))461 if (WARN_ON(!crtc_state))
@@ -663,6 +672,33 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, · 210 unmodified lines
663 hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4);672 hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4);
664 hwdesc->next = dma_hwdesc_addr(priv, next_id);673 hwdesc->next = dma_hwdesc_addr(priv, next_id);
665 674
675 if (priv->soc_info->use_extended_hwdesc) {
676 hwdesc->cmd |= JZ_LCD_CMD_FRM_ENABLE;
677
678 /* Extended 8-byte descriptor */
679 hwdesc->cpos = 0;
680 hwdesc->offsize = 0;
681 hwdesc->pagewidth = 0;
682
683 switch (newstate->fb->format->format) {
684 case DRM_FORMAT_XRGB1555:
685 hwdesc->cpos |= JZ_LCD_CPOS_RGB555;
686 fallthrough;
687 case DRM_FORMAT_RGB565:
688 hwdesc->cpos |= JZ_LCD_CPOS_BPP_15_16;
689 break;
690 case DRM_FORMAT_XRGB8888:
691 hwdesc->cpos |= JZ_LCD_CPOS_BPP_18_24;
692 break;
693 }
694 hwdesc->cpos |= (JZ_LCD_CPOS_COEFFICIENT_1 <<
695 JZ_LCD_CPOS_COEFFICIENT_OFFSET);
696 hwdesc->dessize =
697 (0xff << JZ_LCD_DESSIZE_ALPHA_OFFSET) |
698 FIELD_PREP(JZ_LCD_DESSIZE_HEIGHT_MASK, height - 1) |
699 FIELD_PREP(JZ_LCD_DESSIZE_WIDTH_MASK, width - 1);
700 }
701
666 if (drm_atomic_crtc_needs_modeset(crtc_state)) {702 if (drm_atomic_crtc_needs_modeset(crtc_state)) {
667 fourcc = newstate->fb->format->format;703 fourcc = newstate->fb->format->format;
668 704
@@ -694,6 +730,9 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, · 25 unmodified lines
694 | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE;730 | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE;
695 }731 }
696 732
733 if (priv->soc_info->use_extended_hwdesc)
734 cfg |= JZ_LCD_CFG_DESCRIPTOR_8;
735
697 if (mode->flags & DRM_MODE_FLAG_NHSYNC)736 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
698 cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;737 cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
699 if (mode->flags & DRM_MODE_FLAG_NVSYNC)738 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
@@ -1011,6 +1050,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) · 311 unmodified lines
1011 struct ingenic_drm_bridge *ib;1050 struct ingenic_drm_bridge *ib;
1012 struct drm_device *drm;1051 struct drm_device *drm;
1013 void __iomem *base;1052 void __iomem *base;
1053 struct resource *res;
1054 struct regmap_config regmap_config;
1014 long parent_rate;1055 long parent_rate;
1015 unsigned int i, clone_mask = 0;1056 unsigned int i, clone_mask = 0;
1016 int ret, irq;1057 int ret, irq;
@@ -1056,14 +1097,16 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) · 39 unmodified lines
1056 drm->mode_config.funcs = &ingenic_drm_mode_config_funcs;1097 drm->mode_config.funcs = &ingenic_drm_mode_config_funcs;
1057 drm->mode_config.helper_private = &ingenic_drm_mode_config_helpers;1098 drm->mode_config.helper_private = &ingenic_drm_mode_config_helpers;
1058 1099
1059 base = devm_platform_ioremap_resource(pdev, 0);1100 base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
1060 if (IS_ERR(base)) {1101 if (IS_ERR(base)) {
1061 dev_err(dev, "Failed to get memory resource\n");1102 dev_err(dev, "Failed to get memory resource\n");
1062 return PTR_ERR(base);1103 return PTR_ERR(base);
1063 }1104 }
1064 1105
1106 regmap_config = ingenic_drm_regmap_config;
1107 regmap_config.max_register = res->end - res->start;
1065 priv->map = devm_regmap_init_mmio(dev, base,1108 priv->map = devm_regmap_init_mmio(dev, base,
1066 &ingenic_drm_regmap_config);1109 &regmap_config);
1067 if (IS_ERR(priv->map)) {1110 if (IS_ERR(priv->map)) {
1068 dev_err(dev, "Failed to create regmap\n");1111 dev_err(dev, "Failed to create regmap\n");
1069 return PTR_ERR(priv->map);1112 return PTR_ERR(priv->map);
@@ -1465,10 +1508,23 @@ static const struct jz_soc_info jz4770_soc_info = { · 395 unmodified lines
1465 .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),1508 .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
1466};1509};
1467 1510
1511static const struct jz_soc_info jz4780_soc_info = {
1512 .needs_dev_clk = true,
1513 .has_osd = true,
1514 .use_extended_hwdesc = true,
1515 .max_width = 4096,
1516 .max_height = 2048,
1517 .formats_f1 = jz4770_formats_f1,
1518 .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1),
1519 .formats_f0 = jz4770_formats_f0,
1520 .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
1521};
1522
1468static const struct of_device_id ingenic_drm_of_match[] = {1523static const struct of_device_id ingenic_drm_of_match[] = {
1469 { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info },1524 { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info },
1470 { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info },1525 { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info },
1471 { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info },1526 { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info },
1527 { .compatible = "ingenic,jz4780-lcd", .data = &jz4780_soc_info },
1472 { /* sentinel */ },1528 { /* sentinel */ },
1473};1529};
1474MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);1530MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
drivers/gpu/drm/ingenic/ingenic-drm.h+38−0
@@ -44,8 +44,11 @@ · 43 unmodified lines
44#define JZ_REG_LCD_XYP1 0x12444#define JZ_REG_LCD_XYP1 0x124
45#define JZ_REG_LCD_SIZE0 0x12845#define JZ_REG_LCD_SIZE0 0x128
46#define JZ_REG_LCD_SIZE1 0x12c46#define JZ_REG_LCD_SIZE1 0x12c
47#define JZ_REG_LCD_PCFG 0x2c0
47 48
48#define JZ_LCD_CFG_SLCD BIT(31)49#define JZ_LCD_CFG_SLCD BIT(31)
50#define JZ_LCD_CFG_DESCRIPTOR_8 BIT(28)
51#define JZ_LCD_CFG_RECOVER_FIFO_UNDERRUN BIT(25)
49#define JZ_LCD_CFG_PS_DISABLE BIT(23)52#define JZ_LCD_CFG_PS_DISABLE BIT(23)
50#define JZ_LCD_CFG_CLS_DISABLE BIT(22)53#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
51#define JZ_LCD_CFG_SPL_DISABLE BIT(21)54#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
@@ -63,6 +66,7 @@ · 11 unmodified lines
63#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)66#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
64#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)67#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
65#define JZ_LCD_CFG_18_BIT BIT(7)68#define JZ_LCD_CFG_18_BIT BIT(7)
69#define JZ_LCD_CFG_24_BIT BIT(6)
66#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))70#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
67 71
68#define JZ_LCD_CFG_MODE_GENERIC_16BIT 072#define JZ_LCD_CFG_MODE_GENERIC_16BIT 0
@@ -132,6 +136,7 @@ · 63 unmodified lines
132#define JZ_LCD_CMD_SOF_IRQ BIT(31)136#define JZ_LCD_CMD_SOF_IRQ BIT(31)
133#define JZ_LCD_CMD_EOF_IRQ BIT(30)137#define JZ_LCD_CMD_EOF_IRQ BIT(30)
134#define JZ_LCD_CMD_ENABLE_PAL BIT(28)138#define JZ_LCD_CMD_ENABLE_PAL BIT(28)
139#define JZ_LCD_CMD_FRM_ENABLE BIT(26)
135 140
136#define JZ_LCD_SYNC_MASK 0x3ff141#define JZ_LCD_SYNC_MASK 0x3ff
137 142
@@ -153,6 +158,7 @@ · 15 unmodified lines
153#define JZ_LCD_RGBC_EVEN_BGR (0x5 << 0)158#define JZ_LCD_RGBC_EVEN_BGR (0x5 << 0)
154 159
155#define JZ_LCD_OSDC_OSDEN BIT(0)160#define JZ_LCD_OSDC_OSDEN BIT(0)
161#define JZ_LCD_OSDC_ALPHAEN BIT(2)
156#define JZ_LCD_OSDC_F0EN BIT(3)162#define JZ_LCD_OSDC_F0EN BIT(3)
157#define JZ_LCD_OSDC_F1EN BIT(4)163#define JZ_LCD_OSDC_F1EN BIT(4)
158 164
@@ -176,6 +182,38 @@ · 17 unmodified lines
176#define JZ_LCD_SIZE01_WIDTH_LSB 0182#define JZ_LCD_SIZE01_WIDTH_LSB 0
177#define JZ_LCD_SIZE01_HEIGHT_LSB 16183#define JZ_LCD_SIZE01_HEIGHT_LSB 16
178 184
185#define JZ_LCD_DESSIZE_ALPHA_OFFSET 24
186#define JZ_LCD_DESSIZE_HEIGHT_MASK GENMASK(23, 12)
187#define JZ_LCD_DESSIZE_WIDTH_MASK GENMASK(11, 0)
188
189#define JZ_LCD_CPOS_BPP_15_16 (4 << 27)
190#define JZ_LCD_CPOS_BPP_18_24 (5 << 27)
191#define JZ_LCD_CPOS_BPP_30 (7 << 27)
192#define JZ_LCD_CPOS_RGB555 BIT(30)
193#define JZ_LCD_CPOS_PREMULTIPLY_LCD BIT(26)
194#define JZ_LCD_CPOS_COEFFICIENT_OFFSET 24
195#define JZ_LCD_CPOS_COEFFICIENT_0 0
196#define JZ_LCD_CPOS_COEFFICIENT_1 1
197#define JZ_LCD_CPOS_COEFFICIENT_ALPHA1 2
198#define JZ_LCD_CPOS_COEFFICIENT_1_ALPHA1 3
199
200#define JZ_LCD_RGBC_RGB_PADDING BIT(15)
201#define JZ_LCD_RGBC_RGB_PADDING_FIRST BIT(14)
202#define JZ_LCD_RGBC_422 BIT(8)
203#define JZ_LCD_RGBC_RGB_FORMAT_ENABLE BIT(7)
204
205#define JZ_LCD_PCFG_PRI_MODE BIT(31)
206#define JZ_LCD_PCFG_HP_BST_4 (0 << 28)
207#define JZ_LCD_PCFG_HP_BST_8 (1 << 28)
208#define JZ_LCD_PCFG_HP_BST_16 (2 << 28)
209#define JZ_LCD_PCFG_HP_BST_32 (3 << 28)
210#define JZ_LCD_PCFG_HP_BST_64 (4 << 28)
211#define JZ_LCD_PCFG_HP_BST_16_CONT (5 << 28)
212#define JZ_LCD_PCFG_HP_BST_DISABLE (7 << 28)
213#define JZ_LCD_PCFG_THRESHOLD2_OFFSET 18
214#define JZ_LCD_PCFG_THRESHOLD1_OFFSET 9
215#define JZ_LCD_PCFG_THRESHOLD0_OFFSET 0
216
179struct device;217struct device;
180struct drm_plane;218struct drm_plane;
181struct drm_plane_state;219struct drm_plane_state;
drivers/gpu/drm/meson/meson_drv.c+13−12
@@ -302,42 +302,42 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) · 301 unmodified lines
302 if (priv->afbcd.ops) {302 if (priv->afbcd.ops) {
303 ret = priv->afbcd.ops->init(priv);303 ret = priv->afbcd.ops->init(priv);
304 if (ret)304 if (ret)
305 return ret;305 goto free_drm;
306 }306 }
307 307
308 /* Encoder Initialization */308 /* Encoder Initialization */
309 309
310 ret = meson_encoder_cvbs_init(priv);310 ret = meson_encoder_cvbs_init(priv);
311 if (ret)311 if (ret)
312 goto free_drm;312 goto exit_afbcd;
313 313
314 if (has_components) {314 if (has_components) {
315 ret = component_bind_all(drm->dev, drm);315 ret = component_bind_all(drm->dev, drm);
316 if (ret) {316 if (ret) {
317 dev_err(drm->dev, "Couldn't bind all components\n");317 dev_err(drm->dev, "Couldn't bind all components\n");
318 goto free_drm;318 goto exit_afbcd;
319 }319 }
320 }320 }
321 321
322 ret = meson_encoder_hdmi_init(priv);322 ret = meson_encoder_hdmi_init(priv);
323 if (ret)323 if (ret)
324 goto free_drm;324 goto exit_afbcd;
325 325
326 ret = meson_plane_create(priv);326 ret = meson_plane_create(priv);
327 if (ret)327 if (ret)
328 goto free_drm;328 goto exit_afbcd;
329 329
330 ret = meson_overlay_create(priv);330 ret = meson_overlay_create(priv);
331 if (ret)331 if (ret)
332 goto free_drm;332 goto exit_afbcd;
333 333
334 ret = meson_crtc_create(priv);334 ret = meson_crtc_create(priv);
335 if (ret)335 if (ret)
336 goto free_drm;336 goto exit_afbcd;
337 337
338 ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);338 ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);
339 if (ret)339 if (ret)
340 goto free_drm;340 goto exit_afbcd;
341 341
342 drm_mode_config_reset(drm);342 drm_mode_config_reset(drm);
343 343
@@ -355,6 +355,9 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) · 11 unmodified lines
355 355
356uninstall_irq:356uninstall_irq:
357 free_irq(priv->vsync_irq, drm);357 free_irq(priv->vsync_irq, drm);
358exit_afbcd:
359 if (priv->afbcd.ops)
360 priv->afbcd.ops->exit(priv);
358free_drm:361free_drm:
359 drm_dev_put(drm);362 drm_dev_put(drm);
360 363
@@ -385,10 +388,8 @@ static void meson_drv_unbind(struct device *dev) · 24 unmodified lines
385 free_irq(priv->vsync_irq, drm);388 free_irq(priv->vsync_irq, drm);
386 drm_dev_put(drm);389 drm_dev_put(drm);
387 390
388 if (priv->afbcd.ops) {391 if (priv->afbcd.ops)
389 priv->afbcd.ops->reset(priv);392 priv->afbcd.ops->exit(priv);
390 meson_rdma_free(priv);
391 }
392}393}
393 394
394static const struct component_master_ops meson_drv_master_ops = {395static const struct component_master_ops meson_drv_master_ops = {
drivers/gpu/drm/meson/meson_osd_afbcd.c+27−14
@@ -79,11 +79,6 @@ static bool meson_gxm_afbcd_supported_fmt(u64 modifier, uint32_t format) · 78 unmodified lines
79 return meson_gxm_afbcd_pixel_fmt(modifier, format) >= 0;79 return meson_gxm_afbcd_pixel_fmt(modifier, format) >= 0;
80}80}
81 81
82static int meson_gxm_afbcd_init(struct meson_drm *priv)
83{
84 return 0;
85}
86
87static int meson_gxm_afbcd_reset(struct meson_drm *priv)82static int meson_gxm_afbcd_reset(struct meson_drm *priv)
88{83{
89 writel_relaxed(VIU_SW_RESET_OSD1_AFBCD,84 writel_relaxed(VIU_SW_RESET_OSD1_AFBCD,
@@ -93,6 +88,16 @@ static int meson_gxm_afbcd_reset(struct meson_drm *priv) · 3 unmodified lines
93 return 0;88 return 0;
94}89}
95 90
91static int meson_gxm_afbcd_init(struct meson_drm *priv)
92{
93 return 0;
94}
95
96static void meson_gxm_afbcd_exit(struct meson_drm *priv)
97{
98 meson_gxm_afbcd_reset(priv);
99}
100
96static int meson_gxm_afbcd_enable(struct meson_drm *priv)101static int meson_gxm_afbcd_enable(struct meson_drm *priv)
97{102{
98 writel_relaxed(FIELD_PREP(OSD1_AFBCD_ID_FIFO_THRD, 0x40) |103 writel_relaxed(FIELD_PREP(OSD1_AFBCD_ID_FIFO_THRD, 0x40) |
@@ -172,6 +177,7 @@ static int meson_gxm_afbcd_setup(struct meson_drm *priv) · 73 unmodified lines
172 177
173struct meson_afbcd_ops meson_afbcd_gxm_ops = {178struct meson_afbcd_ops meson_afbcd_gxm_ops = {
174 .init = meson_gxm_afbcd_init,179 .init = meson_gxm_afbcd_init,
180 .exit = meson_gxm_afbcd_exit,
175 .reset = meson_gxm_afbcd_reset,181 .reset = meson_gxm_afbcd_reset,
176 .enable = meson_gxm_afbcd_enable,182 .enable = meson_gxm_afbcd_enable,
177 .disable = meson_gxm_afbcd_disable,183 .disable = meson_gxm_afbcd_disable,
@@ -269,6 +275,18 @@ static bool meson_g12a_afbcd_supported_fmt(u64 modifier, uint32_t format) · 91 unmodified lines
269 return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0;275 return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0;
270}276}
271 277
278static int meson_g12a_afbcd_reset(struct meson_drm *priv)
279{
280 meson_rdma_reset(priv);
281
282 meson_rdma_writel_sync(priv, VIU_SW_RESET_G12A_AFBC_ARB |
283 VIU_SW_RESET_G12A_OSD1_AFBCD,
284 VIU_SW_RESET);
285 meson_rdma_writel_sync(priv, 0, VIU_SW_RESET);
286
287 return 0;
288}
289
272static int meson_g12a_afbcd_init(struct meson_drm *priv)290static int meson_g12a_afbcd_init(struct meson_drm *priv)
273{291{
274 int ret;292 int ret;
@@ -286,16 +304,10 @@ static int meson_g12a_afbcd_init(struct meson_drm *priv) · 11 unmodified lines
286 return 0;304 return 0;
287}305}
288 306
289static int meson_g12a_afbcd_reset(struct meson_drm *priv)307static void meson_g12a_afbcd_exit(struct meson_drm *priv)
290{308{
291 meson_rdma_reset(priv);309 meson_g12a_afbcd_reset(priv);
292 310 meson_rdma_free(priv);
293 meson_rdma_writel_sync(priv, VIU_SW_RESET_G12A_AFBC_ARB |
294 VIU_SW_RESET_G12A_OSD1_AFBCD,
295 VIU_SW_RESET);
296 meson_rdma_writel_sync(priv, 0, VIU_SW_RESET);
297
298 return 0;
299}311}
300 312
301static int meson_g12a_afbcd_enable(struct meson_drm *priv)313static int meson_g12a_afbcd_enable(struct meson_drm *priv)
@@ -380,6 +392,7 @@ static int meson_g12a_afbcd_setup(struct meson_drm *priv) · 78 unmodified lines
380 392
381struct meson_afbcd_ops meson_afbcd_g12a_ops = {393struct meson_afbcd_ops meson_afbcd_g12a_ops = {
382 .init = meson_g12a_afbcd_init,394 .init = meson_g12a_afbcd_init,
395 .exit = meson_g12a_afbcd_exit,
383 .reset = meson_g12a_afbcd_reset,396 .reset = meson_g12a_afbcd_reset,
384 .enable = meson_g12a_afbcd_enable,397 .enable = meson_g12a_afbcd_enable,
385 .disable = meson_g12a_afbcd_disable,398 .disable = meson_g12a_afbcd_disable,
drivers/gpu/drm/meson/meson_osd_afbcd.h+1−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
14 14
15struct meson_afbcd_ops {15struct meson_afbcd_ops {
16 int (*init)(struct meson_drm *priv);16 int (*init)(struct meson_drm *priv);
17 void (*exit)(struct meson_drm *priv);
17 int (*reset)(struct meson_drm *priv);18 int (*reset)(struct meson_drm *priv);
18 int (*enable)(struct meson_drm *priv);19 int (*enable)(struct meson_drm *priv);
19 int (*disable)(struct meson_drm *priv);20 int (*disable)(struct meson_drm *priv);
drivers/gpu/drm/mgag200/mgag200_mode.c+4−1
@@ -529,7 +529,10 @@ static void mgag200_set_format_regs(struct mga_device *mdev, · 528 unmodified lines
529 WREG_GFX(3, 0x00);529 WREG_GFX(3, 0x00);
530 WREG_GFX(4, 0x00);530 WREG_GFX(4, 0x00);
531 WREG_GFX(5, 0x40);531 WREG_GFX(5, 0x40);
532 WREG_GFX(6, 0x05);532 /* GCTL6 should be 0x05, but we configure memmapsl to 0xb8000 (text mode),
533 * so that it doesn't hang when running kexec/kdump on G200_SE rev42.
534 */
535 WREG_GFX(6, 0x0d);
533 WREG_GFX(7, 0x0f);536 WREG_GFX(7, 0x0f);
534 WREG_GFX(8, 0x0f);537 WREG_GFX(8, 0x0f);
535 538
drivers/gpu/drm/msm/Kconfig+1−0
@@ -12,6 +12,7 @@ config DRM_MSM · 11 unmodified lines
12 select IOMMU_IO_PGTABLE12 select IOMMU_IO_PGTABLE
13 select QCOM_MDT_LOADER if ARCH_QCOM13 select QCOM_MDT_LOADER if ARCH_QCOM
14 select REGULATOR14 select REGULATOR
15 select DRM_DP_HELPER
15 select DRM_KMS_HELPER16 select DRM_KMS_HELPER
16 select DRM_PANEL17 select DRM_PANEL
17 select DRM_BRIDGE18 select DRM_BRIDGE
drivers/gpu/drm/msm/dp/dp_audio.c+1−1
@@ -8,7 +8,7 @@ · 7 unmodified lines
8 8
9#include <linux/of_platform.h>9#include <linux/of_platform.h>
10 10
11#include <drm/drm_dp_helper.h>11#include <drm/dp/drm_dp_helper.h>
12#include <drm/drm_edid.h>12#include <drm/drm_edid.h>
13 13
14#include "dp_catalog.h"14#include "dp_catalog.h"
drivers/gpu/drm/msm/dp/dp_aux.h+1−1
@@ -7,7 +7,7 @@ · 6 unmodified lines
7#define _DP_AUX_H_7#define _DP_AUX_H_
8 8
9#include "dp_catalog.h"9#include "dp_catalog.h"
10#include <drm/drm_dp_helper.h>10#include <drm/dp/drm_dp_helper.h>
11 11
12int dp_aux_register(struct drm_dp_aux *dp_aux);12int dp_aux_register(struct drm_dp_aux *dp_aux);
13void dp_aux_unregister(struct drm_dp_aux *dp_aux);13void dp_aux_unregister(struct drm_dp_aux *dp_aux);
drivers/gpu/drm/msm/dp/dp_catalog.c+1−1
@@ -10,7 +10,7 @@ · 9 unmodified lines
10#include <linux/phy/phy.h>10#include <linux/phy/phy.h>
11#include <linux/phy/phy-dp.h>11#include <linux/phy/phy-dp.h>
12#include <linux/rational.h>12#include <linux/rational.h>
13#include <drm/drm_dp_helper.h>13#include <drm/dp/drm_dp_helper.h>
14#include <drm/drm_print.h>14#include <drm/drm_print.h>
15 15
16#include "dp_catalog.h"16#include "dp_catalog.h"
drivers/gpu/drm/msm/dp/dp_ctrl.c+1−1
@@ -12,7 +12,7 @@ · 11 unmodified lines
12#include <linux/phy/phy-dp.h>12#include <linux/phy/phy-dp.h>
13#include <linux/pm_opp.h>13#include <linux/pm_opp.h>
14#include <drm/drm_fixed.h>14#include <drm/drm_fixed.h>
15#include <drm/drm_dp_helper.h>15#include <drm/dp/drm_dp_helper.h>
16#include <drm/drm_print.h>16#include <drm/drm_print.h>
17 17
18#include "dp_reg.h"18#include "dp_reg.h"
drivers/gpu/drm/msm/edp/edp.h+77−0
@@ -0,0 +1,77 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
4 */
5
6#ifndef __EDP_CONNECTOR_H__
7#define __EDP_CONNECTOR_H__
8
9#include <linux/i2c.h>
10#include <linux/interrupt.h>
11#include <linux/kernel.h>
12#include <linux/platform_device.h>
13#include <drm/dp/drm_dp_helper.h>
14#include <drm/drm_bridge.h>
15#include <drm/drm_crtc.h>
16
17#include "msm_drv.h"
18
19#define edp_read(offset) msm_readl((offset))
20#define edp_write(offset, data) msm_writel((data), (offset))
21
22struct edp_ctrl;
23struct edp_aux;
24struct edp_phy;
25
26struct msm_edp {
27 struct drm_device *dev;
28 struct platform_device *pdev;
29
30 struct drm_connector *connector;
31 struct drm_bridge *bridge;
32
33 /* the encoder we are hooked to (outside of eDP block) */
34 struct drm_encoder *encoder;
35
36 struct edp_ctrl *ctrl;
37
38 int irq;
39};
40
41/* eDP bridge */
42struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp);
43void edp_bridge_destroy(struct drm_bridge *bridge);
44
45/* eDP connector */
46struct drm_connector *msm_edp_connector_init(struct msm_edp *edp);
47
48/* AUX */
49void *msm_edp_aux_init(struct msm_edp *edp, void __iomem *regbase, struct drm_dp_aux **drm_aux);
50void msm_edp_aux_destroy(struct device *dev, struct edp_aux *aux);
51irqreturn_t msm_edp_aux_irq(struct edp_aux *aux, u32 isr);
52void msm_edp_aux_ctrl(struct edp_aux *aux, int enable);
53
54/* Phy */
55bool msm_edp_phy_ready(struct edp_phy *phy);
56void msm_edp_phy_ctrl(struct edp_phy *phy, int enable);
57void msm_edp_phy_vm_pe_init(struct edp_phy *phy);
58void msm_edp_phy_vm_pe_cfg(struct edp_phy *phy, u32 v0, u32 v1);
59void msm_edp_phy_lane_power_ctrl(struct edp_phy *phy, bool up, u32 max_lane);
60void *msm_edp_phy_init(struct device *dev, void __iomem *regbase);
61
62/* Ctrl */
63irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl);
64void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on);
65int msm_edp_ctrl_init(struct msm_edp *edp);
66void msm_edp_ctrl_destroy(struct edp_ctrl *ctrl);
67bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl);
68int msm_edp_ctrl_get_panel_info(struct edp_ctrl *ctrl,
69 struct drm_connector *connector, struct edid **edid);
70int msm_edp_ctrl_timing_cfg(struct edp_ctrl *ctrl,
71 const struct drm_display_mode *mode,
72 const struct drm_display_info *info);
73/* @pixel_rate is in kHz */
74bool msm_edp_ctrl_pixel_clock_valid(struct edp_ctrl *ctrl,
75 u32 pixel_rate, u32 *pm, u32 *pn);
76
77#endif /* __EDP_CONNECTOR_H__ */
drivers/gpu/drm/msm/edp/edp_ctrl.c+1373−0
@@ -0,0 +1,1373 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/clk.h>
7#include <linux/gpio/consumer.h>
8#include <linux/regulator/consumer.h>
9#include <drm/dp/drm_dp_helper.h>
10#include <drm/drm_crtc.h>
11#include <drm/drm_edid.h>
12
13#include "edp.h"
14#include "edp.xml.h"
15
16#define VDDA_UA_ON_LOAD 100000 /* uA units */
17#define VDDA_UA_OFF_LOAD 100 /* uA units */
18
19#define DPCD_LINK_VOLTAGE_MAX 4
20#define DPCD_LINK_PRE_EMPHASIS_MAX 4
21
22#define EDP_LINK_BW_MAX DP_LINK_BW_2_7
23
24/* Link training return value */
25#define EDP_TRAIN_FAIL -1
26#define EDP_TRAIN_SUCCESS 0
27#define EDP_TRAIN_RECONFIG 1
28
29#define EDP_CLK_MASK_AHB BIT(0)
30#define EDP_CLK_MASK_AUX BIT(1)
31#define EDP_CLK_MASK_LINK BIT(2)
32#define EDP_CLK_MASK_PIXEL BIT(3)
33#define EDP_CLK_MASK_MDP_CORE BIT(4)
34#define EDP_CLK_MASK_LINK_CHAN (EDP_CLK_MASK_LINK | EDP_CLK_MASK_PIXEL)
35#define EDP_CLK_MASK_AUX_CHAN \
36 (EDP_CLK_MASK_AHB | EDP_CLK_MASK_AUX | EDP_CLK_MASK_MDP_CORE)
37#define EDP_CLK_MASK_ALL (EDP_CLK_MASK_AUX_CHAN | EDP_CLK_MASK_LINK_CHAN)
38
39#define EDP_BACKLIGHT_MAX 255
40
41#define EDP_INTR_STATUS1 \
42 (EDP_INTERRUPT_REG_1_HPD | EDP_INTERRUPT_REG_1_AUX_I2C_DONE | \
43 EDP_INTERRUPT_REG_1_WRONG_ADDR | EDP_INTERRUPT_REG_1_TIMEOUT | \
44 EDP_INTERRUPT_REG_1_NACK_DEFER | EDP_INTERRUPT_REG_1_WRONG_DATA_CNT | \
45 EDP_INTERRUPT_REG_1_I2C_NACK | EDP_INTERRUPT_REG_1_I2C_DEFER | \
46 EDP_INTERRUPT_REG_1_PLL_UNLOCK | EDP_INTERRUPT_REG_1_AUX_ERROR)
47#define EDP_INTR_MASK1 (EDP_INTR_STATUS1 << 2)
48#define EDP_INTR_STATUS2 \
49 (EDP_INTERRUPT_REG_2_READY_FOR_VIDEO | \
50 EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT | \
51 EDP_INTERRUPT_REG_2_FRAME_END | EDP_INTERRUPT_REG_2_CRC_UPDATED)
52#define EDP_INTR_MASK2 (EDP_INTR_STATUS2 << 2)
53
54struct edp_ctrl {
55 struct platform_device *pdev;
56
57 void __iomem *base;
58
59 /* regulators */
60 struct regulator *vdda_vreg; /* 1.8 V */
61 struct regulator *lvl_vreg;
62
63 /* clocks */
64 struct clk *aux_clk;
65 struct clk *pixel_clk;
66 struct clk *ahb_clk;
67 struct clk *link_clk;
68 struct clk *mdp_core_clk;
69
70 /* gpios */
71 struct gpio_desc *panel_en_gpio;
72 struct gpio_desc *panel_hpd_gpio;
73
74 /* completion and mutex */
75 struct completion idle_comp;
76 struct mutex dev_mutex; /* To protect device power status */
77
78 /* work queue */
79 struct work_struct on_work;
80 struct work_struct off_work;
81 struct workqueue_struct *workqueue;
82
83 /* Interrupt register lock */
84 spinlock_t irq_lock;
85
86 bool edp_connected;
87 bool power_on;
88
89 /* edid raw data */
90 struct edid *edid;
91
92 struct drm_dp_aux *drm_aux;
93
94 /* dpcd raw data */
95 u8 dpcd[DP_RECEIVER_CAP_SIZE];
96
97 /* Link status */
98 u8 link_rate;
99 u8 lane_cnt;
100 u8 v_level;
101 u8 p_level;
102
103 /* Timing status */
104 u8 interlaced;
105 u32 pixel_rate; /* in kHz */
106 u32 color_depth;
107
108 struct edp_aux *aux;
109 struct edp_phy *phy;
110};
111
112struct edp_pixel_clk_div {
113 u32 rate; /* in kHz */
114 u32 m;
115 u32 n;
116};
117
118#define EDP_PIXEL_CLK_NUM 8
119static const struct edp_pixel_clk_div clk_divs[2][EDP_PIXEL_CLK_NUM] = {
120 { /* Link clock = 162MHz, source clock = 810MHz */
121 {119000, 31, 211}, /* WSXGA+ 1680x1050@60Hz CVT */
122 {130250, 32, 199}, /* UXGA 1600x1200@60Hz CVT */
123 {148500, 11, 60}, /* FHD 1920x1080@60Hz */
124 {154000, 50, 263}, /* WUXGA 1920x1200@60Hz CVT */
125 {209250, 31, 120}, /* QXGA 2048x1536@60Hz CVT */
126 {268500, 119, 359}, /* WQXGA 2560x1600@60Hz CVT */
127 {138530, 33, 193}, /* AUO B116HAN03.0 Panel */
128 {141400, 48, 275}, /* AUO B133HTN01.2 Panel */
129 },
130 { /* Link clock = 270MHz, source clock = 675MHz */
131 {119000, 52, 295}, /* WSXGA+ 1680x1050@60Hz CVT */
132 {130250, 11, 57}, /* UXGA 1600x1200@60Hz CVT */
133 {148500, 11, 50}, /* FHD 1920x1080@60Hz */
134 {154000, 47, 206}, /* WUXGA 1920x1200@60Hz CVT */
135 {209250, 31, 100}, /* QXGA 2048x1536@60Hz CVT */
136 {268500, 107, 269}, /* WQXGA 2560x1600@60Hz CVT */
137 {138530, 63, 307}, /* AUO B116HAN03.0 Panel */
138 {141400, 53, 253}, /* AUO B133HTN01.2 Panel */
139 },
140};
141
142static int edp_clk_init(struct edp_ctrl *ctrl)
143{
144 struct platform_device *pdev = ctrl->pdev;
145 int ret;
146
147 ctrl->aux_clk = msm_clk_get(pdev, "core");
148 if (IS_ERR(ctrl->aux_clk)) {
149 ret = PTR_ERR(ctrl->aux_clk);
150 pr_err("%s: Can't find core clock, %d\n", __func__, ret);
151 ctrl->aux_clk = NULL;
152 return ret;
153 }
154
155 ctrl->pixel_clk = msm_clk_get(pdev, "pixel");
156 if (IS_ERR(ctrl->pixel_clk)) {
157 ret = PTR_ERR(ctrl->pixel_clk);
158 pr_err("%s: Can't find pixel clock, %d\n", __func__, ret);
159 ctrl->pixel_clk = NULL;
160 return ret;
161 }
162
163 ctrl->ahb_clk = msm_clk_get(pdev, "iface");
164 if (IS_ERR(ctrl->ahb_clk)) {
165 ret = PTR_ERR(ctrl->ahb_clk);
166 pr_err("%s: Can't find iface clock, %d\n", __func__, ret);
167 ctrl->ahb_clk = NULL;
168 return ret;
169 }
170
171 ctrl->link_clk = msm_clk_get(pdev, "link");
172 if (IS_ERR(ctrl->link_clk)) {
173 ret = PTR_ERR(ctrl->link_clk);
174 pr_err("%s: Can't find link clock, %d\n", __func__, ret);
175 ctrl->link_clk = NULL;
176 return ret;
177 }
178
179 /* need mdp core clock to receive irq */
180 ctrl->mdp_core_clk = msm_clk_get(pdev, "mdp_core");
181 if (IS_ERR(ctrl->mdp_core_clk)) {
182 ret = PTR_ERR(ctrl->mdp_core_clk);
183 pr_err("%s: Can't find mdp_core clock, %d\n", __func__, ret);
184 ctrl->mdp_core_clk = NULL;
185 return ret;
186 }
187
188 return 0;
189}
190
191static int edp_clk_enable(struct edp_ctrl *ctrl, u32 clk_mask)
192{
193 int ret;
194
195 DBG("mask=%x", clk_mask);
196 /* ahb_clk should be enabled first */
197 if (clk_mask & EDP_CLK_MASK_AHB) {
198 ret = clk_prepare_enable(ctrl->ahb_clk);
199 if (ret) {
200 pr_err("%s: Failed to enable ahb clk\n", __func__);
201 goto f0;
202 }
203 }
204 if (clk_mask & EDP_CLK_MASK_AUX) {
205 ret = clk_set_rate(ctrl->aux_clk, 19200000);
206 if (ret) {
207 pr_err("%s: Failed to set rate aux clk\n", __func__);
208 goto f1;
209 }
210 ret = clk_prepare_enable(ctrl->aux_clk);
211 if (ret) {
212 pr_err("%s: Failed to enable aux clk\n", __func__);
213 goto f1;
214 }
215 }
216 /* Need to set rate and enable link_clk prior to pixel_clk */
217 if (clk_mask & EDP_CLK_MASK_LINK) {
218 DBG("edp->link_clk, set_rate %ld",
219 (unsigned long)ctrl->link_rate * 27000000);
220 ret = clk_set_rate(ctrl->link_clk,
221 (unsigned long)ctrl->link_rate * 27000000);
222 if (ret) {
223 pr_err("%s: Failed to set rate to link clk\n",
224 __func__);
225 goto f2;
226 }
227
228 ret = clk_prepare_enable(ctrl->link_clk);
229 if (ret) {
230 pr_err("%s: Failed to enable link clk\n", __func__);
231 goto f2;
232 }
233 }
234 if (clk_mask & EDP_CLK_MASK_PIXEL) {
235 DBG("edp->pixel_clk, set_rate %ld",
236 (unsigned long)ctrl->pixel_rate * 1000);
237 ret = clk_set_rate(ctrl->pixel_clk,
238 (unsigned long)ctrl->pixel_rate * 1000);
239 if (ret) {
240 pr_err("%s: Failed to set rate to pixel clk\n",
241 __func__);
242 goto f3;
243 }
244
245 ret = clk_prepare_enable(ctrl->pixel_clk);
246 if (ret) {
247 pr_err("%s: Failed to enable pixel clk\n", __func__);
248 goto f3;
249 }
250 }
251 if (clk_mask & EDP_CLK_MASK_MDP_CORE) {
252 ret = clk_prepare_enable(ctrl->mdp_core_clk);
253 if (ret) {
254 pr_err("%s: Failed to enable mdp core clk\n", __func__);
255 goto f4;
256 }
257 }
258
259 return 0;
260
261f4:
262 if (clk_mask & EDP_CLK_MASK_PIXEL)
263 clk_disable_unprepare(ctrl->pixel_clk);
264f3:
265 if (clk_mask & EDP_CLK_MASK_LINK)
266 clk_disable_unprepare(ctrl->link_clk);
267f2:
268 if (clk_mask & EDP_CLK_MASK_AUX)
269 clk_disable_unprepare(ctrl->aux_clk);
270f1:
271 if (clk_mask & EDP_CLK_MASK_AHB)
272 clk_disable_unprepare(ctrl->ahb_clk);
273f0:
274 return ret;
275}
276
277static void edp_clk_disable(struct edp_ctrl *ctrl, u32 clk_mask)
278{
279 if (clk_mask & EDP_CLK_MASK_MDP_CORE)
280 clk_disable_unprepare(ctrl->mdp_core_clk);
281 if (clk_mask & EDP_CLK_MASK_PIXEL)
282 clk_disable_unprepare(ctrl->pixel_clk);
283 if (clk_mask & EDP_CLK_MASK_LINK)
284 clk_disable_unprepare(ctrl->link_clk);
285 if (clk_mask & EDP_CLK_MASK_AUX)
286 clk_disable_unprepare(ctrl->aux_clk);
287 if (clk_mask & EDP_CLK_MASK_AHB)
288 clk_disable_unprepare(ctrl->ahb_clk);
289}
290
291static int edp_regulator_init(struct edp_ctrl *ctrl)
292{
293 struct device *dev = &ctrl->pdev->dev;
294 int ret;
295
296 DBG("");
297 ctrl->vdda_vreg = devm_regulator_get(dev, "vdda");
298 ret = PTR_ERR_OR_ZERO(ctrl->vdda_vreg);
299 if (ret) {
300 pr_err("%s: Could not get vdda reg, ret = %d\n", __func__,
301 ret);
302 ctrl->vdda_vreg = NULL;
303 return ret;
304 }
305 ctrl->lvl_vreg = devm_regulator_get(dev, "lvl-vdd");
306 ret = PTR_ERR_OR_ZERO(ctrl->lvl_vreg);
307 if (ret) {
308 pr_err("%s: Could not get lvl-vdd reg, ret = %d\n", __func__,
309 ret);
310 ctrl->lvl_vreg = NULL;
311 return ret;
312 }
313
314 return 0;
315}
316
317static int edp_regulator_enable(struct edp_ctrl *ctrl)
318{
319 int ret;
320
321 ret = regulator_set_load(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
322 if (ret < 0) {
323 pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__);
324 goto vdda_set_fail;
325 }
326
327 ret = regulator_enable(ctrl->vdda_vreg);
328 if (ret) {
329 pr_err("%s: Failed to enable vdda_vreg regulator.\n", __func__);
330 goto vdda_enable_fail;
331 }
332
333 ret = regulator_enable(ctrl->lvl_vreg);
334 if (ret) {
335 pr_err("Failed to enable lvl-vdd reg regulator, %d", ret);
336 goto lvl_enable_fail;
337 }
338
339 DBG("exit");
340 return 0;
341
342lvl_enable_fail:
343 regulator_disable(ctrl->vdda_vreg);
344vdda_enable_fail:
345 regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
346vdda_set_fail:
347 return ret;
348}
349
350static void edp_regulator_disable(struct edp_ctrl *ctrl)
351{
352 regulator_disable(ctrl->lvl_vreg);
353 regulator_disable(ctrl->vdda_vreg);
354 regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD);
355}
356
357static int edp_gpio_config(struct edp_ctrl *ctrl)
358{
359 struct device *dev = &ctrl->pdev->dev;
360 int ret;
361
362 ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd", GPIOD_IN);
363 if (IS_ERR(ctrl->panel_hpd_gpio)) {
364 ret = PTR_ERR(ctrl->panel_hpd_gpio);
365 ctrl->panel_hpd_gpio = NULL;
366 pr_err("%s: cannot get panel-hpd-gpios, %d\n", __func__, ret);
367 return ret;
368 }
369
370 ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en", GPIOD_OUT_LOW);
371 if (IS_ERR(ctrl->panel_en_gpio)) {
372 ret = PTR_ERR(ctrl->panel_en_gpio);
373 ctrl->panel_en_gpio = NULL;
374 pr_err("%s: cannot get panel-en-gpios, %d\n", __func__, ret);
375 return ret;
376 }
377
378 DBG("gpio on");
379
380 return 0;
381}
382
383static void edp_ctrl_irq_enable(struct edp_ctrl *ctrl, int enable)
384{
385 unsigned long flags;
386
387 DBG("%d", enable);
388 spin_lock_irqsave(&ctrl->irq_lock, flags);
389 if (enable) {
390 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, EDP_INTR_MASK1);
391 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, EDP_INTR_MASK2);
392 } else {
393 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, 0x0);
394 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, 0x0);
395 }
396 spin_unlock_irqrestore(&ctrl->irq_lock, flags);
397 DBG("exit");
398}
399
400static void edp_fill_link_cfg(struct edp_ctrl *ctrl)
401{
402 u32 prate;
403 u32 lrate;
404 u32 bpp;
405 u8 max_lane = drm_dp_max_lane_count(ctrl->dpcd);
406 u8 lane;
407
408 prate = ctrl->pixel_rate;
409 bpp = ctrl->color_depth * 3;
410
411 /*
412 * By default, use the maximum link rate and minimum lane count,
413 * so that we can do rate down shift during link training.
414 */
415 ctrl->link_rate = ctrl->dpcd[DP_MAX_LINK_RATE];
416
417 prate *= bpp;
418 prate /= 8; /* in kByte */
419
420 lrate = 270000; /* in kHz */
421 lrate *= ctrl->link_rate;
422 lrate /= 10; /* in kByte, 10 bits --> 8 bits */
423
424 for (lane = 1; lane <= max_lane; lane <<= 1) {
425 if (lrate >= prate)
426 break;
427 lrate <<= 1;
428 }
429
430 ctrl->lane_cnt = lane;
431 DBG("rate=%d lane=%d", ctrl->link_rate, ctrl->lane_cnt);
432}
433
434static void edp_config_ctrl(struct edp_ctrl *ctrl)
435{
436 u32 data;
437 enum edp_color_depth depth;
438
439 data = EDP_CONFIGURATION_CTRL_LANES(ctrl->lane_cnt - 1);
440
441 if (drm_dp_enhanced_frame_cap(ctrl->dpcd))
442 data |= EDP_CONFIGURATION_CTRL_ENHANCED_FRAMING;
443
444 depth = EDP_6BIT;
445 if (ctrl->color_depth == 8)
446 depth = EDP_8BIT;
447
448 data |= EDP_CONFIGURATION_CTRL_COLOR(depth);
449
450 if (!ctrl->interlaced) /* progressive */
451 data |= EDP_CONFIGURATION_CTRL_PROGRESSIVE;
452
453 data |= (EDP_CONFIGURATION_CTRL_SYNC_CLK |
454 EDP_CONFIGURATION_CTRL_STATIC_MVID);
455
456 edp_write(ctrl->base + REG_EDP_CONFIGURATION_CTRL, data);
457}
458
459static void edp_state_ctrl(struct edp_ctrl *ctrl, u32 state)
460{
461 edp_write(ctrl->base + REG_EDP_STATE_CTRL, state);
462 /* Make sure H/W status is set */
463 wmb();
464}
465
466static int edp_lane_set_write(struct edp_ctrl *ctrl,
467 u8 voltage_level, u8 pre_emphasis_level)
468{
469 int i;
470 u8 buf[4];
471
472 if (voltage_level >= DPCD_LINK_VOLTAGE_MAX)
473 voltage_level |= 0x04;
474
475 if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX)
476 pre_emphasis_level |= 0x04;
477
478 pre_emphasis_level <<= 3;
479
480 for (i = 0; i < 4; i++)
481 buf[i] = voltage_level | pre_emphasis_level;
482
483 DBG("%s: p|v=0x%x", __func__, voltage_level | pre_emphasis_level);
484 if (drm_dp_dpcd_write(ctrl->drm_aux, 0x103, buf, 4) < 4) {
485 pr_err("%s: Set sw/pe to panel failed\n", __func__);
486 return -ENOLINK;
487 }
488
489 return 0;
490}
491
492static int edp_train_pattern_set_write(struct edp_ctrl *ctrl, u8 pattern)
493{
494 u8 p = pattern;
495
496 DBG("pattern=%x", p);
497 if (drm_dp_dpcd_write(ctrl->drm_aux,
498 DP_TRAINING_PATTERN_SET, &p, 1) < 1) {
499 pr_err("%s: Set training pattern to panel failed\n", __func__);
500 return -ENOLINK;
501 }
502
503 return 0;
504}
505
506static void edp_sink_train_set_adjust(struct edp_ctrl *ctrl,
507 const u8 *link_status)
508{
509 int i;
510 u8 max = 0;
511 u8 data;
512
513 /* use the max level across lanes */
514 for (i = 0; i < ctrl->lane_cnt; i++) {
515 data = drm_dp_get_adjust_request_voltage(link_status, i);
516 DBG("lane=%d req_voltage_swing=0x%x", i, data);
517 if (max < data)
518 max = data;
519 }
520
521 ctrl->v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
522
523 /* use the max level across lanes */
524 max = 0;
525 for (i = 0; i < ctrl->lane_cnt; i++) {
526 data = drm_dp_get_adjust_request_pre_emphasis(link_status, i);
527 DBG("lane=%d req_pre_emphasis=0x%x", i, data);
528 if (max < data)
529 max = data;
530 }
531
532 ctrl->p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
533 DBG("v_level=%d, p_level=%d", ctrl->v_level, ctrl->p_level);
534}
535
536static void edp_host_train_set(struct edp_ctrl *ctrl, u32 train)
537{
538 int cnt = 10;
539 u32 data;
540 u32 shift = train - 1;
541
542 DBG("train=%d", train);
543
544 edp_state_ctrl(ctrl, EDP_STATE_CTRL_TRAIN_PATTERN_1 << shift);
545 while (--cnt) {
546 data = edp_read(ctrl->base + REG_EDP_MAINLINK_READY);
547 if (data & (EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY << shift))
548 break;
549 }
550
551 if (cnt == 0)
552 pr_err("%s: set link_train=%d failed\n", __func__, train);
553}
554
555static const u8 vm_pre_emphasis[4][4] = {
556 {0x03, 0x06, 0x09, 0x0C}, /* pe0, 0 db */
557 {0x03, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */
558 {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */
559 {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
560};
561
562/* voltage swing, 0.2v and 1.0v are not support */
563static const u8 vm_voltage_swing[4][4] = {
564 {0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */
565 {0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */
566 {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */
567 {0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
568};
569
570static int edp_voltage_pre_emphasise_set(struct edp_ctrl *ctrl)
571{
572 u32 value0;
573 u32 value1;
574
575 DBG("v=%d p=%d", ctrl->v_level, ctrl->p_level);
576
577 value0 = vm_pre_emphasis[(int)(ctrl->v_level)][(int)(ctrl->p_level)];
578 value1 = vm_voltage_swing[(int)(ctrl->v_level)][(int)(ctrl->p_level)];
579
580 /* Configure host and panel only if both values are allowed */
581 if (value0 != 0xFF && value1 != 0xFF) {
582 msm_edp_phy_vm_pe_cfg(ctrl->phy, value0, value1);
583 return edp_lane_set_write(ctrl, ctrl->v_level, ctrl->p_level);
584 }
585
586 return -EINVAL;
587}
588
589static int edp_start_link_train_1(struct edp_ctrl *ctrl)
590{
591 u8 link_status[DP_LINK_STATUS_SIZE];
592 u8 old_v_level;
593 int tries;
594 int ret;
595 int rlen;
596
597 DBG("");
598
599 edp_host_train_set(ctrl, DP_TRAINING_PATTERN_1);
600 ret = edp_voltage_pre_emphasise_set(ctrl);
601 if (ret)
602 return ret;
603 ret = edp_train_pattern_set_write(ctrl,
604 DP_TRAINING_PATTERN_1 | DP_RECOVERED_CLOCK_OUT_EN);
605 if (ret)
606 return ret;
607
608 tries = 0;
609 old_v_level = ctrl->v_level;
610 while (1) {
611 drm_dp_link_train_clock_recovery_delay(ctrl->drm_aux, ctrl->dpcd);
612
613 rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status);
614 if (rlen < DP_LINK_STATUS_SIZE) {
615 pr_err("%s: read link status failed\n", __func__);
616 return -ENOLINK;
617 }
618 if (drm_dp_clock_recovery_ok(link_status, ctrl->lane_cnt)) {
619 ret = 0;
620 break;
621 }
622
623 if (ctrl->v_level == DPCD_LINK_VOLTAGE_MAX) {
624 ret = -1;
625 break;
626 }
627
628 if (old_v_level == ctrl->v_level) {
629 tries++;
630 if (tries >= 5) {
631 ret = -1;
632 break;
633 }
634 } else {
635 tries = 0;
636 old_v_level = ctrl->v_level;
637 }
638
639 edp_sink_train_set_adjust(ctrl, link_status);
640 ret = edp_voltage_pre_emphasise_set(ctrl);
641 if (ret)
642 return ret;
643 }
644
645 return ret;
646}
647
648static int edp_start_link_train_2(struct edp_ctrl *ctrl)
649{
650 u8 link_status[DP_LINK_STATUS_SIZE];
651 int tries = 0;
652 int ret;
653 int rlen;
654
655 DBG("");
656
657 edp_host_train_set(ctrl, DP_TRAINING_PATTERN_2);
658 ret = edp_voltage_pre_emphasise_set(ctrl);
659 if (ret)
660 return ret;
661
662 ret = edp_train_pattern_set_write(ctrl,
663 DP_TRAINING_PATTERN_2 | DP_RECOVERED_CLOCK_OUT_EN);
664 if (ret)
665 return ret;
666
667 while (1) {
668 drm_dp_link_train_channel_eq_delay(ctrl->drm_aux, ctrl->dpcd);
669
670 rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status);
671 if (rlen < DP_LINK_STATUS_SIZE) {
672 pr_err("%s: read link status failed\n", __func__);
673 return -ENOLINK;
674 }
675 if (drm_dp_channel_eq_ok(link_status, ctrl->lane_cnt)) {
676 ret = 0;
677 break;
678 }
679
680 tries++;
681 if (tries > 10) {
682 ret = -1;
683 break;
684 }
685
686 edp_sink_train_set_adjust(ctrl, link_status);
687 ret = edp_voltage_pre_emphasise_set(ctrl);
688 if (ret)
689 return ret;
690 }
691
692 return ret;
693}
694
695static int edp_link_rate_down_shift(struct edp_ctrl *ctrl)
696{
697 u32 prate, lrate, bpp;
698 u8 rate, lane, max_lane;
699 int changed = 0;
700
701 rate = ctrl->link_rate;
702 lane = ctrl->lane_cnt;
703 max_lane = drm_dp_max_lane_count(ctrl->dpcd);
704
705 bpp = ctrl->color_depth * 3;
706 prate = ctrl->pixel_rate;
707 prate *= bpp;
708 prate /= 8; /* in kByte */
709
710 if (rate > DP_LINK_BW_1_62 && rate <= EDP_LINK_BW_MAX) {
711 rate -= 4; /* reduce rate */
712 changed++;
713 }
714
715 if (changed) {
716 if (lane >= 1 && lane < max_lane)
717 lane <<= 1; /* increase lane */
718
719 lrate = 270000; /* in kHz */
720 lrate *= rate;
721 lrate /= 10; /* kByte, 10 bits --> 8 bits */
722 lrate *= lane;
723
724 DBG("new lrate=%u prate=%u(kHz) rate=%d lane=%d p=%u b=%d",
725 lrate, prate, rate, lane,
726 ctrl->pixel_rate,
727 bpp);
728
729 if (lrate > prate) {
730 ctrl->link_rate = rate;
731 ctrl->lane_cnt = lane;
732 DBG("new rate=%d %d", rate, lane);
733 return 0;
734 }
735 }
736
737 return -EINVAL;
738}
739
740static int edp_clear_training_pattern(struct edp_ctrl *ctrl)
741{
742 int ret;
743
744 ret = edp_train_pattern_set_write(ctrl, 0);
745
746 drm_dp_link_train_channel_eq_delay(ctrl->drm_aux, ctrl->dpcd);
747
748 return ret;
749}
750
751static int edp_do_link_train(struct edp_ctrl *ctrl)
752{
753 u8 values[2];
754 int ret;
755
756 DBG("");
757 /*
758 * Set the current link rate and lane cnt to panel. They may have been
759 * adjusted and the values are different from them in DPCD CAP
760 */
761 values[0] = ctrl->lane_cnt;
762 values[1] = ctrl->link_rate;
763
764 if (drm_dp_enhanced_frame_cap(ctrl->dpcd))
765 values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
766
767 if (drm_dp_dpcd_write(ctrl->drm_aux, DP_LINK_BW_SET, values,
768 sizeof(values)) < 0)
769 return EDP_TRAIN_FAIL;
770
771 ctrl->v_level = 0; /* start from default level */
772 ctrl->p_level = 0;
773
774 edp_state_ctrl(ctrl, 0);
775 if (edp_clear_training_pattern(ctrl))
776 return EDP_TRAIN_FAIL;
777
778 ret = edp_start_link_train_1(ctrl);
779 if (ret < 0) {
780 if (edp_link_rate_down_shift(ctrl) == 0) {
781 DBG("link reconfig");
782 ret = EDP_TRAIN_RECONFIG;
783 goto clear;
784 } else {
785 pr_err("%s: Training 1 failed", __func__);
786 ret = EDP_TRAIN_FAIL;
787 goto clear;
788 }
789 }
790 DBG("Training 1 completed successfully");
791
792 edp_state_ctrl(ctrl, 0);
793 if (edp_clear_training_pattern(ctrl))
794 return EDP_TRAIN_FAIL;
795
796 ret = edp_start_link_train_2(ctrl);
797 if (ret < 0) {
798 if (edp_link_rate_down_shift(ctrl) == 0) {
799 DBG("link reconfig");
800 ret = EDP_TRAIN_RECONFIG;
801 goto clear;
802 } else {
803 pr_err("%s: Training 2 failed", __func__);
804 ret = EDP_TRAIN_FAIL;
805 goto clear;
806 }
807 }
808 DBG("Training 2 completed successfully");
809
810 edp_state_ctrl(ctrl, EDP_STATE_CTRL_SEND_VIDEO);
811clear:
812 edp_clear_training_pattern(ctrl);
813
814 return ret;
815}
816
817static void edp_clock_synchrous(struct edp_ctrl *ctrl, int sync)
818{
819 u32 data;
820 enum edp_color_depth depth;
821
822 data = edp_read(ctrl->base + REG_EDP_MISC1_MISC0);
823
824 if (sync)
825 data |= EDP_MISC1_MISC0_SYNC;
826 else
827 data &= ~EDP_MISC1_MISC0_SYNC;
828
829 /* only legacy rgb mode supported */
830 depth = EDP_6BIT; /* Default */
831 if (ctrl->color_depth == 8)
832 depth = EDP_8BIT;
833 else if (ctrl->color_depth == 10)
834 depth = EDP_10BIT;
835 else if (ctrl->color_depth == 12)
836 depth = EDP_12BIT;
837 else if (ctrl->color_depth == 16)
838 depth = EDP_16BIT;
839
840 data |= EDP_MISC1_MISC0_COLOR(depth);
841
842 edp_write(ctrl->base + REG_EDP_MISC1_MISC0, data);
843}
844
845static int edp_sw_mvid_nvid(struct edp_ctrl *ctrl, u32 m, u32 n)
846{
847 u32 n_multi, m_multi = 5;
848
849 if (ctrl->link_rate == DP_LINK_BW_1_62) {
850 n_multi = 1;
851 } else if (ctrl->link_rate == DP_LINK_BW_2_7) {
852 n_multi = 2;
853 } else {
854 pr_err("%s: Invalid link rate, %d\n", __func__,
855 ctrl->link_rate);
856 return -EINVAL;
857 }
858
859 edp_write(ctrl->base + REG_EDP_SOFTWARE_MVID, m * m_multi);
860 edp_write(ctrl->base + REG_EDP_SOFTWARE_NVID, n * n_multi);
861
862 return 0;
863}
864
865static void edp_mainlink_ctrl(struct edp_ctrl *ctrl, int enable)
866{
867 u32 data = 0;
868
869 edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, EDP_MAINLINK_CTRL_RESET);
870 /* Make sure fully reset */
871 wmb();
872 usleep_range(500, 1000);
873
874 if (enable)
875 data |= EDP_MAINLINK_CTRL_ENABLE;
876
877 edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, data);
878}
879
880static void edp_ctrl_phy_aux_enable(struct edp_ctrl *ctrl, int enable)
881{
882 if (enable) {
883 edp_regulator_enable(ctrl);
884 edp_clk_enable(ctrl, EDP_CLK_MASK_AUX_CHAN);
885 msm_edp_phy_ctrl(ctrl->phy, 1);
886 msm_edp_aux_ctrl(ctrl->aux, 1);
887 gpiod_set_value(ctrl->panel_en_gpio, 1);
888 } else {
889 gpiod_set_value(ctrl->panel_en_gpio, 0);
890 msm_edp_aux_ctrl(ctrl->aux, 0);
891 msm_edp_phy_ctrl(ctrl->phy, 0);
892 edp_clk_disable(ctrl, EDP_CLK_MASK_AUX_CHAN);
893 edp_regulator_disable(ctrl);
894 }
895}
896
897static void edp_ctrl_link_enable(struct edp_ctrl *ctrl, int enable)
898{
899 u32 m, n;
900
901 if (enable) {
902 /* Enable link channel clocks */
903 edp_clk_enable(ctrl, EDP_CLK_MASK_LINK_CHAN);
904
905 msm_edp_phy_lane_power_ctrl(ctrl->phy, true, ctrl->lane_cnt);
906
907 msm_edp_phy_vm_pe_init(ctrl->phy);
908
909 /* Make sure phy is programed */
910 wmb();
911 msm_edp_phy_ready(ctrl->phy);
912
913 edp_config_ctrl(ctrl);
914 msm_edp_ctrl_pixel_clock_valid(ctrl, ctrl->pixel_rate, &m, &n);
915 edp_sw_mvid_nvid(ctrl, m, n);
916 edp_mainlink_ctrl(ctrl, 1);
917 } else {
918 edp_mainlink_ctrl(ctrl, 0);
919
920 msm_edp_phy_lane_power_ctrl(ctrl->phy, false, 0);
921 edp_clk_disable(ctrl, EDP_CLK_MASK_LINK_CHAN);
922 }
923}
924
925static int edp_ctrl_training(struct edp_ctrl *ctrl)
926{
927 int ret;
928
929 /* Do link training only when power is on */
930 if (!ctrl->power_on)
931 return -EINVAL;
932
933train_start:
934 ret = edp_do_link_train(ctrl);
935 if (ret == EDP_TRAIN_RECONFIG) {
936 /* Re-configure main link */
937 edp_ctrl_irq_enable(ctrl, 0);
938 edp_ctrl_link_enable(ctrl, 0);
939 msm_edp_phy_ctrl(ctrl->phy, 0);
940
941 /* Make sure link is fully disabled */
942 wmb();
943 usleep_range(500, 1000);
944
945 msm_edp_phy_ctrl(ctrl->phy, 1);
946 edp_ctrl_link_enable(ctrl, 1);
947 edp_ctrl_irq_enable(ctrl, 1);
948 goto train_start;
949 }
950
951 return ret;
952}
953
954static void edp_ctrl_on_worker(struct work_struct *work)
955{
956 struct edp_ctrl *ctrl = container_of(
957 work, struct edp_ctrl, on_work);
958 u8 value;
959 int ret;
960
961 mutex_lock(&ctrl->dev_mutex);
962
963 if (ctrl->power_on) {
964 DBG("already on");
965 goto unlock_ret;
966 }
967
968 edp_ctrl_phy_aux_enable(ctrl, 1);
969 edp_ctrl_link_enable(ctrl, 1);
970
971 edp_ctrl_irq_enable(ctrl, 1);
972
973 /* DP_SET_POWER register is only available on DPCD v1.1 and later */
974 if (ctrl->dpcd[DP_DPCD_REV] >= 0x11) {
975 ret = drm_dp_dpcd_readb(ctrl->drm_aux, DP_SET_POWER, &value);
976 if (ret < 0)
977 goto fail;
978
979 value &= ~DP_SET_POWER_MASK;
980 value |= DP_SET_POWER_D0;
981
982 ret = drm_dp_dpcd_writeb(ctrl->drm_aux, DP_SET_POWER, value);
983 if (ret < 0)
984 goto fail;
985
986 /*
987 * According to the DP 1.1 specification, a "Sink Device must
988 * exit the power saving state within 1 ms" (Section 2.5.3.1,
989 * Table 5-52, "Sink Control Field" (register 0x600).
990 */
991 usleep_range(1000, 2000);
992 }
993
994 ctrl->power_on = true;
995
996 /* Start link training */
997 ret = edp_ctrl_training(ctrl);
998 if (ret != EDP_TRAIN_SUCCESS)
999 goto fail;
1000
1001 DBG("DONE");
1002 goto unlock_ret;
1003
1004fail:
1005 edp_ctrl_irq_enable(ctrl, 0);
1006 edp_ctrl_link_enable(ctrl, 0);
1007 edp_ctrl_phy_aux_enable(ctrl, 0);
1008 ctrl->power_on = false;
1009unlock_ret:
1010 mutex_unlock(&ctrl->dev_mutex);
1011}
1012
1013static void edp_ctrl_off_worker(struct work_struct *work)
1014{
1015 struct edp_ctrl *ctrl = container_of(
1016 work, struct edp_ctrl, off_work);
1017 unsigned long time_left;
1018
1019 mutex_lock(&ctrl->dev_mutex);
1020
1021 if (!ctrl->power_on) {
1022 DBG("already off");
1023 goto unlock_ret;
1024 }
1025
1026 reinit_completion(&ctrl->idle_comp);
1027 edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE);
1028
1029 time_left = wait_for_completion_timeout(&ctrl->idle_comp,
1030 msecs_to_jiffies(500));
1031 if (!time_left)
1032 DBG("%s: idle pattern timedout\n", __func__);
1033
1034 edp_state_ctrl(ctrl, 0);
1035
1036 /* DP_SET_POWER register is only available on DPCD v1.1 and later */
1037 if (ctrl->dpcd[DP_DPCD_REV] >= 0x11) {
1038 u8 value;
1039 int ret;
1040
1041 ret = drm_dp_dpcd_readb(ctrl->drm_aux, DP_SET_POWER, &value);
1042 if (ret > 0) {
1043 value &= ~DP_SET_POWER_MASK;
1044 value |= DP_SET_POWER_D3;
1045
1046 drm_dp_dpcd_writeb(ctrl->drm_aux, DP_SET_POWER, value);
1047 }
1048 }
1049
1050 edp_ctrl_irq_enable(ctrl, 0);
1051
1052 edp_ctrl_link_enable(ctrl, 0);
1053
1054 edp_ctrl_phy_aux_enable(ctrl, 0);
1055
1056 ctrl->power_on = false;
1057
1058unlock_ret:
1059 mutex_unlock(&ctrl->dev_mutex);
1060}
1061
1062irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl)
1063{
1064 u32 isr1, isr2, mask1, mask2;
1065 u32 ack;
1066
1067 DBG("");
1068 spin_lock(&ctrl->irq_lock);
1069 isr1 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_1);
1070 isr2 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_2);
1071
1072 mask1 = isr1 & EDP_INTR_MASK1;
1073 mask2 = isr2 & EDP_INTR_MASK2;
1074
1075 isr1 &= ~mask1; /* remove masks bit */
1076 isr2 &= ~mask2;
1077
1078 DBG("isr=%x mask=%x isr2=%x mask2=%x",
1079 isr1, mask1, isr2, mask2);
1080
1081 ack = isr1 & EDP_INTR_STATUS1;
1082 ack <<= 1; /* ack bits */
1083 ack |= mask1;
1084 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, ack);
1085
1086 ack = isr2 & EDP_INTR_STATUS2;
1087 ack <<= 1; /* ack bits */
1088 ack |= mask2;
1089 edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, ack);
1090 spin_unlock(&ctrl->irq_lock);
1091
1092 if (isr1 & EDP_INTERRUPT_REG_1_HPD)
1093 DBG("edp_hpd");
1094
1095 if (isr2 & EDP_INTERRUPT_REG_2_READY_FOR_VIDEO)
1096 DBG("edp_video_ready");
1097
1098 if (isr2 & EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT) {
1099 DBG("idle_patterns_sent");
1100 complete(&ctrl->idle_comp);
1101 }
1102
1103 msm_edp_aux_irq(ctrl->aux, isr1);
1104
1105 return IRQ_HANDLED;
1106}
1107
1108void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on)
1109{
1110 if (on)
1111 queue_work(ctrl->workqueue, &ctrl->on_work);
1112 else
1113 queue_work(ctrl->workqueue, &ctrl->off_work);
1114}
1115
1116int msm_edp_ctrl_init(struct msm_edp *edp)
1117{
1118 struct edp_ctrl *ctrl = NULL;
1119 struct device *dev;
1120 int ret;
1121
1122 if (!edp) {
1123 pr_err("%s: edp is NULL!\n", __func__);
1124 return -EINVAL;
1125 }
1126
1127 dev = &edp->pdev->dev;
1128 ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
1129 if (!ctrl)
1130 return -ENOMEM;
1131
1132 edp->ctrl = ctrl;
1133 ctrl->pdev = edp->pdev;
1134
1135 ctrl->base = msm_ioremap(ctrl->pdev, "edp", "eDP");
1136 if (IS_ERR(ctrl->base))
1137 return PTR_ERR(ctrl->base);
1138
1139 /* Get regulator, clock, gpio, pwm */
1140 ret = edp_regulator_init(ctrl);
1141 if (ret) {
1142 pr_err("%s:regulator init fail\n", __func__);
1143 return ret;
1144 }
1145 ret = edp_clk_init(ctrl);
1146 if (ret) {
1147 pr_err("%s:clk init fail\n", __func__);
1148 return ret;
1149 }
1150 ret = edp_gpio_config(ctrl);
1151 if (ret) {
1152 pr_err("%s:failed to configure GPIOs: %d", __func__, ret);
1153 return ret;
1154 }
1155
1156 /* Init aux and phy */
1157 ctrl->aux = msm_edp_aux_init(edp, ctrl->base, &ctrl->drm_aux);
1158 if (!ctrl->aux || !ctrl->drm_aux) {
1159 pr_err("%s:failed to init aux\n", __func__);
1160 return -ENOMEM;
1161 }
1162
1163 ctrl->phy = msm_edp_phy_init(dev, ctrl->base);
1164 if (!ctrl->phy) {
1165 pr_err("%s:failed to init phy\n", __func__);
1166 ret = -ENOMEM;
1167 goto err_destory_aux;
1168 }
1169
1170 spin_lock_init(&ctrl->irq_lock);
1171 mutex_init(&ctrl->dev_mutex);
1172 init_completion(&ctrl->idle_comp);
1173
1174 /* setup workqueue */
1175 ctrl->workqueue = alloc_ordered_workqueue("edp_drm_work", 0);
1176 INIT_WORK(&ctrl->on_work, edp_ctrl_on_worker);
1177 INIT_WORK(&ctrl->off_work, edp_ctrl_off_worker);
1178
1179 return 0;
1180
1181err_destory_aux:
1182 msm_edp_aux_destroy(dev, ctrl->aux);
1183 ctrl->aux = NULL;
1184 return ret;
1185}
1186
1187void msm_edp_ctrl_destroy(struct edp_ctrl *ctrl)
1188{
1189 if (!ctrl)
1190 return;
1191
1192 if (ctrl->workqueue) {
1193 destroy_workqueue(ctrl->workqueue);
1194 ctrl->workqueue = NULL;
1195 }
1196
1197 if (ctrl->aux) {
1198 msm_edp_aux_destroy(&ctrl->pdev->dev, ctrl->aux);
1199 ctrl->aux = NULL;
1200 }
1201
1202 kfree(ctrl->edid);
1203 ctrl->edid = NULL;
1204
1205 mutex_destroy(&ctrl->dev_mutex);
1206}
1207
1208bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl)
1209{
1210 mutex_lock(&ctrl->dev_mutex);
1211 DBG("connect status = %d", ctrl->edp_connected);
1212 if (ctrl->edp_connected) {
1213 mutex_unlock(&ctrl->dev_mutex);
1214 return true;
1215 }
1216
1217 if (!ctrl->power_on) {
1218 edp_ctrl_phy_aux_enable(ctrl, 1);
1219 edp_ctrl_irq_enable(ctrl, 1);
1220 }
1221
1222 if (drm_dp_dpcd_read(ctrl->drm_aux, DP_DPCD_REV, ctrl->dpcd,
1223 DP_RECEIVER_CAP_SIZE) < DP_RECEIVER_CAP_SIZE) {
1224 pr_err("%s: AUX channel is NOT ready\n", __func__);
1225 memset(ctrl->dpcd, 0, DP_RECEIVER_CAP_SIZE);
1226 } else {
1227 ctrl->edp_connected = true;
1228 }
1229
1230 if (!ctrl->power_on) {
1231 edp_ctrl_irq_enable(ctrl, 0);
1232 edp_ctrl_phy_aux_enable(ctrl, 0);
1233 }
1234
1235 DBG("exit: connect status=%d", ctrl->edp_connected);
1236
1237 mutex_unlock(&ctrl->dev_mutex);
1238
1239 return ctrl->edp_connected;
1240}
1241
1242int msm_edp_ctrl_get_panel_info(struct edp_ctrl *ctrl,
1243 struct drm_connector *connector, struct edid **edid)
1244{
1245 mutex_lock(&ctrl->dev_mutex);
1246
1247 if (ctrl->edid) {
1248 if (edid) {
1249 DBG("Just return edid buffer");
1250 *edid = ctrl->edid;
1251 }
1252 goto unlock_ret;
1253 }
1254
1255 if (!ctrl->power_on) {
1256 edp_ctrl_phy_aux_enable(ctrl, 1);
1257 edp_ctrl_irq_enable(ctrl, 1);
1258 }
1259
1260 /* Initialize link rate as panel max link rate */
1261 ctrl->link_rate = ctrl->dpcd[DP_MAX_LINK_RATE];
1262
1263 ctrl->edid = drm_get_edid(connector, &ctrl->drm_aux->ddc);
1264 if (!ctrl->edid) {
1265 pr_err("%s: edid read fail\n", __func__);
1266 goto disable_ret;
1267 }
1268
1269 if (edid)
1270 *edid = ctrl->edid;
1271
1272disable_ret:
1273 if (!ctrl->power_on) {
1274 edp_ctrl_irq_enable(ctrl, 0);
1275 edp_ctrl_phy_aux_enable(ctrl, 0);
1276 }
1277unlock_ret:
1278 mutex_unlock(&ctrl->dev_mutex);
1279 return 0;
1280}
1281
1282int msm_edp_ctrl_timing_cfg(struct edp_ctrl *ctrl,
1283 const struct drm_display_mode *mode,
1284 const struct drm_display_info *info)
1285{
1286 u32 hstart_from_sync, vstart_from_sync;
1287 u32 data;
1288 int ret = 0;
1289
1290 mutex_lock(&ctrl->dev_mutex);
1291 /*
1292 * Need to keep color depth, pixel rate and
1293 * interlaced information in ctrl context
1294 */
1295 ctrl->color_depth = info->bpc;
1296 ctrl->pixel_rate = mode->clock;
1297 ctrl->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
1298
1299 /* Fill initial link config based on passed in timing */
1300 edp_fill_link_cfg(ctrl);
1301
1302 if (edp_clk_enable(ctrl, EDP_CLK_MASK_AHB)) {
1303 pr_err("%s, fail to prepare enable ahb clk\n", __func__);
1304 ret = -EINVAL;
1305 goto unlock_ret;
1306 }
1307 edp_clock_synchrous(ctrl, 1);
1308
1309 /* Configure eDP timing to HW */
1310 edp_write(ctrl->base + REG_EDP_TOTAL_HOR_VER,
1311 EDP_TOTAL_HOR_VER_HORIZ(mode->htotal) |
1312 EDP_TOTAL_HOR_VER_VERT(mode->vtotal));
1313
1314 vstart_from_sync = mode->vtotal - mode->vsync_start;
1315 hstart_from_sync = mode->htotal - mode->hsync_start;
1316 edp_write(ctrl->base + REG_EDP_START_HOR_VER_FROM_SYNC,
1317 EDP_START_HOR_VER_FROM_SYNC_HORIZ(hstart_from_sync) |
1318 EDP_START_HOR_VER_FROM_SYNC_VERT(vstart_from_sync));
1319
1320 data = EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT(
1321 mode->vsync_end - mode->vsync_start);
1322 data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ(
1323 mode->hsync_end - mode->hsync_start);
1324 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1325 data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NVSYNC;
1326 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1327 data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NHSYNC;
1328 edp_write(ctrl->base + REG_EDP_HSYNC_VSYNC_WIDTH_POLARITY, data);
1329
1330 edp_write(ctrl->base + REG_EDP_ACTIVE_HOR_VER,
1331 EDP_ACTIVE_HOR_VER_HORIZ(mode->hdisplay) |
1332 EDP_ACTIVE_HOR_VER_VERT(mode->vdisplay));
1333
1334 edp_clk_disable(ctrl, EDP_CLK_MASK_AHB);
1335
1336unlock_ret:
1337 mutex_unlock(&ctrl->dev_mutex);
1338 return ret;
1339}
1340
1341bool msm_edp_ctrl_pixel_clock_valid(struct edp_ctrl *ctrl,
1342 u32 pixel_rate, u32 *pm, u32 *pn)
1343{
1344 const struct edp_pixel_clk_div *divs;
1345 u32 err = 1; /* 1% error tolerance */
1346 u32 clk_err;
1347 int i;
1348
1349 if (ctrl->link_rate == DP_LINK_BW_1_62) {
1350 divs = clk_divs[0];
1351 } else if (ctrl->link_rate == DP_LINK_BW_2_7) {
1352 divs = clk_divs[1];
1353 } else {
1354 pr_err("%s: Invalid link rate,%d\n", __func__, ctrl->link_rate);
1355 return false;
1356 }
1357
1358 for (i = 0; i < EDP_PIXEL_CLK_NUM; i++) {
1359 clk_err = abs(divs[i].rate - pixel_rate);
1360 if ((divs[i].rate * err / 100) >= clk_err) {
1361 if (pm)
1362 *pm = divs[i].m;
1363 if (pn)
1364 *pn = divs[i].n;
1365 return true;
1366 }
1367 }
1368
1369 DBG("pixel clock %d(kHz) not supported", pixel_rate);
1370
1371 return false;
1372}
1373
drivers/gpu/drm/mxsfb/mxsfb_drv.c+9−0
@@ -374,12 +374,20 @@ static int mxsfb_remove(struct platform_device *pdev) · 373 unmodified lines
374 struct drm_device *drm = platform_get_drvdata(pdev);374 struct drm_device *drm = platform_get_drvdata(pdev);
375 375
376 drm_dev_unregister(drm);376 drm_dev_unregister(drm);
377 drm_atomic_helper_shutdown(drm);
377 mxsfb_unload(drm);378 mxsfb_unload(drm);
378 drm_dev_put(drm);379 drm_dev_put(drm);
379 380
380 return 0;381 return 0;
381}382}
382 383
384static void mxsfb_shutdown(struct platform_device *pdev)
385{
386 struct drm_device *drm = platform_get_drvdata(pdev);
387
388 drm_atomic_helper_shutdown(drm);
389}
390
383#ifdef CONFIG_PM_SLEEP391#ifdef CONFIG_PM_SLEEP
384static int mxsfb_suspend(struct device *dev)392static int mxsfb_suspend(struct device *dev)
385{393{
@@ -403,6 +411,7 @@ static const struct dev_pm_ops mxsfb_pm_ops = { · 17 unmodified lines
403static struct platform_driver mxsfb_platform_driver = {411static struct platform_driver mxsfb_platform_driver = {
404 .probe = mxsfb_probe,412 .probe = mxsfb_probe,
405 .remove = mxsfb_remove,413 .remove = mxsfb_remove,
414 .shutdown = mxsfb_shutdown,
406 .driver = {415 .driver = {
407 .name = "mxsfb",416 .name = "mxsfb",
408 .of_match_table = mxsfb_dt_ids,417 .of_match_table = mxsfb_dt_ids,
drivers/gpu/drm/nouveau/Kconfig+1−0
@@ -4,6 +4,7 @@ config DRM_NOUVEAU · 3 unmodified lines
4 depends on DRM && PCI && MMU4 depends on DRM && PCI && MMU
5 select IOMMU_API5 select IOMMU_API
6 select FW_LOADER6 select FW_LOADER
7 select DRM_DP_HELPER
7 select DRM_KMS_HELPER8 select DRM_KMS_HELPER
8 select DRM_TTM9 select DRM_TTM
9 select DRM_TTM_HELPER10 select DRM_TTM_HELPER
drivers/gpu/drm/nouveau/dispnv50/disp.c+1−1
@@ -35,7 +35,7 @@ · 34 unmodified lines
35 35
36#include <drm/drm_atomic.h>36#include <drm/drm_atomic.h>
37#include <drm/drm_atomic_helper.h>37#include <drm/drm_atomic_helper.h>
38#include <drm/drm_dp_helper.h>38#include <drm/dp/drm_dp_helper.h>
39#include <drm/drm_edid.h>39#include <drm/drm_edid.h>
40#include <drm/drm_fb_helper.h>40#include <drm/drm_fb_helper.h>
41#include <drm/drm_plane_helper.h>41#include <drm/drm_plane_helper.h>
drivers/gpu/drm/nouveau/nouveau_connector.h+1−1
@@ -36,7 +36,7 @@ · 35 unmodified lines
36#include <drm/drm_crtc.h>36#include <drm/drm_crtc.h>
37#include <drm/drm_edid.h>37#include <drm/drm_edid.h>
38#include <drm/drm_encoder.h>38#include <drm/drm_encoder.h>
39#include <drm/drm_dp_helper.h>39#include <drm/dp/drm_dp_helper.h>
40#include <drm/drm_util.h>40#include <drm/drm_util.h>
41 41
42#include "nouveau_crtc.h"42#include "nouveau_crtc.h"
drivers/gpu/drm/nouveau/nouveau_dp.c+16−1
@@ -22,7 +22,7 @@ · 21 unmodified lines
22 * Authors: Ben Skeggs22 * Authors: Ben Skeggs
23 */23 */
24 24
25#include <drm/drm_dp_helper.h>25#include <drm/dp/drm_dp_helper.h>
26 26
27#include "nouveau_drv.h"27#include "nouveau_drv.h"
28#include "nouveau_connector.h"28#include "nouveau_connector.h"
@@ -147,6 +147,21 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, · 118 unmodified lines
147 nv_encoder->dp.link_nr =147 nv_encoder->dp.link_nr =
148 dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;148 dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
149 149
150 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && dpcd[DP_DPCD_REV] >= 0x13) {
151 struct drm_dp_aux *aux = &nv_connector->aux;
152 int ret, i;
153 u8 sink_rates[16];
154
155 ret = drm_dp_dpcd_read(aux, DP_SUPPORTED_LINK_RATES, sink_rates, sizeof(sink_rates));
156 if (ret == sizeof(sink_rates)) {
157 for (i = 0; i < ARRAY_SIZE(sink_rates); i += 2) {
158 int val = ((sink_rates[i + 1] << 8) | sink_rates[i]) * 200 / 10;
159 if (val && (i == 0 || val > nv_encoder->dp.link_bw))
160 nv_encoder->dp.link_bw = val;
161 }
162 }
163 }
164
150 NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n",165 NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n",
151 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw,166 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw,
152 dpcd[DP_DPCD_REV]);167 dpcd[DP_DPCD_REV]);
drivers/gpu/drm/nouveau/nouveau_encoder.h+2−2
@@ -30,8 +30,8 @@ · 29 unmodified lines
30#include <subdev/bios/dcb.h>30#include <subdev/bios/dcb.h>
31 31
32#include <drm/drm_encoder_slave.h>32#include <drm/drm_encoder_slave.h>
33#include <drm/drm_dp_helper.h>33#include <drm/dp/drm_dp_helper.h>
34#include <drm/drm_dp_mst_helper.h>34#include <drm/dp/drm_dp_mst_helper.h>
35#include "dispnv04/disp.h"35#include "dispnv04/disp.h"
36struct nv50_head_atom;36struct nv50_head_atom;
37struct nouveau_connector;37struct nouveau_connector;
drivers/gpu/drm/nouveau/nouveau_mem.c+2−1
@@ -162,11 +162,12 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page) · 161 unmodified lines
162}162}
163 163
164void164void
165nouveau_mem_del(struct ttm_resource *reg)165nouveau_mem_del(struct ttm_resource_manager *man, struct ttm_resource *reg)
166{166{
167 struct nouveau_mem *mem = nouveau_mem(reg);167 struct nouveau_mem *mem = nouveau_mem(reg);
168 168
169 nouveau_mem_fini(mem);169 nouveau_mem_fini(mem);
170 ttm_resource_fini(man, reg);
170 kfree(mem);171 kfree(mem);
171}172}
172 173
drivers/gpu/drm/nouveau/nouveau_mem.h+2−1
@@ -23,7 +23,8 @@ nouveau_mem(struct ttm_resource *reg) · 22 unmodified lines
23 23
24int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp,24int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp,
25 struct ttm_resource **);25 struct ttm_resource **);
26void nouveau_mem_del(struct ttm_resource *);26void nouveau_mem_del(struct ttm_resource_manager *man,
27 struct ttm_resource *);
27int nouveau_mem_vram(struct ttm_resource *, bool contig, u8 page);28int nouveau_mem_vram(struct ttm_resource *, bool contig, u8 page);
28int nouveau_mem_host(struct ttm_resource *, struct ttm_tt *);29int nouveau_mem_host(struct ttm_resource *, struct ttm_tt *);
29void nouveau_mem_fini(struct nouveau_mem *);30void nouveau_mem_fini(struct nouveau_mem *);
drivers/gpu/drm/nouveau/nouveau_ttm.c+7−6
@@ -36,9 +36,10 @@ · 35 unmodified lines
36#include <core/tegra.h>36#include <core/tegra.h>
37 37
38static void38static void
39nouveau_manager_del(struct ttm_resource_manager *man, struct ttm_resource *reg)39nouveau_manager_del(struct ttm_resource_manager *man,
40 struct ttm_resource *reg)
40{41{
41 nouveau_mem_del(reg);42 nouveau_mem_del(man, reg);
42}43}
43 44
44static int45static int
@@ -62,7 +63,7 @@ nouveau_vram_manager_new(struct ttm_resource_manager *man, · 17 unmodified lines
62 63
63 ret = nouveau_mem_vram(*res, nvbo->contig, nvbo->page);64 ret = nouveau_mem_vram(*res, nvbo->contig, nvbo->page);
64 if (ret) {65 if (ret) {
65 nouveau_mem_del(*res);66 nouveau_mem_del(man, *res);
66 return ret;67 return ret;
67 }68 }
68 69
@@ -118,7 +119,7 @@ nv04_gart_manager_new(struct ttm_resource_manager *man, · 49 unmodified lines
118 ret = nvif_vmm_get(&mem->cli->vmm.vmm, PTES, false, 12, 0,119 ret = nvif_vmm_get(&mem->cli->vmm.vmm, PTES, false, 12, 0,
119 (long)(*res)->num_pages << PAGE_SHIFT, &mem->vma[0]);120 (long)(*res)->num_pages << PAGE_SHIFT, &mem->vma[0]);
120 if (ret) {121 if (ret) {
121 nouveau_mem_del(*res);122 nouveau_mem_del(man, *res);
122 return ret;123 return ret;
123 }124 }
124 125
@@ -163,7 +164,7 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) · 38 unmodified lines
163 164
164 man->func = &nouveau_vram_manager;165 man->func = &nouveau_vram_manager;
165 166
166 ttm_resource_manager_init(man,167 ttm_resource_manager_init(man, &drm->ttm.bdev,
167 drm->gem.vram_available >> PAGE_SHIFT);168 drm->gem.vram_available >> PAGE_SHIFT);
168 ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, man);169 ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, man);
169 ttm_resource_manager_set_used(man, true);170 ttm_resource_manager_set_used(man, true);
@@ -210,7 +211,7 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) · 40 unmodified lines
210 211
211 man->func = func;212 man->func = func;
212 man->use_tt = true;213 man->use_tt = true;
213 ttm_resource_manager_init(man, size_pages);214 ttm_resource_manager_init(man, &drm->ttm.bdev, size_pages);
214 ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man);215 ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man);
215 ttm_resource_manager_set_used(man, true);216 ttm_resource_manager_set_used(man, true);
216 return 0;217 return 0;
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c+224−93
@@ -41,6 +41,10 @@ · 40 unmodified lines
41 41
42struct lt_state {42struct lt_state {
43 struct nvkm_dp *dp;43 struct nvkm_dp *dp;
44
45 int repeaters;
46 int repeater;
47
44 u8 stat[6];48 u8 stat[6];
45 u8 conf[4];49 u8 conf[4];
46 bool pc2;50 bool pc2;
@@ -52,14 +56,26 @@ static int · 5 unmodified lines
52nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay)56nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay)
53{57{
54 struct nvkm_dp *dp = lt->dp;58 struct nvkm_dp *dp = lt->dp;
59 u32 addr;
55 int ret;60 int ret;
56 61
57 if (dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL])62 usleep_range(delay, delay * 2);
58 mdelay(dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4);63
64 if (lt->repeater)
65 addr = DPCD_LTTPR_LANE0_1_STATUS(lt->repeater);
66 else
67 addr = DPCD_LS02;
68
69 ret = nvkm_rdaux(dp->aux, addr, &lt->stat[0], 3);
70 if (ret)
71 return ret;
72
73 if (lt->repeater)
74 addr = DPCD_LTTPR_LANE0_1_ADJUST(lt->repeater);
59 else75 else
60 udelay(delay);76 addr = DPCD_LS06;
61 77
62 ret = nvkm_rdaux(dp->aux, DPCD_LS02, lt->stat, 6);78 ret = nvkm_rdaux(dp->aux, addr, &lt->stat[4], 2);
63 if (ret)79 if (ret)
64 return ret;80 return ret;
65 81
@@ -85,6 +101,7 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) · 19 unmodified lines
85 struct nvbios_dpout info;101 struct nvbios_dpout info;
86 struct nvbios_dpcfg ocfg;102 struct nvbios_dpcfg ocfg;
87 u8 ver, hdr, cnt, len;103 u8 ver, hdr, cnt, len;
104 u32 addr;
88 u32 data;105 u32 data;
89 int ret, i;106 int ret, i;
90 107
@@ -113,6 +130,9 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) · 22 unmodified lines
113 OUTP_TRACE(&dp->outp, "config lane %d %02x %02x",130 OUTP_TRACE(&dp->outp, "config lane %d %02x %02x",
114 i, lt->conf[i], lpc2);131 i, lt->conf[i], lpc2);
115 132
133 if (lt->repeater != lt->repeaters)
134 continue;
135
116 data = nvbios_dpout_match(bios, dp->outp.info.hasht,136 data = nvbios_dpout_match(bios, dp->outp.info.hasht,
117 dp->outp.info.hashm,137 dp->outp.info.hashm,
118 &ver, &hdr, &cnt, &len, &info);138 &ver, &hdr, &cnt, &len, &info);
@@ -129,7 +149,12 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) · 10 unmodified lines
129 ocfg.pe, ocfg.tx_pu);149 ocfg.pe, ocfg.tx_pu);
130 }150 }
131 151
132 ret = nvkm_wraux(dp->aux, DPCD_LC03(0), lt->conf, 4);152 if (lt->repeater)
153 addr = DPCD_LTTPR_LANE0_SET(lt->repeater);
154 else
155 addr = DPCD_LC03(0);
156
157 ret = nvkm_wraux(dp->aux, addr, lt->conf, 4);
133 if (ret)158 if (ret)
134 return ret;159 return ret;
135 160
@@ -146,32 +171,59 @@ static void · 10 unmodified lines
146nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern)171nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern)
147{172{
148 struct nvkm_dp *dp = lt->dp;173 struct nvkm_dp *dp = lt->dp;
174 u32 addr;
149 u8 sink_tp;175 u8 sink_tp;
150 176
151 OUTP_TRACE(&dp->outp, "training pattern %d", pattern);177 OUTP_TRACE(&dp->outp, "training pattern %d", pattern);
152 dp->outp.ior->func->dp.pattern(dp->outp.ior, pattern);178 dp->outp.ior->func->dp.pattern(dp->outp.ior, pattern);
153 179
154 nvkm_rdaux(dp->aux, DPCD_LC02, &sink_tp, 1);180 if (lt->repeater)
181 addr = DPCD_LTTPR_PATTERN_SET(lt->repeater);
182 else
183 addr = DPCD_LC02;
184
185 nvkm_rdaux(dp->aux, addr, &sink_tp, 1);
155 sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET;186 sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET;
156 sink_tp |= pattern;187 sink_tp |= (pattern != 4) ? pattern : 7;
157 nvkm_wraux(dp->aux, DPCD_LC02, &sink_tp, 1);188
189 if (pattern != 0)
190 sink_tp |= DPCD_LC02_SCRAMBLING_DISABLE;
191 else
192 sink_tp &= ~DPCD_LC02_SCRAMBLING_DISABLE;
193 nvkm_wraux(dp->aux, addr, &sink_tp, 1);
158}194}
159 195
160static int196static int
161nvkm_dp_train_eq(struct lt_state *lt)197nvkm_dp_train_eq(struct lt_state *lt)
162{198{
199 struct nvkm_i2c_aux *aux = lt->dp->aux;
163 bool eq_done = false, cr_done = true;200 bool eq_done = false, cr_done = true;
164 int tries = 0, i;201 int tries = 0, usec = 0, i;
202 u8 data;
165 203
166 if (lt->dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED)204 if (lt->repeater) {
167 nvkm_dp_train_pattern(lt, 3);205 if (!nvkm_rdaux(aux, DPCD_LTTPR_AUX_RD_INTERVAL(lt->repeater), &data, sizeof(data)))
168 else206 usec = (data & DPCD_RC0E_AUX_RD_INTERVAL) * 4000;
169 nvkm_dp_train_pattern(lt, 2);207
208 nvkm_dp_train_pattern(lt, 4);
209 } else {
210 if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] >= 0x14 &&
211 lt->dp->dpcd[DPCD_RC03] & DPCD_RC03_TPS4_SUPPORTED)
212 nvkm_dp_train_pattern(lt, 4);
213 else
214 if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] >= 0x12 &&
215 lt->dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED)
216 nvkm_dp_train_pattern(lt, 3);
217 else
218 nvkm_dp_train_pattern(lt, 2);
219
220 usec = (lt->dp->dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000;
221 }
170 222
171 do {223 do {
172 if ((tries &&224 if ((tries &&
173 nvkm_dp_train_drive(lt, lt->pc2)) ||225 nvkm_dp_train_drive(lt, lt->pc2)) ||
174 nvkm_dp_train_sense(lt, lt->pc2, 400))226 nvkm_dp_train_sense(lt, lt->pc2, usec ? usec : 400))
175 break;227 break;
176 228
177 eq_done = !!(lt->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE);229 eq_done = !!(lt->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE);
@@ -193,13 +245,16 @@ nvkm_dp_train_cr(struct lt_state *lt) · 15 unmodified lines
193{245{
194 bool cr_done = false, abort = false;246 bool cr_done = false, abort = false;
195 int voltage = lt->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET;247 int voltage = lt->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET;
196 int tries = 0, i;248 int tries = 0, usec = 0, i;
197 249
198 nvkm_dp_train_pattern(lt, 1);250 nvkm_dp_train_pattern(lt, 1);
199 251
252 if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] < 0x14 && !lt->repeater)
253 usec = (lt->dp->dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000;
254
200 do {255 do {
201 if (nvkm_dp_train_drive(lt, false) ||256 if (nvkm_dp_train_drive(lt, false) ||
202 nvkm_dp_train_sense(lt, false, 100))257 nvkm_dp_train_sense(lt, false, usec ? usec : 100))
203 break;258 break;
204 259
205 cr_done = true;260 cr_done = true;
@@ -223,7 +278,7 @@ nvkm_dp_train_cr(struct lt_state *lt) · 17 unmodified lines
223}278}
224 279
225static int280static int
226nvkm_dp_train_links(struct nvkm_dp *dp)281nvkm_dp_train_links(struct nvkm_dp *dp, int rate)
227{282{
228 struct nvkm_ior *ior = dp->outp.ior;283 struct nvkm_ior *ior = dp->outp.ior;
229 struct nvkm_disp *disp = dp->outp.disp;284 struct nvkm_disp *disp = dp->outp.disp;
@@ -233,13 +288,15 @@ nvkm_dp_train_links(struct nvkm_dp *dp) · 3 unmodified lines
233 .dp = dp,288 .dp = dp,
234 };289 };
235 u32 lnkcmp;290 u32 lnkcmp;
236 u8 sink[2];291 u8 sink[2], data;
237 int ret;292 int ret;
238 293
239 OUTP_DBG(&dp->outp, "training %d x %d MB/s",294 OUTP_DBG(&dp->outp, "training %d x %d MB/s",
240 ior->dp.nr, ior->dp.bw * 27);295 ior->dp.nr, ior->dp.bw * 27);
241 296
242 /* Intersect misc. capabilities of the OR and sink. */297 /* Intersect misc. capabilities of the OR and sink. */
298 if (disp->engine.subdev.device->chipset < 0x110)
299 dp->dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED;
243 if (disp->engine.subdev.device->chipset < 0xd0)300 if (disp->engine.subdev.device->chipset < 0xd0)
244 dp->dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED;301 dp->dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED;
245 lt.pc2 = dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED;302 lt.pc2 = dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED;
@@ -287,8 +344,22 @@ nvkm_dp_train_links(struct nvkm_dp *dp) · 41 unmodified lines
287 344
288 ior->func->dp.power(ior, ior->dp.nr);345 ior->func->dp.power(ior, ior->dp.nr);
289 346
347 /* Select LTTPR non-transparent mode if we have a valid configuration,
348 * use transparent mode otherwise.
349 */
350 if (dp->lttpr[0] >= 0x14) {
351 data = DPCD_LTTPR_MODE_TRANSPARENT;
352 nvkm_wraux(dp->aux, DPCD_LTTPR_MODE, &data, sizeof(data));
353
354 if (dp->lttprs) {
355 data = DPCD_LTTPR_MODE_NON_TRANSPARENT;
356 nvkm_wraux(dp->aux, DPCD_LTTPR_MODE, &data, sizeof(data));
357 lt.repeaters = dp->lttprs;
358 }
359 }
360
290 /* Set desired link configuration on the sink. */361 /* Set desired link configuration on the sink. */
291 sink[0] = ior->dp.bw;362 sink[0] = (dp->rate[rate].dpcd < 0) ? ior->dp.bw : 0;
292 sink[1] = ior->dp.nr;363 sink[1] = ior->dp.nr;
293 if (ior->dp.ef)364 if (ior->dp.ef)
294 sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;365 sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;
@@ -297,12 +368,33 @@ nvkm_dp_train_links(struct nvkm_dp *dp) · 2 unmodified lines
297 if (ret)368 if (ret)
298 return ret;369 return ret;
299 370
371 if (dp->rate[rate].dpcd >= 0) {
372 ret = nvkm_rdaux(dp->aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0]));
373 if (ret)
374 return ret;
375
376 sink[0] &= ~DPCD_LC15_LINK_RATE_SET_MASK;
377 sink[0] |= dp->rate[rate].dpcd;
378
379 ret = nvkm_wraux(dp->aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0]));
380 if (ret)
381 return ret;
382 }
383
300 /* Attempt to train the link in this configuration. */384 /* Attempt to train the link in this configuration. */
301 memset(lt.stat, 0x00, sizeof(lt.stat));385 for (lt.repeater = lt.repeaters; lt.repeater >= 0; lt.repeater--) {
302 ret = nvkm_dp_train_cr(&lt);386 if (lt.repeater)
303 if (ret == 0)387 OUTP_DBG(&dp->outp, "training LTTPR%d", lt.repeater);
304 ret = nvkm_dp_train_eq(&lt);388 else
305 nvkm_dp_train_pattern(&lt, 0);389 OUTP_DBG(&dp->outp, "training sink");
390
391 memset(lt.stat, 0x00, sizeof(lt.stat));
392 ret = nvkm_dp_train_cr(&lt);
393 if (ret == 0)
394 ret = nvkm_dp_train_eq(&lt);
395 nvkm_dp_train_pattern(&lt, 0);
396 }
397
306 return ret;398 return ret;
307}399}
308 400
@@ -345,63 +437,13 @@ nvkm_dp_train_init(struct nvkm_dp *dp) · 36 unmodified lines
345 }437 }
346}438}
347 439
348static const struct dp_rates {
349 u32 rate;
350 u8 bw;
351 u8 nr;
352} nvkm_dp_rates[] = {
353 { 2160000, 0x14, 4 },
354 { 1080000, 0x0a, 4 },
355 { 1080000, 0x14, 2 },
356 { 648000, 0x06, 4 },
357 { 540000, 0x0a, 2 },
358 { 540000, 0x14, 1 },
359 { 324000, 0x06, 2 },
360 { 270000, 0x0a, 1 },
361 { 162000, 0x06, 1 },
362 {}
363};
364
365static int440static int
366nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps)441nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps)
367{442{
368 struct nvkm_ior *ior = dp->outp.ior;443 struct nvkm_ior *ior = dp->outp.ior;
369 const u8 sink_nr = dp->dpcd[DPCD_RC02] & DPCD_RC02_MAX_LANE_COUNT;444 int ret = -EINVAL, nr, rate;
370 const u8 sink_bw = dp->dpcd[DPCD_RC01_MAX_LINK_RATE];
371 const u8 outp_nr = dp->outp.info.dpconf.link_nr;
372 const u8 outp_bw = dp->outp.info.dpconf.link_bw;
373 const struct dp_rates *failsafe = NULL, *cfg;
374 int ret = -EINVAL;
375 u8 pwr;445 u8 pwr;
376 446
377 /* Find the lowest configuration of the OR that can support
378 * the required link rate.
379 *
380 * We will refuse to program the OR to lower rates, even if
381 * link training fails at higher rates (or even if the sink
382 * can't support the rate at all, though the DD is supposed
383 * to prevent such situations from happening).
384 *
385 * Attempting to do so can cause the entire display to hang,
386 * and it's better to have a failed modeset than that.
387 */
388 for (cfg = nvkm_dp_rates; cfg->rate; cfg++) {
389 if (cfg->nr <= outp_nr && cfg->bw <= outp_bw) {
390 /* Try to respect sink limits too when selecting
391 * lowest link configuration.
392 */
393 if (!failsafe ||
394 (cfg->nr <= sink_nr && cfg->bw <= sink_bw))
395 failsafe = cfg;
396 }
397
398 if (failsafe && cfg[1].rate < dataKBps)
399 break;
400 }
401
402 if (WARN_ON(!failsafe))
403 return ret;
404
405 /* Ensure sink is not in a low-power state. */447 /* Ensure sink is not in a low-power state. */
406 if (!nvkm_rdaux(dp->aux, DPCD_SC00, &pwr, 1)) {448 if (!nvkm_rdaux(dp->aux, DPCD_SC00, &pwr, 1)) {
407 if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {449 if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
@@ -411,25 +453,22 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps) · 3 unmodified lines
411 }453 }
412 }454 }
413 455
456 ior->dp.mst = dp->lt.mst;
457 ior->dp.ef = dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP;
458 ior->dp.nr = 0;
459
414 /* Link training. */460 /* Link training. */
415 OUTP_DBG(&dp->outp, "training (min: %d x %d MB/s)",461 OUTP_DBG(&dp->outp, "training");
416 failsafe->nr, failsafe->bw * 27);
417 nvkm_dp_train_init(dp);462 nvkm_dp_train_init(dp);
418 for (cfg = nvkm_dp_rates; ret < 0 && cfg <= failsafe; cfg++) {463 for (nr = dp->links; ret < 0 && nr; nr >>= 1) {
419 /* Skip configurations not supported by both OR and sink. */464 for (rate = 0; ret < 0 && rate < dp->rates; rate++) {
420 if ((cfg->nr > outp_nr || cfg->bw > outp_bw ||465 if (dp->rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) {
421 cfg->nr > sink_nr || cfg->bw > sink_bw)) {466 /* Program selected link configuration. */
422 if (cfg != failsafe)467 ior->dp.bw = dp->rate[rate].rate / 27000;
423 continue;468 ior->dp.nr = nr;
424 OUTP_ERR(&dp->outp, "link rate unsupported by sink");469 ret = nvkm_dp_train_links(dp, rate);
470 }
425 }471 }
426 ior->dp.mst = dp->lt.mst;
427 ior->dp.ef = dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP;
428 ior->dp.bw = cfg->bw;
429 ior->dp.nr = cfg->nr;
430
431 /* Program selected link configuration. */
432 ret = nvkm_dp_train_links(dp);
433 }472 }
434 nvkm_dp_train_fini(dp);473 nvkm_dp_train_fini(dp);
435 if (ret < 0)474 if (ret < 0)
@@ -526,6 +565,47 @@ done: · 90 unmodified lines
526 return ret;565 return ret;
527}566}
528 567
568static bool
569nvkm_dp_enable_supported_link_rates(struct nvkm_dp *dp)
570{
571 u8 sink_rates[DPCD_RC10_SUPPORTED_LINK_RATES__SIZE];
572 int i, j, k;
573
574 if (dp->outp.conn->info.type != DCB_CONNECTOR_eDP ||
575 dp->dpcd[DPCD_RC00_DPCD_REV] < 0x13 ||
576 nvkm_rdaux(dp->aux, DPCD_RC10_SUPPORTED_LINK_RATES(0), sink_rates, sizeof(sink_rates)))
577 return false;
578
579 for (i = 0; i < ARRAY_SIZE(sink_rates); i += 2) {
580 const u32 rate = ((sink_rates[i + 1] << 8) | sink_rates[i]) * 200 / 10;
581
582 if (!rate || WARN_ON(dp->rates == ARRAY_SIZE(dp->rate)))
583 break;
584
585 if (rate > dp->outp.info.dpconf.link_bw * 27000) {
586 OUTP_DBG(&dp->outp, "rate %d !outp", rate);
587 continue;
588 }
589
590 for (j = 0; j < dp->rates; j++) {
591 if (rate > dp->rate[j].rate) {
592 for (k = dp->rates; k > j; k--)
593 dp->rate[k] = dp->rate[k - 1];
594 break;
595 }
596 }
597
598 dp->rate[j].dpcd = i / 2;
599 dp->rate[j].rate = rate;
600 dp->rates++;
601 }
602
603 for (i = 0; i < dp->rates; i++)
604 OUTP_DBG(&dp->outp, "link_rate[%d] = %d", dp->rate[i].dpcd, dp->rate[i].rate);
605
606 return dp->rates != 0;
607}
608
529static bool609static bool
530nvkm_dp_enable(struct nvkm_dp *dp, bool enable)610nvkm_dp_enable(struct nvkm_dp *dp, bool enable)
531{611{
@@ -538,9 +618,60 @@ nvkm_dp_enable(struct nvkm_dp *dp, bool enable) · 6 unmodified lines
538 dp->present = true;618 dp->present = true;
539 }619 }
540 620
541 if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, dp->dpcd,621 /* Detect any LTTPRs before reading DPCD receiver caps. */
542 sizeof(dp->dpcd)))622 if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, dp->lttpr, sizeof(dp->lttpr)) &&
623 dp->lttpr[0] >= 0x14 && dp->lttpr[2]) {
624 switch (dp->lttpr[2]) {
625 case 0x80: dp->lttprs = 1; break;
626 case 0x40: dp->lttprs = 2; break;
627 case 0x20: dp->lttprs = 3; break;
628 case 0x10: dp->lttprs = 4; break;
629 case 0x08: dp->lttprs = 5; break;
630 case 0x04: dp->lttprs = 6; break;
631 case 0x02: dp->lttprs = 7; break;
632 case 0x01: dp->lttprs = 8; break;
633 default:
634 /* Unknown LTTPR count, we'll switch to transparent mode. */
635 WARN_ON(1);
636 dp->lttprs = 0;
637 break;
638 }
639 } else {
640 /* No LTTPR support, or zero LTTPR count - don't touch it at all. */
641 memset(dp->lttpr, 0x00, sizeof(dp->lttpr));
642 }
643
644 if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, dp->dpcd, sizeof(dp->dpcd))) {
645 const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 };
646 const u8 *rate;
647 int rate_max;
648
649 dp->rates = 0;
650 dp->links = dp->dpcd[DPCD_RC02] & DPCD_RC02_MAX_LANE_COUNT;
651 dp->links = min(dp->links, dp->outp.info.dpconf.link_nr);
652 if (dp->lttprs && dp->lttpr[4])
653 dp->links = min_t(int, dp->links, dp->lttpr[4]);
654
655 rate_max = dp->dpcd[DPCD_RC01_MAX_LINK_RATE];
656 rate_max = min(rate_max, dp->outp.info.dpconf.link_bw);
657 if (dp->lttprs && dp->lttpr[1])
658 rate_max = min_t(int, rate_max, dp->lttpr[1]);
659
660 if (!nvkm_dp_enable_supported_link_rates(dp)) {
661 for (rate = rates; *rate; rate++) {
662 if (*rate <= rate_max) {
663 if (WARN_ON(dp->rates == ARRAY_SIZE(dp->rate)))
664 break;
665
666 dp->rate[dp->rates].dpcd = -1;
667 dp->rate[dp->rates].rate = *rate * 27000;
668 dp->rates++;
669 }
670 }
671 }
672
543 return true;673 return true;
674 }
544 }675 }
545 676
546 if (dp->present) {677 if (dp->present) {
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h+29−6
@@ -9,10 +9,7 @@ · 8 unmodified lines
9#include <subdev/bios/dp.h>9#include <subdev/bios/dp.h>
10 10
11struct nvkm_dp {11struct nvkm_dp {
12 union {12 struct nvkm_outp outp;
13 struct nvkm_outp base;
14 struct nvkm_outp outp;
15 };
16 13
17 struct nvbios_dpout info;14 struct nvbios_dpout info;
18 u8 version;15 u8 version;
@@ -21,8 +18,17 @@ struct nvkm_dp { · 2 unmodified lines
21 18
22 struct nvkm_notify hpd;19 struct nvkm_notify hpd;
23 bool present;20 bool present;
21 u8 lttpr[6];
22 u8 lttprs;
24 u8 dpcd[16];23 u8 dpcd[16];
25 24
25 struct {
26 int dpcd; /* -1, or index into SUPPORTED_LINK_RATES table */
27 u32 rate;
28 } rate[8];
29 int rates;
30 int links;
31
26 struct mutex mutex;32 struct mutex mutex;
27 struct {33 struct {
28 atomic_t done;34 atomic_t done;
@@ -42,8 +48,12 @@ void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *); · 13 unmodified lines
42#define DPCD_RC02_TPS3_SUPPORTED 0x4048#define DPCD_RC02_TPS3_SUPPORTED 0x40
43#define DPCD_RC02_MAX_LANE_COUNT 0x1f49#define DPCD_RC02_MAX_LANE_COUNT 0x1f
44#define DPCD_RC03 0x0000350#define DPCD_RC03 0x00003
51#define DPCD_RC03_TPS4_SUPPORTED 0x80
45#define DPCD_RC03_MAX_DOWNSPREAD 0x0152#define DPCD_RC03_MAX_DOWNSPREAD 0x01
46#define DPCD_RC0E_AUX_RD_INTERVAL 0x0000e53#define DPCD_RC0E 0x0000e
54#define DPCD_RC0E_AUX_RD_INTERVAL 0x7f
55#define DPCD_RC10_SUPPORTED_LINK_RATES(i) 0x00010
56#define DPCD_RC10_SUPPORTED_LINK_RATES__SIZE 16
47 57
48/* DPCD Link Configuration */58/* DPCD Link Configuration */
49#define DPCD_LC00_LINK_BW_SET 0x0010059#define DPCD_LC00_LINK_BW_SET 0x00100
@@ -51,7 +61,8 @@ void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *); · 1 unmodified line
51#define DPCD_LC01_ENHANCED_FRAME_EN 0x8061#define DPCD_LC01_ENHANCED_FRAME_EN 0x80
52#define DPCD_LC01_LANE_COUNT_SET 0x1f62#define DPCD_LC01_LANE_COUNT_SET 0x1f
53#define DPCD_LC02 0x0010263#define DPCD_LC02 0x00102
54#define DPCD_LC02_TRAINING_PATTERN_SET 0x0364#define DPCD_LC02_TRAINING_PATTERN_SET 0x0f
65#define DPCD_LC02_SCRAMBLING_DISABLE 0x20
55#define DPCD_LC03(l) ((l) + 0x00103)66#define DPCD_LC03(l) ((l) + 0x00103)
56#define DPCD_LC03_MAX_PRE_EMPHASIS_REACHED 0x2067#define DPCD_LC03_MAX_PRE_EMPHASIS_REACHED 0x20
57#define DPCD_LC03_PRE_EMPHASIS_SET 0x1868#define DPCD_LC03_PRE_EMPHASIS_SET 0x18
@@ -67,6 +78,8 @@ void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *); · 9 unmodified lines
67#define DPCD_LC10_LANE3_POST_CURSOR2_SET 0x3078#define DPCD_LC10_LANE3_POST_CURSOR2_SET 0x30
68#define DPCD_LC10_LANE2_MAX_POST_CURSOR2_REACHED 0x0479#define DPCD_LC10_LANE2_MAX_POST_CURSOR2_REACHED 0x04
69#define DPCD_LC10_LANE2_POST_CURSOR2_SET 0x0380#define DPCD_LC10_LANE2_POST_CURSOR2_SET 0x03
81#define DPCD_LC15_LINK_RATE_SET 0x00115
82#define DPCD_LC15_LINK_RATE_SET_MASK 0x07
70 83
71/* DPCD Link/Sink Status */84/* DPCD Link/Sink Status */
72#define DPCD_LS02 0x0020285#define DPCD_LS02 0x00202
@@ -108,4 +121,14 @@ void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *); · 35 unmodified lines
108#define DPCD_SC00_SET_POWER 0x03121#define DPCD_SC00_SET_POWER 0x03
109#define DPCD_SC00_SET_POWER_D0 0x01122#define DPCD_SC00_SET_POWER_D0 0x01
110#define DPCD_SC00_SET_POWER_D3 0x03123#define DPCD_SC00_SET_POWER_D3 0x03
124
125#define DPCD_LTTPR_REV 0xf0000
126#define DPCD_LTTPR_MODE 0xf0003
127#define DPCD_LTTPR_MODE_TRANSPARENT 0x55
128#define DPCD_LTTPR_MODE_NON_TRANSPARENT 0xaa
129#define DPCD_LTTPR_PATTERN_SET(i) ((i - 1) * 0x50 + 0xf0010)
130#define DPCD_LTTPR_LANE0_SET(i) ((i - 1) * 0x50 + 0xf0011)
131#define DPCD_LTTPR_AUX_RD_INTERVAL(i) ((i - 1) * 0x50 + 0xf0020)
132#define DPCD_LTTPR_LANE0_1_STATUS(i) ((i - 1) * 0x50 + 0xf0030)
133#define DPCD_LTTPR_LANE0_1_ADJUST(i) ((i - 1) * 0x50 + 0xf0033)
111#endif134#endif
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c+12−1
@@ -77,7 +77,18 @@ g94_sor_dp_pattern(struct nvkm_ior *sor, int pattern) · 76 unmodified lines
77{77{
78 struct nvkm_device *device = sor->disp->engine.subdev.device;78 struct nvkm_device *device = sor->disp->engine.subdev.device;
79 const u32 loff = nv50_sor_link(sor);79 const u32 loff = nv50_sor_link(sor);
80 nvkm_mask(device, 0x61c10c + loff, 0x0f000000, pattern << 24);80 u32 data;
81
82 switch (pattern) {
83 case 0: data = 0x00001000; break;
84 case 1: data = 0x01000000; break;
85 case 2: data = 0x02000000; break;
86 default:
87 WARN_ON(1);
88 return;
89 }
90
91 nvkm_mask(device, 0x61c10c + loff, 0x0f001000, data);
81}92}
82 93
83void94void
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c+4−0
@@ -37,6 +37,10 @@ ga102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) · 36 unmodified lines
37 case 0x0a: clksor |= 0x00040000; break;37 case 0x0a: clksor |= 0x00040000; break;
38 case 0x14: clksor |= 0x00080000; break;38 case 0x14: clksor |= 0x00080000; break;
39 case 0x1e: clksor |= 0x000c0000; break;39 case 0x1e: clksor |= 0x000c0000; break;
40 case 0x08: clksor |= 0x00100000; break;
41 case 0x09: clksor |= 0x00140000; break;
42 case 0x0c: clksor |= 0x00180000; break;
43 case 0x10: clksor |= 0x001c0000; break;
40 default:44 default:
41 WARN_ON(1);45 WARN_ON(1);
42 return -EINVAL;46 return -EINVAL;
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c+13−1
@@ -92,7 +92,19 @@ gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern) · 91 unmodified lines
92{92{
93 struct nvkm_device *device = sor->disp->engine.subdev.device;93 struct nvkm_device *device = sor->disp->engine.subdev.device;
94 const u32 soff = nv50_ior_base(sor);94 const u32 soff = nv50_ior_base(sor);
95 nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, 0x01010101 * pattern);95 u32 data;
96
97 switch (pattern) {
98 case 0: data = 0x10101010; break;
99 case 1: data = 0x01010101; break;
100 case 2: data = 0x02020202; break;
101 case 3: data = 0x03030303; break;
102 default:
103 WARN_ON(1);
104 return;
105 }
106
107 nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data);
96}108}
97 109
98int110int
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c+15−3
@@ -28,11 +28,23 @@ gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern) · 27 unmodified lines
28{28{
29 struct nvkm_device *device = sor->disp->engine.subdev.device;29 struct nvkm_device *device = sor->disp->engine.subdev.device;
30 const u32 soff = nv50_ior_base(sor);30 const u32 soff = nv50_ior_base(sor);
31 const u32 data = 0x01010101 * pattern;31 u32 mask = 0x1f1f1f1f, data;
32
33 switch (pattern) {
34 case 0: data = 0x10101010; break;
35 case 1: data = 0x01010101; break;
36 case 2: data = 0x02020202; break;
37 case 3: data = 0x03030303; break;
38 case 4: data = 0x1b1b1b1b; break;
39 default:
40 WARN_ON(1);
41 return;
42 }
43
32 if (sor->asy.link & 1)44 if (sor->asy.link & 1)
33 nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);45 nvkm_mask(device, 0x61c110 + soff, mask, data);
34 else46 else
35 nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);47 nvkm_mask(device, 0x61c12c + soff, mask, data);
36}48}
37 49
38static const struct nvkm_ior_func50static const struct nvkm_ior_func
drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c+5−4
@@ -142,11 +142,12 @@ nvkm_acr_hsfw_load_bl(struct nvkm_acr *acr, const char *name, int ver, · 141 unmodified lines
142 142
143 hsfw->imem_size = desc->code_size;143 hsfw->imem_size = desc->code_size;
144 hsfw->imem_tag = desc->start_tag;144 hsfw->imem_tag = desc->start_tag;
145 hsfw->imem = kmalloc(desc->code_size, GFP_KERNEL);145 hsfw->imem = kmemdup(data + desc->code_off, desc->code_size, GFP_KERNEL);
146 memcpy(hsfw->imem, data + desc->code_off, desc->code_size);
147
148 nvkm_firmware_put(fw);146 nvkm_firmware_put(fw);
149 return 0;147 if (!hsfw->imem)
148 return -ENOMEM;
149 else
150 return 0;
150}151}
151 152
152int153int
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c+1−0
@@ -93,6 +93,7 @@ struct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags) · 92 unmodified lines
93 exp_info.size = omap_gem_mmap_size(obj);93 exp_info.size = omap_gem_mmap_size(obj);
94 exp_info.flags = flags;94 exp_info.flags = flags;
95 exp_info.priv = obj;95 exp_info.priv = obj;
96 exp_info.resv = obj->resv;
96 97
97 return drm_gem_dmabuf_export(obj->dev, &exp_info);98 return drm_gem_dmabuf_export(obj->dev, &exp_info);
98}99}
drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c+4−4
@@ -86,7 +86,7 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { · 85 unmodified lines
86 _INIT_DCS_CMD(0x0F, 0x73),86 _INIT_DCS_CMD(0x0F, 0x73),
87 _INIT_DCS_CMD(0x95, 0xE6),87 _INIT_DCS_CMD(0x95, 0xE6),
88 _INIT_DCS_CMD(0x96, 0xF0),88 _INIT_DCS_CMD(0x96, 0xF0),
89 _INIT_DCS_CMD(0x30, 0x11),89 _INIT_DCS_CMD(0x30, 0x00),
90 _INIT_DCS_CMD(0x6D, 0x66),90 _INIT_DCS_CMD(0x6D, 0x66),
91 _INIT_DCS_CMD(0x75, 0xA2),91 _INIT_DCS_CMD(0x75, 0xA2),
92 _INIT_DCS_CMD(0x77, 0x3B),92 _INIT_DCS_CMD(0x77, 0x3B),
@@ -112,17 +112,17 @@ static const struct panel_init_cmd boe_tv110c9m_init_cmd[] = { · 19 unmodified lines
112 _INIT_DCS_CMD(0xB1, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),112 _INIT_DCS_CMD(0xB1, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
113 _INIT_DCS_CMD(0xB2, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),113 _INIT_DCS_CMD(0xB2, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
114 114
115 _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xA7, 0x03, 0xCF, 0x03, 0xDE, 0x03, 0xE0),115 _INIT_DCS_CMD(0xB3, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
116 _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),116 _INIT_DCS_CMD(0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
117 _INIT_DCS_CMD(0xB5, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),117 _INIT_DCS_CMD(0xB5, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
118 _INIT_DCS_CMD(0xB6, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),118 _INIT_DCS_CMD(0xB6, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
119 _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xA7, 0x03, 0xCF, 0x03, 0xDE, 0x03, 0xE0),119 _INIT_DCS_CMD(0xB7, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
120 120
121 _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),121 _INIT_DCS_CMD(0xB8, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x00, 0x99, 0x00, 0xAE, 0x00, 0xC1),
122 _INIT_DCS_CMD(0xB9, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),122 _INIT_DCS_CMD(0xB9, 0x00, 0xD2, 0x01, 0x0B, 0x01, 0x34, 0x01, 0x76, 0x01, 0xA3, 0x01, 0xEF, 0x02, 0x27, 0x02, 0x29),
123 _INIT_DCS_CMD(0xBA, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),123 _INIT_DCS_CMD(0xBA, 0x02, 0x5F, 0x02, 0x9E, 0x02, 0xC9, 0x03, 0x00, 0x03, 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73),
124 124
125 _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xA7, 0x03, 0xCF, 0x03, 0xDE, 0x03, 0xE0),125 _INIT_DCS_CMD(0xBB, 0x03, 0x86, 0x03, 0x9A, 0x03, 0xAF, 0x03, 0xDF, 0x03, 0xF5, 0x03, 0xE0),
126 _INIT_DCS_CMD(0xFF, 0x24),126 _INIT_DCS_CMD(0xFF, 0x24),
127 _INIT_DCS_CMD(0xFB, 0x01),127 _INIT_DCS_CMD(0xFB, 0x01),
128 128
drivers/gpu/drm/panel/panel-edp.c+19−2
@@ -36,8 +36,8 @@ · 35 unmodified lines
36 36
37#include <drm/drm_crtc.h>37#include <drm/drm_crtc.h>
38#include <drm/drm_device.h>38#include <drm/drm_device.h>
39#include <drm/drm_dp_aux_bus.h>39#include <drm/dp/drm_dp_aux_bus.h>
40#include <drm/drm_dp_helper.h>40#include <drm/dp/drm_dp_helper.h>
41#include <drm/drm_panel.h>41#include <drm/drm_panel.h>
42 42
43/**43/**
@@ -1745,6 +1745,19 @@ static const struct panel_delay delay_200_500_e50 = { · 1701 unmodified lines
1745 .enable = 50,1745 .enable = 50,
1746};1746};
1747 1747
1748static const struct panel_delay delay_200_500_e80_d50 = {
1749 .hpd_absent = 200,
1750 .unprepare = 500,
1751 .enable = 80,
1752 .disable = 50,
1753};
1754
1755static const struct panel_delay delay_100_500_e200 = {
1756 .hpd_absent = 100,
1757 .unprepare = 500,
1758 .enable = 200,
1759};
1760
1748#define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \1761#define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \
1749{ \1762{ \
1750 .name = _name, \1763 .name = _name, \
@@ -1768,13 +1781,17 @@ static const struct edp_panel_entry edp_panels[] = { · 17 unmodified lines
1768 EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"),1781 EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"),
1769 EDP_PANEL_ENTRY('B', 'O', 'E', 0x082d, &boe_nv133fhm_n61.delay, "NV133FHM-N62"),1782 EDP_PANEL_ENTRY('B', 'O', 'E', 0x082d, &boe_nv133fhm_n61.delay, "NV133FHM-N62"),
1770 EDP_PANEL_ENTRY('B', 'O', 'E', 0x098d, &boe_nv110wtm_n61.delay, "NV110WTM-N61"),1783 EDP_PANEL_ENTRY('B', 'O', 'E', 0x098d, &boe_nv110wtm_n61.delay, "NV110WTM-N61"),
1784 EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"),
1771 1785
1772 EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"),1786 EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"),
1773 1787
1774 EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),1788 EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
1789 EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
1775 1790
1776 EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"),1791 EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"),
1777 1792
1793 EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"),
1794
1778 { /* sentinal */ }1795 { /* sentinal */ }
1779};1796};
1780 1797
drivers/gpu/drm/panel/panel-samsung-atna33xc20.c+2−2
@@ -14,8 +14,8 @@ · 13 unmodified lines
14#include <linux/pm_runtime.h>14#include <linux/pm_runtime.h>
15#include <linux/regulator/consumer.h>15#include <linux/regulator/consumer.h>
16 16
17#include <drm/drm_dp_aux_bus.h>17#include <drm/dp/drm_dp_aux_bus.h>
18#include <drm/drm_dp_helper.h>18#include <drm/dp/drm_dp_helper.h>
19#include <drm/drm_edid.h>19#include <drm/drm_edid.h>
20#include <drm/drm_panel.h>20#include <drm/drm_panel.h>
21 21
drivers/gpu/drm/panel/panel-simple.c+33−0
@@ -2525,6 +2525,36 @@ static const struct panel_desc mitsubishi_aa070mc01 = { · 2524 unmodified lines
2525 .bus_flags = DRM_BUS_FLAG_DE_HIGH,2525 .bus_flags = DRM_BUS_FLAG_DE_HIGH,
2526};2526};
2527 2527
2528static const struct display_timing multi_inno_mi0700s4t_6_timing = {
2529 .pixelclock = { 29000000, 33000000, 38000000 },
2530 .hactive = { 800, 800, 800 },
2531 .hfront_porch = { 180, 210, 240 },
2532 .hback_porch = { 16, 16, 16 },
2533 .hsync_len = { 30, 30, 30 },
2534 .vactive = { 480, 480, 480 },
2535 .vfront_porch = { 12, 22, 32 },
2536 .vback_porch = { 10, 10, 10 },
2537 .vsync_len = { 13, 13, 13 },
2538 .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
2539 DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
2540 DISPLAY_FLAGS_SYNC_POSEDGE,
2541};
2542
2543static const struct panel_desc multi_inno_mi0700s4t_6 = {
2544 .timings = &multi_inno_mi0700s4t_6_timing,
2545 .num_timings = 1,
2546 .bpc = 8,
2547 .size = {
2548 .width = 154,
2549 .height = 86,
2550 },
2551 .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
2552 .bus_flags = DRM_BUS_FLAG_DE_HIGH |
2553 DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
2554 DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE,
2555 .connector_type = DRM_MODE_CONNECTOR_DPI,
2556};
2557
2528static const struct display_timing multi_inno_mi1010ait_1cp_timing = {2558static const struct display_timing multi_inno_mi1010ait_1cp_timing = {
2529 .pixelclock = { 68900000, 70000000, 73400000 },2559 .pixelclock = { 68900000, 70000000, 73400000 },
2530 .hactive = { 1280, 1280, 1280 },2560 .hactive = { 1280, 1280, 1280 },
@@ -3871,6 +3901,9 @@ static const struct of_device_id platform_of_match[] = { · 1340 unmodified lines
3871 }, {3901 }, {
3872 .compatible = "mitsubishi,aa070mc01-ca1",3902 .compatible = "mitsubishi,aa070mc01-ca1",
3873 .data = &mitsubishi_aa070mc01,3903 .data = &mitsubishi_aa070mc01,
3904 }, {
3905 .compatible = "multi-inno,mi0700s4t-6",
3906 .data = &multi_inno_mi0700s4t_6,
3874 }, {3907 }, {
3875 .compatible = "multi-inno,mi1010ait-1cp",3908 .compatible = "multi-inno,mi1010ait-1cp",
3876 .data = &multi_inno_mi1010ait_1cp,3909 .data = &multi_inno_mi1010ait_1cp,
drivers/gpu/drm/panfrost/panfrost_features.h+7−205
@@ -12,24 +12,6 @@ enum panfrost_hw_feature { · 11 unmodified lines
12 HW_FEATURE_JOBCHAIN_DISAMBIGUATION,12 HW_FEATURE_JOBCHAIN_DISAMBIGUATION,
13 HW_FEATURE_PWRON_DURING_PWROFF_TRANS,13 HW_FEATURE_PWRON_DURING_PWROFF_TRANS,
14 HW_FEATURE_XAFFINITY,14 HW_FEATURE_XAFFINITY,
15 HW_FEATURE_OUT_OF_ORDER_EXEC,
16 HW_FEATURE_MRT,
17 HW_FEATURE_BRNDOUT_CC,
18 HW_FEATURE_INTERPIPE_REG_ALIASING,
19 HW_FEATURE_LD_ST_TILEBUFFER,
20 HW_FEATURE_MSAA_16X,
21 HW_FEATURE_32_BIT_UNIFORM_ADDRESS,
22 HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL,
23 HW_FEATURE_OPTIMIZED_COVERAGE_MASK,
24 HW_FEATURE_T7XX_PAIRING_RULES,
25 HW_FEATURE_LD_ST_LEA_TEX,
26 HW_FEATURE_LINEAR_FILTER_FLOAT,
27 HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4,
28 HW_FEATURE_IMAGES_IN_FRAGMENT_SHADERS,
29 HW_FEATURE_TEST4_DATUM_MODE,
30 HW_FEATURE_NEXT_INSTRUCTION_TYPE,
31 HW_FEATURE_BRNDOUT_KILL,
32 HW_FEATURE_WARPING,
33 HW_FEATURE_V4,15 HW_FEATURE_V4,
34 HW_FEATURE_FLUSH_REDUCTION,16 HW_FEATURE_FLUSH_REDUCTION,
35 HW_FEATURE_PROTECTED_MODE,17 HW_FEATURE_PROTECTED_MODE,
@@ -42,128 +24,31 @@ enum panfrost_hw_feature { · 6 unmodified lines
42};24};
43 25
44#define hw_features_t600 (\26#define hw_features_t600 (\
45 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
46 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
47 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \27 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
48 BIT_ULL(HW_FEATURE_V4))28 BIT_ULL(HW_FEATURE_V4))
49 29
50#define hw_features_t620 (\30#define hw_features_t620 hw_features_t600
51 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
52 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
53 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
54 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
55 BIT_ULL(HW_FEATURE_V4))
56
57#define hw_features_t720 (\
58 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
59 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
60 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
61 BIT_ULL(HW_FEATURE_OPTIMIZED_COVERAGE_MASK) | \
62 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
63 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
64 BIT_ULL(HW_FEATURE_WORKGROUP_ROUND_MULTIPLE_OF_4) | \
65 BIT_ULL(HW_FEATURE_WARPING) | \
66 BIT_ULL(HW_FEATURE_V4))
67 31
32#define hw_features_t720 hw_features_t600
68 33
69#define hw_features_t760 (\34#define hw_features_t760 (\
70 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \35 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
71 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \36 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
72 BIT_ULL(HW_FEATURE_XAFFINITY) | \37 BIT_ULL(HW_FEATURE_XAFFINITY) | \
73 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
74 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
75 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
76 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
77 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
78 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
79 BIT_ULL(HW_FEATURE_MRT) | \
80 BIT_ULL(HW_FEATURE_MSAA_16X) | \
81 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
82 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
83 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
84 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT))38 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT))
85 39
86// T86040#define hw_features_t860 hw_features_t760
87#define hw_features_t860 (\
88 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
89 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
90 BIT_ULL(HW_FEATURE_XAFFINITY) | \
91 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
92 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
93 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
94 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
95 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
96 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
97 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
98 BIT_ULL(HW_FEATURE_MRT) | \
99 BIT_ULL(HW_FEATURE_MSAA_16X) | \
100 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
101 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
102 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
103 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
104 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT))
105 41
106#define hw_features_t880 hw_features_t86042#define hw_features_t880 hw_features_t760
107 43
108#define hw_features_t830 (\44#define hw_features_t830 hw_features_t760
109 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
110 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
111 BIT_ULL(HW_FEATURE_XAFFINITY) | \
112 BIT_ULL(HW_FEATURE_WARPING) | \
113 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
114 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
115 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
116 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
117 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
118 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
119 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
120 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
121 BIT_ULL(HW_FEATURE_MRT) | \
122 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
123 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
124 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
125 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
126 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT))
127 45
128#define hw_features_t820 (\46#define hw_features_t820 hw_features_t760
129 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
130 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
131 BIT_ULL(HW_FEATURE_XAFFINITY) | \
132 BIT_ULL(HW_FEATURE_WARPING) | \
133 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
134 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
135 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
136 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
137 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
138 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
139 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
140 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
141 BIT_ULL(HW_FEATURE_MRT) | \
142 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
143 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
144 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
145 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
146 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT))
147 47
148#define hw_features_g71 (\48#define hw_features_g71 (\
149 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \49 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
150 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \50 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
151 BIT_ULL(HW_FEATURE_XAFFINITY) | \51 BIT_ULL(HW_FEATURE_XAFFINITY) | \
152 BIT_ULL(HW_FEATURE_WARPING) | \
153 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
154 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
155 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
156 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
157 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
158 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
159 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
160 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
161 BIT_ULL(HW_FEATURE_MRT) | \
162 BIT_ULL(HW_FEATURE_MSAA_16X) | \
163 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
164 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
165 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
166 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
167 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \52 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
168 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \53 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
169 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \54 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
@@ -173,71 +58,18 @@ enum panfrost_hw_feature { · 3 unmodified lines
173 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \58 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
174 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \59 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
175 BIT_ULL(HW_FEATURE_XAFFINITY) | \60 BIT_ULL(HW_FEATURE_XAFFINITY) | \
176 BIT_ULL(HW_FEATURE_WARPING) | \
177 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
178 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
179 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
180 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
181 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
182 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
183 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
184 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
185 BIT_ULL(HW_FEATURE_MRT) | \
186 BIT_ULL(HW_FEATURE_MSAA_16X) | \
187 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
188 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
189 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
190 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
191 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \61 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
192 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \62 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
193 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \63 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
194 BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \64 BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
195 BIT_ULL(HW_FEATURE_COHERENCY_REG))65 BIT_ULL(HW_FEATURE_COHERENCY_REG))
196 66
197#define hw_features_g51 (\67#define hw_features_g51 hw_features_g72
198 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
199 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
200 BIT_ULL(HW_FEATURE_XAFFINITY) | \
201 BIT_ULL(HW_FEATURE_WARPING) | \
202 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
203 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
204 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
205 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
206 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
207 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
208 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
209 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
210 BIT_ULL(HW_FEATURE_MRT) | \
211 BIT_ULL(HW_FEATURE_MSAA_16X) | \
212 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
213 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
214 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
215 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
216 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
217 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
218 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
219 BIT_ULL(HW_FEATURE_PROTECTED_DEBUG_MODE) | \
220 BIT_ULL(HW_FEATURE_COHERENCY_REG))
221 68
222#define hw_features_g52 (\69#define hw_features_g52 (\
223 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \70 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
224 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \71 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
225 BIT_ULL(HW_FEATURE_XAFFINITY) | \72 BIT_ULL(HW_FEATURE_XAFFINITY) | \
226 BIT_ULL(HW_FEATURE_WARPING) | \
227 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
228 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
229 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
230 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
231 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
232 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
233 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
234 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
235 BIT_ULL(HW_FEATURE_MRT) | \
236 BIT_ULL(HW_FEATURE_MSAA_16X) | \
237 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
238 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
239 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
240 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
241 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \73 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
242 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \74 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
243 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \75 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
@@ -248,21 +80,6 @@ enum panfrost_hw_feature { · 4 unmodified lines
248 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \80 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
249 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \81 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
250 BIT_ULL(HW_FEATURE_XAFFINITY) | \82 BIT_ULL(HW_FEATURE_XAFFINITY) | \
251 BIT_ULL(HW_FEATURE_WARPING) | \
252 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
253 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
254 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
255 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
256 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
257 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
258 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
259 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
260 BIT_ULL(HW_FEATURE_MRT) | \
261 BIT_ULL(HW_FEATURE_MSAA_16X) | \
262 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
263 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
264 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
265 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
266 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \83 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
267 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \84 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
268 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \85 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
@@ -276,21 +93,6 @@ enum panfrost_hw_feature { · 7 unmodified lines
276 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \93 BIT_ULL(HW_FEATURE_JOBCHAIN_DISAMBIGUATION) | \
277 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \94 BIT_ULL(HW_FEATURE_PWRON_DURING_PWROFF_TRANS) | \
278 BIT_ULL(HW_FEATURE_XAFFINITY) | \95 BIT_ULL(HW_FEATURE_XAFFINITY) | \
279 BIT_ULL(HW_FEATURE_WARPING) | \
280 BIT_ULL(HW_FEATURE_INTERPIPE_REG_ALIASING) | \
281 BIT_ULL(HW_FEATURE_32_BIT_UNIFORM_ADDRESS) | \
282 BIT_ULL(HW_FEATURE_ATTR_AUTO_TYPE_INFERRAL) | \
283 BIT_ULL(HW_FEATURE_BRNDOUT_CC) | \
284 BIT_ULL(HW_FEATURE_BRNDOUT_KILL) | \
285 BIT_ULL(HW_FEATURE_LD_ST_LEA_TEX) | \
286 BIT_ULL(HW_FEATURE_LD_ST_TILEBUFFER) | \
287 BIT_ULL(HW_FEATURE_LINEAR_FILTER_FLOAT) | \
288 BIT_ULL(HW_FEATURE_MRT) | \
289 BIT_ULL(HW_FEATURE_MSAA_16X) | \
290 BIT_ULL(HW_FEATURE_NEXT_INSTRUCTION_TYPE) | \
291 BIT_ULL(HW_FEATURE_OUT_OF_ORDER_EXEC) | \
292 BIT_ULL(HW_FEATURE_T7XX_PAIRING_RULES) | \
293 BIT_ULL(HW_FEATURE_TEST4_DATUM_MODE) | \
294 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \96 BIT_ULL(HW_FEATURE_THREAD_GROUP_SPLIT) | \
295 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \97 BIT_ULL(HW_FEATURE_FLUSH_REDUCTION) | \
296 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \98 BIT_ULL(HW_FEATURE_PROTECTED_MODE) | \
drivers/gpu/drm/panfrost/panfrost_gpu.c+26−6
@@ -320,19 +320,36 @@ void panfrost_gpu_power_on(struct panfrost_device *pfdev) · 319 unmodified lines
320{320{
321 int ret;321 int ret;
322 u32 val;322 u32 val;
323 u64 core_mask = U64_MAX;
323 324
324 panfrost_gpu_init_quirks(pfdev);325 panfrost_gpu_init_quirks(pfdev);
325 326
326 /* Just turn on everything for now */327 if (pfdev->features.l2_present != 1) {
327 gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present);328 /*
329 * Only support one core group now.
330 * ~(l2_present - 1) unsets all bits in l2_present except
331 * the bottom bit. (l2_present - 2) has all the bits in
332 * the first core group set. AND them together to generate
333 * a mask of cores in the first core group.
334 */
335 core_mask = ~(pfdev->features.l2_present - 1) &
336 (pfdev->features.l2_present - 2);
337 dev_info_once(pfdev->dev, "using only 1st core group (%lu cores from %lu)\n",
338 hweight64(core_mask),
339 hweight64(pfdev->features.shader_present));
340 }
341 gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present & core_mask);
328 ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO,342 ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO,
329 val, val == pfdev->features.l2_present, 100, 20000);343 val, val == (pfdev->features.l2_present & core_mask),
344 100, 20000);
330 if (ret)345 if (ret)
331 dev_err(pfdev->dev, "error powering up gpu L2");346 dev_err(pfdev->dev, "error powering up gpu L2");
332 347
333 gpu_write(pfdev, SHADER_PWRON_LO, pfdev->features.shader_present);348 gpu_write(pfdev, SHADER_PWRON_LO,
349 pfdev->features.shader_present & core_mask);
334 ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO,350 ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO,
335 val, val == pfdev->features.shader_present, 100, 20000);351 val, val == (pfdev->features.shader_present & core_mask),
352 100, 20000);
336 if (ret)353 if (ret)
337 dev_err(pfdev->dev, "error powering up gpu shader");354 dev_err(pfdev->dev, "error powering up gpu shader");
338 355
@@ -360,8 +377,11 @@ int panfrost_gpu_init(struct panfrost_device *pfdev) · 21 unmodified lines
360 377
361 panfrost_gpu_init_features(pfdev);378 panfrost_gpu_init_features(pfdev);
362 379
363 dma_set_mask_and_coherent(pfdev->dev,380 err = dma_set_mask_and_coherent(pfdev->dev,
364 DMA_BIT_MASK(FIELD_GET(0xff00, pfdev->features.mmu_features)));381 DMA_BIT_MASK(FIELD_GET(0xff00, pfdev->features.mmu_features)));
382 if (err)
383 return err;
384
365 dma_set_max_seg_size(pfdev->dev, UINT_MAX);385 dma_set_max_seg_size(pfdev->dev, UINT_MAX);
366 386
367 irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu");387 irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu");
drivers/gpu/drm/radeon/atombios_dp.c+1−1
@@ -30,7 +30,7 @@ · 29 unmodified lines
30 30
31#include "atom.h"31#include "atom.h"
32#include "atom-bits.h"32#include "atom-bits.h"
33#include <drm/drm_dp_helper.h>33#include <drm/dp/drm_dp_helper.h>
34 34
35/* move these to drm_dp_helper.c/h */35/* move these to drm_dp_helper.c/h */
36#define DP_LINK_CONFIGURATION_SIZE 936#define DP_LINK_CONFIGURATION_SIZE 9
drivers/gpu/drm/radeon/radeon_connectors.c+2−2
@@ -27,7 +27,7 @@ · 26 unmodified lines
27#include <drm/drm_edid.h>27#include <drm/drm_edid.h>
28#include <drm/drm_crtc_helper.h>28#include <drm/drm_crtc_helper.h>
29#include <drm/drm_fb_helper.h>29#include <drm/drm_fb_helper.h>
30#include <drm/drm_dp_mst_helper.h>30#include <drm/dp/drm_dp_mst_helper.h>
31#include <drm/drm_probe_helper.h>31#include <drm/drm_probe_helper.h>
32#include <drm/radeon_drm.h>32#include <drm/radeon_drm.h>
33#include "radeon.h"33#include "radeon.h"
@@ -204,7 +204,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) · 170 unmodified lines
204 204
205 /* Check if bpc is within clock limit. Try to degrade gracefully otherwise */205 /* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
206 if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {206 if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
207 if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&207 if ((connector->display_info.edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) &&
208 (mode_clock * 5/4 <= max_tmds_clock))208 (mode_clock * 5/4 <= max_tmds_clock))
209 bpc = 10;209 bpc = 10;
210 else210 else
drivers/gpu/drm/radeon/radeon_dp_mst.c+1−1
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: MIT1// SPDX-License-Identifier: MIT
2 2
3#include <drm/drm_dp_mst_helper.h>3#include <drm/dp/drm_dp_mst_helper.h>
4#include <drm/drm_fb_helper.h>4#include <drm/drm_fb_helper.h>
5#include <drm/drm_file.h>5#include <drm/drm_file.h>
6#include <drm/drm_probe_helper.h>6#include <drm/drm_probe_helper.h>
drivers/gpu/drm/radeon/radeon_mode.h+2−2
@@ -33,8 +33,8 @@ · 32 unmodified lines
33#include <drm/drm_crtc.h>33#include <drm/drm_crtc.h>
34#include <drm/drm_edid.h>34#include <drm/drm_edid.h>
35#include <drm/drm_encoder.h>35#include <drm/drm_encoder.h>
36#include <drm/drm_dp_helper.h>36#include <drm/dp/drm_dp_helper.h>
37#include <drm/drm_dp_mst_helper.h>37#include <drm/dp/drm_dp_mst_helper.h>
38#include <drm/drm_fixed.h>38#include <drm/drm_fixed.h>
39#include <drm/drm_crtc_helper.h>39#include <drm/drm_crtc_helper.h>
40#include <linux/i2c.h>40#include <linux/i2c.h>
drivers/gpu/drm/radeon/radeon_ttm.c+2−2
@@ -802,7 +802,7 @@ static int radeon_mm_vram_dump_table_show(struct seq_file *m, void *unused) · 801 unmodified lines
802 TTM_PL_VRAM);802 TTM_PL_VRAM);
803 struct drm_printer p = drm_seq_file_printer(m);803 struct drm_printer p = drm_seq_file_printer(m);
804 804
805 man->func->debug(man, &p);805 ttm_resource_manager_debug(man, &p);
806 return 0;806 return 0;
807}807}
808 808
@@ -820,7 +820,7 @@ static int radeon_mm_gtt_dump_table_show(struct seq_file *m, void *unused) · 11 unmodified lines
820 TTM_PL_TT);820 TTM_PL_TT);
821 struct drm_printer p = drm_seq_file_printer(m);821 struct drm_printer p = drm_seq_file_printer(m);
822 822
823 man->func->debug(man, &p);823 ttm_resource_manager_debug(man, &p);
824 return 0;824 return 0;
825}825}
826 826
drivers/gpu/drm/rockchip/Kconfig+2−0
@@ -2,11 +2,13 @@ · 1 unmodified line
2config DRM_ROCKCHIP2config DRM_ROCKCHIP
3 tristate "DRM Support for Rockchip"3 tristate "DRM Support for Rockchip"
4 depends on DRM && ROCKCHIP_IOMMU4 depends on DRM && ROCKCHIP_IOMMU
5 select DRM_DP_HELPER
5 select DRM_GEM_CMA_HELPER6 select DRM_GEM_CMA_HELPER
6 select DRM_KMS_HELPER7 select DRM_KMS_HELPER
7 select DRM_PANEL8 select DRM_PANEL
8 select VIDEOMODE_HELPERS9 select VIDEOMODE_HELPERS
9 select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP10 select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
11 select DRM_DP_HELPER if ROCKCHIP_ANALOGIX_DP
10 select DRM_DW_HDMI if ROCKCHIP_DW_HDMI12 select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
11 select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI13 select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
12 select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI14 select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c+2−2
@@ -22,7 +22,7 @@ · 21 unmodified lines
22#include <drm/drm_atomic.h>22#include <drm/drm_atomic.h>
23#include <drm/drm_atomic_helper.h>23#include <drm/drm_atomic_helper.h>
24#include <drm/bridge/analogix_dp.h>24#include <drm/bridge/analogix_dp.h>
25#include <drm/drm_dp_helper.h>25#include <drm/dp/drm_dp_helper.h>
26#include <drm/drm_of.h>26#include <drm/drm_of.h>
27#include <drm/drm_panel.h>27#include <drm/drm_panel.h>
28#include <drm/drm_probe_helper.h>28#include <drm/drm_probe_helper.h>
@@ -117,7 +117,7 @@ static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data, · 88 unmodified lines
117{117{
118 struct drm_display_info *di = &connector->display_info;118 struct drm_display_info *di = &connector->display_info;
119 /* VOP couldn't output YUV video format for eDP rightly */119 /* VOP couldn't output YUV video format for eDP rightly */
120 u32 mask = DRM_COLOR_FORMAT_YCRCB444 | DRM_COLOR_FORMAT_YCRCB422;120 u32 mask = DRM_COLOR_FORMAT_YCBCR444 | DRM_COLOR_FORMAT_YCBCR422;
121 121
122 if ((di->color_formats & mask)) {122 if ((di->color_formats & mask)) {
123 DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n");123 DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n");
drivers/gpu/drm/rockchip/cdn-dp-core.c+1−1
@@ -16,7 +16,7 @@ · 15 unmodified lines
16#include <sound/hdmi-codec.h>16#include <sound/hdmi-codec.h>
17 17
18#include <drm/drm_atomic_helper.h>18#include <drm/drm_atomic_helper.h>
19#include <drm/drm_dp_helper.h>19#include <drm/dp/drm_dp_helper.h>
20#include <drm/drm_edid.h>20#include <drm/drm_edid.h>
21#include <drm/drm_of.h>21#include <drm/drm_of.h>
22#include <drm/drm_probe_helper.h>22#include <drm/drm_probe_helper.h>
drivers/gpu/drm/rockchip/cdn-dp-core.h+1−1
@@ -7,7 +7,7 @@ · 6 unmodified lines
7#ifndef _CDN_DP_CORE_H7#ifndef _CDN_DP_CORE_H
8#define _CDN_DP_CORE_H8#define _CDN_DP_CORE_H
9 9
10#include <drm/drm_dp_helper.h>10#include <drm/dp/drm_dp_helper.h>
11#include <drm/drm_panel.h>11#include <drm/drm_panel.h>
12#include <drm/drm_probe_helper.h>12#include <drm/drm_probe_helper.h>
13 13
drivers/gpu/drm/rockchip/rockchip_lvds.c+1−1
@@ -20,7 +20,7 @@ · 19 unmodified lines
20#include <drm/drm_atomic_helper.h>20#include <drm/drm_atomic_helper.h>
21#include <drm/drm_bridge.h>21#include <drm/drm_bridge.h>
22#include <drm/drm_bridge_connector.h>22#include <drm/drm_bridge_connector.h>
23#include <drm/drm_dp_helper.h>23#include <drm/dp/drm_dp_helper.h>
24#include <drm/drm_of.h>24#include <drm/drm_of.h>
25#include <drm/drm_panel.h>25#include <drm/drm_panel.h>
26#include <drm/drm_probe_helper.h>26#include <drm/drm_probe_helper.h>
drivers/gpu/drm/rockchip/rockchip_rgb.c+1−1
@@ -11,7 +11,7 @@ · 10 unmodified lines
11#include <drm/drm_atomic_helper.h>11#include <drm/drm_atomic_helper.h>
12#include <drm/drm_bridge.h>12#include <drm/drm_bridge.h>
13#include <drm/drm_bridge_connector.h>13#include <drm/drm_bridge_connector.h>
14#include <drm/drm_dp_helper.h>14#include <drm/dp/drm_dp_helper.h>
15#include <drm/drm_of.h>15#include <drm/drm_of.h>
16#include <drm/drm_panel.h>16#include <drm/drm_panel.h>
17#include <drm/drm_probe_helper.h>17#include <drm/drm_probe_helper.h>
drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c+5−3
@@ -7,10 +7,10 @@ · 6 unmodified lines
7 7
8#include <linux/random.h>8#include <linux/random.h>
9 9
10#include <drm/drm_dp_mst_helper.h>10#include <drm/dp/drm_dp_mst_helper.h>
11#include <drm/drm_print.h>11#include <drm/drm_print.h>
12 12
13#include "../drm_dp_mst_topology_internal.h"13#include "../dp/drm_dp_mst_topology_internal.h"
14#include "test-drm_modeset_common.h"14#include "test-drm_modeset_common.h"
15 15
16int igt_dp_mst_calc_pbn_mode(void *ignored)16int igt_dp_mst_calc_pbn_mode(void *ignored)
@@ -131,8 +131,10 @@ sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in) · 114 unmodified lines
131 return false;131 return false;
132 132
133 txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);133 txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
134 if (!txmsg)134 if (!txmsg) {
135 kfree(out);
135 return false;136 return false;
137 }
136 138
137 drm_dp_encode_sideband_req(in, txmsg);139 drm_dp_encode_sideband_req(in, txmsg);
138 ret = drm_dp_decode_sideband_req(txmsg, out);140 ret = drm_dp_decode_sideband_req(txmsg, out);
drivers/gpu/drm/selftests/test-drm_plane_helper.c+4−0
@@ -87,11 +87,15 @@ int igt_check_plane_state(void *ignored) · 86 unmodified lines
87 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)87 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
88 },88 },
89 };89 };
90 struct drm_plane plane = {
91 .dev = NULL
92 };
90 struct drm_framebuffer fb = {93 struct drm_framebuffer fb = {
91 .width = 2048,94 .width = 2048,
92 .height = 204895 .height = 2048
93 };96 };
94 struct drm_plane_state plane_state = {97 struct drm_plane_state plane_state = {
98 .plane = &plane,
95 .crtc = ZERO_SIZE_PTR,99 .crtc = ZERO_SIZE_PTR,
96 .fb = &fb,100 .fb = &fb,
97 .rotation = DRM_MODE_ROTATE_0101 .rotation = DRM_MODE_ROTATE_0
drivers/gpu/drm/stm/drv.c+5−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
14#include <linux/of_platform.h>14#include <linux/of_platform.h>
15#include <linux/pm_runtime.h>15#include <linux/pm_runtime.h>
16 16
17#include <drm/drm_aperture.h>
17#include <drm/drm_atomic.h>18#include <drm/drm_atomic.h>
18#include <drm/drm_atomic_helper.h>19#include <drm/drm_atomic_helper.h>
19#include <drm/drm_drv.h>20#include <drm/drm_drv.h>
@@ -183,6 +184,10 @@ static int stm_drm_platform_probe(struct platform_device *pdev) · 163 unmodified lines
183 184
184 DRM_DEBUG("%s\n", __func__);185 DRM_DEBUG("%s\n", __func__);
185 186
187 ret = drm_aperture_remove_framebuffers(false, &drv_driver);
188 if (ret)
189 return ret;
190
186 dma_set_coherent_mask(dev, DMA_BIT_MASK(32));191 dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
187 192
188 ddev = drm_dev_alloc(&drv_driver, dev);193 ddev = drm_dev_alloc(&drv_driver, dev);
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c+106−8
@@ -247,14 +247,6 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, · 246 unmodified lines
247 int ret, bpp;247 int ret, bpp;
248 u32 val;248 u32 val;
249 249
250 /* Update lane capabilities according to hw version */
251 dsi->lane_min_kbps = LANE_MIN_KBPS;
252 dsi->lane_max_kbps = LANE_MAX_KBPS;
253 if (dsi->hw_version == HWVER_131) {
254 dsi->lane_min_kbps *= 2;
255 dsi->lane_max_kbps *= 2;
256 }
257
258 pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);250 pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);
259 251
260 /* Compute requested pll out */252 /* Compute requested pll out */
@@ -330,6 +322,103 @@ dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps, · 69 unmodified lines
330 return 0;322 return 0;
331}323}
332 324
325#define CLK_TOLERANCE_HZ 50
326
327static enum drm_mode_status
328dw_mipi_dsi_stm_mode_valid(void *priv_data,
329 const struct drm_display_mode *mode,
330 unsigned long mode_flags, u32 lanes, u32 format)
331{
332 struct dw_mipi_dsi_stm *dsi = priv_data;
333 unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
334 int ret, bpp;
335
336 bpp = mipi_dsi_pixel_format_to_bpp(format);
337 if (bpp < 0)
338 return MODE_BAD;
339
340 /* Compute requested pll out */
341 pll_out_khz = mode->clock * bpp / lanes;
342
343 if (pll_out_khz > dsi->lane_max_kbps)
344 return MODE_CLOCK_HIGH;
345
346 if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
347 /* Add 20% to pll out to be higher than pixel bw */
348 pll_out_khz = (pll_out_khz * 12) / 10;
349 } else {
350 if (pll_out_khz < dsi->lane_min_kbps)
351 return MODE_CLOCK_LOW;
352 }
353
354 /* Compute best pll parameters */
355 idf = 0;
356 ndiv = 0;
357 odf = 0;
358 pll_in_khz = clk_get_rate(dsi->pllref_clk) / 1000;
359 ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz, &idf, &ndiv, &odf);
360 if (ret) {
361 DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
362 return MODE_ERROR;
363 }
364
365 if (!(mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) {
366 unsigned int px_clock_hz, target_px_clock_hz, lane_mbps;
367 int dsi_short_packet_size_px, hfp, hsync, hbp, delay_to_lp;
368 struct dw_mipi_dsi_dphy_timing dphy_timing;
369
370 /* Get the adjusted pll out value */
371 pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
372
373 px_clock_hz = DIV_ROUND_CLOSEST_ULL(1000ULL * pll_out_khz * lanes, bpp);
374 target_px_clock_hz = mode->clock * 1000;
375 /*
376 * Filter modes according to the clock value, particularly useful for
377 * hdmi modes that require precise pixel clocks.
378 */
379 if (px_clock_hz < target_px_clock_hz - CLK_TOLERANCE_HZ ||
380 px_clock_hz > target_px_clock_hz + CLK_TOLERANCE_HZ)
381 return MODE_CLOCK_RANGE;
382
383 /* sync packets are codes as DSI short packets (4 bytes) */
384 dsi_short_packet_size_px = DIV_ROUND_UP(4 * BITS_PER_BYTE, bpp);
385
386 hfp = mode->hsync_start - mode->hdisplay;
387 hsync = mode->hsync_end - mode->hsync_start;
388 hbp = mode->htotal - mode->hsync_end;
389
390 /* hsync must be longer than 4 bytes HSS packets */
391 if (hsync < dsi_short_packet_size_px)
392 return MODE_HSYNC_NARROW;
393
394 if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
395 /* HBP must be longer than 4 bytes HSE packets */
396 if (hbp < dsi_short_packet_size_px)
397 return MODE_HSYNC_NARROW;
398 hbp -= dsi_short_packet_size_px;
399 } else {
400 /* With sync events HBP extends in the hsync */
401 hbp += hsync - dsi_short_packet_size_px;
402 }
403
404 lane_mbps = pll_out_khz / 1000;
405 ret = dw_mipi_dsi_phy_get_timing(priv_data, lane_mbps, &dphy_timing);
406 if (ret)
407 return MODE_ERROR;
408 /*
409 * In non-burst mode DSI has to enter in LP during HFP
410 * (horizontal front porch) or HBP (horizontal back porch) to
411 * resync with LTDC pixel clock.
412 */
413 delay_to_lp = DIV_ROUND_UP((dphy_timing.data_hs2lp + dphy_timing.data_lp2hs) *
414 lanes * BITS_PER_BYTE, bpp);
415 if (hfp < delay_to_lp && hbp < delay_to_lp)
416 return MODE_HSYNC;
417 }
418
419 return MODE_OK;
420}
421
333static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {422static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {
334 .init = dw_mipi_dsi_phy_init,423 .init = dw_mipi_dsi_phy_init,
335 .power_on = dw_mipi_dsi_phy_power_on,424 .power_on = dw_mipi_dsi_phy_power_on,
@@ -340,6 +429,7 @@ static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = { · 4 unmodified lines
340 429
341static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {430static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {
342 .max_data_lanes = 2,431 .max_data_lanes = 2,
432 .mode_valid = dw_mipi_dsi_stm_mode_valid,
343 .phy_ops = &dw_mipi_dsi_stm_phy_ops,433 .phy_ops = &dw_mipi_dsi_stm_phy_ops,
344};434};
345 435
@@ -417,6 +507,14 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) · 71 unmodified lines
417 goto err_dsi_probe;507 goto err_dsi_probe;
418 }508 }
419 509
510 /* set lane capabilities according to hw version */
511 dsi->lane_min_kbps = LANE_MIN_KBPS;
512 dsi->lane_max_kbps = LANE_MAX_KBPS;
513 if (dsi->hw_version == HWVER_131) {
514 dsi->lane_min_kbps *= 2;
515 dsi->lane_max_kbps *= 2;
516 }
517
420 dw_mipi_dsi_stm_plat_data.base = dsi->base;518 dw_mipi_dsi_stm_plat_data.base = dsi->base;
421 dw_mipi_dsi_stm_plat_data.priv_data = dsi;519 dw_mipi_dsi_stm_plat_data.priv_data = dsi;
422 520
drivers/gpu/drm/stm/ltdc.c+647−163
@@ -18,6 +18,7 @@ · 17 unmodified lines
18#include <linux/pinctrl/consumer.h>18#include <linux/pinctrl/consumer.h>
19#include <linux/platform_device.h>19#include <linux/platform_device.h>
20#include <linux/pm_runtime.h>20#include <linux/pm_runtime.h>
21#include <linux/regmap.h>
21#include <linux/reset.h>22#include <linux/reset.h>
22 23
23#include <drm/drm_atomic.h>24#include <drm/drm_atomic.h>
@@ -46,15 +47,15 @@ · 22 unmodified lines
46#define HWVER_10200 0x01020047#define HWVER_10200 0x010200
47#define HWVER_10300 0x01030048#define HWVER_10300 0x010300
48#define HWVER_20101 0x02010149#define HWVER_20101 0x020101
50#define HWVER_40100 0x040100
49 51
50/*52/*
51 * The address of some registers depends on the HW version: such registers have53 * The address of some registers depends on the HW version: such registers have
52 * an extra offset specified with reg_ofs.54 * an extra offset specified with layer_ofs.
53 */55 */
54#define REG_OFS_NONE 056#define LAY_OFS_0 0x80
55#define REG_OFS_4 4 /* Insertion of "Layer Conf. 2" reg */57#define LAY_OFS_1 0x100
56#define REG_OFS (ldev->caps.reg_ofs)58#define LAY_OFS (ldev->caps.layer_ofs)
57#define LAY_OFS 0x80 /* Register Offset between 2 layers */
58 59
59/* Global register offsets */60/* Global register offsets */
60#define LTDC_IDR 0x0000 /* IDentification */61#define LTDC_IDR 0x0000 /* IDentification */
@@ -75,29 +76,35 @@ · 14 unmodified lines
75#define LTDC_LIPCR 0x0040 /* Line Interrupt Position Conf. */76#define LTDC_LIPCR 0x0040 /* Line Interrupt Position Conf. */
76#define LTDC_CPSR 0x0044 /* Current Position Status */77#define LTDC_CPSR 0x0044 /* Current Position Status */
77#define LTDC_CDSR 0x0048 /* Current Display Status */78#define LTDC_CDSR 0x0048 /* Current Display Status */
79#define LTDC_EDCR 0x0060 /* External Display Control */
80#define LTDC_FUT 0x0090 /* Fifo underrun Threshold */
78 81
79/* Layer register offsets */82/* Layer register offsets */
80#define LTDC_L1LC1R (0x80) /* L1 Layer Configuration 1 */83#define LTDC_L1C0R (ldev->caps.layer_regs[0]) /* L1 configuration 0 */
81#define LTDC_L1LC2R (0x84) /* L1 Layer Configuration 2 */84#define LTDC_L1C1R (ldev->caps.layer_regs[1]) /* L1 configuration 1 */
82#define LTDC_L1CR (0x84 + REG_OFS)/* L1 Control */85#define LTDC_L1RCR (ldev->caps.layer_regs[2]) /* L1 reload control */
83#define LTDC_L1WHPCR (0x88 + REG_OFS)/* L1 Window Hor Position Config */86#define LTDC_L1CR (ldev->caps.layer_regs[3]) /* L1 control register */
84#define LTDC_L1WVPCR (0x8C + REG_OFS)/* L1 Window Vert Position Config */87#define LTDC_L1WHPCR (ldev->caps.layer_regs[4]) /* L1 window horizontal position configuration */
85#define LTDC_L1CKCR (0x90 + REG_OFS)/* L1 Color Keying Configuration */88#define LTDC_L1WVPCR (ldev->caps.layer_regs[5]) /* L1 window vertical position configuration */
86#define LTDC_L1PFCR (0x94 + REG_OFS)/* L1 Pixel Format Configuration */89#define LTDC_L1CKCR (ldev->caps.layer_regs[6]) /* L1 color keying configuration */
87#define LTDC_L1CACR (0x98 + REG_OFS)/* L1 Constant Alpha Config */90#define LTDC_L1PFCR (ldev->caps.layer_regs[7]) /* L1 pixel format configuration */
88#define LTDC_L1DCCR (0x9C + REG_OFS)/* L1 Default Color Configuration */91#define LTDC_L1CACR (ldev->caps.layer_regs[8]) /* L1 constant alpha configuration */
89#define LTDC_L1BFCR (0xA0 + REG_OFS)/* L1 Blend Factors Configuration */92#define LTDC_L1DCCR (ldev->caps.layer_regs[9]) /* L1 default color configuration */
90#define LTDC_L1FBBCR (0xA4 + REG_OFS)/* L1 FrameBuffer Bus Control */93#define LTDC_L1BFCR (ldev->caps.layer_regs[10]) /* L1 blending factors configuration */
91#define LTDC_L1AFBCR (0xA8 + REG_OFS)/* L1 AuxFB Control */94#define LTDC_L1BLCR (ldev->caps.layer_regs[11]) /* L1 burst length configuration */
92#define LTDC_L1CFBAR (0xAC + REG_OFS)/* L1 Color FrameBuffer Address */95#define LTDC_L1PCR (ldev->caps.layer_regs[12]) /* L1 planar configuration */
93#define LTDC_L1CFBLR (0xB0 + REG_OFS)/* L1 Color FrameBuffer Length */96#define LTDC_L1CFBAR (ldev->caps.layer_regs[13]) /* L1 color frame buffer address */
94#define LTDC_L1CFBLNR (0xB4 + REG_OFS)/* L1 Color FrameBuffer Line Nb */97#define LTDC_L1CFBLR (ldev->caps.layer_regs[14]) /* L1 color frame buffer length */
95#define LTDC_L1AFBAR (0xB8 + REG_OFS)/* L1 AuxFB Address */98#define LTDC_L1CFBLNR (ldev->caps.layer_regs[15]) /* L1 color frame buffer line number */
96#define LTDC_L1AFBLR (0xBC + REG_OFS)/* L1 AuxFB Length */99#define LTDC_L1AFBA0R (ldev->caps.layer_regs[16]) /* L1 auxiliary frame buffer address 0 */
97#define LTDC_L1AFBLNR (0xC0 + REG_OFS)/* L1 AuxFB Line Number */100#define LTDC_L1AFBA1R (ldev->caps.layer_regs[17]) /* L1 auxiliary frame buffer address 1 */
98#define LTDC_L1CLUTWR (0xC4 + REG_OFS)/* L1 CLUT Write */101#define LTDC_L1AFBLR (ldev->caps.layer_regs[18]) /* L1 auxiliary frame buffer length */
99#define LTDC_L1YS1R (0xE0 + REG_OFS)/* L1 YCbCr Scale 1 */102#define LTDC_L1AFBLNR (ldev->caps.layer_regs[19]) /* L1 auxiliary frame buffer line number */
100#define LTDC_L1YS2R (0xE4 + REG_OFS)/* L1 YCbCr Scale 2 */103#define LTDC_L1CLUTWR (ldev->caps.layer_regs[20]) /* L1 CLUT write */
104#define LTDC_L1CYR0R (ldev->caps.layer_regs[21]) /* L1 Conversion YCbCr RGB 0 */
105#define LTDC_L1CYR1R (ldev->caps.layer_regs[22]) /* L1 Conversion YCbCr RGB 1 */
106#define LTDC_L1FPF0R (ldev->caps.layer_regs[23]) /* L1 Flexible Pixel Format 0 */
107#define LTDC_L1FPF1R (ldev->caps.layer_regs[24]) /* L1 Flexible Pixel Format 1 */
101 108
102/* Bit definitions */109/* Bit definitions */
103#define SSCR_VSH GENMASK(10, 0) /* Vertical Synchronization Height */110#define SSCR_VSH GENMASK(10, 0) /* Vertical Synchronization Height */
@@ -164,6 +171,10 @@ · 60 unmodified lines
164#define ISR_TERRIF BIT(2) /* Transfer ERRor Interrupt Flag */171#define ISR_TERRIF BIT(2) /* Transfer ERRor Interrupt Flag */
165#define ISR_RRIF BIT(3) /* Register Reload Interrupt Flag */172#define ISR_RRIF BIT(3) /* Register Reload Interrupt Flag */
166 173
174#define EDCR_OCYEN BIT(25) /* Output Conversion to YCbCr 422: ENable */
175#define EDCR_OCYSEL BIT(26) /* Output Conversion to YCbCr 422: SELection of the CCIR */
176#define EDCR_OCYCO BIT(27) /* Output Conversion to YCbCr 422: Chrominance Order */
177
167#define LXCR_LEN BIT(0) /* Layer ENable */178#define LXCR_LEN BIT(0) /* Layer ENable */
168#define LXCR_COLKEN BIT(1) /* Color Keying Enable */179#define LXCR_COLKEN BIT(1) /* Color Keying Enable */
169#define LXCR_CLUTEN BIT(4) /* Color Look-Up Table ENable */180#define LXCR_CLUTEN BIT(4) /* Color Look-Up Table ENable */
@@ -175,6 +186,7 @@ · 5 unmodified lines
175#define LXWVPCR_WVSPPOS GENMASK(26, 16) /* Window Vertical StoP POSition */186#define LXWVPCR_WVSPPOS GENMASK(26, 16) /* Window Vertical StoP POSition */
176 187
177#define LXPFCR_PF GENMASK(2, 0) /* Pixel Format */188#define LXPFCR_PF GENMASK(2, 0) /* Pixel Format */
189#define PF_FLEXIBLE 0x7 /* Flexible Pixel Format selected */
178 190
179#define LXCACR_CONSTA GENMASK(7, 0) /* CONSTant Alpha */191#define LXCACR_CONSTA GENMASK(7, 0) /* CONSTant Alpha */
180 192
@@ -186,6 +198,25 @@ · 5 unmodified lines
186 198
187#define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */199#define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */
188 200
201#define LXCR_C1R_YIA BIT(0) /* Ycbcr 422 Interleaved Ability */
202#define LXCR_C1R_YSPA BIT(1) /* Ycbcr 420 Semi-Planar Ability */
203#define LXCR_C1R_YFPA BIT(2) /* Ycbcr 420 Full-Planar Ability */
204#define LXCR_C1R_SCA BIT(31) /* SCaling Ability*/
205
206#define LxPCR_YREN BIT(9) /* Y Rescale Enable for the color dynamic range */
207#define LxPCR_OF BIT(8) /* Odd pixel First */
208#define LxPCR_CBF BIT(7) /* CB component First */
209#define LxPCR_YF BIT(6) /* Y component First */
210#define LxPCR_YCM GENMASK(5, 4) /* Ycbcr Conversion Mode */
211#define YCM_I 0x0 /* Interleaved 422 */
212#define YCM_SP 0x1 /* Semi-Planar 420 */
213#define YCM_FP 0x2 /* Full-Planar 420 */
214#define LxPCR_YCEN BIT(3) /* YCbCr-to-RGB Conversion Enable */
215
216#define LXRCR_IMR BIT(0) /* IMmediate Reload */
217#define LXRCR_VBR BIT(1) /* Vertical Blanking Reload */
218#define LXRCR_GRMSK BIT(2) /* Global (centralized) Reload MaSKed */
219
189#define CLUT_SIZE 256220#define CLUT_SIZE 256
190 221
191#define CONSTA_MAX 0xFF /* CONSTant Alpha MAX= 1.0 */222#define CONSTA_MAX 0xFF /* CONSTant Alpha MAX= 1.0 */
@@ -201,8 +232,12 @@ enum ltdc_pix_fmt { · 9 unmodified lines
201 /* RGB formats */232 /* RGB formats */
202 PF_ARGB8888, /* ARGB [32 bits] */233 PF_ARGB8888, /* ARGB [32 bits] */
203 PF_RGBA8888, /* RGBA [32 bits] */234 PF_RGBA8888, /* RGBA [32 bits] */
235 PF_ABGR8888, /* ABGR [32 bits] */
236 PF_BGRA8888, /* BGRA [32 bits] */
204 PF_RGB888, /* RGB [24 bits] */237 PF_RGB888, /* RGB [24 bits] */
238 PF_BGR888, /* BGR [24 bits] */
205 PF_RGB565, /* RGB [16 bits] */239 PF_RGB565, /* RGB [16 bits] */
240 PF_BGR565, /* BGR [16 bits] */
206 PF_ARGB1555, /* ARGB A:1 bit RGB:15 bits [16 bits] */241 PF_ARGB1555, /* ARGB A:1 bit RGB:15 bits [16 bits] */
207 PF_ARGB4444, /* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */242 PF_ARGB4444, /* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */
208 /* Indexed formats */243 /* Indexed formats */
@@ -234,36 +269,198 @@ static const enum ltdc_pix_fmt ltdc_pix_fmt_a1[NB_PF] = { · 25 unmodified lines
234 PF_ARGB4444 /* 0x07 */269 PF_ARGB4444 /* 0x07 */
235};270};
236 271
237static const u64 ltdc_format_modifiers[] = {272static const enum ltdc_pix_fmt ltdc_pix_fmt_a2[NB_PF] = {
238 DRM_FORMAT_MOD_LINEAR,273 PF_ARGB8888, /* 0x00 */
239 DRM_FORMAT_MOD_INVALID274 PF_ABGR8888, /* 0x01 */
275 PF_RGBA8888, /* 0x02 */
276 PF_BGRA8888, /* 0x03 */
277 PF_RGB565, /* 0x04 */
278 PF_BGR565, /* 0x05 */
279 PF_RGB888, /* 0x06 */
280 PF_NONE /* 0x07 */
240};281};
241 282
242static inline u32 reg_read(void __iomem *base, u32 reg)283static const u32 ltdc_drm_fmt_a0[] = {
243{284 DRM_FORMAT_ARGB8888,
244 return readl_relaxed(base + reg);285 DRM_FORMAT_XRGB8888,
245}286 DRM_FORMAT_RGB888,
287 DRM_FORMAT_RGB565,
288 DRM_FORMAT_ARGB1555,
289 DRM_FORMAT_XRGB1555,
290 DRM_FORMAT_ARGB4444,
291 DRM_FORMAT_XRGB4444,
292 DRM_FORMAT_C8
293};
246 294
247static inline void reg_write(void __iomem *base, u32 reg, u32 val)295static const u32 ltdc_drm_fmt_a1[] = {
248{296 DRM_FORMAT_ARGB8888,
249 writel_relaxed(val, base + reg);297 DRM_FORMAT_XRGB8888,
250}298 DRM_FORMAT_RGB888,
299 DRM_FORMAT_RGB565,
300 DRM_FORMAT_RGBA8888,
301 DRM_FORMAT_RGBX8888,
302 DRM_FORMAT_ARGB1555,
303 DRM_FORMAT_XRGB1555,
304 DRM_FORMAT_ARGB4444,
305 DRM_FORMAT_XRGB4444,
306 DRM_FORMAT_C8
307};
251 308
252static inline void reg_set(void __iomem *base, u32 reg, u32 mask)309static const u32 ltdc_drm_fmt_a2[] = {
253{310 DRM_FORMAT_ARGB8888,
254 reg_write(base, reg, reg_read(base, reg) | mask);311 DRM_FORMAT_XRGB8888,
255}312 DRM_FORMAT_ABGR8888,
313 DRM_FORMAT_XBGR8888,
314 DRM_FORMAT_RGBA8888,
315 DRM_FORMAT_RGBX8888,
316 DRM_FORMAT_BGRA8888,
317 DRM_FORMAT_BGRX8888,
318 DRM_FORMAT_RGB565,
319 DRM_FORMAT_BGR565,
320 DRM_FORMAT_RGB888,
321 DRM_FORMAT_BGR888,
322 DRM_FORMAT_ARGB1555,
323 DRM_FORMAT_XRGB1555,
324 DRM_FORMAT_ARGB4444,
325 DRM_FORMAT_XRGB4444,
326 DRM_FORMAT_C8
327};
256 328
257static inline void reg_clear(void __iomem *base, u32 reg, u32 mask)329static const u32 ltdc_drm_fmt_ycbcr_cp[] = {
258{330 DRM_FORMAT_YUYV,
259 reg_write(base, reg, reg_read(base, reg) & ~mask);331 DRM_FORMAT_YVYU,
260}332 DRM_FORMAT_UYVY,
333 DRM_FORMAT_VYUY
334};
261 335
262static inline void reg_update_bits(void __iomem *base, u32 reg, u32 mask,336static const u32 ltdc_drm_fmt_ycbcr_sp[] = {
263 u32 val)337 DRM_FORMAT_NV12,
264{338 DRM_FORMAT_NV21
265 reg_write(base, reg, (reg_read(base, reg) & ~mask) | val);339};
266}340
341static const u32 ltdc_drm_fmt_ycbcr_fp[] = {
342 DRM_FORMAT_YUV420,
343 DRM_FORMAT_YVU420
344};
345
346/* Layer register offsets */
347static const u32 ltdc_layer_regs_a0[] = {
348 0x80, /* L1 configuration 0 */
349 0x00, /* not available */
350 0x00, /* not available */
351 0x84, /* L1 control register */
352 0x88, /* L1 window horizontal position configuration */
353 0x8c, /* L1 window vertical position configuration */
354 0x90, /* L1 color keying configuration */
355 0x94, /* L1 pixel format configuration */
356 0x98, /* L1 constant alpha configuration */
357 0x9c, /* L1 default color configuration */
358 0xa0, /* L1 blending factors configuration */
359 0x00, /* not available */
360 0x00, /* not available */
361 0xac, /* L1 color frame buffer address */
362 0xb0, /* L1 color frame buffer length */
363 0xb4, /* L1 color frame buffer line number */
364 0x00, /* not available */
365 0x00, /* not available */
366 0x00, /* not available */
367 0x00, /* not available */
368 0xc4, /* L1 CLUT write */
369 0x00, /* not available */
370 0x00, /* not available */
371 0x00, /* not available */
372 0x00 /* not available */
373};
374
375static const u32 ltdc_layer_regs_a1[] = {
376 0x80, /* L1 configuration 0 */
377 0x84, /* L1 configuration 1 */
378 0x00, /* L1 reload control */
379 0x88, /* L1 control register */
380 0x8c, /* L1 window horizontal position configuration */
381 0x90, /* L1 window vertical position configuration */
382 0x94, /* L1 color keying configuration */
383 0x98, /* L1 pixel format configuration */
384 0x9c, /* L1 constant alpha configuration */
385 0xa0, /* L1 default color configuration */
386 0xa4, /* L1 blending factors configuration */
387 0xa8, /* L1 burst length configuration */
388 0x00, /* not available */
389 0xac, /* L1 color frame buffer address */
390 0xb0, /* L1 color frame buffer length */
391 0xb4, /* L1 color frame buffer line number */
392 0xb8, /* L1 auxiliary frame buffer address 0 */
393 0xbc, /* L1 auxiliary frame buffer address 1 */
394 0xc0, /* L1 auxiliary frame buffer length */
395 0xc4, /* L1 auxiliary frame buffer line number */
396 0xc8, /* L1 CLUT write */
397 0x00, /* not available */
398 0x00, /* not available */
399 0x00, /* not available */
400 0x00 /* not available */
401};
402
403static const u32 ltdc_layer_regs_a2[] = {
404 0x100, /* L1 configuration 0 */
405 0x104, /* L1 configuration 1 */
406 0x108, /* L1 reload control */
407 0x10c, /* L1 control register */
408 0x110, /* L1 window horizontal position configuration */
409 0x114, /* L1 window vertical position configuration */
410 0x118, /* L1 color keying configuration */
411 0x11c, /* L1 pixel format configuration */
412 0x120, /* L1 constant alpha configuration */
413 0x124, /* L1 default color configuration */
414 0x128, /* L1 blending factors configuration */
415 0x12c, /* L1 burst length configuration */
416 0x130, /* L1 planar configuration */
417 0x134, /* L1 color frame buffer address */
418 0x138, /* L1 color frame buffer length */
419 0x13c, /* L1 color frame buffer line number */
420 0x140, /* L1 auxiliary frame buffer address 0 */
421 0x144, /* L1 auxiliary frame buffer address 1 */
422 0x148, /* L1 auxiliary frame buffer length */
423 0x14c, /* L1 auxiliary frame buffer line number */
424 0x150, /* L1 CLUT write */
425 0x16c, /* L1 Conversion YCbCr RGB 0 */
426 0x170, /* L1 Conversion YCbCr RGB 1 */
427 0x174, /* L1 Flexible Pixel Format 0 */
428 0x178 /* L1 Flexible Pixel Format 1 */
429};
430
431static const u64 ltdc_format_modifiers[] = {
432 DRM_FORMAT_MOD_LINEAR,
433 DRM_FORMAT_MOD_INVALID
434};
435
436static const struct regmap_config stm32_ltdc_regmap_cfg = {
437 .reg_bits = 32,
438 .val_bits = 32,
439 .reg_stride = sizeof(u32),
440 .max_register = 0x400,
441 .use_relaxed_mmio = true,
442 .cache_type = REGCACHE_NONE,
443};
444
445static const u32 ltdc_ycbcr2rgb_coeffs[DRM_COLOR_ENCODING_MAX][DRM_COLOR_RANGE_MAX][2] = {
446 [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
447 0x02040199, /* (b_cb = 516 / r_cr = 409) */
448 0x006400D0 /* (g_cb = 100 / g_cr = 208) */
449 },
450 [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = {
451 0x01C60167, /* (b_cb = 454 / r_cr = 359) */
452 0x005800B7 /* (g_cb = 88 / g_cr = 183) */
453 },
454 [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
455 0x021D01CB, /* (b_cb = 541 / r_cr = 459) */
456 0x00370089 /* (g_cb = 55 / g_cr = 137) */
457 },
458 [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = {
459 0x01DB0193, /* (b_cb = 475 / r_cr = 403) */
460 0x00300078 /* (g_cb = 48 / g_cr = 120) */
461 }
462 /* BT2020 not supported */
463};
267 464
268static inline struct ltdc_device *crtc_to_ltdc(struct drm_crtc *crtc)465static inline struct ltdc_device *crtc_to_ltdc(struct drm_crtc *crtc)
269{466{
@@ -289,16 +486,30 @@ static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) · 19 unmodified lines
289 case DRM_FORMAT_XRGB8888:486 case DRM_FORMAT_XRGB8888:
290 pf = PF_ARGB8888;487 pf = PF_ARGB8888;
291 break;488 break;
489 case DRM_FORMAT_ABGR8888:
490 case DRM_FORMAT_XBGR8888:
491 pf = PF_ABGR8888;
492 break;
292 case DRM_FORMAT_RGBA8888:493 case DRM_FORMAT_RGBA8888:
293 case DRM_FORMAT_RGBX8888:494 case DRM_FORMAT_RGBX8888:
294 pf = PF_RGBA8888;495 pf = PF_RGBA8888;
295 break;496 break;
497 case DRM_FORMAT_BGRA8888:
498 case DRM_FORMAT_BGRX8888:
499 pf = PF_BGRA8888;
500 break;
296 case DRM_FORMAT_RGB888:501 case DRM_FORMAT_RGB888:
297 pf = PF_RGB888;502 pf = PF_RGB888;
298 break;503 break;
504 case DRM_FORMAT_BGR888:
505 pf = PF_BGR888;
506 break;
299 case DRM_FORMAT_RGB565:507 case DRM_FORMAT_RGB565:
300 pf = PF_RGB565;508 pf = PF_RGB565;
301 break;509 break;
510 case DRM_FORMAT_BGR565:
511 pf = PF_BGR565;
512 break;
302 case DRM_FORMAT_ARGB1555:513 case DRM_FORMAT_ARGB1555:
303 case DRM_FORMAT_XRGB1555:514 case DRM_FORMAT_XRGB1555:
304 pf = PF_ARGB1555;515 pf = PF_ARGB1555;
@@ -319,49 +530,138 @@ static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt) · 14 unmodified lines
319 return pf;530 return pf;
320}531}
321 532
322static inline u32 to_drm_pixelformat(enum ltdc_pix_fmt pf)533static inline u32 ltdc_set_flexible_pixel_format(struct drm_plane *plane, enum ltdc_pix_fmt pix_fmt)
323{534{
324 switch (pf) {535 struct ltdc_device *ldev = plane_to_ltdc(plane);
325 case PF_ARGB8888:536 u32 lofs = plane->index * LAY_OFS, ret = PF_FLEXIBLE;
326 return DRM_FORMAT_ARGB8888;537 int psize, alen, apos, rlen, rpos, glen, gpos, blen, bpos;
327 case PF_RGBA8888:538
328 return DRM_FORMAT_RGBA8888;539 switch (pix_fmt) {
329 case PF_RGB888:540 case PF_BGR888:
330 return DRM_FORMAT_RGB888;541 psize = 3;
331 case PF_RGB565:542 alen = 0; apos = 0; rlen = 8; rpos = 0;
332 return DRM_FORMAT_RGB565;543 glen = 8; gpos = 8; blen = 8; bpos = 16;
544 break;
333 case PF_ARGB1555:545 case PF_ARGB1555:
334 return DRM_FORMAT_ARGB1555;546 psize = 2;
547 alen = 1; apos = 15; rlen = 5; rpos = 10;
548 glen = 5; gpos = 5; blen = 5; bpos = 0;
549 break;
335 case PF_ARGB4444:550 case PF_ARGB4444:
336 return DRM_FORMAT_ARGB4444;551 psize = 2;
552 alen = 4; apos = 12; rlen = 4; rpos = 8;
553 glen = 4; gpos = 4; blen = 4; bpos = 0;
554 break;
337 case PF_L8:555 case PF_L8:
338 return DRM_FORMAT_C8;556 psize = 1;
339 case PF_AL44: /* No DRM support */557 alen = 0; apos = 0; rlen = 8; rpos = 0;
340 case PF_AL88: /* No DRM support */558 glen = 8; gpos = 0; blen = 8; bpos = 0;
341 case PF_NONE:559 break;
560 case PF_AL44:
561 psize = 1;
562 alen = 4; apos = 4; rlen = 4; rpos = 0;
563 glen = 4; gpos = 0; blen = 4; bpos = 0;
564 break;
565 case PF_AL88:
566 psize = 2;
567 alen = 8; apos = 8; rlen = 8; rpos = 0;
568 glen = 8; gpos = 0; blen = 8; bpos = 0;
569 break;
342 default:570 default:
343 return 0;571 ret = NB_PF; /* error case, trace msg is handled by the caller */
572 break;
344 }573 }
574
575 if (ret == PF_FLEXIBLE) {
576 regmap_write(ldev->regmap, LTDC_L1FPF0R + lofs,
577 (rlen << 14) + (rpos << 9) + (alen << 5) + apos);
578
579 regmap_write(ldev->regmap, LTDC_L1FPF1R + lofs,
580 (psize << 18) + (blen << 14) + (bpos << 9) + (glen << 5) + gpos);
581 }
582
583 return ret;
345}584}
346 585
347static inline u32 get_pixelformat_without_alpha(u32 drm)586/*
587 * All non-alpha color formats derived from native alpha color formats are
588 * either characterized by a FourCC format code
589 */
590static inline u32 is_xrgb(u32 drm)
348{591{
349 switch (drm) {592 return ((drm & 0xFF) == 'X' || ((drm >> 8) & 0xFF) == 'X');
350 case DRM_FORMAT_ARGB4444:593}
351 return DRM_FORMAT_XRGB4444;594
352 case DRM_FORMAT_RGBA4444:595static inline void ltdc_set_ycbcr_config(struct drm_plane *plane, u32 drm_pix_fmt)
353 return DRM_FORMAT_RGBX4444;596{
354 case DRM_FORMAT_ARGB1555:597 struct ltdc_device *ldev = plane_to_ltdc(plane);
355 return DRM_FORMAT_XRGB1555;598 struct drm_plane_state *state = plane->state;
356 case DRM_FORMAT_RGBA5551:599 u32 lofs = plane->index * LAY_OFS;
357 return DRM_FORMAT_RGBX5551;600 u32 val;
358 case DRM_FORMAT_ARGB8888:601
359 return DRM_FORMAT_XRGB8888;602 switch (drm_pix_fmt) {
360 case DRM_FORMAT_RGBA8888:603 case DRM_FORMAT_YUYV:
361 return DRM_FORMAT_RGBX8888;604 val = (YCM_I << 4) | LxPCR_YF | LxPCR_CBF;
605 break;
606 case DRM_FORMAT_YVYU:
607 val = (YCM_I << 4) | LxPCR_YF;
608 break;
609 case DRM_FORMAT_UYVY:
610 val = (YCM_I << 4) | LxPCR_CBF;
611 break;
612 case DRM_FORMAT_VYUY:
613 val = (YCM_I << 4);
614 break;
615 case DRM_FORMAT_NV12:
616 val = (YCM_SP << 4) | LxPCR_CBF;
617 break;
618 case DRM_FORMAT_NV21:
619 val = (YCM_SP << 4);
620 break;
621 case DRM_FORMAT_YUV420:
622 case DRM_FORMAT_YVU420:
623 val = (YCM_FP << 4);
624 break;
362 default:625 default:
363 return 0;626 /* RGB or not a YCbCr supported format */
627 break;
628 }
629
630 /* Enable limited range */
631 if (state->color_range == DRM_COLOR_YCBCR_LIMITED_RANGE)
632 val |= LxPCR_YREN;
633
634 /* enable ycbcr conversion */
635 val |= LxPCR_YCEN;
636
637 regmap_write(ldev->regmap, LTDC_L1PCR + lofs, val);
638}
639
640static inline void ltdc_set_ycbcr_coeffs(struct drm_plane *plane)
641{
642 struct ltdc_device *ldev = plane_to_ltdc(plane);
643 struct drm_plane_state *state = plane->state;
644 enum drm_color_encoding enc = state->color_encoding;
645 enum drm_color_range ran = state->color_range;
646 u32 lofs = plane->index * LAY_OFS;
647
648 if (enc != DRM_COLOR_YCBCR_BT601 && enc != DRM_COLOR_YCBCR_BT709) {
649 DRM_ERROR("color encoding %d not supported, use bt601 by default\n", enc);
650 /* set by default color encoding to DRM_COLOR_YCBCR_BT601 */
651 enc = DRM_COLOR_YCBCR_BT601;
652 }
653
654 if (ran != DRM_COLOR_YCBCR_LIMITED_RANGE && ran != DRM_COLOR_YCBCR_FULL_RANGE) {
655 DRM_ERROR("color range %d not supported, use limited range by default\n", ran);
656 /* set by default color range to DRM_COLOR_YCBCR_LIMITED_RANGE */
657 ran = DRM_COLOR_YCBCR_LIMITED_RANGE;
364 }658 }
659
660 DRM_DEBUG_DRIVER("Color encoding=%d, range=%d\n", enc, ran);
661 regmap_write(ldev->regmap, LTDC_L1CYR0R + lofs,
662 ltdc_ycbcr2rgb_coeffs[enc][ran][0]);
663 regmap_write(ldev->regmap, LTDC_L1CYR1R + lofs,
664 ltdc_ycbcr2rgb_coeffs[enc][ran][1]);
365}665}
366 666
367static irqreturn_t ltdc_irq_thread(int irq, void *arg)667static irqreturn_t ltdc_irq_thread(int irq, void *arg)
@@ -390,9 +690,13 @@ static irqreturn_t ltdc_irq(int irq, void *arg) · 22 unmodified lines
390 struct drm_device *ddev = arg;690 struct drm_device *ddev = arg;
391 struct ltdc_device *ldev = ddev->dev_private;691 struct ltdc_device *ldev = ddev->dev_private;
392 692
393 /* Read & Clear the interrupt status */693 /*
394 ldev->irq_status = reg_read(ldev->regs, LTDC_ISR);694 * Read & Clear the interrupt status
395 reg_write(ldev->regs, LTDC_ICR, ldev->irq_status);695 * In order to write / read registers in this critical section
696 * very quickly, the regmap functions are not used.
697 */
698 ldev->irq_status = readl_relaxed(ldev->regs + LTDC_ISR);
699 writel_relaxed(ldev->irq_status, ldev->regs + LTDC_ICR);
396 700
397 return IRQ_WAKE_THREAD;701 return IRQ_WAKE_THREAD;
398}702}
@@ -416,7 +720,7 @@ static void ltdc_crtc_update_clut(struct drm_crtc *crtc) · 17 unmodified lines
416 for (i = 0; i < CLUT_SIZE; i++, lut++) {720 for (i = 0; i < CLUT_SIZE; i++, lut++) {
417 val = ((lut->red << 8) & 0xff0000) | (lut->green & 0xff00) |721 val = ((lut->red << 8) & 0xff0000) | (lut->green & 0xff00) |
418 (lut->blue >> 8) | (i << 24);722 (lut->blue >> 8) | (i << 24);
419 reg_write(ldev->regs, LTDC_L1CLUTWR, val);723 regmap_write(ldev->regmap, LTDC_L1CLUTWR, val);
420 }724 }
421}725}
422 726
@@ -431,13 +735,14 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, · 8 unmodified lines
431 pm_runtime_get_sync(ddev->dev);735 pm_runtime_get_sync(ddev->dev);
432 736
433 /* Sets the background color value */737 /* Sets the background color value */
434 reg_write(ldev->regs, LTDC_BCCR, BCCR_BCBLACK);738 regmap_write(ldev->regmap, LTDC_BCCR, BCCR_BCBLACK);
435 739
436 /* Enable IRQ */740 /* Enable IRQ */
437 reg_set(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);741 regmap_set_bits(ldev->regmap, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
438 742
439 /* Commit shadow registers = update planes at next vblank */743 /* Commit shadow registers = update planes at next vblank */
440 reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);744 if (!ldev->caps.plane_reg_shadow)
745 regmap_set_bits(ldev->regmap, LTDC_SRCR, SRCR_VBR);
441 746
442 drm_crtc_vblank_on(crtc);747 drm_crtc_vblank_on(crtc);
443}748}
@@ -453,10 +758,11 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc, · 9 unmodified lines
453 drm_crtc_vblank_off(crtc);758 drm_crtc_vblank_off(crtc);
454 759
455 /* disable IRQ */760 /* disable IRQ */
456 reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);761 regmap_clear_bits(ldev->regmap, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
457 762
458 /* immediately commit disable of layers before switching off LTDC */763 /* immediately commit disable of layers before switching off LTDC */
459 reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR);764 if (!ldev->caps.plane_reg_shadow)
765 regmap_set_bits(ldev->regmap, LTDC_SRCR, SRCR_IMR);
460 766
461 pm_runtime_put_sync(ddev->dev);767 pm_runtime_put_sync(ddev->dev);
462}768}
@@ -533,6 +839,7 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) · 70 unmodified lines
533 struct drm_display_mode *mode = &crtc->state->adjusted_mode;839 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
534 u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h;840 u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h;
535 u32 total_width, total_height;841 u32 total_width, total_height;
842 u32 bus_formats = MEDIA_BUS_FMT_RGB888_1X24;
536 u32 bus_flags = 0;843 u32 bus_flags = 0;
537 u32 val;844 u32 val;
538 int ret;845 int ret;
@@ -558,8 +865,11 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) · 19 unmodified lines
558 865
559 if (bridge && bridge->timings)866 if (bridge && bridge->timings)
560 bus_flags = bridge->timings->input_bus_flags;867 bus_flags = bridge->timings->input_bus_flags;
561 else if (connector)868 else if (connector) {
562 bus_flags = connector->display_info.bus_flags;869 bus_flags = connector->display_info.bus_flags;
870 if (connector->display_info.num_bus_formats)
871 bus_formats = connector->display_info.bus_formats[0];
872 }
563 873
564 if (!pm_runtime_active(ddev->dev)) {874 if (!pm_runtime_active(ddev->dev)) {
565 ret = pm_runtime_get_sync(ddev->dev);875 ret = pm_runtime_get_sync(ddev->dev);
@@ -604,26 +914,56 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) · 38 unmodified lines
604 if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)914 if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
605 val |= GCR_PCPOL;915 val |= GCR_PCPOL;
606 916
607 reg_update_bits(ldev->regs, LTDC_GCR,917 regmap_update_bits(ldev->regmap, LTDC_GCR,
608 GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val);918 GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val);
609 919
610 /* Set Synchronization size */920 /* Set Synchronization size */
611 val = (hsync << 16) | vsync;921 val = (hsync << 16) | vsync;
612 reg_update_bits(ldev->regs, LTDC_SSCR, SSCR_VSH | SSCR_HSW, val);922 regmap_update_bits(ldev->regmap, LTDC_SSCR, SSCR_VSH | SSCR_HSW, val);
613 923
614 /* Set Accumulated Back porch */924 /* Set Accumulated Back porch */
615 val = (accum_hbp << 16) | accum_vbp;925 val = (accum_hbp << 16) | accum_vbp;
616 reg_update_bits(ldev->regs, LTDC_BPCR, BPCR_AVBP | BPCR_AHBP, val);926 regmap_update_bits(ldev->regmap, LTDC_BPCR, BPCR_AVBP | BPCR_AHBP, val);
617 927
618 /* Set Accumulated Active Width */928 /* Set Accumulated Active Width */
619 val = (accum_act_w << 16) | accum_act_h;929 val = (accum_act_w << 16) | accum_act_h;
620 reg_update_bits(ldev->regs, LTDC_AWCR, AWCR_AAW | AWCR_AAH, val);930 regmap_update_bits(ldev->regmap, LTDC_AWCR, AWCR_AAW | AWCR_AAH, val);
621 931
622 /* Set total width & height */932 /* Set total width & height */
623 val = (total_width << 16) | total_height;933 val = (total_width << 16) | total_height;
624 reg_update_bits(ldev->regs, LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val);934 regmap_update_bits(ldev->regmap, LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val);
625 935
626 reg_write(ldev->regs, LTDC_LIPCR, (accum_act_h + 1));936 regmap_write(ldev->regmap, LTDC_LIPCR, (accum_act_h + 1));
937
938 /* Configure the output format (hw version dependent) */
939 if (ldev->caps.ycbcr_output) {
940 /* Input video dynamic_range & colorimetry */
941 int vic = drm_match_cea_mode(mode);
942 u32 val;
943
944 if (vic == 6 || vic == 7 || vic == 21 || vic == 22 ||
945 vic == 2 || vic == 3 || vic == 17 || vic == 18)
946 /* ITU-R BT.601 */
947 val = 0;
948 else
949 /* ITU-R BT.709 */
950 val = EDCR_OCYSEL;
951
952 switch (bus_formats) {
953 case MEDIA_BUS_FMT_YUYV8_1X16:
954 /* enable ycbcr output converter */
955 regmap_write(ldev->regmap, LTDC_EDCR, EDCR_OCYEN | val);
956 break;
957 case MEDIA_BUS_FMT_YVYU8_1X16:
958 /* enable ycbcr output converter & invert chrominance order */
959 regmap_write(ldev->regmap, LTDC_EDCR, EDCR_OCYEN | EDCR_OCYCO | val);
960 break;
961 default:
962 /* disable ycbcr output converter */
963 regmap_write(ldev->regmap, LTDC_EDCR, 0);
964 break;
965 }
966 }
627}967}
628 968
629static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,969static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -638,7 +978,8 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, · 8 unmodified lines
638 ltdc_crtc_update_clut(crtc);978 ltdc_crtc_update_clut(crtc);
639 979
640 /* Commit shadow registers = update planes at next vblank */980 /* Commit shadow registers = update planes at next vblank */
641 reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);981 if (!ldev->caps.plane_reg_shadow)
982 regmap_set_bits(ldev->regmap, LTDC_SRCR, SRCR_VBR);
642 983
643 if (event) {984 if (event) {
644 crtc->state->event = NULL;985 crtc->state->event = NULL;
@@ -680,10 +1021,14 @@ static bool ltdc_crtc_get_scanout_position(struct drm_crtc *crtc, · 35 unmodified lines
680 * simplify the code and only test if line > vactive_end1021 * simplify the code and only test if line > vactive_end
681 */1022 */
682 if (pm_runtime_active(ddev->dev)) {1023 if (pm_runtime_active(ddev->dev)) {
683 line = reg_read(ldev->regs, LTDC_CPSR) & CPSR_CYPOS;1024 regmap_read(ldev->regmap, LTDC_CPSR, &line);
684 vactive_start = reg_read(ldev->regs, LTDC_BPCR) & BPCR_AVBP;1025 line &= CPSR_CYPOS;
685 vactive_end = reg_read(ldev->regs, LTDC_AWCR) & AWCR_AAH;1026 regmap_read(ldev->regmap, LTDC_BPCR, &vactive_start);
686 vtotal = reg_read(ldev->regs, LTDC_TWCR) & TWCR_TOTALH;1027 vactive_start &= BPCR_AVBP;
1028 regmap_read(ldev->regmap, LTDC_AWCR, &vactive_end);
1029 vactive_end &= AWCR_AAH;
1030 regmap_read(ldev->regmap, LTDC_TWCR, &vtotal);
1031 vtotal &= TWCR_TOTALH;
687 1032
688 if (line > vactive_end)1033 if (line > vactive_end)
689 *vpos = line - vtotal - vactive_start;1034 *vpos = line - vtotal - vactive_start;
@@ -719,7 +1064,7 @@ static int ltdc_crtc_enable_vblank(struct drm_crtc *crtc) · 29 unmodified lines
719 DRM_DEBUG_DRIVER("\n");1064 DRM_DEBUG_DRIVER("\n");
720 1065
721 if (state->enable)1066 if (state->enable)
722 reg_set(ldev->regs, LTDC_IER, IER_LIE);1067 regmap_set_bits(ldev->regmap, LTDC_IER, IER_LIE);
723 else1068 else
724 return -EPERM;1069 return -EPERM;
725 1070
@@ -731,7 +1076,7 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc) · 5 unmodified lines
731 struct ltdc_device *ldev = crtc_to_ltdc(crtc);1076 struct ltdc_device *ldev = crtc_to_ltdc(crtc);
732 1077
733 DRM_DEBUG_DRIVER("\n");1078 DRM_DEBUG_DRIVER("\n");
734 reg_clear(ldev->regs, LTDC_IER, IER_LIE);1079 regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE);
735}1080}
736 1081
737static const struct drm_crtc_funcs ltdc_crtc_funcs = {1082static const struct drm_crtc_funcs ltdc_crtc_funcs = {
@@ -789,7 +1134,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, · 51 unmodified lines
789 u32 y0 = newstate->crtc_y;1134 u32 y0 = newstate->crtc_y;
790 u32 y1 = newstate->crtc_y + newstate->crtc_h - 1;1135 u32 y1 = newstate->crtc_y + newstate->crtc_h - 1;
791 u32 src_x, src_y, src_w, src_h;1136 u32 src_x, src_y, src_w, src_h;
792 u32 val, pitch_in_bytes, line_length, paddr, ahbp, avbp, bpcr;1137 u32 val, pitch_in_bytes, line_length, line_number, paddr, ahbp, avbp, bpcr;
793 enum ltdc_pix_fmt pf;1138 enum ltdc_pix_fmt pf;
794 1139
795 if (!newstate->crtc || !fb) {1140 if (!newstate->crtc || !fb) {
@@ -809,19 +1154,20 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, · 13 unmodified lines
809 newstate->crtc_w, newstate->crtc_h,1154 newstate->crtc_w, newstate->crtc_h,
810 newstate->crtc_x, newstate->crtc_y);1155 newstate->crtc_x, newstate->crtc_y);
811 1156
812 bpcr = reg_read(ldev->regs, LTDC_BPCR);1157 regmap_read(ldev->regmap, LTDC_BPCR, &bpcr);
1158
813 ahbp = (bpcr & BPCR_AHBP) >> 16;1159 ahbp = (bpcr & BPCR_AHBP) >> 16;
814 avbp = bpcr & BPCR_AVBP;1160 avbp = bpcr & BPCR_AVBP;
815 1161
816 /* Configures the horizontal start and stop position */1162 /* Configures the horizontal start and stop position */
817 val = ((x1 + 1 + ahbp) << 16) + (x0 + 1 + ahbp);1163 val = ((x1 + 1 + ahbp) << 16) + (x0 + 1 + ahbp);
818 reg_update_bits(ldev->regs, LTDC_L1WHPCR + lofs,1164 regmap_write_bits(ldev->regmap, LTDC_L1WHPCR + lofs,
819 LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS, val);1165 LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS, val);
820 1166
821 /* Configures the vertical start and stop position */1167 /* Configures the vertical start and stop position */
822 val = ((y1 + 1 + avbp) << 16) + (y0 + 1 + avbp);1168 val = ((y1 + 1 + avbp) << 16) + (y0 + 1 + avbp);
823 reg_update_bits(ldev->regs, LTDC_L1WVPCR + lofs,1169 regmap_write_bits(ldev->regmap, LTDC_L1WVPCR + lofs,
824 LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, val);1170 LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, val);
825 1171
826 /* Specifies the pixel format */1172 /* Specifies the pixel format */
827 pf = to_ltdc_pixelformat(fb->format->format);1173 pf = to_ltdc_pixelformat(fb->format->format);
@@ -829,24 +1175,27 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, · 1 unmodified line
829 if (ldev->caps.pix_fmt_hw[val] == pf)1175 if (ldev->caps.pix_fmt_hw[val] == pf)
830 break;1176 break;
831 1177
1178 /* Use the flexible color format feature if necessary and available */
1179 if (ldev->caps.pix_fmt_flex && val == NB_PF)
1180 val = ltdc_set_flexible_pixel_format(plane, pf);
1181
832 if (val == NB_PF) {1182 if (val == NB_PF) {
833 DRM_ERROR("Pixel format %.4s not supported\n",1183 DRM_ERROR("Pixel format %.4s not supported\n",
834 (char *)&fb->format->format);1184 (char *)&fb->format->format);
835 val = 0; /* set by default ARGB 32 bits */1185 val = 0; /* set by default ARGB 32 bits */
836 }1186 }
837 reg_update_bits(ldev->regs, LTDC_L1PFCR + lofs, LXPFCR_PF, val);1187 regmap_write_bits(ldev->regmap, LTDC_L1PFCR + lofs, LXPFCR_PF, val);
838 1188
839 /* Configures the color frame buffer pitch in bytes & line length */1189 /* Configures the color frame buffer pitch in bytes & line length */
840 pitch_in_bytes = fb->pitches[0];1190 pitch_in_bytes = fb->pitches[0];
841 line_length = fb->format->cpp[0] *1191 line_length = fb->format->cpp[0] *
842 (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;1192 (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;
843 val = ((pitch_in_bytes << 16) | line_length);1193 val = ((pitch_in_bytes << 16) | line_length);
844 reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,1194 regmap_write_bits(ldev->regmap, LTDC_L1CFBLR + lofs, LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
845 LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
846 1195
847 /* Specifies the constant alpha value */1196 /* Specifies the constant alpha value */
848 val = newstate->alpha >> 8;1197 val = newstate->alpha >> 8;
849 reg_update_bits(ldev->regs, LTDC_L1CACR + lofs, LXCACR_CONSTA, val);1198 regmap_write_bits(ldev->regmap, LTDC_L1CACR + lofs, LXCACR_CONSTA, val);
850 1199
851 /* Specifies the blending factors */1200 /* Specifies the blending factors */
852 val = BF1_PAXCA | BF2_1PAXCA;1201 val = BF1_PAXCA | BF2_1PAXCA;
@@ -858,24 +1207,98 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, · 5 unmodified lines
858 plane->type != DRM_PLANE_TYPE_PRIMARY)1207 plane->type != DRM_PLANE_TYPE_PRIMARY)
859 val = BF1_PAXCA | BF2_1PAXCA;1208 val = BF1_PAXCA | BF2_1PAXCA;
860 1209
861 reg_update_bits(ldev->regs, LTDC_L1BFCR + lofs,1210 regmap_write_bits(ldev->regmap, LTDC_L1BFCR + lofs, LXBFCR_BF2 | LXBFCR_BF1, val);
862 LXBFCR_BF2 | LXBFCR_BF1, val);
863 1211
864 /* Configures the frame buffer line number */1212 /* Configures the frame buffer line number */
865 val = y1 - y0 + 1;1213 line_number = y1 - y0 + 1;
866 reg_update_bits(ldev->regs, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, val);1214 regmap_write_bits(ldev->regmap, LTDC_L1CFBLNR + lofs, LXCFBLNR_CFBLN, line_number);
867 1215
868 /* Sets the FB address */1216 /* Sets the FB address */
869 paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 0);1217 paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 0);
870 1218
871 DRM_DEBUG_DRIVER("fb: phys 0x%08x", paddr);1219 DRM_DEBUG_DRIVER("fb: phys 0x%08x", paddr);
872 reg_write(ldev->regs, LTDC_L1CFBAR + lofs, paddr);1220 regmap_write(ldev->regmap, LTDC_L1CFBAR + lofs, paddr);
1221
1222 if (ldev->caps.ycbcr_input) {
1223 if (fb->format->is_yuv) {
1224 switch (fb->format->format) {
1225 case DRM_FORMAT_NV12:
1226 case DRM_FORMAT_NV21:
1227 /* Configure the auxiliary frame buffer address 0 & 1 */
1228 paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1);
1229 regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr);
1230 regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr + 1);
1231
1232 /* Configure the buffer length */
1233 val = ((pitch_in_bytes << 16) | line_length);
1234 regmap_write(ldev->regmap, LTDC_L1AFBLR + lofs, val);
1235
1236 /* Configure the frame buffer line number */
1237 val = (line_number >> 1);
1238 regmap_write(ldev->regmap, LTDC_L1AFBLNR + lofs, val);
1239 break;
1240 case DRM_FORMAT_YUV420:
1241 /* Configure the auxiliary frame buffer address 0 */
1242 paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1);
1243 regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr);
1244
1245 /* Configure the auxiliary frame buffer address 1 */
1246 paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2);
1247 regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr);
1248
1249 line_length = ((fb->format->cpp[0] * (x1 - x0 + 1)) >> 1) +
1250 (ldev->caps.bus_width >> 3) - 1;
1251
1252 /* Configure the buffer length */
1253 val = (((pitch_in_bytes >> 1) << 16) | line_length);
1254 regmap_write(ldev->regmap, LTDC_L1AFBLR + lofs, val);
1255
1256 /* Configure the frame buffer line number */
1257 val = (line_number >> 1);
1258 regmap_write(ldev->regmap, LTDC_L1AFBLNR + lofs, val);
1259 break;
1260 case DRM_FORMAT_YVU420:
1261 /* Configure the auxiliary frame buffer address 0 */
1262 paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2);
1263 regmap_write(ldev->regmap, LTDC_L1AFBA0R + lofs, paddr);
1264
1265 /* Configure the auxiliary frame buffer address 1 */
1266 paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1);
1267 regmap_write(ldev->regmap, LTDC_L1AFBA1R + lofs, paddr);
1268
1269 line_length = ((fb->format->cpp[0] * (x1 - x0 + 1)) >> 1) +
1270 (ldev->caps.bus_width >> 3) - 1;
1271
1272 /* Configure the buffer length */
1273 val = (((pitch_in_bytes >> 1) << 16) | line_length);
1274 regmap_write(ldev->regmap, LTDC_L1AFBLR + lofs, val);
1275
1276 /* Configure the frame buffer line number */
1277 val = (line_number >> 1);
1278 regmap_write(ldev->regmap, LTDC_L1AFBLNR + lofs, val);
1279 break;
1280 }
1281
1282 /* Configure YCbC conversion coefficient */
1283 ltdc_set_ycbcr_coeffs(plane);
1284
1285 /* Configure YCbCr format and enable/disable conversion */
1286 ltdc_set_ycbcr_config(plane, fb->format->format);
1287 } else {
1288 /* disable ycbcr conversion */
1289 regmap_write(ldev->regmap, LTDC_L1PCR + lofs, 0);
1290 }
1291 }
873 1292
874 /* Enable layer and CLUT if needed */1293 /* Enable layer and CLUT if needed */
875 val = fb->format->format == DRM_FORMAT_C8 ? LXCR_CLUTEN : 0;1294 val = fb->format->format == DRM_FORMAT_C8 ? LXCR_CLUTEN : 0;
876 val |= LXCR_LEN;1295 val |= LXCR_LEN;
877 reg_update_bits(ldev->regs, LTDC_L1CR + lofs,1296 regmap_write_bits(ldev->regmap, LTDC_L1CR + lofs, LXCR_LEN | LXCR_CLUTEN, val);
878 LXCR_LEN | LXCR_CLUTEN, val);1297
1298 /* Commit shadow registers = update plane at next vblank */
1299 if (ldev->caps.plane_reg_shadow)
1300 regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs,
1301 LXRCR_IMR | LXRCR_VBR | LXRCR_GRMSK, LXRCR_VBR);
879 1302
880 ldev->plane_fpsi[plane->index].counter++;1303 ldev->plane_fpsi[plane->index].counter++;
881 1304
@@ -900,7 +1323,12 @@ static void ltdc_plane_atomic_disable(struct drm_plane *plane, · 18 unmodified lines
900 u32 lofs = plane->index * LAY_OFS;1323 u32 lofs = plane->index * LAY_OFS;
901 1324
902 /* disable layer */1325 /* disable layer */
903 reg_clear(ldev->regs, LTDC_L1CR + lofs, LXCR_LEN);1326 regmap_write_bits(ldev->regmap, LTDC_L1CR + lofs, LXCR_LEN, 0);
1327
1328 /* Commit shadow registers = update plane at next vblank */
1329 if (ldev->caps.plane_reg_shadow)
1330 regmap_write_bits(ldev->regmap, LTDC_L1RCR + lofs,
1331 LXRCR_IMR | LXRCR_VBR | LXRCR_GRMSK, LXRCR_VBR);
904 1332
905 DRM_DEBUG_DRIVER("CRTC:%d plane:%d\n",1333 DRM_DEBUG_DRIVER("CRTC:%d plane:%d\n",
906 oldstate->crtc->base.id, plane->base.id);1334 oldstate->crtc->base.id, plane->base.id);
@@ -925,16 +1353,6 @@ static void ltdc_plane_atomic_print_state(struct drm_printer *p, · 18 unmodified lines
925 fpsi->counter = 0;1353 fpsi->counter = 0;
926}1354}
927 1355
928static bool ltdc_plane_format_mod_supported(struct drm_plane *plane,
929 u32 format,
930 u64 modifier)
931{
932 if (modifier == DRM_FORMAT_MOD_LINEAR)
933 return true;
934
935 return false;
936}
937
938static const struct drm_plane_funcs ltdc_plane_funcs = {1356static const struct drm_plane_funcs ltdc_plane_funcs = {
939 .update_plane = drm_atomic_helper_update_plane,1357 .update_plane = drm_atomic_helper_update_plane,
940 .disable_plane = drm_atomic_helper_disable_plane,1358 .disable_plane = drm_atomic_helper_disable_plane,
@@ -943,7 +1361,6 @@ static const struct drm_plane_funcs ltdc_plane_funcs = { · 2 unmodified lines
943 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,1361 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
944 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,1362 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
945 .atomic_print_state = ltdc_plane_atomic_print_state,1363 .atomic_print_state = ltdc_plane_atomic_print_state,
946 .format_mod_supported = ltdc_plane_format_mod_supported,
947};1364};
948 1365
949static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {1366static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = {
@@ -953,36 +1370,58 @@ static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = { · 3 unmodified lines
953};1370};
954 1371
955static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,1372static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
956 enum drm_plane_type type)1373 enum drm_plane_type type,
1374 int index)
957{1375{
958 unsigned long possible_crtcs = CRTC_MASK;1376 unsigned long possible_crtcs = CRTC_MASK;
959 struct ltdc_device *ldev = ddev->dev_private;1377 struct ltdc_device *ldev = ddev->dev_private;
960 struct device *dev = ddev->dev;1378 struct device *dev = ddev->dev;
961 struct drm_plane *plane;1379 struct drm_plane *plane;
962 unsigned int i, nb_fmt = 0;1380 unsigned int i, nb_fmt = 0;
963 u32 formats[NB_PF * 2];1381 u32 *formats;
964 u32 drm_fmt, drm_fmt_no_alpha;1382 u32 drm_fmt;
965 const u64 *modifiers = ltdc_format_modifiers;1383 const u64 *modifiers = ltdc_format_modifiers;
1384 u32 lofs = index * LAY_OFS;
1385 u32 val;
966 int ret;1386 int ret;
967 1387
968 /* Get supported pixel formats */1388 /* Allocate the biggest size according to supported color formats */
969 for (i = 0; i < NB_PF; i++) {1389 formats = devm_kzalloc(dev, (ldev->caps.pix_fmt_nb +
970 drm_fmt = to_drm_pixelformat(ldev->caps.pix_fmt_hw[i]);1390 ARRAY_SIZE(ltdc_drm_fmt_ycbcr_cp) +
971 if (!drm_fmt)1391 ARRAY_SIZE(ltdc_drm_fmt_ycbcr_sp) +
972 continue;1392 ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp)) *
973 formats[nb_fmt++] = drm_fmt;1393 sizeof(*formats), GFP_KERNEL);
974 1394
975 /* Add the no-alpha related format if any & supported */1395 for (i = 0; i < ldev->caps.pix_fmt_nb; i++) {
976 drm_fmt_no_alpha = get_pixelformat_without_alpha(drm_fmt);1396 drm_fmt = ldev->caps.pix_fmt_drm[i];
977 if (!drm_fmt_no_alpha)
978 continue;
979 1397
980 /* Manage hw-specific capabilities */1398 /* Manage hw-specific capabilities */
981 if (ldev->caps.non_alpha_only_l1 &&1399 if (ldev->caps.non_alpha_only_l1)
982 type != DRM_PLANE_TYPE_PRIMARY)1400 /* XR24 & RX24 like formats supported only on primary layer */
983 continue;1401 if (type != DRM_PLANE_TYPE_PRIMARY && is_xrgb(drm_fmt))
1402 continue;
984 1403
985 formats[nb_fmt++] = drm_fmt_no_alpha;1404 formats[nb_fmt++] = drm_fmt;
1405 }
1406
1407 /* Add YCbCr supported pixel formats */
1408 if (ldev->caps.ycbcr_input) {
1409 regmap_read(ldev->regmap, LTDC_L1C1R + lofs, &val);
1410 if (val & LXCR_C1R_YIA) {
1411 memcpy(&formats[nb_fmt], ltdc_drm_fmt_ycbcr_cp,
1412 ARRAY_SIZE(ltdc_drm_fmt_ycbcr_cp) * sizeof(*formats));
1413 nb_fmt += ARRAY_SIZE(ltdc_drm_fmt_ycbcr_cp);
1414 }
1415 if (val & LXCR_C1R_YSPA) {
1416 memcpy(&formats[nb_fmt], ltdc_drm_fmt_ycbcr_sp,
1417 ARRAY_SIZE(ltdc_drm_fmt_ycbcr_sp) * sizeof(*formats));
1418 nb_fmt += ARRAY_SIZE(ltdc_drm_fmt_ycbcr_sp);
1419 }
1420 if (val & LXCR_C1R_YFPA) {
1421 memcpy(&formats[nb_fmt], ltdc_drm_fmt_ycbcr_fp,
1422 ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp) * sizeof(*formats));
1423 nb_fmt += ARRAY_SIZE(ltdc_drm_fmt_ycbcr_fp);
1424 }
986 }1425 }
987 1426
988 plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);1427 plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);
@@ -995,6 +1434,17 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, · 6 unmodified lines
995 if (ret < 0)1434 if (ret < 0)
996 return NULL;1435 return NULL;
997 1436
1437 if (ldev->caps.ycbcr_input) {
1438 if (val & (LXCR_C1R_YIA | LXCR_C1R_YSPA | LXCR_C1R_YFPA))
1439 drm_plane_create_color_properties(plane,
1440 BIT(DRM_COLOR_YCBCR_BT601) |
1441 BIT(DRM_COLOR_YCBCR_BT709),
1442 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1443 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1444 DRM_COLOR_YCBCR_BT601,
1445 DRM_COLOR_YCBCR_LIMITED_RANGE);
1446 }
1447
998 drm_plane_helper_add(plane, &ltdc_plane_helper_funcs);1448 drm_plane_helper_add(plane, &ltdc_plane_helper_funcs);
999 1449
1000 drm_plane_create_alpha_property(plane);1450 drm_plane_create_alpha_property(plane);
@@ -1020,7 +1470,7 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) · 19 unmodified lines
1020 unsigned int i;1470 unsigned int i;
1021 int ret;1471 int ret;
1022 1472
1023 primary = ltdc_plane_create(ddev, DRM_PLANE_TYPE_PRIMARY);1473 primary = ltdc_plane_create(ddev, DRM_PLANE_TYPE_PRIMARY, 0);
1024 if (!primary) {1474 if (!primary) {
1025 DRM_ERROR("Can not create primary plane\n");1475 DRM_ERROR("Can not create primary plane\n");
1026 return -EINVAL;1476 return -EINVAL;
@@ -1044,7 +1494,7 @@ static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc) · 17 unmodified lines
1044 1494
1045 /* Add planes. Note : the first layer is used by primary plane */1495 /* Add planes. Note : the first layer is used by primary plane */
1046 for (i = 1; i < ldev->caps.nb_layers; i++) {1496 for (i = 1; i < ldev->caps.nb_layers; i++) {
1047 overlay = ltdc_plane_create(ddev, DRM_PLANE_TYPE_OVERLAY);1497 overlay = ltdc_plane_create(ddev, DRM_PLANE_TYPE_OVERLAY, i);
1048 if (!overlay) {1498 if (!overlay) {
1049 ret = -ENOMEM;1499 ret = -ENOMEM;
1050 DRM_ERROR("Can not create overlay plane %d\n", i);1500 DRM_ERROR("Can not create overlay plane %d\n", i);
@@ -1068,7 +1518,7 @@ static void ltdc_encoder_disable(struct drm_encoder *encoder) · 17 unmodified lines
1068 DRM_DEBUG_DRIVER("\n");1518 DRM_DEBUG_DRIVER("\n");
1069 1519
1070 /* Disable LTDC */1520 /* Disable LTDC */
1071 reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN);1521 regmap_clear_bits(ldev->regmap, LTDC_GCR, GCR_LTDCEN);
1072 1522
1073 /* Set to sleep state the pinctrl whatever type of encoder */1523 /* Set to sleep state the pinctrl whatever type of encoder */
1074 pinctrl_pm_select_sleep_state(ddev->dev);1524 pinctrl_pm_select_sleep_state(ddev->dev);
@@ -1082,7 +1532,7 @@ static void ltdc_encoder_enable(struct drm_encoder *encoder) · 7 unmodified lines
1082 DRM_DEBUG_DRIVER("\n");1532 DRM_DEBUG_DRIVER("\n");
1083 1533
1084 /* Enable LTDC */1534 /* Enable LTDC */
1085 reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);1535 regmap_set_bits(ldev->regmap, LTDC_GCR, GCR_LTDCEN);
1086}1536}
1087 1537
1088static void ltdc_encoder_mode_set(struct drm_encoder *encoder,1538static void ltdc_encoder_mode_set(struct drm_encoder *encoder,
@@ -1145,21 +1595,25 @@ static int ltdc_get_caps(struct drm_device *ddev) · 56 unmodified lines
1145 * at least 1 layer must be managed & the number of layers1595 * at least 1 layer must be managed & the number of layers
1146 * must not exceed LTDC_MAX_LAYER1596 * must not exceed LTDC_MAX_LAYER
1147 */1597 */
1148 lcr = reg_read(ldev->regs, LTDC_LCR);1598 regmap_read(ldev->regmap, LTDC_LCR, &lcr);
1149 1599
1150 ldev->caps.nb_layers = clamp((int)lcr, 1, LTDC_MAX_LAYER);1600 ldev->caps.nb_layers = clamp((int)lcr, 1, LTDC_MAX_LAYER);
1151 1601
1152 /* set data bus width */1602 /* set data bus width */
1153 gc2r = reg_read(ldev->regs, LTDC_GC2R);1603 regmap_read(ldev->regmap, LTDC_GC2R, &gc2r);
1154 bus_width_log2 = (gc2r & GC2R_BW) >> 4;1604 bus_width_log2 = (gc2r & GC2R_BW) >> 4;
1155 ldev->caps.bus_width = 8 << bus_width_log2;1605 ldev->caps.bus_width = 8 << bus_width_log2;
1156 ldev->caps.hw_version = reg_read(ldev->regs, LTDC_IDR);1606 regmap_read(ldev->regmap, LTDC_IDR, &ldev->caps.hw_version);
1157 1607
1158 switch (ldev->caps.hw_version) {1608 switch (ldev->caps.hw_version) {
1159 case HWVER_10200:1609 case HWVER_10200:
1160 case HWVER_10300:1610 case HWVER_10300:
1161 ldev->caps.reg_ofs = REG_OFS_NONE;1611 ldev->caps.layer_ofs = LAY_OFS_0;
1612 ldev->caps.layer_regs = ltdc_layer_regs_a0;
1162 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a0;1613 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a0;
1614 ldev->caps.pix_fmt_drm = ltdc_drm_fmt_a0;
1615 ldev->caps.pix_fmt_nb = ARRAY_SIZE(ltdc_drm_fmt_a0);
1616 ldev->caps.pix_fmt_flex = false;
1163 /*1617 /*
1164 * Hw older versions support non-alpha color formats derived1618 * Hw older versions support non-alpha color formats derived
1165 * from native alpha color formats only on the primary layer.1619 * from native alpha color formats only on the primary layer.
@@ -1172,13 +1626,37 @@ static int ltdc_get_caps(struct drm_device *ddev) · 6 unmodified lines
1172 if (ldev->caps.hw_version == HWVER_10200)1626 if (ldev->caps.hw_version == HWVER_10200)
1173 ldev->caps.pad_max_freq_hz = 65000000;1627 ldev->caps.pad_max_freq_hz = 65000000;
1174 ldev->caps.nb_irq = 2;1628 ldev->caps.nb_irq = 2;
1629 ldev->caps.ycbcr_input = false;
1630 ldev->caps.ycbcr_output = false;
1631 ldev->caps.plane_reg_shadow = false;
1175 break;1632 break;
1176 case HWVER_20101:1633 case HWVER_20101:
1177 ldev->caps.reg_ofs = REG_OFS_4;1634 ldev->caps.layer_ofs = LAY_OFS_0;
1635 ldev->caps.layer_regs = ltdc_layer_regs_a1;
1178 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a1;1636 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a1;
1637 ldev->caps.pix_fmt_drm = ltdc_drm_fmt_a1;
1638 ldev->caps.pix_fmt_nb = ARRAY_SIZE(ltdc_drm_fmt_a1);
1639 ldev->caps.pix_fmt_flex = false;
1179 ldev->caps.non_alpha_only_l1 = false;1640 ldev->caps.non_alpha_only_l1 = false;
1180 ldev->caps.pad_max_freq_hz = 150000000;1641 ldev->caps.pad_max_freq_hz = 150000000;
1181 ldev->caps.nb_irq = 4;1642 ldev->caps.nb_irq = 4;
1643 ldev->caps.ycbcr_input = false;
1644 ldev->caps.ycbcr_output = false;
1645 ldev->caps.plane_reg_shadow = false;
1646 break;
1647 case HWVER_40100:
1648 ldev->caps.layer_ofs = LAY_OFS_1;
1649 ldev->caps.layer_regs = ltdc_layer_regs_a2;
1650 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a2;
1651 ldev->caps.pix_fmt_drm = ltdc_drm_fmt_a2;
1652 ldev->caps.pix_fmt_nb = ARRAY_SIZE(ltdc_drm_fmt_a2);
1653 ldev->caps.pix_fmt_flex = true;
1654 ldev->caps.non_alpha_only_l1 = false;
1655 ldev->caps.pad_max_freq_hz = 90000000;
1656 ldev->caps.nb_irq = 2;
1657 ldev->caps.ycbcr_input = true;
1658 ldev->caps.ycbcr_output = true;
1659 ldev->caps.plane_reg_shadow = true;
1182 break;1660 break;
1183 default:1661 default:
1184 return -ENODEV;1662 return -ENODEV;
@@ -1296,9 +1774,15 @@ int ltdc_load(struct drm_device *ddev) · 111 unmodified lines
1296 goto err;1774 goto err;
1297 }1775 }
1298 1776
1777 ldev->regmap = devm_regmap_init_mmio(&pdev->dev, ldev->regs, &stm32_ltdc_regmap_cfg);
1778 if (IS_ERR(ldev->regmap)) {
1779 DRM_ERROR("Unable to regmap ltdc registers\n");
1780 ret = PTR_ERR(ldev->regmap);
1781 goto err;
1782 }
1783
1299 /* Disable interrupts */1784 /* Disable interrupts */
1300 reg_clear(ldev->regs, LTDC_IER,1785 regmap_clear_bits(ldev->regmap, LTDC_IER, IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE);
1301 IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE);
1302 1786
1303 ret = ltdc_get_caps(ddev);1787 ret = ltdc_get_caps(ddev);
1304 if (ret) {1788 if (ret) {
drivers/gpu/drm/stm/ltdc.h+10−2
@@ -14,12 +14,19 @@ · 13 unmodified lines
14struct ltdc_caps {14struct ltdc_caps {
15 u32 hw_version; /* hardware version */15 u32 hw_version; /* hardware version */
16 u32 nb_layers; /* number of supported layers */16 u32 nb_layers; /* number of supported layers */
17 u32 reg_ofs; /* register offset for applicable regs */17 u32 layer_ofs; /* layer offset for applicable regs */
18 const u32 *layer_regs; /* layer register offset */
18 u32 bus_width; /* bus width (32 or 64 bits) */19 u32 bus_width; /* bus width (32 or 64 bits) */
19 const u32 *pix_fmt_hw; /* supported pixel formats */20 const u32 *pix_fmt_hw; /* supported hw pixel formats */
21 const u32 *pix_fmt_drm; /* supported drm pixel formats */
22 int pix_fmt_nb; /* number of pixel format */
23 bool pix_fmt_flex; /* pixel format flexibility supported */
20 bool non_alpha_only_l1; /* non-native no-alpha formats on layer 1 */24 bool non_alpha_only_l1; /* non-native no-alpha formats on layer 1 */
21 int pad_max_freq_hz; /* max frequency supported by pad */25 int pad_max_freq_hz; /* max frequency supported by pad */
22 int nb_irq; /* number of hardware interrupts */26 int nb_irq; /* number of hardware interrupts */
27 bool ycbcr_input; /* ycbcr input converter supported */
28 bool ycbcr_output; /* ycbcr output converter supported */
29 bool plane_reg_shadow; /* plane shadow registers ability */
23};30};
24 31
25#define LTDC_MAX_LAYER 432#define LTDC_MAX_LAYER 4
@@ -31,6 +38,7 @@ struct fps_info { · 5 unmodified lines
31 38
32struct ltdc_device {39struct ltdc_device {
33 void __iomem *regs;40 void __iomem *regs;
41 struct regmap *regmap;
34 struct clk *pixel_clk; /* lcd pixel clock */42 struct clk *pixel_clk; /* lcd pixel clock */
35 struct mutex err_lock; /* protecting error_status */43 struct mutex err_lock; /* protecting error_status */
36 struct ltdc_caps caps;44 struct ltdc_caps caps;
drivers/gpu/drm/tegra/Kconfig+1−0
@@ -5,6 +5,7 @@ config DRM_TEGRA · 4 unmodified lines
5 depends on COMMON_CLK5 depends on COMMON_CLK
6 depends on DRM6 depends on DRM
7 depends on OF7 depends on OF
8 select DRM_DP_HELPER
8 select DRM_KMS_HELPER9 select DRM_KMS_HELPER
9 select DRM_MIPI_DSI10 select DRM_MIPI_DSI
10 select DRM_PANEL11 select DRM_PANEL
drivers/gpu/drm/tegra/dp.c+1−1
@@ -5,7 +5,7 @@ · 4 unmodified lines
5 */5 */
6 6
7#include <drm/drm_crtc.h>7#include <drm/drm_crtc.h>
8#include <drm/drm_dp_helper.h>8#include <drm/dp/drm_dp_helper.h>
9#include <drm/drm_print.h>9#include <drm/drm_print.h>
10 10
11#include "dp.h"11#include "dp.h"
drivers/gpu/drm/tegra/dpaux.c+1−1
@@ -18,7 +18,7 @@ · 17 unmodified lines
18#include <linux/reset.h>18#include <linux/reset.h>
19#include <linux/workqueue.h>19#include <linux/workqueue.h>
20 20
21#include <drm/drm_dp_helper.h>21#include <drm/dp/drm_dp_helper.h>
22#include <drm/drm_panel.h>22#include <drm/drm_panel.h>
23 23
24#include "dp.h"24#include "dp.h"
drivers/gpu/drm/tegra/sor.c+1−1
@@ -18,7 +18,7 @@ · 17 unmodified lines
18 18
19#include <drm/drm_atomic_helper.h>19#include <drm/drm_atomic_helper.h>
20#include <drm/drm_debugfs.h>20#include <drm/drm_debugfs.h>
21#include <drm/drm_dp_helper.h>21#include <drm/dp/drm_dp_helper.h>
22#include <drm/drm_file.h>22#include <drm/drm_file.h>
23#include <drm/drm_panel.h>23#include <drm/drm_panel.h>
24#include <drm/drm_scdc_helper.h>24#include <drm/drm_scdc_helper.h>
drivers/gpu/drm/tilcdc/tilcdc_drv.c+1−3
@@ -60,8 +60,6 @@ void tilcdc_module_cleanup(struct tilcdc_module *mod) · 59 unmodified lines
60 list_del(&mod->list);60 list_del(&mod->list);
61}61}
62 62
63static struct of_device_id tilcdc_of_match[];
64
65static int tilcdc_atomic_check(struct drm_device *dev,63static int tilcdc_atomic_check(struct drm_device *dev,
66 struct drm_atomic_state *state)64 struct drm_atomic_state *state)
67{65{
@@ -587,7 +585,7 @@ static int tilcdc_pdev_remove(struct platform_device *pdev) · 519 unmodified lines
587 return 0;585 return 0;
588}586}
589 587
590static struct of_device_id tilcdc_of_match[] = {588static const struct of_device_id tilcdc_of_match[] = {
591 { .compatible = "ti,am33xx-tilcdc", },589 { .compatible = "ti,am33xx-tilcdc", },
592 { .compatible = "ti,da850-tilcdc", },590 { .compatible = "ti,da850-tilcdc", },
593 { },591 { },
drivers/gpu/drm/tiny/bochs.c+2−18
@@ -10,6 +10,7 @@ · 9 unmodified lines
10#include <drm/drm_gem_framebuffer_helper.h>10#include <drm/drm_gem_framebuffer_helper.h>
11#include <drm/drm_gem_vram_helper.h>11#include <drm/drm_gem_vram_helper.h>
12#include <drm/drm_managed.h>12#include <drm/drm_managed.h>
13#include <drm/drm_module.h>
13#include <drm/drm_probe_helper.h>14#include <drm/drm_probe_helper.h>
14#include <drm/drm_simple_kms_helper.h>15#include <drm/drm_simple_kms_helper.h>
15 16
@@ -716,24 +717,7 @@ static struct pci_driver bochs_pci_driver = { · 700 unmodified lines
716/* ---------------------------------------------------------------------- */717/* ---------------------------------------------------------------------- */
717/* module init/exit */718/* module init/exit */
718 719
719static int __init bochs_init(void)720drm_module_pci_driver_if_modeset(bochs_pci_driver, bochs_modeset);
720{
721 if (drm_firmware_drivers_only() && bochs_modeset == -1)
722 return -EINVAL;
723
724 if (bochs_modeset == 0)
725 return -EINVAL;
726
727 return pci_register_driver(&bochs_pci_driver);
728}
729
730static void __exit bochs_exit(void)
731{
732 pci_unregister_driver(&bochs_pci_driver);
733}
734
735module_init(bochs_init);
736module_exit(bochs_exit);
737 721
738MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);722MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
739MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");723MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
drivers/gpu/drm/tiny/cirrus.c+2−15
@@ -39,6 +39,7 @@ · 38 unmodified lines
39#include <drm/drm_ioctl.h>39#include <drm/drm_ioctl.h>
40#include <drm/drm_managed.h>40#include <drm/drm_managed.h>
41#include <drm/drm_modeset_helper_vtables.h>41#include <drm/drm_modeset_helper_vtables.h>
42#include <drm/drm_module.h>
42#include <drm/drm_probe_helper.h>43#include <drm/drm_probe_helper.h>
43#include <drm/drm_simple_kms_helper.h>44#include <drm/drm_simple_kms_helper.h>
44 45
@@ -633,21 +634,7 @@ static struct pci_driver cirrus_pci_driver = { · 588 unmodified lines
633 .remove = cirrus_pci_remove,634 .remove = cirrus_pci_remove,
634};635};
635 636
636static int __init cirrus_init(void)637drm_module_pci_driver(cirrus_pci_driver)
637{
638 if (drm_firmware_drivers_only())
639 return -EINVAL;
640
641 return pci_register_driver(&cirrus_pci_driver);
642}
643
644static void __exit cirrus_exit(void)
645{
646 pci_unregister_driver(&cirrus_pci_driver);
647}
648
649module_init(cirrus_init);
650module_exit(cirrus_exit);
651 638
652MODULE_DEVICE_TABLE(pci, pciidlist);639MODULE_DEVICE_TABLE(pci, pciidlist);
653MODULE_LICENSE("GPL");640MODULE_LICENSE("GPL");
drivers/gpu/drm/tiny/simpledrm.c+17−5
@@ -526,21 +526,33 @@ static int simpledrm_device_init_mm(struct simpledrm_device *sdev) · 525 unmodified lines
526{526{
527 struct drm_device *dev = &sdev->dev;527 struct drm_device *dev = &sdev->dev;
528 struct platform_device *pdev = sdev->pdev;528 struct platform_device *pdev = sdev->pdev;
529 struct resource *mem;529 struct resource *res, *mem;
530 void __iomem *screen_base;530 void __iomem *screen_base;
531 int ret;531 int ret;
532 532
533 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);533 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
534 if (!mem)534 if (!res)
535 return -EINVAL;535 return -EINVAL;
536 536
537 ret = devm_aperture_acquire_from_firmware(dev, mem->start, resource_size(mem));537 ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res));
538 if (ret) {538 if (ret) {
539 drm_err(dev, "could not acquire memory range %pr: error %d\n",539 drm_err(dev, "could not acquire memory range %pr: error %d\n",
540 mem, ret);540 res, ret);
541 return ret;541 return ret;
542 }542 }
543 543
544 mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
545 sdev->dev.driver->name);
546 if (!mem) {
547 /*
548 * We cannot make this fatal. Sometimes this comes from magic
549 * spaces our resource handlers simply don't know about. Use
550 * the I/O-memory resource as-is and try to map that instead.
551 */
552 drm_warn(dev, "could not acquire memory region %pr\n", res);
553 mem = res;
554 }
555
544 screen_base = devm_ioremap_wc(&pdev->dev, mem->start,556 screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
545 resource_size(mem));557 resource_size(mem));
546 if (!screen_base)558 if (!screen_base)
drivers/gpu/drm/ttm/ttm_bo_util.c+5−2
@@ -241,6 +241,11 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, · 240 unmodified lines
241 if (bo->type != ttm_bo_type_sg)241 if (bo->type != ttm_bo_type_sg)
242 fbo->base.base.resv = &fbo->base.base._resv;242 fbo->base.base.resv = &fbo->base.base._resv;
243 243
244 if (fbo->base.resource) {
245 ttm_resource_set_bo(fbo->base.resource, &fbo->base);
246 bo->resource = NULL;
247 }
248
244 dma_resv_init(&fbo->base.base._resv);249 dma_resv_init(&fbo->base.base._resv);
245 fbo->base.base.dev = NULL;250 fbo->base.base.dev = NULL;
246 ret = dma_resv_trylock(&fbo->base.base._resv);251 ret = dma_resv_trylock(&fbo->base.base._resv);
@@ -509,7 +514,6 @@ static int ttm_bo_move_to_ghost(struct ttm_buffer_object *bo, · 262 unmodified lines
509 ghost_obj->ttm = NULL;514 ghost_obj->ttm = NULL;
510 else515 else
511 bo->ttm = NULL;516 bo->ttm = NULL;
512 bo->resource = NULL;
513 517
514 dma_resv_unlock(&ghost_obj->base._resv);518 dma_resv_unlock(&ghost_obj->base._resv);
515 ttm_bo_put(ghost_obj);519 ttm_bo_put(ghost_obj);
@@ -637,7 +641,6 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) · 121 unmodified lines
637 dma_resv_unlock(&ghost->base._resv);641 dma_resv_unlock(&ghost->base._resv);
638 ttm_bo_put(ghost);642 ttm_bo_put(ghost);
639 bo->ttm = ttm;643 bo->ttm = ttm;
640 bo->resource = NULL;
641 ttm_bo_assign_mem(bo, sys_res);644 ttm_bo_assign_mem(bo, sys_res);
642 return 0;645 return 0;
643 646
drivers/gpu/drm/ttm/ttm_range_manager.c+3−1
@@ -89,6 +89,7 @@ static int ttm_range_man_alloc(struct ttm_resource_manager *man, · 88 unmodified lines
89 spin_unlock(&rman->lock);89 spin_unlock(&rman->lock);
90 90
91 if (unlikely(ret)) {91 if (unlikely(ret)) {
92 ttm_resource_fini(man, *res);
92 kfree(node);93 kfree(node);
93 return ret;94 return ret;
94 }95 }
@@ -108,6 +109,7 @@ static void ttm_range_man_free(struct ttm_resource_manager *man, · 13 unmodified lines
108 drm_mm_remove_node(&node->mm_nodes[0]);109 drm_mm_remove_node(&node->mm_nodes[0]);
109 spin_unlock(&rman->lock);110 spin_unlock(&rman->lock);
110 111
112 ttm_resource_fini(man, res);
111 kfree(node);113 kfree(node);
112}114}
113 115
@@ -156,7 +158,7 @@ int ttm_range_man_init_nocheck(struct ttm_device *bdev, · 42 unmodified lines
156 158
157 man->func = &ttm_range_manager_func;159 man->func = &ttm_range_manager_func;
158 160
159 ttm_resource_manager_init(man, p_size);161 ttm_resource_manager_init(man, bdev, p_size);
160 162
161 drm_mm_init(&rman->mm, 0, p_size);163 drm_mm_init(&rman->mm, 0, p_size);
162 spin_lock_init(&rman->lock);164 spin_lock_init(&rman->lock);
drivers/gpu/drm/ttm/ttm_resource.c+35−0
@@ -29,6 +29,14 @@ · 28 unmodified lines
29#include <drm/ttm/ttm_resource.h>29#include <drm/ttm/ttm_resource.h>
30#include <drm/ttm/ttm_bo_driver.h>30#include <drm/ttm/ttm_bo_driver.h>
31 31
32/**
33 * ttm_resource_init - resource object constructure
34 * @bo: buffer object this resources is allocated for
35 * @place: placement of the resource
36 * @res: the resource object to inistilize
37 *
38 * Initialize a new resource object. Counterpart of &ttm_resource_fini.
39 */
32void ttm_resource_init(struct ttm_buffer_object *bo,40void ttm_resource_init(struct ttm_buffer_object *bo,
33 const struct ttm_place *place,41 const struct ttm_place *place,
34 struct ttm_resource *res)42 struct ttm_resource *res)
@@ -41,9 +49,25 @@ void ttm_resource_init(struct ttm_buffer_object *bo, · 6 unmodified lines
41 res->bus.offset = 0;49 res->bus.offset = 0;
42 res->bus.is_iomem = false;50 res->bus.is_iomem = false;
43 res->bus.caching = ttm_cached;51 res->bus.caching = ttm_cached;
52 res->bo = bo;
44}53}
45EXPORT_SYMBOL(ttm_resource_init);54EXPORT_SYMBOL(ttm_resource_init);
46 55
56/**
57 * ttm_resource_fini - resource destructor
58 * @man: the resource manager this resource belongs to
59 * @res: the resource to clean up
60 *
61 * Should be used by resource manager backends to clean up the TTM resource
62 * objects before freeing the underlying structure. Counterpart of
63 * &ttm_resource_init
64 */
65void ttm_resource_fini(struct ttm_resource_manager *man,
66 struct ttm_resource *res)
67{
68}
69EXPORT_SYMBOL(ttm_resource_fini);
70
47int ttm_resource_alloc(struct ttm_buffer_object *bo,71int ttm_resource_alloc(struct ttm_buffer_object *bo,
48 const struct ttm_place *place,72 const struct ttm_place *place,
49 struct ttm_resource **res_ptr)73 struct ttm_resource **res_ptr)
@@ -116,20 +140,31 @@ bool ttm_resource_compat(struct ttm_resource *res, · 66 unmodified lines
116}140}
117EXPORT_SYMBOL(ttm_resource_compat);141EXPORT_SYMBOL(ttm_resource_compat);
118 142
143void ttm_resource_set_bo(struct ttm_resource *res,
144 struct ttm_buffer_object *bo)
145{
146 spin_lock(&bo->bdev->lru_lock);
147 res->bo = bo;
148 spin_unlock(&bo->bdev->lru_lock);
149}
150
119/**151/**
120 * ttm_resource_manager_init152 * ttm_resource_manager_init
121 *153 *
122 * @man: memory manager object to init154 * @man: memory manager object to init
155 * @bdev: ttm device this manager belongs to
123 * @p_size: size managed area in pages.156 * @p_size: size managed area in pages.
124 *157 *
125 * Initialise core parts of a manager object.158 * Initialise core parts of a manager object.
126 */159 */
127void ttm_resource_manager_init(struct ttm_resource_manager *man,160void ttm_resource_manager_init(struct ttm_resource_manager *man,
161 struct ttm_device *bdev,
128 unsigned long p_size)162 unsigned long p_size)
129{163{
130 unsigned i;164 unsigned i;
131 165
132 spin_lock_init(&man->move_lock);166 spin_lock_init(&man->move_lock);
167 man->bdev = bdev;
133 man->size = p_size;168 man->size = p_size;
134 169
135 for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i)170 for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i)
drivers/gpu/drm/ttm/ttm_sys_manager.c+2−1
@@ -23,6 +23,7 @@ static int ttm_sys_man_alloc(struct ttm_resource_manager *man, · 22 unmodified lines
23static void ttm_sys_man_free(struct ttm_resource_manager *man,23static void ttm_sys_man_free(struct ttm_resource_manager *man,
24 struct ttm_resource *res)24 struct ttm_resource *res)
25{25{
26 ttm_resource_fini(man, res);
26 kfree(res);27 kfree(res);
27}28}
28 29
@@ -42,7 +43,7 @@ void ttm_sys_man_init(struct ttm_device *bdev) · 13 unmodified lines
42 man->use_tt = true;43 man->use_tt = true;
43 man->func = &ttm_sys_manager_func;44 man->func = &ttm_sys_manager_func;
44 45
45 ttm_resource_manager_init(man, 0);46 ttm_resource_manager_init(man, bdev, 0);
46 ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, man);47 ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, man);
47 ttm_resource_manager_set_used(man, true);48 ttm_resource_manager_set_used(man, true);
48}49}
drivers/gpu/drm/v3d/v3d_drv.c+6−2
@@ -219,6 +219,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) · 218 unmodified lines
219 int ret;219 int ret;
220 u32 mmu_debug;220 u32 mmu_debug;
221 u32 ident1;221 u32 ident1;
222 u64 mask;
222 223
223 v3d = devm_drm_dev_alloc(dev, &v3d_drm_driver, struct v3d_dev, drm);224 v3d = devm_drm_dev_alloc(dev, &v3d_drm_driver, struct v3d_dev, drm);
224 if (IS_ERR(v3d))225 if (IS_ERR(v3d))
@@ -237,8 +238,11 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) · 12 unmodified lines
237 return ret;238 return ret;
238 239
239 mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);240 mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
240 dma_set_mask_and_coherent(dev,241 mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
241 DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)));242 ret = dma_set_mask_and_coherent(dev, mask);
243 if (ret)
244 return ret;
245
242 v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);246 v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
243 247
244 ident1 = V3D_READ(V3D_HUB_IDENT1);248 ident1 = V3D_READ(V3D_HUB_IDENT1);
drivers/gpu/drm/vc4/vc4_bo.c+0−2
@@ -355,8 +355,6 @@ static struct vc4_bo *vc4_bo_get_from_cache(struct drm_device *dev, · 354 unmodified lines
355 uint32_t page_index = bo_page_index(size);355 uint32_t page_index = bo_page_index(size);
356 struct vc4_bo *bo = NULL;356 struct vc4_bo *bo = NULL;
357 357
358 size = roundup(size, PAGE_SIZE);
359
360 mutex_lock(&vc4->bo_lock);358 mutex_lock(&vc4->bo_lock);
361 if (page_index >= vc4->bo_cache.size_list_size)359 if (page_index >= vc4->bo_cache.size_list_size)
362 goto out;360 goto out;
drivers/gpu/drm/vc4/vc4_drv.c+29−4
@@ -37,6 +37,8 @@ · 36 unmodified lines
37#include <drm/drm_fb_helper.h>37#include <drm/drm_fb_helper.h>
38#include <drm/drm_vblank.h>38#include <drm/drm_vblank.h>
39 39
40#include <soc/bcm2835/raspberrypi-firmware.h>
41
40#include "uapi/drm/vc4_drm.h"42#include "uapi/drm/vc4_drm.h"
41 43
42#include "vc4_drv.h"44#include "vc4_drv.h"
@@ -215,6 +217,7 @@ static void vc4_match_add_drivers(struct device *dev, · 172 unmodified lines
215static int vc4_drm_bind(struct device *dev)217static int vc4_drm_bind(struct device *dev)
216{218{
217 struct platform_device *pdev = to_platform_device(dev);219 struct platform_device *pdev = to_platform_device(dev);
220 struct rpi_firmware *firmware = NULL;
218 struct drm_device *drm;221 struct drm_device *drm;
219 struct vc4_dev *vc4;222 struct vc4_dev *vc4;
220 struct device_node *node;223 struct device_node *node;
@@ -251,15 +254,34 @@ static int vc4_drm_bind(struct device *dev) · 30 unmodified lines
251 if (ret)254 if (ret)
252 return ret;255 return ret;
253 256
254 ret = component_bind_all(dev, drm);257 node = of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware");
258 if (node) {
259 firmware = rpi_firmware_get(node);
260 of_node_put(node);
261
262 if (!firmware)
263 return -EPROBE_DEFER;
264 }
265
266 ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver);
255 if (ret)267 if (ret)
256 return ret;268 return ret;
257 269
258 ret = vc4_plane_create_additional_planes(drm);270 if (firmware) {
271 ret = rpi_firmware_property(firmware,
272 RPI_FIRMWARE_NOTIFY_DISPLAY_DONE,
273 NULL, 0);
274 if (ret)
275 drm_warn(drm, "Couldn't stop firmware display driver: %d\n", ret);
276
277 rpi_firmware_put(firmware);
278 }
279
280 ret = component_bind_all(dev, drm);
259 if (ret)281 if (ret)
260 goto unbind_all;282 return ret;
261 283
262 ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver);284 ret = vc4_plane_create_additional_planes(drm);
263 if (ret)285 if (ret)
264 goto unbind_all;286 goto unbind_all;
265 287
@@ -357,6 +379,9 @@ static int __init vc4_drm_register(void) · 91 unmodified lines
357{379{
358 int ret;380 int ret;
359 381
382 if (drm_firmware_drivers_only())
383 return -ENODEV;
384
360 ret = platform_register_drivers(component_drivers,385 ret = platform_register_drivers(component_drivers,
361 ARRAY_SIZE(component_drivers));386 ARRAY_SIZE(component_drivers));
362 if (ret)387 if (ret)
drivers/gpu/drm/vc4/vc4_hdmi.c+78−54
@@ -104,6 +104,15 @@ static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode) · 103 unmodified lines
104 return (mode->clock * 1000) > HDMI_14_MAX_TMDS_CLK;104 return (mode->clock * 1000) > HDMI_14_MAX_TMDS_CLK;
105}105}
106 106
107static bool vc4_hdmi_is_full_range_rgb(struct vc4_hdmi *vc4_hdmi,
108 const struct drm_display_mode *mode)
109{
110 struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
111
112 return !vc4_encoder->hdmi_monitor ||
113 drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL;
114}
115
107static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)116static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
108{117{
109 struct drm_info_node *node = (struct drm_info_node *)m->private;118 struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -481,7 +490,6 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, · 371 unmodified lines
481static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)490static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
482{491{
483 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);492 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
484 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
485 struct drm_connector *connector = &vc4_hdmi->connector;493 struct drm_connector *connector = &vc4_hdmi->connector;
486 struct drm_connector_state *cstate = connector->state;494 struct drm_connector_state *cstate = connector->state;
487 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;495 const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
@@ -499,10 +507,10 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) · 11 unmodified lines
499 507
500 drm_hdmi_avi_infoframe_quant_range(&frame.avi,508 drm_hdmi_avi_infoframe_quant_range(&frame.avi,
501 connector, mode,509 connector, mode,
502 vc4_encoder->limited_rgb_range ?510 vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode) ?
503 HDMI_QUANTIZATION_RANGE_LIMITED :511 HDMI_QUANTIZATION_RANGE_FULL :
504 HDMI_QUANTIZATION_RANGE_FULL);512 HDMI_QUANTIZATION_RANGE_LIMITED);
505 drm_hdmi_avi_infoframe_colorspace(&frame.avi, cstate);513 drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate);
506 drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);514 drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);
507 515
508 vc4_hdmi_write_infoframe(encoder, &frame);516 vc4_hdmi_write_infoframe(encoder, &frame);
@@ -726,7 +734,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) · 217 unmodified lines
726 mutex_unlock(&vc4_hdmi->mutex);734 mutex_unlock(&vc4_hdmi->mutex);
727}735}
728 736
729static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)737static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
738 struct drm_connector_state *state,
739 const struct drm_display_mode *mode)
730{740{
731 unsigned long flags;741 unsigned long flags;
732 u32 csc_ctl;742 u32 csc_ctl;
@@ -736,7 +746,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) · 3 unmodified lines
736 csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,746 csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
737 VC4_HD_CSC_CTL_ORDER);747 VC4_HD_CSC_CTL_ORDER);
738 748
739 if (enable) {749 if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) {
740 /* CEA VICs other than #1 requre limited range RGB750 /* CEA VICs other than #1 requre limited range RGB
741 * output unless overridden by an AVI infoframe.751 * output unless overridden by an AVI infoframe.
742 * Apply a colorspace conversion to squash 0-255 down752 * Apply a colorspace conversion to squash 0-255 down
@@ -766,44 +776,67 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) · 23 unmodified lines
766 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);776 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
767}777}
768 778
769static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)779/*
780 * If we need to output Full Range RGB, then use the unity matrix
781 *
782 * [ 1 0 0 0]
783 * [ 0 1 0 0]
784 * [ 0 0 1 0]
785 *
786 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
787 */
788static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = {
789 { 0x2000, 0x0000, 0x0000, 0x0000 },
790 { 0x0000, 0x2000, 0x0000, 0x0000 },
791 { 0x0000, 0x0000, 0x2000, 0x0000 },
792};
793
794/*
795 * CEA VICs other than #1 require limited range RGB output unless
796 * overridden by an AVI infoframe. Apply a colorspace conversion to
797 * squash 0-255 down to 16-235. The matrix here is:
798 *
799 * [ 0.8594 0 0 16]
800 * [ 0 0.8594 0 16]
801 * [ 0 0 0.8594 16]
802 *
803 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
804 */
805static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
806 { 0x1b80, 0x0000, 0x0000, 0x0400 },
807 { 0x0000, 0x1b80, 0x0000, 0x0400 },
808 { 0x0000, 0x0000, 0x1b80, 0x0400 },
809};
810
811static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
812 const u16 coeffs[3][4])
770{813{
771 unsigned long flags;814 lockdep_assert_held(&vc4_hdmi->hw_lock);
772 u32 csc_ctl;815
816 HDMI_WRITE(HDMI_CSC_12_11, (coeffs[0][1] << 16) | coeffs[0][0]);
817 HDMI_WRITE(HDMI_CSC_14_13, (coeffs[0][3] << 16) | coeffs[0][2]);
818 HDMI_WRITE(HDMI_CSC_22_21, (coeffs[1][1] << 16) | coeffs[1][0]);
819 HDMI_WRITE(HDMI_CSC_24_23, (coeffs[1][3] << 16) | coeffs[1][2]);
820 HDMI_WRITE(HDMI_CSC_32_31, (coeffs[2][1] << 16) | coeffs[2][0]);
821 HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]);
822}
773 823
774 csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */824static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
825 struct drm_connector_state *state,
826 const struct drm_display_mode *mode)
827{
828 unsigned long flags;
829 u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
830 VC5_MT_CP_CSC_CTL_MODE);
775 831
776 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);832 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
777 833
778 if (enable) {834 HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
779 /* CEA VICs other than #1 requre limited range RGB835
780 * output unless overridden by an AVI infoframe.836 if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
781 * Apply a colorspace conversion to squash 0-255 down837 vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb);
782 * to 16-235. The matrix here is:838 else
783 *839 vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity);
784 * [ 0.8594 0 0 16]
785 * [ 0 0.8594 0 16]
786 * [ 0 0 0.8594 16]
787 * [ 0 0 0 1]
788 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
789 */
790 HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
791 HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
792 HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
793 HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
794 HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
795 HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
796 } else {
797 /* Still use the matrix for full range, but make it unity.
798 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
799 */
800 HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
801 HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
802 HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
803 HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
804 HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
805 HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
806 }
807 840
808 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);841 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
809 842
@@ -889,7 +922,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, · 79 unmodified lines
889 922
890 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);923 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
891 924
892 HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
893 HDMI_WRITE(HDMI_HORZA,925 HDMI_WRITE(HDMI_HORZA,
894 (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |926 (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
895 (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |927 (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
@@ -1113,24 +1145,16 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, · 217 unmodified lines
1113 struct drm_atomic_state *state)1145 struct drm_atomic_state *state)
1114{1146{
1115 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);1147 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
1148 struct drm_connector *connector = &vc4_hdmi->connector;
1116 struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;1149 struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
1117 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);1150 struct drm_connector_state *conn_state =
1151 drm_atomic_get_new_connector_state(state, connector);
1118 unsigned long flags;1152 unsigned long flags;
1119 1153
1120 mutex_lock(&vc4_hdmi->mutex);1154 mutex_lock(&vc4_hdmi->mutex);
1121 1155
1122 if (vc4_encoder->hdmi_monitor &&1156 if (vc4_hdmi->variant->csc_setup)
1123 drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {1157 vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode);
1124 if (vc4_hdmi->variant->csc_setup)
1125 vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
1126
1127 vc4_encoder->limited_rgb_range = true;
1128 } else {
1129 if (vc4_hdmi->variant->csc_setup)
1130 vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
1131
1132 vc4_encoder->limited_rgb_range = false;
1133 }
1134 1158
1135 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);1159 spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
1136 HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);1160 HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
drivers/gpu/drm/vc4/vc4_hdmi.h+3−2
@@ -12,7 +12,6 @@ · 11 unmodified lines
12struct vc4_hdmi_encoder {12struct vc4_hdmi_encoder {
13 struct vc4_encoder base;13 struct vc4_encoder base;
14 bool hdmi_monitor;14 bool hdmi_monitor;
15 bool limited_rgb_range;
16};15};
17 16
18static inline struct vc4_hdmi_encoder *17static inline struct vc4_hdmi_encoder *
@@ -77,7 +76,9 @@ struct vc4_hdmi_variant { · 58 unmodified lines
77 void (*reset)(struct vc4_hdmi *vc4_hdmi);76 void (*reset)(struct vc4_hdmi *vc4_hdmi);
78 77
79 /* Callback to enable / disable the CSC */78 /* Callback to enable / disable the CSC */
80 void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);79 void (*csc_setup)(struct vc4_hdmi *vc4_hdmi,
80 struct drm_connector_state *state,
81 const struct drm_display_mode *mode);
81 82
82 /* Callback to configure the video timings in the HDMI block */83 /* Callback to configure the video timings in the HDMI block */
83 void (*set_timings)(struct vc4_hdmi *vc4_hdmi,84 void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
drivers/gpu/drm/vc4/vc4_regs.h+3−0
@@ -774,6 +774,9 @@ enum { · 773 unmodified lines
774# define VC4_HD_CSC_CTL_RGB2YCC BIT(1)774# define VC4_HD_CSC_CTL_RGB2YCC BIT(1)
775# define VC4_HD_CSC_CTL_ENABLE BIT(0)775# define VC4_HD_CSC_CTL_ENABLE BIT(0)
776 776
777# define VC5_MT_CP_CSC_CTL_ENABLE BIT(2)
778# define VC5_MT_CP_CSC_CTL_MODE_MASK VC4_MASK(1, 0)
779
777# define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1)780# define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1)
778 781
779/* HVS display list information. */782/* HVS display list information. */
drivers/gpu/drm/virtio/virtgpu_gem.c+3−0
@@ -248,6 +248,9 @@ void virtio_gpu_array_put_free(struct virtio_gpu_object_array *objs) · 247 unmodified lines
248{248{
249 u32 i;249 u32 i;
250 250
251 if (!objs)
252 return;
253
251 for (i = 0; i < objs->nents; i++)254 for (i = 0; i < objs->nents; i++)
252 drm_gem_object_put(objs->objs[i]);255 drm_gem_object_put(objs->objs[i]);
253 virtio_gpu_array_free(objs);256 virtio_gpu_array_free(objs);
drivers/gpu/drm/vkms/vkms_drv.h+2−0
@@ -20,6 +20,8 @@ · 19 unmodified lines
20#define XRES_MAX 819220#define XRES_MAX 8192
21#define YRES_MAX 819221#define YRES_MAX 8192
22 22
23#define NUM_OVERLAY_PLANES 8
24
23struct vkms_writeback_job {25struct vkms_writeback_job {
24 struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];26 struct dma_buf_map map[DRM_FORMAT_MAX_PLANES];
25 struct dma_buf_map data[DRM_FORMAT_MAX_PLANES];27 struct dma_buf_map data[DRM_FORMAT_MAX_PLANES];
drivers/gpu/drm/vkms/vkms_output.c+22−7
@@ -32,6 +32,21 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = { · 31 unmodified lines
32 .get_modes = vkms_conn_get_modes,32 .get_modes = vkms_conn_get_modes,
33};33};
34 34
35static int vkms_add_overlay_plane(struct vkms_device *vkmsdev, int index,
36 struct drm_crtc *crtc)
37{
38 struct vkms_plane *overlay;
39
40 overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);
41 if (IS_ERR(overlay))
42 return PTR_ERR(overlay);
43
44 if (!overlay->base.possible_crtcs)
45 overlay->base.possible_crtcs = drm_crtc_mask(crtc);
46
47 return 0;
48}
49
35int vkms_output_init(struct vkms_device *vkmsdev, int index)50int vkms_output_init(struct vkms_device *vkmsdev, int index)
36{51{
37 struct vkms_output *output = &vkmsdev->output;52 struct vkms_output *output = &vkmsdev->output;
@@ -39,21 +54,21 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) · 1 unmodified line
39 struct drm_connector *connector = &output->connector;54 struct drm_connector *connector = &output->connector;
40 struct drm_encoder *encoder = &output->encoder;55 struct drm_encoder *encoder = &output->encoder;
41 struct drm_crtc *crtc = &output->crtc;56 struct drm_crtc *crtc = &output->crtc;
42 struct vkms_plane *primary, *cursor = NULL, *overlay = NULL;57 struct vkms_plane *primary, *cursor = NULL;
43 int ret;58 int ret;
44 int writeback;59 int writeback;
60 unsigned int n;
45 61
46 primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);62 primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
47 if (IS_ERR(primary))63 if (IS_ERR(primary))
48 return PTR_ERR(primary);64 return PTR_ERR(primary);
49 65
50 if (vkmsdev->config->overlay) {66 if (vkmsdev->config->overlay) {
51 overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);67 for (n = 0; n < NUM_OVERLAY_PLANES; n++) {
52 if (IS_ERR(overlay))68 ret = vkms_add_overlay_plane(vkmsdev, index, crtc);
53 return PTR_ERR(overlay);69 if (ret)
54 70 return ret;
55 if (!overlay->base.possible_crtcs)71 }
56 overlay->base.possible_crtcs = drm_crtc_mask(crtc);
57 }72 }
58 73
59 if (vkmsdev->config->cursor) {74 if (vkmsdev->config->cursor) {
drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c+3−1
@@ -117,6 +117,7 @@ nospace: · 116 unmodified lines
117 gman->used_gmr_pages -= (*res)->num_pages;117 gman->used_gmr_pages -= (*res)->num_pages;
118 spin_unlock(&gman->lock);118 spin_unlock(&gman->lock);
119 ida_free(&gman->gmr_ida, id);119 ida_free(&gman->gmr_ida, id);
120 ttm_resource_fini(man, *res);
120 kfree(*res);121 kfree(*res);
121 return -ENOSPC;122 return -ENOSPC;
122}123}
@@ -130,6 +131,7 @@ static void vmw_gmrid_man_put_node(struct ttm_resource_manager *man, · 7 unmodified lines
130 spin_lock(&gman->lock);131 spin_lock(&gman->lock);
131 gman->used_gmr_pages -= res->num_pages;132 gman->used_gmr_pages -= res->num_pages;
132 spin_unlock(&gman->lock);133 spin_unlock(&gman->lock);
134 ttm_resource_fini(man, res);
133 kfree(res);135 kfree(res);
134}136}
135 137
@@ -160,7 +162,7 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) · 24 unmodified lines
160 162
161 man->func = &vmw_gmrid_manager_func;163 man->func = &vmw_gmrid_manager_func;
162 man->use_tt = true;164 man->use_tt = true;
163 ttm_resource_manager_init(man, 0);165 ttm_resource_manager_init(man, &dev_priv->bdev, 0);
164 spin_lock_init(&gman->lock);166 spin_lock_init(&gman->lock);
165 gman->used_gmr_pages = 0;167 gman->used_gmr_pages = 0;
166 ida_init(&gman->gmr_ida);168 ida_init(&gman->gmr_ida);
drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c+2−1
@@ -49,6 +49,7 @@ static int vmw_sys_man_alloc(struct ttm_resource_manager *man, · 48 unmodified lines
49static void vmw_sys_man_free(struct ttm_resource_manager *man,49static void vmw_sys_man_free(struct ttm_resource_manager *man,
50 struct ttm_resource *res)50 struct ttm_resource *res)
51{51{
52 ttm_resource_fini(man, res);
52 kfree(res);53 kfree(res);
53}54}
54 55
@@ -69,7 +70,7 @@ int vmw_sys_man_init(struct vmw_private *dev_priv) · 14 unmodified lines
69 man->use_tt = true;70 man->use_tt = true;
70 man->func = &vmw_sys_manager_func;71 man->func = &vmw_sys_manager_func;
71 72
72 ttm_resource_manager_init(man, 0);73 ttm_resource_manager_init(man, bdev, 0);
73 ttm_set_driver_manager(bdev, VMW_PL_SYSTEM, man);74 ttm_set_driver_manager(bdev, VMW_PL_SYSTEM, man);
74 ttm_resource_manager_set_used(man, true);75 ttm_resource_manager_set_used(man, true);
75 return 0;76 return 0;
drivers/gpu/drm/xlnx/Kconfig+1−0
@@ -6,6 +6,7 @@ config DRM_ZYNQMP_DPSUB · 5 unmodified lines
6 depends on PHY_XILINX_ZYNQMP6 depends on PHY_XILINX_ZYNQMP
7 depends on XILINX_ZYNQMP_DPDMA7 depends on XILINX_ZYNQMP_DPDMA
8 select DMA_ENGINE8 select DMA_ENGINE
9 select DRM_DP_HELPER
9 select DRM_GEM_CMA_HELPER10 select DRM_GEM_CMA_HELPER
10 select DRM_KMS_HELPER11 select DRM_KMS_HELPER
11 select GENERIC_PHY12 select GENERIC_PHY
drivers/gpu/drm/xlnx/zynqmp_dp.c+1−1
@@ -13,7 +13,7 @@ · 12 unmodified lines
13#include <drm/drm_connector.h>13#include <drm/drm_connector.h>
14#include <drm/drm_crtc.h>14#include <drm/drm_crtc.h>
15#include <drm/drm_device.h>15#include <drm/drm_device.h>
16#include <drm/drm_dp_helper.h>16#include <drm/dp/drm_dp_helper.h>
17#include <drm/drm_edid.h>17#include <drm/drm_edid.h>
18#include <drm/drm_encoder.h>18#include <drm/drm_encoder.h>
19#include <drm/drm_managed.h>19#include <drm/drm_managed.h>
drivers/platform/chrome/Kconfig+11−0
@@ -243,6 +243,17 @@ config CROS_USBPD_NOTIFY · 242 unmodified lines
243 To compile this driver as a module, choose M here: the243 To compile this driver as a module, choose M here: the
244 module will be called cros_usbpd_notify.244 module will be called cros_usbpd_notify.
245 245
246config CHROMEOS_PRIVACY_SCREEN
247 tristate "ChromeOS Privacy Screen support"
248 depends on ACPI
249 depends on DRM
250 select DRM_PRIVACY_SCREEN
251 help
252 This driver provides the support needed for the in-built electronic
253 privacy screen that is present on some ChromeOS devices. When enabled,
254 this should probably always be built into the kernel to avoid or
255 minimize drm probe deferral.
256
246source "drivers/platform/chrome/wilco_ec/Kconfig"257source "drivers/platform/chrome/wilco_ec/Kconfig"
247 258
248endif # CHROMEOS_PLATFORMS259endif # CHROMEOS_PLATFORMS
drivers/platform/chrome/Makefile+1−0
@@ -4,6 +4,7 @@ · 3 unmodified lines
4CFLAGS_cros_ec_trace.o:= -I$(src)4CFLAGS_cros_ec_trace.o:= -I$(src)
5 5
6obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o6obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
7obj-$(CONFIG_CHROMEOS_PRIVACY_SCREEN) += chromeos_privacy_screen.o
7obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o8obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
8obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o9obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
9obj-$(CONFIG_CROS_EC) += cros_ec.o10obj-$(CONFIG_CROS_EC) += cros_ec.o
drivers/platform/chrome/chromeos_privacy_screen.c+153−0
@@ -0,0 +1,153 @@
1// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * ChromeOS Privacy Screen support
5 *
6 * Copyright (C) 2022 Google LLC
7 *
8 * This is the Chromeos privacy screen provider, present on certain chromebooks,
9 * represented by a GOOG0010 device in the ACPI. This ACPI device, if present,
10 * will cause the i915 drm driver to probe defer until this driver registers
11 * the privacy-screen.
12 */
13
14#include <linux/acpi.h>
15#include <drm/drm_privacy_screen_driver.h>
16
17/*
18 * The DSM (Device Specific Method) constants below are the agreed API with
19 * the firmware team, on how to control privacy screen using ACPI methods.
20 */
21#define PRIV_SCRN_DSM_REVID 1 /* DSM version */
22#define PRIV_SCRN_DSM_FN_GET_STATUS 1 /* Get privacy screen status */
23#define PRIV_SCRN_DSM_FN_ENABLE 2 /* Enable privacy screen */
24#define PRIV_SCRN_DSM_FN_DISABLE 3 /* Disable privacy screen */
25
26static const guid_t chromeos_privacy_screen_dsm_guid =
27 GUID_INIT(0xc7033113, 0x8720, 0x4ceb,
28 0x90, 0x90, 0x9d, 0x52, 0xb3, 0xe5, 0x2d, 0x73);
29
30static void
31chromeos_privacy_screen_get_hw_state(struct drm_privacy_screen
32 *drm_privacy_screen)
33{
34 union acpi_object *obj;
35 acpi_handle handle;
36 struct device *privacy_screen =
37 drm_privacy_screen_get_drvdata(drm_privacy_screen);
38
39 handle = acpi_device_handle(to_acpi_device(privacy_screen));
40 obj = acpi_evaluate_dsm(handle, &chromeos_privacy_screen_dsm_guid,
41 PRIV_SCRN_DSM_REVID,
42 PRIV_SCRN_DSM_FN_GET_STATUS, NULL);
43 if (!obj) {
44 dev_err(privacy_screen,
45 "_DSM failed to get privacy-screen state\n");
46 return;
47 }
48
49 if (obj->type != ACPI_TYPE_INTEGER)
50 dev_err(privacy_screen,
51 "Bad _DSM to get privacy-screen state\n");
52 else if (obj->integer.value == 1)
53 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state =
54 PRIVACY_SCREEN_ENABLED;
55 else
56 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state =
57 PRIVACY_SCREEN_DISABLED;
58
59 ACPI_FREE(obj);
60}
61
62static int
63chromeos_privacy_screen_set_sw_state(struct drm_privacy_screen
64 *drm_privacy_screen,
65 enum drm_privacy_screen_status state)
66{
67 union acpi_object *obj = NULL;
68 acpi_handle handle;
69 struct device *privacy_screen =
70 drm_privacy_screen_get_drvdata(drm_privacy_screen);
71
72 handle = acpi_device_handle(to_acpi_device(privacy_screen));
73
74 if (state == PRIVACY_SCREEN_DISABLED) {
75 obj = acpi_evaluate_dsm(handle,
76 &chromeos_privacy_screen_dsm_guid,
77 PRIV_SCRN_DSM_REVID,
78 PRIV_SCRN_DSM_FN_DISABLE, NULL);
79 } else if (state == PRIVACY_SCREEN_ENABLED) {
80 obj = acpi_evaluate_dsm(handle,
81 &chromeos_privacy_screen_dsm_guid,
82 PRIV_SCRN_DSM_REVID,
83 PRIV_SCRN_DSM_FN_ENABLE, NULL);
84 } else {
85 dev_err(privacy_screen,
86 "Bad attempt to set privacy-screen status to %u\n",
87 state);
88 return -EINVAL;
89 }
90
91 if (!obj) {
92 dev_err(privacy_screen,
93 "_DSM failed to set privacy-screen state\n");
94 return -EIO;
95 }
96
97 drm_privacy_screen->hw_state = drm_privacy_screen->sw_state = state;
98 ACPI_FREE(obj);
99 return 0;
100}
101
102static const struct drm_privacy_screen_ops chromeos_privacy_screen_ops = {
103 .get_hw_state = chromeos_privacy_screen_get_hw_state,
104 .set_sw_state = chromeos_privacy_screen_set_sw_state,
105};
106
107static int chromeos_privacy_screen_add(struct acpi_device *adev)
108{
109 struct drm_privacy_screen *drm_privacy_screen =
110 drm_privacy_screen_register(&adev->dev,
111 &chromeos_privacy_screen_ops,
112 &adev->dev);
113
114 if (IS_ERR(drm_privacy_screen)) {
115 dev_err(&adev->dev, "Error registering privacy-screen\n");
116 return PTR_ERR(drm_privacy_screen);
117 }
118
119 adev->driver_data = drm_privacy_screen;
120 dev_info(&adev->dev, "registered privacy-screen '%s'\n",
121 dev_name(&drm_privacy_screen->dev));
122
123 return 0;
124}
125
126static int chromeos_privacy_screen_remove(struct acpi_device *adev)
127{
128 struct drm_privacy_screen *drm_privacy_screen = acpi_driver_data(adev);
129
130 drm_privacy_screen_unregister(drm_privacy_screen);
131 return 0;
132}
133
134static const struct acpi_device_id chromeos_privacy_screen_device_ids[] = {
135 {"GOOG0010", 0}, /* Google's electronic privacy screen for eDP-1 */
136 {}
137};
138MODULE_DEVICE_TABLE(acpi, chromeos_privacy_screen_device_ids);
139
140static struct acpi_driver chromeos_privacy_screen_driver = {
141 .name = "chromeos_privacy_screen_driver",
142 .class = "ChromeOS",
143 .ids = chromeos_privacy_screen_device_ids,
144 .ops = {
145 .add = chromeos_privacy_screen_add,
146 .remove = chromeos_privacy_screen_remove,
147 },
148};
149
150module_acpi_driver(chromeos_privacy_screen_driver);
151MODULE_LICENSE("GPL v2");
152MODULE_DESCRIPTION("ChromeOS ACPI Privacy Screen driver");
153MODULE_AUTHOR("Rajat Jain <rajatja@google.com>");
drivers/platform/x86/thinkpad_acpi.c+1−1
@@ -9869,7 +9869,7 @@ static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm) · 9868 unmodified lines
9869 return 0;9869 return 0;
9870 9870
9871 lcdshadow_dev = drm_privacy_screen_register(&tpacpi_pdev->dev,9871 lcdshadow_dev = drm_privacy_screen_register(&tpacpi_pdev->dev,
9872 &lcdshadow_ops);9872 &lcdshadow_ops, NULL);
9873 if (IS_ERR(lcdshadow_dev))9873 if (IS_ERR(lcdshadow_dev))
9874 return PTR_ERR(lcdshadow_dev);9874 return PTR_ERR(lcdshadow_dev);
9875 9875
drivers/video/fbdev/asiliantfb.c+1−1
@@ -110,7 +110,7 @@ static const struct fb_ops asiliantfb_ops = { · 109 unmodified lines
110static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dclk2_div)110static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dclk2_div)
111{111{
112 unsigned pixclock = *ppixclock;112 unsigned pixclock = *ppixclock;
113 unsigned Ftarget = 1000000 * (1000000 / pixclock);113 unsigned Ftarget;
114 unsigned n;114 unsigned n;
115 unsigned best_error = 0xffffffff;115 unsigned best_error = 0xffffffff;
116 unsigned best_m = 0xffffffff,116 unsigned best_m = 0xffffffff,
drivers/video/fbdev/core/fbmem.c+26−3
@@ -25,6 +25,7 @@ · 24 unmodified lines
25#include <linux/init.h>25#include <linux/init.h>
26#include <linux/linux_logo.h>26#include <linux/linux_logo.h>
27#include <linux/proc_fs.h>27#include <linux/proc_fs.h>
28#include <linux/platform_device.h>
28#include <linux/seq_file.h>29#include <linux/seq_file.h>
29#include <linux/console.h>30#include <linux/console.h>
30#include <linux/kmod.h>31#include <linux/kmod.h>
@@ -1557,18 +1558,36 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a, · 1526 unmodified lines
1557 /* check all firmware fbs and kick off if the base addr overlaps */1558 /* check all firmware fbs and kick off if the base addr overlaps */
1558 for_each_registered_fb(i) {1559 for_each_registered_fb(i) {
1559 struct apertures_struct *gen_aper;1560 struct apertures_struct *gen_aper;
1561 struct device *device;
1560 1562
1561 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))1563 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
1562 continue;1564 continue;
1563 1565
1564 gen_aper = registered_fb[i]->apertures;1566 gen_aper = registered_fb[i]->apertures;
1567 device = registered_fb[i]->device;
1565 if (fb_do_apertures_overlap(gen_aper, a) ||1568 if (fb_do_apertures_overlap(gen_aper, a) ||
1566 (primary && gen_aper && gen_aper->count &&1569 (primary && gen_aper && gen_aper->count &&
1567 gen_aper->ranges[0].base == VGA_FB_PHYS)) {1570 gen_aper->ranges[0].base == VGA_FB_PHYS)) {
1568 1571
1569 printk(KERN_INFO "fb%d: switching to %s from %s\n",1572 printk(KERN_INFO "fb%d: switching to %s from %s\n",
1570 i, name, registered_fb[i]->fix.id);1573 i, name, registered_fb[i]->fix.id);
1571 do_unregister_framebuffer(registered_fb[i]);1574
1575 /*
1576 * If we kick-out a firmware driver, we also want to remove
1577 * the underlying platform device, such as simple-framebuffer,
1578 * VESA, EFI, etc. A native driver will then be able to
1579 * allocate the memory range.
1580 *
1581 * If it's not a platform device, at least print a warning. A
1582 * fix would add code to remove the device from the system.
1583 */
1584 if (dev_is_platform(device)) {
1585 registered_fb[i]->forced_out = true;
1586 platform_device_unregister(to_platform_device(device));
1587 } else {
1588 pr_warn("fb%d: cannot remove device\n", i);
1589 do_unregister_framebuffer(registered_fb[i]);
1590 }
1572 }1591 }
1573 }1592 }
1574}1593}
@@ -1898,9 +1917,13 @@ EXPORT_SYMBOL(register_framebuffer); · 323 unmodified lines
1898void1917void
1899unregister_framebuffer(struct fb_info *fb_info)1918unregister_framebuffer(struct fb_info *fb_info)
1900{1919{
1901 mutex_lock(&registration_lock);1920 bool forced_out = fb_info->forced_out;
1921
1922 if (!forced_out)
1923 mutex_lock(&registration_lock);
1902 do_unregister_framebuffer(fb_info);1924 do_unregister_framebuffer(fb_info);
1903 mutex_unlock(&registration_lock);1925 if (!forced_out)
1926 mutex_unlock(&registration_lock);
1904}1927}
1905EXPORT_SYMBOL(unregister_framebuffer);1928EXPORT_SYMBOL(unregister_framebuffer);
1906 1929
drivers/video/fbdev/s3c-fb.c+1−1
@@ -489,7 +489,7 @@ static int s3c_fb_set_par(struct fb_info *info) · 488 unmodified lines
489 struct s3c_fb_win *win = info->par;489 struct s3c_fb_win *win = info->par;
490 struct s3c_fb *sfb = win->parent;490 struct s3c_fb *sfb = win->parent;
491 void __iomem *regs = sfb->regs;491 void __iomem *regs = sfb->regs;
492 void __iomem *buf = regs;492 void __iomem *buf;
493 int win_no = win->index;493 int win_no = win->index;
494 u32 alpha = 0;494 u32 alpha = 0;
495 u32 data;495 u32 data;
drivers/video/fbdev/simplefb.c+45−20
@@ -66,16 +66,36 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, · 65 unmodified lines
66 return 0;66 return 0;
67}67}
68 68
69struct simplefb_par;69struct simplefb_par {
70 u32 palette[PSEUDO_PALETTE_SIZE];
71 struct resource *mem;
72#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
73 bool clks_enabled;
74 unsigned int clk_count;
75 struct clk **clks;
76#endif
77#if defined CONFIG_OF && defined CONFIG_REGULATOR
78 bool regulators_enabled;
79 u32 regulator_count;
80 struct regulator **regulators;
81#endif
82};
83
70static void simplefb_clocks_destroy(struct simplefb_par *par);84static void simplefb_clocks_destroy(struct simplefb_par *par);
71static void simplefb_regulators_destroy(struct simplefb_par *par);85static void simplefb_regulators_destroy(struct simplefb_par *par);
72 86
73static void simplefb_destroy(struct fb_info *info)87static void simplefb_destroy(struct fb_info *info)
74{88{
89 struct simplefb_par *par = info->par;
90 struct resource *mem = par->mem;
91
75 simplefb_regulators_destroy(info->par);92 simplefb_regulators_destroy(info->par);
76 simplefb_clocks_destroy(info->par);93 simplefb_clocks_destroy(info->par);
77 if (info->screen_base)94 if (info->screen_base)
78 iounmap(info->screen_base);95 iounmap(info->screen_base);
96
97 if (mem)
98 release_mem_region(mem->start, resource_size(mem));
79}99}
80 100
81static const struct fb_ops simplefb_ops = {101static const struct fb_ops simplefb_ops = {
@@ -169,20 +189,6 @@ static int simplefb_parse_pd(struct platform_device *pdev, · 87 unmodified lines
169 return 0;189 return 0;
170}190}
171 191
172struct simplefb_par {
173 u32 palette[PSEUDO_PALETTE_SIZE];
174#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
175 bool clks_enabled;
176 unsigned int clk_count;
177 struct clk **clks;
178#endif
179#if defined CONFIG_OF && defined CONFIG_REGULATOR
180 bool regulators_enabled;
181 u32 regulator_count;
182 struct regulator **regulators;
183#endif
184};
185
186#if defined CONFIG_OF && defined CONFIG_COMMON_CLK192#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
187/*193/*
188 * Clock handling code.194 * Clock handling code.
@@ -405,7 +411,7 @@ static int simplefb_probe(struct platform_device *pdev) · 216 unmodified lines
405 struct simplefb_params params;411 struct simplefb_params params;
406 struct fb_info *info;412 struct fb_info *info;
407 struct simplefb_par *par;413 struct simplefb_par *par;
408 struct resource *mem;414 struct resource *res, *mem;
409 415
410 /*416 /*
411 * Generic drivers must not be registered if a framebuffer exists.417 * Generic drivers must not be registered if a framebuffer exists.
@@ -430,15 +436,28 @@ static int simplefb_probe(struct platform_device *pdev) · 18 unmodified lines
430 if (ret)436 if (ret)
431 return ret;437 return ret;
432 438
433 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);439 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
434 if (!mem) {440 if (!res) {
435 dev_err(&pdev->dev, "No memory resource\n");441 dev_err(&pdev->dev, "No memory resource\n");
436 return -EINVAL;442 return -EINVAL;
437 }443 }
438 444
445 mem = request_mem_region(res->start, resource_size(res), "simplefb");
446 if (!mem) {
447 /*
448 * We cannot make this fatal. Sometimes this comes from magic
449 * spaces our resource handlers simply don't know about. Use
450 * the I/O-memory resource as-is and try to map that instead.
451 */
452 dev_warn(&pdev->dev, "simplefb: cannot reserve video memory at %pR\n", res);
453 mem = res;
454 }
455
439 info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);456 info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);
440 if (!info)457 if (!info) {
441 return -ENOMEM;458 ret = -ENOMEM;
459 goto error_release_mem_region;
460 }
442 platform_set_drvdata(pdev, info);461 platform_set_drvdata(pdev, info);
443 462
444 par = info->par;463 par = info->par;
@@ -495,6 +514,9 @@ static int simplefb_probe(struct platform_device *pdev) · 50 unmodified lines
495 info->var.xres, info->var.yres,514 info->var.xres, info->var.yres,
496 info->var.bits_per_pixel, info->fix.line_length);515 info->var.bits_per_pixel, info->fix.line_length);
497 516
517 if (mem != res)
518 par->mem = mem; /* release in clean-up handler */
519
498 ret = register_framebuffer(info);520 ret = register_framebuffer(info);
499 if (ret < 0) {521 if (ret < 0) {
500 dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);522 dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
@@ -513,6 +535,9 @@ error_unmap: · 12 unmodified lines
513 iounmap(info->screen_base);535 iounmap(info->screen_base);
514error_fb_release:536error_fb_release:
515 framebuffer_release(info);537 framebuffer_release(info);
538error_release_mem_region:
539 if (mem != res)
540 release_mem_region(mem->start, resource_size(mem));
516 return ret;541 return ret;
517}542}
518 543
drivers/video/fbdev/vga16fb.c+5−0
@@ -1351,7 +1351,12 @@ static int vga16fb_probe(struct platform_device *dev) · 1350 unmodified lines
1351 printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);1351 printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
1352 par = info->par;1352 par = info->par;
1353 1353
1354#if defined(CONFIG_X86)
1355 par->isVGA = screen_info.orig_video_isVGA == VIDEO_TYPE_VGAC;
1356#else
1357 /* non-x86 architectures treat orig_video_isVGA as a boolean flag */
1354 par->isVGA = screen_info.orig_video_isVGA;1358 par->isVGA = screen_info.orig_video_isVGA;
1359#endif
1355 par->palette_blanked = 0;1360 par->palette_blanked = 0;
1356 par->vesa_blanked = 0;1361 par->vesa_blanked = 0;
1357 1362
include/drm/bridge/dw_mipi_dsi.h+3−1
@@ -51,7 +51,9 @@ struct dw_mipi_dsi_plat_data { · 50 unmodified lines
51 unsigned int max_data_lanes;51 unsigned int max_data_lanes;
52 52
53 enum drm_mode_status (*mode_valid)(void *priv_data,53 enum drm_mode_status (*mode_valid)(void *priv_data,
54 const struct drm_display_mode *mode);54 const struct drm_display_mode *mode,
55 unsigned long mode_flags,
56 u32 lanes, u32 format);
55 57
56 const struct dw_mipi_dsi_phy_ops *phy_ops;58 const struct dw_mipi_dsi_phy_ops *phy_ops;
57 const struct dw_mipi_dsi_host_ops *host_ops;59 const struct dw_mipi_dsi_host_ops *host_ops;
include/drm/dp/drm_dp_aux_bus.hrenamed from include/drm/drm_dp_aux_bus.h+0−0

File renamed without changes.

include/drm/dp/drm_dp_dual_mode_helper.hrenamed from include/drm/drm_dp_dual_mode_helper.h+0−0

File renamed without changes.

include/drm/dp/drm_dp_helper.hrenamed from include/drm/drm_dp_helper.h+2−5
@@ -1038,11 +1038,8 @@ struct drm_panel; · 1037 unmodified lines
1038#define DP_SIDEBAND_MSG_UP_REQ_BASE 0x1600 /* 1.2 MST */1038#define DP_SIDEBAND_MSG_UP_REQ_BASE 0x1600 /* 1.2 MST */
1039 1039
1040/* DPRX Event Status Indicator */1040/* DPRX Event Status Indicator */
1041#define DP_SINK_COUNT_ESI 0x2002 /* 1.2 */1041#define DP_SINK_COUNT_ESI 0x2002 /* same as 0x200 */
1042/* 0-5 sink count */1042#define DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 0x2003 /* same as 0x201 */
1043# define DP_SINK_COUNT_CP_READY (1 << 6)
1044
1045#define DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 0x2003 /* 1.2 */
1046 1043
1047#define DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 0x2004 /* 1.2 */1044#define DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 0x2004 /* 1.2 */
1048# define DP_RX_GTC_MSTR_REQ_STATUS_CHANGE (1 << 0)1045# define DP_RX_GTC_MSTR_REQ_STATUS_CHANGE (1 << 0)
include/drm/dp/drm_dp_mst_helper.hrenamed from include/drm/drm_dp_mst_helper.h+1−1
@@ -23,7 +23,7 @@ · 22 unmodified lines
23#define _DRM_DP_MST_HELPER_H_23#define _DRM_DP_MST_HELPER_H_
24 24
25#include <linux/types.h>25#include <linux/types.h>
26#include <drm/drm_dp_helper.h>26#include <drm/dp/drm_dp_helper.h>
27#include <drm/drm_atomic.h>27#include <drm/drm_atomic.h>
28 28
29#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)29#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
include/drm/drm_buddy.h+150−0
@@ -0,0 +1,150 @@
1/* SPDX-License-Identifier: MIT */
2/*
3 * Copyright © 2021 Intel Corporation
4 */
5
6#ifndef __DRM_BUDDY_H__
7#define __DRM_BUDDY_H__
8
9#include <linux/bitops.h>
10#include <linux/list.h>
11#include <linux/slab.h>
12#include <linux/sched.h>
13
14#include <drm/drm_print.h>
15
16#define range_overflows(start, size, max) ({ \
17 typeof(start) start__ = (start); \
18 typeof(size) size__ = (size); \
19 typeof(max) max__ = (max); \
20 (void)(&start__ == &size__); \
21 (void)(&start__ == &max__); \
22 start__ >= max__ || size__ > max__ - start__; \
23})
24
25struct drm_buddy_block {
26#define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
27#define DRM_BUDDY_HEADER_STATE GENMASK_ULL(11, 10)
28#define DRM_BUDDY_ALLOCATED (1 << 10)
29#define DRM_BUDDY_FREE (2 << 10)
30#define DRM_BUDDY_SPLIT (3 << 10)
31/* Free to be used, if needed in the future */
32#define DRM_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6)
33#define DRM_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0)
34 u64 header;
35
36 struct drm_buddy_block *left;
37 struct drm_buddy_block *right;
38 struct drm_buddy_block *parent;
39
40 void *private; /* owned by creator */
41
42 /*
43 * While the block is allocated by the user through drm_buddy_alloc*,
44 * the user has ownership of the link, for example to maintain within
45 * a list, if so desired. As soon as the block is freed with
46 * drm_buddy_free* ownership is given back to the mm.
47 */
48 struct list_head link;
49 struct list_head tmp_link;
50};
51
52/* Order-zero must be at least PAGE_SIZE */
53#define DRM_BUDDY_MAX_ORDER (63 - PAGE_SHIFT)
54
55/*
56 * Binary Buddy System.
57 *
58 * Locking should be handled by the user, a simple mutex around
59 * drm_buddy_alloc* and drm_buddy_free* should suffice.
60 */
61struct drm_buddy {
62 /* Maintain a free list for each order. */
63 struct list_head *free_list;
64
65 /*
66 * Maintain explicit binary tree(s) to track the allocation of the
67 * address space. This gives us a simple way of finding a buddy block
68 * and performing the potentially recursive merge step when freeing a
69 * block. Nodes are either allocated or free, in which case they will
70 * also exist on the respective free list.
71 */
72 struct drm_buddy_block **roots;
73
74 /*
75 * Anything from here is public, and remains static for the lifetime of
76 * the mm. Everything above is considered do-not-touch.
77 */
78 unsigned int n_roots;
79 unsigned int max_order;
80
81 /* Must be at least PAGE_SIZE */
82 u64 chunk_size;
83 u64 size;
84 u64 avail;
85};
86
87static inline u64
88drm_buddy_block_offset(struct drm_buddy_block *block)
89{
90 return block->header & DRM_BUDDY_HEADER_OFFSET;
91}
92
93static inline unsigned int
94drm_buddy_block_order(struct drm_buddy_block *block)
95{
96 return block->header & DRM_BUDDY_HEADER_ORDER;
97}
98
99static inline unsigned int
100drm_buddy_block_state(struct drm_buddy_block *block)
101{
102 return block->header & DRM_BUDDY_HEADER_STATE;
103}
104
105static inline bool
106drm_buddy_block_is_allocated(struct drm_buddy_block *block)
107{
108 return drm_buddy_block_state(block) == DRM_BUDDY_ALLOCATED;
109}
110
111static inline bool
112drm_buddy_block_is_free(struct drm_buddy_block *block)
113{
114 return drm_buddy_block_state(block) == DRM_BUDDY_FREE;
115}
116
117static inline bool
118drm_buddy_block_is_split(struct drm_buddy_block *block)
119{
120 return drm_buddy_block_state(block) == DRM_BUDDY_SPLIT;
121}
122
123static inline u64
124drm_buddy_block_size(struct drm_buddy *mm,
125 struct drm_buddy_block *block)
126{
127 return mm->chunk_size << drm_buddy_block_order(block);
128}
129
130int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
131
132void drm_buddy_fini(struct drm_buddy *mm);
133
134struct drm_buddy_block *
135drm_buddy_alloc_blocks(struct drm_buddy *mm, unsigned int order);
136
137int drm_buddy_alloc_range(struct drm_buddy *mm,
138 struct list_head *blocks,
139 u64 start, u64 size);
140
141void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block);
142
143void drm_buddy_free_list(struct drm_buddy *mm, struct list_head *objects);
144
145void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p);
146void drm_buddy_block_print(struct drm_buddy *mm,
147 struct drm_buddy_block *block,
148 struct drm_printer *p);
149
150#endif
include/drm/drm_connector.h+12−6
@@ -522,9 +522,9 @@ struct drm_display_info { · 521 unmodified lines
522 enum subpixel_order subpixel_order;522 enum subpixel_order subpixel_order;
523 523
524#define DRM_COLOR_FORMAT_RGB444 (1<<0)524#define DRM_COLOR_FORMAT_RGB444 (1<<0)
525#define DRM_COLOR_FORMAT_YCRCB444 (1<<1)525#define DRM_COLOR_FORMAT_YCBCR444 (1<<1)
526#define DRM_COLOR_FORMAT_YCRCB422 (1<<2)526#define DRM_COLOR_FORMAT_YCBCR422 (1<<2)
527#define DRM_COLOR_FORMAT_YCRCB420 (1<<3)527#define DRM_COLOR_FORMAT_YCBCR420 (1<<3)
528 528
529 /**529 /**
530 * @panel_orientation: Read only connector property for built-in panels,530 * @panel_orientation: Read only connector property for built-in panels,
@@ -592,10 +592,16 @@ struct drm_display_info { · 61 unmodified lines
592 bool rgb_quant_range_selectable;592 bool rgb_quant_range_selectable;
593 593
594 /**594 /**
595 * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even595 * @edid_hdmi_dc_rgb444_modes: Mask of supported hdmi deep color modes
596 * more stuff redundant with @bus_formats.596 * in RGB 4:4:4. Even more stuff redundant with @bus_formats.
597 */597 */
598 u8 edid_hdmi_dc_modes;598 u8 edid_hdmi_rgb444_dc_modes;
599
600 /**
601 * @edid_hdmi_dc_ycbcr444_modes: Mask of supported hdmi deep color
602 * modes in YCbCr 4:4:4. Even more stuff redundant with @bus_formats.
603 */
604 u8 edid_hdmi_ycbcr444_dc_modes;
599 605
600 /**606 /**
601 * @cea_rev: CEA revision of the HDMI sink.607 * @cea_rev: CEA revision of the HDMI sink.
include/drm/drm_crtc.h+10−0
@@ -285,6 +285,10 @@ struct drm_crtc_state { · 284 unmodified lines
285 * Lookup table for converting pixel data after the color conversion285 * Lookup table for converting pixel data after the color conversion
286 * matrix @ctm. See drm_crtc_enable_color_mgmt(). The blob (if not286 * matrix @ctm. See drm_crtc_enable_color_mgmt(). The blob (if not
287 * NULL) is an array of &struct drm_color_lut.287 * NULL) is an array of &struct drm_color_lut.
288 *
289 * Note that for mostly historical reasons stemming from Xorg heritage,
290 * this is also used to store the color map (also sometimes color lut,
291 * CLUT or color palette) for indexed formats like DRM_FORMAT_C8.
288 */292 */
289 struct drm_property_blob *gamma_lut;293 struct drm_property_blob *gamma_lut;
290 294
@@ -1075,12 +1079,18 @@ struct drm_crtc { · 784 unmodified lines
1075 /**1079 /**
1076 * @gamma_size: Size of legacy gamma ramp reported to userspace. Set up1080 * @gamma_size: Size of legacy gamma ramp reported to userspace. Set up
1077 * by calling drm_mode_crtc_set_gamma_size().1081 * by calling drm_mode_crtc_set_gamma_size().
1082 *
1083 * Note that atomic drivers need to instead use
1084 * &drm_crtc_state.gamma_lut. See drm_crtc_enable_color_mgmt().
1078 */1085 */
1079 uint32_t gamma_size;1086 uint32_t gamma_size;
1080 1087
1081 /**1088 /**
1082 * @gamma_store: Gamma ramp values used by the legacy SETGAMMA and1089 * @gamma_store: Gamma ramp values used by the legacy SETGAMMA and
1083 * GETGAMMA IOCTls. Set up by calling drm_mode_crtc_set_gamma_size().1090 * GETGAMMA IOCTls. Set up by calling drm_mode_crtc_set_gamma_size().
1091 *
1092 * Note that atomic drivers need to instead use
1093 * &drm_crtc_state.gamma_lut. See drm_crtc_enable_color_mgmt().
1084 */1094 */
1085 uint16_t *gamma_store;1095 uint16_t *gamma_store;
1086 1096
include/drm/drm_dsc.h+1−1
@@ -8,7 +8,7 @@ · 7 unmodified lines
8#ifndef DRM_DSC_H_8#ifndef DRM_DSC_H_
9#define DRM_DSC_H_9#define DRM_DSC_H_
10 10
11#include <drm/drm_dp_helper.h>11#include <drm/dp/drm_dp_helper.h>
12 12
13/* VESA Display Stream Compression DSC 1.2 constants */13/* VESA Display Stream Compression DSC 1.2 constants */
14#define DSC_NUM_BUF_RANGES 1514#define DSC_NUM_BUF_RANGES 15
include/drm/drm_edid.h+2−2
@@ -401,8 +401,8 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, · 400 unmodified lines
401 const struct drm_display_mode *mode);401 const struct drm_display_mode *mode);
402 402
403void403void
404drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,404drm_hdmi_avi_infoframe_colorimetry(struct hdmi_avi_infoframe *frame,
405 const struct drm_connector_state *conn_state);405 const struct drm_connector_state *conn_state);
406 406
407void407void
408drm_hdmi_avi_infoframe_bars(struct hdmi_avi_infoframe *frame,408drm_hdmi_avi_infoframe_bars(struct hdmi_avi_infoframe *frame,
include/drm/drm_mipi_dbi.h+1−1
@@ -194,7 +194,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, · 193 unmodified lines
194#ifdef CONFIG_DEBUG_FS194#ifdef CONFIG_DEBUG_FS
195void mipi_dbi_debugfs_init(struct drm_minor *minor);195void mipi_dbi_debugfs_init(struct drm_minor *minor);
196#else196#else
197#define mipi_dbi_debugfs_init NULL197static inline void mipi_dbi_debugfs_init(struct drm_minor *minor) {}
198#endif198#endif
199 199
200#endif /* __LINUX_MIPI_DBI_H */200#endif /* __LINUX_MIPI_DBI_H */
include/drm/drm_modeset_lock.h+1−0
@@ -34,6 +34,7 @@ struct drm_modeset_lock; · 33 unmodified lines
34 * struct drm_modeset_acquire_ctx - locking context (see ww_acquire_ctx)34 * struct drm_modeset_acquire_ctx - locking context (see ww_acquire_ctx)
35 * @ww_ctx: base acquire ctx35 * @ww_ctx: base acquire ctx
36 * @contended: used internally for -EDEADLK handling36 * @contended: used internally for -EDEADLK handling
37 * @stack_depot: used internally for contention debugging
37 * @locked: list of held locks38 * @locked: list of held locks
38 * @trylock_only: trylock mode used in atomic contexts/panic notifiers39 * @trylock_only: trylock mode used in atomic contexts/panic notifiers
39 * @interruptible: whether interruptible locking should be used.40 * @interruptible: whether interruptible locking should be used.
include/drm/drm_module.h+125−0
@@ -0,0 +1,125 @@
1/* SPDX-License-Identifier: MIT */
2
3#ifndef DRM_MODULE_H
4#define DRM_MODULE_H
5
6#include <linux/pci.h>
7#include <linux/platform_device.h>
8
9#include <drm/drm_drv.h>
10
11/**
12 * DOC: overview
13 *
14 * This library provides helpers registering DRM drivers during module
15 * initialization and shutdown. The provided helpers act like bus-specific
16 * module helpers, such as module_pci_driver(), but respect additional
17 * parameters that control DRM driver registration.
18 *
19 * Below is an example of initializing a DRM driver for a device on the
20 * PCI bus.
21 *
22 * .. code-block:: c
23 *
24 * struct pci_driver my_pci_drv = {
25 * };
26 *
27 * drm_module_pci_driver(my_pci_drv);
28 *
29 * The generated code will test if DRM drivers are enabled and register
30 * the PCI driver my_pci_drv. For more complex module initialization, you
31 * can still use module_init() and module_exit() in your driver.
32 */
33
34/*
35 * PCI drivers
36 */
37
38static inline int __init drm_pci_register_driver(struct pci_driver *pci_drv)
39{
40 if (drm_firmware_drivers_only())
41 return -ENODEV;
42
43 return pci_register_driver(pci_drv);
44}
45
46/**
47 * drm_module_pci_driver - Register a DRM driver for PCI-based devices
48 * @__pci_drv: the PCI driver structure
49 *
50 * Registers a DRM driver for devices on the PCI bus. The helper
51 * macro behaves like module_pci_driver() but tests the state of
52 * drm_firmware_drivers_only(). For more complex module initialization,
53 * use module_init() and module_exit() directly.
54 *
55 * Each module may only use this macro once. Calling it replaces
56 * module_init() and module_exit().
57 */
58#define drm_module_pci_driver(__pci_drv) \
59 module_driver(__pci_drv, drm_pci_register_driver, pci_unregister_driver)
60
61static inline int __init
62drm_pci_register_driver_if_modeset(struct pci_driver *pci_drv, int modeset)
63{
64 if (drm_firmware_drivers_only() && modeset == -1)
65 return -ENODEV;
66 if (modeset == 0)
67 return -ENODEV;
68
69 return pci_register_driver(pci_drv);
70}
71
72static inline void __exit
73drm_pci_unregister_driver_if_modeset(struct pci_driver *pci_drv, int modeset)
74{
75 pci_unregister_driver(pci_drv);
76}
77
78/**
79 * drm_module_pci_driver_if_modeset - Register a DRM driver for PCI-based devices
80 * @__pci_drv: the PCI driver structure
81 * @__modeset: an additional parameter that disables the driver
82 *
83 * This macro is deprecated and only provided for existing drivers. For
84 * new drivers, use drm_module_pci_driver().
85 *
86 * Registers a DRM driver for devices on the PCI bus. The helper macro
87 * behaves like drm_module_pci_driver() with an additional driver-specific
88 * flag. If __modeset is 0, the driver has been disabled, if __modeset is
89 * -1 the driver state depends on the global DRM state. For all other
90 * values, the PCI driver has been enabled. The default should be -1.
91 */
92#define drm_module_pci_driver_if_modeset(__pci_drv, __modeset) \
93 module_driver(__pci_drv, drm_pci_register_driver_if_modeset, \
94 drm_pci_unregister_driver_if_modeset, __modeset)
95
96/*
97 * Platform drivers
98 */
99
100static inline int __init
101drm_platform_driver_register(struct platform_driver *platform_drv)
102{
103 if (drm_firmware_drivers_only())
104 return -ENODEV;
105
106 return platform_driver_register(platform_drv);
107}
108
109/**
110 * drm_module_platform_driver - Register a DRM driver for platform devices
111 * @__platform_drv: the platform driver structure
112 *
113 * Registers a DRM driver for devices on the platform bus. The helper
114 * macro behaves like module_platform_driver() but tests the state of
115 * drm_firmware_drivers_only(). For more complex module initialization,
116 * use module_init() and module_exit() directly.
117 *
118 * Each module may only use this macro once. Calling it replaces
119 * module_init() and module_exit().
120 */
121#define drm_module_platform_driver(__platform_drv) \
122 module_driver(__platform_drv, drm_platform_driver_register, \
123 platform_driver_unregister)
124
125#endif
include/drm/drm_plane.h+1−1
@@ -516,7 +516,7 @@ struct drm_plane_funcs { · 515 unmodified lines
516 * This optional hook is used for the DRM to determine if the given516 * This optional hook is used for the DRM to determine if the given
517 * format/modifier combination is valid for the plane. This allows the517 * format/modifier combination is valid for the plane. This allows the
518 * DRM to generate the correct format bitmask (which formats apply to518 * DRM to generate the correct format bitmask (which formats apply to
519 * which modifier), and to valdiate modifiers at atomic_check time.519 * which modifier), and to validate modifiers at atomic_check time.
520 *520 *
521 * If not present, then any modifier in the plane's modifier521 * If not present, then any modifier in the plane's modifier
522 * list is allowed with any of the plane's formats.522 * list is allowed with any of the plane's formats.
include/drm/drm_privacy_screen_driver.h+12−1
@@ -73,10 +73,21 @@ struct drm_privacy_screen { · 72 unmodified lines
73 * for more info.73 * for more info.
74 */74 */
75 enum drm_privacy_screen_status hw_state;75 enum drm_privacy_screen_status hw_state;
76 /**
77 * @drvdata: Private data owned by the privacy screen provider
78 */
79 void *drvdata;
76};80};
77 81
82static inline
83void *drm_privacy_screen_get_drvdata(struct drm_privacy_screen *priv)
84{
85 return priv->drvdata;
86}
87
78struct drm_privacy_screen *drm_privacy_screen_register(88struct drm_privacy_screen *drm_privacy_screen_register(
79 struct device *parent, const struct drm_privacy_screen_ops *ops);89 struct device *parent, const struct drm_privacy_screen_ops *ops,
90 void *data);
80void drm_privacy_screen_unregister(struct drm_privacy_screen *priv);91void drm_privacy_screen_unregister(struct drm_privacy_screen *priv);
81 92
82void drm_privacy_screen_call_notifier_chain(struct drm_privacy_screen *priv);93void drm_privacy_screen_call_notifier_chain(struct drm_privacy_screen *priv);
include/drm/ttm/ttm_resource.h+16−7
@@ -105,11 +105,11 @@ struct ttm_resource_manager_func { · 104 unmodified lines
105 * @use_type: The memory type is enabled.105 * @use_type: The memory type is enabled.
106 * @use_tt: If a TT object should be used for the backing store.106 * @use_tt: If a TT object should be used for the backing store.
107 * @size: Size of the managed region.107 * @size: Size of the managed region.
108 * @bdev: ttm device this manager belongs to
108 * @func: structure pointer implementing the range manager. See above109 * @func: structure pointer implementing the range manager. See above
109 * @move_lock: lock for move fence110 * @move_lock: lock for move fence
110 * static information. bdev::driver::io_mem_free is never used.
111 * @lru: The lru list for this memory type.
112 * @move: The fence of the last pipelined move operation.111 * @move: The fence of the last pipelined move operation.
112 * @lru: The lru list for this memory type.
113 *113 *
114 * This structure is used to identify and manage memory types for a device.114 * This structure is used to identify and manage memory types for a device.
115 */115 */
@@ -119,20 +119,21 @@ struct ttm_resource_manager { · 3 unmodified lines
119 */119 */
120 bool use_type;120 bool use_type;
121 bool use_tt;121 bool use_tt;
122 struct ttm_device *bdev;
122 uint64_t size;123 uint64_t size;
123 const struct ttm_resource_manager_func *func;124 const struct ttm_resource_manager_func *func;
124 spinlock_t move_lock;125 spinlock_t move_lock;
125 126
126 /*127 /*
127 * Protected by the global->lru_lock.128 * Protected by @move_lock.
128 */129 */
129 130 struct dma_fence *move;
130 struct list_head lru[TTM_MAX_BO_PRIORITY];
131 131
132 /*132 /*
133 * Protected by @move_lock.133 * Protected by the global->lru_lock.
134 */134 */
135 struct dma_fence *move;135
136 struct list_head lru[TTM_MAX_BO_PRIORITY];
136};137};
137 138
138/**139/**
@@ -160,6 +161,7 @@ struct ttm_bus_placement { · 21 unmodified lines
160 * @mem_type: Resource type of the allocation.161 * @mem_type: Resource type of the allocation.
161 * @placement: Placement flags.162 * @placement: Placement flags.
162 * @bus: Placement on io bus accessible to the CPU163 * @bus: Placement on io bus accessible to the CPU
164 * @bo: weak reference to the BO, protected by ttm_device::lru_lock
163 *165 *
164 * Structure indicating the placement and space resources used by a166 * Structure indicating the placement and space resources used by a
165 * buffer object.167 * buffer object.
@@ -170,6 +172,7 @@ struct ttm_resource { · 4 unmodified lines
170 uint32_t mem_type;172 uint32_t mem_type;
171 uint32_t placement;173 uint32_t placement;
172 struct ttm_bus_placement bus;174 struct ttm_bus_placement bus;
175 struct ttm_buffer_object *bo;
173};176};
174 177
175/**178/**
@@ -261,14 +264,20 @@ ttm_resource_manager_cleanup(struct ttm_resource_manager *man) · 85 unmodified lines
261void ttm_resource_init(struct ttm_buffer_object *bo,264void ttm_resource_init(struct ttm_buffer_object *bo,
262 const struct ttm_place *place,265 const struct ttm_place *place,
263 struct ttm_resource *res);266 struct ttm_resource *res);
267void ttm_resource_fini(struct ttm_resource_manager *man,
268 struct ttm_resource *res);
269
264int ttm_resource_alloc(struct ttm_buffer_object *bo,270int ttm_resource_alloc(struct ttm_buffer_object *bo,
265 const struct ttm_place *place,271 const struct ttm_place *place,
266 struct ttm_resource **res);272 struct ttm_resource **res);
267void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res);273void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res);
268bool ttm_resource_compat(struct ttm_resource *res,274bool ttm_resource_compat(struct ttm_resource *res,
269 struct ttm_placement *placement);275 struct ttm_placement *placement);
276void ttm_resource_set_bo(struct ttm_resource *res,
277 struct ttm_buffer_object *bo);
270 278
271void ttm_resource_manager_init(struct ttm_resource_manager *man,279void ttm_resource_manager_init(struct ttm_resource_manager *man,
280 struct ttm_device *bdev,
272 unsigned long p_size);281 unsigned long p_size);
273 282
274int ttm_resource_manager_evict_all(struct ttm_device *bdev,283int ttm_resource_manager_evict_all(struct ttm_device *bdev,
include/linux/dma-buf-map.h+2−2
@@ -52,13 +52,13 @@ · 51 unmodified lines
52 *52 *
53 * struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(0xdeadbeaf);53 * struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(0xdeadbeaf);
54 *54 *
55 * dma_buf_map_set_vaddr(&map. 0xdeadbeaf);55 * dma_buf_map_set_vaddr(&map, 0xdeadbeaf);
56 *56 *
57 * To set an address in I/O memory, use dma_buf_map_set_vaddr_iomem().57 * To set an address in I/O memory, use dma_buf_map_set_vaddr_iomem().
58 *58 *
59 * .. code-block:: c59 * .. code-block:: c
60 *60 *
61 * dma_buf_map_set_vaddr_iomem(&map. 0xdeadbeaf);61 * dma_buf_map_set_vaddr_iomem(&map, 0xdeadbeaf);
62 *62 *
63 * Instances of struct dma_buf_map do not have to be cleaned up, but63 * Instances of struct dma_buf_map do not have to be cleaned up, but
64 * can be cleared to NULL with dma_buf_map_clear(). Cleared mappings64 * can be cleared to NULL with dma_buf_map_clear(). Cleared mappings
include/linux/dma-resv.h+2−2
@@ -458,8 +458,8 @@ void dma_resv_fini(struct dma_resv *obj); · 457 unmodified lines
458int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences);458int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences);
459void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence);459void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence);
460void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence);460void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence);
461int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **pfence_excl,461int dma_resv_get_fences(struct dma_resv *obj, bool write,
462 unsigned *pshared_count, struct dma_fence ***pshared);462 unsigned int *num_fences, struct dma_fence ***fences);
463int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src);463int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src);
464long dma_resv_wait_timeout(struct dma_resv *obj, bool wait_all, bool intr,464long dma_resv_wait_timeout(struct dma_resv *obj, bool wait_all, bool intr,
465 unsigned long timeout);465 unsigned long timeout);
include/linux/fb.h+1−0
@@ -502,6 +502,7 @@ struct fb_info { · 501 unmodified lines
502 } *apertures;502 } *apertures;
503 503
504 bool skip_vt_switch; /* no VT switch on suspend/resume required */504 bool skip_vt_switch; /* no VT switch on suspend/resume required */
505 bool forced_out; /* set when being removed by another driver */
505};506};
506 507
507static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {508static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
include/linux/rwsem.h+1−1
@@ -230,7 +230,7 @@ extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map * · 229 unmodified lines
230do { \230do { \
231 typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \231 typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \
232 _down_write_nest_lock(sem, &(nest_lock)->dep_map); \232 _down_write_nest_lock(sem, &(nest_lock)->dep_map); \
233} while (0);233} while (0)
234 234
235/*235/*
236 * Take/release a lock when not the owner will release it.236 * Take/release a lock when not the owner will release it.
include/soc/bcm2835/raspberrypi-firmware.h+1−0
@@ -91,6 +91,7 @@ enum rpi_firmware_property_tag { · 90 unmodified lines
91 RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,91 RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,
92 RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,92 RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,
93 RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058,93 RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058,
94 RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066,
94 95
95 /* Dispmanx TAGS */96 /* Dispmanx TAGS */
96 RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001,97 RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001,
include/uapi/drm/panfrost_drm.h+2−2
@@ -84,14 +84,14 @@ struct drm_panfrost_wait_bo { · 83 unmodified lines
84 __s64 timeout_ns; /* absolute */84 __s64 timeout_ns; /* absolute */
85};85};
86 86
87/* Valid flags to pass to drm_panfrost_create_bo */
87#define PANFROST_BO_NOEXEC 188#define PANFROST_BO_NOEXEC 1
88#define PANFROST_BO_HEAP 289#define PANFROST_BO_HEAP 2
89 90
90/**91/**
91 * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs.92 * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs.
92 *93 *
93 * There are currently no values for the flags argument, but it may be94 * The flags argument is a bit mask of PANFROST_BO_* flags.
94 * used in a future extension.
95 */95 */
96struct drm_panfrost_create_bo {96struct drm_panfrost_create_bo {
97 __u32 size;97 __u32 size;