2 * Copyright (c) 2016 MediaTek Inc.
3 * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <linux/clk.h>
16 #include <linux/device.h>
18 #include <linux/of_address.h>
19 #include <linux/of_platform.h>
20 #include <soc/mediatek/smi.h>
22 #include "mtk_mdp_comp.h"
25 static const char * const mtk_mdp_comp_stem
[MTK_MDP_COMP_TYPE_MAX
] = {
32 struct mtk_mdp_comp_match
{
33 enum mtk_mdp_comp_type type
;
37 static const struct mtk_mdp_comp_match mtk_mdp_matches
[MTK_MDP_COMP_ID_MAX
] = {
48 int mtk_mdp_comp_get_id(struct device
*dev
, struct device_node
*node
,
49 enum mtk_mdp_comp_type comp_type
)
51 int id
= of_alias_get_id(node
, mtk_mdp_comp_stem
[comp_type
]);
54 for (i
= 0; i
< ARRAY_SIZE(mtk_mdp_matches
); i
++) {
55 if (comp_type
== mtk_mdp_matches
[i
].type
&&
56 id
== mtk_mdp_matches
[i
].alias_id
)
60 dev_err(dev
, "Failed to get id. type: %d, id: %d\n", comp_type
, id
);
65 void mtk_mdp_comp_clock_on(struct device
*dev
, struct mtk_mdp_comp
*comp
)
70 err
= mtk_smi_larb_get(comp
->larb_dev
);
73 "failed to get larb, err %d. type:%d id:%d\n",
74 err
, comp
->type
, comp
->id
);
77 for (i
= 0; i
< ARRAY_SIZE(comp
->clk
); i
++) {
78 if (IS_ERR(comp
->clk
[i
]))
80 err
= clk_prepare_enable(comp
->clk
[i
]);
83 "failed to enable clock, err %d. type:%d id:%d i:%d\n",
84 err
, comp
->type
, comp
->id
, i
);
88 void mtk_mdp_comp_clock_off(struct device
*dev
, struct mtk_mdp_comp
*comp
)
92 for (i
= 0; i
< ARRAY_SIZE(comp
->clk
); i
++) {
93 if (IS_ERR(comp
->clk
[i
]))
95 clk_disable_unprepare(comp
->clk
[i
]);
99 mtk_smi_larb_put(comp
->larb_dev
);
102 int mtk_mdp_comp_init(struct device
*dev
, struct device_node
*node
,
103 struct mtk_mdp_comp
*comp
, enum mtk_mdp_comp_id comp_id
)
105 struct device_node
*larb_node
;
106 struct platform_device
*larb_pdev
;
109 if (comp_id
< 0 || comp_id
>= MTK_MDP_COMP_ID_MAX
) {
110 dev_err(dev
, "Invalid comp_id %d\n", comp_id
);
114 comp
->dev_node
= of_node_get(node
);
116 comp
->type
= mtk_mdp_matches
[comp_id
].type
;
117 comp
->regs
= of_iomap(node
, 0);
119 for (i
= 0; i
< ARRAY_SIZE(comp
->clk
); i
++) {
120 comp
->clk
[i
] = of_clk_get(node
, i
);
122 /* Only RDMA needs two clocks */
123 if (comp
->type
!= MTK_MDP_RDMA
)
127 /* Only DMA capable components need the LARB property */
128 comp
->larb_dev
= NULL
;
129 if (comp
->type
!= MTK_MDP_RDMA
&&
130 comp
->type
!= MTK_MDP_WDMA
&&
131 comp
->type
!= MTK_MDP_WROT
)
134 larb_node
= of_parse_phandle(node
, "mediatek,larb", 0);
137 "Missing mediadek,larb phandle in %pOF node\n", node
);
141 larb_pdev
= of_find_device_by_node(larb_node
);
143 dev_warn(dev
, "Waiting for larb device %pOF\n", larb_node
);
144 of_node_put(larb_node
);
145 return -EPROBE_DEFER
;
147 of_node_put(larb_node
);
149 comp
->larb_dev
= &larb_pdev
->dev
;
154 void mtk_mdp_comp_deinit(struct device
*dev
, struct mtk_mdp_comp
*comp
)
156 of_node_put(comp
->dev_node
);