Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'drm-misc-next-2017-04-07' of git://anongit.freedesktop.org/git/drm-misc into drm-next

Last drm-misc-next pull req for 4.12

Core changes:
- fb_helper checkpatch cleanup and simplified _add_one_connector() (Thierry)
- drm_ioctl and drm_sysfs improved/gained documentation (Daniel)
- [ABI] Repurpose reserved field in drm_event_vblank for crtc_id (Ander)
- Plumb acquire ctx through legacy paths to avoid lock_all and legacy_backoff
(Daniel)
- Add connector_atomic_check to check conn constraints on modeset (Maarten)
- Add drm_of_find_panel_or_bridge to remove boilerplate in drivers (Rob)

Driver changes:
- meson moved to drm-misc (Neil)
- Added support for Amlogic GX SoCs in dw-hdmi (Neil)
- Rockchip unbind actually cleans up the things bind initializes (Jeffy)
- A couple misc fixes in virtio, dw-hdmi

NOTE: this also includes a backmerge of drm-next as well rc5 (we needed vmwgfx
as well as the new synopsys media formats)

* tag 'drm-misc-next-2017-04-07' of git://anongit.freedesktop.org/git/drm-misc: (77 commits)
Revert "drm: Don't allow interruptions when opening debugfs/crc"
drm: Only take cursor locks when the cursor plane exists
drm/vmwgfx: Fix fbdev emulation using legacy functions
drm/rockchip: Shutdown all crtcs when unbinding drm
drm/rockchip: Reorder drm bind/unbind sequence
drm/rockchip: analogix_dp: Disable clock when unbinding
drm/rockchip: vop: Unprepare clocks when unbinding
drm/rockchip: vop: Enable pm domain before vop_initial
drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding
drm/rockchip: cdn-dp: Don't try to release firmware when not loaded
drm: bridge: analogix: Destroy connector & encoder when unbinding
drm: bridge: analogix: Disable clock when unbinding
drm: bridge: analogix: Unregister dp aux when unbinding
drm: bridge: analogix: Detach panel when unbinding analogix dp
drm: Don't allow interruptions when opening debugfs/crc
drm/virtio: don't leak bo on drm_gem_object_init failure
drm: bridge: dw-hdmi: fix input format/encoding from plat_data
drm: omap: use common OF graph helpers
drm: convert drivers to use drm_of_find_panel_or_bridge
drm: convert drivers to use of_graph_get_remote_node
...

+6064 -1997
+111
Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt
··· 1 + Amlogic specific extensions to the Synopsys Designware HDMI Controller 2 + ====================================================================== 3 + 4 + The Amlogic Meson Synopsys Designware Integration is composed of : 5 + - A Synopsys DesignWare HDMI Controller IP 6 + - A TOP control block controlling the Clocks and PHY 7 + - A custom HDMI PHY in order to convert video to TMDS signal 8 + ___________________________________ 9 + | HDMI TOP |<= HPD 10 + |___________________________________| 11 + | | | 12 + | Synopsys HDMI | HDMI PHY |=> TMDS 13 + | Controller |________________| 14 + |___________________________________|<=> DDC 15 + 16 + The HDMI TOP block only supports HPD sensing. 17 + The Synopsys HDMI Controller interrupt is routed through the 18 + TOP Block interrupt. 19 + Communication to the TOP Block and the Synopsys HDMI Controller is done 20 + via a pair of dedicated addr+read/write registers. 21 + The HDMI PHY is configured by registers in the HHI register block. 22 + 23 + Pixel data arrives in 4:4:4 format from the VENC block and the VPU HDMI mux 24 + selects either the ENCI encoder for the 576i or 480i formats or the ENCP 25 + encoder for all the other formats including interlaced HD formats. 26 + 27 + The VENC uses a DVI encoder on top of the ENCI or ENCP encoders to generate 28 + DVI timings for the HDMI controller. 29 + 30 + Amlogic Meson GXBB, GXL and GXM SoCs families embeds the Synopsys DesignWare 31 + HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF 32 + audio source interfaces. 33 + 34 + Required properties: 35 + - compatible: value should be different for each SoC family as : 36 + - GXBB (S905) : "amlogic,meson-gxbb-dw-hdmi" 37 + - GXL (S905X, S905D) : "amlogic,meson-gxl-dw-hdmi" 38 + - GXM (S912) : "amlogic,meson-gxm-dw-hdmi" 39 + followed by the common "amlogic,meson-gx-dw-hdmi" 40 + - reg: Physical base address and length of the controller's registers. 41 + - interrupts: The HDMI interrupt number 42 + - clocks, clock-names : must have the phandles to the HDMI iahb and isfr clocks, 43 + and the Amlogic Meson venci clocks as described in 44 + Documentation/devicetree/bindings/clock/clock-bindings.txt, 45 + the clocks are soc specific, the clock-names should be "iahb", "isfr", "venci" 46 + - resets, resets-names: must have the phandles to the HDMI apb, glue and phy 47 + resets as described in : 48 + Documentation/devicetree/bindings/reset/reset.txt, 49 + the reset-names should be "hdmitx_apb", "hdmitx", "hdmitx_phy" 50 + 51 + Required nodes: 52 + 53 + The connections to the HDMI ports are modeled using the OF graph 54 + bindings specified in Documentation/devicetree/bindings/graph.txt. 55 + 56 + The following table lists for each supported model the port number 57 + corresponding to each HDMI output and input. 58 + 59 + Port 0 Port 1 60 + ----------------------------------------- 61 + S905 (GXBB) VENC Input TMDS Output 62 + S905X (GXL) VENC Input TMDS Output 63 + S905D (GXL) VENC Input TMDS Output 64 + S912 (GXM) VENC Input TMDS Output 65 + 66 + Example: 67 + 68 + hdmi-connector { 69 + compatible = "hdmi-connector"; 70 + type = "a"; 71 + 72 + port { 73 + hdmi_connector_in: endpoint { 74 + remote-endpoint = <&hdmi_tx_tmds_out>; 75 + }; 76 + }; 77 + }; 78 + 79 + hdmi_tx: hdmi-tx@c883a000 { 80 + compatible = "amlogic,meson-gxbb-dw-hdmi", "amlogic,meson-gx-dw-hdmi"; 81 + reg = <0x0 0xc883a000 0x0 0x1c>; 82 + interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>; 83 + resets = <&reset RESET_HDMITX_CAPB3>, 84 + <&reset RESET_HDMI_SYSTEM_RESET>, 85 + <&reset RESET_HDMI_TX>; 86 + reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy"; 87 + clocks = <&clkc CLKID_HDMI_PCLK>, 88 + <&clkc CLKID_CLK81>, 89 + <&clkc CLKID_GCLK_VENCI_INT0>; 90 + clock-names = "isfr", "iahb", "venci"; 91 + #address-cells = <1>; 92 + #size-cells = <0>; 93 + 94 + /* VPU VENC Input */ 95 + hdmi_tx_venc_port: port@0 { 96 + reg = <0>; 97 + 98 + hdmi_tx_in: endpoint { 99 + remote-endpoint = <&hdmi_tx_out>; 100 + }; 101 + }; 102 + 103 + /* TMDS Output */ 104 + hdmi_tx_tmds_port: port@1 { 105 + reg = <1>; 106 + 107 + hdmi_tx_tmds_out: endpoint { 108 + remote-endpoint = <&hdmi_connector_in>; 109 + }; 110 + }; 111 + };
+5
Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
··· 17 17 18 18 Optional properties: 19 19 - power-domains: a phandle to mipi dsi power domain node. 20 + - resets: list of phandle + reset specifier pairs, as described in [3]. 21 + - reset-names: string reset name, must be "apb". 20 22 21 23 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 22 24 [2] Documentation/devicetree/bindings/media/video-interfaces.txt 25 + [3] Documentation/devicetree/bindings/reset/reset.txt 23 26 24 27 Example: 25 28 mipi_dsi: mipi@ff960000 { ··· 33 30 interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; 34 31 clocks = <&cru SCLK_MIPI_24M>, <&cru PCLK_MIPI_DSI0>; 35 32 clock-names = "ref", "pclk"; 33 + resets = <&cru SRST_MIPIDSI0>; 34 + reset-names = "apb"; 36 35 rockchip,grf = <&grf>; 37 36 status = "okay"; 38 37
+15
Documentation/gpu/bridge/dw-hdmi.rst
··· 1 + ======================================================= 2 + drm/bridge/dw-hdmi Synopsys DesignWare HDMI Controller 3 + ======================================================= 4 + 5 + Synopsys DesignWare HDMI Controller 6 + =================================== 7 + 8 + This section covers everything related to the Synopsys DesignWare HDMI 9 + Controller implemented as a DRM bridge. 10 + 11 + Supported Input Formats and Encodings 12 + ------------------------------------- 13 + 14 + .. kernel-doc:: include/drm/bridge/dw_hdmi.h 15 + :doc: Supported input formats and encodings
-50
Documentation/gpu/drm-internals.rst
··· 255 255 .. kernel-doc:: drivers/gpu/drm/drm_file.c 256 256 :export: 257 257 258 - IOCTLs 259 - ------ 260 - 261 - struct drm_ioctl_desc \*ioctls; int num_ioctls; 262 - Driver-specific ioctls descriptors table. 263 - 264 - Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls 265 - descriptors table is indexed by the ioctl number offset from the base 266 - value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize 267 - the table entries. 268 - 269 - :: 270 - 271 - DRM_IOCTL_DEF_DRV(ioctl, func, flags) 272 - 273 - ``ioctl`` is the ioctl name. Drivers must define the DRM_##ioctl and 274 - DRM_IOCTL_##ioctl macros to the ioctl number offset from 275 - DRM_COMMAND_BASE and the ioctl number respectively. The first macro is 276 - private to the device while the second must be exposed to userspace in a 277 - public header. 278 - 279 - ``func`` is a pointer to the ioctl handler function compatible with the 280 - ``drm_ioctl_t`` type. 281 - 282 - :: 283 - 284 - typedef int drm_ioctl_t(struct drm_device *dev, void *data, 285 - struct drm_file *file_priv); 286 - 287 - ``flags`` is a bitmask combination of the following values. It restricts 288 - how the ioctl is allowed to be called. 289 - 290 - - DRM_AUTH - Only authenticated callers allowed 291 - 292 - - DRM_MASTER - The ioctl can only be called on the master file handle 293 - 294 - - DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed 295 - 296 - - DRM_CONTROL_ALLOW - The ioctl can only be called on a control 297 - device 298 - 299 - - DRM_UNLOCKED - The ioctl handler will be called without locking the 300 - DRM global mutex. This is the enforced default for kms drivers (i.e. 301 - using the DRIVER_MODESET flag) and hence shouldn't be used any more 302 - for new drivers. 303 - 304 - .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c 305 - :export: 306 - 307 - 308 258 Misc Utilities 309 259 ============== 310 260
+24
Documentation/gpu/drm-uapi.rst
··· 160 160 visible to user-space and accessible beyond open-file boundaries, they 161 161 cannot support render nodes. 162 162 163 + IOCTL Support on Device Nodes 164 + ============================= 165 + 166 + .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c 167 + :doc: driver specific ioctls 168 + 169 + .. kernel-doc:: include/drm/drm_ioctl.h 170 + :internal: 171 + 172 + .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c 173 + :export: 174 + 175 + .. kernel-doc:: drivers/gpu/drm/drm_ioc32.c 176 + :export: 163 177 164 178 Testing and validation 165 179 ====================== ··· 232 218 233 219 .. kernel-doc:: drivers/gpu/drm/drm_debugfs.c 234 220 :export: 221 + 222 + Sysfs Support 223 + ============= 224 + 225 + .. kernel-doc:: drivers/gpu/drm/drm_sysfs.c 226 + :doc: overview 227 + 228 + .. kernel-doc:: drivers/gpu/drm/drm_sysfs.c 229 + :export: 230 + 235 231 236 232 VBlank event handling 237 233 =====================
+2
Documentation/gpu/index.rst
··· 11 11 drm-kms-helpers 12 12 drm-uapi 13 13 i915 14 + meson 14 15 tinydrm 15 16 vc4 16 17 vga-switcheroo 17 18 vgaarbiter 19 + bridge/dw-hdmi 18 20 todo 19 21 20 22 .. only:: subproject and html
+61
Documentation/gpu/meson.rst
··· 1 + ============================================= 2 + drm/meson AmLogic Meson Video Processing Unit 3 + ============================================= 4 + 5 + .. kernel-doc:: drivers/gpu/drm/meson/meson_drv.c 6 + :doc: Video Processing Unit 7 + 8 + Video Processing Unit 9 + ===================== 10 + 11 + The Amlogic Meson Display controller is composed of several components 12 + that are going to be documented below: 13 + 14 + .. code:: 15 + 16 + DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| 17 + | vd1 _______ _____________ _________________ | | 18 + D |-------| |----| | | | | HDMI PLL | 19 + D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | 20 + R |-------| |----| Processing | | | | | 21 + | osd2 | | | |---| Enci ----------|----|-----VDAC------| 22 + R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| 23 + A | osd1 | | | Blenders | | Encl ----------|----|---------------| 24 + M |-------|______|----|____________| |________________| | | 25 + ___|__________________________________________________________|_______________| 26 + 27 + Video Input Unit 28 + ================ 29 + 30 + .. kernel-doc:: drivers/gpu/drm/meson/meson_viu.c 31 + :doc: Video Input Unit 32 + 33 + Video Post Processing 34 + ===================== 35 + 36 + .. kernel-doc:: drivers/gpu/drm/meson/meson_vpp.c 37 + :doc: Video Post Processing 38 + 39 + Video Encoder 40 + ============= 41 + 42 + .. kernel-doc:: drivers/gpu/drm/meson/meson_venc.c 43 + :doc: Video Encoder 44 + 45 + Video Canvas Management 46 + ======================= 47 + 48 + .. kernel-doc:: drivers/gpu/drm/meson/meson_canvas.c 49 + :doc: Canvas 50 + 51 + Video Clocks 52 + ============ 53 + 54 + .. kernel-doc:: drivers/gpu/drm/meson/meson_vclk.c 55 + :doc: Video Clocks 56 + 57 + HDMI Video Output 58 + ================= 59 + 60 + .. kernel-doc:: drivers/gpu/drm/meson/meson_dw_hdmi.c 61 + :doc: HDMI Output
+4 -27
Documentation/gpu/todo.rst
··· 16 16 With the recent ``drm_bus`` cleanup patches for 3.17 it is no longer required 17 17 to have a ``drm_bus`` structure set up. Drivers can directly set up the 18 18 ``drm_device`` structure instead of relying on bus methods in ``drm_usb.c`` 19 - and ``drm_platform.c``. The goal is to get rid of the driver's ``->load`` / 19 + and ``drm_pci.c``. The goal is to get rid of the driver's ``->load`` / 20 20 ``->unload`` callbacks and open-code the load/unload sequence properly, using 21 21 the new two-stage ``drm_device`` setup/teardown. 22 22 ··· 175 175 following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and 176 176 ``udl``. 177 177 178 - Contact: Daniel Vetter 178 + Contact: Daniel Vetter, respective driver maintainers 179 179 180 180 Switch to drm_connector_list_iter for any connector_list walking 181 181 ---------------------------------------------------------------- ··· 217 217 the kerneldoc better. This should also allow more fine-grained ``#include`` 218 218 directives. 219 219 220 + In the end no .c file should need to include ``drmP.h`` anymore. 221 + 220 222 Contact: Daniel Vetter 221 223 222 224 Add missing kerneldoc for exported functions ··· 246 244 prevent security issues in those legacy IOCTLs from being exploited on modern 247 245 drivers. This has multiple possible subtasks: 248 246 249 - * Make sure legacy IOCTLs can't be used on modern drivers. 250 247 * Extract support code for legacy features into a ``drm-legacy.ko`` kernel 251 248 module and compile it only when one of the legacy drivers is enabled. 252 - * Extract legacy functions into their own headers and remove it that from the 253 - monolithic ``drmP.h`` header. 254 - * Remove any lingering cruft from the OS abstraction layer from modern 255 - drivers. 256 249 257 250 This is mostly done, the only thing left is to split up ``drm_irq.c`` into 258 251 legacy cruft and the parts needed by modern KMS drivers. ··· 405 408 406 409 Outside DRM 407 410 =========== 408 - 409 - Better kerneldoc 410 - ---------------- 411 - 412 - This is pretty much done, but there's some advanced topics: 413 - 414 - Come up with a way to hyperlink to struct members. Currently you can hyperlink 415 - to the struct using ``#struct_name``, but not to a member within. Would need 416 - buy-in from kerneldoc maintainers, and the big question is how to make it work 417 - without totally unsightly 418 - ``drm_foo_bar_really_long_structure->even_longer_memeber`` all over the text 419 - which breaks text flow. 420 - 421 - Figure out how to integrate the asciidoc support for ascii-diagrams. We have a 422 - few of those (e.g. to describe mode timings), and asciidoc supports converting 423 - some ascii-art dialect into pngs. Would be really pretty to make that work. 424 - 425 - Contact: Daniel Vetter, Jani Nikula 426 - 427 - Jani is working on this already, hopefully lands in 4.8.
+959 -1
Documentation/media/uapi/v4l/subdev-formats.rst
··· 1258 1258 - b\ :sub:`2` 1259 1259 - b\ :sub:`1` 1260 1260 - b\ :sub:`0` 1261 + * .. _MEDIA-BUS-FMT-RGB101010-1X30: 1262 + 1263 + - MEDIA_BUS_FMT_RGB101010_1X30 1264 + - 0x1018 1265 + - 1266 + - 0 1267 + - 0 1268 + - r\ :sub:`9` 1269 + - r\ :sub:`8` 1270 + - r\ :sub:`7` 1271 + - r\ :sub:`6` 1272 + - r\ :sub:`5` 1273 + - r\ :sub:`4` 1274 + - r\ :sub:`3` 1275 + - r\ :sub:`2` 1276 + - r\ :sub:`1` 1277 + - r\ :sub:`0` 1278 + - g\ :sub:`9` 1279 + - g\ :sub:`8` 1280 + - g\ :sub:`7` 1281 + - g\ :sub:`6` 1282 + - g\ :sub:`5` 1283 + - g\ :sub:`4` 1284 + - g\ :sub:`3` 1285 + - g\ :sub:`2` 1286 + - g\ :sub:`1` 1287 + - g\ :sub:`0` 1288 + - b\ :sub:`9` 1289 + - b\ :sub:`8` 1290 + - b\ :sub:`7` 1291 + - b\ :sub:`6` 1292 + - b\ :sub:`5` 1293 + - b\ :sub:`4` 1294 + - b\ :sub:`3` 1295 + - b\ :sub:`2` 1296 + - b\ :sub:`1` 1297 + - b\ :sub:`0` 1298 + 1299 + .. raw:: latex 1300 + 1301 + \endgroup 1302 + 1303 + 1304 + The following table list existing packed 36bit wide RGB formats. 1305 + 1306 + .. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| 1307 + 1308 + .. _v4l2-mbus-pixelcode-rgb-36: 1309 + 1310 + .. raw:: latex 1311 + 1312 + \begingroup 1313 + \tiny 1314 + \setlength{\tabcolsep}{2pt} 1315 + 1316 + .. flat-table:: 36bit RGB formats 1317 + :header-rows: 2 1318 + :stub-columns: 0 1319 + :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1320 + 1321 + * - Identifier 1322 + - Code 1323 + - 1324 + - :cspan:`35` Data organization 1325 + * - 1326 + - 1327 + - Bit 1328 + - 35 1329 + - 34 1330 + - 33 1331 + - 32 1332 + - 31 1333 + - 30 1334 + - 29 1335 + - 28 1336 + - 27 1337 + - 26 1338 + - 25 1339 + - 24 1340 + - 23 1341 + - 22 1342 + - 21 1343 + - 20 1344 + - 19 1345 + - 18 1346 + - 17 1347 + - 16 1348 + - 15 1349 + - 14 1350 + - 13 1351 + - 12 1352 + - 11 1353 + - 10 1354 + - 9 1355 + - 8 1356 + - 7 1357 + - 6 1358 + - 5 1359 + - 4 1360 + - 3 1361 + - 2 1362 + - 1 1363 + - 0 1364 + * .. _MEDIA-BUS-FMT-RGB121212-1X36: 1365 + 1366 + - MEDIA_BUS_FMT_RGB121212_1X36 1367 + - 0x1019 1368 + - 1369 + - r\ :sub:`11` 1370 + - r\ :sub:`10` 1371 + - r\ :sub:`9` 1372 + - r\ :sub:`8` 1373 + - r\ :sub:`7` 1374 + - r\ :sub:`6` 1375 + - r\ :sub:`5` 1376 + - r\ :sub:`4` 1377 + - r\ :sub:`3` 1378 + - r\ :sub:`2` 1379 + - r\ :sub:`1` 1380 + - r\ :sub:`0` 1381 + - g\ :sub:`11` 1382 + - g\ :sub:`10` 1383 + - g\ :sub:`9` 1384 + - g\ :sub:`8` 1385 + - g\ :sub:`7` 1386 + - g\ :sub:`6` 1387 + - g\ :sub:`5` 1388 + - g\ :sub:`4` 1389 + - g\ :sub:`3` 1390 + - g\ :sub:`2` 1391 + - g\ :sub:`1` 1392 + - g\ :sub:`0` 1393 + - b\ :sub:`11` 1394 + - b\ :sub:`10` 1395 + - b\ :sub:`9` 1396 + - b\ :sub:`8` 1397 + - b\ :sub:`7` 1398 + - b\ :sub:`6` 1399 + - b\ :sub:`5` 1400 + - b\ :sub:`4` 1401 + - b\ :sub:`3` 1402 + - b\ :sub:`2` 1403 + - b\ :sub:`1` 1404 + - b\ :sub:`0` 1405 + 1406 + .. raw:: latex 1407 + 1408 + \endgroup 1409 + 1410 + 1411 + The following table list existing packed 48bit wide RGB formats. 1412 + 1413 + .. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| 1414 + 1415 + .. _v4l2-mbus-pixelcode-rgb-48: 1416 + 1417 + .. raw:: latex 1418 + 1419 + \begingroup 1420 + \tiny 1421 + \setlength{\tabcolsep}{2pt} 1422 + 1423 + .. flat-table:: 48bit RGB formats 1424 + :header-rows: 3 1425 + :stub-columns: 0 1426 + :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1427 + 1428 + * - Identifier 1429 + - Code 1430 + - 1431 + - :cspan:`31` Data organization 1432 + * - 1433 + - 1434 + - Bit 1435 + - 1436 + - 1437 + - 1438 + - 1439 + - 1440 + - 1441 + - 1442 + - 1443 + - 1444 + - 1445 + - 1446 + - 1447 + - 1448 + - 1449 + - 1450 + - 1451 + - 47 1452 + - 46 1453 + - 45 1454 + - 44 1455 + - 43 1456 + - 42 1457 + - 41 1458 + - 40 1459 + - 39 1460 + - 38 1461 + - 37 1462 + - 36 1463 + - 35 1464 + - 34 1465 + - 33 1466 + - 32 1467 + * - 1468 + - 1469 + - 1470 + - 31 1471 + - 30 1472 + - 29 1473 + - 28 1474 + - 27 1475 + - 26 1476 + - 25 1477 + - 24 1478 + - 23 1479 + - 22 1480 + - 21 1481 + - 20 1482 + - 19 1483 + - 18 1484 + - 17 1485 + - 16 1486 + - 15 1487 + - 14 1488 + - 13 1489 + - 12 1490 + - 11 1491 + - 10 1492 + - 9 1493 + - 8 1494 + - 7 1495 + - 6 1496 + - 5 1497 + - 4 1498 + - 3 1499 + - 2 1500 + - 1 1501 + - 0 1502 + * .. _MEDIA-BUS-FMT-RGB161616-1X48: 1503 + 1504 + - MEDIA_BUS_FMT_RGB161616_1X48 1505 + - 0x101a 1506 + - 1507 + - 1508 + - 1509 + - 1510 + - 1511 + - 1512 + - 1513 + - 1514 + - 1515 + - 1516 + - 1517 + - 1518 + - 1519 + - 1520 + - 1521 + - 1522 + - 1523 + - r\ :sub:`15` 1524 + - r\ :sub:`14` 1525 + - r\ :sub:`13` 1526 + - r\ :sub:`12` 1527 + - r\ :sub:`11` 1528 + - r\ :sub:`10` 1529 + - r\ :sub:`9` 1530 + - r\ :sub:`8` 1531 + - r\ :sub:`7` 1532 + - r\ :sub:`6` 1533 + - r\ :sub:`5` 1534 + - r\ :sub:`4` 1535 + - r\ :sub:`3` 1536 + - r\ :sub:`2` 1537 + - r\ :sub:`1` 1538 + - r\ :sub:`0` 1539 + * - 1540 + - 1541 + - 1542 + - g\ :sub:`15` 1543 + - g\ :sub:`14` 1544 + - g\ :sub:`13` 1545 + - g\ :sub:`12` 1546 + - g\ :sub:`11` 1547 + - g\ :sub:`10` 1548 + - g\ :sub:`9` 1549 + - g\ :sub:`8` 1550 + - g\ :sub:`7` 1551 + - g\ :sub:`6` 1552 + - g\ :sub:`5` 1553 + - g\ :sub:`4` 1554 + - g\ :sub:`3` 1555 + - g\ :sub:`2` 1556 + - g\ :sub:`1` 1557 + - g\ :sub:`0` 1558 + - b\ :sub:`15` 1559 + - b\ :sub:`14` 1560 + - b\ :sub:`13` 1561 + - b\ :sub:`12` 1562 + - b\ :sub:`11` 1563 + - b\ :sub:`10` 1564 + - b\ :sub:`9` 1565 + - b\ :sub:`8` 1566 + - b\ :sub:`7` 1567 + - b\ :sub:`6` 1568 + - b\ :sub:`5` 1569 + - b\ :sub:`4` 1570 + - b\ :sub:`3` 1571 + - b\ :sub:`2` 1572 + - b\ :sub:`1` 1573 + - b\ :sub:`0` 1261 1574 1262 1575 .. raw:: latex 1263 1576 ··· 2657 2344 2658 2345 - The number of bus samples per pixel. Pixels that are wider than the 2659 2346 bus width must be transferred in multiple samples. Common values are 2660 - 1, 1.5 (encoded as 1_5) and 2. 2347 + 0.5 (encoded as 0_5; in this case two pixels are transferred per bus 2348 + sample), 1, 1.5 (encoded as 1_5) and 2. 2661 2349 2662 2350 - The bus width. When the bus width is larger than the number of bits 2663 2351 per pixel component, several components are packed in a single bus ··· 6276 5962 - v\ :sub:`2` 6277 5963 - v\ :sub:`1` 6278 5964 - v\ :sub:`0` 5965 + * .. _MEDIA-BUS-FMT-UYYVYY8-0-5X24: 5966 + 5967 + - MEDIA_BUS_FMT_UYYVYY8_0_5X24 5968 + - 0x2026 5969 + - 5970 + - 5971 + - 5972 + - 5973 + - 5974 + - 5975 + - 5976 + - 5977 + - 5978 + - u\ :sub:`7` 5979 + - u\ :sub:`6` 5980 + - u\ :sub:`5` 5981 + - u\ :sub:`4` 5982 + - u\ :sub:`3` 5983 + - u\ :sub:`2` 5984 + - u\ :sub:`1` 5985 + - u\ :sub:`0` 5986 + - y\ :sub:`7` 5987 + - y\ :sub:`6` 5988 + - y\ :sub:`5` 5989 + - y\ :sub:`4` 5990 + - y\ :sub:`3` 5991 + - y\ :sub:`2` 5992 + - y\ :sub:`1` 5993 + - y\ :sub:`0` 5994 + - y\ :sub:`7` 5995 + - y\ :sub:`6` 5996 + - y\ :sub:`5` 5997 + - y\ :sub:`4` 5998 + - y\ :sub:`3` 5999 + - y\ :sub:`2` 6000 + - y\ :sub:`1` 6001 + - y\ :sub:`0` 6002 + * - 6003 + - 6004 + - 6005 + - 6006 + - 6007 + - 6008 + - 6009 + - 6010 + - 6011 + - 6012 + - 6013 + - v\ :sub:`7` 6014 + - v\ :sub:`6` 6015 + - v\ :sub:`5` 6016 + - v\ :sub:`4` 6017 + - v\ :sub:`3` 6018 + - v\ :sub:`2` 6019 + - v\ :sub:`1` 6020 + - v\ :sub:`0` 6021 + - y\ :sub:`7` 6022 + - y\ :sub:`6` 6023 + - y\ :sub:`5` 6024 + - y\ :sub:`4` 6025 + - y\ :sub:`3` 6026 + - y\ :sub:`2` 6027 + - y\ :sub:`1` 6028 + - y\ :sub:`0` 6029 + - y\ :sub:`7` 6030 + - y\ :sub:`6` 6031 + - y\ :sub:`5` 6032 + - y\ :sub:`4` 6033 + - y\ :sub:`3` 6034 + - y\ :sub:`2` 6035 + - y\ :sub:`1` 6036 + - y\ :sub:`0` 6279 6037 * .. _MEDIA-BUS-FMT-UYVY12-1X24: 6280 6038 6281 6039 - MEDIA_BUS_FMT_UYVY12_1X24 ··· 6673 6287 - v\ :sub:`2` 6674 6288 - v\ :sub:`1` 6675 6289 - v\ :sub:`0` 6290 + * .. _MEDIA-BUS-FMT-UYYVYY10-0-5X30: 6291 + 6292 + - MEDIA_BUS_FMT_UYYVYY10_0_5X30 6293 + - 0x2027 6294 + - 6295 + - 6296 + - 6297 + - u\ :sub:`9` 6298 + - u\ :sub:`8` 6299 + - u\ :sub:`7` 6300 + - u\ :sub:`6` 6301 + - u\ :sub:`5` 6302 + - u\ :sub:`4` 6303 + - u\ :sub:`3` 6304 + - u\ :sub:`2` 6305 + - u\ :sub:`1` 6306 + - u\ :sub:`0` 6307 + - y\ :sub:`9` 6308 + - y\ :sub:`8` 6309 + - y\ :sub:`7` 6310 + - y\ :sub:`6` 6311 + - y\ :sub:`5` 6312 + - y\ :sub:`4` 6313 + - y\ :sub:`3` 6314 + - y\ :sub:`2` 6315 + - y\ :sub:`1` 6316 + - y\ :sub:`0` 6317 + - y\ :sub:`9` 6318 + - y\ :sub:`8` 6319 + - y\ :sub:`7` 6320 + - y\ :sub:`6` 6321 + - y\ :sub:`5` 6322 + - y\ :sub:`4` 6323 + - y\ :sub:`3` 6324 + - y\ :sub:`2` 6325 + - y\ :sub:`1` 6326 + - y\ :sub:`0` 6327 + * - 6328 + - 6329 + - 6330 + - 6331 + - 6332 + - v\ :sub:`9` 6333 + - v\ :sub:`8` 6334 + - v\ :sub:`7` 6335 + - v\ :sub:`6` 6336 + - v\ :sub:`5` 6337 + - v\ :sub:`4` 6338 + - v\ :sub:`3` 6339 + - v\ :sub:`2` 6340 + - v\ :sub:`1` 6341 + - v\ :sub:`0` 6342 + - y\ :sub:`9` 6343 + - y\ :sub:`8` 6344 + - y\ :sub:`7` 6345 + - y\ :sub:`6` 6346 + - y\ :sub:`5` 6347 + - y\ :sub:`4` 6348 + - y\ :sub:`3` 6349 + - y\ :sub:`2` 6350 + - y\ :sub:`1` 6351 + - y\ :sub:`0` 6352 + - y\ :sub:`9` 6353 + - y\ :sub:`8` 6354 + - y\ :sub:`7` 6355 + - y\ :sub:`6` 6356 + - y\ :sub:`5` 6357 + - y\ :sub:`4` 6358 + - y\ :sub:`3` 6359 + - y\ :sub:`2` 6360 + - y\ :sub:`1` 6361 + - y\ :sub:`0` 6676 6362 * .. _MEDIA-BUS-FMT-AYUV8-1X32: 6677 6363 6678 6364 - MEDIA_BUS_FMT_AYUV8_1X32 ··· 6782 6324 - v\ :sub:`2` 6783 6325 - v\ :sub:`1` 6784 6326 - v\ :sub:`0` 6327 + 6328 + 6329 + .. raw:: latex 6330 + 6331 + \endgroup 6332 + 6333 + 6334 + The following table list existing packed 36bit wide YUV formats. 6335 + 6336 + .. raw:: latex 6337 + 6338 + \begingroup 6339 + \tiny 6340 + \setlength{\tabcolsep}{2pt} 6341 + 6342 + .. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| 6343 + 6344 + .. _v4l2-mbus-pixelcode-yuv8-36bit: 6345 + 6346 + .. flat-table:: 36bit YUV Formats 6347 + :header-rows: 2 6348 + :stub-columns: 0 6349 + :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 6350 + 6351 + * - Identifier 6352 + - Code 6353 + - 6354 + - :cspan:`35` Data organization 6355 + * - 6356 + - 6357 + - Bit 6358 + - 35 6359 + - 34 6360 + - 33 6361 + - 32 6362 + - 31 6363 + - 30 6364 + - 29 6365 + - 28 6366 + - 27 6367 + - 26 6368 + - 25 6369 + - 24 6370 + - 23 6371 + - 22 6372 + - 21 6373 + - 10 6374 + - 19 6375 + - 18 6376 + - 17 6377 + - 16 6378 + - 15 6379 + - 14 6380 + - 13 6381 + - 12 6382 + - 11 6383 + - 10 6384 + - 9 6385 + - 8 6386 + - 7 6387 + - 6 6388 + - 5 6389 + - 4 6390 + - 3 6391 + - 2 6392 + - 1 6393 + - 0 6394 + * .. _MEDIA-BUS-FMT-UYYVYY12-0-5X36: 6395 + 6396 + - MEDIA_BUS_FMT_UYYVYY12_0_5X36 6397 + - 0x2028 6398 + - 6399 + - u\ :sub:`11` 6400 + - u\ :sub:`10` 6401 + - u\ :sub:`9` 6402 + - u\ :sub:`8` 6403 + - u\ :sub:`7` 6404 + - u\ :sub:`6` 6405 + - u\ :sub:`5` 6406 + - u\ :sub:`4` 6407 + - u\ :sub:`3` 6408 + - u\ :sub:`2` 6409 + - u\ :sub:`1` 6410 + - u\ :sub:`0` 6411 + - y\ :sub:`11` 6412 + - y\ :sub:`10` 6413 + - y\ :sub:`9` 6414 + - y\ :sub:`8` 6415 + - y\ :sub:`7` 6416 + - y\ :sub:`6` 6417 + - y\ :sub:`5` 6418 + - y\ :sub:`4` 6419 + - y\ :sub:`3` 6420 + - y\ :sub:`2` 6421 + - y\ :sub:`1` 6422 + - y\ :sub:`0` 6423 + - y\ :sub:`11` 6424 + - y\ :sub:`10` 6425 + - y\ :sub:`9` 6426 + - y\ :sub:`8` 6427 + - y\ :sub:`7` 6428 + - y\ :sub:`6` 6429 + - y\ :sub:`5` 6430 + - y\ :sub:`4` 6431 + - y\ :sub:`3` 6432 + - y\ :sub:`2` 6433 + - y\ :sub:`1` 6434 + - y\ :sub:`0` 6435 + * - 6436 + - 6437 + - 6438 + - v\ :sub:`11` 6439 + - v\ :sub:`10` 6440 + - v\ :sub:`9` 6441 + - v\ :sub:`8` 6442 + - v\ :sub:`7` 6443 + - v\ :sub:`6` 6444 + - v\ :sub:`5` 6445 + - v\ :sub:`4` 6446 + - v\ :sub:`3` 6447 + - v\ :sub:`2` 6448 + - v\ :sub:`1` 6449 + - v\ :sub:`0` 6450 + - y\ :sub:`11` 6451 + - y\ :sub:`10` 6452 + - y\ :sub:`9` 6453 + - y\ :sub:`8` 6454 + - y\ :sub:`7` 6455 + - y\ :sub:`6` 6456 + - y\ :sub:`5` 6457 + - y\ :sub:`4` 6458 + - y\ :sub:`3` 6459 + - y\ :sub:`2` 6460 + - y\ :sub:`1` 6461 + - y\ :sub:`0` 6462 + - y\ :sub:`11` 6463 + - y\ :sub:`10` 6464 + - y\ :sub:`9` 6465 + - y\ :sub:`8` 6466 + - y\ :sub:`7` 6467 + - y\ :sub:`6` 6468 + - y\ :sub:`5` 6469 + - y\ :sub:`4` 6470 + - y\ :sub:`3` 6471 + - y\ :sub:`2` 6472 + - y\ :sub:`1` 6473 + - y\ :sub:`0` 6474 + * .. _MEDIA-BUS-FMT-YUV12-1X36: 6475 + 6476 + - MEDIA_BUS_FMT_YUV12_1X36 6477 + - 0x2029 6478 + - 6479 + - y\ :sub:`11` 6480 + - y\ :sub:`10` 6481 + - y\ :sub:`9` 6482 + - y\ :sub:`8` 6483 + - y\ :sub:`7` 6484 + - y\ :sub:`6` 6485 + - y\ :sub:`5` 6486 + - y\ :sub:`4` 6487 + - y\ :sub:`3` 6488 + - y\ :sub:`2` 6489 + - y\ :sub:`1` 6490 + - y\ :sub:`0` 6491 + - u\ :sub:`11` 6492 + - u\ :sub:`10` 6493 + - u\ :sub:`9` 6494 + - u\ :sub:`8` 6495 + - u\ :sub:`7` 6496 + - u\ :sub:`6` 6497 + - u\ :sub:`5` 6498 + - u\ :sub:`4` 6499 + - u\ :sub:`3` 6500 + - u\ :sub:`2` 6501 + - u\ :sub:`1` 6502 + - u\ :sub:`0` 6503 + - v\ :sub:`11` 6504 + - v\ :sub:`10` 6505 + - v\ :sub:`9` 6506 + - v\ :sub:`8` 6507 + - v\ :sub:`7` 6508 + - v\ :sub:`6` 6509 + - v\ :sub:`5` 6510 + - v\ :sub:`4` 6511 + - v\ :sub:`3` 6512 + - v\ :sub:`2` 6513 + - v\ :sub:`1` 6514 + - v\ :sub:`0` 6515 + 6516 + 6517 + .. raw:: latex 6518 + 6519 + \endgroup 6520 + 6521 + 6522 + The following table list existing packed 48bit wide YUV formats. 6523 + 6524 + .. raw:: latex 6525 + 6526 + \begingroup 6527 + \tiny 6528 + \setlength{\tabcolsep}{2pt} 6529 + 6530 + .. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| 6531 + 6532 + .. _v4l2-mbus-pixelcode-yuv8-48bit: 6533 + 6534 + .. flat-table:: 48bit YUV Formats 6535 + :header-rows: 3 6536 + :stub-columns: 0 6537 + :widths: 36 7 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 6538 + 6539 + * - Identifier 6540 + - Code 6541 + - 6542 + - :cspan:`31` Data organization 6543 + * - 6544 + - 6545 + - Bit 6546 + - 6547 + - 6548 + - 6549 + - 6550 + - 6551 + - 6552 + - 6553 + - 6554 + - 6555 + - 6556 + - 6557 + - 6558 + - 6559 + - 6560 + - 6561 + - 6562 + - 47 6563 + - 46 6564 + - 45 6565 + - 44 6566 + - 43 6567 + - 42 6568 + - 41 6569 + - 40 6570 + - 39 6571 + - 38 6572 + - 37 6573 + - 36 6574 + - 35 6575 + - 34 6576 + - 33 6577 + - 32 6578 + * - 6579 + - 6580 + - 6581 + - 31 6582 + - 30 6583 + - 29 6584 + - 28 6585 + - 27 6586 + - 26 6587 + - 25 6588 + - 24 6589 + - 23 6590 + - 22 6591 + - 21 6592 + - 10 6593 + - 19 6594 + - 18 6595 + - 17 6596 + - 16 6597 + - 15 6598 + - 14 6599 + - 13 6600 + - 12 6601 + - 11 6602 + - 10 6603 + - 9 6604 + - 8 6605 + - 7 6606 + - 6 6607 + - 5 6608 + - 4 6609 + - 3 6610 + - 2 6611 + - 1 6612 + - 0 6613 + * .. _MEDIA-BUS-FMT-YUV16-1X48: 6614 + 6615 + - MEDIA_BUS_FMT_YUV16_1X48 6616 + - 0x202a 6617 + - 6618 + - 6619 + - 6620 + - 6621 + - 6622 + - 6623 + - 6624 + - 6625 + - 6626 + - 6627 + - 6628 + - 6629 + - 6630 + - 6631 + - 6632 + - 6633 + - 6634 + - y\ :sub:`15` 6635 + - y\ :sub:`14` 6636 + - y\ :sub:`13` 6637 + - y\ :sub:`12` 6638 + - y\ :sub:`11` 6639 + - y\ :sub:`10` 6640 + - y\ :sub:`8` 6641 + - y\ :sub:`8` 6642 + - y\ :sub:`7` 6643 + - y\ :sub:`6` 6644 + - y\ :sub:`5` 6645 + - y\ :sub:`4` 6646 + - y\ :sub:`3` 6647 + - y\ :sub:`2` 6648 + - y\ :sub:`1` 6649 + - y\ :sub:`0` 6650 + * - 6651 + - 6652 + - 6653 + - u\ :sub:`15` 6654 + - u\ :sub:`14` 6655 + - u\ :sub:`13` 6656 + - u\ :sub:`12` 6657 + - u\ :sub:`11` 6658 + - u\ :sub:`10` 6659 + - u\ :sub:`9` 6660 + - u\ :sub:`8` 6661 + - u\ :sub:`7` 6662 + - u\ :sub:`6` 6663 + - u\ :sub:`5` 6664 + - u\ :sub:`4` 6665 + - u\ :sub:`3` 6666 + - u\ :sub:`2` 6667 + - u\ :sub:`1` 6668 + - u\ :sub:`0` 6669 + - v\ :sub:`15` 6670 + - v\ :sub:`14` 6671 + - v\ :sub:`13` 6672 + - v\ :sub:`12` 6673 + - v\ :sub:`11` 6674 + - v\ :sub:`10` 6675 + - v\ :sub:`9` 6676 + - v\ :sub:`8` 6677 + - v\ :sub:`7` 6678 + - v\ :sub:`6` 6679 + - v\ :sub:`5` 6680 + - v\ :sub:`4` 6681 + - v\ :sub:`3` 6682 + - v\ :sub:`2` 6683 + - v\ :sub:`1` 6684 + - v\ :sub:`0` 6685 + * .. _MEDIA-BUS-FMT-UYYVYY16-0-5X48: 6686 + 6687 + - MEDIA_BUS_FMT_UYYVYY16_0_5X48 6688 + - 0x202b 6689 + - 6690 + - 6691 + - 6692 + - 6693 + - 6694 + - 6695 + - 6696 + - 6697 + - 6698 + - 6699 + - 6700 + - 6701 + - 6702 + - 6703 + - 6704 + - 6705 + - 6706 + - u\ :sub:`15` 6707 + - u\ :sub:`14` 6708 + - u\ :sub:`13` 6709 + - u\ :sub:`12` 6710 + - u\ :sub:`11` 6711 + - u\ :sub:`10` 6712 + - u\ :sub:`9` 6713 + - u\ :sub:`8` 6714 + - u\ :sub:`7` 6715 + - u\ :sub:`6` 6716 + - u\ :sub:`5` 6717 + - u\ :sub:`4` 6718 + - u\ :sub:`3` 6719 + - u\ :sub:`2` 6720 + - u\ :sub:`1` 6721 + - u\ :sub:`0` 6722 + * - 6723 + - 6724 + - 6725 + - y\ :sub:`15` 6726 + - y\ :sub:`14` 6727 + - y\ :sub:`13` 6728 + - y\ :sub:`12` 6729 + - y\ :sub:`11` 6730 + - y\ :sub:`10` 6731 + - y\ :sub:`9` 6732 + - y\ :sub:`8` 6733 + - y\ :sub:`7` 6734 + - y\ :sub:`6` 6735 + - y\ :sub:`5` 6736 + - y\ :sub:`4` 6737 + - y\ :sub:`3` 6738 + - y\ :sub:`2` 6739 + - y\ :sub:`1` 6740 + - y\ :sub:`0` 6741 + - y\ :sub:`15` 6742 + - y\ :sub:`14` 6743 + - y\ :sub:`13` 6744 + - y\ :sub:`12` 6745 + - y\ :sub:`11` 6746 + - y\ :sub:`10` 6747 + - y\ :sub:`8` 6748 + - y\ :sub:`8` 6749 + - y\ :sub:`7` 6750 + - y\ :sub:`6` 6751 + - y\ :sub:`5` 6752 + - y\ :sub:`4` 6753 + - y\ :sub:`3` 6754 + - y\ :sub:`2` 6755 + - y\ :sub:`1` 6756 + - y\ :sub:`0` 6757 + * - 6758 + - 6759 + - 6760 + - 6761 + - 6762 + - 6763 + - 6764 + - 6765 + - 6766 + - 6767 + - 6768 + - 6769 + - 6770 + - 6771 + - 6772 + - 6773 + - 6774 + - 6775 + - 6776 + - v\ :sub:`15` 6777 + - v\ :sub:`14` 6778 + - v\ :sub:`13` 6779 + - v\ :sub:`12` 6780 + - v\ :sub:`11` 6781 + - v\ :sub:`10` 6782 + - v\ :sub:`9` 6783 + - v\ :sub:`8` 6784 + - v\ :sub:`7` 6785 + - v\ :sub:`6` 6786 + - v\ :sub:`5` 6787 + - v\ :sub:`4` 6788 + - v\ :sub:`3` 6789 + - v\ :sub:`2` 6790 + - v\ :sub:`1` 6791 + - v\ :sub:`0` 6792 + * - 6793 + - 6794 + - 6795 + - y\ :sub:`15` 6796 + - y\ :sub:`14` 6797 + - y\ :sub:`13` 6798 + - y\ :sub:`12` 6799 + - y\ :sub:`11` 6800 + - y\ :sub:`10` 6801 + - y\ :sub:`9` 6802 + - y\ :sub:`8` 6803 + - y\ :sub:`7` 6804 + - y\ :sub:`6` 6805 + - y\ :sub:`5` 6806 + - y\ :sub:`4` 6807 + - y\ :sub:`3` 6808 + - y\ :sub:`2` 6809 + - y\ :sub:`1` 6810 + - y\ :sub:`0` 6811 + - y\ :sub:`15` 6812 + - y\ :sub:`14` 6813 + - y\ :sub:`13` 6814 + - y\ :sub:`12` 6815 + - y\ :sub:`11` 6816 + - y\ :sub:`10` 6817 + - y\ :sub:`8` 6818 + - y\ :sub:`8` 6819 + - y\ :sub:`7` 6820 + - y\ :sub:`6` 6821 + - y\ :sub:`5` 6822 + - y\ :sub:`4` 6823 + - y\ :sub:`3` 6824 + - y\ :sub:`2` 6825 + - y\ :sub:`1` 6826 + - y\ :sub:`0` 6785 6827 6786 6828 6787 6829 .. raw:: latex
+2 -1
MAINTAINERS
··· 4256 4256 S: Supported 4257 4257 F: drivers/gpu/drm/meson/ 4258 4258 F: Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt 4259 - T: git git://anongit.freedesktop.org/drm/drm-meson 4259 + F: Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt 4260 + F: Documentation/gpu/meson.rst 4260 4261 T: git git://anongit.freedesktop.org/drm/drm-misc 4261 4262 4262 4263 DRM DRIVERS FOR EXYNOS
+35 -2
drivers/dma-buf/dma-buf.c
··· 1059 1059 int ret; 1060 1060 struct dma_buf *buf_obj; 1061 1061 struct dma_buf_attachment *attach_obj; 1062 - int count = 0, attach_count; 1062 + struct reservation_object *robj; 1063 + struct reservation_object_list *fobj; 1064 + struct dma_fence *fence; 1065 + unsigned seq; 1066 + int count = 0, attach_count, shared_count, i; 1063 1067 size_t size = 0; 1064 1068 1065 1069 ret = mutex_lock_interruptible(&db_list.lock); ··· 1072 1068 return ret; 1073 1069 1074 1070 seq_puts(s, "\nDma-buf Objects:\n"); 1075 - seq_puts(s, "size\tflags\tmode\tcount\texp_name\n"); 1071 + seq_printf(s, "%-8s\t%-8s\t%-8s\t%-8s\texp_name\n", 1072 + "size", "flags", "mode", "count"); 1076 1073 1077 1074 list_for_each_entry(buf_obj, &db_list.head, list_node) { 1078 1075 ret = mutex_lock_interruptible(&buf_obj->lock); ··· 1089 1084 buf_obj->file->f_flags, buf_obj->file->f_mode, 1090 1085 file_count(buf_obj->file), 1091 1086 buf_obj->exp_name); 1087 + 1088 + robj = buf_obj->resv; 1089 + while (true) { 1090 + seq = read_seqcount_begin(&robj->seq); 1091 + rcu_read_lock(); 1092 + fobj = rcu_dereference(robj->fence); 1093 + shared_count = fobj ? fobj->shared_count : 0; 1094 + fence = rcu_dereference(robj->fence_excl); 1095 + if (!read_seqcount_retry(&robj->seq, seq)) 1096 + break; 1097 + rcu_read_unlock(); 1098 + } 1099 + 1100 + if (fence) 1101 + seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n", 1102 + fence->ops->get_driver_name(fence), 1103 + fence->ops->get_timeline_name(fence), 1104 + dma_fence_is_signaled(fence) ? "" : "un"); 1105 + for (i = 0; i < shared_count; i++) { 1106 + fence = rcu_dereference(fobj->shared[i]); 1107 + if (!dma_fence_get_rcu(fence)) 1108 + continue; 1109 + seq_printf(s, "\tShared fence: %s %s %ssignalled\n", 1110 + fence->ops->get_driver_name(fence), 1111 + fence->ops->get_timeline_name(fence), 1112 + dma_fence_is_signaled(fence) ? "" : "un"); 1113 + } 1114 + rcu_read_unlock(); 1092 1115 1093 1116 seq_puts(s, "\tAttached Devices:\n"); 1094 1117 attach_count = 0;
+2 -1
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
··· 2618 2618 } 2619 2619 2620 2620 static int dce_v10_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 2621 - u16 *blue, uint32_t size) 2621 + u16 *blue, uint32_t size, 2622 + struct drm_modeset_acquire_ctx *ctx) 2622 2623 { 2623 2624 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 2624 2625 int i;
+2 -1
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
··· 2638 2638 } 2639 2639 2640 2640 static int dce_v11_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 2641 - u16 *blue, uint32_t size) 2641 + u16 *blue, uint32_t size, 2642 + struct drm_modeset_acquire_ctx *ctx) 2642 2643 { 2643 2644 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 2644 2645 int i;
+2 -1
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
··· 1985 1985 } 1986 1986 1987 1987 static int dce_v6_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 1988 - u16 *blue, uint32_t size) 1988 + u16 *blue, uint32_t size, 1989 + struct drm_modeset_acquire_ctx *ctx) 1989 1990 { 1990 1991 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 1991 1992 int i;
+2 -1
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
··· 2469 2469 } 2470 2470 2471 2471 static int dce_v8_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 2472 - u16 *blue, uint32_t size) 2472 + u16 *blue, uint32_t size, 2473 + struct drm_modeset_acquire_ctx *ctx) 2473 2474 { 2474 2475 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 2475 2476 int i;
+2 -1
drivers/gpu/drm/amd/amdgpu/dce_virtual.c
··· 165 165 } 166 166 167 167 static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, 168 - u16 *green, u16 *blue, uint32_t size) 168 + u16 *green, u16 *blue, uint32_t size, 169 + struct drm_modeset_acquire_ctx *ctx) 169 170 { 170 171 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 171 172 int i;
+3 -19
drivers/gpu/drm/arm/hdlcd_drv.c
··· 392 392 393 393 static int hdlcd_probe(struct platform_device *pdev) 394 394 { 395 - struct device_node *port, *ep; 395 + struct device_node *port; 396 396 struct component_match *match = NULL; 397 397 398 - if (!pdev->dev.of_node) 399 - return -ENODEV; 400 - 401 398 /* there is only one output port inside each device, find it */ 402 - ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); 403 - if (!ep) 399 + port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0); 400 + if (!port) 404 401 return -ENODEV; 405 - 406 - if (!of_device_is_available(ep)) { 407 - of_node_put(ep); 408 - return -ENODEV; 409 - } 410 - 411 - /* add the remote encoder port as component */ 412 - port = of_graph_get_remote_port_parent(ep); 413 - of_node_put(ep); 414 - if (!port || !of_device_is_available(port)) { 415 - of_node_put(port); 416 - return -EAGAIN; 417 - } 418 402 419 403 drm_of_component_match_add(&pdev->dev, &match, compare_dev, port); 420 404 of_node_put(port);
+4 -24
drivers/gpu/drm/arm/malidp_drv.c
··· 283 283 { 284 284 struct resource *res; 285 285 struct drm_device *drm; 286 - struct device_node *ep; 287 286 struct malidp_drm *malidp; 288 287 struct malidp_hw_device *hwdev; 289 288 struct platform_device *pdev = to_platform_device(dev); ··· 397 398 goto init_fail; 398 399 399 400 /* Set the CRTC's port so that the encoder component can find it */ 400 - ep = of_graph_get_next_endpoint(dev->of_node, NULL); 401 - if (!ep) { 402 - ret = -EINVAL; 403 - goto port_fail; 404 - } 405 - malidp->crtc.port = of_get_next_parent(ep); 401 + malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0); 406 402 407 403 ret = component_bind_all(dev, drm); 408 404 if (ret) { ··· 452 458 bind_fail: 453 459 of_node_put(malidp->crtc.port); 454 460 malidp->crtc.port = NULL; 455 - port_fail: 456 461 malidp_fini(drm); 457 462 init_fail: 458 463 drm->dev_private = NULL; ··· 509 516 510 517 static int malidp_platform_probe(struct platform_device *pdev) 511 518 { 512 - struct device_node *port, *ep; 519 + struct device_node *port; 513 520 struct component_match *match = NULL; 514 521 515 522 if (!pdev->dev.of_node) 516 523 return -ENODEV; 517 524 518 525 /* there is only one output port inside each device, find it */ 519 - ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); 520 - if (!ep) 526 + port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0); 527 + if (!port) 521 528 return -ENODEV; 522 - 523 - if (!of_device_is_available(ep)) { 524 - of_node_put(ep); 525 - return -ENODEV; 526 - } 527 - 528 - /* add the remote encoder port as component */ 529 - port = of_graph_get_remote_port_parent(ep); 530 - of_node_put(ep); 531 - if (!port || !of_device_is_available(port)) { 532 - of_node_put(port); 533 - return -EAGAIN; 534 - } 535 529 536 530 drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev, 537 531 port);
+2 -1
drivers/gpu/drm/ast/ast_mode.c
··· 645 645 } 646 646 647 647 static int ast_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 648 - u16 *blue, uint32_t size) 648 + u16 *blue, uint32_t size, 649 + struct drm_modeset_acquire_ctx *ctx) 649 650 { 650 651 struct ast_crtc *ast_crtc = to_ast_crtc(crtc); 651 652 int i;
+19 -50
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
··· 22 22 #include <linux/of_graph.h> 23 23 24 24 #include <drm/drmP.h> 25 - #include <drm/drm_panel.h> 25 + #include <drm/drm_of.h> 26 26 27 27 #include "atmel_hlcdc_dc.h" 28 28 ··· 152 152 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 153 153 }; 154 154 155 - static int atmel_hlcdc_check_endpoint(struct drm_device *dev, 156 - const struct of_endpoint *ep) 157 - { 158 - struct device_node *np; 159 - void *obj; 160 - 161 - np = of_graph_get_remote_port_parent(ep->local_node); 162 - 163 - obj = of_drm_find_panel(np); 164 - if (!obj) 165 - obj = of_drm_find_bridge(np); 166 - 167 - of_node_put(np); 168 - 169 - return obj ? 0 : -EPROBE_DEFER; 170 - } 171 - 172 155 static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, 173 - const struct of_endpoint *ep) 156 + const struct device_node *np) 174 157 { 175 158 struct atmel_hlcdc_dc *dc = dev->dev_private; 176 159 struct atmel_hlcdc_rgb_output *output; 177 - struct device_node *np; 178 160 struct drm_panel *panel; 179 161 struct drm_bridge *bridge; 180 162 int ret; ··· 177 195 178 196 output->encoder.possible_crtcs = 0x1; 179 197 180 - np = of_graph_get_remote_port_parent(ep->local_node); 198 + ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge); 199 + if (ret) 200 + return ret; 181 201 182 - ret = -EPROBE_DEFER; 183 - 184 - panel = of_drm_find_panel(np); 185 202 if (panel) { 186 - of_node_put(np); 187 203 output->connector.dpms = DRM_MODE_DPMS_OFF; 188 204 output->connector.polled = DRM_CONNECTOR_POLL_CONNECT; 189 205 drm_connector_helper_add(&output->connector, ··· 206 226 return 0; 207 227 } 208 228 209 - bridge = of_drm_find_bridge(np); 210 - of_node_put(np); 211 - 212 229 if (bridge) { 213 230 ret = drm_bridge_attach(&output->encoder, bridge, NULL); 214 231 if (!ret) ··· 220 243 221 244 int atmel_hlcdc_create_outputs(struct drm_device *dev) 222 245 { 223 - struct device_node *ep_np = NULL; 224 - struct of_endpoint ep; 225 - int ret; 246 + struct device_node *remote; 247 + int ret, endpoint = 0; 226 248 227 - for_each_endpoint_of_node(dev->dev->of_node, ep_np) { 228 - ret = of_graph_parse_endpoint(ep_np, &ep); 229 - if (!ret) 230 - ret = atmel_hlcdc_check_endpoint(dev, &ep); 249 + while (true) { 250 + /* Loop thru possible multiple connections to the output */ 251 + remote = of_graph_get_remote_node(dev->dev->of_node, 0, 252 + endpoint++); 253 + if (!remote) 254 + break; 231 255 232 - if (ret) { 233 - of_node_put(ep_np); 256 + ret = atmel_hlcdc_attach_endpoint(dev, remote); 257 + of_node_put(remote); 258 + if (ret) 234 259 return ret; 235 - } 236 260 } 237 261 238 - for_each_endpoint_of_node(dev->dev->of_node, ep_np) { 239 - ret = of_graph_parse_endpoint(ep_np, &ep); 240 - if (!ret) 241 - ret = atmel_hlcdc_attach_endpoint(dev, &ep); 242 - 243 - if (ret) { 244 - of_node_put(ep_np); 245 - return ret; 246 - } 247 - } 248 - 249 - return 0; 262 + if (!endpoint) 263 + return -ENODEV; 264 + return ret; 250 265 }
+2 -10
drivers/gpu/drm/bridge/adv7511/adv7533.c
··· 232 232 int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv) 233 233 { 234 234 u32 num_lanes; 235 - struct device_node *endpoint; 236 235 237 236 of_property_read_u32(np, "adi,dsi-lanes", &num_lanes); 238 237 ··· 240 241 241 242 adv->num_dsi_lanes = num_lanes; 242 243 243 - endpoint = of_graph_get_next_endpoint(np, NULL); 244 - if (!endpoint) 244 + adv->host_node = of_graph_get_remote_node(np, 0, 0); 245 + if (!adv->host_node) 245 246 return -ENODEV; 246 247 247 - adv->host_node = of_graph_get_remote_port_parent(endpoint); 248 - if (!adv->host_node) { 249 - of_node_put(endpoint); 250 - return -ENODEV; 251 - } 252 - 253 - of_node_put(endpoint); 254 248 of_node_put(adv->host_node); 255 249 256 250 adv->use_timing_gen = !of_property_read_bool(np,
+6
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
··· 1439 1439 struct analogix_dp_device *dp = dev_get_drvdata(dev); 1440 1440 1441 1441 analogix_dp_bridge_disable(dp->bridge); 1442 + dp->connector.funcs->destroy(&dp->connector); 1443 + dp->encoder->funcs->destroy(dp->encoder); 1442 1444 1443 1445 if (dp->plat_data->panel) { 1444 1446 if (drm_panel_unprepare(dp->plat_data->panel)) 1445 1447 DRM_ERROR("failed to turnoff the panel\n"); 1448 + if (drm_panel_detach(dp->plat_data->panel)) 1449 + DRM_ERROR("failed to detach the panel\n"); 1446 1450 } 1447 1451 1452 + drm_dp_aux_unregister(&dp->aux); 1448 1453 pm_runtime_disable(dev); 1454 + clk_disable_unprepare(dp->clock); 1449 1455 } 1450 1456 EXPORT_SYMBOL_GPL(analogix_dp_unbind); 1451 1457
+3 -12
drivers/gpu/drm/bridge/dumb-vga-dac.c
··· 154 154 155 155 static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev) 156 156 { 157 - struct device_node *end_node, *phandle, *remote; 157 + struct device_node *phandle, *remote; 158 158 struct i2c_adapter *ddc; 159 159 160 - end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1); 161 - if (!end_node) { 162 - dev_err(dev, "Missing connector endpoint\n"); 163 - return ERR_PTR(-ENODEV); 164 - } 165 - 166 - remote = of_graph_get_remote_port_parent(end_node); 167 - of_node_put(end_node); 168 - if (!remote) { 169 - dev_err(dev, "Enable to parse remote node\n"); 160 + remote = of_graph_get_remote_node(dev->of_node, 1, -1); 161 + if (!remote) 170 162 return ERR_PTR(-EINVAL); 171 - } 172 163 173 164 phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0); 174 165 of_node_put(remote);
+5 -4
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
··· 279 279 return -ENOMEM; 280 280 } 281 281 282 - ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; 283 - ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node; 284 - drm_bridge_add(&ge_b850v3_lvds_ptr->bridge); 285 - 286 282 success: 287 283 mutex_unlock(&ge_b850v3_lvds_dev_mutex); 288 284 return 0; ··· 312 316 313 317 ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c; 314 318 i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr); 319 + 320 + /* drm bridge initialization */ 321 + ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; 322 + ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node; 323 + drm_bridge_add(&ge_b850v3_lvds_ptr->bridge); 315 324 316 325 /* Clear pending interrupts since power up. */ 317 326 i2c_smbus_write_word_data(stdp4028_i2c,
+4 -12
drivers/gpu/drm/bridge/nxp-ptn3460.c
··· 20 20 #include <linux/module.h> 21 21 #include <linux/of.h> 22 22 #include <linux/of_gpio.h> 23 - #include <linux/of_graph.h> 24 23 24 + #include <drm/drm_of.h> 25 25 #include <drm/drm_panel.h> 26 26 27 27 #include "drm_crtc.h" ··· 292 292 { 293 293 struct device *dev = &client->dev; 294 294 struct ptn3460_bridge *ptn_bridge; 295 - struct device_node *endpoint, *panel_node; 296 295 int ret; 297 296 298 297 ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL); ··· 299 300 return -ENOMEM; 300 301 } 301 302 302 - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); 303 - if (endpoint) { 304 - panel_node = of_graph_get_remote_port_parent(endpoint); 305 - if (panel_node) { 306 - ptn_bridge->panel = of_drm_find_panel(panel_node); 307 - of_node_put(panel_node); 308 - if (!ptn_bridge->panel) 309 - return -EPROBE_DEFER; 310 - } 311 - } 303 + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL); 304 + if (ret) 305 + return ret; 312 306 313 307 ptn_bridge->client = client; 314 308
+4 -12
drivers/gpu/drm/bridge/parade-ps8622.c
··· 22 22 #include <linux/module.h> 23 23 #include <linux/of.h> 24 24 #include <linux/of_device.h> 25 - #include <linux/of_graph.h> 26 25 #include <linux/pm.h> 27 26 #include <linux/regulator/consumer.h> 28 27 28 + #include <drm/drm_of.h> 29 29 #include <drm/drm_panel.h> 30 30 31 31 #include "drmP.h" ··· 536 536 const struct i2c_device_id *id) 537 537 { 538 538 struct device *dev = &client->dev; 539 - struct device_node *endpoint, *panel_node; 540 539 struct ps8622_bridge *ps8622; 541 540 int ret; 542 541 ··· 543 544 if (!ps8622) 544 545 return -ENOMEM; 545 546 546 - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); 547 - if (endpoint) { 548 - panel_node = of_graph_get_remote_port_parent(endpoint); 549 - if (panel_node) { 550 - ps8622->panel = of_drm_find_panel(panel_node); 551 - of_node_put(panel_node); 552 - if (!ps8622->panel) 553 - return -EPROBE_DEFER; 554 - } 555 - } 547 + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ps8622->panel, NULL); 548 + if (ret) 549 + return ret; 556 550 557 551 ps8622->client = client; 558 552
+304 -159
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
··· 30 30 #include <drm/drm_encoder_slave.h> 31 31 #include <drm/bridge/dw_hdmi.h> 32 32 33 + #include <uapi/linux/media-bus-format.h> 34 + #include <uapi/linux/videodev2.h> 35 + 33 36 #include "dw-hdmi.h" 34 37 #include "dw-hdmi-audio.h" 35 38 36 39 #define DDC_SEGMENT_ADDR 0x30 37 40 #define HDMI_EDID_LEN 512 38 - 39 - #define RGB 0 40 - #define YCBCR444 1 41 - #define YCBCR422_16BITS 2 42 - #define YCBCR422_8BITS 3 43 - #define XVYCC444 4 44 41 45 42 enum hdmi_datamap { 46 43 RGB444_8B = 0x01, ··· 92 95 }; 93 96 94 97 struct hdmi_data_info { 95 - unsigned int enc_in_format; 96 - unsigned int enc_out_format; 97 - unsigned int enc_color_depth; 98 - unsigned int colorimetry; 98 + unsigned int enc_in_bus_format; 99 + unsigned int enc_out_bus_format; 100 + unsigned int enc_in_encoding; 101 + unsigned int enc_out_encoding; 99 102 unsigned int pix_repet_factor; 100 103 unsigned int hdcp_enable; 101 104 struct hdmi_vmode video_mode; ··· 564 567 } 565 568 EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); 566 569 570 + static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format) 571 + { 572 + switch (bus_format) { 573 + case MEDIA_BUS_FMT_RGB888_1X24: 574 + case MEDIA_BUS_FMT_RGB101010_1X30: 575 + case MEDIA_BUS_FMT_RGB121212_1X36: 576 + case MEDIA_BUS_FMT_RGB161616_1X48: 577 + return true; 578 + 579 + default: 580 + return false; 581 + } 582 + } 583 + 584 + static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format) 585 + { 586 + switch (bus_format) { 587 + case MEDIA_BUS_FMT_YUV8_1X24: 588 + case MEDIA_BUS_FMT_YUV10_1X30: 589 + case MEDIA_BUS_FMT_YUV12_1X36: 590 + case MEDIA_BUS_FMT_YUV16_1X48: 591 + return true; 592 + 593 + default: 594 + return false; 595 + } 596 + } 597 + 598 + static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format) 599 + { 600 + switch (bus_format) { 601 + case MEDIA_BUS_FMT_UYVY8_1X16: 602 + case MEDIA_BUS_FMT_UYVY10_1X20: 603 + case MEDIA_BUS_FMT_UYVY12_1X24: 604 + return true; 605 + 606 + default: 607 + return false; 608 + } 609 + } 610 + 611 + static int hdmi_bus_fmt_color_depth(unsigned int bus_format) 612 + { 613 + switch (bus_format) { 614 + case MEDIA_BUS_FMT_RGB888_1X24: 615 + case MEDIA_BUS_FMT_YUV8_1X24: 616 + case MEDIA_BUS_FMT_UYVY8_1X16: 617 + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 618 + return 8; 619 + 620 + case MEDIA_BUS_FMT_RGB101010_1X30: 621 + case MEDIA_BUS_FMT_YUV10_1X30: 622 + case MEDIA_BUS_FMT_UYVY10_1X20: 623 + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 624 + return 10; 625 + 626 + case MEDIA_BUS_FMT_RGB121212_1X36: 627 + case MEDIA_BUS_FMT_YUV12_1X36: 628 + case MEDIA_BUS_FMT_UYVY12_1X24: 629 + case MEDIA_BUS_FMT_UYYVYY12_0_5X36: 630 + return 12; 631 + 632 + case MEDIA_BUS_FMT_RGB161616_1X48: 633 + case MEDIA_BUS_FMT_YUV16_1X48: 634 + case MEDIA_BUS_FMT_UYYVYY16_0_5X48: 635 + return 16; 636 + 637 + default: 638 + return 0; 639 + } 640 + } 641 + 567 642 /* 568 643 * this submodule is responsible for the video data synchronization. 569 644 * for example, for RGB 4:4:4 input, the data map is defined as ··· 648 579 int color_format = 0; 649 580 u8 val; 650 581 651 - if (hdmi->hdmi_data.enc_in_format == RGB) { 652 - if (hdmi->hdmi_data.enc_color_depth == 8) 653 - color_format = 0x01; 654 - else if (hdmi->hdmi_data.enc_color_depth == 10) 655 - color_format = 0x03; 656 - else if (hdmi->hdmi_data.enc_color_depth == 12) 657 - color_format = 0x05; 658 - else if (hdmi->hdmi_data.enc_color_depth == 16) 659 - color_format = 0x07; 660 - else 661 - return; 662 - } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) { 663 - if (hdmi->hdmi_data.enc_color_depth == 8) 664 - color_format = 0x09; 665 - else if (hdmi->hdmi_data.enc_color_depth == 10) 666 - color_format = 0x0B; 667 - else if (hdmi->hdmi_data.enc_color_depth == 12) 668 - color_format = 0x0D; 669 - else if (hdmi->hdmi_data.enc_color_depth == 16) 670 - color_format = 0x0F; 671 - else 672 - return; 673 - } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) { 674 - if (hdmi->hdmi_data.enc_color_depth == 8) 675 - color_format = 0x16; 676 - else if (hdmi->hdmi_data.enc_color_depth == 10) 677 - color_format = 0x14; 678 - else if (hdmi->hdmi_data.enc_color_depth == 12) 679 - color_format = 0x12; 680 - else 681 - return; 582 + switch (hdmi->hdmi_data.enc_in_bus_format) { 583 + case MEDIA_BUS_FMT_RGB888_1X24: 584 + color_format = 0x01; 585 + break; 586 + case MEDIA_BUS_FMT_RGB101010_1X30: 587 + color_format = 0x03; 588 + break; 589 + case MEDIA_BUS_FMT_RGB121212_1X36: 590 + color_format = 0x05; 591 + break; 592 + case MEDIA_BUS_FMT_RGB161616_1X48: 593 + color_format = 0x07; 594 + break; 595 + 596 + case MEDIA_BUS_FMT_YUV8_1X24: 597 + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 598 + color_format = 0x09; 599 + break; 600 + case MEDIA_BUS_FMT_YUV10_1X30: 601 + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 602 + color_format = 0x0B; 603 + break; 604 + case MEDIA_BUS_FMT_YUV12_1X36: 605 + case MEDIA_BUS_FMT_UYYVYY12_0_5X36: 606 + color_format = 0x0D; 607 + break; 608 + case MEDIA_BUS_FMT_YUV16_1X48: 609 + case MEDIA_BUS_FMT_UYYVYY16_0_5X48: 610 + color_format = 0x0F; 611 + break; 612 + 613 + case MEDIA_BUS_FMT_UYVY8_1X16: 614 + color_format = 0x16; 615 + break; 616 + case MEDIA_BUS_FMT_UYVY10_1X20: 617 + color_format = 0x14; 618 + break; 619 + case MEDIA_BUS_FMT_UYVY12_1X24: 620 + color_format = 0x12; 621 + break; 622 + 623 + default: 624 + return; 682 625 } 683 626 684 627 val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE | ··· 713 632 714 633 static int is_color_space_conversion(struct dw_hdmi *hdmi) 715 634 { 716 - return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format; 635 + return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format; 717 636 } 718 637 719 638 static int is_color_space_decimation(struct dw_hdmi *hdmi) 720 639 { 721 - if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS) 640 + if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) 722 641 return 0; 723 - if (hdmi->hdmi_data.enc_in_format == RGB || 724 - hdmi->hdmi_data.enc_in_format == YCBCR444) 642 + 643 + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) || 644 + hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format)) 725 645 return 1; 646 + 726 647 return 0; 727 648 } 728 649 729 650 static int is_color_space_interpolation(struct dw_hdmi *hdmi) 730 651 { 731 - if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS) 652 + if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format)) 732 653 return 0; 733 - if (hdmi->hdmi_data.enc_out_format == RGB || 734 - hdmi->hdmi_data.enc_out_format == YCBCR444) 654 + 655 + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) || 656 + hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) 735 657 return 1; 658 + 736 659 return 0; 737 660 } 738 661 ··· 747 662 u32 csc_scale = 1; 748 663 749 664 if (is_color_space_conversion(hdmi)) { 750 - if (hdmi->hdmi_data.enc_out_format == RGB) { 751 - if (hdmi->hdmi_data.colorimetry == 752 - HDMI_COLORIMETRY_ITU_601) 665 + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { 666 + if (hdmi->hdmi_data.enc_out_encoding == 667 + V4L2_YCBCR_ENC_601) 753 668 csc_coeff = &csc_coeff_rgb_out_eitu601; 754 669 else 755 670 csc_coeff = &csc_coeff_rgb_out_eitu709; 756 - } else if (hdmi->hdmi_data.enc_in_format == RGB) { 757 - if (hdmi->hdmi_data.colorimetry == 758 - HDMI_COLORIMETRY_ITU_601) 671 + } else if (hdmi_bus_fmt_is_rgb( 672 + hdmi->hdmi_data.enc_in_bus_format)) { 673 + if (hdmi->hdmi_data.enc_out_encoding == 674 + V4L2_YCBCR_ENC_601) 759 675 csc_coeff = &csc_coeff_rgb_in_eitu601; 760 676 else 761 677 csc_coeff = &csc_coeff_rgb_in_eitu709; ··· 794 708 else if (is_color_space_decimation(hdmi)) 795 709 decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3; 796 710 797 - if (hdmi->hdmi_data.enc_color_depth == 8) 711 + switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) { 712 + case 8: 798 713 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP; 799 - else if (hdmi->hdmi_data.enc_color_depth == 10) 714 + break; 715 + case 10: 800 716 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP; 801 - else if (hdmi->hdmi_data.enc_color_depth == 12) 717 + break; 718 + case 12: 802 719 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP; 803 - else if (hdmi->hdmi_data.enc_color_depth == 16) 720 + break; 721 + case 16: 804 722 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP; 805 - else 723 + break; 724 + 725 + default: 806 726 return; 727 + } 807 728 808 729 /* Configure the CSC registers */ 809 730 hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG); ··· 833 740 struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; 834 741 u8 val, vp_conf; 835 742 836 - if (hdmi_data->enc_out_format == RGB || 837 - hdmi_data->enc_out_format == YCBCR444) { 838 - if (!hdmi_data->enc_color_depth) { 839 - output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 840 - } else if (hdmi_data->enc_color_depth == 8) { 743 + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) || 744 + hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) { 745 + switch (hdmi_bus_fmt_color_depth( 746 + hdmi->hdmi_data.enc_out_bus_format)) { 747 + case 8: 841 748 color_depth = 4; 842 749 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 843 - } else if (hdmi_data->enc_color_depth == 10) { 750 + break; 751 + case 10: 844 752 color_depth = 5; 845 - } else if (hdmi_data->enc_color_depth == 12) { 753 + break; 754 + case 12: 846 755 color_depth = 6; 847 - } else if (hdmi_data->enc_color_depth == 16) { 756 + break; 757 + case 16: 848 758 color_depth = 7; 849 - } else { 759 + break; 760 + default: 761 + output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 762 + } 763 + } else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { 764 + switch (hdmi_bus_fmt_color_depth( 765 + hdmi->hdmi_data.enc_out_bus_format)) { 766 + case 0: 767 + case 8: 768 + remap_size = HDMI_VP_REMAP_YCC422_16bit; 769 + break; 770 + case 10: 771 + remap_size = HDMI_VP_REMAP_YCC422_20bit; 772 + break; 773 + case 12: 774 + remap_size = HDMI_VP_REMAP_YCC422_24bit; 775 + break; 776 + 777 + default: 850 778 return; 851 779 } 852 - } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { 853 - if (!hdmi_data->enc_color_depth || 854 - hdmi_data->enc_color_depth == 8) 855 - remap_size = HDMI_VP_REMAP_YCC422_16bit; 856 - else if (hdmi_data->enc_color_depth == 10) 857 - remap_size = HDMI_VP_REMAP_YCC422_20bit; 858 - else if (hdmi_data->enc_color_depth == 12) 859 - remap_size = HDMI_VP_REMAP_YCC422_24bit; 860 - else 861 - return; 862 780 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; 863 781 } else { 864 782 return; ··· 1215 1111 connector_status_connected : connector_status_disconnected; 1216 1112 } 1217 1113 1114 + static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, 1115 + bool force, bool disabled, bool rxsense) 1116 + { 1117 + u8 old_mask = hdmi->phy_mask; 1118 + 1119 + if (force || disabled || !rxsense) 1120 + hdmi->phy_mask |= HDMI_PHY_RX_SENSE; 1121 + else 1122 + hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; 1123 + 1124 + if (old_mask != hdmi->phy_mask) 1125 + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); 1126 + } 1127 + 1128 + static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data) 1129 + { 1130 + /* 1131 + * Configure the PHY RX SENSE and HPD interrupts polarities and clear 1132 + * any pending interrupt. 1133 + */ 1134 + hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); 1135 + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, 1136 + HDMI_IH_PHY_STAT0); 1137 + 1138 + /* Enable cable hot plug irq. */ 1139 + hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); 1140 + 1141 + /* Clear and unmute interrupts. */ 1142 + hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, 1143 + HDMI_IH_PHY_STAT0); 1144 + hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), 1145 + HDMI_IH_MUTE_PHY_STAT0); 1146 + } 1147 + 1218 1148 static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { 1219 1149 .init = dw_hdmi_phy_init, 1220 1150 .disable = dw_hdmi_phy_disable, 1221 1151 .read_hpd = dw_hdmi_phy_read_hpd, 1152 + .update_hpd = dw_hdmi_phy_update_hpd, 1153 + .setup_hpd = dw_hdmi_phy_setup_hpd, 1222 1154 }; 1223 1155 1224 1156 /* ----------------------------------------------------------------------------- ··· 1288 1148 /* Initialise info frame from DRM mode */ 1289 1149 drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 1290 1150 1291 - if (hdmi->hdmi_data.enc_out_format == YCBCR444) 1151 + if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) 1292 1152 frame.colorspace = HDMI_COLORSPACE_YUV444; 1293 - else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) 1153 + else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) 1294 1154 frame.colorspace = HDMI_COLORSPACE_YUV422; 1295 1155 else 1296 1156 frame.colorspace = HDMI_COLORSPACE_RGB; 1297 1157 1298 1158 /* Set up colorimetry */ 1299 - if (hdmi->hdmi_data.enc_out_format == XVYCC444) { 1300 - frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; 1301 - if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) 1302 - frame.extended_colorimetry = 1159 + switch (hdmi->hdmi_data.enc_out_encoding) { 1160 + case V4L2_YCBCR_ENC_601: 1161 + if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) 1162 + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; 1163 + else 1164 + frame.colorimetry = HDMI_COLORIMETRY_ITU_601; 1165 + frame.extended_colorimetry = 1303 1166 HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1304 - else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ 1305 - frame.extended_colorimetry = 1167 + break; 1168 + case V4L2_YCBCR_ENC_709: 1169 + if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) 1170 + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; 1171 + else 1172 + frame.colorimetry = HDMI_COLORIMETRY_ITU_709; 1173 + frame.extended_colorimetry = 1306 1174 HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; 1307 - } else if (hdmi->hdmi_data.enc_out_format != RGB) { 1308 - frame.colorimetry = hdmi->hdmi_data.colorimetry; 1309 - frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1310 - } else { /* Carries no data */ 1311 - frame.colorimetry = HDMI_COLORIMETRY_NONE; 1312 - frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1175 + break; 1176 + default: /* Carries no data */ 1177 + frame.colorimetry = HDMI_COLORIMETRY_ITU_601; 1178 + frame.extended_colorimetry = 1179 + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1180 + break; 1313 1181 } 1314 1182 1315 1183 frame.scan_mode = HDMI_SCAN_MODE_NONE; ··· 1646 1498 (hdmi->vic == 21) || (hdmi->vic == 22) || 1647 1499 (hdmi->vic == 2) || (hdmi->vic == 3) || 1648 1500 (hdmi->vic == 17) || (hdmi->vic == 18)) 1649 - hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; 1501 + hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601; 1650 1502 else 1651 - hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; 1503 + hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709; 1652 1504 1653 1505 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; 1654 1506 hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; 1655 1507 1656 - /* TODO: Get input format from IPU (via FB driver interface) */ 1657 - hdmi->hdmi_data.enc_in_format = RGB; 1508 + /* TOFIX: Get input format from plat data or fallback to RGB888 */ 1509 + if (hdmi->plat_data->input_bus_format) 1510 + hdmi->hdmi_data.enc_in_bus_format = 1511 + hdmi->plat_data->input_bus_format; 1512 + else 1513 + hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24; 1658 1514 1659 - hdmi->hdmi_data.enc_out_format = RGB; 1515 + /* TOFIX: Get input encoding from plat data or fallback to none */ 1516 + if (hdmi->plat_data->input_bus_encoding) 1517 + hdmi->hdmi_data.enc_in_encoding = 1518 + hdmi->plat_data->input_bus_encoding; 1519 + else 1520 + hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT; 1660 1521 1661 - hdmi->hdmi_data.enc_color_depth = 8; 1522 + /* TOFIX: Default to RGB888 output format */ 1523 + hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24; 1524 + 1662 1525 hdmi->hdmi_data.pix_repet_factor = 0; 1663 1526 hdmi->hdmi_data.hdcp_enable = 0; 1664 1527 hdmi->hdmi_data.video_mode.mdataenablepolarity = true; ··· 1717 1558 return 0; 1718 1559 } 1719 1560 1720 - /* Wait until we are registered to enable interrupts */ 1721 - static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi) 1561 + static void dw_hdmi_setup_i2c(struct dw_hdmi *hdmi) 1722 1562 { 1723 1563 hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, 1724 1564 HDMI_PHY_I2CM_INT_ADDR); ··· 1725 1567 hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL | 1726 1568 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL, 1727 1569 HDMI_PHY_I2CM_CTLINT_ADDR); 1728 - 1729 - /* enable cable hot plug irq */ 1730 - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); 1731 - 1732 - /* Clear Hotplug interrupts */ 1733 - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, 1734 - HDMI_IH_PHY_STAT0); 1735 - 1736 - return 0; 1737 1570 } 1738 1571 1739 1572 static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) ··· 1831 1682 */ 1832 1683 static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi) 1833 1684 { 1834 - u8 old_mask = hdmi->phy_mask; 1835 - 1836 - if (hdmi->force || hdmi->disabled || !hdmi->rxsense) 1837 - hdmi->phy_mask |= HDMI_PHY_RX_SENSE; 1838 - else 1839 - hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE; 1840 - 1841 - if (old_mask != hdmi->phy_mask) 1842 - hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); 1685 + if (hdmi->phy.ops->update_hpd) 1686 + hdmi->phy.ops->update_hpd(hdmi, hdmi->phy.data, 1687 + hdmi->force, hdmi->disabled, 1688 + hdmi->rxsense); 1843 1689 } 1844 1690 1845 1691 static enum drm_connector_status ··· 2026 1882 return ret; 2027 1883 } 2028 1884 1885 + void __dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense) 1886 + { 1887 + mutex_lock(&hdmi->mutex); 1888 + 1889 + if (!hdmi->force) { 1890 + /* 1891 + * If the RX sense status indicates we're disconnected, 1892 + * clear the software rxsense status. 1893 + */ 1894 + if (!rx_sense) 1895 + hdmi->rxsense = false; 1896 + 1897 + /* 1898 + * Only set the software rxsense status when both 1899 + * rxsense and hpd indicates we're connected. 1900 + * This avoids what seems to be bad behaviour in 1901 + * at least iMX6S versions of the phy. 1902 + */ 1903 + if (hpd) 1904 + hdmi->rxsense = true; 1905 + 1906 + dw_hdmi_update_power(hdmi); 1907 + dw_hdmi_update_phy_mask(hdmi); 1908 + } 1909 + mutex_unlock(&hdmi->mutex); 1910 + } 1911 + 1912 + void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense) 1913 + { 1914 + struct dw_hdmi *hdmi = dev_get_drvdata(dev); 1915 + 1916 + __dw_hdmi_setup_rx_sense(hdmi, hpd, rx_sense); 1917 + } 1918 + EXPORT_SYMBOL_GPL(dw_hdmi_setup_rx_sense); 1919 + 2029 1920 static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) 2030 1921 { 2031 1922 struct dw_hdmi *hdmi = dev_id; ··· 2093 1914 * ask the source to re-read the EDID. 2094 1915 */ 2095 1916 if (intr_stat & 2096 - (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { 2097 - mutex_lock(&hdmi->mutex); 2098 - if (!hdmi->force) { 2099 - /* 2100 - * If the RX sense status indicates we're disconnected, 2101 - * clear the software rxsense status. 2102 - */ 2103 - if (!(phy_stat & HDMI_PHY_RX_SENSE)) 2104 - hdmi->rxsense = false; 2105 - 2106 - /* 2107 - * Only set the software rxsense status when both 2108 - * rxsense and hpd indicates we're connected. 2109 - * This avoids what seems to be bad behaviour in 2110 - * at least iMX6S versions of the phy. 2111 - */ 2112 - if (phy_stat & HDMI_PHY_HPD) 2113 - hdmi->rxsense = true; 2114 - 2115 - dw_hdmi_update_power(hdmi); 2116 - dw_hdmi_update_phy_mask(hdmi); 2117 - } 2118 - mutex_unlock(&hdmi->mutex); 2119 - } 1917 + (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) 1918 + __dw_hdmi_setup_rx_sense(hdmi, 1919 + phy_stat & HDMI_PHY_HPD, 1920 + phy_stat & HDMI_PHY_RX_SENSE); 2120 1921 2121 1922 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { 2122 1923 dev_dbg(hdmi->dev, "EVENT=%s\n", ··· 2363 2204 hdmi->ddc = NULL; 2364 2205 } 2365 2206 2366 - /* 2367 - * Configure registers related to HDMI interrupt 2368 - * generation before registering IRQ. 2369 - */ 2370 - hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0); 2371 - 2372 - /* Clear Hotplug interrupts */ 2373 - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE, 2374 - HDMI_IH_PHY_STAT0); 2375 - 2376 2207 hdmi->bridge.driver_private = hdmi; 2377 2208 hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; 2378 2209 #ifdef CONFIG_OF 2379 2210 hdmi->bridge.of_node = pdev->dev.of_node; 2380 2211 #endif 2381 2212 2382 - ret = dw_hdmi_fb_registered(hdmi); 2383 - if (ret) 2384 - goto err_iahb; 2385 - 2386 - /* Unmute interrupts */ 2387 - hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), 2388 - HDMI_IH_MUTE_PHY_STAT0); 2213 + dw_hdmi_setup_i2c(hdmi); 2214 + if (hdmi->phy.ops->setup_hpd) 2215 + hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); 2389 2216 2390 2217 memset(&pdevinfo, 0, sizeof(pdevinfo)); 2391 2218 pdevinfo.parent = dev;
+3 -24
drivers/gpu/drm/bridge/tc358767.c
··· 1244 1244 static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) 1245 1245 { 1246 1246 struct device *dev = &client->dev; 1247 - struct device_node *ep; 1248 1247 struct tc_data *tc; 1249 1248 int ret; 1250 1249 ··· 1254 1255 tc->dev = dev; 1255 1256 1256 1257 /* port@2 is the output port */ 1257 - ep = of_graph_get_endpoint_by_regs(dev->of_node, 2, -1); 1258 - if (ep) { 1259 - struct device_node *remote; 1260 - 1261 - remote = of_graph_get_remote_port_parent(ep); 1262 - if (!remote) { 1263 - dev_warn(dev, "endpoint %s not connected\n", 1264 - ep->full_name); 1265 - of_node_put(ep); 1266 - return -ENODEV; 1267 - } 1268 - of_node_put(ep); 1269 - tc->panel = of_drm_find_panel(remote); 1270 - if (tc->panel) { 1271 - dev_dbg(dev, "found panel %s\n", remote->full_name); 1272 - } else { 1273 - dev_dbg(dev, "waiting for panel %s\n", 1274 - remote->full_name); 1275 - of_node_put(remote); 1276 - return -EPROBE_DEFER; 1277 - } 1278 - of_node_put(remote); 1279 - } 1258 + ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &tc->panel, NULL); 1259 + if (ret) 1260 + return ret; 1280 1261 1281 1262 /* Shut down GPIO is optional */ 1282 1263 tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
+6 -11
drivers/gpu/drm/bridge/ti-tfp410.c
··· 165 165 166 166 static int tfp410_get_connector_properties(struct tfp410 *dvi) 167 167 { 168 - struct device_node *ep = NULL, *connector_node = NULL; 169 - struct device_node *ddc_phandle = NULL; 168 + struct device_node *connector_node, *ddc_phandle; 170 169 int ret = 0; 171 170 172 171 /* port@1 is the connector node */ 173 - ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 1, -1); 174 - if (!ep) 175 - goto fail; 176 - 177 - connector_node = of_graph_get_remote_port_parent(ep); 172 + connector_node = of_graph_get_remote_node(dvi->dev->of_node, 1, -1); 178 173 if (!connector_node) 179 - goto fail; 174 + return -ENODEV; 180 175 181 176 dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode, 182 177 "hpd-gpios", 0, GPIOD_IN, "hpd"); ··· 194 199 else 195 200 ret = -EPROBE_DEFER; 196 201 197 - fail: 198 - of_node_put(ep); 199 - of_node_put(connector_node); 200 202 of_node_put(ddc_phandle); 203 + 204 + fail: 205 + of_node_put(connector_node); 201 206 return ret; 202 207 } 203 208
+2 -1
drivers/gpu/drm/cirrus/cirrus_mode.c
··· 327 327 * but it's a requirement that we provide the function 328 328 */ 329 329 static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 330 - u16 *blue, uint32_t size) 330 + u16 *blue, uint32_t size, 331 + struct drm_modeset_acquire_ctx *ctx) 331 332 { 332 333 struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc); 333 334 int i;
+40 -124
drivers/gpu/drm/drm_atomic.c
··· 1516 1516 void drm_atomic_legacy_backoff(struct drm_atomic_state *state) 1517 1517 { 1518 1518 struct drm_device *dev = state->dev; 1519 - unsigned crtc_mask = 0; 1520 - struct drm_crtc *crtc; 1521 1519 int ret; 1522 1520 bool global = false; 1523 - 1524 - drm_for_each_crtc(crtc, dev) { 1525 - if (crtc->acquire_ctx != state->acquire_ctx) 1526 - continue; 1527 - 1528 - crtc_mask |= drm_crtc_mask(crtc); 1529 - crtc->acquire_ctx = NULL; 1530 - } 1531 1521 1532 1522 if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) { 1533 1523 global = true; ··· 1531 1541 ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); 1532 1542 if (ret) 1533 1543 goto retry; 1534 - 1535 - drm_for_each_crtc(crtc, dev) 1536 - if (drm_crtc_mask(crtc) & crtc_mask) 1537 - crtc->acquire_ctx = state->acquire_ctx; 1538 1544 1539 1545 if (global) 1540 1546 dev->mode_config.acquire_ctx = state->acquire_ctx; ··· 1676 1690 drm_atomic_connector_print_state(&p, connector_state); 1677 1691 } 1678 1692 1693 + static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p, 1694 + bool take_locks) 1695 + { 1696 + struct drm_mode_config *config = &dev->mode_config; 1697 + struct drm_plane *plane; 1698 + struct drm_crtc *crtc; 1699 + struct drm_connector *connector; 1700 + struct drm_connector_list_iter conn_iter; 1701 + 1702 + if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) 1703 + return; 1704 + 1705 + list_for_each_entry(plane, &config->plane_list, head) { 1706 + if (take_locks) 1707 + drm_modeset_lock(&plane->mutex, NULL); 1708 + drm_atomic_plane_print_state(p, plane->state); 1709 + if (take_locks) 1710 + drm_modeset_unlock(&plane->mutex); 1711 + } 1712 + 1713 + list_for_each_entry(crtc, &config->crtc_list, head) { 1714 + if (take_locks) 1715 + drm_modeset_lock(&crtc->mutex, NULL); 1716 + drm_atomic_crtc_print_state(p, crtc->state); 1717 + if (take_locks) 1718 + drm_modeset_unlock(&crtc->mutex); 1719 + } 1720 + 1721 + drm_connector_list_iter_begin(dev, &conn_iter); 1722 + if (take_locks) 1723 + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); 1724 + drm_for_each_connector_iter(connector, &conn_iter) 1725 + drm_atomic_connector_print_state(p, connector->state); 1726 + if (take_locks) 1727 + drm_modeset_unlock(&dev->mode_config.connection_mutex); 1728 + drm_connector_list_iter_end(&conn_iter); 1729 + } 1730 + 1679 1731 /** 1680 1732 * drm_state_dump - dump entire device atomic state 1681 1733 * @dev: the drm device ··· 1731 1707 */ 1732 1708 void drm_state_dump(struct drm_device *dev, struct drm_printer *p) 1733 1709 { 1734 - struct drm_mode_config *config = &dev->mode_config; 1735 - struct drm_plane *plane; 1736 - struct drm_crtc *crtc; 1737 - struct drm_connector *connector; 1738 - struct drm_connector_list_iter conn_iter; 1739 - 1740 - if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) 1741 - return; 1742 - 1743 - list_for_each_entry(plane, &config->plane_list, head) 1744 - drm_atomic_plane_print_state(p, plane->state); 1745 - 1746 - list_for_each_entry(crtc, &config->crtc_list, head) 1747 - drm_atomic_crtc_print_state(p, crtc->state); 1748 - 1749 - drm_connector_list_iter_begin(dev, &conn_iter); 1750 - drm_for_each_connector_iter(connector, &conn_iter) 1751 - drm_atomic_connector_print_state(p, connector->state); 1752 - drm_connector_list_iter_end(&conn_iter); 1710 + __drm_state_dump(dev, p, false); 1753 1711 } 1754 1712 EXPORT_SYMBOL(drm_state_dump); 1755 1713 ··· 1742 1736 struct drm_device *dev = node->minor->dev; 1743 1737 struct drm_printer p = drm_seq_file_printer(m); 1744 1738 1745 - drm_modeset_lock_all(dev); 1746 - drm_state_dump(dev, &p); 1747 - drm_modeset_unlock_all(dev); 1739 + __drm_state_dump(dev, &p, true); 1748 1740 1749 1741 return 0; 1750 1742 } ··· 2079 2075 } 2080 2076 2081 2077 kfree(fence_state); 2082 - } 2083 - 2084 - int drm_atomic_remove_fb(struct drm_framebuffer *fb) 2085 - { 2086 - struct drm_modeset_acquire_ctx ctx; 2087 - struct drm_device *dev = fb->dev; 2088 - struct drm_atomic_state *state; 2089 - struct drm_plane *plane; 2090 - struct drm_connector *conn; 2091 - struct drm_connector_state *conn_state; 2092 - int i, ret = 0; 2093 - unsigned plane_mask; 2094 - 2095 - state = drm_atomic_state_alloc(dev); 2096 - if (!state) 2097 - return -ENOMEM; 2098 - 2099 - drm_modeset_acquire_init(&ctx, 0); 2100 - state->acquire_ctx = &ctx; 2101 - 2102 - retry: 2103 - plane_mask = 0; 2104 - ret = drm_modeset_lock_all_ctx(dev, &ctx); 2105 - if (ret) 2106 - goto unlock; 2107 - 2108 - drm_for_each_plane(plane, dev) { 2109 - struct drm_plane_state *plane_state; 2110 - 2111 - if (plane->state->fb != fb) 2112 - continue; 2113 - 2114 - plane_state = drm_atomic_get_plane_state(state, plane); 2115 - if (IS_ERR(plane_state)) { 2116 - ret = PTR_ERR(plane_state); 2117 - goto unlock; 2118 - } 2119 - 2120 - if (plane_state->crtc->primary == plane) { 2121 - struct drm_crtc_state *crtc_state; 2122 - 2123 - crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); 2124 - 2125 - ret = drm_atomic_add_affected_connectors(state, plane_state->crtc); 2126 - if (ret) 2127 - goto unlock; 2128 - 2129 - crtc_state->active = false; 2130 - ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); 2131 - if (ret) 2132 - goto unlock; 2133 - } 2134 - 2135 - drm_atomic_set_fb_for_plane(plane_state, NULL); 2136 - ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); 2137 - if (ret) 2138 - goto unlock; 2139 - 2140 - plane_mask |= BIT(drm_plane_index(plane)); 2141 - 2142 - plane->old_fb = plane->fb; 2143 - } 2144 - 2145 - for_each_connector_in_state(state, conn, conn_state, i) { 2146 - ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); 2147 - 2148 - if (ret) 2149 - goto unlock; 2150 - } 2151 - 2152 - if (plane_mask) 2153 - ret = drm_atomic_commit(state); 2154 - 2155 - unlock: 2156 - if (plane_mask) 2157 - drm_atomic_clean_old_fb(dev, plane_mask, ret); 2158 - 2159 - if (ret == -EDEADLK) { 2160 - drm_modeset_backoff(&ctx); 2161 - goto retry; 2162 - } 2163 - 2164 - drm_atomic_state_put(state); 2165 - 2166 - drm_modeset_drop_locks(&ctx); 2167 - drm_modeset_acquire_fini(&ctx); 2168 - 2169 - return ret; 2170 2078 } 2171 2079 2172 2080 int drm_mode_atomic_ioctl(struct drm_device *dev,
+77 -42
drivers/gpu/drm/drm_atomic_helper.c
··· 459 459 * 460 460 * Check the state object to see if the requested state is physically possible. 461 461 * This does all the crtc and connector related computations for an atomic 462 - * update and adds any additional connectors needed for full modesets and calls 463 - * down into &drm_crtc_helper_funcs.mode_fixup and 464 - * &drm_encoder_helper_funcs.mode_fixup or 465 - * &drm_encoder_helper_funcs.atomic_check functions of the driver backend. 462 + * update and adds any additional connectors needed for full modesets. It calls 463 + * the various per-object callbacks in the follow order: 464 + * 465 + * 1. &drm_connector_helper_funcs.atomic_best_encoder for determining the new encoder. 466 + * 2. &drm_connector_helper_funcs.atomic_check to validate the connector state. 467 + * 3. If it's determined a modeset is needed then all connectors on the affected crtc 468 + * crtc are added and &drm_connector_helper_funcs.atomic_check is run on them. 469 + * 4. &drm_bridge_funcs.mode_fixup is called on all encoder bridges. 470 + * 5. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state. 471 + * This function is only called when the encoder will be part of a configured crtc, 472 + * it must not be used for implementing connector property validation. 473 + * If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called 474 + * instead. 475 + * 6. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints. 466 476 * 467 477 * &drm_crtc_state.mode_changed is set when the input mode is changed. 468 478 * &drm_crtc_state.connectors_changed is set when a connector is added or ··· 502 492 struct drm_connector *connector; 503 493 struct drm_connector_state *old_connector_state, *new_connector_state; 504 494 int i, ret; 495 + unsigned connectors_mask = 0; 505 496 506 497 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 498 + bool has_connectors = 499 + !!new_crtc_state->connector_mask; 500 + 507 501 if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) { 508 502 DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n", 509 503 crtc->base.id, crtc->name); ··· 529 515 new_crtc_state->mode_changed = true; 530 516 new_crtc_state->connectors_changed = true; 531 517 } 518 + 519 + if (old_crtc_state->active != new_crtc_state->active) { 520 + DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n", 521 + crtc->base.id, crtc->name); 522 + new_crtc_state->active_changed = true; 523 + } 524 + 525 + if (new_crtc_state->enable != has_connectors) { 526 + DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n", 527 + crtc->base.id, crtc->name); 528 + 529 + return -EINVAL; 530 + } 532 531 } 533 532 534 - ret = handle_conflicting_encoders(state, state->legacy_set_config); 533 + ret = handle_conflicting_encoders(state, false); 535 534 if (ret) 536 535 return ret; 537 536 538 537 for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { 538 + const struct drm_connector_helper_funcs *funcs = connector->helper_private; 539 + 539 540 /* 540 541 * This only sets crtc->connectors_changed for routing changes, 541 542 * drivers must set crtc->connectors_changed themselves when ··· 568 539 new_connector_state->link_status) 569 540 new_crtc_state->connectors_changed = true; 570 541 } 542 + 543 + if (funcs->atomic_check) 544 + ret = funcs->atomic_check(connector, new_connector_state); 545 + if (ret) 546 + return ret; 547 + 548 + connectors_mask += BIT(i); 571 549 } 572 550 573 551 /* ··· 584 548 * crtc only changed its mode but has the same set of connectors. 585 549 */ 586 550 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 587 - bool has_connectors = 588 - !!new_crtc_state->connector_mask; 589 - 590 - /* 591 - * We must set ->active_changed after walking connectors for 592 - * otherwise an update that only changes active would result in 593 - * a full modeset because update_connector_routing force that. 594 - */ 595 - if (old_crtc_state->active != new_crtc_state->active) { 596 - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active changed\n", 597 - crtc->base.id, crtc->name); 598 - new_crtc_state->active_changed = true; 599 - } 600 - 601 551 if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) 602 552 continue; 603 553 ··· 599 577 ret = drm_atomic_add_affected_planes(state, crtc); 600 578 if (ret != 0) 601 579 return ret; 580 + } 602 581 603 - if (new_crtc_state->enable != has_connectors) { 604 - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled/connectors mismatch\n", 605 - crtc->base.id, crtc->name); 582 + /* 583 + * Iterate over all connectors again, to make sure atomic_check() 584 + * has been called on them when a modeset is forced. 585 + */ 586 + for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) { 587 + const struct drm_connector_helper_funcs *funcs = connector->helper_private; 606 588 607 - return -EINVAL; 608 - } 589 + if (connectors_mask & BIT(i)) 590 + continue; 591 + 592 + if (funcs->atomic_check) 593 + ret = funcs->atomic_check(connector, new_connector_state); 594 + if (ret) 595 + return ret; 609 596 } 610 597 611 598 return mode_fixup(state); ··· 2320 2289 if (!state) 2321 2290 return -ENOMEM; 2322 2291 2323 - state->legacy_set_config = true; 2324 2292 state->acquire_ctx = ctx; 2325 2293 ret = __drm_atomic_helper_set_config(set, state); 2326 2294 if (ret != 0) 2327 2295 goto fail; 2296 + 2297 + ret = handle_conflicting_encoders(state, true); 2298 + if (ret) 2299 + return ret; 2328 2300 2329 2301 ret = drm_atomic_commit(state); 2330 2302 ··· 2656 2622 int drm_atomic_helper_resume(struct drm_device *dev, 2657 2623 struct drm_atomic_state *state) 2658 2624 { 2659 - struct drm_mode_config *config = &dev->mode_config; 2625 + struct drm_modeset_acquire_ctx ctx; 2660 2626 int err; 2661 2627 2662 2628 drm_mode_config_reset(dev); 2663 2629 2664 - drm_modeset_lock_all(dev); 2665 - err = drm_atomic_helper_commit_duplicated_state(state, config->acquire_ctx); 2666 - drm_modeset_unlock_all(dev); 2630 + drm_modeset_acquire_init(&ctx, 0); 2631 + while (1) { 2632 + err = drm_atomic_helper_commit_duplicated_state(state, &ctx); 2633 + if (err != -EDEADLK) 2634 + break; 2635 + 2636 + drm_modeset_backoff(&ctx); 2637 + } 2638 + 2639 + drm_modeset_drop_locks(&ctx); 2640 + drm_modeset_acquire_fini(&ctx); 2667 2641 2668 2642 return err; 2669 2643 } ··· 3017 2975 if (!state) 3018 2976 return -ENOMEM; 3019 2977 3020 - state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); 2978 + state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; 3021 2979 retry: 3022 2980 crtc_state = drm_atomic_get_crtc_state(state, crtc); 3023 2981 if (IS_ERR(crtc_state)) { ··· 3513 3471 * @green: green correction table 3514 3472 * @blue: green correction table 3515 3473 * @size: size of the tables 3474 + * @ctx: lock acquire context 3516 3475 * 3517 3476 * Implements support for legacy gamma correction table for drivers 3518 3477 * that support color management through the DEGAMMA_LUT/GAMMA_LUT ··· 3521 3478 */ 3522 3479 int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, 3523 3480 u16 *red, u16 *green, u16 *blue, 3524 - uint32_t size) 3481 + uint32_t size, 3482 + struct drm_modeset_acquire_ctx *ctx) 3525 3483 { 3526 3484 struct drm_device *dev = crtc->dev; 3527 3485 struct drm_mode_config *config = &dev->mode_config; ··· 3553 3509 blob_data[i].blue = blue[i]; 3554 3510 } 3555 3511 3556 - state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; 3557 - retry: 3512 + state->acquire_ctx = ctx; 3558 3513 crtc_state = drm_atomic_get_crtc_state(state, crtc); 3559 3514 if (IS_ERR(crtc_state)) { 3560 3515 ret = PTR_ERR(crtc_state); ··· 3577 3534 goto fail; 3578 3535 3579 3536 ret = drm_atomic_commit(state); 3580 - fail: 3581 - if (ret == -EDEADLK) 3582 - goto backoff; 3583 3537 3538 + fail: 3584 3539 drm_atomic_state_put(state); 3585 3540 drm_property_blob_put(blob); 3586 3541 return ret; 3587 - 3588 - backoff: 3589 - drm_atomic_state_clear(state); 3590 - drm_atomic_legacy_backoff(state); 3591 - 3592 - goto retry; 3593 3542 } 3594 3543 EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
+27 -24
drivers/gpu/drm/drm_color_mgmt.c
··· 218 218 struct drm_crtc *crtc; 219 219 void *r_base, *g_base, *b_base; 220 220 int size; 221 + struct drm_modeset_acquire_ctx ctx; 221 222 int ret = 0; 222 223 223 224 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 224 225 return -EINVAL; 225 226 226 - drm_modeset_lock_all(dev); 227 227 crtc = drm_crtc_find(dev, crtc_lut->crtc_id); 228 - if (!crtc) { 229 - ret = -ENOENT; 230 - goto out; 231 - } 228 + if (!crtc) 229 + return -ENOENT; 232 230 233 - if (crtc->funcs->gamma_set == NULL) { 234 - ret = -ENOSYS; 235 - goto out; 236 - } 231 + if (crtc->funcs->gamma_set == NULL) 232 + return -ENOSYS; 237 233 238 234 /* memcpy into gamma store */ 239 - if (crtc_lut->gamma_size != crtc->gamma_size) { 240 - ret = -EINVAL; 235 + if (crtc_lut->gamma_size != crtc->gamma_size) 236 + return -EINVAL; 237 + 238 + drm_modeset_acquire_init(&ctx, 0); 239 + retry: 240 + ret = drm_modeset_lock_all_ctx(dev, &ctx); 241 + if (ret) 241 242 goto out; 242 - } 243 243 244 244 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 245 245 r_base = crtc->gamma_store; ··· 260 260 goto out; 261 261 } 262 262 263 - ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); 263 + ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 264 + crtc->gamma_size, &ctx); 264 265 265 266 out: 266 - drm_modeset_unlock_all(dev); 267 + if (ret == -EDEADLK) { 268 + drm_modeset_backoff(&ctx); 269 + goto retry; 270 + } 271 + drm_modeset_drop_locks(&ctx); 272 + drm_modeset_acquire_fini(&ctx); 273 + 267 274 return ret; 268 275 269 276 } ··· 302 295 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 303 296 return -EINVAL; 304 297 305 - drm_modeset_lock_all(dev); 306 298 crtc = drm_crtc_find(dev, crtc_lut->crtc_id); 307 - if (!crtc) { 308 - ret = -ENOENT; 309 - goto out; 310 - } 299 + if (!crtc) 300 + return -ENOENT; 311 301 312 302 /* memcpy into gamma store */ 313 - if (crtc_lut->gamma_size != crtc->gamma_size) { 314 - ret = -EINVAL; 315 - goto out; 316 - } 303 + if (crtc_lut->gamma_size != crtc->gamma_size) 304 + return -EINVAL; 317 305 306 + drm_modeset_lock(&crtc->mutex, NULL); 318 307 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 319 308 r_base = crtc->gamma_store; 320 309 if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) { ··· 330 327 goto out; 331 328 } 332 329 out: 333 - drm_modeset_unlock_all(dev); 330 + drm_modeset_unlock(&crtc->mutex); 334 331 return ret; 335 332 }
+2
drivers/gpu/drm/drm_crtc.c
··· 576 576 } 577 577 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); 578 578 579 + mutex_lock(&crtc->dev->mode_config.mutex); 579 580 drm_modeset_acquire_init(&ctx, 0); 580 581 retry: 581 582 ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx); ··· 722 721 } 723 722 drm_modeset_drop_locks(&ctx); 724 723 drm_modeset_acquire_fini(&ctx); 724 + mutex_unlock(&crtc->dev->mode_config.mutex); 725 725 726 726 return ret; 727 727 }
-1
drivers/gpu/drm/drm_crtc_internal.h
··· 182 182 struct drm_property *property, uint64_t *val); 183 183 int drm_mode_atomic_ioctl(struct drm_device *dev, 184 184 void *data, struct drm_file *file_priv); 185 - int drm_atomic_remove_fb(struct drm_framebuffer *fb); 186 185 187 186 188 187 /* drm_plane.c */
+120 -81
drivers/gpu/drm/drm_fb_helper.c
··· 109 109 for (({ lockdep_assert_held(&(fbh)->dev->mode_config.mutex); }), \ 110 110 i__ = 0; i__ < (fbh)->connector_count; i__++) 111 111 112 + int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, 113 + struct drm_connector *connector) 114 + { 115 + struct drm_fb_helper_connector *fb_conn; 116 + struct drm_fb_helper_connector **temp; 117 + unsigned int count; 118 + 119 + if (!drm_fbdev_emulation) 120 + return 0; 121 + 122 + WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex)); 123 + 124 + count = fb_helper->connector_count + 1; 125 + 126 + if (count > fb_helper->connector_info_alloc_count) { 127 + size_t size = count * sizeof(fb_conn); 128 + 129 + temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL); 130 + if (!temp) 131 + return -ENOMEM; 132 + 133 + fb_helper->connector_info_alloc_count = count; 134 + fb_helper->connector_info = temp; 135 + } 136 + 137 + fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL); 138 + if (!fb_conn) 139 + return -ENOMEM; 140 + 141 + drm_connector_get(connector); 142 + fb_conn->connector = connector; 143 + fb_helper->connector_info[fb_helper->connector_count++] = fb_conn; 144 + return 0; 145 + } 146 + EXPORT_SYMBOL(drm_fb_helper_add_one_connector); 147 + 112 148 /** 113 149 * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev 114 150 * emulation helper ··· 198 162 } 199 163 EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); 200 164 201 - int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector) 202 - { 203 - struct drm_fb_helper_connector **temp; 204 - struct drm_fb_helper_connector *fb_helper_connector; 205 - 206 - if (!drm_fbdev_emulation) 207 - return 0; 208 - 209 - WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex)); 210 - if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) { 211 - temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL); 212 - if (!temp) 213 - return -ENOMEM; 214 - 215 - fb_helper->connector_info_alloc_count = fb_helper->connector_count + 1; 216 - fb_helper->connector_info = temp; 217 - } 218 - 219 - 220 - fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); 221 - if (!fb_helper_connector) 222 - return -ENOMEM; 223 - 224 - drm_connector_get(connector); 225 - fb_helper_connector->connector = connector; 226 - fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector; 227 - return 0; 228 - } 229 - EXPORT_SYMBOL(drm_fb_helper_add_one_connector); 230 - 231 165 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, 232 166 struct drm_connector *connector) 233 167 { ··· 219 213 fb_helper_connector = fb_helper->connector_info[i]; 220 214 drm_connector_put(fb_helper_connector->connector); 221 215 222 - for (j = i + 1; j < fb_helper->connector_count; j++) { 216 + for (j = i + 1; j < fb_helper->connector_count; j++) 223 217 fb_helper->connector_info[j - 1] = fb_helper->connector_info[j]; 224 - } 218 + 225 219 fb_helper->connector_count--; 226 220 kfree(fb_helper_connector); 227 221 ··· 256 250 g_base = r_base + crtc->gamma_size; 257 251 b_base = g_base + crtc->gamma_size; 258 252 259 - crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); 253 + crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 254 + crtc->gamma_size, NULL); 260 255 } 261 256 262 257 /** ··· 280 273 281 274 funcs = mode_set->crtc->helper_private; 282 275 if (funcs->mode_set_base_atomic == NULL) 276 + continue; 277 + 278 + if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev)) 283 279 continue; 284 280 285 281 drm_fb_helper_save_lut_atomic(mode_set->crtc, helper); ··· 326 316 327 317 for (i = 0; i < helper->crtc_count; i++) { 328 318 struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; 319 + 329 320 crtc = mode_set->crtc; 330 321 funcs = crtc->helper_private; 331 322 fb = drm_mode_config_fb(crtc); ··· 340 329 } 341 330 342 331 if (funcs->mode_set_base_atomic == NULL) 332 + continue; 333 + 334 + if (drm_drv_uses_atomic_modeset(crtc->dev)) 343 335 continue; 344 336 345 337 drm_fb_helper_restore_lut_atomic(mode_set->crtc); ··· 360 346 struct drm_plane *plane; 361 347 struct drm_atomic_state *state; 362 348 int i, ret; 363 - unsigned plane_mask; 349 + unsigned int plane_mask; 364 350 365 351 state = drm_atomic_state_alloc(dev); 366 352 if (!state) ··· 392 378 goto fail; 393 379 } 394 380 395 - for(i = 0; i < fb_helper->crtc_count; i++) { 381 + for (i = 0; i < fb_helper->crtc_count; i++) { 396 382 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; 397 383 398 384 ret = __drm_atomic_helper_set_config(mode_set, state); ··· 418 404 goto retry; 419 405 } 420 406 421 - static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) 407 + static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper) 422 408 { 423 409 struct drm_device *dev = fb_helper->dev; 424 410 struct drm_plane *plane; 425 411 int i; 426 - 427 - drm_warn_on_modeset_not_all_locked(dev); 428 - 429 - if (drm_drv_uses_atomic_modeset(dev)) 430 - return restore_fbdev_mode_atomic(fb_helper); 431 412 432 413 drm_for_each_plane(plane, dev) { 433 414 if (plane->type != DRM_PLANE_TYPE_PRIMARY) ··· 455 446 } 456 447 457 448 return 0; 449 + } 450 + 451 + static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) 452 + { 453 + struct drm_device *dev = fb_helper->dev; 454 + 455 + drm_warn_on_modeset_not_all_locked(dev); 456 + 457 + if (drm_drv_uses_atomic_modeset(dev)) 458 + return restore_fbdev_mode_atomic(fb_helper); 459 + else 460 + return restore_fbdev_mode_legacy(fb_helper); 458 461 } 459 462 460 463 /** ··· 509 488 struct drm_crtc *crtc; 510 489 int bound = 0, crtcs_bound = 0; 511 490 512 - /* Sometimes user space wants everything disabled, so don't steal the 513 - * display if there's a master. */ 491 + /* 492 + * Sometimes user space wants everything disabled, so don't steal the 493 + * display if there's a master. 494 + */ 514 495 if (READ_ONCE(dev->master)) 515 496 return false; 516 497 ··· 560 537 static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) 561 538 { 562 539 bool ret; 540 + 563 541 ret = drm_fb_helper_force_kernel_mode(); 564 542 if (ret == true) 565 543 DRM_ERROR("Failed to restore crtc configuration\n"); ··· 894 870 mutex_lock(&kernel_fb_helper_lock); 895 871 if (!list_empty(&fb_helper->kernel_fb_list)) { 896 872 list_del(&fb_helper->kernel_fb_list); 897 - if (list_empty(&kernel_fb_helper_list)) { 873 + if (list_empty(&kernel_fb_helper_list)) 898 874 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); 899 - } 900 875 } 901 876 mutex_unlock(&kernel_fb_helper_lock); 902 877 ··· 1188 1165 (blue << info->var.blue.offset); 1189 1166 if (info->var.transp.length > 0) { 1190 1167 u32 mask = (1 << info->var.transp.length) - 1; 1168 + 1191 1169 mask <<= info->var.transp.offset; 1192 1170 value |= mask; 1193 1171 } ··· 1471 1447 struct drm_atomic_state *state; 1472 1448 struct drm_plane *plane; 1473 1449 int i, ret; 1474 - unsigned plane_mask; 1450 + unsigned int plane_mask; 1475 1451 1476 1452 state = drm_atomic_state_alloc(dev); 1477 1453 if (!state) ··· 1480 1456 state->acquire_ctx = dev->mode_config.acquire_ctx; 1481 1457 retry: 1482 1458 plane_mask = 0; 1483 - for(i = 0; i < fb_helper->crtc_count; i++) { 1459 + for (i = 0; i < fb_helper->crtc_count; i++) { 1484 1460 struct drm_mode_set *mode_set; 1485 1461 1486 1462 mode_set = &fb_helper->crtc_info[i].mode_set; ··· 1520 1496 goto retry; 1521 1497 } 1522 1498 1523 - /** 1524 - * drm_fb_helper_pan_display - implementation for &fb_ops.fb_pan_display 1525 - * @var: updated screen information 1526 - * @info: fbdev registered by the helper 1527 - */ 1528 - int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, 1499 + static int pan_display_legacy(struct fb_var_screeninfo *var, 1529 1500 struct fb_info *info) 1530 1501 { 1531 1502 struct drm_fb_helper *fb_helper = info->par; 1532 - struct drm_device *dev = fb_helper->dev; 1533 1503 struct drm_mode_set *modeset; 1534 1504 int ret = 0; 1535 1505 int i; 1536 - 1537 - if (oops_in_progress) 1538 - return -EBUSY; 1539 - 1540 - drm_modeset_lock_all(dev); 1541 - if (!drm_fb_helper_is_bound(fb_helper)) { 1542 - drm_modeset_unlock_all(dev); 1543 - return -EBUSY; 1544 - } 1545 - 1546 - if (drm_drv_uses_atomic_modeset(dev)) { 1547 - ret = pan_display_atomic(var, info); 1548 - goto unlock; 1549 - } 1550 1506 1551 1507 for (i = 0; i < fb_helper->crtc_count; i++) { 1552 1508 modeset = &fb_helper->crtc_info[i].mode_set; ··· 1542 1538 } 1543 1539 } 1544 1540 } 1545 - unlock: 1541 + 1542 + return ret; 1543 + } 1544 + 1545 + /** 1546 + * drm_fb_helper_pan_display - implementation for &fb_ops.fb_pan_display 1547 + * @var: updated screen information 1548 + * @info: fbdev registered by the helper 1549 + */ 1550 + int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, 1551 + struct fb_info *info) 1552 + { 1553 + struct drm_fb_helper *fb_helper = info->par; 1554 + struct drm_device *dev = fb_helper->dev; 1555 + int ret; 1556 + 1557 + if (oops_in_progress) 1558 + return -EBUSY; 1559 + 1560 + drm_modeset_lock_all(dev); 1561 + if (!drm_fb_helper_is_bound(fb_helper)) { 1562 + drm_modeset_unlock_all(dev); 1563 + return -EBUSY; 1564 + } 1565 + 1566 + if (drm_drv_uses_atomic_modeset(dev)) 1567 + ret = pan_display_atomic(var, info); 1568 + else 1569 + ret = pan_display_legacy(var, info); 1546 1570 drm_modeset_unlock_all(dev); 1571 + 1547 1572 return ret; 1548 1573 } 1549 1574 EXPORT_SYMBOL(drm_fb_helper_pan_display); ··· 1594 1561 memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size)); 1595 1562 sizes.surface_depth = 24; 1596 1563 sizes.surface_bpp = 32; 1597 - sizes.fb_width = (unsigned)-1; 1598 - sizes.fb_height = (unsigned)-1; 1564 + sizes.fb_width = (u32)-1; 1565 + sizes.fb_height = (u32)-1; 1599 1566 1600 - /* if driver picks 8 or 16 by default use that 1601 - for both depth/bpp */ 1567 + /* if driver picks 8 or 16 by default use that for both depth/bpp */ 1602 1568 if (preferred_bpp != sizes.surface_bpp) 1603 1569 sizes.surface_depth = sizes.surface_bpp = preferred_bpp; 1604 1570 ··· 1662 1630 1663 1631 for (j = 0; j < mode_set->num_connectors; j++) { 1664 1632 struct drm_connector *connector = mode_set->connectors[j]; 1633 + 1665 1634 if (connector->has_tile) { 1666 1635 lasth = (connector->tile_h_loc == (connector->num_h_tile - 1)); 1667 1636 lastv = (connector->tile_v_loc == (connector->num_v_tile - 1)); ··· 1678 1645 } 1679 1646 1680 1647 if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { 1681 - /* hmm everyone went away - assume VGA cable just fell out 1682 - and will come back later. */ 1648 + /* 1649 + * hmm everyone went away - assume VGA cable just fell out 1650 + * and will come back later. 1651 + */ 1683 1652 DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n"); 1684 1653 sizes.fb_width = sizes.surface_width = 1024; 1685 1654 sizes.fb_height = sizes.surface_height = 768; ··· 1738 1703 info->fix.accel = FB_ACCEL_NONE; 1739 1704 1740 1705 info->fix.line_length = pitch; 1741 - return; 1742 1706 } 1743 1707 EXPORT_SYMBOL(drm_fb_helper_fill_fix); 1744 1708 ··· 1759 1725 uint32_t fb_width, uint32_t fb_height) 1760 1726 { 1761 1727 struct drm_framebuffer *fb = fb_helper->fb; 1728 + 1762 1729 info->pseudo_palette = fb_helper->pseudo_palette; 1763 1730 info->var.xres_virtual = fb->width; 1764 1731 info->var.yres_virtual = fb->height; ··· 2092 2057 continue; 2093 2058 2094 2059 } else { 2095 - if (fb_helper_conn->connector->tile_h_loc != tile_pass -1 && 2060 + if (fb_helper_conn->connector->tile_h_loc != tile_pass - 1 && 2096 2061 fb_helper_conn->connector->tile_v_loc != tile_pass - 1) 2097 2062 /* if this tile_pass doesn't cover any of the tiles - keep going */ 2098 2063 continue; 2099 2064 2100 - /* find the tile offsets for this pass - need 2101 - to find all tiles left and above */ 2065 + /* 2066 + * find the tile offsets for this pass - need to find 2067 + * all tiles left and above 2068 + */ 2102 2069 drm_get_tile_offsets(fb_helper, modes, offsets, 2103 2070 i, fb_helper_conn->connector->tile_h_loc, fb_helper_conn->connector->tile_v_loc); 2104 2071 } ··· 2184 2147 if (!encoder) 2185 2148 goto out; 2186 2149 2187 - /* select a crtc for this connector and then attempt to configure 2188 - remaining connectors */ 2150 + /* 2151 + * select a crtc for this connector and then attempt to configure 2152 + * remaining connectors 2153 + */ 2189 2154 for (c = 0; c < fb_helper->crtc_count; c++) { 2190 2155 crtc = &fb_helper->crtc_info[c]; 2191 2156
+115 -22
drivers/gpu/drm/drm_framebuffer.c
··· 24 24 #include <drm/drmP.h> 25 25 #include <drm/drm_auth.h> 26 26 #include <drm/drm_framebuffer.h> 27 + #include <drm/drm_atomic.h> 27 28 28 29 #include "drm_crtc_internal.h" 29 30 ··· 756 755 } 757 756 EXPORT_SYMBOL(drm_framebuffer_cleanup); 758 757 758 + static int atomic_remove_fb(struct drm_framebuffer *fb) 759 + { 760 + struct drm_modeset_acquire_ctx ctx; 761 + struct drm_device *dev = fb->dev; 762 + struct drm_atomic_state *state; 763 + struct drm_plane *plane; 764 + struct drm_connector *conn; 765 + struct drm_connector_state *conn_state; 766 + int i, ret = 0; 767 + unsigned plane_mask; 768 + 769 + state = drm_atomic_state_alloc(dev); 770 + if (!state) 771 + return -ENOMEM; 772 + 773 + drm_modeset_acquire_init(&ctx, 0); 774 + state->acquire_ctx = &ctx; 775 + 776 + retry: 777 + plane_mask = 0; 778 + ret = drm_modeset_lock_all_ctx(dev, &ctx); 779 + if (ret) 780 + goto unlock; 781 + 782 + drm_for_each_plane(plane, dev) { 783 + struct drm_plane_state *plane_state; 784 + 785 + if (plane->state->fb != fb) 786 + continue; 787 + 788 + plane_state = drm_atomic_get_plane_state(state, plane); 789 + if (IS_ERR(plane_state)) { 790 + ret = PTR_ERR(plane_state); 791 + goto unlock; 792 + } 793 + 794 + if (plane_state->crtc->primary == plane) { 795 + struct drm_crtc_state *crtc_state; 796 + 797 + crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); 798 + 799 + ret = drm_atomic_add_affected_connectors(state, plane_state->crtc); 800 + if (ret) 801 + goto unlock; 802 + 803 + crtc_state->active = false; 804 + ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); 805 + if (ret) 806 + goto unlock; 807 + } 808 + 809 + drm_atomic_set_fb_for_plane(plane_state, NULL); 810 + ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); 811 + if (ret) 812 + goto unlock; 813 + 814 + plane_mask |= BIT(drm_plane_index(plane)); 815 + 816 + plane->old_fb = plane->fb; 817 + } 818 + 819 + for_each_connector_in_state(state, conn, conn_state, i) { 820 + ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); 821 + 822 + if (ret) 823 + goto unlock; 824 + } 825 + 826 + if (plane_mask) 827 + ret = drm_atomic_commit(state); 828 + 829 + unlock: 830 + if (plane_mask) 831 + drm_atomic_clean_old_fb(dev, plane_mask, ret); 832 + 833 + if (ret == -EDEADLK) { 834 + drm_modeset_backoff(&ctx); 835 + goto retry; 836 + } 837 + 838 + drm_atomic_state_put(state); 839 + 840 + drm_modeset_drop_locks(&ctx); 841 + drm_modeset_acquire_fini(&ctx); 842 + 843 + return ret; 844 + } 845 + 846 + static void legacy_remove_fb(struct drm_framebuffer *fb) 847 + { 848 + struct drm_device *dev = fb->dev; 849 + struct drm_crtc *crtc; 850 + struct drm_plane *plane; 851 + 852 + drm_modeset_lock_all(dev); 853 + /* remove from any CRTC */ 854 + drm_for_each_crtc(crtc, dev) { 855 + if (crtc->primary->fb == fb) { 856 + /* should turn off the crtc */ 857 + if (drm_crtc_force_disable(crtc)) 858 + DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); 859 + } 860 + } 861 + 862 + drm_for_each_plane(plane, dev) { 863 + if (plane->fb == fb) 864 + drm_plane_force_disable(plane); 865 + } 866 + drm_modeset_unlock_all(dev); 867 + } 868 + 759 869 /** 760 870 * drm_framebuffer_remove - remove and unreference a framebuffer object 761 871 * @fb: framebuffer to remove ··· 882 770 void drm_framebuffer_remove(struct drm_framebuffer *fb) 883 771 { 884 772 struct drm_device *dev; 885 - struct drm_crtc *crtc; 886 - struct drm_plane *plane; 887 773 888 774 if (!fb) 889 775 return; ··· 907 797 */ 908 798 if (drm_framebuffer_read_refcount(fb) > 1) { 909 799 if (drm_drv_uses_atomic_modeset(dev)) { 910 - int ret = drm_atomic_remove_fb(fb); 800 + int ret = atomic_remove_fb(fb); 911 801 WARN(ret, "atomic remove_fb failed with %i\n", ret); 912 - goto out; 913 - } 914 - 915 - drm_modeset_lock_all(dev); 916 - /* remove from any CRTC */ 917 - drm_for_each_crtc(crtc, dev) { 918 - if (crtc->primary->fb == fb) { 919 - /* should turn off the crtc */ 920 - if (drm_crtc_force_disable(crtc)) 921 - DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); 922 - } 923 - } 924 - 925 - drm_for_each_plane(plane, dev) { 926 - if (plane->fb == fb) 927 - drm_plane_force_disable(plane); 928 - } 929 - drm_modeset_unlock_all(dev); 802 + } else 803 + legacy_remove_fb(fb); 930 804 } 931 805 932 - out: 933 806 drm_framebuffer_put(fb); 934 807 } 935 808 EXPORT_SYMBOL(drm_framebuffer_remove);
+40 -36
drivers/gpu/drm/drm_ioc32.c
··· 1 - /** 1 + /* 2 2 * \file drm_ioc32.c 3 3 * 4 4 * 32-bit ioctl compatibility routines for the DRM. ··· 72 72 #define DRM_IOCTL_MODE_ADDFB232 DRM_IOWR(0xb8, drm_mode_fb_cmd232_t) 73 73 74 74 typedef struct drm_version_32 { 75 - int version_major; /**< Major version */ 76 - int version_minor; /**< Minor version */ 77 - int version_patchlevel; /**< Patch level */ 78 - u32 name_len; /**< Length of name buffer */ 79 - u32 name; /**< Name of driver */ 80 - u32 date_len; /**< Length of date buffer */ 81 - u32 date; /**< User-space buffer to hold date */ 82 - u32 desc_len; /**< Length of desc buffer */ 83 - u32 desc; /**< User-space buffer to hold desc */ 75 + int version_major; /* Major version */ 76 + int version_minor; /* Minor version */ 77 + int version_patchlevel; /* Patch level */ 78 + u32 name_len; /* Length of name buffer */ 79 + u32 name; /* Name of driver */ 80 + u32 date_len; /* Length of date buffer */ 81 + u32 date; /* User-space buffer to hold date */ 82 + u32 desc_len; /* Length of desc buffer */ 83 + u32 desc; /* User-space buffer to hold desc */ 84 84 } drm_version32_t; 85 85 86 86 static int compat_drm_version(struct file *file, unsigned int cmd, ··· 126 126 } 127 127 128 128 typedef struct drm_unique32 { 129 - u32 unique_len; /**< Length of unique */ 130 - u32 unique; /**< Unique name for driver instantiation */ 129 + u32 unique_len; /* Length of unique */ 130 + u32 unique; /* Unique name for driver instantiation */ 131 131 } drm_unique32_t; 132 132 133 133 static int compat_drm_getunique(struct file *file, unsigned int cmd, ··· 180 180 } 181 181 182 182 typedef struct drm_map32 { 183 - u32 offset; /**< Requested physical address (0 for SAREA)*/ 184 - u32 size; /**< Requested physical size (bytes) */ 185 - enum drm_map_type type; /**< Type of memory to map */ 186 - enum drm_map_flags flags; /**< Flags */ 187 - u32 handle; /**< User-space: "Handle" to pass to mmap() */ 188 - int mtrr; /**< MTRR slot used */ 183 + u32 offset; /* Requested physical address (0 for SAREA) */ 184 + u32 size; /* Requested physical size (bytes) */ 185 + enum drm_map_type type; /* Type of memory to map */ 186 + enum drm_map_flags flags; /* Flags */ 187 + u32 handle; /* User-space: "Handle" to pass to mmap() */ 188 + int mtrr; /* MTRR slot used */ 189 189 } drm_map32_t; 190 190 191 191 static int compat_drm_getmap(struct file *file, unsigned int cmd, ··· 286 286 } 287 287 288 288 typedef struct drm_client32 { 289 - int idx; /**< Which client desired? */ 290 - int auth; /**< Is client authenticated? */ 291 - u32 pid; /**< Process ID */ 292 - u32 uid; /**< User ID */ 293 - u32 magic; /**< Magic */ 294 - u32 iocs; /**< Ioctl count */ 289 + int idx; /* Which client desired? */ 290 + int auth; /* Is client authenticated? */ 291 + u32 pid; /* Process ID */ 292 + u32 uid; /* User ID */ 293 + u32 magic; /* Magic */ 294 + u32 iocs; /* Ioctl count */ 295 295 } drm_client32_t; 296 296 297 297 static int compat_drm_getclient(struct file *file, unsigned int cmd, ··· 366 366 } 367 367 368 368 typedef struct drm_buf_desc32 { 369 - int count; /**< Number of buffers of this size */ 370 - int size; /**< Size in bytes */ 371 - int low_mark; /**< Low water mark */ 372 - int high_mark; /**< High water mark */ 369 + int count; /* Number of buffers of this size */ 370 + int size; /* Size in bytes */ 371 + int low_mark; /* Low water mark */ 372 + int high_mark; /* High water mark */ 373 373 int flags; 374 - u32 agp_start; /**< Start address in the AGP aperture */ 374 + u32 agp_start; /* Start address in the AGP aperture */ 375 375 } drm_buf_desc32_t; 376 376 377 377 static int compat_drm_addbufs(struct file *file, unsigned int cmd, ··· 1111 1111 }; 1112 1112 1113 1113 /** 1114 - * Called whenever a 32-bit process running under a 64-bit kernel 1115 - * performs an ioctl on /dev/drm. 1114 + * drm_compat_ioctl - 32bit IOCTL compatibility handler for DRM drivers 1115 + * @filp: file this ioctl is called on 1116 + * @cmd: ioctl cmd number 1117 + * @arg: user argument 1116 1118 * 1117 - * \param file_priv DRM file private. 1118 - * \param cmd command. 1119 - * \param arg user argument. 1120 - * \return zero on success or negative number on failure. 1119 + * Compatibility handler for 32 bit userspace running on 64 kernels. All actual 1120 + * IOCTL handling is forwarded to drm_ioctl(), while marshalling structures as 1121 + * appropriate. Note that this only handles DRM core IOCTLs, if the driver has 1122 + * botched IOCTL itself, it must handle those by wrapping this function. 1123 + * 1124 + * Returns: 1125 + * Zero on success, negative error code on failure. 1121 1126 */ 1122 1127 long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 1123 1128 { ··· 1146 1141 1147 1142 return ret; 1148 1143 } 1149 - 1150 1144 EXPORT_SYMBOL(drm_compat_ioctl);
+51 -2
drivers/gpu/drm/drm_ioctl.c
··· 286 286 case DRM_CAP_ADDFB2_MODIFIERS: 287 287 req->value = dev->mode_config.allow_fb_modifiers; 288 288 break; 289 + case DRM_CAP_CRTC_IN_VBLANK_EVENT: 290 + req->value = 1; 291 + break; 289 292 default: 290 293 return -EINVAL; 291 294 } ··· 650 647 #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) 651 648 652 649 /** 650 + * DOC: driver specific ioctls 651 + * 652 + * First things first, driver private IOCTLs should only be needed for drivers 653 + * supporting rendering. Kernel modesetting is all standardized, and extended 654 + * through properties. There are a few exceptions in some existing drivers, 655 + * which define IOCTL for use by the display DRM master, but they all predate 656 + * properties. 657 + * 658 + * Now if you do have a render driver you always have to support it through 659 + * driver private properties. There's a few steps needed to wire all the things 660 + * up. 661 + * 662 + * First you need to define the structure for your IOCTL in your driver private 663 + * UAPI header in ``include/uapi/drm/my_driver_drm.h``:: 664 + * 665 + * struct my_driver_operation { 666 + * u32 some_thing; 667 + * u32 another_thing; 668 + * }; 669 + * 670 + * Please make sure that you follow all the best practices from 671 + * ``Documentation/ioctl/botching-up-ioctls.txt``. Note that drm_ioctl() 672 + * automatically zero-extends structures, hence make sure you can add more stuff 673 + * at the end, i.e. don't put a variable sized array there. 674 + * 675 + * Then you need to define your IOCTL number, using one of DRM_IO(), DRM_IOR(), 676 + * DRM_IOW() or DRM_IOWR(). It must start with the DRM_IOCTL\_ prefix:: 677 + * 678 + * ##define DRM_IOCTL_MY_DRIVER_OPERATION \ 679 + * DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation) 680 + * 681 + * DRM driver private IOCTL must be in the range from DRM_COMMAND_BASE to 682 + * DRM_COMMAND_END. Finally you need an array of &struct drm_ioctl_desc to wire 683 + * up the handlers and set the access rights: 684 + * 685 + * static const struct drm_ioctl_desc my_driver_ioctls[] = { 686 + * DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation, 687 + * DRM_AUTH|DRM_RENDER_ALLOW), 688 + * }; 689 + * 690 + * And then assign this to the &drm_driver.ioctls field in your driver 691 + * structure. 692 + */ 693 + 694 + /** 653 695 * drm_ioctl - ioctl callback implementation for DRM drivers 654 696 * @filp: file this ioctl is called on 655 697 * @cmd: ioctl cmd number 656 698 * @arg: user argument 657 699 * 658 - * Looks up the ioctl function in the ::ioctls table, checking for root 659 - * previleges if so required, and dispatches to the respective function. 700 + * Looks up the ioctl function in the DRM core and the driver dispatch table, 701 + * stored in &drm_driver.ioctls. It checks for necessary permission by calling 702 + * drm_ioctl_permit(), and dispatches to the respective function. 660 703 * 661 704 * Returns: 662 705 * Zero on success, negative error code on failure.
+2
drivers/gpu/drm/drm_irq.c
··· 1026 1026 1027 1027 e->pipe = pipe; 1028 1028 e->event.sequence = drm_vblank_count(dev, pipe); 1029 + e->event.crtc_id = crtc->base.id; 1029 1030 list_add_tail(&e->base.link, &dev->vblank_event_list); 1030 1031 } 1031 1032 EXPORT_SYMBOL(drm_crtc_arm_vblank_event); ··· 1057 1056 now = get_drm_timestamp(); 1058 1057 } 1059 1058 e->pipe = pipe; 1059 + e->event.crtc_id = crtc->base.id; 1060 1060 send_vblank_event(dev, e, seq, &now); 1061 1061 } 1062 1062 EXPORT_SYMBOL(drm_crtc_send_vblank_event);
-102
drivers/gpu/drm/drm_modeset_lock.c
··· 149 149 EXPORT_SYMBOL(drm_modeset_unlock_all); 150 150 151 151 /** 152 - * drm_modeset_lock_crtc - lock crtc with hidden acquire ctx for a plane update 153 - * @crtc: DRM CRTC 154 - * @plane: DRM plane to be updated on @crtc 155 - * 156 - * This function locks the given crtc and plane (which should be either the 157 - * primary or cursor plane) using a hidden acquire context. This is necessary so 158 - * that drivers internally using the atomic interfaces can grab further locks 159 - * with the lock acquire context. 160 - * 161 - * Note that @plane can be NULL, e.g. when the cursor support hasn't yet been 162 - * converted to universal planes yet. 163 - */ 164 - void drm_modeset_lock_crtc(struct drm_crtc *crtc, 165 - struct drm_plane *plane) 166 - { 167 - struct drm_modeset_acquire_ctx *ctx; 168 - int ret; 169 - 170 - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 171 - if (WARN_ON(!ctx)) 172 - return; 173 - 174 - drm_modeset_acquire_init(ctx, 0); 175 - 176 - retry: 177 - ret = drm_modeset_lock(&crtc->mutex, ctx); 178 - if (ret) 179 - goto fail; 180 - 181 - if (plane) { 182 - ret = drm_modeset_lock(&plane->mutex, ctx); 183 - if (ret) 184 - goto fail; 185 - 186 - if (plane->crtc) { 187 - ret = drm_modeset_lock(&plane->crtc->mutex, ctx); 188 - if (ret) 189 - goto fail; 190 - } 191 - } 192 - 193 - WARN_ON(crtc->acquire_ctx); 194 - 195 - /* now we hold the locks, so now that it is safe, stash the 196 - * ctx for drm_modeset_unlock_crtc(): 197 - */ 198 - crtc->acquire_ctx = ctx; 199 - 200 - return; 201 - 202 - fail: 203 - if (ret == -EDEADLK) { 204 - drm_modeset_backoff(ctx); 205 - goto retry; 206 - } 207 - } 208 - EXPORT_SYMBOL(drm_modeset_lock_crtc); 209 - 210 - /** 211 - * drm_modeset_legacy_acquire_ctx - find acquire ctx for legacy ioctls 212 - * @crtc: drm crtc 213 - * 214 - * Legacy ioctl operations like cursor updates or page flips only have per-crtc 215 - * locking, and store the acquire ctx in the corresponding crtc. All other 216 - * legacy operations take all locks and use a global acquire context. This 217 - * function grabs the right one. 218 - */ 219 - struct drm_modeset_acquire_ctx * 220 - drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc) 221 - { 222 - if (crtc->acquire_ctx) 223 - return crtc->acquire_ctx; 224 - 225 - WARN_ON(!crtc->dev->mode_config.acquire_ctx); 226 - 227 - return crtc->dev->mode_config.acquire_ctx; 228 - } 229 - EXPORT_SYMBOL(drm_modeset_legacy_acquire_ctx); 230 - 231 - /** 232 - * drm_modeset_unlock_crtc - drop crtc lock 233 - * @crtc: drm crtc 234 - * 235 - * This drops the crtc lock acquire with drm_modeset_lock_crtc() and all other 236 - * locks acquired through the hidden context. 237 - */ 238 - void drm_modeset_unlock_crtc(struct drm_crtc *crtc) 239 - { 240 - struct drm_modeset_acquire_ctx *ctx = crtc->acquire_ctx; 241 - 242 - if (WARN_ON(!ctx)) 243 - return; 244 - 245 - crtc->acquire_ctx = NULL; 246 - drm_modeset_drop_locks(ctx); 247 - drm_modeset_acquire_fini(ctx); 248 - 249 - kfree(ctx); 250 - } 251 - EXPORT_SYMBOL(drm_modeset_unlock_crtc); 252 - 253 - /** 254 152 * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked 255 153 * @dev: device 256 154 *
+52
drivers/gpu/drm/drm_of.c
··· 3 3 #include <linux/list.h> 4 4 #include <linux/of_graph.h> 5 5 #include <drm/drmP.h> 6 + #include <drm/drm_bridge.h> 6 7 #include <drm/drm_crtc.h> 7 8 #include <drm/drm_encoder.h> 9 + #include <drm/drm_panel.h> 8 10 #include <drm/drm_of.h> 9 11 10 12 static void drm_release_of(struct device *dev, void *data) ··· 210 208 return -EINVAL; 211 209 } 212 210 EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); 211 + 212 + /* 213 + * drm_of_find_panel_or_bridge - return connected panel or bridge device 214 + * @np: device tree node containing encoder output ports 215 + * @panel: pointer to hold returned drm_panel 216 + * @bridge: pointer to hold returned drm_bridge 217 + * 218 + * Given a DT node's port and endpoint number, find the connected node and 219 + * return either the associated struct drm_panel or drm_bridge device. Either 220 + * @panel or @bridge must not be NULL. 221 + * 222 + * Returns zero if successful, or one of the standard error codes if it fails. 223 + */ 224 + int drm_of_find_panel_or_bridge(const struct device_node *np, 225 + int port, int endpoint, 226 + struct drm_panel **panel, 227 + struct drm_bridge **bridge) 228 + { 229 + int ret = -EPROBE_DEFER; 230 + struct device_node *remote; 231 + 232 + if (!panel && !bridge) 233 + return -EINVAL; 234 + 235 + remote = of_graph_get_remote_node(np, port, endpoint); 236 + if (!remote) 237 + return -ENODEV; 238 + 239 + if (panel) { 240 + *panel = of_drm_find_panel(remote); 241 + if (*panel) 242 + ret = 0; 243 + } 244 + 245 + /* No panel found yet, check for a bridge next. */ 246 + if (bridge) { 247 + if (ret) { 248 + *bridge = of_drm_find_bridge(remote); 249 + if (*bridge) 250 + ret = 0; 251 + } else { 252 + *bridge = NULL; 253 + } 254 + 255 + } 256 + 257 + of_node_put(remote); 258 + return ret; 259 + } 260 + EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge);
+24 -25
drivers/gpu/drm/drm_plane.c
··· 620 620 621 621 static int drm_mode_cursor_universal(struct drm_crtc *crtc, 622 622 struct drm_mode_cursor2 *req, 623 - struct drm_file *file_priv) 623 + struct drm_file *file_priv, 624 + struct drm_modeset_acquire_ctx *ctx) 624 625 { 625 626 struct drm_device *dev = crtc->dev; 626 627 struct drm_framebuffer *fb = NULL; ··· 635 634 int32_t crtc_x, crtc_y; 636 635 uint32_t crtc_w = 0, crtc_h = 0; 637 636 uint32_t src_w = 0, src_h = 0; 638 - struct drm_modeset_acquire_ctx ctx; 639 637 int ret = 0; 640 638 641 639 BUG_ON(!crtc->cursor); 642 640 WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL); 643 - 644 - drm_modeset_acquire_init(&ctx, 0); 645 - retry: 646 - ret = drm_modeset_lock(&crtc->mutex, &ctx); 647 - if (ret) 648 - goto fail; 649 - ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx); 650 - if (ret) 651 - goto fail; 652 641 653 642 /* 654 643 * Obtain fb we'll be using (either new or existing) and take an extra ··· 684 693 */ 685 694 ret = __setplane_internal(crtc->cursor, crtc, fb, 686 695 crtc_x, crtc_y, crtc_w, crtc_h, 687 - 0, 0, src_w, src_h, &ctx); 696 + 0, 0, src_w, src_h, ctx); 688 697 689 698 /* Update successful; save new cursor position, if necessary */ 690 699 if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { 691 700 crtc->cursor_x = req->x; 692 701 crtc->cursor_y = req->y; 693 702 } 694 - 695 - fail: 696 - if (ret == -EDEADLK) { 697 - drm_modeset_backoff(&ctx); 698 - goto retry; 699 - } 700 - 701 - drm_modeset_drop_locks(&ctx); 702 - drm_modeset_acquire_fini(&ctx); 703 703 704 704 return ret; 705 705 } ··· 700 718 struct drm_file *file_priv) 701 719 { 702 720 struct drm_crtc *crtc; 721 + struct drm_modeset_acquire_ctx ctx; 703 722 int ret = 0; 704 723 705 724 if (!drm_core_check_feature(dev, DRIVER_MODESET)) ··· 715 732 return -ENOENT; 716 733 } 717 734 735 + drm_modeset_acquire_init(&ctx, 0); 736 + retry: 737 + ret = drm_modeset_lock(&crtc->mutex, &ctx); 738 + if (ret) 739 + goto out; 718 740 /* 719 741 * If this crtc has a universal cursor plane, call that plane's update 720 742 * handler rather than using legacy cursor handlers. 721 743 */ 722 - if (crtc->cursor) 723 - return drm_mode_cursor_universal(crtc, req, file_priv); 744 + if (crtc->cursor) { 745 + ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx); 746 + if (ret) 747 + goto out; 724 748 725 - drm_modeset_lock_crtc(crtc, crtc->cursor); 749 + ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx); 750 + goto out; 751 + } 752 + 726 753 if (req->flags & DRM_MODE_CURSOR_BO) { 727 754 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 728 755 ret = -ENXIO; ··· 756 763 } 757 764 } 758 765 out: 759 - drm_modeset_unlock_crtc(crtc); 766 + if (ret == -EDEADLK) { 767 + drm_modeset_backoff(&ctx); 768 + goto retry; 769 + } 770 + 771 + drm_modeset_drop_locks(&ctx); 772 + drm_modeset_acquire_fini(&ctx); 760 773 761 774 return ret; 762 775
+93 -9
drivers/gpu/drm/drm_probe_helper.c
··· 44 44 * 45 45 * This library provides some helper code for output probing. It provides an 46 46 * implementation of the core &drm_connector_funcs.fill_modes interface with 47 - * drm_helper_probe_single_connector_modes. 47 + * drm_helper_probe_single_connector_modes(). 48 48 * 49 49 * It also provides support for polling connectors with a work item and for 50 50 * generic hotplug interrupt handling where the driver doesn't or cannot keep ··· 169 169 EXPORT_SYMBOL(drm_kms_helper_poll_enable); 170 170 171 171 static enum drm_connector_status 172 - drm_connector_detect(struct drm_connector *connector, bool force) 172 + drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force) 173 173 { 174 - return connector->funcs->detect ? 175 - connector->funcs->detect(connector, force) : 176 - connector_status_connected; 174 + const struct drm_connector_helper_funcs *funcs = connector->helper_private; 175 + struct drm_modeset_acquire_ctx ctx; 176 + int ret; 177 + 178 + drm_modeset_acquire_init(&ctx, 0); 179 + 180 + retry: 181 + ret = drm_modeset_lock(&connector->dev->mode_config.connection_mutex, &ctx); 182 + if (!ret) { 183 + if (funcs->detect_ctx) 184 + ret = funcs->detect_ctx(connector, &ctx, force); 185 + else if (connector->funcs->detect) 186 + ret = connector->funcs->detect(connector, force); 187 + else 188 + ret = connector_status_connected; 189 + } 190 + 191 + if (ret == -EDEADLK) { 192 + drm_modeset_backoff(&ctx); 193 + goto retry; 194 + } 195 + 196 + if (WARN_ON(ret < 0)) 197 + ret = connector_status_unknown; 198 + 199 + drm_modeset_drop_locks(&ctx); 200 + drm_modeset_acquire_fini(&ctx); 201 + 202 + return ret; 177 203 } 204 + 205 + /** 206 + * drm_helper_probe_detect - probe connector status 207 + * @connector: connector to probe 208 + * @ctx: acquire_ctx, or NULL to let this function handle locking. 209 + * @force: Whether destructive probe operations should be performed. 210 + * 211 + * This function calls the detect callbacks of the connector. 212 + * This function returns &drm_connector_status, or 213 + * if @ctx is set, it might also return -EDEADLK. 214 + */ 215 + int 216 + drm_helper_probe_detect(struct drm_connector *connector, 217 + struct drm_modeset_acquire_ctx *ctx, 218 + bool force) 219 + { 220 + const struct drm_connector_helper_funcs *funcs = connector->helper_private; 221 + struct drm_device *dev = connector->dev; 222 + int ret; 223 + 224 + if (!ctx) 225 + return drm_helper_probe_detect_ctx(connector, force); 226 + 227 + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx); 228 + if (ret) 229 + return ret; 230 + 231 + if (funcs->detect_ctx) 232 + return funcs->detect_ctx(connector, ctx, force); 233 + else if (connector->funcs->detect) 234 + return connector->funcs->detect(connector, force); 235 + else 236 + return connector_status_connected; 237 + } 238 + EXPORT_SYMBOL(drm_helper_probe_detect); 178 239 179 240 /** 180 241 * drm_helper_probe_single_connector_modes - get complete set of display modes ··· 300 239 struct drm_display_mode *mode; 301 240 const struct drm_connector_helper_funcs *connector_funcs = 302 241 connector->helper_private; 303 - int count = 0; 242 + int count = 0, ret; 304 243 int mode_flags = 0; 305 244 bool verbose_prune = true; 306 245 enum drm_connector_status old_status; 246 + struct drm_modeset_acquire_ctx ctx; 307 247 308 248 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); 309 249 250 + drm_modeset_acquire_init(&ctx, 0); 251 + 310 252 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, 311 253 connector->name); 254 + 255 + retry: 256 + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); 257 + if (ret == -EDEADLK) { 258 + drm_modeset_backoff(&ctx); 259 + goto retry; 260 + } else 261 + WARN_ON(ret < 0); 262 + 312 263 /* set all old modes to the stale state */ 313 264 list_for_each_entry(mode, &connector->modes, head) 314 265 mode->status = MODE_STALE; ··· 336 263 if (connector->funcs->force) 337 264 connector->funcs->force(connector); 338 265 } else { 339 - connector->status = drm_connector_detect(connector, true); 266 + ret = drm_helper_probe_detect(connector, &ctx, true); 267 + 268 + if (ret == -EDEADLK) { 269 + drm_modeset_backoff(&ctx); 270 + goto retry; 271 + } else if (WARN(ret < 0, "Invalid return value %i for connector detection\n", ret)) 272 + ret = connector_status_unknown; 273 + 274 + connector->status = ret; 340 275 } 341 276 342 277 /* ··· 436 355 prune: 437 356 drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); 438 357 358 + drm_modeset_drop_locks(&ctx); 359 + drm_modeset_acquire_fini(&ctx); 360 + 439 361 if (list_empty(&connector->modes)) 440 362 return 0; 441 363 ··· 524 440 525 441 repoll = true; 526 442 527 - connector->status = drm_connector_detect(connector, false); 443 + connector->status = drm_helper_probe_detect(connector, NULL, false); 528 444 if (old_status != connector->status) { 529 445 const char *old, *new; 530 446 ··· 672 588 673 589 old_status = connector->status; 674 590 675 - connector->status = drm_connector_detect(connector, false); 591 + connector->status = drm_helper_probe_detect(connector, NULL, false); 676 592 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", 677 593 connector->base.id, 678 594 connector->name,
+27 -41
drivers/gpu/drm/drm_property.c
··· 442 442 struct drm_property *property; 443 443 int enum_count = 0; 444 444 int value_count = 0; 445 - int ret = 0, i; 446 - int copied; 445 + int i, copied; 447 446 struct drm_property_enum *prop_enum; 448 447 struct drm_mode_property_enum __user *enum_ptr; 449 448 uint64_t __user *values_ptr; ··· 450 451 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 451 452 return -EINVAL; 452 453 453 - drm_modeset_lock_all(dev); 454 454 property = drm_property_find(dev, out_resp->prop_id); 455 - if (!property) { 456 - ret = -ENOENT; 457 - goto done; 458 - } 459 - 460 - if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || 461 - drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { 462 - list_for_each_entry(prop_enum, &property->enum_list, head) 463 - enum_count++; 464 - } 465 - 466 - value_count = property->num_values; 455 + if (!property) 456 + return -ENOENT; 467 457 468 458 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); 469 459 out_resp->name[DRM_PROP_NAME_LEN-1] = 0; 470 460 out_resp->flags = property->flags; 471 461 472 - if ((out_resp->count_values >= value_count) && value_count) { 473 - values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr; 474 - for (i = 0; i < value_count; i++) { 475 - if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { 476 - ret = -EFAULT; 477 - goto done; 478 - } 462 + value_count = property->num_values; 463 + values_ptr = u64_to_user_ptr(out_resp->values_ptr); 464 + 465 + for (i = 0; i < value_count; i++) { 466 + if (i < out_resp->count_values && 467 + put_user(property->values[i], values_ptr + i)) { 468 + return -EFAULT; 479 469 } 480 470 } 481 471 out_resp->count_values = value_count; 482 472 473 + copied = 0; 474 + enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr); 475 + 483 476 if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || 484 - drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { 485 - if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { 486 - copied = 0; 487 - enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; 488 - list_for_each_entry(prop_enum, &property->enum_list, head) { 477 + drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { 478 + list_for_each_entry(prop_enum, &property->enum_list, head) { 479 + enum_count++; 480 + if (out_resp->count_enum_blobs <= enum_count) 481 + continue; 489 482 490 - if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { 491 - ret = -EFAULT; 492 - goto done; 493 - } 483 + if (copy_to_user(&enum_ptr[copied].value, 484 + &prop_enum->value, sizeof(uint64_t))) 485 + return -EFAULT; 494 486 495 - if (copy_to_user(&enum_ptr[copied].name, 496 - &prop_enum->name, DRM_PROP_NAME_LEN)) { 497 - ret = -EFAULT; 498 - goto done; 499 - } 500 - copied++; 501 - } 487 + if (copy_to_user(&enum_ptr[copied].name, 488 + &prop_enum->name, DRM_PROP_NAME_LEN)) 489 + return -EFAULT; 490 + copied++; 502 491 } 503 492 out_resp->count_enum_blobs = enum_count; 504 493 } ··· 501 514 */ 502 515 if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) 503 516 out_resp->count_enum_blobs = 0; 504 - done: 505 - drm_modeset_unlock_all(dev); 506 - return ret; 517 + 518 + return 0; 507 519 } 508 520 509 521 static void drm_property_free_blob(struct kref *kref)
+27 -43
drivers/gpu/drm/drm_sysfs.c
··· 25 25 #define to_drm_minor(d) dev_get_drvdata(d) 26 26 #define to_drm_connector(d) dev_get_drvdata(d) 27 27 28 + /** 29 + * DOC: overview 30 + * 31 + * DRM provides very little additional support to drivers for sysfs 32 + * interactions, beyond just all the standard stuff. Drivers who want to expose 33 + * additional sysfs properties and property groups can attach them at either 34 + * &drm_device.dev or &drm_connector.kdev. 35 + * 36 + * Registration is automatically handled when calling drm_dev_register(), or 37 + * drm_connector_register() in case of hot-plugged connectors. Unregistration is 38 + * also automatically handled by drm_dev_unregister() and 39 + * drm_connector_unregister(). 40 + */ 41 + 28 42 static struct device_type drm_sysfs_device_minor = { 29 43 .name = "drm_minor" 30 44 }; ··· 264 250 NULL 265 251 }; 266 252 267 - /** 268 - * drm_sysfs_connector_add - add a connector to sysfs 269 - * @connector: connector to add 270 - * 271 - * Create a connector device in sysfs, along with its associated connector 272 - * properties (so far, connection status, dpms, mode list and edid) and 273 - * generate a hotplug event so userspace knows there's a new connector 274 - * available. 275 - */ 276 253 int drm_sysfs_connector_add(struct drm_connector *connector) 277 254 { 278 255 struct drm_device *dev = connector->dev; ··· 290 285 return 0; 291 286 } 292 287 293 - /** 294 - * drm_sysfs_connector_remove - remove an connector device from sysfs 295 - * @connector: connector to remove 296 - * 297 - * Remove @connector and its associated attributes from sysfs. Note that 298 - * the device model core will take care of sending the "remove" uevent 299 - * at this time, so we don't need to do it. 300 - * 301 - * Note: 302 - * This routine should only be called if the connector was previously 303 - * successfully registered. If @connector hasn't been registered yet, 304 - * you'll likely see a panic somewhere deep in sysfs code when called. 305 - */ 306 288 void drm_sysfs_connector_remove(struct drm_connector *connector) 307 289 { 308 290 if (!connector->kdev) ··· 325 333 kfree(dev); 326 334 } 327 335 328 - /** 329 - * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor 330 - * @minor: minor to allocate sysfs device for 331 - * 332 - * This allocates a new sysfs device for @minor and returns it. The device is 333 - * not registered nor linked. The caller has to use device_add() and 334 - * device_del() to register and unregister it. 335 - * 336 - * Note that dev_get_drvdata() on the new device will return the minor. 337 - * However, the device does not hold a ref-count to the minor nor to the 338 - * underlying drm_device. This is unproblematic as long as you access the 339 - * private data only in sysfs callbacks. device_del() disables those 340 - * synchronously, so they cannot be called after you cleanup a minor. 341 - */ 342 336 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor) 343 337 { 344 338 const char *minor_str; ··· 362 384 } 363 385 364 386 /** 365 - * drm_class_device_register - Register a struct device in the drm class. 387 + * drm_class_device_register - register new device with the DRM sysfs class 388 + * @dev: device to register 366 389 * 367 - * @dev: pointer to struct device to register. 368 - * 369 - * @dev should have all relevant members pre-filled with the exception 370 - * of the class member. In particular, the device_type member must 371 - * be set. 390 + * Registers a new &struct device within the DRM sysfs class. Essentially only 391 + * used by ttm to have a place for its global settings. Drivers should never use 392 + * this. 372 393 */ 373 - 374 394 int drm_class_device_register(struct device *dev) 375 395 { 376 396 if (!drm_class || IS_ERR(drm_class)) ··· 379 403 } 380 404 EXPORT_SYMBOL_GPL(drm_class_device_register); 381 405 406 + /** 407 + * drm_class_device_unregister - unregister device with the DRM sysfs class 408 + * @dev: device to unregister 409 + * 410 + * Unregisters a &struct device from the DRM sysfs class. Essentially only used 411 + * by ttm to have a place for its global settings. Drivers should never use 412 + * this. 413 + */ 382 414 void drm_class_device_unregister(struct device *dev) 383 415 { 384 416 return device_unregister(dev);
+12 -23
drivers/gpu/drm/exynos/exynos_dp.c
··· 23 23 #include <drm/drmP.h> 24 24 #include <drm/drm_crtc.h> 25 25 #include <drm/drm_crtc_helper.h> 26 + #include <drm/drm_of.h> 26 27 #include <drm/drm_panel.h> 27 28 28 29 #include <drm/bridge/analogix_dp.h> ··· 212 211 static int exynos_dp_probe(struct platform_device *pdev) 213 212 { 214 213 struct device *dev = &pdev->dev; 215 - struct device_node *np = NULL, *endpoint = NULL; 214 + struct device_node *np; 216 215 struct exynos_dp_device *dp; 216 + struct drm_panel *panel; 217 + struct drm_bridge *bridge; 218 + int ret; 217 219 218 220 dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), 219 221 GFP_KERNEL); ··· 240 236 goto out; 241 237 } 242 238 243 - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); 244 - if (endpoint) { 245 - np = of_graph_get_remote_port_parent(endpoint); 246 - if (np) { 247 - /* The remote port can be either a panel or a bridge */ 248 - dp->plat_data.panel = of_drm_find_panel(np); 249 - if (!dp->plat_data.panel) { 250 - dp->ptn_bridge = of_drm_find_bridge(np); 251 - if (!dp->ptn_bridge) { 252 - of_node_put(np); 253 - return -EPROBE_DEFER; 254 - } 255 - } 256 - of_node_put(np); 257 - } else { 258 - DRM_ERROR("no remote endpoint device node found.\n"); 259 - return -EINVAL; 260 - } 261 - } else { 262 - DRM_ERROR("no port endpoint subnode found.\n"); 263 - return -EINVAL; 264 - } 239 + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, &bridge); 240 + if (ret) 241 + return ret; 242 + 243 + /* The remote port can be either a panel or a bridge */ 244 + dp->plat_data.panel = panel; 245 + dp->ptn_bridge = bridge; 265 246 266 247 out: 267 248 return component_add(&pdev->dev, &exynos_dp_ops);
+1 -15
drivers/gpu/drm/exynos/exynos_drm_dpi.c
··· 163 163 FIMD_PORT_WRB, 164 164 }; 165 165 166 - static struct device_node *exynos_dpi_of_find_panel_node(struct device *dev) 167 - { 168 - struct device_node *np, *ep; 169 - 170 - ep = of_graph_get_endpoint_by_regs(dev->of_node, FIMD_PORT_RGB, 0); 171 - if (!ep) 172 - return NULL; 173 - 174 - np = of_graph_get_remote_port_parent(ep); 175 - of_node_put(ep); 176 - 177 - return np; 178 - } 179 - 180 166 static int exynos_dpi_parse_dt(struct exynos_dpi *ctx) 181 167 { 182 168 struct device *dev = ctx->dev; 183 169 struct device_node *dn = dev->of_node; 184 170 struct device_node *np; 185 171 186 - ctx->panel_node = exynos_dpi_of_find_panel_node(dev); 172 + ctx->panel_node = of_graph_get_remote_node(dn, FIMD_PORT_RGB, 0); 187 173 188 174 np = of_get_child_by_name(dn, "display-timings"); 189 175 if (np) {
+3 -10
drivers/gpu/drm/exynos/exynos_drm_dsi.c
··· 1659 1659 1660 1660 of_node_put(ep); 1661 1661 1662 - ep = of_graph_get_next_endpoint(node, NULL); 1663 - if (!ep) { 1664 - ret = -EINVAL; 1665 - goto end; 1666 - } 1662 + dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0); 1663 + if (!dsi->bridge_node) 1664 + return -EINVAL; 1667 1665 1668 - dsi->bridge_node = of_graph_get_remote_port_parent(ep); 1669 - if (!dsi->bridge_node) { 1670 - ret = -EINVAL; 1671 - goto end; 1672 - } 1673 1666 end: 1674 1667 of_node_put(ep); 1675 1668
+1 -24
drivers/gpu/drm/exynos/exynos_drm_mic.c
··· 229 229 writel(reg, mic->reg + MIC_OP); 230 230 } 231 231 232 - static struct device_node *get_remote_node(struct device_node *from, int reg) 233 - { 234 - struct device_node *endpoint = NULL, *remote_node = NULL; 235 - 236 - endpoint = of_graph_get_endpoint_by_regs(from, reg, -1); 237 - if (!endpoint) { 238 - DRM_ERROR("mic: Failed to find remote port from %s", 239 - from->full_name); 240 - goto exit; 241 - } 242 - 243 - remote_node = of_graph_get_remote_port_parent(endpoint); 244 - if (!remote_node) { 245 - DRM_ERROR("mic: Failed to find remote port parent from %s", 246 - from->full_name); 247 - goto exit; 248 - } 249 - 250 - exit: 251 - of_node_put(endpoint); 252 - return remote_node; 253 - } 254 - 255 232 static int parse_dt(struct exynos_mic *mic) 256 233 { 257 234 int ret = 0, i, j; ··· 240 263 * The first node must be for decon and the second one must be for dsi. 241 264 */ 242 265 for (i = 0, j = 0; i < NUM_ENDPOINTS; i++) { 243 - remote_node = get_remote_node(mic->dev->of_node, i); 266 + remote_node = of_graph_get_remote_node(mic->dev->of_node, i, 0); 244 267 if (!remote_node) { 245 268 ret = -EPIPE; 246 269 goto exit;
+12 -32
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
··· 15 15 #include <drm/drmP.h> 16 16 #include <drm/drm_atomic_helper.h> 17 17 #include <drm/drm_crtc_helper.h> 18 + #include <drm/drm_of.h> 18 19 #include <drm/drm_panel.h> 19 20 20 21 #include "fsl_dcu_drm_drv.h" ··· 142 141 return ret; 143 142 } 144 143 145 - static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev, 146 - const struct of_endpoint *ep) 147 - { 148 - struct drm_bridge *bridge; 149 - struct device_node *np; 150 - 151 - np = of_graph_get_remote_port_parent(ep->local_node); 152 - 153 - fsl_dev->connector.panel = of_drm_find_panel(np); 154 - if (fsl_dev->connector.panel) { 155 - of_node_put(np); 156 - return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); 157 - } 158 - 159 - bridge = of_drm_find_bridge(np); 160 - of_node_put(np); 161 - if (!bridge) 162 - return -ENODEV; 163 - 164 - return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL); 165 - } 166 - 167 144 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev) 168 145 { 169 - struct of_endpoint ep; 170 - struct device_node *ep_node, *panel_node; 146 + struct device_node *panel_node; 147 + struct drm_panel *panel; 148 + struct drm_bridge *bridge; 171 149 int ret; 172 150 173 151 /* This is for backward compatibility */ ··· 159 179 return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); 160 180 } 161 181 162 - ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL); 163 - if (!ep_node) 164 - return -ENODEV; 165 - 166 - ret = of_graph_parse_endpoint(ep_node, &ep); 167 - of_node_put(ep_node); 182 + ret = drm_of_find_panel_or_bridge(fsl_dev->np, 0, 0, &panel, &bridge); 168 183 if (ret) 169 - return -ENODEV; 184 + return ret; 170 185 171 - return fsl_dcu_attach_endpoint(fsl_dev, &ep); 186 + if (panel) { 187 + fsl_dev->connector.panel = panel; 188 + return fsl_dcu_attach_panel(fsl_dev, panel); 189 + } 190 + 191 + return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL); 172 192 }
+2 -1
drivers/gpu/drm/gma500/gma_display.c
··· 177 177 } 178 178 179 179 int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, 180 - u32 size) 180 + u32 size, 181 + struct drm_modeset_acquire_ctx *ctx) 181 182 { 182 183 struct gma_crtc *gma_crtc = to_gma_crtc(crtc); 183 184 int i;
+2 -1
drivers/gpu/drm/gma500/gma_display.h
··· 73 73 extern int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); 74 74 extern void gma_crtc_load_lut(struct drm_crtc *crtc); 75 75 extern int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 76 - u16 *blue, u32 size); 76 + u16 *blue, u32 size, 77 + struct drm_modeset_acquire_ctx *ctx); 77 78 extern void gma_crtc_dpms(struct drm_crtc *crtc, int mode); 78 79 extern void gma_crtc_prepare(struct drm_crtc *crtc); 79 80 extern void gma_crtc_commit(struct drm_crtc *crtc);
+4 -23
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
··· 17 17 18 18 #include <linux/clk.h> 19 19 #include <linux/component.h> 20 - #include <linux/of_graph.h> 21 20 22 21 #include <drm/drm_of.h> 23 22 #include <drm/drm_crtc_helper.h> ··· 753 754 { 754 755 struct dsi_hw_ctx *ctx = dsi->ctx; 755 756 struct device_node *np = pdev->dev.of_node; 756 - struct device_node *endpoint, *bridge_node; 757 - struct drm_bridge *bridge; 758 757 struct resource *res; 758 + int ret; 759 759 760 760 /* 761 761 * Get the endpoint node. In our case, dsi has one output port1 762 762 * to which the external HDMI bridge is connected. 763 763 */ 764 - endpoint = of_graph_get_endpoint_by_regs(np, 1, -1); 765 - if (!endpoint) { 766 - DRM_ERROR("no valid endpoint node\n"); 767 - return -ENODEV; 768 - } 769 - of_node_put(endpoint); 770 - 771 - bridge_node = of_graph_get_remote_port_parent(endpoint); 772 - if (!bridge_node) { 773 - DRM_ERROR("no valid bridge node\n"); 774 - return -ENODEV; 775 - } 776 - of_node_put(bridge_node); 777 - 778 - bridge = of_drm_find_bridge(bridge_node); 779 - if (!bridge) { 780 - DRM_INFO("wait for external HDMI bridge driver.\n"); 781 - return -EPROBE_DEFER; 782 - } 783 - dsi->bridge = bridge; 764 + ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge); 765 + if (ret) 766 + return ret; 784 767 785 768 ctx->pclk = devm_clk_get(&pdev->dev, "pclk"); 786 769 if (IS_ERR(ctx->pclk)) {
+1 -29
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
··· 230 230 .unbind = kirin_drm_unbind, 231 231 }; 232 232 233 - static struct device_node *kirin_get_remote_node(struct device_node *np) 234 - { 235 - struct device_node *endpoint, *remote; 236 - 237 - /* get the first endpoint, in our case only one remote node 238 - * is connected to display controller. 239 - */ 240 - endpoint = of_graph_get_next_endpoint(np, NULL); 241 - if (!endpoint) { 242 - DRM_ERROR("no valid endpoint node\n"); 243 - return ERR_PTR(-ENODEV); 244 - } 245 - 246 - remote = of_graph_get_remote_port_parent(endpoint); 247 - of_node_put(endpoint); 248 - if (!remote) { 249 - DRM_ERROR("no valid remote node\n"); 250 - return ERR_PTR(-ENODEV); 251 - } 252 - 253 - if (!of_device_is_available(remote)) { 254 - DRM_ERROR("not available for remote node\n"); 255 - return ERR_PTR(-ENODEV); 256 - } 257 - 258 - return remote; 259 - } 260 - 261 233 static int kirin_drm_platform_probe(struct platform_device *pdev) 262 234 { 263 235 struct device *dev = &pdev->dev; ··· 243 271 return -EINVAL; 244 272 } 245 273 246 - remote = kirin_get_remote_node(np); 274 + remote = of_graph_get_remote_node(np, 0, 0); 247 275 if (IS_ERR(remote)) 248 276 return PTR_ERR(remote); 249 277
+12 -13
drivers/gpu/drm/i915/intel_crt.c
··· 669 669 { } 670 670 }; 671 671 672 - static enum drm_connector_status 673 - intel_crt_detect(struct drm_connector *connector, bool force) 672 + static int 673 + intel_crt_detect(struct drm_connector *connector, 674 + struct drm_modeset_acquire_ctx *ctx, 675 + bool force) 674 676 { 675 677 struct drm_i915_private *dev_priv = to_i915(connector->dev); 676 678 struct intel_crt *crt = intel_attached_crt(connector); 677 679 struct intel_encoder *intel_encoder = &crt->base; 678 - enum drm_connector_status status; 680 + int status, ret; 679 681 struct intel_load_detect_pipe tmp; 680 - struct drm_modeset_acquire_ctx ctx; 681 682 682 683 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", 683 684 connector->base.id, connector->name, ··· 722 721 goto out; 723 722 } 724 723 725 - drm_modeset_acquire_init(&ctx, 0); 726 - 727 724 /* for pre-945g platforms use load detect */ 728 - if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { 725 + ret = intel_get_load_detect_pipe(connector, NULL, &tmp, ctx); 726 + if (ret > 0) { 729 727 if (intel_crt_detect_ddc(connector)) 730 728 status = connector_status_connected; 731 729 else if (INTEL_GEN(dev_priv) < 4) ··· 734 734 status = connector_status_disconnected; 735 735 else 736 736 status = connector_status_unknown; 737 - intel_release_load_detect_pipe(connector, &tmp, &ctx); 738 - } else 737 + intel_release_load_detect_pipe(connector, &tmp, ctx); 738 + } else if (ret == 0) 739 739 status = connector_status_unknown; 740 - 741 - drm_modeset_drop_locks(&ctx); 742 - drm_modeset_acquire_fini(&ctx); 740 + else if (ret < 0) 741 + status = ret; 743 742 744 743 out: 745 744 intel_display_power_put(dev_priv, intel_encoder->power_domain); ··· 810 811 811 812 static const struct drm_connector_funcs intel_crt_connector_funcs = { 812 813 .dpms = drm_atomic_helper_connector_dpms, 813 - .detect = intel_crt_detect, 814 814 .fill_modes = drm_helper_probe_single_connector_modes, 815 815 .late_register = intel_connector_register, 816 816 .early_unregister = intel_connector_unregister, ··· 821 823 }; 822 824 823 825 static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { 826 + .detect_ctx = intel_crt_detect, 824 827 .mode_valid = intel_crt_mode_valid, 825 828 .get_modes = intel_crt_get_modes, 826 829 };
+15 -70
drivers/gpu/drm/i915/intel_display.c
··· 3412 3412 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 3413 3413 } 3414 3414 3415 - /* Assume fb object is pinned & idle & fenced and just update base pointers */ 3416 - static int 3417 - intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, 3418 - int x, int y, enum mode_set_atomic state) 3419 - { 3420 - /* Support for kgdboc is disabled, this needs a major rework. */ 3421 - DRM_ERROR("legacy panic handler not supported any more.\n"); 3422 - 3423 - return -ENODEV; 3424 - } 3425 - 3426 3415 static void intel_complete_page_flips(struct drm_i915_private *dev_priv) 3427 3416 { 3428 3417 struct intel_crtc *crtc; ··· 9492 9503 return 0; 9493 9504 } 9494 9505 9495 - bool intel_get_load_detect_pipe(struct drm_connector *connector, 9496 - struct drm_display_mode *mode, 9497 - struct intel_load_detect_pipe *old, 9498 - struct drm_modeset_acquire_ctx *ctx) 9506 + int intel_get_load_detect_pipe(struct drm_connector *connector, 9507 + struct drm_display_mode *mode, 9508 + struct intel_load_detect_pipe *old, 9509 + struct drm_modeset_acquire_ctx *ctx) 9499 9510 { 9500 9511 struct intel_crtc *intel_crtc; 9501 9512 struct intel_encoder *intel_encoder = ··· 9518 9529 9519 9530 old->restore_state = NULL; 9520 9531 9521 - retry: 9522 - ret = drm_modeset_lock(&config->connection_mutex, ctx); 9523 - if (ret) 9524 - goto fail; 9532 + WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); 9525 9533 9526 9534 /* 9527 9535 * Algorithm gets a little messy: ··· 9668 9682 restore_state = NULL; 9669 9683 } 9670 9684 9671 - if (ret == -EDEADLK) { 9672 - drm_modeset_backoff(ctx); 9673 - goto retry; 9674 - } 9685 + if (ret == -EDEADLK) 9686 + return ret; 9675 9687 9676 9688 return false; 9677 9689 } ··· 10711 10727 state = drm_atomic_state_alloc(dev); 10712 10728 if (!state) 10713 10729 return -ENOMEM; 10714 - state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); 10730 + state->acquire_ctx = dev->mode_config.acquire_ctx; 10715 10731 10716 10732 retry: 10717 10733 plane_state = drm_atomic_get_plane_state(state, primary); ··· 11001 11017 } 11002 11018 11003 11019 static const struct drm_crtc_helper_funcs intel_helper_funcs = { 11004 - .mode_set_base_atomic = intel_pipe_set_base_atomic, 11005 11020 .atomic_begin = intel_begin_crtc_commit, 11006 11021 .atomic_flush = intel_finish_crtc_commit, 11007 11022 .atomic_check = intel_crtc_atomic_check, ··· 13073 13090 return; 13074 13091 } 13075 13092 13076 - state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); 13093 + state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; 13077 13094 13078 13095 retry: 13079 13096 crtc_state = drm_atomic_get_crtc_state(state, crtc); ··· 13096 13113 drm_atomic_state_put(state); 13097 13114 } 13098 13115 13099 - /* 13100 - * FIXME: Remove this once i915 is fully DRIVER_ATOMIC by calling 13101 - * drm_atomic_helper_legacy_gamma_set() directly. 13102 - */ 13103 - static int intel_atomic_legacy_gamma_set(struct drm_crtc *crtc, 13104 - u16 *red, u16 *green, u16 *blue, 13105 - uint32_t size) 13106 - { 13107 - struct drm_device *dev = crtc->dev; 13108 - struct drm_mode_config *config = &dev->mode_config; 13109 - struct drm_crtc_state *state; 13110 - int ret; 13111 - 13112 - ret = drm_atomic_helper_legacy_gamma_set(crtc, red, green, blue, size); 13113 - if (ret) 13114 - return ret; 13115 - 13116 - /* 13117 - * Make sure we update the legacy properties so this works when 13118 - * atomic is not enabled. 13119 - */ 13120 - 13121 - state = crtc->state; 13122 - 13123 - drm_object_property_set_value(&crtc->base, 13124 - config->degamma_lut_property, 13125 - (state->degamma_lut) ? 13126 - state->degamma_lut->base.id : 0); 13127 - 13128 - drm_object_property_set_value(&crtc->base, 13129 - config->ctm_property, 13130 - (state->ctm) ? 13131 - state->ctm->base.id : 0); 13132 - 13133 - drm_object_property_set_value(&crtc->base, 13134 - config->gamma_lut_property, 13135 - (state->gamma_lut) ? 13136 - state->gamma_lut->base.id : 0); 13137 - 13138 - return 0; 13139 - } 13140 - 13141 13116 static const struct drm_crtc_funcs intel_crtc_funcs = { 13142 - .gamma_set = intel_atomic_legacy_gamma_set, 13117 + .gamma_set = drm_atomic_helper_legacy_gamma_set, 13143 13118 .set_config = drm_atomic_helper_set_config, 13144 13119 .set_property = drm_atomic_helper_crtc_set_property, 13145 13120 .destroy = intel_crtc_destroy, ··· 15048 15107 struct drm_connector *crt = NULL; 15049 15108 struct intel_load_detect_pipe load_detect_temp; 15050 15109 struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx; 15110 + int ret; 15051 15111 15052 15112 /* We can't just switch on the pipe A, we need to set things up with a 15053 15113 * proper mode and output configuration. As a gross hack, enable pipe A ··· 15065 15123 if (!crt) 15066 15124 return; 15067 15125 15068 - if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx)) 15126 + ret = intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx); 15127 + WARN(ret < 0, "All modeset mutexes are locked, but intel_get_load_detect_pipe failed\n"); 15128 + 15129 + if (ret > 0) 15069 15130 intel_release_load_detect_pipe(crt, &load_detect_temp, ctx); 15070 15131 } 15071 15132
+9 -12
drivers/gpu/drm/i915/intel_dp.c
··· 4566 4566 intel_dp->has_audio = false; 4567 4567 } 4568 4568 4569 - static enum drm_connector_status 4569 + static int 4570 4570 intel_dp_long_pulse(struct intel_connector *intel_connector) 4571 4571 { 4572 4572 struct drm_connector *connector = &intel_connector->base; ··· 4576 4576 struct drm_device *dev = connector->dev; 4577 4577 enum drm_connector_status status; 4578 4578 u8 sink_irq_vector = 0; 4579 + 4580 + WARN_ON(!drm_modeset_is_locked(&connector->dev->mode_config.connection_mutex)); 4579 4581 4580 4582 intel_display_power_get(to_i915(dev), intel_dp->aux_power_domain); 4581 4583 ··· 4637 4635 status = connector_status_disconnected; 4638 4636 goto out; 4639 4637 } else if (connector->status == connector_status_connected) { 4640 - /* 4641 - * If display was connected already and is still connected 4642 - * check links status, there has been known issues of 4643 - * link loss triggerring long pulse!!!! 4644 - */ 4645 - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); 4646 4638 intel_dp_check_link_status(intel_dp); 4647 - drm_modeset_unlock(&dev->mode_config.connection_mutex); 4648 4639 goto out; 4649 4640 } 4650 4641 ··· 4677 4682 return status; 4678 4683 } 4679 4684 4680 - static enum drm_connector_status 4681 - intel_dp_detect(struct drm_connector *connector, bool force) 4685 + static int 4686 + intel_dp_detect(struct drm_connector *connector, 4687 + struct drm_modeset_acquire_ctx *ctx, 4688 + bool force) 4682 4689 { 4683 4690 struct intel_dp *intel_dp = intel_attached_dp(connector); 4684 - enum drm_connector_status status = connector->status; 4691 + int status = connector->status; 4685 4692 4686 4693 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 4687 4694 connector->base.id, connector->name); ··· 5011 5014 5012 5015 static const struct drm_connector_funcs intel_dp_connector_funcs = { 5013 5016 .dpms = drm_atomic_helper_connector_dpms, 5014 - .detect = intel_dp_detect, 5015 5017 .force = intel_dp_force, 5016 5018 .fill_modes = drm_helper_probe_single_connector_modes, 5017 5019 .set_property = intel_dp_set_property, ··· 5023 5027 }; 5024 5028 5025 5029 static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { 5030 + .detect_ctx = intel_dp_detect, 5026 5031 .get_modes = intel_dp_get_modes, 5027 5032 .mode_valid = intel_dp_mode_valid, 5028 5033 };
+4 -4
drivers/gpu/drm/i915/intel_drv.h
··· 1358 1358 void vlv_wait_port_ready(struct drm_i915_private *dev_priv, 1359 1359 struct intel_digital_port *dport, 1360 1360 unsigned int expected_mask); 1361 - bool intel_get_load_detect_pipe(struct drm_connector *connector, 1362 - struct drm_display_mode *mode, 1363 - struct intel_load_detect_pipe *old, 1364 - struct drm_modeset_acquire_ctx *ctx); 1361 + int intel_get_load_detect_pipe(struct drm_connector *connector, 1362 + struct drm_display_mode *mode, 1363 + struct intel_load_detect_pipe *old, 1364 + struct drm_modeset_acquire_ctx *ctx); 1365 1365 void intel_release_load_detect_pipe(struct drm_connector *connector, 1366 1366 struct intel_load_detect_pipe *old, 1367 1367 struct drm_modeset_acquire_ctx *ctx);
+2 -1
drivers/gpu/drm/i915/intel_hotplug.c
··· 243 243 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); 244 244 old_status = connector->status; 245 245 246 - connector->status = connector->funcs->detect(connector, false); 246 + connector->status = drm_helper_probe_detect(connector, NULL, false); 247 + 247 248 if (old_status == connector->status) 248 249 return false; 249 250
+1 -1
drivers/gpu/drm/i915/intel_pipe_crc.c
··· 522 522 goto unlock; 523 523 } 524 524 525 - state->acquire_ctx = drm_modeset_legacy_acquire_ctx(&crtc->base); 525 + state->acquire_ctx = crtc->base.dev->mode_config.acquire_ctx; 526 526 pipe_config = intel_atomic_get_crtc_state(state, crtc); 527 527 if (IS_ERR(pipe_config)) { 528 528 ret = PTR_ERR(pipe_config);
+11 -10
drivers/gpu/drm/i915/intel_tv.c
··· 1315 1315 * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure 1316 1316 * we have a pipe programmed in order to probe the TV. 1317 1317 */ 1318 - static enum drm_connector_status 1319 - intel_tv_detect(struct drm_connector *connector, bool force) 1318 + static int 1319 + intel_tv_detect(struct drm_connector *connector, 1320 + struct drm_modeset_acquire_ctx *ctx, 1321 + bool force) 1320 1322 { 1321 1323 struct drm_display_mode mode; 1322 1324 struct intel_tv *intel_tv = intel_attached_tv(connector); ··· 1333 1331 1334 1332 if (force) { 1335 1333 struct intel_load_detect_pipe tmp; 1336 - struct drm_modeset_acquire_ctx ctx; 1334 + int ret; 1337 1335 1338 - drm_modeset_acquire_init(&ctx, 0); 1336 + ret = intel_get_load_detect_pipe(connector, &mode, &tmp, ctx); 1337 + if (ret < 0) 1338 + return ret; 1339 1339 1340 - if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) { 1340 + if (ret > 0) { 1341 1341 type = intel_tv_detect_type(intel_tv, connector); 1342 - intel_release_load_detect_pipe(connector, &tmp, &ctx); 1342 + intel_release_load_detect_pipe(connector, &tmp, ctx); 1343 1343 status = type < 0 ? 1344 1344 connector_status_disconnected : 1345 1345 connector_status_connected; 1346 1346 } else 1347 1347 status = connector_status_unknown; 1348 - 1349 - drm_modeset_drop_locks(&ctx); 1350 - drm_modeset_acquire_fini(&ctx); 1351 1348 } else 1352 1349 return connector->status; 1353 1350 ··· 1517 1516 1518 1517 static const struct drm_connector_funcs intel_tv_connector_funcs = { 1519 1518 .dpms = drm_atomic_helper_connector_dpms, 1520 - .detect = intel_tv_detect, 1521 1519 .late_register = intel_connector_register, 1522 1520 .early_unregister = intel_connector_unregister, 1523 1521 .destroy = intel_tv_destroy, ··· 1528 1528 }; 1529 1529 1530 1530 static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = { 1531 + .detect_ctx = intel_tv_detect, 1531 1532 .mode_valid = intel_tv_mode_valid, 1532 1533 .get_modes = intel_tv_get_modes, 1533 1534 };
+5 -22
drivers/gpu/drm/imx/imx-ldb.c
··· 647 647 648 648 for_each_child_of_node(np, child) { 649 649 struct imx_ldb_channel *channel; 650 - struct device_node *ep; 651 650 int bus_format; 652 651 653 652 ret = of_property_read_u32(child, "reg", &i); ··· 670 671 * The output port is port@4 with an external 4-port mux or 671 672 * port@2 with the internal 2-port mux. 672 673 */ 673 - ep = of_graph_get_endpoint_by_regs(child, 674 - imx_ldb->lvds_mux ? 4 : 2, 675 - -1); 676 - if (ep) { 677 - struct device_node *remote; 678 - 679 - remote = of_graph_get_remote_port_parent(ep); 680 - of_node_put(ep); 681 - if (remote) { 682 - channel->panel = of_drm_find_panel(remote); 683 - channel->bridge = of_drm_find_bridge(remote); 684 - } else 685 - return -EPROBE_DEFER; 686 - of_node_put(remote); 687 - 688 - if (!channel->panel && !channel->bridge) { 689 - dev_err(dev, "panel/bridge not found: %s\n", 690 - remote->full_name); 691 - return -EPROBE_DEFER; 692 - } 693 - } 674 + ret = drm_of_find_panel_or_bridge(child, 675 + imx_ldb->lvds_mux ? 4 : 2, 0, 676 + &channel->panel, &channel->bridge); 677 + if (ret) 678 + return ret; 694 679 695 680 /* panel ddc only if there is no bridge */ 696 681 if (!channel->bridge) {
+4 -32
drivers/gpu/drm/imx/parallel-display.c
··· 19 19 #include <drm/drm_atomic_helper.h> 20 20 #include <drm/drm_fb_helper.h> 21 21 #include <drm/drm_crtc_helper.h> 22 + #include <drm/drm_of.h> 22 23 #include <drm/drm_panel.h> 23 24 #include <linux/videodev2.h> 24 25 #include <video/of_display_timing.h> 25 - #include <linux/of_graph.h> 26 26 27 27 #include "imx-drm.h" 28 28 ··· 208 208 { 209 209 struct drm_device *drm = data; 210 210 struct device_node *np = dev->of_node; 211 - struct device_node *ep; 212 211 const u8 *edidp; 213 212 struct imx_parallel_display *imxpd; 214 213 int ret; ··· 236 237 imxpd->bus_format = bus_format; 237 238 238 239 /* port@1 is the output port */ 239 - ep = of_graph_get_endpoint_by_regs(np, 1, -1); 240 - if (ep) { 241 - struct device_node *remote; 242 - 243 - remote = of_graph_get_remote_port_parent(ep); 244 - if (!remote) { 245 - dev_warn(dev, "endpoint %s not connected\n", 246 - ep->full_name); 247 - of_node_put(ep); 248 - return -ENODEV; 249 - } 250 - of_node_put(ep); 251 - 252 - imxpd->panel = of_drm_find_panel(remote); 253 - if (imxpd->panel) { 254 - dev_dbg(dev, "found panel %s\n", remote->full_name); 255 - } else { 256 - imxpd->bridge = of_drm_find_bridge(remote); 257 - if (imxpd->bridge) 258 - dev_dbg(dev, "found bridge %s\n", 259 - remote->full_name); 260 - } 261 - if (!imxpd->panel && !imxpd->bridge) { 262 - dev_dbg(dev, "waiting for panel or bridge %s\n", 263 - remote->full_name); 264 - of_node_put(remote); 265 - return -EPROBE_DEFER; 266 - } 267 - of_node_put(remote); 268 - } 240 + ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel, &imxpd->bridge); 241 + if (ret) 242 + return ret; 269 243 270 244 imxpd->dev = dev; 271 245
+3 -9
drivers/gpu/drm/mediatek/mtk_dpi.c
··· 661 661 struct device *dev = &pdev->dev; 662 662 struct mtk_dpi *dpi; 663 663 struct resource *mem; 664 - struct device_node *ep, *bridge_node = NULL; 664 + struct device_node *bridge_node; 665 665 int comp_id; 666 666 int ret; 667 667 ··· 706 706 return -EINVAL; 707 707 } 708 708 709 - ep = of_graph_get_next_endpoint(dev->of_node, NULL); 710 - if (ep) { 711 - bridge_node = of_graph_get_remote_port_parent(ep); 712 - of_node_put(ep); 713 - } 714 - if (!bridge_node) { 715 - dev_err(dev, "Failed to find bridge node\n"); 709 + bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0); 710 + if (!bridge_node) 716 711 return -ENODEV; 717 - } 718 712 719 713 dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name); 720 714
+5 -18
drivers/gpu/drm/mediatek/mtk_dsi.c
··· 16 16 #include <drm/drm_crtc_helper.h> 17 17 #include <drm/drm_mipi_dsi.h> 18 18 #include <drm/drm_panel.h> 19 + #include <drm/drm_of.h> 19 20 #include <linux/clk.h> 20 21 #include <linux/component.h> 21 22 #include <linux/irq.h> 22 23 #include <linux/of.h> 23 24 #include <linux/of_platform.h> 24 - #include <linux/of_graph.h> 25 25 #include <linux/phy/phy.h> 26 26 #include <linux/platform_device.h> 27 27 #include <video/mipi_display.h> ··· 1097 1097 { 1098 1098 struct mtk_dsi *dsi; 1099 1099 struct device *dev = &pdev->dev; 1100 - struct device_node *remote_node, *endpoint; 1101 1100 struct resource *regs; 1102 1101 int irq_num; 1103 1102 int comp_id; ··· 1109 1110 dsi->host.ops = &mtk_dsi_ops; 1110 1111 dsi->host.dev = dev; 1111 1112 1112 - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); 1113 - if (endpoint) { 1114 - remote_node = of_graph_get_remote_port_parent(endpoint); 1115 - if (!remote_node) { 1116 - dev_err(dev, "No panel connected\n"); 1117 - return -ENODEV; 1118 - } 1119 - 1120 - dsi->bridge = of_drm_find_bridge(remote_node); 1121 - dsi->panel = of_drm_find_panel(remote_node); 1122 - of_node_put(remote_node); 1123 - if (!dsi->bridge && !dsi->panel) { 1124 - dev_info(dev, "Waiting for bridge or panel driver\n"); 1125 - return -EPROBE_DEFER; 1126 - } 1127 - } 1113 + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, 1114 + &dsi->panel, &dsi->bridge); 1115 + if (ret) 1116 + return ret; 1128 1117 1129 1118 dsi->engine_clk = devm_clk_get(dev, "engine"); 1130 1119 if (IS_ERR(dsi->engine_clk)) {
+3 -23
drivers/gpu/drm/mediatek/mtk_hdmi.c
··· 1434 1434 { 1435 1435 struct device *dev = &pdev->dev; 1436 1436 struct device_node *np = dev->of_node; 1437 - struct device_node *cec_np, *port, *ep, *remote, *i2c_np; 1437 + struct device_node *cec_np, *remote, *i2c_np; 1438 1438 struct platform_device *cec_pdev; 1439 1439 struct regmap *regmap; 1440 1440 struct resource *mem; ··· 1486 1486 if (IS_ERR(hdmi->regs)) 1487 1487 return PTR_ERR(hdmi->regs); 1488 1488 1489 - port = of_graph_get_port_by_id(np, 1); 1490 - if (!port) { 1491 - dev_err(dev, "Missing output port node\n"); 1489 + remote = of_graph_get_remote_node(np, 1, 0); 1490 + if (!remote) 1492 1491 return -EINVAL; 1493 - } 1494 - 1495 - ep = of_get_child_by_name(port, "endpoint"); 1496 - if (!ep) { 1497 - dev_err(dev, "Missing endpoint node in port %s\n", 1498 - port->full_name); 1499 - of_node_put(port); 1500 - return -EINVAL; 1501 - } 1502 - of_node_put(port); 1503 - 1504 - remote = of_graph_get_remote_port_parent(ep); 1505 - if (!remote) { 1506 - dev_err(dev, "Missing connector/bridge node for endpoint %s\n", 1507 - ep->full_name); 1508 - of_node_put(ep); 1509 - return -EINVAL; 1510 - } 1511 - of_node_put(ep); 1512 1492 1513 1493 if (!of_device_is_compatible(remote, "hdmi-connector")) { 1514 1494 hdmi->next_bridge = of_drm_find_bridge(remote);
+6
drivers/gpu/drm/meson/Kconfig
··· 7 7 select DRM_GEM_CMA_HELPER 8 8 select VIDEOMODE_HELPERS 9 9 select REGMAP_MMIO 10 + 11 + config DRM_MESON_DW_HDMI 12 + tristate "HDMI Synopsys Controller support for Amlogic Meson Display" 13 + depends on DRM_MESON 14 + default y if DRM_MESON 15 + select DRM_DW_HDMI
+1
drivers/gpu/drm/meson/Makefile
··· 2 2 meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o 3 3 4 4 obj-$(CONFIG_DRM_MESON) += meson-drm.o 5 + obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o
+3 -1
drivers/gpu/drm/meson/meson_canvas.c
··· 24 24 #include "meson_canvas.h" 25 25 #include "meson_registers.h" 26 26 27 - /* 27 + /** 28 + * DOC: Canvas 29 + * 28 30 * CANVAS is a memory zone where physical memory frames information 29 31 * are stored for the VIU to scanout. 30 32 */
+11 -4
drivers/gpu/drm/meson/meson_crtc.c
··· 82 82 static void meson_crtc_enable(struct drm_crtc *crtc) 83 83 { 84 84 struct meson_crtc *meson_crtc = to_meson_crtc(crtc); 85 - struct drm_plane *plane = meson_crtc->priv->primary_plane; 85 + struct drm_crtc_state *crtc_state = crtc->state; 86 86 struct meson_drm *priv = meson_crtc->priv; 87 87 88 + DRM_DEBUG_DRIVER("\n"); 89 + 90 + if (!crtc_state) { 91 + DRM_ERROR("Invalid crtc_state\n"); 92 + return; 93 + } 94 + 88 95 /* Enable VPP Postblend */ 89 - writel(plane->state->crtc_w, 96 + writel(crtc_state->mode.hdisplay, 90 97 priv->io_base + _REG(VPP_POSTBLEND_H_SIZE)); 91 98 92 99 writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE, ··· 108 101 struct meson_drm *priv = meson_crtc->priv; 109 102 110 103 priv->viu.osd1_enabled = false; 104 + priv->viu.osd1_commit = false; 111 105 112 106 /* Disable VPP Postblend */ 113 107 writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0, ··· 145 137 struct meson_crtc *meson_crtc = to_meson_crtc(crtc); 146 138 struct meson_drm *priv = meson_crtc->priv; 147 139 148 - if (priv->viu.osd1_enabled) 149 - priv->viu.osd1_commit = true; 140 + priv->viu.osd1_commit = true; 150 141 } 151 142 152 143 static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
+102 -16
drivers/gpu/drm/meson/meson_drv.c
··· 24 24 #include <linux/module.h> 25 25 #include <linux/mutex.h> 26 26 #include <linux/platform_device.h> 27 + #include <linux/component.h> 27 28 #include <linux/of_graph.h> 28 29 29 30 #include <drm/drmP.h> ··· 52 51 #define DRIVER_NAME "meson" 53 52 #define DRIVER_DESC "Amlogic Meson DRM driver" 54 53 55 - /* 56 - * Video Processing Unit 54 + /** 55 + * DOC: Video Processing Unit 57 56 * 58 57 * VPU Handles the Global Video Processing, it includes management of the 59 58 * clocks gates, blocks reset lines and power domains. 60 59 * 61 60 * What is missing : 61 + * 62 62 * - Full reset of entire video processing HW blocks 63 63 * - Scaling and setup of the VPU clock 64 64 * - Bus clock gates ··· 152 150 .max_register = 0x1000, 153 151 }; 154 152 155 - static int meson_drv_probe(struct platform_device *pdev) 153 + static int meson_drv_bind(struct device *dev) 156 154 { 157 - struct device *dev = &pdev->dev; 155 + struct platform_device *pdev = to_platform_device(dev); 158 156 struct meson_drm *priv; 159 157 struct drm_device *drm; 160 158 struct resource *res; ··· 217 215 218 216 drm_vblank_init(drm, 1); 219 217 drm_mode_config_init(drm); 218 + drm->mode_config.max_width = 3840; 219 + drm->mode_config.max_height = 2160; 220 + drm->mode_config.funcs = &meson_mode_config_funcs; 221 + 222 + /* Hardware Initialization */ 223 + 224 + meson_venc_init(priv); 225 + meson_vpp_init(priv); 226 + meson_viu_init(priv); 220 227 221 228 /* Encoder Initialization */ 222 229 ··· 233 222 if (ret) 234 223 goto free_drm; 235 224 236 - /* Hardware Initialization */ 237 - 238 - meson_venc_init(priv); 239 - meson_vpp_init(priv); 240 - meson_viu_init(priv); 225 + ret = component_bind_all(drm->dev, drm); 226 + if (ret) { 227 + dev_err(drm->dev, "Couldn't bind all components\n"); 228 + goto free_drm; 229 + } 241 230 242 231 ret = meson_plane_create(priv); 243 232 if (ret) ··· 252 241 goto free_drm; 253 242 254 243 drm_mode_config_reset(drm); 255 - drm->mode_config.max_width = 8192; 256 - drm->mode_config.max_height = 8192; 257 - drm->mode_config.funcs = &meson_mode_config_funcs; 258 244 259 245 priv->fbdev = drm_fbdev_cma_init(drm, 32, 260 246 drm->mode_config.num_connector); ··· 276 268 return ret; 277 269 } 278 270 279 - static int meson_drv_remove(struct platform_device *pdev) 271 + static void meson_drv_unbind(struct device *dev) 280 272 { 281 - struct drm_device *drm = dev_get_drvdata(&pdev->dev); 273 + struct drm_device *drm = dev_get_drvdata(dev); 282 274 struct meson_drm *priv = drm->dev_private; 283 275 284 276 drm_dev_unregister(drm); ··· 288 280 drm_vblank_cleanup(drm); 289 281 drm_dev_unref(drm); 290 282 291 - return 0; 292 283 } 284 + 285 + static const struct component_master_ops meson_drv_master_ops = { 286 + .bind = meson_drv_bind, 287 + .unbind = meson_drv_unbind, 288 + }; 289 + 290 + static int compare_of(struct device *dev, void *data) 291 + { 292 + DRM_DEBUG_DRIVER("Comparing of node %s with %s\n", 293 + of_node_full_name(dev->of_node), 294 + of_node_full_name(data)); 295 + 296 + return dev->of_node == data; 297 + } 298 + 299 + /* Possible connectors nodes to ignore */ 300 + static const struct of_device_id connectors_match[] = { 301 + { .compatible = "composite-video-connector" }, 302 + { .compatible = "svideo-connector" }, 303 + { .compatible = "hdmi-connector" }, 304 + { .compatible = "dvi-connector" }, 305 + {} 306 + }; 307 + 308 + static int meson_probe_remote(struct platform_device *pdev, 309 + struct component_match **match, 310 + struct device_node *parent, 311 + struct device_node *remote) 312 + { 313 + struct device_node *ep, *remote_node; 314 + int count = 1; 315 + 316 + /* If node is a connector, return and do not add to match table */ 317 + if (of_match_node(connectors_match, remote)) 318 + return 1; 319 + 320 + component_match_add(&pdev->dev, match, compare_of, remote); 321 + 322 + for_each_endpoint_of_node(remote, ep) { 323 + remote_node = of_graph_get_remote_port_parent(ep); 324 + if (!remote_node || 325 + remote_node == parent || /* Ignore parent endpoint */ 326 + !of_device_is_available(remote_node)) 327 + continue; 328 + 329 + count += meson_probe_remote(pdev, match, remote, remote_node); 330 + 331 + of_node_put(remote_node); 332 + } 333 + 334 + return count; 335 + } 336 + 337 + static int meson_drv_probe(struct platform_device *pdev) 338 + { 339 + struct component_match *match = NULL; 340 + struct device_node *np = pdev->dev.of_node; 341 + struct device_node *ep, *remote; 342 + int count = 0; 343 + 344 + for_each_endpoint_of_node(np, ep) { 345 + remote = of_graph_get_remote_port_parent(ep); 346 + if (!remote || !of_device_is_available(remote)) 347 + continue; 348 + 349 + count += meson_probe_remote(pdev, &match, np, remote); 350 + } 351 + 352 + /* If some endpoints were found, initialize the nodes */ 353 + if (count) { 354 + dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count); 355 + 356 + return component_master_add_with_match(&pdev->dev, 357 + &meson_drv_master_ops, 358 + match); 359 + } 360 + 361 + /* If no output endpoints were available, simply bail out */ 362 + return 0; 363 + }; 293 364 294 365 static const struct of_device_id dt_match[] = { 295 366 { .compatible = "amlogic,meson-gxbb-vpu" }, ··· 380 293 381 294 static struct platform_driver meson_drm_platform_driver = { 382 295 .probe = meson_drv_probe, 383 - .remove = meson_drv_remove, 384 296 .driver = { 385 297 .name = "meson-drm", 386 298 .of_match_table = dt_match,
+3
drivers/gpu/drm/meson/meson_drv.h
··· 47 47 48 48 struct { 49 49 unsigned int current_mode; 50 + bool hdmi_repeat; 51 + bool venc_repeat; 52 + bool hdmi_use_enci; 50 53 } venc; 51 54 }; 52 55
+919
drivers/gpu/drm/meson/meson_dw_hdmi.c
··· 1 + /* 2 + * Copyright (C) 2016 BayLibre, SAS 3 + * Author: Neil Armstrong <narmstrong@baylibre.com> 4 + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License as 8 + * published by the Free Software Foundation; either version 2 of the 9 + * License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, but 12 + * WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include <linux/kernel.h> 21 + #include <linux/module.h> 22 + #include <linux/component.h> 23 + #include <linux/of_graph.h> 24 + #include <linux/reset.h> 25 + #include <linux/clk.h> 26 + 27 + #include <drm/drmP.h> 28 + #include <drm/drm_edid.h> 29 + #include <drm/drm_crtc_helper.h> 30 + #include <drm/drm_atomic_helper.h> 31 + #include <drm/bridge/dw_hdmi.h> 32 + 33 + #include <uapi/linux/media-bus-format.h> 34 + #include <uapi/linux/videodev2.h> 35 + 36 + #include "meson_drv.h" 37 + #include "meson_venc.h" 38 + #include "meson_vclk.h" 39 + #include "meson_dw_hdmi.h" 40 + #include "meson_registers.h" 41 + 42 + #define DRIVER_NAME "meson-dw-hdmi" 43 + #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver" 44 + 45 + /** 46 + * DOC: HDMI Output 47 + * 48 + * HDMI Output is composed of : 49 + * 50 + * - A Synopsys DesignWare HDMI Controller IP 51 + * - A TOP control block controlling the Clocks and PHY 52 + * - A custom HDMI PHY in order convert video to TMDS signal 53 + * 54 + * .. code:: 55 + * 56 + * ___________________________________ 57 + * | HDMI TOP |<= HPD 58 + * |___________________________________| 59 + * | | | 60 + * | Synopsys HDMI | HDMI PHY |=> TMDS 61 + * | Controller |________________| 62 + * |___________________________________|<=> DDC 63 + * 64 + * 65 + * The HDMI TOP block only supports HPD sensing. 66 + * The Synopsys HDMI Controller interrupt is routed 67 + * through the TOP Block interrupt. 68 + * Communication to the TOP Block and the Synopsys 69 + * HDMI Controller is done a pair of addr+read/write 70 + * registers. 71 + * The HDMI PHY is configured by registers in the 72 + * HHI register block. 73 + * 74 + * Pixel data arrives in 4:4:4 format from the VENC 75 + * block and the VPU HDMI mux selects either the ENCI 76 + * encoder for the 576i or 480i formats or the ENCP 77 + * encoder for all the other formats including 78 + * interlaced HD formats. 79 + * The VENC uses a DVI encoder on top of the ENCI 80 + * or ENCP encoders to generate DVI timings for the 81 + * HDMI controller. 82 + * 83 + * GXBB, GXL and GXM embeds the Synopsys DesignWare 84 + * HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF 85 + * audio source interfaces. 86 + * 87 + * We handle the following features : 88 + * 89 + * - HPD Rise & Fall interrupt 90 + * - HDMI Controller Interrupt 91 + * - HDMI PHY Init for 480i to 1080p60 92 + * - VENC & HDMI Clock setup for 480i to 1080p60 93 + * - VENC Mode setup for 480i to 1080p60 94 + * 95 + * What is missing : 96 + * 97 + * - PHY, Clock and Mode setup for 2k && 4k modes 98 + * - SDDC Scrambling mode for HDMI 2.0a 99 + * - HDCP Setup 100 + * - CEC Management 101 + */ 102 + 103 + /* TOP Block Communication Channel */ 104 + #define HDMITX_TOP_ADDR_REG 0x0 105 + #define HDMITX_TOP_DATA_REG 0x4 106 + #define HDMITX_TOP_CTRL_REG 0x8 107 + 108 + /* Controller Communication Channel */ 109 + #define HDMITX_DWC_ADDR_REG 0x10 110 + #define HDMITX_DWC_DATA_REG 0x14 111 + #define HDMITX_DWC_CTRL_REG 0x18 112 + 113 + /* HHI Registers */ 114 + #define HHI_MEM_PD_REG0 0x100 /* 0x40 */ 115 + #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 */ 116 + #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 */ 117 + #define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */ 118 + #define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */ 119 + #define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */ 120 + 121 + static DEFINE_SPINLOCK(reg_lock); 122 + 123 + enum meson_venc_source { 124 + MESON_VENC_SOURCE_NONE = 0, 125 + MESON_VENC_SOURCE_ENCI = 1, 126 + MESON_VENC_SOURCE_ENCP = 2, 127 + }; 128 + 129 + struct meson_dw_hdmi { 130 + struct drm_encoder encoder; 131 + struct dw_hdmi_plat_data dw_plat_data; 132 + struct meson_drm *priv; 133 + struct device *dev; 134 + void __iomem *hdmitx; 135 + struct reset_control *hdmitx_apb; 136 + struct reset_control *hdmitx_ctrl; 137 + struct reset_control *hdmitx_phy; 138 + struct clk *hdmi_pclk; 139 + struct clk *venci_clk; 140 + u32 irq_stat; 141 + }; 142 + #define encoder_to_meson_dw_hdmi(x) \ 143 + container_of(x, struct meson_dw_hdmi, encoder) 144 + 145 + static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi, 146 + const char *compat) 147 + { 148 + return of_device_is_compatible(dw_hdmi->dev->of_node, compat); 149 + } 150 + 151 + /* PHY (via TOP bridge) and Controller dedicated register interface */ 152 + 153 + static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi, 154 + unsigned int addr) 155 + { 156 + unsigned long flags; 157 + unsigned int data; 158 + 159 + spin_lock_irqsave(&reg_lock, flags); 160 + 161 + /* ADDR must be written twice */ 162 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 163 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 164 + 165 + /* Read needs a second DATA read */ 166 + data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG); 167 + data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG); 168 + 169 + spin_unlock_irqrestore(&reg_lock, flags); 170 + 171 + return data; 172 + } 173 + 174 + static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi, 175 + unsigned int addr, unsigned int data) 176 + { 177 + unsigned long flags; 178 + 179 + spin_lock_irqsave(&reg_lock, flags); 180 + 181 + /* ADDR must be written twice */ 182 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 183 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 184 + 185 + /* Write needs single DATA write */ 186 + writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG); 187 + 188 + spin_unlock_irqrestore(&reg_lock, flags); 189 + } 190 + 191 + /* Helper to change specific bits in PHY registers */ 192 + static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi, 193 + unsigned int addr, 194 + unsigned int mask, 195 + unsigned int val) 196 + { 197 + unsigned int data = dw_hdmi_top_read(dw_hdmi, addr); 198 + 199 + data &= ~mask; 200 + data |= val; 201 + 202 + dw_hdmi_top_write(dw_hdmi, addr, data); 203 + } 204 + 205 + static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi, 206 + unsigned int addr) 207 + { 208 + unsigned long flags; 209 + unsigned int data; 210 + 211 + spin_lock_irqsave(&reg_lock, flags); 212 + 213 + /* ADDR must be written twice */ 214 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 215 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 216 + 217 + /* Read needs a second DATA read */ 218 + data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG); 219 + data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG); 220 + 221 + spin_unlock_irqrestore(&reg_lock, flags); 222 + 223 + return data; 224 + } 225 + 226 + static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi, 227 + unsigned int addr, unsigned int data) 228 + { 229 + unsigned long flags; 230 + 231 + spin_lock_irqsave(&reg_lock, flags); 232 + 233 + /* ADDR must be written twice */ 234 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 235 + writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 236 + 237 + /* Write needs single DATA write */ 238 + writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG); 239 + 240 + spin_unlock_irqrestore(&reg_lock, flags); 241 + } 242 + 243 + /* Helper to change specific bits in controller registers */ 244 + static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi, 245 + unsigned int addr, 246 + unsigned int mask, 247 + unsigned int val) 248 + { 249 + unsigned int data = dw_hdmi_dwc_read(dw_hdmi, addr); 250 + 251 + data &= ~mask; 252 + data |= val; 253 + 254 + dw_hdmi_dwc_write(dw_hdmi, addr, data); 255 + } 256 + 257 + /* Bridge */ 258 + 259 + /* Setup PHY bandwidth modes */ 260 + static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi, 261 + struct drm_display_mode *mode) 262 + { 263 + struct meson_drm *priv = dw_hdmi->priv; 264 + unsigned int pixel_clock = mode->clock; 265 + 266 + if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || 267 + dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) { 268 + if (pixel_clock >= 371250) { 269 + /* 5.94Gbps, 3.7125Gbps */ 270 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282); 271 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b); 272 + } else if (pixel_clock >= 297000) { 273 + /* 2.97Gbps */ 274 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382); 275 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b); 276 + } else if (pixel_clock >= 148500) { 277 + /* 1.485Gbps */ 278 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362); 279 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b); 280 + } else { 281 + /* 742.5Mbps, and below */ 282 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142); 283 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b); 284 + } 285 + } else if (dw_hdmi_is_compatible(dw_hdmi, 286 + "amlogic,meson-gxbb-dw-hdmi")) { 287 + if (pixel_clock >= 371250) { 288 + /* 5.94Gbps, 3.7125Gbps */ 289 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245); 290 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b); 291 + } else if (pixel_clock >= 297000) { 292 + /* 2.97Gbps */ 293 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283); 294 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b); 295 + } else { 296 + /* 1.485Gbps, and below */ 297 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122); 298 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b); 299 + } 300 + } 301 + } 302 + 303 + static inline void dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi) 304 + { 305 + struct meson_drm *priv = dw_hdmi->priv; 306 + 307 + /* Enable and software reset */ 308 + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf); 309 + 310 + mdelay(2); 311 + 312 + /* Enable and unreset */ 313 + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe); 314 + 315 + mdelay(2); 316 + } 317 + 318 + static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi, 319 + struct drm_display_mode *mode) 320 + { 321 + struct meson_drm *priv = dw_hdmi->priv; 322 + int vic = drm_match_cea_mode(mode); 323 + unsigned int vclk_freq; 324 + unsigned int venc_freq; 325 + unsigned int hdmi_freq; 326 + 327 + vclk_freq = mode->clock; 328 + 329 + if (mode->flags & DRM_MODE_FLAG_DBLCLK) 330 + vclk_freq *= 2; 331 + 332 + venc_freq = vclk_freq; 333 + hdmi_freq = vclk_freq; 334 + 335 + if (meson_venc_hdmi_venc_repeat(vic)) 336 + venc_freq *= 2; 337 + 338 + vclk_freq = max(venc_freq, hdmi_freq); 339 + 340 + if (mode->flags & DRM_MODE_FLAG_DBLCLK) 341 + venc_freq /= 2; 342 + 343 + DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n", 344 + vclk_freq, venc_freq, hdmi_freq, 345 + priv->venc.hdmi_use_enci); 346 + 347 + meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq, 348 + venc_freq, hdmi_freq, priv->venc.hdmi_use_enci); 349 + } 350 + 351 + static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, 352 + struct drm_display_mode *mode) 353 + { 354 + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 355 + struct meson_drm *priv = dw_hdmi->priv; 356 + unsigned int wr_clk = 357 + readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING)); 358 + 359 + DRM_DEBUG_DRIVER("%d:\"%s\"\n", mode->base.id, mode->name); 360 + 361 + /* Enable clocks */ 362 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100); 363 + 364 + /* Bring HDMITX MEM output of power down */ 365 + regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0); 366 + 367 + /* Bring out of reset */ 368 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0); 369 + 370 + /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */ 371 + dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, 372 + 0x3, 0x3); 373 + dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, 374 + 0x3 << 4, 0x3 << 4); 375 + 376 + /* Enable normal output to PHY */ 377 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12)); 378 + 379 + /* TMDS pattern setup (TOFIX pattern for 4k2k scrambling) */ 380 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0x001f001f); 381 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 0x001f001f); 382 + 383 + /* Load TMDS pattern */ 384 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1); 385 + msleep(20); 386 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2); 387 + 388 + /* Setup PHY parameters */ 389 + meson_hdmi_phy_setup_mode(dw_hdmi, mode); 390 + 391 + /* Setup PHY */ 392 + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 393 + 0xffff << 16, 0x0390 << 16); 394 + 395 + /* BIT_INVERT */ 396 + if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || 397 + dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) 398 + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 399 + BIT(17), 0); 400 + else 401 + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 402 + BIT(17), BIT(17)); 403 + 404 + /* Disable clock, fifo, fifo_wr */ 405 + regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0); 406 + 407 + msleep(100); 408 + 409 + /* Reset PHY 3 times in a row */ 410 + dw_hdmi_phy_reset(dw_hdmi); 411 + dw_hdmi_phy_reset(dw_hdmi); 412 + dw_hdmi_phy_reset(dw_hdmi); 413 + 414 + /* Temporary Disable VENC video stream */ 415 + if (priv->venc.hdmi_use_enci) 416 + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); 417 + else 418 + writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); 419 + 420 + /* Temporary Disable HDMI video stream to HDMI-TX */ 421 + writel_bits_relaxed(0x3, 0, 422 + priv->io_base + _REG(VPU_HDMI_SETTING)); 423 + writel_bits_relaxed(0xf << 8, 0, 424 + priv->io_base + _REG(VPU_HDMI_SETTING)); 425 + 426 + /* Re-Enable VENC video stream */ 427 + if (priv->venc.hdmi_use_enci) 428 + writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); 429 + else 430 + writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); 431 + 432 + /* Push back HDMI clock settings */ 433 + writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8), 434 + priv->io_base + _REG(VPU_HDMI_SETTING)); 435 + 436 + /* Enable and Select HDMI video source for HDMI-TX */ 437 + if (priv->venc.hdmi_use_enci) 438 + writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI, 439 + priv->io_base + _REG(VPU_HDMI_SETTING)); 440 + else 441 + writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP, 442 + priv->io_base + _REG(VPU_HDMI_SETTING)); 443 + 444 + return 0; 445 + } 446 + 447 + static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, 448 + void *data) 449 + { 450 + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 451 + struct meson_drm *priv = dw_hdmi->priv; 452 + 453 + DRM_DEBUG_DRIVER("\n"); 454 + 455 + regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0); 456 + } 457 + 458 + static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi, 459 + void *data) 460 + { 461 + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 462 + 463 + return !!dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_STAT0) ? 464 + connector_status_connected : connector_status_disconnected; 465 + } 466 + 467 + static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi, 468 + void *data) 469 + { 470 + struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 471 + 472 + /* Setup HPD Filter */ 473 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER, 474 + (0xa << 12) | 0xa0); 475 + 476 + /* Clear interrupts */ 477 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, 478 + HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL); 479 + 480 + /* Unmask interrupts */ 481 + dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN, 482 + HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL, 483 + HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL); 484 + } 485 + 486 + static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = { 487 + .init = dw_hdmi_phy_init, 488 + .disable = dw_hdmi_phy_disable, 489 + .read_hpd = dw_hdmi_read_hpd, 490 + .setup_hpd = dw_hdmi_setup_hpd, 491 + }; 492 + 493 + static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id) 494 + { 495 + struct meson_dw_hdmi *dw_hdmi = dev_id; 496 + u32 stat; 497 + 498 + stat = dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_INTR_STAT); 499 + dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat); 500 + 501 + /* HPD Events, handle in the threaded interrupt handler */ 502 + if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) { 503 + dw_hdmi->irq_stat = stat; 504 + return IRQ_WAKE_THREAD; 505 + } 506 + 507 + /* HDMI Controller Interrupt */ 508 + if (stat & 1) 509 + return IRQ_NONE; 510 + 511 + /* TOFIX Handle HDCP Interrupts */ 512 + 513 + return IRQ_HANDLED; 514 + } 515 + 516 + /* Threaded interrupt handler to manage HPD events */ 517 + static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) 518 + { 519 + struct meson_dw_hdmi *dw_hdmi = dev_id; 520 + u32 stat = dw_hdmi->irq_stat; 521 + 522 + /* HPD Events */ 523 + if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) { 524 + bool hpd_connected = false; 525 + 526 + if (stat & HDMITX_TOP_INTR_HPD_RISE) 527 + hpd_connected = true; 528 + 529 + dw_hdmi_setup_rx_sense(dw_hdmi->dev, hpd_connected, 530 + hpd_connected); 531 + 532 + drm_helper_hpd_irq_event(dw_hdmi->encoder.dev); 533 + } 534 + 535 + return IRQ_HANDLED; 536 + } 537 + 538 + /* TOFIX Enable support for non-vic modes */ 539 + static enum drm_mode_status dw_hdmi_mode_valid(struct drm_connector *connector, 540 + struct drm_display_mode *mode) 541 + { 542 + unsigned int vclk_freq; 543 + unsigned int venc_freq; 544 + unsigned int hdmi_freq; 545 + int vic = drm_match_cea_mode(mode); 546 + 547 + DRM_DEBUG_DRIVER("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", 548 + mode->base.id, mode->name, mode->vrefresh, mode->clock, 549 + mode->hdisplay, mode->hsync_start, 550 + mode->hsync_end, mode->htotal, 551 + mode->vdisplay, mode->vsync_start, 552 + mode->vsync_end, mode->vtotal, mode->type, mode->flags); 553 + 554 + /* For now, only accept VIC modes */ 555 + if (!vic) 556 + return MODE_BAD; 557 + 558 + /* For now, filter by supported VIC modes */ 559 + if (!meson_venc_hdmi_supported_vic(vic)) 560 + return MODE_BAD; 561 + 562 + vclk_freq = mode->clock; 563 + 564 + /* 480i/576i needs global pixel doubling */ 565 + if (mode->flags & DRM_MODE_FLAG_DBLCLK) 566 + vclk_freq *= 2; 567 + 568 + venc_freq = vclk_freq; 569 + hdmi_freq = vclk_freq; 570 + 571 + /* VENC double pixels for 1080i and 720p modes */ 572 + if (meson_venc_hdmi_venc_repeat(vic)) 573 + venc_freq *= 2; 574 + 575 + vclk_freq = max(venc_freq, hdmi_freq); 576 + 577 + if (mode->flags & DRM_MODE_FLAG_DBLCLK) 578 + venc_freq /= 2; 579 + 580 + dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__, 581 + vclk_freq, venc_freq, hdmi_freq); 582 + 583 + /* Finally filter by configurable vclk frequencies */ 584 + switch (vclk_freq) { 585 + case 54000: 586 + case 74250: 587 + case 148500: 588 + case 297000: 589 + case 594000: 590 + return MODE_OK; 591 + } 592 + 593 + return MODE_CLOCK_RANGE; 594 + } 595 + 596 + /* Encoder */ 597 + 598 + static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder) 599 + { 600 + drm_encoder_cleanup(encoder); 601 + } 602 + 603 + static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = { 604 + .destroy = meson_venc_hdmi_encoder_destroy, 605 + }; 606 + 607 + static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder, 608 + struct drm_crtc_state *crtc_state, 609 + struct drm_connector_state *conn_state) 610 + { 611 + return 0; 612 + } 613 + 614 + static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder) 615 + { 616 + struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder); 617 + struct meson_drm *priv = dw_hdmi->priv; 618 + 619 + DRM_DEBUG_DRIVER("\n"); 620 + 621 + writel_bits_relaxed(0x3, 0, 622 + priv->io_base + _REG(VPU_HDMI_SETTING)); 623 + 624 + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); 625 + writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); 626 + } 627 + 628 + static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder) 629 + { 630 + struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder); 631 + struct meson_drm *priv = dw_hdmi->priv; 632 + 633 + DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP"); 634 + 635 + if (priv->venc.hdmi_use_enci) 636 + writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); 637 + else 638 + writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); 639 + } 640 + 641 + static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder, 642 + struct drm_display_mode *mode, 643 + struct drm_display_mode *adjusted_mode) 644 + { 645 + struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder); 646 + struct meson_drm *priv = dw_hdmi->priv; 647 + int vic = drm_match_cea_mode(mode); 648 + 649 + DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n", 650 + mode->base.id, mode->name, vic); 651 + 652 + /* Should have been filtered */ 653 + if (!vic) 654 + return; 655 + 656 + /* VENC + VENC-DVI Mode setup */ 657 + meson_venc_hdmi_mode_set(priv, vic, mode); 658 + 659 + /* VCLK Set clock */ 660 + dw_hdmi_set_vclk(dw_hdmi, mode); 661 + 662 + /* Setup YUV444 to HDMI-TX, no 10bit diphering */ 663 + writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL)); 664 + } 665 + 666 + static const struct drm_encoder_helper_funcs 667 + meson_venc_hdmi_encoder_helper_funcs = { 668 + .atomic_check = meson_venc_hdmi_encoder_atomic_check, 669 + .disable = meson_venc_hdmi_encoder_disable, 670 + .enable = meson_venc_hdmi_encoder_enable, 671 + .mode_set = meson_venc_hdmi_encoder_mode_set, 672 + }; 673 + 674 + /* DW HDMI Regmap */ 675 + 676 + static int meson_dw_hdmi_reg_read(void *context, unsigned int reg, 677 + unsigned int *result) 678 + { 679 + *result = dw_hdmi_dwc_read(context, reg); 680 + 681 + return 0; 682 + 683 + } 684 + 685 + static int meson_dw_hdmi_reg_write(void *context, unsigned int reg, 686 + unsigned int val) 687 + { 688 + dw_hdmi_dwc_write(context, reg, val); 689 + 690 + return 0; 691 + } 692 + 693 + static const struct regmap_config meson_dw_hdmi_regmap_config = { 694 + .reg_bits = 32, 695 + .val_bits = 8, 696 + .reg_read = meson_dw_hdmi_reg_read, 697 + .reg_write = meson_dw_hdmi_reg_write, 698 + .max_register = 0x10000, 699 + }; 700 + 701 + static bool meson_hdmi_connector_is_available(struct device *dev) 702 + { 703 + struct device_node *ep, *remote; 704 + 705 + /* HDMI Connector is on the second port, first endpoint */ 706 + ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0); 707 + if (!ep) 708 + return false; 709 + 710 + /* If the endpoint node exists, consider it enabled */ 711 + remote = of_graph_get_remote_port(ep); 712 + if (remote) { 713 + of_node_put(ep); 714 + return true; 715 + } 716 + 717 + of_node_put(ep); 718 + of_node_put(remote); 719 + 720 + return false; 721 + } 722 + 723 + static int meson_dw_hdmi_bind(struct device *dev, struct device *master, 724 + void *data) 725 + { 726 + struct platform_device *pdev = to_platform_device(dev); 727 + struct meson_dw_hdmi *meson_dw_hdmi; 728 + struct drm_device *drm = data; 729 + struct meson_drm *priv = drm->dev_private; 730 + struct dw_hdmi_plat_data *dw_plat_data; 731 + struct drm_encoder *encoder; 732 + struct resource *res; 733 + int irq; 734 + int ret; 735 + 736 + DRM_DEBUG_DRIVER("\n"); 737 + 738 + if (!meson_hdmi_connector_is_available(dev)) { 739 + dev_info(drm->dev, "HDMI Output connector not available\n"); 740 + return -ENODEV; 741 + } 742 + 743 + meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi), 744 + GFP_KERNEL); 745 + if (!meson_dw_hdmi) 746 + return -ENOMEM; 747 + 748 + meson_dw_hdmi->priv = priv; 749 + meson_dw_hdmi->dev = dev; 750 + dw_plat_data = &meson_dw_hdmi->dw_plat_data; 751 + encoder = &meson_dw_hdmi->encoder; 752 + 753 + meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev, 754 + "hdmitx_apb"); 755 + if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) { 756 + dev_err(dev, "Failed to get hdmitx_apb reset\n"); 757 + return PTR_ERR(meson_dw_hdmi->hdmitx_apb); 758 + } 759 + 760 + meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev, 761 + "hdmitx"); 762 + if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) { 763 + dev_err(dev, "Failed to get hdmitx reset\n"); 764 + return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl); 765 + } 766 + 767 + meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev, 768 + "hdmitx_phy"); 769 + if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) { 770 + dev_err(dev, "Failed to get hdmitx_phy reset\n"); 771 + return PTR_ERR(meson_dw_hdmi->hdmitx_phy); 772 + } 773 + 774 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 775 + meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res); 776 + if (IS_ERR(meson_dw_hdmi->hdmitx)) 777 + return PTR_ERR(meson_dw_hdmi->hdmitx); 778 + 779 + meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr"); 780 + if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) { 781 + dev_err(dev, "Unable to get HDMI pclk\n"); 782 + return PTR_ERR(meson_dw_hdmi->hdmi_pclk); 783 + } 784 + clk_prepare_enable(meson_dw_hdmi->hdmi_pclk); 785 + 786 + meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci"); 787 + if (IS_ERR(meson_dw_hdmi->venci_clk)) { 788 + dev_err(dev, "Unable to get venci clk\n"); 789 + return PTR_ERR(meson_dw_hdmi->venci_clk); 790 + } 791 + clk_prepare_enable(meson_dw_hdmi->venci_clk); 792 + 793 + dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi, 794 + &meson_dw_hdmi_regmap_config); 795 + if (IS_ERR(dw_plat_data->regm)) 796 + return PTR_ERR(dw_plat_data->regm); 797 + 798 + irq = platform_get_irq(pdev, 0); 799 + if (irq < 0) { 800 + dev_err(dev, "Failed to get hdmi top irq\n"); 801 + return irq; 802 + } 803 + 804 + ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq, 805 + dw_hdmi_top_thread_irq, IRQF_SHARED, 806 + "dw_hdmi_top_irq", meson_dw_hdmi); 807 + if (ret) { 808 + dev_err(dev, "Failed to request hdmi top irq\n"); 809 + return ret; 810 + } 811 + 812 + /* Encoder */ 813 + 814 + drm_encoder_helper_add(encoder, &meson_venc_hdmi_encoder_helper_funcs); 815 + 816 + ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs, 817 + DRM_MODE_ENCODER_TMDS, "meson_hdmi"); 818 + if (ret) { 819 + dev_err(priv->dev, "Failed to init HDMI encoder\n"); 820 + return ret; 821 + } 822 + 823 + encoder->possible_crtcs = BIT(0); 824 + 825 + DRM_DEBUG_DRIVER("encoder initialized\n"); 826 + 827 + /* Enable clocks */ 828 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100); 829 + 830 + /* Bring HDMITX MEM output of power down */ 831 + regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0); 832 + 833 + /* Reset HDMITX APB & TX & PHY */ 834 + reset_control_reset(meson_dw_hdmi->hdmitx_apb); 835 + reset_control_reset(meson_dw_hdmi->hdmitx_ctrl); 836 + reset_control_reset(meson_dw_hdmi->hdmitx_phy); 837 + 838 + /* Enable APB3 fail on error */ 839 + writel_bits_relaxed(BIT(15), BIT(15), 840 + meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG); 841 + writel_bits_relaxed(BIT(15), BIT(15), 842 + meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG); 843 + 844 + /* Bring out of reset */ 845 + dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_SW_RESET, 0); 846 + 847 + msleep(20); 848 + 849 + dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_CLK_CNTL, 0xff); 850 + 851 + /* Enable HDMI-TX Interrupt */ 852 + dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, 853 + HDMITX_TOP_INTR_CORE); 854 + 855 + dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN, 856 + HDMITX_TOP_INTR_CORE); 857 + 858 + /* Bridge / Connector */ 859 + 860 + dw_plat_data->mode_valid = dw_hdmi_mode_valid; 861 + dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops; 862 + dw_plat_data->phy_name = "meson_dw_hdmi_phy"; 863 + dw_plat_data->phy_data = meson_dw_hdmi; 864 + dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24; 865 + dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; 866 + 867 + ret = dw_hdmi_bind(pdev, encoder, &meson_dw_hdmi->dw_plat_data); 868 + if (ret) 869 + return ret; 870 + 871 + DRM_DEBUG_DRIVER("HDMI controller initialized\n"); 872 + 873 + return 0; 874 + } 875 + 876 + static void meson_dw_hdmi_unbind(struct device *dev, struct device *master, 877 + void *data) 878 + { 879 + dw_hdmi_unbind(dev); 880 + } 881 + 882 + static const struct component_ops meson_dw_hdmi_ops = { 883 + .bind = meson_dw_hdmi_bind, 884 + .unbind = meson_dw_hdmi_unbind, 885 + }; 886 + 887 + static int meson_dw_hdmi_probe(struct platform_device *pdev) 888 + { 889 + return component_add(&pdev->dev, &meson_dw_hdmi_ops); 890 + } 891 + 892 + static int meson_dw_hdmi_remove(struct platform_device *pdev) 893 + { 894 + component_del(&pdev->dev, &meson_dw_hdmi_ops); 895 + 896 + return 0; 897 + } 898 + 899 + static const struct of_device_id meson_dw_hdmi_of_table[] = { 900 + { .compatible = "amlogic,meson-gxbb-dw-hdmi" }, 901 + { .compatible = "amlogic,meson-gxl-dw-hdmi" }, 902 + { .compatible = "amlogic,meson-gxm-dw-hdmi" }, 903 + { } 904 + }; 905 + MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table); 906 + 907 + static struct platform_driver meson_dw_hdmi_platform_driver = { 908 + .probe = meson_dw_hdmi_probe, 909 + .remove = meson_dw_hdmi_remove, 910 + .driver = { 911 + .name = DRIVER_NAME, 912 + .of_match_table = meson_dw_hdmi_of_table, 913 + }, 914 + }; 915 + module_platform_driver(meson_dw_hdmi_platform_driver); 916 + 917 + MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 918 + MODULE_DESCRIPTION(DRIVER_DESC); 919 + MODULE_LICENSE("GPL");
+146
drivers/gpu/drm/meson/meson_dw_hdmi.h
··· 1 + /* 2 + * Copyright (C) 2016 BayLibre, SAS 3 + * Author: Neil Armstrong <narmstrong@baylibre.com> 4 + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License as 8 + * published by the Free Software Foundation; either version 2 of the 9 + * License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, but 12 + * WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef __MESON_DW_HDMI_H 21 + #define __MESON_DW_HDMI_H 22 + 23 + /* 24 + * Bit 7 RW Reserved. Default 1. 25 + * Bit 6 RW Reserved. Default 1. 26 + * Bit 5 RW Reserved. Default 1. 27 + * Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset. 28 + * Default 1. 29 + * Bit 3 RW sw_reset_intr: interrupt module. 1=Apply reset; 30 + * 0=Release from reset. 31 + * Default 1. 32 + * Bit 2 RW sw_reset_mem: KSV/REVOC mem. 1=Apply reset; 0=Release from reset. 33 + * Default 1. 34 + * Bit 1 RW sw_reset_rnd: random number interface to HDCP. 1=Apply reset; 35 + * 0=Release from reset. Default 1. 36 + * Bit 0 RW sw_reset_core: connects to IP's ~irstz. 1=Apply reset; 37 + * 0=Release from reset. Default 1. 38 + */ 39 + #define HDMITX_TOP_SW_RESET (0x000) 40 + 41 + /* 42 + * Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0. 43 + * Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0. 44 + * Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0. 45 + * Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0. 46 + * Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0. 47 + * Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0. 48 + * Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0. 49 + * Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0. 50 + * Bit 1 RW tmds_clk_en: 1=enable tmds_clk; 0=disable. Default 0. 51 + * Bit 0 RW pixel_clk_en: 1=enable pixel_clk; 0=disable. Default 0. 52 + */ 53 + #define HDMITX_TOP_CLK_CNTL (0x001) 54 + 55 + /* 56 + * Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024. Default 0. 57 + * Bit 15:12 RW hpd_glitch_width: filter out glitch <= N. Default 0. 58 + */ 59 + #define HDMITX_TOP_HPD_FILTER (0x002) 60 + 61 + /* 62 + * intr_maskn: MASK_N, one bit per interrupt source. 63 + * 1=Enable interrupt source; 0=Disable interrupt source. Default 0. 64 + * [ 4] hdcp22_rndnum_err 65 + * [ 3] nonce_rfrsh_rise 66 + * [ 2] hpd_fall_intr 67 + * [ 1] hpd_rise_intr 68 + * [ 0] core_intr 69 + */ 70 + #define HDMITX_TOP_INTR_MASKN (0x003) 71 + 72 + /* 73 + * Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt 74 + * bit, read back the interrupt status. 75 + * Bit 31 R IP interrupt status 76 + * Bit 2 RW hpd_fall 77 + * Bit 1 RW hpd_rise 78 + * Bit 0 RW IP interrupt 79 + */ 80 + #define HDMITX_TOP_INTR_STAT (0x004) 81 + 82 + /* 83 + * [4] hdcp22_rndnum_err 84 + * [3] nonce_rfrsh_rise 85 + * [2] hpd_fall 86 + * [1] hpd_rise 87 + * [0] core_intr_rise 88 + */ 89 + #define HDMITX_TOP_INTR_STAT_CLR (0x005) 90 + 91 + #define HDMITX_TOP_INTR_CORE BIT(0) 92 + #define HDMITX_TOP_INTR_HPD_RISE BIT(1) 93 + #define HDMITX_TOP_INTR_HPD_FALL BIT(2) 94 + 95 + /* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data; 96 + * 3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0. 97 + * Bit 11: 9 RW shift_pttn_repeat: 0=New pattern every clk cycle; 1=New pattern 98 + * every 2 clk cycles; ...; 7=New pattern every 8 clk cycles. Default 0. 99 + * Bit 8 RW shift_pttn_en: 1= Enable shift pattern generator; 0=Disable. 100 + * Default 0. 101 + * Bit 4: 3 RW prbs_pttn_mode: 0=PRBS11; 1=PRBS15; 2=PRBS7; 3=PRBS31. Default 0. 102 + * Bit 2: 1 RW prbs_pttn_width: 0=idle; 1=output 8-bit pattern; 103 + * 2=Output 1-bit pattern; 3=output 10-bit pattern. Default 0. 104 + * Bit 0 RW prbs_pttn_en: 1=Enable PRBS generator; 0=Disable. Default 0. 105 + */ 106 + #define HDMITX_TOP_BIST_CNTL (0x006) 107 + 108 + /* Bit 29:20 RW shift_pttn_data[59:50]. Default 0. */ 109 + /* Bit 19:10 RW shift_pttn_data[69:60]. Default 0. */ 110 + /* Bit 9: 0 RW shift_pttn_data[79:70]. Default 0. */ 111 + #define HDMITX_TOP_SHIFT_PTTN_012 (0x007) 112 + 113 + /* Bit 29:20 RW shift_pttn_data[29:20]. Default 0. */ 114 + /* Bit 19:10 RW shift_pttn_data[39:30]. Default 0. */ 115 + /* Bit 9: 0 RW shift_pttn_data[49:40]. Default 0. */ 116 + #define HDMITX_TOP_SHIFT_PTTN_345 (0x008) 117 + 118 + /* Bit 19:10 RW shift_pttn_data[ 9: 0]. Default 0. */ 119 + /* Bit 9: 0 RW shift_pttn_data[19:10]. Default 0. */ 120 + #define HDMITX_TOP_SHIFT_PTTN_67 (0x009) 121 + 122 + /* Bit 25:16 RW tmds_clk_pttn[19:10]. Default 0. */ 123 + /* Bit 9: 0 RW tmds_clk_pttn[ 9: 0]. Default 0. */ 124 + #define HDMITX_TOP_TMDS_CLK_PTTN_01 (0x00A) 125 + 126 + /* Bit 25:16 RW tmds_clk_pttn[39:30]. Default 0. */ 127 + /* Bit 9: 0 RW tmds_clk_pttn[29:20]. Default 0. */ 128 + #define HDMITX_TOP_TMDS_CLK_PTTN_23 (0x00B) 129 + 130 + /* Bit 1 RW shift_tmds_clk_pttn:1=Enable shifting clk pattern, 131 + * used when TMDS CLK rate = TMDS character rate /4. Default 0. 132 + * Bit 0 R Reserved. Default 0. 133 + * [ 1] shift_tmds_clk_pttn 134 + * [ 0] load_tmds_clk_pttn 135 + */ 136 + #define HDMITX_TOP_TMDS_CLK_PTTN_CNTL (0x00C) 137 + 138 + /* Bit 0 RW revocmem_wr_fail: Read back 1 to indicate Host write REVOC MEM 139 + * failure, write 1 to clear the failure flag. Default 0. 140 + */ 141 + #define HDMITX_TOP_REVOCMEM_STAT (0x00D) 142 + 143 + /* Bit 0 R filtered HPD status. */ 144 + #define HDMITX_TOP_STAT0 (0x00E) 145 + 146 + #endif /* __MESON_DW_HDMI_H */
+1
drivers/gpu/drm/meson/meson_registers.h
··· 1319 1319 #define VPU_MISC_CTRL 0x2740 1320 1320 #define VPU_ISP_GCLK_CTRL0 0x2741 1321 1321 #define VPU_ISP_GCLK_CTRL1 0x2742 1322 + #define VPU_HDMI_FMT_CTRL 0x2743 1322 1323 #define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743 1323 1324 #define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744 1324 1325 #define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745
+621 -15
drivers/gpu/drm/meson/meson_vclk.c
··· 23 23 #include "meson_drv.h" 24 24 #include "meson_vclk.h" 25 25 26 - /* 26 + /** 27 + * DOC: Video Clocks 28 + * 27 29 * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL. 28 30 * We handle the following encodings : 31 + * 29 32 * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks 33 + * - HDMI Pixel Clocks generation 30 34 * 31 35 * What is missing : 32 - * - HDMI Pixel Clocks generation 36 + * 37 + * - Genenate Pixel clocks for 2K/4K 10bit formats 38 + * 39 + * Clock generator scheme : 40 + * 41 + * .. code:: 42 + * 43 + * __________ _________ _____ 44 + * | | | | | |--ENCI 45 + * | HDMI PLL |-| PLL_DIV |--- VCLK--| |--ENCL 46 + * |__________| |_________| \ | MUX |--ENCP 47 + * --VCLK2-| |--VDAC 48 + * |_____|--HDMI-TX 49 + * 50 + * Final clocks can take input for either VCLK or VCLK2, but 51 + * VCLK is the preferred path for HDMI clocking and VCLK2 is the 52 + * preferred path for CVBS VDAC clocking. 53 + * 54 + * VCLK and VCLK2 have fixed divided clocks paths for /1, /2, /4, /6 or /12. 55 + * 56 + * The PLL_DIV can achieve an additional fractional dividing like 57 + * 1.5, 3.5, 3.75... to generate special 2K and 4K 10bit clocks. 33 58 */ 34 59 35 60 /* HHI Registers */ ··· 75 50 #define VCLK2_SOFT_RESET BIT(15) 76 51 #define VCLK2_DIV1_EN BIT(0) 77 52 #define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */ 53 + #define VCLK_DIV_MASK 0xff 54 + #define VCLK_DIV_EN BIT(16) 55 + #define VCLK_DIV_RESET BIT(17) 56 + #define CTS_ENCP_SEL_MASK (0xf << 24) 57 + #define CTS_ENCP_SEL_SHIFT 24 78 58 #define CTS_ENCI_SEL_MASK (0xf << 28) 79 59 #define CTS_ENCI_SEL_SHIFT 28 60 + #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */ 61 + #define VCLK_EN BIT(19) 62 + #define VCLK_SEL_MASK (0x7 << 16) 63 + #define VCLK_SEL_SHIFT 16 64 + #define VCLK_SOFT_RESET BIT(15) 65 + #define VCLK_DIV1_EN BIT(0) 66 + #define VCLK_DIV2_EN BIT(1) 67 + #define VCLK_DIV4_EN BIT(2) 68 + #define VCLK_DIV6_EN BIT(3) 69 + #define VCLK_DIV12_EN BIT(4) 80 70 #define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */ 81 71 #define CTS_ENCI_EN BIT(0) 72 + #define CTS_ENCP_EN BIT(2) 82 73 #define CTS_VDAC_EN BIT(4) 74 + #define HDMI_TX_PIXEL_EN BIT(5) 75 + #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */ 76 + #define HDMI_TX_PIXEL_SEL_MASK (0xf << 16) 77 + #define HDMI_TX_PIXEL_SEL_SHIFT 16 78 + #define CTS_HDMI_SYS_SEL_MASK (0x7 << 9) 79 + #define CTS_HDMI_SYS_DIV_MASK (0x7f) 80 + #define CTS_HDMI_SYS_EN BIT(8) 83 81 84 82 #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ 85 83 #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ ··· 116 68 117 69 #define HDMI_PLL_RESET BIT(28) 118 70 #define HDMI_PLL_LOCK BIT(31) 71 + 72 + /* VID PLL Dividers */ 73 + enum { 74 + VID_PLL_DIV_1 = 0, 75 + VID_PLL_DIV_2, 76 + VID_PLL_DIV_2p5, 77 + VID_PLL_DIV_3, 78 + VID_PLL_DIV_3p5, 79 + VID_PLL_DIV_3p75, 80 + VID_PLL_DIV_4, 81 + VID_PLL_DIV_5, 82 + VID_PLL_DIV_6, 83 + VID_PLL_DIV_6p25, 84 + VID_PLL_DIV_7, 85 + VID_PLL_DIV_7p5, 86 + VID_PLL_DIV_12, 87 + VID_PLL_DIV_14, 88 + VID_PLL_DIV_15, 89 + }; 90 + 91 + void meson_vid_pll_set(struct meson_drm *priv, unsigned int div) 92 + { 93 + unsigned int shift_val = 0; 94 + unsigned int shift_sel = 0; 95 + 96 + /* Disable vid_pll output clock */ 97 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0); 98 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0); 99 + 100 + switch (div) { 101 + case VID_PLL_DIV_2: 102 + shift_val = 0x0aaa; 103 + shift_sel = 0; 104 + break; 105 + case VID_PLL_DIV_2p5: 106 + shift_val = 0x5294; 107 + shift_sel = 2; 108 + break; 109 + case VID_PLL_DIV_3: 110 + shift_val = 0x0db6; 111 + shift_sel = 0; 112 + break; 113 + case VID_PLL_DIV_3p5: 114 + shift_val = 0x36cc; 115 + shift_sel = 1; 116 + break; 117 + case VID_PLL_DIV_3p75: 118 + shift_val = 0x6666; 119 + shift_sel = 2; 120 + break; 121 + case VID_PLL_DIV_4: 122 + shift_val = 0x0ccc; 123 + shift_sel = 0; 124 + break; 125 + case VID_PLL_DIV_5: 126 + shift_val = 0x739c; 127 + shift_sel = 2; 128 + break; 129 + case VID_PLL_DIV_6: 130 + shift_val = 0x0e38; 131 + shift_sel = 0; 132 + break; 133 + case VID_PLL_DIV_6p25: 134 + shift_val = 0x0000; 135 + shift_sel = 3; 136 + break; 137 + case VID_PLL_DIV_7: 138 + shift_val = 0x3c78; 139 + shift_sel = 1; 140 + break; 141 + case VID_PLL_DIV_7p5: 142 + shift_val = 0x78f0; 143 + shift_sel = 2; 144 + break; 145 + case VID_PLL_DIV_12: 146 + shift_val = 0x0fc0; 147 + shift_sel = 0; 148 + break; 149 + case VID_PLL_DIV_14: 150 + shift_val = 0x3f80; 151 + shift_sel = 1; 152 + break; 153 + case VID_PLL_DIV_15: 154 + shift_val = 0x7f80; 155 + shift_sel = 2; 156 + break; 157 + } 158 + 159 + if (div == VID_PLL_DIV_1) 160 + /* Enable vid_pll bypass to HDMI pll */ 161 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 162 + VID_PLL_BYPASS, VID_PLL_BYPASS); 163 + else { 164 + /* Disable Bypass */ 165 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 166 + VID_PLL_BYPASS, 0); 167 + /* Clear sel */ 168 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 169 + 3 << 16, 0); 170 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 171 + VID_PLL_PRESET, 0); 172 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 173 + 0x7fff, 0); 174 + 175 + /* Setup sel and val */ 176 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 177 + 3 << 16, shift_sel << 16); 178 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 179 + VID_PLL_PRESET, VID_PLL_PRESET); 180 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 181 + 0x7fff, shift_val); 182 + 183 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 184 + VID_PLL_PRESET, 0); 185 + } 186 + 187 + /* Enable the vid_pll output clock */ 188 + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 189 + VID_PLL_EN, VID_PLL_EN); 190 + } 119 191 120 192 /* 121 193 * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC ··· 278 110 /* Disable VCLK2 */ 279 111 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0); 280 112 281 - /* Disable vid_pll output clock */ 282 - regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0); 283 - regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0); 284 - /* Enable vid_pll bypass to HDMI pll */ 285 - regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 286 - VID_PLL_BYPASS, VID_PLL_BYPASS); 287 - /* Enable the vid_pll output clock */ 288 - regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, 289 - VID_PLL_EN, VID_PLL_EN); 113 + /* Setup vid_pll to /1 */ 114 + meson_vid_pll_set(priv, VID_PLL_DIV_1); 290 115 291 116 /* Setup the VCLK2 divider value to achieve 27MHz */ 292 117 regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV, ··· 320 159 CTS_VDAC_EN, CTS_VDAC_EN); 321 160 } 322 161 323 - void meson_vclk_setup(struct meson_drm *priv, unsigned int target, 324 - unsigned int freq) 162 + 163 + /* PLL O1 O2 O3 VP DV EN TX */ 164 + /* 4320 /4 /4 /1 /5 /1 => /2 /2 */ 165 + #define MESON_VCLK_HDMI_ENCI_54000 1 166 + /* 4320 /4 /4 /1 /5 /1 => /1 /2 */ 167 + #define MESON_VCLK_HDMI_DDR_54000 2 168 + /* 2970 /4 /1 /1 /5 /1 => /1 /2 */ 169 + #define MESON_VCLK_HDMI_DDR_148500 3 170 + /* 2970 /2 /2 /2 /5 /1 => /1 /1 */ 171 + #define MESON_VCLK_HDMI_74250 4 172 + /* 2970 /1 /2 /2 /5 /1 => /1 /1 */ 173 + #define MESON_VCLK_HDMI_148500 5 174 + /* 2970 /1 /1 /1 /5 /2 => /1 /1 */ 175 + #define MESON_VCLK_HDMI_297000 6 176 + /* 5940 /1 /1 /2 /5 /1 => /1 /1 */ 177 + #define MESON_VCLK_HDMI_594000 7 178 + 179 + struct meson_vclk_params { 180 + unsigned int pll_base_freq; 181 + unsigned int pll_od1; 182 + unsigned int pll_od2; 183 + unsigned int pll_od3; 184 + unsigned int vid_pll_div; 185 + unsigned int vclk_div; 186 + } params[] = { 187 + [MESON_VCLK_HDMI_ENCI_54000] = { 188 + .pll_base_freq = 4320000, 189 + .pll_od1 = 4, 190 + .pll_od2 = 4, 191 + .pll_od3 = 1, 192 + .vid_pll_div = VID_PLL_DIV_5, 193 + .vclk_div = 1, 194 + }, 195 + [MESON_VCLK_HDMI_DDR_54000] = { 196 + .pll_base_freq = 4320000, 197 + .pll_od1 = 4, 198 + .pll_od2 = 4, 199 + .pll_od3 = 1, 200 + .vid_pll_div = VID_PLL_DIV_5, 201 + .vclk_div = 1, 202 + }, 203 + [MESON_VCLK_HDMI_DDR_148500] = { 204 + .pll_base_freq = 2970000, 205 + .pll_od1 = 4, 206 + .pll_od2 = 1, 207 + .pll_od3 = 1, 208 + .vid_pll_div = VID_PLL_DIV_5, 209 + .vclk_div = 1, 210 + }, 211 + [MESON_VCLK_HDMI_74250] = { 212 + .pll_base_freq = 2970000, 213 + .pll_od1 = 2, 214 + .pll_od2 = 2, 215 + .pll_od3 = 2, 216 + .vid_pll_div = VID_PLL_DIV_5, 217 + .vclk_div = 1, 218 + }, 219 + [MESON_VCLK_HDMI_148500] = { 220 + .pll_base_freq = 2970000, 221 + .pll_od1 = 1, 222 + .pll_od2 = 2, 223 + .pll_od3 = 2, 224 + .vid_pll_div = VID_PLL_DIV_5, 225 + .vclk_div = 1, 226 + }, 227 + [MESON_VCLK_HDMI_297000] = { 228 + .pll_base_freq = 2970000, 229 + .pll_od1 = 1, 230 + .pll_od2 = 1, 231 + .pll_od3 = 1, 232 + .vid_pll_div = VID_PLL_DIV_5, 233 + .vclk_div = 2, 234 + }, 235 + [MESON_VCLK_HDMI_594000] = { 236 + .pll_base_freq = 5940000, 237 + .pll_od1 = 1, 238 + .pll_od2 = 1, 239 + .pll_od3 = 2, 240 + .vid_pll_div = VID_PLL_DIV_5, 241 + .vclk_div = 1, 242 + }, 243 + }; 244 + 245 + static inline unsigned int pll_od_to_reg(unsigned int od) 325 246 { 326 - if (target == MESON_VCLK_TARGET_CVBS && freq == MESON_VCLK_CVBS) 327 - meson_venci_cvbs_clock_config(priv); 247 + switch (od) { 248 + case 1: 249 + return 0; 250 + case 2: 251 + return 1; 252 + case 4: 253 + return 2; 254 + case 8: 255 + return 3; 256 + } 257 + 258 + /* Invalid */ 259 + return 0; 328 260 } 261 + 262 + void meson_hdmi_pll_set(struct meson_drm *priv, 263 + unsigned int base, 264 + unsigned int od1, 265 + unsigned int od2, 266 + unsigned int od3) 267 + { 268 + unsigned int val; 269 + 270 + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) { 271 + switch (base) { 272 + case 2970000: 273 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d); 274 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); 275 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091); 276 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); 277 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); 278 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); 279 + 280 + /* Enable and unreset */ 281 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, 282 + 0x7 << 28, 0x4 << 28); 283 + 284 + /* Poll for lock bit */ 285 + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, 286 + val, (val & HDMI_PLL_LOCK), 10, 0); 287 + 288 + /* div_frac */ 289 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 290 + 0xFFFF, 0x4e00); 291 + break; 292 + 293 + case 4320000: 294 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a); 295 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); 296 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091); 297 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); 298 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); 299 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); 300 + 301 + /* unreset */ 302 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, 303 + BIT(28), 0); 304 + 305 + /* Poll for lock bit */ 306 + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, 307 + val, (val & HDMI_PLL_LOCK), 10, 0); 308 + break; 309 + 310 + case 5940000: 311 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800027b); 312 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 313 + 0xFFFF, 0x4c00); 314 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091); 315 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); 316 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); 317 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); 318 + 319 + /* unreset */ 320 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, 321 + BIT(28), 0); 322 + 323 + /* Poll for lock bit */ 324 + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, 325 + val, (val & HDMI_PLL_LOCK), 10, 0); 326 + break; 327 + }; 328 + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 329 + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { 330 + switch (base) { 331 + case 2970000: 332 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b); 333 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300); 334 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); 335 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); 336 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); 337 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); 338 + break; 339 + 340 + case 4320000: 341 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4); 342 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000); 343 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); 344 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); 345 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); 346 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); 347 + break; 348 + 349 + case 5940000: 350 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002f7); 351 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb200); 352 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); 353 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); 354 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); 355 + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); 356 + break; 357 + 358 + }; 359 + 360 + /* Reset PLL */ 361 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, 362 + HDMI_PLL_RESET, HDMI_PLL_RESET); 363 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, 364 + HDMI_PLL_RESET, 0); 365 + 366 + /* Poll for lock bit */ 367 + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val, 368 + (val & HDMI_PLL_LOCK), 10, 0); 369 + }; 370 + 371 + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) 372 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 373 + 3 << 16, pll_od_to_reg(od1) << 16); 374 + else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 375 + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 376 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3, 377 + 3 << 21, pll_od_to_reg(od1) << 21); 378 + 379 + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) 380 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 381 + 3 << 22, pll_od_to_reg(od2) << 22); 382 + else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 383 + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 384 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3, 385 + 3 << 23, pll_od_to_reg(od2) << 23); 386 + 387 + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) 388 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, 389 + 3 << 18, pll_od_to_reg(od3) << 18); 390 + else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 391 + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) 392 + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3, 393 + 3 << 19, pll_od_to_reg(od3) << 19); 394 + } 395 + 396 + void meson_vclk_setup(struct meson_drm *priv, unsigned int target, 397 + unsigned int vclk_freq, unsigned int venc_freq, 398 + unsigned int dac_freq, bool hdmi_use_enci) 399 + { 400 + unsigned int freq; 401 + unsigned int hdmi_tx_div; 402 + unsigned int venc_div; 403 + 404 + if (target == MESON_VCLK_TARGET_CVBS) { 405 + meson_venci_cvbs_clock_config(priv); 406 + return; 407 + } 408 + 409 + hdmi_tx_div = vclk_freq / dac_freq; 410 + 411 + if (hdmi_tx_div == 0) { 412 + pr_err("Fatal Error, invalid HDMI-TX freq %d\n", 413 + dac_freq); 414 + return; 415 + } 416 + 417 + venc_div = vclk_freq / venc_freq; 418 + 419 + if (venc_div == 0) { 420 + pr_err("Fatal Error, invalid HDMI venc freq %d\n", 421 + venc_freq); 422 + return; 423 + } 424 + 425 + switch (vclk_freq) { 426 + case 54000: 427 + if (hdmi_use_enci) 428 + freq = MESON_VCLK_HDMI_ENCI_54000; 429 + else 430 + freq = MESON_VCLK_HDMI_DDR_54000; 431 + break; 432 + case 74250: 433 + freq = MESON_VCLK_HDMI_74250; 434 + break; 435 + case 148500: 436 + if (dac_freq != 148500) 437 + freq = MESON_VCLK_HDMI_DDR_148500; 438 + else 439 + freq = MESON_VCLK_HDMI_148500; 440 + break; 441 + case 297000: 442 + freq = MESON_VCLK_HDMI_297000; 443 + break; 444 + case 594000: 445 + freq = MESON_VCLK_HDMI_594000; 446 + break; 447 + default: 448 + pr_err("Fatal Error, invalid HDMI vclk freq %d\n", 449 + vclk_freq); 450 + return; 451 + } 452 + 453 + /* Set HDMI-TX sys clock */ 454 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 455 + CTS_HDMI_SYS_SEL_MASK, 0); 456 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 457 + CTS_HDMI_SYS_DIV_MASK, 0); 458 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 459 + CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN); 460 + 461 + /* Set HDMI PLL rate */ 462 + meson_hdmi_pll_set(priv, params[freq].pll_base_freq, 463 + params[freq].pll_od1, 464 + params[freq].pll_od2, 465 + params[freq].pll_od3); 466 + 467 + /* Setup vid_pll divider */ 468 + meson_vid_pll_set(priv, params[freq].vid_pll_div); 469 + 470 + /* Set VCLK div */ 471 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 472 + VCLK_SEL_MASK, 0); 473 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 474 + VCLK_DIV_MASK, params[freq].vclk_div - 1); 475 + 476 + /* Set HDMI-TX source */ 477 + switch (hdmi_tx_div) { 478 + case 1: 479 + /* enable vclk_div1 gate */ 480 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 481 + VCLK_DIV1_EN, VCLK_DIV1_EN); 482 + 483 + /* select vclk_div1 for HDMI-TX */ 484 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 485 + HDMI_TX_PIXEL_SEL_MASK, 0); 486 + break; 487 + case 2: 488 + /* enable vclk_div2 gate */ 489 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 490 + VCLK_DIV2_EN, VCLK_DIV2_EN); 491 + 492 + /* select vclk_div2 for HDMI-TX */ 493 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 494 + HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT); 495 + break; 496 + case 4: 497 + /* enable vclk_div4 gate */ 498 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 499 + VCLK_DIV4_EN, VCLK_DIV4_EN); 500 + 501 + /* select vclk_div4 for HDMI-TX */ 502 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 503 + HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT); 504 + break; 505 + case 6: 506 + /* enable vclk_div6 gate */ 507 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 508 + VCLK_DIV6_EN, VCLK_DIV6_EN); 509 + 510 + /* select vclk_div6 for HDMI-TX */ 511 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 512 + HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT); 513 + break; 514 + case 12: 515 + /* enable vclk_div12 gate */ 516 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 517 + VCLK_DIV12_EN, VCLK_DIV12_EN); 518 + 519 + /* select vclk_div12 for HDMI-TX */ 520 + regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 521 + HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT); 522 + break; 523 + } 524 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2, 525 + HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN); 526 + 527 + /* Set ENCI/ENCP Source */ 528 + switch (venc_div) { 529 + case 1: 530 + /* enable vclk_div1 gate */ 531 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 532 + VCLK_DIV1_EN, VCLK_DIV1_EN); 533 + 534 + if (hdmi_use_enci) 535 + /* select vclk_div1 for enci */ 536 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 537 + CTS_ENCI_SEL_MASK, 0); 538 + else 539 + /* select vclk_div1 for encp */ 540 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 541 + CTS_ENCP_SEL_MASK, 0); 542 + break; 543 + case 2: 544 + /* enable vclk_div2 gate */ 545 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 546 + VCLK_DIV2_EN, VCLK_DIV2_EN); 547 + 548 + if (hdmi_use_enci) 549 + /* select vclk_div2 for enci */ 550 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 551 + CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT); 552 + else 553 + /* select vclk_div2 for encp */ 554 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 555 + CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT); 556 + break; 557 + case 4: 558 + /* enable vclk_div4 gate */ 559 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 560 + VCLK_DIV4_EN, VCLK_DIV4_EN); 561 + 562 + if (hdmi_use_enci) 563 + /* select vclk_div4 for enci */ 564 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 565 + CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT); 566 + else 567 + /* select vclk_div4 for encp */ 568 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 569 + CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT); 570 + break; 571 + case 6: 572 + /* enable vclk_div6 gate */ 573 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 574 + VCLK_DIV6_EN, VCLK_DIV6_EN); 575 + 576 + if (hdmi_use_enci) 577 + /* select vclk_div6 for enci */ 578 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 579 + CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT); 580 + else 581 + /* select vclk_div6 for encp */ 582 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 583 + CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT); 584 + break; 585 + case 12: 586 + /* enable vclk_div12 gate */ 587 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, 588 + VCLK_DIV12_EN, VCLK_DIV12_EN); 589 + 590 + if (hdmi_use_enci) 591 + /* select vclk_div12 for enci */ 592 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 593 + CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT); 594 + else 595 + /* select vclk_div12 for encp */ 596 + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, 597 + CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT); 598 + break; 599 + } 600 + 601 + if (hdmi_use_enci) 602 + /* Enable ENCI clock gate */ 603 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2, 604 + CTS_ENCI_EN, CTS_ENCI_EN); 605 + else 606 + /* Enable ENCP clock gate */ 607 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2, 608 + CTS_ENCP_EN, CTS_ENCP_EN); 609 + 610 + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN); 611 + } 612 + EXPORT_SYMBOL_GPL(meson_vclk_setup);
+4 -2
drivers/gpu/drm/meson/meson_vclk.h
··· 23 23 24 24 enum { 25 25 MESON_VCLK_TARGET_CVBS = 0, 26 + MESON_VCLK_TARGET_HDMI = 1, 26 27 }; 27 28 28 29 /* 27MHz is the CVBS Pixel Clock */ 29 - #define MESON_VCLK_CVBS 27000 30 + #define MESON_VCLK_CVBS 27000 30 31 31 32 void meson_vclk_setup(struct meson_drm *priv, unsigned int target, 32 - unsigned int freq); 33 + unsigned int vclk_freq, unsigned int venc_freq, 34 + unsigned int dac_freq, bool hdmi_use_enci); 33 35 34 36 #endif /* __MESON_VCLK_H */
+1248 -6
drivers/gpu/drm/meson/meson_venc.c
··· 26 26 #include "meson_vclk.h" 27 27 #include "meson_registers.h" 28 28 29 - /* 29 + /** 30 + * DOC: Video Encoder 31 + * 30 32 * VENC Handle the pixels encoding to the output formats. 31 33 * We handle the following encodings : 32 - * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter 33 34 * 34 - * What is missing : 35 + * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter 35 36 * - TMDS/HDMI Encoding via ENCI_DIV and ENCP 36 37 * - Setup of more clock rates for HDMI modes 38 + * 39 + * What is missing : 40 + * 37 41 * - LCD Panel encoding via ENCL 38 42 * - TV Panel encoding via ENCT 43 + * 44 + * VENC paths : 45 + * 46 + * .. code:: 47 + * 48 + * _____ _____ ____________________ 49 + * vd1---| |-| | | VENC /---------|----VDAC 50 + * vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|-| 51 + * osd1--| |-| | | \ | X--HDMI-TX 52 + * osd2--|_____|-|_____| | |\-ENCP--ENCP_DVI-|-| 53 + * | | | 54 + * | \--ENCL-----------|----LVDS 55 + * |____________________| 56 + * 57 + * The ENCI is designed for PAl or NTSC encoding and can go through the VDAC 58 + * directly for CVBS encoding or through the ENCI_DVI encoder for HDMI. 59 + * The ENCP is designed for Progressive encoding but can also generate 60 + * 1080i interlaced pixels, and was initialy desined to encode pixels for 61 + * VDAC to output RGB ou YUV analog outputs. 62 + * It's output is only used through the ENCP_DVI encoder for HDMI. 63 + * The ENCL LVDS encoder is not implemented. 64 + * 65 + * The ENCI and ENCP encoders needs specially defined parameters for each 66 + * supported mode and thus cannot be determined from standard video timings. 67 + * 68 + * The ENCI end ENCP DVI encoders are more generic and can generate any timings 69 + * from the pixel data generated by ENCI or ENCP, so can use the standard video 70 + * timings are source for HW parameters. 39 71 */ 40 72 41 73 /* HHI Registers */ ··· 122 90 .video_hue = 0, 123 91 .analog_sync_adj = 0x9c00, 124 92 }; 93 + 94 + union meson_hdmi_venc_mode { 95 + struct { 96 + unsigned int mode_tag; 97 + unsigned int hso_begin; 98 + unsigned int hso_end; 99 + unsigned int vso_even; 100 + unsigned int vso_odd; 101 + unsigned int macv_max_amp; 102 + unsigned int video_prog_mode; 103 + unsigned int video_mode; 104 + unsigned int sch_adjust; 105 + unsigned int yc_delay; 106 + unsigned int pixel_start; 107 + unsigned int pixel_end; 108 + unsigned int top_field_line_start; 109 + unsigned int top_field_line_end; 110 + unsigned int bottom_field_line_start; 111 + unsigned int bottom_field_line_end; 112 + } enci; 113 + struct { 114 + unsigned int dvi_settings; 115 + unsigned int video_mode; 116 + unsigned int video_mode_adv; 117 + unsigned int video_prog_mode; 118 + bool video_prog_mode_present; 119 + unsigned int video_sync_mode; 120 + bool video_sync_mode_present; 121 + unsigned int video_yc_dly; 122 + bool video_yc_dly_present; 123 + unsigned int video_rgb_ctrl; 124 + bool video_rgb_ctrl_present; 125 + unsigned int video_filt_ctrl; 126 + bool video_filt_ctrl_present; 127 + unsigned int video_ofld_voav_ofst; 128 + bool video_ofld_voav_ofst_present; 129 + unsigned int yfp1_htime; 130 + unsigned int yfp2_htime; 131 + unsigned int max_pxcnt; 132 + unsigned int hspuls_begin; 133 + unsigned int hspuls_end; 134 + unsigned int hspuls_switch; 135 + unsigned int vspuls_begin; 136 + unsigned int vspuls_end; 137 + unsigned int vspuls_bline; 138 + unsigned int vspuls_eline; 139 + unsigned int eqpuls_begin; 140 + bool eqpuls_begin_present; 141 + unsigned int eqpuls_end; 142 + bool eqpuls_end_present; 143 + unsigned int eqpuls_bline; 144 + bool eqpuls_bline_present; 145 + unsigned int eqpuls_eline; 146 + bool eqpuls_eline_present; 147 + unsigned int havon_begin; 148 + unsigned int havon_end; 149 + unsigned int vavon_bline; 150 + unsigned int vavon_eline; 151 + unsigned int hso_begin; 152 + unsigned int hso_end; 153 + unsigned int vso_begin; 154 + unsigned int vso_end; 155 + unsigned int vso_bline; 156 + unsigned int vso_eline; 157 + bool vso_eline_present; 158 + unsigned int sy_val; 159 + bool sy_val_present; 160 + unsigned int sy2_val; 161 + bool sy2_val_present; 162 + unsigned int max_lncnt; 163 + } encp; 164 + }; 165 + 166 + union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = { 167 + .enci = { 168 + .hso_begin = 5, 169 + .hso_end = 129, 170 + .vso_even = 3, 171 + .vso_odd = 260, 172 + .macv_max_amp = 0x810b, 173 + .video_prog_mode = 0xf0, 174 + .video_mode = 0x8, 175 + .sch_adjust = 0x20, 176 + .yc_delay = 0, 177 + .pixel_start = 227, 178 + .pixel_end = 1667, 179 + .top_field_line_start = 18, 180 + .top_field_line_end = 258, 181 + .bottom_field_line_start = 19, 182 + .bottom_field_line_end = 259, 183 + }, 184 + }; 185 + 186 + union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = { 187 + .enci = { 188 + .hso_begin = 3, 189 + .hso_end = 129, 190 + .vso_even = 3, 191 + .vso_odd = 260, 192 + .macv_max_amp = 8107, 193 + .video_prog_mode = 0xff, 194 + .video_mode = 0x13, 195 + .sch_adjust = 0x28, 196 + .yc_delay = 0x333, 197 + .pixel_start = 251, 198 + .pixel_end = 1691, 199 + .top_field_line_start = 22, 200 + .top_field_line_end = 310, 201 + .bottom_field_line_start = 23, 202 + .bottom_field_line_end = 311, 203 + }, 204 + }; 205 + 206 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = { 207 + .encp = { 208 + .dvi_settings = 0x21, 209 + .video_mode = 0x4000, 210 + .video_mode_adv = 0x9, 211 + .video_prog_mode = 0, 212 + .video_prog_mode_present = true, 213 + .video_sync_mode = 7, 214 + .video_sync_mode_present = true, 215 + /* video_yc_dly */ 216 + /* video_rgb_ctrl */ 217 + .video_filt_ctrl = 0x2052, 218 + .video_filt_ctrl_present = true, 219 + /* video_ofld_voav_ofst */ 220 + .yfp1_htime = 244, 221 + .yfp2_htime = 1630, 222 + .max_pxcnt = 1715, 223 + .hspuls_begin = 0x22, 224 + .hspuls_end = 0xa0, 225 + .hspuls_switch = 88, 226 + .vspuls_begin = 0, 227 + .vspuls_end = 1589, 228 + .vspuls_bline = 0, 229 + .vspuls_eline = 5, 230 + .havon_begin = 249, 231 + .havon_end = 1689, 232 + .vavon_bline = 42, 233 + .vavon_eline = 521, 234 + /* eqpuls_begin */ 235 + /* eqpuls_end */ 236 + /* eqpuls_bline */ 237 + /* eqpuls_eline */ 238 + .hso_begin = 3, 239 + .hso_end = 5, 240 + .vso_begin = 3, 241 + .vso_end = 5, 242 + .vso_bline = 0, 243 + /* vso_eline */ 244 + .sy_val = 8, 245 + .sy_val_present = true, 246 + .sy2_val = 0x1d8, 247 + .sy2_val_present = true, 248 + .max_lncnt = 524, 249 + }, 250 + }; 251 + 252 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = { 253 + .encp = { 254 + .dvi_settings = 0x21, 255 + .video_mode = 0x4000, 256 + .video_mode_adv = 0x9, 257 + .video_prog_mode = 0, 258 + .video_prog_mode_present = true, 259 + .video_sync_mode = 7, 260 + .video_sync_mode_present = true, 261 + /* video_yc_dly */ 262 + /* video_rgb_ctrl */ 263 + .video_filt_ctrl = 0x52, 264 + .video_filt_ctrl_present = true, 265 + /* video_ofld_voav_ofst */ 266 + .yfp1_htime = 235, 267 + .yfp2_htime = 1674, 268 + .max_pxcnt = 1727, 269 + .hspuls_begin = 0, 270 + .hspuls_end = 0x80, 271 + .hspuls_switch = 88, 272 + .vspuls_begin = 0, 273 + .vspuls_end = 1599, 274 + .vspuls_bline = 0, 275 + .vspuls_eline = 4, 276 + .havon_begin = 235, 277 + .havon_end = 1674, 278 + .vavon_bline = 44, 279 + .vavon_eline = 619, 280 + /* eqpuls_begin */ 281 + /* eqpuls_end */ 282 + /* eqpuls_bline */ 283 + /* eqpuls_eline */ 284 + .hso_begin = 0x80, 285 + .hso_end = 0, 286 + .vso_begin = 0, 287 + .vso_end = 5, 288 + .vso_bline = 0, 289 + /* vso_eline */ 290 + .sy_val = 8, 291 + .sy_val_present = true, 292 + .sy2_val = 0x1d8, 293 + .sy2_val_present = true, 294 + .max_lncnt = 624, 295 + }, 296 + }; 297 + 298 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = { 299 + .encp = { 300 + .dvi_settings = 0x2029, 301 + .video_mode = 0x4040, 302 + .video_mode_adv = 0x19, 303 + /* video_prog_mode */ 304 + /* video_sync_mode */ 305 + /* video_yc_dly */ 306 + /* video_rgb_ctrl */ 307 + /* video_filt_ctrl */ 308 + /* video_ofld_voav_ofst */ 309 + .yfp1_htime = 648, 310 + .yfp2_htime = 3207, 311 + .max_pxcnt = 3299, 312 + .hspuls_begin = 80, 313 + .hspuls_end = 240, 314 + .hspuls_switch = 80, 315 + .vspuls_begin = 688, 316 + .vspuls_end = 3248, 317 + .vspuls_bline = 4, 318 + .vspuls_eline = 8, 319 + .havon_begin = 648, 320 + .havon_end = 3207, 321 + .vavon_bline = 29, 322 + .vavon_eline = 748, 323 + /* eqpuls_begin */ 324 + /* eqpuls_end */ 325 + /* eqpuls_bline */ 326 + /* eqpuls_eline */ 327 + .hso_begin = 256, 328 + .hso_end = 168, 329 + .vso_begin = 168, 330 + .vso_end = 256, 331 + .vso_bline = 0, 332 + .vso_eline = 5, 333 + .vso_eline_present = true, 334 + /* sy_val */ 335 + /* sy2_val */ 336 + .max_lncnt = 749, 337 + }, 338 + }; 339 + 340 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = { 341 + .encp = { 342 + .dvi_settings = 0x202d, 343 + .video_mode = 0x4040, 344 + .video_mode_adv = 0x19, 345 + .video_prog_mode = 0x100, 346 + .video_prog_mode_present = true, 347 + .video_sync_mode = 0x407, 348 + .video_sync_mode_present = true, 349 + .video_yc_dly = 0, 350 + .video_yc_dly_present = true, 351 + /* video_rgb_ctrl */ 352 + /* video_filt_ctrl */ 353 + /* video_ofld_voav_ofst */ 354 + .yfp1_htime = 648, 355 + .yfp2_htime = 3207, 356 + .max_pxcnt = 3959, 357 + .hspuls_begin = 80, 358 + .hspuls_end = 240, 359 + .hspuls_switch = 80, 360 + .vspuls_begin = 688, 361 + .vspuls_end = 3248, 362 + .vspuls_bline = 4, 363 + .vspuls_eline = 8, 364 + .havon_begin = 648, 365 + .havon_end = 3207, 366 + .vavon_bline = 29, 367 + .vavon_eline = 748, 368 + /* eqpuls_begin */ 369 + /* eqpuls_end */ 370 + /* eqpuls_bline */ 371 + /* eqpuls_eline */ 372 + .hso_begin = 128, 373 + .hso_end = 208, 374 + .vso_begin = 128, 375 + .vso_end = 128, 376 + .vso_bline = 0, 377 + .vso_eline = 5, 378 + .vso_eline_present = true, 379 + /* sy_val */ 380 + /* sy2_val */ 381 + .max_lncnt = 749, 382 + }, 383 + }; 384 + 385 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = { 386 + .encp = { 387 + .dvi_settings = 0x2029, 388 + .video_mode = 0x5ffc, 389 + .video_mode_adv = 0x19, 390 + .video_prog_mode = 0x100, 391 + .video_prog_mode_present = true, 392 + .video_sync_mode = 0x207, 393 + .video_sync_mode_present = true, 394 + /* video_yc_dly */ 395 + /* video_rgb_ctrl */ 396 + /* video_filt_ctrl */ 397 + .video_ofld_voav_ofst = 0x11, 398 + .video_ofld_voav_ofst_present = true, 399 + .yfp1_htime = 516, 400 + .yfp2_htime = 4355, 401 + .max_pxcnt = 4399, 402 + .hspuls_begin = 88, 403 + .hspuls_end = 264, 404 + .hspuls_switch = 88, 405 + .vspuls_begin = 440, 406 + .vspuls_end = 2200, 407 + .vspuls_bline = 0, 408 + .vspuls_eline = 4, 409 + .havon_begin = 516, 410 + .havon_end = 4355, 411 + .vavon_bline = 20, 412 + .vavon_eline = 559, 413 + .eqpuls_begin = 2288, 414 + .eqpuls_begin_present = true, 415 + .eqpuls_end = 2464, 416 + .eqpuls_end_present = true, 417 + .eqpuls_bline = 0, 418 + .eqpuls_bline_present = true, 419 + .eqpuls_eline = 4, 420 + .eqpuls_eline_present = true, 421 + .hso_begin = 264, 422 + .hso_end = 176, 423 + .vso_begin = 88, 424 + .vso_end = 88, 425 + .vso_bline = 0, 426 + .vso_eline = 5, 427 + .vso_eline_present = true, 428 + /* sy_val */ 429 + /* sy2_val */ 430 + .max_lncnt = 1124, 431 + }, 432 + }; 433 + 434 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = { 435 + .encp = { 436 + .dvi_settings = 0x202d, 437 + .video_mode = 0x5ffc, 438 + .video_mode_adv = 0x19, 439 + .video_prog_mode = 0x100, 440 + .video_prog_mode_present = true, 441 + .video_sync_mode = 0x7, 442 + .video_sync_mode_present = true, 443 + /* video_yc_dly */ 444 + /* video_rgb_ctrl */ 445 + /* video_filt_ctrl */ 446 + .video_ofld_voav_ofst = 0x11, 447 + .video_ofld_voav_ofst_present = true, 448 + .yfp1_htime = 526, 449 + .yfp2_htime = 4365, 450 + .max_pxcnt = 5279, 451 + .hspuls_begin = 88, 452 + .hspuls_end = 264, 453 + .hspuls_switch = 88, 454 + .vspuls_begin = 440, 455 + .vspuls_end = 2200, 456 + .vspuls_bline = 0, 457 + .vspuls_eline = 4, 458 + .havon_begin = 526, 459 + .havon_end = 4365, 460 + .vavon_bline = 20, 461 + .vavon_eline = 559, 462 + .eqpuls_begin = 2288, 463 + .eqpuls_begin_present = true, 464 + .eqpuls_end = 2464, 465 + .eqpuls_end_present = true, 466 + .eqpuls_bline = 0, 467 + .eqpuls_bline_present = true, 468 + .eqpuls_eline = 4, 469 + .eqpuls_eline_present = true, 470 + .hso_begin = 142, 471 + .hso_end = 230, 472 + .vso_begin = 142, 473 + .vso_end = 142, 474 + .vso_bline = 0, 475 + .vso_eline = 5, 476 + .vso_eline_present = true, 477 + /* sy_val */ 478 + /* sy2_val */ 479 + .max_lncnt = 1124, 480 + }, 481 + }; 482 + 483 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = { 484 + .encp = { 485 + .dvi_settings = 0xd, 486 + .video_mode = 0x4040, 487 + .video_mode_adv = 0x18, 488 + .video_prog_mode = 0x100, 489 + .video_prog_mode_present = true, 490 + .video_sync_mode = 0x7, 491 + .video_sync_mode_present = true, 492 + .video_yc_dly = 0, 493 + .video_yc_dly_present = true, 494 + .video_rgb_ctrl = 2, 495 + .video_rgb_ctrl_present = true, 496 + .video_filt_ctrl = 0x1052, 497 + .video_filt_ctrl_present = true, 498 + /* video_ofld_voav_ofst */ 499 + .yfp1_htime = 271, 500 + .yfp2_htime = 2190, 501 + .max_pxcnt = 2749, 502 + .hspuls_begin = 44, 503 + .hspuls_end = 132, 504 + .hspuls_switch = 44, 505 + .vspuls_begin = 220, 506 + .vspuls_end = 2140, 507 + .vspuls_bline = 0, 508 + .vspuls_eline = 4, 509 + .havon_begin = 271, 510 + .havon_end = 2190, 511 + .vavon_bline = 41, 512 + .vavon_eline = 1120, 513 + /* eqpuls_begin */ 514 + /* eqpuls_end */ 515 + .eqpuls_bline = 0, 516 + .eqpuls_bline_present = true, 517 + .eqpuls_eline = 4, 518 + .eqpuls_eline_present = true, 519 + .hso_begin = 79, 520 + .hso_end = 123, 521 + .vso_begin = 79, 522 + .vso_end = 79, 523 + .vso_bline = 0, 524 + .vso_eline = 5, 525 + .vso_eline_present = true, 526 + /* sy_val */ 527 + /* sy2_val */ 528 + .max_lncnt = 1124, 529 + }, 530 + }; 531 + 532 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = { 533 + .encp = { 534 + .dvi_settings = 0x1, 535 + .video_mode = 0x4040, 536 + .video_mode_adv = 0x18, 537 + .video_prog_mode = 0x100, 538 + .video_prog_mode_present = true, 539 + /* video_sync_mode */ 540 + /* video_yc_dly */ 541 + /* video_rgb_ctrl */ 542 + .video_filt_ctrl = 0x1052, 543 + .video_filt_ctrl_present = true, 544 + /* video_ofld_voav_ofst */ 545 + .yfp1_htime = 140, 546 + .yfp2_htime = 2060, 547 + .max_pxcnt = 2199, 548 + .hspuls_begin = 2156, 549 + .hspuls_end = 44, 550 + .hspuls_switch = 44, 551 + .vspuls_begin = 140, 552 + .vspuls_end = 2059, 553 + .vspuls_bline = 0, 554 + .vspuls_eline = 4, 555 + .havon_begin = 148, 556 + .havon_end = 2067, 557 + .vavon_bline = 41, 558 + .vavon_eline = 1120, 559 + /* eqpuls_begin */ 560 + /* eqpuls_end */ 561 + /* eqpuls_bline */ 562 + /* eqpuls_eline */ 563 + .hso_begin = 44, 564 + .hso_end = 2156, 565 + .vso_begin = 2100, 566 + .vso_end = 2164, 567 + .vso_bline = 0, 568 + .vso_eline = 5, 569 + .vso_eline_present = true, 570 + /* sy_val */ 571 + /* sy2_val */ 572 + .max_lncnt = 1124, 573 + }, 574 + }; 575 + 576 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = { 577 + .encp = { 578 + .dvi_settings = 0xd, 579 + .video_mode = 0x4040, 580 + .video_mode_adv = 0x18, 581 + .video_prog_mode = 0x100, 582 + .video_prog_mode_present = true, 583 + .video_sync_mode = 0x7, 584 + .video_sync_mode_present = true, 585 + .video_yc_dly = 0, 586 + .video_yc_dly_present = true, 587 + .video_rgb_ctrl = 2, 588 + .video_rgb_ctrl_present = true, 589 + /* video_filt_ctrl */ 590 + /* video_ofld_voav_ofst */ 591 + .yfp1_htime = 271, 592 + .yfp2_htime = 2190, 593 + .max_pxcnt = 2639, 594 + .hspuls_begin = 44, 595 + .hspuls_end = 132, 596 + .hspuls_switch = 44, 597 + .vspuls_begin = 220, 598 + .vspuls_end = 2140, 599 + .vspuls_bline = 0, 600 + .vspuls_eline = 4, 601 + .havon_begin = 271, 602 + .havon_end = 2190, 603 + .vavon_bline = 41, 604 + .vavon_eline = 1120, 605 + /* eqpuls_begin */ 606 + /* eqpuls_end */ 607 + .eqpuls_bline = 0, 608 + .eqpuls_bline_present = true, 609 + .eqpuls_eline = 4, 610 + .eqpuls_eline_present = true, 611 + .hso_begin = 79, 612 + .hso_end = 123, 613 + .vso_begin = 79, 614 + .vso_end = 79, 615 + .vso_bline = 0, 616 + .vso_eline = 5, 617 + .vso_eline_present = true, 618 + /* sy_val */ 619 + /* sy2_val */ 620 + .max_lncnt = 1124, 621 + }, 622 + }; 623 + 624 + union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = { 625 + .encp = { 626 + .dvi_settings = 0x1, 627 + .video_mode = 0x4040, 628 + .video_mode_adv = 0x18, 629 + .video_prog_mode = 0x100, 630 + .video_prog_mode_present = true, 631 + /* video_sync_mode */ 632 + /* video_yc_dly */ 633 + /* video_rgb_ctrl */ 634 + .video_filt_ctrl = 0x1052, 635 + .video_filt_ctrl_present = true, 636 + /* video_ofld_voav_ofst */ 637 + .yfp1_htime = 140, 638 + .yfp2_htime = 2060, 639 + .max_pxcnt = 2199, 640 + .hspuls_begin = 2156, 641 + .hspuls_end = 44, 642 + .hspuls_switch = 44, 643 + .vspuls_begin = 140, 644 + .vspuls_end = 2059, 645 + .vspuls_bline = 0, 646 + .vspuls_eline = 4, 647 + .havon_begin = 148, 648 + .havon_end = 2067, 649 + .vavon_bline = 41, 650 + .vavon_eline = 1120, 651 + /* eqpuls_begin */ 652 + /* eqpuls_end */ 653 + /* eqpuls_bline */ 654 + /* eqpuls_eline */ 655 + .hso_begin = 44, 656 + .hso_end = 2156, 657 + .vso_begin = 2100, 658 + .vso_end = 2164, 659 + .vso_bline = 0, 660 + .vso_eline = 5, 661 + .vso_eline_present = true, 662 + /* sy_val */ 663 + /* sy2_val */ 664 + .max_lncnt = 1124, 665 + }, 666 + }; 667 + 668 + struct meson_hdmi_venc_vic_mode { 669 + unsigned int vic; 670 + union meson_hdmi_venc_mode *mode; 671 + } meson_hdmi_venc_vic_modes[] = { 672 + { 6, &meson_hdmi_enci_mode_480i }, 673 + { 7, &meson_hdmi_enci_mode_480i }, 674 + { 21, &meson_hdmi_enci_mode_576i }, 675 + { 22, &meson_hdmi_enci_mode_576i }, 676 + { 2, &meson_hdmi_encp_mode_480p }, 677 + { 3, &meson_hdmi_encp_mode_480p }, 678 + { 17, &meson_hdmi_encp_mode_576p }, 679 + { 18, &meson_hdmi_encp_mode_576p }, 680 + { 4, &meson_hdmi_encp_mode_720p60 }, 681 + { 19, &meson_hdmi_encp_mode_720p50 }, 682 + { 5, &meson_hdmi_encp_mode_1080i60 }, 683 + { 20, &meson_hdmi_encp_mode_1080i50 }, 684 + { 32, &meson_hdmi_encp_mode_1080p24 }, 685 + { 34, &meson_hdmi_encp_mode_1080p30 }, 686 + { 31, &meson_hdmi_encp_mode_1080p50 }, 687 + { 16, &meson_hdmi_encp_mode_1080p60 }, 688 + { 0, NULL}, /* sentinel */ 689 + }; 690 + 691 + static signed int to_signed(unsigned int a) 692 + { 693 + if (a <= 7) 694 + return a; 695 + else 696 + return a - 16; 697 + } 698 + 699 + static unsigned long modulo(unsigned long a, unsigned long b) 700 + { 701 + if (a >= b) 702 + return a - b; 703 + else 704 + return a; 705 + } 706 + 707 + bool meson_venc_hdmi_supported_vic(int vic) 708 + { 709 + struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; 710 + 711 + while (vmode->vic && vmode->mode) { 712 + if (vmode->vic == vic) 713 + return true; 714 + vmode++; 715 + } 716 + 717 + return false; 718 + } 719 + EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic); 720 + 721 + static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic) 722 + { 723 + struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; 724 + 725 + while (vmode->vic && vmode->mode) { 726 + if (vmode->vic == vic) 727 + return vmode->mode; 728 + vmode++; 729 + } 730 + 731 + return NULL; 732 + } 733 + 734 + bool meson_venc_hdmi_venc_repeat(int vic) 735 + { 736 + /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */ 737 + if (vic == 6 || vic == 7 || /* 480i */ 738 + vic == 21 || vic == 22 || /* 576i */ 739 + vic == 17 || vic == 18 || /* 576p */ 740 + vic == 2 || vic == 3 || /* 480p */ 741 + vic == 4 || /* 720p60 */ 742 + vic == 19 || /* 720p50 */ 743 + vic == 5 || /* 1080i60 */ 744 + vic == 20) /* 1080i50 */ 745 + return true; 746 + 747 + return false; 748 + } 749 + EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat); 750 + 751 + void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, 752 + struct drm_display_mode *mode) 753 + { 754 + union meson_hdmi_venc_mode *vmode = NULL; 755 + bool use_enci = false; 756 + bool venc_repeat = false; 757 + bool hdmi_repeat = false; 758 + unsigned int venc_hdmi_latency = 2; 759 + unsigned long total_pixels_venc = 0; 760 + unsigned long active_pixels_venc = 0; 761 + unsigned long front_porch_venc = 0; 762 + unsigned long hsync_pixels_venc = 0; 763 + unsigned long de_h_begin = 0; 764 + unsigned long de_h_end = 0; 765 + unsigned long de_v_begin_even = 0; 766 + unsigned long de_v_end_even = 0; 767 + unsigned long de_v_begin_odd = 0; 768 + unsigned long de_v_end_odd = 0; 769 + unsigned long hs_begin = 0; 770 + unsigned long hs_end = 0; 771 + unsigned long vs_adjust = 0; 772 + unsigned long vs_bline_evn = 0; 773 + unsigned long vs_eline_evn = 0; 774 + unsigned long vs_bline_odd = 0; 775 + unsigned long vs_eline_odd = 0; 776 + unsigned long vso_begin_evn = 0; 777 + unsigned long vso_begin_odd = 0; 778 + unsigned int eof_lines; 779 + unsigned int sof_lines; 780 + unsigned int vsync_lines; 781 + 782 + vmode = meson_venc_hdmi_get_vic_vmode(vic); 783 + if (!vmode) { 784 + dev_err(priv->dev, "%s: Fatal Error, unsupported vic %d\n", 785 + __func__, vic); 786 + return; 787 + } 788 + 789 + /* Use VENCI for 480i and 576i and double HDMI pixels */ 790 + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { 791 + hdmi_repeat = true; 792 + use_enci = true; 793 + venc_hdmi_latency = 1; 794 + } 795 + 796 + /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */ 797 + if (meson_venc_hdmi_venc_repeat(vic)) 798 + venc_repeat = true; 799 + 800 + eof_lines = mode->vsync_start - mode->vdisplay; 801 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) 802 + eof_lines /= 2; 803 + sof_lines = mode->vtotal - mode->vsync_end; 804 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) 805 + sof_lines /= 2; 806 + vsync_lines = mode->vsync_end - mode->vsync_start; 807 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) 808 + vsync_lines /= 2; 809 + 810 + total_pixels_venc = mode->htotal; 811 + if (hdmi_repeat) 812 + total_pixels_venc /= 2; 813 + if (venc_repeat) 814 + total_pixels_venc *= 2; 815 + 816 + active_pixels_venc = mode->hdisplay; 817 + if (hdmi_repeat) 818 + active_pixels_venc /= 2; 819 + if (venc_repeat) 820 + active_pixels_venc *= 2; 821 + 822 + front_porch_venc = (mode->hsync_start - mode->hdisplay); 823 + if (hdmi_repeat) 824 + front_porch_venc /= 2; 825 + if (venc_repeat) 826 + front_porch_venc *= 2; 827 + 828 + hsync_pixels_venc = (mode->hsync_end - mode->hsync_start); 829 + if (hdmi_repeat) 830 + hsync_pixels_venc /= 2; 831 + if (venc_repeat) 832 + hsync_pixels_venc *= 2; 833 + 834 + /* Disable VDACs */ 835 + writel_bits_relaxed(0x1f, 0x1f, 836 + priv->io_base + _REG(VENC_VDAC_SETTING)); 837 + 838 + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); 839 + writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); 840 + 841 + if (use_enci) { 842 + unsigned int lines_f0; 843 + unsigned int lines_f1; 844 + 845 + /* CVBS Filter settings */ 846 + writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL)); 847 + writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2)); 848 + 849 + /* Digital Video Select : Interlace, clk27 clk, external */ 850 + writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING)); 851 + 852 + /* Reset Video Mode */ 853 + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE)); 854 + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); 855 + 856 + /* Horizontal sync signal output */ 857 + writel_relaxed(vmode->enci.hso_begin, 858 + priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN)); 859 + writel_relaxed(vmode->enci.hso_end, 860 + priv->io_base + _REG(ENCI_SYNC_HSO_END)); 861 + 862 + /* Vertical Sync lines */ 863 + writel_relaxed(vmode->enci.vso_even, 864 + priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN)); 865 + writel_relaxed(vmode->enci.vso_odd, 866 + priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN)); 867 + 868 + /* Macrovision max amplitude change */ 869 + writel_relaxed(vmode->enci.macv_max_amp, 870 + priv->io_base + _REG(ENCI_MACV_MAX_AMP)); 871 + 872 + /* Video mode */ 873 + writel_relaxed(vmode->enci.video_prog_mode, 874 + priv->io_base + _REG(VENC_VIDEO_PROG_MODE)); 875 + writel_relaxed(vmode->enci.video_mode, 876 + priv->io_base + _REG(ENCI_VIDEO_MODE)); 877 + 878 + /* Advanced Video Mode : 879 + * Demux shifting 0x2 880 + * Blank line end at line17/22 881 + * High bandwidth Luma Filter 882 + * Low bandwidth Chroma Filter 883 + * Bypass luma low pass filter 884 + * No macrovision on CSYNC 885 + */ 886 + writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); 887 + 888 + writel(vmode->enci.sch_adjust, 889 + priv->io_base + _REG(ENCI_VIDEO_SCH)); 890 + 891 + /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */ 892 + writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE)); 893 + 894 + if (vmode->enci.yc_delay) 895 + writel_relaxed(vmode->enci.yc_delay, 896 + priv->io_base + _REG(ENCI_YC_DELAY)); 897 + 898 + 899 + /* UNreset Interlaced TV Encoder */ 900 + writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST)); 901 + 902 + /* Enable Vfifo2vd, Y_Cb_Y_Cr select */ 903 + writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); 904 + 905 + /* Timings */ 906 + writel_relaxed(vmode->enci.pixel_start, 907 + priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START)); 908 + writel_relaxed(vmode->enci.pixel_end, 909 + priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END)); 910 + 911 + writel_relaxed(vmode->enci.top_field_line_start, 912 + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START)); 913 + writel_relaxed(vmode->enci.top_field_line_end, 914 + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END)); 915 + 916 + writel_relaxed(vmode->enci.bottom_field_line_start, 917 + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START)); 918 + writel_relaxed(vmode->enci.bottom_field_line_end, 919 + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END)); 920 + 921 + /* Select ENCI for VIU */ 922 + meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI); 923 + 924 + /* Interlace video enable */ 925 + writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); 926 + 927 + lines_f0 = mode->vtotal >> 1; 928 + lines_f1 = lines_f0 + 1; 929 + 930 + de_h_begin = modulo(readl_relaxed(priv->io_base + 931 + _REG(ENCI_VFIFO2VD_PIXEL_START)) 932 + + venc_hdmi_latency, 933 + total_pixels_venc); 934 + de_h_end = modulo(de_h_begin + active_pixels_venc, 935 + total_pixels_venc); 936 + 937 + writel_relaxed(de_h_begin, 938 + priv->io_base + _REG(ENCI_DE_H_BEGIN)); 939 + writel_relaxed(de_h_end, 940 + priv->io_base + _REG(ENCI_DE_H_END)); 941 + 942 + de_v_begin_even = readl_relaxed(priv->io_base + 943 + _REG(ENCI_VFIFO2VD_LINE_TOP_START)); 944 + de_v_end_even = de_v_begin_even + mode->vdisplay; 945 + de_v_begin_odd = readl_relaxed(priv->io_base + 946 + _REG(ENCI_VFIFO2VD_LINE_BOT_START)); 947 + de_v_end_odd = de_v_begin_odd + mode->vdisplay; 948 + 949 + writel_relaxed(de_v_begin_even, 950 + priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN)); 951 + writel_relaxed(de_v_end_even, 952 + priv->io_base + _REG(ENCI_DE_V_END_EVEN)); 953 + writel_relaxed(de_v_begin_odd, 954 + priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD)); 955 + writel_relaxed(de_v_end_odd, 956 + priv->io_base + _REG(ENCI_DE_V_END_ODD)); 957 + 958 + /* Program Hsync timing */ 959 + hs_begin = de_h_end + front_porch_venc; 960 + if (de_h_end + front_porch_venc >= total_pixels_venc) { 961 + hs_begin -= total_pixels_venc; 962 + vs_adjust = 1; 963 + } else { 964 + hs_begin = de_h_end + front_porch_venc; 965 + vs_adjust = 0; 966 + } 967 + 968 + hs_end = modulo(hs_begin + hsync_pixels_venc, 969 + total_pixels_venc); 970 + writel_relaxed(hs_begin, 971 + priv->io_base + _REG(ENCI_DVI_HSO_BEGIN)); 972 + writel_relaxed(hs_end, 973 + priv->io_base + _REG(ENCI_DVI_HSO_END)); 974 + 975 + /* Program Vsync timing for even field */ 976 + if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) { 977 + vs_bline_evn = (de_v_end_odd - 1) 978 + + eof_lines 979 + + vs_adjust 980 + - lines_f1; 981 + vs_eline_evn = vs_bline_evn + vsync_lines; 982 + 983 + writel_relaxed(vs_bline_evn, 984 + priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN)); 985 + 986 + writel_relaxed(vs_eline_evn, 987 + priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN)); 988 + 989 + writel_relaxed(hs_begin, 990 + priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN)); 991 + writel_relaxed(hs_begin, 992 + priv->io_base + _REG(ENCI_DVI_VSO_END_EVN)); 993 + } else { 994 + vs_bline_odd = (de_v_end_odd - 1) 995 + + eof_lines 996 + + vs_adjust; 997 + 998 + writel_relaxed(vs_bline_odd, 999 + priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD)); 1000 + 1001 + writel_relaxed(hs_begin, 1002 + priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD)); 1003 + 1004 + if ((vs_bline_odd + vsync_lines) >= lines_f1) { 1005 + vs_eline_evn = vs_bline_odd 1006 + + vsync_lines 1007 + - lines_f1; 1008 + 1009 + writel_relaxed(vs_eline_evn, priv->io_base 1010 + + _REG(ENCI_DVI_VSO_ELINE_EVN)); 1011 + 1012 + writel_relaxed(hs_begin, priv->io_base 1013 + + _REG(ENCI_DVI_VSO_END_EVN)); 1014 + } else { 1015 + vs_eline_odd = vs_bline_odd 1016 + + vsync_lines; 1017 + 1018 + writel_relaxed(vs_eline_odd, priv->io_base 1019 + + _REG(ENCI_DVI_VSO_ELINE_ODD)); 1020 + 1021 + writel_relaxed(hs_begin, priv->io_base 1022 + + _REG(ENCI_DVI_VSO_END_ODD)); 1023 + } 1024 + } 1025 + 1026 + /* Program Vsync timing for odd field */ 1027 + if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) { 1028 + vs_bline_odd = (de_v_end_even - 1) 1029 + + (eof_lines + 1) 1030 + - lines_f0; 1031 + vs_eline_odd = vs_bline_odd + vsync_lines; 1032 + 1033 + writel_relaxed(vs_bline_odd, 1034 + priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD)); 1035 + 1036 + writel_relaxed(vs_eline_odd, 1037 + priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD)); 1038 + 1039 + vso_begin_odd = modulo(hs_begin 1040 + + (total_pixels_venc >> 1), 1041 + total_pixels_venc); 1042 + 1043 + writel_relaxed(vso_begin_odd, 1044 + priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD)); 1045 + writel_relaxed(vso_begin_odd, 1046 + priv->io_base + _REG(ENCI_DVI_VSO_END_ODD)); 1047 + } else { 1048 + vs_bline_evn = (de_v_end_even - 1) 1049 + + (eof_lines + 1); 1050 + 1051 + writel_relaxed(vs_bline_evn, 1052 + priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN)); 1053 + 1054 + vso_begin_evn = modulo(hs_begin 1055 + + (total_pixels_venc >> 1), 1056 + total_pixels_venc); 1057 + 1058 + writel_relaxed(vso_begin_evn, priv->io_base 1059 + + _REG(ENCI_DVI_VSO_BEGIN_EVN)); 1060 + 1061 + if (vs_bline_evn + vsync_lines >= lines_f0) { 1062 + vs_eline_odd = vs_bline_evn 1063 + + vsync_lines 1064 + - lines_f0; 1065 + 1066 + writel_relaxed(vs_eline_odd, priv->io_base 1067 + + _REG(ENCI_DVI_VSO_ELINE_ODD)); 1068 + 1069 + writel_relaxed(vso_begin_evn, priv->io_base 1070 + + _REG(ENCI_DVI_VSO_END_ODD)); 1071 + } else { 1072 + vs_eline_evn = vs_bline_evn + vsync_lines; 1073 + 1074 + writel_relaxed(vs_eline_evn, priv->io_base 1075 + + _REG(ENCI_DVI_VSO_ELINE_EVN)); 1076 + 1077 + writel_relaxed(vso_begin_evn, priv->io_base 1078 + + _REG(ENCI_DVI_VSO_END_EVN)); 1079 + } 1080 + } 1081 + } else { 1082 + writel_relaxed(vmode->encp.dvi_settings, 1083 + priv->io_base + _REG(VENC_DVI_SETTING)); 1084 + writel_relaxed(vmode->encp.video_mode, 1085 + priv->io_base + _REG(ENCP_VIDEO_MODE)); 1086 + writel_relaxed(vmode->encp.video_mode_adv, 1087 + priv->io_base + _REG(ENCP_VIDEO_MODE_ADV)); 1088 + if (vmode->encp.video_prog_mode_present) 1089 + writel_relaxed(vmode->encp.video_prog_mode, 1090 + priv->io_base + _REG(VENC_VIDEO_PROG_MODE)); 1091 + if (vmode->encp.video_sync_mode_present) 1092 + writel_relaxed(vmode->encp.video_sync_mode, 1093 + priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE)); 1094 + if (vmode->encp.video_yc_dly_present) 1095 + writel_relaxed(vmode->encp.video_yc_dly, 1096 + priv->io_base + _REG(ENCP_VIDEO_YC_DLY)); 1097 + if (vmode->encp.video_rgb_ctrl_present) 1098 + writel_relaxed(vmode->encp.video_rgb_ctrl, 1099 + priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL)); 1100 + if (vmode->encp.video_filt_ctrl_present) 1101 + writel_relaxed(vmode->encp.video_filt_ctrl, 1102 + priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL)); 1103 + if (vmode->encp.video_ofld_voav_ofst_present) 1104 + writel_relaxed(vmode->encp.video_ofld_voav_ofst, 1105 + priv->io_base 1106 + + _REG(ENCP_VIDEO_OFLD_VOAV_OFST)); 1107 + writel_relaxed(vmode->encp.yfp1_htime, 1108 + priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME)); 1109 + writel_relaxed(vmode->encp.yfp2_htime, 1110 + priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME)); 1111 + writel_relaxed(vmode->encp.max_pxcnt, 1112 + priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT)); 1113 + writel_relaxed(vmode->encp.hspuls_begin, 1114 + priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN)); 1115 + writel_relaxed(vmode->encp.hspuls_end, 1116 + priv->io_base + _REG(ENCP_VIDEO_HSPULS_END)); 1117 + writel_relaxed(vmode->encp.hspuls_switch, 1118 + priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH)); 1119 + writel_relaxed(vmode->encp.vspuls_begin, 1120 + priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN)); 1121 + writel_relaxed(vmode->encp.vspuls_end, 1122 + priv->io_base + _REG(ENCP_VIDEO_VSPULS_END)); 1123 + writel_relaxed(vmode->encp.vspuls_bline, 1124 + priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE)); 1125 + writel_relaxed(vmode->encp.vspuls_eline, 1126 + priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE)); 1127 + if (vmode->encp.eqpuls_begin_present) 1128 + writel_relaxed(vmode->encp.eqpuls_begin, 1129 + priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN)); 1130 + if (vmode->encp.eqpuls_end_present) 1131 + writel_relaxed(vmode->encp.eqpuls_end, 1132 + priv->io_base + _REG(ENCP_VIDEO_EQPULS_END)); 1133 + if (vmode->encp.eqpuls_bline_present) 1134 + writel_relaxed(vmode->encp.eqpuls_bline, 1135 + priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE)); 1136 + if (vmode->encp.eqpuls_eline_present) 1137 + writel_relaxed(vmode->encp.eqpuls_eline, 1138 + priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE)); 1139 + writel_relaxed(vmode->encp.havon_begin, 1140 + priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN)); 1141 + writel_relaxed(vmode->encp.havon_end, 1142 + priv->io_base + _REG(ENCP_VIDEO_HAVON_END)); 1143 + writel_relaxed(vmode->encp.vavon_bline, 1144 + priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE)); 1145 + writel_relaxed(vmode->encp.vavon_eline, 1146 + priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE)); 1147 + writel_relaxed(vmode->encp.hso_begin, 1148 + priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN)); 1149 + writel_relaxed(vmode->encp.hso_end, 1150 + priv->io_base + _REG(ENCP_VIDEO_HSO_END)); 1151 + writel_relaxed(vmode->encp.vso_begin, 1152 + priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN)); 1153 + writel_relaxed(vmode->encp.vso_end, 1154 + priv->io_base + _REG(ENCP_VIDEO_VSO_END)); 1155 + writel_relaxed(vmode->encp.vso_bline, 1156 + priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE)); 1157 + if (vmode->encp.vso_eline_present) 1158 + writel_relaxed(vmode->encp.vso_eline, 1159 + priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE)); 1160 + if (vmode->encp.sy_val_present) 1161 + writel_relaxed(vmode->encp.sy_val, 1162 + priv->io_base + _REG(ENCP_VIDEO_SY_VAL)); 1163 + if (vmode->encp.sy2_val_present) 1164 + writel_relaxed(vmode->encp.sy2_val, 1165 + priv->io_base + _REG(ENCP_VIDEO_SY2_VAL)); 1166 + writel_relaxed(vmode->encp.max_lncnt, 1167 + priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT)); 1168 + 1169 + writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); 1170 + 1171 + /* Set DE signal’s polarity is active high */ 1172 + writel_bits_relaxed(BIT(14), BIT(14), 1173 + priv->io_base + _REG(ENCP_VIDEO_MODE)); 1174 + 1175 + /* Program DE timing */ 1176 + de_h_begin = modulo(readl_relaxed(priv->io_base + 1177 + _REG(ENCP_VIDEO_HAVON_BEGIN)) 1178 + + venc_hdmi_latency, 1179 + total_pixels_venc); 1180 + de_h_end = modulo(de_h_begin + active_pixels_venc, 1181 + total_pixels_venc); 1182 + 1183 + writel_relaxed(de_h_begin, 1184 + priv->io_base + _REG(ENCP_DE_H_BEGIN)); 1185 + writel_relaxed(de_h_end, 1186 + priv->io_base + _REG(ENCP_DE_H_END)); 1187 + 1188 + /* Program DE timing for even field */ 1189 + de_v_begin_even = readl_relaxed(priv->io_base 1190 + + _REG(ENCP_VIDEO_VAVON_BLINE)); 1191 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) 1192 + de_v_end_even = de_v_begin_even + 1193 + (mode->vdisplay / 2); 1194 + else 1195 + de_v_end_even = de_v_begin_even + mode->vdisplay; 1196 + 1197 + writel_relaxed(de_v_begin_even, 1198 + priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN)); 1199 + writel_relaxed(de_v_end_even, 1200 + priv->io_base + _REG(ENCP_DE_V_END_EVEN)); 1201 + 1202 + /* Program DE timing for odd field if needed */ 1203 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1204 + unsigned int ofld_voav_ofst = 1205 + readl_relaxed(priv->io_base + 1206 + _REG(ENCP_VIDEO_OFLD_VOAV_OFST)); 1207 + de_v_begin_odd = to_signed((ofld_voav_ofst & 0xf0) >> 4) 1208 + + de_v_begin_even 1209 + + ((mode->vtotal - 1) / 2); 1210 + de_v_end_odd = de_v_begin_odd + (mode->vdisplay / 2); 1211 + 1212 + writel_relaxed(de_v_begin_odd, 1213 + priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD)); 1214 + writel_relaxed(de_v_end_odd, 1215 + priv->io_base + _REG(ENCP_DE_V_END_ODD)); 1216 + } 1217 + 1218 + /* Program Hsync timing */ 1219 + if ((de_h_end + front_porch_venc) >= total_pixels_venc) { 1220 + hs_begin = de_h_end 1221 + + front_porch_venc 1222 + - total_pixels_venc; 1223 + vs_adjust = 1; 1224 + } else { 1225 + hs_begin = de_h_end 1226 + + front_porch_venc; 1227 + vs_adjust = 0; 1228 + } 1229 + 1230 + hs_end = modulo(hs_begin + hsync_pixels_venc, 1231 + total_pixels_venc); 1232 + 1233 + writel_relaxed(hs_begin, 1234 + priv->io_base + _REG(ENCP_DVI_HSO_BEGIN)); 1235 + writel_relaxed(hs_end, 1236 + priv->io_base + _REG(ENCP_DVI_HSO_END)); 1237 + 1238 + /* Program Vsync timing for even field */ 1239 + if (de_v_begin_even >= 1240 + (sof_lines + vsync_lines + (1 - vs_adjust))) 1241 + vs_bline_evn = de_v_begin_even 1242 + - sof_lines 1243 + - vsync_lines 1244 + - (1 - vs_adjust); 1245 + else 1246 + vs_bline_evn = mode->vtotal 1247 + + de_v_begin_even 1248 + - sof_lines 1249 + - vsync_lines 1250 + - (1 - vs_adjust); 1251 + 1252 + vs_eline_evn = modulo(vs_bline_evn + vsync_lines, 1253 + mode->vtotal); 1254 + 1255 + writel_relaxed(vs_bline_evn, 1256 + priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN)); 1257 + writel_relaxed(vs_eline_evn, 1258 + priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN)); 1259 + 1260 + vso_begin_evn = hs_begin; 1261 + writel_relaxed(vso_begin_evn, 1262 + priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN)); 1263 + writel_relaxed(vso_begin_evn, 1264 + priv->io_base + _REG(ENCP_DVI_VSO_END_EVN)); 1265 + 1266 + /* Program Vsync timing for odd field if needed */ 1267 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1268 + vs_bline_odd = (de_v_begin_odd - 1) 1269 + - sof_lines 1270 + - vsync_lines; 1271 + vs_eline_odd = (de_v_begin_odd - 1) 1272 + - vsync_lines; 1273 + vso_begin_odd = modulo(hs_begin 1274 + + (total_pixels_venc >> 1), 1275 + total_pixels_venc); 1276 + 1277 + writel_relaxed(vs_bline_odd, 1278 + priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD)); 1279 + writel_relaxed(vs_eline_odd, 1280 + priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD)); 1281 + writel_relaxed(vso_begin_odd, 1282 + priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD)); 1283 + writel_relaxed(vso_begin_odd, 1284 + priv->io_base + _REG(ENCP_DVI_VSO_END_ODD)); 1285 + } 1286 + 1287 + /* Select ENCP for VIU */ 1288 + meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP); 1289 + } 1290 + 1291 + writel_relaxed((use_enci ? 1 : 2) | 1292 + (mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) | 1293 + (mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) | 1294 + 4 << 5 | 1295 + (venc_repeat ? 1 << 8 : 0) | 1296 + (hdmi_repeat ? 1 << 12 : 0), 1297 + priv->io_base + _REG(VPU_HDMI_SETTING)); 1298 + 1299 + priv->venc.hdmi_repeat = hdmi_repeat; 1300 + priv->venc.venc_repeat = venc_repeat; 1301 + priv->venc.hdmi_use_enci = use_enci; 1302 + 1303 + priv->venc.current_mode = MESON_VENC_MODE_HDMI; 1304 + } 1305 + EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set); 125 1306 126 1307 void meson_venci_cvbs_mode_set(struct meson_drm *priv, 127 1308 struct meson_cvbs_enci_mode *mode) ··· 1467 222 /* Analog Synchronization and color burst value adjust */ 1468 223 writel_relaxed(mode->analog_sync_adj, 1469 224 priv->io_base + _REG(ENCI_SYNC_ADJ)); 1470 - 1471 - /* Setup 27MHz vclk2 for ENCI and VDAC */ 1472 - meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS); 1473 225 1474 226 priv->venc.current_mode = mode->mode_tag; 1475 227 }
+7
drivers/gpu/drm/meson/meson_venc.h
··· 30 30 MESON_VENC_MODE_NONE = 0, 31 31 MESON_VENC_MODE_CVBS_PAL, 32 32 MESON_VENC_MODE_CVBS_NTSC, 33 + MESON_VENC_MODE_HDMI, 33 34 }; 34 35 35 36 struct meson_cvbs_enci_mode { ··· 57 56 unsigned int analog_sync_adj; 58 57 }; 59 58 59 + /* HDMI Clock parameters */ 60 + bool meson_venc_hdmi_supported_vic(int vic); 61 + bool meson_venc_hdmi_venc_repeat(int vic); 62 + 60 63 /* CVBS Timings and Parameters */ 61 64 extern struct meson_cvbs_enci_mode meson_cvbs_enci_pal; 62 65 extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc; 63 66 64 67 void meson_venci_cvbs_mode_set(struct meson_drm *priv, 65 68 struct meson_cvbs_enci_mode *mode); 69 + void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, 70 + struct drm_display_mode *mode); 66 71 unsigned int meson_venci_get_field(struct meson_drm *priv); 67 72 68 73 void meson_venc_enable_vsync(struct meson_drm *priv);
+13 -17
drivers/gpu/drm/meson/meson_venc_cvbs.c
··· 32 32 33 33 #include "meson_venc_cvbs.h" 34 34 #include "meson_venc.h" 35 + #include "meson_vclk.h" 35 36 #include "meson_registers.h" 36 37 37 38 /* HHI VDAC Registers */ ··· 195 194 { 196 195 struct meson_venc_cvbs *meson_venc_cvbs = 197 196 encoder_to_meson_venc_cvbs(encoder); 197 + struct meson_drm *priv = meson_venc_cvbs->priv; 198 198 int i; 199 199 200 200 for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { 201 201 struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; 202 202 203 203 if (drm_mode_equal(mode, &meson_mode->mode)) { 204 - meson_venci_cvbs_mode_set(meson_venc_cvbs->priv, 204 + meson_venci_cvbs_mode_set(priv, 205 205 meson_mode->enci); 206 + 207 + /* Setup 27MHz vclk2 for ENCI and VDAC */ 208 + meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, 209 + MESON_VCLK_CVBS, MESON_VCLK_CVBS, 210 + MESON_VCLK_CVBS, true); 206 211 break; 207 212 } 208 213 } ··· 224 217 225 218 static bool meson_venc_cvbs_connector_is_available(struct meson_drm *priv) 226 219 { 227 - struct device_node *ep, *remote; 220 + struct device_node *remote; 228 221 229 - /* CVBS VDAC output is on the first port, first endpoint */ 230 - ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0); 231 - if (!ep) 222 + remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0); 223 + if (!remote) 232 224 return false; 233 225 234 - 235 - /* If the endpoint node exists, consider it enabled */ 236 - remote = of_graph_get_remote_port(ep); 237 - if (remote) { 238 - of_node_put(ep); 239 - return true; 240 - } 241 - 242 - of_node_put(ep); 243 226 of_node_put(remote); 244 - 245 - return false; 227 + return true; 246 228 } 247 229 248 230 int meson_venc_cvbs_create(struct meson_drm *priv) ··· 244 248 245 249 if (!meson_venc_cvbs_connector_is_available(priv)) { 246 250 dev_info(drm->dev, "CVBS Output connector not available\n"); 247 - return -ENODEV; 251 + return 0; 248 252 } 249 253 250 254 meson_venc_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_venc_cvbs),
+5 -1
drivers/gpu/drm/meson/meson_viu.c
··· 28 28 #include "meson_canvas.h" 29 29 #include "meson_registers.h" 30 30 31 - /* 31 + /** 32 + * DOC: Video Input Unit 33 + * 32 34 * VIU Handles the Pixel scanout and the basic Colorspace conversions 33 35 * We handle the following features : 36 + * 34 37 * - OSD1 RGB565/RGB888/xRGB8888 scanout 35 38 * - RGB conversion to x/cb/cr 36 39 * - Progressive or Interlace buffer scanout ··· 41 38 * - HDR OSD matrix for GXL/GXM 42 39 * 43 40 * What is missing : 41 + * 44 42 * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes 45 43 * - YUV4:2:2 Y0CbY1Cr scanout 46 44 * - Conversion to YUV 4:4:4 from 4:2:2 input
+6 -2
drivers/gpu/drm/meson/meson_vpp.c
··· 25 25 #include "meson_vpp.h" 26 26 #include "meson_registers.h" 27 27 28 - /* 28 + /** 29 + * DOC: Video Post Processing 30 + * 29 31 * VPP Handles all the Post Processing after the Scanout from the VIU 30 32 * We handle the following post processings : 31 - * - Postblend : Blends the OSD1 only 33 + * 34 + * - Postblend, Blends the OSD1 only 32 35 * We exclude OSD2, VS1, VS1 and Preblend output 33 36 * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and 34 37 * use it only for interlace scanout 35 38 * - Intermediate FIFO with default Amlogic values 36 39 * 37 40 * What is missing : 41 + * 38 42 * - Preblend for video overlay pre-scaling 39 43 * - OSD2 support for cursor framebuffer 40 44 * - Video pre-scaling before postblend
+2
drivers/gpu/drm/meson/meson_vpp.h
··· 23 23 24 24 /* Mux VIU/VPP to ENCI */ 25 25 #define MESON_VIU_VPP_MUX_ENCI 0x5 26 + /* Mux VIU/VPP to ENCP */ 27 + #define MESON_VIU_VPP_MUX_ENCP 0xA 26 28 27 29 void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux); 28 30
+2 -1
drivers/gpu/drm/mgag200/mgag200_mode.c
··· 1393 1393 * but it's a requirement that we provide the function 1394 1394 */ 1395 1395 static int mga_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 1396 - u16 *blue, uint32_t size) 1396 + u16 *blue, uint32_t size, 1397 + struct drm_modeset_acquire_ctx *ctx) 1397 1398 { 1398 1399 struct mga_crtc *mga_crtc = to_mga_crtc(crtc); 1399 1400 int i;
+1 -1
drivers/gpu/drm/msm/dsi/dsi_host.c
··· 1635 1635 } 1636 1636 1637 1637 /* Get panel node from the output port's endpoint data */ 1638 - device_node = of_graph_get_remote_port_parent(endpoint); 1638 + device_node = of_graph_get_remote_node(np, 1, 0); 1639 1639 if (!device_node) { 1640 1640 dev_dbg(dev, "%s: no valid device\n", __func__); 1641 1641 goto err;
+1 -27
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
··· 225 225 return 0; 226 226 } 227 227 228 - static struct device_node *mdp4_detect_lcdc_panel(struct drm_device *dev) 229 - { 230 - struct device_node *endpoint, *panel_node; 231 - struct device_node *np = dev->dev->of_node; 232 - 233 - /* 234 - * LVDS/LCDC is the first port described in the list of ports in the 235 - * MDP4 DT node. 236 - */ 237 - endpoint = of_graph_get_endpoint_by_regs(np, 0, -1); 238 - if (!endpoint) { 239 - DBG("no LVDS remote endpoint\n"); 240 - return NULL; 241 - } 242 - 243 - panel_node = of_graph_get_remote_port_parent(endpoint); 244 - if (!panel_node) { 245 - DBG("no valid panel node in LVDS endpoint\n"); 246 - of_node_put(endpoint); 247 - return NULL; 248 - } 249 - 250 - of_node_put(endpoint); 251 - 252 - return panel_node; 253 - } 254 228 255 229 static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, 256 230 int intf_type) ··· 243 269 * bail out early if there is no panel node (no need to 244 270 * initialize LCDC encoder and LVDS connector) 245 271 */ 246 - panel_node = mdp4_detect_lcdc_panel(dev); 272 + panel_node = of_graph_get_remote_node(dev->dev->of_node, 0, 0); 247 273 if (!panel_node) 248 274 return 0; 249 275
+6 -34
drivers/gpu/drm/mxsfb/mxsfb_out.c
··· 19 19 #include <drm/drm_crtc_helper.h> 20 20 #include <drm/drm_fb_cma_helper.h> 21 21 #include <drm/drm_gem_cma_helper.h> 22 + #include <drm/drm_of.h> 22 23 #include <drm/drm_panel.h> 23 24 #include <drm/drm_plane_helper.h> 24 25 #include <drm/drm_simple_kms_helper.h> ··· 83 82 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 84 83 }; 85 84 86 - static int mxsfb_attach_endpoint(struct drm_device *drm, 87 - const struct of_endpoint *ep) 85 + int mxsfb_create_output(struct drm_device *drm) 88 86 { 89 87 struct mxsfb_drm_private *mxsfb = drm->dev_private; 90 - struct device_node *np; 91 88 struct drm_panel *panel; 92 - int ret = -EPROBE_DEFER; 89 + int ret; 93 90 94 - np = of_graph_get_remote_port_parent(ep->local_node); 95 - panel = of_drm_find_panel(np); 96 - of_node_put(np); 97 - 98 - if (!panel) 99 - return -EPROBE_DEFER; 91 + ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, NULL); 92 + if (ret) 93 + return ret; 100 94 101 95 mxsfb->connector.dpms = DRM_MODE_DPMS_OFF; 102 96 mxsfb->connector.polled = 0; ··· 104 108 mxsfb->panel = panel; 105 109 106 110 return ret; 107 - } 108 - 109 - int mxsfb_create_output(struct drm_device *drm) 110 - { 111 - struct mxsfb_drm_private *mxsfb = drm->dev_private; 112 - struct device_node *ep_np = NULL; 113 - struct of_endpoint ep; 114 - int ret; 115 - 116 - for_each_endpoint_of_node(drm->dev->of_node, ep_np) { 117 - ret = of_graph_parse_endpoint(ep_np, &ep); 118 - if (!ret) 119 - ret = mxsfb_attach_endpoint(drm, &ep); 120 - 121 - if (ret) { 122 - of_node_put(ep_np); 123 - return ret; 124 - } 125 - } 126 - 127 - if (!mxsfb->panel) 128 - return -EPROBE_DEFER; 129 - 130 - return 0; 131 111 }
+2 -1
drivers/gpu/drm/nouveau/dispnv04/crtc.c
··· 788 788 789 789 static int 790 790 nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, 791 - uint32_t size) 791 + uint32_t size, 792 + struct drm_modeset_acquire_ctx *ctx) 792 793 { 793 794 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 794 795 int i;
+2 -11
drivers/gpu/drm/nouveau/nv50_display.c
··· 2210 2210 } 2211 2211 } 2212 2212 2213 - static int 2214 - nv50_head_mode_set_base_atomic(struct drm_crtc *crtc, 2215 - struct drm_framebuffer *fb, int x, int y, 2216 - enum mode_set_atomic state) 2217 - { 2218 - WARN_ON(1); 2219 - return 0; 2220 - } 2221 - 2222 2213 static const struct drm_crtc_helper_funcs 2223 2214 nv50_head_help = { 2224 - .mode_set_base_atomic = nv50_head_mode_set_base_atomic, 2225 2215 .load_lut = nv50_head_lut_load, 2226 2216 .atomic_check = nv50_head_atomic_check, 2227 2217 }; 2228 2218 2229 2219 static int 2230 2220 nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, 2231 - uint32_t size) 2221 + uint32_t size, 2222 + struct drm_modeset_acquire_ctx *ctx) 2232 2223 { 2233 2224 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 2234 2225 u32 i;
+1 -1
drivers/gpu/drm/omapdrm/dss/dpi.c
··· 877 877 if (!dpi) 878 878 return -ENOMEM; 879 879 880 - ep = omapdss_of_get_next_endpoint(port, NULL); 880 + ep = of_get_next_child(port, NULL); 881 881 if (!ep) 882 882 return 0; 883 883
+2 -1
drivers/gpu/drm/omapdrm/dss/dsi.c
··· 39 39 #include <linux/debugfs.h> 40 40 #include <linux/pm_runtime.h> 41 41 #include <linux/of.h> 42 + #include <linux/of_graph.h> 42 43 #include <linux/of_platform.h> 43 44 #include <linux/component.h> 44 45 ··· 5091 5090 struct device_node *ep; 5092 5091 struct omap_dsi_pin_config pin_cfg; 5093 5092 5094 - ep = omapdss_of_get_first_endpoint(node); 5093 + ep = of_graph_get_endpoint_by_regs(node, 0, 0); 5095 5094 if (!ep) 5096 5095 return 0; 5097 5096
+3 -99
drivers/gpu/drm/omapdrm/dss/dss-of.c
··· 16 16 #include <linux/err.h> 17 17 #include <linux/module.h> 18 18 #include <linux/of.h> 19 + #include <linux/of_graph.h> 19 20 #include <linux/seq_file.h> 20 21 21 22 #include "omapdss.h" 22 - 23 - struct device_node * 24 - omapdss_of_get_next_port(const struct device_node *parent, 25 - struct device_node *prev) 26 - { 27 - struct device_node *port = NULL; 28 - 29 - if (!parent) 30 - return NULL; 31 - 32 - if (!prev) { 33 - struct device_node *ports; 34 - /* 35 - * It's the first call, we have to find a port subnode 36 - * within this node or within an optional 'ports' node. 37 - */ 38 - ports = of_get_child_by_name(parent, "ports"); 39 - if (ports) 40 - parent = ports; 41 - 42 - port = of_get_child_by_name(parent, "port"); 43 - 44 - /* release the 'ports' node */ 45 - of_node_put(ports); 46 - } else { 47 - struct device_node *ports; 48 - 49 - ports = of_get_parent(prev); 50 - if (!ports) 51 - return NULL; 52 - 53 - do { 54 - port = of_get_next_child(ports, prev); 55 - if (!port) { 56 - of_node_put(ports); 57 - return NULL; 58 - } 59 - prev = port; 60 - } while (of_node_cmp(port->name, "port") != 0); 61 - 62 - of_node_put(ports); 63 - } 64 - 65 - return port; 66 - } 67 - EXPORT_SYMBOL_GPL(omapdss_of_get_next_port); 68 - 69 - struct device_node * 70 - omapdss_of_get_next_endpoint(const struct device_node *parent, 71 - struct device_node *prev) 72 - { 73 - struct device_node *ep = NULL; 74 - 75 - if (!parent) 76 - return NULL; 77 - 78 - do { 79 - ep = of_get_next_child(parent, prev); 80 - if (!ep) 81 - return NULL; 82 - prev = ep; 83 - } while (of_node_cmp(ep->name, "endpoint") != 0); 84 - 85 - return ep; 86 - } 87 - EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); 88 23 89 24 struct device_node *dss_of_port_get_parent_device(struct device_node *port) 90 25 { ··· 59 124 } 60 125 EXPORT_SYMBOL_GPL(dss_of_port_get_port_number); 61 126 62 - static struct device_node *omapdss_of_get_remote_port(const struct device_node *node) 63 - { 64 - struct device_node *np; 65 - 66 - np = of_parse_phandle(node, "remote-endpoint", 0); 67 - if (!np) 68 - return NULL; 69 - 70 - np = of_get_next_parent(np); 71 - 72 - return np; 73 - } 74 - 75 - struct device_node * 76 - omapdss_of_get_first_endpoint(const struct device_node *parent) 77 - { 78 - struct device_node *port, *ep; 79 - 80 - port = omapdss_of_get_next_port(parent, NULL); 81 - 82 - if (!port) 83 - return NULL; 84 - 85 - ep = omapdss_of_get_next_endpoint(port, NULL); 86 - 87 - of_node_put(port); 88 - 89 - return ep; 90 - } 91 - EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint); 92 - 93 127 struct omap_dss_device * 94 128 omapdss_of_find_source_for_first_ep(struct device_node *node) 95 129 { ··· 66 162 struct device_node *src_port; 67 163 struct omap_dss_device *src; 68 164 69 - ep = omapdss_of_get_first_endpoint(node); 165 + ep = of_graph_get_endpoint_by_regs(node, 0, 0); 70 166 if (!ep) 71 167 return ERR_PTR(-EINVAL); 72 168 73 - src_port = omapdss_of_get_remote_port(ep); 169 + src_port = of_graph_get_remote_port(ep); 74 170 if (!src_port) { 75 171 of_node_put(ep); 76 172 return ERR_PTR(-EINVAL);
+13 -48
drivers/gpu/drm/omapdrm/dss/dss.c
··· 38 38 #include <linux/mfd/syscon.h> 39 39 #include <linux/regmap.h> 40 40 #include <linux/of.h> 41 + #include <linux/of_graph.h> 41 42 #include <linux/regulator/consumer.h> 42 43 #include <linux/suspend.h> 43 44 #include <linux/component.h> ··· 1036 1035 { 1037 1036 struct device_node *parent = pdev->dev.of_node; 1038 1037 struct device_node *port; 1039 - int r; 1038 + int i; 1040 1039 1041 - if (parent == NULL) 1042 - return 0; 1043 - 1044 - port = omapdss_of_get_next_port(parent, NULL); 1045 - if (!port) 1046 - return 0; 1047 - 1048 - if (dss.feat->num_ports == 0) 1049 - return 0; 1050 - 1051 - do { 1052 - enum omap_display_type port_type; 1053 - u32 reg; 1054 - 1055 - r = of_property_read_u32(port, "reg", &reg); 1056 - if (r) 1057 - reg = 0; 1058 - 1059 - if (reg >= dss.feat->num_ports) 1040 + for (i = 0; i < dss.feat->num_ports; i++) { 1041 + port = of_graph_get_port_by_id(parent, i); 1042 + if (!port) 1060 1043 continue; 1061 1044 1062 - port_type = dss.feat->ports[reg]; 1063 - 1064 - switch (port_type) { 1045 + switch (dss.feat->ports[i]) { 1065 1046 case OMAP_DISPLAY_TYPE_DPI: 1066 1047 dpi_init_port(pdev, port); 1067 1048 break; ··· 1053 1070 default: 1054 1071 break; 1055 1072 } 1056 - } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); 1073 + } 1057 1074 1058 1075 return 0; 1059 1076 } ··· 1062 1079 { 1063 1080 struct device_node *parent = pdev->dev.of_node; 1064 1081 struct device_node *port; 1082 + int i; 1065 1083 1066 - if (parent == NULL) 1067 - return; 1068 - 1069 - port = omapdss_of_get_next_port(parent, NULL); 1070 - if (!port) 1071 - return; 1072 - 1073 - if (dss.feat->num_ports == 0) 1074 - return; 1075 - 1076 - do { 1077 - enum omap_display_type port_type; 1078 - u32 reg; 1079 - int r; 1080 - 1081 - r = of_property_read_u32(port, "reg", &reg); 1082 - if (r) 1083 - reg = 0; 1084 - 1085 - if (reg >= dss.feat->num_ports) 1084 + for (i = 0; i < dss.feat->num_ports; i++) { 1085 + port = of_graph_get_port_by_id(parent, i); 1086 + if (!port) 1086 1087 continue; 1087 1088 1088 - port_type = dss.feat->ports[reg]; 1089 - 1090 - switch (port_type) { 1089 + switch (dss.feat->ports[i]) { 1091 1090 case OMAP_DISPLAY_TYPE_DPI: 1092 1091 dpi_uninit_port(port); 1093 1092 break; ··· 1079 1114 default: 1080 1115 break; 1081 1116 } 1082 - } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); 1117 + } 1083 1118 } 1084 1119 1085 1120 static int dss_video_pll_probe(struct platform_device *pdev)
+2 -1
drivers/gpu/drm/omapdrm/dss/hdmi4.c
··· 34 34 #include <linux/regulator/consumer.h> 35 35 #include <linux/component.h> 36 36 #include <linux/of.h> 37 + #include <linux/of_graph.h> 37 38 #include <sound/omap-hdmi-audio.h> 38 39 39 40 #include "omapdss.h" ··· 547 546 struct device_node *ep; 548 547 int r; 549 548 550 - ep = omapdss_of_get_first_endpoint(node); 549 + ep = of_graph_get_endpoint_by_regs(node, 0, 0); 551 550 if (!ep) 552 551 return 0; 553 552
+2 -1
drivers/gpu/drm/omapdrm/dss/hdmi5.c
··· 39 39 #include <linux/regulator/consumer.h> 40 40 #include <linux/component.h> 41 41 #include <linux/of.h> 42 + #include <linux/of_graph.h> 42 43 #include <sound/omap-hdmi-audio.h> 43 44 44 45 #include "omapdss.h" ··· 573 572 struct device_node *ep; 574 573 int r; 575 574 576 - ep = omapdss_of_get_first_endpoint(node); 575 + ep = of_graph_get_endpoint_by_regs(node, 0, 0); 577 576 if (!ep) 578 577 return 0; 579 578
-11
drivers/gpu/drm/omapdrm/dss/omapdss.h
··· 830 830 return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE; 831 831 } 832 832 833 - struct device_node * 834 - omapdss_of_get_next_port(const struct device_node *parent, 835 - struct device_node *prev); 836 - 837 - struct device_node * 838 - omapdss_of_get_next_endpoint(const struct device_node *parent, 839 - struct device_node *prev); 840 - 841 - struct device_node * 842 - omapdss_of_get_first_endpoint(const struct device_node *parent); 843 - 844 833 struct omap_dss_device * 845 834 omapdss_of_find_source_for_first_ep(struct device_node *node); 846 835
+1 -1
drivers/gpu/drm/omapdrm/dss/sdi.c
··· 414 414 u32 datapairs; 415 415 int r; 416 416 417 - ep = omapdss_of_get_next_endpoint(port, NULL); 417 + ep = of_get_next_child(port, NULL); 418 418 if (!ep) 419 419 return 0; 420 420
+2 -1
drivers/gpu/drm/omapdrm/dss/venc.c
··· 35 35 #include <linux/regulator/consumer.h> 36 36 #include <linux/pm_runtime.h> 37 37 #include <linux/of.h> 38 + #include <linux/of_graph.h> 38 39 #include <linux/component.h> 39 40 40 41 #include "omapdss.h" ··· 819 818 u32 channels; 820 819 int r; 821 820 822 - ep = omapdss_of_get_first_endpoint(node); 821 + ep = of_graph_get_endpoint_by_regs(node, 0, 0); 823 822 if (!ep) 824 823 return 0; 825 824
+2 -1
drivers/gpu/drm/radeon/radeon_display.c
··· 232 232 } 233 233 234 234 static int radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 235 - u16 *blue, uint32_t size) 235 + u16 *blue, uint32_t size, 236 + struct drm_modeset_acquire_ctx *ctx) 236 237 { 237 238 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 238 239 int i;
+6 -23
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
··· 417 417 418 418 rockchip_drm_psr_unregister(&dp->encoder); 419 419 420 - return analogix_dp_unbind(dev, master, data); 420 + analogix_dp_unbind(dev, master, data); 421 + clk_disable_unprepare(dp->pclk); 421 422 } 422 423 423 424 static const struct component_ops rockchip_dp_component_ops = { ··· 429 428 static int rockchip_dp_probe(struct platform_device *pdev) 430 429 { 431 430 struct device *dev = &pdev->dev; 432 - struct device_node *panel_node, *port, *endpoint; 433 431 struct drm_panel *panel = NULL; 434 432 struct rockchip_dp_device *dp; 433 + int ret; 435 434 436 - port = of_graph_get_port_by_id(dev->of_node, 1); 437 - if (port) { 438 - endpoint = of_get_child_by_name(port, "endpoint"); 439 - of_node_put(port); 440 - if (!endpoint) { 441 - dev_err(dev, "no output endpoint found\n"); 442 - return -EINVAL; 443 - } 444 - 445 - panel_node = of_graph_get_remote_port_parent(endpoint); 446 - of_node_put(endpoint); 447 - if (!panel_node) { 448 - dev_err(dev, "no output node found\n"); 449 - return -EINVAL; 450 - } 451 - 452 - panel = of_drm_find_panel(panel_node); 453 - of_node_put(panel_node); 454 - if (!panel) 455 - return -EPROBE_DEFER; 456 - } 435 + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); 436 + if (ret) 437 + return ret; 457 438 458 439 dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); 459 440 if (!dp)
+6 -4
drivers/gpu/drm/rockchip/cdn-dp-core.c
··· 1053 1053 dp->connected = false; 1054 1054 dp->active = false; 1055 1055 dp->active_port = -1; 1056 + dp->fw_loaded = false; 1056 1057 1057 1058 INIT_WORK(&dp->event_work, cdn_dp_pd_event_work); 1058 1059 ··· 1092 1091 goto err_free_connector; 1093 1092 } 1094 1093 1095 - cdn_dp_audio_codec_init(dp, dev); 1096 - 1097 1094 for (i = 0; i < dp->ports; i++) { 1098 1095 port = dp->port[i]; 1099 1096 ··· 1126 1127 struct drm_connector *connector = &dp->connector; 1127 1128 1128 1129 cancel_work_sync(&dp->event_work); 1129 - platform_device_unregister(dp->audio_pdev); 1130 1130 cdn_dp_encoder_disable(encoder); 1131 1131 encoder->funcs->destroy(encoder); 1132 1132 connector->funcs->destroy(connector); 1133 1133 1134 1134 pm_runtime_disable(dev); 1135 - release_firmware(dp->fw); 1135 + if (dp->fw_loaded) 1136 + release_firmware(dp->fw); 1136 1137 kfree(dp->edid); 1137 1138 dp->edid = NULL; 1138 1139 } ··· 1218 1219 mutex_init(&dp->lock); 1219 1220 dev_set_drvdata(dev, dp); 1220 1221 1222 + cdn_dp_audio_codec_init(dp, dev); 1223 + 1221 1224 return component_add(dev, &cdn_dp_component_ops); 1222 1225 } 1223 1226 ··· 1227 1226 { 1228 1227 struct cdn_dp_device *dp = platform_get_drvdata(pdev); 1229 1228 1229 + platform_device_unregister(dp->audio_pdev); 1230 1230 cdn_dp_suspend(dp->dev); 1231 1231 component_del(&pdev->dev, &cdn_dp_component_ops); 1232 1232
+31 -27
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
··· 136 136 INIT_LIST_HEAD(&private->psr_list); 137 137 spin_lock_init(&private->psr_list_lock); 138 138 139 + ret = rockchip_drm_init_iommu(drm_dev); 140 + if (ret) 141 + goto err_free; 142 + 139 143 drm_mode_config_init(drm_dev); 140 144 141 145 rockchip_drm_mode_config_init(drm_dev); 142 146 143 - ret = rockchip_drm_init_iommu(drm_dev); 144 - if (ret) 145 - goto err_config_cleanup; 146 - 147 147 /* Try to bind all sub drivers. */ 148 148 ret = component_bind_all(dev, drm_dev); 149 149 if (ret) 150 - goto err_iommu_cleanup; 150 + goto err_mode_config_cleanup; 151 151 152 - /* init kms poll for handling hpd */ 153 - drm_kms_helper_poll_init(drm_dev); 152 + ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); 153 + if (ret) 154 + goto err_unbind_all; 155 + 156 + drm_mode_config_reset(drm_dev); 154 157 155 158 /* 156 159 * enable drm irq mode. ··· 161 158 */ 162 159 drm_dev->irq_enabled = true; 163 160 164 - ret = drm_vblank_init(drm_dev, ROCKCHIP_MAX_CRTC); 165 - if (ret) 166 - goto err_kms_helper_poll_fini; 167 - 168 - drm_mode_config_reset(drm_dev); 161 + /* init kms poll for handling hpd */ 162 + drm_kms_helper_poll_init(drm_dev); 169 163 170 164 ret = rockchip_drm_fbdev_init(drm_dev); 171 165 if (ret) 172 - goto err_vblank_cleanup; 166 + goto err_kms_helper_poll_fini; 173 167 174 168 ret = drm_dev_register(drm_dev, 0); 175 169 if (ret) ··· 175 175 return 0; 176 176 err_fbdev_fini: 177 177 rockchip_drm_fbdev_fini(drm_dev); 178 - err_vblank_cleanup: 179 - drm_vblank_cleanup(drm_dev); 180 178 err_kms_helper_poll_fini: 181 179 drm_kms_helper_poll_fini(drm_dev); 180 + drm_vblank_cleanup(drm_dev); 181 + err_unbind_all: 182 182 component_unbind_all(dev, drm_dev); 183 - err_iommu_cleanup: 184 - rockchip_iommu_cleanup(drm_dev); 185 - err_config_cleanup: 183 + err_mode_config_cleanup: 186 184 drm_mode_config_cleanup(drm_dev); 187 - drm_dev->dev_private = NULL; 185 + rockchip_iommu_cleanup(drm_dev); 188 186 err_free: 187 + drm_dev->dev_private = NULL; 188 + dev_set_drvdata(dev, NULL); 189 189 drm_dev_unref(drm_dev); 190 190 return ret; 191 191 } ··· 194 194 { 195 195 struct drm_device *drm_dev = dev_get_drvdata(dev); 196 196 197 - rockchip_drm_fbdev_fini(drm_dev); 198 - drm_vblank_cleanup(drm_dev); 199 - drm_kms_helper_poll_fini(drm_dev); 200 - component_unbind_all(dev, drm_dev); 201 - rockchip_iommu_cleanup(drm_dev); 202 - drm_mode_config_cleanup(drm_dev); 203 - drm_dev->dev_private = NULL; 204 197 drm_dev_unregister(drm_dev); 205 - drm_dev_unref(drm_dev); 198 + 199 + rockchip_drm_fbdev_fini(drm_dev); 200 + drm_kms_helper_poll_fini(drm_dev); 201 + 202 + drm_atomic_helper_shutdown(drm_dev); 203 + drm_vblank_cleanup(drm_dev); 204 + component_unbind_all(dev, drm_dev); 205 + drm_mode_config_cleanup(drm_dev); 206 + rockchip_iommu_cleanup(drm_dev); 207 + 208 + drm_dev->dev_private = NULL; 206 209 dev_set_drvdata(dev, NULL); 210 + drm_dev_unref(drm_dev); 207 211 } 208 212 209 213 static void rockchip_drm_lastclose(struct drm_device *dev)
+25 -8
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
··· 506 506 ret = pm_runtime_get_sync(vop->dev); 507 507 if (ret < 0) { 508 508 dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); 509 - goto err_put_pm_runtime; 509 + return ret; 510 510 } 511 511 512 512 ret = clk_enable(vop->hclk); ··· 1405 1405 return PTR_ERR(vop->dclk); 1406 1406 } 1407 1407 1408 + ret = pm_runtime_get_sync(vop->dev); 1409 + if (ret < 0) { 1410 + dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); 1411 + return ret; 1412 + } 1413 + 1408 1414 ret = clk_prepare(vop->dclk); 1409 1415 if (ret < 0) { 1410 1416 dev_err(vop->dev, "failed to prepare dclk\n"); 1411 - return ret; 1417 + goto err_put_pm_runtime; 1412 1418 } 1413 1419 1414 1420 /* Enable both the hclk and aclk to setup the vop */ ··· 1474 1468 1475 1469 vop->is_enabled = false; 1476 1470 1471 + pm_runtime_put_sync(vop->dev); 1472 + 1477 1473 return 0; 1478 1474 1479 1475 err_disable_aclk: ··· 1484 1476 clk_disable_unprepare(vop->hclk); 1485 1477 err_unprepare_dclk: 1486 1478 clk_unprepare(vop->dclk); 1479 + err_put_pm_runtime: 1480 + pm_runtime_put_sync(vop->dev); 1487 1481 return ret; 1488 1482 } 1489 1483 ··· 1586 1576 if (!vop->regsbak) 1587 1577 return -ENOMEM; 1588 1578 1589 - ret = vop_initial(vop); 1590 - if (ret < 0) { 1591 - dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); 1592 - return ret; 1593 - } 1594 - 1595 1579 irq = platform_get_irq(pdev, 0); 1596 1580 if (irq < 0) { 1597 1581 dev_err(dev, "cannot find irq for vop\n"); ··· 1612 1608 1613 1609 pm_runtime_enable(&pdev->dev); 1614 1610 1611 + ret = vop_initial(vop); 1612 + if (ret < 0) { 1613 + dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); 1614 + goto err_disable_pm_runtime; 1615 + } 1616 + 1615 1617 return 0; 1616 1618 1619 + err_disable_pm_runtime: 1620 + pm_runtime_disable(&pdev->dev); 1621 + vop_destroy_crtc(vop); 1617 1622 err_enable_irq: 1618 1623 enable_irq(vop->irq); /* To balance out the disable_irq above */ 1619 1624 return ret; ··· 1634 1621 1635 1622 pm_runtime_disable(dev); 1636 1623 vop_destroy_crtc(vop); 1624 + 1625 + clk_unprepare(vop->aclk); 1626 + clk_unprepare(vop->hclk); 1627 + clk_unprepare(vop->dclk); 1637 1628 } 1638 1629 1639 1630 const struct component_ops vop_component_ops = {
+6 -5
drivers/gpu/drm/sun4i/sun4i_rgb.c
··· 15 15 #include <drm/drmP.h> 16 16 #include <drm/drm_atomic_helper.h> 17 17 #include <drm/drm_crtc_helper.h> 18 + #include <drm/drm_of.h> 18 19 #include <drm/drm_panel.h> 19 20 20 21 #include "sun4i_drv.h" ··· 219 218 rgb->drv = drv; 220 219 encoder = &rgb->encoder; 221 220 222 - tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node); 223 - bridge = sun4i_tcon_find_bridge(tcon->dev->of_node); 224 - if (IS_ERR(tcon->panel) && IS_ERR(bridge)) { 221 + ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0, 222 + &tcon->panel, &bridge); 223 + if (ret) { 225 224 dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n"); 226 225 return 0; 227 226 } ··· 241 240 /* The RGB encoder can only work with the TCON channel 0 */ 242 241 rgb->encoder.possible_crtcs = BIT(0); 243 242 244 - if (!IS_ERR(tcon->panel)) { 243 + if (tcon->panel) { 245 244 drm_connector_helper_add(&rgb->connector, 246 245 &sun4i_rgb_con_helper_funcs); 247 246 ret = drm_connector_init(drm, &rgb->connector, ··· 262 261 } 263 262 } 264 263 265 - if (!IS_ERR(bridge)) { 264 + if (bridge) { 266 265 ret = drm_bridge_attach(encoder, bridge, NULL); 267 266 if (ret) { 268 267 dev_err(drm->dev, "Couldn't attach our bridge\n");
+5 -85
drivers/gpu/drm/sun4i/sun4i_tcon.c
··· 15 15 #include <drm/drm_crtc.h> 16 16 #include <drm/drm_crtc_helper.h> 17 17 #include <drm/drm_modes.h> 18 - #include <drm/drm_panel.h> 18 + #include <drm/drm_of.h> 19 19 20 20 #include <linux/component.h> 21 21 #include <linux/ioport.h> 22 22 #include <linux/of_address.h> 23 23 #include <linux/of_device.h> 24 - #include <linux/of_graph.h> 25 24 #include <linux/of_irq.h> 26 25 #include <linux/regmap.h> 27 26 #include <linux/reset.h> ··· 404 405 return 0; 405 406 } 406 407 407 - struct drm_panel *sun4i_tcon_find_panel(struct device_node *node) 408 - { 409 - struct device_node *port, *remote, *child; 410 - struct device_node *end_node = NULL; 411 - 412 - /* Inputs are listed first, then outputs */ 413 - port = of_graph_get_port_by_id(node, 1); 414 - 415 - /* 416 - * Our first output is the RGB interface where the panel will 417 - * be connected. 418 - */ 419 - for_each_child_of_node(port, child) { 420 - u32 reg; 421 - 422 - of_property_read_u32(child, "reg", &reg); 423 - if (reg == 0) 424 - end_node = child; 425 - } 426 - 427 - if (!end_node) { 428 - DRM_DEBUG_DRIVER("Missing panel endpoint\n"); 429 - return ERR_PTR(-ENODEV); 430 - } 431 - 432 - remote = of_graph_get_remote_port_parent(end_node); 433 - if (!remote) { 434 - DRM_DEBUG_DRIVER("Unable to parse remote node\n"); 435 - return ERR_PTR(-EINVAL); 436 - } 437 - 438 - return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER); 439 - } 440 - 441 - struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node) 442 - { 443 - struct device_node *port, *remote, *child; 444 - struct device_node *end_node = NULL; 445 - 446 - /* Inputs are listed first, then outputs */ 447 - port = of_graph_get_port_by_id(node, 1); 448 - 449 - /* 450 - * Our first output is the RGB interface where the panel will 451 - * be connected. 452 - */ 453 - for_each_child_of_node(port, child) { 454 - u32 reg; 455 - 456 - of_property_read_u32(child, "reg", &reg); 457 - if (reg == 0) 458 - end_node = child; 459 - } 460 - 461 - if (!end_node) { 462 - DRM_DEBUG_DRIVER("Missing bridge endpoint\n"); 463 - return ERR_PTR(-ENODEV); 464 - } 465 - 466 - remote = of_graph_get_remote_port_parent(end_node); 467 - if (!remote) { 468 - DRM_DEBUG_DRIVER("Enable to parse remote node\n"); 469 - return ERR_PTR(-EINVAL); 470 - } 471 - 472 - return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER); 473 - } 474 - 475 408 static int sun4i_tcon_bind(struct device *dev, struct device *master, 476 409 void *data) 477 410 { ··· 486 555 struct device_node *node = pdev->dev.of_node; 487 556 struct drm_bridge *bridge; 488 557 struct drm_panel *panel; 558 + int ret; 489 559 490 - /* 491 - * Neither the bridge or the panel is ready. 492 - * Defer the probe. 493 - */ 494 - panel = sun4i_tcon_find_panel(node); 495 - bridge = sun4i_tcon_find_bridge(node); 496 - 497 - /* 498 - * If we don't have a panel endpoint, just go on 499 - */ 500 - if ((PTR_ERR(panel) == -EPROBE_DEFER) && 501 - (PTR_ERR(bridge) == -EPROBE_DEFER)) { 502 - DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n"); 503 - return -EPROBE_DEFER; 504 - } 560 + ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge); 561 + if (ret == -EPROBE_DEFER) 562 + return ret; 505 563 506 564 return component_add(&pdev->dev, &sun4i_tcon_ops); 507 565 }
+2 -10
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
··· 23 23 #include <linux/workqueue.h> 24 24 #include <linux/completion.h> 25 25 #include <linux/dma-mapping.h> 26 + #include <linux/of_graph.h> 26 27 27 28 #include "tilcdc_drv.h" 28 29 #include "tilcdc_regs.h" ··· 1036 1035 drm_crtc_helper_add(crtc, &tilcdc_crtc_helper_funcs); 1037 1036 1038 1037 if (priv->is_componentized) { 1039 - struct device_node *ports = 1040 - of_get_child_by_name(dev->dev->of_node, "ports"); 1041 - 1042 - if (ports) { 1043 - crtc->port = of_get_child_by_name(ports, "port"); 1044 - of_node_put(ports); 1045 - } else { 1046 - crtc->port = 1047 - of_get_child_by_name(dev->dev->of_node, "port"); 1048 - } 1038 + crtc->port = of_graph_get_port_by_id(dev->dev->of_node, 0); 1049 1039 if (!crtc->port) { /* This should never happen */ 1050 1040 dev_err(dev->dev, "Port node not found in %s\n", 1051 1041 dev->dev->of_node->full_name);
+8 -60
drivers/gpu/drm/tilcdc/tilcdc_external.c
··· 185 185 return ret; 186 186 } 187 187 188 - static int tilcdc_node_has_port(struct device_node *dev_node) 189 - { 190 - struct device_node *node; 191 - 192 - node = of_get_child_by_name(dev_node, "ports"); 193 - if (!node) 194 - node = of_get_child_by_name(dev_node, "port"); 195 - if (!node) 196 - return 0; 197 - of_node_put(node); 198 - 199 - return 1; 200 - } 201 - 202 - static 203 - struct device_node *tilcdc_get_remote_node(struct device_node *node) 204 - { 205 - struct device_node *ep; 206 - struct device_node *parent; 207 - 208 - if (!tilcdc_node_has_port(node)) 209 - return NULL; 210 - 211 - ep = of_graph_get_next_endpoint(node, NULL); 212 - if (!ep) 213 - return NULL; 214 - 215 - parent = of_graph_get_remote_port_parent(ep); 216 - of_node_put(ep); 217 - 218 - return parent; 219 - } 220 - 221 188 int tilcdc_attach_external_device(struct drm_device *ddev) 222 189 { 223 190 struct tilcdc_drm_private *priv = ddev->dev_private; ··· 192 225 struct drm_bridge *bridge; 193 226 int ret; 194 227 195 - remote_node = tilcdc_get_remote_node(ddev->dev->of_node); 228 + remote_node = of_graph_get_remote_node(ddev->dev->of_node, 0, 0); 196 229 if (!remote_node) 197 230 return 0; 198 231 ··· 231 264 struct component_match **match) 232 265 { 233 266 struct device_node *node; 234 - struct device_node *ep = NULL; 235 - int count = 0; 236 - int ret = 0; 237 267 238 - if (!tilcdc_node_has_port(dev->of_node)) 239 - return 0; 268 + node = of_graph_get_remote_node(dev->of_node, 0, 0); 240 269 241 - while ((ep = of_graph_get_next_endpoint(dev->of_node, ep))) { 242 - node = of_graph_get_remote_port_parent(ep); 243 - if (!node || !of_device_is_available(node)) { 244 - of_node_put(node); 245 - continue; 246 - } 247 - 248 - dev_dbg(dev, "Subdevice node '%s' found\n", node->name); 249 - 250 - if (of_device_is_compatible(node, "nxp,tda998x")) { 251 - if (match) 252 - drm_of_component_match_add(dev, match, 253 - dev_match_of, node); 254 - ret = 1; 255 - } 256 - 270 + if (!of_device_is_compatible(node, "nxp,tda998x")) { 257 271 of_node_put(node); 258 - if (count++ > 1) { 259 - dev_err(dev, "Only one port is supported\n"); 260 - return -EINVAL; 261 - } 272 + return 0; 262 273 } 263 274 264 - return ret; 275 + if (match) 276 + drm_of_component_match_add(dev, match, dev_match_of, node); 277 + of_node_put(node); 278 + return 1; 265 279 }
+2 -1
drivers/gpu/drm/vc4/vc4_crtc.c
··· 314 314 315 315 static int 316 316 vc4_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, 317 - uint32_t size) 317 + uint32_t size, 318 + struct drm_modeset_acquire_ctx *ctx) 318 319 { 319 320 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); 320 321 u32 i;
+3 -12
drivers/gpu/drm/vc4/vc4_dpi.c
··· 356 356 */ 357 357 static struct drm_panel *vc4_dpi_get_panel(struct device *dev) 358 358 { 359 - struct device_node *endpoint, *panel_node; 359 + struct device_node *panel_node; 360 360 struct device_node *np = dev->of_node; 361 361 struct drm_panel *panel; 362 362 363 - endpoint = of_graph_get_next_endpoint(np, NULL); 364 - if (!endpoint) { 365 - dev_err(dev, "no endpoint to fetch DPI panel\n"); 366 - return NULL; 367 - } 368 - 369 363 /* don't proceed if we have an endpoint but no panel_node tied to it */ 370 - panel_node = of_graph_get_remote_port_parent(endpoint); 371 - of_node_put(endpoint); 372 - if (!panel_node) { 373 - dev_err(dev, "no valid panel node\n"); 364 + panel_node = of_graph_get_remote_node(np, 0, 0); 365 + if (!panel_node) 374 366 return NULL; 375 - } 376 367 377 368 panel = of_drm_find_panel(panel_node); 378 369 of_node_put(panel_node);
+1
drivers/gpu/drm/virtio/virtgpu_drv.h
··· 334 334 void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev); 335 335 336 336 /* virtio_gpu_plane.c */ 337 + uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc); 337 338 struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, 338 339 enum drm_plane_type type, 339 340 int index);
+2 -56
drivers/gpu/drm/virtio/virtgpu_fb.c
··· 231 231 mode_cmd.pitches[0] = mode_cmd.width * 4; 232 232 mode_cmd.pixel_format = drm_mode_legacy_fb_format(32, 24); 233 233 234 - switch (mode_cmd.pixel_format) { 235 - #ifdef __BIG_ENDIAN 236 - case DRM_FORMAT_XRGB8888: 237 - format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; 238 - break; 239 - case DRM_FORMAT_ARGB8888: 240 - format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; 241 - break; 242 - case DRM_FORMAT_BGRX8888: 243 - format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; 244 - break; 245 - case DRM_FORMAT_BGRA8888: 246 - format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; 247 - break; 248 - case DRM_FORMAT_RGBX8888: 249 - format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM; 250 - break; 251 - case DRM_FORMAT_RGBA8888: 252 - format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM; 253 - break; 254 - case DRM_FORMAT_XBGR8888: 255 - format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM; 256 - break; 257 - case DRM_FORMAT_ABGR8888: 258 - format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM; 259 - break; 260 - #else 261 - case DRM_FORMAT_XRGB8888: 262 - format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; 263 - break; 264 - case DRM_FORMAT_ARGB8888: 265 - format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; 266 - break; 267 - case DRM_FORMAT_BGRX8888: 268 - format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; 269 - break; 270 - case DRM_FORMAT_BGRA8888: 271 - format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; 272 - break; 273 - case DRM_FORMAT_RGBX8888: 274 - format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM; 275 - break; 276 - case DRM_FORMAT_RGBA8888: 277 - format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM; 278 - break; 279 - case DRM_FORMAT_XBGR8888: 280 - format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM; 281 - break; 282 - case DRM_FORMAT_ABGR8888: 283 - format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM; 284 - break; 285 - #endif 286 - default: 287 - DRM_ERROR("failed to find virtio gpu format for %d\n", 288 - mode_cmd.pixel_format); 234 + format = virtio_gpu_translate_format(mode_cmd.pixel_format); 235 + if (format == 0) 289 236 return -EINVAL; 290 - } 291 237 292 238 size = mode_cmd.pitches[0] * mode_cmd.height; 293 239 obj = virtio_gpu_alloc_object(dev, size, false, true);
+4 -2
drivers/gpu/drm/virtio/virtgpu_gem.c
··· 88 88 int ret; 89 89 uint32_t pitch; 90 90 uint32_t resid; 91 + uint32_t format; 91 92 92 93 pitch = args->width * ((args->bpp + 1) / 8); 93 94 args->size = pitch * args->height; ··· 99 98 if (ret) 100 99 goto fail; 101 100 101 + format = virtio_gpu_translate_format(DRM_FORMAT_XRGB8888); 102 102 virtio_gpu_resource_id_get(vgdev, &resid); 103 - virtio_gpu_cmd_create_resource(vgdev, resid, 104 - 2, args->width, args->height); 103 + virtio_gpu_cmd_create_resource(vgdev, resid, format, 104 + args->width, args->height); 105 105 106 106 /* attach the object to the resource */ 107 107 obj = gem_to_virtio_gpu_obj(gobj);
+3 -1
drivers/gpu/drm/virtio/virtgpu_object.c
··· 81 81 return -ENOMEM; 82 82 size = roundup(size, PAGE_SIZE); 83 83 ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, size); 84 - if (ret != 0) 84 + if (ret != 0) { 85 + kfree(bo); 85 86 return ret; 87 + } 86 88 bo->dumb = false; 87 89 virtio_gpu_init_ttm_placement(bo, pinned); 88 90
+72
drivers/gpu/drm/virtio/virtgpu_plane.c
··· 39 39 }; 40 40 41 41 static const uint32_t virtio_gpu_cursor_formats[] = { 42 + #ifdef __BIG_ENDIAN 43 + DRM_FORMAT_BGRA8888, 44 + #else 42 45 DRM_FORMAT_ARGB8888, 46 + #endif 43 47 }; 48 + 49 + uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc) 50 + { 51 + uint32_t format; 52 + 53 + switch (drm_fourcc) { 54 + #ifdef __BIG_ENDIAN 55 + case DRM_FORMAT_XRGB8888: 56 + format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; 57 + break; 58 + case DRM_FORMAT_ARGB8888: 59 + format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; 60 + break; 61 + case DRM_FORMAT_BGRX8888: 62 + format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; 63 + break; 64 + case DRM_FORMAT_BGRA8888: 65 + format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; 66 + break; 67 + case DRM_FORMAT_RGBX8888: 68 + format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM; 69 + break; 70 + case DRM_FORMAT_RGBA8888: 71 + format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM; 72 + break; 73 + case DRM_FORMAT_XBGR8888: 74 + format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM; 75 + break; 76 + case DRM_FORMAT_ABGR8888: 77 + format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM; 78 + break; 79 + #else 80 + case DRM_FORMAT_XRGB8888: 81 + format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; 82 + break; 83 + case DRM_FORMAT_ARGB8888: 84 + format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; 85 + break; 86 + case DRM_FORMAT_BGRX8888: 87 + format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; 88 + break; 89 + case DRM_FORMAT_BGRA8888: 90 + format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; 91 + break; 92 + case DRM_FORMAT_RGBX8888: 93 + format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM; 94 + break; 95 + case DRM_FORMAT_RGBA8888: 96 + format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM; 97 + break; 98 + case DRM_FORMAT_XBGR8888: 99 + format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM; 100 + break; 101 + case DRM_FORMAT_ABGR8888: 102 + format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM; 103 + break; 104 + #endif 105 + default: 106 + /* 107 + * This should not happen, we handle everything listed 108 + * in virtio_gpu_formats[]. 109 + */ 110 + format = 0; 111 + break; 112 + } 113 + WARN_ON(format == 0); 114 + return format; 115 + } 44 116 45 117 static void virtio_gpu_plane_destroy(struct drm_plane *plane) 46 118 {
+56 -2
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
··· 418 418 return 0; 419 419 } 420 420 421 + static int vmwgfx_set_config_internal(struct drm_mode_set *set) 422 + { 423 + struct drm_crtc *crtc = set->crtc; 424 + struct drm_framebuffer *fb; 425 + struct drm_crtc *tmp; 426 + struct drm_modeset_acquire_ctx *ctx; 427 + struct drm_device *dev = set->crtc->dev; 428 + int ret; 429 + 430 + ctx = dev->mode_config.acquire_ctx; 431 + 432 + restart: 433 + /* 434 + * NOTE: ->set_config can also disable other crtcs (if we steal all 435 + * connectors from it), hence we need to refcount the fbs across all 436 + * crtcs. Atomic modeset will have saner semantics ... 437 + */ 438 + drm_for_each_crtc(tmp, dev) 439 + tmp->primary->old_fb = tmp->primary->fb; 440 + 441 + fb = set->fb; 442 + 443 + ret = crtc->funcs->set_config(set, ctx); 444 + if (ret == 0) { 445 + crtc->primary->crtc = crtc; 446 + crtc->primary->fb = fb; 447 + } 448 + 449 + drm_for_each_crtc(tmp, dev) { 450 + if (tmp->primary->fb) 451 + drm_framebuffer_get(tmp->primary->fb); 452 + if (tmp->primary->old_fb) 453 + drm_framebuffer_put(tmp->primary->old_fb); 454 + tmp->primary->old_fb = NULL; 455 + } 456 + 457 + if (ret == -EDEADLK) { 458 + dev->mode_config.acquire_ctx = NULL; 459 + 460 + retry_locking: 461 + drm_modeset_backoff(ctx); 462 + 463 + ret = drm_modeset_lock_all_ctx(dev, ctx); 464 + if (ret) 465 + goto retry_locking; 466 + 467 + dev->mode_config.acquire_ctx = ctx; 468 + 469 + goto restart; 470 + } 471 + 472 + return ret; 473 + } 474 + 421 475 static int vmw_fb_kms_detach(struct vmw_fb_par *par, 422 476 bool detach_bo, 423 477 bool unref_bo) ··· 490 436 set.fb = NULL; 491 437 set.num_connectors = 0; 492 438 set.connectors = &par->con; 493 - ret = drm_mode_set_config_internal(&set); 439 + ret = vmwgfx_set_config_internal(&set); 494 440 if (ret) { 495 441 DRM_ERROR("Could not unset a mode.\n"); 496 442 return ret; ··· 632 578 set.num_connectors = 1; 633 579 set.connectors = &par->con; 634 580 635 - ret = drm_mode_set_config_internal(&set); 581 + ret = vmwgfx_set_config_internal(&set); 636 582 if (ret) 637 583 goto out_unlock; 638 584
+2 -1
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 2026 2026 2027 2027 int vmw_du_crtc_gamma_set(struct drm_crtc *crtc, 2028 2028 u16 *r, u16 *g, u16 *b, 2029 - uint32_t size) 2029 + uint32_t size, 2030 + struct drm_modeset_acquire_ctx *ctx) 2030 2031 { 2031 2032 struct vmw_private *dev_priv = vmw_priv(crtc->dev); 2032 2033 int i;
+2 -1
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
··· 254 254 void vmw_du_crtc_restore(struct drm_crtc *crtc); 255 255 int vmw_du_crtc_gamma_set(struct drm_crtc *crtc, 256 256 u16 *r, u16 *g, u16 *b, 257 - uint32_t size); 257 + uint32_t size, 258 + struct drm_modeset_acquire_ctx *ctx); 258 259 int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, 259 260 uint32_t handle, uint32_t width, uint32_t height, 260 261 int32_t hot_x, int32_t hot_y);
+68
include/drm/bridge/dw_hdmi.h
··· 14 14 15 15 struct dw_hdmi; 16 16 17 + /** 18 + * DOC: Supported input formats and encodings 19 + * 20 + * Depending on the Hardware configuration of the Controller IP, it supports 21 + * a subset of the following input formats and encodings on its internal 22 + * 48bit bus. 23 + * 24 + * +----------------------+----------------------------------+------------------------------+ 25 + * + Format Name + Format Code + Encodings + 26 + * +----------------------+----------------------------------+------------------------------+ 27 + * + RGB 4:4:4 8bit + ``MEDIA_BUS_FMT_RGB888_1X24`` + ``V4L2_YCBCR_ENC_DEFAULT`` + 28 + * +----------------------+----------------------------------+------------------------------+ 29 + * + RGB 4:4:4 10bits + ``MEDIA_BUS_FMT_RGB101010_1X30`` + ``V4L2_YCBCR_ENC_DEFAULT`` + 30 + * +----------------------+----------------------------------+------------------------------+ 31 + * + RGB 4:4:4 12bits + ``MEDIA_BUS_FMT_RGB121212_1X36`` + ``V4L2_YCBCR_ENC_DEFAULT`` + 32 + * +----------------------+----------------------------------+------------------------------+ 33 + * + RGB 4:4:4 16bits + ``MEDIA_BUS_FMT_RGB161616_1X48`` + ``V4L2_YCBCR_ENC_DEFAULT`` + 34 + * +----------------------+----------------------------------+------------------------------+ 35 + * + YCbCr 4:4:4 8bit + ``MEDIA_BUS_FMT_YUV8_1X24`` + ``V4L2_YCBCR_ENC_601`` + 36 + * + + + or ``V4L2_YCBCR_ENC_709`` + 37 + * + + + or ``V4L2_YCBCR_ENC_XV601`` + 38 + * + + + or ``V4L2_YCBCR_ENC_XV709`` + 39 + * +----------------------+----------------------------------+------------------------------+ 40 + * + YCbCr 4:4:4 10bits + ``MEDIA_BUS_FMT_YUV10_1X30`` + ``V4L2_YCBCR_ENC_601`` + 41 + * + + + or ``V4L2_YCBCR_ENC_709`` + 42 + * + + + or ``V4L2_YCBCR_ENC_XV601`` + 43 + * + + + or ``V4L2_YCBCR_ENC_XV709`` + 44 + * +----------------------+----------------------------------+------------------------------+ 45 + * + YCbCr 4:4:4 12bits + ``MEDIA_BUS_FMT_YUV12_1X36`` + ``V4L2_YCBCR_ENC_601`` + 46 + * + + + or ``V4L2_YCBCR_ENC_709`` + 47 + * + + + or ``V4L2_YCBCR_ENC_XV601`` + 48 + * + + + or ``V4L2_YCBCR_ENC_XV709`` + 49 + * +----------------------+----------------------------------+------------------------------+ 50 + * + YCbCr 4:4:4 16bits + ``MEDIA_BUS_FMT_YUV16_1X48`` + ``V4L2_YCBCR_ENC_601`` + 51 + * + + + or ``V4L2_YCBCR_ENC_709`` + 52 + * + + + or ``V4L2_YCBCR_ENC_XV601`` + 53 + * + + + or ``V4L2_YCBCR_ENC_XV709`` + 54 + * +----------------------+----------------------------------+------------------------------+ 55 + * + YCbCr 4:2:2 8bit + ``MEDIA_BUS_FMT_UYVY8_1X16`` + ``V4L2_YCBCR_ENC_601`` + 56 + * + + + or ``V4L2_YCBCR_ENC_709`` + 57 + * +----------------------+----------------------------------+------------------------------+ 58 + * + YCbCr 4:2:2 10bits + ``MEDIA_BUS_FMT_UYVY10_1X20`` + ``V4L2_YCBCR_ENC_601`` + 59 + * + + + or ``V4L2_YCBCR_ENC_709`` + 60 + * +----------------------+----------------------------------+------------------------------+ 61 + * + YCbCr 4:2:2 12bits + ``MEDIA_BUS_FMT_UYVY12_1X24`` + ``V4L2_YCBCR_ENC_601`` + 62 + * + + + or ``V4L2_YCBCR_ENC_709`` + 63 + * +----------------------+----------------------------------+------------------------------+ 64 + * + YCbCr 4:2:0 8bit + ``MEDIA_BUS_FMT_UYYVYY8_0_5X24`` + ``V4L2_YCBCR_ENC_601`` + 65 + * + + + or ``V4L2_YCBCR_ENC_709`` + 66 + * +----------------------+----------------------------------+------------------------------+ 67 + * + YCbCr 4:2:0 10bits + ``MEDIA_BUS_FMT_UYYVYY10_0_5X30``+ ``V4L2_YCBCR_ENC_601`` + 68 + * + + + or ``V4L2_YCBCR_ENC_709`` + 69 + * +----------------------+----------------------------------+------------------------------+ 70 + * + YCbCr 4:2:0 12bits + ``MEDIA_BUS_FMT_UYYVYY12_0_5X36``+ ``V4L2_YCBCR_ENC_601`` + 71 + * + + + or ``V4L2_YCBCR_ENC_709`` + 72 + * +----------------------+----------------------------------+------------------------------+ 73 + * + YCbCr 4:2:0 16bits + ``MEDIA_BUS_FMT_UYYVYY16_0_5X48``+ ``V4L2_YCBCR_ENC_601`` + 74 + * + + + or ``V4L2_YCBCR_ENC_709`` + 75 + * +----------------------+----------------------------------+------------------------------+ 76 + */ 77 + 17 78 enum { 18 79 DW_HDMI_RES_8, 19 80 DW_HDMI_RES_10, ··· 117 56 struct drm_display_mode *mode); 118 57 void (*disable)(struct dw_hdmi *hdmi, void *data); 119 58 enum drm_connector_status (*read_hpd)(struct dw_hdmi *hdmi, void *data); 59 + void (*update_hpd)(struct dw_hdmi *hdmi, void *data, 60 + bool force, bool disabled, bool rxsense); 61 + void (*setup_hpd)(struct dw_hdmi *hdmi, void *data); 120 62 }; 121 63 122 64 struct dw_hdmi_plat_data { 123 65 struct regmap *regm; 124 66 enum drm_mode_status (*mode_valid)(struct drm_connector *connector, 125 67 struct drm_display_mode *mode); 68 + unsigned long input_bus_format; 69 + unsigned long input_bus_encoding; 126 70 127 71 /* Vendor PHY support */ 128 72 const struct dw_hdmi_phy_ops *phy_ops; ··· 149 83 void dw_hdmi_unbind(struct device *dev); 150 84 int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, 151 85 const struct dw_hdmi_plat_data *plat_data); 86 + 87 + void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense); 152 88 153 89 void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); 154 90 void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
+1 -4
include/drm/drmP.h
··· 80 80 #include <drm/drm_file.h> 81 81 #include <drm/drm_debugfs.h> 82 82 #include <drm/drm_ioctl.h> 83 + #include <drm/drm_sysfs.h> 83 84 84 85 struct module; 85 86 ··· 512 511 * These are exported to drivers so that they can implement fencing using 513 512 * DMA quiscent + idle. DMA quiescent usually requires the hardware lock. 514 513 */ 515 - 516 - /* sysfs support (drm_sysfs.c) */ 517 - extern void drm_sysfs_hotplug_event(struct drm_device *dev); 518 - 519 514 520 515 /*@}*/ 521 516
-2
include/drm/drm_atomic.h
··· 160 160 * @dev: parent DRM device 161 161 * @allow_modeset: allow full modeset 162 162 * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics 163 - * @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL. 164 163 * @planes: pointer to array of structures with per-plane data 165 164 * @crtcs: pointer to array of CRTC pointers 166 165 * @num_connector: size of the @connectors and @connector_states arrays ··· 172 173 struct drm_device *dev; 173 174 bool allow_modeset : 1; 174 175 bool legacy_cursor_update : 1; 175 - bool legacy_set_config : 1; 176 176 struct __drm_planes_state *planes; 177 177 struct __drm_crtcs_state *crtcs; 178 178 int num_connector;
+2 -1
include/drm/drm_atomic_helper.h
··· 176 176 struct drm_connector_state *state); 177 177 int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, 178 178 u16 *red, u16 *green, u16 *blue, 179 - uint32_t size); 179 + uint32_t size, 180 + struct drm_modeset_acquire_ctx *ctx); 180 181 181 182 /** 182 183 * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
+6
include/drm/drm_connector.h
··· 32 32 struct drm_device; 33 33 34 34 struct drm_connector_helper_funcs; 35 + struct drm_modeset_acquire_ctx; 35 36 struct drm_device; 36 37 struct drm_crtc; 37 38 struct drm_encoder; ··· 382 381 * Note that this hook is only called by the probe helper. It's not in 383 382 * the helper library vtable purely for historical reasons. The only DRM 384 383 * core entry point to probe connector state is @fill_modes. 384 + * 385 + * Note that the helper library will already hold 386 + * &drm_mode_config.connection_mutex. Drivers which need to grab additional 387 + * locks to avoid races with concurrent modeset changes need to use 388 + * &drm_connector_helper_funcs.detect_ctx instead. 385 389 * 386 390 * RETURNS: 387 391 *
+2 -10
include/drm/drm_crtc.h
··· 322 322 * hooks. 323 323 */ 324 324 int (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, 325 - uint32_t size); 325 + uint32_t size, 326 + struct drm_modeset_acquire_ctx *ctx); 326 327 327 328 /** 328 329 * @destroy: ··· 782 781 * Spinlock to protect @commit_list. 783 782 */ 784 783 spinlock_t commit_lock; 785 - 786 - /** 787 - * @acquire_ctx: 788 - * 789 - * Per-CRTC implicit acquire context used by atomic drivers for legacy 790 - * IOCTLs, so that atomic drivers can get at the locking acquire 791 - * context. 792 - */ 793 - struct drm_modeset_acquire_ctx *acquire_ctx; 794 784 795 785 #ifdef CONFIG_DEBUG_FS 796 786 /**
+3
include/drm/drm_crtc_helper.h
··· 67 67 int drm_helper_probe_single_connector_modes(struct drm_connector 68 68 *connector, uint32_t maxX, 69 69 uint32_t maxY); 70 + int drm_helper_probe_detect(struct drm_connector *connector, 71 + struct drm_modeset_acquire_ctx *ctx, 72 + bool force); 70 73 void drm_kms_helper_poll_init(struct drm_device *dev); 71 74 void drm_kms_helper_poll_fini(struct drm_device *dev); 72 75 bool drm_helper_hpd_irq_event(struct drm_device *dev);
+101 -15
include/drm/drm_ioctl.h
··· 33 33 #define _DRM_IOCTL_H_ 34 34 35 35 #include <linux/types.h> 36 + #include <linux/bitops.h> 36 37 37 38 #include <asm/ioctl.h> 38 39 ··· 42 41 struct file; 43 42 44 43 /** 45 - * Ioctl function type. 44 + * drm_ioctl_t - DRM ioctl function type. 45 + * @dev: DRM device inode 46 + * @data: private pointer of the ioctl call 47 + * @file_priv: DRM file this ioctl was made on 46 48 * 47 - * \param inode device inode. 48 - * \param file_priv DRM file private pointer. 49 - * \param cmd command. 50 - * \param arg argument. 49 + * This is the DRM ioctl typedef. Note that drm_ioctl() has alrady copied @data 50 + * into kernel-space, and will also copy it back, depending upon the read/write 51 + * settings in the ioctl command code. 51 52 */ 52 53 typedef int drm_ioctl_t(struct drm_device *dev, void *data, 53 54 struct drm_file *file_priv); 54 55 56 + /** 57 + * drm_ioctl_compat_t - compatibility DRM ioctl function type. 58 + * @filp: file pointer 59 + * @cmd: ioctl command code 60 + * @arg: DRM file this ioctl was made on 61 + * 62 + * Just a typedef to make declaring an array of compatibility handlers easier. 63 + * New drivers shouldn't screw up the structure layout for their ioctl 64 + * structures and hence never need this. 65 + */ 55 66 typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, 56 67 unsigned long arg); 57 68 58 69 #define DRM_IOCTL_NR(n) _IOC_NR(n) 59 70 #define DRM_MAJOR 226 60 71 61 - #define DRM_AUTH 0x1 62 - #define DRM_MASTER 0x2 63 - #define DRM_ROOT_ONLY 0x4 64 - #define DRM_CONTROL_ALLOW 0x8 65 - #define DRM_UNLOCKED 0x10 66 - #define DRM_RENDER_ALLOW 0x20 72 + /** 73 + * enum drm_ioctl_flags - DRM ioctl flags 74 + * 75 + * Various flags that can be set in &drm_ioctl_desc.flags to control how 76 + * userspace can use a given ioctl. 77 + */ 78 + enum drm_ioctl_flags { 79 + /** 80 + * @DRM_AUTH: 81 + * 82 + * This is for ioctl which are used for rendering, and require that the 83 + * file descriptor is either for a render node, or if it's a 84 + * legacy/primary node, then it must be authenticated. 85 + */ 86 + DRM_AUTH = BIT(0), 87 + /** 88 + * @DRM_MASTER: 89 + * 90 + * This must be set for any ioctl which can change the modeset or 91 + * display state. Userspace must call the ioctl through a primary node, 92 + * while it is the active master. 93 + * 94 + * Note that read-only modeset ioctl can also be called by 95 + * unauthenticated clients, or when a master is not the currently active 96 + * one. 97 + */ 98 + DRM_MASTER = BIT(1), 99 + /** 100 + * @DRM_ROOT_ONLY: 101 + * 102 + * Anything that could potentially wreak a master file descriptor needs 103 + * to have this flag set. Current that's only for the SETMASTER and 104 + * DROPMASTER ioctl, which e.g. logind can call to force a non-behaving 105 + * master (display compositor) into compliance. 106 + * 107 + * This is equivalent to callers with the SYSADMIN capability. 108 + */ 109 + DRM_ROOT_ONLY = BIT(2), 110 + /** 111 + * @DRM_CONTROL_ALLOW: 112 + * 113 + * Deprecated, do not use. Control nodes are in the process of getting 114 + * removed. 115 + */ 116 + DRM_CONTROL_ALLOW = BIT(3), 117 + /** 118 + * @DRM_UNLOCKED: 119 + * 120 + * Whether &drm_ioctl_desc.func should be called with the DRM BKL held 121 + * or not. Enforced as the default for all modern drivers, hence there 122 + * should never be a need to set this flag. 123 + */ 124 + DRM_UNLOCKED = BIT(4), 125 + /** 126 + * @DRM_RENDER_ALLOW: 127 + * 128 + * This is used for all ioctl needed for rendering only, for drivers 129 + * which support render nodes. This should be all new render drivers, 130 + * and hence it should be always set for any ioctl with DRM_AUTH set. 131 + * Note though that read-only query ioctl might have this set, but have 132 + * not set DRM_AUTH because they do not require authentication. 133 + */ 134 + DRM_RENDER_ALLOW = BIT(5), 135 + }; 67 136 137 + /** 138 + * struct drm_ioctl_desc - DRM driver ioctl entry 139 + * @cmd: ioctl command number, without flags 140 + * @flags: a bitmask of &enum drm_ioctl_flags 141 + * @func: handler for this ioctl 142 + * @name: user-readable name for debug output 143 + * 144 + * For convenience it's easier to create these using the DRM_IOCTL_DEF_DRV() 145 + * macro. 146 + */ 68 147 struct drm_ioctl_desc { 69 148 unsigned int cmd; 70 - int flags; 149 + enum drm_ioctl_flags flags; 71 150 drm_ioctl_t *func; 72 151 const char *name; 73 152 }; 74 153 75 154 /** 76 - * Creates a driver or general drm_ioctl_desc array entry for the given 77 - * ioctl, for use by drm_ioctl(). 155 + * DRM_IOCTL_DEF_DRV() - helper macro to fill out a &struct drm_ioctl_desc 156 + * @ioctl: ioctl command suffix 157 + * @_func: handler for the ioctl 158 + * @_flags: a bitmask of &enum drm_ioctl_flags 159 + * 160 + * Small helper macro to create a &struct drm_ioctl_desc entry. The ioctl 161 + * command number is constructed by prepending ``DRM_IOCTL\_`` and passing that 162 + * to DRM_IOCTL_NR(). 78 163 */ 79 - 80 164 #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ 81 165 [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \ 82 166 .cmd = DRM_IOCTL_##ioctl, \
+70
include/drm/drm_modeset_helper_vtables.h
··· 747 747 * This callback is used by the probe helpers in e.g. 748 748 * drm_helper_probe_single_connector_modes(). 749 749 * 750 + * To avoid races with concurrent connector state updates, the helper 751 + * libraries always call this with the &drm_mode_config.connection_mutex 752 + * held. Because of this it's safe to inspect &drm_connector->state. 753 + * 750 754 * RETURNS: 751 755 * 752 756 * The number of modes added by calling drm_mode_probed_add(). 753 757 */ 754 758 int (*get_modes)(struct drm_connector *connector); 759 + 760 + /** 761 + * @detect_ctx: 762 + * 763 + * Check to see if anything is attached to the connector. The parameter 764 + * force is set to false whilst polling, true when checking the 765 + * connector due to a user request. force can be used by the driver to 766 + * avoid expensive, destructive operations during automated probing. 767 + * 768 + * This callback is optional, if not implemented the connector will be 769 + * considered as always being attached. 770 + * 771 + * This is the atomic version of &drm_connector_funcs.detect. 772 + * 773 + * To avoid races against concurrent connector state updates, the 774 + * helper libraries always call this with ctx set to a valid context, 775 + * and &drm_mode_config.connection_mutex will always be locked with 776 + * the ctx parameter set to this ctx. This allows taking additional 777 + * locks as required. 778 + * 779 + * RETURNS: 780 + * 781 + * &drm_connector_status indicating the connector's status, 782 + * or the error code returned by drm_modeset_lock(), -EDEADLK. 783 + */ 784 + int (*detect_ctx)(struct drm_connector *connector, 785 + struct drm_modeset_acquire_ctx *ctx, 786 + bool force); 755 787 756 788 /** 757 789 * @mode_valid: ··· 803 771 * CRTC helpers will not call this function. Drivers therefore must 804 772 * still fully validate any mode passed in in a modeset request. 805 773 * 774 + * To avoid races with concurrent connector state updates, the helper 775 + * libraries always call this with the &drm_mode_config.connection_mutex 776 + * held. Because of this it's safe to inspect &drm_connector->state. 777 + * 806 778 * RETURNS: 807 779 * 808 780 * Either &drm_mode_status.MODE_OK or one of the failure reasons in &enum ··· 872 836 */ 873 837 struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, 874 838 struct drm_connector_state *connector_state); 839 + 840 + /** 841 + * @atomic_check: 842 + * 843 + * This hook is used to validate connector state. This function is 844 + * called from &drm_atomic_helper_check_modeset, and is called when 845 + * a connector property is set, or a modeset on the crtc is forced. 846 + * 847 + * Because &drm_atomic_helper_check_modeset may be called multiple times, 848 + * this function should handle being called multiple times as well. 849 + * 850 + * This function is also allowed to inspect any other object's state and 851 + * can add more state objects to the atomic commit if needed. Care must 852 + * be taken though to ensure that state check and compute functions for 853 + * these added states are all called, and derived state in other objects 854 + * all updated. Again the recommendation is to just call check helpers 855 + * until a maximal configuration is reached. 856 + * 857 + * NOTE: 858 + * 859 + * This function is called in the check phase of an atomic update. The 860 + * driver is not allowed to change anything outside of the free-standing 861 + * state objects passed-in or assembled in the overall &drm_atomic_state 862 + * update tracking structure. 863 + * 864 + * RETURNS: 865 + * 866 + * 0 on success, -EINVAL if the state or the transition can't be 867 + * supported, -ENOMEM on memory allocation failure and -EDEADLK if an 868 + * attempt to obtain another state object ran into a &drm_modeset_lock 869 + * deadlock. 870 + */ 871 + int (*atomic_check)(struct drm_connector *connector, 872 + struct drm_connector_state *state); 875 873 }; 876 874 877 875 /**
-5
include/drm/drm_modeset_lock.h
··· 121 121 122 122 void drm_modeset_lock_all(struct drm_device *dev); 123 123 void drm_modeset_unlock_all(struct drm_device *dev); 124 - void drm_modeset_lock_crtc(struct drm_crtc *crtc, 125 - struct drm_plane *plane); 126 - void drm_modeset_unlock_crtc(struct drm_crtc *crtc); 127 124 void drm_warn_on_modeset_not_all_locked(struct drm_device *dev); 128 - struct drm_modeset_acquire_ctx * 129 - drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc); 130 125 131 126 int drm_modeset_lock_all_ctx(struct drm_device *dev, 132 127 struct drm_modeset_acquire_ctx *ctx);
+13
include/drm/drm_of.h
··· 8 8 struct device; 9 9 struct drm_device; 10 10 struct drm_encoder; 11 + struct drm_panel; 12 + struct drm_bridge; 11 13 struct device_node; 12 14 13 15 #ifdef CONFIG_OF ··· 25 23 int drm_of_encoder_active_endpoint(struct device_node *node, 26 24 struct drm_encoder *encoder, 27 25 struct of_endpoint *endpoint); 26 + int drm_of_find_panel_or_bridge(const struct device_node *np, 27 + int port, int endpoint, 28 + struct drm_panel **panel, 29 + struct drm_bridge **bridge); 28 30 #else 29 31 static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 30 32 struct device_node *port) ··· 55 49 static inline int drm_of_encoder_active_endpoint(struct device_node *node, 56 50 struct drm_encoder *encoder, 57 51 struct of_endpoint *endpoint) 52 + { 53 + return -EINVAL; 54 + } 55 + static inline int drm_of_find_panel_or_bridge(const struct device_node *np, 56 + int port, int endpoint, 57 + struct drm_panel **panel, 58 + struct drm_bridge **bridge) 58 59 { 59 60 return -EINVAL; 60 61 }
+1 -1
include/drm/drm_panel.h
··· 192 192 int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector); 193 193 int drm_panel_detach(struct drm_panel *panel); 194 194 195 - #ifdef CONFIG_OF 195 + #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) 196 196 struct drm_panel *of_drm_find_panel(const struct device_node *np); 197 197 #else 198 198 static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
+4 -4
include/drm/drm_sysfs.h
··· 1 1 #ifndef _DRM_SYSFS_H_ 2 2 #define _DRM_SYSFS_H_ 3 3 4 - /** 5 - * This minimalistic include file is intended for users (read TTM) that 6 - * don't want to include the full drmP.h file. 7 - */ 4 + struct drm_device; 5 + struct device; 8 6 9 7 int drm_class_device_register(struct device *dev); 10 8 void drm_class_device_unregister(struct device *dev); 9 + 10 + void drm_sysfs_hotplug_event(struct drm_device *dev); 11 11 12 12 #endif
+2 -1
include/uapi/drm/drm.h
··· 647 647 #define DRM_CAP_CURSOR_HEIGHT 0x9 648 648 #define DRM_CAP_ADDFB2_MODIFIERS 0x10 649 649 #define DRM_CAP_PAGE_FLIP_TARGET 0x11 650 + #define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 650 651 651 652 /** DRM_IOCTL_GET_CAP ioctl argument type */ 652 653 struct drm_get_cap { ··· 852 851 __u32 tv_sec; 853 852 __u32 tv_usec; 854 853 __u32 sequence; 855 - __u32 reserved; 854 + __u32 crtc_id; /* 0 on older kernels that do not support this */ 856 855 }; 857 856 858 857 /* typedef area */
+11 -2
include/uapi/linux/media-bus-format.h
··· 33 33 34 34 #define MEDIA_BUS_FMT_FIXED 0x0001 35 35 36 - /* RGB - next is 0x1018 */ 36 + /* RGB - next is 0x101b */ 37 37 #define MEDIA_BUS_FMT_RGB444_1X12 0x1016 38 38 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001 39 39 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002 ··· 57 57 #define MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA 0x1012 58 58 #define MEDIA_BUS_FMT_ARGB8888_1X32 0x100d 59 59 #define MEDIA_BUS_FMT_RGB888_1X32_PADHI 0x100f 60 + #define MEDIA_BUS_FMT_RGB101010_1X30 0x1018 61 + #define MEDIA_BUS_FMT_RGB121212_1X36 0x1019 62 + #define MEDIA_BUS_FMT_RGB161616_1X48 0x101a 60 63 61 - /* YUV (including grey) - next is 0x2026 */ 64 + /* YUV (including grey) - next is 0x202c */ 62 65 #define MEDIA_BUS_FMT_Y8_1X8 0x2001 63 66 #define MEDIA_BUS_FMT_UV8_1X8 0x2015 64 67 #define MEDIA_BUS_FMT_UYVY8_1_5X8 0x2002 ··· 93 90 #define MEDIA_BUS_FMT_YVYU10_1X20 0x200e 94 91 #define MEDIA_BUS_FMT_VUY8_1X24 0x2024 95 92 #define MEDIA_BUS_FMT_YUV8_1X24 0x2025 93 + #define MEDIA_BUS_FMT_UYYVYY8_0_5X24 0x2026 96 94 #define MEDIA_BUS_FMT_UYVY12_1X24 0x2020 97 95 #define MEDIA_BUS_FMT_VYUY12_1X24 0x2021 98 96 #define MEDIA_BUS_FMT_YUYV12_1X24 0x2022 99 97 #define MEDIA_BUS_FMT_YVYU12_1X24 0x2023 100 98 #define MEDIA_BUS_FMT_YUV10_1X30 0x2016 99 + #define MEDIA_BUS_FMT_UYYVYY10_0_5X30 0x2027 101 100 #define MEDIA_BUS_FMT_AYUV8_1X32 0x2017 101 + #define MEDIA_BUS_FMT_UYYVYY12_0_5X36 0x2028 102 + #define MEDIA_BUS_FMT_YUV12_1X36 0x2029 103 + #define MEDIA_BUS_FMT_YUV16_1X48 0x202a 104 + #define MEDIA_BUS_FMT_UYYVYY16_0_5X48 0x202b 102 105 103 106 /* Bayer - next is 0x3021 */ 104 107 #define MEDIA_BUS_FMT_SBGGR8_1X8 0x3001