aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2014-06-25 09:54:36 -0400
committerRob Clark <robdclark@gmail.com>2014-08-04 11:55:28 -0400
commit034fbcc3d8a5dff5d3df5a4ad6bf9cc0b01bd970 (patch)
tree9c27803c6c44f446ed71680fb058927bbc08dd98 /drivers/gpu/drm/msm
parent89301471e6bf942c026d6ebfcbc9a6a937cc6865 (diff)
drm/msm: hdmi phy 8960 phy pll
On downstream kernel the clk driver directly bangs hdmi phy registers. For upstream kernel, we need to model this as a clock and register with the clock framework. Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c377
1 files changed, 376 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
index e5b7ed5b8f01..902d7685d441 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
@@ -15,13 +15,370 @@
15 * this program. If not, see <http://www.gnu.org/licenses/>. 15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18#include <linux/clk.h>
19#include <linux/clk-provider.h>
20
18#include "hdmi.h" 21#include "hdmi.h"
19 22
20struct hdmi_phy_8960 { 23struct hdmi_phy_8960 {
21 struct hdmi_phy base; 24 struct hdmi_phy base;
22 struct hdmi *hdmi; 25 struct hdmi *hdmi;
26 struct clk_hw pll_hw;
27 struct clk *pll;
28 unsigned long pixclk;
23}; 29};
24#define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base) 30#define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base)
31#define clk_to_phy(x) container_of(x, struct hdmi_phy_8960, pll_hw)
32
33/*
34 * HDMI PLL:
35 *
36 * To get the parent clock setup properly, we need to plug in hdmi pll
37 * configuration into common-clock-framework.
38 */
39
40struct pll_rate {
41 unsigned long rate;
42 struct {
43 uint32_t val;
44 uint32_t reg;
45 } conf[32];
46};
47
48/* NOTE: keep sorted highest freq to lowest: */
49static const struct pll_rate freqtbl[] = {
50 /* 1080p60/1080p50 case */
51 { 148500000, {
52 { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
53 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
54 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
55 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
56 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
57 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
58 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
59 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
60 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
61 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
62 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
63 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
64 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
65 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
66 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
67 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
68 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
69 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
70 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
71 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
72 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
73 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
74 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
75 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
76 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
77 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
78 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
79 { 0, 0 } }
80 },
81 { 108000000, {
82 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
83 { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
84 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
85 { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
86 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
87 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
88 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
89 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
90 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
91 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
92 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
93 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
94 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
95 { 0, 0 } }
96 },
97 /* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */
98 { 74250000, {
99 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
100 { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
101 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
102 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
103 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
104 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
105 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
106 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
107 { 0, 0 } }
108 },
109 { 65000000, {
110 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
111 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
112 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
113 { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
114 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
115 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
116 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
117 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
118 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
119 { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
120 { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
121 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
122 { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
123 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
124 { 0, 0 } }
125 },
126 /* 480p60/480i60 */
127 { 27030000, {
128 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
129 { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
130 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
131 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
132 { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
133 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
134 { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
135 { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
136 { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
137 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
138 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
139 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
140 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
141 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
142 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
143 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
144 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
145 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
146 { 0, 0 } }
147 },
148 /* 576p50/576i50 */
149 { 27000000, {
150 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
151 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
152 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
153 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
154 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
155 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
156 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
157 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
158 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
159 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
160 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
161 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
162 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
163 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
164 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
165 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
166 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
167 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
168 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
169 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
170 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
171 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
172 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
173 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
174 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
175 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
176 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
177 { 0, 0 } }
178 },
179 /* 640x480p60 */
180 { 25200000, {
181 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
182 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
183 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
184 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
185 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
186 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
187 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
188 { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
189 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
190 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
191 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
192 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
193 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
194 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
195 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
196 { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
197 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
198 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
199 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
200 { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
201 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
202 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
203 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
204 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
205 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
206 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
207 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
208 { 0, 0 } }
209 },
210};
211
212static int hdmi_pll_enable(struct clk_hw *hw)
213{
214 struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
215 struct hdmi *hdmi = phy_8960->hdmi;
216 int timeout_count, pll_lock_retry = 10;
217 unsigned int val;
218
219 DBG("");
220
221 /* Assert PLL S/W reset */
222 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
223 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);
224 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);
225
226 /* Wait for a short time before de-asserting
227 * to allow the hardware to complete its job.
228 * This much of delay should be fine for hardware
229 * to assert and de-assert.
230 */
231 udelay(10);
232
233 /* De-assert PLL S/W reset */
234 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
235
236 val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
237 val |= HDMI_8960_PHY_REG12_SW_RESET;
238 /* Assert PHY S/W reset */
239 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
240 val &= ~HDMI_8960_PHY_REG12_SW_RESET;
241 /* Wait for a short time before de-asserting
242 to allow the hardware to complete its job.
243 This much of delay should be fine for hardware
244 to assert and de-assert. */
245 udelay(10);
246 /* De-assert PHY S/W reset */
247 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
248 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x3f);
249
250 val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
251 val |= HDMI_8960_PHY_REG12_PWRDN_B;
252 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
253 /* Wait 10 us for enabling global power for PHY */
254 mb();
255 udelay(10);
256
257 val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
258 val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;
259 val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;
260 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
261 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x80);
262
263 timeout_count = 1000;
264 while (--pll_lock_retry > 0) {
265
266 /* are we there yet? */
267 val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_STATUS0);
268 if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)
269 break;
270
271 udelay(1);
272
273 if (--timeout_count > 0)
274 continue;
275
276 /*
277 * PLL has still not locked.
278 * Do a software reset and try again
279 * Assert PLL S/W reset first
280 */
281 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
282 udelay(10);
283 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
284
285 /*
286 * Wait for a short duration for the PLL calibration
287 * before checking if the PLL gets locked
288 */
289 udelay(350);
290
291 timeout_count = 1000;
292 }
293
294 return 0;
295}
296
297static void hdmi_pll_disable(struct clk_hw *hw)
298{
299 struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
300 struct hdmi *hdmi = phy_8960->hdmi;
301 unsigned int val;
302
303 DBG("");
304
305 val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
306 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
307 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
308
309 val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
310 val |= HDMI_8960_PHY_REG12_SW_RESET;
311 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
312 hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
313 /* Make sure HDMI PHY/PLL are powered down */
314 mb();
315}
316
317static const struct pll_rate *find_rate(unsigned long rate)
318{
319 int i;
320 for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
321 if (rate > freqtbl[i].rate)
322 return &freqtbl[i-1];
323 return &freqtbl[i-1];
324}
325
326static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
327 unsigned long parent_rate)
328{
329 struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
330 return phy_8960->pixclk;
331}
332
333static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
334 unsigned long *parent_rate)
335{
336 const struct pll_rate *pll_rate = find_rate(rate);
337 return pll_rate->rate;
338}
339
340static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
341 unsigned long parent_rate)
342{
343 struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
344 struct hdmi *hdmi = phy_8960->hdmi;
345 const struct pll_rate *pll_rate = find_rate(rate);
346 int i;
347
348 DBG("rate=%lu", rate);
349
350 for (i = 0; pll_rate->conf[i].reg; i++)
351 hdmi_write(hdmi, pll_rate->conf[i].reg, pll_rate->conf[i].val);
352
353 phy_8960->pixclk = rate;
354
355 return 0;
356}
357
358
359static const struct clk_ops hdmi_pll_ops = {
360 .enable = hdmi_pll_enable,
361 .disable = hdmi_pll_disable,
362 .recalc_rate = hdmi_pll_recalc_rate,
363 .round_rate = hdmi_pll_round_rate,
364 .set_rate = hdmi_pll_set_rate,
365};
366
367static const char *hdmi_pll_parents[] = {
368 "pxo",
369};
370
371static struct clk_init_data pll_init = {
372 .name = "hdmi_pll",
373 .ops = &hdmi_pll_ops,
374 .parent_names = hdmi_pll_parents,
375 .num_parents = ARRAY_SIZE(hdmi_pll_parents),
376};
377
378
379/*
380 * HDMI Phy:
381 */
25 382
26static void hdmi_phy_8960_destroy(struct hdmi_phy *phy) 383static void hdmi_phy_8960_destroy(struct hdmi_phy *phy)
27{ 384{
@@ -86,6 +443,9 @@ static void hdmi_phy_8960_powerup(struct hdmi_phy *phy,
86 struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy); 443 struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
87 struct hdmi *hdmi = phy_8960->hdmi; 444 struct hdmi *hdmi = phy_8960->hdmi;
88 445
446 DBG("pixclock: %lu", pixclock);
447
448 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x00);
89 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG0, 0x1b); 449 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG0, 0x1b);
90 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG1, 0xf2); 450 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG1, 0xf2);
91 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG4, 0x00); 451 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG4, 0x00);
@@ -104,6 +464,8 @@ static void hdmi_phy_8960_powerdown(struct hdmi_phy *phy)
104 struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy); 464 struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
105 struct hdmi *hdmi = phy_8960->hdmi; 465 struct hdmi *hdmi = phy_8960->hdmi;
106 466
467 DBG("");
468
107 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x7f); 469 hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x7f);
108} 470}
109 471
@@ -118,7 +480,12 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
118{ 480{
119 struct hdmi_phy_8960 *phy_8960; 481 struct hdmi_phy_8960 *phy_8960;
120 struct hdmi_phy *phy = NULL; 482 struct hdmi_phy *phy = NULL;
121 int ret; 483 int ret, i;
484
485 /* sanity check: */
486 for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
487 if (WARN_ON(freqtbl[i].rate < freqtbl[i+1].rate))
488 return ERR_PTR(-EINVAL);
122 489
123 phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL); 490 phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL);
124 if (!phy_8960) { 491 if (!phy_8960) {
@@ -132,6 +499,14 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
132 499
133 phy_8960->hdmi = hdmi; 500 phy_8960->hdmi = hdmi;
134 501
502 phy_8960->pll_hw.init = &pll_init;
503 phy_8960->pll = devm_clk_register(hdmi->dev->dev, &phy_8960->pll_hw);
504 if (IS_ERR(phy_8960->pll)) {
505 ret = PTR_ERR(phy_8960->pll);
506 phy_8960->pll = NULL;
507 goto fail;
508 }
509
135 return phy; 510 return phy;
136 511
137fail: 512fail: