0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <media/dvb_frontend.h>
0011
0012 #include "cxd2880_tnrdmd_dvbt2.h"
0013 #include "cxd2880_tnrdmd_dvbt2_mon.h"
0014
0015 static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = {
0016 {0x00, 0x00}, {0x31, 0x02},
0017 };
0018
0019 static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = {
0020 {0x00, 0x04}, {0x5d, 0x0b},
0021 };
0022
0023 static int x_tune_dvbt2_demod_setting(struct cxd2880_tnrdmd
0024 *tnr_dmd,
0025 enum cxd2880_dtv_bandwidth
0026 bandwidth,
0027 enum cxd2880_tnrdmd_clockmode
0028 clk_mode)
0029 {
0030 static const u8 tsif_settings[2] = { 0x01, 0x01 };
0031 static const u8 init_settings[14] = {
0032 0x07, 0x06, 0x01, 0xf0, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x00,
0033 0x09, 0x9c, 0x0e, 0x4c
0034 };
0035 static const u8 clk_mode_settings_a1[9] = {
0036 0x52, 0x49, 0x2c, 0x51, 0x51, 0x3d, 0x15, 0x29, 0x0c
0037 };
0038
0039 static const u8 clk_mode_settings_b1[9] = {
0040 0x5d, 0x55, 0x32, 0x5c, 0x5c, 0x45, 0x17, 0x2e, 0x0d
0041 };
0042
0043 static const u8 clk_mode_settings_c1[9] = {
0044 0x60, 0x00, 0x34, 0x5e, 0x5e, 0x47, 0x18, 0x2f, 0x0e
0045 };
0046
0047 static const u8 clk_mode_settings_a2[13] = {
0048 0x04, 0xe7, 0x94, 0x92, 0x09, 0xcf, 0x7e, 0xd0, 0x49,
0049 0xcd, 0xcd, 0x1f, 0x5b
0050 };
0051
0052 static const u8 clk_mode_settings_b2[13] = {
0053 0x05, 0x90, 0x27, 0x55, 0x0b, 0x20, 0x8f, 0xd6, 0xea,
0054 0xc8, 0xc8, 0x23, 0x91
0055 };
0056
0057 static const u8 clk_mode_settings_c2[13] = {
0058 0x05, 0xb8, 0xd8, 0x00, 0x0b, 0x72, 0x93, 0xf3, 0x00,
0059 0xcd, 0xcd, 0x24, 0x95
0060 };
0061
0062 static const u8 clk_mode_settings_a3[5] = {
0063 0x0b, 0x6a, 0xc9, 0x03, 0x33
0064 };
0065 static const u8 clk_mode_settings_b3[5] = {
0066 0x01, 0x02, 0xe4, 0x03, 0x39
0067 };
0068 static const u8 clk_mode_settings_c3[5] = {
0069 0x01, 0x02, 0xeb, 0x03, 0x3b
0070 };
0071
0072 static const u8 gtdofst[2] = { 0x3f, 0xff };
0073
0074 static const u8 bw8_gtdofst_a[2] = { 0x19, 0xd2 };
0075 static const u8 bw8_nomi_ac[6] = { 0x15, 0x00, 0x00, 0x00, 0x00, 0x00 };
0076 static const u8 bw8_nomi_b[6] = { 0x14, 0x6a, 0xaa, 0xaa, 0xab, 0x00 };
0077 static const u8 bw8_sst_a[2] = { 0x06, 0x2a };
0078 static const u8 bw8_sst_b[2] = { 0x06, 0x29 };
0079 static const u8 bw8_sst_c[2] = { 0x06, 0x28 };
0080 static const u8 bw8_mrc_a[9] = {
0081 0x28, 0x00, 0x50, 0x00, 0x60, 0x00, 0x00, 0x90, 0x00
0082 };
0083 static const u8 bw8_mrc_b[9] = {
0084 0x2d, 0x5e, 0x5a, 0xbd, 0x6c, 0xe3, 0x00, 0xa3, 0x55
0085 };
0086 static const u8 bw8_mrc_c[9] = {
0087 0x2e, 0xaa, 0x5d, 0x55, 0x70, 0x00, 0x00, 0xa8, 0x00
0088 };
0089
0090 static const u8 bw7_nomi_ac[6] = { 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 };
0091 static const u8 bw7_nomi_b[6] = { 0x17, 0x55, 0x55, 0x55, 0x55, 0x00 };
0092 static const u8 bw7_sst_a[2] = { 0x06, 0x23 };
0093 static const u8 bw7_sst_b[2] = { 0x06, 0x22 };
0094 static const u8 bw7_sst_c[2] = { 0x06, 0x21 };
0095 static const u8 bw7_mrc_a[9] = {
0096 0x2d, 0xb6, 0x5b, 0x6d, 0x6d, 0xb6, 0x00, 0xa4, 0x92
0097 };
0098 static const u8 bw7_mrc_b[9] = {
0099 0x33, 0xda, 0x67, 0xb4, 0x7c, 0x71, 0x00, 0xba, 0xaa
0100 };
0101 static const u8 bw7_mrc_c[9] = {
0102 0x35, 0x55, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xc0, 0x00
0103 };
0104
0105 static const u8 bw6_nomi_ac[6] = { 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00 };
0106 static const u8 bw6_nomi_b[6] = { 0x1b, 0x38, 0xe3, 0x8e, 0x39, 0x00 };
0107 static const u8 bw6_sst_a[2] = { 0x06, 0x1c };
0108 static const u8 bw6_sst_b[2] = { 0x06, 0x1b };
0109 static const u8 bw6_sst_c[2] = { 0x06, 0x1a };
0110 static const u8 bw6_mrc_a[9] = {
0111 0x35, 0x55, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xc0, 0x00
0112 };
0113 static const u8 bw6_mrc_b[9] = {
0114 0x3c, 0x7e, 0x78, 0xfc, 0x91, 0x2f, 0x00, 0xd9, 0xc7
0115 };
0116 static const u8 bw6_mrc_c[9] = {
0117 0x3e, 0x38, 0x7c, 0x71, 0x95, 0x55, 0x00, 0xdf, 0xff
0118 };
0119
0120 static const u8 bw5_nomi_ac[6] = { 0x21, 0x99, 0x99, 0x99, 0x9a, 0x00 };
0121 static const u8 bw5_nomi_b[6] = { 0x20, 0xaa, 0xaa, 0xaa, 0xab, 0x00 };
0122 static const u8 bw5_sst_a[2] = { 0x06, 0x15 };
0123 static const u8 bw5_sst_b[2] = { 0x06, 0x15 };
0124 static const u8 bw5_sst_c[2] = { 0x06, 0x14 };
0125 static const u8 bw5_mrc_a[9] = {
0126 0x40, 0x00, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xe6, 0x66
0127 };
0128 static const u8 bw5_mrc_b[9] = {
0129 0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x01, 0x05, 0x55
0130 };
0131 static const u8 bw5_mrc_c[9] = {
0132 0x4a, 0xaa, 0x7c, 0x71, 0x95, 0x55, 0x01, 0x0c, 0xcc
0133 };
0134
0135 static const u8 bw1_7_nomi_a[6] = {
0136 0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03
0137 };
0138 static const u8 bw1_7_nomi_c[6] = {
0139 0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03
0140 };
0141 static const u8 bw1_7_nomi_b[6] = {
0142 0x65, 0x2b, 0xa4, 0xcd, 0xd8, 0x03
0143 };
0144 static const u8 bw1_7_sst_a[2] = { 0x06, 0x0c };
0145 static const u8 bw1_7_sst_b[2] = { 0x06, 0x0c };
0146 static const u8 bw1_7_sst_c[2] = { 0x06, 0x0b };
0147 static const u8 bw1_7_mrc_a[9] = {
0148 0x40, 0x00, 0x6a, 0xaa, 0x80, 0x00, 0x02, 0xc9, 0x8f
0149 };
0150 static const u8 bw1_7_mrc_b[9] = {
0151 0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x03, 0x29, 0x5d
0152 };
0153 static const u8 bw1_7_mrc_c[9] = {
0154 0x4a, 0xaa, 0x7c, 0x71, 0x95, 0x55, 0x03, 0x40, 0x7d
0155 };
0156
0157 const u8 *data = NULL;
0158 const u8 *data2 = NULL;
0159 const u8 *data3 = NULL;
0160 int ret;
0161
0162 if (!tnr_dmd)
0163 return -EINVAL;
0164
0165 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0166 CXD2880_IO_TGT_SYS,
0167 tune_dmd_setting_seq1,
0168 ARRAY_SIZE(tune_dmd_setting_seq1));
0169 if (ret)
0170 return ret;
0171
0172 ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
0173 CXD2880_IO_TGT_DMD,
0174 tune_dmd_setting_seq2,
0175 ARRAY_SIZE(tune_dmd_setting_seq2));
0176 if (ret)
0177 return ret;
0178
0179 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
0180 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0181 CXD2880_IO_TGT_DMD,
0182 0x00, 0x00);
0183 if (ret)
0184 return ret;
0185
0186 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0187 CXD2880_IO_TGT_DMD,
0188 0xce, tsif_settings, 2);
0189 if (ret)
0190 return ret;
0191 }
0192
0193 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0194 CXD2880_IO_TGT_DMD,
0195 0x00, 0x20);
0196 if (ret)
0197 return ret;
0198
0199 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0200 CXD2880_IO_TGT_DMD,
0201 0x8a, init_settings[0]);
0202 if (ret)
0203 return ret;
0204
0205 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0206 CXD2880_IO_TGT_DMD,
0207 0x90, init_settings[1]);
0208 if (ret)
0209 return ret;
0210
0211 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0212 CXD2880_IO_TGT_DMD,
0213 0x00, 0x25);
0214 if (ret)
0215 return ret;
0216
0217 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0218 CXD2880_IO_TGT_DMD,
0219 0xf0, &init_settings[2], 2);
0220 if (ret)
0221 return ret;
0222
0223 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0224 CXD2880_IO_TGT_DMD,
0225 0x00, 0x2a);
0226 if (ret)
0227 return ret;
0228
0229 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0230 CXD2880_IO_TGT_DMD,
0231 0xdc, init_settings[4]);
0232 if (ret)
0233 return ret;
0234
0235 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0236 CXD2880_IO_TGT_DMD,
0237 0xde, init_settings[5]);
0238 if (ret)
0239 return ret;
0240
0241 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0242 CXD2880_IO_TGT_DMD,
0243 0x00, 0x2d);
0244 if (ret)
0245 return ret;
0246
0247 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0248 CXD2880_IO_TGT_DMD,
0249 0x73, &init_settings[6], 4);
0250 if (ret)
0251 return ret;
0252
0253 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0254 CXD2880_IO_TGT_DMD,
0255 0x8f, &init_settings[10], 4);
0256 if (ret)
0257 return ret;
0258
0259 switch (clk_mode) {
0260 case CXD2880_TNRDMD_CLOCKMODE_A:
0261 data = clk_mode_settings_a1;
0262 data2 = clk_mode_settings_a2;
0263 data3 = clk_mode_settings_a3;
0264 break;
0265 case CXD2880_TNRDMD_CLOCKMODE_B:
0266 data = clk_mode_settings_b1;
0267 data2 = clk_mode_settings_b2;
0268 data3 = clk_mode_settings_b3;
0269 break;
0270 case CXD2880_TNRDMD_CLOCKMODE_C:
0271 data = clk_mode_settings_c1;
0272 data2 = clk_mode_settings_c2;
0273 data3 = clk_mode_settings_c3;
0274 break;
0275 default:
0276 return -EINVAL;
0277 }
0278
0279 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0280 CXD2880_IO_TGT_DMD,
0281 0x00, 0x04);
0282 if (ret)
0283 return ret;
0284
0285 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0286 CXD2880_IO_TGT_DMD,
0287 0x1d, &data[0], 3);
0288 if (ret)
0289 return ret;
0290
0291 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0292 CXD2880_IO_TGT_DMD,
0293 0x22, data[3]);
0294 if (ret)
0295 return ret;
0296
0297 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0298 CXD2880_IO_TGT_DMD,
0299 0x24, data[4]);
0300 if (ret)
0301 return ret;
0302
0303 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0304 CXD2880_IO_TGT_DMD,
0305 0x26, data[5]);
0306 if (ret)
0307 return ret;
0308
0309 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0310 CXD2880_IO_TGT_DMD,
0311 0x29, &data[6], 2);
0312 if (ret)
0313 return ret;
0314
0315 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0316 CXD2880_IO_TGT_DMD,
0317 0x2d, data[8]);
0318 if (ret)
0319 return ret;
0320
0321 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
0322 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0323 CXD2880_IO_TGT_DMD,
0324 0x2e, &data2[0], 6);
0325 if (ret)
0326 return ret;
0327
0328 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0329 CXD2880_IO_TGT_DMD,
0330 0x35, &data2[6], 7);
0331 if (ret)
0332 return ret;
0333 }
0334
0335 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0336 CXD2880_IO_TGT_DMD,
0337 0x3c, &data3[0], 2);
0338 if (ret)
0339 return ret;
0340
0341 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0342 CXD2880_IO_TGT_DMD,
0343 0x56, &data3[2], 3);
0344 if (ret)
0345 return ret;
0346
0347 switch (bandwidth) {
0348 case CXD2880_DTV_BW_8_MHZ:
0349 switch (clk_mode) {
0350 case CXD2880_TNRDMD_CLOCKMODE_A:
0351 case CXD2880_TNRDMD_CLOCKMODE_C:
0352 data = bw8_nomi_ac;
0353 break;
0354 case CXD2880_TNRDMD_CLOCKMODE_B:
0355 data = bw8_nomi_b;
0356 break;
0357 default:
0358 return -EINVAL;
0359 }
0360
0361 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0362 CXD2880_IO_TGT_DMD,
0363 0x10, data, 6);
0364 if (ret)
0365 return ret;
0366
0367 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0368 CXD2880_IO_TGT_DMD,
0369 0x4a, 0x00);
0370 if (ret)
0371 return ret;
0372
0373 switch (clk_mode) {
0374 case CXD2880_TNRDMD_CLOCKMODE_A:
0375 data = bw8_gtdofst_a;
0376 break;
0377 case CXD2880_TNRDMD_CLOCKMODE_B:
0378 case CXD2880_TNRDMD_CLOCKMODE_C:
0379 data = gtdofst;
0380 break;
0381 default:
0382 return -EINVAL;
0383 }
0384
0385 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0386 CXD2880_IO_TGT_DMD,
0387 0x19, data, 2);
0388 if (ret)
0389 return ret;
0390
0391 switch (clk_mode) {
0392 case CXD2880_TNRDMD_CLOCKMODE_A:
0393 data = bw8_sst_a;
0394 break;
0395 case CXD2880_TNRDMD_CLOCKMODE_B:
0396 data = bw8_sst_b;
0397 break;
0398 case CXD2880_TNRDMD_CLOCKMODE_C:
0399 data = bw8_sst_c;
0400 break;
0401 default:
0402 return -EINVAL;
0403 }
0404
0405 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0406 CXD2880_IO_TGT_DMD,
0407 0x1b, data, 2);
0408 if (ret)
0409 return ret;
0410
0411 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0412 switch (clk_mode) {
0413 case CXD2880_TNRDMD_CLOCKMODE_A:
0414 data = bw8_mrc_a;
0415 break;
0416 case CXD2880_TNRDMD_CLOCKMODE_B:
0417 data = bw8_mrc_b;
0418 break;
0419 case CXD2880_TNRDMD_CLOCKMODE_C:
0420 data = bw8_mrc_c;
0421 break;
0422 default:
0423 return -EINVAL;
0424 }
0425
0426 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0427 CXD2880_IO_TGT_DMD,
0428 0x4b, data, 9);
0429 if (ret)
0430 return ret;
0431 }
0432 break;
0433
0434 case CXD2880_DTV_BW_7_MHZ:
0435 switch (clk_mode) {
0436 case CXD2880_TNRDMD_CLOCKMODE_A:
0437 case CXD2880_TNRDMD_CLOCKMODE_C:
0438 data = bw7_nomi_ac;
0439 break;
0440 case CXD2880_TNRDMD_CLOCKMODE_B:
0441 data = bw7_nomi_b;
0442 break;
0443 default:
0444 return -EINVAL;
0445 }
0446
0447 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0448 CXD2880_IO_TGT_DMD,
0449 0x10, data, 6);
0450 if (ret)
0451 return ret;
0452
0453 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0454 CXD2880_IO_TGT_DMD,
0455 0x4a, 0x02);
0456 if (ret)
0457 return ret;
0458
0459 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0460 CXD2880_IO_TGT_DMD,
0461 0x19, gtdofst, 2);
0462 if (ret)
0463 return ret;
0464
0465 switch (clk_mode) {
0466 case CXD2880_TNRDMD_CLOCKMODE_A:
0467 data = bw7_sst_a;
0468 break;
0469 case CXD2880_TNRDMD_CLOCKMODE_B:
0470 data = bw7_sst_b;
0471 break;
0472 case CXD2880_TNRDMD_CLOCKMODE_C:
0473 data = bw7_sst_c;
0474 break;
0475 default:
0476 return -EINVAL;
0477 }
0478
0479 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0480 CXD2880_IO_TGT_DMD,
0481 0x1b, data, 2);
0482 if (ret)
0483 return ret;
0484
0485 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0486 switch (clk_mode) {
0487 case CXD2880_TNRDMD_CLOCKMODE_A:
0488 data = bw7_mrc_a;
0489 break;
0490 case CXD2880_TNRDMD_CLOCKMODE_B:
0491 data = bw7_mrc_b;
0492 break;
0493 case CXD2880_TNRDMD_CLOCKMODE_C:
0494 data = bw7_mrc_c;
0495 break;
0496 default:
0497 return -EINVAL;
0498 }
0499
0500 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0501 CXD2880_IO_TGT_DMD,
0502 0x4b, data, 9);
0503 if (ret)
0504 return ret;
0505 }
0506 break;
0507
0508 case CXD2880_DTV_BW_6_MHZ:
0509 switch (clk_mode) {
0510 case CXD2880_TNRDMD_CLOCKMODE_A:
0511 case CXD2880_TNRDMD_CLOCKMODE_C:
0512 data = bw6_nomi_ac;
0513 break;
0514 case CXD2880_TNRDMD_CLOCKMODE_B:
0515 data = bw6_nomi_b;
0516 break;
0517 default:
0518 return -EINVAL;
0519 }
0520
0521 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0522 CXD2880_IO_TGT_DMD,
0523 0x10, data, 6);
0524 if (ret)
0525 return ret;
0526
0527 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0528 CXD2880_IO_TGT_DMD,
0529 0x4a, 0x04);
0530 if (ret)
0531 return ret;
0532
0533 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0534 CXD2880_IO_TGT_DMD,
0535 0x19, gtdofst, 2);
0536 if (ret)
0537 return ret;
0538
0539 switch (clk_mode) {
0540 case CXD2880_TNRDMD_CLOCKMODE_A:
0541 data = bw6_sst_a;
0542 break;
0543 case CXD2880_TNRDMD_CLOCKMODE_B:
0544 data = bw6_sst_b;
0545 break;
0546 case CXD2880_TNRDMD_CLOCKMODE_C:
0547 data = bw6_sst_c;
0548 break;
0549 default:
0550 return -EINVAL;
0551 }
0552
0553 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0554 CXD2880_IO_TGT_DMD,
0555 0x1b, data, 2);
0556 if (ret)
0557 return ret;
0558
0559 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0560 switch (clk_mode) {
0561 case CXD2880_TNRDMD_CLOCKMODE_A:
0562 data = bw6_mrc_a;
0563 break;
0564 case CXD2880_TNRDMD_CLOCKMODE_B:
0565 data = bw6_mrc_b;
0566 break;
0567 case CXD2880_TNRDMD_CLOCKMODE_C:
0568 data = bw6_mrc_c;
0569 break;
0570 default:
0571 return -EINVAL;
0572 }
0573
0574 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0575 CXD2880_IO_TGT_DMD,
0576 0x4b, data, 9);
0577 if (ret)
0578 return ret;
0579 }
0580 break;
0581
0582 case CXD2880_DTV_BW_5_MHZ:
0583 switch (clk_mode) {
0584 case CXD2880_TNRDMD_CLOCKMODE_A:
0585 case CXD2880_TNRDMD_CLOCKMODE_C:
0586 data = bw5_nomi_ac;
0587 break;
0588 case CXD2880_TNRDMD_CLOCKMODE_B:
0589 data = bw5_nomi_b;
0590 break;
0591 default:
0592 return -EINVAL;
0593 }
0594
0595 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0596 CXD2880_IO_TGT_DMD,
0597 0x10, data, 6);
0598 if (ret)
0599 return ret;
0600
0601 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0602 CXD2880_IO_TGT_DMD,
0603 0x4a, 0x06);
0604 if (ret)
0605 return ret;
0606
0607 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0608 CXD2880_IO_TGT_DMD,
0609 0x19, gtdofst, 2);
0610 if (ret)
0611 return ret;
0612
0613 switch (clk_mode) {
0614 case CXD2880_TNRDMD_CLOCKMODE_A:
0615 data = bw5_sst_a;
0616 break;
0617 case CXD2880_TNRDMD_CLOCKMODE_B:
0618 data = bw5_sst_b;
0619 break;
0620 case CXD2880_TNRDMD_CLOCKMODE_C:
0621 data = bw5_sst_c;
0622 break;
0623 default:
0624 return -EINVAL;
0625 }
0626
0627 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0628 CXD2880_IO_TGT_DMD,
0629 0x1b, data, 2);
0630 if (ret)
0631 return ret;
0632
0633 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0634 switch (clk_mode) {
0635 case CXD2880_TNRDMD_CLOCKMODE_A:
0636 data = bw5_mrc_a;
0637 break;
0638 case CXD2880_TNRDMD_CLOCKMODE_B:
0639 data = bw5_mrc_b;
0640 break;
0641 case CXD2880_TNRDMD_CLOCKMODE_C:
0642 data = bw5_mrc_c;
0643 break;
0644 default:
0645 return -EINVAL;
0646 }
0647
0648 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0649 CXD2880_IO_TGT_DMD,
0650 0x4b, data, 9);
0651 if (ret)
0652 return ret;
0653 }
0654 break;
0655
0656 case CXD2880_DTV_BW_1_7_MHZ:
0657
0658 switch (clk_mode) {
0659 case CXD2880_TNRDMD_CLOCKMODE_A:
0660 data = bw1_7_nomi_a;
0661 break;
0662 case CXD2880_TNRDMD_CLOCKMODE_C:
0663 data = bw1_7_nomi_c;
0664 break;
0665 case CXD2880_TNRDMD_CLOCKMODE_B:
0666 data = bw1_7_nomi_b;
0667 break;
0668 default:
0669 return -EINVAL;
0670 }
0671
0672 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0673 CXD2880_IO_TGT_DMD,
0674 0x10, data, 6);
0675 if (ret)
0676 return ret;
0677
0678 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0679 CXD2880_IO_TGT_DMD,
0680 0x4a, 0x03);
0681 if (ret)
0682 return ret;
0683
0684 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0685 CXD2880_IO_TGT_DMD,
0686 0x19, gtdofst, 2);
0687 if (ret)
0688 return ret;
0689
0690 switch (clk_mode) {
0691 case CXD2880_TNRDMD_CLOCKMODE_A:
0692 data = bw1_7_sst_a;
0693 break;
0694 case CXD2880_TNRDMD_CLOCKMODE_B:
0695 data = bw1_7_sst_b;
0696 break;
0697 case CXD2880_TNRDMD_CLOCKMODE_C:
0698 data = bw1_7_sst_c;
0699 break;
0700 default:
0701 return -EINVAL;
0702 }
0703
0704 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0705 CXD2880_IO_TGT_DMD,
0706 0x1b, data, 2);
0707 if (ret)
0708 return ret;
0709
0710 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0711 switch (clk_mode) {
0712 case CXD2880_TNRDMD_CLOCKMODE_A:
0713 data = bw1_7_mrc_a;
0714 break;
0715 case CXD2880_TNRDMD_CLOCKMODE_B:
0716 data = bw1_7_mrc_b;
0717 break;
0718 case CXD2880_TNRDMD_CLOCKMODE_C:
0719 data = bw1_7_mrc_c;
0720 break;
0721 default:
0722 return -EINVAL;
0723 }
0724
0725 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0726 CXD2880_IO_TGT_DMD,
0727 0x4b, data, 9);
0728 if (ret)
0729 return ret;
0730 }
0731 break;
0732
0733 default:
0734 return -EINVAL;
0735 }
0736
0737 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0738 CXD2880_IO_TGT_DMD,
0739 0x00, 0x00);
0740 if (ret)
0741 return ret;
0742
0743 return tnr_dmd->io->write_reg(tnr_dmd->io,
0744 CXD2880_IO_TGT_DMD,
0745 0xfd, 0x01);
0746 }
0747
0748 static int x_sleep_dvbt2_demod_setting(struct cxd2880_tnrdmd
0749 *tnr_dmd)
0750 {
0751 static const u8 difint_clip[] = {
0752 0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32
0753 };
0754 int ret = 0;
0755
0756 if (!tnr_dmd)
0757 return -EINVAL;
0758
0759 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0760 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0761 CXD2880_IO_TGT_DMD,
0762 0x00, 0x1d);
0763 if (ret)
0764 return ret;
0765
0766 ret = tnr_dmd->io->write_regs(tnr_dmd->io,
0767 CXD2880_IO_TGT_DMD,
0768 0x47, difint_clip, 12);
0769 }
0770
0771 return ret;
0772 }
0773
0774 static int dvbt2_set_profile(struct cxd2880_tnrdmd *tnr_dmd,
0775 enum cxd2880_dvbt2_profile profile)
0776 {
0777 u8 t2_mode_tune_mode = 0;
0778 u8 seq_not2_dtime = 0;
0779 u8 dtime1 = 0;
0780 u8 dtime2 = 0;
0781 int ret;
0782
0783 if (!tnr_dmd)
0784 return -EINVAL;
0785
0786 switch (tnr_dmd->clk_mode) {
0787 case CXD2880_TNRDMD_CLOCKMODE_A:
0788 dtime1 = 0x27;
0789 dtime2 = 0x0c;
0790 break;
0791 case CXD2880_TNRDMD_CLOCKMODE_B:
0792 dtime1 = 0x2c;
0793 dtime2 = 0x0d;
0794 break;
0795 case CXD2880_TNRDMD_CLOCKMODE_C:
0796 dtime1 = 0x2e;
0797 dtime2 = 0x0e;
0798 break;
0799 default:
0800 return -EINVAL;
0801 }
0802
0803 switch (profile) {
0804 case CXD2880_DVBT2_PROFILE_BASE:
0805 t2_mode_tune_mode = 0x01;
0806 seq_not2_dtime = dtime2;
0807 break;
0808
0809 case CXD2880_DVBT2_PROFILE_LITE:
0810 t2_mode_tune_mode = 0x05;
0811 seq_not2_dtime = dtime1;
0812 break;
0813
0814 case CXD2880_DVBT2_PROFILE_ANY:
0815 t2_mode_tune_mode = 0x00;
0816 seq_not2_dtime = dtime1;
0817 break;
0818
0819 default:
0820 return -EINVAL;
0821 }
0822
0823 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0824 CXD2880_IO_TGT_DMD,
0825 0x00, 0x2e);
0826 if (ret)
0827 return ret;
0828
0829 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0830 CXD2880_IO_TGT_DMD,
0831 0x10, t2_mode_tune_mode);
0832 if (ret)
0833 return ret;
0834
0835 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
0836 CXD2880_IO_TGT_DMD,
0837 0x00, 0x04);
0838 if (ret)
0839 return ret;
0840
0841 return tnr_dmd->io->write_reg(tnr_dmd->io,
0842 CXD2880_IO_TGT_DMD,
0843 0x2c, seq_not2_dtime);
0844 }
0845
0846 int cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd,
0847 struct cxd2880_dvbt2_tune_param
0848 *tune_param)
0849 {
0850 int ret;
0851
0852 if (!tnr_dmd || !tune_param)
0853 return -EINVAL;
0854
0855 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0856 return -EINVAL;
0857
0858 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
0859 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0860 return -EINVAL;
0861
0862 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN &&
0863 tune_param->profile == CXD2880_DVBT2_PROFILE_ANY)
0864 return -ENOTTY;
0865
0866 ret =
0867 cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT2,
0868 tune_param->center_freq_khz,
0869 tune_param->bandwidth, 0, 0);
0870 if (ret)
0871 return ret;
0872
0873 ret =
0874 x_tune_dvbt2_demod_setting(tnr_dmd, tune_param->bandwidth,
0875 tnr_dmd->clk_mode);
0876 if (ret)
0877 return ret;
0878
0879 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0880 ret =
0881 x_tune_dvbt2_demod_setting(tnr_dmd->diver_sub,
0882 tune_param->bandwidth,
0883 tnr_dmd->diver_sub->clk_mode);
0884 if (ret)
0885 return ret;
0886 }
0887
0888 ret = dvbt2_set_profile(tnr_dmd, tune_param->profile);
0889 if (ret)
0890 return ret;
0891
0892 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0893 ret =
0894 dvbt2_set_profile(tnr_dmd->diver_sub, tune_param->profile);
0895 if (ret)
0896 return ret;
0897 }
0898
0899 if (tune_param->data_plp_id == CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO)
0900 ret = cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 1, 0);
0901 else
0902 ret =
0903 cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 0,
0904 (u8)(tune_param->data_plp_id));
0905
0906 return ret;
0907 }
0908
0909 int cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd,
0910 struct cxd2880_dvbt2_tune_param
0911 *tune_param)
0912 {
0913 u8 en_fef_intmtnt_ctrl = 1;
0914 int ret;
0915
0916 if (!tnr_dmd || !tune_param)
0917 return -EINVAL;
0918
0919 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0920 return -EINVAL;
0921
0922 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
0923 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0924 return -EINVAL;
0925
0926 switch (tune_param->profile) {
0927 case CXD2880_DVBT2_PROFILE_BASE:
0928 en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_base;
0929 break;
0930 case CXD2880_DVBT2_PROFILE_LITE:
0931 en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_lite;
0932 break;
0933 case CXD2880_DVBT2_PROFILE_ANY:
0934 if (tnr_dmd->en_fef_intmtnt_base &&
0935 tnr_dmd->en_fef_intmtnt_lite)
0936 en_fef_intmtnt_ctrl = 1;
0937 else
0938 en_fef_intmtnt_ctrl = 0;
0939 break;
0940 default:
0941 return -EINVAL;
0942 }
0943
0944 ret =
0945 cxd2880_tnrdmd_common_tune_setting2(tnr_dmd,
0946 CXD2880_DTV_SYS_DVBT2,
0947 en_fef_intmtnt_ctrl);
0948 if (ret)
0949 return ret;
0950
0951 tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;
0952 tnr_dmd->frequency_khz = tune_param->center_freq_khz;
0953 tnr_dmd->sys = CXD2880_DTV_SYS_DVBT2;
0954 tnr_dmd->bandwidth = tune_param->bandwidth;
0955
0956 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
0957 tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;
0958 tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;
0959 tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT2;
0960 tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;
0961 }
0962
0963 return 0;
0964 }
0965
0966 int cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd
0967 *tnr_dmd)
0968 {
0969 int ret;
0970
0971 if (!tnr_dmd)
0972 return -EINVAL;
0973
0974 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
0975 return -EINVAL;
0976
0977 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
0978 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
0979 return -EINVAL;
0980
0981 ret = x_sleep_dvbt2_demod_setting(tnr_dmd);
0982 if (ret)
0983 return ret;
0984
0985 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
0986 ret = x_sleep_dvbt2_demod_setting(tnr_dmd->diver_sub);
0987
0988 return ret;
0989 }
0990
0991 int cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
0992 *tnr_dmd,
0993 enum
0994 cxd2880_tnrdmd_lock_result
0995 *lock)
0996 {
0997 int ret;
0998
0999 u8 sync_stat = 0;
1000 u8 ts_lock = 0;
1001 u8 unlock_detected = 0;
1002 u8 unlock_detected_sub = 0;
1003
1004 if (!tnr_dmd || !lock)
1005 return -EINVAL;
1006
1007 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1008 return -EINVAL;
1009
1010 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1011 return -EINVAL;
1012
1013 ret =
1014 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
1015 &unlock_detected);
1016 if (ret)
1017 return ret;
1018
1019 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
1020 if (sync_stat == 6)
1021 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1022 else if (unlock_detected)
1023 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1024 else
1025 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1026
1027 return ret;
1028 }
1029
1030 if (sync_stat == 6) {
1031 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1032 return ret;
1033 }
1034
1035 ret =
1036 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,
1037 &unlock_detected_sub);
1038 if (ret)
1039 return ret;
1040
1041 if (sync_stat == 6)
1042 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1043 else if (unlock_detected && unlock_detected_sub)
1044 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1045 else
1046 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1047
1048 return ret;
1049 }
1050
1051 int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
1052 *tnr_dmd,
1053 enum
1054 cxd2880_tnrdmd_lock_result
1055 *lock)
1056 {
1057 int ret;
1058
1059 u8 sync_stat = 0;
1060 u8 ts_lock = 0;
1061 u8 unlock_detected = 0;
1062 u8 unlock_detected_sub = 0;
1063
1064 if (!tnr_dmd || !lock)
1065 return -EINVAL;
1066
1067 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1068 return -EINVAL;
1069
1070 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1071 return -EINVAL;
1072
1073 ret =
1074 cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
1075 &unlock_detected);
1076 if (ret)
1077 return ret;
1078
1079 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
1080 if (ts_lock)
1081 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1082 else if (unlock_detected)
1083 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1084 else
1085 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1086
1087 return ret;
1088 }
1089
1090 if (ts_lock) {
1091 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
1092 return ret;
1093 } else if (!unlock_detected) {
1094 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1095 return ret;
1096 }
1097
1098 ret =
1099 cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,
1100 &unlock_detected_sub);
1101 if (ret)
1102 return ret;
1103
1104 if (unlock_detected && unlock_detected_sub)
1105 *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
1106 else
1107 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
1108
1109 return ret;
1110 }
1111
1112 int cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd
1113 *tnr_dmd, u8 auto_plp,
1114 u8 plp_id)
1115 {
1116 int ret;
1117
1118 if (!tnr_dmd)
1119 return -EINVAL;
1120
1121 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1122 return -EINVAL;
1123
1124 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
1125 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1126 return -EINVAL;
1127
1128 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1129 CXD2880_IO_TGT_DMD,
1130 0x00, 0x23);
1131 if (ret)
1132 return ret;
1133
1134 if (!auto_plp) {
1135 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1136 CXD2880_IO_TGT_DMD,
1137 0xaf, plp_id);
1138 if (ret)
1139 return ret;
1140 }
1141
1142 return tnr_dmd->io->write_reg(tnr_dmd->io,
1143 CXD2880_IO_TGT_DMD,
1144 0xad, auto_plp ? 0x00 : 0x01);
1145 }
1146
1147 int cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd
1148 *tnr_dmd)
1149 {
1150 struct cxd2880_dvbt2_ofdm ofdm;
1151 static const u8 data[] = { 0, 8, 0, 16, 0, 32, 0, 64, 0, 128, 1, 0};
1152 int ret;
1153
1154 if (!tnr_dmd)
1155 return -EINVAL;
1156
1157 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1158 return -EINVAL;
1159
1160 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1161 return -EINVAL;
1162
1163 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE)
1164 return 0;
1165
1166 ret = cxd2880_tnrdmd_dvbt2_mon_ofdm(tnr_dmd, &ofdm);
1167 if (ret)
1168 return ret;
1169
1170 if (!ofdm.mixed)
1171 return 0;
1172
1173 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1174 CXD2880_IO_TGT_DMD,
1175 0x00, 0x1d);
1176 if (ret)
1177 return ret;
1178
1179 return tnr_dmd->io->write_regs(tnr_dmd->io,
1180 CXD2880_IO_TGT_DMD,
1181 0x47, data, 12);
1182 }
1183
1184 int cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd
1185 *tnr_dmd,
1186 u8 *l1_post_valid)
1187 {
1188 int ret;
1189
1190 u8 data;
1191
1192 if (!tnr_dmd || !l1_post_valid)
1193 return -EINVAL;
1194
1195 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
1196 return -EINVAL;
1197
1198 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
1199 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
1200 return -EINVAL;
1201
1202 ret = tnr_dmd->io->write_reg(tnr_dmd->io,
1203 CXD2880_IO_TGT_DMD,
1204 0x00, 0x0b);
1205 if (ret)
1206 return ret;
1207
1208 ret = tnr_dmd->io->read_regs(tnr_dmd->io,
1209 CXD2880_IO_TGT_DMD,
1210 0x86, &data, 1);
1211 if (ret)
1212 return ret;
1213
1214 *l1_post_valid = data & 0x01;
1215
1216 return ret;
1217 }