drm/msm: rename hdmi symbols
[deliverable/linux.git] / drivers / gpu / drm / msm / hdmi / hdmi_pll_8960.c
CommitLineData
ea184891
AT
1/*
2 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
3 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/clk-provider.h>
20#include "hdmi.h"
21
22struct hdmi_pll_8960 {
23 struct platform_device *pdev;
24 struct clk_hw clk_hw;
25 void __iomem *mmio;
26
27 unsigned long pixclk;
28};
29
30#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8960, clk_hw)
31
32/*
33 * HDMI PLL:
34 *
35 * To get the parent clock setup properly, we need to plug in hdmi pll
36 * configuration into common-clock-framework.
37 */
38
39struct pll_rate {
40 unsigned long rate;
41 int num_reg;
42 struct {
43 u32 val;
44 u32 reg;
45 } conf[32];
46};
47
48/* NOTE: keep sorted highest freq to lowest: */
49static const struct pll_rate freqtbl[] = {
50 { 154000000, 14, {
51 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
52 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
53 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
54 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
55 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
56 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
57 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
58 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
59 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
60 { 0x0d, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
61 { 0x4d, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
62 { 0x5e, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
63 { 0x42, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
64 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
65 }
66 },
67 /* 1080p60/1080p50 case */
68 { 148500000, 27, {
69 { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
70 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
71 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
72 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
73 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
74 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
75 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
76 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
77 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
78 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
79 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
80 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
81 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
82 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
83 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
84 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
85 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
86 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
87 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
88 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
89 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
90 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
91 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
92 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
93 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
94 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
95 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
96 }
97 },
98 { 108000000, 13, {
99 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
100 { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
101 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
102 { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
103 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
104 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
105 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
106 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
107 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
108 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
109 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
110 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
111 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
112 }
113 },
114 /* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */
115 { 74250000, 8, {
116 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
117 { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
118 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
119 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
120 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
121 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
122 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
123 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
124 }
125 },
126 { 74176000, 14, {
127 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
128 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
129 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
130 { 0xe5, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
131 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
132 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
133 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
134 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
135 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
136 { 0x0c, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
137 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
138 { 0x7d, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
139 { 0xbc, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
140 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
141 }
142 },
143 { 65000000, 14, {
144 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
145 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
146 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
147 { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
148 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
149 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
150 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
151 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
152 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
153 { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
154 { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
155 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
156 { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
157 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
158 }
159 },
160 /* 480p60/480i60 */
161 { 27030000, 18, {
162 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
163 { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
164 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
165 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
166 { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
167 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
168 { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
169 { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
170 { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
171 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
172 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
173 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
174 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
175 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
176 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
177 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
178 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
179 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
180 }
181 },
182 /* 576p50/576i50 */
183 { 27000000, 27, {
184 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
185 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
186 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
187 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
188 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
189 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
190 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
191 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
192 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
193 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
194 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
195 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
196 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
197 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
198 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
199 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
200 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
201 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
202 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
203 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
204 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
205 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
206 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
207 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
208 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
209 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
210 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
211 }
212 },
213 /* 640x480p60 */
214 { 25200000, 27, {
215 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
216 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
217 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
218 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
219 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
220 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
221 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
222 { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
223 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
224 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
225 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
226 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
227 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
228 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
229 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
230 { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
231 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
232 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
233 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
234 { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
235 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
236 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
237 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
238 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
239 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
240 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
241 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
242 }
243 },
244};
245
246static inline void pll_write(struct hdmi_pll_8960 *pll, u32 reg, u32 data)
247{
248 msm_writel(data, pll->mmio + reg);
249}
250
251static inline u32 pll_read(struct hdmi_pll_8960 *pll, u32 reg)
252{
253 return msm_readl(pll->mmio + reg);
254}
255
256static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8960 *pll)
257{
258 return platform_get_drvdata(pll->pdev);
259}
260
261static int hdmi_pll_enable(struct clk_hw *hw)
262{
263 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
264 struct hdmi_phy *phy = pll_get_phy(pll);
265 int timeout_count, pll_lock_retry = 10;
266 unsigned int val;
267
268 DBG("");
269
270 /* Assert PLL S/W reset */
271 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
272 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);
273 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);
274
275 /* Wait for a short time before de-asserting
276 * to allow the hardware to complete its job.
277 * This much of delay should be fine for hardware
278 * to assert and de-assert.
279 */
280 udelay(10);
281
282 /* De-assert PLL S/W reset */
283 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
284
285 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
286 val |= HDMI_8960_PHY_REG12_SW_RESET;
287 /* Assert PHY S/W reset */
288 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
289 val &= ~HDMI_8960_PHY_REG12_SW_RESET;
290 /*
291 * Wait for a short time before de-asserting to allow the hardware to
292 * complete its job. This much of delay should be fine for hardware to
293 * assert and de-assert.
294 */
295 udelay(10);
296 /* De-assert PHY S/W reset */
297 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
298 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x3f);
299
300 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
301 val |= HDMI_8960_PHY_REG12_PWRDN_B;
302 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
303 /* Wait 10 us for enabling global power for PHY */
304 mb();
305 udelay(10);
306
307 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);
308 val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;
309 val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;
310 pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
311 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x80);
312
313 timeout_count = 1000;
314 while (--pll_lock_retry > 0) {
315 /* are we there yet? */
316 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_STATUS0);
317 if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)
318 break;
319
320 udelay(1);
321
322 if (--timeout_count > 0)
323 continue;
324
325 /*
326 * PLL has still not locked.
327 * Do a software reset and try again
328 * Assert PLL S/W reset first
329 */
330 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
331 udelay(10);
332 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
333
334 /*
335 * Wait for a short duration for the PLL calibration
336 * before checking if the PLL gets locked
337 */
338 udelay(350);
339
340 timeout_count = 1000;
341 }
342
343 return 0;
344}
345
346static void hdmi_pll_disable(struct clk_hw *hw)
347{
348 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
349 struct hdmi_phy *phy = pll_get_phy(pll);
350 unsigned int val;
351
352 DBG("");
353
354 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);
355 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
356 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);
357
358 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);
359 val |= HDMI_8960_PHY_REG12_SW_RESET;
360 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
361 pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
362 /* Make sure HDMI PHY/PLL are powered down */
363 mb();
364}
365
366static const struct pll_rate *find_rate(unsigned long rate)
367{
368 int i;
369
370 for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
371 if (rate > freqtbl[i].rate)
372 return &freqtbl[i - 1];
373
374 return &freqtbl[i - 1];
375}
376
377static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
378 unsigned long parent_rate)
379{
380 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
381
382 return pll->pixclk;
383}
384
385static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
386 unsigned long *parent_rate)
387{
388 const struct pll_rate *pll_rate = find_rate(rate);
389
390 return pll_rate->rate;
391}
392
393static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
394 unsigned long parent_rate)
395{
396 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);
397 const struct pll_rate *pll_rate = find_rate(rate);
398 int i;
399
400 DBG("rate=%lu", rate);
401
402 for (i = 0; i < pll_rate->num_reg; i++)
403 pll_write(pll, pll_rate->conf[i].reg, pll_rate->conf[i].val);
404
405 pll->pixclk = rate;
406
407 return 0;
408}
409
410static const struct clk_ops hdmi_pll_ops = {
411 .enable = hdmi_pll_enable,
412 .disable = hdmi_pll_disable,
413 .recalc_rate = hdmi_pll_recalc_rate,
414 .round_rate = hdmi_pll_round_rate,
415 .set_rate = hdmi_pll_set_rate,
416};
417
418static const char * const hdmi_pll_parents[] = {
419 "pxo",
420};
421
422static struct clk_init_data pll_init = {
423 .name = "hdmi_pll",
424 .ops = &hdmi_pll_ops,
425 .parent_names = hdmi_pll_parents,
426 .num_parents = ARRAY_SIZE(hdmi_pll_parents),
427};
428
fcda50c8 429int msm_hdmi_pll_8960_init(struct platform_device *pdev)
ea184891
AT
430{
431 struct device *dev = &pdev->dev;
432 struct hdmi_pll_8960 *pll;
433 struct clk *clk;
434 int i;
435
436 /* sanity check: */
437 for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
438 if (WARN_ON(freqtbl[i].rate < freqtbl[i + 1].rate))
439 return -EINVAL;
440
441 pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
442 if (!pll)
443 return -ENOMEM;
444
445 pll->mmio = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL");
446 if (IS_ERR(pll->mmio)) {
447 dev_err(dev, "failed to map pll base\n");
448 return -ENOMEM;
449 }
450
451 pll->pdev = pdev;
452 pll->clk_hw.init = &pll_init;
453
454 clk = devm_clk_register(dev, &pll->clk_hw);
455 if (IS_ERR(clk)) {
456 dev_err(dev, "failed to register pll clock\n");
457 return -EINVAL;
458 }
459
460 return 0;
461}
This page took 0.041243 seconds and 5 git commands to generate.