blob: 3cda4bb3f52e2e735523e7163314c882e0170c73 [file] [log] [blame]
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are 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 copyright
9 * notice, this list of conditions and the following disclaimer in
10 * the documentation and/or other materials provided with the
11 * 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include "edp.h"
31
32struct edp_aux_ctrl edpctrl;
33
34int edp_hpd_done = 0;
35int edp_video_ready = 0;
36
37/*
38 * edid
39 */
40static char edid_hdr[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
41
42
43int edp_edid_buf_error(char *buf, int len)
44{
45 char *bp;
46 int i;
47 char csum = 0;
48 int ret = 0;
49
50 bp = buf;
51 if (len < 128) {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -070052 dprintf(INFO, "%s: Error: len=%x\n", __func__, len);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -070053 return -1;
54 }
55
56 for (i = 0; i < 128; i++)
57 csum += *bp++;
58
59 if (csum != 0) {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -070060 dprintf(INFO, "%s: Error: csum=%x\n", __func__, csum);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -070061 return -1;
62 }
63
64 if (buf[1] != 0xff) {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -070065 dprintf(INFO, "%s: Error: header\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -070066 return -1;
67 }
68
69 return ret;
70}
71
72
73void edp_extract_edid_manufacturer(struct edp_edid *edid, char *buf)
74{
75 char *bp;
76 char data;
77
78 bp = &buf[8];
79 data = *bp & 0x7f;
80 data >>= 2;
81 edid->id_name[0] = 'A' + data - 1;
82 data = *bp & 0x03;
83 data <<= 3;
84 bp++;
85 data |= (*bp >> 5);
86 edid->id_name[1] = 'A' + data - 1;
87 data = *bp & 0x1f;
88 edid->id_name[2] = 'A' + data - 1;
89 edid->id_name[3] = 0;
90
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -070091 dprintf(SPEW, "%s: edid manufacturer = %s", __func__, edid->id_name);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -070092}
93
94void edp_extract_edid_product(struct edp_edid *edid, char *buf)
95{
96 char *bp;
97 int data;
98
99 bp = &buf[0x0a];
100 data = *bp;
101 edid->id_product = *bp++;
102 edid->id_product &= 0x0ff;
103 data = *bp & 0x0ff;
104 data <<= 8;
105 edid->id_product |= data;
106
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700107 dprintf(SPEW, "%s: edid product = 0x%x\n", __func__, edid->id_product);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700108};
109
110void edp_extract_edid_version(struct edp_edid *edid, char *buf)
111{
112 edid->version = buf[0x12];
113 edid->revision = buf[0x13];
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700114 dprintf(SPEW, "%s: edid version = %d.%d", __func__,
115 edid->version, edid->revision);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700116};
117
118void edp_extract_edid_ext_block_cnt(struct edp_edid *edid, char *buf)
119{
120 edid->ext_block_cnt = buf[0x7e];
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700121 dprintf(SPEW, "%s: edid extension = %d", __func__, edid->ext_block_cnt);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700122};
123
124void edp_extract_edid_video_support(struct edp_edid *edid, char *buf)
125{
126 char *bp;
127
128 bp = &buf[0x14];
129 if (*bp & 0x80) {
130 edid->video_intf = *bp & 0x0f;
131 /* 6, 8, 10, 12, 14 and 16 bit per component */
132 edid->color_depth = ((*bp & 0x70) >> 4); /* color bit depth */
133 if (edid->color_depth) {
134 edid->color_depth *= 2;
135 edid->color_depth += 4;
136 }
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700137 dprintf(SPEW, "%s: Digital Video intf=%d color_depth=%d\n",
138 __func__, edid->video_intf, edid->color_depth);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700139 return;
140 }
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700141 dprintf(INFO, "%s: Error, Analog video interface", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700142};
143
144void edp_extract_edid_feature(struct edp_edid *edid, char *buf)
145{
146 char *bp;
147 char data;
148
149 bp = &buf[0x18];
150 data = *bp;
151 data &= 0xe0;
152 data >>= 5;
153 if (data == 0x01)
154 edid->dpm = 1; /* display power management */
155
156 if (edid->video_intf) {
157 if (*bp & 0x80) {
158 /* RGB 4:4:4, YcrCb 4:4:4 and YCrCb 4:2:2 */
159 edid->color_format = *bp & 0x18;
160 edid->color_format >>= 3;
161 }
162 }
163
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700164 dprintf(SPEW, "%s: edid dpm=%d color_format=%d",
165 __func__, edid->dpm, edid->color_format);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700166};
167
168void edp_extract_edid_detailed_timing_description(struct edp_edid *edid,
169 char *buf)
170{
171 char *bp;
172 int data;
173 struct display_timing_desc *dp;
174
175 dp = &edid->timing[0];
176
177 bp = &buf[0x36];
178 dp->pclk = 0;
179 dp->pclk = *bp++; /* byte 0x36 */
180 dp->pclk |= (*bp++ << 8); /* byte 0x37 */
181
182 dp->h_addressable = *bp++; /* byte 0x38 */
183
184 if (dp->pclk == 0 && dp->h_addressable == 0)
185 return; /* Not detailed timing definition */
186
187 dp->pclk *= 10000;
188
189 dp->h_blank = *bp++;/* byte 0x39 */
190 data = *bp & 0xf0; /* byte 0x3A */
191 data <<= 4;
192 dp->h_addressable |= data;
193
194 data = *bp++ & 0x0f;
195 data <<= 8;
196 dp->h_blank |= data;
197
198 dp->v_addressable = *bp++; /* byte 0x3B */
199 dp->v_blank = *bp++; /* byte 0x3C */
200 data = *bp & 0xf0; /* byte 0x3D */
201 data <<= 4;
202 dp->v_addressable |= data;
203
204 data = *bp++ & 0x0f;
205 data <<= 8;
206 dp->v_blank |= data;
207
208 dp->h_fporch = *bp++; /* byte 0x3E */
209 dp->h_sync_pulse = *bp++; /* byte 0x3F */
210
211 dp->v_fporch = *bp & 0x0f0; /* byte 0x40 */
212 dp->v_fporch >>= 4;
213 dp->v_sync_pulse = *bp & 0x0f;
214
215 bp++;
216 data = *bp & 0xc0; /* byte 0x41 */
217 data <<= 2;
218 dp->h_fporch |= data;
219
220 data = *bp & 0x30;
221 data <<= 4;
222 dp->h_sync_pulse |= data;
223
224 data = *bp & 0x0c;
225 data <<= 2;
226 dp->v_fporch |= data;
227
228 data = *bp & 0x03;
229 data <<= 4;
230 dp->v_sync_pulse |= data;
231
232 bp++;
233 dp->width_mm = *bp++; /* byte 0x42 */
234 dp->height_mm = *bp++; /* byte 0x43 */
235 data = *bp & 0x0f0; /* byte 0x44 */
236 data <<= 4;
237 dp->width_mm |= data;
238 data = *bp & 0x0f;
239 data <<= 8;
240 dp->height_mm |= data;
241
242 bp++;
243 dp->h_border = *bp++; /* byte 0x45 */
244 dp->v_border = *bp++; /* byte 0x46 */
245
246 dp->interlaced = *bp & 0x80; /* byte 0x47 */
247
248 dp->stereo = *bp & 0x60;
249 dp->stereo >>= 5;
250
251 data = *bp & 0x1e; /* bit 4,3,2 1*/
252 data >>= 1;
253 dp->sync_type = data & 0x08;
254 dp->sync_type >>= 3; /* analog or digital */
255 if (dp->sync_type) {
256 dp->sync_separate = data & 0x04;
257 dp->sync_separate >>= 2;
258 if (dp->sync_separate) {
259 if (data & 0x02)
260 dp->vsync_pol = 1; /* positive */
261 else
262 dp->vsync_pol = 0;/* negative */
263
264 if (data & 0x01)
265 dp->hsync_pol = 1; /* positive */
266 else
267 dp->hsync_pol = 0; /* negative */
268 }
269 }
270
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700271 dprintf(SPEW, "%s: pixel_clock = %d\n", __func__, dp->pclk);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700272
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700273 dprintf(SPEW, "%s: horizontal=%d, blank=%d, porch=%d, sync=%d\n",
274 __func__, dp->h_addressable, dp->h_blank,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700275 dp->h_fporch, dp->h_sync_pulse);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700276 dprintf(SPEW, "%s: vertical=%d, blank=%d, porch=%d, vsync=%d\n",
277 __func__, dp->v_addressable, dp->v_blank,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700278 dp->v_fporch, dp->v_sync_pulse);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700279 dprintf(SPEW, "%s: panel size in mm, width=%d height=%d\n",
280 __func__, dp->width_mm, dp->height_mm);
281 dprintf(SPEW, "%s: panel border horizontal=%d vertical=%d\n",
282 __func__, dp->h_border, dp->v_border);
283 dprintf(SPEW, "%s: interlaced=%d stereo=%d sync_type=%d sync_sep=%d\n",
284 __func__, dp->interlaced, dp->stereo,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700285 dp->sync_type, dp->sync_separate);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700286 dprintf(SPEW, "%s: polarity vsync=%d, hsync=%d\n",
287 __func__, dp->vsync_pol, dp->hsync_pol);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700288}
289
290
291/*
292 * EDID structure can be found in VESA standart here:
293 * http://read.pudn.com/downloads110/ebook/456020/E-EDID%20Standard.pdf
294 *
295 * following table contains default edid
296 * static char edid_raw_data[128] = {
297 * 0, 255, 255, 255, 255, 255, 255, 0,
298 * 6, 175, 93, 48, 0, 0, 0, 0, 0, 22,
299 * 1, 4,
300 * 149, 26, 14, 120, 2,
301 * 164, 21,158, 85, 78, 155, 38, 15, 80, 84,
302 * 0, 0, 0,
303 * 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
304 * 29, 54, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
305 * 19, 36, 128, 160, 112, 56, 30, 64, 48, 32, 142, 0, 0, 144, 16,0,0,24,
306 * 0, 0, 0, 254, 0, 65, 85, 79, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
307 * 0, 0, 0, 254, 0, 66, 49, 49, 54, 72, 65, 78, 48, 51, 46, 48, 32, 10,
308 * 0, 75 };
309 */
310
311static int edp_aux_chan_ready(struct edp_aux_ctrl *ep)
312{
313 int cnt, ret;
314 char data = 0;
315
316 cnt = 5;
317 while(cnt--) {
318 ret = edp_aux_write_buf(ep, 0x50, &data, 1, 1);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700319 dprintf(SPEW, "%s: ret=%d\n", __func__, ret);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700320 if (ret >= 0)
321 break;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700322 dprintf(INFO, "%s: failed in write\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700323 mdelay(100);
324 }
325
326 if (cnt == 0)
327 return 0;
328
329 return 1;
330}
331
332static int edp_sink_edid_read(struct edp_aux_ctrl *ep, int block)
333{
334 struct edp_buf *rp;
335 int cnt, rlen;
336 char data = 0;
337 int ret = 0;
338
339start:
340 cnt = 5;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700341 dprintf(SPEW, "%s: cnt=%d\n", __func__, cnt);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700342 /* need to write a dummy byte before read edid */
343 while(cnt--) {
344 ret = edp_aux_write_buf(ep, 0x50, &data, 1, 1);
345 if (ret >= 0)
346 break;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700347 dprintf(INFO, "%s: failed in write\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700348 mdelay(100);
349 }
350
351 if (cnt == 0)
352 return -1;
353
354 rlen = edp_aux_read_buf(ep, 0x50, 128, 1);
355
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700356 dprintf(SPEW, "%s: rlen=%d\n", rlen, __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700357
358 if (rlen < 0)
359 goto start;
360
361 rp = &ep->rxp;
362 if (edp_edid_buf_error(rp->data, rp->len))
363 goto start;
364
365 edp_extract_edid_manufacturer(&ep->edid, rp->data);
366 edp_extract_edid_product(&ep->edid, rp->data);
367 edp_extract_edid_version(&ep->edid, rp->data);
368 edp_extract_edid_ext_block_cnt(&ep->edid, rp->data);
369 edp_extract_edid_video_support(&ep->edid, rp->data);
370 edp_extract_edid_feature(&ep->edid, rp->data);
371 edp_extract_edid_detailed_timing_description(&ep->edid, rp->data);
372
373 return 128;
374}
375
376/*
377 * Converts from EDID struct to msm_panel_info
378 */
379void edp_edid2pinfo(struct msm_panel_info *pinfo)
380{
381 struct display_timing_desc *dp;
382
383 dp = &edpctrl.edid.timing[0];
384
385 pinfo->clk_rate = dp->pclk;
386
387 dprintf(SPEW, "%s: pclk=%d\n", __func__, pinfo->clk_rate);
388
389 pinfo->xres = dp->h_addressable + dp->h_border * 2;
390 pinfo->yres = dp->v_addressable + dp->v_border * 2;
391
392 pinfo->lcdc.h_back_porch = dp->h_blank - dp->h_fporch \
393 - dp->h_sync_pulse;
394 pinfo->lcdc.h_front_porch = dp->h_fporch;
395 pinfo->lcdc.h_pulse_width = dp->h_sync_pulse;
396
397 pinfo->lcdc.v_back_porch = dp->v_blank - dp->v_fporch \
398 - dp->v_sync_pulse;
399 pinfo->lcdc.v_front_porch = dp->v_fporch;
400 pinfo->lcdc.v_pulse_width = dp->v_sync_pulse;
401
402 pinfo->type = EDP_PANEL;
403 pinfo->wait_cycle = 0;
404 pinfo->bpp = 24;
405
406 pinfo->lcdc.border_clr = 0; /* black */
407 pinfo->lcdc.underflow_clr = 0xff; /* blue */
408 pinfo->lcdc.hsync_skew = 0;
409}
410
411void edp_cap2pinfo(struct msm_panel_info *pinfo)
412{
413 struct dpcd_cap *cap;
414
415 cap = &edpctrl.dpcd;
416
417 pinfo->edp.max_lane_count = cap->max_lane_count;
418 pinfo->edp.max_link_clk = cap->max_link_rate;
419
420 dprintf(SPEW, "%s: clk=%d lane=%d\n", __func__,
421 pinfo->edp.max_lane_count, pinfo->edp.max_link_clk);
422}
423
424static void edp_sink_capability_read(struct edp_aux_ctrl *ep,
425 int len)
426{
427 char *bp;
428 char data;
429 struct dpcd_cap *cap;
430 struct edp_buf *rp;
431 int rlen;
432
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700433 dprintf(SPEW, "%s:\n",__func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700434
435 rlen = edp_aux_read_buf(ep, 0, len, 0);
436 if (rlen <= 0) {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700437 dprintf(INFO, "%s: edp aux read failed\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700438 return;
439 }
440 rp = &ep->rxp;
441 cap = &ep->dpcd;
442 bp = rp->data;
443
444 data = *bp++; /* byte 0 */
445 cap->major = (data >> 4) & 0x0f;
446 cap->minor = data & 0x0f;
447 if (--rlen <= 0)
448 return;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700449 dprintf(SPEW, "%s: version: %d.%d\n", __func__, cap->major, cap->minor);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700450
451 data = *bp++; /* byte 1 */
452 /* 162, 270 and 540 MB, symbol rate, NOT bit rate */
453 cap->max_link_rate = data * 27;
454 if (--rlen <= 0)
455 return;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700456 dprintf(SPEW, "%s: link_rate=%d\n", __func__, cap->max_link_rate);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700457
458 data = *bp++; /* byte 2 */
459 if (data & BIT(7))
460 cap->flags |= DPCD_ENHANCED_FRAME;
461 if (data & 0x40)
462 cap->flags |= DPCD_TPS3;
463 data &= 0x0f;
464 cap->max_lane_count = data;
465 if (--rlen <= 0)
466 return;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700467 dprintf(SPEW, "%s: lane_count=%d\n", __func__, cap->max_lane_count);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700468
469 data = *bp++; /* byte 3 */
470 if (data & BIT(0)) {
471 cap->flags |= DPCD_MAX_DOWNSPREAD_0_5;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700472 dprintf(SPEW, "%s: max_downspread\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700473 }
474
475 if (data & BIT(6)) {
476 cap->flags |= DPCD_NO_AUX_HANDSHAKE;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700477 dprintf(SPEW, "%s: NO Link Training\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700478 }
479 if (--rlen <= 0)
480 return;
481
482 data = *bp++; /* byte 4 */
483 cap->num_rx_port = (data & BIT(0)) + 1;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700484 dprintf(SPEW, "%s: rx_ports=%d", __func__, cap->num_rx_port);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700485 if (--rlen <= 0)
486 return;
487
488 bp += 3; /* skip 5, 6 and 7 */
489 rlen -= 3;
490 if (rlen <= 0)
491 return;
492
493 data = *bp++; /* byte 8 */
494 if (data & BIT(1)) {
495 cap->flags |= DPCD_PORT_0_EDID_PRESENTED;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700496 dprintf(SPEW, "%s: edid presented\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700497 }
498 if (--rlen <= 0)
499 return;
500
501 data = *bp++; /* byte 9 */
502 cap->rx_port0_buf_size = (data + 1) * 32;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700503 dprintf(SPEW, "%s: lane_buf_size=%d", __func__, cap->rx_port0_buf_size);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700504 if (--rlen <= 0)
505 return;
506
507 bp += 2; /* skip 10, 11 port1 capability */
508 rlen -= 2;
509 if (rlen <= 0)
510 return;
511
512 data = *bp++; /* byte 12 */
513 cap->i2c_speed_ctrl = data;
514 if (cap->i2c_speed_ctrl > 0)
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700515 dprintf(SPEW, "%s: i2c_rate=%d", __func__, cap->i2c_speed_ctrl);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700516 if (--rlen <= 0)
517 return;
518
519 data = *bp++; /* byte 13 */
520 cap->scrambler_reset = data & BIT(0);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700521 dprintf(SPEW, "%s: scrambler_reset=%d\n", __func__,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700522 cap->scrambler_reset);
523
524 cap->enhanced_frame = data & BIT(1);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700525 dprintf(SPEW, "%s: enhanced_framing=%d\n", __func__,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700526 cap->enhanced_frame);
527 if (--rlen <= 0)
528 return;
529
530 data = *bp++; /* byte 14 */
531 if (data == 0)
532 cap->training_read_interval = 100; /* us */
533 else
534 cap->training_read_interval = 4000 * data; /* us */
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700535 dprintf(SPEW, "%s: training_interval=%d\n", __func__,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700536 cap->training_read_interval);
537}
538
539static void edp_link_status_read(struct edp_aux_ctrl *ep, int len)
540{
541 char *bp;
542 char data;
543 struct dpcd_link_status *sp;
544 struct edp_buf *rp;
545 int rlen;
546
547
548 /* skip byte 0x200 and 0x201 */
549 rlen = edp_aux_read_buf(ep, 0x202, len, 0);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700550 dprintf(SPEW, "%s: rlen=%d\n", __func__, rlen);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700551 if (rlen <= 0) {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700552 dprintf(SPEW, "%s: edp aux read failed\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700553 return;
554 }
555 rp = &ep->rxp;
556 bp = rp->data;
557 sp = &ep->link_status;
558
559 data = *bp++; /* byte 0x202 */
560 sp->lane_01_status = data; /* lane 0, 1 */
561 if (--rlen <= 0)
562 return;
563
564 data = *bp++; /* byte 0x203 */
565 sp->lane_23_status = data; /* lane 2, 3 */
566 if (--rlen <= 0)
567 return;
568
569 data = *bp++; /* byte 0x204 */
570 sp->interlane_align_done = (data & BIT(0));
571 sp->downstream_port_status_changed = (data & BIT(6));
572 sp->link_status_updated = (data & BIT(7));
573 if (--rlen <= 0)
574 return;
575
576 data = *bp++; /* byte 0x205 */
577 sp->port_0_in_sync = (data & BIT(0));
578 sp->port_1_in_sync = (data & BIT(1));
579 if (--rlen <= 0)
580 return;
581
582 data = *bp++; /* byte 0x206 */
583 sp->req_voltage_swing[0] = data & 0x03;
584 data >>= 2;
585 sp->req_pre_emphasis[0] = data & 0x03;
586 data >>= 2;
587 sp->req_voltage_swing[1] = data & 0x03;
588 data >>= 2;
589 sp->req_pre_emphasis[1] = data & 0x03;
590 if (--rlen <= 0)
591 return;
592
593 data = *bp++; /* byte 0x207 */
594 sp->req_voltage_swing[2] = data & 0x03;
595 data >>= 2;
596 sp->req_pre_emphasis[2] = data & 0x03;
597 data >>= 2;
598 sp->req_voltage_swing[3] = data & 0x03;
599 data >>= 2;
600 sp->req_pre_emphasis[3] = data & 0x03;
601
602 bp = rp->data;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700603 dprintf(SPEW, "%s: %x %x %x %x %x %x\n", __func__, *bp,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700604 *(bp+1), *(bp+2), *(bp+3), *(bp+4), *(bp+5));
605
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700606 dprintf(SPEW, "%s: align=%d v=%d p=%d\n", __func__,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700607 sp->interlane_align_done, sp->req_voltage_swing[0], sp->req_pre_emphasis[0]);
608}
609
610
611static int edp_cap_lane_rate_set(struct edp_aux_ctrl *ep)
612{
613 char buf[4];
614 int len = 0;
615
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700616 dprintf(SPEW, "%s: bw=%x lane=%d\n", __func__,
617 ep->link_rate, ep->lane_cnt);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700618 buf[0] = ep->link_rate;
619 buf[1] = ep->lane_cnt;
620 len = edp_aux_write_buf(ep, 0x100, buf, 2, 0);
621
622 return len;
623}
624
625static int edp_lane_set_write(struct edp_aux_ctrl *ep, int voltage_level,
626 int pre_emphasis_level)
627{
628 int i;
629 char buf[4];
630
631
632 if (voltage_level >= DPCD_LINK_VOLTAGE_MAX)
633 voltage_level |= 0x04;
634
635 if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX)
636 pre_emphasis_level |= 0x04;
637
638 pre_emphasis_level <<= 3;
639
640 for (i = 0; i < 4; i++)
641 buf[i] = voltage_level | pre_emphasis_level;
642
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700643 dprintf(SPEW, "%s: p|v=0x%x\n", __func__, voltage_level | pre_emphasis_level);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700644 return edp_aux_write_buf(ep, 0x103, buf, 4, 0);
645}
646
647static int edp_powerstate_write(struct edp_aux_ctrl *ep,
648 char powerstate)
649{
650 return edp_aux_write_buf(ep, 0x600, &powerstate, 1, 0);
651}
652
653static int edp_train_pattern_set_write(struct edp_aux_ctrl *ep,
654 int pattern)
655{
656 char buf[4];
657
658 buf[0] = pattern;
659 return edp_aux_write_buf(ep, 0x102, buf, 1, 0);
660}
661
662static int edp_sink_clock_recovery_done(struct edp_aux_ctrl *ep)
663{
664 int mask;
665 int data;
666
667
668 if (ep->lane_cnt == 1) {
669 mask = 0x01; /* lane 0 */
670 data = ep->link_status.lane_01_status;
671 } else if (ep->lane_cnt == 2) {
672 mask = 0x011; /*B lane 0, 1 */
673 data = ep->link_status.lane_01_status;
674 } else {
675 mask = 0x01111; /*B lane 0, 1 */
676 data = ep->link_status.lane_23_status;
677 data <<= 8;
678 data |= ep->link_status.lane_01_status;
679 }
680
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700681 dprintf(SPEW, "%s: data=%x mask=%x\n", __func__, data, mask);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700682 data &= mask;
683 if (data == mask) /* all done */
684 return 1;
685
686 return 0;
687}
688
689static int edp_sink_channel_eq_done(struct edp_aux_ctrl *ep)
690{
691 int mask;
692 int data;
693
694
695 if (!ep->link_status.interlane_align_done) /* not align */
696 return 0;
697
698 if (ep->lane_cnt == 1) {
699 mask = 0x7;
700 data = ep->link_status.lane_01_status;
701 } else if (ep->lane_cnt == 2) {
702 mask = 0x77;
703 data = ep->link_status.lane_01_status;
704 } else {
705 mask = 0x7777;
706 data = ep->link_status.lane_23_status;
707 data <<= 8;
708 data |= ep->link_status.lane_01_status;
709 }
710
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700711 dprintf(SPEW, "%s: data=%x mask=%x\n", __func__, data, mask);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700712
713 data &= mask;
714 if (data == mask)/* all done */
715 return 1;
716
717 return 0;
718}
719
720void edp_sink_train_set_adjust(struct edp_aux_ctrl *ep)
721{
722 int i;
723 int max = 0;
724
725
726 /* use the max level across lanes */
727 for (i = 0; i < ep->lane_cnt; i++) {
728 if (max < ep->link_status.req_voltage_swing[i])
729 max = ep->link_status.req_voltage_swing[i];
730 }
731
732 ep->v_level = max;
733
734 /* use the max level across lanes */
735 max = 0;
736 for (i = 0; i < ep->lane_cnt; i++) {
737 if (max < ep->link_status.req_pre_emphasis[i])
738 max = ep->link_status.req_pre_emphasis[i];
739 }
740
741 ep->p_level = max;
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700742 dprintf(SPEW, "%s: v_level=%d, p_level=%d\n", __func__,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700743 ep->v_level, ep->p_level);
744}
745
746static void edp_host_train_set(struct edp_aux_ctrl *ep, int train)
747{
748 int bit, cnt;
749 int data;
750
751
752 bit = 1;
753 bit <<= (train - 1);
754 edp_write(EDP_BASE + EDP_STATE_CTRL, bit);
755
756 bit = 8;
757 bit <<= (train - 1);
758 cnt = 10;
759 while (cnt--) {
760 data = edp_read(EDP_BASE + EDP_MAINLINK_READY);
761 if (data & bit)
762 break;
763 }
764
765 if (cnt == 0)
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700766 dprintf(SPEW, "%s: set link_train=%d failed\n", __func__, train);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700767}
768
769char vm_pre_emphasis[4][4] = {
770 {0x03, 0x06, 0x09, 0x0C},
771 {0x03, 0x06, 0x09, 0xFF},
772 {0x03, 0x06, 0xFF, 0xFF},
773 {0x03, 0xFF, 0xFF, 0xFF}
774};
775
776char vm_voltage_swing[4][4] = {
777 {0x64, 0x68, 0x6A, 0x6E},
778 {0x68, 0x6A, 0x6E, 0xFF},
779 {0x6A, 0x6E, 0xFF, 0xFF},
780 {0x6E, 0xFF, 0xFF, 0xFF}
781};
782
783static void edp_voltage_pre_emphasise_set(struct edp_aux_ctrl *ep)
784{
785 int value0 = 0;
786 int value1 = 0;
787
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700788 dprintf(SPEW, "%s: v=%d p=%d\n", __func__, ep->v_level, ep->p_level);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700789
790 value0 = vm_pre_emphasis[(int)(ep->v_level)][(int)(ep->p_level)];
791 value1 = vm_voltage_swing[(int)(ep->v_level)][(int)(ep->p_level)];
792
793 /* Configure host and panel only if both values are allowed */
794 if (value0 != 0xFF && value1 != 0xFF) {
795 edp_write(EDP_BASE + EDP_PHY_EDPPHY_GLB_VM_CFG0, value0);
796 edp_write(EDP_BASE + EDP_PHY_EDPPHY_GLB_VM_CFG1, value1);
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700797 dprintf(SPEW, "%s: value0=0x%x value1=0x%x\n", __func__,
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700798 value0, value1);
799 edp_lane_set_write(ep, ep->v_level, ep->p_level);
800 }
801
802}
803
804static int edp_start_link_train_1(struct edp_aux_ctrl *ep)
805{
806 int tries, old_v_level;
807 int ret = 0;
808
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700809 dprintf(SPEW, "%s:\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700810
811 edp_host_train_set(ep, 0x01); /* train_1 */
812 edp_voltage_pre_emphasise_set(ep);
813 edp_train_pattern_set_write(ep, 0x21); /* train_1 */
814
815 tries = 0;
816 old_v_level = ep->v_level;
817 while (1) {
818 udelay(ep->dpcd.training_read_interval * 10);
819
820 edp_link_status_read(ep, 6);
821 if (edp_sink_clock_recovery_done(ep)) {
822 ret = 0;
823 break;
824 }
825
826 if (ep->v_level == DPCD_LINK_VOLTAGE_MAX) {
827 ret = -1;
828 break; /* quit */
829 }
830
831 if (old_v_level == ep->v_level) {
832 tries++;
833 if (tries >= 5) {
834 ret = -1;
835 break; /* quit */
836 }
837 } else {
838 tries = 0;
839 old_v_level = ep->v_level;
840 }
841
842 edp_sink_train_set_adjust(ep);
843 edp_voltage_pre_emphasise_set(ep);
844 }
845
846 return ret;
847}
848
849static int edp_start_link_train_2(struct edp_aux_ctrl *ep)
850{
851 int tries;
852 int ret = 0;
853 char pattern;
854
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700855 dprintf(SPEW, "%s\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700856
857 if (ep->dpcd.flags & DPCD_TPS3)
858 pattern = 0x03;
859 else
860 pattern = 0x02;
861
862 edp_host_train_set(ep, pattern); /* train_2 */
863 edp_voltage_pre_emphasise_set(ep);
864 edp_train_pattern_set_write(ep, pattern | 0x20);/* train_2 */
865
866 tries = 0;
867 while (1) {
868 udelay(ep->dpcd.training_read_interval);
869
870 edp_link_status_read(ep, 6);
871
872 if (edp_sink_channel_eq_done(ep)) {
873 ret = 0;
874 break;
875 }
876
877 tries++;
878 if (tries > 5) {
879 ret = -1;
880 break;
881 }
882
883 edp_sink_train_set_adjust(ep);
884 edp_voltage_pre_emphasise_set(ep);
885 }
886
887 return ret;
888}
889
890static int edp_link_rate_shift(struct edp_aux_ctrl *ep)
891{
892 /* add calculation later */
893 return -1;
894}
895
896static void edp_clear_training_pattern(struct edp_aux_ctrl *ep)
897{
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700898 dprintf(SPEW, "%s:\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700899 edp_write(EDP_BASE + EDP_STATE_CTRL, 0);
900 edp_train_pattern_set_write(ep, 0);
901 udelay(ep->dpcd.training_read_interval);
902}
903
904static int edp_aux_link_train(struct edp_aux_ctrl *ep)
905{
906 int ret = 0;
907
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700908 dprintf(SPEW, "%s:\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700909 ret = edp_aux_chan_ready(ep);
910 if (ret == 0) {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700911 dprintf(INFO, "%s: Error: aux chan NOT ready\n",
912 __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700913 return ret;
914 }
915
916 /* start with max rate and lane */
917 ep->lane_cnt = ep->dpcd.max_lane_count;
918 ep->link_rate = ep->dpcd.max_link_rate;
919 edp_write(EDP_BASE + EDP_MAINLINK_CTRL, 0x1);
920
921train_start:
922 ep->v_level = 0; /* start from default level */
923 ep->p_level = 0;
924 edp_cap_lane_rate_set(ep);
925
926 edp_clear_training_pattern(ep);
927 udelay(ep->dpcd.training_read_interval);
928 edp_powerstate_write(ep, 1);
929
930 ret = edp_start_link_train_1(ep);
931 if (ret < 0) {
932 if (edp_link_rate_shift(ep) == 0) {
933 goto train_start;
934 } else {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700935 dprintf(INFO, "%s: Training 1 failed\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700936 ret = -1;
937 goto clear;
938 }
939 }
940
941 dprintf(INFO, "%s: Training 1 completed successfully\n", __func__);
942
943 edp_clear_training_pattern(ep);
944 ret = edp_start_link_train_2(ep);
945 if (ret < 0) {
946 if (edp_link_rate_shift(ep) == 0) {
947 goto train_start;
948 } else {
Kuogee Hsiehe3b50dd2013-09-25 14:40:25 -0700949 dprintf(INFO, "%s: Training 2 failed\n", __func__);
Kuogee Hsiehad69c3c2013-08-01 14:34:29 -0700950 ret = -1;
951 goto clear;
952 }
953 }
954
955 dprintf(INFO, "%s: Training 2 completed successfully\n", __func__);
956
957clear:
958 edp_clear_training_pattern(ep);
959
960 return ret;
961}
962
963void mdss_edp_wait_for_hpd(void)
964{
965 while(1) {
966 udelay(1000);
967 edp_isr_poll();
968 if (edp_hpd_done) {
969 edp_hpd_done = 0;
970 break;
971 }
972 }
973}
974
975void mdss_edp_wait_for_video_ready(void)
976{
977 while(1) {
978 udelay(1000);
979 edp_isr_poll();
980 if (edp_video_ready) {
981 edp_video_ready = 0;
982 break;
983 }
984 }
985}
986
987void mdss_edp_dpcd_cap_read(void)
988{
989 edp_sink_capability_read(&edpctrl, 16);
990}
991void mdss_edp_pll_configure(void)
992{
993 struct display_timing_desc *dp;
994
995 dp = &edpctrl.edid.timing[0];
996 edp_pll_configure(dp->pclk);
997}
998
999void mdss_edp_lane_power_ctrl(int up)
1000{
1001
1002 dprintf(SPEW, "%s: max_lane=%d\n", __func__, edpctrl.dpcd.max_lane_count);
1003 edp_lane_power_ctrl(edpctrl.dpcd.max_lane_count, up);
1004
1005}
1006
1007void mdss_edp_dpcd_status_read(void)
1008{
1009 edp_link_status_read(&edpctrl, 6);
1010}
1011
1012void mdss_edp_edid_read(void)
1013{
1014 edp_sink_edid_read(&edpctrl, 0);
1015}
1016
1017int mdss_edp_link_train(void)
1018{
1019 return edp_aux_link_train(&edpctrl);
1020}
1021
1022void mdss_edp_aux_init(void)
1023{
1024 edp_buf_init(&edpctrl.txp, edpctrl.txbuf, sizeof(edpctrl.txbuf));
1025 edp_buf_init(&edpctrl.rxp, edpctrl.rxbuf, sizeof(edpctrl.rxbuf));
1026}