blob: 834b53585ccb63c0fa78ed3c175c8c621830b8e1 [file] [log] [blame]
Naitik Bharadiyaa0508742019-11-19 19:23:47 +05301/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
Pratap Nirujogi6e759912018-01-17 17:51:17 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "CAM-SOC %s:%d " fmt, __func__, __LINE__
14#define NO_SET_RATE -1
15#define INIT_RATE -2
16
17#ifdef CONFIG_CAM_SOC_API_DBG
18#define CDBG(fmt, args...) pr_err(fmt, ##args)
19#else
20#define CDBG(fmt, args...) pr_debug(fmt, ##args)
21#endif
22
23#include <linux/delay.h>
24#include <linux/module.h>
25#include <linux/of_platform.h>
26#include <linux/msm-bus.h>
27#include <linux/clk/msm-clk.h>
28#include "cam_soc_api.h"
29
30struct msm_cam_bus_pscale_data {
31 struct msm_bus_scale_pdata *pdata;
32 uint32_t bus_client;
33 uint32_t num_usecases;
34 uint32_t num_paths;
35 unsigned int vector_index;
36 bool dyn_vote;
37 struct mutex lock;
38};
39
40static struct msm_cam_bus_pscale_data g_cv[CAM_BUS_CLIENT_MAX];
41
42
43/* Get all clocks from DT */
44static int msm_camera_get_clk_info_internal(struct device *dev,
45 struct msm_cam_clk_info **clk_info,
46 struct clk ***clk_ptr,
47 size_t *num_clk)
48{
49 int rc = 0;
50 size_t cnt, tmp;
51 uint32_t *rates, i = 0;
52 const char *clk_ctl = NULL;
53 bool clock_cntl_support = false;
54 struct device_node *of_node;
55
56 of_node = dev->of_node;
57
58 cnt = of_property_count_strings(of_node, "clock-names");
59 if (cnt <= 0) {
60 pr_err("err: No clocks found in DT=%zu\n", cnt);
61 return -EINVAL;
62 }
63
64 tmp = of_property_count_u32_elems(of_node, "qcom,clock-rates");
65 if (tmp <= 0) {
66 pr_err("err: No clk rates device tree, count=%zu", tmp);
67 return -EINVAL;
68 }
69
70 if (cnt != tmp) {
71 pr_err("err: clk name/rates mismatch, strings=%zu, rates=%zu\n",
72 cnt, tmp);
73 return -EINVAL;
74 }
75
76 if (of_property_read_bool(of_node, "qcom,clock-cntl-support")) {
77 tmp = of_property_count_strings(of_node,
78 "qcom,clock-control");
79 if (tmp <= 0) {
80 pr_err("err: control strings not found in DT count=%zu",
81 tmp);
82 return -EINVAL;
83 }
84 if (cnt != tmp) {
85 pr_err("err: controls mismatch, strings=%zu, ctl=%zu\n",
86 cnt, tmp);
87 return -EINVAL;
88 }
89 clock_cntl_support = true;
90 }
91
92 *num_clk = cnt;
93
94 *clk_info = devm_kcalloc(dev, cnt,
95 sizeof(struct msm_cam_clk_info), GFP_KERNEL);
96 if (!*clk_info)
97 return -ENOMEM;
98
99 *clk_ptr = devm_kcalloc(dev, cnt, sizeof(struct clk *),
100 GFP_KERNEL);
101 if (!*clk_ptr) {
102 rc = -ENOMEM;
103 goto err1;
104 }
105
106 rates = devm_kcalloc(dev, cnt, sizeof(long), GFP_KERNEL);
107 if (!rates) {
108 rc = -ENOMEM;
109 goto err2;
110 }
111
112 rc = of_property_read_u32_array(of_node, "qcom,clock-rates",
113 rates, cnt);
114 if (rc < 0) {
115 pr_err("err: failed reading clock rates\n");
116 rc = -EINVAL;
117 goto err3;
118 }
119
120 for (i = 0; i < cnt; i++) {
121 rc = of_property_read_string_index(of_node, "clock-names",
122 i, &((*clk_info)[i].clk_name));
123 if (rc < 0) {
124 pr_err("%s reading clock-name failed index %d\n",
125 __func__, i);
126 rc = -EINVAL;
127 goto err3;
128 }
129
130 CDBG("dbg: clk-name[%d] = %s\n", i, (*clk_info)[i].clk_name);
131 if (clock_cntl_support) {
132 rc = of_property_read_string_index(of_node,
133 "qcom,clock-control", i, &clk_ctl);
134 if (rc < 0) {
135 pr_err("%s reading clock-control failed index %d\n",
136 __func__, i);
137 rc = -EINVAL;
138 goto err3;
139 }
140
141 if (!strcmp(clk_ctl, "NO_SET_RATE"))
142 (*clk_info)[i].clk_rate = NO_SET_RATE;
143 else if (!strcmp(clk_ctl, "INIT_RATE"))
144 (*clk_info)[i].clk_rate = INIT_RATE;
145 else if (!strcmp(clk_ctl, "SET_RATE"))
146 (*clk_info)[i].clk_rate = rates[i];
147 else {
148 pr_err("%s: error: clock control has invalid value\n",
149 __func__);
150 rc = -EBUSY;
151 goto err3;
152 }
153 } else
154 (*clk_info)[i].clk_rate =
155 (rates[i] == 0) ? (long)-1 : rates[i];
156
157 CDBG("dbg: clk-rate[%d] = rate: %ld\n",
158 i, (*clk_info)[i].clk_rate);
159
160 (*clk_ptr)[i] =
161 devm_clk_get(dev, (*clk_info)[i].clk_name);
162 if (IS_ERR((*clk_ptr)[i])) {
163 rc = PTR_ERR((*clk_ptr)[i]);
164 goto err4;
165 }
166 CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]);
167 }
168
169 devm_kfree(dev, rates);
170 return rc;
171
172err4:
173 if (i > 0) {
174 do {
175 devm_clk_put(dev, (*clk_ptr)[--i]);
176 } while (i);
177 }
178err3:
179 devm_kfree(dev, rates);
180err2:
181 devm_kfree(dev, *clk_ptr);
182err1:
183 devm_kfree(dev, *clk_info);
184 return rc;
185}
186
187/* Get all clocks from DT for I2C devices */
188int msm_camera_i2c_dev_get_clk_info(struct device *dev,
189 struct msm_cam_clk_info **clk_info,
190 struct clk ***clk_ptr,
191 size_t *num_clk)
192{
193 int rc = 0;
194
195 if (!dev || !clk_info || !clk_ptr || !num_clk)
196 return -EINVAL;
197
198 rc = msm_camera_get_clk_info_internal(dev, clk_info, clk_ptr, num_clk);
199 return rc;
200}
201EXPORT_SYMBOL(msm_camera_i2c_dev_get_clk_info);
202
203/* Get all clocks from DT for platform devices */
204int msm_camera_get_clk_info(struct platform_device *pdev,
205 struct msm_cam_clk_info **clk_info,
206 struct clk ***clk_ptr,
207 size_t *num_clk)
208{
209 int rc = 0;
210
Naitik Bharadiyaa0508742019-11-19 19:23:47 +0530211 if (!pdev || (&pdev->dev == NULL) || !clk_info || !clk_ptr || !num_clk)
Pratap Nirujogi6e759912018-01-17 17:51:17 +0530212 return -EINVAL;
213
214 rc = msm_camera_get_clk_info_internal(&pdev->dev,
215 clk_info, clk_ptr, num_clk);
216 return rc;
217}
218EXPORT_SYMBOL(msm_camera_get_clk_info);
219
220/* Get all clocks and multiple rates from DT */
221int msm_camera_get_clk_info_and_rates(
222 struct platform_device *pdev,
223 struct msm_cam_clk_info **pclk_info,
224 struct clk ***pclks,
225 uint32_t ***pclk_rates,
226 size_t *num_set,
227 size_t *num_clk)
228{
229 int rc = 0, tmp_var, cnt, tmp;
230 int32_t i = 0, j = 0;
231 struct device_node *of_node;
232 uint32_t **rates;
233 struct clk **clks;
234 struct msm_cam_clk_info *clk_info;
235
236 if (!pdev || !pclk_info || !num_clk
237 || !pclk_rates || !pclks || !num_set)
238 return -EINVAL;
239
240 of_node = pdev->dev.of_node;
241
242 cnt = of_property_count_strings(of_node, "clock-names");
243 if (cnt <= 0) {
244 pr_err("err: No clocks found in DT=%d\n", cnt);
245 return -EINVAL;
246 }
247
248 tmp = of_property_count_u32_elems(of_node, "qcom,clock-rates");
249 if (tmp <= 0) {
250 pr_err("err: No clk rates device tree, count=%d\n", tmp);
251 return -EINVAL;
252 }
253
254 if ((tmp % cnt) != 0) {
255 pr_err("err: clk name/rates mismatch, strings=%d, rates=%d\n",
256 cnt, tmp);
257 return -EINVAL;
258 }
259
260 *num_clk = cnt;
261 *num_set = (tmp / cnt);
262
263 clk_info = devm_kcalloc(&pdev->dev, cnt,
264 sizeof(struct msm_cam_clk_info), GFP_KERNEL);
265 if (!clk_info)
266 return -ENOMEM;
267
268 clks = devm_kcalloc(&pdev->dev, cnt, sizeof(struct clk *),
269 GFP_KERNEL);
270 if (!clks) {
271 rc = -ENOMEM;
272 goto err1;
273 }
274
275 rates = devm_kcalloc(&pdev->dev, *num_set,
276 sizeof(uint32_t *), GFP_KERNEL);
277 if (!rates) {
278 rc = -ENOMEM;
279 goto err2;
280 }
281
282 for (i = 0; i < *num_set; i++) {
283 rates[i] = devm_kcalloc(&pdev->dev, *num_clk,
284 sizeof(uint32_t), GFP_KERNEL);
285 if (!rates[i] && (i > 0)) {
286 rc = -ENOMEM;
287 for (j = i - 1; j >= 0; j--)
288 devm_kfree(&pdev->dev, rates[j]);
289 goto err3;
290 }
291 }
292
293 tmp_var = 0;
294 for (i = 0; i < *num_set; i++) {
295 for (j = 0; j < *num_clk; j++) {
296 rc = of_property_read_u32_index(of_node,
297 "qcom,clock-rates", tmp_var++, &rates[i][j]);
298 if (rc < 0) {
299 pr_err("err: failed reading clock rates\n");
300 rc = -EINVAL;
301 goto err4;
302 }
303 CDBG("Clock rate idx %d idx %d value %d\n",
304 i, j, rates[i][j]);
305 }
306 }
307 for (i = 0; i < *num_clk; i++) {
308 rc = of_property_read_string_index(of_node, "clock-names",
309 i, &clk_info[i].clk_name);
310 if (rc < 0) {
311 pr_err("%s reading clock-name failed index %d\n",
312 __func__, i);
313 rc = -EINVAL;
314 goto err4;
315 }
316
317 CDBG("dbg: clk-name[%d] = %s\n", i, clk_info[i].clk_name);
318
319 clks[i] =
320 devm_clk_get(&pdev->dev, clk_info[i].clk_name);
321 if (IS_ERR(clks[i])) {
322 rc = PTR_ERR(clks[i]);
323 goto err5;
324 }
325 CDBG("clk ptr[%d] :%pK\n", i, clks[i]);
326 }
327 *pclk_info = clk_info;
328 *pclks = clks;
329 *pclk_rates = rates;
330
331 return rc;
332
333err5:
334 if (i > 0) {
335 do {
336 devm_clk_put(&pdev->dev, clks[--i]);
337 } while (i);
338 }
339err4:
340 for (i = 0; i < *num_set; i++)
341 devm_kfree(&pdev->dev, rates[i]);
342err3:
343 devm_kfree(&pdev->dev, rates);
344err2:
345 devm_kfree(&pdev->dev, clks);
346err1:
347 devm_kfree(&pdev->dev, clk_info);
348 return rc;
349}
350EXPORT_SYMBOL(msm_camera_get_clk_info_and_rates);
351
352/* Enable/Disable all clocks */
353int msm_camera_clk_enable(struct device *dev,
354 struct msm_cam_clk_info *clk_info,
355 struct clk **clk_ptr, int num_clk, int enable)
356{
357 int i;
358 int rc = 0;
359 long clk_rate;
360
361 if (enable) {
362 for (i = 0; i < num_clk; i++) {
363 CDBG("enable %s\n", clk_info[i].clk_name);
364 if (clk_info[i].clk_rate > 0) {
365 clk_rate = clk_round_rate(clk_ptr[i],
366 clk_info[i].clk_rate);
367 if (clk_rate < 0) {
368 pr_err("%s round failed\n",
369 clk_info[i].clk_name);
370 goto cam_clk_set_err;
371 }
372 rc = clk_set_rate(clk_ptr[i],
373 clk_rate);
374 if (rc < 0) {
375 pr_err("%s set failed\n",
376 clk_info[i].clk_name);
377 goto cam_clk_set_err;
378 }
379
380 } else if (clk_info[i].clk_rate == INIT_RATE) {
381 clk_rate = clk_get_rate(clk_ptr[i]);
382 if (clk_rate == 0) {
383 clk_rate =
384 clk_round_rate(clk_ptr[i], 0);
385 if (clk_rate <= 0) {
386 pr_err("%s round rate failed\n",
387 clk_info[i].clk_name);
388 goto cam_clk_set_err;
389 }
390 }
391 rc = clk_set_rate(clk_ptr[i], clk_rate);
392 if (rc < 0) {
393 pr_err("%s set rate failed\n",
394 clk_info[i].clk_name);
395 goto cam_clk_set_err;
396 }
397 }
398 rc = clk_prepare_enable(clk_ptr[i]);
399 if (rc < 0) {
400 pr_err("%s enable failed\n",
401 clk_info[i].clk_name);
402 goto cam_clk_enable_err;
403 }
404 if (clk_info[i].delay > 20) {
405 msleep(clk_info[i].delay);
406 } else if (clk_info[i].delay) {
407 usleep_range(clk_info[i].delay * 1000,
408 (clk_info[i].delay * 1000) + 1000);
409 }
410 }
411 } else {
412 for (i = num_clk - 1; i >= 0; i--) {
413 if (clk_ptr[i] != NULL) {
414 CDBG("%s disable %s\n", __func__,
415 clk_info[i].clk_name);
416 clk_disable_unprepare(clk_ptr[i]);
417 }
418 }
419 }
420 return rc;
421
422cam_clk_enable_err:
423cam_clk_set_err:
424 for (i--; i >= 0; i--) {
425 if (clk_ptr[i] != NULL)
426 clk_disable_unprepare(clk_ptr[i]);
427 }
428 return rc;
429}
430EXPORT_SYMBOL(msm_camera_clk_enable);
431
432/* Set rate on a specific clock */
433long msm_camera_clk_set_rate(struct device *dev,
434 struct clk *clk,
435 long clk_rate)
436{
437 int rc = 0;
438 long rate = 0;
439
440 if (!dev || !clk || (clk_rate < 0))
441 return -EINVAL;
442
443 CDBG("clk : %pK, enable : %ld\n", clk, clk_rate);
444
445 if (clk_rate > 0) {
446 rate = clk_round_rate(clk, clk_rate);
447 if (rate < 0) {
448 pr_err("round rate failed\n");
449 return -EINVAL;
450 }
451
452 rc = clk_set_rate(clk, rate);
453 if (rc < 0) {
454 pr_err("set rate failed\n");
455 return -EINVAL;
456 }
457 }
458
459 return rate;
460}
461EXPORT_SYMBOL(msm_camera_clk_set_rate);
462
463int msm_camera_set_clk_flags(struct clk *clk, unsigned long flags)
464{
465 if (!clk)
466 return -EINVAL;
467
468 CDBG("clk : %pK, flags : %ld\n", clk, flags);
469
470 return clk_set_flags(clk, flags);
471}
472EXPORT_SYMBOL(msm_camera_set_clk_flags);
473
474/* release memory allocated for clocks */
475static int msm_camera_put_clk_info_internal(struct device *dev,
476 struct msm_cam_clk_info **clk_info,
477 struct clk ***clk_ptr, int cnt)
478{
479 int i;
480
481 for (i = cnt - 1; i >= 0; i--) {
482 if (clk_ptr[i] != NULL)
483 devm_clk_put(dev, (*clk_ptr)[i]);
484
485 CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]);
486 }
487 devm_kfree(dev, *clk_info);
488 devm_kfree(dev, *clk_ptr);
489 *clk_info = NULL;
490 *clk_ptr = NULL;
491 return 0;
492}
493
494/* release memory allocated for clocks for i2c devices */
495int msm_camera_i2c_dev_put_clk_info(struct device *dev,
496 struct msm_cam_clk_info **clk_info,
497 struct clk ***clk_ptr, int cnt)
498{
499 int rc = 0;
500
501 if (!dev || !clk_info || !clk_ptr)
502 return -EINVAL;
503
504 rc = msm_camera_put_clk_info_internal(dev, clk_info, clk_ptr, cnt);
505 return rc;
506}
507EXPORT_SYMBOL(msm_camera_i2c_dev_put_clk_info);
508
509/* release memory allocated for clocks for platform devices */
510int msm_camera_put_clk_info(struct platform_device *pdev,
511 struct msm_cam_clk_info **clk_info,
512 struct clk ***clk_ptr, int cnt)
513{
514 int rc = 0;
515
Naitik Bharadiyaa0508742019-11-19 19:23:47 +0530516 if (!pdev || (&pdev->dev == NULL) || !clk_info || !clk_ptr)
Pratap Nirujogi6e759912018-01-17 17:51:17 +0530517 return -EINVAL;
518
519 rc = msm_camera_put_clk_info_internal(&pdev->dev,
520 clk_info, clk_ptr, cnt);
521 return rc;
522}
523EXPORT_SYMBOL(msm_camera_put_clk_info);
524
525int msm_camera_put_clk_info_and_rates(struct platform_device *pdev,
526 struct msm_cam_clk_info **clk_info,
527 struct clk ***clk_ptr, uint32_t ***clk_rates,
528 size_t set, size_t cnt)
529{
530 int i;
531
532 for (i = set - 1; i >= 0; i--)
533 devm_kfree(&pdev->dev, (*clk_rates)[i]);
534
535 devm_kfree(&pdev->dev, *clk_rates);
536 for (i = cnt - 1; i >= 0; i--) {
537 if (clk_ptr[i] != NULL)
538 devm_clk_put(&pdev->dev, (*clk_ptr)[i]);
539 CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]);
540 }
541 devm_kfree(&pdev->dev, *clk_info);
542 devm_kfree(&pdev->dev, *clk_ptr);
543 *clk_info = NULL;
544 *clk_ptr = NULL;
545 *clk_rates = NULL;
546 return 0;
547}
548EXPORT_SYMBOL(msm_camera_put_clk_info_and_rates);
549
550/* Get reset info from DT */
551int msm_camera_get_reset_info(struct platform_device *pdev,
552 struct reset_control **micro_iface_reset)
553{
554 if (!pdev || !micro_iface_reset)
555 return -EINVAL;
556
557 if (of_property_match_string(pdev->dev.of_node, "reset-names",
558 "micro_iface_reset")) {
559 pr_err("err: Reset property not found\n");
560 return -EINVAL;
561 }
562
563 *micro_iface_reset = devm_reset_control_get
564 (&pdev->dev, "micro_iface_reset");
565 if (IS_ERR(*micro_iface_reset))
566 return PTR_ERR(*micro_iface_reset);
567
568 return 0;
569}
570EXPORT_SYMBOL(msm_camera_get_reset_info);
571
572/* Get regulators from DT */
573int msm_camera_get_regulator_info(struct platform_device *pdev,
574 struct msm_cam_regulator **vdd_info,
575 int *num_reg)
576{
577 uint32_t cnt;
578 int i, rc;
579 struct device_node *of_node;
580 char prop_name[32];
581 struct msm_cam_regulator *tmp_reg;
582
583 if (!pdev || !vdd_info || !num_reg)
584 return -EINVAL;
585
586 of_node = pdev->dev.of_node;
587
588 if (!of_get_property(of_node, "qcom,vdd-names", NULL)) {
589 pr_err("err: Regulators property not found\n");
590 return -EINVAL;
591 }
592
593 cnt = of_property_count_strings(of_node, "qcom,vdd-names");
594 if (cnt <= 0) {
595 pr_err("err: no regulators found in device tree, count=%d",
596 cnt);
597 return -EINVAL;
598 }
599
600 tmp_reg = devm_kcalloc(&pdev->dev, cnt,
601 sizeof(struct msm_cam_regulator), GFP_KERNEL);
602 if (!tmp_reg)
603 return -ENOMEM;
604
605 for (i = 0; i < cnt; i++) {
606 rc = of_property_read_string_index(of_node,
607 "qcom,vdd-names", i, &tmp_reg[i].name);
608 if (rc < 0) {
609 pr_err("Fail to fetch regulators: %d\n", i);
610 rc = -EINVAL;
611 goto err1;
612 }
613
614 CDBG("regulator-names[%d] = %s\n", i, tmp_reg[i].name);
615
616 snprintf(prop_name, 32, "%s-supply", tmp_reg[i].name);
617
618 if (of_get_property(of_node, prop_name, NULL)) {
619 tmp_reg[i].vdd =
620 devm_regulator_get(&pdev->dev, tmp_reg[i].name);
621 if (IS_ERR(tmp_reg[i].vdd)) {
622 rc = -EINVAL;
623 pr_err("Fail to get regulator :%d\n", i);
624 goto err1;
625 }
626 } else {
627 pr_err("Regulator phandle not found :%s\n",
628 tmp_reg[i].name);
629 rc = -EINVAL;
630 goto err1;
631 }
632 CDBG("vdd ptr[%d] :%pK\n", i, tmp_reg[i].vdd);
633 }
634
635 *num_reg = cnt;
636 *vdd_info = tmp_reg;
637
638 return 0;
639
640err1:
641 for (--i; i >= 0; i--)
642 devm_regulator_put(tmp_reg[i].vdd);
643 devm_kfree(&pdev->dev, tmp_reg);
644 return rc;
645}
646EXPORT_SYMBOL(msm_camera_get_regulator_info);
647
648
649/* Enable/Disable regulators */
650int msm_camera_regulator_enable(struct msm_cam_regulator *vdd_info,
651 int cnt, int enable)
652{
653 int i;
654 int rc;
655 struct msm_cam_regulator *tmp = vdd_info;
656
657 if (!tmp) {
658 pr_err("Invalid params");
659 return -EINVAL;
660 }
661 CDBG("cnt : %d\n", cnt);
662
663 for (i = 0; i < cnt; i++) {
664 if (tmp && !IS_ERR_OR_NULL(tmp->vdd)) {
665 CDBG("name : %s, enable : %d\n", tmp->name, enable);
666 if (enable) {
667 rc = regulator_enable(tmp->vdd);
668 if (rc < 0) {
669 pr_err("regulator enable failed %d\n",
670 i);
671 goto error;
672 }
673 } else {
674 rc = regulator_disable(tmp->vdd);
675 if (rc < 0)
676 pr_err("regulator disable failed %d\n",
677 i);
678 }
679 }
680 tmp++;
681 }
682
683 return 0;
684error:
685 for (--i; i > 0; i--) {
686 --tmp;
687 if (!IS_ERR_OR_NULL(tmp->vdd))
688 regulator_disable(tmp->vdd);
689 }
690 return rc;
691}
692EXPORT_SYMBOL(msm_camera_regulator_enable);
693
694/* set regulator mode */
695int msm_camera_regulator_set_mode(struct msm_cam_regulator *vdd_info,
696 int cnt, bool mode)
697{
698 int i;
699 int rc;
700 struct msm_cam_regulator *tmp = vdd_info;
701
702 if (!tmp) {
703 pr_err("Invalid params");
704 return -EINVAL;
705 }
706 CDBG("cnt : %d\n", cnt);
707
708 for (i = 0; i < cnt; i++) {
709 if (tmp && !IS_ERR_OR_NULL(tmp->vdd)) {
710 CDBG("name : %s, enable : %d\n", tmp->name, mode);
711 if (mode) {
712 rc = regulator_set_mode(tmp->vdd,
Trishansh Bhardwaj586ba082018-02-24 15:02:44 +0530713 REGULATOR_MODE_NORMAL);
Pratap Nirujogi6e759912018-01-17 17:51:17 +0530714 if (rc < 0) {
715 pr_err("regulator enable failed %d\n",
716 i);
717 goto error;
718 }
719 } else {
720 rc = regulator_set_mode(tmp->vdd,
721 REGULATOR_MODE_NORMAL);
722 if (rc < 0)
723 pr_err("regulator disable failed %d\n",
724 i);
725 goto error;
726 }
727 }
728 tmp++;
729 }
730
731 return 0;
732error:
733 return rc;
734}
735EXPORT_SYMBOL(msm_camera_regulator_set_mode);
736
737
738/* Put regulators regulators */
739void msm_camera_put_regulators(struct platform_device *pdev,
740 struct msm_cam_regulator **vdd_info, int cnt)
741{
742 int i;
743
744 if (!vdd_info || !*vdd_info) {
745 pr_err("Invalid params\n");
746 return;
747 }
748
749 for (i = cnt - 1; i >= 0; i--) {
750 if (vdd_info[i] && !IS_ERR_OR_NULL(vdd_info[i]->vdd))
751 devm_regulator_put(vdd_info[i]->vdd);
752 CDBG("vdd ptr[%d] :%pK\n", i, vdd_info[i]->vdd);
753 }
754
755 devm_kfree(&pdev->dev, *vdd_info);
756 *vdd_info = NULL;
757}
758EXPORT_SYMBOL(msm_camera_put_regulators);
759
760struct resource *msm_camera_get_irq(struct platform_device *pdev,
761 char *irq_name)
762{
763 if (!pdev || !irq_name) {
764 pr_err("Invalid params\n");
765 return NULL;
766 }
767
768 CDBG("Get irq for %s\n", irq_name);
769 return platform_get_resource_byname(pdev, IORESOURCE_IRQ, irq_name);
770}
771EXPORT_SYMBOL(msm_camera_get_irq);
772
773int msm_camera_register_irq(struct platform_device *pdev,
774 struct resource *irq, irq_handler_t handler,
775 unsigned long irqflags, char *irq_name, void *dev_id)
776{
777 int rc = 0;
778
779 if (!pdev || !irq || !handler || !irq_name || !dev_id) {
780 pr_err("Invalid params\n");
781 return -EINVAL;
782 }
783
784 rc = devm_request_irq(&pdev->dev, irq->start, handler,
785 irqflags, irq_name, dev_id);
786 if (rc < 0) {
787 pr_err("irq request fail\n");
788 rc = -EINVAL;
789 }
790
791 CDBG("Registered irq for %s[resource - %pK]\n", irq_name, irq);
792
793 return rc;
794}
795EXPORT_SYMBOL(msm_camera_register_irq);
796
797int msm_camera_register_threaded_irq(struct platform_device *pdev,
798 struct resource *irq, irq_handler_t handler_fn,
799 irq_handler_t thread_fn, unsigned long irqflags,
800 const char *irq_name, void *dev_id)
801{
802 int rc = 0;
803
804 if (!pdev || !irq || !irq_name || !dev_id) {
805 pr_err("Invalid params\n");
806 return -EINVAL;
807 }
808
809 rc = devm_request_threaded_irq(&pdev->dev, irq->start, handler_fn,
810 thread_fn, irqflags, irq_name, dev_id);
811 if (rc < 0) {
812 pr_err("irq request fail\n");
813 rc = -EINVAL;
814 }
815
816 CDBG("Registered irq for %s[resource - %pK]\n", irq_name, irq);
817
818 return rc;
819}
820EXPORT_SYMBOL(msm_camera_register_threaded_irq);
821
822int msm_camera_enable_irq(struct resource *irq, int enable)
823{
824 if (!irq) {
825 pr_err("Invalid params\n");
826 return -EINVAL;
827 }
828
829 CDBG("irq Enable %d\n", enable);
830 if (enable)
831 enable_irq(irq->start);
832 else
833 disable_irq(irq->start);
834
835 return 0;
836}
837EXPORT_SYMBOL(msm_camera_enable_irq);
838
839int msm_camera_unregister_irq(struct platform_device *pdev,
840 struct resource *irq, void *dev_id)
841{
842
843 if (!pdev || !irq || !dev_id) {
844 pr_err("Invalid params\n");
845 return -EINVAL;
846 }
847
848 CDBG("Un Registering irq for [resource - %pK]\n", irq);
849 devm_free_irq(&pdev->dev, irq->start, dev_id);
850
851 return 0;
852}
853EXPORT_SYMBOL(msm_camera_unregister_irq);
854
855void __iomem *msm_camera_get_reg_base(struct platform_device *pdev,
856 char *device_name, int reserve_mem)
857{
858 struct resource *mem;
859 void __iomem *base;
860
861 if (!pdev || !device_name) {
862 pr_err("Invalid params\n");
863 return NULL;
864 }
865
866 CDBG("device name :%s\n", device_name);
867 mem = platform_get_resource_byname(pdev,
868 IORESOURCE_MEM, device_name);
869 if (!mem) {
870 pr_err("err: mem resource %s not found\n", device_name);
871 return NULL;
872 }
873
874 if (reserve_mem) {
875 CDBG("device:%pK, mem : %pK, size : %d\n",
876 &pdev->dev, mem, (int)resource_size(mem));
877 if (!devm_request_mem_region(&pdev->dev, mem->start,
878 resource_size(mem),
879 device_name)) {
880 pr_err("err: no valid mem region for device:%s\n",
881 device_name);
882 return NULL;
883 }
884 }
885
886 base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
887 if (!base) {
888 devm_release_mem_region(&pdev->dev, mem->start,
889 resource_size(mem));
890 pr_err("err: ioremap failed: %s\n", device_name);
891 return NULL;
892 }
893
894 CDBG("base : %pK\n", base);
895 return base;
896}
897EXPORT_SYMBOL(msm_camera_get_reg_base);
898
899uint32_t msm_camera_get_res_size(struct platform_device *pdev,
900 char *device_name)
901{
902 struct resource *mem;
903
904 if (!pdev || !device_name) {
905 pr_err("Invalid params\n");
906 return 0;
907 }
908
909 CDBG("device name :%s\n", device_name);
910 mem = platform_get_resource_byname(pdev,
911 IORESOURCE_MEM, device_name);
912 if (!mem) {
913 pr_err("err: mem resource %s not found\n", device_name);
914 return 0;
915 }
916 return resource_size(mem);
917}
918EXPORT_SYMBOL(msm_camera_get_res_size);
919
920
921int msm_camera_put_reg_base(struct platform_device *pdev,
922 void __iomem *base, char *device_name, int reserve_mem)
923{
924 struct resource *mem;
925
926 if (!pdev || !base || !device_name) {
927 pr_err("Invalid params\n");
928 return -EINVAL;
929 }
930
931 CDBG("device name :%s\n", device_name);
932 mem = platform_get_resource_byname(pdev,
933 IORESOURCE_MEM, device_name);
934 if (!mem) {
935 pr_err("err: mem resource %s not found\n", device_name);
936 return -EINVAL;
937 }
938 CDBG("mem : %pK, size : %d\n", mem, (int)resource_size(mem));
939
940 devm_iounmap(&pdev->dev, base);
941 if (reserve_mem)
942 devm_release_mem_region(&pdev->dev,
943 mem->start, resource_size(mem));
944
945 return 0;
946}
947EXPORT_SYMBOL(msm_camera_put_reg_base);
948
949/* Register the bus client */
950uint32_t msm_camera_register_bus_client(struct platform_device *pdev,
951 enum cam_bus_client id)
952{
953 int rc = 0;
954 uint32_t bus_client, num_usecases, num_paths;
955 struct msm_bus_scale_pdata *pdata;
956 struct device_node *of_node;
957
958 CDBG("Register client ID: %d\n", id);
959
960 if (id >= CAM_BUS_CLIENT_MAX || !pdev) {
961 pr_err("Invalid params");
962 return -EINVAL;
963 }
964
965 of_node = pdev->dev.of_node;
966
967 if (!g_cv[id].pdata) {
968 rc = of_property_read_u32(of_node, "qcom,msm-bus,num-cases",
969 &num_usecases);
970 if (rc) {
971 pr_err("num-usecases not found\n");
972 return -EINVAL;
973 }
974 rc = of_property_read_u32(of_node, "qcom,msm-bus,num-paths",
975 &num_paths);
976 if (rc) {
977 pr_err("num-usecases not found\n");
978 return -EINVAL;
979 }
980
981 if (num_paths != 1) {
982 pr_err("Exceeds number of paths\n");
983 return -EINVAL;
984 }
985
986 if (of_property_read_bool(of_node,
987 "qcom,msm-bus-vector-dyn-vote")) {
988 if (num_usecases != 2) {
989 pr_err("Excess or less vectors\n");
990 return -EINVAL;
991 }
992 g_cv[id].dyn_vote = true;
993 }
994
995 pdata = msm_bus_cl_get_pdata(pdev);
996 if (!pdata) {
997 pr_err("failed get_pdata client_id :%d\n", id);
998 return -EINVAL;
999 }
1000 bus_client = msm_bus_scale_register_client(pdata);
1001 if (!bus_client) {
1002 pr_err("Unable to register bus client :%d\n", id);
1003 return -EINVAL;
1004 }
1005 } else {
1006 pr_err("vector already setup client_id : %d\n", id);
1007 return -EINVAL;
1008 }
1009
1010 g_cv[id].pdata = pdata;
1011 g_cv[id].bus_client = bus_client;
1012 g_cv[id].vector_index = 0;
1013 g_cv[id].num_usecases = num_usecases;
1014 g_cv[id].num_paths = num_paths;
1015 mutex_init(&g_cv[id].lock);
1016 CDBG("Exit Client ID: %d\n", id);
1017 return 0;
1018}
1019EXPORT_SYMBOL(msm_camera_register_bus_client);
1020
1021/* Update the bus bandwidth */
1022uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib)
1023{
1024 struct msm_bus_paths *path;
1025 struct msm_bus_scale_pdata *pdata;
1026 int idx = 0;
1027
1028 if (id >= CAM_BUS_CLIENT_MAX) {
1029 pr_err("Invalid params");
1030 return -EINVAL;
1031 }
1032 if (g_cv[id].num_usecases != 2 ||
1033 g_cv[id].num_paths != 1 ||
1034 g_cv[id].dyn_vote != true) {
1035 pr_err("dynamic update not allowed\n");
1036 return -EINVAL;
1037 }
1038
1039 mutex_lock(&g_cv[id].lock);
1040 idx = g_cv[id].vector_index;
1041 idx = 1 - idx;
1042 g_cv[id].vector_index = idx;
1043 mutex_unlock(&g_cv[id].lock);
1044
1045 pdata = g_cv[id].pdata;
1046 path = &(pdata->usecase[idx]);
1047 path->vectors[0].ab = ab;
1048 path->vectors[0].ib = ib;
1049
1050 CDBG("Register client ID : %d [ab : %llx, ib : %llx], update :%d\n",
1051 id, ab, ib, idx);
1052 msm_bus_scale_client_update_request(g_cv[id].bus_client, idx);
1053
1054 return 0;
1055}
1056EXPORT_SYMBOL(msm_camera_update_bus_bw);
1057
1058/* Update the bus vector */
1059uint32_t msm_camera_update_bus_vector(enum cam_bus_client id,
1060 int vector_index)
1061{
1062 if (id >= CAM_BUS_CLIENT_MAX || g_cv[id].dyn_vote == true) {
1063 pr_err("Invalid params");
1064 return -EINVAL;
1065 }
1066
1067 if (vector_index < 0 || vector_index > g_cv[id].num_usecases) {
1068 pr_err("Invalid params");
1069 return -EINVAL;
1070 }
1071
1072 CDBG("Register client ID : %d vector idx: %d,\n", id, vector_index);
1073 msm_bus_scale_client_update_request(g_cv[id].bus_client,
1074 vector_index);
1075
1076 return 0;
1077}
1078EXPORT_SYMBOL(msm_camera_update_bus_vector);
1079
1080/* Unregister the bus client */
1081uint32_t msm_camera_unregister_bus_client(enum cam_bus_client id)
1082{
1083 if (id >= CAM_BUS_CLIENT_MAX) {
1084 pr_err("Invalid params");
1085 return -EINVAL;
1086 }
1087
1088 CDBG("UnRegister client ID: %d\n", id);
1089
1090 mutex_destroy(&g_cv[id].lock);
1091 msm_bus_scale_unregister_client(g_cv[id].bus_client);
1092 g_cv[id].bus_client = 0;
1093 g_cv[id].num_usecases = 0;
1094 g_cv[id].num_paths = 0;
1095 g_cv[id].vector_index = 0;
1096 g_cv[id].dyn_vote = 0;
1097
1098 return 0;
1099}
1100EXPORT_SYMBOL(msm_camera_unregister_bus_client);