1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4 *
5 * Author: Algea Cao <algea.cao@rock-chips.com>
6 */
7
8 #include <linux/kernel.h>
9 #include <linux/clk.h>
10 #include <linux/delay.h>
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/platform_device.h>
15 #include <linux/reset.h>
16 #include <linux/phy/phy.h>
17 #include <linux/mfd/rk628.h>
18
19 struct rk628_combrxphy {
20 struct device *dev;
21 struct rk628 *parent;
22 struct regmap *regmap;
23 struct clk *pclk;
24 struct reset_control *rstc;
25 bool is_cable_mode;
26 };
27
28 #define REG(x) ((x) + 0x10000)
29 #define COMBRXPHY_MAX_REGISTER REG(0x6790)
30
31 #define MAX_ROUND 6
32 #define MAX_DATA_NUM 16
33 #define MAX_CHANNEL 3
34 #define CLK_DET_TRY_TIMES 10
35 #define CLK_STABLE_LOOP_CNT 10
36 #define CLK_STABLE_THRESHOLD 6
37
38 static int debug;
39 module_param(debug, int, 0644);
40 MODULE_PARM_DESC(debug, "debug level (0-1)");
41
rk628_combrxphy_set_data_of_round(u32 * data,u32 * data_in)42 static void rk628_combrxphy_set_data_of_round(u32 *data, u32 *data_in)
43 {
44 if ((data != NULL) && (data_in != NULL)) {
45 data_in[0] = data[0];
46 data_in[1] = data[7];
47 data_in[2] = data[13];
48 data_in[3] = data[14];
49 data_in[4] = data[15];
50 data_in[5] = data[1];
51 data_in[6] = data[2];
52 data_in[7] = data[3];
53 data_in[8] = data[4];
54 data_in[9] = data[5];
55 data_in[10] = data[6];
56 data_in[11] = data[8];
57 data_in[12] = data[9];
58 data_in[13] = data[10];
59 data_in[14] = data[11];
60 data_in[15] = data[12];
61 }
62 }
63
64 static void
rk628_combrxphy_max_zero_of_round(struct rk628_combrxphy * combrxphy,u32 * data_in,u32 * max_zero,u32 * max_val,int n,int ch)65 rk628_combrxphy_max_zero_of_round(struct rk628_combrxphy *combrxphy,
66 u32 *data_in, u32 *max_zero, u32 *max_val,
67 int n, int ch)
68 {
69 u32 i;
70 u32 cnt = 0;
71 u32 max_cnt = 0;
72 u32 max_v = 0;
73
74 if (debug > 0) {
75 dev_info(combrxphy->dev,
76 "%s channel:%d, round:%d ====\n", __func__, ch, n);
77 print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_NONE, 32, 4,
78 data_in, MAX_DATA_NUM * sizeof(u32), false);
79 }
80
81 for (i = 0; i < MAX_DATA_NUM; i++) {
82 if (max_v < data_in[i])
83 max_v = data_in[i];
84 }
85
86 for (i = 0; i < MAX_DATA_NUM; i++) {
87 if (data_in[i] == 0)
88 cnt = cnt + 200;
89 else if ((data_in[i] > 0) && (data_in[i] < 100))
90 cnt = cnt + 100 - data_in[i];
91 }
92 max_cnt = (cnt >= 3200) ? 0 : cnt;
93
94 max_zero[n] = max_cnt;
95 max_val[n] = max_v;
96 dev_dbg(combrxphy->dev,
97 "channel:%d, round:%d, max_zero_cnt:%d, max_val:%#x",
98 ch, n, max_zero[n], max_val[n]);
99 }
100
101 static int
rk628_combrxphy_chose_round_for_ch(struct rk628_combrxphy * combrxphy,u32 * rd_max_zero,u32 * rd_max_val,int ch)102 rk628_combrxphy_chose_round_for_ch(struct rk628_combrxphy *combrxphy,
103 u32 *rd_max_zero,
104 u32 *rd_max_val, int ch)
105 {
106 int i, rd = 0;
107 u32 max = 0;
108 u32 max_v = 0;
109
110 if (debug > 0) {
111 dev_info(combrxphy->dev,
112 "%s max cnt of channel:%d ====\n", __func__, ch);
113 print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_NONE, 32, 4,
114 rd_max_zero, MAX_ROUND * sizeof(u32), false);
115
116 dev_info(combrxphy->dev,
117 "%s max value of channel:%d ====\n", __func__, ch);
118 print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_NONE, 32, 4,
119 rd_max_val, MAX_ROUND * sizeof(u32), false);
120 }
121
122 for (i = 0; i < MAX_ROUND; i++) {
123 if (rd_max_zero[i] > max) {
124 max = rd_max_zero[i];
125 max_v = rd_max_val[i];
126 rd = i;
127 } else if (rd_max_zero[i] == max && rd_max_val[i] > max_v) {
128 max = rd_max_zero[i];
129 max_v = rd_max_val[i];
130 rd = i;
131 }
132 }
133
134 dev_dbg(combrxphy->dev, "%s channel:%d, rd:%d\n", __func__, ch, rd);
135 return rd;
136 }
137
rk628_combrxphy_get_data_of_round(struct rk628_combrxphy * combrxphy,u32 * data)138 static void rk628_combrxphy_get_data_of_round(struct rk628_combrxphy
139 *combrxphy, u32 *data)
140 {
141 u32 i;
142
143 for (i = 0; i < MAX_DATA_NUM; i++)
144 regmap_read(combrxphy->regmap, REG(0x6740 + i * 4), &data[i]);
145 }
146
147 static void
rk628_combrxphy_set_dc_gain(struct rk628_combrxphy * combrxphy,u32 x,u32 y,u32 z)148 rk628_combrxphy_set_dc_gain(struct rk628_combrxphy *combrxphy,
149 u32 x, u32 y, u32 z)
150 {
151 u32 val;
152 u32 dc_gain_ch0, dc_gain_ch1, dc_gain_ch2;
153
154 dev_dbg(combrxphy->dev, "channel dc gain ch0:%d, ch1:%d, ch2:%d\n",
155 x, y, z);
156
157 dc_gain_ch0 = x & 0xf;
158 dc_gain_ch1 = y & 0xf;
159 dc_gain_ch2 = z & 0xf;
160 regmap_read(combrxphy->regmap, REG(0x661c), &val);
161
162 val = (val & 0xff0f0f0f) | (dc_gain_ch0 << 20) | (dc_gain_ch1 << 12) |
163 (dc_gain_ch2 << 4);
164 regmap_write(combrxphy->regmap, REG(0x661c), val);
165 }
166
rk628_combrxphy_set_sample_edge_round(struct rk628_combrxphy * combrxphy,u32 x,u32 y,u32 z)167 static void rk628_combrxphy_set_sample_edge_round(struct rk628_combrxphy
168 *combrxphy, u32 x, u32 y, u32 z)
169 {
170 u32 val;
171 u32 equ_gain_ch0, equ_gain_ch1, equ_gain_ch2;
172
173 dev_dbg(combrxphy->dev, "channel equ gain ch0:%d, ch1:%d, ch2:%d\n",
174 x, y, z);
175
176 equ_gain_ch0 = (x & 0xf);
177 equ_gain_ch1 = (y & 0xf);
178 equ_gain_ch2 = (z & 0xf);
179 regmap_read(combrxphy->regmap, REG(0x6618), &val);
180 val = (val & 0xff00f0ff) | (equ_gain_ch1 << 20) |
181 (equ_gain_ch0 << 16) | (equ_gain_ch2 << 8);
182 regmap_write(combrxphy->regmap, REG(0x6618), val);
183 }
184
rk628_combrxphy_start_sample_edge(struct rk628_combrxphy * combrxphy)185 static void rk628_combrxphy_start_sample_edge(struct rk628_combrxphy *combrxphy)
186 {
187 u32 val;
188
189 regmap_read(combrxphy->regmap, REG(0x66f0), &val);
190 val &= 0xfffff1ff;
191 regmap_write(combrxphy->regmap, REG(0x66f0), val);
192 regmap_read(combrxphy->regmap, REG(0x66f0), &val);
193 val = (val & 0xfffff1ff) | (0x7 << 9);
194 regmap_write(combrxphy->regmap, REG(0x66f0), val);
195 }
196
197 static void
rk628_combrxphy_set_sample_edge_mode(struct rk628_combrxphy * combrxphy,int ch)198 rk628_combrxphy_set_sample_edge_mode(struct rk628_combrxphy *combrxphy,
199 int ch)
200 {
201 u32 val;
202
203 regmap_read(combrxphy->regmap, REG(0x6634), &val);
204 val = val & (~(0xf << ((ch + 1) * 4)));
205 regmap_write(combrxphy->regmap, REG(0x6634), val);
206 }
207
rk628_combrxphy_select_channel(struct rk628_combrxphy * combrxphy,int ch)208 static void rk628_combrxphy_select_channel(struct rk628_combrxphy *combrxphy,
209 int ch)
210 {
211 u32 val;
212
213 regmap_read(combrxphy->regmap, REG(0x6700), &val);
214 val = (val & 0xfffffffc) | (ch & 0x3);
215 regmap_write(combrxphy->regmap, REG(0x6700), val);
216 }
217
rk628_combrxphy_cfg_6730(struct rk628_combrxphy * combrxphy)218 static void rk628_combrxphy_cfg_6730(struct rk628_combrxphy *combrxphy)
219 {
220 u32 val;
221
222 regmap_read(combrxphy->regmap, REG(0x6730), &val);
223 val = (val & 0xffff0000) | 0x1;
224 regmap_write(combrxphy->regmap, REG(0x6730), val);
225 }
226
rk628_combrxphy_sample_edge_procedure_for_cable(struct rk628_combrxphy * combrxphy,u32 cdr_mode)227 static void rk628_combrxphy_sample_edge_procedure_for_cable(
228 struct rk628_combrxphy *combrxphy, u32 cdr_mode)
229 {
230 u32 n, ch;
231 u32 data[MAX_DATA_NUM];
232 u32 data_in[MAX_DATA_NUM];
233 u32 round_max_zero[MAX_CHANNEL][MAX_ROUND];
234 u32 round_max_value[MAX_CHANNEL][MAX_ROUND];
235 u32 ch_round[MAX_CHANNEL];
236 u32 edge, dc_gain;
237 u32 rd_offset;
238
239 /* Step1: set sample edge mode for channel 0~2 */
240 for (ch = 0; ch < MAX_CHANNEL; ch++)
241 rk628_combrxphy_set_sample_edge_mode(combrxphy, ch);
242
243 /* step2: once per round */
244 for (ch = 0; ch < MAX_CHANNEL; ch++) {
245 rk628_combrxphy_select_channel(combrxphy, ch);
246 rk628_combrxphy_cfg_6730(combrxphy);
247 }
248
249 /* step3: config sample edge until the end of one frame
250 * (for example 1080p:2200*1125=32’h25c3f8)
251 */
252 if (cdr_mode < 16) {
253 dc_gain = 0;
254 rd_offset = 0;
255 } else if (cdr_mode < 18) {
256 dc_gain = 1;
257 rd_offset = 0;
258 } else {
259 dc_gain = 3;
260 rd_offset = 2;
261 }
262
263 /* When the pix clk is the same, the low frame rate resolution is used
264 * to calculate the sampling window (the frame rate is not less than
265 * 30). The sampling delay time is configured as 40ms.
266 */
267 if (cdr_mode <= 1) { /* 27M vic17 720x576P50 */
268 edge = 864 * 625;
269 } else if (cdr_mode <= 4) { /* 59.4M vic81 1680x720P30 */
270 edge = 2640 * 750;
271 } else if (cdr_mode <= 7) { /* 74.25M vic34 1920x1080P30 */
272 edge = 2200 * 1125;
273 } else if (cdr_mode <= 14) { /* 119M vic88 2560x1180P30 */
274 edge = 3520 * 1125;
275 } else if (cdr_mode <= 16) { /* 148.5M vic31 1920x1080P50 */
276 edge = 2640 * 1125;
277 } else if (cdr_mode <= 17) { /* 162M vic89 2560x1080P50 */
278 edge = 3300 * 1125;
279 } else if (cdr_mode <= 18) { /* 297M vic95 3840x2160P30 */
280 edge = 4400 * 2250;
281 } else { /* unkonw vic16 1920x1080P60 */
282 edge = 2200 * 1125;
283 }
284
285 dev_info(combrxphy->dev,
286 "cdr_mode:%d, dc_gain:%d, rd_offset:%d, edge:%#x\n",
287 cdr_mode, dc_gain, rd_offset, edge);
288 for (ch = 0; ch < MAX_CHANNEL; ch++) {
289 rk628_combrxphy_select_channel(combrxphy, ch);
290 regmap_write(combrxphy->regmap, REG(0x6708), edge);
291 }
292
293 rk628_combrxphy_set_dc_gain(combrxphy, dc_gain, dc_gain, dc_gain);
294 for (n = rd_offset; n < (rd_offset + MAX_ROUND); n++) {
295 /* step4:set sample edge round value n,n=0(n=0~31) */
296 rk628_combrxphy_set_sample_edge_round(combrxphy, n, n, n);
297 /* step5:start sample edge */
298 rk628_combrxphy_start_sample_edge(combrxphy);
299 /* step6:waiting more than one frame time */
300 usleep_range(40*1000, 41*1000);
301 for (ch = 0; ch < MAX_CHANNEL; ch++) {
302 /* step7: get data of round n */
303 rk628_combrxphy_select_channel(combrxphy, ch);
304 rk628_combrxphy_get_data_of_round(combrxphy, data);
305 rk628_combrxphy_set_data_of_round(data, data_in);
306 /* step8: get the max constant value of round n */
307 rk628_combrxphy_max_zero_of_round(combrxphy, data_in,
308 round_max_zero[ch], round_max_value[ch],
309 n - rd_offset, ch);
310 }
311 }
312
313 /* step9: after finish round, get the max constant value and
314 * corresponding value n.
315 */
316 for (ch = 0; ch < MAX_CHANNEL; ch++) {
317 ch_round[ch] = rk628_combrxphy_chose_round_for_ch(combrxphy,
318 round_max_zero[ch], round_max_value[ch], ch)
319 + rd_offset;
320 }
321 dev_info(combrxphy->dev, "last equ gain ch0:%d, ch1:%d, ch2:%d\n",
322 ch_round[0], ch_round[1], ch_round[2]);
323
324 /* step10: write result to sample edge round value */
325 rk628_combrxphy_set_sample_edge_round(combrxphy, ch_round[0],
326 ch_round[1], ch_round[2]);
327
328 /* do step5, step6 again */
329 /* step5:start sample edge */
330 rk628_combrxphy_start_sample_edge(combrxphy);
331 /* step6:waiting more than one frame time */
332 usleep_range(40*1000, 41*1000);
333 }
334
335 static void
rk628_combrxphy_sample_edge_procedure(struct rk628_combrxphy * combrxphy,int f,u32 rd_offset)336 rk628_combrxphy_sample_edge_procedure(struct rk628_combrxphy *combrxphy,
337 int f, u32 rd_offset)
338 {
339 u32 n, ch;
340 u32 data[MAX_DATA_NUM];
341 u32 data_in[MAX_DATA_NUM];
342 u32 round_max_zero[MAX_CHANNEL][MAX_ROUND];
343 u32 round_max_value[MAX_CHANNEL][MAX_ROUND];
344 u32 ch_round[MAX_CHANNEL];
345 u32 edge, dc_gain;
346
347 dev_dbg(combrxphy->dev, "%s in!", __func__);
348 /* Step1: set sample edge mode for channel 0~2 */
349 for (ch = 0; ch < MAX_CHANNEL; ch++)
350 rk628_combrxphy_set_sample_edge_mode(combrxphy, ch);
351
352 dev_dbg(combrxphy->dev, "step1 set sample edge mode ok!");
353
354 /* step2: once per round */
355 for (ch = 0; ch < MAX_CHANNEL; ch++) {
356 rk628_combrxphy_select_channel(combrxphy, ch);
357 rk628_combrxphy_cfg_6730(combrxphy);
358 }
359 dev_dbg(combrxphy->dev, "step2 once per round ok!");
360
361 /*
362 * step3:config sample edge until the end of one frame
363 * (for example 1080p:2200*1125=32’h25c3f8)
364 */
365 switch (f) {
366 case 27000:
367 edge = 858 * 525;
368 dc_gain = 0;
369 break;
370 case 64000:
371 edge = 1317 * 810;
372 dc_gain = 0;
373 break;
374 case 74250:
375 edge = 1650 * 750;
376 dc_gain = 0;
377 break;
378 case 148500:
379 edge = 2200 * 1125;
380 dc_gain = 1;
381 break;
382 case 297000:
383 dc_gain = 3;
384 edge = 4400 * 2250;
385 break;
386 case 594000:
387 dc_gain = 0xf;
388 edge = 4400 * 2250;
389 break;
390 default:
391 edge = 2200 * 1125;
392 dc_gain = 1;
393 break;
394 }
395 dev_dbg(combrxphy->dev, "===>>> f:%d, edge:%#x", f, edge);
396 for (ch = 0; ch < MAX_CHANNEL; ch++) {
397 rk628_combrxphy_select_channel(combrxphy, ch);
398 regmap_write(combrxphy->regmap, REG(0x6708), edge);
399 }
400 dev_dbg(combrxphy->dev, "step3 cfg sample edge ok!");
401
402 rk628_combrxphy_set_dc_gain(combrxphy, dc_gain, dc_gain, dc_gain);
403
404 for (n = rd_offset; n < (rd_offset + MAX_ROUND); n++) {
405 /* step4:set sample edge round value n,n=0(n=0~31) */
406 rk628_combrxphy_set_sample_edge_round(combrxphy, n, n, n);
407 dev_dbg(combrxphy->dev, "step4 ok!");
408 /* step5:start sample edge */
409 rk628_combrxphy_start_sample_edge(combrxphy);
410 dev_dbg(combrxphy->dev, "step5 ok!");
411 /* step6:waiting more than one frame time */
412 usleep_range(40*1000, 41*1000);
413 for (ch = 0; ch < MAX_CHANNEL; ch++) {
414 /* step7:get data of round n */
415 rk628_combrxphy_select_channel(combrxphy, ch);
416 dev_dbg(combrxphy->dev, "step7 set ch ok!");
417 rk628_combrxphy_get_data_of_round(combrxphy, data);
418 dev_dbg(combrxphy->dev, "step7 get data ok!");
419 rk628_combrxphy_set_data_of_round(data, data_in);
420 dev_dbg(combrxphy->dev, "step7 set data ok!");
421 rk628_combrxphy_max_zero_of_round(combrxphy, data_in,
422 round_max_zero[ch],
423 round_max_value[ch],
424 n - rd_offset, ch);
425 }
426 }
427 for (ch = 0; ch < MAX_CHANNEL; ch++)
428 ch_round[ch] =
429 rk628_combrxphy_chose_round_for_ch(combrxphy,
430 round_max_zero[ch],
431 round_max_value[ch],
432 ch) + rd_offset;
433
434 /*
435 * step8:after finish round 31, get the max constant value and
436 * corresponding value n.
437 * write result to sample edge round value.
438 */
439 rk628_combrxphy_set_sample_edge_round(combrxphy, ch_round[0],
440 ch_round[1], ch_round[2]);
441
442 /* do step5, step6 again */
443 dev_dbg(combrxphy->dev, "do step5 step6 again!");
444 rk628_combrxphy_start_sample_edge(combrxphy);
445 usleep_range(40*1000, 41*1000);
446 }
447
rk628_combrxphy_try_clk_detect(struct rk628_combrxphy * combrxphy)448 static int rk628_combrxphy_try_clk_detect(struct rk628_combrxphy *combrxphy)
449 {
450 u32 val, i;
451 int ret;
452
453 ret = -1;
454 reset_control_assert(combrxphy->rstc);
455 usleep_range(10, 20);
456 reset_control_deassert(combrxphy->rstc);
457 usleep_range(10, 20);
458
459 /* step1: set pin_rst_n to 1’b0.wait 1 period(1us).release reset */
460 /* step2: select pll clock src and enable auto check */
461 regmap_read(combrxphy->regmap, REG(0x6630), &val);
462 /* clear bit0 and bit3 */
463 val = val & 0xfffffff6;
464 regmap_write(combrxphy->regmap, REG(0x6630), val);
465 /* step3: select hdmi mode and enable chip, read reg6654,
466 * make sure auto setup done.
467 */
468 /* auto fsm reset related */
469 regmap_read(combrxphy->regmap, REG(0x6630), &val);
470 val = val | BIT(24);
471 regmap_write(combrxphy->regmap, REG(0x6630), val);
472 /* pull down ana rstn */
473 regmap_read(combrxphy->regmap, REG(0x66f0), &val);
474 val = val & 0xfffffeff;
475 regmap_write(combrxphy->regmap, REG(0x66f0), val);
476 /* pull down dig rstn */
477 regmap_read(combrxphy->regmap, REG(0x66f4), &val);
478 val = val & 0xfffffffe;
479 regmap_write(combrxphy->regmap, REG(0x66f4), val);
480 /* pull up ana rstn */
481 regmap_read(combrxphy->regmap, REG(0x66f0), &val);
482 val = val | 0x100;
483 regmap_write(combrxphy->regmap, REG(0x66f0), val);
484 /* pull up dig rstn */
485 regmap_read(combrxphy->regmap, REG(0x66f4), &val);
486 val = val | 0x1;
487 regmap_write(combrxphy->regmap, REG(0x66f4), val);
488
489 regmap_read(combrxphy->regmap, REG(0x66f0), &val);
490 /* set bit0 and bit2 to 1*/
491 val = (val & 0xfffffff8) | 0x5;
492 regmap_write(combrxphy->regmap, REG(0x66f0), val);
493
494 /* auto fsm en = 0 */
495 regmap_read(combrxphy->regmap, REG(0x66f0), &val);
496 /* set bit0 and bit2 to 1*/
497 val = (val & 0xfffffff8) | 0x4;
498 regmap_write(combrxphy->regmap, REG(0x66f0), val);
499
500 for (i = 0; i < 10; i++) {
501 usleep_range(500, 510);
502 regmap_read(combrxphy->regmap, REG(0x6654), &val);
503 if ((val & 0xf0000000) == 0x80000000) {
504 ret = 0;
505 dev_info(combrxphy->dev, "clock detected!");
506 break;
507 }
508 }
509
510 return ret;
511 }
512
513 static int
rk628_combrxphy_set_hdmi_mode_for_cable(struct rk628_combrxphy * combrxphy,int f)514 rk628_combrxphy_set_hdmi_mode_for_cable(struct rk628_combrxphy *combrxphy,
515 int f)
516 {
517 u32 val, val_a, val_b, data_a, data_b;
518 u32 i, j, count, ret;
519 u32 cdr_mode, cdr_data, pll_man;
520 u32 tmds_bitrate_per_lane;
521 u32 cdr_data_min, cdr_data_max;
522
523 /*
524 * use the mode of automatic clock detection, only supports fixed TMDS
525 * frequency.Refer to register 0x6654[21:16]:
526 * 5'd31:Error mode
527 * 5'd30:manual mode detected
528 * 5'd18:rx3p clock = 297MHz
529 * 5'd17:rx3p clock = 162MHz
530 * 5'd16:rx3p clock = 148.5MHz
531 * 5'd15:rx3p clock = 135MHz
532 * 5'd14:rx3p clock = 119MHz
533 * 5'd13:rx3p clock = 108MHz
534 * 5'd12:rx3p clock = 101MHz
535 * 5'd11:rx3p clock = 92.8125MHz
536 * 5'd10:rx3p clock = 88.75MHz
537 * 5'd9:rx3p clock = 85.5MHz
538 * 5'd8:rx3p clock = 83.5MHz
539 * 5'd7:rx3p clock = 74.25MHz
540 * 5'd6:rx3p clock = 68.25MHz
541 * 5'd5:rx3p clock = 65MHz
542 * 5'd4:rx3p clock = 59.4MHz
543 * 5'd3:rx3p clock = 40MHz
544 * 5'd2:rx3p clock = 33.75MHz
545 * 5'd1:rx3p clock = 27MHz
546 * 5'd0:rx3p clock = 25.17MHz
547 */
548
549 const u32 cdr_mode_to_khz[] = {
550 25170, 27000, 33750, 40000, 59400, 65000, 68250,
551 74250, 83500, 85500, 88750, 92812, 101000, 108000,
552 119000, 135000, 148500, 162000, 297000,
553 };
554
555 for (i = 0; i < CLK_DET_TRY_TIMES; i++) {
556 if (rk628_combrxphy_try_clk_detect(combrxphy) >= 0)
557 break;
558 usleep_range(100*1000, 100*1000);
559 }
560 regmap_read(combrxphy->regmap, REG(0x6654), &val);
561 dev_info(combrxphy->dev, "clk det over cnt:%d, reg_0x6654:%#x", i, val);
562
563 regmap_read(combrxphy->regmap, REG(0x6620), &val);
564 if ((i == CLK_DET_TRY_TIMES) ||
565 ((val & 0x7f000000) == 0) ||
566 ((val & 0x007f0000) == 0) ||
567 ((val & 0x00007f00) == 0) ||
568 ((val & 0x0000007f) == 0)) {
569 dev_info(combrxphy->dev,
570 "clock detected failed, cfg resistance manual!");
571 regmap_write(combrxphy->regmap, REG(0x6620), 0x66666666);
572 regmap_update_bits(combrxphy->regmap, REG(0x6604), BIT(31),
573 BIT(31));
574 usleep_range(1000, 1100);
575 }
576
577 /* step4: get cdr_mode and cdr_data */
578 for (j = 0; j < CLK_STABLE_LOOP_CNT ; j++) {
579 cdr_data_min = 0xffffffff;
580 cdr_data_max = 0;
581
582 for (i = 0; i < CLK_DET_TRY_TIMES; i++) {
583 regmap_read(combrxphy->regmap, REG(0x6654), &val);
584 cdr_data = val & 0xffff;
585 if (cdr_data <= cdr_data_min)
586 cdr_data_min = cdr_data;
587 if (cdr_data >= cdr_data_max)
588 cdr_data_max = cdr_data;
589 udelay(50);
590 }
591
592 if (((cdr_data_max - cdr_data_min) <= CLK_STABLE_THRESHOLD) &&
593 (cdr_data_min >= 60)) {
594 dev_info(combrxphy->dev, "clock stable!");
595 break;
596 }
597 }
598
599 if (j == CLK_STABLE_LOOP_CNT) {
600 regmap_read(combrxphy->regmap, REG(0x6630), &val_a);
601 regmap_read(combrxphy->regmap, REG(0x6608), &val_b);
602 dev_err(combrxphy->dev,
603 "err, clk not stable, reg_0x6630:%#x, reg_0x6608:%#x",
604 val_a, val_b);
605
606 return -EINVAL;
607 }
608
609 regmap_read(combrxphy->regmap, REG(0x6654), &val);
610 if ((val & 0x1f0000) == 0x1f0000) {
611 regmap_read(combrxphy->regmap, REG(0x6630), &val_a);
612 regmap_read(combrxphy->regmap, REG(0x6608), &val_b);
613 dev_err(combrxphy->dev,
614 "clock error: 0x1f, reg_0x6630:%#x, reg_0x6608:%#x",
615 val_a, val_b);
616
617 return -EINVAL;
618 }
619
620 cdr_mode = (val >> 16) & 0x1f;
621 cdr_data = val & 0xffff;
622 dev_info(combrxphy->dev, "cdr_mode:%d, cdr_data:%d\n", cdr_mode,
623 cdr_data);
624
625 /* step5: manually configure PLL
626 * cfg reg 66a8 tmds clock div2 for rgb/yuv444 as default
627 * reg 662c[16:8] pll_pre_div
628 */
629 if (f <= 340000) {
630 regmap_write(combrxphy->regmap, REG(0x662c), 0x01000500);
631 regmap_write(combrxphy->regmap, REG(0x66a8), 0x0000c600);
632 } else {
633 regmap_write(combrxphy->regmap, REG(0x662c), 0x01001400);
634 regmap_write(combrxphy->regmap, REG(0x66a8), 0x0000c600);
635 }
636
637 /* when tmds bitrate/lane <= 340M, bitrate/lane = pix_clk * 10 */
638 tmds_bitrate_per_lane = cdr_mode_to_khz[cdr_mode] * 10;
639 if (tmds_bitrate_per_lane < 400000)
640 pll_man = 0x7960c;
641 else if (tmds_bitrate_per_lane < 600000)
642 pll_man = 0x7750c;
643 else if (tmds_bitrate_per_lane < 800000)
644 pll_man = 0x7964c;
645 else if (tmds_bitrate_per_lane < 1000000)
646 pll_man = 0x7754c;
647 else if (tmds_bitrate_per_lane < 1600000)
648 pll_man = 0x7a108;
649 else if (tmds_bitrate_per_lane < 2400000)
650 pll_man = 0x73588;
651 else if (tmds_bitrate_per_lane < 3400000)
652 pll_man = 0x7a108;
653 else
654 pll_man = 0x7f0c8;
655
656 dev_info(combrxphy->dev, "cdr_mode:%d, pll_man:%#x\n", cdr_mode,
657 pll_man);
658 regmap_write(combrxphy->regmap, REG(0x6630), pll_man);
659
660 /* step6: EQ and SAMPLE cfg */
661 rk628_combrxphy_sample_edge_procedure_for_cable(combrxphy, cdr_mode);
662
663 /* step7: Deassert fifo reset,enable fifo write and read */
664 /* reset rx_infifo */
665 regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000003);
666 /* rx_infofo wr/rd disable */
667 regmap_write(combrxphy->regmap, REG(0x66b0), 0x00080060);
668 /* deassert rx_infifo reset */
669 regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000083);
670 /* enable rx_infofo wr/rd en */
671 regmap_write(combrxphy->regmap, REG(0x66b0), 0x00380060);
672 /* cfg 0x2260 high_8b to 0x66ac high_8b, low_8b to 0x66b0 low_8b */
673 regmap_update_bits(combrxphy->regmap, REG(0x66ac), GENMASK(31, 24),
674 UPDATE(0x22, 31, 24));
675 usleep_range(5*1000, 6*1000);
676
677 /* step8: check all 3 data channels alignment */
678 count = 0;
679 for (i = 0; i < 100; i++) {
680 usleep_range(100, 110);
681 regmap_read(combrxphy->regmap, REG(0x66b4), &data_a);
682 regmap_read(combrxphy->regmap, REG(0x66b8), &data_b);
683 /* ch0 ch1 ch2 lock */
684 if (((data_a & 0x00ff00ff) == 0x00ff00ff) &&
685 ((data_b & 0xff) == 0xff)) {
686 count++;
687 }
688 }
689
690 if (count >= 100) {
691 dev_info(combrxphy->dev, "channel alignment done");
692 dev_info(combrxphy->dev, "rx initial done");
693 ret = 0;
694 } else if (count > 0) {
695 dev_err(combrxphy->dev, "link not stable, count:%d of 100",
696 count);
697 ret = 0;
698 } else {
699 dev_err(combrxphy->dev, "channel alignment failed!");
700 ret = -EINVAL;
701 }
702
703 return ret;
704 }
705
rk628_combrxphy_set_hdmi_mode(struct rk628_combrxphy * combrxphy,int bus_width)706 static int rk628_combrxphy_set_hdmi_mode(struct rk628_combrxphy *combrxphy,
707 int bus_width)
708 {
709 u32 val, data_a, data_b, f, val2 = 0;
710 int i, ret, count;
711 u32 pll_man, rd_offset;
712 bool is_yuv420;
713
714 is_yuv420 = bus_width & BIT(30);
715
716 if (is_yuv420)
717 f = (bus_width & 0xffffff) / 2;
718 else
719 f = bus_width & 0xffffff;
720
721 dev_dbg(combrxphy->dev, "f:%d\n", f);
722
723 regmap_read(combrxphy->regmap, REG(0x6630), &val);
724 val &= ~BIT(23);
725 val |= 0x18;
726 regmap_write(combrxphy->regmap, REG(0x6630), val);
727
728 /* enable cal */
729 regmap_read(combrxphy->regmap, REG(0x6610), &val);
730 val |= 0x18000000;
731 regmap_write(combrxphy->regmap, REG(0x6610), val);
732
733 usleep_range(10*1000, 11*1000);
734 /* disable cal */
735 val &= ~BIT(28);
736 val |= BIT(27);
737 regmap_write(combrxphy->regmap, REG(0x6610), val);
738
739 /* save cal val */
740 regmap_read(combrxphy->regmap, REG(0x6614), &val);
741 if (!(val & 0x3f00)) {
742 dev_err(combrxphy->dev, "resistor error\n");
743 return -EINVAL;
744 }
745
746 val &= 0x3f00;
747 val = val >> 8;
748 val2 |= 0x40404040;
749 val2 |= val << 24 | val << 16 | val << 8 | val;
750
751 /* rtm inc */
752 regmap_read(combrxphy->regmap, REG(0x6604), &val);
753 val |= BIT(31);
754 regmap_write(combrxphy->regmap, REG(0x6604), val);
755
756 regmap_write(combrxphy->regmap, REG(0x6620), val2);
757
758 /* rtm en bypass */
759 regmap_read(combrxphy->regmap, REG(0x6600), &val);
760 val |= BIT(7);
761 regmap_write(combrxphy->regmap, REG(0x6600), val);
762
763 /* rtm prot en bypass */
764 regmap_read(combrxphy->regmap, REG(0x6610), &val);
765 val |= 0x80f000;
766 regmap_write(combrxphy->regmap, REG(0x6610), val);
767
768 regmap_read(combrxphy->regmap, REG(0x661c), &val);
769 val |= 0x81000000;
770 regmap_write(combrxphy->regmap, REG(0x661c), val);
771
772 /* enable pll */
773 regmap_read(combrxphy->regmap, REG(0x6630), &val);
774 val &= ~BIT(4);
775 val |= BIT(3);
776 regmap_write(combrxphy->regmap, REG(0x6630), val);
777
778 /* equ en */
779 regmap_read(combrxphy->regmap, REG(0x6618), &val);
780 val |= BIT(4);
781 regmap_write(combrxphy->regmap, REG(0x6618), val);
782
783 regmap_read(combrxphy->regmap, REG(0x6614), &val);
784 val |= 0x10900000;
785 regmap_write(combrxphy->regmap, REG(0x6614), val);
786
787 regmap_read(combrxphy->regmap, REG(0x6610), &val);
788 val |= 0xf00;
789 regmap_write(combrxphy->regmap, REG(0x6610), val);
790
791 regmap_read(combrxphy->regmap, REG(0x6630), &val);
792 val |= 0x870000;
793 regmap_write(combrxphy->regmap, REG(0x6630), val);
794
795 udelay(10);
796
797 /* get cdr_mode,make sure cdr_mode != 5’h1f */
798 regmap_read(combrxphy->regmap, REG(0x6654), &val);
799 if ((val & 0x1f0000) == 0x1f0000)
800 dev_err(combrxphy->dev, "error,clock error!");
801
802 /* manually configure PLL */
803 if (f <= 340000) {
804 regmap_write(combrxphy->regmap, REG(0x662c), 0x01000500);
805 if (is_yuv420)
806 regmap_write(combrxphy->regmap, REG(0x66a8),
807 0x0000c000);
808 else
809 regmap_write(combrxphy->regmap, REG(0x66a8),
810 0x0000c600);
811 } else {
812 regmap_write(combrxphy->regmap, REG(0x662c), 0x01001400);
813 regmap_write(combrxphy->regmap, REG(0x66a8), 0x0000c600);
814 }
815
816 switch (f) {
817 case 27000:
818 case 64000:
819 case 74250:
820 rd_offset = 0;
821 pll_man = 0x7964c;
822 break;
823 case 148500:
824 pll_man = 0x7a1c8;
825 rd_offset = 0;
826 break;
827 case 297000:
828 pll_man = 0x7a108;
829 rd_offset = 2;
830 break;
831 case 594000:
832 pll_man = 0x7f0c8;
833 rd_offset = 4;
834 break;
835 default:
836 pll_man = 0x7964c;
837 rd_offset = 1;
838 break;
839 }
840
841 pll_man |= BIT(23);
842 regmap_write(combrxphy->regmap, REG(0x6630), pll_man);
843
844 /* EQ and SAMPLE cfg */
845 rk628_combrxphy_sample_edge_procedure(combrxphy, f, rd_offset);
846
847 /* Deassert fifo reset,enable fifo write and read */
848 regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000003);
849 regmap_write(combrxphy->regmap, REG(0x66b0), 0x00080060);
850 regmap_write(combrxphy->regmap, REG(0x66a0), 0x00000083);
851 regmap_write(combrxphy->regmap, REG(0x66b0), 0x00380060);
852 regmap_update_bits(combrxphy->regmap, REG(0x66ac), GENMASK(31, 24),
853 UPDATE(0x22, 31, 24));
854 usleep_range(10*1000, 11*1000);
855
856 /* check all 3 data channels alignment */
857 count = 0;
858 for (i = 0; i < 100; i++) {
859 udelay(100);
860 regmap_read(combrxphy->regmap, REG(0x66b4), &data_a);
861 regmap_read(combrxphy->regmap, REG(0x66b8), &data_b);
862 /* ch0 ch1 ch2 lock */
863 if (((data_a & 0x00ff00ff) == 0x00ff00ff) &&
864 ((data_b & 0xff) == 0xff))
865 count++;
866 }
867
868 if (count >= 100) {
869 dev_info(combrxphy->dev, "channel alignment done");
870 ret = 0;
871 } else if (count > 0) {
872 dev_err(combrxphy->dev, "not stable, count:%d of 100", count);
873 ret = -EINVAL;
874 } else {
875 dev_err(combrxphy->dev, "channel alignment failed!");
876 ret = -EINVAL;
877 }
878
879 return ret;
880 }
881
rk628_combrxphy_power_on(struct phy * phy)882 static int rk628_combrxphy_power_on(struct phy *phy)
883 {
884 struct rk628_combrxphy *combrxphy = phy_get_drvdata(phy);
885 int f = phy_get_bus_width(phy);
886 int ret;
887
888 /* Bit31 is used to distinguish HDMI cable mode and direct
889 * connection mode.
890 * Bit31: 0 -direct connection mode;
891 * 1 -cable mode;
892 */
893 combrxphy->is_cable_mode = (f & BIT(31)) ? true : false;
894 dev_dbg(combrxphy->dev, "%s\n", __func__);
895 clk_prepare_enable(combrxphy->pclk);
896 reset_control_assert(combrxphy->rstc);
897 udelay(10);
898 reset_control_deassert(combrxphy->rstc);
899 udelay(10);
900
901 if (combrxphy->is_cable_mode) {
902 f = f & 0x7fffffff;
903 ret = rk628_combrxphy_set_hdmi_mode_for_cable(combrxphy, f);
904 } else {
905 ret = rk628_combrxphy_set_hdmi_mode(combrxphy, f);
906 }
907
908 return ret;
909 }
910
rk628_combrxphy_power_off(struct phy * phy)911 static int rk628_combrxphy_power_off(struct phy *phy)
912 {
913 struct rk628_combrxphy *combrxphy = phy_get_drvdata(phy);
914
915 dev_dbg(combrxphy->dev, "%s\n", __func__);
916 reset_control_assert(combrxphy->rstc);
917 udelay(10);
918 clk_disable_unprepare(combrxphy->pclk);
919
920 return 0;
921 }
922
923 static const struct phy_ops rk628_combrxphy_ops = {
924 .power_on = rk628_combrxphy_power_on,
925 .power_off = rk628_combrxphy_power_off,
926 .owner = THIS_MODULE,
927 };
928
929 static const struct regmap_range rk628_combrxphy_readable_ranges[] = {
930 regmap_reg_range(REG(0x6600), REG(0x665b)),
931 regmap_reg_range(REG(0x66a0), REG(0x66db)),
932 regmap_reg_range(REG(0x66f0), REG(0x66ff)),
933 regmap_reg_range(REG(0x6700), REG(0x6790)),
934 };
935
936 static const struct regmap_access_table rk628_combrxphy_readable_table = {
937 .yes_ranges = rk628_combrxphy_readable_ranges,
938 .n_yes_ranges = ARRAY_SIZE(rk628_combrxphy_readable_ranges),
939 };
940
941 static const struct regmap_config rk628_combrxphy_regmap_cfg = {
942 .name = "combrxphy",
943 .reg_bits = 32,
944 .val_bits = 32,
945 .reg_stride = 4,
946 .max_register = COMBRXPHY_MAX_REGISTER,
947 .reg_format_endian = REGMAP_ENDIAN_LITTLE,
948 .val_format_endian = REGMAP_ENDIAN_LITTLE,
949 .rd_table = &rk628_combrxphy_readable_table,
950 };
951
rk628_combrxphy_probe(struct platform_device * pdev)952 static int rk628_combrxphy_probe(struct platform_device *pdev)
953 {
954 struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
955 struct device *dev = &pdev->dev;
956 struct rk628_combrxphy *combrxphy;
957 struct phy_provider *phy_provider;
958 struct phy *phy;
959 int ret;
960
961 if (!of_device_is_available(dev->of_node))
962 return -ENODEV;
963
964 combrxphy = devm_kzalloc(dev, sizeof(*combrxphy), GFP_KERNEL);
965 if (!combrxphy)
966 return -ENOMEM;
967
968 combrxphy->dev = dev;
969 combrxphy->parent = rk628;
970 platform_set_drvdata(pdev, combrxphy);
971
972 combrxphy->pclk = devm_clk_get(dev, "pclk");
973 if (IS_ERR(combrxphy->pclk)) {
974 ret = PTR_ERR(combrxphy->pclk);
975 dev_err(dev, "failed to get pclk: %d\n", ret);
976 return ret;
977 }
978
979 combrxphy->rstc = of_reset_control_get(dev->of_node, NULL);
980 if (IS_ERR(combrxphy->rstc)) {
981 ret = PTR_ERR(combrxphy->rstc);
982 dev_err(dev, "failed to get reset control: %d\n", ret);
983 return ret;
984 }
985
986 combrxphy->regmap = devm_regmap_init_i2c(rk628->client,
987 &rk628_combrxphy_regmap_cfg);
988 if (IS_ERR(combrxphy->regmap)) {
989 ret = PTR_ERR(combrxphy->regmap);
990 dev_err(dev, "failed to allocate host register map: %d\n", ret);
991 return ret;
992 }
993
994 phy = devm_phy_create(dev, NULL, &rk628_combrxphy_ops);
995 if (IS_ERR(phy)) {
996 ret = PTR_ERR(phy);
997 dev_err(dev, "failed to create phy: %d\n", ret);
998 return ret;
999 }
1000
1001 phy_set_drvdata(phy, combrxphy);
1002
1003 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
1004 if (IS_ERR(phy_provider)) {
1005 ret = PTR_ERR(phy_provider);
1006 dev_err(dev, "failed to register phy provider: %d\n", ret);
1007 return ret;
1008 }
1009
1010 return 0;
1011 }
1012
1013 static const struct of_device_id rk628_combrxphy_of_match[] = {
1014 { .compatible = "rockchip,rk628-combrxphy", },
1015 {}
1016 };
1017 MODULE_DEVICE_TABLE(of, rk628_combrxphy_of_match);
1018
1019 static struct platform_driver rk628_combrxphy_driver = {
1020 .driver = {
1021 .name = "rk628-combrxphy",
1022 .of_match_table = of_match_ptr(rk628_combrxphy_of_match),
1023 },
1024 .probe = rk628_combrxphy_probe,
1025 };
1026 module_platform_driver(rk628_combrxphy_driver);
1027
1028 MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");
1029 MODULE_DESCRIPTION("Rockchip RK628 HDMI Combo RX PHY driver");
1030 MODULE_LICENSE("GPL v2");
1031