]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.c
This is the driver for Sony CXD2880 DVB-T2/T tuner + demodulator. It includes the...
[mirror_ubuntu-artful-kernel.git] / drivers / media / dvb-frontends / cxd2880 / cxd2880_tnrdmd_dvbt2.c
1 /*
2 * cxd2880_tnrdmd_dvbt2.c
3 * Sony CXD2880 DVB-T2/T tuner + demodulator driver
4 * control functions for DVB-T2
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_dvbt2.h"
28 #include "cxd2880_tnrdmd_dvbt2_mon.h"
29
30 static enum cxd2880_ret x_tune_dvbt2_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 0x02) != CXD2880_RESULT_OK)
48 return CXD2880_RESULT_ERROR_IO;
49
50 if (tnr_dmd->io->write_reg(tnr_dmd->io,
51 CXD2880_IO_TGT_DMD, 0x00,
52 0x04) != CXD2880_RESULT_OK)
53 return CXD2880_RESULT_ERROR_IO;
54
55 if (tnr_dmd->io->write_reg(tnr_dmd->io,
56 CXD2880_IO_TGT_DMD, 0x5D,
57 0x0B) != CXD2880_RESULT_OK)
58 return CXD2880_RESULT_ERROR_IO;
59
60 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
61 u8 data[2] = { 0x01, 0x01 };
62
63 if (tnr_dmd->io->write_reg(tnr_dmd->io,
64 CXD2880_IO_TGT_DMD, 0x00,
65 0x00) != CXD2880_RESULT_OK)
66 return CXD2880_RESULT_ERROR_IO;
67
68 if (tnr_dmd->io->write_regs(tnr_dmd->io,
69 CXD2880_IO_TGT_DMD, 0xCE, data,
70 2) != CXD2880_RESULT_OK)
71 return CXD2880_RESULT_ERROR_IO;
72 }
73
74 {
75 u8 data[14] = { 0x07, 0x06, 0x01, 0xF0,
76 0x00, 0x00, 0x04, 0xB0, 0x00, 0x00, 0x09, 0x9C, 0x0E,
77 0x4C
78 };
79
80 if (tnr_dmd->io->write_reg(tnr_dmd->io,
81 CXD2880_IO_TGT_DMD, 0x00,
82 0x20) != CXD2880_RESULT_OK)
83 return CXD2880_RESULT_ERROR_IO;
84
85 if (tnr_dmd->io->write_reg(tnr_dmd->io,
86 CXD2880_IO_TGT_DMD, 0x8A,
87 data[0]) != CXD2880_RESULT_OK)
88 return CXD2880_RESULT_ERROR_IO;
89
90 if (tnr_dmd->io->write_reg(tnr_dmd->io,
91 CXD2880_IO_TGT_DMD, 0x90,
92 data[1]) != CXD2880_RESULT_OK)
93 return CXD2880_RESULT_ERROR_IO;
94
95 if (tnr_dmd->io->write_reg(tnr_dmd->io,
96 CXD2880_IO_TGT_DMD, 0x00,
97 0x25) != CXD2880_RESULT_OK)
98 return CXD2880_RESULT_ERROR_IO;
99
100 if (tnr_dmd->io->write_regs(tnr_dmd->io,
101 CXD2880_IO_TGT_DMD, 0xF0, &data[2],
102 2) != 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, 0x00,
107 0x2A) != 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, 0xDC,
112 data[4]) != 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, 0xDE,
117 data[5]) != 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 0x2D) != CXD2880_RESULT_OK)
123 return CXD2880_RESULT_ERROR_IO;
124
125 if (tnr_dmd->io->write_regs(tnr_dmd->io,
126 CXD2880_IO_TGT_DMD, 0x73, &data[6],
127 4) != CXD2880_RESULT_OK)
128 return CXD2880_RESULT_ERROR_IO;
129
130 if (tnr_dmd->io->write_regs(tnr_dmd->io,
131 CXD2880_IO_TGT_DMD, 0x8F, &data[10],
132 4) != CXD2880_RESULT_OK)
133 return CXD2880_RESULT_ERROR_IO;
134 }
135
136 {
137 u8 data_a_1[9] = { 0x52, 0x49, 0x2C, 0x51,
138 0x51, 0x3D, 0x15, 0x29, 0x0C
139 };
140 u8 data_b_1[9] = { 0x5D, 0x55, 0x32, 0x5C,
141 0x5C, 0x45, 0x17, 0x2E, 0x0D
142 };
143 u8 data_c_1[9] = { 0x60, 0x00, 0x34, 0x5E,
144 0x5E, 0x47, 0x18, 0x2F, 0x0E
145 };
146
147 u8 data_a_2[13] = { 0x04, 0xE7, 0x94, 0x92,
148 0x09, 0xCF, 0x7E, 0xD0, 0x49, 0xCD, 0xCD, 0x1F, 0x5B
149 };
150 u8 data_b_2[13] = { 0x05, 0x90, 0x27, 0x55,
151 0x0B, 0x20, 0x8F, 0xD6, 0xEA, 0xC8, 0xC8, 0x23, 0x91
152 };
153 u8 data_c_2[13] = { 0x05, 0xB8, 0xD8, 0x00,
154 0x0B, 0x72, 0x93, 0xF3, 0x00, 0xCD, 0xCD, 0x24, 0x95
155 };
156
157 u8 data_a_3[5] = { 0x0B, 0x6A, 0xC9, 0x03,
158 0x33
159 };
160 u8 data_b_3[5] = { 0x01, 0x02, 0xE4, 0x03,
161 0x39
162 };
163 u8 data_c_3[5] = { 0x01, 0x02, 0xEB, 0x03,
164 0x3B
165 };
166
167 u8 *data_1 = NULL;
168 u8 *data_2 = NULL;
169 u8 *data_3 = NULL;
170
171 switch (clk_mode) {
172 case CXD2880_TNRDMD_CLOCKMODE_A:
173 data_1 = data_a_1;
174 data_2 = data_a_2;
175 data_3 = data_a_3;
176 break;
177 case CXD2880_TNRDMD_CLOCKMODE_B:
178 data_1 = data_b_1;
179 data_2 = data_b_2;
180 data_3 = data_b_3;
181 break;
182 case CXD2880_TNRDMD_CLOCKMODE_C:
183 data_1 = data_c_1;
184 data_2 = data_c_2;
185 data_3 = data_c_3;
186 break;
187 default:
188 return CXD2880_RESULT_ERROR_SW_STATE;
189 }
190
191 if (tnr_dmd->io->write_reg(tnr_dmd->io,
192 CXD2880_IO_TGT_DMD, 0x00,
193 0x04) != CXD2880_RESULT_OK)
194 return CXD2880_RESULT_ERROR_IO;
195
196 if (tnr_dmd->io->write_regs(tnr_dmd->io,
197 CXD2880_IO_TGT_DMD, 0x1D,
198 &data_1[0], 3) != CXD2880_RESULT_OK)
199 return CXD2880_RESULT_ERROR_IO;
200
201 if (tnr_dmd->io->write_reg(tnr_dmd->io,
202 CXD2880_IO_TGT_DMD, 0x22,
203 data_1[3]) != CXD2880_RESULT_OK)
204 return CXD2880_RESULT_ERROR_IO;
205
206 if (tnr_dmd->io->write_reg(tnr_dmd->io,
207 CXD2880_IO_TGT_DMD, 0x24,
208 data_1[4]) != CXD2880_RESULT_OK)
209 return CXD2880_RESULT_ERROR_IO;
210
211 if (tnr_dmd->io->write_reg(tnr_dmd->io,
212 CXD2880_IO_TGT_DMD, 0x26,
213 data_1[5]) != CXD2880_RESULT_OK)
214 return CXD2880_RESULT_ERROR_IO;
215
216 if (tnr_dmd->io->write_regs(tnr_dmd->io,
217 CXD2880_IO_TGT_DMD, 0x29,
218 &data_1[6], 2) != CXD2880_RESULT_OK)
219 return CXD2880_RESULT_ERROR_IO;
220
221 if (tnr_dmd->io->write_reg(tnr_dmd->io,
222 CXD2880_IO_TGT_DMD, 0x2D,
223 data_1[8]) != CXD2880_RESULT_OK)
224 return CXD2880_RESULT_ERROR_IO;
225
226 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
227 if (tnr_dmd->io->write_regs(tnr_dmd->io,
228 CXD2880_IO_TGT_DMD, 0x2E,
229 &data_2[0],
230 6) != CXD2880_RESULT_OK)
231 return CXD2880_RESULT_ERROR_IO;
232
233 if (tnr_dmd->io->write_regs(tnr_dmd->io,
234 CXD2880_IO_TGT_DMD, 0x35,
235 &data_2[6],
236 7) != CXD2880_RESULT_OK)
237 return CXD2880_RESULT_ERROR_IO;
238 }
239
240 if (tnr_dmd->io->write_regs(tnr_dmd->io,
241 CXD2880_IO_TGT_DMD, 0x3C,
242 &data_3[0], 2) != CXD2880_RESULT_OK)
243 return CXD2880_RESULT_ERROR_IO;
244
245 if (tnr_dmd->io->write_regs(tnr_dmd->io,
246 CXD2880_IO_TGT_DMD, 0x56,
247 &data_3[2], 3) != CXD2880_RESULT_OK)
248 return CXD2880_RESULT_ERROR_IO;
249 }
250
251 switch (bandwidth) {
252 case CXD2880_DTV_BW_8_MHZ:
253
254 {
255 u8 data_ac[6] = { 0x15, 0x00, 0x00, 0x00,
256 0x00, 0x00
257 };
258 u8 data_b[6] = { 0x14, 0x6A, 0xAA, 0xAA,
259 0xAB, 0x00
260 };
261 u8 *data = NULL;
262
263 switch (clk_mode) {
264 case CXD2880_TNRDMD_CLOCKMODE_A:
265 case CXD2880_TNRDMD_CLOCKMODE_C:
266 data = data_ac;
267 break;
268 case CXD2880_TNRDMD_CLOCKMODE_B:
269 data = data_b;
270 break;
271 default:
272 return CXD2880_RESULT_ERROR_SW_STATE;
273 }
274
275 if (tnr_dmd->io->write_regs(tnr_dmd->io,
276 CXD2880_IO_TGT_DMD, 0x10,
277 data,
278 6) != CXD2880_RESULT_OK)
279 return CXD2880_RESULT_ERROR_IO;
280 }
281
282 if (tnr_dmd->io->write_reg(tnr_dmd->io,
283 CXD2880_IO_TGT_DMD, 0x4A,
284 0x00) != CXD2880_RESULT_OK)
285 return CXD2880_RESULT_ERROR_IO;
286
287 {
288 u8 data_a[2] = { 0x19, 0xD2 };
289 u8 data_bc[2] = { 0x3F, 0xFF };
290 u8 *data = NULL;
291
292 switch (clk_mode) {
293 case CXD2880_TNRDMD_CLOCKMODE_A:
294 data = data_a;
295 break;
296 case CXD2880_TNRDMD_CLOCKMODE_B:
297 case CXD2880_TNRDMD_CLOCKMODE_C:
298 data = data_bc;
299 break;
300 default:
301 return CXD2880_RESULT_ERROR_SW_STATE;
302 }
303
304 if (tnr_dmd->io->write_regs(tnr_dmd->io,
305 CXD2880_IO_TGT_DMD, 0x19,
306 data,
307 2) != CXD2880_RESULT_OK)
308 return CXD2880_RESULT_ERROR_IO;
309 }
310
311 {
312 u8 data_a[2] = { 0x06, 0x2A };
313 u8 data_b[2] = { 0x06, 0x29 };
314 u8 data_c[2] = { 0x06, 0x28 };
315 u8 *data = NULL;
316
317 switch (clk_mode) {
318 case CXD2880_TNRDMD_CLOCKMODE_A:
319 data = data_a;
320 break;
321 case CXD2880_TNRDMD_CLOCKMODE_B:
322 data = data_b;
323 break;
324 case CXD2880_TNRDMD_CLOCKMODE_C:
325 data = data_c;
326 break;
327 default:
328 return CXD2880_RESULT_ERROR_SW_STATE;
329 }
330
331 if (tnr_dmd->io->write_regs(tnr_dmd->io,
332 CXD2880_IO_TGT_DMD, 0x1B,
333 data,
334 2) != CXD2880_RESULT_OK)
335 return CXD2880_RESULT_ERROR_IO;
336 }
337
338 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
339 u8 data_a[9] = { 0x28, 0x00, 0x50, 0x00,
340 0x60, 0x00, 0x00, 0x90, 0x00
341 };
342 u8 data_b[9] = { 0x2D, 0x5E, 0x5A, 0xBD,
343 0x6C, 0xE3, 0x00, 0xA3, 0x55
344 };
345 u8 data_c[9] = { 0x2E, 0xAA, 0x5D, 0x55,
346 0x70, 0x00, 0x00, 0xA8, 0x00
347 };
348 u8 *data = NULL;
349
350 switch (clk_mode) {
351 case CXD2880_TNRDMD_CLOCKMODE_A:
352 data = data_a;
353 break;
354 case CXD2880_TNRDMD_CLOCKMODE_B:
355 data = data_b;
356 break;
357 case CXD2880_TNRDMD_CLOCKMODE_C:
358 data = data_c;
359 break;
360 default:
361 return CXD2880_RESULT_ERROR_SW_STATE;
362 }
363
364 if (tnr_dmd->io->write_regs(tnr_dmd->io,
365 CXD2880_IO_TGT_DMD, 0x4B,
366 data,
367 9) != CXD2880_RESULT_OK)
368 return CXD2880_RESULT_ERROR_IO;
369 }
370 break;
371
372 case CXD2880_DTV_BW_7_MHZ:
373
374 {
375 u8 data_ac[6] = { 0x18, 0x00, 0x00, 0x00,
376 0x00, 0x00
377 };
378 u8 data_b[6] = { 0x17, 0x55, 0x55, 0x55,
379 0x55, 0x00
380 };
381 u8 *data = NULL;
382
383 switch (clk_mode) {
384 case CXD2880_TNRDMD_CLOCKMODE_A:
385 case CXD2880_TNRDMD_CLOCKMODE_C:
386 data = data_ac;
387 break;
388 case CXD2880_TNRDMD_CLOCKMODE_B:
389 data = data_b;
390 break;
391 default:
392 return CXD2880_RESULT_ERROR_SW_STATE;
393 }
394
395 if (tnr_dmd->io->write_regs(tnr_dmd->io,
396 CXD2880_IO_TGT_DMD, 0x10,
397 data,
398 6) != CXD2880_RESULT_OK)
399 return CXD2880_RESULT_ERROR_IO;
400 }
401
402 if (tnr_dmd->io->write_reg(tnr_dmd->io,
403 CXD2880_IO_TGT_DMD, 0x4A,
404 0x02) != CXD2880_RESULT_OK)
405 return CXD2880_RESULT_ERROR_IO;
406
407 {
408 u8 data[2] = { 0x3F, 0xFF };
409
410 if (tnr_dmd->io->write_regs(tnr_dmd->io,
411 CXD2880_IO_TGT_DMD, 0x19,
412 data,
413 2) != CXD2880_RESULT_OK)
414 return CXD2880_RESULT_ERROR_IO;
415 }
416
417 {
418 u8 data_a[2] = { 0x06, 0x23 };
419 u8 data_b[2] = { 0x06, 0x22 };
420 u8 data_c[2] = { 0x06, 0x21 };
421 u8 *data = NULL;
422
423 switch (clk_mode) {
424 case CXD2880_TNRDMD_CLOCKMODE_A:
425 data = data_a;
426 break;
427 case CXD2880_TNRDMD_CLOCKMODE_B:
428 data = data_b;
429 break;
430 case CXD2880_TNRDMD_CLOCKMODE_C:
431 data = data_c;
432 break;
433 default:
434 return CXD2880_RESULT_ERROR_SW_STATE;
435 }
436
437 if (tnr_dmd->io->write_regs(tnr_dmd->io,
438 CXD2880_IO_TGT_DMD, 0x1B,
439 data,
440 2) != CXD2880_RESULT_OK)
441 return CXD2880_RESULT_ERROR_IO;
442 }
443
444 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
445 u8 data_a[9] = { 0x2D, 0xB6, 0x5B, 0x6D,
446 0x6D, 0xB6, 0x00, 0xA4, 0x92
447 };
448 u8 data_b[9] = { 0x33, 0xDA, 0x67, 0xB4,
449 0x7C, 0x71, 0x00, 0xBA, 0xAA
450 };
451 u8 data_c[9] = { 0x35, 0x55, 0x6A, 0xAA,
452 0x80, 0x00, 0x00, 0xC0, 0x00
453 };
454 u8 *data = NULL;
455
456 switch (clk_mode) {
457 case CXD2880_TNRDMD_CLOCKMODE_A:
458 data = data_a;
459 break;
460 case CXD2880_TNRDMD_CLOCKMODE_B:
461 data = data_b;
462 break;
463 case CXD2880_TNRDMD_CLOCKMODE_C:
464 data = data_c;
465 break;
466 default:
467 return CXD2880_RESULT_ERROR_SW_STATE;
468 }
469
470 if (tnr_dmd->io->write_regs(tnr_dmd->io,
471 CXD2880_IO_TGT_DMD, 0x4B,
472 data,
473 9) != CXD2880_RESULT_OK)
474 return CXD2880_RESULT_ERROR_IO;
475 }
476 break;
477
478 case CXD2880_DTV_BW_6_MHZ:
479
480 {
481 u8 data_ac[6] = { 0x1C, 0x00, 0x00, 0x00,
482 0x00, 0x00
483 };
484 u8 data_b[6] = { 0x1B, 0x38, 0xE3, 0x8E,
485 0x39, 0x00
486 };
487 u8 *data = NULL;
488
489 switch (clk_mode) {
490 case CXD2880_TNRDMD_CLOCKMODE_A:
491 case CXD2880_TNRDMD_CLOCKMODE_C:
492 data = data_ac;
493 break;
494 case CXD2880_TNRDMD_CLOCKMODE_B:
495 data = data_b;
496 break;
497 default:
498 return CXD2880_RESULT_ERROR_SW_STATE;
499 }
500
501 if (tnr_dmd->io->write_regs(tnr_dmd->io,
502 CXD2880_IO_TGT_DMD, 0x10,
503 data,
504 6) != CXD2880_RESULT_OK)
505 return CXD2880_RESULT_ERROR_IO;
506 }
507
508 if (tnr_dmd->io->write_reg(tnr_dmd->io,
509 CXD2880_IO_TGT_DMD, 0x4A,
510 0x04) != CXD2880_RESULT_OK)
511 return CXD2880_RESULT_ERROR_IO;
512
513 {
514 u8 data[2] = { 0x3F, 0xFF };
515
516 if (tnr_dmd->io->write_regs(tnr_dmd->io,
517 CXD2880_IO_TGT_DMD, 0x19,
518 data,
519 2) != CXD2880_RESULT_OK)
520 return CXD2880_RESULT_ERROR_IO;
521 }
522
523 {
524 u8 data_a[2] = { 0x06, 0x1C };
525 u8 data_b[2] = { 0x06, 0x1B };
526 u8 data_c[2] = { 0x06, 0x1A };
527 u8 *data = NULL;
528
529 switch (clk_mode) {
530 case CXD2880_TNRDMD_CLOCKMODE_A:
531 data = data_a;
532 break;
533 case CXD2880_TNRDMD_CLOCKMODE_B:
534 data = data_b;
535 break;
536 case CXD2880_TNRDMD_CLOCKMODE_C:
537 data = data_c;
538 break;
539 default:
540 return CXD2880_RESULT_ERROR_SW_STATE;
541 }
542
543 if (tnr_dmd->io->write_regs(tnr_dmd->io,
544 CXD2880_IO_TGT_DMD, 0x1B,
545 data,
546 2) != CXD2880_RESULT_OK)
547 return CXD2880_RESULT_ERROR_IO;
548 }
549
550 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
551 u8 data_a[9] = { 0x35, 0x55, 0x6A, 0xAA,
552 0x80, 0x00, 0x00, 0xC0, 0x00
553 };
554 u8 data_b[9] = { 0x3C, 0x7E, 0x78, 0xFC,
555 0x91, 0x2F, 0x00, 0xD9, 0xC7
556 };
557 u8 data_c[9] = { 0x3E, 0x38, 0x7C, 0x71,
558 0x95, 0x55, 0x00, 0xDF, 0xFF
559 };
560 u8 *data = NULL;
561
562 switch (clk_mode) {
563 case CXD2880_TNRDMD_CLOCKMODE_A:
564 data = data_a;
565 break;
566 case CXD2880_TNRDMD_CLOCKMODE_B:
567 data = data_b;
568 break;
569 case CXD2880_TNRDMD_CLOCKMODE_C:
570 data = data_c;
571 break;
572 default:
573 return CXD2880_RESULT_ERROR_SW_STATE;
574 }
575
576 if (tnr_dmd->io->write_regs(tnr_dmd->io,
577 CXD2880_IO_TGT_DMD, 0x4B,
578 data,
579 9) != CXD2880_RESULT_OK)
580 return CXD2880_RESULT_ERROR_IO;
581 }
582 break;
583
584 case CXD2880_DTV_BW_5_MHZ:
585
586 {
587 u8 data_ac[6] = { 0x21, 0x99, 0x99, 0x99,
588 0x9A, 0x00
589 };
590 u8 data_b[6] = { 0x20, 0xAA, 0xAA, 0xAA,
591 0xAB, 0x00
592 };
593 u8 *data = NULL;
594
595 switch (clk_mode) {
596 case CXD2880_TNRDMD_CLOCKMODE_A:
597 case CXD2880_TNRDMD_CLOCKMODE_C:
598 data = data_ac;
599 break;
600 case CXD2880_TNRDMD_CLOCKMODE_B:
601 data = data_b;
602 break;
603 default:
604 return CXD2880_RESULT_ERROR_SW_STATE;
605 }
606
607 if (tnr_dmd->io->write_regs(tnr_dmd->io,
608 CXD2880_IO_TGT_DMD, 0x10,
609 data,
610 6) != CXD2880_RESULT_OK)
611 return CXD2880_RESULT_ERROR_IO;
612 }
613
614 if (tnr_dmd->io->write_reg(tnr_dmd->io,
615 CXD2880_IO_TGT_DMD, 0x4A,
616 0x06) != CXD2880_RESULT_OK)
617 return CXD2880_RESULT_ERROR_IO;
618
619 {
620 u8 data[2] = { 0x3F, 0xFF };
621
622 if (tnr_dmd->io->write_regs(tnr_dmd->io,
623 CXD2880_IO_TGT_DMD, 0x19,
624 data,
625 2) != CXD2880_RESULT_OK)
626 return CXD2880_RESULT_ERROR_IO;
627 }
628
629 {
630 u8 data_a[2] = { 0x06, 0x15 };
631 u8 data_b[2] = { 0x06, 0x15 };
632 u8 data_c[2] = { 0x06, 0x14 };
633 u8 *data = NULL;
634
635 switch (clk_mode) {
636 case CXD2880_TNRDMD_CLOCKMODE_A:
637 data = data_a;
638 break;
639 case CXD2880_TNRDMD_CLOCKMODE_B:
640 data = data_b;
641 break;
642 case CXD2880_TNRDMD_CLOCKMODE_C:
643 data = data_c;
644 break;
645 default:
646 return CXD2880_RESULT_ERROR_SW_STATE;
647 }
648
649 if (tnr_dmd->io->write_regs(tnr_dmd->io,
650 CXD2880_IO_TGT_DMD, 0x1B,
651 data,
652 2) != CXD2880_RESULT_OK)
653 return CXD2880_RESULT_ERROR_IO;
654 }
655
656 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
657 u8 data_a[9] = { 0x40, 0x00, 0x6A, 0xAA,
658 0x80, 0x00, 0x00, 0xE6, 0x66
659 };
660 u8 data_b[9] = { 0x48, 0x97, 0x78, 0xFC,
661 0x91, 0x2F, 0x01, 0x05, 0x55
662 };
663 u8 data_c[9] = { 0x4A, 0xAA, 0x7C, 0x71,
664 0x95, 0x55, 0x01, 0x0C, 0xCC
665 };
666 u8 *data = NULL;
667
668 switch (clk_mode) {
669 case CXD2880_TNRDMD_CLOCKMODE_A:
670 data = data_a;
671 break;
672 case CXD2880_TNRDMD_CLOCKMODE_B:
673 data = data_b;
674 break;
675 case CXD2880_TNRDMD_CLOCKMODE_C:
676 data = data_c;
677 break;
678 default:
679 return CXD2880_RESULT_ERROR_SW_STATE;
680 }
681
682 if (tnr_dmd->io->write_regs(tnr_dmd->io,
683 CXD2880_IO_TGT_DMD, 0x4B,
684 data,
685 9) != CXD2880_RESULT_OK)
686 return CXD2880_RESULT_ERROR_IO;
687 }
688 break;
689
690 case CXD2880_DTV_BW_1_7_MHZ:
691
692 {
693 u8 data_a[6] = { 0x68, 0x0F, 0xA2, 0x32,
694 0xCF, 0x03
695 };
696 u8 data_c[6] = { 0x68, 0x0F, 0xA2, 0x32,
697 0xCF, 0x03
698 };
699 u8 data_b[6] = { 0x65, 0x2B, 0xA4, 0xCD,
700 0xD8, 0x03
701 };
702 u8 *data = NULL;
703
704 switch (clk_mode) {
705 case CXD2880_TNRDMD_CLOCKMODE_A:
706 data = data_a;
707 break;
708 case CXD2880_TNRDMD_CLOCKMODE_C:
709 data = data_c;
710 break;
711 case CXD2880_TNRDMD_CLOCKMODE_B:
712 data = data_b;
713 break;
714 default:
715 return CXD2880_RESULT_ERROR_SW_STATE;
716 }
717
718 if (tnr_dmd->io->write_regs(tnr_dmd->io,
719 CXD2880_IO_TGT_DMD, 0x10,
720 data,
721 6) != CXD2880_RESULT_OK)
722 return CXD2880_RESULT_ERROR_IO;
723 }
724
725 if (tnr_dmd->io->write_reg(tnr_dmd->io,
726 CXD2880_IO_TGT_DMD, 0x4A,
727 0x03) != CXD2880_RESULT_OK)
728 return CXD2880_RESULT_ERROR_IO;
729
730 {
731 u8 data[2] = { 0x3F, 0xFF };
732
733 if (tnr_dmd->io->write_regs(tnr_dmd->io,
734 CXD2880_IO_TGT_DMD, 0x19,
735 data,
736 2) != CXD2880_RESULT_OK)
737 return CXD2880_RESULT_ERROR_IO;
738 }
739
740 {
741 u8 data_a[2] = { 0x06, 0x0C };
742 u8 data_b[2] = { 0x06, 0x0C };
743 u8 data_c[2] = { 0x06, 0x0B };
744 u8 *data = NULL;
745
746 switch (clk_mode) {
747 case CXD2880_TNRDMD_CLOCKMODE_A:
748 data = data_a;
749 break;
750 case CXD2880_TNRDMD_CLOCKMODE_B:
751 data = data_b;
752 break;
753 case CXD2880_TNRDMD_CLOCKMODE_C:
754 data = data_c;
755 break;
756 default:
757 return CXD2880_RESULT_ERROR_SW_STATE;
758 }
759
760 if (tnr_dmd->io->write_regs(tnr_dmd->io,
761 CXD2880_IO_TGT_DMD, 0x1B,
762 data,
763 2) != CXD2880_RESULT_OK)
764 return CXD2880_RESULT_ERROR_IO;
765 }
766
767 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
768 u8 data_a[9] = { 0x40, 0x00, 0x6A, 0xAA,
769 0x80, 0x00, 0x02, 0xC9, 0x8F
770 };
771 u8 data_b[9] = { 0x48, 0x97, 0x78, 0xFC,
772 0x91, 0x2F, 0x03, 0x29, 0x5D
773 };
774 u8 data_c[9] = { 0x4A, 0xAA, 0x7C, 0x71,
775 0x95, 0x55, 0x03, 0x40, 0x7D
776 };
777 u8 *data = NULL;
778
779 switch (clk_mode) {
780 case CXD2880_TNRDMD_CLOCKMODE_A:
781 data = data_a;
782 break;
783 case CXD2880_TNRDMD_CLOCKMODE_B:
784 data = data_b;
785 break;
786 case CXD2880_TNRDMD_CLOCKMODE_C:
787 data = data_c;
788 break;
789 default:
790 return CXD2880_RESULT_ERROR_SW_STATE;
791 }
792
793 if (tnr_dmd->io->write_regs(tnr_dmd->io,
794 CXD2880_IO_TGT_DMD, 0x4B,
795 data,
796 9) != CXD2880_RESULT_OK)
797 return CXD2880_RESULT_ERROR_IO;
798 }
799 break;
800
801 default:
802 return CXD2880_RESULT_ERROR_SW_STATE;
803 }
804
805 if (tnr_dmd->io->write_reg(tnr_dmd->io,
806 CXD2880_IO_TGT_DMD, 0x00,
807 0x00) != CXD2880_RESULT_OK)
808 return CXD2880_RESULT_ERROR_IO;
809
810 if (tnr_dmd->io->write_reg(tnr_dmd->io,
811 CXD2880_IO_TGT_DMD, 0xFD,
812 0x01) != CXD2880_RESULT_OK)
813 return CXD2880_RESULT_ERROR_IO;
814
815 return CXD2880_RESULT_OK;
816 }
817
818 static enum cxd2880_ret x_sleep_dvbt2_demod_setting(struct cxd2880_tnrdmd
819 *tnr_dmd)
820 {
821 if (!tnr_dmd)
822 return CXD2880_RESULT_ERROR_ARG;
823
824 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
825 u8 data[] = { 0, 1, 0, 2,
826 0, 4, 0, 8, 0, 16, 0, 32
827 };
828
829 if (tnr_dmd->io->write_reg(tnr_dmd->io,
830 CXD2880_IO_TGT_DMD, 0x00,
831 0x1D) != CXD2880_RESULT_OK)
832 return CXD2880_RESULT_ERROR_IO;
833
834 if (tnr_dmd->io->write_regs(tnr_dmd->io,
835 CXD2880_IO_TGT_DMD, 0x47, data,
836 12) != CXD2880_RESULT_OK)
837 return CXD2880_RESULT_ERROR_IO;
838 }
839
840 return CXD2880_RESULT_OK;
841 }
842
843 static enum cxd2880_ret dvbt2_set_profile(struct cxd2880_tnrdmd *tnr_dmd,
844 enum cxd2880_dvbt2_profile profile)
845 {
846 u8 t2_mode_tune_mode = 0;
847 u8 seq_not2_dtime = 0;
848 enum cxd2880_ret ret = CXD2880_RESULT_OK;
849
850 if (!tnr_dmd)
851 return CXD2880_RESULT_ERROR_ARG;
852
853 {
854 u8 dtime1 = 0;
855 u8 dtime2 = 0;
856
857 switch (tnr_dmd->clk_mode) {
858 case CXD2880_TNRDMD_CLOCKMODE_A:
859 dtime1 = 0x27;
860 dtime2 = 0x0C;
861 break;
862 case CXD2880_TNRDMD_CLOCKMODE_B:
863 dtime1 = 0x2C;
864 dtime2 = 0x0D;
865 break;
866 case CXD2880_TNRDMD_CLOCKMODE_C:
867 dtime1 = 0x2E;
868 dtime2 = 0x0E;
869 break;
870 default:
871 return CXD2880_RESULT_ERROR_SW_STATE;
872 }
873
874 switch (profile) {
875 case CXD2880_DVBT2_PROFILE_BASE:
876 t2_mode_tune_mode = 0x01;
877 seq_not2_dtime = dtime2;
878 break;
879
880 case CXD2880_DVBT2_PROFILE_LITE:
881 t2_mode_tune_mode = 0x05;
882 seq_not2_dtime = dtime1;
883 break;
884
885 case CXD2880_DVBT2_PROFILE_ANY:
886 t2_mode_tune_mode = 0x00;
887 seq_not2_dtime = dtime1;
888 break;
889
890 default:
891 return CXD2880_RESULT_ERROR_ARG;
892 }
893 }
894
895 if (tnr_dmd->io->write_reg(tnr_dmd->io,
896 CXD2880_IO_TGT_DMD, 0x00,
897 0x2E) != CXD2880_RESULT_OK)
898 return CXD2880_RESULT_ERROR_IO;
899
900 if (tnr_dmd->io->write_reg(tnr_dmd->io,
901 CXD2880_IO_TGT_DMD, 0x10,
902 t2_mode_tune_mode) != CXD2880_RESULT_OK)
903 return CXD2880_RESULT_ERROR_IO;
904
905 if (tnr_dmd->io->write_reg(tnr_dmd->io,
906 CXD2880_IO_TGT_DMD, 0x00,
907 0x04) != CXD2880_RESULT_OK)
908 return CXD2880_RESULT_ERROR_IO;
909
910 if (tnr_dmd->io->write_reg(tnr_dmd->io,
911 CXD2880_IO_TGT_DMD, 0x2C,
912 seq_not2_dtime) != CXD2880_RESULT_OK)
913 return CXD2880_RESULT_ERROR_IO;
914
915 return ret;
916 }
917
918 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd,
919 struct cxd2880_dvbt2_tune_param
920 *tune_param)
921 {
922 enum cxd2880_ret ret = CXD2880_RESULT_OK;
923
924 if ((!tnr_dmd) || (!tune_param))
925 return CXD2880_RESULT_ERROR_ARG;
926
927 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
928 return CXD2880_RESULT_ERROR_ARG;
929
930 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
931 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
932 return CXD2880_RESULT_ERROR_SW_STATE;
933
934 if ((tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) &&
935 (tune_param->profile == CXD2880_DVBT2_PROFILE_ANY))
936 return CXD2880_RESULT_ERROR_NOSUPPORT;
937
938 ret =
939 cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT2,
940 tune_param->center_freq_khz,
941 tune_param->bandwidth, 0, 0);
942 if (ret != CXD2880_RESULT_OK)
943 return ret;
944
945 ret =
946 x_tune_dvbt2_demod_setting(tnr_dmd, tune_param->bandwidth,
947 tnr_dmd->clk_mode);
948 if (ret != CXD2880_RESULT_OK)
949 return ret;
950
951 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
952 ret =
953 x_tune_dvbt2_demod_setting(tnr_dmd->diver_sub,
954 tune_param->bandwidth,
955 tnr_dmd->diver_sub->clk_mode);
956 if (ret != CXD2880_RESULT_OK)
957 return ret;
958 }
959
960 ret = dvbt2_set_profile(tnr_dmd, tune_param->profile);
961 if (ret != CXD2880_RESULT_OK)
962 return ret;
963
964 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
965 ret =
966 dvbt2_set_profile(tnr_dmd->diver_sub, tune_param->profile);
967 if (ret != CXD2880_RESULT_OK)
968 return ret;
969 }
970
971 if (tune_param->data_plp_id == CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO) {
972 ret = cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 1, 0);
973 if (ret != CXD2880_RESULT_OK)
974 return ret;
975 } else {
976 ret =
977 cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 0,
978 (u8)(tune_param->data_plp_id));
979 if (ret != CXD2880_RESULT_OK)
980 return ret;
981 }
982
983 return CXD2880_RESULT_OK;
984 }
985
986 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd,
987 struct cxd2880_dvbt2_tune_param
988 *tune_param)
989 {
990 enum cxd2880_ret ret = CXD2880_RESULT_OK;
991
992 if ((!tnr_dmd) || (!tune_param))
993 return CXD2880_RESULT_ERROR_ARG;
994
995 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
996 return CXD2880_RESULT_ERROR_ARG;
997
998 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
999 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
1000 return CXD2880_RESULT_ERROR_SW_STATE;
1001
1002 {
1003 u8 en_fef_intmtnt_ctrl = 1;
1004
1005 switch (tune_param->profile) {
1006 case CXD2880_DVBT2_PROFILE_BASE:
1007 en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_base;
1008 break;
1009 case CXD2880_DVBT2_PROFILE_LITE:
1010 en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_lite;
1011 break;
1012 case CXD2880_DVBT2_PROFILE_ANY:
1013 if (tnr_dmd->en_fef_intmtnt_base &&
1014 tnr_dmd->en_fef_intmtnt_lite)
1015 en_fef_intmtnt_ctrl = 1;
1016 else
1017 en_fef_intmtnt_ctrl = 0;
1018 break;
1019 default:
1020 return CXD2880_RESULT_ERROR_ARG;
1021 }
1022
1023 ret =
1024 cxd2880_tnrdmd_common_tune_setting2(tnr_dmd,
1025 CXD2880_DTV_SYS_DVBT2,
1026 en_fef_intmtnt_ctrl);
1027 if (ret != CXD2880_RESULT_OK)
1028 return ret;
1029 }
1030
1031 tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;
1032 tnr_dmd->frequency_khz = tune_param->center_freq_khz;
1033 tnr_dmd->sys = CXD2880_DTV_SYS_DVBT2;
1034 tnr_dmd->bandwidth = tune_param->bandwidth;
1035
1036 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
1037 tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;
1038 tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;
1039 tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT2;
1040 tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;
1041 }
1042
1043 return CXD2880_RESULT_OK;
1044 }
1045
1046 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd
1047 *tnr_dmd)
1048 {
1049 enum cxd2880_ret ret = CXD2880_RESULT_OK;
1050
1051 if (!tnr_dmd)
1052 return CXD2880_RESULT_ERROR_ARG;
1053
1054 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1055 return CXD2880_RESULT_ERROR_ARG;
1056
1057 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
1058 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
1059 return CXD2880_RESULT_ERROR_SW_STATE;
1060
1061 ret = x_sleep_dvbt2_demod_setting(tnr_dmd);
1062 if (ret != CXD2880_RESULT_OK)
1063 return ret;
1064
1065 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
1066 ret = x_sleep_dvbt2_demod_setting(tnr_dmd->diver_sub);
1067 if (ret != CXD2880_RESULT_OK)
1068 return ret;
1069 }
1070
1071 return CXD2880_RESULT_OK;
1072 }
1073
1074 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
1075 *tnr_dmd,
1076 enum
1077 cxd2880_tnrdmd_lock_result
1078 *lock)
1079 {
1080 enum cxd2880_ret ret = CXD2880_RESULT_OK;
1081
1082 u8 sync_stat = 0;
1083 u8 ts_lock = 0;
1084 u8 unlock_detected = 0;
1085 u8 unlock_detected_sub = 0;
1086
1087 if ((!tnr_dmd) || (!lock))
1088 return CXD2880_RESULT_ERROR_ARG;
1089
1090 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1091 return CXD2880_RESULT_ERROR_ARG;
1092
1093 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1094 return CXD2880_RESULT_ERROR_SW_STATE;
1095
1096 ret =
1097 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
1098 &unlock_detected);
1099 if (ret != CXD2880_RESULT_OK)
1100 return ret;
1101
1102 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
1103 if (sync_stat == 6)
1104 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1105 else if (unlock_detected)
1106 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1107 else
1108 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1109
1110 return ret;
1111 }
1112
1113 if (sync_stat == 6) {
1114 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1115 return ret;
1116 }
1117
1118 ret =
1119 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,
1120 &unlock_detected_sub);
1121 if (ret != CXD2880_RESULT_OK)
1122 return ret;
1123
1124 if (sync_stat == 6)
1125 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1126 else if (unlock_detected && unlock_detected_sub)
1127 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1128 else
1129 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1130
1131 return ret;
1132 }
1133
1134 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
1135 *tnr_dmd,
1136 enum
1137 cxd2880_tnrdmd_lock_result
1138 *lock)
1139 {
1140 enum cxd2880_ret ret = CXD2880_RESULT_OK;
1141
1142 u8 sync_stat = 0;
1143 u8 ts_lock = 0;
1144 u8 unlock_detected = 0;
1145 u8 unlock_detected_sub = 0;
1146
1147 if ((!tnr_dmd) || (!lock))
1148 return CXD2880_RESULT_ERROR_ARG;
1149
1150 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1151 return CXD2880_RESULT_ERROR_ARG;
1152
1153 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1154 return CXD2880_RESULT_ERROR_SW_STATE;
1155
1156 ret =
1157 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
1158 &unlock_detected);
1159 if (ret != CXD2880_RESULT_OK)
1160 return ret;
1161
1162 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
1163 if (ts_lock)
1164 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1165 else if (unlock_detected)
1166 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1167 else
1168 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1169
1170 return ret;
1171 }
1172
1173 if (ts_lock) {
1174 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1175 return ret;
1176 } else if (!unlock_detected) {
1177 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1178 return ret;
1179 }
1180
1181 ret =
1182 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,
1183 &unlock_detected_sub);
1184 if (ret != CXD2880_RESULT_OK)
1185 return ret;
1186
1187 if (unlock_detected && unlock_detected_sub)
1188 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1189 else
1190 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1191
1192 return ret;
1193 }
1194
1195 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd
1196 *tnr_dmd, u8 auto_plp,
1197 u8 plp_id)
1198 {
1199 enum cxd2880_ret ret = CXD2880_RESULT_OK;
1200
1201 if (!tnr_dmd)
1202 return CXD2880_RESULT_ERROR_ARG;
1203
1204 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1205 return CXD2880_RESULT_ERROR_ARG;
1206
1207 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
1208 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
1209 return CXD2880_RESULT_ERROR_SW_STATE;
1210
1211 if (tnr_dmd->io->write_reg(tnr_dmd->io,
1212 CXD2880_IO_TGT_DMD, 0x00,
1213 0x23) != CXD2880_RESULT_OK)
1214 return CXD2880_RESULT_ERROR_IO;
1215
1216 if (!auto_plp) {
1217 if (tnr_dmd->io->write_reg(tnr_dmd->io,
1218 CXD2880_IO_TGT_DMD, 0xAF,
1219 plp_id) != CXD2880_RESULT_OK)
1220 return CXD2880_RESULT_ERROR_IO;
1221 }
1222
1223 if (tnr_dmd->io->write_reg(tnr_dmd->io,
1224 CXD2880_IO_TGT_DMD, 0xAD,
1225 auto_plp ? 0x00 : 0x01) != CXD2880_RESULT_OK)
1226 return CXD2880_RESULT_ERROR_IO;
1227
1228 return ret;
1229 }
1230
1231 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd
1232 *tnr_dmd)
1233 {
1234 enum cxd2880_ret ret = CXD2880_RESULT_OK;
1235
1236 if (!tnr_dmd)
1237 return CXD2880_RESULT_ERROR_ARG;
1238
1239 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1240 return CXD2880_RESULT_ERROR_ARG;
1241
1242 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1243 return CXD2880_RESULT_ERROR_SW_STATE;
1244
1245 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE)
1246 return CXD2880_RESULT_OK;
1247
1248 {
1249 struct cxd2880_dvbt2_ofdm ofdm;
1250
1251 ret = cxd2880_tnrdmd_dvbt2_mon_ofdm(tnr_dmd, &ofdm);
1252 if (ret != CXD2880_RESULT_OK)
1253 return ret;
1254
1255 if (!ofdm.mixed)
1256 return CXD2880_RESULT_OK;
1257 }
1258
1259 {
1260 u8 data[] = { 0, 8, 0, 16,
1261 0, 32, 0, 64, 0, 128, 1, 0
1262 };
1263
1264 if (tnr_dmd->io->write_reg(tnr_dmd->io,
1265 CXD2880_IO_TGT_DMD, 0x00,
1266 0x1D) != CXD2880_RESULT_OK)
1267 return CXD2880_RESULT_ERROR_IO;
1268
1269 if (tnr_dmd->io->write_regs(tnr_dmd->io,
1270 CXD2880_IO_TGT_DMD, 0x47, data,
1271 12) != CXD2880_RESULT_OK)
1272 return CXD2880_RESULT_ERROR_IO;
1273 }
1274
1275 return CXD2880_RESULT_OK;
1276 }
1277
1278 enum cxd2880_ret cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd
1279 *tnr_dmd,
1280 u8 *l1_post_valid)
1281 {
1282 enum cxd2880_ret ret = CXD2880_RESULT_OK;
1283
1284 u8 data;
1285
1286 if ((!tnr_dmd) || (!l1_post_valid))
1287 return CXD2880_RESULT_ERROR_ARG;
1288
1289 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1290 return CXD2880_RESULT_ERROR_ARG;
1291
1292 if ((tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP) &&
1293 (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE))
1294 return CXD2880_RESULT_ERROR_SW_STATE;
1295
1296 if (tnr_dmd->io->write_reg(tnr_dmd->io,
1297 CXD2880_IO_TGT_DMD, 0x00,
1298 0x0B) != CXD2880_RESULT_OK)
1299 return CXD2880_RESULT_ERROR_IO;
1300
1301 if (tnr_dmd->io->read_regs(tnr_dmd->io,
1302 CXD2880_IO_TGT_DMD, 0x86, &data,
1303 1) != CXD2880_RESULT_OK)
1304 return CXD2880_RESULT_ERROR_IO;
1305
1306 *l1_post_valid = data & 0x01;
1307
1308 return ret;
1309 }