blob: c85c2a2d9de8f128c92a2822b91073b75b63cdf8 [file] [log] [blame]
Ajay Singh Parmar769215f2017-03-19 22:35:13 -07001/*
2 * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
16
17#include <linux/of_gpio.h>
18
19#include "dp_parser.h"
20
21static void dp_parser_unmap_io_resources(struct dp_parser *parser)
22{
23 struct dp_io *io = &parser->io;
24
25 if (&io->ctrl_io)
26 msm_dss_iounmap(&io->ctrl_io);
27 if (&io->phy_io)
28 msm_dss_iounmap(&io->phy_io);
29 if (&io->ln_tx0_io)
30 msm_dss_iounmap(&io->ln_tx0_io);
31 if (&io->ln_tx1_io)
32 msm_dss_iounmap(&io->ln_tx0_io);
33 if (&io->dp_pll_io)
34 msm_dss_iounmap(&io->dp_pll_io);
35 if (&io->dp_cc_io)
36 msm_dss_iounmap(&io->dp_cc_io);
37 if (&io->qfprom_io)
38 msm_dss_iounmap(&io->qfprom_io);
39 if (&io->hdcp_io)
40 msm_dss_iounmap(&io->hdcp_io);
41}
42
43static int dp_parser_ctrl_res(struct dp_parser *parser)
44{
45 int rc = 0;
46 u32 index;
47 struct platform_device *pdev = parser->pdev;
48 struct device_node *of_node = parser->pdev->dev.of_node;
49 struct dp_io *io = &parser->io;
50
51 rc = of_property_read_u32(of_node, "cell-index", &index);
52 if (rc) {
53 pr_err("cell-index not specified, rc=%d\n", rc);
54 goto err;
55 }
56
57 rc = msm_dss_ioremap_byname(pdev, &io->ctrl_io, "dp_ctrl");
58 if (rc) {
59 pr_err("unable to remap dp io resources\n");
60 goto err;
61 }
62
63 rc = msm_dss_ioremap_byname(pdev, &io->phy_io, "dp_phy");
64 if (rc) {
65 pr_err("unable to remap dp PHY resources\n");
66 goto err;
67 }
68
69 rc = msm_dss_ioremap_byname(pdev, &io->ln_tx0_io, "dp_ln_tx0");
70 if (rc) {
71 pr_err("unable to remap dp TX0 resources\n");
72 goto err;
73 }
74
75 rc = msm_dss_ioremap_byname(pdev, &io->ln_tx1_io, "dp_ln_tx1");
76 if (rc) {
77 pr_err("unable to remap dp TX1 resources\n");
78 goto err;
79 }
80
81 rc = msm_dss_ioremap_byname(pdev, &io->dp_pll_io, "dp_pll");
82 if (rc) {
83 pr_err("unable to remap DP PLL resources\n");
84 goto err;
85 }
86
87 if (msm_dss_ioremap_byname(pdev, &io->dp_cc_io, "dp_mmss_cc")) {
88 pr_err("unable to remap dp MMSS_CC resources\n");
89 goto err;
90 }
91
92 if (msm_dss_ioremap_byname(pdev, &io->qfprom_io, "qfprom_physical"))
93 pr_warn("unable to remap dp qfprom resources\n");
94
95 if (msm_dss_ioremap_byname(pdev, &io->hdcp_io, "hdcp_physical"))
96 pr_warn("unable to remap dp hdcp resources\n");
97
98 return 0;
99err:
100 dp_parser_unmap_io_resources(parser);
101 return rc;
102}
103
Padmanabhan Komanduru20a21db2017-07-10 16:58:59 +0530104static const char *dp_get_phy_aux_config_property(u32 cfg_type)
105{
106 switch (cfg_type) {
107 case PHY_AUX_CFG0:
108 return "qcom,aux-cfg0-settings";
109 case PHY_AUX_CFG1:
110 return "qcom,aux-cfg1-settings";
111 case PHY_AUX_CFG2:
112 return "qcom,aux-cfg2-settings";
113 case PHY_AUX_CFG3:
114 return "qcom,aux-cfg3-settings";
115 case PHY_AUX_CFG4:
116 return "qcom,aux-cfg4-settings";
117 case PHY_AUX_CFG5:
118 return "qcom,aux-cfg5-settings";
119 case PHY_AUX_CFG6:
120 return "qcom,aux-cfg6-settings";
121 case PHY_AUX_CFG7:
122 return "qcom,aux-cfg7-settings";
123 case PHY_AUX_CFG8:
124 return "qcom,aux-cfg8-settings";
125 case PHY_AUX_CFG9:
126 return "qcom,aux-cfg9-settings";
127 default:
128 return "unknown";
129 }
130}
131
132static void dp_parser_phy_aux_cfg_reset(struct dp_parser *parser)
133{
134 int i = 0;
135
136 for (i = 0; i < PHY_AUX_CFG_MAX; i++)
137 parser->aux_cfg[i] = (const struct dp_aux_cfg){ 0 };
138}
139
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700140static int dp_parser_aux(struct dp_parser *parser)
141{
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700142 struct device_node *of_node = parser->pdev->dev.of_node;
Padmanabhan Komanduru20a21db2017-07-10 16:58:59 +0530143 int len = 0, i = 0, j = 0, config_count = 0;
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700144 const char *data;
Padmanabhan Komanduru20a21db2017-07-10 16:58:59 +0530145 int const minimum_config_count = 1;
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700146
Padmanabhan Komanduru20a21db2017-07-10 16:58:59 +0530147 for (i = 0; i < PHY_AUX_CFG_MAX; i++) {
148 const char *property = dp_get_phy_aux_config_property(i);
149
150 data = of_get_property(of_node, property, &len);
151 if (!data) {
152 pr_err("Unable to read %s\n", property);
153 goto error;
154 }
155
156 config_count = len - 1;
157 if ((config_count < minimum_config_count) ||
158 (config_count > DP_AUX_CFG_MAX_VALUE_CNT)) {
159 pr_err("Invalid config count (%d) configs for %s\n",
160 config_count, property);
161 goto error;
162 }
163
164 parser->aux_cfg[i].offset = data[0];
165 parser->aux_cfg[i].cfg_cnt = config_count;
166 pr_debug("%s offset=0x%x, cfg_cnt=%d\n",
167 property,
168 parser->aux_cfg[i].offset,
169 parser->aux_cfg[i].cfg_cnt);
170 for (j = 1; j < len; j++) {
171 parser->aux_cfg[i].lut[j - 1] = data[j];
172 pr_debug("%s lut[%d]=0x%x\n",
173 property,
174 i,
175 parser->aux_cfg[i].lut[j - 1]);
176 }
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700177 }
Padmanabhan Komanduru20a21db2017-07-10 16:58:59 +0530178 return 0;
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700179
Padmanabhan Komanduru20a21db2017-07-10 16:58:59 +0530180error:
181 dp_parser_phy_aux_cfg_reset(parser);
182 return -EINVAL;
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700183}
184
185static int dp_parser_misc(struct dp_parser *parser)
186{
187 int rc = 0;
188 struct device_node *of_node = parser->pdev->dev.of_node;
189
190 rc = of_property_read_u32(of_node,
191 "qcom,max-pclk-frequency-khz", &parser->max_pclk_khz);
192 if (rc)
193 parser->max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ;
194
195 return 0;
196}
197
198static int dp_parser_pinctrl(struct dp_parser *parser)
199{
200 int rc = 0;
201 struct dp_pinctrl *pinctrl = &parser->pinctrl;
202
203 pinctrl->pin = devm_pinctrl_get(&parser->pdev->dev);
204
205 if (IS_ERR_OR_NULL(pinctrl->pin)) {
206 rc = PTR_ERR(pinctrl->pin);
207 pr_err("failed to get pinctrl, rc=%d\n", rc);
208 goto error;
209 }
210
211 pinctrl->state_active = pinctrl_lookup_state(pinctrl->pin,
212 "mdss_dp_active");
213 if (IS_ERR_OR_NULL(pinctrl->state_active)) {
214 rc = PTR_ERR(pinctrl->state_active);
215 pr_err("failed to get pinctrl active state, rc=%d\n", rc);
216 goto error;
217 }
218
219 pinctrl->state_suspend = pinctrl_lookup_state(pinctrl->pin,
220 "mdss_dp_sleep");
221 if (IS_ERR_OR_NULL(pinctrl->state_suspend)) {
222 rc = PTR_ERR(pinctrl->state_suspend);
223 pr_err("failed to get pinctrl suspend state, rc=%d\n", rc);
224 goto error;
225 }
226error:
227 return rc;
228}
229
230static int dp_parser_gpio(struct dp_parser *parser)
231{
232 int i = 0;
233 struct device *dev = &parser->pdev->dev;
234 struct device_node *of_node = dev->of_node;
235 struct dss_module_power *mp = &parser->mp[DP_CORE_PM];
236 static const char * const dp_gpios[] = {
237 "qcom,aux-en-gpio",
238 "qcom,aux-sel-gpio",
239 "qcom,usbplug-cc-gpio",
240 };
241
242 mp->gpio_config = devm_kzalloc(dev,
243 sizeof(struct dss_gpio) * ARRAY_SIZE(dp_gpios), GFP_KERNEL);
244 mp->num_gpio = ARRAY_SIZE(dp_gpios);
245
246 for (i = 0; i < ARRAY_SIZE(dp_gpios); i++) {
247 mp->gpio_config[i].gpio = of_get_named_gpio(of_node,
248 dp_gpios[i], 0);
249
250 if (!gpio_is_valid(mp->gpio_config[i].gpio)) {
251 pr_err("%s gpio not specified\n", dp_gpios[i]);
252 return -EINVAL;
253 }
254
255 strlcpy(mp->gpio_config[i].gpio_name, dp_gpios[i],
256 sizeof(mp->gpio_config[i].gpio_name));
257
258 mp->gpio_config[i].value = 0;
259 }
260
261 return 0;
262}
263
264static const char *dp_parser_supply_node_name(enum dp_pm_type module)
265{
266 switch (module) {
267 case DP_CORE_PM: return "qcom,core-supply-entries";
268 case DP_CTRL_PM: return "qcom,ctrl-supply-entries";
269 case DP_PHY_PM: return "qcom,phy-supply-entries";
270 default: return "???";
271 }
272}
273
274static int dp_parser_get_vreg(struct dp_parser *parser,
275 enum dp_pm_type module)
276{
277 int i = 0, rc = 0;
278 u32 tmp = 0;
279 const char *pm_supply_name = NULL;
280 struct device_node *supply_node = NULL;
281 struct device_node *of_node = parser->pdev->dev.of_node;
282 struct device_node *supply_root_node = NULL;
283 struct dss_module_power *mp = &parser->mp[module];
284
285 mp->num_vreg = 0;
286 pm_supply_name = dp_parser_supply_node_name(module);
287 supply_root_node = of_get_child_by_name(of_node, pm_supply_name);
288 if (!supply_root_node) {
289 pr_err("no supply entry present: %s\n", pm_supply_name);
290 goto novreg;
291 }
292
293 mp->num_vreg = of_get_available_child_count(supply_root_node);
294
295 if (mp->num_vreg == 0) {
296 pr_debug("no vreg\n");
297 goto novreg;
298 } else {
299 pr_debug("vreg found. count=%d\n", mp->num_vreg);
300 }
301
302 mp->vreg_config = devm_kzalloc(&parser->pdev->dev,
303 sizeof(struct dss_vreg) * mp->num_vreg, GFP_KERNEL);
304 if (!mp->vreg_config) {
305 rc = -ENOMEM;
306 goto error;
307 }
308
309 for_each_child_of_node(supply_root_node, supply_node) {
310 const char *st = NULL;
311 /* vreg-name */
312 rc = of_property_read_string(supply_node,
313 "qcom,supply-name", &st);
314 if (rc) {
315 pr_err("error reading name. rc=%d\n",
316 rc);
317 goto error;
318 }
319 snprintf(mp->vreg_config[i].vreg_name,
320 ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st);
321 /* vreg-min-voltage */
322 rc = of_property_read_u32(supply_node,
323 "qcom,supply-min-voltage", &tmp);
324 if (rc) {
325 pr_err("error reading min volt. rc=%d\n",
326 rc);
327 goto error;
328 }
329 mp->vreg_config[i].min_voltage = tmp;
330
331 /* vreg-max-voltage */
332 rc = of_property_read_u32(supply_node,
333 "qcom,supply-max-voltage", &tmp);
334 if (rc) {
335 pr_err("error reading max volt. rc=%d\n",
336 rc);
337 goto error;
338 }
339 mp->vreg_config[i].max_voltage = tmp;
340
341 /* enable-load */
342 rc = of_property_read_u32(supply_node,
343 "qcom,supply-enable-load", &tmp);
344 if (rc) {
345 pr_err("error reading enable load. rc=%d\n",
346 rc);
347 goto error;
348 }
349 mp->vreg_config[i].enable_load = tmp;
350
351 /* disable-load */
352 rc = of_property_read_u32(supply_node,
353 "qcom,supply-disable-load", &tmp);
354 if (rc) {
355 pr_err("error reading disable load. rc=%d\n",
356 rc);
357 goto error;
358 }
359 mp->vreg_config[i].disable_load = tmp;
360
361 pr_debug("%s min=%d, max=%d, enable=%d, disable=%d\n",
362 mp->vreg_config[i].vreg_name,
363 mp->vreg_config[i].min_voltage,
364 mp->vreg_config[i].max_voltage,
365 mp->vreg_config[i].enable_load,
366 mp->vreg_config[i].disable_load
367 );
368 ++i;
369 }
370
371 return rc;
372
373error:
374 if (mp->vreg_config) {
375 devm_kfree(&parser->pdev->dev, mp->vreg_config);
376 mp->vreg_config = NULL;
377 }
378novreg:
379 mp->num_vreg = 0;
380
381 return rc;
382}
383
384static void dp_parser_put_vreg_data(struct device *dev,
385 struct dss_module_power *mp)
386{
387 if (!mp) {
388 DEV_ERR("invalid input\n");
389 return;
390 }
391
392 if (mp->vreg_config) {
393 devm_kfree(dev, mp->vreg_config);
394 mp->vreg_config = NULL;
395 }
396 mp->num_vreg = 0;
397}
398
399static int dp_parser_regulator(struct dp_parser *parser)
400{
401 int i, rc = 0;
402 struct platform_device *pdev = parser->pdev;
403
404 /* Parse the regulator information */
405 for (i = DP_CORE_PM; i < DP_MAX_PM; i++) {
406 rc = dp_parser_get_vreg(parser, i);
407 if (rc) {
408 pr_err("get_dt_vreg_data failed for %s. rc=%d\n",
409 dp_parser_pm_name(i), rc);
410 i--;
411 for (; i >= DP_CORE_PM; i--)
412 dp_parser_put_vreg_data(&pdev->dev,
413 &parser->mp[i]);
414 break;
415 }
416 }
417
418 return rc;
419}
420
421static bool dp_parser_check_prefix(const char *clk_prefix, const char *clk_name)
422{
423 return !!strnstr(clk_name, clk_prefix, strlen(clk_name));
424}
425
426static void dp_parser_put_clk_data(struct device *dev,
427 struct dss_module_power *mp)
428{
429 if (!mp) {
430 DEV_ERR("%s: invalid input\n", __func__);
431 return;
432 }
433
434 if (mp->clk_config) {
435 devm_kfree(dev, mp->clk_config);
436 mp->clk_config = NULL;
437 }
438
439 mp->num_clk = 0;
440}
441
442static int dp_parser_init_clk_data(struct dp_parser *parser)
443{
444 int num_clk = 0, i = 0, rc = 0;
445 int core_clk_count = 0, ctrl_clk_count = 0;
446 const char *core_clk = "core";
447 const char *ctrl_clk = "ctrl";
448 const char *clk_name;
449 struct device *dev = &parser->pdev->dev;
450 struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
451 struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
452
453 num_clk = of_property_count_strings(dev->of_node, "clock-names");
454 if (num_clk <= 0) {
455 pr_err("no clocks are defined\n");
456 rc = -EINVAL;
457 goto exit;
458 }
459
460 for (i = 0; i < num_clk; i++) {
461 of_property_read_string_index(dev->of_node,
462 "clock-names", i, &clk_name);
463
464 if (dp_parser_check_prefix(core_clk, clk_name))
465 core_clk_count++;
466
467 if (dp_parser_check_prefix(ctrl_clk, clk_name))
468 ctrl_clk_count++;
469 }
470
471 /* Initialize the CORE power module */
472 if (core_clk_count <= 0) {
473 pr_err("no core clocks are defined\n");
474 rc = -EINVAL;
475 goto exit;
476 }
477
478 core_power->num_clk = core_clk_count;
479 core_power->clk_config = devm_kzalloc(dev,
480 sizeof(struct dss_clk) * core_power->num_clk,
481 GFP_KERNEL);
482 if (!core_power->clk_config) {
483 rc = -EINVAL;
484 goto exit;
485 }
486
487 /* Initialize the CTRL power module */
488 if (ctrl_clk_count <= 0) {
489 pr_err("no ctrl clocks are defined\n");
490 rc = -EINVAL;
491 goto ctrl_clock_error;
492 }
493
494 ctrl_power->num_clk = ctrl_clk_count;
495 ctrl_power->clk_config = devm_kzalloc(dev,
496 sizeof(struct dss_clk) * ctrl_power->num_clk,
497 GFP_KERNEL);
498 if (!ctrl_power->clk_config) {
499 ctrl_power->num_clk = 0;
500 rc = -EINVAL;
501 goto ctrl_clock_error;
502 }
503
504 return rc;
505
506ctrl_clock_error:
507 dp_parser_put_clk_data(dev, core_power);
508exit:
509 return rc;
510}
511
512static int dp_parser_clock(struct dp_parser *parser)
513{
514 int rc = 0, i = 0;
515 int num_clk = 0;
516 int core_clk_index = 0, ctrl_clk_index = 0;
517 int core_clk_count = 0, ctrl_clk_count = 0;
518 const char *clk_name;
519 const char *core_clk = "core";
520 const char *ctrl_clk = "ctrl";
521 struct device *dev = &parser->pdev->dev;
522 struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
523 struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
524
525 core_power = &parser->mp[DP_CORE_PM];
526 ctrl_power = &parser->mp[DP_CTRL_PM];
527
528 rc = dp_parser_init_clk_data(parser);
529 if (rc) {
530 pr_err("failed to initialize power data\n");
531 rc = -EINVAL;
532 goto exit;
533 }
534
535 core_clk_count = core_power->num_clk;
536 ctrl_clk_count = ctrl_power->num_clk;
537
538 num_clk = core_clk_count + ctrl_clk_count;
539
540 for (i = 0; i < num_clk; i++) {
541 of_property_read_string_index(dev->of_node, "clock-names",
542 i, &clk_name);
543
544 if (dp_parser_check_prefix(core_clk, clk_name) &&
545 core_clk_index < core_clk_count) {
546 struct dss_clk *clk =
547 &core_power->clk_config[core_clk_index];
548 strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
549 clk->type = DSS_CLK_AHB;
550 core_clk_index++;
551 } else if (dp_parser_check_prefix(ctrl_clk, clk_name) &&
552 ctrl_clk_index < ctrl_clk_count) {
553 struct dss_clk *clk =
554 &ctrl_power->clk_config[ctrl_clk_index];
555 strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
556 ctrl_clk_index++;
557
558 if (!strcmp(clk_name, "ctrl_link_clk") ||
Tatenda Chipeperekwac44d51b2017-06-16 17:12:00 -0700559 !strcmp(clk_name, "ctrl_pixel_clk"))
Ajay Singh Parmar769215f2017-03-19 22:35:13 -0700560 clk->type = DSS_CLK_PCLK;
561 else
562 clk->type = DSS_CLK_AHB;
563 }
564 }
565
566 pr_debug("clock parsing successful\n");
567
568exit:
569 return rc;
570}
571
572static int dp_parser_parse(struct dp_parser *parser)
573{
574 int rc = 0;
575
576 if (!parser) {
577 pr_err("invalid input\n");
578 rc = -EINVAL;
579 goto err;
580 }
581
582 rc = dp_parser_ctrl_res(parser);
583 if (rc)
584 goto err;
585
586 rc = dp_parser_aux(parser);
587 if (rc)
588 goto err;
589
590 rc = dp_parser_misc(parser);
591 if (rc)
592 goto err;
593
594 rc = dp_parser_clock(parser);
595 if (rc)
596 goto err;
597
598 rc = dp_parser_regulator(parser);
599 if (rc)
600 goto err;
601
602 rc = dp_parser_gpio(parser);
603 if (rc)
604 goto err;
605
606 rc = dp_parser_pinctrl(parser);
607err:
608 return rc;
609}
610
611struct dp_parser *dp_parser_get(struct platform_device *pdev)
612{
613 struct dp_parser *parser;
614
615 parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
616 if (!parser)
617 return ERR_PTR(-ENOMEM);
618
619 parser->parse = dp_parser_parse;
620 parser->pdev = pdev;
621
622 return parser;
623}
624
625void dp_parser_put(struct dp_parser *parser)
626{
627 int i = 0;
628 struct dss_module_power *power = NULL;
629
630 if (!parser) {
631 pr_err("invalid parser module\n");
632 return;
633 }
634
635 power = parser->mp;
636
637 for (i = 0; i < DP_MAX_PM; i++) {
638 struct dss_module_power *mp = &power[i];
639
640 devm_kfree(&parser->pdev->dev, mp->clk_config);
641 devm_kfree(&parser->pdev->dev, mp->vreg_config);
642 devm_kfree(&parser->pdev->dev, mp->gpio_config);
643 }
644
645 devm_kfree(&parser->pdev->dev, parser);
646}