2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef CONFIG_COMMON_CLK
19 #include <linux/clk.h>
20 #include <linux/clk-provider.h>
25 struct hdmi_phy_8960
{
28 #ifdef CONFIG_COMMON_CLK
34 #define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base)
36 #ifdef CONFIG_COMMON_CLK
37 #define clk_to_phy(x) container_of(x, struct hdmi_phy_8960, pll_hw)
42 * To get the parent clock setup properly, we need to plug in hdmi pll
43 * configuration into common-clock-framework.
54 /* NOTE: keep sorted highest freq to lowest: */
55 static const struct pll_rate freqtbl
[] = {
57 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
58 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
59 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
60 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
61 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
62 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
63 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3
},
64 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
65 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
66 { 0x0d, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
67 { 0x4d, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
68 { 0x5e, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
69 { 0x42, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
70 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
73 /* 1080p60/1080p50 case */
75 { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
76 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG
},
77 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
78 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
79 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG
},
80 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG
},
81 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B
},
82 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
83 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
84 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
85 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
86 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
87 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0
},
88 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1
},
89 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2
},
90 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3
},
91 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0
},
92 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1
},
93 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2
},
94 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
95 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
96 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
97 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3
},
98 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
99 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
100 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6
},
101 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7
},
105 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
106 { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
107 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
108 { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
109 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
110 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
111 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
112 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
113 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
114 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
115 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
116 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
117 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
120 /* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */
122 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B
},
123 { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
124 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
125 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
126 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
127 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
128 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
129 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
133 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
134 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
135 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
136 { 0xe5, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
137 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
138 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
139 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3
},
140 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
141 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
142 { 0x0c, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
143 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
144 { 0x7d, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
145 { 0xbc, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
146 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
150 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
151 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
152 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
153 { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
154 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
155 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
156 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3
},
157 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
158 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
159 { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
160 { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
161 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
162 { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
163 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
168 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B
},
169 { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
170 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG
},
171 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
172 { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
173 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
174 { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
175 { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
176 { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
177 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
178 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
179 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
180 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
181 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3
},
182 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
183 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
184 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6
},
185 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7
},
190 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
191 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG
},
192 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
193 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
194 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG
},
195 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG
},
196 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B
},
197 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
198 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
199 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
200 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
201 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
202 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0
},
203 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1
},
204 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2
},
205 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3
},
206 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0
},
207 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1
},
208 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2
},
209 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
210 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
211 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
212 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3
},
213 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
214 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
215 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6
},
216 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7
},
221 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG
},
222 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG
},
223 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0
},
224 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1
},
225 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG
},
226 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG
},
227 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B
},
228 { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0
},
229 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1
},
230 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2
},
231 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3
},
232 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4
},
233 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0
},
234 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1
},
235 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2
},
236 { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3
},
237 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0
},
238 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1
},
239 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2
},
240 { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0
},
241 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1
},
242 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2
},
243 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3
},
244 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4
},
245 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5
},
246 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6
},
247 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7
},
252 static int hdmi_pll_enable(struct clk_hw
*hw
)
254 struct hdmi_phy_8960
*phy_8960
= clk_to_phy(hw
);
255 struct hdmi
*hdmi
= phy_8960
->hdmi
;
256 int timeout_count
, pll_lock_retry
= 10;
261 /* Assert PLL S/W reset */
262 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2
, 0x8d);
263 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0
, 0x10);
264 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1
, 0x1a);
266 /* Wait for a short time before de-asserting
267 * to allow the hardware to complete its job.
268 * This much of delay should be fine for hardware
269 * to assert and de-assert.
273 /* De-assert PLL S/W reset */
274 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2
, 0x0d);
276 val
= hdmi_read(hdmi
, REG_HDMI_8960_PHY_REG12
);
277 val
|= HDMI_8960_PHY_REG12_SW_RESET
;
278 /* Assert PHY S/W reset */
279 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG12
, val
);
280 val
&= ~HDMI_8960_PHY_REG12_SW_RESET
;
281 /* Wait for a short time before de-asserting
282 to allow the hardware to complete its job.
283 This much of delay should be fine for hardware
284 to assert and de-assert. */
286 /* De-assert PHY S/W reset */
287 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG12
, val
);
288 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG2
, 0x3f);
290 val
= hdmi_read(hdmi
, REG_HDMI_8960_PHY_REG12
);
291 val
|= HDMI_8960_PHY_REG12_PWRDN_B
;
292 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG12
, val
);
293 /* Wait 10 us for enabling global power for PHY */
297 val
= hdmi_read(hdmi
, REG_HDMI_8960_PHY_PLL_PWRDN_B
);
298 val
|= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B
;
299 val
&= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL
;
300 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_PWRDN_B
, val
);
301 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG2
, 0x80);
303 timeout_count
= 1000;
304 while (--pll_lock_retry
> 0) {
306 /* are we there yet? */
307 val
= hdmi_read(hdmi
, REG_HDMI_8960_PHY_PLL_STATUS0
);
308 if (val
& HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK
)
313 if (--timeout_count
> 0)
317 * PLL has still not locked.
318 * Do a software reset and try again
319 * Assert PLL S/W reset first
321 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2
, 0x8d);
323 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2
, 0x0d);
326 * Wait for a short duration for the PLL calibration
327 * before checking if the PLL gets locked
331 timeout_count
= 1000;
337 static void hdmi_pll_disable(struct clk_hw
*hw
)
339 struct hdmi_phy_8960
*phy_8960
= clk_to_phy(hw
);
340 struct hdmi
*hdmi
= phy_8960
->hdmi
;
345 val
= hdmi_read(hdmi
, REG_HDMI_8960_PHY_REG12
);
346 val
&= ~HDMI_8960_PHY_REG12_PWRDN_B
;
347 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG12
, val
);
349 val
= hdmi_read(hdmi
, REG_HDMI_8960_PHY_PLL_PWRDN_B
);
350 val
|= HDMI_8960_PHY_REG12_SW_RESET
;
351 val
&= ~HDMI_8960_PHY_REG12_PWRDN_B
;
352 hdmi_write(hdmi
, REG_HDMI_8960_PHY_PLL_PWRDN_B
, val
);
353 /* Make sure HDMI PHY/PLL are powered down */
357 static const struct pll_rate
*find_rate(unsigned long rate
)
360 for (i
= 1; i
< ARRAY_SIZE(freqtbl
); i
++)
361 if (rate
> freqtbl
[i
].rate
)
362 return &freqtbl
[i
-1];
363 return &freqtbl
[i
-1];
366 static unsigned long hdmi_pll_recalc_rate(struct clk_hw
*hw
,
367 unsigned long parent_rate
)
369 struct hdmi_phy_8960
*phy_8960
= clk_to_phy(hw
);
370 return phy_8960
->pixclk
;
373 static long hdmi_pll_round_rate(struct clk_hw
*hw
, unsigned long rate
,
374 unsigned long *parent_rate
)
376 const struct pll_rate
*pll_rate
= find_rate(rate
);
377 return pll_rate
->rate
;
380 static int hdmi_pll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
381 unsigned long parent_rate
)
383 struct hdmi_phy_8960
*phy_8960
= clk_to_phy(hw
);
384 struct hdmi
*hdmi
= phy_8960
->hdmi
;
385 const struct pll_rate
*pll_rate
= find_rate(rate
);
388 DBG("rate=%lu", rate
);
390 for (i
= 0; pll_rate
->conf
[i
].reg
; i
++)
391 hdmi_write(hdmi
, pll_rate
->conf
[i
].reg
, pll_rate
->conf
[i
].val
);
393 phy_8960
->pixclk
= rate
;
399 static const struct clk_ops hdmi_pll_ops
= {
400 .enable
= hdmi_pll_enable
,
401 .disable
= hdmi_pll_disable
,
402 .recalc_rate
= hdmi_pll_recalc_rate
,
403 .round_rate
= hdmi_pll_round_rate
,
404 .set_rate
= hdmi_pll_set_rate
,
407 static const char *hdmi_pll_parents
[] = {
411 static struct clk_init_data pll_init
= {
413 .ops
= &hdmi_pll_ops
,
414 .parent_names
= hdmi_pll_parents
,
415 .num_parents
= ARRAY_SIZE(hdmi_pll_parents
),
423 static void hdmi_phy_8960_destroy(struct hdmi_phy
*phy
)
425 struct hdmi_phy_8960
*phy_8960
= to_hdmi_phy_8960(phy
);
429 static void hdmi_phy_8960_reset(struct hdmi_phy
*phy
)
431 struct hdmi_phy_8960
*phy_8960
= to_hdmi_phy_8960(phy
);
432 struct hdmi
*hdmi
= phy_8960
->hdmi
;
435 val
= hdmi_read(hdmi
, REG_HDMI_PHY_CTRL
);
437 if (val
& HDMI_PHY_CTRL_SW_RESET_LOW
) {
439 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
440 val
& ~HDMI_PHY_CTRL_SW_RESET
);
443 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
444 val
| HDMI_PHY_CTRL_SW_RESET
);
447 if (val
& HDMI_PHY_CTRL_SW_RESET_PLL_LOW
) {
449 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
450 val
& ~HDMI_PHY_CTRL_SW_RESET_PLL
);
453 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
454 val
| HDMI_PHY_CTRL_SW_RESET_PLL
);
459 if (val
& HDMI_PHY_CTRL_SW_RESET_LOW
) {
461 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
462 val
| HDMI_PHY_CTRL_SW_RESET
);
465 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
466 val
& ~HDMI_PHY_CTRL_SW_RESET
);
469 if (val
& HDMI_PHY_CTRL_SW_RESET_PLL_LOW
) {
471 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
472 val
| HDMI_PHY_CTRL_SW_RESET_PLL
);
475 hdmi_write(hdmi
, REG_HDMI_PHY_CTRL
,
476 val
& ~HDMI_PHY_CTRL_SW_RESET_PLL
);
480 static void hdmi_phy_8960_powerup(struct hdmi_phy
*phy
,
481 unsigned long int pixclock
)
483 struct hdmi_phy_8960
*phy_8960
= to_hdmi_phy_8960(phy
);
484 struct hdmi
*hdmi
= phy_8960
->hdmi
;
486 DBG("pixclock: %lu", pixclock
);
488 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG2
, 0x00);
489 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG0
, 0x1b);
490 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG1
, 0xf2);
491 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG4
, 0x00);
492 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG5
, 0x00);
493 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG6
, 0x00);
494 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG7
, 0x00);
495 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG8
, 0x00);
496 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG9
, 0x00);
497 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG10
, 0x00);
498 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG11
, 0x00);
499 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG3
, 0x20);
502 static void hdmi_phy_8960_powerdown(struct hdmi_phy
*phy
)
504 struct hdmi_phy_8960
*phy_8960
= to_hdmi_phy_8960(phy
);
505 struct hdmi
*hdmi
= phy_8960
->hdmi
;
509 hdmi_write(hdmi
, REG_HDMI_8960_PHY_REG2
, 0x7f);
512 static const struct hdmi_phy_funcs hdmi_phy_8960_funcs
= {
513 .destroy
= hdmi_phy_8960_destroy
,
514 .reset
= hdmi_phy_8960_reset
,
515 .powerup
= hdmi_phy_8960_powerup
,
516 .powerdown
= hdmi_phy_8960_powerdown
,
519 struct hdmi_phy
*hdmi_phy_8960_init(struct hdmi
*hdmi
)
521 struct hdmi_phy_8960
*phy_8960
;
522 struct hdmi_phy
*phy
= NULL
;
524 #ifdef CONFIG_COMMON_CLK
528 for (i
= 0; i
< (ARRAY_SIZE(freqtbl
) - 1); i
++)
529 if (WARN_ON(freqtbl
[i
].rate
< freqtbl
[i
+1].rate
))
530 return ERR_PTR(-EINVAL
);
533 phy_8960
= kzalloc(sizeof(*phy_8960
), GFP_KERNEL
);
539 phy
= &phy_8960
->base
;
541 phy
->funcs
= &hdmi_phy_8960_funcs
;
543 phy_8960
->hdmi
= hdmi
;
545 #ifdef CONFIG_COMMON_CLK
546 phy_8960
->pll_hw
.init
= &pll_init
;
547 phy_8960
->pll
= devm_clk_register(&hdmi
->pdev
->dev
, &phy_8960
->pll_hw
);
548 if (IS_ERR(phy_8960
->pll
)) {
549 ret
= PTR_ERR(phy_8960
->pll
);
550 phy_8960
->pll
= NULL
;
559 hdmi_phy_8960_destroy(phy
);