]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-jammy-kernel.git] / drivers / gpu / drm / msm / disp / dpu1 / dpu_io_util.c
CommitLineData
97fb5e8d 1// SPDX-License-Identifier: GPL-2.0-only
25fdd593
JS
2/* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation.
3 * All rights reserved.
25fdd593
JS
4 */
5
6#include <linux/clk.h>
7#include <linux/clk/clk-conf.h>
8#include <linux/err.h>
9#include <linux/delay.h>
10
6a41da17
MS
11#include <drm/drm_print.h>
12
25fdd593
JS
13#include "dpu_io_util.h"
14
15void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
16{
17 int i;
18
19 for (i = num_clk - 1; i >= 0; i--) {
20 if (clk_arry[i].clk)
21 clk_put(clk_arry[i].clk);
22 clk_arry[i].clk = NULL;
23 }
24}
25
26int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk)
27{
28 int i, rc = 0;
29
30 for (i = 0; i < num_clk; i++) {
31 clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name);
aff24cd1 32 rc = PTR_ERR_OR_ZERO(clk_arry[i].clk);
25fdd593
JS
33 if (rc) {
34 DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n",
35 __builtin_return_address(0), __func__,
36 clk_arry[i].clk_name, rc);
37 goto error;
38 }
39 }
40
41 return rc;
42
43error:
44 for (i--; i >= 0; i--) {
45 if (clk_arry[i].clk)
46 clk_put(clk_arry[i].clk);
47 clk_arry[i].clk = NULL;
48 }
49
50 return rc;
51}
52
53int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk)
54{
55 int i, rc = 0;
56
57 for (i = 0; i < num_clk; i++) {
58 if (clk_arry[i].clk) {
59 if (clk_arry[i].type != DSS_CLK_AHB) {
60 DEV_DBG("%pS->%s: '%s' rate %ld\n",
61 __builtin_return_address(0), __func__,
62 clk_arry[i].clk_name,
63 clk_arry[i].rate);
64 rc = clk_set_rate(clk_arry[i].clk,
65 clk_arry[i].rate);
66 if (rc) {
67 DEV_ERR("%pS->%s: %s failed. rc=%d\n",
68 __builtin_return_address(0),
69 __func__,
70 clk_arry[i].clk_name, rc);
71 break;
72 }
73 }
74 } else {
75 DEV_ERR("%pS->%s: '%s' is not available\n",
76 __builtin_return_address(0), __func__,
77 clk_arry[i].clk_name);
78 rc = -EPERM;
79 break;
80 }
81 }
82
83 return rc;
84}
85
86int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
87{
88 int i, rc = 0;
89
90 if (enable) {
91 for (i = 0; i < num_clk; i++) {
92 DEV_DBG("%pS->%s: enable '%s'\n",
93 __builtin_return_address(0), __func__,
94 clk_arry[i].clk_name);
95 if (clk_arry[i].clk) {
96 rc = clk_prepare_enable(clk_arry[i].clk);
97 if (rc)
98 DEV_ERR("%pS->%s: %s en fail. rc=%d\n",
99 __builtin_return_address(0),
100 __func__,
101 clk_arry[i].clk_name, rc);
102 } else {
103 DEV_ERR("%pS->%s: '%s' is not available\n",
104 __builtin_return_address(0), __func__,
105 clk_arry[i].clk_name);
106 rc = -EPERM;
107 }
108
109 if (rc) {
110 msm_dss_enable_clk(&clk_arry[i],
111 i, false);
112 break;
113 }
114 }
115 } else {
116 for (i = num_clk - 1; i >= 0; i--) {
117 DEV_DBG("%pS->%s: disable '%s'\n",
118 __builtin_return_address(0), __func__,
119 clk_arry[i].clk_name);
120
121 if (clk_arry[i].clk)
122 clk_disable_unprepare(clk_arry[i].clk);
123 else
124 DEV_ERR("%pS->%s: '%s' is not available\n",
125 __builtin_return_address(0), __func__,
126 clk_arry[i].clk_name);
127 }
128 }
129
130 return rc;
131}
132
133int msm_dss_parse_clock(struct platform_device *pdev,
134 struct dss_module_power *mp)
135{
136 u32 i, rc = 0;
137 const char *clock_name;
138 int num_clk = 0;
139
140 if (!pdev || !mp)
141 return -EINVAL;
142
143 mp->num_clk = 0;
41a8e886 144 num_clk = of_property_count_strings(pdev->dev.of_node, "clock-names");
25fdd593
JS
145 if (num_clk <= 0) {
146 pr_debug("clocks are not defined\n");
147 return 0;
148 }
149
329e0989
KC
150 mp->clk_config = devm_kcalloc(&pdev->dev,
151 num_clk, sizeof(struct dss_clk),
25fdd593
JS
152 GFP_KERNEL);
153 if (!mp->clk_config)
154 return -ENOMEM;
155
156 for (i = 0; i < num_clk; i++) {
157 rc = of_property_read_string_index(pdev->dev.of_node,
41a8e886 158 "clock-names", i,
25fdd593
JS
159 &clock_name);
160 if (rc) {
6a41da17 161 DRM_DEV_ERROR(&pdev->dev, "Failed to get clock name for %d\n",
25fdd593
JS
162 i);
163 break;
164 }
165 strlcpy(mp->clk_config[i].clk_name, clock_name,
166 sizeof(mp->clk_config[i].clk_name));
167
168 mp->clk_config[i].type = DSS_CLK_AHB;
169 }
170
171 rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, num_clk);
172 if (rc) {
6a41da17 173 DRM_DEV_ERROR(&pdev->dev, "Failed to get clock refs %d\n", rc);
25fdd593
JS
174 goto err;
175 }
176
177 rc = of_clk_set_defaults(pdev->dev.of_node, false);
178 if (rc) {
6a41da17 179 DRM_DEV_ERROR(&pdev->dev, "Failed to set clock defaults %d\n", rc);
25fdd593
JS
180 goto err;
181 }
182
183 for (i = 0; i < num_clk; i++) {
184 u32 rate = clk_get_rate(mp->clk_config[i].clk);
185 if (!rate)
186 continue;
187 mp->clk_config[i].rate = rate;
188 mp->clk_config[i].type = DSS_CLK_PCLK;
189 }
190
191 mp->num_clk = num_clk;
192 return 0;
193
194err:
195 msm_dss_put_clk(mp->clk_config, num_clk);
196 return rc;
197}