1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2016 MediaTek Inc.
4 * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
8 #include <linux/device.h>
10 #include <linux/of_address.h>
11 #include <linux/of_platform.h>
12 #include <soc/mediatek/smi.h>
14 #include "mtk_mdp_comp.h"
17 static const char * const mtk_mdp_comp_stem
[MTK_MDP_COMP_TYPE_MAX
] = {
24 struct mtk_mdp_comp_match
{
25 enum mtk_mdp_comp_type type
;
29 static const struct mtk_mdp_comp_match mtk_mdp_matches
[MTK_MDP_COMP_ID_MAX
] = {
40 int mtk_mdp_comp_get_id(struct device
*dev
, struct device_node
*node
,
41 enum mtk_mdp_comp_type comp_type
)
43 int id
= of_alias_get_id(node
, mtk_mdp_comp_stem
[comp_type
]);
46 for (i
= 0; i
< ARRAY_SIZE(mtk_mdp_matches
); i
++) {
47 if (comp_type
== mtk_mdp_matches
[i
].type
&&
48 id
== mtk_mdp_matches
[i
].alias_id
)
52 dev_err(dev
, "Failed to get id. type: %d, id: %d\n", comp_type
, id
);
57 void mtk_mdp_comp_clock_on(struct device
*dev
, struct mtk_mdp_comp
*comp
)
62 err
= mtk_smi_larb_get(comp
->larb_dev
);
65 "failed to get larb, err %d. type:%d id:%d\n",
66 err
, comp
->type
, comp
->id
);
69 for (i
= 0; i
< ARRAY_SIZE(comp
->clk
); i
++) {
70 if (IS_ERR(comp
->clk
[i
]))
72 err
= clk_prepare_enable(comp
->clk
[i
]);
75 "failed to enable clock, err %d. type:%d id:%d i:%d\n",
76 err
, comp
->type
, comp
->id
, i
);
80 void mtk_mdp_comp_clock_off(struct device
*dev
, struct mtk_mdp_comp
*comp
)
84 for (i
= 0; i
< ARRAY_SIZE(comp
->clk
); i
++) {
85 if (IS_ERR(comp
->clk
[i
]))
87 clk_disable_unprepare(comp
->clk
[i
]);
91 mtk_smi_larb_put(comp
->larb_dev
);
94 int mtk_mdp_comp_init(struct device
*dev
, struct device_node
*node
,
95 struct mtk_mdp_comp
*comp
, enum mtk_mdp_comp_id comp_id
)
97 struct device_node
*larb_node
;
98 struct platform_device
*larb_pdev
;
101 if (comp_id
< 0 || comp_id
>= MTK_MDP_COMP_ID_MAX
) {
102 dev_err(dev
, "Invalid comp_id %d\n", comp_id
);
106 comp
->dev_node
= of_node_get(node
);
108 comp
->type
= mtk_mdp_matches
[comp_id
].type
;
109 comp
->regs
= of_iomap(node
, 0);
111 for (i
= 0; i
< ARRAY_SIZE(comp
->clk
); i
++) {
112 comp
->clk
[i
] = of_clk_get(node
, i
);
114 /* Only RDMA needs two clocks */
115 if (comp
->type
!= MTK_MDP_RDMA
)
119 /* Only DMA capable components need the LARB property */
120 comp
->larb_dev
= NULL
;
121 if (comp
->type
!= MTK_MDP_RDMA
&&
122 comp
->type
!= MTK_MDP_WDMA
&&
123 comp
->type
!= MTK_MDP_WROT
)
126 larb_node
= of_parse_phandle(node
, "mediatek,larb", 0);
129 "Missing mediadek,larb phandle in %pOF node\n", node
);
133 larb_pdev
= of_find_device_by_node(larb_node
);
135 dev_warn(dev
, "Waiting for larb device %pOF\n", larb_node
);
136 of_node_put(larb_node
);
137 return -EPROBE_DEFER
;
139 of_node_put(larb_node
);
141 comp
->larb_dev
= &larb_pdev
->dev
;
146 void mtk_mdp_comp_deinit(struct device
*dev
, struct mtk_mdp_comp
*comp
)
148 of_node_put(comp
->dev_node
);