920 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * cxd2880_tnrdmd_dvbt.c4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver5 * control functions for DVB-T6 *7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation8 */9 10#include <media/dvb_frontend.h>11 12#include "cxd2880_tnrdmd_dvbt.h"13#include "cxd2880_tnrdmd_dvbt_mon.h"14 15static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = {16 {0x00, 0x00}, {0x31, 0x01},17};18 19static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = {20 {0x00, 0x04}, {0x5c, 0xfb}, {0x00, 0x10}, {0xa4, 0x03},21 {0x00, 0x14}, {0xb0, 0x00}, {0x00, 0x25},22};23 24static const struct cxd2880_reg_value tune_dmd_setting_seq3[] = {25 {0x00, 0x12}, {0x44, 0x00},26};27 28static const struct cxd2880_reg_value tune_dmd_setting_seq4[] = {29 {0x00, 0x11}, {0x87, 0xd2},30};31 32static const struct cxd2880_reg_value tune_dmd_setting_seq5[] = {33 {0x00, 0x00}, {0xfd, 0x01},34};35 36static const struct cxd2880_reg_value sleep_dmd_setting_seq1[] = {37 {0x00, 0x04}, {0x5c, 0xd8}, {0x00, 0x10}, {0xa4, 0x00},38};39 40static const struct cxd2880_reg_value sleep_dmd_setting_seq2[] = {41 {0x00, 0x11}, {0x87, 0x04},42};43 44static int x_tune_dvbt_demod_setting(struct cxd2880_tnrdmd45 *tnr_dmd,46 enum cxd2880_dtv_bandwidth47 bandwidth,48 enum cxd2880_tnrdmd_clockmode49 clk_mode)50{51 static const u8 clk_mode_ckffrq_a[2] = { 0x52, 0x49 };52 static const u8 clk_mode_ckffrq_b[2] = { 0x5d, 0x55 };53 static const u8 clk_mode_ckffrq_c[2] = { 0x60, 0x00 };54 static const u8 ratectl_margin[2] = { 0x01, 0xf0 };55 static const u8 maxclkcnt_a[3] = { 0x73, 0xca, 0x49 };56 static const u8 maxclkcnt_b[3] = { 0xc8, 0x13, 0xaa };57 static const u8 maxclkcnt_c[3] = { 0xdc, 0x6c, 0x00 };58 59 static const u8 bw8_nomi_ac[5] = { 0x15, 0x00, 0x00, 0x00, 0x00};60 static const u8 bw8_nomi_b[5] = { 0x14, 0x6a, 0xaa, 0xaa, 0xaa};61 static const u8 bw8_gtdofst_a[2] = { 0x01, 0x28 };62 static const u8 bw8_gtdofst_b[2] = { 0x11, 0x44 };63 static const u8 bw8_gtdofst_c[2] = { 0x15, 0x28 };64 static const u8 bw8_mrc_a[5] = { 0x30, 0x00, 0x00, 0x90, 0x00 };65 static const u8 bw8_mrc_b[5] = { 0x36, 0x71, 0x00, 0xa3, 0x55 };66 static const u8 bw8_mrc_c[5] = { 0x38, 0x00, 0x00, 0xa8, 0x00 };67 static const u8 bw8_notch[4] = { 0xb3, 0x00, 0x01, 0x02 };68 69 static const u8 bw7_nomi_ac[5] = { 0x18, 0x00, 0x00, 0x00, 0x00};70 static const u8 bw7_nomi_b[5] = { 0x17, 0x55, 0x55, 0x55, 0x55};71 static const u8 bw7_gtdofst_a[2] = { 0x12, 0x4c };72 static const u8 bw7_gtdofst_b[2] = { 0x1f, 0x15 };73 static const u8 bw7_gtdofst_c[2] = { 0x1f, 0xf8 };74 static const u8 bw7_mrc_a[5] = { 0x36, 0xdb, 0x00, 0xa4, 0x92 };75 static const u8 bw7_mrc_b[5] = { 0x3e, 0x38, 0x00, 0xba, 0xaa };76 static const u8 bw7_mrc_c[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };77 static const u8 bw7_notch[4] = { 0xb8, 0x00, 0x00, 0x03 };78 79 static const u8 bw6_nomi_ac[5] = { 0x1c, 0x00, 0x00, 0x00, 0x00};80 static const u8 bw6_nomi_b[5] = { 0x1b, 0x38, 0xe3, 0x8e, 0x38};81 static const u8 bw6_gtdofst_a[2] = { 0x1f, 0xf8 };82 static const u8 bw6_gtdofst_b[2] = { 0x24, 0x43 };83 static const u8 bw6_gtdofst_c[2] = { 0x25, 0x4c };84 static const u8 bw6_mrc_a[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };85 static const u8 bw6_mrc_b[5] = { 0x48, 0x97, 0x00, 0xd9, 0xc7 };86 static const u8 bw6_mrc_c[5] = { 0x4a, 0xaa, 0x00, 0xdf, 0xff };87 static const u8 bw6_notch[4] = { 0xbe, 0xab, 0x00, 0x03 };88 89 static const u8 bw5_nomi_ac[5] = { 0x21, 0x99, 0x99, 0x99, 0x99};90 static const u8 bw5_nomi_b[5] = { 0x20, 0xaa, 0xaa, 0xaa, 0xaa};91 static const u8 bw5_gtdofst_a[2] = { 0x26, 0x5d };92 static const u8 bw5_gtdofst_b[2] = { 0x2b, 0x84 };93 static const u8 bw5_gtdofst_c[2] = { 0x2c, 0xc2 };94 static const u8 bw5_mrc_a[5] = { 0x4c, 0xcc, 0x00, 0xe6, 0x66 };95 static const u8 bw5_mrc_b[5] = { 0x57, 0x1c, 0x01, 0x05, 0x55 };96 static const u8 bw5_mrc_c[5] = { 0x59, 0x99, 0x01, 0x0c, 0xcc };97 static const u8 bw5_notch[4] = { 0xc8, 0x01, 0x00, 0x03 };98 const u8 *data = NULL;99 u8 sst_data;100 int ret;101 102 if (!tnr_dmd)103 return -EINVAL;104 105 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,106 CXD2880_IO_TGT_SYS,107 tune_dmd_setting_seq1,108 ARRAY_SIZE(tune_dmd_setting_seq1));109 if (ret)110 return ret;111 112 ret = tnr_dmd->io->write_reg(tnr_dmd->io,113 CXD2880_IO_TGT_DMD,114 0x00, 0x04);115 if (ret)116 return ret;117 118 switch (clk_mode) {119 case CXD2880_TNRDMD_CLOCKMODE_A:120 data = clk_mode_ckffrq_a;121 break;122 case CXD2880_TNRDMD_CLOCKMODE_B:123 data = clk_mode_ckffrq_b;124 break;125 case CXD2880_TNRDMD_CLOCKMODE_C:126 data = clk_mode_ckffrq_c;127 break;128 default:129 return -EINVAL;130 }131 132 ret = tnr_dmd->io->write_regs(tnr_dmd->io,133 CXD2880_IO_TGT_DMD,134 0x65, data, 2);135 if (ret)136 return ret;137 138 ret = tnr_dmd->io->write_reg(tnr_dmd->io,139 CXD2880_IO_TGT_DMD,140 0x5d, 0x07);141 if (ret)142 return ret;143 144 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {145 u8 data[2] = { 0x01, 0x01 };146 147 ret = tnr_dmd->io->write_reg(tnr_dmd->io,148 CXD2880_IO_TGT_DMD,149 0x00, 0x00);150 if (ret)151 return ret;152 153 ret = tnr_dmd->io->write_regs(tnr_dmd->io,154 CXD2880_IO_TGT_DMD,155 0xce, data, 2);156 if (ret)157 return ret;158 }159 160 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,161 CXD2880_IO_TGT_DMD,162 tune_dmd_setting_seq2,163 ARRAY_SIZE(tune_dmd_setting_seq2));164 if (ret)165 return ret;166 167 ret = tnr_dmd->io->write_regs(tnr_dmd->io,168 CXD2880_IO_TGT_DMD,169 0xf0, ratectl_margin, 2);170 if (ret)171 return ret;172 173 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN ||174 tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {175 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,176 CXD2880_IO_TGT_DMD,177 tune_dmd_setting_seq3,178 ARRAY_SIZE(tune_dmd_setting_seq3));179 if (ret)180 return ret;181 }182 183 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {184 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,185 CXD2880_IO_TGT_DMD,186 tune_dmd_setting_seq4,187 ARRAY_SIZE(tune_dmd_setting_seq4));188 if (ret)189 return ret;190 }191 192 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {193 ret = tnr_dmd->io->write_reg(tnr_dmd->io,194 CXD2880_IO_TGT_DMD,195 0x00, 0x04);196 if (ret)197 return ret;198 199 switch (clk_mode) {200 case CXD2880_TNRDMD_CLOCKMODE_A:201 data = maxclkcnt_a;202 break;203 case CXD2880_TNRDMD_CLOCKMODE_B:204 data = maxclkcnt_b;205 break;206 case CXD2880_TNRDMD_CLOCKMODE_C:207 data = maxclkcnt_c;208 break;209 default:210 return -EINVAL;211 }212 213 ret = tnr_dmd->io->write_regs(tnr_dmd->io,214 CXD2880_IO_TGT_DMD,215 0x68, data, 3);216 if (ret)217 return ret;218 }219 220 ret = tnr_dmd->io->write_reg(tnr_dmd->io,221 CXD2880_IO_TGT_DMD,222 0x00, 0x04);223 if (ret)224 return ret;225 226 switch (bandwidth) {227 case CXD2880_DTV_BW_8_MHZ:228 switch (clk_mode) {229 case CXD2880_TNRDMD_CLOCKMODE_A:230 case CXD2880_TNRDMD_CLOCKMODE_C:231 data = bw8_nomi_ac;232 break;233 case CXD2880_TNRDMD_CLOCKMODE_B:234 data = bw8_nomi_b;235 break;236 default:237 return -EINVAL;238 }239 240 ret = tnr_dmd->io->write_regs(tnr_dmd->io,241 CXD2880_IO_TGT_DMD,242 0x60, data, 5);243 if (ret)244 return ret;245 246 ret = tnr_dmd->io->write_reg(tnr_dmd->io,247 CXD2880_IO_TGT_DMD,248 0x4a, 0x00);249 if (ret)250 return ret;251 252 switch (clk_mode) {253 case CXD2880_TNRDMD_CLOCKMODE_A:254 data = bw8_gtdofst_a;255 break;256 case CXD2880_TNRDMD_CLOCKMODE_B:257 data = bw8_gtdofst_b;258 break;259 case CXD2880_TNRDMD_CLOCKMODE_C:260 data = bw8_gtdofst_c;261 break;262 default:263 return -EINVAL;264 }265 266 ret = tnr_dmd->io->write_regs(tnr_dmd->io,267 CXD2880_IO_TGT_DMD,268 0x7d, data, 2);269 if (ret)270 return ret;271 272 switch (clk_mode) {273 case CXD2880_TNRDMD_CLOCKMODE_A:274 case CXD2880_TNRDMD_CLOCKMODE_B:275 sst_data = 0x35;276 break;277 case CXD2880_TNRDMD_CLOCKMODE_C:278 sst_data = 0x34;279 break;280 default:281 return -EINVAL;282 }283 284 ret = tnr_dmd->io->write_reg(tnr_dmd->io,285 CXD2880_IO_TGT_DMD,286 0x71, sst_data);287 if (ret)288 return ret;289 290 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {291 switch (clk_mode) {292 case CXD2880_TNRDMD_CLOCKMODE_A:293 data = bw8_mrc_a;294 break;295 case CXD2880_TNRDMD_CLOCKMODE_B:296 data = bw8_mrc_b;297 break;298 case CXD2880_TNRDMD_CLOCKMODE_C:299 data = bw8_mrc_c;300 break;301 default:302 return -EINVAL;303 }304 305 ret = tnr_dmd->io->write_regs(tnr_dmd->io,306 CXD2880_IO_TGT_DMD,307 0x4b, &data[0], 2);308 if (ret)309 return ret;310 311 ret = tnr_dmd->io->write_regs(tnr_dmd->io,312 CXD2880_IO_TGT_DMD,313 0x51, &data[2], 3);314 if (ret)315 return ret;316 }317 318 ret = tnr_dmd->io->write_regs(tnr_dmd->io,319 CXD2880_IO_TGT_DMD,320 0x72, &bw8_notch[0], 2);321 if (ret)322 return ret;323 324 ret = tnr_dmd->io->write_regs(tnr_dmd->io,325 CXD2880_IO_TGT_DMD,326 0x6b, &bw8_notch[2], 2);327 if (ret)328 return ret;329 break;330 331 case CXD2880_DTV_BW_7_MHZ:332 switch (clk_mode) {333 case CXD2880_TNRDMD_CLOCKMODE_A:334 case CXD2880_TNRDMD_CLOCKMODE_C:335 data = bw7_nomi_ac;336 break;337 case CXD2880_TNRDMD_CLOCKMODE_B:338 data = bw7_nomi_b;339 break;340 default:341 return -EINVAL;342 }343 344 ret = tnr_dmd->io->write_regs(tnr_dmd->io,345 CXD2880_IO_TGT_DMD,346 0x60, data, 5);347 if (ret)348 return ret;349 350 ret = tnr_dmd->io->write_reg(tnr_dmd->io,351 CXD2880_IO_TGT_DMD,352 0x4a, 0x02);353 if (ret)354 return ret;355 356 switch (clk_mode) {357 case CXD2880_TNRDMD_CLOCKMODE_A:358 data = bw7_gtdofst_a;359 break;360 case CXD2880_TNRDMD_CLOCKMODE_B:361 data = bw7_gtdofst_b;362 break;363 case CXD2880_TNRDMD_CLOCKMODE_C:364 data = bw7_gtdofst_c;365 break;366 default:367 return -EINVAL;368 }369 370 ret = tnr_dmd->io->write_regs(tnr_dmd->io,371 CXD2880_IO_TGT_DMD,372 0x7d, data, 2);373 if (ret)374 return ret;375 376 switch (clk_mode) {377 case CXD2880_TNRDMD_CLOCKMODE_A:378 case CXD2880_TNRDMD_CLOCKMODE_B:379 sst_data = 0x2f;380 break;381 case CXD2880_TNRDMD_CLOCKMODE_C:382 sst_data = 0x2e;383 break;384 default:385 return -EINVAL;386 }387 388 ret = tnr_dmd->io->write_reg(tnr_dmd->io,389 CXD2880_IO_TGT_DMD,390 0x71, sst_data);391 if (ret)392 return ret;393 394 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {395 switch (clk_mode) {396 case CXD2880_TNRDMD_CLOCKMODE_A:397 data = bw7_mrc_a;398 break;399 case CXD2880_TNRDMD_CLOCKMODE_B:400 data = bw7_mrc_b;401 break;402 case CXD2880_TNRDMD_CLOCKMODE_C:403 data = bw7_mrc_c;404 break;405 default:406 return -EINVAL;407 }408 409 ret = tnr_dmd->io->write_regs(tnr_dmd->io,410 CXD2880_IO_TGT_DMD,411 0x4b, &data[0], 2);412 if (ret)413 return ret;414 415 ret = tnr_dmd->io->write_regs(tnr_dmd->io,416 CXD2880_IO_TGT_DMD,417 0x51, &data[2], 3);418 if (ret)419 return ret;420 }421 422 ret = tnr_dmd->io->write_regs(tnr_dmd->io,423 CXD2880_IO_TGT_DMD,424 0x72, &bw7_notch[0], 2);425 if (ret)426 return ret;427 428 ret = tnr_dmd->io->write_regs(tnr_dmd->io,429 CXD2880_IO_TGT_DMD,430 0x6b, &bw7_notch[2], 2);431 if (ret)432 return ret;433 break;434 435 case CXD2880_DTV_BW_6_MHZ:436 switch (clk_mode) {437 case CXD2880_TNRDMD_CLOCKMODE_A:438 case CXD2880_TNRDMD_CLOCKMODE_C:439 data = bw6_nomi_ac;440 break;441 case CXD2880_TNRDMD_CLOCKMODE_B:442 data = bw6_nomi_b;443 break;444 default:445 return -EINVAL;446 }447 448 ret = tnr_dmd->io->write_regs(tnr_dmd->io,449 CXD2880_IO_TGT_DMD,450 0x60, data, 5);451 if (ret)452 return ret;453 454 ret = tnr_dmd->io->write_reg(tnr_dmd->io,455 CXD2880_IO_TGT_DMD,456 0x4a, 0x04);457 if (ret)458 return ret;459 460 switch (clk_mode) {461 case CXD2880_TNRDMD_CLOCKMODE_A:462 data = bw6_gtdofst_a;463 break;464 case CXD2880_TNRDMD_CLOCKMODE_B:465 data = bw6_gtdofst_b;466 break;467 case CXD2880_TNRDMD_CLOCKMODE_C:468 data = bw6_gtdofst_c;469 break;470 default:471 return -EINVAL;472 }473 474 ret = tnr_dmd->io->write_regs(tnr_dmd->io,475 CXD2880_IO_TGT_DMD,476 0x7d, data, 2);477 if (ret)478 return ret;479 480 switch (clk_mode) {481 case CXD2880_TNRDMD_CLOCKMODE_A:482 case CXD2880_TNRDMD_CLOCKMODE_C:483 sst_data = 0x29;484 break;485 case CXD2880_TNRDMD_CLOCKMODE_B:486 sst_data = 0x2a;487 break;488 default:489 return -EINVAL;490 }491 492 ret = tnr_dmd->io->write_reg(tnr_dmd->io,493 CXD2880_IO_TGT_DMD,494 0x71, sst_data);495 if (ret)496 return ret;497 498 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {499 switch (clk_mode) {500 case CXD2880_TNRDMD_CLOCKMODE_A:501 data = bw6_mrc_a;502 break;503 case CXD2880_TNRDMD_CLOCKMODE_B:504 data = bw6_mrc_b;505 break;506 case CXD2880_TNRDMD_CLOCKMODE_C:507 data = bw6_mrc_c;508 break;509 default:510 return -EINVAL;511 }512 513 ret = tnr_dmd->io->write_regs(tnr_dmd->io,514 CXD2880_IO_TGT_DMD,515 0x4b, &data[0], 2);516 if (ret)517 return ret;518 519 ret = tnr_dmd->io->write_regs(tnr_dmd->io,520 CXD2880_IO_TGT_DMD,521 0x51, &data[2], 3);522 if (ret)523 return ret;524 }525 526 ret = tnr_dmd->io->write_regs(tnr_dmd->io,527 CXD2880_IO_TGT_DMD,528 0x72, &bw6_notch[0], 2);529 if (ret)530 return ret;531 532 ret = tnr_dmd->io->write_regs(tnr_dmd->io,533 CXD2880_IO_TGT_DMD,534 0x6b, &bw6_notch[2], 2);535 if (ret)536 return ret;537 break;538 539 case CXD2880_DTV_BW_5_MHZ:540 switch (clk_mode) {541 case CXD2880_TNRDMD_CLOCKMODE_A:542 case CXD2880_TNRDMD_CLOCKMODE_C:543 data = bw5_nomi_ac;544 break;545 case CXD2880_TNRDMD_CLOCKMODE_B:546 data = bw5_nomi_b;547 break;548 default:549 return -EINVAL;550 }551 552 ret = tnr_dmd->io->write_regs(tnr_dmd->io,553 CXD2880_IO_TGT_DMD,554 0x60, data, 5);555 if (ret)556 return ret;557 558 ret = tnr_dmd->io->write_reg(tnr_dmd->io,559 CXD2880_IO_TGT_DMD,560 0x4a, 0x06);561 if (ret)562 return ret;563 564 switch (clk_mode) {565 case CXD2880_TNRDMD_CLOCKMODE_A:566 data = bw5_gtdofst_a;567 break;568 case CXD2880_TNRDMD_CLOCKMODE_B:569 data = bw5_gtdofst_b;570 break;571 case CXD2880_TNRDMD_CLOCKMODE_C:572 data = bw5_gtdofst_c;573 break;574 default:575 return -EINVAL;576 }577 578 ret = tnr_dmd->io->write_regs(tnr_dmd->io,579 CXD2880_IO_TGT_DMD,580 0x7d, data, 2);581 if (ret)582 return ret;583 584 switch (clk_mode) {585 case CXD2880_TNRDMD_CLOCKMODE_A:586 case CXD2880_TNRDMD_CLOCKMODE_B:587 sst_data = 0x24;588 break;589 case CXD2880_TNRDMD_CLOCKMODE_C:590 sst_data = 0x23;591 break;592 default:593 return -EINVAL;594 }595 596 ret = tnr_dmd->io->write_reg(tnr_dmd->io,597 CXD2880_IO_TGT_DMD,598 0x71, sst_data);599 if (ret)600 return ret;601 602 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {603 switch (clk_mode) {604 case CXD2880_TNRDMD_CLOCKMODE_A:605 data = bw5_mrc_a;606 break;607 case CXD2880_TNRDMD_CLOCKMODE_B:608 data = bw5_mrc_b;609 break;610 case CXD2880_TNRDMD_CLOCKMODE_C:611 data = bw5_mrc_c;612 break;613 default:614 return -EINVAL;615 }616 617 ret = tnr_dmd->io->write_regs(tnr_dmd->io,618 CXD2880_IO_TGT_DMD,619 0x4b, &data[0], 2);620 if (ret)621 return ret;622 623 ret = tnr_dmd->io->write_regs(tnr_dmd->io,624 CXD2880_IO_TGT_DMD,625 0x51, &data[2], 3);626 if (ret)627 return ret;628 }629 630 ret = tnr_dmd->io->write_regs(tnr_dmd->io,631 CXD2880_IO_TGT_DMD,632 0x72, &bw5_notch[0], 2);633 if (ret)634 return ret;635 636 ret = tnr_dmd->io->write_regs(tnr_dmd->io,637 CXD2880_IO_TGT_DMD,638 0x6b, &bw5_notch[2], 2);639 if (ret)640 return ret;641 break;642 643 default:644 return -EINVAL;645 }646 647 return cxd2880_io_write_multi_regs(tnr_dmd->io,648 CXD2880_IO_TGT_DMD,649 tune_dmd_setting_seq5,650 ARRAY_SIZE(tune_dmd_setting_seq5));651}652 653static int x_sleep_dvbt_demod_setting(struct cxd2880_tnrdmd654 *tnr_dmd)655{656 int ret;657 658 if (!tnr_dmd)659 return -EINVAL;660 661 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,662 CXD2880_IO_TGT_DMD,663 sleep_dmd_setting_seq1,664 ARRAY_SIZE(sleep_dmd_setting_seq1));665 if (ret)666 return ret;667 668 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)669 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,670 CXD2880_IO_TGT_DMD,671 sleep_dmd_setting_seq2,672 ARRAY_SIZE(sleep_dmd_setting_seq2));673 674 return ret;675}676 677static int dvbt_set_profile(struct cxd2880_tnrdmd *tnr_dmd,678 enum cxd2880_dvbt_profile profile)679{680 int ret;681 682 if (!tnr_dmd)683 return -EINVAL;684 685 ret = tnr_dmd->io->write_reg(tnr_dmd->io,686 CXD2880_IO_TGT_DMD,687 0x00, 0x10);688 if (ret)689 return ret;690 691 return tnr_dmd->io->write_reg(tnr_dmd->io,692 CXD2880_IO_TGT_DMD,693 0x67,694 (profile == CXD2880_DVBT_PROFILE_HP)695 ? 0x00 : 0x01);696}697 698int cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd,699 struct cxd2880_dvbt_tune_param700 *tune_param)701{702 int ret;703 704 if (!tnr_dmd || !tune_param)705 return -EINVAL;706 707 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)708 return -EINVAL;709 710 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&711 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)712 return -EINVAL;713 714 ret =715 cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT,716 tune_param->center_freq_khz,717 tune_param->bandwidth, 0, 0);718 if (ret)719 return ret;720 721 ret =722 x_tune_dvbt_demod_setting(tnr_dmd, tune_param->bandwidth,723 tnr_dmd->clk_mode);724 if (ret)725 return ret;726 727 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {728 ret =729 x_tune_dvbt_demod_setting(tnr_dmd->diver_sub,730 tune_param->bandwidth,731 tnr_dmd->diver_sub->clk_mode);732 if (ret)733 return ret;734 }735 736 return dvbt_set_profile(tnr_dmd, tune_param->profile);737}738 739int cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd,740 struct cxd2880_dvbt_tune_param741 *tune_param)742{743 int ret;744 745 if (!tnr_dmd || !tune_param)746 return -EINVAL;747 748 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)749 return -EINVAL;750 751 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&752 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)753 return -EINVAL;754 755 ret =756 cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, CXD2880_DTV_SYS_DVBT,757 0);758 if (ret)759 return ret;760 761 tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;762 tnr_dmd->frequency_khz = tune_param->center_freq_khz;763 tnr_dmd->sys = CXD2880_DTV_SYS_DVBT;764 tnr_dmd->bandwidth = tune_param->bandwidth;765 766 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {767 tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;768 tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;769 tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT;770 tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;771 }772 773 return 0;774}775 776int cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd *tnr_dmd)777{778 int ret;779 780 if (!tnr_dmd)781 return -EINVAL;782 783 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)784 return -EINVAL;785 786 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&787 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)788 return -EINVAL;789 790 ret = x_sleep_dvbt_demod_setting(tnr_dmd);791 if (ret)792 return ret;793 794 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)795 ret = x_sleep_dvbt_demod_setting(tnr_dmd->diver_sub);796 797 return ret;798}799 800int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd801 *tnr_dmd,802 enum803 cxd2880_tnrdmd_lock_result804 *lock)805{806 int ret;807 808 u8 sync_stat = 0;809 u8 ts_lock = 0;810 u8 unlock_detected = 0;811 u8 unlock_detected_sub = 0;812 813 if (!tnr_dmd || !lock)814 return -EINVAL;815 816 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)817 return -EINVAL;818 819 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)820 return -EINVAL;821 822 ret =823 cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,824 &unlock_detected);825 if (ret)826 return ret;827 828 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {829 if (sync_stat == 6)830 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;831 else if (unlock_detected)832 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;833 else834 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;835 836 return 0;837 }838 839 if (sync_stat == 6) {840 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;841 return 0;842 }843 844 ret =845 cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,846 &unlock_detected_sub);847 if (ret)848 return ret;849 850 if (sync_stat == 6)851 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;852 else if (unlock_detected && unlock_detected_sub)853 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;854 else855 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;856 857 return 0;858}859 860int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd861 *tnr_dmd,862 enum863 cxd2880_tnrdmd_lock_result864 *lock)865{866 int ret;867 868 u8 sync_stat = 0;869 u8 ts_lock = 0;870 u8 unlock_detected = 0;871 u8 unlock_detected_sub = 0;872 873 if (!tnr_dmd || !lock)874 return -EINVAL;875 876 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)877 return -EINVAL;878 879 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)880 return -EINVAL;881 882 ret =883 cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,884 &unlock_detected);885 if (ret)886 return ret;887 888 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {889 if (ts_lock)890 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;891 else if (unlock_detected)892 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;893 else894 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;895 896 return 0;897 }898 899 if (ts_lock) {900 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;901 return 0;902 } else if (!unlock_detected) {903 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;904 return 0;905 }906 907 ret =908 cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,909 &unlock_detected_sub);910 if (ret)911 return ret;912 913 if (unlock_detected && unlock_detected_sub)914 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;915 else916 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;917 918 return 0;919}920