blob: 8d6ff34b87a0ddfb6073ab9a2ab885f82a5916d4 [file] [log] [blame]
Ajay Singh Parmarfdab1ec2013-02-13 20:35:50 +05301/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#include <hdmi.h>
31#include <dev/pm8921.h>
32#include <platform/timer.h>
33#include <platform/gpio.h>
34#include <platform/clock.h>
35#include <platform/iomap.h>
36
37extern void hdmi_app_clk_init(int);
38extern int hdmi_msm_turn_on();
39
40/* HDMI PLL macros */
41#define HDMI_PHY_PLL_REFCLK_CFG (MSM_HDMI_BASE + 0x00000500)
42#define HDMI_PHY_PLL_CHRG_PUMP_CFG (MSM_HDMI_BASE + 0x00000504)
43#define HDMI_PHY_PLL_LOOP_FLT_CFG0 (MSM_HDMI_BASE + 0x00000508)
44#define HDMI_PHY_PLL_LOOP_FLT_CFG1 (MSM_HDMI_BASE + 0x0000050c)
45#define HDMI_PHY_PLL_IDAC_ADJ_CFG (MSM_HDMI_BASE + 0x00000510)
46#define HDMI_PHY_PLL_I_VI_KVCO_CFG (MSM_HDMI_BASE + 0x00000514)
47#define HDMI_PHY_PLL_PWRDN_B (MSM_HDMI_BASE + 0x00000518)
48#define HDMI_PHY_PLL_SDM_CFG0 (MSM_HDMI_BASE + 0x0000051c)
49#define HDMI_PHY_PLL_SDM_CFG1 (MSM_HDMI_BASE + 0x00000520)
50#define HDMI_PHY_PLL_SDM_CFG2 (MSM_HDMI_BASE + 0x00000524)
51#define HDMI_PHY_PLL_SDM_CFG3 (MSM_HDMI_BASE + 0x00000528)
52#define HDMI_PHY_PLL_SDM_CFG4 (MSM_HDMI_BASE + 0x0000052c)
53#define HDMI_PHY_PLL_SSC_CFG0 (MSM_HDMI_BASE + 0x00000530)
54#define HDMI_PHY_PLL_SSC_CFG1 (MSM_HDMI_BASE + 0x00000534)
55#define HDMI_PHY_PLL_SSC_CFG2 (MSM_HDMI_BASE + 0x00000538)
56#define HDMI_PHY_PLL_SSC_CFG3 (MSM_HDMI_BASE + 0x0000053c)
57#define HDMI_PHY_PLL_LOCKDET_CFG0 (MSM_HDMI_BASE + 0x00000540)
58#define HDMI_PHY_PLL_LOCKDET_CFG1 (MSM_HDMI_BASE + 0x00000544)
59#define HDMI_PHY_PLL_LOCKDET_CFG2 (MSM_HDMI_BASE + 0x00000548)
60#define HDMI_PHY_PLL_VCOCAL_CFG0 (MSM_HDMI_BASE + 0x0000054c)
61#define HDMI_PHY_PLL_VCOCAL_CFG1 (MSM_HDMI_BASE + 0x00000550)
62#define HDMI_PHY_PLL_VCOCAL_CFG2 (MSM_HDMI_BASE + 0x00000554)
63#define HDMI_PHY_PLL_VCOCAL_CFG3 (MSM_HDMI_BASE + 0x00000558)
64#define HDMI_PHY_PLL_VCOCAL_CFG4 (MSM_HDMI_BASE + 0x0000055c)
65#define HDMI_PHY_PLL_VCOCAL_CFG5 (MSM_HDMI_BASE + 0x00000560)
66#define HDMI_PHY_PLL_VCOCAL_CFG6 (MSM_HDMI_BASE + 0x00000564)
67#define HDMI_PHY_PLL_VCOCAL_CFG7 (MSM_HDMI_BASE + 0x00000568)
68#define HDMI_PHY_PLL_DEBUG_SEL (MSM_HDMI_BASE + 0x0000056c)
69#define HDMI_PHY_PLL_PWRDN_B (MSM_HDMI_BASE + 0x00000518)
70#define HDMI_PHY_PLL_STATUS0 (MSM_HDMI_BASE + 0x00000598)
71
72/* HDMI PHY/PLL bit field macros */
73#define SW_RESET BIT(2)
74#define SW_RESET_PLL BIT(0)
75#define PWRDN_B BIT(7)
76
77#define PLL_PWRDN_B BIT(3)
78#define PD_PLL BIT(1)
79
80static unsigned hdmi_pll_on;
81
82void hdmi_msm_init_phy()
83{
84 dprintf(INFO, "phy init\n");
85 uint32_t offset;
86
87 writel(0x1B, HDMI_PHY_REG_0);
88 writel(0xf2, HDMI_PHY_REG_1);
89
90 offset = HDMI_PHY_REG_4;
91 while (offset <= HDMI_PHY_REG_11) {
92 writel(0x0, offset);
93 offset += 0x4;
94 }
95
96 writel(0x20, HDMI_PHY_REG_3);
97}
98
99static void hdmi_gpio_config()
100{
101 writel(0x07, GPIO_CONFIG_ADDR(70));
102 writel(0x07, GPIO_CONFIG_ADDR(71));
103 writel(0x05, GPIO_CONFIG_ADDR(72));
104}
105
106void hdmi_msm_reset_core()
107{
108 uint32_t reg_val = 0;
109
110 // Disable clocks
111 hdmi_app_clk_init(0);
112 udelay(5);
113 // Enable clocks
114 hdmi_app_clk_init(1);
115
116 reg_val = readl(SW_RESET_CORE_REG);
117 reg_val |= BIT(11);
118 writel(reg_val, SW_RESET_CORE_REG);
119 udelay(5);
120 reg_val = readl(SW_RESET_CORE_REG);
121 reg_val &= ~(BIT(11));
122 writel(reg_val, SW_RESET_CORE_REG);
123 udelay(5);
124}
125
126void hdmi_phy_reset(void)
127{
128 uint32_t phy_reset_polarity = 0x0;
129 uint32_t pll_reset_polarity = 0x0;
130
131 uint32_t val = readl(HDMI_PHY_CTRL);
132
133 phy_reset_polarity = val >> 3 & 0x1;
134 pll_reset_polarity = val >> 1 & 0x1;
135
136 if (phy_reset_polarity == 0)
137 writel(val | SW_RESET, HDMI_PHY_CTRL);
138 else
139 writel(val & (~SW_RESET), HDMI_PHY_CTRL);
140
141 if (pll_reset_polarity == 0)
142 writel(val | SW_RESET_PLL, HDMI_PHY_CTRL);
143 else
144 writel(val & (~SW_RESET_PLL), HDMI_PHY_CTRL);
145
146 udelay(10);
147
148 if (phy_reset_polarity == 0)
149 writel(val & (~SW_RESET), HDMI_PHY_CTRL);
150 else
151 writel(val | SW_RESET, HDMI_PHY_CTRL);
152
153 if (pll_reset_polarity == 0)
154 writel(val & (~SW_RESET_PLL), HDMI_PHY_CTRL);
155 else
156 writel(val | SW_RESET_PLL, HDMI_PHY_CTRL);
157}
158
159/*
160 * This is the start function which initializes clocks , gpios for hdmi
161 * & powers on the HDMI core
162 */
163void hdmi_power_init()
164{
165 pm8921_low_voltage_switch_enable(lvs_7);
166 apq8064_ext_3p3V_enable();
167 pm8921_HDMI_Switch();
168 hdmi_gpio_config();
169 hdmi_phy_reset();
170 hdmi_msm_set_mode(1);
171}
172
173void hdmi_pll_disable(void)
174{
175 uint32_t val;
176 uint32_t ahb_en_reg, ahb_enabled;
177
178 ahb_en_reg = readl(AHB_EN_REG);
179 ahb_enabled = ahb_en_reg & BIT(4);
180 if (!ahb_enabled) {
181 writel(ahb_en_reg | BIT(4), AHB_EN_REG);
182 udelay(10);
183 }
184
185 val = readl(HDMI_PHY_REG_12);
186 val &= (~PWRDN_B);
187 writel(val, HDMI_PHY_REG_12);
188
189 val = readl(HDMI_PHY_PLL_PWRDN_B);
190 val |= PD_PLL;
191 val &= (~PLL_PWRDN_B);
192 writel(val, HDMI_PHY_PLL_PWRDN_B);
193 /* Make sure HDMI PHY/PLL are powered down */
194 udelay(10);
195
196 if (!ahb_enabled)
197 writel(ahb_en_reg & ~BIT(4), AHB_EN_REG);
198 hdmi_pll_on = 0;
199}
200
201void hdmi_pll_enable(void)
202{
203 uint32_t val;
204 uint32_t ahb_en_reg, ahb_enabled;
205 uint32_t timeout_count;
206 int pll_lock_retry = 10;
207
208 ahb_en_reg = readl(AHB_EN_REG);
209 ahb_enabled = ahb_en_reg & BIT(4);
210 if (!ahb_enabled) {
211 dprintf(INFO, "ahb not enabled\n");
212 writel(ahb_en_reg | BIT(4), AHB_EN_REG);
213 /* Make sure iface clock is enabled before register access */
214 udelay(10);
215 }
216
217 /* Assert PLL S/W reset */
218 writel(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
219 writel(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
220 writel(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
221 /* Wait for a short time before de-asserting
222 * to allow the hardware to complete its job.
223 * This much of delay should be fine for hardware
224 * to assert and de-assert.
225 */
226 udelay(10);
227 /* De-assert PLL S/W reset */
228 writel(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
229
230 val = readl(HDMI_PHY_REG_12);
231 val |= BIT(5);
232 /* Assert PHY S/W reset */
233 writel(val, HDMI_PHY_REG_12);
234 val &= ~BIT(5);
235 /* Wait for a short time before de-asserting
236 to allow the hardware to complete its job.
237 This much of delay should be fine for hardware
238 to assert and de-assert. */
239 udelay(10);
240 /* De-assert PHY S/W reset */
241 writel(val, HDMI_PHY_REG_12);
242 writel(0x3f, HDMI_PHY_REG_2);
243
244 val = readl(HDMI_PHY_REG_12);
245 val |= PWRDN_B;
246 writel(val, HDMI_PHY_REG_12);
247 /* Wait 10 us for enabling global power for PHY */
248 udelay(10);
249
250 val = readl(HDMI_PHY_PLL_PWRDN_B);
251 val |= PLL_PWRDN_B;
252 val &= ~PD_PLL;
253 writel(val, HDMI_PHY_PLL_PWRDN_B);
254 writel(0x80, HDMI_PHY_REG_2);
255
256 timeout_count = 1000;
257 while (!(readl(HDMI_PHY_PLL_STATUS0) & BIT(0)) &&
258 timeout_count && pll_lock_retry) {
259 if (--timeout_count == 0) {
260 dprintf(INFO, "PLL not locked, retry\n");
261 /*
262 * PLL has still not locked.
263 * Do a software reset and try again
264 * Assert PLL S/W reset first
265 */
266 writel(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
267
268 /* Wait for a short time before de-asserting
269 * to allow the hardware to complete its job.
270 * This much of delay should be fine for hardware
271 * to assert and de-assert.
272 */
273 udelay(10);
274 writel(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
275
276 /*
277 * Wait for a short duration for the PLL calibration
278 * before checking if the PLL gets locked
279 */
280 udelay(350);
281
282 timeout_count = 1000;
283 pll_lock_retry--;
284 }
285 }
286
287 if (!ahb_enabled) {
288 writel(ahb_en_reg & ~BIT(4), AHB_EN_REG);
289 udelay(10);
290 }
291
292 if (!pll_lock_retry) {
293 dprintf(INFO, "%s: HDMI PLL not locked\n", __func__);
294 hdmi_pll_disable();
295 }
296
297 hdmi_pll_on = 1;
298}
299
300
301int hdmi_dtv_on()
302{
303 uint32_t ahb_en_reg = readl(AHB_EN_REG);
304 uint32_t ahb_enabled = ahb_en_reg & BIT(4);
305 uint32_t val, pll_mode, ns_val, pll_config;
306
307 if (!ahb_enabled) {
308 dprintf(INFO, "ahb not enabled, turning on\n");
309 writel(ahb_en_reg | BIT(4), AHB_EN_REG);
310 /* Make sure iface clock is enabled before register access */
311 udelay(10);
312 }
313
314 if (hdmi_pll_on)
315 hdmi_pll_disable();
316
317 /* 1080p60/1080p50 case */
318 writel(0x2, HDMI_PHY_PLL_REFCLK_CFG);
319 writel(0x2, HDMI_PHY_PLL_CHRG_PUMP_CFG);
320 writel(0x01, HDMI_PHY_PLL_LOOP_FLT_CFG0);
321 writel(0x33, HDMI_PHY_PLL_LOOP_FLT_CFG1);
322 writel(0x2C, HDMI_PHY_PLL_IDAC_ADJ_CFG);
323 writel(0x6, HDMI_PHY_PLL_I_VI_KVCO_CFG);
324 writel(0xA, HDMI_PHY_PLL_PWRDN_B);
325 writel(0x76, HDMI_PHY_PLL_SDM_CFG0);
326 writel(0x01, HDMI_PHY_PLL_SDM_CFG1);
327 writel(0x4C, HDMI_PHY_PLL_SDM_CFG2);
328 writel(0xC0, HDMI_PHY_PLL_SDM_CFG3);
329 writel(0x00, HDMI_PHY_PLL_SDM_CFG4);
330 writel(0x9A, HDMI_PHY_PLL_SSC_CFG0);
331 writel(0x00, HDMI_PHY_PLL_SSC_CFG1);
332 writel(0x00, HDMI_PHY_PLL_SSC_CFG2);
333 writel(0x00, HDMI_PHY_PLL_SSC_CFG3);
334 writel(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
335 writel(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
336 writel(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
337 writel(0xe6, HDMI_PHY_PLL_VCOCAL_CFG0);
338 writel(0x02, HDMI_PHY_PLL_VCOCAL_CFG1);
339 writel(0x3B, HDMI_PHY_PLL_VCOCAL_CFG2);
340 writel(0x00, HDMI_PHY_PLL_VCOCAL_CFG3);
341 writel(0x86, HDMI_PHY_PLL_VCOCAL_CFG4);
342 writel(0x00, HDMI_PHY_PLL_VCOCAL_CFG5);
343 writel(0x33, HDMI_PHY_PLL_VCOCAL_CFG6);
344 writel(0x00, HDMI_PHY_PLL_VCOCAL_CFG7);
345
346 udelay(10);
347
348 hdmi_pll_enable();
349
350 if (!ahb_enabled)
351 writel(ahb_en_reg & ~BIT(4), AHB_EN_REG);
352
353 // set M N D
354 ns_val = readl(TV_NS_REG);
355 ns_val |= BIT(7);
356 writel(ns_val, TV_NS_REG);
357
358 writel(0x00, TV_MD_REG);
359
360 val = readl(TV_CC_REG);
361 val &= ~(BM(7, 6));
362 val |= CC(6, 0);
363 writel(val, TV_CC_REG);
364
365 ns_val &= ~BIT(7);
366 writel(ns_val, TV_NS_REG);
367
368 // confiure hdmi_ref clk to run @ 148.5 MHz
369 val = readl(MISC_CC2_REG);
370 val |= BIT(11);
371 writel(val, MISC_CC2_REG);
372
373 // Enable TV src clk
374 writel(0x03, TV_NS_REG);
375
376 // Enable hdmi clk
377 val = readl(TV_CC_REG);
378 val |= BIT(12);
379 writel(val, TV_CC_REG);
380
381 // De-Assert hdmi clk
382 val = readl(SW_RESET_CORE_REG);
383 val |= BIT(1);
384 writel(val, SW_RESET_CORE_REG);
385 udelay(10);
386 val = readl(SW_RESET_CORE_REG);
387 val &= ~(BIT(1));
388 writel(val, SW_RESET_CORE_REG);
389 udelay(10);
390
391 // Root en of tv src clk
392 val = readl(TV_CC_REG);
393 val |= BIT(2);
394 writel(val, TV_CC_REG);
395
396 // enable mdp dtv clk
397 val = readl(TV_CC_REG);
398 val |= BIT(0);
399 writel(val, TV_CC_REG);
400 udelay(10);
401
402 return 0;
403}
404