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