blob: f26d36d806b42968c50e22ba33afd864293405f9 [file] [log] [blame]
Duy Truongf3ac7b32013-02-13 01:07:28 -08001/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
Channagoud Kadabie4884122011-09-21 23:54:44 +05302 *
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.
Duy Truongf3ac7b32013-02-13 01:07:28 -080012 * * Neither the name of The Linux Foundation nor the names of its
Channagoud Kadabie4884122011-09-21 23:54:44 +053013 * 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#include <hdmi.h>
30#include <platform/timer.h>
31#include <platform/clock.h>
32#include <platform/iomap.h>
33#include <platform/scm-io.h>
34
35#define MDP4_OVERLAYPROC1_BASE 0x18000
36#define MDP4_RGB_BASE 0x40000
37#define MDP4_RGB_OFF 0x10000
38
39struct hdmi_disp_mode_timing_type hdmi_timing_default = {
40 .height = 1080,
41 .hsync_porch_fp = 88,
42 .hsync_width = 44,
43 .hsync_porch_bp = 148,
44 .width = 1920,
45 .vsync_porch_fp = 4,
46 .vsync_width = 5,
47 .vsync_porch_bp = 36,
48};
49
50static void hdmi_msm_set_mode(int on)
51{
52 uint32_t val = 0;
53 if (on) {
54 val |= 0x00000003;
Ajay Dudanib01e5062011-12-03 23:23:42 -080055 writel(val, HDMI_CTRL);
Channagoud Kadabie4884122011-09-21 23:54:44 +053056 } else {
57 val &= ~0x00000002;
Ajay Dudanib01e5062011-12-03 23:23:42 -080058 writel(val, HDMI_CTRL);
Channagoud Kadabie4884122011-09-21 23:54:44 +053059 }
60}
61
Ajay Dudanib01e5062011-12-03 23:23:42 -080062struct hdmi_disp_mode_timing_type *hdmi_common_init_panel_info()
Channagoud Kadabie4884122011-09-21 23:54:44 +053063{
64 return &hdmi_timing_default;
65}
66
67void hdmi_video_setup()
68{
69 uint32_t hsync_total = 0;
70 uint32_t vsync_total = 0;
71 uint32_t hsync_start = 0;
72 uint32_t hsync_end = 0;
73 uint32_t vsync_start = 0;
74 uint32_t vsync_end = 0;
75 uint32_t hvsync_total = 0;
76 uint32_t hsync_active = 0;
77 uint32_t vsync_active = 0;
78 uint32_t hdmi_frame_ctrl = 0;
79 uint32_t val;
Ajay Dudanib01e5062011-12-03 23:23:42 -080080 struct hdmi_disp_mode_timing_type *hdmi_timing =
81 hdmi_common_init_panel_info();
Channagoud Kadabie4884122011-09-21 23:54:44 +053082
83 hsync_total = hdmi_timing->width + hdmi_timing->hsync_porch_fp
Ajay Dudanib01e5062011-12-03 23:23:42 -080084 + hdmi_timing->hsync_porch_bp + hdmi_timing->hsync_width - 1;
Channagoud Kadabie4884122011-09-21 23:54:44 +053085 vsync_total = hdmi_timing->height + hdmi_timing->vsync_porch_fp
Ajay Dudanib01e5062011-12-03 23:23:42 -080086 + hdmi_timing->vsync_porch_bp + hdmi_timing->vsync_width - 1;
Channagoud Kadabie4884122011-09-21 23:54:44 +053087
88 hvsync_total = (vsync_total << 16) & 0x0FFF0000;
89 hvsync_total |= (hsync_total << 0) & 0x00000FFF;
Ajay Dudanib01e5062011-12-03 23:23:42 -080090 writel(hvsync_total, HDMI_TOTAL);
Channagoud Kadabie4884122011-09-21 23:54:44 +053091
92 hsync_start = hdmi_timing->hsync_porch_bp + hdmi_timing->hsync_width;
93 hsync_end = (hsync_total + 1) - hdmi_timing->hsync_porch_fp;
94 hsync_active = (hsync_end << 16) & 0x0FFF0000;
95 hsync_active |= (hsync_start << 0) & 0x00000FFF;
96 writel(hsync_active, HDMI_ACTIVE_HSYNC);
97
Ajay Dudanib01e5062011-12-03 23:23:42 -080098 vsync_start =
99 hdmi_timing->vsync_porch_bp + hdmi_timing->vsync_width - 1;
Channagoud Kadabie4884122011-09-21 23:54:44 +0530100 vsync_end = vsync_total - hdmi_timing->vsync_porch_fp;
101 vsync_active = (vsync_end << 16) & 0x0FFF0000;
102 vsync_active |= (vsync_start << 0) & 0x00000FFF;
103 writel(vsync_active, HDMI_ACTIVE_VSYNC);
104
Ajay Dudanib01e5062011-12-03 23:23:42 -0800105 writel(0, HDMI_VSYNC_TOTAL_F2);
106 writel(0, HDMI_VSYNC_ACTIVE_F2);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530107 hdmi_frame_ctrl_reg();
108}
109
110void hdmi_app_clk_init(int on)
111{
112 uint32_t val = 0;
113 if (on) {
114 // Enable clocks
115 val = secure_readl(MISC_CC2_REG);
116 val |= BIT(11);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800117 secure_writel(val, MISC_CC2_REG);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530118 udelay(10);
119 val = secure_readl(MMSS_AHB_EN_REG);
120 val |= BIT(14);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800121 secure_writel(val, MMSS_AHB_EN_REG);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530122 udelay(10);
123 val = secure_readl(MMSS_AHB_EN_REG);
124 val |= BIT(4);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800125 secure_writel(val, MMSS_AHB_EN_REG);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530126 udelay(10);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800127 } else {
Channagoud Kadabie4884122011-09-21 23:54:44 +0530128 // Disable clocks
129 val = secure_readl(MISC_CC2_REG);
130 val &= ~(BIT(11));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800131 secure_writel(val, MISC_CC2_REG);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530132 udelay(10);
133 val = secure_readl(MMSS_AHB_EN_REG);
134 val &= ~(BIT(14));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800135 secure_writel(val, MMSS_AHB_EN_REG);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530136 udelay(10);
137 val = secure_readl(MMSS_AHB_EN_REG);
138 val &= ~(BIT(4));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800139 secure_writel(val, MMSS_AHB_EN_REG);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530140 udelay(10);
141 }
142}
143
144static void hdmi_msm_reset_core()
145{
146 uint32_t reg_val = 0;
147 hdmi_msm_set_mode(0);
148 // Disable clocks
149 hdmi_app_clk_init(0);
150 udelay(5);
151 // Enable clocks
152 hdmi_app_clk_init(1);
153
154 reg_val = secure_readl(SW_RESET_CORE_REG);
155 reg_val |= BIT(11);
156 secure_writel(reg_val, SW_RESET_CORE_REG);
157 udelay(5);
158 reg_val = secure_readl(SW_RESET_AHB_REG);
159 reg_val |= BIT(9);
160 secure_writel(reg_val, SW_RESET_AHB_REG);
161 udelay(5);
162 reg_val = secure_readl(SW_RESET_AHB_REG);
163 reg_val |= BIT(9);
164 secure_writel(reg_val, SW_RESET_AHB_REG);
165 udelay(20);
166 reg_val = secure_readl(SW_RESET_CORE_REG);
167 reg_val &= ~(BIT(11));
168 secure_writel(reg_val, SW_RESET_CORE_REG);
169 udelay(5);
170 reg_val = secure_readl(SW_RESET_AHB_REG);
171 reg_val &= ~(BIT(9));
172 secure_writel(reg_val, SW_RESET_AHB_REG);
173 udelay(5);
174 reg_val = secure_readl(SW_RESET_AHB_REG);
175 reg_val &= ~(BIT(9));
176 secure_writel(reg_val, SW_RESET_AHB_REG);
177 udelay(5);
178}
179
180void hdmi_msm_turn_on(void)
181{
182 uint32_t hotplug_control;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800183 hdmi_msm_reset_core(); // Reset the core
Channagoud Kadabie4884122011-09-21 23:54:44 +0530184 hdmi_msm_init_phy();
185 // Enable USEC REF timer
Ajay Dudanib01e5062011-12-03 23:23:42 -0800186 writel(0x0001001B, HDMI_USEC_REFTIMER);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530187 // Video setup for HDMI
188 hdmi_video_setup();
189 // Write 1 to HDMI_CTRL to enable HDMI
190 hdmi_msm_set_mode(1);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800191 dprintf(SPEW, "HDMI Core is: %s\n",
192 (readl(HDMI_CTRL) & 0x00000001) ? "on" : "off");
Channagoud Kadabie4884122011-09-21 23:54:44 +0530193}
194
195struct fbcon_config *hdmi_dtv_init(struct hdmi_disp_mode_timing_type *timing)
196{
197 uint32_t dtv_width;
198 uint32_t dtv_height;
199 uint32_t dtv_bpp;
200 uint32_t hsync_period;
201 uint32_t hsync_ctrl;
202 uint32_t hsync_start_x;
203 uint32_t hsync_end_x;
204 uint32_t display_hctl;
205 uint32_t vsync_period;
206 uint32_t display_v_start;
207 uint32_t display_v_end;
208 uint32_t hsync_polarity;
209 uint32_t vsync_polarity;
210 uint32_t data_en_polarity;
211 uint32_t ctrl_polarity;
212 uint32_t dtv_border_clr = 0;
213 uint32_t dtv_underflow_clr = 0;
214 uint32_t active_v_start = 0;
215 uint32_t active_v_end = 0;
216 uint32_t dtv_hsync_skew = 0;
217 uint32_t intf, stage, snum, mask, data;
218 unsigned char *rgb_base;
219 unsigned char *overlay_base;
220 uint32_t val;
221
Ajay Dudanib01e5062011-12-03 23:23:42 -0800222 dprintf(SPEW, "In DTV on function\n");
Channagoud Kadabie4884122011-09-21 23:54:44 +0530223
224 // Turn on all the clocks
225 dtv_on();
226
227 dtv_width = timing->width;
228 dtv_height = timing->height;
229 dtv_bpp = fb_cfg.bpp;
230 fb_cfg.base = FB_ADDR;
231
232 // MDP E config
Ajay Dudanib01e5062011-12-03 23:23:42 -0800233 writel((unsigned)fb_cfg.base, MDP_BASE + 0xb0008); //FB Address
Channagoud Kadabie4884122011-09-21 23:54:44 +0530234
235 writel(((fb_cfg.height << 16) | fb_cfg.width), MDP_BASE + 0xb0004);
236 writel((fb_cfg.width * fb_cfg.bpp / 8), MDP_BASE + 0xb000c);
237 writel(0, MDP_BASE + 0xb0010);
238
Ajay Dudanib01e5062011-12-03 23:23:42 -0800239 writel(DMA_PACK_PATTERN_RGB | DMA_DSTC0G_8BITS | DMA_DSTC1B_8BITS |
240 DMA_DSTC2R_8BITS, MDP_BASE + 0xb0000);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530241 writel(0xff0000, MDP_BASE + 0xb0070);
242 writel(0xff0000, MDP_BASE + 0xb0074);
243 writel(0xff0000, MDP_BASE + 0xb0078);
244
245 // overlay rgb setup RGB2
246 rgb_base = MDP_BASE + MDP4_RGB_BASE;
247 rgb_base += (MDP4_RGB_OFF * 1);
248 writel(((timing->height << 16) | timing->width), rgb_base + 0x0000);
249 writel(0x0, rgb_base + 0x0004);
250 writel(0x0, rgb_base + 0x0008);
251 writel(0x0, rgb_base + 0x000c);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800252 writel(fb_cfg.base, rgb_base + 0x0010); //FB address
Channagoud Kadabie4884122011-09-21 23:54:44 +0530253 writel((fb_cfg.width * fb_cfg.bpp / 8), rgb_base + 0x0040);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800254 writel(0x24216, rgb_base + 0x0050); //format
255 writel(0x20001, rgb_base + 0x0054); //pattern
Channagoud Kadabie4884122011-09-21 23:54:44 +0530256 writel(0x0, rgb_base + 0x0058);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800257 writel(0x20000000, rgb_base + 0x005c); //phaseX
258 writel(0x20000000, rgb_base + 0x0060); // phaseY
Channagoud Kadabie4884122011-09-21 23:54:44 +0530259
260 // mdp4 mixer setup MDP4_MIXER1
261 data = readl(MDP_BASE + 0x10100);
262 stage = 9;
263 snum = 12;
264 mask = 0x0f;
265 mask <<= snum;
266 stage <<= snum;
267 data &= ~mask;
268 data |= stage;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800269 writel(data, MDP_BASE + 0x10100); // Overlay CFG conf
Channagoud Kadabie4884122011-09-21 23:54:44 +0530270 data = readl(MDP_BASE + 0x10100);
271
272 // Overlay cfg
273 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800274 writel(0x0, MDP_BASE + 0x0038); //EXternal interface select
Channagoud Kadabie4884122011-09-21 23:54:44 +0530275
276 data = ((timing->height << 16) | timing->width);
277 writel(data, overlay_base + 0x0008);
278 writel(fb_cfg.base, overlay_base + 0x000c);
279 writel((fb_cfg.width * fb_cfg.bpp / 8), overlay_base + 0x0010);
280 writel(0x10, overlay_base + 0x104);
281 writel(0x10, overlay_base + 0x124);
282 writel(0x10, overlay_base + 0x144);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800283 writel(0x1, overlay_base + 0x0004); /* directout */
Channagoud Kadabie4884122011-09-21 23:54:44 +0530284
Ajay Dudanib01e5062011-12-03 23:23:42 -0800285 hsync_period =
286 timing->hsync_width + timing->hsync_porch_bp + dtv_width +
287 timing->hsync_porch_fp;
Channagoud Kadabie4884122011-09-21 23:54:44 +0530288 hsync_ctrl = (hsync_period << 16) | timing->hsync_width;
289 hsync_start_x = timing->hsync_width + timing->hsync_porch_bp;
290 hsync_end_x = hsync_period - timing->hsync_porch_fp - 1;
291 display_hctl = (hsync_end_x << 16) | hsync_start_x;
292
Ajay Dudanib01e5062011-12-03 23:23:42 -0800293 vsync_period =
294 (timing->vsync_width + timing->vsync_porch_bp + dtv_height +
295 timing->vsync_porch_fp) * hsync_period;
296 display_v_start =
297 (timing->vsync_width + timing->vsync_porch_bp) * hsync_period;
298 display_v_end =
299 vsync_period - (timing->vsync_porch_bp * hsync_period) - 1;
Channagoud Kadabie4884122011-09-21 23:54:44 +0530300
301 dtv_underflow_clr |= 0x80000000;
302 hsync_polarity = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800303 vsync_polarity = 0;
Channagoud Kadabie4884122011-09-21 23:54:44 +0530304 data_en_polarity = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800305 ctrl_polarity =
306 (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530307
308 writel(hsync_ctrl, MDP_BASE + DTV_BASE + 0x4);
309 writel(vsync_period, MDP_BASE + DTV_BASE + 0x8);
310 writel(timing->vsync_width * hsync_period, MDP_BASE + DTV_BASE + 0xc);
311 writel(display_hctl, MDP_BASE + DTV_BASE + 0x18);
312 writel(display_v_start, MDP_BASE + DTV_BASE + 0x1c);
313 writel(0x25a197, MDP_BASE + DTV_BASE + 0x20);
314 writel(dtv_border_clr, MDP_BASE + DTV_BASE + 0x40);
315 writel(0x8fffffff, MDP_BASE + DTV_BASE + 0x44);
316 writel(dtv_hsync_skew, MDP_BASE + DTV_BASE + 0x48);
317 writel(ctrl_polarity, MDP_BASE + DTV_BASE + 0x50);
318 writel(0, MDP_BASE + DTV_BASE + 0x2c);
319 writel(active_v_start, MDP_BASE + DTV_BASE + 0x30);
320 writel(active_v_end, MDP_BASE + DTV_BASE + 0x38);
321
322 /*
323 * Keep Display solid color, for future debugging
324 */
325# if 0
326 writel(0xffffffff, 0x05151008);
327 val = readl(MDP_BASE + 0x50050);
328 val |= BIT(22);
329 writel(val, MDP_BASE + 0x50050);
330 writel(BIT(5), MDP_BASE + 0x18000);
331#endif
Ajay Dudanib01e5062011-12-03 23:23:42 -0800332 /* Enable DTV block */
Channagoud Kadabie4884122011-09-21 23:54:44 +0530333 writel(0x1, MDP_BASE + DTV_BASE);
334 val = BIT(1);
335 val |= BIT(5);
336 writel(val, MDP_BASE + 0x18000);
337 return &fb_cfg;
338}
339
340void hdmi_display_shutdown()
341{
342 writel(0x0, MDP_BASE + DTV_BASE);
343 writel(0x8, MDP_BASE + 0x0038);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800344 writel(0x0, MDP_BASE + 0x10100);
Channagoud Kadabie4884122011-09-21 23:54:44 +0530345}