blob: 4908c19180e63b51d07bb9152dd9c3724df7ed89 [file] [log] [blame]
Ajay Singh Parmar2a2e3d62015-02-12 16:57:28 -08001/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07002 *
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>
Casey Piper77f69c52015-03-20 15:55:12 -070032#include <malloc.h>
33#include <string.h>
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -070034#include <msm_panel.h>
35#include <platform/timer.h>
36#include <platform/clock.h>
Casey Piper77f69c52015-03-20 15:55:12 -070037#include "mdp5.h"
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -070038#include <platform/iomap.h>
Casey Piper77f69c52015-03-20 15:55:12 -070039#include "mdss_hdmi.h"
Casey Piper6c2f1132015-03-24 11:37:19 -070040#include <target/display.h>
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -070041
42static struct msm_fb_panel_data panel;
Casey Piper77f69c52015-03-20 15:55:12 -070043extern int msm_display_init(struct msm_fb_panel_data *pdata);
Casey Piper7ab92992015-03-18 14:19:23 -070044static bool hdmi_power_enabled;
45static bool hdmi_panel_clock_enabled;
46static bool hdmi_pll_clock_enabled;
Casey Piper77f69c52015-03-20 15:55:12 -070047
Casey Piper1d3611d2015-03-17 15:45:44 -070048/* Supported HDMI Audio channels */
49#define MSM_HDMI_AUDIO_CHANNEL_2 1
50#define MSM_HDMI_AUDIO_CHANNEL_MAX 8
51
52enum msm_hdmi_supported_audio_sample_rates {
53 AUDIO_SAMPLE_RATE_32KHZ,
54 AUDIO_SAMPLE_RATE_44_1KHZ,
55 AUDIO_SAMPLE_RATE_48KHZ,
56 AUDIO_SAMPLE_RATE_88_2KHZ,
57 AUDIO_SAMPLE_RATE_96KHZ,
58 AUDIO_SAMPLE_RATE_176_4KHZ,
59 AUDIO_SAMPLE_RATE_192KHZ,
60 AUDIO_SAMPLE_RATE_MAX
61};
62
63struct hdmi_msm_audio_acr {
64 uint32_t n; /* N parameter for clock regeneration */
65 uint32_t cts; /* CTS parameter for clock regeneration */
66};
67
68struct hdmi_msm_audio_arcs {
69 uint32_t pclk;
70 struct hdmi_msm_audio_acr lut[AUDIO_SAMPLE_RATE_MAX];
71};
72
73#define HDMI_MSM_AUDIO_ARCS(pclk, ...) { pclk, __VA_ARGS__ }
74
75/* Audio constants lookup table for hdmi_msm_audio_acr_setup */
76/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
77static struct hdmi_msm_audio_arcs hdmi_audio_acr_lut[] = {
78 /* 25.200MHz */
79 HDMI_MSM_AUDIO_ARCS(25200, {
80 {4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
81 {12288, 25200}, {25088, 28000}, {24576, 25200} }),
82 /* 27.000MHz */
83 HDMI_MSM_AUDIO_ARCS(27000, {
84 {4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
85 {12288, 27000}, {25088, 30000}, {24576, 27000} }),
86 /* 27.027MHz */
87 HDMI_MSM_AUDIO_ARCS(27030, {
88 {4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
89 {12288, 27027}, {25088, 30030}, {24576, 27027} }),
90 /* 74.250MHz */
91 HDMI_MSM_AUDIO_ARCS(74250, {
92 {4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
93 {12288, 74250}, {25088, 82500}, {24576, 74250} }),
94 /* 148.500MHz */
95 HDMI_MSM_AUDIO_ARCS(148500, {
96 {4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000},
97 {12288, 148500}, {25088, 165000}, {24576, 148500} }),
98 /* 297.000MHz */
99 HDMI_MSM_AUDIO_ARCS(297000, {
100 {3072, 222750}, {4704, 247500}, {5120, 247500}, {9408, 247500},
101 {10240, 247500}, {18816, 247500}, {20480, 247500} }),
102};
103
Ajay Singh Parmar2a2e3d62015-02-12 16:57:28 -0800104extern int msm_display_init(struct msm_fb_panel_data *pdata);
105
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700106/* AVI INFOFRAME DATA */
107#define NUM_MODES_AVI 20
108#define AVI_MAX_DATA_BYTES 13
109
110enum {
111 DATA_BYTE_1,
112 DATA_BYTE_2,
113 DATA_BYTE_3,
114 DATA_BYTE_4,
115 DATA_BYTE_5,
116 DATA_BYTE_6,
117 DATA_BYTE_7,
118 DATA_BYTE_8,
119 DATA_BYTE_9,
120 DATA_BYTE_10,
121 DATA_BYTE_11,
122 DATA_BYTE_12,
123 DATA_BYTE_13,
124};
125
126#define IFRAME_PACKET_OFFSET 0x80
127/*
128 * InfoFrame Type Code:
129 * 0x0 - Reserved
130 * 0x1 - Vendor Specific
131 * 0x2 - Auxiliary Video Information
132 * 0x3 - Source Product Description
133 * 0x4 - AUDIO
134 * 0x5 - MPEG Source
135 * 0x6 - NTSC VBI
136 * 0x7 - 0xFF - Reserved
137 */
138#define AVI_IFRAME_TYPE 0x2
139#define AVI_IFRAME_VERSION 0x2
140#define LEFT_SHIFT_BYTE(x) ((x) << 8)
141#define LEFT_SHIFT_WORD(x) ((x) << 16)
142#define LEFT_SHIFT_24BITS(x) ((x) << 24)
143
Casey Piper1d3611d2015-03-17 15:45:44 -0700144#define MAX_AUDIO_DATA_BLOCK_SIZE 0x80
Casey Piper97d25272015-03-17 15:10:34 -0700145#define DBC_START_OFFSET 4
146#define VIC_INDEX 3
147#define HDMI_VIC_STR_MAX 3
148
149enum edid_data_block_type {
150 RESERVED_DATA_BLOCK1 = 0,
151 AUDIO_DATA_BLOCK,
152 VIDEO_DATA_BLOCK,
153 VENDOR_SPECIFIC_DATA_BLOCK,
154 SPEAKER_ALLOCATION_DATA_BLOCK,
155 VESA_DTC_DATA_BLOCK,
156 RESERVED_DATA_BLOCK2,
157 USE_EXTENDED_TAG
158};
159
160/* video formats defined by CEA 861D */
161#define HDMI_VFRMT_UNKNOWN 0
162#define HDMI_VFRMT_640x480p60_4_3 1
163#define HDMI_VFRMT_1280x720p60_16_9 4
164#define HDMI_VFRMT_1920x1080p60_16_9 16
165#define HDMI_VFRMT_MAX 3
166
167#define DEFAULT_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9
168static uint8_t mdss_hdmi_video_fmt = HDMI_VFRMT_UNKNOWN;
169static uint8_t mdss_hdmi_pref_fmt = HDMI_VFRMT_UNKNOWN;
170static uint8_t pt_scan_info;
171static uint8_t it_scan_info;
172static uint8_t ce_scan_info;
173
174static uint8_t mdss_hdmi_edid_buf[0x80];
175
176enum aspect_ratio {
177 HDMI_RES_AR_INVALID,
178 HDMI_RES_AR_4_3,
179 HDMI_RES_AR_5_4,
180 HDMI_RES_AR_16_9,
181 HDMI_RES_AR_16_10,
182 HDMI_RES_AR_MAX,
183};
184
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700185struct mdss_hdmi_timing_info {
186 uint32_t video_format;
187 uint32_t active_h;
188 uint32_t front_porch_h;
189 uint32_t pulse_width_h;
190 uint32_t back_porch_h;
191 uint32_t active_low_h;
192 uint32_t active_v;
193 uint32_t front_porch_v;
194 uint32_t pulse_width_v;
195 uint32_t back_porch_v;
196 uint32_t active_low_v;
197 /* Must divide by 1000 to get the actual frequency in MHZ */
198 uint32_t pixel_freq;
199 /* Must divide by 1000 to get the actual frequency in HZ */
200 uint32_t refresh_rate;
201 uint32_t interlaced;
202 uint32_t supported;
Casey Piper97d25272015-03-17 15:10:34 -0700203 enum aspect_ratio ar;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700204};
205
Casey Piper97d25272015-03-17 15:10:34 -0700206#define HDMI_VFRMT_640x480p60_4_3_TIMING \
207 {HDMI_VFRMT_640x480p60_4_3, 640, 16, 96, 48, true, \
208 480, 10, 2, 33, true, 25200, 60000, false, true, HDMI_RES_AR_4_3}
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800209
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700210#define HDMI_VFRMT_1280x720p60_16_9_TIMING \
211 {HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, false, \
Casey Piper97d25272015-03-17 15:10:34 -0700212 720, 5, 5, 20, false, 74250, 60000, false, true, HDMI_RES_AR_16_9}
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700213
Casey Piper97d25272015-03-17 15:10:34 -0700214#define HDMI_VFRMT_1920x1080p60_16_9_TIMING \
215 {HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, false, \
216 1080, 4, 5, 36, false, 148500, 60000, false, true, HDMI_RES_AR_16_9}
217
218#define MSM_HDMI_MODES_GET_DETAILS(mode, MODE) do { \
219 struct mdss_hdmi_timing_info info = MODE##_TIMING; \
220 *mode = info; \
221 } while (0)
222
223static inline int mdss_hdmi_get_timing_info(
224 struct mdss_hdmi_timing_info *mode, int id)
225{
226 int ret = 0;
227
228 switch (id) {
229 case HDMI_VFRMT_640x480p60_4_3:
230 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_640x480p60_4_3);
231 break;
232
233 case HDMI_VFRMT_1280x720p60_16_9:
234 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_1280x720p60_16_9);
235 break;
236
237 case HDMI_VFRMT_1920x1080p60_16_9:
238 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_1920x1080p60_16_9);
239 break;
240
241 default:
242 ret = ERROR;
243 }
244
245 return ret;
246}
247
248
249/*
250 * 13 Bytes of AVI infoframe data wrt each resolution
251 * Data Byte 01: 0 Y1 Y0 A0 B1 B0 S1 S0
252 * Data Byte 02: C1 C0 M1 M0 R3 R2 R1 R0
253 * Data Byte 03: ITC EC2 EC1 EC0 Q1 Q0 SC1 SC0
254 * Data Byte 04: 0 VIC6 VIC5 VIC4 VIC3 VIC2 VIC1 VIC0
255 * Data Byte 05: 0 0 0 0 PR3 PR2 PR1 PR0
256 * Data Byte 06: LSB Line No of End of Top Bar
257 * Data Byte 07: MSB Line No of End of Top Bar
258 * Data Byte 08: LSB Line No of Start of Bottom Bar
259 * Data Byte 09: MSB Line No of Start of Bottom Bar
260 * Data Byte 10: LSB Pixel Number of End of Left Bar
261 * Data Byte 11: MSB Pixel Number of End of Left Bar
262 * Data Byte 12: LSB Pixel Number of Start of Right Bar
263 * Data Byte 13: MSB Pixel Number of Start of Right Bar
264 */
265static uint8_t mdss_hdmi_avi_info_db[HDMI_VFRMT_MAX][AVI_MAX_DATA_BYTES] = {
266 /* 480p */
267 {0x10, 0x18, 0x00, 0x01, 0x00, 0x00, 0x00,
268 0xE1, 0x01, 0x00, 0x00, 0x81, 0x02},
269 /* 720p */
270 {0x10, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00,
271 0xD1, 0x02, 0x00, 0x00, 0x01, 0x05},
272 /* 1080p */
273 {0x10, 0x28, 0x00, 0x10, 0x00, 0x00, 0x00,
274 0x39, 0x04, 0x00, 0x00, 0x81, 0x07},
275};
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700276
Casey Piper1d3611d2015-03-17 15:45:44 -0700277static void mdss_hdmi_audio_acr_setup(uint32_t sample_rate)
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700278{
Casey Piper1d3611d2015-03-17 15:45:44 -0700279 /* Read first before writing */
280 uint32_t acr_pck_ctrl_reg = readl(HDMI_ACR_PKT_CTRL);
281 struct mdss_hdmi_timing_info tinfo = {0};
282 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
283 struct hdmi_msm_audio_arcs *audio_acr = &hdmi_audio_acr_lut[0];
284 uint32_t lut_size = sizeof(hdmi_audio_acr_lut)
285 / sizeof(*hdmi_audio_acr_lut);
286 uint32_t i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
287 uint32_t channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700288
Casey Piper1d3611d2015-03-17 15:45:44 -0700289 if (ret || !tinfo.supported) {
290 dprintf(CRITICAL, "%s: video format %d not supported\n",
291 __func__, mdss_hdmi_video_fmt);
292 return;
293 }
294
295 for (i = 0; i < lut_size; audio_acr = &hdmi_audio_acr_lut[++i]) {
296 if (audio_acr->pclk == tinfo.pixel_freq)
297 break;
298 }
299
300 if (i >= lut_size) {
301 dprintf(CRITICAL, "%s: pixel clk %d not supported\n", __func__,
302 tinfo.pixel_freq);
303 return;
304 }
305
306 n = audio_acr->lut[sample_rate].n;
307 cts = audio_acr->lut[sample_rate].cts;
308 layout = (MSM_HDMI_AUDIO_CHANNEL_2 == channel_num) ? 0 : 1;
309
310 if ((AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
311 (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
312 multiplier = 4;
313 n >>= 2; /* divide N by 4 and use multiplier */
314 } else if ((AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
315 (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
316 multiplier = 2;
317 n >>= 1; /* divide N by 2 and use multiplier */
318 } else {
319 multiplier = 1;
320 }
321
322 dprintf(SPEW, "%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
323 layout);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700324
325 /* AUDIO_PRIORITY | SOURCE */
326 acr_pck_ctrl_reg |= 0x80000100;
327
Casey Piper1d3611d2015-03-17 15:45:44 -0700328 /* Reset multiplier bits */
329 acr_pck_ctrl_reg &= ~(7 << 16);
330
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700331 /* N_MULTIPLE(multiplier) */
332 acr_pck_ctrl_reg |= (multiplier & 7) << 16;
333
Casey Piper1d3611d2015-03-17 15:45:44 -0700334 if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
335 (AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
336 (AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
337 /* SELECT(3) */
338 acr_pck_ctrl_reg |= 3 << 4;
339 /* CTS_48 */
340 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700341
Casey Piper1d3611d2015-03-17 15:45:44 -0700342 /* CTS: need to determine how many fractional bits */
343 writel(cts, HDMI_ACR_48_0);
344 /* N */
345 writel(n, HDMI_ACR_48_1);
346 } else if ((AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
347 (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
348 (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
349 /* SELECT(2) */
350 acr_pck_ctrl_reg |= 2 << 4;
351 /* CTS_44 */
352 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700353
Casey Piper1d3611d2015-03-17 15:45:44 -0700354 /* CTS: need to determine how many fractional bits */
355 writel(cts, HDMI_ACR_44_0);
356 /* N */
357 writel(n, HDMI_ACR_44_1);
358 } else { /* default to 32k */
359 /* SELECT(1) */
360 acr_pck_ctrl_reg |= 1 << 4;
361 /* CTS_32 */
362 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700363
Casey Piper1d3611d2015-03-17 15:45:44 -0700364 /* CTS: need to determine how many fractional bits */
365 writel(cts, HDMI_ACR_32_0);
366 /* N */
367 writel(n, HDMI_ACR_32_1);
368 }
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700369
370 /* Payload layout depends on number of audio channels */
Casey Piper1d3611d2015-03-17 15:45:44 -0700371 /* LAYOUT_SEL(layout) */
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700372 aud_pck_ctrl_2_reg = 1 | (layout << 1);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700373 /* override | layout */
374 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
375
376 /* SEND | CONT */
Casey Piper1d3611d2015-03-17 15:45:44 -0700377 acr_pck_ctrl_reg |= 0x00000003;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700378
379 writel(acr_pck_ctrl_reg, HDMI_ACR_PKT_CTRL);
380}
381
Casey Piper1d3611d2015-03-17 15:45:44 -0700382static void mdss_hdmi_audio_info_setup(void)
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700383{
Casey Piper1d3611d2015-03-17 15:45:44 -0700384 uint32_t channel_count = MSM_HDMI_AUDIO_CHANNEL_2;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700385 uint32_t channel_allocation = 0;
386 uint32_t level_shift = 0;
387 uint32_t down_mix = 0;
388 uint32_t check_sum, audio_info_0_reg, audio_info_1_reg;
389 uint32_t audio_info_ctrl_reg;
390 uint32_t aud_pck_ctrl_2_reg;
391 uint32_t layout;
392
Casey Piper1d3611d2015-03-17 15:45:44 -0700393 layout = (MSM_HDMI_AUDIO_CHANNEL_2 == channel_count) ? 0 : 1;;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700394 aud_pck_ctrl_2_reg = 1 | (layout << 1);
395 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
396
397 /* Read first then write because it is bundled with other controls */
398 audio_info_ctrl_reg = readl(HDMI_INFOFRAME_CTRL0);
399
400 channel_allocation = 0; /* Default to FR,FL */
401
402 /* Program the Channel-Speaker allocation */
403 audio_info_1_reg = 0;
404
405 /* CA(channel_allocation) */
406 audio_info_1_reg |= channel_allocation & 0xff;
407
408 /* Program the Level shifter */
409 /* LSV(level_shift) */
410 audio_info_1_reg |= (level_shift << 11) & 0x00007800;
411
412 /* Program the Down-mix Inhibit Flag */
413 /* DM_INH(down_mix) */
414 audio_info_1_reg |= (down_mix << 15) & 0x00008000;
415
416 writel(audio_info_1_reg, HDMI_AUDIO_INFO1);
417
418 check_sum = 0;
419 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
420 check_sum += 0x84;
421 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
422 check_sum += 1;
423 /* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
424 check_sum += 0x0A;
425 check_sum += channel_count;
426 check_sum += channel_allocation;
427 /* See Table 8.5 in HDMI spec */
428 check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
429 check_sum &= 0xFF;
430 check_sum = (256 - check_sum);
431
432 audio_info_0_reg = 0;
433 /* CHECKSUM(check_sum) */
434 audio_info_0_reg |= check_sum & 0xff;
435 /* CC(channel_count) */
436 audio_info_0_reg |= (channel_count << 8) & 0x00000700;
437
438 writel(audio_info_0_reg, HDMI_AUDIO_INFO0);
439
440 /* Set these flags */
441 /* AUDIO_INFO_UPDATE | AUDIO_INFO_SOURCE | AUDIO_INFO_CONT
442 | AUDIO_INFO_SEND */
443 audio_info_ctrl_reg |= 0xF0;
444
445 /* HDMI_INFOFRAME_CTRL0[0x002C] */
446 writel(audio_info_ctrl_reg, HDMI_INFOFRAME_CTRL0);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700447}
448
Casey Piper97d25272015-03-17 15:10:34 -0700449static uint8_t* hdmi_edid_find_block(uint32_t start_offset,
450 uint8_t type, uint8_t *len)
451{
452 /* the start of data block collection, start of Video Data Block */
453 uint8_t *in_buf = mdss_hdmi_edid_buf;
454 uint32_t offset = start_offset;
455 uint32_t end_dbc_offset = in_buf[2];
456
457 *len = 0;
458
459 /*
460 * edid buffer 1, byte 2 being 4 means no non-DTD/Data block collection
461 * present.
462 * edid buffer 1, byte 2 being 0 means no non-DTD/DATA block collection
463 * present and no DTD data present.
464 */
465 if ((end_dbc_offset == 0) || (end_dbc_offset == 4))
466 return NULL;
467
468 while (offset < end_dbc_offset) {
469 uint8_t block_len = in_buf[offset] & 0x1F;
470 if ((in_buf[offset] >> 5) == type) {
471 *len = block_len;
472 dprintf(SPEW,
473 "EDID: block=%d found @ %d with length=%d\n",
474 type, offset, block_len);
475 return in_buf + offset;
476 }
477 offset += 1 + block_len;
478 }
479
480 return NULL;
481}
482
Casey Piper1d3611d2015-03-17 15:45:44 -0700483static bool mdss_hdmi_is_audio_freq_supported(uint32_t freq)
484{
485 uint8_t *in_buf = mdss_hdmi_edid_buf;
486 const uint8_t *adb = NULL;
487 uint32_t adb_size = 0;
488 uint8_t len = 0, count = 0;
489 uint32_t next_offset = DBC_START_OFFSET;
490 uint8_t audio_data_block[MAX_AUDIO_DATA_BLOCK_SIZE];
491
492 do {
493 adb = hdmi_edid_find_block(next_offset,
494 AUDIO_DATA_BLOCK, &len);
495
496 if ((adb_size + len) > MAX_AUDIO_DATA_BLOCK_SIZE) {
497 dprintf(INFO, "%s: invalid adb length\n", __func__);
498 break;
499 }
500
501 if (!adb)
502 break;
503
504 memcpy((audio_data_block + adb_size), adb + 1, len);
505 next_offset = (adb - in_buf) + 1 + len;
506
507 adb_size += len;
508
509 } while (adb);
510
511 count = adb_size/3;
512 adb = audio_data_block;
513
514 while (count--) {
515 uint8_t freq_lst = *(adb + 1) & 0xFF;
516
517 if (freq_lst & BIT(freq))
518 return true;
519
520 adb += 3;
521 }
522
523 return false;
524}
525
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700526static void mdss_hdmi_audio_playback(void)
527{
Casey Piper77f69c52015-03-20 15:55:12 -0700528 char *base_addr;
Casey Piper1d3611d2015-03-17 15:45:44 -0700529 uint32_t sample_rate;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700530
Casey Piper77f69c52015-03-20 15:55:12 -0700531 base_addr = (char *) memalign(4096, 0x1000);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700532 if (base_addr == NULL) {
533 dprintf(CRITICAL, "%s: Error audio buffer alloc\n", __func__);
534 return;
535 }
536
537 memset(base_addr, 0, 0x1000);
538
539 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
540 writel(0x00000080, HDMI_AUDIO_CFG);
541
542 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
543 writel(0x00000A6E, LPASS_LPAIF_RDDMA_CTL0);
544 writel(0x00002000, HDMI_VBI_PKT_CTRL);
545 writel(0x00000000, HDMI_GEN_PKT_CTRL);
546 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
Casey Piper77f69c52015-03-20 15:55:12 -0700547 writel((uint32_t) base_addr, LPASS_LPAIF_RDDMA_BASE0);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700548 writel(0x000005FF, LPASS_LPAIF_RDDMA_BUFF_LEN0);
549 writel(0x000005FF, LPASS_LPAIF_RDDMA_PER_LEN0);
550 writel(0x0000096F, LPASS_LPAIF_RDDMA_CTL0);
551 writel(0x00000010, LPASS_LPAIF_DEBUG_CTL);
552 writel(0x00000000, HDMI_GC);
553 writel(0x00002030, HDMI_VBI_PKT_CTRL);
554 writel(0x00002030, HDMI_VBI_PKT_CTRL);
555 writel(0x00002030, HDMI_VBI_PKT_CTRL);
556
Casey Piper1d3611d2015-03-17 15:45:44 -0700557 if (mdss_hdmi_is_audio_freq_supported(AUDIO_SAMPLE_RATE_48KHZ))
558 sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
559 else
560 sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
561
562 mdss_hdmi_audio_acr_setup(sample_rate);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700563 mdss_hdmi_audio_info_setup();
564
565 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
566 writel(0x00000080, HDMI_AUDIO_CFG);
567 writel(0x00000011, HDMI_AUDIO_PKT_CTRL);
568 writel(0x00000081, HDMI_AUDIO_CFG);
Casey Piper1d3611d2015-03-17 15:45:44 -0700569
570 dprintf(SPEW, "audio sample rate %s\n",
571 sample_rate == AUDIO_SAMPLE_RATE_48KHZ ? "48KHz" : "32KHz");
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700572}
573
Casey Piper77f69c52015-03-20 15:55:12 -0700574static uint32_t mdss_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700575{
Casey Piper7ab92992015-03-18 14:19:23 -0700576 int ret = NO_ERROR;
577 if (hdmi_panel_clock_enabled)
578 return ret;
579
580 ret = target_hdmi_panel_clock(enable, pinfo);
581
582 hdmi_panel_clock_enabled = enable;
583
584 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700585}
586
Casey Piper6c2f1132015-03-24 11:37:19 -0700587static uint32_t mdss_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo)
588{
Casey Piper7ab92992015-03-18 14:19:23 -0700589 int ret = NO_ERROR;
590
591 if (hdmi_pll_clock_enabled)
592 return ret;
593
594 ret = target_hdmi_pll_clock(enable, pinfo);
595
596 hdmi_pll_clock_enabled = enable;
597
598 return ret;
Casey Piper6c2f1132015-03-24 11:37:19 -0700599}
600
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700601static int mdss_hdmi_enable_power(uint8_t enable, struct msm_panel_info *pinfo)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700602{
Casey Piper7ab92992015-03-18 14:19:23 -0700603 int ret = NO_ERROR;
604
605 if (hdmi_power_enabled)
606 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700607
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700608 ret = target_hdmi_regulator_ctrl(enable);
609 if (ret) {
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700610 dprintf(CRITICAL, "hdmi regulator control enable failed\n");
611 goto bail_regulator_fail;
Casey Piper7ab92992015-03-18 14:19:23 -0700612 }
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700613
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700614 ret = target_hdmi_gpio_ctrl(enable);
615 if (ret) {
616 dprintf(CRITICAL, "hdmi gpio control enable failed\n");
617 goto bail_gpio_fail;
Casey Piper7ab92992015-03-18 14:19:23 -0700618 }
619
620 hdmi_power_enabled = enable;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700621
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700622 dprintf(SPEW, "HDMI Panel power %s done\n", enable ? "on" : "off");
623
624 return ret;
625
626bail_gpio_fail:
627 target_hdmi_regulator_ctrl(0);
628
629bail_regulator_fail:
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700630 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700631}
632
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800633static bool mdss_hdmi_is_dvi_mode(void)
634{
635 uint8_t len;
636 uint32_t ieee_tag;
637 const uint8_t *vsd = NULL;
638
639 vsd = hdmi_edid_find_block(DBC_START_OFFSET,
640 VENDOR_SPECIFIC_DATA_BLOCK, &len);
641
642 if (vsd == NULL || len == 0) {
643 dprintf(SPEW, "%s: Invalid VSDB\n", __func__);
644 return false;
645 }
646
647 ieee_tag = ((uint32_t) vsd[3] << 16) + ((uint32_t) vsd[2] << 8) +
648 (uint32_t) vsd[1];
649
650 if (ieee_tag == 0x0c03)
651 return false;
652 else
653 return true;
654}
655
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700656static void mdss_hdmi_set_mode(bool on)
657{
658 uint32_t val = 0;
659
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800660 if (on) {
661 /* tx on */
662 val = 0x1;
663
664 if (!mdss_hdmi_is_dvi_mode())
665 val |= 0x2;
666 }
Casey Piper6c2f1132015-03-24 11:37:19 -0700667
668 writel(val, HDMI_CTRL);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700669}
670
Casey Piper97d25272015-03-17 15:10:34 -0700671
672static int mdss_hdmi_read_edid(void)
673{
674 uint8_t ndx;
675 uint32_t reg_val;
676 uint32_t dev_addr = 0xA0;
677 uint32_t len = 0x80;
678 uint32_t offset = 0x80;
679 uint32_t time_out;
680 uint32_t retry = 5;
681
682 dev_addr &= 0xFE;
683
684again:
685 time_out = 10;
686 writel(readl(HDMI_DDC_ARBITRATION) & ~BIT(4), HDMI_DDC_ARBITRATION);
687
688 /* Enable DDC Interrupts */
689 writel(BIT(1) | BIT(2), HDMI_DDC_INT_CTRL);
690
691 /* config DDC to read CEA block */
692 writel((10 << 16) | (2 << 0), HDMI_DDC_SPEED);
693 writel(0xFF000000, HDMI_DDC_SETUP);
694 writel((1 << 16) | (19 << 0), HDMI_DDC_REF);
695 writel(BIT(31) | (dev_addr << 8), HDMI_DDC_DATA);
696 writel(offset << 8, HDMI_DDC_DATA);
697 writel((dev_addr | BIT(0)) << 8, HDMI_DDC_DATA);
698 writel(BIT(12) | BIT(16), HDMI_DDC_TRANS0);
699 writel(BIT(0) | BIT(12) | BIT(13) | (len << 16), HDMI_DDC_TRANS1);
700 writel(BIT(0) | BIT(20), HDMI_DDC_CTRL);
701
702 /* poll for 100ms for read to complete */
703 reg_val = readl(HDMI_DDC_INT_CTRL);
704 while (!(reg_val & BIT(0)) && time_out) {
705 reg_val = readl(HDMI_DDC_INT_CTRL);
706 time_out--;
707 mdelay(10);
708 }
709
710 if (!time_out) {
711 dprintf(CRITICAL, "%s: Timeout reading EDID\n", __func__);
712 if (retry--)
713 goto again;
714 else
715 return ERROR;
716 }
717
718 /* clear interrupts */
719 writel(BIT(1), HDMI_DDC_INT_CTRL);
720
721 reg_val = readl(HDMI_DDC_SW_STATUS);
722 reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
723
724 /* Check if any NACK occurred */
725 if (reg_val) {
726 /* SW_STATUS_RESET */
727 writel(BIT(3), HDMI_DDC_CTRL);
728
729 /* SOFT_RESET */
730 writel(BIT(1), HDMI_DDC_CTRL);
731
732 dprintf(CRITICAL, "%s: NACK reading EDID\n", __func__);
733
734 if (retry--)
735 goto again;
736 else
737 return ERROR;
738 }
739
740 /* Write this data to DDC buffer */
741 writel(BIT(0) | (3 << 16) | BIT(31), HDMI_DDC_DATA);
742
743 /* Discard first byte */
744 readl(HDMI_DDC_DATA);
745
746 for (ndx = 0; ndx < 0x80; ndx++) {
747 reg_val = readl(HDMI_DDC_DATA);
748 mdss_hdmi_edid_buf[ndx] = (uint8_t)((reg_val & 0x0000FF00) >> 8);
749 }
750
751 dprintf(INFO, "%s: EDID read successful\n", __func__);
752
753 return NO_ERROR;
754}
755
756static void mdss_hdmi_parse_res(void)
757{
758 uint8_t len, i;
759 uint32_t video_format;
760 struct mdss_hdmi_timing_info tinfo_fmt = {0};
761
762 uint8_t *svd = hdmi_edid_find_block(DBC_START_OFFSET,
763 VIDEO_DATA_BLOCK, &len);
764
765 mdss_hdmi_video_fmt = HDMI_VFRMT_UNKNOWN;
766
767 if (!svd) {
768 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800769 return;
Casey Piper97d25272015-03-17 15:10:34 -0700770 }
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800771
Casey Piper97d25272015-03-17 15:10:34 -0700772 ++svd;
773
774 for (i = 0; i < len; ++i, ++svd) {
775 struct mdss_hdmi_timing_info tinfo = {0};
776 uint32_t ret = 0;
777
778 video_format = (*svd & 0x7F);
779
780 if (i == 0)
781 mdss_hdmi_pref_fmt = video_format;
782
783 ret = mdss_hdmi_get_timing_info(&tinfo, video_format);
784
785 if (ret || !tinfo.supported)
786 continue;
787
788 if (!tinfo_fmt.video_format) {
789 memcpy(&tinfo_fmt, &tinfo, sizeof(tinfo));
790 mdss_hdmi_video_fmt = video_format;
791 continue;
792 }
793
794 if (tinfo.active_v > tinfo_fmt.active_v) {
795 memcpy(&tinfo_fmt, &tinfo, sizeof(tinfo));
796 mdss_hdmi_video_fmt = video_format;
797 }
798 }
799
800 if (mdss_hdmi_video_fmt == HDMI_VFRMT_UNKNOWN)
801 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800802}
803
Casey Piper6c2f1132015-03-24 11:37:19 -0700804void mdss_hdmi_get_vic(char *buf)
805{
806 struct mdss_hdmi_timing_info tinfo = {0};
807 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
808
809 if (ret)
810 snprintf(buf, HDMI_VIC_STR_MAX, "%d", HDMI_VFRMT_UNKNOWN);
811 else
812 snprintf(buf, HDMI_VIC_STR_MAX, "%d", tinfo.video_format);
813
814}
815
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700816static void mdss_hdmi_panel_init(struct msm_panel_info *pinfo)
817{
Casey Piper97d25272015-03-17 15:10:34 -0700818 struct mdss_hdmi_timing_info tinfo = {0};
819 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700820
Casey Piper97d25272015-03-17 15:10:34 -0700821 if (!pinfo || ret)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700822 return;
823
824 pinfo->xres = tinfo.active_h;
825 pinfo->yres = tinfo.active_v;
826 pinfo->bpp = 24;
827 pinfo->type = HDMI_PANEL;
Casey Piper97d25272015-03-17 15:10:34 -0700828 pinfo->clk_rate = tinfo.pixel_freq * 1000;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700829
Casey Piper97d25272015-03-17 15:10:34 -0700830 pinfo->lcdc.h_back_porch = tinfo.back_porch_h;
831 pinfo->lcdc.h_front_porch = tinfo.front_porch_h;
832 pinfo->lcdc.h_pulse_width = tinfo.pulse_width_h;
833 pinfo->lcdc.v_back_porch = tinfo.back_porch_v;
834 pinfo->lcdc.v_front_porch = tinfo.front_porch_v;
835 pinfo->lcdc.v_pulse_width = tinfo.pulse_width_v;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700836
Casey Piper97d25272015-03-17 15:10:34 -0700837 pinfo->lcdc.hsync_skew = 0;
838 pinfo->lcdc.xres_pad = 0;
839 pinfo->lcdc.yres_pad = 0;
840 pinfo->lcdc.dual_pipe = 0;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700841}
842
Casey Piper7ab92992015-03-18 14:19:23 -0700843static uint8_t mdss_hdmi_cable_status(void)
844{
845 uint32_t reg_val;
846 uint8_t cable_status;
847
848 mdss_hdmi_set_mode(true);
849
850 /* Enable USEC REF timer */
851 writel(0x0001001B, HDMI_USEC_REFTIMER);
852
853 /* set timeout to 4.1ms (max) for hardware debounce */
854 reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
855
856 /* enable HPD circuit */
857 writel(reg_val | BIT(28), HDMI_HPD_CTRL);
858
859 writel(BIT(2) | BIT(1), HDMI_HPD_INT_CTRL);
860
861 /* Toggle HPD circuit to trigger HPD sense */
862 reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
863 writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
864 writel(reg_val & BIT(28), HDMI_HPD_CTRL);
865
866 mdelay(20);
867
868 cable_status = (readl(HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
869
870 dprintf(INFO, "hdmi cable %s\n",
871 cable_status ? "connected" : "not connected");
872
873 writel(BIT(0), HDMI_HPD_INT_CTRL);
874 writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
875
876 mdss_hdmi_set_mode(false);
877
878 return cable_status;
879}
880
Casey Piper6c2f1132015-03-24 11:37:19 -0700881static int mdss_hdmi_update_panel_info(void)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700882{
Casey Piper6c2f1132015-03-24 11:37:19 -0700883 mdss_hdmi_set_mode(true);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700884
Casey Piper6c2f1132015-03-24 11:37:19 -0700885 if (!mdss_hdmi_read_edid())
886 mdss_hdmi_parse_res();
887 else
888 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
889
890 mdss_hdmi_set_mode(false);
891
892 mdss_hdmi_panel_init(&(panel.panel_info));
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700893
894 panel.fb.width = panel.panel_info.xres;
895 panel.fb.height = panel.panel_info.yres;
896 panel.fb.stride = panel.panel_info.xres;
897 panel.fb.bpp = panel.panel_info.bpp;
898 panel.fb.format = FB_FORMAT_RGB888;
899
Casey Piper6c2f1132015-03-24 11:37:19 -0700900 return NO_ERROR;
901}
902
903void mdss_hdmi_display_init(uint32_t rev, void *base)
904{
905 panel.power_func = mdss_hdmi_enable_power;
906 panel.clk_func = mdss_hdmi_panel_clock;
907 panel.update_panel_info = mdss_hdmi_update_panel_info;
908 panel.pll_clk_func = mdss_hdmi_pll_clock;
909
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700910 panel.fb.base = base;
911 panel.mdp_rev = rev;
912
913 msm_display_init(&panel);
914}
915
916static int mdss_hdmi_video_setup(void)
917{
918 uint32_t total_v = 0;
919 uint32_t total_h = 0;
920 uint32_t start_h = 0;
921 uint32_t end_h = 0;
922 uint32_t start_v = 0;
923 uint32_t end_v = 0;
924
Casey Piper97d25272015-03-17 15:10:34 -0700925 struct mdss_hdmi_timing_info tinfo = {0};
926 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
927
928 if (ret)
929 return ERROR;
930
931 dprintf(INFO, "hdmi resolution %dx%d@p%dHz (%d)\n",
932 tinfo.active_h, tinfo.active_v, tinfo.refresh_rate/1000,
933 mdss_hdmi_video_fmt);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700934
935 total_h = tinfo.active_h + tinfo.front_porch_h +
936 tinfo.back_porch_h + tinfo.pulse_width_h - 1;
937 total_v = tinfo.active_v + tinfo.front_porch_v +
938 tinfo.back_porch_v + tinfo.pulse_width_v - 1;
939 if (((total_v << 16) & 0xE0000000) || (total_h & 0xFFFFE000)) {
940 dprintf(CRITICAL,
941 "%s: total v=%d or h=%d is larger than supported\n",
942 __func__, total_v, total_h);
943 return ERROR;
944 }
945 writel((total_v << 16) | (total_h << 0), HDMI_TOTAL);
946
947 start_h = tinfo.back_porch_h + tinfo.pulse_width_h;
948 end_h = (total_h + 1) - tinfo.front_porch_h;
949 if (((end_h << 16) & 0xE0000000) || (start_h & 0xFFFFE000)) {
950 dprintf(CRITICAL,
951 "%s: end_h=%d or start_h=%d is larger than supported\n",
952 __func__, end_h, start_h);
953 return ERROR;
954 }
955 writel((end_h << 16) | (start_h << 0), HDMI_ACTIVE_H);
956
957 start_v = tinfo.back_porch_v + tinfo.pulse_width_v - 1;
958 end_v = total_v - tinfo.front_porch_v;
959 if (((end_v << 16) & 0xE0000000) || (start_v & 0xFFFFE000)) {
960 dprintf(CRITICAL,
961 "%s: end_v=%d or start_v=%d is larger than supported\n",
962 __func__, end_v, start_v);
963 return ERROR;
964 }
965 writel((end_v << 16) | (start_v << 0), HDMI_ACTIVE_V);
966
967 if (tinfo.interlaced) {
968 writel((total_v + 1) << 0, HDMI_V_TOTAL_F2);
969 writel(((end_v + 1) << 16) | ((start_v + 1) << 0),
970 HDMI_ACTIVE_V_F2);
971 } else {
972 writel(0, HDMI_V_TOTAL_F2);
973 writel(0, HDMI_ACTIVE_V_F2);
974 }
975
976 writel(((tinfo.interlaced << 31) & 0x80000000) |
977 ((tinfo.active_low_h << 29) & 0x20000000) |
978 ((tinfo.active_low_v << 28) & 0x10000000), HDMI_FRAME_CTRL);
979
980 return 0;
981}
982
Casey Piper97d25272015-03-17 15:10:34 -0700983static void mdss_hdmi_extract_extended_data_blocks(void)
984{
985 uint8_t len = 0;
986 uint32_t start_offset = DBC_START_OFFSET;
987 uint8_t const *etag = NULL;
988 uint8_t *in_buf = mdss_hdmi_edid_buf;
989
990 do {
991 /* A Tage code of 7 identifies extended data blocks */
992 etag = hdmi_edid_find_block(start_offset,
993 USE_EXTENDED_TAG, &len);
994
995 start_offset = etag - in_buf + len + 1;
996
997 /* The extended data block should at least be 2 bytes long */
998 if (len < 2) {
999 dprintf(SPEW, "%s: data block of len < 2 bytes\n",
1000 __func__);
1001 continue;
1002 }
1003
1004 /*
1005 * The second byte of the extended data block has the
1006 * extended tag code
1007 */
1008 switch (etag[1]) {
1009 case 0:
1010 /*
1011 * Check if the sink specifies underscan
1012 * support for:
1013 * BIT 5: preferred video format
1014 * BIT 3: IT video format
1015 * BIT 1: CE video format
1016 */
1017 pt_scan_info = (etag[2] & (BIT(4) | BIT(5))) >> 4;
1018 it_scan_info = (etag[2] & (BIT(3) | BIT(2))) >> 2;
1019 ce_scan_info = etag[2] & (BIT(1) | BIT(0));
1020
1021 dprintf(INFO, "scan Info (pt|it|ce): (%d|%d|%d)\n",
1022 pt_scan_info, it_scan_info, ce_scan_info);
1023 break;
1024 default:
1025 dprintf(SPEW, "%s: Tag Code %d not supported\n",
1026 __func__, etag[1]);
1027 break;
1028 }
1029 } while (etag != NULL);
1030}
1031
1032/*
1033 * If the sink specified support for both underscan/overscan then, by default,
1034 * set the underscan bit. Only checking underscan support for preferred
1035 * format and cea formats.
1036 */
1037uint8_t mdss_hdmi_get_scan_info(void)
1038{
1039 uint8_t scaninfo = 0;
1040 bool use_ce_scan_info = true;
1041
1042 mdss_hdmi_extract_extended_data_blocks();
1043
1044 if (mdss_hdmi_video_fmt == mdss_hdmi_pref_fmt) {
1045 use_ce_scan_info = false;
1046
1047 switch (pt_scan_info) {
1048 case 0:
1049 use_ce_scan_info = true;
1050 break;
1051 case 3:
1052 scaninfo = BIT(1);
1053 break;
1054 default:
1055 break;
1056 }
1057 }
1058
1059 if (use_ce_scan_info) {
1060 if (3 == ce_scan_info)
1061 scaninfo |= BIT(1);
1062 }
1063
1064 return scaninfo;
1065}
1066
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001067void mdss_hdmi_avi_info_frame(void)
1068{
1069 uint32_t sum;
1070 uint32_t reg_val;
1071 uint8_t checksum;
Casey Piper97d25272015-03-17 15:10:34 -07001072 uint8_t scaninfo;
1073 uint32_t i, index;
1074
1075 scaninfo = mdss_hdmi_get_scan_info();
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001076
1077 sum = IFRAME_PACKET_OFFSET + AVI_IFRAME_TYPE +
1078 AVI_IFRAME_VERSION + AVI_MAX_DATA_BYTES;
1079
Casey Piper97d25272015-03-17 15:10:34 -07001080 for (index = 0; index < HDMI_VFRMT_MAX; index++) {
1081 if (mdss_hdmi_avi_info_db[index][VIC_INDEX] == mdss_hdmi_video_fmt)
1082 break;
1083 }
1084
1085 if (index == VIC_INDEX)
1086 return;
1087
1088 mdss_hdmi_avi_info_db[index][DATA_BYTE_1] |=
1089 scaninfo & (BIT(1) | BIT(0));
1090
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001091 for (i = 0; i < AVI_MAX_DATA_BYTES; i++)
Casey Piper97d25272015-03-17 15:10:34 -07001092 sum += mdss_hdmi_avi_info_db[index][i];
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001093
1094 sum &= 0xFF;
1095 sum = 256 - sum;
1096 checksum = (uint8_t) sum;
1097
1098 reg_val = checksum |
Casey Piper97d25272015-03-17 15:10:34 -07001099 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_1]) |
1100 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[index][DATA_BYTE_2]) |
1101 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[index][DATA_BYTE_3]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001102 writel(reg_val, HDMI_AVI_INFO0);
1103
Casey Piper97d25272015-03-17 15:10:34 -07001104 reg_val = mdss_hdmi_avi_info_db[index][DATA_BYTE_4] |
1105 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_5]) |
1106 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[index][DATA_BYTE_6]) |
1107 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[index][DATA_BYTE_7]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001108 writel(reg_val, HDMI_AVI_INFO1);
1109
Casey Piper97d25272015-03-17 15:10:34 -07001110 reg_val = mdss_hdmi_avi_info_db[index][DATA_BYTE_8] |
1111 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_9]) |
1112 LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[index][DATA_BYTE_10]) |
1113 LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[index][DATA_BYTE_11]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001114 writel(reg_val, HDMI_AVI_INFO2);
1115
Casey Piper97d25272015-03-17 15:10:34 -07001116 reg_val = mdss_hdmi_avi_info_db[index][DATA_BYTE_12] |
1117 LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_13]) |
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001118 LEFT_SHIFT_24BITS(AVI_IFRAME_VERSION);
1119 writel(reg_val, HDMI_AVI_INFO3);
1120
1121 /* AVI InfFrame enable (every frame) */
1122 writel(readl(HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0),
1123 HDMI_INFOFRAME_CTRL0);
1124}
1125
1126int mdss_hdmi_init(void)
1127{
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001128 bool is_dvi_mode = mdss_hdmi_is_dvi_mode();
1129
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001130 mdss_hdmi_set_mode(false);
1131
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001132 /* Audio settings */
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001133 if (!is_dvi_mode)
1134 mdss_hdmi_audio_playback();
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001135
1136 /* Video settings */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001137 mdss_hdmi_video_setup();
1138
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001139 /* AVI info settings */
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001140 if (!is_dvi_mode)
1141 mdss_hdmi_avi_info_frame();
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001142
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001143 /* Enable HDMI */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001144 mdss_hdmi_set_mode(true);
1145
1146 return 0;
1147}