mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
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
This commit is contained in:
@@ -62,6 +62,27 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: AAL input port
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
AAL output to the next component's input, for example could be one
|
||||
of many gamma, overdrive or other blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -89,5 +110,24 @@ examples:
|
||||
power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
|
||||
clocks = <&mmsys CLK_MM_DISP_AAL>;
|
||||
mediatek,gce-client-reg = <&gce SUBSYS_1401XXXX 0x5000 0x1000>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
aal0_in: endpoint {
|
||||
remote-endpoint = <&ccorr0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
aal0_out: endpoint {
|
||||
remote-endpoint = <&gamma0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -57,6 +57,27 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: CCORR input port
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
CCORR output to the input of the next desired component in the
|
||||
display pipeline, usually only one of the available AAL blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -65,6 +65,28 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: COLOR input port
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
COLOR output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available CCORR or AAL
|
||||
blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -56,6 +56,28 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: DITHER input, usually from a POSTMASK or GAMMA block.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
DITHER output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available DSC compressors,
|
||||
DP_INTF, DSI, LVDS or others.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -81,13 +81,34 @@ properties:
|
||||
Output port node. This port should be connected to the input port of an
|
||||
attached HDMI, LVDS or DisplayPort encoder chip.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: DPI input port
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: DPI output to an HDMI, LVDS or DisplayPort encoder input
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- port
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- port
|
||||
- required:
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
@@ -96,7 +117,7 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/mt8173-clk.h>
|
||||
|
||||
dpi0: dpi@1401d000 {
|
||||
dpi: dpi@1401d000 {
|
||||
compatible = "mediatek,mt8173-dpi";
|
||||
reg = <0x1401d000 0x1000>;
|
||||
interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
@@ -49,6 +49,30 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Display Stream Compression input, usually from one of the DITHER
|
||||
or MERGE blocks.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Display Stream Compression output to the input of the next desired
|
||||
component in the display pipeline, for example to MERGE, DP_INTF,
|
||||
DPI or DSI.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -77,6 +77,26 @@ properties:
|
||||
Output port node. This port should be connected to the input
|
||||
port of an attached DSI panel or DSI-to-eDP encoder chip.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input ports can have multiple endpoints, each of those connects
|
||||
to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: DSI input port, usually from DITHER, DSC or MERGE
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
DSI output to an attached DSI panel, or a DSI-to-X encoder chip
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -86,7 +106,12 @@ required:
|
||||
- clock-names
|
||||
- phys
|
||||
- phy-names
|
||||
- port
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- port
|
||||
- required:
|
||||
- ports
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -110,6 +110,28 @@ properties:
|
||||
include/dt-bindings/gce/<chip>-gce.h, mapping to the register of display
|
||||
function block.
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: ETHDR input, usually from one of the MERGE blocks.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
ETHDR output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available MERGE blocks,
|
||||
or others.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -65,6 +65,25 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: GAMMA input, usually from one of the AAL blocks.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
GAMMA output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available DITHER or
|
||||
POSTMASK blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -77,6 +77,29 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
MERGE input port, usually from DITHER, DPI, DSC, DSI, MDP_RDMA,
|
||||
ETHDR or even from a different MERGE block
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
MERGE output to a DSC, DPI, DP_INTF, DSI, ETHDR, Write DMA, or
|
||||
a different MERGE block, or others.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
resets:
|
||||
description: reset controller
|
||||
See Documentation/devicetree/bindings/reset/reset.txt for details.
|
||||
|
||||
@@ -38,6 +38,28 @@ properties:
|
||||
items:
|
||||
- description: OD Clock
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: OD input port, usually from an AAL block
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
OD output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available RDMA or
|
||||
other blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -57,6 +57,28 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: OVL input port from MMSYS, VDOSYS or other OVLs
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
OVL output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available COLOR, RDMA
|
||||
or WDMA blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -75,6 +75,28 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: OVL input port from MMSYS or one of multiple VDOSYS
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
OVL output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available COLOR, RDMA
|
||||
or WDMA blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -52,6 +52,27 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: POSTMASK input port, usually from GAMMA
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
POSTMASK output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available DITHER blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -87,6 +87,28 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: RDMA input port, usually from MMSYS, OD or OVL
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
RDMA output to the input of the next desired component in the
|
||||
display pipeline, for example one of the available COLOR, DPI,
|
||||
DSI, MERGE or UFOE blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -43,6 +43,27 @@ properties:
|
||||
items:
|
||||
- description: UFOe Clock
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
description:
|
||||
Input and output ports can have multiple endpoints, each of those
|
||||
connects to either the primary, secondary, etc, display pipeline.
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: UFOE input, usually from one of the RDMA blocks.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
UFOE output to the input of the next desired component in the
|
||||
display pipeline, usually one of the available DSI blocks.
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -109,6 +109,7 @@ size_t mtk_ovl_get_num_formats(struct device *dev);
|
||||
|
||||
void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
|
||||
void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
|
||||
bool mtk_ovl_adaptor_is_comp_present(struct device_node *node);
|
||||
void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev,
|
||||
unsigned int next);
|
||||
void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
|
||||
|
||||
@@ -497,6 +497,41 @@ static int compare_of(struct device *dev, void *data)
|
||||
return dev->of_node == data;
|
||||
}
|
||||
|
||||
static int ovl_adaptor_of_get_ddp_comp_type(struct device_node *node,
|
||||
enum mtk_ovl_adaptor_comp_type *ctype)
|
||||
{
|
||||
const struct of_device_id *of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node);
|
||||
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
*ctype = (enum mtk_ovl_adaptor_comp_type)((uintptr_t)of_id->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mtk_ovl_adaptor_is_comp_present(struct device_node *node)
|
||||
{
|
||||
enum mtk_ovl_adaptor_comp_type type;
|
||||
int ret;
|
||||
|
||||
ret = ovl_adaptor_of_get_ddp_comp_type(node, &type);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
if (type >= OVL_ADAPTOR_TYPE_NUM)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* In the context of mediatek-drm, ETHDR, MDP_RDMA and Padding are
|
||||
* used exclusively by OVL Adaptor: if this component is not one of
|
||||
* those, it's likely not an OVL Adaptor path.
|
||||
*/
|
||||
return type == OVL_ADAPTOR_TYPE_ETHDR ||
|
||||
type == OVL_ADAPTOR_TYPE_MDP_RDMA ||
|
||||
type == OVL_ADAPTOR_TYPE_PADDING;
|
||||
}
|
||||
|
||||
static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match)
|
||||
{
|
||||
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
|
||||
@@ -506,12 +541,11 @@ static int ovl_adaptor_comp_init(struct device *dev, struct component_match **ma
|
||||
parent = dev->parent->parent->of_node->parent;
|
||||
|
||||
for_each_child_of_node_scoped(parent, node) {
|
||||
const struct of_device_id *of_id;
|
||||
enum mtk_ovl_adaptor_comp_type type;
|
||||
int id;
|
||||
int id, ret;
|
||||
|
||||
of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node);
|
||||
if (!of_id)
|
||||
ret = ovl_adaptor_of_get_ddp_comp_type(node, &type);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
if (!of_device_is_available(node)) {
|
||||
@@ -520,7 +554,6 @@ static int ovl_adaptor_comp_init(struct device *dev, struct component_match **ma
|
||||
continue;
|
||||
}
|
||||
|
||||
type = (enum mtk_ovl_adaptor_comp_type)(uintptr_t)of_id->data;
|
||||
id = ovl_adaptor_comp_get_id(dev, node, type);
|
||||
if (id < 0) {
|
||||
dev_warn(dev, "Skipping unknown component %pOF\n",
|
||||
|
||||
@@ -704,6 +704,20 @@ static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
|
||||
int ret;
|
||||
|
||||
dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 1, -1);
|
||||
if (IS_ERR(dpi->next_bridge)) {
|
||||
ret = PTR_ERR(dpi->next_bridge);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
/* Old devicetree has only one endpoint */
|
||||
dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 0, 0);
|
||||
if (IS_ERR(dpi->next_bridge))
|
||||
return dev_err_probe(dpi->dev, PTR_ERR(dpi->next_bridge),
|
||||
"Failed to get bridge\n");
|
||||
}
|
||||
|
||||
return drm_bridge_attach(bridge->encoder, dpi->next_bridge,
|
||||
&dpi->bridge, flags);
|
||||
@@ -1058,13 +1072,6 @@ static int mtk_dpi_probe(struct platform_device *pdev)
|
||||
if (dpi->irq < 0)
|
||||
return dpi->irq;
|
||||
|
||||
dpi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
|
||||
if (IS_ERR(dpi->next_bridge))
|
||||
return dev_err_probe(dev, PTR_ERR(dpi->next_bridge),
|
||||
"Failed to get bridge\n");
|
||||
|
||||
dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node);
|
||||
|
||||
platform_set_drvdata(pdev, dpi);
|
||||
|
||||
dpi->bridge.funcs = &mtk_dpi_bridge_funcs;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "mtk_crtc.h"
|
||||
#include "mtk_ddp_comp.h"
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_drv.h"
|
||||
#include "mtk_gem.h"
|
||||
|
||||
@@ -372,12 +373,11 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
|
||||
struct mtk_drm_private *temp_drm_priv;
|
||||
struct device_node *phandle = dev->parent->of_node;
|
||||
const struct of_device_id *of_id;
|
||||
struct device_node *node;
|
||||
struct device *drm_dev;
|
||||
unsigned int cnt = 0;
|
||||
int i, j;
|
||||
|
||||
for_each_child_of_node(phandle->parent, node) {
|
||||
for_each_child_of_node_scoped(phandle->parent, node) {
|
||||
struct platform_device *pdev;
|
||||
|
||||
of_id = of_match_node(mtk_drm_of_ids, node);
|
||||
@@ -820,12 +820,235 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static int mtk_drm_of_get_ddp_comp_type(struct device_node *node, enum mtk_ddp_comp_type *ctype)
|
||||
{
|
||||
const struct of_device_id *of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
|
||||
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
*ctype = (enum mtk_ddp_comp_type)((uintptr_t)of_id->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_drm_of_get_ddp_ep_cid(struct device_node *node,
|
||||
int output_port, enum mtk_crtc_path crtc_path,
|
||||
struct device_node **next, unsigned int *cid)
|
||||
{
|
||||
struct device_node *ep_dev_node, *ep_out;
|
||||
enum mtk_ddp_comp_type comp_type;
|
||||
int ret;
|
||||
|
||||
ep_out = of_graph_get_endpoint_by_regs(node, output_port, crtc_path);
|
||||
if (!ep_out)
|
||||
return -ENOENT;
|
||||
|
||||
ep_dev_node = of_graph_get_remote_port_parent(ep_out);
|
||||
of_node_put(ep_out);
|
||||
if (!ep_dev_node)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Pass the next node pointer regardless of failures in the later code
|
||||
* so that if this function is called in a loop it will walk through all
|
||||
* of the subsequent endpoints anyway.
|
||||
*/
|
||||
*next = ep_dev_node;
|
||||
|
||||
if (!of_device_is_available(ep_dev_node))
|
||||
return -ENODEV;
|
||||
|
||||
ret = mtk_drm_of_get_ddp_comp_type(ep_dev_node, &comp_type);
|
||||
if (ret) {
|
||||
if (mtk_ovl_adaptor_is_comp_present(ep_dev_node)) {
|
||||
*cid = (unsigned int)DDP_COMPONENT_DRM_OVL_ADAPTOR;
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_get_id(ep_dev_node, comp_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* All ok! Pass the Component ID to the caller. */
|
||||
*cid = (unsigned int)ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mtk_drm_of_ddp_path_build_one - Build a Display HW Pipeline for a CRTC Path
|
||||
* @dev: The mediatek-drm device
|
||||
* @cpath: CRTC Path relative to a VDO or MMSYS
|
||||
* @out_path: Pointer to an array that will contain the new pipeline
|
||||
* @out_path_len: Number of entries in the pipeline array
|
||||
*
|
||||
* MediaTek SoCs can use different DDP hardware pipelines (or paths) depending
|
||||
* on the board-specific desired display configuration; this function walks
|
||||
* through all of the output endpoints starting from a VDO or MMSYS hardware
|
||||
* instance and builds the right pipeline as specified in device trees.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - Display HW Pipeline successfully built and validated
|
||||
* * %-ENOENT - Display pipeline was not specified in device tree
|
||||
* * %-EINVAL - Display pipeline built but validation failed
|
||||
* * %-ENOMEM - Failure to allocate pipeline array to pass to the caller
|
||||
*/
|
||||
static int mtk_drm_of_ddp_path_build_one(struct device *dev, enum mtk_crtc_path cpath,
|
||||
const unsigned int **out_path,
|
||||
unsigned int *out_path_len)
|
||||
{
|
||||
struct device_node *next, *prev, *vdo = dev->parent->of_node;
|
||||
unsigned int temp_path[DDP_COMPONENT_DRM_ID_MAX] = { 0 };
|
||||
unsigned int *final_ddp_path;
|
||||
unsigned short int idx = 0;
|
||||
bool ovl_adaptor_comp_added = false;
|
||||
int ret;
|
||||
|
||||
/* Get the first entry for the temp_path array */
|
||||
ret = mtk_drm_of_get_ddp_ep_cid(vdo, 0, cpath, &next, &temp_path[idx]);
|
||||
if (ret) {
|
||||
if (next && temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) {
|
||||
dev_dbg(dev, "Adding OVL Adaptor for %pOF\n", next);
|
||||
ovl_adaptor_comp_added = true;
|
||||
} else {
|
||||
if (next)
|
||||
dev_err(dev, "Invalid component %pOF\n", next);
|
||||
else
|
||||
dev_err(dev, "Cannot find first endpoint for path %d\n", cpath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
|
||||
/*
|
||||
* Walk through port outputs until we reach the last valid mediatek-drm component.
|
||||
* To be valid, this must end with an "invalid" component that is a display node.
|
||||
*/
|
||||
do {
|
||||
prev = next;
|
||||
ret = mtk_drm_of_get_ddp_ep_cid(next, 1, cpath, &next, &temp_path[idx]);
|
||||
of_node_put(prev);
|
||||
if (ret) {
|
||||
of_node_put(next);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is an OVL adaptor exclusive component and one of those
|
||||
* was already added, don't add another instance of the generic
|
||||
* DDP_COMPONENT_OVL_ADAPTOR, as this is used only to decide whether
|
||||
* to probe that component master driver of which only one instance
|
||||
* is needed and possible.
|
||||
*/
|
||||
if (temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) {
|
||||
if (!ovl_adaptor_comp_added)
|
||||
ovl_adaptor_comp_added = true;
|
||||
else
|
||||
idx--;
|
||||
}
|
||||
} while (++idx < DDP_COMPONENT_DRM_ID_MAX);
|
||||
|
||||
/*
|
||||
* The device component might not be enabled: in that case, don't
|
||||
* check the last entry and just report that the device is missing.
|
||||
*/
|
||||
if (ret == -ENODEV)
|
||||
return ret;
|
||||
|
||||
/* If the last entry is not a final display output, the configuration is wrong */
|
||||
switch (temp_path[idx - 1]) {
|
||||
case DDP_COMPONENT_DP_INTF0:
|
||||
case DDP_COMPONENT_DP_INTF1:
|
||||
case DDP_COMPONENT_DPI0:
|
||||
case DDP_COMPONENT_DPI1:
|
||||
case DDP_COMPONENT_DSI0:
|
||||
case DDP_COMPONENT_DSI1:
|
||||
case DDP_COMPONENT_DSI2:
|
||||
case DDP_COMPONENT_DSI3:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Invalid display hw pipeline. Last component: %d (ret=%d)\n",
|
||||
temp_path[idx - 1], ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
final_ddp_path = devm_kmemdup(dev, temp_path, idx * sizeof(temp_path[0]), GFP_KERNEL);
|
||||
if (!final_ddp_path)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_dbg(dev, "Display HW Pipeline built with %d components.\n", idx);
|
||||
|
||||
/* Pipeline built! */
|
||||
*out_path = final_ddp_path;
|
||||
*out_path_len = idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_drm_of_ddp_path_build(struct device *dev, struct device_node *node,
|
||||
struct mtk_mmsys_driver_data *data)
|
||||
{
|
||||
struct device_node *ep_node;
|
||||
struct of_endpoint of_ep;
|
||||
bool output_present[MAX_CRTC] = { false };
|
||||
int ret;
|
||||
|
||||
for_each_endpoint_of_node(node, ep_node) {
|
||||
ret = of_graph_parse_endpoint(ep_node, &of_ep);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Cannot parse endpoint\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (of_ep.id >= MAX_CRTC) {
|
||||
ret = dev_err_probe(dev, -EINVAL,
|
||||
"Invalid endpoint%u number\n", of_ep.port);
|
||||
break;
|
||||
}
|
||||
|
||||
output_present[of_ep.id] = true;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
of_node_put(ep_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (output_present[CRTC_MAIN]) {
|
||||
ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_MAIN,
|
||||
&data->main_path, &data->main_len);
|
||||
if (ret && ret != -ENODEV)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (output_present[CRTC_EXT]) {
|
||||
ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_EXT,
|
||||
&data->ext_path, &data->ext_len);
|
||||
if (ret && ret != -ENODEV)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (output_present[CRTC_THIRD]) {
|
||||
ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_THIRD,
|
||||
&data->third_path, &data->third_len);
|
||||
if (ret && ret != -ENODEV)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_drm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *phandle = dev->parent->of_node;
|
||||
const struct of_device_id *of_id;
|
||||
struct mtk_drm_private *private;
|
||||
struct mtk_mmsys_driver_data *mtk_drm_data;
|
||||
struct device_node *node;
|
||||
struct component_match *match = NULL;
|
||||
struct platform_device *ovl_adaptor;
|
||||
@@ -846,7 +1069,27 @@ static int mtk_drm_probe(struct platform_device *pdev)
|
||||
if (!of_id)
|
||||
return -ENODEV;
|
||||
|
||||
private->data = of_id->data;
|
||||
mtk_drm_data = (struct mtk_mmsys_driver_data *)of_id->data;
|
||||
if (!mtk_drm_data)
|
||||
return -EINVAL;
|
||||
|
||||
/* Try to build the display pipeline from devicetree graphs */
|
||||
if (of_graph_is_present(phandle)) {
|
||||
dev_dbg(dev, "Building display pipeline for MMSYS %u\n",
|
||||
mtk_drm_data->mmsys_id);
|
||||
private->data = devm_kmemdup(dev, mtk_drm_data,
|
||||
sizeof(*mtk_drm_data), GFP_KERNEL);
|
||||
if (!private->data)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mtk_drm_of_ddp_path_build(dev, phandle, private->data);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* No devicetree graphs support: go with hardcoded paths if present */
|
||||
dev_dbg(dev, "Using hardcoded paths for MMSYS %u\n", mtk_drm_data->mmsys_id);
|
||||
private->data = mtk_drm_data;
|
||||
};
|
||||
|
||||
private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
|
||||
sizeof(*private->all_drm_private),
|
||||
@@ -868,12 +1111,11 @@ static int mtk_drm_probe(struct platform_device *pdev)
|
||||
|
||||
/* Iterate over sibling DISP function blocks */
|
||||
for_each_child_of_node(phandle->parent, node) {
|
||||
const struct of_device_id *of_id;
|
||||
enum mtk_ddp_comp_type comp_type;
|
||||
int comp_id;
|
||||
|
||||
of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
|
||||
if (!of_id)
|
||||
ret = mtk_drm_of_get_ddp_comp_type(node, &comp_type);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
if (!of_device_is_available(node)) {
|
||||
@@ -882,8 +1124,6 @@ static int mtk_drm_probe(struct platform_device *pdev)
|
||||
continue;
|
||||
}
|
||||
|
||||
comp_type = (enum mtk_ddp_comp_type)(uintptr_t)of_id->data;
|
||||
|
||||
if (comp_type == MTK_DISP_MUTEX) {
|
||||
int id;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ struct mtk_drm_private {
|
||||
struct device *mmsys_dev;
|
||||
struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX];
|
||||
struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX];
|
||||
const struct mtk_mmsys_driver_data *data;
|
||||
struct mtk_mmsys_driver_data *data;
|
||||
struct drm_atomic_state *suspend_state;
|
||||
unsigned int mbox_index;
|
||||
struct mtk_drm_private **all_drm_private;
|
||||
|
||||
@@ -988,9 +988,17 @@ static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
|
||||
dsi->lanes = device->lanes;
|
||||
dsi->format = device->format;
|
||||
dsi->mode_flags = device->mode_flags;
|
||||
dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
|
||||
if (IS_ERR(dsi->next_bridge))
|
||||
return PTR_ERR(dsi->next_bridge);
|
||||
dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
|
||||
if (IS_ERR(dsi->next_bridge)) {
|
||||
ret = PTR_ERR(dsi->next_bridge);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
/* Old devicetree has only one endpoint */
|
||||
dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
|
||||
if (IS_ERR(dsi->next_bridge))
|
||||
return PTR_ERR(dsi->next_bridge);
|
||||
}
|
||||
|
||||
drm_bridge_add(&dsi->bridge);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user