blob: 2b37ce434d2a674a3ae06b025764b2dc00e3f041 [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
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -0800140#define AVI_IFRAME_LINE_NUMBER 1
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700141#define LEFT_SHIFT_BYTE(x) ((x) << 8)
142#define LEFT_SHIFT_WORD(x) ((x) << 16)
143#define LEFT_SHIFT_24BITS(x) ((x) << 24)
144
Casey Piper1d3611d2015-03-17 15:45:44 -0700145#define MAX_AUDIO_DATA_BLOCK_SIZE 0x80
Casey Piper97d25272015-03-17 15:10:34 -0700146#define DBC_START_OFFSET 4
147#define VIC_INDEX 3
148#define HDMI_VIC_STR_MAX 3
149
150enum edid_data_block_type {
151 RESERVED_DATA_BLOCK1 = 0,
152 AUDIO_DATA_BLOCK,
153 VIDEO_DATA_BLOCK,
154 VENDOR_SPECIFIC_DATA_BLOCK,
155 SPEAKER_ALLOCATION_DATA_BLOCK,
156 VESA_DTC_DATA_BLOCK,
157 RESERVED_DATA_BLOCK2,
158 USE_EXTENDED_TAG
159};
160
161/* video formats defined by CEA 861D */
162#define HDMI_VFRMT_UNKNOWN 0
163#define HDMI_VFRMT_640x480p60_4_3 1
164#define HDMI_VFRMT_1280x720p60_16_9 4
165#define HDMI_VFRMT_1920x1080p60_16_9 16
166#define HDMI_VFRMT_MAX 3
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -0800167#define HDMI_VFRMT_END 127
Casey Piper97d25272015-03-17 15:10:34 -0700168
169#define DEFAULT_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9
170static uint8_t mdss_hdmi_video_fmt = HDMI_VFRMT_UNKNOWN;
171static uint8_t mdss_hdmi_pref_fmt = HDMI_VFRMT_UNKNOWN;
172static uint8_t pt_scan_info;
173static uint8_t it_scan_info;
174static uint8_t ce_scan_info;
175
176static uint8_t mdss_hdmi_edid_buf[0x80];
177
178enum aspect_ratio {
179 HDMI_RES_AR_INVALID,
180 HDMI_RES_AR_4_3,
181 HDMI_RES_AR_5_4,
182 HDMI_RES_AR_16_9,
183 HDMI_RES_AR_16_10,
184 HDMI_RES_AR_MAX,
185};
186
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -0800187enum hdmi_quantization_range {
188 HDMI_QUANTIZATION_DEFAULT,
189 HDMI_QUANTIZATION_LIMITED_RANGE,
190 HDMI_QUANTIZATION_FULL_RANGE
191};
192
193enum hdmi_scaling_info {
194 HDMI_SCALING_NONE,
195 HDMI_SCALING_HORZ,
196 HDMI_SCALING_VERT,
197 HDMI_SCALING_HORZ_VERT,
198};
199
200struct hdmi_avi_iframe_bar_info {
201 bool vert_binfo_present;
202 bool horz_binfo_present;
203 uint32_t end_of_top_bar;
204 uint32_t start_of_bottom_bar;
205 uint32_t end_of_left_bar;
206 uint32_t start_of_right_bar;
207};
208
209struct hdmi_avi_infoframe_config {
210 uint32_t pixel_format;
211 uint32_t scan_info;
212 bool act_fmt_info_present;
213 uint32_t colorimetry_info;
214 uint32_t ext_colorimetry_info;
215 uint32_t rgb_quantization_range;
216 uint32_t yuv_quantization_range;
217 uint32_t scaling_info;
218 bool is_it_content;
219 uint8_t content_type;
220 uint8_t pixel_rpt_factor;
221 struct hdmi_avi_iframe_bar_info bar_info;
222};
223
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700224struct mdss_hdmi_timing_info {
225 uint32_t video_format;
226 uint32_t active_h;
227 uint32_t front_porch_h;
228 uint32_t pulse_width_h;
229 uint32_t back_porch_h;
230 uint32_t active_low_h;
231 uint32_t active_v;
232 uint32_t front_porch_v;
233 uint32_t pulse_width_v;
234 uint32_t back_porch_v;
235 uint32_t active_low_v;
236 /* Must divide by 1000 to get the actual frequency in MHZ */
237 uint32_t pixel_freq;
238 /* Must divide by 1000 to get the actual frequency in HZ */
239 uint32_t refresh_rate;
240 uint32_t interlaced;
241 uint32_t supported;
Casey Piper97d25272015-03-17 15:10:34 -0700242 enum aspect_ratio ar;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700243};
244
Casey Piper97d25272015-03-17 15:10:34 -0700245#define HDMI_VFRMT_640x480p60_4_3_TIMING \
246 {HDMI_VFRMT_640x480p60_4_3, 640, 16, 96, 48, true, \
247 480, 10, 2, 33, true, 25200, 60000, false, true, HDMI_RES_AR_4_3}
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800248
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700249#define HDMI_VFRMT_1280x720p60_16_9_TIMING \
250 {HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, false, \
Casey Piper97d25272015-03-17 15:10:34 -0700251 720, 5, 5, 20, false, 74250, 60000, false, true, HDMI_RES_AR_16_9}
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700252
Casey Piper97d25272015-03-17 15:10:34 -0700253#define HDMI_VFRMT_1920x1080p60_16_9_TIMING \
254 {HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, false, \
255 1080, 4, 5, 36, false, 148500, 60000, false, true, HDMI_RES_AR_16_9}
256
257#define MSM_HDMI_MODES_GET_DETAILS(mode, MODE) do { \
258 struct mdss_hdmi_timing_info info = MODE##_TIMING; \
259 *mode = info; \
260 } while (0)
261
262static inline int mdss_hdmi_get_timing_info(
263 struct mdss_hdmi_timing_info *mode, int id)
264{
265 int ret = 0;
266
267 switch (id) {
268 case HDMI_VFRMT_640x480p60_4_3:
269 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_640x480p60_4_3);
270 break;
271
272 case HDMI_VFRMT_1280x720p60_16_9:
273 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_1280x720p60_16_9);
274 break;
275
276 case HDMI_VFRMT_1920x1080p60_16_9:
277 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_1920x1080p60_16_9);
278 break;
279
280 default:
281 ret = ERROR;
282 }
283
284 return ret;
285}
286
Casey Piper1d3611d2015-03-17 15:45:44 -0700287static void mdss_hdmi_audio_acr_setup(uint32_t sample_rate)
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700288{
Casey Piper1d3611d2015-03-17 15:45:44 -0700289 /* Read first before writing */
290 uint32_t acr_pck_ctrl_reg = readl(HDMI_ACR_PKT_CTRL);
291 struct mdss_hdmi_timing_info tinfo = {0};
292 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
293 struct hdmi_msm_audio_arcs *audio_acr = &hdmi_audio_acr_lut[0];
294 uint32_t lut_size = sizeof(hdmi_audio_acr_lut)
295 / sizeof(*hdmi_audio_acr_lut);
296 uint32_t i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
297 uint32_t channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700298
Casey Piper1d3611d2015-03-17 15:45:44 -0700299 if (ret || !tinfo.supported) {
300 dprintf(CRITICAL, "%s: video format %d not supported\n",
301 __func__, mdss_hdmi_video_fmt);
302 return;
303 }
304
305 for (i = 0; i < lut_size; audio_acr = &hdmi_audio_acr_lut[++i]) {
306 if (audio_acr->pclk == tinfo.pixel_freq)
307 break;
308 }
309
310 if (i >= lut_size) {
311 dprintf(CRITICAL, "%s: pixel clk %d not supported\n", __func__,
312 tinfo.pixel_freq);
313 return;
314 }
315
316 n = audio_acr->lut[sample_rate].n;
317 cts = audio_acr->lut[sample_rate].cts;
318 layout = (MSM_HDMI_AUDIO_CHANNEL_2 == channel_num) ? 0 : 1;
319
320 if ((AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
321 (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
322 multiplier = 4;
323 n >>= 2; /* divide N by 4 and use multiplier */
324 } else if ((AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
325 (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
326 multiplier = 2;
327 n >>= 1; /* divide N by 2 and use multiplier */
328 } else {
329 multiplier = 1;
330 }
331
332 dprintf(SPEW, "%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
333 layout);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700334
335 /* AUDIO_PRIORITY | SOURCE */
336 acr_pck_ctrl_reg |= 0x80000100;
337
Casey Piper1d3611d2015-03-17 15:45:44 -0700338 /* Reset multiplier bits */
339 acr_pck_ctrl_reg &= ~(7 << 16);
340
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700341 /* N_MULTIPLE(multiplier) */
342 acr_pck_ctrl_reg |= (multiplier & 7) << 16;
343
Casey Piper1d3611d2015-03-17 15:45:44 -0700344 if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
345 (AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
346 (AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
347 /* SELECT(3) */
348 acr_pck_ctrl_reg |= 3 << 4;
349 /* CTS_48 */
350 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700351
Casey Piper1d3611d2015-03-17 15:45:44 -0700352 /* CTS: need to determine how many fractional bits */
353 writel(cts, HDMI_ACR_48_0);
354 /* N */
355 writel(n, HDMI_ACR_48_1);
356 } else if ((AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
357 (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
358 (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
359 /* SELECT(2) */
360 acr_pck_ctrl_reg |= 2 << 4;
361 /* CTS_44 */
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_44_0);
366 /* N */
367 writel(n, HDMI_ACR_44_1);
368 } else { /* default to 32k */
369 /* SELECT(1) */
370 acr_pck_ctrl_reg |= 1 << 4;
371 /* CTS_32 */
372 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700373
Casey Piper1d3611d2015-03-17 15:45:44 -0700374 /* CTS: need to determine how many fractional bits */
375 writel(cts, HDMI_ACR_32_0);
376 /* N */
377 writel(n, HDMI_ACR_32_1);
378 }
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700379
380 /* Payload layout depends on number of audio channels */
Casey Piper1d3611d2015-03-17 15:45:44 -0700381 /* LAYOUT_SEL(layout) */
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700382 aud_pck_ctrl_2_reg = 1 | (layout << 1);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700383 /* override | layout */
384 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
385
386 /* SEND | CONT */
Casey Piper1d3611d2015-03-17 15:45:44 -0700387 acr_pck_ctrl_reg |= 0x00000003;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700388
389 writel(acr_pck_ctrl_reg, HDMI_ACR_PKT_CTRL);
390}
391
Casey Piper1d3611d2015-03-17 15:45:44 -0700392static void mdss_hdmi_audio_info_setup(void)
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700393{
Casey Piper1d3611d2015-03-17 15:45:44 -0700394 uint32_t channel_count = MSM_HDMI_AUDIO_CHANNEL_2;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700395 uint32_t channel_allocation = 0;
396 uint32_t level_shift = 0;
397 uint32_t down_mix = 0;
398 uint32_t check_sum, audio_info_0_reg, audio_info_1_reg;
399 uint32_t audio_info_ctrl_reg;
400 uint32_t aud_pck_ctrl_2_reg;
401 uint32_t layout;
402
Casey Piper1d3611d2015-03-17 15:45:44 -0700403 layout = (MSM_HDMI_AUDIO_CHANNEL_2 == channel_count) ? 0 : 1;;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700404 aud_pck_ctrl_2_reg = 1 | (layout << 1);
405 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
406
407 /* Read first then write because it is bundled with other controls */
408 audio_info_ctrl_reg = readl(HDMI_INFOFRAME_CTRL0);
409
410 channel_allocation = 0; /* Default to FR,FL */
411
412 /* Program the Channel-Speaker allocation */
413 audio_info_1_reg = 0;
414
415 /* CA(channel_allocation) */
416 audio_info_1_reg |= channel_allocation & 0xff;
417
418 /* Program the Level shifter */
419 /* LSV(level_shift) */
420 audio_info_1_reg |= (level_shift << 11) & 0x00007800;
421
422 /* Program the Down-mix Inhibit Flag */
423 /* DM_INH(down_mix) */
424 audio_info_1_reg |= (down_mix << 15) & 0x00008000;
425
426 writel(audio_info_1_reg, HDMI_AUDIO_INFO1);
427
428 check_sum = 0;
429 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
430 check_sum += 0x84;
431 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
432 check_sum += 1;
433 /* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
434 check_sum += 0x0A;
435 check_sum += channel_count;
436 check_sum += channel_allocation;
437 /* See Table 8.5 in HDMI spec */
438 check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
439 check_sum &= 0xFF;
440 check_sum = (256 - check_sum);
441
442 audio_info_0_reg = 0;
443 /* CHECKSUM(check_sum) */
444 audio_info_0_reg |= check_sum & 0xff;
445 /* CC(channel_count) */
446 audio_info_0_reg |= (channel_count << 8) & 0x00000700;
447
448 writel(audio_info_0_reg, HDMI_AUDIO_INFO0);
449
450 /* Set these flags */
451 /* AUDIO_INFO_UPDATE | AUDIO_INFO_SOURCE | AUDIO_INFO_CONT
452 | AUDIO_INFO_SEND */
453 audio_info_ctrl_reg |= 0xF0;
454
455 /* HDMI_INFOFRAME_CTRL0[0x002C] */
456 writel(audio_info_ctrl_reg, HDMI_INFOFRAME_CTRL0);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700457}
458
Casey Piper97d25272015-03-17 15:10:34 -0700459static uint8_t* hdmi_edid_find_block(uint32_t start_offset,
460 uint8_t type, uint8_t *len)
461{
462 /* the start of data block collection, start of Video Data Block */
463 uint8_t *in_buf = mdss_hdmi_edid_buf;
464 uint32_t offset = start_offset;
465 uint32_t end_dbc_offset = in_buf[2];
466
467 *len = 0;
468
469 /*
470 * edid buffer 1, byte 2 being 4 means no non-DTD/Data block collection
471 * present.
472 * edid buffer 1, byte 2 being 0 means no non-DTD/DATA block collection
473 * present and no DTD data present.
474 */
475 if ((end_dbc_offset == 0) || (end_dbc_offset == 4))
476 return NULL;
477
478 while (offset < end_dbc_offset) {
479 uint8_t block_len = in_buf[offset] & 0x1F;
480 if ((in_buf[offset] >> 5) == type) {
481 *len = block_len;
482 dprintf(SPEW,
483 "EDID: block=%d found @ %d with length=%d\n",
484 type, offset, block_len);
485 return in_buf + offset;
486 }
487 offset += 1 + block_len;
488 }
489
490 return NULL;
491}
492
Casey Piper1d3611d2015-03-17 15:45:44 -0700493static bool mdss_hdmi_is_audio_freq_supported(uint32_t freq)
494{
495 uint8_t *in_buf = mdss_hdmi_edid_buf;
496 const uint8_t *adb = NULL;
497 uint32_t adb_size = 0;
498 uint8_t len = 0, count = 0;
499 uint32_t next_offset = DBC_START_OFFSET;
500 uint8_t audio_data_block[MAX_AUDIO_DATA_BLOCK_SIZE];
501
502 do {
503 adb = hdmi_edid_find_block(next_offset,
504 AUDIO_DATA_BLOCK, &len);
505
506 if ((adb_size + len) > MAX_AUDIO_DATA_BLOCK_SIZE) {
507 dprintf(INFO, "%s: invalid adb length\n", __func__);
508 break;
509 }
510
511 if (!adb)
512 break;
513
514 memcpy((audio_data_block + adb_size), adb + 1, len);
515 next_offset = (adb - in_buf) + 1 + len;
516
517 adb_size += len;
518
519 } while (adb);
520
521 count = adb_size/3;
522 adb = audio_data_block;
523
524 while (count--) {
525 uint8_t freq_lst = *(adb + 1) & 0xFF;
526
527 if (freq_lst & BIT(freq))
528 return true;
529
530 adb += 3;
531 }
532
533 return false;
534}
535
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700536static void mdss_hdmi_audio_playback(void)
537{
Casey Piper77f69c52015-03-20 15:55:12 -0700538 char *base_addr;
Casey Piper1d3611d2015-03-17 15:45:44 -0700539 uint32_t sample_rate;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700540
Casey Piper77f69c52015-03-20 15:55:12 -0700541 base_addr = (char *) memalign(4096, 0x1000);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700542 if (base_addr == NULL) {
543 dprintf(CRITICAL, "%s: Error audio buffer alloc\n", __func__);
544 return;
545 }
546
547 memset(base_addr, 0, 0x1000);
548
549 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
550 writel(0x00000080, HDMI_AUDIO_CFG);
551
552 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
553 writel(0x00000A6E, LPASS_LPAIF_RDDMA_CTL0);
554 writel(0x00002000, HDMI_VBI_PKT_CTRL);
555 writel(0x00000000, HDMI_GEN_PKT_CTRL);
556 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
Casey Piper77f69c52015-03-20 15:55:12 -0700557 writel((uint32_t) base_addr, LPASS_LPAIF_RDDMA_BASE0);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700558 writel(0x000005FF, LPASS_LPAIF_RDDMA_BUFF_LEN0);
559 writel(0x000005FF, LPASS_LPAIF_RDDMA_PER_LEN0);
560 writel(0x0000096F, LPASS_LPAIF_RDDMA_CTL0);
561 writel(0x00000010, LPASS_LPAIF_DEBUG_CTL);
562 writel(0x00000000, HDMI_GC);
563 writel(0x00002030, HDMI_VBI_PKT_CTRL);
564 writel(0x00002030, HDMI_VBI_PKT_CTRL);
565 writel(0x00002030, HDMI_VBI_PKT_CTRL);
566
Casey Piper1d3611d2015-03-17 15:45:44 -0700567 if (mdss_hdmi_is_audio_freq_supported(AUDIO_SAMPLE_RATE_48KHZ))
568 sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
569 else
570 sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
571
572 mdss_hdmi_audio_acr_setup(sample_rate);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700573 mdss_hdmi_audio_info_setup();
574
575 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
576 writel(0x00000080, HDMI_AUDIO_CFG);
577 writel(0x00000011, HDMI_AUDIO_PKT_CTRL);
578 writel(0x00000081, HDMI_AUDIO_CFG);
Casey Piper1d3611d2015-03-17 15:45:44 -0700579
580 dprintf(SPEW, "audio sample rate %s\n",
581 sample_rate == AUDIO_SAMPLE_RATE_48KHZ ? "48KHz" : "32KHz");
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700582}
583
Casey Piper77f69c52015-03-20 15:55:12 -0700584static uint32_t mdss_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700585{
Casey Piper7ab92992015-03-18 14:19:23 -0700586 int ret = NO_ERROR;
587 if (hdmi_panel_clock_enabled)
588 return ret;
589
590 ret = target_hdmi_panel_clock(enable, pinfo);
591
592 hdmi_panel_clock_enabled = enable;
593
594 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700595}
596
Casey Piper6c2f1132015-03-24 11:37:19 -0700597static uint32_t mdss_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo)
598{
Casey Piper7ab92992015-03-18 14:19:23 -0700599 int ret = NO_ERROR;
600
601 if (hdmi_pll_clock_enabled)
602 return ret;
603
604 ret = target_hdmi_pll_clock(enable, pinfo);
605
606 hdmi_pll_clock_enabled = enable;
607
608 return ret;
Casey Piper6c2f1132015-03-24 11:37:19 -0700609}
610
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700611static int mdss_hdmi_enable_power(uint8_t enable, struct msm_panel_info *pinfo)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700612{
Casey Piper7ab92992015-03-18 14:19:23 -0700613 int ret = NO_ERROR;
614
615 if (hdmi_power_enabled)
616 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700617
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700618 ret = target_hdmi_regulator_ctrl(enable);
619 if (ret) {
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700620 dprintf(CRITICAL, "hdmi regulator control enable failed\n");
621 goto bail_regulator_fail;
Casey Piper7ab92992015-03-18 14:19:23 -0700622 }
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700623
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700624 ret = target_hdmi_gpio_ctrl(enable);
625 if (ret) {
626 dprintf(CRITICAL, "hdmi gpio control enable failed\n");
627 goto bail_gpio_fail;
Casey Piper7ab92992015-03-18 14:19:23 -0700628 }
629
630 hdmi_power_enabled = enable;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700631
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700632 dprintf(SPEW, "HDMI Panel power %s done\n", enable ? "on" : "off");
633
634 return ret;
635
636bail_gpio_fail:
637 target_hdmi_regulator_ctrl(0);
638
639bail_regulator_fail:
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700640 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700641}
642
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800643static bool mdss_hdmi_is_dvi_mode(void)
644{
645 uint8_t len;
646 uint32_t ieee_tag;
647 const uint8_t *vsd = NULL;
648
649 vsd = hdmi_edid_find_block(DBC_START_OFFSET,
650 VENDOR_SPECIFIC_DATA_BLOCK, &len);
651
652 if (vsd == NULL || len == 0) {
653 dprintf(SPEW, "%s: Invalid VSDB\n", __func__);
654 return false;
655 }
656
657 ieee_tag = ((uint32_t) vsd[3] << 16) + ((uint32_t) vsd[2] << 8) +
658 (uint32_t) vsd[1];
659
660 if (ieee_tag == 0x0c03)
661 return false;
662 else
663 return true;
664}
665
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700666static void mdss_hdmi_set_mode(bool on)
667{
668 uint32_t val = 0;
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800669 if (on) {
670 /* tx on */
Tatenda Chipeperekwab12d7db2015-12-04 15:39:10 -0800671 val |= BIT(0);
672 /* hdcp legacy mode*/
673 val |= BIT(31);
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800674
675 if (!mdss_hdmi_is_dvi_mode())
Tatenda Chipeperekwab12d7db2015-12-04 15:39:10 -0800676 val |= BIT(1);
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800677 }
Casey Piper6c2f1132015-03-24 11:37:19 -0700678
679 writel(val, HDMI_CTRL);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700680}
681
Casey Piper97d25272015-03-17 15:10:34 -0700682
683static int mdss_hdmi_read_edid(void)
684{
685 uint8_t ndx;
686 uint32_t reg_val;
687 uint32_t dev_addr = 0xA0;
688 uint32_t len = 0x80;
689 uint32_t offset = 0x80;
690 uint32_t time_out;
691 uint32_t retry = 5;
692
693 dev_addr &= 0xFE;
694
695again:
696 time_out = 10;
697 writel(readl(HDMI_DDC_ARBITRATION) & ~BIT(4), HDMI_DDC_ARBITRATION);
698
699 /* Enable DDC Interrupts */
700 writel(BIT(1) | BIT(2), HDMI_DDC_INT_CTRL);
701
702 /* config DDC to read CEA block */
703 writel((10 << 16) | (2 << 0), HDMI_DDC_SPEED);
704 writel(0xFF000000, HDMI_DDC_SETUP);
705 writel((1 << 16) | (19 << 0), HDMI_DDC_REF);
706 writel(BIT(31) | (dev_addr << 8), HDMI_DDC_DATA);
707 writel(offset << 8, HDMI_DDC_DATA);
708 writel((dev_addr | BIT(0)) << 8, HDMI_DDC_DATA);
709 writel(BIT(12) | BIT(16), HDMI_DDC_TRANS0);
710 writel(BIT(0) | BIT(12) | BIT(13) | (len << 16), HDMI_DDC_TRANS1);
711 writel(BIT(0) | BIT(20), HDMI_DDC_CTRL);
712
713 /* poll for 100ms for read to complete */
714 reg_val = readl(HDMI_DDC_INT_CTRL);
715 while (!(reg_val & BIT(0)) && time_out) {
716 reg_val = readl(HDMI_DDC_INT_CTRL);
717 time_out--;
718 mdelay(10);
719 }
720
721 if (!time_out) {
722 dprintf(CRITICAL, "%s: Timeout reading EDID\n", __func__);
723 if (retry--)
724 goto again;
725 else
726 return ERROR;
727 }
728
729 /* clear interrupts */
730 writel(BIT(1), HDMI_DDC_INT_CTRL);
731
732 reg_val = readl(HDMI_DDC_SW_STATUS);
733 reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
734
735 /* Check if any NACK occurred */
736 if (reg_val) {
737 /* SW_STATUS_RESET */
738 writel(BIT(3), HDMI_DDC_CTRL);
739
740 /* SOFT_RESET */
741 writel(BIT(1), HDMI_DDC_CTRL);
742
743 dprintf(CRITICAL, "%s: NACK reading EDID\n", __func__);
744
745 if (retry--)
746 goto again;
747 else
748 return ERROR;
749 }
750
751 /* Write this data to DDC buffer */
752 writel(BIT(0) | (3 << 16) | BIT(31), HDMI_DDC_DATA);
753
754 /* Discard first byte */
755 readl(HDMI_DDC_DATA);
756
757 for (ndx = 0; ndx < 0x80; ndx++) {
758 reg_val = readl(HDMI_DDC_DATA);
759 mdss_hdmi_edid_buf[ndx] = (uint8_t)((reg_val & 0x0000FF00) >> 8);
760 }
761
762 dprintf(INFO, "%s: EDID read successful\n", __func__);
763
764 return NO_ERROR;
765}
766
767static void mdss_hdmi_parse_res(void)
768{
769 uint8_t len, i;
770 uint32_t video_format;
771 struct mdss_hdmi_timing_info tinfo_fmt = {0};
772
773 uint8_t *svd = hdmi_edid_find_block(DBC_START_OFFSET,
774 VIDEO_DATA_BLOCK, &len);
775
776 mdss_hdmi_video_fmt = HDMI_VFRMT_UNKNOWN;
777
778 if (!svd) {
779 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800780 return;
Casey Piper97d25272015-03-17 15:10:34 -0700781 }
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800782
Casey Piper97d25272015-03-17 15:10:34 -0700783 ++svd;
784
785 for (i = 0; i < len; ++i, ++svd) {
786 struct mdss_hdmi_timing_info tinfo = {0};
787 uint32_t ret = 0;
788
789 video_format = (*svd & 0x7F);
790
791 if (i == 0)
792 mdss_hdmi_pref_fmt = video_format;
793
794 ret = mdss_hdmi_get_timing_info(&tinfo, video_format);
795
796 if (ret || !tinfo.supported)
797 continue;
798
799 if (!tinfo_fmt.video_format) {
800 memcpy(&tinfo_fmt, &tinfo, sizeof(tinfo));
801 mdss_hdmi_video_fmt = video_format;
802 continue;
803 }
804
805 if (tinfo.active_v > tinfo_fmt.active_v) {
806 memcpy(&tinfo_fmt, &tinfo, sizeof(tinfo));
807 mdss_hdmi_video_fmt = video_format;
808 }
809 }
810
811 if (mdss_hdmi_video_fmt == HDMI_VFRMT_UNKNOWN)
812 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800813}
814
Casey Piper6c2f1132015-03-24 11:37:19 -0700815void mdss_hdmi_get_vic(char *buf)
816{
817 struct mdss_hdmi_timing_info tinfo = {0};
818 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
819
820 if (ret)
821 snprintf(buf, HDMI_VIC_STR_MAX, "%d", HDMI_VFRMT_UNKNOWN);
822 else
823 snprintf(buf, HDMI_VIC_STR_MAX, "%d", tinfo.video_format);
824
825}
826
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700827static void mdss_hdmi_panel_init(struct msm_panel_info *pinfo)
828{
Casey Piper97d25272015-03-17 15:10:34 -0700829 struct mdss_hdmi_timing_info tinfo = {0};
830 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700831
Casey Piper97d25272015-03-17 15:10:34 -0700832 if (!pinfo || ret)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700833 return;
834
835 pinfo->xres = tinfo.active_h;
836 pinfo->yres = tinfo.active_v;
837 pinfo->bpp = 24;
838 pinfo->type = HDMI_PANEL;
Casey Piper97d25272015-03-17 15:10:34 -0700839 pinfo->clk_rate = tinfo.pixel_freq * 1000;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700840
Casey Piper97d25272015-03-17 15:10:34 -0700841 pinfo->lcdc.h_back_porch = tinfo.back_porch_h;
842 pinfo->lcdc.h_front_porch = tinfo.front_porch_h;
843 pinfo->lcdc.h_pulse_width = tinfo.pulse_width_h;
844 pinfo->lcdc.v_back_porch = tinfo.back_porch_v;
845 pinfo->lcdc.v_front_porch = tinfo.front_porch_v;
846 pinfo->lcdc.v_pulse_width = tinfo.pulse_width_v;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700847
Casey Piper97d25272015-03-17 15:10:34 -0700848 pinfo->lcdc.hsync_skew = 0;
849 pinfo->lcdc.xres_pad = 0;
850 pinfo->lcdc.yres_pad = 0;
851 pinfo->lcdc.dual_pipe = 0;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700852}
853
Casey Piper7ab92992015-03-18 14:19:23 -0700854static uint8_t mdss_hdmi_cable_status(void)
855{
856 uint32_t reg_val;
857 uint8_t cable_status;
858
859 mdss_hdmi_set_mode(true);
860
861 /* Enable USEC REF timer */
862 writel(0x0001001B, HDMI_USEC_REFTIMER);
863
864 /* set timeout to 4.1ms (max) for hardware debounce */
865 reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
866
867 /* enable HPD circuit */
868 writel(reg_val | BIT(28), HDMI_HPD_CTRL);
869
870 writel(BIT(2) | BIT(1), HDMI_HPD_INT_CTRL);
871
872 /* Toggle HPD circuit to trigger HPD sense */
873 reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
874 writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
875 writel(reg_val & BIT(28), HDMI_HPD_CTRL);
876
877 mdelay(20);
878
879 cable_status = (readl(HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
880
881 dprintf(INFO, "hdmi cable %s\n",
882 cable_status ? "connected" : "not connected");
883
884 writel(BIT(0), HDMI_HPD_INT_CTRL);
885 writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
886
887 mdss_hdmi_set_mode(false);
888
889 return cable_status;
890}
891
Casey Piper6c2f1132015-03-24 11:37:19 -0700892static int mdss_hdmi_update_panel_info(void)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700893{
Casey Piper6c2f1132015-03-24 11:37:19 -0700894 mdss_hdmi_set_mode(true);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700895
Casey Piper6c2f1132015-03-24 11:37:19 -0700896 if (!mdss_hdmi_read_edid())
897 mdss_hdmi_parse_res();
898 else
899 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
900
901 mdss_hdmi_set_mode(false);
902
903 mdss_hdmi_panel_init(&(panel.panel_info));
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700904
905 panel.fb.width = panel.panel_info.xres;
906 panel.fb.height = panel.panel_info.yres;
907 panel.fb.stride = panel.panel_info.xres;
908 panel.fb.bpp = panel.panel_info.bpp;
909 panel.fb.format = FB_FORMAT_RGB888;
910
Casey Piper6c2f1132015-03-24 11:37:19 -0700911 return NO_ERROR;
912}
913
914void mdss_hdmi_display_init(uint32_t rev, void *base)
915{
916 panel.power_func = mdss_hdmi_enable_power;
917 panel.clk_func = mdss_hdmi_panel_clock;
918 panel.update_panel_info = mdss_hdmi_update_panel_info;
919 panel.pll_clk_func = mdss_hdmi_pll_clock;
920
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700921 panel.fb.base = base;
922 panel.mdp_rev = rev;
923
924 msm_display_init(&panel);
925}
926
927static int mdss_hdmi_video_setup(void)
928{
929 uint32_t total_v = 0;
930 uint32_t total_h = 0;
931 uint32_t start_h = 0;
932 uint32_t end_h = 0;
933 uint32_t start_v = 0;
934 uint32_t end_v = 0;
935
Casey Piper97d25272015-03-17 15:10:34 -0700936 struct mdss_hdmi_timing_info tinfo = {0};
937 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
938
939 if (ret)
940 return ERROR;
941
942 dprintf(INFO, "hdmi resolution %dx%d@p%dHz (%d)\n",
943 tinfo.active_h, tinfo.active_v, tinfo.refresh_rate/1000,
944 mdss_hdmi_video_fmt);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700945
946 total_h = tinfo.active_h + tinfo.front_porch_h +
947 tinfo.back_porch_h + tinfo.pulse_width_h - 1;
948 total_v = tinfo.active_v + tinfo.front_porch_v +
949 tinfo.back_porch_v + tinfo.pulse_width_v - 1;
950 if (((total_v << 16) & 0xE0000000) || (total_h & 0xFFFFE000)) {
951 dprintf(CRITICAL,
952 "%s: total v=%d or h=%d is larger than supported\n",
953 __func__, total_v, total_h);
954 return ERROR;
955 }
956 writel((total_v << 16) | (total_h << 0), HDMI_TOTAL);
957
958 start_h = tinfo.back_porch_h + tinfo.pulse_width_h;
959 end_h = (total_h + 1) - tinfo.front_porch_h;
960 if (((end_h << 16) & 0xE0000000) || (start_h & 0xFFFFE000)) {
961 dprintf(CRITICAL,
962 "%s: end_h=%d or start_h=%d is larger than supported\n",
963 __func__, end_h, start_h);
964 return ERROR;
965 }
966 writel((end_h << 16) | (start_h << 0), HDMI_ACTIVE_H);
967
968 start_v = tinfo.back_porch_v + tinfo.pulse_width_v - 1;
969 end_v = total_v - tinfo.front_porch_v;
970 if (((end_v << 16) & 0xE0000000) || (start_v & 0xFFFFE000)) {
971 dprintf(CRITICAL,
972 "%s: end_v=%d or start_v=%d is larger than supported\n",
973 __func__, end_v, start_v);
974 return ERROR;
975 }
976 writel((end_v << 16) | (start_v << 0), HDMI_ACTIVE_V);
977
978 if (tinfo.interlaced) {
979 writel((total_v + 1) << 0, HDMI_V_TOTAL_F2);
980 writel(((end_v + 1) << 16) | ((start_v + 1) << 0),
981 HDMI_ACTIVE_V_F2);
982 } else {
983 writel(0, HDMI_V_TOTAL_F2);
984 writel(0, HDMI_ACTIVE_V_F2);
985 }
986
987 writel(((tinfo.interlaced << 31) & 0x80000000) |
988 ((tinfo.active_low_h << 29) & 0x20000000) |
989 ((tinfo.active_low_v << 28) & 0x10000000), HDMI_FRAME_CTRL);
990
991 return 0;
992}
993
Casey Piper97d25272015-03-17 15:10:34 -0700994static void mdss_hdmi_extract_extended_data_blocks(void)
995{
996 uint8_t len = 0;
997 uint32_t start_offset = DBC_START_OFFSET;
998 uint8_t const *etag = NULL;
999 uint8_t *in_buf = mdss_hdmi_edid_buf;
1000
1001 do {
1002 /* A Tage code of 7 identifies extended data blocks */
1003 etag = hdmi_edid_find_block(start_offset,
1004 USE_EXTENDED_TAG, &len);
1005
1006 start_offset = etag - in_buf + len + 1;
1007
1008 /* The extended data block should at least be 2 bytes long */
1009 if (len < 2) {
1010 dprintf(SPEW, "%s: data block of len < 2 bytes\n",
1011 __func__);
1012 continue;
1013 }
1014
1015 /*
1016 * The second byte of the extended data block has the
1017 * extended tag code
1018 */
1019 switch (etag[1]) {
1020 case 0:
1021 /*
1022 * Check if the sink specifies underscan
1023 * support for:
1024 * BIT 5: preferred video format
1025 * BIT 3: IT video format
1026 * BIT 1: CE video format
1027 */
1028 pt_scan_info = (etag[2] & (BIT(4) | BIT(5))) >> 4;
1029 it_scan_info = (etag[2] & (BIT(3) | BIT(2))) >> 2;
1030 ce_scan_info = etag[2] & (BIT(1) | BIT(0));
1031
1032 dprintf(INFO, "scan Info (pt|it|ce): (%d|%d|%d)\n",
1033 pt_scan_info, it_scan_info, ce_scan_info);
1034 break;
1035 default:
1036 dprintf(SPEW, "%s: Tag Code %d not supported\n",
1037 __func__, etag[1]);
1038 break;
1039 }
1040 } while (etag != NULL);
1041}
1042
1043/*
1044 * If the sink specified support for both underscan/overscan then, by default,
1045 * set the underscan bit. Only checking underscan support for preferred
1046 * format and cea formats.
1047 */
1048uint8_t mdss_hdmi_get_scan_info(void)
1049{
1050 uint8_t scaninfo = 0;
1051 bool use_ce_scan_info = true;
1052
1053 mdss_hdmi_extract_extended_data_blocks();
1054
1055 if (mdss_hdmi_video_fmt == mdss_hdmi_pref_fmt) {
1056 use_ce_scan_info = false;
1057
1058 switch (pt_scan_info) {
1059 case 0:
1060 use_ce_scan_info = true;
1061 break;
1062 case 3:
1063 scaninfo = BIT(1);
1064 break;
1065 default:
1066 break;
1067 }
1068 }
1069
1070 if (use_ce_scan_info) {
1071 if (3 == ce_scan_info)
1072 scaninfo |= BIT(1);
1073 }
1074
1075 return scaninfo;
1076}
1077
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001078void mdss_hdmi_avi_info_frame(void)
1079{
1080 uint32_t sum;
1081 uint32_t reg_val;
1082 uint8_t checksum;
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001083 uint32_t i;
1084 struct hdmi_avi_infoframe_config avi_info = {0};
1085 struct mdss_hdmi_timing_info tinfo = {0};
1086 uint8_t avi_iframe[AVI_MAX_DATA_BYTES] = {0};
Casey Piper97d25272015-03-17 15:10:34 -07001087
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001088 mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
1089
1090 /* Setup AVI Infoframe content */
1091 avi_info.scan_info = mdss_hdmi_get_scan_info();
1092 avi_info.bar_info.end_of_top_bar = 0x0;
1093 avi_info.bar_info.start_of_bottom_bar = tinfo.active_v + 1;
1094 avi_info.bar_info.end_of_left_bar = 0;
1095 avi_info.bar_info.start_of_right_bar = tinfo.active_h + 1;
1096 avi_info.act_fmt_info_present = true;
1097 avi_info.rgb_quantization_range = HDMI_QUANTIZATION_DEFAULT;
1098 avi_info.yuv_quantization_range = HDMI_QUANTIZATION_DEFAULT;
1099 avi_info.scaling_info = HDMI_SCALING_NONE;
1100 avi_info.colorimetry_info = 0;
1101 avi_info.ext_colorimetry_info = 0;
1102 avi_info.pixel_rpt_factor = 0;
1103
1104 /*
1105 * BYTE - 1:
1106 * 0:1 - Scan Information
1107 * 2:3 - Bar Info
1108 * 4 - Active Format Info present
1109 * 5:6 - Pixel format type;
1110 * 7 - Reserved;
1111 */
1112 avi_iframe[0] = (avi_info.scan_info & 0x3) |
1113 (avi_info.bar_info.vert_binfo_present ? BIT(2) : 0) |
1114 (avi_info.bar_info.horz_binfo_present ? BIT(3) : 0) |
1115 (avi_info.act_fmt_info_present ? BIT(4) : 0);
1116
1117 /*
1118 * BYTE - 2:
1119 * 0:3 - Active format info
1120 * 4:5 - Picture aspect ratio
1121 * 6:7 - Colorimetry info
1122 */
1123 avi_iframe[1] |= 0x08;
1124 if (tinfo.ar == HDMI_RES_AR_4_3)
1125 avi_iframe[1] |= (0x1 << 4);
1126 else if (tinfo.ar == HDMI_RES_AR_16_9)
1127 avi_iframe[1] |= (0x2 << 4);
1128
1129 avi_iframe[1] |= (avi_info.colorimetry_info & 0x3) << 6;
1130
1131 /*
1132 * BYTE - 3:
1133 * 0:1 - Scaling info
1134 * 2:3 - Quantization range
1135 * 4:6 - Extended Colorimetry
1136 * 7 - IT content
1137 */
1138 avi_iframe[2] |= (avi_info.scaling_info & 0x3) |
1139 ((avi_info.rgb_quantization_range & 0x3) << 2) |
1140 ((avi_info.ext_colorimetry_info & 0x7) << 4) |
1141 ((avi_info.is_it_content ? 0x1 : 0x0) << 7);
1142 /*
1143 * BYTE - 4:
1144 * 0:7 - VIC
1145 */
1146 if (tinfo.video_format < HDMI_VFRMT_END)
1147 avi_iframe[3] = tinfo.video_format;
1148
1149 /*
1150 * BYTE - 5:
1151 * 0:3 - Pixel Repeat factor
1152 * 4:5 - Content type
1153 * 6:7 - YCC Quantization range
1154 */
1155 avi_iframe[4] = (avi_info.pixel_rpt_factor & 0xF) |
1156 ((avi_info.content_type & 0x3) << 4) |
1157 ((avi_info.yuv_quantization_range & 0x3) << 6);
1158
1159 /* BYTE - 6,7: End of top bar */
1160 avi_iframe[5] = avi_info.bar_info.end_of_top_bar & 0xFF;
1161 avi_iframe[6] = ((avi_info.bar_info.end_of_top_bar & 0xFF00) >> 8);
1162
1163 /* BYTE - 8,9: Start of bottom bar */
1164 avi_iframe[7] = avi_info.bar_info.start_of_bottom_bar & 0xFF;
1165 avi_iframe[8] = ((avi_info.bar_info.start_of_bottom_bar & 0xFF00) >> 8);
1166
1167 /* BYTE - 10,11: Endof of left bar */
1168 avi_iframe[9] = avi_info.bar_info.end_of_left_bar & 0xFF;
1169 avi_iframe[10] = ((avi_info.bar_info.end_of_left_bar & 0xFF00) >> 8);
1170
1171 /* BYTE - 12,13: Start of right bar */
1172 avi_iframe[11] = avi_info.bar_info.start_of_right_bar & 0xFF;
1173 avi_iframe[12] = ((avi_info.bar_info.start_of_right_bar & 0xFF00) >> 8);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001174
1175 sum = IFRAME_PACKET_OFFSET + AVI_IFRAME_TYPE +
1176 AVI_IFRAME_VERSION + AVI_MAX_DATA_BYTES;
1177
1178 for (i = 0; i < AVI_MAX_DATA_BYTES; i++)
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001179 sum += avi_iframe[i];
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001180 sum &= 0xFF;
1181 sum = 256 - sum;
1182 checksum = (uint8_t) sum;
1183
1184 reg_val = checksum |
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001185 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_1]) |
1186 LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_2]) |
1187 LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_3]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001188 writel(reg_val, HDMI_AVI_INFO0);
1189
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001190 reg_val = avi_iframe[DATA_BYTE_4] |
1191 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_5]) |
1192 LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_6]) |
1193 LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_7]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001194 writel(reg_val, HDMI_AVI_INFO1);
1195
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001196 reg_val = avi_iframe[DATA_BYTE_8] |
1197 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_9]) |
1198 LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_10]) |
1199 LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_11]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001200 writel(reg_val, HDMI_AVI_INFO2);
1201
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001202 reg_val = avi_iframe[DATA_BYTE_12] |
1203 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_13]) |
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001204 LEFT_SHIFT_24BITS(AVI_IFRAME_VERSION);
1205 writel(reg_val, HDMI_AVI_INFO3);
1206
1207 /* AVI InfFrame enable (every frame) */
1208 writel(readl(HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0),
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001209 HDMI_INFOFRAME_CTRL0);
1210
1211 reg_val = readl(HDMI_INFOFRAME_CTRL1);
1212 reg_val &= ~0x3F;
1213 reg_val |= AVI_IFRAME_LINE_NUMBER;
1214 writel(reg_val, HDMI_INFOFRAME_CTRL1);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001215}
1216
1217int mdss_hdmi_init(void)
1218{
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001219 bool is_dvi_mode = mdss_hdmi_is_dvi_mode();
1220
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001221 mdss_hdmi_set_mode(false);
1222
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001223 /* Audio settings */
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001224 if (!is_dvi_mode)
1225 mdss_hdmi_audio_playback();
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001226
1227 /* Video settings */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001228 mdss_hdmi_video_setup();
1229
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001230 /* AVI info settings */
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001231 if (!is_dvi_mode)
1232 mdss_hdmi_avi_info_frame();
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001233
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001234 /* Enable HDMI */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001235 mdss_hdmi_set_mode(true);
1236
1237 return 0;
1238}