blob: e030410ae6b2e9287497d98f70bf67d40f018078 [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
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700264static int mdss_hdmi_enable_power(uint8_t enable, struct msm_panel_info *pinfo)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700265{
266 int ret = NO_ERROR;
267
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700268 ret = target_ldo_ctrl(enable, pinfo);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700269 if (ret) {
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700270 dprintf(CRITICAL, "LDO control enable failed\n");
271 goto bail_ldo_fail;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700272 }
273
274 ret = target_hdmi_regulator_ctrl(enable);
275 if (ret) {
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700276 dprintf(CRITICAL, "hdmi regulator control enable failed\n");
277 goto bail_regulator_fail;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700278 }
279
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700280 ret = target_hdmi_gpio_ctrl(enable);
281 if (ret) {
282 dprintf(CRITICAL, "hdmi gpio control enable failed\n");
283 goto bail_gpio_fail;
284 }
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700285
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700286 dprintf(SPEW, "HDMI Panel power %s done\n", enable ? "on" : "off");
287
288 return ret;
289
290bail_gpio_fail:
291 target_hdmi_regulator_ctrl(0);
292
293bail_regulator_fail:
294 target_ldo_ctrl(0, pinfo);
295
296bail_ldo_fail:
297 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700298}
299
300static void mdss_hdmi_set_mode(bool on)
301{
302 uint32_t val = 0;
303
304 if (on) {
305 val = 0x3;
306 writel(val, HDMI_CTRL);
307 } else {
308 writel(val, HDMI_CTRL);
309 }
310}
311
312static void mdss_hdmi_panel_init(struct msm_panel_info *pinfo)
313{
314 struct mdss_hdmi_timing_info tinfo = HDMI_RESOLUTION_DATA;
315
316 if (!pinfo)
317 return;
318
319 pinfo->xres = tinfo.active_h;
320 pinfo->yres = tinfo.active_v;
321 pinfo->bpp = 24;
322 pinfo->type = HDMI_PANEL;
323
324 pinfo->lcdc.h_back_porch = tinfo.back_porch_h;
325 pinfo->lcdc.h_front_porch = tinfo.front_porch_h;
326 pinfo->lcdc.h_pulse_width = tinfo.pulse_width_h;
327 pinfo->lcdc.v_back_porch = tinfo.back_porch_v;
328 pinfo->lcdc.v_front_porch = tinfo.front_porch_v;
329 pinfo->lcdc.v_pulse_width = tinfo.pulse_width_v;
330
331 pinfo->lcdc.hsync_skew = 0;
332 pinfo->lcdc.xres_pad = 0;
333 pinfo->lcdc.yres_pad = 0;
334 pinfo->lcdc.dual_pipe = 0;
335}
336
337void mdss_hdmi_display_init(uint32_t rev, void *base)
338{
339 mdss_hdmi_panel_init(&(panel.panel_info));
340
341 panel.clk_func = mdss_hdmi_panel_clock;
342 panel.power_func = mdss_hdmi_enable_power;
343
344 panel.fb.width = panel.panel_info.xres;
345 panel.fb.height = panel.panel_info.yres;
346 panel.fb.stride = panel.panel_info.xres;
347 panel.fb.bpp = panel.panel_info.bpp;
348 panel.fb.format = FB_FORMAT_RGB888;
349
350 panel.fb.base = base;
351 panel.mdp_rev = rev;
352
353 msm_display_init(&panel);
354}
355
356static int mdss_hdmi_video_setup(void)
357{
358 uint32_t total_v = 0;
359 uint32_t total_h = 0;
360 uint32_t start_h = 0;
361 uint32_t end_h = 0;
362 uint32_t start_v = 0;
363 uint32_t end_v = 0;
364
365 struct mdss_hdmi_timing_info tinfo = HDMI_RESOLUTION_DATA;
366
367 total_h = tinfo.active_h + tinfo.front_porch_h +
368 tinfo.back_porch_h + tinfo.pulse_width_h - 1;
369 total_v = tinfo.active_v + tinfo.front_porch_v +
370 tinfo.back_porch_v + tinfo.pulse_width_v - 1;
371 if (((total_v << 16) & 0xE0000000) || (total_h & 0xFFFFE000)) {
372 dprintf(CRITICAL,
373 "%s: total v=%d or h=%d is larger than supported\n",
374 __func__, total_v, total_h);
375 return ERROR;
376 }
377 writel((total_v << 16) | (total_h << 0), HDMI_TOTAL);
378
379 start_h = tinfo.back_porch_h + tinfo.pulse_width_h;
380 end_h = (total_h + 1) - tinfo.front_porch_h;
381 if (((end_h << 16) & 0xE0000000) || (start_h & 0xFFFFE000)) {
382 dprintf(CRITICAL,
383 "%s: end_h=%d or start_h=%d is larger than supported\n",
384 __func__, end_h, start_h);
385 return ERROR;
386 }
387 writel((end_h << 16) | (start_h << 0), HDMI_ACTIVE_H);
388
389 start_v = tinfo.back_porch_v + tinfo.pulse_width_v - 1;
390 end_v = total_v - tinfo.front_porch_v;
391 if (((end_v << 16) & 0xE0000000) || (start_v & 0xFFFFE000)) {
392 dprintf(CRITICAL,
393 "%s: end_v=%d or start_v=%d is larger than supported\n",
394 __func__, end_v, start_v);
395 return ERROR;
396 }
397 writel((end_v << 16) | (start_v << 0), HDMI_ACTIVE_V);
398
399 if (tinfo.interlaced) {
400 writel((total_v + 1) << 0, HDMI_V_TOTAL_F2);
401 writel(((end_v + 1) << 16) | ((start_v + 1) << 0),
402 HDMI_ACTIVE_V_F2);
403 } else {
404 writel(0, HDMI_V_TOTAL_F2);
405 writel(0, HDMI_ACTIVE_V_F2);
406 }
407
408 writel(((tinfo.interlaced << 31) & 0x80000000) |
409 ((tinfo.active_low_h << 29) & 0x20000000) |
410 ((tinfo.active_low_v << 28) & 0x10000000), HDMI_FRAME_CTRL);
411
412 return 0;
413}
414
415void mdss_hdmi_avi_info_frame(void)
416{
417 uint32_t sum;
418 uint32_t reg_val;
419 uint8_t checksum;
420 uint32_t i;
421
422 sum = IFRAME_PACKET_OFFSET + AVI_IFRAME_TYPE +
423 AVI_IFRAME_VERSION + AVI_MAX_DATA_BYTES;
424
425 for (i = 0; i < AVI_MAX_DATA_BYTES; i++)
426 sum += mdss_hdmi_avi_info_db[i];
427
428 sum &= 0xFF;
429 sum = 256 - sum;
430 checksum = (uint8_t) sum;
431
432 reg_val = checksum |
433 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_1]) |
434 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[DATA_BYTE_2]) |
435 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[DATA_BYTE_3]);
436 writel(reg_val, HDMI_AVI_INFO0);
437
438 reg_val = mdss_hdmi_avi_info_db[DATA_BYTE_4] |
439 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_5]) |
440 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[DATA_BYTE_6]) |
441 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[DATA_BYTE_7]);
442 writel(reg_val, HDMI_AVI_INFO1);
443
444 reg_val = mdss_hdmi_avi_info_db[DATA_BYTE_8] |
445 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_9]) |
446 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[DATA_BYTE_10]) |
447 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[DATA_BYTE_11]);
448 writel(reg_val, HDMI_AVI_INFO2);
449
450 reg_val = mdss_hdmi_avi_info_db[DATA_BYTE_12] |
451 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[DATA_BYTE_13]) |
452 LEFT_SHIFT_24BITS(AVI_IFRAME_VERSION);
453 writel(reg_val, HDMI_AVI_INFO3);
454
455 /* AVI InfFrame enable (every frame) */
456 writel(readl(HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0),
457 HDMI_INFOFRAME_CTRL0);
458}
459
460int mdss_hdmi_init(void)
461{
462 uint32_t hotplug_control;
463
464 mdss_hdmi_set_mode(false);
465
466 hdmi_phy_init();
467
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700468 /* Enable USEC REF timer */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700469 writel(0x0001001B, HDMI_USEC_REFTIMER);
470
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700471 /* Audio settings */
472 mdss_hdmi_audio_playback();
473
474 /* Video settings */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700475 mdss_hdmi_video_setup();
476
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700477 /* AVI info settings */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700478 mdss_hdmi_avi_info_frame();
479
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700480 /* Enable HDMI */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700481 mdss_hdmi_set_mode(true);
482
483 return 0;
484}