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

Merge tag 'mediatek-drm-next-6.13' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-next

Mediatek DRM Next for Linux 6.13

1. Add support for OF graphs
2. Fix child node refcount handling and use scoped

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20241104124103.8041-1-chunkuang.hu@kernel.org

+685 -27
+40
Documentation/devicetree/bindings/display/mediatek/mediatek,aal.yaml
··· 62 62 $ref: /schemas/types.yaml#/definitions/phandle-array 63 63 maxItems: 1 64 64 65 + ports: 66 + $ref: /schemas/graph.yaml#/properties/ports 67 + description: 68 + Input and output ports can have multiple endpoints, each of those 69 + connects to either the primary, secondary, etc, display pipeline. 70 + 71 + properties: 72 + port@0: 73 + $ref: /schemas/graph.yaml#/properties/port 74 + description: AAL input port 75 + 76 + port@1: 77 + $ref: /schemas/graph.yaml#/properties/port 78 + description: 79 + AAL output to the next component's input, for example could be one 80 + of many gamma, overdrive or other blocks. 81 + 82 + required: 83 + - port@0 84 + - port@1 85 + 65 86 required: 66 87 - compatible 67 88 - reg ··· 110 89 power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; 111 90 clocks = <&mmsys CLK_MM_DISP_AAL>; 112 91 mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x5000 0x1000>; 92 + 93 + ports { 94 + #address-cells = <1>; 95 + #size-cells = <0>; 96 + 97 + port@0 { 98 + reg = <0>; 99 + aal0_in: endpoint { 100 + remote-endpoint = <&ccorr0_out>; 101 + }; 102 + }; 103 + 104 + port@1 { 105 + reg = <1>; 106 + aal0_out: endpoint { 107 + remote-endpoint = <&gamma0_in>; 108 + }; 109 + }; 110 + }; 113 111 }; 114 112 };
+21
Documentation/devicetree/bindings/display/mediatek/mediatek,ccorr.yaml
··· 57 57 $ref: /schemas/types.yaml#/definitions/phandle-array 58 58 maxItems: 1 59 59 60 + ports: 61 + $ref: /schemas/graph.yaml#/properties/ports 62 + description: 63 + Input and output ports can have multiple endpoints, each of those 64 + connects to either the primary, secondary, etc, display pipeline. 65 + 66 + properties: 67 + port@0: 68 + $ref: /schemas/graph.yaml#/properties/port 69 + description: CCORR input port 70 + 71 + port@1: 72 + $ref: /schemas/graph.yaml#/properties/port 73 + description: 74 + CCORR output to the input of the next desired component in the 75 + display pipeline, usually only one of the available AAL blocks. 76 + 77 + required: 78 + - port@0 79 + - port@1 80 + 60 81 required: 61 82 - compatible 62 83 - reg
+22
Documentation/devicetree/bindings/display/mediatek/mediatek,color.yaml
··· 65 65 $ref: /schemas/types.yaml#/definitions/phandle-array 66 66 maxItems: 1 67 67 68 + ports: 69 + $ref: /schemas/graph.yaml#/properties/ports 70 + description: 71 + Input and output ports can have multiple endpoints, each of those 72 + connects to either the primary, secondary, etc, display pipeline. 73 + 74 + properties: 75 + port@0: 76 + $ref: /schemas/graph.yaml#/properties/port 77 + description: COLOR input port 78 + 79 + port@1: 80 + $ref: /schemas/graph.yaml#/properties/port 81 + description: 82 + COLOR output to the input of the next desired component in the 83 + display pipeline, for example one of the available CCORR or AAL 84 + blocks. 85 + 86 + required: 87 + - port@0 88 + - port@1 89 + 68 90 required: 69 91 - compatible 70 92 - reg
+22
Documentation/devicetree/bindings/display/mediatek/mediatek,dither.yaml
··· 56 56 $ref: /schemas/types.yaml#/definitions/phandle-array 57 57 maxItems: 1 58 58 59 + ports: 60 + $ref: /schemas/graph.yaml#/properties/ports 61 + description: 62 + Input and output ports can have multiple endpoints, each of those 63 + connects to either the primary, secondary, etc, display pipeline. 64 + 65 + properties: 66 + port@0: 67 + $ref: /schemas/graph.yaml#/properties/port 68 + description: DITHER input, usually from a POSTMASK or GAMMA block. 69 + 70 + port@1: 71 + $ref: /schemas/graph.yaml#/properties/port 72 + description: 73 + DITHER output to the input of the next desired component in the 74 + display pipeline, for example one of the available DSC compressors, 75 + DP_INTF, DSI, LVDS or others. 76 + 77 + required: 78 + - port@0 79 + - port@1 80 + 59 81 required: 60 82 - compatible 61 83 - reg
+23 -2
Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
··· 81 81 Output port node. This port should be connected to the input port of an 82 82 attached HDMI, LVDS or DisplayPort encoder chip. 83 83 84 + ports: 85 + $ref: /schemas/graph.yaml#/properties/ports 86 + 87 + properties: 88 + port@0: 89 + $ref: /schemas/graph.yaml#/properties/port 90 + description: DPI input port 91 + 92 + port@1: 93 + $ref: /schemas/graph.yaml#/properties/port 94 + description: DPI output to an HDMI, LVDS or DisplayPort encoder input 95 + 96 + required: 97 + - port@0 98 + - port@1 99 + 84 100 required: 85 101 - compatible 86 102 - reg 87 103 - interrupts 88 104 - clocks 89 105 - clock-names 90 - - port 106 + 107 + oneOf: 108 + - required: 109 + - port 110 + - required: 111 + - ports 91 112 92 113 additionalProperties: false 93 114 ··· 117 96 #include <dt-bindings/interrupt-controller/arm-gic.h> 118 97 #include <dt-bindings/clock/mt8173-clk.h> 119 98 120 - dpi0: dpi@1401d000 { 99 + dpi: dpi@1401d000 { 121 100 compatible = "mediatek,mt8173-dpi"; 122 101 reg = <0x1401d000 0x1000>; 123 102 interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
+24
Documentation/devicetree/bindings/display/mediatek/mediatek,dsc.yaml
··· 49 49 $ref: /schemas/types.yaml#/definitions/phandle-array 50 50 maxItems: 1 51 51 52 + ports: 53 + $ref: /schemas/graph.yaml#/properties/ports 54 + description: 55 + Input and output ports can have multiple endpoints, each of those 56 + connects to either the primary, secondary, etc, display pipeline. 57 + 58 + properties: 59 + port@0: 60 + $ref: /schemas/graph.yaml#/properties/port 61 + description: 62 + Display Stream Compression input, usually from one of the DITHER 63 + or MERGE blocks. 64 + 65 + port@1: 66 + $ref: /schemas/graph.yaml#/properties/port 67 + description: 68 + Display Stream Compression output to the input of the next desired 69 + component in the display pipeline, for example to MERGE, DP_INTF, 70 + DPI or DSI. 71 + 72 + required: 73 + - port@0 74 + - port@1 75 + 52 76 required: 53 77 - compatible 54 78 - reg
+26 -1
Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.yaml
··· 77 77 Output port node. This port should be connected to the input 78 78 port of an attached DSI panel or DSI-to-eDP encoder chip. 79 79 80 + ports: 81 + $ref: /schemas/graph.yaml#/properties/ports 82 + description: 83 + Input ports can have multiple endpoints, each of those connects 84 + to either the primary, secondary, etc, display pipeline. 85 + 86 + properties: 87 + port@0: 88 + $ref: /schemas/graph.yaml#/properties/port 89 + description: DSI input port, usually from DITHER, DSC or MERGE 90 + 91 + port@1: 92 + $ref: /schemas/graph.yaml#/properties/port 93 + description: 94 + DSI output to an attached DSI panel, or a DSI-to-X encoder chip 95 + 96 + required: 97 + - port@0 98 + - port@1 99 + 80 100 required: 81 101 - compatible 82 102 - reg ··· 106 86 - clock-names 107 87 - phys 108 88 - phy-names 109 - - port 89 + 90 + oneOf: 91 + - required: 92 + - port 93 + - required: 94 + - ports 110 95 111 96 unevaluatedProperties: false 112 97
+22
Documentation/devicetree/bindings/display/mediatek/mediatek,ethdr.yaml
··· 110 110 include/dt-bindings/gce/<chip>-gce.h, mapping to the register of display 111 111 function block. 112 112 113 + ports: 114 + $ref: /schemas/graph.yaml#/properties/ports 115 + description: 116 + Input and output ports can have multiple endpoints, each of those 117 + connects to either the primary, secondary, etc, display pipeline. 118 + 119 + properties: 120 + port@0: 121 + $ref: /schemas/graph.yaml#/properties/port 122 + description: ETHDR input, usually from one of the MERGE blocks. 123 + 124 + port@1: 125 + $ref: /schemas/graph.yaml#/properties/port 126 + description: 127 + ETHDR output to the input of the next desired component in the 128 + display pipeline, for example one of the available MERGE blocks, 129 + or others. 130 + 131 + required: 132 + - port@0 133 + - port@1 134 + 113 135 required: 114 136 - compatible 115 137 - reg
+19
Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml
··· 65 65 $ref: /schemas/types.yaml#/definitions/phandle-array 66 66 maxItems: 1 67 67 68 + ports: 69 + $ref: /schemas/graph.yaml#/properties/ports 70 + 71 + properties: 72 + port@0: 73 + $ref: /schemas/graph.yaml#/properties/port 74 + description: GAMMA input, usually from one of the AAL blocks. 75 + 76 + port@1: 77 + $ref: /schemas/graph.yaml#/properties/port 78 + description: 79 + GAMMA output to the input of the next desired component in the 80 + display pipeline, for example one of the available DITHER or 81 + POSTMASK blocks. 82 + 83 + required: 84 + - port@0 85 + - port@1 86 + 68 87 required: 69 88 - compatible 70 89 - reg
+23
Documentation/devicetree/bindings/display/mediatek/mediatek,merge.yaml
··· 77 77 $ref: /schemas/types.yaml#/definitions/phandle-array 78 78 maxItems: 1 79 79 80 + ports: 81 + $ref: /schemas/graph.yaml#/properties/ports 82 + description: 83 + Input and output ports can have multiple endpoints, each of those 84 + connects to either the primary, secondary, etc, display pipeline. 85 + 86 + properties: 87 + port@0: 88 + $ref: /schemas/graph.yaml#/properties/port 89 + description: 90 + MERGE input port, usually from DITHER, DPI, DSC, DSI, MDP_RDMA, 91 + ETHDR or even from a different MERGE block 92 + 93 + port@1: 94 + $ref: /schemas/graph.yaml#/properties/port 95 + description: 96 + MERGE output to a DSC, DPI, DP_INTF, DSI, ETHDR, Write DMA, or 97 + a different MERGE block, or others. 98 + 99 + required: 100 + - port@0 101 + - port@1 102 + 80 103 resets: 81 104 description: reset controller 82 105 See Documentation/devicetree/bindings/reset/reset.txt for details.
+22
Documentation/devicetree/bindings/display/mediatek/mediatek,od.yaml
··· 38 38 items: 39 39 - description: OD Clock 40 40 41 + ports: 42 + $ref: /schemas/graph.yaml#/properties/ports 43 + description: 44 + Input and output ports can have multiple endpoints, each of those 45 + connects to either the primary, secondary, etc, display pipeline. 46 + 47 + properties: 48 + port@0: 49 + $ref: /schemas/graph.yaml#/properties/port 50 + description: OD input port, usually from an AAL block 51 + 52 + port@1: 53 + $ref: /schemas/graph.yaml#/properties/port 54 + description: 55 + OD output to the input of the next desired component in the 56 + display pipeline, for example one of the available RDMA or 57 + other blocks. 58 + 59 + required: 60 + - port@0 61 + - port@1 62 + 41 63 required: 42 64 - compatible 43 65 - reg
+22
Documentation/devicetree/bindings/display/mediatek/mediatek,ovl-2l.yaml
··· 57 57 $ref: /schemas/types.yaml#/definitions/phandle-array 58 58 maxItems: 1 59 59 60 + ports: 61 + $ref: /schemas/graph.yaml#/properties/ports 62 + description: 63 + Input and output ports can have multiple endpoints, each of those 64 + connects to either the primary, secondary, etc, display pipeline. 65 + 66 + properties: 67 + port@0: 68 + $ref: /schemas/graph.yaml#/properties/port 69 + description: OVL input port from MMSYS, VDOSYS or other OVLs 70 + 71 + port@1: 72 + $ref: /schemas/graph.yaml#/properties/port 73 + description: 74 + OVL output to the input of the next desired component in the 75 + display pipeline, for example one of the available COLOR, RDMA 76 + or WDMA blocks. 77 + 78 + required: 79 + - port@0 80 + - port@1 81 + 60 82 required: 61 83 - compatible 62 84 - reg
+22
Documentation/devicetree/bindings/display/mediatek/mediatek,ovl.yaml
··· 75 75 $ref: /schemas/types.yaml#/definitions/phandle-array 76 76 maxItems: 1 77 77 78 + ports: 79 + $ref: /schemas/graph.yaml#/properties/ports 80 + description: 81 + Input and output ports can have multiple endpoints, each of those 82 + connects to either the primary, secondary, etc, display pipeline. 83 + 84 + properties: 85 + port@0: 86 + $ref: /schemas/graph.yaml#/properties/port 87 + description: OVL input port from MMSYS or one of multiple VDOSYS 88 + 89 + port@1: 90 + $ref: /schemas/graph.yaml#/properties/port 91 + description: 92 + OVL output to the input of the next desired component in the 93 + display pipeline, for example one of the available COLOR, RDMA 94 + or WDMA blocks. 95 + 96 + required: 97 + - port@0 98 + - port@1 99 + 78 100 required: 79 101 - compatible 80 102 - reg
+21
Documentation/devicetree/bindings/display/mediatek/mediatek,postmask.yaml
··· 52 52 $ref: /schemas/types.yaml#/definitions/phandle-array 53 53 maxItems: 1 54 54 55 + ports: 56 + $ref: /schemas/graph.yaml#/properties/ports 57 + description: 58 + Input and output ports can have multiple endpoints, each of those 59 + connects to either the primary, secondary, etc, display pipeline. 60 + 61 + properties: 62 + port@0: 63 + $ref: /schemas/graph.yaml#/properties/port 64 + description: POSTMASK input port, usually from GAMMA 65 + 66 + port@1: 67 + $ref: /schemas/graph.yaml#/properties/port 68 + description: 69 + POSTMASK output to the input of the next desired component in the 70 + display pipeline, for example one of the available DITHER blocks. 71 + 72 + required: 73 + - port@0 74 + - port@1 75 + 55 76 required: 56 77 - compatible 57 78 - reg
+22
Documentation/devicetree/bindings/display/mediatek/mediatek,rdma.yaml
··· 87 87 $ref: /schemas/types.yaml#/definitions/phandle-array 88 88 maxItems: 1 89 89 90 + ports: 91 + $ref: /schemas/graph.yaml#/properties/ports 92 + description: 93 + Input and output ports can have multiple endpoints, each of those 94 + connects to either the primary, secondary, etc, display pipeline. 95 + 96 + properties: 97 + port@0: 98 + $ref: /schemas/graph.yaml#/properties/port 99 + description: RDMA input port, usually from MMSYS, OD or OVL 100 + 101 + port@1: 102 + $ref: /schemas/graph.yaml#/properties/port 103 + description: 104 + RDMA output to the input of the next desired component in the 105 + display pipeline, for example one of the available COLOR, DPI, 106 + DSI, MERGE or UFOE blocks. 107 + 108 + required: 109 + - port@0 110 + - port@1 111 + 90 112 required: 91 113 - compatible 92 114 - reg
+21
Documentation/devicetree/bindings/display/mediatek/mediatek,ufoe.yaml
··· 43 43 items: 44 44 - description: UFOe Clock 45 45 46 + ports: 47 + $ref: /schemas/graph.yaml#/properties/ports 48 + description: 49 + Input and output ports can have multiple endpoints, each of those 50 + connects to either the primary, secondary, etc, display pipeline. 51 + 52 + properties: 53 + port@0: 54 + $ref: /schemas/graph.yaml#/properties/port 55 + description: UFOE input, usually from one of the RDMA blocks. 56 + 57 + port@1: 58 + $ref: /schemas/graph.yaml#/properties/port 59 + description: 60 + UFOE output to the input of the next desired component in the 61 + display pipeline, usually one of the available DSI blocks. 62 + 63 + required: 64 + - port@0 65 + - port@1 66 + 46 67 required: 47 68 - compatible 48 69 - reg
+1
drivers/gpu/drm/mediatek/mtk_disp_drv.h
··· 109 109 110 110 void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex); 111 111 void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex); 112 + bool mtk_ovl_adaptor_is_comp_present(struct device_node *node); 112 113 void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev, 113 114 unsigned int next); 114 115 void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
+38 -5
drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
··· 497 497 return dev->of_node == data; 498 498 } 499 499 500 + static int ovl_adaptor_of_get_ddp_comp_type(struct device_node *node, 501 + enum mtk_ovl_adaptor_comp_type *ctype) 502 + { 503 + const struct of_device_id *of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node); 504 + 505 + if (!of_id) 506 + return -EINVAL; 507 + 508 + *ctype = (enum mtk_ovl_adaptor_comp_type)((uintptr_t)of_id->data); 509 + 510 + return 0; 511 + } 512 + 513 + bool mtk_ovl_adaptor_is_comp_present(struct device_node *node) 514 + { 515 + enum mtk_ovl_adaptor_comp_type type; 516 + int ret; 517 + 518 + ret = ovl_adaptor_of_get_ddp_comp_type(node, &type); 519 + if (ret) 520 + return false; 521 + 522 + if (type >= OVL_ADAPTOR_TYPE_NUM) 523 + return false; 524 + 525 + /* 526 + * In the context of mediatek-drm, ETHDR, MDP_RDMA and Padding are 527 + * used exclusively by OVL Adaptor: if this component is not one of 528 + * those, it's likely not an OVL Adaptor path. 529 + */ 530 + return type == OVL_ADAPTOR_TYPE_ETHDR || 531 + type == OVL_ADAPTOR_TYPE_MDP_RDMA || 532 + type == OVL_ADAPTOR_TYPE_PADDING; 533 + } 534 + 500 535 static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match) 501 536 { 502 537 struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev); ··· 541 506 parent = dev->parent->parent->of_node->parent; 542 507 543 508 for_each_child_of_node_scoped(parent, node) { 544 - const struct of_device_id *of_id; 545 509 enum mtk_ovl_adaptor_comp_type type; 546 - int id; 510 + int id, ret; 547 511 548 - of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node); 549 - if (!of_id) 512 + ret = ovl_adaptor_of_get_ddp_comp_type(node, &type); 513 + if (ret) 550 514 continue; 551 515 552 516 if (!of_device_is_available(node)) { ··· 554 520 continue; 555 521 } 556 522 557 - type = (enum mtk_ovl_adaptor_comp_type)(uintptr_t)of_id->data; 558 523 id = ovl_adaptor_comp_get_id(dev, node, type); 559 524 if (id < 0) { 560 525 dev_warn(dev, "Skipping unknown component %pOF\n",
+14 -7
drivers/gpu/drm/mediatek/mtk_dpi.c
··· 704 704 enum drm_bridge_attach_flags flags) 705 705 { 706 706 struct mtk_dpi *dpi = bridge_to_dpi(bridge); 707 + int ret; 708 + 709 + dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 1, -1); 710 + if (IS_ERR(dpi->next_bridge)) { 711 + ret = PTR_ERR(dpi->next_bridge); 712 + if (ret == -EPROBE_DEFER) 713 + return ret; 714 + 715 + /* Old devicetree has only one endpoint */ 716 + dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 0, 0); 717 + if (IS_ERR(dpi->next_bridge)) 718 + return dev_err_probe(dpi->dev, PTR_ERR(dpi->next_bridge), 719 + "Failed to get bridge\n"); 720 + } 707 721 708 722 return drm_bridge_attach(bridge->encoder, dpi->next_bridge, 709 723 &dpi->bridge, flags); ··· 1071 1057 dpi->irq = platform_get_irq(pdev, 0); 1072 1058 if (dpi->irq < 0) 1073 1059 return dpi->irq; 1074 - 1075 - dpi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); 1076 - if (IS_ERR(dpi->next_bridge)) 1077 - return dev_err_probe(dev, PTR_ERR(dpi->next_bridge), 1078 - "Failed to get bridge\n"); 1079 - 1080 - dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node); 1081 1060 1082 1061 platform_set_drvdata(pdev, dpi); 1083 1062
+248 -8
drivers/gpu/drm/mediatek/mtk_drm_drv.c
··· 27 27 28 28 #include "mtk_crtc.h" 29 29 #include "mtk_ddp_comp.h" 30 + #include "mtk_disp_drv.h" 30 31 #include "mtk_drm_drv.h" 31 32 #include "mtk_gem.h" 32 33 ··· 373 372 struct mtk_drm_private *temp_drm_priv; 374 373 struct device_node *phandle = dev->parent->of_node; 375 374 const struct of_device_id *of_id; 376 - struct device_node *node; 377 375 struct device *drm_dev; 378 376 unsigned int cnt = 0; 379 377 int i, j; 380 378 381 - for_each_child_of_node(phandle->parent, node) { 379 + for_each_child_of_node_scoped(phandle->parent, node) { 382 380 struct platform_device *pdev; 383 381 384 382 of_id = of_match_node(mtk_drm_of_ids, node); ··· 820 820 { } 821 821 }; 822 822 823 + static int mtk_drm_of_get_ddp_comp_type(struct device_node *node, enum mtk_ddp_comp_type *ctype) 824 + { 825 + const struct of_device_id *of_id = of_match_node(mtk_ddp_comp_dt_ids, node); 826 + 827 + if (!of_id) 828 + return -EINVAL; 829 + 830 + *ctype = (enum mtk_ddp_comp_type)((uintptr_t)of_id->data); 831 + 832 + return 0; 833 + } 834 + 835 + static int mtk_drm_of_get_ddp_ep_cid(struct device_node *node, 836 + int output_port, enum mtk_crtc_path crtc_path, 837 + struct device_node **next, unsigned int *cid) 838 + { 839 + struct device_node *ep_dev_node, *ep_out; 840 + enum mtk_ddp_comp_type comp_type; 841 + int ret; 842 + 843 + ep_out = of_graph_get_endpoint_by_regs(node, output_port, crtc_path); 844 + if (!ep_out) 845 + return -ENOENT; 846 + 847 + ep_dev_node = of_graph_get_remote_port_parent(ep_out); 848 + of_node_put(ep_out); 849 + if (!ep_dev_node) 850 + return -EINVAL; 851 + 852 + /* 853 + * Pass the next node pointer regardless of failures in the later code 854 + * so that if this function is called in a loop it will walk through all 855 + * of the subsequent endpoints anyway. 856 + */ 857 + *next = ep_dev_node; 858 + 859 + if (!of_device_is_available(ep_dev_node)) 860 + return -ENODEV; 861 + 862 + ret = mtk_drm_of_get_ddp_comp_type(ep_dev_node, &comp_type); 863 + if (ret) { 864 + if (mtk_ovl_adaptor_is_comp_present(ep_dev_node)) { 865 + *cid = (unsigned int)DDP_COMPONENT_DRM_OVL_ADAPTOR; 866 + return 0; 867 + } 868 + return ret; 869 + } 870 + 871 + ret = mtk_ddp_comp_get_id(ep_dev_node, comp_type); 872 + if (ret < 0) 873 + return ret; 874 + 875 + /* All ok! Pass the Component ID to the caller. */ 876 + *cid = (unsigned int)ret; 877 + 878 + return 0; 879 + } 880 + 881 + /** 882 + * mtk_drm_of_ddp_path_build_one - Build a Display HW Pipeline for a CRTC Path 883 + * @dev: The mediatek-drm device 884 + * @cpath: CRTC Path relative to a VDO or MMSYS 885 + * @out_path: Pointer to an array that will contain the new pipeline 886 + * @out_path_len: Number of entries in the pipeline array 887 + * 888 + * MediaTek SoCs can use different DDP hardware pipelines (or paths) depending 889 + * on the board-specific desired display configuration; this function walks 890 + * through all of the output endpoints starting from a VDO or MMSYS hardware 891 + * instance and builds the right pipeline as specified in device trees. 892 + * 893 + * Return: 894 + * * %0 - Display HW Pipeline successfully built and validated 895 + * * %-ENOENT - Display pipeline was not specified in device tree 896 + * * %-EINVAL - Display pipeline built but validation failed 897 + * * %-ENOMEM - Failure to allocate pipeline array to pass to the caller 898 + */ 899 + static int mtk_drm_of_ddp_path_build_one(struct device *dev, enum mtk_crtc_path cpath, 900 + const unsigned int **out_path, 901 + unsigned int *out_path_len) 902 + { 903 + struct device_node *next, *prev, *vdo = dev->parent->of_node; 904 + unsigned int temp_path[DDP_COMPONENT_DRM_ID_MAX] = { 0 }; 905 + unsigned int *final_ddp_path; 906 + unsigned short int idx = 0; 907 + bool ovl_adaptor_comp_added = false; 908 + int ret; 909 + 910 + /* Get the first entry for the temp_path array */ 911 + ret = mtk_drm_of_get_ddp_ep_cid(vdo, 0, cpath, &next, &temp_path[idx]); 912 + if (ret) { 913 + if (next && temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) { 914 + dev_dbg(dev, "Adding OVL Adaptor for %pOF\n", next); 915 + ovl_adaptor_comp_added = true; 916 + } else { 917 + if (next) 918 + dev_err(dev, "Invalid component %pOF\n", next); 919 + else 920 + dev_err(dev, "Cannot find first endpoint for path %d\n", cpath); 921 + 922 + return ret; 923 + } 924 + } 925 + idx++; 926 + 927 + /* 928 + * Walk through port outputs until we reach the last valid mediatek-drm component. 929 + * To be valid, this must end with an "invalid" component that is a display node. 930 + */ 931 + do { 932 + prev = next; 933 + ret = mtk_drm_of_get_ddp_ep_cid(next, 1, cpath, &next, &temp_path[idx]); 934 + of_node_put(prev); 935 + if (ret) { 936 + of_node_put(next); 937 + break; 938 + } 939 + 940 + /* 941 + * If this is an OVL adaptor exclusive component and one of those 942 + * was already added, don't add another instance of the generic 943 + * DDP_COMPONENT_OVL_ADAPTOR, as this is used only to decide whether 944 + * to probe that component master driver of which only one instance 945 + * is needed and possible. 946 + */ 947 + if (temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) { 948 + if (!ovl_adaptor_comp_added) 949 + ovl_adaptor_comp_added = true; 950 + else 951 + idx--; 952 + } 953 + } while (++idx < DDP_COMPONENT_DRM_ID_MAX); 954 + 955 + /* 956 + * The device component might not be enabled: in that case, don't 957 + * check the last entry and just report that the device is missing. 958 + */ 959 + if (ret == -ENODEV) 960 + return ret; 961 + 962 + /* If the last entry is not a final display output, the configuration is wrong */ 963 + switch (temp_path[idx - 1]) { 964 + case DDP_COMPONENT_DP_INTF0: 965 + case DDP_COMPONENT_DP_INTF1: 966 + case DDP_COMPONENT_DPI0: 967 + case DDP_COMPONENT_DPI1: 968 + case DDP_COMPONENT_DSI0: 969 + case DDP_COMPONENT_DSI1: 970 + case DDP_COMPONENT_DSI2: 971 + case DDP_COMPONENT_DSI3: 972 + break; 973 + default: 974 + dev_err(dev, "Invalid display hw pipeline. Last component: %d (ret=%d)\n", 975 + temp_path[idx - 1], ret); 976 + return -EINVAL; 977 + } 978 + 979 + final_ddp_path = devm_kmemdup(dev, temp_path, idx * sizeof(temp_path[0]), GFP_KERNEL); 980 + if (!final_ddp_path) 981 + return -ENOMEM; 982 + 983 + dev_dbg(dev, "Display HW Pipeline built with %d components.\n", idx); 984 + 985 + /* Pipeline built! */ 986 + *out_path = final_ddp_path; 987 + *out_path_len = idx; 988 + 989 + return 0; 990 + } 991 + 992 + static int mtk_drm_of_ddp_path_build(struct device *dev, struct device_node *node, 993 + struct mtk_mmsys_driver_data *data) 994 + { 995 + struct device_node *ep_node; 996 + struct of_endpoint of_ep; 997 + bool output_present[MAX_CRTC] = { false }; 998 + int ret; 999 + 1000 + for_each_endpoint_of_node(node, ep_node) { 1001 + ret = of_graph_parse_endpoint(ep_node, &of_ep); 1002 + if (ret) { 1003 + dev_err_probe(dev, ret, "Cannot parse endpoint\n"); 1004 + break; 1005 + } 1006 + 1007 + if (of_ep.id >= MAX_CRTC) { 1008 + ret = dev_err_probe(dev, -EINVAL, 1009 + "Invalid endpoint%u number\n", of_ep.port); 1010 + break; 1011 + } 1012 + 1013 + output_present[of_ep.id] = true; 1014 + } 1015 + 1016 + if (ret) { 1017 + of_node_put(ep_node); 1018 + return ret; 1019 + } 1020 + 1021 + if (output_present[CRTC_MAIN]) { 1022 + ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_MAIN, 1023 + &data->main_path, &data->main_len); 1024 + if (ret && ret != -ENODEV) 1025 + return ret; 1026 + } 1027 + 1028 + if (output_present[CRTC_EXT]) { 1029 + ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_EXT, 1030 + &data->ext_path, &data->ext_len); 1031 + if (ret && ret != -ENODEV) 1032 + return ret; 1033 + } 1034 + 1035 + if (output_present[CRTC_THIRD]) { 1036 + ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_THIRD, 1037 + &data->third_path, &data->third_len); 1038 + if (ret && ret != -ENODEV) 1039 + return ret; 1040 + } 1041 + 1042 + return 0; 1043 + } 1044 + 823 1045 static int mtk_drm_probe(struct platform_device *pdev) 824 1046 { 825 1047 struct device *dev = &pdev->dev; 826 1048 struct device_node *phandle = dev->parent->of_node; 827 1049 const struct of_device_id *of_id; 828 1050 struct mtk_drm_private *private; 1051 + struct mtk_mmsys_driver_data *mtk_drm_data; 829 1052 struct device_node *node; 830 1053 struct component_match *match = NULL; 831 1054 struct platform_device *ovl_adaptor; ··· 1069 846 if (!of_id) 1070 847 return -ENODEV; 1071 848 1072 - private->data = of_id->data; 849 + mtk_drm_data = (struct mtk_mmsys_driver_data *)of_id->data; 850 + if (!mtk_drm_data) 851 + return -EINVAL; 852 + 853 + /* Try to build the display pipeline from devicetree graphs */ 854 + if (of_graph_is_present(phandle)) { 855 + dev_dbg(dev, "Building display pipeline for MMSYS %u\n", 856 + mtk_drm_data->mmsys_id); 857 + private->data = devm_kmemdup(dev, mtk_drm_data, 858 + sizeof(*mtk_drm_data), GFP_KERNEL); 859 + if (!private->data) 860 + return -ENOMEM; 861 + 862 + ret = mtk_drm_of_ddp_path_build(dev, phandle, private->data); 863 + if (ret) 864 + return ret; 865 + } else { 866 + /* No devicetree graphs support: go with hardcoded paths if present */ 867 + dev_dbg(dev, "Using hardcoded paths for MMSYS %u\n", mtk_drm_data->mmsys_id); 868 + private->data = mtk_drm_data; 869 + }; 1073 870 1074 871 private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num, 1075 872 sizeof(*private->all_drm_private), ··· 1111 868 1112 869 /* Iterate over sibling DISP function blocks */ 1113 870 for_each_child_of_node(phandle->parent, node) { 1114 - const struct of_device_id *of_id; 1115 871 enum mtk_ddp_comp_type comp_type; 1116 872 int comp_id; 1117 873 1118 - of_id = of_match_node(mtk_ddp_comp_dt_ids, node); 1119 - if (!of_id) 874 + ret = mtk_drm_of_get_ddp_comp_type(node, &comp_type); 875 + if (ret) 1120 876 continue; 1121 877 1122 878 if (!of_device_is_available(node)) { ··· 1123 881 node); 1124 882 continue; 1125 883 } 1126 - 1127 - comp_type = (enum mtk_ddp_comp_type)(uintptr_t)of_id->data; 1128 884 1129 885 if (comp_type == MTK_DISP_MUTEX) { 1130 886 int id;
+1 -1
drivers/gpu/drm/mediatek/mtk_drm_drv.h
··· 63 63 struct device *mmsys_dev; 64 64 struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX]; 65 65 struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX]; 66 - const struct mtk_mmsys_driver_data *data; 66 + struct mtk_mmsys_driver_data *data; 67 67 struct drm_atomic_state *suspend_state; 68 68 unsigned int mbox_index; 69 69 struct mtk_drm_private **all_drm_private;
+11 -3
drivers/gpu/drm/mediatek/mtk_dsi.c
··· 988 988 dsi->lanes = device->lanes; 989 989 dsi->format = device->format; 990 990 dsi->mode_flags = device->mode_flags; 991 - dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); 992 - if (IS_ERR(dsi->next_bridge)) 993 - return PTR_ERR(dsi->next_bridge); 991 + dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); 992 + if (IS_ERR(dsi->next_bridge)) { 993 + ret = PTR_ERR(dsi->next_bridge); 994 + if (ret == -EPROBE_DEFER) 995 + return ret; 996 + 997 + /* Old devicetree has only one endpoint */ 998 + dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); 999 + if (IS_ERR(dsi->next_bridge)) 1000 + return PTR_ERR(dsi->next_bridge); 1001 + } 994 1002 995 1003 drm_bridge_add(&dsi->bridge); 996 1004