1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
4 */
5
6 #include <linux/of_gpio.h>
7 #include <linux/phy/phy.h>
8
9 #include <drm/drm_print.h>
10
11 #include "dp_parser.h"
12 #include "dp_reg.h"
13
14 static const struct dp_regulator_cfg sdm845_dp_reg_cfg = {
15 .num = 2,
16 .regs = {
17 {"vdda-1p2", 21800, 4 }, /* 1.2 V */
18 {"vdda-0p9", 36000, 32 }, /* 0.9 V */
19 },
20 };
21
msm_dss_ioremap(struct platform_device * pdev,struct dss_io_data * io_data)22 static int msm_dss_ioremap(struct platform_device *pdev,
23 struct dss_io_data *io_data)
24 {
25 struct resource *res = NULL;
26
27 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
28 if (!res) {
29 DRM_ERROR("%pS->%s: msm_dss_get_res failed\n",
30 __builtin_return_address(0), __func__);
31 return -ENODEV;
32 }
33
34 io_data->len = (u32)resource_size(res);
35 io_data->base = ioremap(res->start, io_data->len);
36 if (!io_data->base) {
37 DRM_ERROR("%pS->%s: ioremap failed\n",
38 __builtin_return_address(0), __func__);
39 return -EIO;
40 }
41
42 return 0;
43 }
44
msm_dss_iounmap(struct dss_io_data * io_data)45 static void msm_dss_iounmap(struct dss_io_data *io_data)
46 {
47 if (io_data->base) {
48 iounmap(io_data->base);
49 io_data->base = NULL;
50 }
51 io_data->len = 0;
52 }
53
dp_parser_unmap_io_resources(struct dp_parser * parser)54 static void dp_parser_unmap_io_resources(struct dp_parser *parser)
55 {
56 struct dp_io *io = &parser->io;
57
58 msm_dss_iounmap(&io->dp_controller);
59 }
60
dp_parser_ctrl_res(struct dp_parser * parser)61 static int dp_parser_ctrl_res(struct dp_parser *parser)
62 {
63 int rc = 0;
64 struct platform_device *pdev = parser->pdev;
65 struct dp_io *io = &parser->io;
66
67 rc = msm_dss_ioremap(pdev, &io->dp_controller);
68 if (rc) {
69 DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc);
70 goto err;
71 }
72
73 io->phy = devm_phy_get(&pdev->dev, "dp");
74 if (IS_ERR(io->phy)) {
75 rc = PTR_ERR(io->phy);
76 goto err;
77 }
78
79 return 0;
80 err:
81 dp_parser_unmap_io_resources(parser);
82 return rc;
83 }
84
dp_parser_misc(struct dp_parser * parser)85 static int dp_parser_misc(struct dp_parser *parser)
86 {
87 struct device_node *of_node = parser->pdev->dev.of_node;
88 int len = 0;
89 const char *data_lane_property = "data-lanes";
90
91 len = of_property_count_elems_of_size(of_node,
92 data_lane_property, sizeof(u32));
93 if (len < 0) {
94 DRM_WARN("Invalid property %s, default max DP lanes = %d\n",
95 data_lane_property, DP_MAX_NUM_DP_LANES);
96 len = DP_MAX_NUM_DP_LANES;
97 }
98
99 parser->max_dp_lanes = len;
100 return 0;
101 }
102
dp_parser_check_prefix(const char * clk_prefix,const char * clk_name)103 static inline bool dp_parser_check_prefix(const char *clk_prefix,
104 const char *clk_name)
105 {
106 return !strncmp(clk_prefix, clk_name, strlen(clk_prefix));
107 }
108
dp_parser_init_clk_data(struct dp_parser * parser)109 static int dp_parser_init_clk_data(struct dp_parser *parser)
110 {
111 int num_clk, i, rc;
112 int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
113 const char *clk_name;
114 struct device *dev = &parser->pdev->dev;
115 struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
116 struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
117 struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
118
119 num_clk = of_property_count_strings(dev->of_node, "clock-names");
120 if (num_clk <= 0) {
121 DRM_ERROR("no clocks are defined\n");
122 return -EINVAL;
123 }
124
125 for (i = 0; i < num_clk; i++) {
126 rc = of_property_read_string_index(dev->of_node,
127 "clock-names", i, &clk_name);
128 if (rc < 0)
129 return rc;
130
131 if (dp_parser_check_prefix("core", clk_name))
132 core_clk_count++;
133
134 if (dp_parser_check_prefix("ctrl", clk_name))
135 ctrl_clk_count++;
136
137 if (dp_parser_check_prefix("stream", clk_name))
138 stream_clk_count++;
139 }
140
141 /* Initialize the CORE power module */
142 if (core_clk_count == 0) {
143 DRM_ERROR("no core clocks are defined\n");
144 return -EINVAL;
145 }
146
147 core_power->num_clk = core_clk_count;
148 core_power->clk_config = devm_kzalloc(dev,
149 sizeof(struct dss_clk) * core_power->num_clk,
150 GFP_KERNEL);
151 if (!core_power->clk_config)
152 return -EINVAL;
153
154 /* Initialize the CTRL power module */
155 if (ctrl_clk_count == 0) {
156 DRM_ERROR("no ctrl clocks are defined\n");
157 return -EINVAL;
158 }
159
160 ctrl_power->num_clk = ctrl_clk_count;
161 ctrl_power->clk_config = devm_kzalloc(dev,
162 sizeof(struct dss_clk) * ctrl_power->num_clk,
163 GFP_KERNEL);
164 if (!ctrl_power->clk_config) {
165 ctrl_power->num_clk = 0;
166 return -EINVAL;
167 }
168
169 /* Initialize the STREAM power module */
170 if (stream_clk_count == 0) {
171 DRM_ERROR("no stream (pixel) clocks are defined\n");
172 return -EINVAL;
173 }
174
175 stream_power->num_clk = stream_clk_count;
176 stream_power->clk_config = devm_kzalloc(dev,
177 sizeof(struct dss_clk) * stream_power->num_clk,
178 GFP_KERNEL);
179 if (!stream_power->clk_config) {
180 stream_power->num_clk = 0;
181 return -EINVAL;
182 }
183
184 return 0;
185 }
186
dp_parser_clock(struct dp_parser * parser)187 static int dp_parser_clock(struct dp_parser *parser)
188 {
189 int rc = 0, i = 0;
190 int num_clk = 0;
191 int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0;
192 int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
193 const char *clk_name;
194 struct device *dev = &parser->pdev->dev;
195 struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
196 struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
197 struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
198
199 rc = dp_parser_init_clk_data(parser);
200 if (rc) {
201 DRM_ERROR("failed to initialize power data %d\n", rc);
202 return -EINVAL;
203 }
204
205 core_clk_count = core_power->num_clk;
206 ctrl_clk_count = ctrl_power->num_clk;
207 stream_clk_count = stream_power->num_clk;
208
209 num_clk = core_clk_count + ctrl_clk_count + stream_clk_count;
210
211 for (i = 0; i < num_clk; i++) {
212 rc = of_property_read_string_index(dev->of_node, "clock-names",
213 i, &clk_name);
214 if (rc) {
215 DRM_ERROR("error reading clock-names %d\n", rc);
216 return rc;
217 }
218 if (dp_parser_check_prefix("core", clk_name) &&
219 core_clk_index < core_clk_count) {
220 struct dss_clk *clk =
221 &core_power->clk_config[core_clk_index];
222 strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
223 clk->type = DSS_CLK_AHB;
224 core_clk_index++;
225 } else if (dp_parser_check_prefix("stream", clk_name) &&
226 stream_clk_index < stream_clk_count) {
227 struct dss_clk *clk =
228 &stream_power->clk_config[stream_clk_index];
229 strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
230 clk->type = DSS_CLK_PCLK;
231 stream_clk_index++;
232 } else if (dp_parser_check_prefix("ctrl", clk_name) &&
233 ctrl_clk_index < ctrl_clk_count) {
234 struct dss_clk *clk =
235 &ctrl_power->clk_config[ctrl_clk_index];
236 strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
237 ctrl_clk_index++;
238 if (dp_parser_check_prefix("ctrl_link", clk_name) ||
239 dp_parser_check_prefix("stream_pixel", clk_name))
240 clk->type = DSS_CLK_PCLK;
241 else
242 clk->type = DSS_CLK_AHB;
243 }
244 }
245
246 DRM_DEBUG_DP("clock parsing successful\n");
247
248 return 0;
249 }
250
dp_parser_parse(struct dp_parser * parser)251 static int dp_parser_parse(struct dp_parser *parser)
252 {
253 int rc = 0;
254
255 if (!parser) {
256 DRM_ERROR("invalid input\n");
257 return -EINVAL;
258 }
259
260 rc = dp_parser_ctrl_res(parser);
261 if (rc)
262 return rc;
263
264 rc = dp_parser_misc(parser);
265 if (rc)
266 return rc;
267
268 rc = dp_parser_clock(parser);
269 if (rc)
270 return rc;
271
272 /* Map the corresponding regulator information according to
273 * version. Currently, since we only have one supported platform,
274 * mapping the regulator directly.
275 */
276 parser->regulator_cfg = &sdm845_dp_reg_cfg;
277
278 return 0;
279 }
280
dp_parser_get(struct platform_device * pdev)281 struct dp_parser *dp_parser_get(struct platform_device *pdev)
282 {
283 struct dp_parser *parser;
284
285 parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
286 if (!parser)
287 return ERR_PTR(-ENOMEM);
288
289 parser->parse = dp_parser_parse;
290 parser->pdev = pdev;
291
292 return parser;
293 }
294