blob: b0f060eb9fae8876059de5ae621830beee7a6c46 [file] [log] [blame]
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001/* Copyright (c) 2010-2014, 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#include <err.h>
30#include <debug.h>
31#include <reg.h>
32#include <msm_panel.h>
33#include <platform/timer.h>
34#include <platform/clock.h>
35#include <platform/iomap.h>
36
37static struct msm_fb_panel_data panel;
38
39/* AVI INFOFRAME DATA */
40#define NUM_MODES_AVI 20
41#define AVI_MAX_DATA_BYTES 13
42
43enum {
44 DATA_BYTE_1,
45 DATA_BYTE_2,
46 DATA_BYTE_3,
47 DATA_BYTE_4,
48 DATA_BYTE_5,
49 DATA_BYTE_6,
50 DATA_BYTE_7,
51 DATA_BYTE_8,
52 DATA_BYTE_9,
53 DATA_BYTE_10,
54 DATA_BYTE_11,
55 DATA_BYTE_12,
56 DATA_BYTE_13,
57};
58
59#define IFRAME_PACKET_OFFSET 0x80
60/*
61 * InfoFrame Type Code:
62 * 0x0 - Reserved
63 * 0x1 - Vendor Specific
64 * 0x2 - Auxiliary Video Information
65 * 0x3 - Source Product Description
66 * 0x4 - AUDIO
67 * 0x5 - MPEG Source
68 * 0x6 - NTSC VBI
69 * 0x7 - 0xFF - Reserved
70 */
71#define AVI_IFRAME_TYPE 0x2
72#define AVI_IFRAME_VERSION 0x2
73#define LEFT_SHIFT_BYTE(x) ((x) << 8)
74#define LEFT_SHIFT_WORD(x) ((x) << 16)
75#define LEFT_SHIFT_24BITS(x) ((x) << 24)
76
77struct mdss_hdmi_timing_info {
78 uint32_t video_format;
79 uint32_t active_h;
80 uint32_t front_porch_h;
81 uint32_t pulse_width_h;
82 uint32_t back_porch_h;
83 uint32_t active_low_h;
84 uint32_t active_v;
85 uint32_t front_porch_v;
86 uint32_t pulse_width_v;
87 uint32_t back_porch_v;
88 uint32_t active_low_v;
89 /* Must divide by 1000 to get the actual frequency in MHZ */
90 uint32_t pixel_freq;
91 /* Must divide by 1000 to get the actual frequency in HZ */
92 uint32_t refresh_rate;
93 uint32_t interlaced;
94 uint32_t supported;
95};
96
97#define HDMI_VFRMT_1280x720p60_16_9 4
98#define HDMI_RESOLUTION_DATA HDMI_VFRMT_1280x720p60_16_9##_TIMING
99
100#define HDMI_VFRMT_1280x720p60_16_9_TIMING \
101 {HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, false, \
102 720, 5, 5, 20, false, 74250, 60000, false, true}
103
104uint32_t mdss_hdmi_avi_info_db[] = {
105 0x10, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00,
106 0xD1, 0x02, 0x00, 0x00, 0x01, 0x05};
107
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700108static void mdss_hdmi_audio_acr_setup(void)
109{
110 int n, cts, layout, multiplier;
111 uint32_t aud_pck_ctrl_2_reg = 0, acr_pck_ctrl_reg = 0;
112
113 /* 74.25MHz ACR settings */
114 n = 4096;
115 cts = 74250;
116 layout = 0;
117 multiplier = 1;
118
119 /* AUDIO_PRIORITY | SOURCE */
120 acr_pck_ctrl_reg |= 0x80000100;
121
122 /* N_MULTIPLE(multiplier) */
123 acr_pck_ctrl_reg |= (multiplier & 7) << 16;
124
125 /* SELECT(3) */
126 acr_pck_ctrl_reg |= 3 << 4;
127
128 /* CTS_48 */
129 cts <<= 12;
130
131 /* CTS: need to determine how many fractional bits */
132 writel(cts, HDMI_ACR_48_0);
133
134 /* N */
135 /* HDMI_ACR_48_1 */
136 writel(n, HDMI_ACR_48_1);
137
138 /* Payload layout depends on number of audio channels */
139 aud_pck_ctrl_2_reg = 1 | (layout << 1);
140
141 /* override | layout */
142 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
143
144 /* SEND | CONT */
145 acr_pck_ctrl_reg |= 0x3;
146
147 writel(acr_pck_ctrl_reg, HDMI_ACR_PKT_CTRL);
148}
149
150static int mdss_hdmi_audio_info_setup(void)
151{
152 uint32_t channel_count = 1; /* Default to 2 channels
153 -> See Table 17 in CEA-D spec */
154 uint32_t channel_allocation = 0;
155 uint32_t level_shift = 0;
156 uint32_t down_mix = 0;
157 uint32_t check_sum, audio_info_0_reg, audio_info_1_reg;
158 uint32_t audio_info_ctrl_reg;
159 uint32_t aud_pck_ctrl_2_reg;
160 uint32_t layout;
161
162 layout = 0;
163 aud_pck_ctrl_2_reg = 1 | (layout << 1);
164 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
165
166 /* Read first then write because it is bundled with other controls */
167 audio_info_ctrl_reg = readl(HDMI_INFOFRAME_CTRL0);
168
169 channel_allocation = 0; /* Default to FR,FL */
170
171 /* Program the Channel-Speaker allocation */
172 audio_info_1_reg = 0;
173
174 /* CA(channel_allocation) */
175 audio_info_1_reg |= channel_allocation & 0xff;
176
177 /* Program the Level shifter */
178 /* LSV(level_shift) */
179 audio_info_1_reg |= (level_shift << 11) & 0x00007800;
180
181 /* Program the Down-mix Inhibit Flag */
182 /* DM_INH(down_mix) */
183 audio_info_1_reg |= (down_mix << 15) & 0x00008000;
184
185 writel(audio_info_1_reg, HDMI_AUDIO_INFO1);
186
187 check_sum = 0;
188 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
189 check_sum += 0x84;
190 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
191 check_sum += 1;
192 /* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
193 check_sum += 0x0A;
194 check_sum += channel_count;
195 check_sum += channel_allocation;
196 /* See Table 8.5 in HDMI spec */
197 check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
198 check_sum &= 0xFF;
199 check_sum = (256 - check_sum);
200
201 audio_info_0_reg = 0;
202 /* CHECKSUM(check_sum) */
203 audio_info_0_reg |= check_sum & 0xff;
204 /* CC(channel_count) */
205 audio_info_0_reg |= (channel_count << 8) & 0x00000700;
206
207 writel(audio_info_0_reg, HDMI_AUDIO_INFO0);
208
209 /* Set these flags */
210 /* AUDIO_INFO_UPDATE | AUDIO_INFO_SOURCE | AUDIO_INFO_CONT
211 | AUDIO_INFO_SEND */
212 audio_info_ctrl_reg |= 0xF0;
213
214 /* HDMI_INFOFRAME_CTRL0[0x002C] */
215 writel(audio_info_ctrl_reg, HDMI_INFOFRAME_CTRL0);
216
217 return 0;
218}
219
220static void mdss_hdmi_audio_playback(void)
221{
222 uint32_t base_addr;
223
224 base_addr = memalign(4096, 0x1000);
225 if (base_addr == NULL) {
226 dprintf(CRITICAL, "%s: Error audio buffer alloc\n", __func__);
227 return;
228 }
229
230 memset(base_addr, 0, 0x1000);
231
232 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
233 writel(0x00000080, HDMI_AUDIO_CFG);
234
235 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
236 writel(0x00000A6E, LPASS_LPAIF_RDDMA_CTL0);
237 writel(0x00002000, HDMI_VBI_PKT_CTRL);
238 writel(0x00000000, HDMI_GEN_PKT_CTRL);
239 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
240 writel(base_addr, LPASS_LPAIF_RDDMA_BASE0);
241 writel(0x000005FF, LPASS_LPAIF_RDDMA_BUFF_LEN0);
242 writel(0x000005FF, LPASS_LPAIF_RDDMA_PER_LEN0);
243 writel(0x0000096F, LPASS_LPAIF_RDDMA_CTL0);
244 writel(0x00000010, LPASS_LPAIF_DEBUG_CTL);
245 writel(0x00000000, HDMI_GC);
246 writel(0x00002030, HDMI_VBI_PKT_CTRL);
247 writel(0x00002030, HDMI_VBI_PKT_CTRL);
248 writel(0x00002030, HDMI_VBI_PKT_CTRL);
249
250 mdss_hdmi_audio_acr_setup();
251 mdss_hdmi_audio_info_setup();
252
253 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
254 writel(0x00000080, HDMI_AUDIO_CFG);
255 writel(0x00000011, HDMI_AUDIO_PKT_CTRL);
256 writel(0x00000081, HDMI_AUDIO_CFG);
257}
258
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700259static int mdss_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
260{
261 return target_hdmi_panel_clock(enable, pinfo);
262}
263
264static int mdss_hdmi_enable_power(uint8_t enable)
265{
266 int ret = NO_ERROR;
267
268 ret = target_ldo_ctrl(enable);
269 if (ret) {
270 dprintf(CRITICAL, "LDO control enable failed\n");
271 return ret;
272 }
273
274 ret = target_hdmi_regulator_ctrl(enable);
275 if (ret) {
276 dprintf(CRITICAL, "hdmi regulator control enable failed\n");
277 return ret;
278 }
279
280 dprintf(SPEW, "HDMI Panel power %s done\n", enable ? "on" : "off");
281
282 return ret;
283}
284
285static void mdss_hdmi_set_mode(bool on)
286{
287 uint32_t val = 0;
288
289 if (on) {
290 val = 0x3;
291 writel(val, HDMI_CTRL);
292 } else {
293 writel(val, HDMI_CTRL);
294 }
295}
296
297static void mdss_hdmi_panel_init(struct msm_panel_info *pinfo)
298{
299 struct mdss_hdmi_timing_info tinfo = HDMI_RESOLUTION_DATA;
300
301 if (!pinfo)
302 return;
303
304 pinfo->xres = tinfo.active_h;
305 pinfo->yres = tinfo.active_v;
306 pinfo->bpp = 24;
307 pinfo->type = HDMI_PANEL;
308
309 pinfo->lcdc.h_back_porch = tinfo.back_porch_h;
310 pinfo->lcdc.h_front_porch = tinfo.front_porch_h;
311 pinfo->lcdc.h_pulse_width = tinfo.pulse_width_h;
312 pinfo->lcdc.v_back_porch = tinfo.back_porch_v;
313 pinfo->lcdc.v_front_porch = tinfo.front_porch_v;
314 pinfo->lcdc.v_pulse_width = tinfo.pulse_width_v;
315
316 pinfo->lcdc.hsync_skew = 0;
317 pinfo->lcdc.xres_pad = 0;
318 pinfo->lcdc.yres_pad = 0;
319 pinfo->lcdc.dual_pipe = 0;
320}
321
322void mdss_hdmi_display_init(uint32_t rev, void *base)
323{
324 mdss_hdmi_panel_init(&(panel.panel_info));
325
326 panel.clk_func = mdss_hdmi_panel_clock;
327 panel.power_func = mdss_hdmi_enable_power;
328
329 panel.fb.width = panel.panel_info.xres;
330 panel.fb.height = panel.panel_info.yres;
331 panel.fb.stride = panel.panel_info.xres;
332 panel.fb.bpp = panel.panel_info.bpp;
333 panel.fb.format = FB_FORMAT_RGB888;
334
335 panel.fb.base = base;
336 panel.mdp_rev = rev;
337
338 msm_display_init(&panel);
339}
340
341static int mdss_hdmi_video_setup(void)
342{
343 uint32_t total_v = 0;
344 uint32_t total_h = 0;
345 uint32_t start_h = 0;
346 uint32_t end_h = 0;
347 uint32_t start_v = 0;
348 uint32_t end_v = 0;
349
350 struct mdss_hdmi_timing_info tinfo = HDMI_RESOLUTION_DATA;
351
352 total_h = tinfo.active_h + tinfo.front_porch_h +
353 tinfo.back_porch_h + tinfo.pulse_width_h - 1;
354 total_v = tinfo.active_v + tinfo.front_porch_v +
355 tinfo.back_porch_v + tinfo.pulse_width_v - 1;
356 if (((total_v << 16) & 0xE0000000) || (total_h & 0xFFFFE000)) {
357 dprintf(CRITICAL,
358 "%s: total v=%d or h=%d is larger than supported\n",
359 __func__, total_v, total_h);
360 return ERROR;
361 }
362 writel((total_v << 16) | (total_h << 0), HDMI_TOTAL);
363
364 start_h = tinfo.back_porch_h + tinfo.pulse_width_h;
365 end_h = (total_h + 1) - tinfo.front_porch_h;
366 if (((end_h << 16) & 0xE0000000) || (start_h & 0xFFFFE000)) {
367 dprintf(CRITICAL,
368 "%s: end_h=%d or start_h=%d is larger than supported\n",
369 __func__, end_h, start_h);
370 return ERROR;
371 }
372 writel((end_h << 16) | (start_h << 0), HDMI_ACTIVE_H);
373
374 start_v = tinfo.back_porch_v + tinfo.pulse_width_v - 1;
375 end_v = total_v - tinfo.front_porch_v;
376 if (((end_v << 16) & 0xE0000000) || (start_v & 0xFFFFE000)) {
377 dprintf(CRITICAL,
378 "%s: end_v=%d or start_v=%d is larger than supported\n",
379 __func__, end_v, start_v);
380 return ERROR;
381 }
382 writel((end_v << 16) | (start_v << 0), HDMI_ACTIVE_V);
383
384 if (tinfo.interlaced) {
385 writel((total_v + 1) << 0, HDMI_V_TOTAL_F2);
386 writel(((end_v + 1) << 16) | ((start_v + 1) << 0),
387 HDMI_ACTIVE_V_F2);
388 } else {
389 writel(0, HDMI_V_TOTAL_F2);
390 writel(0, HDMI_ACTIVE_V_F2);
391 }
392
393 writel(((tinfo.interlaced << 31) & 0x80000000) |
394 ((tinfo.active_low_h << 29) & 0x20000000) |
395 ((tinfo.active_low_v << 28) & 0x10000000), HDMI_FRAME_CTRL);
396
397 return 0;
398}
399
400void mdss_hdmi_avi_info_frame(void)
401{
402 uint32_t sum;
403 uint32_t reg_val;
404 uint8_t checksum;
405 uint32_t i;
406
407 sum = IFRAME_PACKET_OFFSET + AVI_IFRAME_TYPE +
408 AVI_IFRAME_VERSION + AVI_MAX_DATA_BYTES;
409
410 for (i = 0; i < AVI_MAX_DATA_BYTES; i++)
411 sum += mdss_hdmi_avi_info_db[i];
412
413 sum &= 0xFF;
414 sum = 256 - sum;
415 checksum = (uint8_t) sum;
416
417 reg_val = checksum |
418 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_1]) |
419 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[DATA_BYTE_2]) |
420 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[DATA_BYTE_3]);
421 writel(reg_val, HDMI_AVI_INFO0);
422
423 reg_val = mdss_hdmi_avi_info_db[DATA_BYTE_4] |
424 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_5]) |
425 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[DATA_BYTE_6]) |
426 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[DATA_BYTE_7]);
427 writel(reg_val, HDMI_AVI_INFO1);
428
429 reg_val = mdss_hdmi_avi_info_db[DATA_BYTE_8] |
430 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_9]) |
431 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[DATA_BYTE_10]) |
432 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[DATA_BYTE_11]);
433 writel(reg_val, HDMI_AVI_INFO2);
434
435 reg_val = mdss_hdmi_avi_info_db[DATA_BYTE_12] |
436 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_13]) |
437 LEFT_SHIFT_24BITS(AVI_IFRAME_VERSION);
438 writel(reg_val, HDMI_AVI_INFO3);
439
440 /* AVI InfFrame enable (every frame) */
441 writel(readl(HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0),
442 HDMI_INFOFRAME_CTRL0);
443}
444
445int mdss_hdmi_init(void)
446{
447 uint32_t hotplug_control;
448
449 mdss_hdmi_set_mode(false);
450
451 hdmi_phy_init();
452
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700453 /* Enable USEC REF timer */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700454 writel(0x0001001B, HDMI_USEC_REFTIMER);
455
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700456 /* Audio settings */
457 mdss_hdmi_audio_playback();
458
459 /* Video settings */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700460 mdss_hdmi_video_setup();
461
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700462 /* AVI info settings */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700463 mdss_hdmi_avi_info_frame();
464
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700465 /* Enable HDMI */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700466 mdss_hdmi_set_mode(true);
467
468 return 0;
469}