blob: f1e23a92b373836fcb20f82855f3f9d25b2deab4 [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} }),
Tatenda Chipeperekwa8edad1d2016-03-15 10:47:02 -0700102 /* 594.000MHz */
103 HDMI_MSM_AUDIO_ARCS(594000, {{3072, 445500}, {9408, 990000}, {6144, 594000},
104 {18816, 990000}, {12288, 594000}, {37632, 990000},
105 {24576, 594000} } ),
Casey Piper1d3611d2015-03-17 15:45:44 -0700106};
107
Ajay Singh Parmar2a2e3d62015-02-12 16:57:28 -0800108extern int msm_display_init(struct msm_fb_panel_data *pdata);
109
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700110/* AVI INFOFRAME DATA */
111#define NUM_MODES_AVI 20
112#define AVI_MAX_DATA_BYTES 13
113
114enum {
115 DATA_BYTE_1,
116 DATA_BYTE_2,
117 DATA_BYTE_3,
118 DATA_BYTE_4,
119 DATA_BYTE_5,
120 DATA_BYTE_6,
121 DATA_BYTE_7,
122 DATA_BYTE_8,
123 DATA_BYTE_9,
124 DATA_BYTE_10,
125 DATA_BYTE_11,
126 DATA_BYTE_12,
127 DATA_BYTE_13,
128};
129
130#define IFRAME_PACKET_OFFSET 0x80
131/*
132 * InfoFrame Type Code:
133 * 0x0 - Reserved
134 * 0x1 - Vendor Specific
135 * 0x2 - Auxiliary Video Information
136 * 0x3 - Source Product Description
137 * 0x4 - AUDIO
138 * 0x5 - MPEG Source
139 * 0x6 - NTSC VBI
140 * 0x7 - 0xFF - Reserved
141 */
142#define AVI_IFRAME_TYPE 0x2
143#define AVI_IFRAME_VERSION 0x2
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -0800144#define AVI_IFRAME_LINE_NUMBER 1
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700145#define LEFT_SHIFT_BYTE(x) ((x) << 8)
146#define LEFT_SHIFT_WORD(x) ((x) << 16)
147#define LEFT_SHIFT_24BITS(x) ((x) << 24)
148
Casey Piper1d3611d2015-03-17 15:45:44 -0700149#define MAX_AUDIO_DATA_BLOCK_SIZE 0x80
Casey Piper97d25272015-03-17 15:10:34 -0700150#define DBC_START_OFFSET 4
151#define VIC_INDEX 3
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800152#define HDMI_VIC_STR_MAX 4
153#define MAX_EDID_BLOCK_SIZE 0x80
Casey Piper97d25272015-03-17 15:10:34 -0700154
155enum edid_data_block_type {
156 RESERVED_DATA_BLOCK1 = 0,
157 AUDIO_DATA_BLOCK,
158 VIDEO_DATA_BLOCK,
159 VENDOR_SPECIFIC_DATA_BLOCK,
160 SPEAKER_ALLOCATION_DATA_BLOCK,
161 VESA_DTC_DATA_BLOCK,
162 RESERVED_DATA_BLOCK2,
163 USE_EXTENDED_TAG
164};
165
166/* video formats defined by CEA 861D */
167#define HDMI_VFRMT_UNKNOWN 0
168#define HDMI_VFRMT_640x480p60_4_3 1
169#define HDMI_VFRMT_1280x720p60_16_9 4
170#define HDMI_VFRMT_1920x1080p60_16_9 16
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800171#define HDMI_VFRMT_4096x2160p24_256_135 98
172#define HDMI_VFRMT_4096x2160p25_256_135 99
173#define HDMI_VFRMT_4096x2160p30_256_135 100
174#define HDMI_VFRMT_3840x2160p24_64_27 103
175#define HDMI_VFRMT_3840x2160p25_64_27 104
176#define HDMI_VFRMT_3840x2160p30_64_27 105
177#define HDMI_EVFRMT_4096x2160p24_16_9 131
Tatenda Chipeperekwa8edad1d2016-03-15 10:47:02 -0700178#define HDMI_VFRMT_4096x2160p60_256_135 102
179#define HDMI_VFRMT_COUNT 11
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -0800180#define HDMI_VFRMT_END 127
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800181#define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \
182 (!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
Tatenda Chipeperekwaf4917642016-03-23 11:34:48 -0700183#define MSM_MDP_MAX_PIPE_WIDTH 2560
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800184static uint8_t mdss_hdmi_video_formats[HDMI_VFRMT_COUNT];
185static uint8_t mdss_hdmi_mode_count;
Casey Piper97d25272015-03-17 15:10:34 -0700186
187#define DEFAULT_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9
188static uint8_t mdss_hdmi_video_fmt = HDMI_VFRMT_UNKNOWN;
189static uint8_t mdss_hdmi_pref_fmt = HDMI_VFRMT_UNKNOWN;
190static uint8_t pt_scan_info;
191static uint8_t it_scan_info;
192static uint8_t ce_scan_info;
193
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800194static uint8_t mdss_hdmi_edid_buf[MAX_EDID_BLOCK_SIZE];
Casey Piper97d25272015-03-17 15:10:34 -0700195
196enum aspect_ratio {
197 HDMI_RES_AR_INVALID,
198 HDMI_RES_AR_4_3,
199 HDMI_RES_AR_5_4,
200 HDMI_RES_AR_16_9,
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800201 HDMI_RES_AR_64_27,
Casey Piper97d25272015-03-17 15:10:34 -0700202 HDMI_RES_AR_16_10,
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800203 HDMI_RES_AR_256_135,
Casey Piper97d25272015-03-17 15:10:34 -0700204 HDMI_RES_AR_MAX,
205};
206
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -0800207enum hdmi_quantization_range {
208 HDMI_QUANTIZATION_DEFAULT,
209 HDMI_QUANTIZATION_LIMITED_RANGE,
210 HDMI_QUANTIZATION_FULL_RANGE
211};
212
213enum hdmi_scaling_info {
214 HDMI_SCALING_NONE,
215 HDMI_SCALING_HORZ,
216 HDMI_SCALING_VERT,
217 HDMI_SCALING_HORZ_VERT,
218};
219
220struct hdmi_avi_iframe_bar_info {
221 bool vert_binfo_present;
222 bool horz_binfo_present;
223 uint32_t end_of_top_bar;
224 uint32_t start_of_bottom_bar;
225 uint32_t end_of_left_bar;
226 uint32_t start_of_right_bar;
227};
228
229struct hdmi_avi_infoframe_config {
230 uint32_t pixel_format;
231 uint32_t scan_info;
232 bool act_fmt_info_present;
233 uint32_t colorimetry_info;
234 uint32_t ext_colorimetry_info;
235 uint32_t rgb_quantization_range;
236 uint32_t yuv_quantization_range;
237 uint32_t scaling_info;
238 bool is_it_content;
239 uint8_t content_type;
240 uint8_t pixel_rpt_factor;
241 struct hdmi_avi_iframe_bar_info bar_info;
242};
243
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700244struct mdss_hdmi_timing_info {
245 uint32_t video_format;
246 uint32_t active_h;
247 uint32_t front_porch_h;
248 uint32_t pulse_width_h;
249 uint32_t back_porch_h;
250 uint32_t active_low_h;
251 uint32_t active_v;
252 uint32_t front_porch_v;
253 uint32_t pulse_width_v;
254 uint32_t back_porch_v;
255 uint32_t active_low_v;
256 /* Must divide by 1000 to get the actual frequency in MHZ */
257 uint32_t pixel_freq;
258 /* Must divide by 1000 to get the actual frequency in HZ */
259 uint32_t refresh_rate;
260 uint32_t interlaced;
261 uint32_t supported;
Casey Piper97d25272015-03-17 15:10:34 -0700262 enum aspect_ratio ar;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700263};
264
Casey Piper97d25272015-03-17 15:10:34 -0700265#define HDMI_VFRMT_640x480p60_4_3_TIMING \
266 {HDMI_VFRMT_640x480p60_4_3, 640, 16, 96, 48, true, \
267 480, 10, 2, 33, true, 25200, 60000, false, true, HDMI_RES_AR_4_3}
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800268
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700269#define HDMI_VFRMT_1280x720p60_16_9_TIMING \
270 {HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, false, \
Casey Piper97d25272015-03-17 15:10:34 -0700271 720, 5, 5, 20, false, 74250, 60000, false, true, HDMI_RES_AR_16_9}
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700272
Casey Piper97d25272015-03-17 15:10:34 -0700273#define HDMI_VFRMT_1920x1080p60_16_9_TIMING \
274 {HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, false, \
275 1080, 4, 5, 36, false, 148500, 60000, false, true, HDMI_RES_AR_16_9}
276
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800277#define HDMI_VFRMT_4096x2160p24_256_135_TIMING \
278 {HDMI_VFRMT_4096x2160p24_256_135, 4096, 1020, 88, 296, false, \
279 2160, 8, 10, 72, false, 297000, 24000, false, true, \
280 HDMI_RES_AR_256_135}
281
282#define HDMI_VFRMT_4096x2160p25_256_135_TIMING \
283 {HDMI_VFRMT_4096x2160p25_256_135, 4096, 968, 88, 128, false, \
284 2160, 8, 10, 72, false, 297000, 25000, false, true, \
285 HDMI_RES_AR_256_135}
286
287#define HDMI_VFRMT_4096x2160p30_256_135_TIMING \
288 {HDMI_VFRMT_4096x2160p30_256_135, 4096, 88, 88, 128, false, \
289 2160, 8, 10, 72, false, 297000, 30000, false, true, \
290 HDMI_RES_AR_256_135}
291
292#define HDMI_EVFRMT_4096x2160p24_16_9_TIMING \
293 {HDMI_EVFRMT_4096x2160p24_16_9, 4096, 1020, 88, 296, false, \
294 2160, 8, 10, 72, false, 297000, 24000, false, true, \
295 HDMI_RES_AR_16_9}
296
297#define HDMI_VFRMT_3840x2160p24_64_27_TIMING \
298 {HDMI_VFRMT_3840x2160p24_64_27, 3840, 1276, 88, 296, false, \
299 2160, 8, 10, 72, false, 297000, 24000, false, true, \
300 HDMI_RES_AR_64_27}
301
302#define HDMI_VFRMT_3840x2160p25_64_27_TIMING \
303 {HDMI_VFRMT_3840x2160p25_64_27, 3840, 1056, 88, 296, false, \
304 2160, 8, 10, 72, false, 297000, 25000, false, true, \
305 HDMI_RES_AR_64_27}
306
307#define HDMI_VFRMT_3840x2160p30_64_27_TIMING \
308 {HDMI_VFRMT_3840x2160p30_64_27, 3840, 176, 88, 296, false, \
309 2160, 8, 10, 72, false, 297000, 30000, false, true, \
310 HDMI_RES_AR_64_27}
311
Tatenda Chipeperekwa8edad1d2016-03-15 10:47:02 -0700312#define HDMI_VFRMT_4096x2160p60_256_135_TIMING \
313 {HDMI_VFRMT_4096x2160p60_256_135, 4096, 88, 88, 128, false, \
314 2160, 8, 10, 72, false, 594000, 60000, false, true, \
315 HDMI_RES_AR_256_135}
316
Casey Piper97d25272015-03-17 15:10:34 -0700317#define MSM_HDMI_MODES_GET_DETAILS(mode, MODE) do { \
318 struct mdss_hdmi_timing_info info = MODE##_TIMING; \
319 *mode = info; \
320 } while (0)
321
322static inline int mdss_hdmi_get_timing_info(
323 struct mdss_hdmi_timing_info *mode, int id)
324{
325 int ret = 0;
326
327 switch (id) {
328 case HDMI_VFRMT_640x480p60_4_3:
329 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_640x480p60_4_3);
330 break;
331
332 case HDMI_VFRMT_1280x720p60_16_9:
333 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_1280x720p60_16_9);
334 break;
335
336 case HDMI_VFRMT_1920x1080p60_16_9:
337 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_1920x1080p60_16_9);
338 break;
339
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800340 case HDMI_VFRMT_4096x2160p24_256_135:
341 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p24_256_135);
342 break;
343
344 case HDMI_VFRMT_4096x2160p25_256_135:
345 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p25_256_135);
346 break;
347
348 case HDMI_VFRMT_4096x2160p30_256_135:
349 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p30_256_135);
350 break;
351
352 case HDMI_EVFRMT_4096x2160p24_16_9:
353 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_EVFRMT_4096x2160p24_16_9);
354 break;
355
356 case HDMI_VFRMT_3840x2160p24_64_27:
357 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p24_64_27);
358 break;
359
360 case HDMI_VFRMT_3840x2160p25_64_27:
361 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p25_64_27);
362 break;
363
364 case HDMI_VFRMT_3840x2160p30_64_27:
365 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p30_64_27);
366 break;
367
Tatenda Chipeperekwa8edad1d2016-03-15 10:47:02 -0700368 case HDMI_VFRMT_4096x2160p60_256_135:
369 MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p60_256_135);
370 break;
371
Casey Piper97d25272015-03-17 15:10:34 -0700372 default:
373 ret = ERROR;
374 }
375
376 return ret;
377}
378
Casey Piper1d3611d2015-03-17 15:45:44 -0700379static void mdss_hdmi_audio_acr_setup(uint32_t sample_rate)
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700380{
Casey Piper1d3611d2015-03-17 15:45:44 -0700381 /* Read first before writing */
382 uint32_t acr_pck_ctrl_reg = readl(HDMI_ACR_PKT_CTRL);
383 struct mdss_hdmi_timing_info tinfo = {0};
384 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
385 struct hdmi_msm_audio_arcs *audio_acr = &hdmi_audio_acr_lut[0];
386 uint32_t lut_size = sizeof(hdmi_audio_acr_lut)
387 / sizeof(*hdmi_audio_acr_lut);
388 uint32_t i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
389 uint32_t channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700390
Casey Piper1d3611d2015-03-17 15:45:44 -0700391 if (ret || !tinfo.supported) {
392 dprintf(CRITICAL, "%s: video format %d not supported\n",
393 __func__, mdss_hdmi_video_fmt);
394 return;
395 }
396
397 for (i = 0; i < lut_size; audio_acr = &hdmi_audio_acr_lut[++i]) {
398 if (audio_acr->pclk == tinfo.pixel_freq)
399 break;
400 }
401
402 if (i >= lut_size) {
403 dprintf(CRITICAL, "%s: pixel clk %d not supported\n", __func__,
404 tinfo.pixel_freq);
405 return;
406 }
407
408 n = audio_acr->lut[sample_rate].n;
409 cts = audio_acr->lut[sample_rate].cts;
410 layout = (MSM_HDMI_AUDIO_CHANNEL_2 == channel_num) ? 0 : 1;
411
412 if ((AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
413 (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
414 multiplier = 4;
415 n >>= 2; /* divide N by 4 and use multiplier */
416 } else if ((AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
417 (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
418 multiplier = 2;
419 n >>= 1; /* divide N by 2 and use multiplier */
420 } else {
421 multiplier = 1;
422 }
423
424 dprintf(SPEW, "%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
425 layout);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700426
427 /* AUDIO_PRIORITY | SOURCE */
428 acr_pck_ctrl_reg |= 0x80000100;
429
Casey Piper1d3611d2015-03-17 15:45:44 -0700430 /* Reset multiplier bits */
431 acr_pck_ctrl_reg &= ~(7 << 16);
432
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700433 /* N_MULTIPLE(multiplier) */
434 acr_pck_ctrl_reg |= (multiplier & 7) << 16;
435
Casey Piper1d3611d2015-03-17 15:45:44 -0700436 if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
437 (AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
438 (AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
439 /* SELECT(3) */
440 acr_pck_ctrl_reg |= 3 << 4;
441 /* CTS_48 */
442 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700443
Casey Piper1d3611d2015-03-17 15:45:44 -0700444 /* CTS: need to determine how many fractional bits */
445 writel(cts, HDMI_ACR_48_0);
446 /* N */
447 writel(n, HDMI_ACR_48_1);
448 } else if ((AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
449 (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
450 (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
451 /* SELECT(2) */
452 acr_pck_ctrl_reg |= 2 << 4;
453 /* CTS_44 */
454 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700455
Casey Piper1d3611d2015-03-17 15:45:44 -0700456 /* CTS: need to determine how many fractional bits */
457 writel(cts, HDMI_ACR_44_0);
458 /* N */
459 writel(n, HDMI_ACR_44_1);
460 } else { /* default to 32k */
461 /* SELECT(1) */
462 acr_pck_ctrl_reg |= 1 << 4;
463 /* CTS_32 */
464 cts <<= 12;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700465
Casey Piper1d3611d2015-03-17 15:45:44 -0700466 /* CTS: need to determine how many fractional bits */
467 writel(cts, HDMI_ACR_32_0);
468 /* N */
469 writel(n, HDMI_ACR_32_1);
470 }
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700471
472 /* Payload layout depends on number of audio channels */
Casey Piper1d3611d2015-03-17 15:45:44 -0700473 /* LAYOUT_SEL(layout) */
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700474 aud_pck_ctrl_2_reg = 1 | (layout << 1);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700475 /* override | layout */
476 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
477
478 /* SEND | CONT */
Casey Piper1d3611d2015-03-17 15:45:44 -0700479 acr_pck_ctrl_reg |= 0x00000003;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700480
481 writel(acr_pck_ctrl_reg, HDMI_ACR_PKT_CTRL);
482}
483
Casey Piper1d3611d2015-03-17 15:45:44 -0700484static void mdss_hdmi_audio_info_setup(void)
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700485{
Casey Piper1d3611d2015-03-17 15:45:44 -0700486 uint32_t channel_count = MSM_HDMI_AUDIO_CHANNEL_2;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700487 uint32_t channel_allocation = 0;
488 uint32_t level_shift = 0;
489 uint32_t down_mix = 0;
490 uint32_t check_sum, audio_info_0_reg, audio_info_1_reg;
491 uint32_t audio_info_ctrl_reg;
492 uint32_t aud_pck_ctrl_2_reg;
493 uint32_t layout;
494
Casey Piper1d3611d2015-03-17 15:45:44 -0700495 layout = (MSM_HDMI_AUDIO_CHANNEL_2 == channel_count) ? 0 : 1;;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700496 aud_pck_ctrl_2_reg = 1 | (layout << 1);
497 writel(aud_pck_ctrl_2_reg, HDMI_AUDIO_PKT_CTRL2);
498
499 /* Read first then write because it is bundled with other controls */
500 audio_info_ctrl_reg = readl(HDMI_INFOFRAME_CTRL0);
501
502 channel_allocation = 0; /* Default to FR,FL */
503
504 /* Program the Channel-Speaker allocation */
505 audio_info_1_reg = 0;
506
507 /* CA(channel_allocation) */
508 audio_info_1_reg |= channel_allocation & 0xff;
509
510 /* Program the Level shifter */
511 /* LSV(level_shift) */
512 audio_info_1_reg |= (level_shift << 11) & 0x00007800;
513
514 /* Program the Down-mix Inhibit Flag */
515 /* DM_INH(down_mix) */
516 audio_info_1_reg |= (down_mix << 15) & 0x00008000;
517
518 writel(audio_info_1_reg, HDMI_AUDIO_INFO1);
519
520 check_sum = 0;
521 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
522 check_sum += 0x84;
523 /* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
524 check_sum += 1;
525 /* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
526 check_sum += 0x0A;
527 check_sum += channel_count;
528 check_sum += channel_allocation;
529 /* See Table 8.5 in HDMI spec */
530 check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
531 check_sum &= 0xFF;
532 check_sum = (256 - check_sum);
533
534 audio_info_0_reg = 0;
535 /* CHECKSUM(check_sum) */
536 audio_info_0_reg |= check_sum & 0xff;
537 /* CC(channel_count) */
538 audio_info_0_reg |= (channel_count << 8) & 0x00000700;
539
540 writel(audio_info_0_reg, HDMI_AUDIO_INFO0);
541
542 /* Set these flags */
543 /* AUDIO_INFO_UPDATE | AUDIO_INFO_SOURCE | AUDIO_INFO_CONT
544 | AUDIO_INFO_SEND */
545 audio_info_ctrl_reg |= 0xF0;
546
547 /* HDMI_INFOFRAME_CTRL0[0x002C] */
548 writel(audio_info_ctrl_reg, HDMI_INFOFRAME_CTRL0);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700549}
550
Casey Piper97d25272015-03-17 15:10:34 -0700551static uint8_t* hdmi_edid_find_block(uint32_t start_offset,
552 uint8_t type, uint8_t *len)
553{
554 /* the start of data block collection, start of Video Data Block */
555 uint8_t *in_buf = mdss_hdmi_edid_buf;
556 uint32_t offset = start_offset;
557 uint32_t end_dbc_offset = in_buf[2];
558
559 *len = 0;
560
561 /*
562 * edid buffer 1, byte 2 being 4 means no non-DTD/Data block collection
563 * present.
564 * edid buffer 1, byte 2 being 0 means no non-DTD/DATA block collection
565 * present and no DTD data present.
566 */
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800567 if ((end_dbc_offset == 0) || (end_dbc_offset == 4) ||
568 (end_dbc_offset >= MAX_EDID_BLOCK_SIZE))
Casey Piper97d25272015-03-17 15:10:34 -0700569 return NULL;
570
571 while (offset < end_dbc_offset) {
572 uint8_t block_len = in_buf[offset] & 0x1F;
573 if ((in_buf[offset] >> 5) == type) {
574 *len = block_len;
575 dprintf(SPEW,
576 "EDID: block=%d found @ %d with length=%d\n",
577 type, offset, block_len);
578 return in_buf + offset;
579 }
580 offset += 1 + block_len;
581 }
582
583 return NULL;
584}
585
Casey Piper1d3611d2015-03-17 15:45:44 -0700586static bool mdss_hdmi_is_audio_freq_supported(uint32_t freq)
587{
588 uint8_t *in_buf = mdss_hdmi_edid_buf;
589 const uint8_t *adb = NULL;
590 uint32_t adb_size = 0;
591 uint8_t len = 0, count = 0;
592 uint32_t next_offset = DBC_START_OFFSET;
593 uint8_t audio_data_block[MAX_AUDIO_DATA_BLOCK_SIZE];
594
595 do {
596 adb = hdmi_edid_find_block(next_offset,
597 AUDIO_DATA_BLOCK, &len);
598
599 if ((adb_size + len) > MAX_AUDIO_DATA_BLOCK_SIZE) {
600 dprintf(INFO, "%s: invalid adb length\n", __func__);
601 break;
602 }
603
604 if (!adb)
605 break;
606
607 memcpy((audio_data_block + adb_size), adb + 1, len);
608 next_offset = (adb - in_buf) + 1 + len;
609
610 adb_size += len;
611
612 } while (adb);
613
614 count = adb_size/3;
615 adb = audio_data_block;
616
617 while (count--) {
618 uint8_t freq_lst = *(adb + 1) & 0xFF;
619
620 if (freq_lst & BIT(freq))
621 return true;
622
623 adb += 3;
624 }
625
626 return false;
627}
628
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700629static void mdss_hdmi_audio_playback(void)
630{
Casey Piper77f69c52015-03-20 15:55:12 -0700631 char *base_addr;
Casey Piper1d3611d2015-03-17 15:45:44 -0700632 uint32_t sample_rate;
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700633
Casey Piper77f69c52015-03-20 15:55:12 -0700634 base_addr = (char *) memalign(4096, 0x1000);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700635 if (base_addr == NULL) {
636 dprintf(CRITICAL, "%s: Error audio buffer alloc\n", __func__);
637 return;
638 }
639
640 memset(base_addr, 0, 0x1000);
641
642 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
643 writel(0x00000080, HDMI_AUDIO_CFG);
644
645 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
646 writel(0x00000A6E, LPASS_LPAIF_RDDMA_CTL0);
647 writel(0x00002000, HDMI_VBI_PKT_CTRL);
648 writel(0x00000000, HDMI_GEN_PKT_CTRL);
649 writel(0x0000096E, LPASS_LPAIF_RDDMA_CTL0);
Casey Piper77f69c52015-03-20 15:55:12 -0700650 writel((uint32_t) base_addr, LPASS_LPAIF_RDDMA_BASE0);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700651 writel(0x000005FF, LPASS_LPAIF_RDDMA_BUFF_LEN0);
652 writel(0x000005FF, LPASS_LPAIF_RDDMA_PER_LEN0);
653 writel(0x0000096F, LPASS_LPAIF_RDDMA_CTL0);
654 writel(0x00000010, LPASS_LPAIF_DEBUG_CTL);
655 writel(0x00000000, HDMI_GC);
656 writel(0x00002030, HDMI_VBI_PKT_CTRL);
657 writel(0x00002030, HDMI_VBI_PKT_CTRL);
658 writel(0x00002030, HDMI_VBI_PKT_CTRL);
659
Casey Piper1d3611d2015-03-17 15:45:44 -0700660 if (mdss_hdmi_is_audio_freq_supported(AUDIO_SAMPLE_RATE_48KHZ))
661 sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
662 else
663 sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
664
665 mdss_hdmi_audio_acr_setup(sample_rate);
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700666 mdss_hdmi_audio_info_setup();
667
668 writel(0x00000010, HDMI_AUDIO_PKT_CTRL);
669 writel(0x00000080, HDMI_AUDIO_CFG);
670 writel(0x00000011, HDMI_AUDIO_PKT_CTRL);
671 writel(0x00000081, HDMI_AUDIO_CFG);
Casey Piper1d3611d2015-03-17 15:45:44 -0700672
673 dprintf(SPEW, "audio sample rate %s\n",
674 sample_rate == AUDIO_SAMPLE_RATE_48KHZ ? "48KHz" : "32KHz");
Ajay Singh Parmara1771a12014-08-13 15:56:11 -0700675}
676
Casey Piper77f69c52015-03-20 15:55:12 -0700677static uint32_t mdss_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700678{
Casey Piper7ab92992015-03-18 14:19:23 -0700679 int ret = NO_ERROR;
680 if (hdmi_panel_clock_enabled)
681 return ret;
682
683 ret = target_hdmi_panel_clock(enable, pinfo);
684
685 hdmi_panel_clock_enabled = enable;
686
687 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700688}
689
Casey Piper6c2f1132015-03-24 11:37:19 -0700690static uint32_t mdss_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo)
691{
Casey Piper7ab92992015-03-18 14:19:23 -0700692 int ret = NO_ERROR;
693
694 if (hdmi_pll_clock_enabled)
695 return ret;
696
697 ret = target_hdmi_pll_clock(enable, pinfo);
698
699 hdmi_pll_clock_enabled = enable;
700
701 return ret;
Casey Piper6c2f1132015-03-24 11:37:19 -0700702}
703
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700704static int mdss_hdmi_enable_power(uint8_t enable, struct msm_panel_info *pinfo)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700705{
Casey Piper7ab92992015-03-18 14:19:23 -0700706 int ret = NO_ERROR;
707
708 if (hdmi_power_enabled)
709 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700710
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700711 ret = target_hdmi_regulator_ctrl(enable);
712 if (ret) {
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700713 dprintf(CRITICAL, "hdmi regulator control enable failed\n");
714 goto bail_regulator_fail;
Casey Piper7ab92992015-03-18 14:19:23 -0700715 }
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700716
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700717 ret = target_hdmi_gpio_ctrl(enable);
718 if (ret) {
719 dprintf(CRITICAL, "hdmi gpio control enable failed\n");
720 goto bail_gpio_fail;
Casey Piper7ab92992015-03-18 14:19:23 -0700721 }
722
723 hdmi_power_enabled = enable;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700724
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700725 dprintf(SPEW, "HDMI Panel power %s done\n", enable ? "on" : "off");
726
727 return ret;
728
729bail_gpio_fail:
730 target_hdmi_regulator_ctrl(0);
731
732bail_regulator_fail:
Ajay Singh Parmar9d2ba152014-08-14 00:42:24 -0700733 return ret;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700734}
735
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800736static bool mdss_hdmi_is_dvi_mode(void)
737{
738 uint8_t len;
739 uint32_t ieee_tag;
740 const uint8_t *vsd = NULL;
741
742 vsd = hdmi_edid_find_block(DBC_START_OFFSET,
743 VENDOR_SPECIFIC_DATA_BLOCK, &len);
744
745 if (vsd == NULL || len == 0) {
746 dprintf(SPEW, "%s: Invalid VSDB\n", __func__);
747 return false;
748 }
749
750 ieee_tag = ((uint32_t) vsd[3] << 16) + ((uint32_t) vsd[2] << 8) +
751 (uint32_t) vsd[1];
752
753 if (ieee_tag == 0x0c03)
754 return false;
755 else
756 return true;
757}
758
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700759static void mdss_hdmi_set_mode(bool on)
760{
761 uint32_t val = 0;
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800762 if (on) {
763 /* tx on */
Tatenda Chipeperekwab12d7db2015-12-04 15:39:10 -0800764 val |= BIT(0);
765 /* hdcp legacy mode*/
766 val |= BIT(31);
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800767
768 if (!mdss_hdmi_is_dvi_mode())
Tatenda Chipeperekwab12d7db2015-12-04 15:39:10 -0800769 val |= BIT(1);
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -0800770 }
Casey Piper6c2f1132015-03-24 11:37:19 -0700771
772 writel(val, HDMI_CTRL);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -0700773}
774
Casey Piper97d25272015-03-17 15:10:34 -0700775
776static int mdss_hdmi_read_edid(void)
777{
778 uint8_t ndx;
779 uint32_t reg_val;
780 uint32_t dev_addr = 0xA0;
781 uint32_t len = 0x80;
782 uint32_t offset = 0x80;
783 uint32_t time_out;
784 uint32_t retry = 5;
785
786 dev_addr &= 0xFE;
787
788again:
789 time_out = 10;
790 writel(readl(HDMI_DDC_ARBITRATION) & ~BIT(4), HDMI_DDC_ARBITRATION);
791
792 /* Enable DDC Interrupts */
793 writel(BIT(1) | BIT(2), HDMI_DDC_INT_CTRL);
794
795 /* config DDC to read CEA block */
796 writel((10 << 16) | (2 << 0), HDMI_DDC_SPEED);
797 writel(0xFF000000, HDMI_DDC_SETUP);
798 writel((1 << 16) | (19 << 0), HDMI_DDC_REF);
799 writel(BIT(31) | (dev_addr << 8), HDMI_DDC_DATA);
800 writel(offset << 8, HDMI_DDC_DATA);
801 writel((dev_addr | BIT(0)) << 8, HDMI_DDC_DATA);
802 writel(BIT(12) | BIT(16), HDMI_DDC_TRANS0);
803 writel(BIT(0) | BIT(12) | BIT(13) | (len << 16), HDMI_DDC_TRANS1);
804 writel(BIT(0) | BIT(20), HDMI_DDC_CTRL);
805
806 /* poll for 100ms for read to complete */
807 reg_val = readl(HDMI_DDC_INT_CTRL);
808 while (!(reg_val & BIT(0)) && time_out) {
809 reg_val = readl(HDMI_DDC_INT_CTRL);
810 time_out--;
811 mdelay(10);
812 }
813
814 if (!time_out) {
815 dprintf(CRITICAL, "%s: Timeout reading EDID\n", __func__);
816 if (retry--)
817 goto again;
818 else
819 return ERROR;
820 }
821
822 /* clear interrupts */
823 writel(BIT(1), HDMI_DDC_INT_CTRL);
824
825 reg_val = readl(HDMI_DDC_SW_STATUS);
826 reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
827
828 /* Check if any NACK occurred */
829 if (reg_val) {
830 /* SW_STATUS_RESET */
831 writel(BIT(3), HDMI_DDC_CTRL);
832
833 /* SOFT_RESET */
834 writel(BIT(1), HDMI_DDC_CTRL);
835
836 dprintf(CRITICAL, "%s: NACK reading EDID\n", __func__);
837
838 if (retry--)
839 goto again;
840 else
841 return ERROR;
842 }
843
844 /* Write this data to DDC buffer */
845 writel(BIT(0) | (3 << 16) | BIT(31), HDMI_DDC_DATA);
846
847 /* Discard first byte */
848 readl(HDMI_DDC_DATA);
849
850 for (ndx = 0; ndx < 0x80; ndx++) {
851 reg_val = readl(HDMI_DDC_DATA);
852 mdss_hdmi_edid_buf[ndx] = (uint8_t)((reg_val & 0x0000FF00) >> 8);
853 }
854
855 dprintf(INFO, "%s: EDID read successful\n", __func__);
856
857 return NO_ERROR;
858}
859
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800860static void mdss_hdmi_add_video_format(uint32_t video_format)
861{
862 if (mdss_hdmi_mode_count >= HDMI_VFRMT_COUNT) {
863 dprintf(SPEW, "%s: unsupported format (%d)", __func__,
864 video_format);
865 return;
866 }
867
868 dprintf(SPEW, "%s: vic=%d\n", __func__, video_format);
869 mdss_hdmi_video_formats[mdss_hdmi_mode_count] = video_format;
870 mdss_hdmi_mode_count++;
871}
872
873static void mdss_hdmi_get_extended_video_formats()
874{
875 uint8_t db_len, offset, i;
876 uint8_t hdmi_vic_len;
877 uint32_t video_format;
878 const uint8_t *vsd = NULL;
879
880 vsd = hdmi_edid_find_block(DBC_START_OFFSET,
881 VENDOR_SPECIFIC_DATA_BLOCK, &db_len);
882
883 if (!vsd || db_len == 0) {
884 dprintf(SPEW, "%s: No/Invalid Vendor Specific Data Block\n",
885 __func__);
886 return;
887 }
888
889 /* check if HDMI_Video_present flag is set or not */
890 if (!(vsd[8] & BIT(5))) {
891 dprintf(SPEW, "%s: extended vfmts not supported by the sink.\n",
892 __func__);
893 return;
894 }
895
896 offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
897
898 hdmi_vic_len = vsd[offset + 1] >> 5;
899 if (hdmi_vic_len) {
900 for (i = 0; i < hdmi_vic_len; i++) {
901 struct mdss_hdmi_timing_info tinfo = {0};
902 uint32_t ret = 0;
903
904 video_format = HDMI_VFRMT_END + vsd[offset + 2 + i];
905 ret = mdss_hdmi_get_timing_info(&tinfo, video_format);
906
907 if (ret || !tinfo.supported)
908 continue;
909
910 mdss_hdmi_add_video_format(video_format);
911 }
912 }
913}
914
915static void mdss_hdmi_get_cea_video_formats()
Casey Piper97d25272015-03-17 15:10:34 -0700916{
917 uint8_t len, i;
918 uint32_t video_format;
Casey Piper97d25272015-03-17 15:10:34 -0700919
920 uint8_t *svd = hdmi_edid_find_block(DBC_START_OFFSET,
921 VIDEO_DATA_BLOCK, &len);
922
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800923 if (!svd || len == 0) {
924 dprintf(SPEW, "%s: No/Invalid Video Data Block\n",
925 __func__);
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800926 return;
Casey Piper97d25272015-03-17 15:10:34 -0700927 }
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800928
Casey Piper97d25272015-03-17 15:10:34 -0700929 ++svd;
930
931 for (i = 0; i < len; ++i, ++svd) {
932 struct mdss_hdmi_timing_info tinfo = {0};
933 uint32_t ret = 0;
934
935 video_format = (*svd & 0x7F);
936
937 if (i == 0)
938 mdss_hdmi_pref_fmt = video_format;
939
940 ret = mdss_hdmi_get_timing_info(&tinfo, video_format);
941
942 if (ret || !tinfo.supported)
943 continue;
944
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800945 mdss_hdmi_add_video_format(video_format);
946 }
947}
Casey Piper97d25272015-03-17 15:10:34 -0700948
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800949static void mdss_hdmi_parse_res(void)
950{
951 int index, ret;
952 uint8_t current_video_format;
953 struct mdss_hdmi_timing_info current_timing_info = {0};
954
955 mdss_hdmi_mode_count = 0;
956 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
957 current_video_format = mdss_hdmi_video_fmt;
958 mdss_hdmi_get_timing_info(&current_timing_info, mdss_hdmi_video_fmt);
959
960 mdss_hdmi_get_extended_video_formats();
961 mdss_hdmi_get_cea_video_formats();
962
963 for (index = 0; index < mdss_hdmi_mode_count; index++) {
964 struct mdss_hdmi_timing_info new_timing_info = {0};
965
966 if (!mdss_hdmi_video_formats[index])
967 break;
968
969 ret = mdss_hdmi_get_timing_info(&new_timing_info, mdss_hdmi_video_formats[index]);
970 if (ret || !new_timing_info.supported)
971 continue;
972
973 if (new_timing_info.active_h > current_timing_info.active_h) {
974 current_video_format = mdss_hdmi_video_formats[index];
975 } else if (new_timing_info.active_h ==
976 current_timing_info.active_h) {
977 if (new_timing_info.active_v >
978 current_timing_info.active_v) {
979 current_video_format = mdss_hdmi_video_formats[index];
980 } else if (new_timing_info.active_v ==
981 current_timing_info.active_v) {
Tatenda Chipeperekwad83a3002016-03-15 10:37:06 -0700982 if (new_timing_info.refresh_rate >
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800983 current_timing_info.refresh_rate) {
984 current_video_format = mdss_hdmi_video_formats[index];
985 }
986 }
Casey Piper97d25272015-03-17 15:10:34 -0700987 }
Tatenda Chipeperekwad83a3002016-03-15 10:37:06 -0700988
989 mdss_hdmi_get_timing_info(&current_timing_info, current_video_format);
Casey Piper97d25272015-03-17 15:10:34 -0700990 }
991
Tatenda Chipeperekwa3fe8bd82016-02-23 18:49:10 -0800992 if (mdss_hdmi_video_fmt != current_video_format)
993 mdss_hdmi_video_fmt = current_video_format;
Ajay Singh Parmar392f07a2014-11-19 15:06:19 -0800994}
995
Casey Piper6c2f1132015-03-24 11:37:19 -0700996void mdss_hdmi_get_vic(char *buf)
997{
998 struct mdss_hdmi_timing_info tinfo = {0};
999 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
1000
1001 if (ret)
1002 snprintf(buf, HDMI_VIC_STR_MAX, "%d", HDMI_VFRMT_UNKNOWN);
1003 else
1004 snprintf(buf, HDMI_VIC_STR_MAX, "%d", tinfo.video_format);
1005
1006}
1007
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001008static void mdss_hdmi_panel_init(struct msm_panel_info *pinfo)
1009{
Casey Piper97d25272015-03-17 15:10:34 -07001010 struct mdss_hdmi_timing_info tinfo = {0};
1011 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001012
Casey Piper97d25272015-03-17 15:10:34 -07001013 if (!pinfo || ret)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001014 return;
1015
1016 pinfo->xres = tinfo.active_h;
1017 pinfo->yres = tinfo.active_v;
1018 pinfo->bpp = 24;
1019 pinfo->type = HDMI_PANEL;
Casey Piper97d25272015-03-17 15:10:34 -07001020 pinfo->clk_rate = tinfo.pixel_freq * 1000;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001021
Casey Piper97d25272015-03-17 15:10:34 -07001022 pinfo->lcdc.h_back_porch = tinfo.back_porch_h;
1023 pinfo->lcdc.h_front_porch = tinfo.front_porch_h;
1024 pinfo->lcdc.h_pulse_width = tinfo.pulse_width_h;
1025 pinfo->lcdc.v_back_porch = tinfo.back_porch_v;
1026 pinfo->lcdc.v_front_porch = tinfo.front_porch_v;
1027 pinfo->lcdc.v_pulse_width = tinfo.pulse_width_v;
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001028
Casey Piper97d25272015-03-17 15:10:34 -07001029 pinfo->lcdc.hsync_skew = 0;
1030 pinfo->lcdc.xres_pad = 0;
1031 pinfo->lcdc.yres_pad = 0;
Tatenda Chipeperekwaf4917642016-03-23 11:34:48 -07001032
1033 /* Add dual pipe configuration for resultions greater than
1034 * MSM_MDP_MAX_PIPE_WIDTH.
1035 */
1036 if (pinfo->xres > MSM_MDP_MAX_PIPE_WIDTH) {
1037 pinfo->lcdc.dual_pipe = 1;
1038 pinfo->lm_split[0] = pinfo->xres / 2;
1039 pinfo->lm_split[1] = pinfo->xres - pinfo->lm_split[0];
1040 }
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001041}
1042
Casey Piper7ab92992015-03-18 14:19:23 -07001043static uint8_t mdss_hdmi_cable_status(void)
1044{
1045 uint32_t reg_val;
1046 uint8_t cable_status;
1047
1048 mdss_hdmi_set_mode(true);
1049
1050 /* Enable USEC REF timer */
1051 writel(0x0001001B, HDMI_USEC_REFTIMER);
1052
1053 /* set timeout to 4.1ms (max) for hardware debounce */
1054 reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
1055
1056 /* enable HPD circuit */
1057 writel(reg_val | BIT(28), HDMI_HPD_CTRL);
1058
1059 writel(BIT(2) | BIT(1), HDMI_HPD_INT_CTRL);
1060
1061 /* Toggle HPD circuit to trigger HPD sense */
1062 reg_val = readl(HDMI_HPD_CTRL) | 0x1FFF;
1063 writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
1064 writel(reg_val & BIT(28), HDMI_HPD_CTRL);
1065
1066 mdelay(20);
1067
1068 cable_status = (readl(HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
1069
1070 dprintf(INFO, "hdmi cable %s\n",
1071 cable_status ? "connected" : "not connected");
1072
1073 writel(BIT(0), HDMI_HPD_INT_CTRL);
1074 writel(reg_val & ~BIT(28), HDMI_HPD_CTRL);
1075
1076 mdss_hdmi_set_mode(false);
1077
1078 return cable_status;
1079}
1080
Casey Piper6c2f1132015-03-24 11:37:19 -07001081static int mdss_hdmi_update_panel_info(void)
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001082{
Casey Piper6c2f1132015-03-24 11:37:19 -07001083 mdss_hdmi_set_mode(true);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001084
Casey Piper6c2f1132015-03-24 11:37:19 -07001085 if (!mdss_hdmi_read_edid())
1086 mdss_hdmi_parse_res();
1087 else
1088 mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
1089
1090 mdss_hdmi_set_mode(false);
1091
1092 mdss_hdmi_panel_init(&(panel.panel_info));
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001093
1094 panel.fb.width = panel.panel_info.xres;
1095 panel.fb.height = panel.panel_info.yres;
1096 panel.fb.stride = panel.panel_info.xres;
1097 panel.fb.bpp = panel.panel_info.bpp;
1098 panel.fb.format = FB_FORMAT_RGB888;
1099
Casey Piper6c2f1132015-03-24 11:37:19 -07001100 return NO_ERROR;
1101}
1102
1103void mdss_hdmi_display_init(uint32_t rev, void *base)
1104{
1105 panel.power_func = mdss_hdmi_enable_power;
1106 panel.clk_func = mdss_hdmi_panel_clock;
1107 panel.update_panel_info = mdss_hdmi_update_panel_info;
1108 panel.pll_clk_func = mdss_hdmi_pll_clock;
1109
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001110 panel.fb.base = base;
1111 panel.mdp_rev = rev;
1112
1113 msm_display_init(&panel);
1114}
1115
1116static int mdss_hdmi_video_setup(void)
1117{
1118 uint32_t total_v = 0;
1119 uint32_t total_h = 0;
1120 uint32_t start_h = 0;
1121 uint32_t end_h = 0;
1122 uint32_t start_v = 0;
1123 uint32_t end_v = 0;
1124
Casey Piper97d25272015-03-17 15:10:34 -07001125 struct mdss_hdmi_timing_info tinfo = {0};
1126 uint32_t ret = mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
1127
1128 if (ret)
1129 return ERROR;
1130
1131 dprintf(INFO, "hdmi resolution %dx%d@p%dHz (%d)\n",
1132 tinfo.active_h, tinfo.active_v, tinfo.refresh_rate/1000,
1133 mdss_hdmi_video_fmt);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001134
1135 total_h = tinfo.active_h + tinfo.front_porch_h +
1136 tinfo.back_porch_h + tinfo.pulse_width_h - 1;
1137 total_v = tinfo.active_v + tinfo.front_porch_v +
1138 tinfo.back_porch_v + tinfo.pulse_width_v - 1;
1139 if (((total_v << 16) & 0xE0000000) || (total_h & 0xFFFFE000)) {
1140 dprintf(CRITICAL,
1141 "%s: total v=%d or h=%d is larger than supported\n",
1142 __func__, total_v, total_h);
1143 return ERROR;
1144 }
1145 writel((total_v << 16) | (total_h << 0), HDMI_TOTAL);
1146
1147 start_h = tinfo.back_porch_h + tinfo.pulse_width_h;
1148 end_h = (total_h + 1) - tinfo.front_porch_h;
1149 if (((end_h << 16) & 0xE0000000) || (start_h & 0xFFFFE000)) {
1150 dprintf(CRITICAL,
1151 "%s: end_h=%d or start_h=%d is larger than supported\n",
1152 __func__, end_h, start_h);
1153 return ERROR;
1154 }
1155 writel((end_h << 16) | (start_h << 0), HDMI_ACTIVE_H);
1156
1157 start_v = tinfo.back_porch_v + tinfo.pulse_width_v - 1;
1158 end_v = total_v - tinfo.front_porch_v;
1159 if (((end_v << 16) & 0xE0000000) || (start_v & 0xFFFFE000)) {
1160 dprintf(CRITICAL,
1161 "%s: end_v=%d or start_v=%d is larger than supported\n",
1162 __func__, end_v, start_v);
1163 return ERROR;
1164 }
1165 writel((end_v << 16) | (start_v << 0), HDMI_ACTIVE_V);
1166
1167 if (tinfo.interlaced) {
1168 writel((total_v + 1) << 0, HDMI_V_TOTAL_F2);
1169 writel(((end_v + 1) << 16) | ((start_v + 1) << 0),
1170 HDMI_ACTIVE_V_F2);
1171 } else {
1172 writel(0, HDMI_V_TOTAL_F2);
1173 writel(0, HDMI_ACTIVE_V_F2);
1174 }
1175
1176 writel(((tinfo.interlaced << 31) & 0x80000000) |
1177 ((tinfo.active_low_h << 29) & 0x20000000) |
1178 ((tinfo.active_low_v << 28) & 0x10000000), HDMI_FRAME_CTRL);
1179
1180 return 0;
1181}
1182
Casey Piper97d25272015-03-17 15:10:34 -07001183static void mdss_hdmi_extract_extended_data_blocks(void)
1184{
1185 uint8_t len = 0;
1186 uint32_t start_offset = DBC_START_OFFSET;
1187 uint8_t const *etag = NULL;
1188 uint8_t *in_buf = mdss_hdmi_edid_buf;
1189
1190 do {
1191 /* A Tage code of 7 identifies extended data blocks */
1192 etag = hdmi_edid_find_block(start_offset,
1193 USE_EXTENDED_TAG, &len);
1194
1195 start_offset = etag - in_buf + len + 1;
1196
1197 /* The extended data block should at least be 2 bytes long */
1198 if (len < 2) {
1199 dprintf(SPEW, "%s: data block of len < 2 bytes\n",
1200 __func__);
1201 continue;
1202 }
1203
1204 /*
1205 * The second byte of the extended data block has the
1206 * extended tag code
1207 */
1208 switch (etag[1]) {
1209 case 0:
1210 /*
1211 * Check if the sink specifies underscan
1212 * support for:
1213 * BIT 5: preferred video format
1214 * BIT 3: IT video format
1215 * BIT 1: CE video format
1216 */
1217 pt_scan_info = (etag[2] & (BIT(4) | BIT(5))) >> 4;
1218 it_scan_info = (etag[2] & (BIT(3) | BIT(2))) >> 2;
1219 ce_scan_info = etag[2] & (BIT(1) | BIT(0));
1220
1221 dprintf(INFO, "scan Info (pt|it|ce): (%d|%d|%d)\n",
1222 pt_scan_info, it_scan_info, ce_scan_info);
1223 break;
1224 default:
1225 dprintf(SPEW, "%s: Tag Code %d not supported\n",
1226 __func__, etag[1]);
1227 break;
1228 }
1229 } while (etag != NULL);
1230}
1231
1232/*
1233 * If the sink specified support for both underscan/overscan then, by default,
1234 * set the underscan bit. Only checking underscan support for preferred
1235 * format and cea formats.
1236 */
1237uint8_t mdss_hdmi_get_scan_info(void)
1238{
1239 uint8_t scaninfo = 0;
1240 bool use_ce_scan_info = true;
1241
1242 mdss_hdmi_extract_extended_data_blocks();
1243
1244 if (mdss_hdmi_video_fmt == mdss_hdmi_pref_fmt) {
1245 use_ce_scan_info = false;
1246
1247 switch (pt_scan_info) {
1248 case 0:
1249 use_ce_scan_info = true;
1250 break;
1251 case 3:
1252 scaninfo = BIT(1);
1253 break;
1254 default:
1255 break;
1256 }
1257 }
1258
1259 if (use_ce_scan_info) {
1260 if (3 == ce_scan_info)
1261 scaninfo |= BIT(1);
1262 }
1263
1264 return scaninfo;
1265}
1266
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001267void mdss_hdmi_avi_info_frame(void)
1268{
1269 uint32_t sum;
1270 uint32_t reg_val;
1271 uint8_t checksum;
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001272 uint32_t i;
1273 struct hdmi_avi_infoframe_config avi_info = {0};
1274 struct mdss_hdmi_timing_info tinfo = {0};
1275 uint8_t avi_iframe[AVI_MAX_DATA_BYTES] = {0};
Casey Piper97d25272015-03-17 15:10:34 -07001276
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001277 mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
1278
1279 /* Setup AVI Infoframe content */
1280 avi_info.scan_info = mdss_hdmi_get_scan_info();
1281 avi_info.bar_info.end_of_top_bar = 0x0;
1282 avi_info.bar_info.start_of_bottom_bar = tinfo.active_v + 1;
1283 avi_info.bar_info.end_of_left_bar = 0;
1284 avi_info.bar_info.start_of_right_bar = tinfo.active_h + 1;
1285 avi_info.act_fmt_info_present = true;
1286 avi_info.rgb_quantization_range = HDMI_QUANTIZATION_DEFAULT;
1287 avi_info.yuv_quantization_range = HDMI_QUANTIZATION_DEFAULT;
1288 avi_info.scaling_info = HDMI_SCALING_NONE;
1289 avi_info.colorimetry_info = 0;
1290 avi_info.ext_colorimetry_info = 0;
1291 avi_info.pixel_rpt_factor = 0;
1292
1293 /*
1294 * BYTE - 1:
1295 * 0:1 - Scan Information
1296 * 2:3 - Bar Info
1297 * 4 - Active Format Info present
1298 * 5:6 - Pixel format type;
1299 * 7 - Reserved;
1300 */
1301 avi_iframe[0] = (avi_info.scan_info & 0x3) |
1302 (avi_info.bar_info.vert_binfo_present ? BIT(2) : 0) |
1303 (avi_info.bar_info.horz_binfo_present ? BIT(3) : 0) |
1304 (avi_info.act_fmt_info_present ? BIT(4) : 0);
1305
1306 /*
1307 * BYTE - 2:
1308 * 0:3 - Active format info
1309 * 4:5 - Picture aspect ratio
1310 * 6:7 - Colorimetry info
1311 */
1312 avi_iframe[1] |= 0x08;
1313 if (tinfo.ar == HDMI_RES_AR_4_3)
1314 avi_iframe[1] |= (0x1 << 4);
1315 else if (tinfo.ar == HDMI_RES_AR_16_9)
1316 avi_iframe[1] |= (0x2 << 4);
1317
1318 avi_iframe[1] |= (avi_info.colorimetry_info & 0x3) << 6;
1319
1320 /*
1321 * BYTE - 3:
1322 * 0:1 - Scaling info
1323 * 2:3 - Quantization range
1324 * 4:6 - Extended Colorimetry
1325 * 7 - IT content
1326 */
1327 avi_iframe[2] |= (avi_info.scaling_info & 0x3) |
1328 ((avi_info.rgb_quantization_range & 0x3) << 2) |
1329 ((avi_info.ext_colorimetry_info & 0x7) << 4) |
1330 ((avi_info.is_it_content ? 0x1 : 0x0) << 7);
1331 /*
1332 * BYTE - 4:
1333 * 0:7 - VIC
1334 */
1335 if (tinfo.video_format < HDMI_VFRMT_END)
1336 avi_iframe[3] = tinfo.video_format;
1337
1338 /*
1339 * BYTE - 5:
1340 * 0:3 - Pixel Repeat factor
1341 * 4:5 - Content type
1342 * 6:7 - YCC Quantization range
1343 */
1344 avi_iframe[4] = (avi_info.pixel_rpt_factor & 0xF) |
1345 ((avi_info.content_type & 0x3) << 4) |
1346 ((avi_info.yuv_quantization_range & 0x3) << 6);
1347
1348 /* BYTE - 6,7: End of top bar */
1349 avi_iframe[5] = avi_info.bar_info.end_of_top_bar & 0xFF;
1350 avi_iframe[6] = ((avi_info.bar_info.end_of_top_bar & 0xFF00) >> 8);
1351
1352 /* BYTE - 8,9: Start of bottom bar */
1353 avi_iframe[7] = avi_info.bar_info.start_of_bottom_bar & 0xFF;
1354 avi_iframe[8] = ((avi_info.bar_info.start_of_bottom_bar & 0xFF00) >> 8);
1355
1356 /* BYTE - 10,11: Endof of left bar */
1357 avi_iframe[9] = avi_info.bar_info.end_of_left_bar & 0xFF;
1358 avi_iframe[10] = ((avi_info.bar_info.end_of_left_bar & 0xFF00) >> 8);
1359
1360 /* BYTE - 12,13: Start of right bar */
1361 avi_iframe[11] = avi_info.bar_info.start_of_right_bar & 0xFF;
1362 avi_iframe[12] = ((avi_info.bar_info.start_of_right_bar & 0xFF00) >> 8);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001363
1364 sum = IFRAME_PACKET_OFFSET + AVI_IFRAME_TYPE +
1365 AVI_IFRAME_VERSION + AVI_MAX_DATA_BYTES;
1366
1367 for (i = 0; i < AVI_MAX_DATA_BYTES; i++)
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001368 sum += avi_iframe[i];
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001369 sum &= 0xFF;
1370 sum = 256 - sum;
1371 checksum = (uint8_t) sum;
1372
1373 reg_val = checksum |
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001374 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_1]) |
1375 LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_2]) |
1376 LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_3]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001377 writel(reg_val, HDMI_AVI_INFO0);
1378
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001379 reg_val = avi_iframe[DATA_BYTE_4] |
1380 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_5]) |
1381 LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_6]) |
1382 LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_7]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001383 writel(reg_val, HDMI_AVI_INFO1);
1384
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001385 reg_val = avi_iframe[DATA_BYTE_8] |
1386 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_9]) |
1387 LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_10]) |
1388 LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_11]);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001389 writel(reg_val, HDMI_AVI_INFO2);
1390
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001391 reg_val = avi_iframe[DATA_BYTE_12] |
1392 LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_13]) |
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001393 LEFT_SHIFT_24BITS(AVI_IFRAME_VERSION);
1394 writel(reg_val, HDMI_AVI_INFO3);
1395
1396 /* AVI InfFrame enable (every frame) */
1397 writel(readl(HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0),
Tatenda Chipeperekwac50c8dd2016-02-23 18:59:08 -08001398 HDMI_INFOFRAME_CTRL0);
1399
1400 reg_val = readl(HDMI_INFOFRAME_CTRL1);
1401 reg_val &= ~0x3F;
1402 reg_val |= AVI_IFRAME_LINE_NUMBER;
1403 writel(reg_val, HDMI_INFOFRAME_CTRL1);
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001404}
1405
1406int mdss_hdmi_init(void)
1407{
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001408 bool is_dvi_mode = mdss_hdmi_is_dvi_mode();
1409
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001410 mdss_hdmi_set_mode(false);
1411
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001412 /* Audio settings */
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001413 if (!is_dvi_mode)
1414 mdss_hdmi_audio_playback();
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001415
1416 /* Video settings */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001417 mdss_hdmi_video_setup();
1418
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001419 /* AVI info settings */
Ajay Singh Parmar9ddfa572015-02-17 12:49:53 -08001420 if (!is_dvi_mode)
1421 mdss_hdmi_avi_info_frame();
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001422
Ajay Singh Parmara1771a12014-08-13 15:56:11 -07001423 /* Enable HDMI */
Ajay Singh Parmar243d82b2014-07-23 23:01:44 -07001424 mdss_hdmi_set_mode(true);
1425
1426 return 0;
1427}