soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / drivers / analogix / anx7625 / anx7625.c
blobe3a511131f0b38f1ab6636e0bfa96f820e528f72
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <delay.h>
5 #include <device/i2c_simple.h>
6 #include <edid.h>
7 #include <gpio.h>
8 #include <string.h>
9 #include <types.h>
11 #include "anx7625.h"
13 #define ANXERROR(format, ...) \
14 printk(BIOS_ERR, "%s: " format, __func__, ##__VA_ARGS__)
15 #define ANXINFO(format, ...) \
16 printk(BIOS_INFO, "%s: " format, __func__, ##__VA_ARGS__)
17 #define ANXDEBUG(format, ...) \
18 printk(BIOS_DEBUG, "%s: " format, __func__, ##__VA_ARGS__)
21 * There is a sync issue while accessing I2C register between AP(CPU) and
22 * internal firmware(OCM). To avoid the race condition, AP should access the
23 * reserved slave address before slave address changes.
25 static int i2c_access_workaround(uint8_t bus, uint8_t saddr)
27 uint8_t offset;
28 static uint8_t saddr_backup = 0;
29 int ret = 0;
31 if (saddr == saddr_backup)
32 return ret;
34 saddr_backup = saddr;
36 switch (saddr) {
37 case TCPC_INTERFACE_ADDR:
38 offset = RSVD_00_ADDR;
39 break;
40 case TX_P0_ADDR:
41 offset = RSVD_D1_ADDR;
42 break;
43 case TX_P1_ADDR:
44 offset = RSVD_60_ADDR;
45 break;
46 case RX_P0_ADDR:
47 offset = RSVD_39_ADDR;
48 break;
49 case RX_P1_ADDR:
50 offset = RSVD_7F_ADDR;
51 break;
52 default:
53 offset = RSVD_00_ADDR;
54 break;
57 ret = i2c_writeb(bus, saddr, offset, 0x00);
58 if (ret < 0) {
59 ANXERROR("Failed to access %#x:%#x\n", saddr, offset);
60 return ret;
62 return 0;
65 static int anx7625_reg_read(uint8_t bus, uint8_t saddr, uint8_t offset,
66 uint8_t *val)
68 int ret;
70 i2c_access_workaround(bus, saddr);
71 ret = i2c_readb(bus, saddr, offset, val);
72 if (ret < 0) {
73 ANXERROR("Failed to read i2c reg=%#x:%#x\n", saddr, offset);
74 return ret;
76 return 0;
79 static int anx7625_reg_block_read(uint8_t bus, uint8_t saddr, uint8_t reg_addr,
80 uint8_t len, uint8_t *buf)
82 int ret;
84 i2c_access_workaround(bus, saddr);
85 ret = i2c_read_bytes(bus, saddr, reg_addr, buf, len);
86 if (ret < 0) {
87 ANXERROR("Failed to read i2c block=%#x:%#x[len=%#x]\n", saddr,
88 reg_addr, len);
89 return ret;
91 return 0;
94 static int anx7625_reg_write(uint8_t bus, uint8_t saddr, uint8_t reg_addr,
95 uint8_t reg_val)
97 int ret;
99 i2c_access_workaround(bus, saddr);
100 ret = i2c_writeb(bus, saddr, reg_addr, reg_val);
101 if (ret < 0) {
102 ANXERROR("Failed to write i2c id=%#x:%#x\n", saddr, reg_addr);
103 return ret;
105 return 0;
108 static int anx7625_write_or(uint8_t bus, uint8_t saddr, uint8_t offset,
109 uint8_t mask)
111 uint8_t val;
112 int ret;
114 ret = anx7625_reg_read(bus, saddr, offset, &val);
115 if (ret < 0)
116 return ret;
118 return anx7625_reg_write(bus, saddr, offset, val | mask);
121 static int anx7625_write_and(uint8_t bus, uint8_t saddr, uint8_t offset,
122 uint8_t mask)
124 int ret;
125 uint8_t val;
127 ret = anx7625_reg_read(bus, saddr, offset, &val);
128 if (ret < 0)
129 return ret;
131 return anx7625_reg_write(bus, saddr, offset, val & mask);
134 static int wait_aux_op_finish(uint8_t bus)
136 uint8_t val;
137 int ret;
139 if (!retry(150,
140 (anx7625_reg_read(bus, RX_P0_ADDR, AP_AUX_CTRL_STATUS, &val),
141 !(val & AP_AUX_CTRL_OP_EN)), mdelay(2))) {
142 ANXERROR("Timed out waiting aux operation.\n");
143 return -1;
146 ret = anx7625_reg_read(bus, RX_P0_ADDR, AP_AUX_CTRL_STATUS, &val);
147 if (ret < 0 || val & 0x0F) {
148 ANXDEBUG("aux status %02x\n", val);
149 return -1;
152 return 0;
155 static unsigned long gcd(unsigned long a, unsigned long b)
157 if (a == 0)
158 return b;
160 while (b != 0) {
161 if (a > b)
162 a = a - b;
163 else
164 b = b - a;
167 return a;
170 /* Reduce fraction a/b */
171 static void anx7625_reduction_of_a_fraction(unsigned long *_a,
172 unsigned long *_b)
174 unsigned long gcd_num;
175 unsigned long a = *_a, b = *_b, old_a, old_b;
176 u32 denom = 1;
178 gcd_num = gcd(a, b);
179 a /= gcd_num;
180 b /= gcd_num;
182 old_a = a;
183 old_b = b;
185 while (a > MAX_UNSIGNED_24BIT || b > MAX_UNSIGNED_24BIT) {
186 denom++;
187 a = old_a / denom;
188 b = old_b / denom;
191 /* Increase a, b to have higher ODFC PLL output frequency accuracy. */
192 while ((a << 1) < MAX_UNSIGNED_24BIT && (b << 1) < MAX_UNSIGNED_24BIT) {
193 a <<= 1;
194 b <<= 1;
197 *_a = a;
198 *_b = b;
201 static int anx7625_calculate_m_n(u32 pixelclock,
202 unsigned long *m, unsigned long *n,
203 uint8_t *pd)
205 uint8_t post_divider = *pd;
206 if (pixelclock > PLL_OUT_FREQ_ABS_MAX / POST_DIVIDER_MIN) {
207 /* pixel clock frequency is too high */
208 ANXERROR("pixelclock %u higher than %lu, "
209 "output may be unstable\n",
210 pixelclock, PLL_OUT_FREQ_ABS_MAX / POST_DIVIDER_MIN);
211 return -1;
214 if (pixelclock < PLL_OUT_FREQ_ABS_MIN / POST_DIVIDER_MAX) {
215 /* pixel clock frequency is too low */
216 ANXERROR("pixelclock %u lower than %lu, "
217 "output may be unstable\n",
218 pixelclock, PLL_OUT_FREQ_ABS_MIN / POST_DIVIDER_MAX);
219 return -1;
222 post_divider = 1;
224 for (post_divider = 1;
225 pixelclock < PLL_OUT_FREQ_MIN / post_divider;
226 post_divider++)
229 if (post_divider > POST_DIVIDER_MAX) {
230 for (post_divider = 1;
231 pixelclock < PLL_OUT_FREQ_ABS_MIN / post_divider;
232 post_divider++)
235 if (post_divider > POST_DIVIDER_MAX) {
236 ANXERROR("cannot find property post_divider(%d)\n",
237 post_divider);
238 return -1;
242 /* Patch to improve the accuracy */
243 if (post_divider == 7) {
244 /* 27,000,000 is not divisible by 7 */
245 post_divider = 8;
246 } else if (post_divider == 11) {
247 /* 27,000,000 is not divisible by 11 */
248 post_divider = 12;
249 } else if (post_divider == 13 || post_divider == 14) {
250 /*27,000,000 is not divisible by 13 or 14*/
251 post_divider = 15;
254 if (pixelclock * post_divider > PLL_OUT_FREQ_ABS_MAX) {
255 ANXINFO("act clock(%u) large than maximum(%lu)\n",
256 pixelclock * post_divider, PLL_OUT_FREQ_ABS_MAX);
257 return -1;
260 *m = pixelclock;
261 *n = XTAL_FRQ / post_divider;
262 *pd = post_divider;
264 anx7625_reduction_of_a_fraction(m, n);
266 return 0;
269 static int anx7625_odfc_config(uint8_t bus, uint8_t post_divider)
271 int ret;
273 /* config input reference clock frequency 27MHz/19.2MHz */
274 ret = anx7625_write_and(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_16,
275 ~(REF_CLK_27000kHz << MIPI_FREF_D_IND));
276 ret |= anx7625_write_or(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_16,
277 (REF_CLK_27000kHz << MIPI_FREF_D_IND));
278 /* post divider */
279 ret |= anx7625_write_and(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_8, 0x0f);
280 ret |= anx7625_write_or(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_8,
281 post_divider << 4);
283 /* add patch for MIS2-125 (5pcs ANX7625 fail ATE MBIST test) */
284 ret |= anx7625_write_and(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_7,
285 ~MIPI_PLL_VCO_TUNE_REG_VAL);
287 /* reset ODFC PLL */
288 ret |= anx7625_write_and(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_7,
289 ~MIPI_PLL_RESET_N);
290 ret |= anx7625_write_or(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_7,
291 MIPI_PLL_RESET_N);
293 if (ret < 0) {
294 ANXERROR("IO error.\n");
295 return ret;
298 return 0;
301 static int anx7625_dsi_video_config(uint8_t bus, struct display_timing *dt)
303 unsigned long m, n;
304 u16 htotal;
305 int ret;
306 uint8_t post_divider = 0;
308 if (anx7625_calculate_m_n(dt->pixelclock * 1000, &m, &n,
309 &post_divider) < 0) {
310 ANXERROR("cannot get property m n value.\n");
311 return -1;
314 ANXINFO("compute M(%lu), N(%lu), divider(%d).\n", m, n, post_divider);
316 /* configure pixel clock */
317 ret = anx7625_reg_write(bus, RX_P0_ADDR, PIXEL_CLOCK_L,
318 (dt->pixelclock / 1000) & 0xFF);
319 ret |= anx7625_reg_write(bus, RX_P0_ADDR, PIXEL_CLOCK_H,
320 (dt->pixelclock / 1000) >> 8);
321 /* lane count */
322 ret |= anx7625_write_and(bus, RX_P1_ADDR, MIPI_LANE_CTRL_0, 0xfc);
324 ret |= anx7625_write_or(bus, RX_P1_ADDR, MIPI_LANE_CTRL_0, 3);
326 /* Htotal */
327 htotal = dt->hactive + dt->hfront_porch +
328 dt->hback_porch + dt->hsync_len;
329 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
330 HORIZONTAL_TOTAL_PIXELS_L, htotal & 0xFF);
331 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
332 HORIZONTAL_TOTAL_PIXELS_H, htotal >> 8);
333 /* Hactive */
334 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
335 HORIZONTAL_ACTIVE_PIXELS_L, dt->hactive & 0xFF);
336 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
337 HORIZONTAL_ACTIVE_PIXELS_H, dt->hactive >> 8);
338 /* HFP */
339 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
340 HORIZONTAL_FRONT_PORCH_L, dt->hfront_porch);
341 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
342 HORIZONTAL_FRONT_PORCH_H,
343 dt->hfront_porch >> 8);
344 /* HWS */
345 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
346 HORIZONTAL_SYNC_WIDTH_L, dt->hsync_len);
347 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
348 HORIZONTAL_SYNC_WIDTH_H, dt->hsync_len >> 8);
349 /* HBP */
350 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
351 HORIZONTAL_BACK_PORCH_L, dt->hback_porch);
352 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
353 HORIZONTAL_BACK_PORCH_H, dt->hback_porch >> 8);
354 /* Vactive */
355 ret |= anx7625_reg_write(bus, RX_P2_ADDR, ACTIVE_LINES_L, dt->vactive);
356 ret |= anx7625_reg_write(bus, RX_P2_ADDR, ACTIVE_LINES_H,
357 dt->vactive >> 8);
358 /* VFP */
359 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
360 VERTICAL_FRONT_PORCH, dt->vfront_porch);
361 /* VWS */
362 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
363 VERTICAL_SYNC_WIDTH, dt->vsync_len);
364 /* VBP */
365 ret |= anx7625_reg_write(bus, RX_P2_ADDR,
366 VERTICAL_BACK_PORCH, dt->vback_porch);
367 /* M value */
368 ret |= anx7625_reg_write(bus, RX_P1_ADDR,
369 MIPI_PLL_M_NUM_23_16, (m >> 16) & 0xff);
370 ret |= anx7625_reg_write(bus, RX_P1_ADDR,
371 MIPI_PLL_M_NUM_15_8, (m >> 8) & 0xff);
372 ret |= anx7625_reg_write(bus, RX_P1_ADDR,
373 MIPI_PLL_M_NUM_7_0, (m & 0xff));
374 /* N value */
375 ret |= anx7625_reg_write(bus, RX_P1_ADDR,
376 MIPI_PLL_N_NUM_23_16, (n >> 16) & 0xff);
377 ret |= anx7625_reg_write(bus, RX_P1_ADDR,
378 MIPI_PLL_N_NUM_15_8, (n >> 8) & 0xff);
379 ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_PLL_N_NUM_7_0,
380 (n & 0xff));
381 /* diff */
382 ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_DIGITAL_ADJ_1, dt->k_val);
384 ret |= anx7625_odfc_config(bus, post_divider - 1);
386 if (ret < 0) {
387 ANXERROR("mipi dsi setup IO error.\n");
388 return ret;
391 return 0;
394 static int anx7625_swap_dsi_lane3(uint8_t bus)
396 int ret;
397 uint8_t val;
399 /* swap MIPI-DSI data lane 3 P and N */
400 ret = anx7625_reg_read(bus, RX_P1_ADDR, MIPI_SWAP, &val);
401 if (ret < 0) {
402 ANXERROR("IO error: access MIPI_SWAP.\n");
403 return ret;
406 val |= (1 << MIPI_SWAP_CH3);
407 return anx7625_reg_write(bus, RX_P1_ADDR, MIPI_SWAP, val);
410 static int anx7625_api_dsi_config(uint8_t bus, struct display_timing *dt)
413 int val, ret;
415 /* swap MIPI-DSI data lane 3 P and N */
416 ret = anx7625_swap_dsi_lane3(bus);
417 if (ret < 0) {
418 ANXERROR("IO error: swap dsi lane 3 failed.\n");
419 return ret;
422 /* DSI clock settings */
423 val = (0 << MIPI_HS_PWD_CLK) |
424 (0 << MIPI_HS_RT_CLK) |
425 (0 << MIPI_PD_CLK) |
426 (1 << MIPI_CLK_RT_MANUAL_PD_EN) |
427 (1 << MIPI_CLK_HS_MANUAL_PD_EN) |
428 (0 << MIPI_CLK_DET_DET_BYPASS) |
429 (0 << MIPI_CLK_MISS_CTRL) |
430 (0 << MIPI_PD_LPTX_CH_MANUAL_PD_EN);
431 ret = anx7625_reg_write(bus, RX_P1_ADDR, MIPI_PHY_CONTROL_3, val);
434 * Decreased HS prepare tg delay from 160ns to 80ns work with
435 * a) Dragon board 810 series (Qualcomm AP)
436 * b) Moving Pixel DSI source (PG3A pattern generator +
437 * P332 D-PHY Probe) default D-PHY tg 5ns/step
439 ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_TIME_HS_PRPR, 0x10);
441 /* enable DSI mode */
442 ret |= anx7625_write_or(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_18,
443 SELECT_DSI << MIPI_DPI_SELECT);
445 ret |= anx7625_dsi_video_config(bus, dt);
446 if (ret < 0) {
447 ANXERROR("dsi video tg config failed\n");
448 return ret;
451 /* toggle m, n ready */
452 ret = anx7625_write_and(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_6,
453 ~(MIPI_M_NUM_READY | MIPI_N_NUM_READY));
454 mdelay(1);
455 ret |= anx7625_write_or(bus, RX_P1_ADDR, MIPI_DIGITAL_PLL_6,
456 MIPI_M_NUM_READY | MIPI_N_NUM_READY);
458 /* configure integer stable register */
459 ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_VIDEO_STABLE_CNT, 0x02);
460 /* power on MIPI RX */
461 ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_LANE_CTRL_10, 0x00);
462 ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_LANE_CTRL_10, 0x80);
464 if (ret < 0) {
465 ANXERROR("IO error: mipi dsi enable init failed.\n");
466 return ret;
469 return 0;
472 static int anx7625_dsi_config(uint8_t bus, struct display_timing *dt)
474 int ret;
476 ANXINFO("config dsi.\n");
478 /* DSC disable */
479 ret = anx7625_write_and(bus, RX_P0_ADDR, R_DSC_CTRL_0, ~DSC_EN);
480 ret |= anx7625_api_dsi_config(bus, dt);
482 if (ret < 0) {
483 ANXERROR("IO error: api dsi config error.\n");
484 return ret;
487 /* set MIPI RX EN */
488 ret = anx7625_write_or(bus, RX_P0_ADDR, AP_AV_STATUS, AP_MIPI_RX_EN);
489 /* clear mute flag */
490 ret |= anx7625_write_and(bus, RX_P0_ADDR, AP_AV_STATUS, ~AP_MIPI_MUTE);
492 if (ret < 0) {
493 ANXERROR("IO error: enable mipi rx failed.\n");
494 return ret;
497 ANXINFO("success to config DSI\n");
498 return 0;
501 static int sp_tx_rst_aux(uint8_t bus)
503 int ret;
505 ret = anx7625_write_or(bus, TX_P2_ADDR, RST_CTRL2, AUX_RST);
506 ret |= anx7625_write_and(bus, TX_P2_ADDR, RST_CTRL2, ~AUX_RST);
507 return ret;
510 static int sp_tx_aux_wr(uint8_t bus, uint8_t offset)
512 int ret;
514 ret = anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_BUFF_START, offset);
515 ret |= anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_COMMAND, 0x04);
516 ret |= anx7625_write_or(bus, RX_P0_ADDR,
517 AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
518 return ret | wait_aux_op_finish(bus);
521 static int sp_tx_aux_rd(uint8_t bus, uint8_t len_cmd)
523 int ret;
525 ret = anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_COMMAND, len_cmd);
526 ret |= anx7625_write_or(bus, RX_P0_ADDR,
527 AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
528 return ret | wait_aux_op_finish(bus);
531 static int sp_tx_get_edid_block(uint8_t bus)
533 int ret;
534 uint8_t val = 0;
536 sp_tx_aux_wr(bus, 0x7e);
537 sp_tx_aux_rd(bus, 0x01);
538 ret = anx7625_reg_read(bus, RX_P0_ADDR, AP_AUX_BUFF_START, &val);
540 if (ret < 0) {
541 ANXERROR("IO error: access AUX BUFF.\n");
542 return -1;
545 ANXINFO("EDID Block = %d\n", val + 1);
547 if (val > 3)
548 val = 1;
550 return val;
553 static int edid_read(uint8_t bus, uint8_t offset, uint8_t *pblock_buf)
555 int ret, cnt;
557 for (cnt = 0; cnt < 3; cnt++) {
558 sp_tx_aux_wr(bus, offset);
559 /* set I2C read com 0x01 mot = 0 and read 16 bytes */
560 ret = sp_tx_aux_rd(bus, 0xf1);
562 if (ret < 0) {
563 sp_tx_rst_aux(bus);
564 ANXERROR("edid read failed, reset!\n");
565 } else {
566 if (anx7625_reg_block_read(bus, RX_P0_ADDR,
567 AP_AUX_BUFF_START,
568 MAX_DPCD_BUFFER_SIZE,
569 pblock_buf) >= 0)
570 return 0;
574 return -1;
577 static int segments_edid_read(uint8_t bus, uint8_t segment, uint8_t *buf,
578 uint8_t offset)
580 int ret, cnt;
582 /* write address only */
583 ret = anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_ADDR_7_0, 0x30);
584 ret |= anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_COMMAND, 0x04);
585 ret |= anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_CTRL_STATUS,
586 AP_AUX_CTRL_ADDRONLY | AP_AUX_CTRL_OP_EN);
588 ret |= wait_aux_op_finish(bus);
589 /* write segment address */
590 ret |= sp_tx_aux_wr(bus, segment);
591 /* data read */
592 ret |= anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_ADDR_7_0, 0x50);
594 if (ret < 0) {
595 ANXERROR("IO error: aux initial failed.\n");
596 return ret;
599 for (cnt = 0; cnt < 3; cnt++) {
600 sp_tx_aux_wr(bus, offset);
601 /* set I2C read com 0x01 mot = 0 and read 16 bytes */
602 ret = sp_tx_aux_rd(bus, 0xf1);
604 if (ret < 0) {
605 sp_tx_rst_aux(bus);
606 ANXERROR("segment read failed, reset!\n");
607 } else {
608 if (anx7625_reg_block_read(bus, RX_P0_ADDR,
609 AP_AUX_BUFF_START,
610 MAX_DPCD_BUFFER_SIZE,
611 buf) >= 0)
612 return 0;
616 return -1;
619 static int sp_tx_edid_read(uint8_t bus, uint8_t *pedid_blocks_buf,
620 uint32_t size)
622 uint8_t offset, edid_pos;
623 int count, blocks_num;
624 uint8_t pblock_buf[MAX_DPCD_BUFFER_SIZE];
625 int i, ret, g_edid_break = 0;
627 /* address initial */
628 ret = anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_ADDR_7_0, 0x50);
629 ret |= anx7625_reg_write(bus, RX_P0_ADDR, AP_AUX_ADDR_15_8, 0);
630 ret |= anx7625_write_and(bus, RX_P0_ADDR, AP_AUX_ADDR_19_16, 0xf0);
632 if (ret < 0) {
633 ANXERROR("access aux channel IO error.\n");
634 return -1;
637 blocks_num = sp_tx_get_edid_block(bus);
638 if (blocks_num < 0)
639 return -1;
641 count = 0;
643 do {
644 switch (count) {
645 case 0:
646 case 1:
647 for (i = 0; i < 8; i++) {
648 offset = (i + count * 8) * MAX_DPCD_BUFFER_SIZE;
649 g_edid_break = !!edid_read(bus, offset,
650 pblock_buf);
652 if (g_edid_break)
653 break;
655 if (offset <= size - MAX_DPCD_BUFFER_SIZE)
656 memcpy(&pedid_blocks_buf[offset],
657 pblock_buf,
658 MAX_DPCD_BUFFER_SIZE);
661 break;
662 case 2:
663 case 3:
664 offset = (count == 2) ? 0x00 : 0x80;
666 for (i = 0; i < 8; i++) {
667 edid_pos = (i + count * 8) *
668 MAX_DPCD_BUFFER_SIZE;
670 if (g_edid_break)
671 break;
673 segments_edid_read(bus, count / 2,
674 pblock_buf, offset);
675 if (edid_pos <= size - MAX_DPCD_BUFFER_SIZE)
676 memcpy(&pedid_blocks_buf[edid_pos],
677 pblock_buf,
678 MAX_DPCD_BUFFER_SIZE);
679 offset = offset + 0x10;
682 break;
683 default:
684 die("%s: count should be <= 3", __func__);
685 break;
688 count++;
690 } while (blocks_num >= count);
692 /* reset aux channel */
693 sp_tx_rst_aux(bus);
695 return blocks_num;
698 static void anx7625_disable_pd_protocol(uint8_t bus)
700 int ret;
702 /* reset main ocm */
703 ret = anx7625_reg_write(bus, RX_P0_ADDR, 0x88, 0x40);
704 /* Disable PD */
705 ret |= anx7625_reg_write(bus, RX_P0_ADDR, AP_AV_STATUS, AP_DISABLE_PD);
706 /* release main ocm */
707 ret |= anx7625_reg_write(bus, RX_P0_ADDR, 0x88, 0x00);
709 if (ret < 0)
710 ANXERROR("Failed to disable PD feature.\n");
711 else
712 ANXINFO("Disabled PD feature.\n");
715 #define FLASH_LOAD_STA 0x05
716 #define FLASH_LOAD_STA_CHK (1 << 7)
718 static int anx7625_power_on_init(uint8_t bus)
720 int i, ret;
721 uint8_t val, version, revision;
723 anx7625_reg_write(bus, RX_P0_ADDR, XTAL_FRQ_SEL, XTAL_FRQ_27M);
725 for (i = 0; i < OCM_LOADING_TIME; i++) {
726 /* check interface */
727 ret = anx7625_reg_read(bus, RX_P0_ADDR, FLASH_LOAD_STA, &val);
728 if (ret < 0) {
729 ANXERROR("Failed to load flash\n");
730 return ret;
733 if ((val & FLASH_LOAD_STA_CHK) != FLASH_LOAD_STA_CHK) {
734 mdelay(1);
735 continue;
737 ANXINFO("Init interface.\n");
739 anx7625_disable_pd_protocol(bus);
740 anx7625_reg_read(bus, RX_P0_ADDR, OCM_FW_VERSION, &version);
741 anx7625_reg_read(bus, RX_P0_ADDR, OCM_FW_REVERSION, &revision);
742 ANXINFO("Firmware: ver %#02x, rev %#02x.\n", version, revision);
743 return 0;
745 return -1;
748 static void anx7625_start_dp_work(uint8_t bus)
750 int ret;
751 uint8_t val;
753 /* not support HDCP */
754 ret = anx7625_write_and(bus, RX_P1_ADDR, 0xee, 0x9f);
756 /* try auth flag */
757 ret |= anx7625_write_or(bus, RX_P1_ADDR, 0xec, 0x10);
758 /* interrupt for DRM */
759 ret |= anx7625_write_or(bus, RX_P1_ADDR, 0xff, 0x01);
760 if (ret < 0)
761 return;
763 ret = anx7625_reg_read(bus, RX_P1_ADDR, 0x86, &val);
764 if (ret < 0)
765 return;
767 ANXINFO("Secure OCM version=%02x\n", val);
770 static int anx7625_hpd_change_detect(uint8_t bus)
772 int ret;
773 uint8_t status;
775 ret = anx7625_reg_read(bus, RX_P0_ADDR, SYSTEM_STSTUS, &status);
776 if (ret < 0) {
777 ANXERROR("IO error: Failed to clear interrupt status.\n");
778 return ret;
781 if (status & HPD_STATUS) {
782 anx7625_start_dp_work(bus);
783 ANXINFO("HPD received 0x7e:0x45=%#x\n", status);
784 return 1;
786 return 0;
789 static void anx7625_parse_edid(const struct edid *edid,
790 struct display_timing *dt)
792 dt->pixelclock = edid->mode.pixel_clock;
794 dt->hactive = edid->mode.ha;
795 dt->hsync_len = edid->mode.hspw;
796 dt->hback_porch = (edid->mode.hbl - edid->mode.hso -
797 edid->mode.hborder - edid->mode.hspw);
798 dt->hfront_porch = edid->mode.hso - edid->mode.hborder;
800 dt->vactive = edid->mode.va;
801 dt->vsync_len = edid->mode.vspw;
802 dt->vfront_porch = edid->mode.vso - edid->mode.vborder;
803 dt->vback_porch = (edid->mode.vbl - edid->mode.vso -
804 edid->mode.vspw - edid->mode.vborder);
807 * The k_val is a ratio to match MIPI input and DP output video clocks.
808 * Most panels can follow the default value (0x3d).
809 * IVO panels have smaller variation than DP CTS spec and need smaller
810 * k_val (0x3b).
812 if (!strncmp(edid->manufacturer_name, "IVO", 3)) {
813 dt->k_val = 0x3b;
814 ANXINFO("detected IVO panel, use k value 0x3b\n");
815 } else {
816 dt->k_val = 0x3d;
817 ANXINFO("set default k value to 0x3d for panel\n");
820 ANXINFO("pixelclock(%d).\n"
821 " hactive(%d), hsync(%d), hfp(%d), hbp(%d)\n"
822 " vactive(%d), vsync(%d), vfp(%d), vbp(%d)\n",
823 dt->pixelclock,
824 dt->hactive, dt->hsync_len, dt->hfront_porch, dt->hback_porch,
825 dt->vactive, dt->vsync_len, dt->vfront_porch, dt->vback_porch);
828 int anx7625_dp_start(uint8_t bus, const struct edid *edid)
830 int ret;
831 struct display_timing dt;
833 anx7625_parse_edid(edid, &dt);
835 ret = anx7625_dsi_config(bus, &dt);
836 if (ret < 0) {
837 ANXERROR("MIPI phy setup error.\n");
838 return ret;
841 ANXINFO("MIPI phy setup OK.\n");
842 return 0;
845 int anx7625_dp_get_edid(uint8_t bus, struct edid *out)
847 int block_num;
848 int ret;
849 u8 edid[FOUR_BLOCK_SIZE];
851 block_num = sp_tx_edid_read(bus, edid, FOUR_BLOCK_SIZE);
852 if (block_num < 0) {
853 ANXERROR("Failed to get eDP EDID.\n");
854 return -1;
857 ret = decode_edid(edid, (block_num + 1) * ONE_BLOCK_SIZE, out);
858 if (ret != EDID_CONFORMANT) {
859 ANXERROR("Failed to decode EDID.\n");
860 return -1;
863 return 0;
866 int anx7625_init(uint8_t bus)
868 int retry_hpd_change = 50;
870 if (!retry(3, anx7625_power_on_init(bus) >= 0)) {
871 ANXERROR("Failed to power on.\n");
872 return -1;
875 while (--retry_hpd_change) {
876 mdelay(10);
877 int detected = anx7625_hpd_change_detect(bus);
878 if (detected < 0)
879 return -1;
880 if (detected > 0)
881 return 0;
884 ANXERROR("Timed out to detect HPD change on bus %d.\n", bus);
885 return -1;