]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt.c
This is the driver for Sony CXD2880 DVB-T2/T tuner + demodulator.
[mirror_ubuntu-artful-kernel.git] / drivers / media / dvb-frontends / cxd2880 / cxd2880_tnrdmd_dvbt.c
1 /*
2 * cxd2880_tnrdmd_dvbt.c
3 * Sony CXD2880 DVB-T2/T tuner + demodulator driver
4 * control functions for DVB-T
5 *
6 * Copyright (C) 2016, 2017 Sony Semiconductor Solutions Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; version 2 of the License.
11 *
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #include "cxd2880_tnrdmd_dvbt.h"
28 #include "cxd2880_tnrdmd_dvbt_mon.h"
29
30 static enum cxd2880_ret x_tune_dvbt_demod_setting(struct cxd2880_tnrdmd
31 *tnr_dmd,
32 enum cxd2880_dtv_bandwidth
33 bandwidth,
34 enum cxd2880_tnrdmd_clockmode
35 clk_mode)
36 {
37 if (!tnr_dmd)
38 return CXD2880_RESULT_ERROR_ARG;
39
40 if (tnr_dmd->io->write_reg(tnr_dmd->io,
41 CXD2880_IO_TGT_SYS, 0x00,
42 0x00) != CXD2880_RESULT_OK)
43 return CXD2880_RESULT_ERROR_IO;
44
45 if (tnr_dmd->io->write_reg(tnr_dmd->io,
46 CXD2880_IO_TGT_SYS, 0x31,
47 0x01) != CXD2880_RESULT_OK)
48 return CXD2880_RESULT_ERROR_IO;
49
50 {
51 u8 data_a[2] = { 0x52, 0x49 };
52 u8 data_b[2] = { 0x5D, 0x55 };
53 u8 data_c[2] = { 0x60, 0x00 };
54 u8 *data = NULL;
55
56 if (tnr_dmd->io->write_reg(tnr_dmd->io,
57 CXD2880_IO_TGT_DMD, 0x00,
58 0x04) != CXD2880_RESULT_OK)
59 return CXD2880_RESULT_ERROR_IO;
60
61 switch (clk_mode) {
62 case CXD2880_TNRDMD_CLOCKMODE_A:
63 data = data_a;
64 break;
65 case CXD2880_TNRDMD_CLOCKMODE_B:
66 data = data_b;
67 break;
68 case CXD2880_TNRDMD_CLOCKMODE_C:
69 data = data_c;
70 break;
71 default:
72 return CXD2880_RESULT_ERROR_SW_STATE;
73 }
74
75 if (tnr_dmd->io->write_regs(tnr_dmd->io,
76 CXD2880_IO_TGT_DMD, 0x65, data,
77 2) != CXD2880_RESULT_OK)
78 return CXD2880_RESULT_ERROR_IO;
79 }
80
81 if (tnr_dmd->io->write_reg(tnr_dmd->io,
82 CXD2880_IO_TGT_DMD, 0x5D,
83 0x07) != CXD2880_RESULT_OK)
84 return CXD2880_RESULT_ERROR_IO;
85
86 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
87 u8 data[2] = { 0x01, 0x01 };
88
89 if (tnr_dmd->io->write_reg(tnr_dmd->io,
90 CXD2880_IO_TGT_DMD, 0x00,
91 0x00) != CXD2880_RESULT_OK)
92 return CXD2880_RESULT_ERROR_IO;
93
94 if (tnr_dmd->io->write_regs(tnr_dmd->io,
95 CXD2880_IO_TGT_DMD, 0xCE, data,
96 2) != CXD2880_RESULT_OK)
97 return CXD2880_RESULT_ERROR_IO;
98 }
99
100 if (tnr_dmd->io->write_reg(tnr_dmd->io,
101 CXD2880_IO_TGT_DMD, 0x00,
102 0x04) != CXD2880_RESULT_OK)
103 return CXD2880_RESULT_ERROR_IO;
104
105 if (tnr_dmd->io->write_reg(tnr_dmd->io,
106 CXD2880_IO_TGT_DMD, 0x5C,
107 0xFB) != CXD2880_RESULT_OK)
108 return CXD2880_RESULT_ERROR_IO;
109
110 if (tnr_dmd->io->write_reg(tnr_dmd->io,
111 CXD2880_IO_TGT_DMD, 0x00,
112 0x10) != CXD2880_RESULT_OK)
113 return CXD2880_RESULT_ERROR_IO;
114
115 if (tnr_dmd->io->write_reg(tnr_dmd->io,
116 CXD2880_IO_TGT_DMD, 0xA4,
117 0x03) != CXD2880_RESULT_OK)
118 return CXD2880_RESULT_ERROR_IO;
119
120 if (tnr_dmd->io->write_reg(tnr_dmd->io,
121 CXD2880_IO_TGT_DMD, 0x00,
122 0x14) != CXD2880_RESULT_OK)
123 return CXD2880_RESULT_ERROR_IO;
124
125 if (tnr_dmd->io->write_reg(tnr_dmd->io,
126 CXD2880_IO_TGT_DMD, 0xB0,
127 0x00) != CXD2880_RESULT_OK)
128 return CXD2880_RESULT_ERROR_IO;
129
130 if (tnr_dmd->io->write_reg(tnr_dmd->io,
131 CXD2880_IO_TGT_DMD, 0x00,
132 0x25) != CXD2880_RESULT_OK)
133 return CXD2880_RESULT_ERROR_IO;
134
135 {
136 u8 data[2] = { 0x01, 0xF0 };
137
138 if (tnr_dmd->io->write_regs(tnr_dmd->io,
139 CXD2880_IO_TGT_DMD, 0xF0, data,
140 2) != CXD2880_RESULT_OK)
141 return CXD2880_RESULT_ERROR_IO;
142 }
143
144 if ((tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) ||
145 (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)) {
146 if (tnr_dmd->io->write_reg(tnr_dmd->io,
147 CXD2880_IO_TGT_DMD, 0x00,
148 0x12) != CXD2880_RESULT_OK)
149 return CXD2880_RESULT_ERROR_IO;
150
151 if (tnr_dmd->io->write_reg(tnr_dmd->io,
152 CXD2880_IO_TGT_DMD, 0x44,
153 0x00) != CXD2880_RESULT_OK)
154 return CXD2880_RESULT_ERROR_IO;
155 }
156
157 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
158 if (tnr_dmd->io->write_reg(tnr_dmd->io,
159 CXD2880_IO_TGT_DMD, 0x00,
160 0x11) != CXD2880_RESULT_OK)
161 return CXD2880_RESULT_ERROR_IO;
162
163 if (tnr_dmd->io->write_reg(tnr_dmd->io,
164 CXD2880_IO_TGT_DMD, 0x87,
165 0xD2) != CXD2880_RESULT_OK)
166 return CXD2880_RESULT_ERROR_IO;
167 }
168
169 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
170 u8 data_a[3] = { 0x73, 0xCA, 0x49 };
171 u8 data_b[3] = { 0xC8, 0x13, 0xAA };
172 u8 data_c[3] = { 0xDC, 0x6C, 0x00 };
173 u8 *data = NULL;
174
175 if (tnr_dmd->io->write_reg(tnr_dmd->io,
176 CXD2880_IO_TGT_DMD, 0x00,
177 0x04) != CXD2880_RESULT_OK)
178 return CXD2880_RESULT_ERROR_IO;
179
180 switch (clk_mode) {
181 case CXD2880_TNRDMD_CLOCKMODE_A:
182 data = data_a;
183 break;
184 case CXD2880_TNRDMD_CLOCKMODE_B:
185 data = data_b;
186 break;
187 case CXD2880_TNRDMD_CLOCKMODE_C:
188 data = data_c;
189 break;
190 default:
191 return CXD2880_RESULT_ERROR_SW_STATE;
192 }
193
194 if (tnr_dmd->io->write_regs(tnr_dmd->io,
195 CXD2880_IO_TGT_DMD, 0x68, data,
196 3) != CXD2880_RESULT_OK)
197 return CXD2880_RESULT_ERROR_IO;
198 }
199
200 if (tnr_dmd->io->write_reg(tnr_dmd->io,
201 CXD2880_IO_TGT_DMD, 0x00,
202 0x04) != CXD2880_RESULT_OK)
203 return CXD2880_RESULT_ERROR_IO;
204
205 switch (bandwidth) {
206 case CXD2880_DTV_BW_8_MHZ:
207
208 {
209 u8 data_ac[5] = { 0x15, 0x00, 0x00, 0x00,
210 0x00
211 };
212 u8 data_b[5] = { 0x14, 0x6A, 0xAA, 0xAA,
213 0xAA
214 };
215 u8 *data = NULL;
216
217 switch (clk_mode) {
218 case CXD2880_TNRDMD_CLOCKMODE_A:
219 case CXD2880_TNRDMD_CLOCKMODE_C:
220 data = data_ac;
221 break;
222 case CXD2880_TNRDMD_CLOCKMODE_B:
223 data = data_b;
224 break;
225 default:
226 return CXD2880_RESULT_ERROR_SW_STATE;
227 }
228
229 if (tnr_dmd->io->write_regs(tnr_dmd->io,
230 CXD2880_IO_TGT_DMD, 0x60,
231 data,
232 5) != CXD2880_RESULT_OK)
233 return CXD2880_RESULT_ERROR_IO;
234 }
235
236 if (tnr_dmd->io->write_reg(tnr_dmd->io,
237 CXD2880_IO_TGT_DMD, 0x4A,
238 0x00) != CXD2880_RESULT_OK)
239 return CXD2880_RESULT_ERROR_IO;
240
241 {
242 u8 data_a[2] = { 0x01, 0x28 };
243 u8 data_b[2] = { 0x11, 0x44 };
244 u8 data_c[2] = { 0x15, 0x28 };
245 u8 *data = NULL;
246
247 switch (clk_mode) {
248 case CXD2880_TNRDMD_CLOCKMODE_A:
249 data = data_a;
250 break;
251 case CXD2880_TNRDMD_CLOCKMODE_B:
252 data = data_b;
253 break;
254 case CXD2880_TNRDMD_CLOCKMODE_C:
255 data = data_c;
256 break;
257 default:
258 return CXD2880_RESULT_ERROR_SW_STATE;
259 }
260
261 if (tnr_dmd->io->write_regs(tnr_dmd->io,
262 CXD2880_IO_TGT_DMD, 0x7D,
263 data,
264 2) != CXD2880_RESULT_OK)
265 return CXD2880_RESULT_ERROR_IO;
266 }
267
268 {
269 u8 data = 0;
270
271 switch (clk_mode) {
272 case CXD2880_TNRDMD_CLOCKMODE_A:
273 case CXD2880_TNRDMD_CLOCKMODE_B:
274 data = 0x35;
275 break;
276 case CXD2880_TNRDMD_CLOCKMODE_C:
277 data = 0x34;
278 break;
279 default:
280 return CXD2880_RESULT_ERROR_SW_STATE;
281 }
282
283 if (tnr_dmd->io->write_reg(tnr_dmd->io,
284 CXD2880_IO_TGT_DMD, 0x71,
285 data) != CXD2880_RESULT_OK)
286 return CXD2880_RESULT_ERROR_IO;
287 }
288
289 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
290 u8 data_a[5] = { 0x30, 0x00, 0x00, 0x90,
291 0x00
292 };
293 u8 data_b[5] = { 0x36, 0x71, 0x00, 0xA3,
294 0x55
295 };
296 u8 data_c[5] = { 0x38, 0x00, 0x00, 0xA8,
297 0x00
298 };
299 u8 *data = NULL;
300
301 switch (clk_mode) {
302 case CXD2880_TNRDMD_CLOCKMODE_A:
303 data = data_a;
304 break;
305 case CXD2880_TNRDMD_CLOCKMODE_B:
306 data = data_b;
307 break;
308 case CXD2880_TNRDMD_CLOCKMODE_C:
309 data = data_c;
310 break;
311 default:
312 return CXD2880_RESULT_ERROR_SW_STATE;
313 }
314
315 if (tnr_dmd->io->write_regs(tnr_dmd->io,
316 CXD2880_IO_TGT_DMD, 0x4B,
317 &data[0],
318 2) != CXD2880_RESULT_OK)
319 return CXD2880_RESULT_ERROR_IO;
320
321 if (tnr_dmd->io->write_regs(tnr_dmd->io,
322 CXD2880_IO_TGT_DMD, 0x51,
323 &data[2],
324 3) != CXD2880_RESULT_OK)
325 return CXD2880_RESULT_ERROR_IO;
326 }
327
328 {
329 u8 data[4] = { 0xB3, 0x00, 0x01, 0x02 };
330
331 if (tnr_dmd->io->write_regs(tnr_dmd->io,
332 CXD2880_IO_TGT_DMD, 0x72,
333 &data[0],
334 2) != CXD2880_RESULT_OK)
335 return CXD2880_RESULT_ERROR_IO;
336
337 if (tnr_dmd->io->write_regs(tnr_dmd->io,
338 CXD2880_IO_TGT_DMD, 0x6B,
339 &data[2],
340 2) != CXD2880_RESULT_OK)
341 return CXD2880_RESULT_ERROR_IO;
342 }
343 break;
344
345 case CXD2880_DTV_BW_7_MHZ:
346
347 {
348 u8 data_ac[5] = { 0x18, 0x00, 0x00, 0x00,
349 0x00
350 };
351 u8 data_b[5] = { 0x17, 0x55, 0x55, 0x55,
352 0x55
353 };
354 u8 *data = NULL;
355
356 switch (clk_mode) {
357 case CXD2880_TNRDMD_CLOCKMODE_A:
358 case CXD2880_TNRDMD_CLOCKMODE_C:
359 data = data_ac;
360 break;
361 case CXD2880_TNRDMD_CLOCKMODE_B:
362 data = data_b;
363 break;
364 default:
365 return CXD2880_RESULT_ERROR_SW_STATE;
366 }
367
368 if (tnr_dmd->io->write_regs(tnr_dmd->io,
369 CXD2880_IO_TGT_DMD, 0x60,
370 data,
371 5) != CXD2880_RESULT_OK)
372 return CXD2880_RESULT_ERROR_IO;
373 }
374
375 if (tnr_dmd->io->write_reg(tnr_dmd->io,
376 CXD2880_IO_TGT_DMD, 0x4A,
377 0x02) != CXD2880_RESULT_OK)
378 return CXD2880_RESULT_ERROR_IO;
379
380 {
381 u8 data_a[2] = { 0x12, 0x4C };
382 u8 data_b[2] = { 0x1F, 0x15 };
383 u8 data_c[2] = { 0x1F, 0xF8 };
384 u8 *data = NULL;
385
386 switch (clk_mode) {
387 case CXD2880_TNRDMD_CLOCKMODE_A:
388 data = data_a;
389 break;
390 case CXD2880_TNRDMD_CLOCKMODE_B:
391 data = data_b;
392 break;
393 case CXD2880_TNRDMD_CLOCKMODE_C:
394 data = data_c;
395 break;
396 default:
397 return CXD2880_RESULT_ERROR_SW_STATE;
398 }
399
400 if (tnr_dmd->io->write_regs(tnr_dmd->io,
401 CXD2880_IO_TGT_DMD, 0x7D,
402 data,
403 2) != CXD2880_RESULT_OK)
404 return CXD2880_RESULT_ERROR_IO;
405 }
406
407 {
408 u8 data = 0;
409
410 switch (clk_mode) {
411 case CXD2880_TNRDMD_CLOCKMODE_A:
412 case CXD2880_TNRDMD_CLOCKMODE_B:
413 data = 0x2F;
414 break;
415 case CXD2880_TNRDMD_CLOCKMODE_C:
416 data = 0x2E;
417 break;
418 default:
419 return CXD2880_RESULT_ERROR_SW_STATE;
420 }
421
422 if (tnr_dmd->io->write_reg(tnr_dmd->io,
423 CXD2880_IO_TGT_DMD, 0x71,
424 data) != CXD2880_RESULT_OK)
425 return CXD2880_RESULT_ERROR_IO;
426 }
427
428 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
429 u8 data_a[5] = { 0x36, 0xDB, 0x00, 0xA4,
430 0x92
431 };
432 u8 data_b[5] = { 0x3E, 0x38, 0x00, 0xBA,
433 0xAA
434 };
435 u8 data_c[5] = { 0x40, 0x00, 0x00, 0xC0,
436 0x00
437 };
438 u8 *data = NULL;
439
440 switch (clk_mode) {
441 case CXD2880_TNRDMD_CLOCKMODE_A:
442 data = data_a;
443 break;
444 case CXD2880_TNRDMD_CLOCKMODE_B:
445 data = data_b;
446 break;
447 case CXD2880_TNRDMD_CLOCKMODE_C:
448 data = data_c;
449 break;
450 default:
451 return CXD2880_RESULT_ERROR_SW_STATE;
452 }
453
454 if (tnr_dmd->io->write_regs(tnr_dmd->io,
455 CXD2880_IO_TGT_DMD, 0x4B,
456 &data[0],
457 2) != CXD2880_RESULT_OK)
458 return CXD2880_RESULT_ERROR_IO;
459
460 if (tnr_dmd->io->write_regs(tnr_dmd->io,
461 CXD2880_IO_TGT_DMD, 0x51,
462 &data[2],
463 3) != CXD2880_RESULT_OK)
464 return CXD2880_RESULT_ERROR_IO;
465 }
466
467 {
468 u8 data[4] = { 0xB8, 0x00, 0x00, 0x03 };
469
470 if (tnr_dmd->io->write_regs(tnr_dmd->io,
471 CXD2880_IO_TGT_DMD, 0x72,
472 &data[0],
473 2) != CXD2880_RESULT_OK)
474 return CXD2880_RESULT_ERROR_IO;
475
476 if (tnr_dmd->io->write_regs(tnr_dmd->io,
477 CXD2880_IO_TGT_DMD, 0x6B,
478 &data[2],
479 2) != CXD2880_RESULT_OK)
480 return CXD2880_RESULT_ERROR_IO;
481 }
482 break;
483
484 case CXD2880_DTV_BW_6_MHZ:
485
486 {
487 u8 data_ac[5] = { 0x1C, 0x00, 0x00, 0x00,
488 0x00
489 };
490 u8 data_b[5] = { 0x1B, 0x38, 0xE3, 0x8E,
491 0x38
492 };
493 u8 *data = NULL;
494
495 switch (clk_mode) {
496 case CXD2880_TNRDMD_CLOCKMODE_A:
497 case CXD2880_TNRDMD_CLOCKMODE_C:
498 data = data_ac;
499 break;
500 case CXD2880_TNRDMD_CLOCKMODE_B:
501 data = data_b;
502 break;
503 default:
504 return CXD2880_RESULT_ERROR_SW_STATE;
505 }
506
507 if (tnr_dmd->io->write_regs(tnr_dmd->io,
508 CXD2880_IO_TGT_DMD, 0x60,
509 data,
510 5) != CXD2880_RESULT_OK)
511 return CXD2880_RESULT_ERROR_IO;
512 }
513
514 if (tnr_dmd->io->write_reg(tnr_dmd->io,
515 CXD2880_IO_TGT_DMD, 0x4A,
516 0x04) != CXD2880_RESULT_OK)
517 return CXD2880_RESULT_ERROR_IO;
518
519 {
520 u8 data_a[2] = { 0x1F, 0xF8 };
521 u8 data_b[2] = { 0x24, 0x43 };
522 u8 data_c[2] = { 0x25, 0x4C };
523 u8 *data = NULL;
524
525 switch (clk_mode) {
526 case CXD2880_TNRDMD_CLOCKMODE_A:
527 data = data_a;
528 break;
529 case CXD2880_TNRDMD_CLOCKMODE_B:
530 data = data_b;
531 break;
532 case CXD2880_TNRDMD_CLOCKMODE_C:
533 data = data_c;
534 break;
535 default:
536 return CXD2880_RESULT_ERROR_SW_STATE;
537 }
538
539 if (tnr_dmd->io->write_regs(tnr_dmd->io,
540 CXD2880_IO_TGT_DMD, 0x7D,
541 data,
542 2) != CXD2880_RESULT_OK)
543 return CXD2880_RESULT_ERROR_IO;
544 }
545
546 {
547 u8 data = 0;
548
549 switch (clk_mode) {
550 case CXD2880_TNRDMD_CLOCKMODE_A:
551 case CXD2880_TNRDMD_CLOCKMODE_C:
552 data = 0x29;
553 break;
554 case CXD2880_TNRDMD_CLOCKMODE_B:
555 data = 0x2A;
556 break;
557 default:
558 return CXD2880_RESULT_ERROR_SW_STATE;
559 }
560
561 if (tnr_dmd->io->write_reg(tnr_dmd->io,
562 CXD2880_IO_TGT_DMD, 0x71,
563 data) != CXD2880_RESULT_OK)
564 return CXD2880_RESULT_ERROR_IO;
565 }
566
567 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
568 u8 data_a[5] = { 0x40, 0x00, 0x00, 0xC0,
569 0x00
570 };
571 u8 data_b[5] = { 0x48, 0x97, 0x00, 0xD9,
572 0xC7
573 };
574 u8 data_c[5] = { 0x4A, 0xAA, 0x00, 0xDF,
575 0xFF
576 };
577 u8 *data = NULL;
578
579 switch (clk_mode) {
580 case CXD2880_TNRDMD_CLOCKMODE_A:
581 data = data_a;
582 break;
583 case CXD2880_TNRDMD_CLOCKMODE_B:
584 data = data_b;
585 break;
586 case CXD2880_TNRDMD_CLOCKMODE_C:
587 data = data_c;
588 break;
589 default:
590 return CXD2880_RESULT_ERROR_SW_STATE;
591 }
592
593 if (tnr_dmd->io->write_regs(tnr_dmd->io,
594 CXD2880_IO_TGT_DMD, 0x4B,
595 &data[0],
596 2) != CXD2880_RESULT_OK)
597 return CXD2880_RESULT_ERROR_IO;
598
599 if (tnr_dmd->io->write_regs(tnr_dmd->io,
600 CXD2880_IO_TGT_DMD, 0x51,
601 &data[2],
602 3) != CXD2880_RESULT_OK)
603 return CXD2880_RESULT_ERROR_IO;
604 }
605
606 {
607 u8 data[4] = { 0xBE, 0xAB, 0x00, 0x03 };
608
609 if (tnr_dmd->io->write_regs(tnr_dmd->io,
610 CXD2880_IO_TGT_DMD, 0x72,
611 &data[0],
612 2) != CXD2880_RESULT_OK)
613 return CXD2880_RESULT_ERROR_IO;
614
615 if (tnr_dmd->io->write_regs(tnr_dmd->io,
616 CXD2880_IO_TGT_DMD, 0x6B,
617 &data[2],
618 2) != CXD2880_RESULT_OK)
619 return CXD2880_RESULT_ERROR_IO;
620 }
621 break;
622
623 case CXD2880_DTV_BW_5_MHZ:
624
625 {
626 u8 data_ac[5] = { 0x21, 0x99, 0x99, 0x99,
627 0x99
628 };
629 u8 data_b[5] = { 0x20, 0xAA, 0xAA, 0xAA,
630 0xAA
631 };
632 u8 *data = NULL;
633
634 switch (clk_mode) {
635 case CXD2880_TNRDMD_CLOCKMODE_A:
636 case CXD2880_TNRDMD_CLOCKMODE_C:
637 data = data_ac;
638 break;
639 case CXD2880_TNRDMD_CLOCKMODE_B:
640 data = data_b;
641 break;
642 default:
643 return CXD2880_RESULT_ERROR_SW_STATE;
644 }
645
646 if (tnr_dmd->io->write_regs(tnr_dmd->io,
647 CXD2880_IO_TGT_DMD, 0x60,
648 data,
649 5) != CXD2880_RESULT_OK)
650 return CXD2880_RESULT_ERROR_IO;
651 }
652
653 if (tnr_dmd->io->write_reg(tnr_dmd->io,
654 CXD2880_IO_TGT_DMD, 0x4A,
655 0x06) != CXD2880_RESULT_OK)
656 return CXD2880_RESULT_ERROR_IO;
657
658 {
659 u8 data_a[2] = { 0x26, 0x5D };
660 u8 data_b[2] = { 0x2B, 0x84 };
661 u8 data_c[2] = { 0x2C, 0xC2 };
662 u8 *data = NULL;
663
664 switch (clk_mode) {
665 case CXD2880_TNRDMD_CLOCKMODE_A:
666 data = data_a;
667 break;
668 case CXD2880_TNRDMD_CLOCKMODE_B:
669 data = data_b;
670 break;
671 case CXD2880_TNRDMD_CLOCKMODE_C:
672 data = data_c;
673 break;
674 default:
675 return CXD2880_RESULT_ERROR_SW_STATE;
676 }
677
678 if (tnr_dmd->io->write_regs(tnr_dmd->io,
679 CXD2880_IO_TGT_DMD, 0x7D,
680 data,
681 2) != CXD2880_RESULT_OK)
682 return CXD2880_RESULT_ERROR_IO;
683 }
684
685 {
686 u8 data = 0;
687
688 switch (clk_mode) {
689 case CXD2880_TNRDMD_CLOCKMODE_A:
690 case CXD2880_TNRDMD_CLOCKMODE_B:
691 data = 0x24;
692 break;
693 case CXD2880_TNRDMD_CLOCKMODE_C:
694 data = 0x23;
695 break;
696 default:
697 return CXD2880_RESULT_ERROR_SW_STATE;
698 }
699
700 if (tnr_dmd->io->write_reg(tnr_dmd->io,
701 CXD2880_IO_TGT_DMD, 0x71,
702 data) != CXD2880_RESULT_OK)
703 return CXD2880_RESULT_ERROR_IO;
704 }
705
706 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
707 u8 data_a[5] = { 0x4C, 0xCC, 0x00, 0xE6,
708 0x66
709 };
710 u8 data_b[5] = { 0x57, 0x1C, 0x01, 0x05,
711 0x55
712 };
713 u8 data_c[5] = { 0x59, 0x99, 0x01, 0x0C,
714 0xCC
715 };
716 u8 *data = NULL;
717
718 switch (clk_mode) {
719 case CXD2880_TNRDMD_CLOCKMODE_A:
720 data = data_a;
721 break;
722 case CXD2880_TNRDMD_CLOCKMODE_B:
723 data = data_b;
724 break;
725 case CXD2880_TNRDMD_CLOCKMODE_C:
726 data = data_c;
727 break;
728 default:
729 return CXD2880_RESULT_ERROR_SW_STATE;
730 }
731
732 if (tnr_dmd->io->write_regs(tnr_dmd->io,
733 CXD2880_IO_TGT_DMD, 0x4B,
734 &data[0],
735 2) != CXD2880_RESULT_OK)
736 return CXD2880_RESULT_ERROR_IO;
737
738 if (tnr_dmd->io->write_regs(tnr_dmd->io,
739 CXD2880_IO_TGT_DMD, 0x51,
740 &data[2],
741 3) != CXD2880_RESULT_OK)
742 return CXD2880_RESULT_ERROR_IO;
743 }
744
745 {
746 u8 data[4] = { 0xC8, 0x01, 0x00, 0x03 };
747
748 if (tnr_dmd->io->write_regs(tnr_dmd->io,
749 CXD2880_IO_TGT_DMD, 0x72,
750 &data[0],
751 2) != CXD2880_RESULT_OK)
752 return CXD2880_RESULT_ERROR_IO;
753
754 if (tnr_dmd->io->write_regs(tnr_dmd->io,
755 CXD2880_IO_TGT_DMD, 0x6B,
756 &data[2],
757 2) != CXD2880_RESULT_OK)
758 return CXD2880_RESULT_ERROR_IO;
759 }
760 break;
761
762 default:
763 return CXD2880_RESULT_ERROR_SW_STATE;
764 }
765
766 if (tnr_dmd->io->write_reg(tnr_dmd->io,
767 CXD2880_IO_TGT_DMD, 0x00,
768 0x00) != CXD2880_RESULT_OK)
769 return CXD2880_RESULT_ERROR_IO;
770
771 if (tnr_dmd->io->write_reg(tnr_dmd->io,
772 CXD2880_IO_TGT_DMD, 0xFD,
773 0x01) != CXD2880_RESULT_OK)
774 return CXD2880_RESULT_ERROR_IO;
775
776 return CXD2880_RESULT_OK;
777 }
778
779 static enum cxd2880_ret x_sleep_dvbt_demod_setting(struct cxd2880_tnrdmd
780 *tnr_dmd)
781 {
782 if (!tnr_dmd)
783 return CXD2880_RESULT_ERROR_ARG;
784
785 if (tnr_dmd->io->write_reg(tnr_dmd->io,
786 CXD2880_IO_TGT_DMD, 0x00,
787 0x04) != CXD2880_RESULT_OK)
788 return CXD2880_RESULT_ERROR_IO;
789
790 if (tnr_dmd->io->write_reg(tnr_dmd->io,
791 CXD2880_IO_TGT_DMD, 0x5C,
792 0xD8) != CXD2880_RESULT_OK)
793 return CXD2880_RESULT_ERROR_IO;
794
795 if (tnr_dmd->io->write_reg(tnr_dmd->io,
796 CXD2880_IO_TGT_DMD, 0x00,
797 0x10) != CXD2880_RESULT_OK)
798 return CXD2880_RESULT_ERROR_IO;
799
800 if (tnr_dmd->io->write_reg(tnr_dmd->io,
801 CXD2880_IO_TGT_DMD, 0xA4,
802 0x00) != CXD2880_RESULT_OK)
803 return CXD2880_RESULT_ERROR_IO;
804
805 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
806 if (tnr_dmd->io->write_reg(tnr_dmd->io,
807 CXD2880_IO_TGT_DMD, 0x00,
808 0x11) != CXD2880_RESULT_OK)
809 return CXD2880_RESULT_ERROR_IO;
810
811 if (tnr_dmd->io->write_reg(tnr_dmd->io,
812 CXD2880_IO_TGT_DMD, 0x87,
813 0x04) != CXD2880_RESULT_OK)
814 return CXD2880_RESULT_ERROR_IO;
815 }
816
817 return CXD2880_RESULT_OK;
818 }
819
820 static enum cxd2880_ret dvbt_set_profile(struct cxd2880_tnrdmd *tnr_dmd,
821 enum cxd2880_dvbt_profile profile)
822 {
823 enum cxd2880_ret ret = CXD2880_RESULT_OK;
824
825 if (!tnr_dmd)
826 return CXD2880_RESULT_ERROR_ARG;
827
828 if (tnr_dmd->io->write_reg(tnr_dmd->io,
829 CXD2880_IO_TGT_DMD, 0x00,
830 0x10) != CXD2880_RESULT_OK)
831 return CXD2880_RESULT_ERROR_IO;
832
833 if (tnr_dmd->io->write_reg(tnr_dmd->io,
834 CXD2880_IO_TGT_DMD, 0x67,
835 (profile ==
836 CXD2880_DVBT_PROFILE_HP) ? 0x00 : 0x01) !=
837 CXD2880_RESULT_OK)
838 return CXD2880_RESULT_ERROR_IO;
839
840 return ret;
841 }
842
843 enum cxd2880_ret cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd,
844 struct cxd2880_dvbt_tune_param
845 *tune_param)
846 {
847 enum cxd2880_ret ret = CXD2880_RESULT_OK;
848
849 if ((!tnr_dmd) || (!tune_param))
850 return CXD2880_RESULT_ERROR_ARG;
851
852 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
853 return CXD2880_RESULT_ERROR_ARG;
854
855 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
856 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
857 return CXD2880_RESULT_ERROR_SW_STATE;
858
859 ret =
860 cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT,
861 tune_param->center_freq_khz,
862 tune_param->bandwidth, 0, 0);
863 if (ret != CXD2880_RESULT_OK)
864 return ret;
865
866 ret =
867 x_tune_dvbt_demod_setting(tnr_dmd, tune_param->bandwidth,
868 tnr_dmd->clk_mode);
869 if (ret != CXD2880_RESULT_OK)
870 return ret;
871
872 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
873 ret =
874 x_tune_dvbt_demod_setting(tnr_dmd->diver_sub,
875 tune_param->bandwidth,
876 tnr_dmd->diver_sub->clk_mode);
877 if (ret != CXD2880_RESULT_OK)
878 return ret;
879 }
880
881 ret = dvbt_set_profile(tnr_dmd, tune_param->profile);
882 if (ret != CXD2880_RESULT_OK)
883 return ret;
884
885 return CXD2880_RESULT_OK;
886 }
887
888 enum cxd2880_ret cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd,
889 struct cxd2880_dvbt_tune_param
890 *tune_param)
891 {
892 enum cxd2880_ret ret = CXD2880_RESULT_OK;
893
894 if ((!tnr_dmd) || (!tune_param))
895 return CXD2880_RESULT_ERROR_ARG;
896
897 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
898 return CXD2880_RESULT_ERROR_ARG;
899
900 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
901 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
902 return CXD2880_RESULT_ERROR_SW_STATE;
903
904 ret =
905 cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, CXD2880_DTV_SYS_DVBT,
906 0);
907 if (ret != CXD2880_RESULT_OK)
908 return ret;
909
910 tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;
911 tnr_dmd->frequency_khz = tune_param->center_freq_khz;
912 tnr_dmd->sys = CXD2880_DTV_SYS_DVBT;
913 tnr_dmd->bandwidth = tune_param->bandwidth;
914
915 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
916 tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;
917 tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;
918 tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT;
919 tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;
920 }
921
922 return CXD2880_RESULT_OK;
923 }
924
925 enum cxd2880_ret cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd
926 *tnr_dmd)
927 {
928 enum cxd2880_ret ret = CXD2880_RESULT_OK;
929
930 if (!tnr_dmd)
931 return CXD2880_RESULT_ERROR_ARG;
932
933 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
934 return CXD2880_RESULT_ERROR_ARG;
935
936 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
937 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
938 return CXD2880_RESULT_ERROR_SW_STATE;
939
940 ret = x_sleep_dvbt_demod_setting(tnr_dmd);
941 if (ret != CXD2880_RESULT_OK)
942 return ret;
943
944 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
945 ret = x_sleep_dvbt_demod_setting(tnr_dmd->diver_sub);
946 if (ret != CXD2880_RESULT_OK)
947 return ret;
948 }
949
950 return CXD2880_RESULT_OK;
951 }
952
953 enum cxd2880_ret cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
954 *tnr_dmd,
955 enum
956 cxd2880_tnrdmd_lock_result
957 *lock)
958 {
959 enum cxd2880_ret ret = CXD2880_RESULT_OK;
960
961 u8 sync_stat = 0;
962 u8 ts_lock = 0;
963 u8 unlock_detected = 0;
964 u8 unlock_detected_sub = 0;
965
966 if ((!tnr_dmd) || (!lock))
967 return CXD2880_RESULT_ERROR_ARG;
968
969 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
970 return CXD2880_RESULT_ERROR_ARG;
971
972 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
973 return CXD2880_RESULT_ERROR_SW_STATE;
974
975 ret =
976 cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
977 &unlock_detected);
978 if (ret != CXD2880_RESULT_OK)
979 return ret;
980
981 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
982 if (sync_stat == 6)
983 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
984 else if (unlock_detected)
985 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
986 else
987 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
988
989 return ret;
990 }
991
992 if (sync_stat == 6) {
993 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
994 return ret;
995 }
996
997 ret =
998 cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
999 &unlock_detected_sub);
1000 if (ret != CXD2880_RESULT_OK)
1001 return ret;
1002
1003 if (sync_stat == 6)
1004 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1005 else if (unlock_detected && unlock_detected_sub)
1006 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1007 else
1008 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1009
1010 return ret;
1011 }
1012
1013 enum cxd2880_ret cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
1014 *tnr_dmd,
1015 enum
1016 cxd2880_tnrdmd_lock_result
1017 *lock)
1018 {
1019 enum cxd2880_ret ret = CXD2880_RESULT_OK;
1020
1021 u8 sync_stat = 0;
1022 u8 ts_lock = 0;
1023 u8 unlock_detected = 0;
1024 u8 unlock_detected_sub = 0;
1025
1026 if ((!tnr_dmd) || (!lock))
1027 return CXD2880_RESULT_ERROR_ARG;
1028
1029 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1030 return CXD2880_RESULT_ERROR_ARG;
1031
1032 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1033 return CXD2880_RESULT_ERROR_SW_STATE;
1034
1035 ret =
1036 cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
1037 &unlock_detected);
1038 if (ret != CXD2880_RESULT_OK)
1039 return ret;
1040
1041 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
1042 if (ts_lock)
1043 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1044 else if (unlock_detected)
1045 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1046 else
1047 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1048
1049 return ret;
1050 }
1051
1052 if (ts_lock) {
1053 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1054 return ret;
1055 } else if (!unlock_detected) {
1056 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1057 return ret;
1058 }
1059
1060 ret =
1061 cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
1062 &unlock_detected_sub);
1063 if (ret != CXD2880_RESULT_OK)
1064 return ret;
1065
1066 if (unlock_detected && unlock_detected_sub)
1067 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1068 else
1069 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1070
1071 return ret;
1072 }