xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/it66353/it66353_EQ.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
4  *
5  * it66353 HDMI 3 in 1 out driver.
6  *
7  * Author: Kenneth.Hung@ite.com.tw
8  *         Wangqiang Guo <kay.guo@rock-chips.com>
9  * Version: IT66353_SAMPLE_1.08
10  *
11  */
12 #include "config.h"
13 #include "platform.h"
14 #include "debug.h"
15 #include "it66353_drv.h"
16 #include "it66353_EQ.h"
17 #include "it66353.h"
18 #include <linux/time.h>
19 #include <linux/timer.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/delay.h>
23 #include <linux/printk.h>
24 
25 #define Channel_B 0
26 #define Channel_G 1
27 #define Channel_R 2
28 
29 #define PR_ERR(...); 	{if (dbg_level >= 0) printk(__VA_ARGS__);}
30 #define PR_INFO(...);	{if (dbg_level >= 1) printk(__VA_ARGS__);}
31 #define PR_INFO2(...);	{if (dbg_level >= 2) printk(__VA_ARGS__);}
32 #define PR_AEQ(...);	{if (dbg_level >= 2) printk(__VA_ARGS__);}
33 
34 const u8 it66353_rs_value[] =  {0x7F, 0x7E, 0x3F, 0x3E, 0x1F, 0x1E, 0x0F,
35 			0x0E, 0x07, 0x06, 0x03, 0x02, 0x01, 0x00};
36 static u8 rs_try_idx[] = {7, 6, 8, 5, 9, 4, 10, 3, 11, 2, 12, 1, 13, 0};
37 static int dbg_level;
38 #if 0
39 static u8 _rx_is_h14_tmds_over_1G(void)
40 {
41 	return it66353_get_port_info1(it66353_gdev.vars.Rx_active_port, PI_PLL_HS1G);
42 }
43 #endif
44 
it66353_rx_DFE_enable(u8 enable)45 void it66353_rx_DFE_enable(u8 enable)
46 {
47 	it66353_chgrxbank(3);
48 	if (enable)
49 		it66353_h2rxset(0x22, 0x40, 0x40); // Enable DFE
50 	else
51 		it66353_h2rxset(0x22, 0x40, 0x00); // Disable DFE
52 	it66353_chgrxbank(0);
53 }
54 
it66353_rx_set_rs_3ch(u8 * rs_value)55 void it66353_rx_set_rs_3ch(u8 *rs_value)
56 {
57 	u8 rs[3];
58 
59 	if (rs_value) {
60 		rs[0] = rs_value[0] | 0x80;
61 		rs[1] = rs_value[1] | 0x80;
62 		rs[2] = rs_value[2] | 0x80;
63 		it66353_chgrxbank(3);
64 		it66353_h2rxbwr(0x27, 3, rs);
65 		rs[0] = 0xCC;
66 		rs[1] = 0xCC;
67 		rs[2] = 0xCC;
68 		it66353_h2rxbrd(0x27, 3, rs);
69 		it66353_chgrxbank(0);
70 		// it66353_h2rxwr(0x0f, 0x00);
71 	}
72 }
73 
it66353_rx_set_rs(u8 ch,u8 rs_value)74 void it66353_rx_set_rs(u8 ch, u8 rs_value)
75 {
76 	rs_value |= 0x80;
77 	it66353_chgrxbank(3);
78 	it66353_h2rxwr(0x27 + ch, rs_value);
79 	it66353_chgrxbank(0);
80 
81 }
82 
83 #if 0
84 static u8 _rx_get_rs(u8 ch)
85 {
86 	u8 rs_value;
87 
88 	it66353_chgrxbank(3);
89 	rs_value = it66353_h2rxrd(0x27+ch);
90 	it66353_chgrxbank(0);
91 
92 	return rs_value;
93 }
94 #endif
95 
it66353_rx_clear_ced_err(void)96 void it66353_rx_clear_ced_err(void)
97 {
98 	// read CED Error from SAREQ CEDError Counter
99 	it66353_h2rxset(0x3B, 0x08, 0x08);
100 	it66353_chgrxbank(3);
101 	it66353_h2rxset(0x55, 0x80, 0x00);
102 	it66353_h2rxwr(0xe9, 0x80);
103 	it66353_chgrxbank(0);
104 }
105 
_rx_ced_err_recheck(void)106 static void _rx_ced_err_recheck(void)
107 {
108 	u8 i;
109 	u8 tmp;
110 
111 	it66353_h2rxwr(0xB9, 0xFF);
112 	it66353_h2rxwr(0xBE, 0xFF);
113 	msleep(10);
114 
115 	for (i = 0 ; i < 3 ; i++) {
116 		if ((it66353_gdev.vars.RxCEDErrValid&(1 << i)) &&
117 		    (it66353_gdev.vars.RxCEDErr[i] > 0x100)) {
118 			if ((it66353_h2rxrd(0x19)&0x80)) {
119 				tmp = it66353_h2rxrd(0xB9);
120 				if (0 == (tmp & (0x03<<i)))
121 					it66353_gdev.vars.RxCEDErr[i] = 0;
122 			}
123 		}
124 	}
125 }
126 
it66353_rx_update_ced_err_from_hw(void)127 void it66353_rx_update_ced_err_from_hw(void)
128 {
129 	u8 symlock;
130 
131 	if (it66353_rx_is_clock_stable()) {
132 		symlock = it66353_h2rxrd(0x14);
133 
134 		if (0 == (symlock & 0x38)) {
135 			it66353_gdev.vars.RxCEDErrValid = 0;
136 		} else {
137 			// read CED Error from SAREQ CEDError Counter
138 			it66353_h2rxset(0x3B, 0x08, 0x08);
139 			it66353_chgrxbank(3);
140 			it66353_h2rxset(0x55, 0x80, 0x00);
141 
142 			if (symlock & 0x08) {
143 				it66353_h2rxwr(0xe9, 0x00);
144 				it66353_gdev.vars.RxCEDErr[0] = it66353_h2rxrd(0xEB);
145 				// ced valid
146 				if (it66353_gdev.vars.RxCEDErr[0] & 0x80) {
147 					it66353_gdev.vars.RxCEDErr[0] = it66353_gdev.vars.RxCEDErr[0] & 0x7F;
148 					it66353_gdev.vars.RxCEDErr[0] = (it66353_gdev.vars.RxCEDErr[0] << 8) +
149 								it66353_h2rxrd(0xEA);
150 					it66353_gdev.vars.RxCEDErrValid = 1;
151 				} else {
152 					it66353_gdev.vars.RxCEDErrValid = 0;
153 				}
154 			} else {
155 				it66353_gdev.vars.RxCEDErrValid = 0;
156 			}
157 
158 			if (symlock & 0x10) {
159 				it66353_h2rxwr(0xe9, 0x20);
160 				it66353_gdev.vars.RxCEDErr[1] = it66353_h2rxrd(0xEB);
161 
162 				if (it66353_gdev.vars.RxCEDErr[1] & 0x80) {
163 					it66353_gdev.vars.RxCEDErr[1] = it66353_gdev.vars.RxCEDErr[1] & 0x7F;
164 					it66353_gdev.vars.RxCEDErr[1] = (it66353_gdev.vars.RxCEDErr[1]<<8) +
165 								it66353_h2rxrd(0xEA);
166 					it66353_gdev.vars.RxCEDErrValid |= 0x02;
167 				} else {
168 					it66353_gdev.vars.RxCEDErrValid &= ~0x02;
169 				}
170 			} else {
171 				it66353_gdev.vars.RxCEDErrValid &= ~0x02;
172 			}
173 
174 			if (symlock & 0x20) {
175 				it66353_h2rxwr(0xe9, 0x40);
176 				it66353_gdev.vars.RxCEDErr[2] = it66353_h2rxrd(0xEB);
177 
178 				if (it66353_gdev.vars.RxCEDErr[2] & 0x80) {
179 					it66353_gdev.vars.RxCEDErr[2] = it66353_gdev.vars.RxCEDErr[2] & 0x7F;
180 					it66353_gdev.vars.RxCEDErr[2] = (it66353_gdev.vars.RxCEDErr[2]<<8) +
181 								it66353_h2rxrd(0xEA);
182 					it66353_gdev.vars.RxCEDErrValid |= 0x04;
183 				} else {
184 					it66353_gdev.vars.RxCEDErrValid &= ~0x04;
185 				}
186 			} else {
187 				it66353_gdev.vars.RxCEDErrValid &= ~0x04;
188 			}
189 
190 			it66353_h2rxwr(0xe9, 0x80);
191 
192 			it66353_chgrxbank(0);
193 
194 			_rx_ced_err_recheck();
195 
196 		}
197 	} else {
198 		it66353_gdev.vars.RxCEDErrValid = 0;
199 	}
200 }
201 
_rx_record_ced_err(void)202 static void _rx_record_ced_err(void)
203 {
204 	u8 i;
205 
206 	if (it66353_gdev.EQ.ced_acc_count == 0) {
207 		for (i = 0 ; i < 3 ; i++) {
208 			it66353_gdev.EQ.ced_err_avg[i] = it66353_gdev.vars.RxCEDErr[i];
209 			// it66353_gdev.EQ.ced_err_avg_prev[i] = 0x8888;
210 		}
211 	} else {
212 		for (i = 0 ; i < 3 ; i++) {
213 			it66353_gdev.EQ.ced_err_avg[i] = it66353_gdev.EQ.ced_err_avg[i] +
214 						 it66353_gdev.vars.RxCEDErr[i];
215 			it66353_gdev.EQ.ced_err_avg[i] >>= 1;
216 		}
217 	}
218 	it66353_gdev.EQ.ced_acc_count++;
219 }
220 
it66353_rx_monitor_ced_err(void)221 u8 it66353_rx_monitor_ced_err(void)
222 {
223 	static u8 err_acc;
224 
225 	if (0 == it66353_rx_is_all_ch_symlock()) {
226 		return 0;
227 	}
228 
229 	_rx_record_ced_err();
230 
231 
232 	if (it66353_gdev.vars.RxCEDErrValid) {
233 		if ((it66353_gdev.vars.RxCEDErr[0] || it66353_gdev.vars.RxCEDErr[1] ||
234 		    it66353_gdev.vars.RxCEDErr[2])) {
235 			err_acc++;
236 
237 			if (err_acc > 10) {
238 				err_acc = 0;
239 				if ((it66353_gdev.vars.RxCEDErr[0] > 0x08 ||
240 				     it66353_gdev.vars.RxCEDErr[1] > 0x08 ||
241 				     it66353_gdev.vars.RxCEDErr[2] > 0x08)) {
242 					// return 1, means too much CED
243 					return 1;
244 				}
245 			}
246 		} else {
247 			err_acc = 0;
248 		}
249 	} else {
250 		// no ced error value for reference
251 		// do nothing about CED error
252 	}
253 
254 	return 0;
255 }
256 
it66353_rx_is_hdmi20(void)257 u8 it66353_rx_is_hdmi20(void)
258 {
259 #if 1
260 	return it66353_gdev.vars.clock_ratio;
261 #else
262 	if (it66353_h2swrd(0x61 + it66353_gdev.vars.Rx_active_port * 3) & 0x40) {
263 		return 1;
264 	}
265 	return 0;
266 #endif
267 }
268 
269 #if EN_H14_SKEW
it66353_rx_skew_adj(u8 ch)270 void it66353_rx_skew_adj(u8 ch)
271 {
272 	static u8 idx[3] = {0};
273 
274 	it66353_chgrxbank(3);
275 	it66353_h2rxset(0x2D, 0x1 << ch, 0x01 << ch);
276 	switch (idx[ch]) {
277 	case 0:
278 		it66353_h2rxset(0x2C, 0x3 << ch, 0x02 << ch);
279 		idx[ch] = 1;
280 		break;
281 	case 1:
282 		it66353_h2rxset(0x2C, 0x3 << ch, 0x03 << ch);
283 		idx[ch] = 2;
284 		break;
285 	case 2:
286 		it66353_h2rxset(0x2C, 0x3 << ch, 0x00 << ch);
287 		idx[ch] = 0;
288 		break;
289 	default:
290 		idx[ch] = 0;
291 		break;
292 	}
293 	it66353_chgrxbank(0);
294 
295 }
296 #endif
297 
it66353_eq_save_h20(void)298 void it66353_eq_save_h20(void)
299 {
300 	it66353_chgrxbank(3);
301 	it66353_gdev.EQ.stored_RS_20[0] = it66353_h2rxrd(0x27);
302 	it66353_gdev.EQ.stored_RS_20[1] = it66353_h2rxrd(0x28);
303 	it66353_gdev.EQ.stored_RS_20[2] = it66353_h2rxrd(0x29);
304 	it66353_chgrxbank(0);
305 }
306 
it66353_eq_load_h20(void)307 void it66353_eq_load_h20(void)
308 {
309 	PR_INFO("enter it66353_eq_load_h20\r\n");
310 	it66353_rx_set_rs_3ch(it66353_gdev.EQ.stored_RS_20);
311 	it66353_aeq_set_DFE2(it66353_gdev.EQ.stored_RS_20[0], it66353_gdev.EQ.stored_RS_20[1],
312 		      it66353_gdev.EQ.stored_RS_20[2]);
313 	it66353_rx_DFE_enable(1);
314 }
315 
it66353_eq_save_h14(void)316 void it66353_eq_save_h14(void)
317 {
318 	it66353_chgrxbank(3);
319 	it66353_gdev.EQ.stored_RS_14[0] = it66353_h2rxrd(0x27);
320 	it66353_gdev.EQ.stored_RS_14[1] = it66353_h2rxrd(0x28);
321 	it66353_gdev.EQ.stored_RS_14[2] = it66353_h2rxrd(0x29);
322 	it66353_chgrxbank(0);
323 }
324 
it66353_eq_load_h14(void)325 void it66353_eq_load_h14(void)
326 {
327 	PR_INFO("enter it66353_eq_load_h14\r\n");
328 	it66353_rx_set_rs_3ch(it66353_gdev.EQ.stored_RS_14);
329 }
330 
it66353_eq_load_previous(void)331 void it66353_eq_load_previous(void)
332 {
333 	if (it66353_rx_is_hdmi20()) {
334 		if (it66353_gdev.EQ.current_eq_mode == 0) {
335 			it66353_gdev.EQ.current_eq_mode = 1;
336 			it66353_eq_load_h20();
337 		}
338 	} else {
339 		if (it66353_gdev.EQ.current_eq_mode == 1) {
340 			it66353_gdev.EQ.current_eq_mode = 0;
341 			it66353_eq_load_h14();
342 		}
343 	}
344 }
345 
it66353_eq_load_default(void)346 void it66353_eq_load_default(void)
347 {
348 	it66353_rx_set_rs_3ch(it66353_gdev.opts.active_rx_opt->DefaultEQ);
349 
350 	if (it66353_rx_is_hdmi20()) {
351 		it66353_rx_DFE_enable(0);
352 		// PR_INFO(("_eq_load_def_20\r\n"));
353 	} else {
354 		// PR_INFO(("_eq_load_def_14\r\n"));
355 	}
356 }
357 
_eq_find_rs_index(u8 EQ_Value)358 static u8 _eq_find_rs_index(u8 EQ_Value)
359 {
360 	u8 i = 0;
361 	EQ_Value &= ~0x80;
362 	for (i = 0; i < sizeof(it66353_rs_value); i++) {
363 		if (it66353_rs_value[i] == EQ_Value)
364 			return i;
365 	}
366 
367 	PR_ERR("EQ %02X not found !!\r\n", EQ_Value);
368 	return 4;
369 }
370 
it66353_eq_reset_txoe_ready(void)371 void it66353_eq_reset_txoe_ready(void)
372 {
373 	it66353_gdev.EQ.txoe_ready20 = 0;
374 	it66353_gdev.EQ.txoe_ready14 = 0;
375 }
376 
it66353_eq_set_txoe_ready(u8 ready)377 void it66353_eq_set_txoe_ready(u8 ready)
378 {
379 	if (it66353_rx_is_hdmi20())
380 		it66353_gdev.EQ.txoe_ready20 = ready;
381 	else
382 		it66353_gdev.EQ.txoe_ready14 = ready;
383 
384 	PR_INFO("set ready 14=%d 20=%d\r\n", it66353_gdev.EQ.txoe_ready14,
385 		it66353_gdev.EQ.txoe_ready20);
386 }
387 
it66353_eq_get_txoe_ready(void)388 u8 it66353_eq_get_txoe_ready(void)
389 {
390 	PR_INFO("get ready 14=%d 20=%d\r\n", it66353_gdev.EQ.txoe_ready14,
391 		it66353_gdev.EQ.txoe_ready20);
392 	if (it66353_rx_is_hdmi20()) {
393 		return it66353_gdev.EQ.txoe_ready20;
394 	} else {
395 		return it66353_gdev.EQ.txoe_ready14;
396 	}
397 }
398 
it66353_eq_reset_state(void)399 void it66353_eq_reset_state(void)
400 {
401 	it66353_gdev.EQ.EQ_flag_20 = SysAEQ_RUN;
402 	it66353_gdev.EQ.EQ_flag_14 = SysAEQ_RUN;
403 }
404 
it66353_eq_set_state(u8 state)405 void it66353_eq_set_state(u8 state)
406 {
407 	if (it66353_rx_is_hdmi20()) {
408 		it66353_gdev.EQ.EQ_flag_20 = state;
409 	} else {
410 		it66353_gdev.EQ.EQ_flag_14 = state;
411 	}
412 
413 	PR_INFO("set eq flag 14=%d 20=%d\r\n", it66353_gdev.EQ.EQ_flag_14,
414 		it66353_gdev.EQ.EQ_flag_20);
415 }
416 
it66353_eq_get_state(void)417 u8 it66353_eq_get_state(void)
418 {
419 	PR_INFO("get eq flag 14=%d 20=%d\r\n", it66353_gdev.EQ.EQ_flag_14,
420 		it66353_gdev.EQ.EQ_flag_20);
421 
422 	if (it66353_rx_is_hdmi20()) {
423 		return it66353_gdev.EQ.EQ_flag_20;
424 	} else {
425 		return it66353_gdev.EQ.EQ_flag_14;
426 	}
427 }
428 
_aeq_ready_to_start(void)429 static u8 _aeq_ready_to_start(void)
430 {
431 	return it66353_rx_is_clock_stable();
432 }
433 
it66353_aeq_diable_eq_trigger(void)434 void it66353_aeq_diable_eq_trigger(void)
435 {
436 	it66353_chgrxbank(3);
437 	it66353_h2rxset(0x22, 0x04, 0x00);
438 	it66353_chgrxbank(0);
439 }
440 
_aeq_reset(void)441 static void _aeq_reset(void)
442 {
443 	it66353_aeq_diable_eq_trigger();
444 
445 	it66353_h2rxwr(0x07, 0xff);
446 	it66353_h2rxwr(0x23, 0xB0);
447 	msleep(10);
448 	it66353_h2rxwr(0x23, 0xA0);
449 }
450 
_aeq_get_DFE2(u8 ch,u8 rs_idx)451 static void _aeq_get_DFE2(u8 ch, u8 rs_idx)
452 {
453 	u8 i;
454 	u8 amp_a, amp_b, amp_c, amp_d;
455 	u8 tap1_sign, tap1_value;
456 	u8 tap2_sign, tap2_value;
457 	u8 tap3_sign, tap3_value;
458 	u8 dfe_a, dfe_b, dfe_c;
459 	u8 reg37o, reg37;
460 	u8 rec[4];
461 
462 	it66353_chgrxbank(3);
463 
464 	i = rs_idx;
465 
466 	it66353_h2rxset(0x36, 0x0F, i);
467 	reg37o = it66353_h2rxrd(0x37) & (~0xC0);
468 	PR_AEQ("RS=%02x DEF:\r\n", 0x80|it66353_rs_value[i]);
469 
470 	for (ch = 0 ; ch < 3 ; ch++) {
471 		// hdmirxset(0x37 ,0xC0 ,ch<<6);
472 		reg37 = reg37o | (ch << 6);
473 		it66353_h2rxwr(0x37, reg37);
474 
475 #if 0
476 		amp_a = hdmirxrd(0x5d);
477 		amp_b = hdmirxrd(0x5e);
478 		amp_c = hdmirxrd(0x5f);
479 		amp_d = hdmirxrd(0x60);
480 #else
481 		it66353_h2rxbrd(0x5d, 4, rec);
482 		amp_a = rec[0];
483 		amp_b = rec[1];
484 		amp_c = rec[2];
485 		amp_d = rec[3];
486 #endif
487 
488 		if (amp_a > amp_b) {
489 			tap1_sign = 1;
490 			tap1_value = (amp_a - amp_b) >> 1;
491 		} else {
492 			tap1_sign = 0;
493 			tap1_value = (amp_b - amp_a) >> 1;
494 		}
495 
496 		if (amp_a > amp_c) {
497 			tap2_sign = 1;
498 			tap2_value = (amp_a - amp_c) >> 1;
499 		} else {
500 			tap2_sign = 0;
501 			tap2_value = (amp_c - amp_a) >> 1;
502 		}
503 
504 		if (amp_a > amp_d) {
505 			tap3_sign = 1;
506 			tap3_value = (amp_a - amp_d) >> 1;
507 		} else {
508 			tap3_sign = 0;
509 			tap3_value = (amp_d - amp_a) >> 1;
510 		}
511 
512 		if (tap1_value > 0x1F)
513 			tap1_value = 0x1F;
514 		if (tap2_value > 0x0F)
515 			tap2_value = 0x0F;
516 		if (tap3_value > 0x07)
517 			tap3_value = 0x07;
518 
519 		dfe_a = (0x40) + (tap1_sign << 5) + tap1_value;
520 		dfe_b = (0x20) + (tap2_sign << 4) + tap2_value;
521 		dfe_c = (0x10) + (tap3_sign << 3) + tap3_value;
522 
523 		it66353_gdev.EQ.DFE[i][ch][0] = dfe_a;
524 		it66353_gdev.EQ.DFE[i][ch][1] = dfe_b;
525 		it66353_gdev.EQ.DFE[i][ch][2] = dfe_c;
526 
527 		PR_AEQ(" ch%d=%02X %02X %02X |", ch, dfe_a, dfe_b, dfe_c);
528 	}
529 	PR_AEQ("\r\n");
530 
531 	it66353_chgrxbank(0);
532 
533 }
534 
it66353_aeq_set_DFE2(u8 EQ0,u8 EQ1,u8 EQ2)535 void it66353_aeq_set_DFE2(u8 EQ0, u8 EQ1, u8 EQ2)
536 {
537 	u8 dfe[9];
538 	u8 i;
539 
540 	i = _eq_find_rs_index(EQ0);
541 	_aeq_get_DFE2(0, i);
542 	dfe[0] = it66353_gdev.EQ.DFE[i][Channel_B][0];
543 	dfe[1] = it66353_gdev.EQ.DFE[i][Channel_B][1];
544 	dfe[2] = it66353_gdev.EQ.DFE[i][Channel_B][2];
545 
546 	i = _eq_find_rs_index(EQ1);
547 	_aeq_get_DFE2(1, i);
548 	dfe[3] = it66353_gdev.EQ.DFE[i][Channel_G][0];
549 	dfe[4] = it66353_gdev.EQ.DFE[i][Channel_G][1];
550 	dfe[5] = it66353_gdev.EQ.DFE[i][Channel_G][2];
551 
552 	i = _eq_find_rs_index(EQ2);
553 	_aeq_get_DFE2(2, i);
554 	dfe[6] = it66353_gdev.EQ.DFE[i][Channel_R][0];
555 	dfe[7] = it66353_gdev.EQ.DFE[i][Channel_R][1];
556 	dfe[8] = it66353_gdev.EQ.DFE[i][Channel_R][2];
557 
558 	it66353_chgrxbank(3);
559 	it66353_h2rxbwr(0x4B, 9, dfe);
560 	// it66353_h2rxbrd(0x4B, 9, dfe); // for recheck only
561 	for (i = 0; i < 3; i++) {
562 		PR_AEQ("DFE:CH%d=%02X %02X %02X\r\n",
563 			i, dfe[0+i*3], dfe[1+i*3], dfe[2+i*3]);
564 	}
565 	it66353_chgrxbank(0);
566 }
567 
_aeq_get_calc_rs(void)568 static void _aeq_get_calc_rs(void)
569 {
570 	it66353_chgrxbank(3);
571 	it66353_h2rxbrd(0xD5, 3, it66353_gdev.EQ.CalcRS);
572 	it66353_chgrxbank(0);
573 	PR_AEQ("AEQ RS=%02X %02X %02X\r\n",
574 		it66353_gdev.EQ.CalcRS[0], it66353_gdev.EQ.CalcRS[1], it66353_gdev.EQ.CalcRS[2]);
575 }
576 
577 #if 0
578 static void _aeq_trigger_EQ(void)
579 {
580 	_aeq_reset();
581 
582 	it66353_chgrxbank(3);
583 
584 	// if 1G~3G, need to force set CSEL to 110
585 	if (_rx_is_h14_tmds_over_1G()) {
586 		PR_AEQ("over 1G\r\n");
587 		it66353_h2rxwr(0x20, 0x36);
588 		it66353_h2rxwr(0x21, 0x0E);
589 	} else {
590 		PR_AEQ("under 1G\r\n");
591 		it66353_h2rxwr(0x20, 0x1B);
592 		it66353_h2rxwr(0x21, 0x03);
593 	}
594 
595 	it66353_h2rxwr(0x26, 0x00);
596 	it66353_h2rxwr(0x22, 0x38); // [5:3] AUTOAMP , AUTOEQ , EQPWDB
597 	it66353_h2rxset(0x22, 0x04, 0x04); // Trigger EQ
598 	msleep(1);
599 	it66353_h2rxset(0x22, 0x04, 0x00); // Trigger EQ
600 	it66353_chgrxbank(0);
601 
602 	it66353_gdev.EQ.AutoEQ_WaitTime = 0;
603 }
604 #endif
605 
_aeq_trigger_SAREQ(void)606 static void _aeq_trigger_SAREQ(void)
607 {
608 	// MUST disable EQTrg before EQRst
609 	u8 def_opt = 1;
610 
611 	it66353_chgrxbank(3);
612 	//  init CSC value
613 	it66353_h2rxwr(0x20, 0x1B);
614 	it66353_h2rxwr(0x21, 0x03);
615 	it66353_h2rxset(0x20, 0x80, 0x00);	// disable CLKStb AutoEQTrg
616 	it66353_h2rxwr(0x22, 0x00);	// disable [4] ENDFE, set [2] EQTrg low
617 	it66353_chgrxbank(0);
618 
619 	_aeq_reset();
620 
621 	it66353_h2rxwr(0x3B, 0x03);	// Reg_CEDOPT[5:0]
622 
623 	it66353_chgrxbank(3);
624 
625 	it66353_h2rxwr(0x26, 0x00);
626 	// it66353_h2rxwr(0x27, 0x1F);
627 	// it66353_h2rxwr(0x28, 0x1F);
628 	// it66353_h2rxwr(0x29, 0x1F);
629 	it66353_h2rxset(0x27, 0x80, 0x00);
630 	it66353_h2rxset(0x28, 0x80, 0x00);
631 	it66353_h2rxset(0x29, 0x80, 0x00);
632 
633 	it66353_h2rxset(0x2C, 0xC0, 0xC0);
634 	// it66353_h2rxset(0x2D, 0xF0, 0x20);
635 	it66353_h2rxset(0x2D, 0xF0, 0x20+(def_opt<<4)); // rsdfeopt=1
636 	it66353_h2rxset(0x2D, 0x07, 0x00);
637 	it66353_h2rxwr(0x30, 0x8C);
638 
639 	it66353_h2rxwr(0x31, 0xB0);		// AMPTime[7:0]
640 
641 	it66353_h2rxwr(0x32, 0x43);
642 	it66353_h2rxwr(0x33, 0x47);
643 	it66353_h2rxwr(0x34, 0x4B);
644 	it66353_h2rxwr(0x35, 0x53);
645 
646 	it66353_h2rxset(0x36, 0xc0, 0x00);	// [7:6] AMPTime[9:8]
647 
648 	it66353_h2rxwr(0x37, 0x0B);		// [7:6] RecChannel, [4]: RSOnestage,
649 						// [3] IgnoreOPT, [1:0] MacthNoSel
650 
651 	it66353_h2rxwr(0x38, 0xF2);		// [7:4] MonTime
652 	/* [5] POLBOPT, [4] ADDPClrOPT, [3:0] CED Valid Threshold 0x0D */
653 	it66353_h2rxwr(0x39, 0x04);
654 	it66353_h2rxset(0x4A, 0x80, 0x00);
655 	it66353_h2rxset(0x4B, 0x80, 0x00);
656 	it66353_h2rxset(0x54, 0x80, 0x80);	// Reg_EN_PREEQ
657 	it66353_h2rxset(0x54, 0x38, 0x38);
658 
659 	it66353_h2rxwr(0x55, 0x40);		// RSM Threshold
660 
661 	// it66353_h2rxset(0x22, 0x04, 0x04);	// Trigger EQ
662 	it66353_h2rxset(0x22, 0x44, 0x04+(def_opt<<6));	// Trigger EQ
663 	it66353_chgrxbank(0);
664 
665 	it66353_gdev.EQ.AutoEQ_WaitTime = 0;
666 }
667 
_aeq_check_amp_and_rs_status(void)668 static void _aeq_check_amp_and_rs_status(void)
669 {
670 	u8 i;
671 	u8 reg63, reg6D;
672 	u16 reg64, reg6E;
673 	u16 amp_timeout;
674 
675 	it66353_gdev.EQ.DFE_Valid = 1;
676 	it66353_gdev.EQ.RS_Valid = 1;
677 
678 	it66353_chgrxbank(3);
679 	for (i = 0; i < 3; i++) {
680 		it66353_h2rxset(0x37, 0xC0, i<<6);
681 		reg63 = it66353_h2rxrd(0x63);
682 		reg64 = it66353_h2rxrd(0x64)&0x3F;
683 		reg6D = it66353_h2rxrd(0x6D);
684 		reg6E = it66353_h2rxrd(0x6E);
685 
686 		it66353_gdev.EQ.RS_ValidMap[i] = (reg6E<<8) + reg6D;
687 		amp_timeout = (reg64<<8) + reg63;
688 
689 		PR_AEQ("CH %d, AMP_TimeOut = 0x%04X \r\n", i, amp_timeout);
690 		PR_AEQ("CH %d, RS_ValidMap = 0x%04X \r\n", i,
691 			it66353_gdev.EQ.RS_ValidMap[i]);
692 
693 		if (amp_timeout == 0x3FFF) {
694 			it66353_gdev.EQ.DFE_Valid = 0;
695 		}
696 
697 		reg63 = it66353_h2rxrd(0x61);
698 		reg64 = it66353_h2rxrd(0x62) & 0x3F;
699 		amp_timeout = (reg64 << 8) + reg63;
700 
701 		PR_AEQ("CH %d, AMP_Done = 0x%04X \r\n", i, amp_timeout);
702 
703 		if (it66353_gdev.EQ.RS_ValidMap[i] == 0x0000) {
704 			it66353_gdev.EQ.RS_Valid = 0;
705 		}
706 	}
707 	it66353_chgrxbank(0);
708 }
709 
it66353_aeq_check_sareq_result(void)710 u8 it66353_aeq_check_sareq_result(void)
711 {
712 	u8 tmp;
713 
714 	tmp = it66353_h2rxrd(0x07);
715 	if (tmp & (0x20 | 0x10)) {		// EQ fail | EQ Done
716 		it66353_aeq_diable_eq_trigger();
717 		_aeq_check_amp_and_rs_status();
718 		if (tmp & 0x10) {
719 			it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_DONE;
720 		} else {
721 			it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_FAIL;
722 		}
723 
724 		return 1;
725 	}
726 	/*
727 	 * else if (tmp & BIT5) {		// EQ fail
728 	 *	it66353_aeq_diable_eq_trigger();
729 	 *	_aeq_check_amp_and_rs_status();
730 	 *	it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_FAIL;
731 	 * }
732 	 */
733 	else {
734 		it66353_gdev.EQ.AutoEQ_WaitTime++;
735 		msleep(20);
736 		if (it66353_gdev.EQ.AutoEQ_WaitTime > 30) {
737 			it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_TIMEOUT;
738 			return 1;
739 		}
740 	}
741 
742 	return 0;
743 }
744 
745 #if 0
746 static u8 _aeq_check_h14eq_result(void)
747 {
748 	u8 tmp;
749 
750 	tmp = it66353_h2rxrd(0x07);
751 	if (tmp & 0x40) {		// EQ Done
752 		it66353_aeq_diable_eq_trigger();
753 		PR_AEQ("AEQ 14, DONE\r\n");
754 		return EQRES_H14EQ_DONE;
755 	} else if (tmp & 0x80) {	// EQ fail
756 		it66353_aeq_diable_eq_trigger();
757 		PR_ERR("AEQ 14, FAIL\r\n");
758 		return EQRES_H14EQ_FAIL;
759 	} else {
760 		msleep(25);
761 		it66353_gdev.EQ.AutoEQ_WaitTime++;
762 		if (it66353_gdev.EQ.AutoEQ_WaitTime > 100) {
763 			it66353_gdev.EQ.AutoEQ_Result = EQRES_SAREQ_TIMEOUT;
764 			PR_ERR("AEQ 14, TIMEOUT\r\n");
765 			return EQRES_H14EQ_TIMEOUT;
766 		} else {
767 			// return EQRES_BUSY;
768 		}
769 
770 	}
771 	return EQRES_BUSY;
772 }
773 #endif
774 
_meq_14(void)775 static u8 _meq_14(void)
776 {
777 	u8 rs_idx;
778 	static u8 ch_rs_idx[3];
779 	u8 ch;
780 	u8 ch_all_done;
781 	u8 ch_done[3];
782 	u8 res = EQRES_H14EQ_FAIL;
783 
784 	ch_done[0] = 0;
785 	ch_done[1] = 0;
786 	ch_done[2] = 0;
787 	ch_all_done = 0;
788 	ch_rs_idx[0] = 0;
789 	ch_rs_idx[1] = 0;
790 	ch_rs_idx[2] = 0;
791 
792 	it66353_rx_clear_ced_err();
793 	msleep(50);
794 
795 
796 	for (rs_idx = 0; rs_idx < 14; rs_idx++) {
797 		if (0 == _aeq_ready_to_start()) {
798 			PR_ERR("Cannot perform EQ adjust\r\n");
799 			break;
800 		}
801 
802 
803 		it66353_rx_update_ced_err_from_hw();
804 
805 		for (ch = 0; ch < 3; ch++) {
806 			if (ch_done[ch]) {
807 				// break;
808 			}
809 
810 			if (it66353_gdev.vars.RxCEDErrValid & (1 << ch)) {
811 				if (it66353_gdev.vars.RxCEDErr[ch] < 0x01) {
812 					ch_done[ch] = 1;
813 					ch_all_done++;
814 					PR_AEQ("RS good ch%d = %02X\r\n",
815 						ch, it66353_rs_value[ch_rs_idx[ch]]);
816 				} else {
817 					ch_done[ch] = 0;
818 					PR_AEQ("RS NG ch%d = %02X, err=%04X\r\n",
819 						ch, it66353_rs_value[ch_rs_idx[ch]],
820 						it66353_gdev.vars.RxCEDErr[ch]);
821 				}
822 			} else {
823 				ch_done[ch] = 0;
824 			}
825 		}
826 
827 		if (ch_done[0] && ch_done[1] && ch_done[2]) {
828 			PR_AEQ("ch_all_done\r\n");
829 			res = EQRES_H14EQ_DONE;
830 			break;
831 		}
832 
833 		it66353_rx_clear_ced_err();
834 		for (ch = 0; ch < 3; ch++) {
835 			if (0 == ch_done[ch]) {
836 				it66353_rx_set_rs(ch, it66353_rs_value[rs_try_idx[ch_rs_idx[ch]]]);
837 				ch_rs_idx[ch]++;
838 				if (ch_rs_idx[ch] >= 14) {
839 					ch_rs_idx[ch] = 0;
840 				}
841 			}
842 		}
843 
844 		msleep(100);
845 	}
846 
847 	return res;
848 }
849 
850 
it66353_auto_eq_adjust(void)851 bool it66353_auto_eq_adjust(void)
852 {
853 	u8 result;
854 	u8 ret = false;
855 
856 	if (_aeq_ready_to_start()) {
857 		it66353_h2swset(0xD4, 0x03, 0x01);	  // Set TXOE off
858 
859 		if (it66353_gdev.vars.count_auto_eq_fail > 13) {
860 			it66353_gdev.vars.count_auto_eq_fail = 0;
861 			it66353_rx_caof_init(it66353_gdev.vars.Rx_active_port);
862 		}
863 
864 		if (it66353_rx_is_hdmi20()) {
865 			it66353_gdev.EQ.current_eq_mode = EQ_MODE_H20;
866 			it66353_gdev.EQ.RS_Valid = 0;
867 			it66353_gdev.EQ.DFE_Valid = 0;
868 			_aeq_trigger_SAREQ();
869 
870 			while (it66353_aeq_check_sareq_result() == 0) {
871 				// auto EQ will wait about 400ms here
872 			}
873 
874 			if (it66353_gdev.EQ.DFE_Valid && it66353_gdev.EQ.RS_Valid) {
875 				_aeq_get_calc_rs();
876 				it66353_rx_set_rs_3ch(it66353_gdev.EQ.CalcRS);
877 				it66353_aeq_set_DFE2(it66353_gdev.EQ.CalcRS[0],
878 					      it66353_gdev.EQ.CalcRS[1],
879 					      it66353_gdev.EQ.CalcRS[2]);
880 				it66353_rx_DFE_enable(1);
881 
882 				it66353_eq_save_h20();
883 
884 				ret = true;
885 			} else {
886 				it66353_chgrxbank(3);
887 				it66353_h2rxset(0x27, 0x80, 0x80);
888 				it66353_h2rxset(0x28, 0x80, 0x80);
889 				it66353_h2rxset(0x29, 0x80, 0x80);
890 				it66353_chgrxbank(0);
891 			}
892 		} else {
893 			it66353_gdev.EQ.current_eq_mode = EQ_MODE_H14;
894 
895 #if 0
896 			_aeq_trigger_EQ();
897 
898 			result = _aeq_check_h14eq_result();
899 			while (EQRES_BUSY == result) {
900 				result = _aeq_check_h14eq_result();
901 			}
902 
903 			if (result == EQRES_H14EQ_DONE) {
904 				_aeq_get_calc_rs();
905 				it66353_rx_set_rs_3ch(it66353_gdev.EQ.CalcRS);
906 			} else {
907 				result = _meq_14();
908 			}
909 #else
910 			result = _meq_14();
911 #endif
912 
913 			if (result == EQRES_H14EQ_DONE) {
914 				it66353_eq_save_h14();
915 				ret = true;
916 			}
917 
918 		}
919 
920 		it66353_h2swset(0xD4, 0x03, 0x00);	  // Set DRV_RST='1'
921 
922 		if (ret) {
923 			it66353_gdev.vars.count_auto_eq_fail = 0;
924 		} else {
925 			it66353_gdev.vars.count_auto_eq_fail++;
926 			PR_ERR("EQ result NG %d\r\n", it66353_gdev.vars.count_auto_eq_fail);
927 		}
928 	} else {
929 		PR_ERR("EQ adjust not available\r\n");
930 	}
931 
932 	return ret;
933 }
934 
935 MODULE_LICENSE("GPL v2");
936