blob: d53ef1140f997e5f95e5b7dca7006ec8450ff69e [file] [log] [blame]
Ajay Singh Parmar67f31322016-06-22 17:37:56 -07001/*
2 * Copyright (c) 2016, 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#define pr_fmt(fmt) "msm-dsi-phy:[%s] " fmt, __func__
15
16#include <linux/of_device.h>
17#include <linux/err.h>
18#include <linux/regulator/consumer.h>
19#include <linux/clk.h>
20#include <linux/msm-bus.h>
21#include <linux/list.h>
22
23#include "msm_drv.h"
24#include "msm_kms.h"
25#include "msm_gpu.h"
26#include "dsi_phy.h"
27#include "dsi_phy_hw.h"
28#include "dsi_clk_pwr.h"
29#include "dsi_catalog.h"
30
31#define DSI_PHY_DEFAULT_LABEL "MDSS PHY CTRL"
32
33struct dsi_phy_list_item {
34 struct msm_dsi_phy *phy;
35 struct list_head list;
36};
37
38static LIST_HEAD(dsi_phy_list);
39static DEFINE_MUTEX(dsi_phy_list_lock);
40
41static const struct dsi_ver_spec_info dsi_phy_v1_0 = {
42 .version = DSI_PHY_VERSION_1_0,
43 .lane_cfg_count = 4,
44 .strength_cfg_count = 2,
45 .regulator_cfg_count = 1,
46 .timing_cfg_count = 8,
47};
48static const struct dsi_ver_spec_info dsi_phy_v2_0 = {
49 .version = DSI_PHY_VERSION_2_0,
50 .lane_cfg_count = 4,
51 .strength_cfg_count = 2,
52 .regulator_cfg_count = 1,
53 .timing_cfg_count = 8,
54};
55static const struct dsi_ver_spec_info dsi_phy_v3_0 = {
56 .version = DSI_PHY_VERSION_3_0,
57 .lane_cfg_count = 4,
58 .strength_cfg_count = 2,
59 .regulator_cfg_count = 1,
60 .timing_cfg_count = 8,
61};
62static const struct dsi_ver_spec_info dsi_phy_v4_0 = {
63 .version = DSI_PHY_VERSION_4_0,
64 .lane_cfg_count = 4,
65 .strength_cfg_count = 2,
66 .regulator_cfg_count = 1,
67 .timing_cfg_count = 8,
68};
69
70static const struct of_device_id msm_dsi_phy_of_match[] = {
71 { .compatible = "qcom,dsi-phy-v1.0",
72 .data = &dsi_phy_v1_0,},
73 { .compatible = "qcom,dsi-phy-v2.0",
74 .data = &dsi_phy_v2_0,},
75 { .compatible = "qcom,dsi-phy-v3.0",
76 .data = &dsi_phy_v3_0,},
77 { .compatible = "qcom,dsi-phy-v4.0",
78 .data = &dsi_phy_v4_0,},
79 {}
80};
81
82static int dsi_phy_regmap_init(struct platform_device *pdev,
83 struct msm_dsi_phy *phy)
84{
85 int rc = 0;
86 void __iomem *ptr;
87
88 ptr = msm_ioremap(pdev, "dsi_phy", phy->name);
89 if (IS_ERR(ptr)) {
90 rc = PTR_ERR(ptr);
91 return rc;
92 }
93
94 phy->hw.base = ptr;
95
96 pr_debug("[%s] map dsi_phy registers to %p\n", phy->name, phy->hw.base);
97
98 return rc;
99}
100
101static int dsi_phy_regmap_deinit(struct msm_dsi_phy *phy)
102{
103 pr_debug("[%s] unmap registers\n", phy->name);
104 return 0;
105}
106
107static int dsi_phy_clocks_deinit(struct msm_dsi_phy *phy)
108{
109 int rc = 0;
110 struct dsi_core_clk_info *core = &phy->clks.core_clks;
111
112 if (core->mdp_core_clk)
113 devm_clk_put(&phy->pdev->dev, core->mdp_core_clk);
114 if (core->iface_clk)
115 devm_clk_put(&phy->pdev->dev, core->iface_clk);
116 if (core->core_mmss_clk)
117 devm_clk_put(&phy->pdev->dev, core->core_mmss_clk);
118 if (core->bus_clk)
119 devm_clk_put(&phy->pdev->dev, core->bus_clk);
120
121 memset(core, 0x0, sizeof(*core));
122
123 return rc;
124}
125
126static int dsi_phy_clocks_init(struct platform_device *pdev,
127 struct msm_dsi_phy *phy)
128{
129 int rc = 0;
130 struct dsi_core_clk_info *core = &phy->clks.core_clks;
131
132 core->mdp_core_clk = devm_clk_get(&pdev->dev, "mdp_core_clk");
133 if (IS_ERR(core->mdp_core_clk)) {
134 rc = PTR_ERR(core->mdp_core_clk);
135 pr_err("failed to get mdp_core_clk, rc=%d\n", rc);
136 goto fail;
137 }
138
139 core->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
140 if (IS_ERR(core->iface_clk)) {
141 rc = PTR_ERR(core->iface_clk);
142 pr_err("failed to get iface_clk, rc=%d\n", rc);
143 goto fail;
144 }
145
146 core->core_mmss_clk = devm_clk_get(&pdev->dev, "core_mmss_clk");
147 if (IS_ERR(core->core_mmss_clk)) {
148 rc = PTR_ERR(core->core_mmss_clk);
149 pr_err("failed to get core_mmss_clk, rc=%d\n", rc);
150 goto fail;
151 }
152
153 core->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
154 if (IS_ERR(core->bus_clk)) {
155 rc = PTR_ERR(core->bus_clk);
156 pr_err("failed to get bus_clk, rc=%d\n", rc);
157 goto fail;
158 }
159
160 return rc;
161fail:
162 dsi_phy_clocks_deinit(phy);
163 return rc;
164}
165
166static int dsi_phy_supplies_init(struct platform_device *pdev,
167 struct msm_dsi_phy *phy)
168{
169 int rc = 0;
170 int i = 0;
171 struct dsi_regulator_info *regs;
172 struct regulator *vreg = NULL;
173
174 regs = &phy->pwr_info.digital;
175 regs->vregs = devm_kzalloc(&pdev->dev, sizeof(struct dsi_vreg),
176 GFP_KERNEL);
177 if (!regs->vregs)
178 goto error;
179
180 regs->count = 1;
181 snprintf(regs->vregs->vreg_name,
182 ARRAY_SIZE(regs->vregs[i].vreg_name),
183 "%s", "gdsc");
184
185 rc = dsi_clk_pwr_get_dt_vreg_data(&pdev->dev,
186 &phy->pwr_info.phy_pwr,
187 "qcom,phy-supply-entries");
188 if (rc) {
189 pr_err("failed to get host power supplies, rc = %d\n", rc);
190 goto error_digital;
191 }
192
193 regs = &phy->pwr_info.digital;
194 for (i = 0; i < regs->count; i++) {
195 vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name);
196 rc = PTR_RET(vreg);
197 if (rc) {
198 pr_err("failed to get %s regulator\n",
199 regs->vregs[i].vreg_name);
200 goto error_host_pwr;
201 }
202 regs->vregs[i].vreg = vreg;
203 }
204
205 regs = &phy->pwr_info.phy_pwr;
206 for (i = 0; i < regs->count; i++) {
207 vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name);
208 rc = PTR_RET(vreg);
209 if (rc) {
210 pr_err("failed to get %s regulator\n",
211 regs->vregs[i].vreg_name);
212 for (--i; i >= 0; i--)
213 devm_regulator_put(regs->vregs[i].vreg);
214 goto error_digital_put;
215 }
216 regs->vregs[i].vreg = vreg;
217 }
218
219 return rc;
220
221error_digital_put:
222 regs = &phy->pwr_info.digital;
223 for (i = 0; i < regs->count; i++)
224 devm_regulator_put(regs->vregs[i].vreg);
225error_host_pwr:
226 devm_kfree(&pdev->dev, phy->pwr_info.phy_pwr.vregs);
227 phy->pwr_info.phy_pwr.vregs = NULL;
228 phy->pwr_info.phy_pwr.count = 0;
229error_digital:
230 devm_kfree(&pdev->dev, phy->pwr_info.digital.vregs);
231 phy->pwr_info.digital.vregs = NULL;
232 phy->pwr_info.digital.count = 0;
233error:
234 return rc;
235}
236
237static int dsi_phy_supplies_deinit(struct msm_dsi_phy *phy)
238{
239 int i = 0;
240 int rc = 0;
241 struct dsi_regulator_info *regs;
242
243 regs = &phy->pwr_info.digital;
244 for (i = 0; i < regs->count; i++) {
245 if (!regs->vregs[i].vreg)
246 pr_err("vreg is NULL, should not reach here\n");
247 else
248 devm_regulator_put(regs->vregs[i].vreg);
249 }
250
251 regs = &phy->pwr_info.phy_pwr;
252 for (i = 0; i < regs->count; i++) {
253 if (!regs->vregs[i].vreg)
254 pr_err("vreg is NULL, should not reach here\n");
255 else
256 devm_regulator_put(regs->vregs[i].vreg);
257 }
258
259 if (phy->pwr_info.phy_pwr.vregs) {
260 devm_kfree(&phy->pdev->dev, phy->pwr_info.phy_pwr.vregs);
261 phy->pwr_info.phy_pwr.vregs = NULL;
262 phy->pwr_info.phy_pwr.count = 0;
263 }
264 if (phy->pwr_info.digital.vregs) {
265 devm_kfree(&phy->pdev->dev, phy->pwr_info.digital.vregs);
266 phy->pwr_info.digital.vregs = NULL;
267 phy->pwr_info.digital.count = 0;
268 }
269
270 return rc;
271}
272
273static int dsi_phy_parse_dt_per_lane_cfgs(struct platform_device *pdev,
274 struct dsi_phy_per_lane_cfgs *cfg,
275 char *property)
276{
277 int rc = 0, i = 0, j = 0;
278 const u8 *data;
279 u32 len = 0;
280
281 data = of_get_property(pdev->dev.of_node, property, &len);
282 if (!data) {
283 pr_err("Unable to read Phy %s settings\n", property);
284 return -EINVAL;
285 }
286
287 if (len != DSI_LANE_MAX * cfg->count_per_lane) {
288 pr_err("incorrect phy %s settings, exp=%d, act=%d\n",
289 property, (DSI_LANE_MAX * cfg->count_per_lane), len);
290 return -EINVAL;
291 }
292
293 for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
294 for (j = 0; j < cfg->count_per_lane; j++) {
295 cfg->lane[i][j] = *data;
296 data++;
297 }
298 }
299
300 return rc;
301}
302
303static int dsi_phy_settings_init(struct platform_device *pdev,
304 struct msm_dsi_phy *phy)
305{
306 int rc = 0;
307 struct dsi_phy_per_lane_cfgs *lane = &phy->cfg.lanecfg;
308 struct dsi_phy_per_lane_cfgs *strength = &phy->cfg.strength;
309 struct dsi_phy_per_lane_cfgs *timing = &phy->cfg.timing;
310 struct dsi_phy_per_lane_cfgs *regs = &phy->cfg.regulators;
311
312 lane->count_per_lane = phy->ver_info->lane_cfg_count;
313 rc = dsi_phy_parse_dt_per_lane_cfgs(pdev, lane,
314 "qcom,platform-lane-config");
315 if (rc) {
316 pr_err("failed to parse lane cfgs, rc=%d\n", rc);
317 goto err;
318 }
319
320 strength->count_per_lane = phy->ver_info->strength_cfg_count;
321 rc = dsi_phy_parse_dt_per_lane_cfgs(pdev, strength,
322 "qcom,platform-strength-ctrl");
323 if (rc) {
324 pr_err("failed to parse lane cfgs, rc=%d\n", rc);
325 goto err;
326 }
327
328 regs->count_per_lane = phy->ver_info->regulator_cfg_count;
329 rc = dsi_phy_parse_dt_per_lane_cfgs(pdev, regs,
330 "qcom,platform-regulator-settings");
331 if (rc) {
332 pr_err("failed to parse lane cfgs, rc=%d\n", rc);
333 goto err;
334 }
335
336 /* Actual timing values are dependent on panel */
337 timing->count_per_lane = phy->ver_info->timing_cfg_count;
338
339err:
340 lane->count_per_lane = 0;
341 strength->count_per_lane = 0;
342 regs->count_per_lane = 0;
343 timing->count_per_lane = 0;
344 return rc;
345}
346
347static int dsi_phy_settings_deinit(struct msm_dsi_phy *phy)
348{
349 memset(&phy->cfg.lanecfg, 0x0, sizeof(phy->cfg.lanecfg));
350 memset(&phy->cfg.strength, 0x0, sizeof(phy->cfg.strength));
351 memset(&phy->cfg.timing, 0x0, sizeof(phy->cfg.timing));
352 memset(&phy->cfg.regulators, 0x0, sizeof(phy->cfg.regulators));
353 return 0;
354}
355
356static int dsi_phy_driver_probe(struct platform_device *pdev)
357{
358 struct msm_dsi_phy *dsi_phy;
359 struct dsi_phy_list_item *item;
360 const struct of_device_id *id;
361 const struct dsi_ver_spec_info *ver_info;
362 int rc = 0;
363 u32 index = 0;
364
365 if (!pdev || !pdev->dev.of_node) {
366 pr_err("pdev not found\n");
367 return -ENODEV;
368 }
369
370 id = of_match_node(msm_dsi_phy_of_match, pdev->dev.of_node);
371 if (!id)
372 return -ENODEV;
373
374 ver_info = id->data;
375
376 item = devm_kzalloc(&pdev->dev, sizeof(*item), GFP_KERNEL);
377 if (!item)
378 return -ENOMEM;
379
380
381 dsi_phy = devm_kzalloc(&pdev->dev, sizeof(*dsi_phy), GFP_KERNEL);
382 if (!dsi_phy) {
383 devm_kfree(&pdev->dev, item);
384 return -ENOMEM;
385 }
386
387 rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &index);
388 if (rc) {
389 pr_debug("cell index not set, default to 0\n");
390 index = 0;
391 }
392
393 dsi_phy->index = index;
394
395 dsi_phy->name = of_get_property(pdev->dev.of_node, "label", NULL);
396 if (!dsi_phy->name)
397 dsi_phy->name = DSI_PHY_DEFAULT_LABEL;
398
399 pr_debug("Probing %s device\n", dsi_phy->name);
400
401 rc = dsi_phy_regmap_init(pdev, dsi_phy);
402 if (rc) {
403 pr_err("Failed to parse register information, rc=%d\n", rc);
404 goto fail;
405 }
406
407 rc = dsi_phy_clocks_init(pdev, dsi_phy);
408 if (rc) {
409 pr_err("failed to parse clock information, rc = %d\n", rc);
410 goto fail_regmap;
411 }
412
413 rc = dsi_phy_supplies_init(pdev, dsi_phy);
414 if (rc) {
415 pr_err("failed to parse voltage supplies, rc = %d\n", rc);
416 goto fail_clks;
417 }
418
419 rc = dsi_catalog_phy_setup(&dsi_phy->hw, ver_info->version,
420 dsi_phy->index);
421 if (rc) {
422 pr_err("Catalog does not support version (%d)\n",
423 ver_info->version);
424 goto fail_supplies;
425 }
426
427 dsi_phy->ver_info = ver_info;
428 rc = dsi_phy_settings_init(pdev, dsi_phy);
429 if (rc) {
430 pr_err("Failed to parse phy setting, rc=%d\n", rc);
431 goto fail_supplies;
432 }
433
434 item->phy = dsi_phy;
435
436 mutex_lock(&dsi_phy_list_lock);
437 list_add(&item->list, &dsi_phy_list);
438 mutex_unlock(&dsi_phy_list_lock);
439
440 mutex_init(&dsi_phy->phy_lock);
441 /** TODO: initialize debugfs */
442 dsi_phy->pdev = pdev;
443 platform_set_drvdata(pdev, dsi_phy);
444 pr_debug("Probe successful for %s\n", dsi_phy->name);
445 return 0;
446
447fail_supplies:
448 (void)dsi_phy_supplies_deinit(dsi_phy);
449fail_clks:
450 (void)dsi_phy_clocks_deinit(dsi_phy);
451fail_regmap:
452 (void)dsi_phy_regmap_deinit(dsi_phy);
453fail:
454 devm_kfree(&pdev->dev, dsi_phy);
455 devm_kfree(&pdev->dev, item);
456 return rc;
457}
458
459static int dsi_phy_driver_remove(struct platform_device *pdev)
460{
461 int rc = 0;
462 struct msm_dsi_phy *phy = platform_get_drvdata(pdev);
463 struct list_head *pos, *tmp;
464
465 if (!pdev || !phy) {
466 pr_err("Invalid device\n");
467 return -EINVAL;
468 }
469
470 mutex_lock(&dsi_phy_list_lock);
471 list_for_each_safe(pos, tmp, &dsi_phy_list) {
472 struct dsi_phy_list_item *n;
473
474 n = list_entry(pos, struct dsi_phy_list_item, list);
475 if (n->phy == phy) {
476 list_del(&n->list);
477 devm_kfree(&pdev->dev, n);
478 break;
479 }
480 }
481 mutex_unlock(&dsi_phy_list_lock);
482
483 mutex_lock(&phy->phy_lock);
484 rc = dsi_phy_settings_deinit(phy);
485 if (rc)
486 pr_err("failed to deinitialize phy settings, rc=%d\n", rc);
487
488 rc = dsi_phy_supplies_deinit(phy);
489 if (rc)
490 pr_err("failed to deinitialize voltage supplies, rc=%d\n", rc);
491
492 rc = dsi_phy_clocks_deinit(phy);
493 if (rc)
494 pr_err("failed to deinitialize clocks, rc=%d\n", rc);
495
496 rc = dsi_phy_regmap_deinit(phy);
497 if (rc)
498 pr_err("failed to deinitialize regmap, rc=%d\n", rc);
499 mutex_unlock(&phy->phy_lock);
500
501 mutex_destroy(&phy->phy_lock);
502 devm_kfree(&pdev->dev, phy);
503
504 platform_set_drvdata(pdev, NULL);
505
506 return 0;
507}
508
509static struct platform_driver dsi_phy_platform_driver = {
510 .probe = dsi_phy_driver_probe,
511 .remove = dsi_phy_driver_remove,
512 .driver = {
513 .name = "msm_dsi_phy",
514 .of_match_table = msm_dsi_phy_of_match,
515 },
516};
517
518static void dsi_phy_enable_hw(struct msm_dsi_phy *phy)
519{
520 if (phy->hw.ops.regulator_enable)
521 phy->hw.ops.regulator_enable(&phy->hw, &phy->cfg.regulators);
522
523 if (phy->hw.ops.enable)
524 phy->hw.ops.enable(&phy->hw, &phy->cfg);
525}
526
527static void dsi_phy_disable_hw(struct msm_dsi_phy *phy)
528{
529 if (phy->hw.ops.disable)
530 phy->hw.ops.disable(&phy->hw);
531
532 if (phy->hw.ops.regulator_disable)
533 phy->hw.ops.regulator_disable(&phy->hw);
534}
535
536/**
537 * dsi_phy_get() - get a dsi phy handle from device node
538 * @of_node: device node for dsi phy controller
539 *
540 * Gets the DSI PHY handle for the corresponding of_node. The ref count is
541 * incremented to one all subsequents get will fail until the original client
542 * calls a put.
543 *
544 * Return: DSI PHY handle or an error code.
545 */
546struct msm_dsi_phy *dsi_phy_get(struct device_node *of_node)
547{
548 struct list_head *pos, *tmp;
549 struct msm_dsi_phy *phy = NULL;
550
551 mutex_lock(&dsi_phy_list_lock);
552 list_for_each_safe(pos, tmp, &dsi_phy_list) {
553 struct dsi_phy_list_item *n;
554
555 n = list_entry(pos, struct dsi_phy_list_item, list);
556 if (n->phy->pdev->dev.of_node == of_node) {
557 phy = n->phy;
558 break;
559 }
560 }
561 mutex_unlock(&dsi_phy_list_lock);
562
563 if (!phy) {
564 pr_err("Device with of node not found\n");
565 phy = ERR_PTR(-EPROBE_DEFER);
566 return phy;
567 }
568
569 mutex_lock(&phy->phy_lock);
570 if (phy->refcount > 0) {
571 pr_err("[PHY_%d] Device under use\n", phy->index);
572 phy = ERR_PTR(-EINVAL);
573 } else {
574 phy->refcount++;
575 }
576 mutex_unlock(&phy->phy_lock);
577 return phy;
578}
579
580/**
581 * dsi_phy_put() - release dsi phy handle
582 * @dsi_phy: DSI PHY handle.
583 *
584 * Release the DSI PHY hardware. Driver will clean up all resources and puts
585 * back the DSI PHY into reset state.
586 */
587void dsi_phy_put(struct msm_dsi_phy *dsi_phy)
588{
589 mutex_lock(&dsi_phy->phy_lock);
590
591 if (dsi_phy->refcount == 0)
592 pr_err("Unbalanced dsi_phy_put call\n");
593 else
594 dsi_phy->refcount--;
595
596 mutex_unlock(&dsi_phy->phy_lock);
597}
598
599/**
600 * dsi_phy_drv_init() - initialize dsi phy driver
601 * @dsi_phy: DSI PHY handle.
602 *
603 * Initializes DSI PHY driver. Should be called after dsi_phy_get().
604 *
605 * Return: error code.
606 */
607int dsi_phy_drv_init(struct msm_dsi_phy *dsi_phy)
608{
609 return 0;
610}
611
612/**
613 * dsi_phy_drv_deinit() - de-initialize dsi phy driver
614 * @dsi_phy: DSI PHY handle.
615 *
616 * Release all resources acquired by dsi_phy_drv_init().
617 *
618 * Return: error code.
619 */
620int dsi_phy_drv_deinit(struct msm_dsi_phy *dsi_phy)
621{
622 return 0;
623}
624
625/**
626 * dsi_phy_validate_mode() - validate a display mode
627 * @dsi_phy: DSI PHY handle.
628 * @mode: Mode information.
629 *
630 * Validation will fail if the mode cannot be supported by the PHY driver or
631 * hardware.
632 *
633 * Return: error code.
634 */
635int dsi_phy_validate_mode(struct msm_dsi_phy *dsi_phy,
636 struct dsi_mode_info *mode)
637{
638 int rc = 0;
639
640 if (!dsi_phy || !mode) {
641 pr_err("Invalid params\n");
642 return -EINVAL;
643 }
644
645 mutex_lock(&dsi_phy->phy_lock);
646
647 pr_debug("[PHY_%d] Skipping validation\n", dsi_phy->index);
648
649 mutex_unlock(&dsi_phy->phy_lock);
650 return rc;
651}
652
653/**
654 * dsi_phy_set_power_state() - enable/disable dsi phy power supplies
655 * @dsi_phy: DSI PHY handle.
656 * @enable: Boolean flag to enable/disable.
657 *
658 * Return: error code.
659 */
660int dsi_phy_set_power_state(struct msm_dsi_phy *dsi_phy, bool enable)
661{
662 int rc = 0;
663
664 if (!dsi_phy) {
665 pr_err("Invalid params\n");
666 return -EINVAL;
667 }
668
669 mutex_lock(&dsi_phy->phy_lock);
670
671 if (enable == dsi_phy->power_state) {
672 pr_err("[PHY_%d] No state change\n", dsi_phy->index);
673 goto error;
674 }
675
676 if (enable) {
677 rc = dsi_pwr_enable_regulator(&dsi_phy->pwr_info.digital, true);
678 if (rc) {
679 pr_err("failed to enable digital regulator\n");
680 goto error;
681 }
682 rc = dsi_pwr_enable_regulator(&dsi_phy->pwr_info.phy_pwr, true);
683 if (rc) {
684 pr_err("failed to enable phy power\n");
685 (void)dsi_pwr_enable_regulator(
686 &dsi_phy->pwr_info.digital,
687 false
688 );
689 goto error;
690 }
691 } else {
692 rc = dsi_pwr_enable_regulator(&dsi_phy->pwr_info.phy_pwr,
693 false);
694 if (rc) {
695 pr_err("failed to enable digital regulator\n");
696 goto error;
697 }
698 rc = dsi_pwr_enable_regulator(&dsi_phy->pwr_info.digital,
699 false);
700 if (rc) {
701 pr_err("failed to enable phy power\n");
702 goto error;
703 }
704 }
705
706 dsi_phy->power_state = enable;
707error:
708 mutex_unlock(&dsi_phy->phy_lock);
709 return rc;
710}
711
712/**
713 * dsi_phy_enable() - enable DSI PHY hardware
714 * @dsi_phy: DSI PHY handle.
715 * @config: DSI host configuration.
716 * @pll_source: Source PLL for PHY clock.
717 * @skip_validation: Validation will not be performed on parameters.
718 *
719 * Validates and enables DSI PHY.
720 *
721 * Return: error code.
722 */
723int dsi_phy_enable(struct msm_dsi_phy *phy,
724 struct dsi_host_config *config,
725 enum dsi_phy_pll_source pll_source,
726 bool skip_validation)
727{
728 int rc = 0;
729
730 if (!phy || !config) {
731 pr_err("Invalid params\n");
732 return -EINVAL;
733 }
734
735 mutex_lock(&phy->phy_lock);
736
737 if (!skip_validation)
738 pr_debug("[PHY_%d] TODO: perform validation\n", phy->index);
739
740 rc = dsi_clk_enable_core_clks(&phy->clks.core_clks, true);
741 if (rc) {
742 pr_err("failed to enable core clocks, rc=%d\n", rc);
743 goto error;
744 }
745
746 memcpy(&phy->mode, &config->video_timing, sizeof(phy->mode));
747 phy->data_lanes = config->common_config.data_lanes;
748 phy->dst_format = config->common_config.dst_format;
749 phy->lane_map = config->lane_map;
750 phy->cfg.pll_source = pll_source;
751
752 rc = phy->hw.ops.calculate_timing_params(&phy->hw,
753 &phy->mode,
754 &config->common_config,
755 &phy->cfg.timing);
756 if (rc) {
757 pr_err("[%s] failed to set timing, rc=%d\n", phy->name, rc);
758 goto error_disable_clks;
759 }
760
761 dsi_phy_enable_hw(phy);
762
763error_disable_clks:
764 rc = dsi_clk_enable_core_clks(&phy->clks.core_clks, false);
765 if (rc) {
766 pr_err("failed to disable clocks, skip phy disable\n");
767 goto error;
768 }
769error:
770 mutex_unlock(&phy->phy_lock);
771 return rc;
772}
773
774/**
775 * dsi_phy_disable() - disable DSI PHY hardware.
776 * @phy: DSI PHY handle.
777 *
778 * Return: error code.
779 */
780int dsi_phy_disable(struct msm_dsi_phy *phy)
781{
782 int rc = 0;
783
784 if (!phy) {
785 pr_err("Invalid params\n");
786 return -EINVAL;
787 }
788
789 mutex_lock(&phy->phy_lock);
790
791 rc = dsi_clk_enable_core_clks(&phy->clks.core_clks, true);
792 if (rc) {
793 pr_err("failed to enable core clocks, rc=%d\n", rc);
794 goto error;
795 }
796
797 dsi_phy_disable_hw(phy);
798
799 rc = dsi_clk_enable_core_clks(&phy->clks.core_clks, false);
800 if (rc) {
801 pr_err("failed to disable core clocks, rc=%d\n", rc);
802 goto error;
803 }
804
805error:
806 mutex_unlock(&phy->phy_lock);
807 return rc;
808}
809
810/**
811 * dsi_phy_set_timing_params() - timing parameters for the panel
812 * @phy: DSI PHY handle
813 * @timing: array holding timing params.
814 * @size: size of the array.
815 *
816 * When PHY timing calculator is not implemented, this array will be used to
817 * pass PHY timing information.
818 *
819 * Return: error code.
820 */
821int dsi_phy_set_timing_params(struct msm_dsi_phy *phy,
822 u8 *timing, u32 size)
823{
824 int rc = 0;
825 int i, j;
826 struct dsi_phy_per_lane_cfgs *timing_cfg;
827
828 if (!phy || !timing || !size) {
829 pr_err("Invalid params\n");
830 return -EINVAL;
831 }
832
833 mutex_lock(&phy->phy_lock);
834
835 if (size != (DSI_LANE_MAX * phy->cfg.timing.count_per_lane)) {
836 pr_err("Unexpected timing array size %d\n", size);
837 rc = -EINVAL;
838 } else {
839 timing_cfg = &phy->cfg.timing;
840 for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
841 for (j = 0; j < timing_cfg->count_per_lane; j++) {
842 timing_cfg->lane[i][j] = *timing;
843 timing++;
844 }
845 }
846 }
847 mutex_unlock(&phy->phy_lock);
848 return rc;
849}
850
851void __init dsi_phy_drv_register(void)
852{
853 platform_driver_register(&dsi_phy_platform_driver);
854}
855
856void __exit dsi_phy_drv_unregister(void)
857{
858 platform_driver_unregister(&dsi_phy_platform_driver);
859}