0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <media/dvb_frontend.h>
0011
0012 #include "cxd2880_tnrdmd_dvbt.h"
0013 #include "cxd2880_tnrdmd_dvbt_mon.h"
0014
0015 static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = {
0016 {0x00, 0x00}, {0x31, 0x01},
0017 };
0018
0019 static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = {
0020 {0x00, 0x04}, {0x5c, 0xfb}, {0x00, 0x10}, {0xa4, 0x03},
0021 {0x00, 0x14}, {0xb0, 0x00}, {0x00, 0x25},
0022 };
0023
0024 static const struct cxd2880_reg_value tune_dmd_setting_seq3[] = {
0025 {0x00, 0x12}, {0x44, 0x00},
0026 };
0027
0028 static const struct cxd2880_reg_value tune_dmd_setting_seq4[] = {
0029 {0x00, 0x11}, {0x87, 0xd2},
0030 };
0031
0032 static const struct cxd2880_reg_value tune_dmd_setting_seq5[] = {
0033 {0x00, 0x00}, {0xfd, 0x01},
0034 };
0035
0036 static const struct cxd2880_reg_value sleep_dmd_setting_seq1[] = {
0037 {0x00, 0x04}, {0x5c, 0xd8}, {0x00, 0x10}, {0xa4, 0x00},
0038 };
0039
0040 static const struct cxd2880_reg_value sleep_dmd_setting_seq2[] = {
0041 {0x00, 0x11}, {0x87, 0x04},
0042 };
0043
0044 static int x_tune_dvbt_demod_setting(struct cxd2880_tnrdmd
0045 *tnr_dmd,
0046 enum cxd2880_dtv_bandwidth
0047 bandwidth,
0048 enum cxd2880_tnrdmd_clockmode
0049 clk_mode)
0050 {
0051 static const u8 clk_mode_ckffrq_a[2] = { 0x52, 0x49 };
0052 static const u8 clk_mode_ckffrq_b[2] = { 0x5d, 0x55 };
0053 static const u8 clk_mode_ckffrq_c[2] = { 0x60, 0x00 };
0054 static const u8 ratectl_margin[2] = { 0x01, 0xf0 };
0055 static const u8 maxclkcnt_a[3] = { 0x73, 0xca, 0x49 };
0056 static const u8 maxclkcnt_b[3] = { 0xc8, 0x13, 0xaa };
0057 static const u8 maxclkcnt_c[3] = { 0xdc, 0x6c, 0x00 };
0058
0059 static const u8 bw8_nomi_ac[5] = { 0x15, 0x00, 0x00, 0x00, 0x00};
0060 static const u8 bw8_nomi_b[5] = { 0x14, 0x6a, 0xaa, 0xaa, 0xaa};
0061 static const u8 bw8_gtdofst_a[2] = { 0x01, 0x28 };
0062 static const u8 bw8_gtdofst_b[2] = { 0x11, 0x44 };
0063 static const u8 bw8_gtdofst_c[2] = { 0x15, 0x28 };
0064 static const u8 bw8_mrc_a[5] = { 0x30, 0x00, 0x00, 0x90, 0x00 };
0065 static const u8 bw8_mrc_b[5] = { 0x36, 0x71, 0x00, 0xa3, 0x55 };
0066 static const u8 bw8_mrc_c[5] = { 0x38, 0x00, 0x00, 0xa8, 0x00 };
0067 static const u8 bw8_notch[4] = { 0xb3, 0x00, 0x01, 0x02 };
0068
0069 static const u8 bw7_nomi_ac[5] = { 0x18, 0x00, 0x00, 0x00, 0x00};
0070 static const u8 bw7_nomi_b[5] = { 0x17, 0x55, 0x55, 0x55, 0x55};
0071 static const u8 bw7_gtdofst_a[2] = { 0x12, 0x4c };
0072 static const u8 bw7_gtdofst_b[2] = { 0x1f, 0x15 };
0073 static const u8 bw7_gtdofst_c[2] = { 0x1f, 0xf8 };
0074 static const u8 bw7_mrc_a[5] = { 0x36, 0xdb, 0x00, 0xa4, 0x92 };
0075 static const u8 bw7_mrc_b[5] = { 0x3e, 0x38, 0x00, 0xba, 0xaa };
0076 static const u8 bw7_mrc_c[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };
0077 static const u8 bw7_notch[4] = { 0xb8, 0x00, 0x00, 0x03 };
0078
0079 static const u8 bw6_nomi_ac[5] = { 0x1c, 0x00, 0x00, 0x00, 0x00};
0080 static const u8 bw6_nomi_b[5] = { 0x1b, 0x38, 0xe3, 0x8e, 0x38};
0081 static const u8 bw6_gtdofst_a[2] = { 0x1f, 0xf8 };
0082 static const u8 bw6_gtdofst_b[2] = { 0x24, 0x43 };
0083 static const u8 bw6_gtdofst_c[2] = { 0x25, 0x4c };
0084 static const u8 bw6_mrc_a[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };
0085 static const u8 bw6_mrc_b[5] = { 0x48, 0x97, 0x00, 0xd9, 0xc7 };
0086 static const u8 bw6_mrc_c[5] = { 0x4a, 0xaa, 0x00, 0xdf, 0xff };
0087 static const u8 bw6_notch[4] = { 0xbe, 0xab, 0x00, 0x03 };
0088
0089 static const u8 bw5_nomi_ac[5] = { 0x21, 0x99, 0x99, 0x99, 0x99};
0090 static const u8 bw5_nomi_b[5] = { 0x20, 0xaa, 0xaa, 0xaa, 0xaa};
0091 static const u8 bw5_gtdofst_a[2] = { 0x26, 0x5d };
0092 static const u8 bw5_gtdofst_b[2] = { 0x2b, 0x84 };
0093 static const u8 bw5_gtdofst_c[2] = { 0x2c, 0xc2 };
0094 static const u8 bw5_mrc_a[5] = { 0x4c, 0xcc, 0x00, 0xe6, 0x66 };
0095 static const u8 bw5_mrc_b[5] = { 0x57, 0x1c, 0x01, 0x05, 0x55 };
0096 static const u8 bw5_mrc_c[5] = { 0x59, 0x99, 0x01, 0x0c, 0xcc };
0097 static const u8 bw5_notch[4] = { 0xc8, 0x01, 0x00, 0x03 };
0098 const u8 *data = NULL;
0099 u8 sst_data;
0100 int ret;
0101
0102 if (!tnr_dmd)
0103 return -EINVAL;
0104
0105 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0106 CXD2880_IO_TGT_SYS,
0107 tune_dmd_setting_seq1,
0108 ARRAY_SIZE(tune_dmd_setting_seq1));
0109 if (ret)
0110 return ret;
0111
0112 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0113 CXD2880_IO_TGT_DMD,
0114 0x00, 0x04);
0115 if (ret)
0116 return ret;
0117
0118 switch (clk_mode) {
0119 case CXD2880_TNRDMD_CLOCKMODE_A:
0120 data = clk_mode_ckffrq_a;
0121 break;
0122 case CXD2880_TNRDMD_CLOCKMODE_B:
0123 data = clk_mode_ckffrq_b;
0124 break;
0125 case CXD2880_TNRDMD_CLOCKMODE_C:
0126 data = clk_mode_ckffrq_c;
0127 break;
0128 default:
0129 return -EINVAL;
0130 }
0131
0132 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0133 CXD2880_IO_TGT_DMD,
0134 0x65, data, 2);
0135 if (ret)
0136 return ret;
0137
0138 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0139 CXD2880_IO_TGT_DMD,
0140 0x5d, 0x07);
0141 if (ret)
0142 return ret;
0143
0144 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
0145 u8 data[2] = { 0x01, 0x01 };
0146
0147 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0148 CXD2880_IO_TGT_DMD,
0149 0x00, 0x00);
0150 if (ret)
0151 return ret;
0152
0153 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0154 CXD2880_IO_TGT_DMD,
0155 0xce, data, 2);
0156 if (ret)
0157 return ret;
0158 }
0159
0160 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0161 CXD2880_IO_TGT_DMD,
0162 tune_dmd_setting_seq2,
0163 ARRAY_SIZE(tune_dmd_setting_seq2));
0164 if (ret)
0165 return ret;
0166
0167 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0168 CXD2880_IO_TGT_DMD,
0169 0xf0, ratectl_margin, 2);
0170 if (ret)
0171 return ret;
0172
0173 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN ||
0174 tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
0175 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0176 CXD2880_IO_TGT_DMD,
0177 tune_dmd_setting_seq3,
0178 ARRAY_SIZE(tune_dmd_setting_seq3));
0179 if (ret)
0180 return ret;
0181 }
0182
0183 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
0184 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0185 CXD2880_IO_TGT_DMD,
0186 tune_dmd_setting_seq4,
0187 ARRAY_SIZE(tune_dmd_setting_seq4));
0188 if (ret)
0189 return ret;
0190 }
0191
0192 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
0193 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0194 CXD2880_IO_TGT_DMD,
0195 0x00, 0x04);
0196 if (ret)
0197 return ret;
0198
0199 switch (clk_mode) {
0200 case CXD2880_TNRDMD_CLOCKMODE_A:
0201 data = maxclkcnt_a;
0202 break;
0203 case CXD2880_TNRDMD_CLOCKMODE_B:
0204 data = maxclkcnt_b;
0205 break;
0206 case CXD2880_TNRDMD_CLOCKMODE_C:
0207 data = maxclkcnt_c;
0208 break;
0209 default:
0210 return -EINVAL;
0211 }
0212
0213 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0214 CXD2880_IO_TGT_DMD,
0215 0x68, data, 3);
0216 if (ret)
0217 return ret;
0218 }
0219
0220 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0221 CXD2880_IO_TGT_DMD,
0222 0x00, 0x04);
0223 if (ret)
0224 return ret;
0225
0226 switch (bandwidth) {
0227 case CXD2880_DTV_BW_8_MHZ:
0228 switch (clk_mode) {
0229 case CXD2880_TNRDMD_CLOCKMODE_A:
0230 case CXD2880_TNRDMD_CLOCKMODE_C:
0231 data = bw8_nomi_ac;
0232 break;
0233 case CXD2880_TNRDMD_CLOCKMODE_B:
0234 data = bw8_nomi_b;
0235 break;
0236 default:
0237 return -EINVAL;
0238 }
0239
0240 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0241 CXD2880_IO_TGT_DMD,
0242 0x60, data, 5);
0243 if (ret)
0244 return ret;
0245
0246 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0247 CXD2880_IO_TGT_DMD,
0248 0x4a, 0x00);
0249 if (ret)
0250 return ret;
0251
0252 switch (clk_mode) {
0253 case CXD2880_TNRDMD_CLOCKMODE_A:
0254 data = bw8_gtdofst_a;
0255 break;
0256 case CXD2880_TNRDMD_CLOCKMODE_B:
0257 data = bw8_gtdofst_b;
0258 break;
0259 case CXD2880_TNRDMD_CLOCKMODE_C:
0260 data = bw8_gtdofst_c;
0261 break;
0262 default:
0263 return -EINVAL;
0264 }
0265
0266 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0267 CXD2880_IO_TGT_DMD,
0268 0x7d, data, 2);
0269 if (ret)
0270 return ret;
0271
0272 switch (clk_mode) {
0273 case CXD2880_TNRDMD_CLOCKMODE_A:
0274 case CXD2880_TNRDMD_CLOCKMODE_B:
0275 sst_data = 0x35;
0276 break;
0277 case CXD2880_TNRDMD_CLOCKMODE_C:
0278 sst_data = 0x34;
0279 break;
0280 default:
0281 return -EINVAL;
0282 }
0283
0284 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0285 CXD2880_IO_TGT_DMD,
0286 0x71, sst_data);
0287 if (ret)
0288 return ret;
0289
0290 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0291 switch (clk_mode) {
0292 case CXD2880_TNRDMD_CLOCKMODE_A:
0293 data = bw8_mrc_a;
0294 break;
0295 case CXD2880_TNRDMD_CLOCKMODE_B:
0296 data = bw8_mrc_b;
0297 break;
0298 case CXD2880_TNRDMD_CLOCKMODE_C:
0299 data = bw8_mrc_c;
0300 break;
0301 default:
0302 return -EINVAL;
0303 }
0304
0305 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0306 CXD2880_IO_TGT_DMD,
0307 0x4b, &data[0], 2);
0308 if (ret)
0309 return ret;
0310
0311 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0312 CXD2880_IO_TGT_DMD,
0313 0x51, &data[2], 3);
0314 if (ret)
0315 return ret;
0316 }
0317
0318 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0319 CXD2880_IO_TGT_DMD,
0320 0x72, &bw8_notch[0], 2);
0321 if (ret)
0322 return ret;
0323
0324 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0325 CXD2880_IO_TGT_DMD,
0326 0x6b, &bw8_notch[2], 2);
0327 if (ret)
0328 return ret;
0329 break;
0330
0331 case CXD2880_DTV_BW_7_MHZ:
0332 switch (clk_mode) {
0333 case CXD2880_TNRDMD_CLOCKMODE_A:
0334 case CXD2880_TNRDMD_CLOCKMODE_C:
0335 data = bw7_nomi_ac;
0336 break;
0337 case CXD2880_TNRDMD_CLOCKMODE_B:
0338 data = bw7_nomi_b;
0339 break;
0340 default:
0341 return -EINVAL;
0342 }
0343
0344 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0345 CXD2880_IO_TGT_DMD,
0346 0x60, data, 5);
0347 if (ret)
0348 return ret;
0349
0350 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0351 CXD2880_IO_TGT_DMD,
0352 0x4a, 0x02);
0353 if (ret)
0354 return ret;
0355
0356 switch (clk_mode) {
0357 case CXD2880_TNRDMD_CLOCKMODE_A:
0358 data = bw7_gtdofst_a;
0359 break;
0360 case CXD2880_TNRDMD_CLOCKMODE_B:
0361 data = bw7_gtdofst_b;
0362 break;
0363 case CXD2880_TNRDMD_CLOCKMODE_C:
0364 data = bw7_gtdofst_c;
0365 break;
0366 default:
0367 return -EINVAL;
0368 }
0369
0370 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0371 CXD2880_IO_TGT_DMD,
0372 0x7d, data, 2);
0373 if (ret)
0374 return ret;
0375
0376 switch (clk_mode) {
0377 case CXD2880_TNRDMD_CLOCKMODE_A:
0378 case CXD2880_TNRDMD_CLOCKMODE_B:
0379 sst_data = 0x2f;
0380 break;
0381 case CXD2880_TNRDMD_CLOCKMODE_C:
0382 sst_data = 0x2e;
0383 break;
0384 default:
0385 return -EINVAL;
0386 }
0387
0388 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0389 CXD2880_IO_TGT_DMD,
0390 0x71, sst_data);
0391 if (ret)
0392 return ret;
0393
0394 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0395 switch (clk_mode) {
0396 case CXD2880_TNRDMD_CLOCKMODE_A:
0397 data = bw7_mrc_a;
0398 break;
0399 case CXD2880_TNRDMD_CLOCKMODE_B:
0400 data = bw7_mrc_b;
0401 break;
0402 case CXD2880_TNRDMD_CLOCKMODE_C:
0403 data = bw7_mrc_c;
0404 break;
0405 default:
0406 return -EINVAL;
0407 }
0408
0409 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0410 CXD2880_IO_TGT_DMD,
0411 0x4b, &data[0], 2);
0412 if (ret)
0413 return ret;
0414
0415 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0416 CXD2880_IO_TGT_DMD,
0417 0x51, &data[2], 3);
0418 if (ret)
0419 return ret;
0420 }
0421
0422 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0423 CXD2880_IO_TGT_DMD,
0424 0x72, &bw7_notch[0], 2);
0425 if (ret)
0426 return ret;
0427
0428 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0429 CXD2880_IO_TGT_DMD,
0430 0x6b, &bw7_notch[2], 2);
0431 if (ret)
0432 return ret;
0433 break;
0434
0435 case CXD2880_DTV_BW_6_MHZ:
0436 switch (clk_mode) {
0437 case CXD2880_TNRDMD_CLOCKMODE_A:
0438 case CXD2880_TNRDMD_CLOCKMODE_C:
0439 data = bw6_nomi_ac;
0440 break;
0441 case CXD2880_TNRDMD_CLOCKMODE_B:
0442 data = bw6_nomi_b;
0443 break;
0444 default:
0445 return -EINVAL;
0446 }
0447
0448 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0449 CXD2880_IO_TGT_DMD,
0450 0x60, data, 5);
0451 if (ret)
0452 return ret;
0453
0454 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0455 CXD2880_IO_TGT_DMD,
0456 0x4a, 0x04);
0457 if (ret)
0458 return ret;
0459
0460 switch (clk_mode) {
0461 case CXD2880_TNRDMD_CLOCKMODE_A:
0462 data = bw6_gtdofst_a;
0463 break;
0464 case CXD2880_TNRDMD_CLOCKMODE_B:
0465 data = bw6_gtdofst_b;
0466 break;
0467 case CXD2880_TNRDMD_CLOCKMODE_C:
0468 data = bw6_gtdofst_c;
0469 break;
0470 default:
0471 return -EINVAL;
0472 }
0473
0474 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0475 CXD2880_IO_TGT_DMD,
0476 0x7d, data, 2);
0477 if (ret)
0478 return ret;
0479
0480 switch (clk_mode) {
0481 case CXD2880_TNRDMD_CLOCKMODE_A:
0482 case CXD2880_TNRDMD_CLOCKMODE_C:
0483 sst_data = 0x29;
0484 break;
0485 case CXD2880_TNRDMD_CLOCKMODE_B:
0486 sst_data = 0x2a;
0487 break;
0488 default:
0489 return -EINVAL;
0490 }
0491
0492 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0493 CXD2880_IO_TGT_DMD,
0494 0x71, sst_data);
0495 if (ret)
0496 return ret;
0497
0498 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0499 switch (clk_mode) {
0500 case CXD2880_TNRDMD_CLOCKMODE_A:
0501 data = bw6_mrc_a;
0502 break;
0503 case CXD2880_TNRDMD_CLOCKMODE_B:
0504 data = bw6_mrc_b;
0505 break;
0506 case CXD2880_TNRDMD_CLOCKMODE_C:
0507 data = bw6_mrc_c;
0508 break;
0509 default:
0510 return -EINVAL;
0511 }
0512
0513 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0514 CXD2880_IO_TGT_DMD,
0515 0x4b, &data[0], 2);
0516 if (ret)
0517 return ret;
0518
0519 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0520 CXD2880_IO_TGT_DMD,
0521 0x51, &data[2], 3);
0522 if (ret)
0523 return ret;
0524 }
0525
0526 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0527 CXD2880_IO_TGT_DMD,
0528 0x72, &bw6_notch[0], 2);
0529 if (ret)
0530 return ret;
0531
0532 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0533 CXD2880_IO_TGT_DMD,
0534 0x6b, &bw6_notch[2], 2);
0535 if (ret)
0536 return ret;
0537 break;
0538
0539 case CXD2880_DTV_BW_5_MHZ:
0540 switch (clk_mode) {
0541 case CXD2880_TNRDMD_CLOCKMODE_A:
0542 case CXD2880_TNRDMD_CLOCKMODE_C:
0543 data = bw5_nomi_ac;
0544 break;
0545 case CXD2880_TNRDMD_CLOCKMODE_B:
0546 data = bw5_nomi_b;
0547 break;
0548 default:
0549 return -EINVAL;
0550 }
0551
0552 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0553 CXD2880_IO_TGT_DMD,
0554 0x60, data, 5);
0555 if (ret)
0556 return ret;
0557
0558 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0559 CXD2880_IO_TGT_DMD,
0560 0x4a, 0x06);
0561 if (ret)
0562 return ret;
0563
0564 switch (clk_mode) {
0565 case CXD2880_TNRDMD_CLOCKMODE_A:
0566 data = bw5_gtdofst_a;
0567 break;
0568 case CXD2880_TNRDMD_CLOCKMODE_B:
0569 data = bw5_gtdofst_b;
0570 break;
0571 case CXD2880_TNRDMD_CLOCKMODE_C:
0572 data = bw5_gtdofst_c;
0573 break;
0574 default:
0575 return -EINVAL;
0576 }
0577
0578 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0579 CXD2880_IO_TGT_DMD,
0580 0x7d, data, 2);
0581 if (ret)
0582 return ret;
0583
0584 switch (clk_mode) {
0585 case CXD2880_TNRDMD_CLOCKMODE_A:
0586 case CXD2880_TNRDMD_CLOCKMODE_B:
0587 sst_data = 0x24;
0588 break;
0589 case CXD2880_TNRDMD_CLOCKMODE_C:
0590 sst_data = 0x23;
0591 break;
0592 default:
0593 return -EINVAL;
0594 }
0595
0596 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0597 CXD2880_IO_TGT_DMD,
0598 0x71, sst_data);
0599 if (ret)
0600 return ret;
0601
0602 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0603 switch (clk_mode) {
0604 case CXD2880_TNRDMD_CLOCKMODE_A:
0605 data = bw5_mrc_a;
0606 break;
0607 case CXD2880_TNRDMD_CLOCKMODE_B:
0608 data = bw5_mrc_b;
0609 break;
0610 case CXD2880_TNRDMD_CLOCKMODE_C:
0611 data = bw5_mrc_c;
0612 break;
0613 default:
0614 return -EINVAL;
0615 }
0616
0617 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0618 CXD2880_IO_TGT_DMD,
0619 0x4b, &data[0], 2);
0620 if (ret)
0621 return ret;
0622
0623 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0624 CXD2880_IO_TGT_DMD,
0625 0x51, &data[2], 3);
0626 if (ret)
0627 return ret;
0628 }
0629
0630 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0631 CXD2880_IO_TGT_DMD,
0632 0x72, &bw5_notch[0], 2);
0633 if (ret)
0634 return ret;
0635
0636 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0637 CXD2880_IO_TGT_DMD,
0638 0x6b, &bw5_notch[2], 2);
0639 if (ret)
0640 return ret;
0641 break;
0642
0643 default:
0644 return -EINVAL;
0645 }
0646
0647 return cxd2880_io_write_multi_regs(tnr_dmd->io,
0648 CXD2880_IO_TGT_DMD,
0649 tune_dmd_setting_seq5,
0650 ARRAY_SIZE(tune_dmd_setting_seq5));
0651 }
0652
0653 static int x_sleep_dvbt_demod_setting(struct cxd2880_tnrdmd
0654 *tnr_dmd)
0655 {
0656 int ret;
0657
0658 if (!tnr_dmd)
0659 return -EINVAL;
0660
0661 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0662 CXD2880_IO_TGT_DMD,
0663 sleep_dmd_setting_seq1,
0664 ARRAY_SIZE(sleep_dmd_setting_seq1));
0665 if (ret)
0666 return ret;
0667
0668 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0669 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0670 CXD2880_IO_TGT_DMD,
0671 sleep_dmd_setting_seq2,
0672 ARRAY_SIZE(sleep_dmd_setting_seq2));
0673
0674 return ret;
0675 }
0676
0677 static int dvbt_set_profile(struct cxd2880_tnrdmd *tnr_dmd,
0678 enum cxd2880_dvbt_profile profile)
0679 {
0680 int ret;
0681
0682 if (!tnr_dmd)
0683 return -EINVAL;
0684
0685 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0686 CXD2880_IO_TGT_DMD,
0687 0x00, 0x10);
0688 if (ret)
0689 return ret;
0690
0691 return tnr_dmd->io->write_reg(tnr_dmd->io,
0692 CXD2880_IO_TGT_DMD,
0693 0x67,
0694 (profile == CXD2880_DVBT_PROFILE_HP)
0695 ? 0x00 : 0x01);
0696 }
0697
0698 int cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd,
0699 struct cxd2880_dvbt_tune_param
0700 *tune_param)
0701 {
0702 int ret;
0703
0704 if (!tnr_dmd || !tune_param)
0705 return -EINVAL;
0706
0707 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0708 return -EINVAL;
0709
0710 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
0711 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0712 return -EINVAL;
0713
0714 ret =
0715 cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT,
0716 tune_param->center_freq_khz,
0717 tune_param->bandwidth, 0, 0);
0718 if (ret)
0719 return ret;
0720
0721 ret =
0722 x_tune_dvbt_demod_setting(tnr_dmd, tune_param->bandwidth,
0723 tnr_dmd->clk_mode);
0724 if (ret)
0725 return ret;
0726
0727 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0728 ret =
0729 x_tune_dvbt_demod_setting(tnr_dmd->diver_sub,
0730 tune_param->bandwidth,
0731 tnr_dmd->diver_sub->clk_mode);
0732 if (ret)
0733 return ret;
0734 }
0735
0736 return dvbt_set_profile(tnr_dmd, tune_param->profile);
0737 }
0738
0739 int cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd,
0740 struct cxd2880_dvbt_tune_param
0741 *tune_param)
0742 {
0743 int ret;
0744
0745 if (!tnr_dmd || !tune_param)
0746 return -EINVAL;
0747
0748 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0749 return -EINVAL;
0750
0751 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
0752 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0753 return -EINVAL;
0754
0755 ret =
0756 cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, CXD2880_DTV_SYS_DVBT,
0757 0);
0758 if (ret)
0759 return ret;
0760
0761 tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;
0762 tnr_dmd->frequency_khz = tune_param->center_freq_khz;
0763 tnr_dmd->sys = CXD2880_DTV_SYS_DVBT;
0764 tnr_dmd->bandwidth = tune_param->bandwidth;
0765
0766 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0767 tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;
0768 tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;
0769 tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT;
0770 tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;
0771 }
0772
0773 return 0;
0774 }
0775
0776 int cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd *tnr_dmd)
0777 {
0778 int ret;
0779
0780 if (!tnr_dmd)
0781 return -EINVAL;
0782
0783 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0784 return -EINVAL;
0785
0786 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
0787 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0788 return -EINVAL;
0789
0790 ret = x_sleep_dvbt_demod_setting(tnr_dmd);
0791 if (ret)
0792 return ret;
0793
0794 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
0795 ret = x_sleep_dvbt_demod_setting(tnr_dmd->diver_sub);
0796
0797 return ret;
0798 }
0799
0800 int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
0801 *tnr_dmd,
0802 enum
0803 cxd2880_tnrdmd_lock_result
0804 *lock)
0805 {
0806 int ret;
0807
0808 u8 sync_stat = 0;
0809 u8 ts_lock = 0;
0810 u8 unlock_detected = 0;
0811 u8 unlock_detected_sub = 0;
0812
0813 if (!tnr_dmd || !lock)
0814 return -EINVAL;
0815
0816 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0817 return -EINVAL;
0818
0819 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0820 return -EINVAL;
0821
0822 ret =
0823 cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
0824 &unlock_detected);
0825 if (ret)
0826 return ret;
0827
0828 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
0829 if (sync_stat == 6)
0830 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
0831 else if (unlock_detected)
0832 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
0833 else
0834 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
0835
0836 return ret;
0837 }
0838
0839 if (sync_stat == 6) {
0840 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
0841 return ret;
0842 }
0843
0844 ret =
0845 cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
0846 &unlock_detected_sub);
0847 if (ret)
0848 return ret;
0849
0850 if (sync_stat == 6)
0851 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
0852 else if (unlock_detected && unlock_detected_sub)
0853 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
0854 else
0855 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
0856
0857 return ret;
0858 }
0859
0860 int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
0861 *tnr_dmd,
0862 enum
0863 cxd2880_tnrdmd_lock_result
0864 *lock)
0865 {
0866 int ret;
0867
0868 u8 sync_stat = 0;
0869 u8 ts_lock = 0;
0870 u8 unlock_detected = 0;
0871 u8 unlock_detected_sub = 0;
0872
0873 if (!tnr_dmd || !lock)
0874 return -EINVAL;
0875
0876 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0877 return -EINVAL;
0878
0879 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0880 return -EINVAL;
0881
0882 ret =
0883 cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
0884 &unlock_detected);
0885 if (ret)
0886 return ret;
0887
0888 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
0889 if (ts_lock)
0890 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
0891 else if (unlock_detected)
0892 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
0893 else
0894 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
0895
0896 return ret;
0897 }
0898
0899 if (ts_lock) {
0900 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
0901 return ret;
0902 } else if (!unlock_detected) {
0903 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
0904 return ret;
0905 }
0906
0907 ret =
0908 cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
0909 &unlock_detected_sub);
0910 if (ret)
0911 return ret;
0912
0913 if (unlock_detected && unlock_detected_sub)
0914 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
0915 else
0916 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
0917
0918 return ret;
0919 }