1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * cxd2880_tnrdmd_dvbt2.c 4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver 5 * control functions for DVB-T2 6 * 7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation 8 */ 9 10 #include <media/dvb_frontend.h> 11 12 #include "cxd2880_tnrdmd_dvbt2.h" 13 #include "cxd2880_tnrdmd_dvbt2_mon.h" 14 15 static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = { 16 {0x00, 0x00}, {0x31, 0x02}, 17 }; 18 19 static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = { 20 {0x00, 0x04}, {0x5d, 0x0b}, 21 }; 22 23 static int x_tune_dvbt2_demod_setting(struct cxd2880_tnrdmd 24 *tnr_dmd, 25 enum cxd2880_dtv_bandwidth 26 bandwidth, 27 enum cxd2880_tnrdmd_clockmode 28 clk_mode) 29 { 30 static const u8 tsif_settings[2] = { 0x01, 0x01 }; 31 static const u8 init_settings[14] = { 32 0x07, 0x06, 0x01, 0xf0, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x00, 33 0x09, 0x9c, 0x0e, 0x4c 34 }; 35 static const u8 clk_mode_settings_a1[9] = { 36 0x52, 0x49, 0x2c, 0x51, 0x51, 0x3d, 0x15, 0x29, 0x0c 37 }; 38 39 static const u8 clk_mode_settings_b1[9] = { 40 0x5d, 0x55, 0x32, 0x5c, 0x5c, 0x45, 0x17, 0x2e, 0x0d 41 }; 42 43 static const u8 clk_mode_settings_c1[9] = { 44 0x60, 0x00, 0x34, 0x5e, 0x5e, 0x47, 0x18, 0x2f, 0x0e 45 }; 46 47 static const u8 clk_mode_settings_a2[13] = { 48 0x04, 0xe7, 0x94, 0x92, 0x09, 0xcf, 0x7e, 0xd0, 0x49, 49 0xcd, 0xcd, 0x1f, 0x5b 50 }; 51 52 static const u8 clk_mode_settings_b2[13] = { 53 0x05, 0x90, 0x27, 0x55, 0x0b, 0x20, 0x8f, 0xd6, 0xea, 54 0xc8, 0xc8, 0x23, 0x91 55 }; 56 57 static const u8 clk_mode_settings_c2[13] = { 58 0x05, 0xb8, 0xd8, 0x00, 0x0b, 0x72, 0x93, 0xf3, 0x00, 59 0xcd, 0xcd, 0x24, 0x95 60 }; 61 62 static const u8 clk_mode_settings_a3[5] = { 63 0x0b, 0x6a, 0xc9, 0x03, 0x33 64 }; 65 static const u8 clk_mode_settings_b3[5] = { 66 0x01, 0x02, 0xe4, 0x03, 0x39 67 }; 68 static const u8 clk_mode_settings_c3[5] = { 69 0x01, 0x02, 0xeb, 0x03, 0x3b 70 }; 71 72 static const u8 gtdofst[2] = { 0x3f, 0xff }; 73 74 static const u8 bw8_gtdofst_a[2] = { 0x19, 0xd2 }; 75 static const u8 bw8_nomi_ac[6] = { 0x15, 0x00, 0x00, 0x00, 0x00, 0x00 }; 76 static const u8 bw8_nomi_b[6] = { 0x14, 0x6a, 0xaa, 0xaa, 0xab, 0x00 }; 77 static const u8 bw8_sst_a[2] = { 0x06, 0x2a }; 78 static const u8 bw8_sst_b[2] = { 0x06, 0x29 }; 79 static const u8 bw8_sst_c[2] = { 0x06, 0x28 }; 80 static const u8 bw8_mrc_a[9] = { 81 0x28, 0x00, 0x50, 0x00, 0x60, 0x00, 0x00, 0x90, 0x00 82 }; 83 static const u8 bw8_mrc_b[9] = { 84 0x2d, 0x5e, 0x5a, 0xbd, 0x6c, 0xe3, 0x00, 0xa3, 0x55 85 }; 86 static const u8 bw8_mrc_c[9] = { 87 0x2e, 0xaa, 0x5d, 0x55, 0x70, 0x00, 0x00, 0xa8, 0x00 88 }; 89 90 static const u8 bw7_nomi_ac[6] = { 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }; 91 static const u8 bw7_nomi_b[6] = { 0x17, 0x55, 0x55, 0x55, 0x55, 0x00 }; 92 static const u8 bw7_sst_a[2] = { 0x06, 0x23 }; 93 static const u8 bw7_sst_b[2] = { 0x06, 0x22 }; 94 static const u8 bw7_sst_c[2] = { 0x06, 0x21 }; 95 static const u8 bw7_mrc_a[9] = { 96 0x2d, 0xb6, 0x5b, 0x6d, 0x6d, 0xb6, 0x00, 0xa4, 0x92 97 }; 98 static const u8 bw7_mrc_b[9] = { 99 0x33, 0xda, 0x67, 0xb4, 0x7c, 0x71, 0x00, 0xba, 0xaa 100 }; 101 static const u8 bw7_mrc_c[9] = { 102 0x35, 0x55, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xc0, 0x00 103 }; 104 105 static const u8 bw6_nomi_ac[6] = { 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00 }; 106 static const u8 bw6_nomi_b[6] = { 0x1b, 0x38, 0xe3, 0x8e, 0x39, 0x00 }; 107 static const u8 bw6_sst_a[2] = { 0x06, 0x1c }; 108 static const u8 bw6_sst_b[2] = { 0x06, 0x1b }; 109 static const u8 bw6_sst_c[2] = { 0x06, 0x1a }; 110 static const u8 bw6_mrc_a[9] = { 111 0x35, 0x55, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xc0, 0x00 112 }; 113 static const u8 bw6_mrc_b[9] = { 114 0x3c, 0x7e, 0x78, 0xfc, 0x91, 0x2f, 0x00, 0xd9, 0xc7 115 }; 116 static const u8 bw6_mrc_c[9] = { 117 0x3e, 0x38, 0x7c, 0x71, 0x95, 0x55, 0x00, 0xdf, 0xff 118 }; 119 120 static const u8 bw5_nomi_ac[6] = { 0x21, 0x99, 0x99, 0x99, 0x9a, 0x00 }; 121 static const u8 bw5_nomi_b[6] = { 0x20, 0xaa, 0xaa, 0xaa, 0xab, 0x00 }; 122 static const u8 bw5_sst_a[2] = { 0x06, 0x15 }; 123 static const u8 bw5_sst_b[2] = { 0x06, 0x15 }; 124 static const u8 bw5_sst_c[2] = { 0x06, 0x14 }; 125 static const u8 bw5_mrc_a[9] = { 126 0x40, 0x00, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xe6, 0x66 127 }; 128 static const u8 bw5_mrc_b[9] = { 129 0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x01, 0x05, 0x55 130 }; 131 static const u8 bw5_mrc_c[9] = { 132 0x4a, 0xaa, 0x7c, 0x71, 0x95, 0x55, 0x01, 0x0c, 0xcc 133 }; 134 135 static const u8 bw1_7_nomi_a[6] = { 136 0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03 137 }; 138 static const u8 bw1_7_nomi_c[6] = { 139 0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03 140 }; 141 static const u8 bw1_7_nomi_b[6] = { 142 0x65, 0x2b, 0xa4, 0xcd, 0xd8, 0x03 143 }; 144 static const u8 bw1_7_sst_a[2] = { 0x06, 0x0c }; 145 static const u8 bw1_7_sst_b[2] = { 0x06, 0x0c }; 146 static const u8 bw1_7_sst_c[2] = { 0x06, 0x0b }; 147 static const u8 bw1_7_mrc_a[9] = { 148 0x40, 0x00, 0x6a, 0xaa, 0x80, 0x00, 0x02, 0xc9, 0x8f 149 }; 150 static const u8 bw1_7_mrc_b[9] = { 151 0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x03, 0x29, 0x5d 152 }; 153 static const u8 bw1_7_mrc_c[9] = { 154 0x4a, 0xaa, 0x7c, 0x71, 0x95, 0x55, 0x03, 0x40, 0x7d 155 }; 156 157 const u8 *data = NULL; 158 const u8 *data2 = NULL; 159 const u8 *data3 = NULL; 160 int ret; 161 162 if (!tnr_dmd) 163 return -EINVAL; 164 165 ret = cxd2880_io_write_multi_regs(tnr_dmd->io, 166 CXD2880_IO_TGT_SYS, 167 tune_dmd_setting_seq1, 168 ARRAY_SIZE(tune_dmd_setting_seq1)); 169 if (ret) 170 return ret; 171 172 ret = cxd2880_io_write_multi_regs(tnr_dmd->io, 173 CXD2880_IO_TGT_DMD, 174 tune_dmd_setting_seq2, 175 ARRAY_SIZE(tune_dmd_setting_seq2)); 176 if (ret) 177 return ret; 178 179 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) { 180 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 181 CXD2880_IO_TGT_DMD, 182 0x00, 0x00); 183 if (ret) 184 return ret; 185 186 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 187 CXD2880_IO_TGT_DMD, 188 0xce, tsif_settings, 2); 189 if (ret) 190 return ret; 191 } 192 193 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 194 CXD2880_IO_TGT_DMD, 195 0x00, 0x20); 196 if (ret) 197 return ret; 198 199 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 200 CXD2880_IO_TGT_DMD, 201 0x8a, init_settings[0]); 202 if (ret) 203 return ret; 204 205 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 206 CXD2880_IO_TGT_DMD, 207 0x90, init_settings[1]); 208 if (ret) 209 return ret; 210 211 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 212 CXD2880_IO_TGT_DMD, 213 0x00, 0x25); 214 if (ret) 215 return ret; 216 217 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 218 CXD2880_IO_TGT_DMD, 219 0xf0, &init_settings[2], 2); 220 if (ret) 221 return ret; 222 223 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 224 CXD2880_IO_TGT_DMD, 225 0x00, 0x2a); 226 if (ret) 227 return ret; 228 229 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 230 CXD2880_IO_TGT_DMD, 231 0xdc, init_settings[4]); 232 if (ret) 233 return ret; 234 235 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 236 CXD2880_IO_TGT_DMD, 237 0xde, init_settings[5]); 238 if (ret) 239 return ret; 240 241 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 242 CXD2880_IO_TGT_DMD, 243 0x00, 0x2d); 244 if (ret) 245 return ret; 246 247 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 248 CXD2880_IO_TGT_DMD, 249 0x73, &init_settings[6], 4); 250 if (ret) 251 return ret; 252 253 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 254 CXD2880_IO_TGT_DMD, 255 0x8f, &init_settings[10], 4); 256 if (ret) 257 return ret; 258 259 switch (clk_mode) { 260 case CXD2880_TNRDMD_CLOCKMODE_A: 261 data = clk_mode_settings_a1; 262 data2 = clk_mode_settings_a2; 263 data3 = clk_mode_settings_a3; 264 break; 265 case CXD2880_TNRDMD_CLOCKMODE_B: 266 data = clk_mode_settings_b1; 267 data2 = clk_mode_settings_b2; 268 data3 = clk_mode_settings_b3; 269 break; 270 case CXD2880_TNRDMD_CLOCKMODE_C: 271 data = clk_mode_settings_c1; 272 data2 = clk_mode_settings_c2; 273 data3 = clk_mode_settings_c3; 274 break; 275 default: 276 return -EINVAL; 277 } 278 279 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 280 CXD2880_IO_TGT_DMD, 281 0x00, 0x04); 282 if (ret) 283 return ret; 284 285 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 286 CXD2880_IO_TGT_DMD, 287 0x1d, &data[0], 3); 288 if (ret) 289 return ret; 290 291 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 292 CXD2880_IO_TGT_DMD, 293 0x22, data[3]); 294 if (ret) 295 return ret; 296 297 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 298 CXD2880_IO_TGT_DMD, 299 0x24, data[4]); 300 if (ret) 301 return ret; 302 303 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 304 CXD2880_IO_TGT_DMD, 305 0x26, data[5]); 306 if (ret) 307 return ret; 308 309 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 310 CXD2880_IO_TGT_DMD, 311 0x29, &data[6], 2); 312 if (ret) 313 return ret; 314 315 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 316 CXD2880_IO_TGT_DMD, 317 0x2d, data[8]); 318 if (ret) 319 return ret; 320 321 if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) { 322 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 323 CXD2880_IO_TGT_DMD, 324 0x2e, &data2[0], 6); 325 if (ret) 326 return ret; 327 328 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 329 CXD2880_IO_TGT_DMD, 330 0x35, &data2[6], 7); 331 if (ret) 332 return ret; 333 } 334 335 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 336 CXD2880_IO_TGT_DMD, 337 0x3c, &data3[0], 2); 338 if (ret) 339 return ret; 340 341 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 342 CXD2880_IO_TGT_DMD, 343 0x56, &data3[2], 3); 344 if (ret) 345 return ret; 346 347 switch (bandwidth) { 348 case CXD2880_DTV_BW_8_MHZ: 349 switch (clk_mode) { 350 case CXD2880_TNRDMD_CLOCKMODE_A: 351 case CXD2880_TNRDMD_CLOCKMODE_C: 352 data = bw8_nomi_ac; 353 break; 354 case CXD2880_TNRDMD_CLOCKMODE_B: 355 data = bw8_nomi_b; 356 break; 357 default: 358 return -EINVAL; 359 } 360 361 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 362 CXD2880_IO_TGT_DMD, 363 0x10, data, 6); 364 if (ret) 365 return ret; 366 367 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 368 CXD2880_IO_TGT_DMD, 369 0x4a, 0x00); 370 if (ret) 371 return ret; 372 373 switch (clk_mode) { 374 case CXD2880_TNRDMD_CLOCKMODE_A: 375 data = bw8_gtdofst_a; 376 break; 377 case CXD2880_TNRDMD_CLOCKMODE_B: 378 case CXD2880_TNRDMD_CLOCKMODE_C: 379 data = gtdofst; 380 break; 381 default: 382 return -EINVAL; 383 } 384 385 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 386 CXD2880_IO_TGT_DMD, 387 0x19, data, 2); 388 if (ret) 389 return ret; 390 391 switch (clk_mode) { 392 case CXD2880_TNRDMD_CLOCKMODE_A: 393 data = bw8_sst_a; 394 break; 395 case CXD2880_TNRDMD_CLOCKMODE_B: 396 data = bw8_sst_b; 397 break; 398 case CXD2880_TNRDMD_CLOCKMODE_C: 399 data = bw8_sst_c; 400 break; 401 default: 402 return -EINVAL; 403 } 404 405 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 406 CXD2880_IO_TGT_DMD, 407 0x1b, data, 2); 408 if (ret) 409 return ret; 410 411 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 412 switch (clk_mode) { 413 case CXD2880_TNRDMD_CLOCKMODE_A: 414 data = bw8_mrc_a; 415 break; 416 case CXD2880_TNRDMD_CLOCKMODE_B: 417 data = bw8_mrc_b; 418 break; 419 case CXD2880_TNRDMD_CLOCKMODE_C: 420 data = bw8_mrc_c; 421 break; 422 default: 423 return -EINVAL; 424 } 425 426 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 427 CXD2880_IO_TGT_DMD, 428 0x4b, data, 9); 429 if (ret) 430 return ret; 431 } 432 break; 433 434 case CXD2880_DTV_BW_7_MHZ: 435 switch (clk_mode) { 436 case CXD2880_TNRDMD_CLOCKMODE_A: 437 case CXD2880_TNRDMD_CLOCKMODE_C: 438 data = bw7_nomi_ac; 439 break; 440 case CXD2880_TNRDMD_CLOCKMODE_B: 441 data = bw7_nomi_b; 442 break; 443 default: 444 return -EINVAL; 445 } 446 447 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 448 CXD2880_IO_TGT_DMD, 449 0x10, data, 6); 450 if (ret) 451 return ret; 452 453 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 454 CXD2880_IO_TGT_DMD, 455 0x4a, 0x02); 456 if (ret) 457 return ret; 458 459 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 460 CXD2880_IO_TGT_DMD, 461 0x19, gtdofst, 2); 462 if (ret) 463 return ret; 464 465 switch (clk_mode) { 466 case CXD2880_TNRDMD_CLOCKMODE_A: 467 data = bw7_sst_a; 468 break; 469 case CXD2880_TNRDMD_CLOCKMODE_B: 470 data = bw7_sst_b; 471 break; 472 case CXD2880_TNRDMD_CLOCKMODE_C: 473 data = bw7_sst_c; 474 break; 475 default: 476 return -EINVAL; 477 } 478 479 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 480 CXD2880_IO_TGT_DMD, 481 0x1b, data, 2); 482 if (ret) 483 return ret; 484 485 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 486 switch (clk_mode) { 487 case CXD2880_TNRDMD_CLOCKMODE_A: 488 data = bw7_mrc_a; 489 break; 490 case CXD2880_TNRDMD_CLOCKMODE_B: 491 data = bw7_mrc_b; 492 break; 493 case CXD2880_TNRDMD_CLOCKMODE_C: 494 data = bw7_mrc_c; 495 break; 496 default: 497 return -EINVAL; 498 } 499 500 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 501 CXD2880_IO_TGT_DMD, 502 0x4b, data, 9); 503 if (ret) 504 return ret; 505 } 506 break; 507 508 case CXD2880_DTV_BW_6_MHZ: 509 switch (clk_mode) { 510 case CXD2880_TNRDMD_CLOCKMODE_A: 511 case CXD2880_TNRDMD_CLOCKMODE_C: 512 data = bw6_nomi_ac; 513 break; 514 case CXD2880_TNRDMD_CLOCKMODE_B: 515 data = bw6_nomi_b; 516 break; 517 default: 518 return -EINVAL; 519 } 520 521 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 522 CXD2880_IO_TGT_DMD, 523 0x10, data, 6); 524 if (ret) 525 return ret; 526 527 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 528 CXD2880_IO_TGT_DMD, 529 0x4a, 0x04); 530 if (ret) 531 return ret; 532 533 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 534 CXD2880_IO_TGT_DMD, 535 0x19, gtdofst, 2); 536 if (ret) 537 return ret; 538 539 switch (clk_mode) { 540 case CXD2880_TNRDMD_CLOCKMODE_A: 541 data = bw6_sst_a; 542 break; 543 case CXD2880_TNRDMD_CLOCKMODE_B: 544 data = bw6_sst_b; 545 break; 546 case CXD2880_TNRDMD_CLOCKMODE_C: 547 data = bw6_sst_c; 548 break; 549 default: 550 return -EINVAL; 551 } 552 553 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 554 CXD2880_IO_TGT_DMD, 555 0x1b, data, 2); 556 if (ret) 557 return ret; 558 559 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 560 switch (clk_mode) { 561 case CXD2880_TNRDMD_CLOCKMODE_A: 562 data = bw6_mrc_a; 563 break; 564 case CXD2880_TNRDMD_CLOCKMODE_B: 565 data = bw6_mrc_b; 566 break; 567 case CXD2880_TNRDMD_CLOCKMODE_C: 568 data = bw6_mrc_c; 569 break; 570 default: 571 return -EINVAL; 572 } 573 574 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 575 CXD2880_IO_TGT_DMD, 576 0x4b, data, 9); 577 if (ret) 578 return ret; 579 } 580 break; 581 582 case CXD2880_DTV_BW_5_MHZ: 583 switch (clk_mode) { 584 case CXD2880_TNRDMD_CLOCKMODE_A: 585 case CXD2880_TNRDMD_CLOCKMODE_C: 586 data = bw5_nomi_ac; 587 break; 588 case CXD2880_TNRDMD_CLOCKMODE_B: 589 data = bw5_nomi_b; 590 break; 591 default: 592 return -EINVAL; 593 } 594 595 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 596 CXD2880_IO_TGT_DMD, 597 0x10, data, 6); 598 if (ret) 599 return ret; 600 601 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 602 CXD2880_IO_TGT_DMD, 603 0x4a, 0x06); 604 if (ret) 605 return ret; 606 607 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 608 CXD2880_IO_TGT_DMD, 609 0x19, gtdofst, 2); 610 if (ret) 611 return ret; 612 613 switch (clk_mode) { 614 case CXD2880_TNRDMD_CLOCKMODE_A: 615 data = bw5_sst_a; 616 break; 617 case CXD2880_TNRDMD_CLOCKMODE_B: 618 data = bw5_sst_b; 619 break; 620 case CXD2880_TNRDMD_CLOCKMODE_C: 621 data = bw5_sst_c; 622 break; 623 default: 624 return -EINVAL; 625 } 626 627 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 628 CXD2880_IO_TGT_DMD, 629 0x1b, data, 2); 630 if (ret) 631 return ret; 632 633 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 634 switch (clk_mode) { 635 case CXD2880_TNRDMD_CLOCKMODE_A: 636 data = bw5_mrc_a; 637 break; 638 case CXD2880_TNRDMD_CLOCKMODE_B: 639 data = bw5_mrc_b; 640 break; 641 case CXD2880_TNRDMD_CLOCKMODE_C: 642 data = bw5_mrc_c; 643 break; 644 default: 645 return -EINVAL; 646 } 647 648 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 649 CXD2880_IO_TGT_DMD, 650 0x4b, data, 9); 651 if (ret) 652 return ret; 653 } 654 break; 655 656 case CXD2880_DTV_BW_1_7_MHZ: 657 658 switch (clk_mode) { 659 case CXD2880_TNRDMD_CLOCKMODE_A: 660 data = bw1_7_nomi_a; 661 break; 662 case CXD2880_TNRDMD_CLOCKMODE_C: 663 data = bw1_7_nomi_c; 664 break; 665 case CXD2880_TNRDMD_CLOCKMODE_B: 666 data = bw1_7_nomi_b; 667 break; 668 default: 669 return -EINVAL; 670 } 671 672 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 673 CXD2880_IO_TGT_DMD, 674 0x10, data, 6); 675 if (ret) 676 return ret; 677 678 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 679 CXD2880_IO_TGT_DMD, 680 0x4a, 0x03); 681 if (ret) 682 return ret; 683 684 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 685 CXD2880_IO_TGT_DMD, 686 0x19, gtdofst, 2); 687 if (ret) 688 return ret; 689 690 switch (clk_mode) { 691 case CXD2880_TNRDMD_CLOCKMODE_A: 692 data = bw1_7_sst_a; 693 break; 694 case CXD2880_TNRDMD_CLOCKMODE_B: 695 data = bw1_7_sst_b; 696 break; 697 case CXD2880_TNRDMD_CLOCKMODE_C: 698 data = bw1_7_sst_c; 699 break; 700 default: 701 return -EINVAL; 702 } 703 704 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 705 CXD2880_IO_TGT_DMD, 706 0x1b, data, 2); 707 if (ret) 708 return ret; 709 710 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 711 switch (clk_mode) { 712 case CXD2880_TNRDMD_CLOCKMODE_A: 713 data = bw1_7_mrc_a; 714 break; 715 case CXD2880_TNRDMD_CLOCKMODE_B: 716 data = bw1_7_mrc_b; 717 break; 718 case CXD2880_TNRDMD_CLOCKMODE_C: 719 data = bw1_7_mrc_c; 720 break; 721 default: 722 return -EINVAL; 723 } 724 725 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 726 CXD2880_IO_TGT_DMD, 727 0x4b, data, 9); 728 if (ret) 729 return ret; 730 } 731 break; 732 733 default: 734 return -EINVAL; 735 } 736 737 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 738 CXD2880_IO_TGT_DMD, 739 0x00, 0x00); 740 if (ret) 741 return ret; 742 743 return tnr_dmd->io->write_reg(tnr_dmd->io, 744 CXD2880_IO_TGT_DMD, 745 0xfd, 0x01); 746 } 747 748 static int x_sleep_dvbt2_demod_setting(struct cxd2880_tnrdmd 749 *tnr_dmd) 750 { 751 static const u8 difint_clip[] = { 752 0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32 753 }; 754 int ret = 0; 755 756 if (!tnr_dmd) 757 return -EINVAL; 758 759 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 760 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 761 CXD2880_IO_TGT_DMD, 762 0x00, 0x1d); 763 if (ret) 764 return ret; 765 766 ret = tnr_dmd->io->write_regs(tnr_dmd->io, 767 CXD2880_IO_TGT_DMD, 768 0x47, difint_clip, 12); 769 } 770 771 return ret; 772 } 773 774 static int dvbt2_set_profile(struct cxd2880_tnrdmd *tnr_dmd, 775 enum cxd2880_dvbt2_profile profile) 776 { 777 u8 t2_mode_tune_mode = 0; 778 u8 seq_not2_dtime = 0; 779 u8 dtime1 = 0; 780 u8 dtime2 = 0; 781 int ret; 782 783 if (!tnr_dmd) 784 return -EINVAL; 785 786 switch (tnr_dmd->clk_mode) { 787 case CXD2880_TNRDMD_CLOCKMODE_A: 788 dtime1 = 0x27; 789 dtime2 = 0x0c; 790 break; 791 case CXD2880_TNRDMD_CLOCKMODE_B: 792 dtime1 = 0x2c; 793 dtime2 = 0x0d; 794 break; 795 case CXD2880_TNRDMD_CLOCKMODE_C: 796 dtime1 = 0x2e; 797 dtime2 = 0x0e; 798 break; 799 default: 800 return -EINVAL; 801 } 802 803 switch (profile) { 804 case CXD2880_DVBT2_PROFILE_BASE: 805 t2_mode_tune_mode = 0x01; 806 seq_not2_dtime = dtime2; 807 break; 808 809 case CXD2880_DVBT2_PROFILE_LITE: 810 t2_mode_tune_mode = 0x05; 811 seq_not2_dtime = dtime1; 812 break; 813 814 case CXD2880_DVBT2_PROFILE_ANY: 815 t2_mode_tune_mode = 0x00; 816 seq_not2_dtime = dtime1; 817 break; 818 819 default: 820 return -EINVAL; 821 } 822 823 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 824 CXD2880_IO_TGT_DMD, 825 0x00, 0x2e); 826 if (ret) 827 return ret; 828 829 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 830 CXD2880_IO_TGT_DMD, 831 0x10, t2_mode_tune_mode); 832 if (ret) 833 return ret; 834 835 ret = tnr_dmd->io->write_reg(tnr_dmd->io, 836 CXD2880_IO_TGT_DMD, 837 0x00, 0x04); 838 if (ret) 839 return ret; 840 841 return tnr_dmd->io->write_reg(tnr_dmd->io, 842 CXD2880_IO_TGT_DMD, 843 0x2c, seq_not2_dtime); 844 } 845 846 int cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd, 847 struct cxd2880_dvbt2_tune_param 848 *tune_param) 849 { 850 int ret; 851 852 if (!tnr_dmd || !tune_param) 853 return -EINVAL; 854 855 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) 856 return -EINVAL; 857 858 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP && 859 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) 860 return -EINVAL; 861 862 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN && 863 tune_param->profile == CXD2880_DVBT2_PROFILE_ANY) 864 return -ENOTTY; 865 866 ret = 867 cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT2, 868 tune_param->center_freq_khz, 869 tune_param->bandwidth, 0, 0); 870 if (ret) 871 return ret; 872 873 ret = 874 x_tune_dvbt2_demod_setting(tnr_dmd, tune_param->bandwidth, 875 tnr_dmd->clk_mode); 876 if (ret) 877 return ret; 878 879 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 880 ret = 881 x_tune_dvbt2_demod_setting(tnr_dmd->diver_sub, 882 tune_param->bandwidth, 883 tnr_dmd->diver_sub->clk_mode); 884 if (ret) 885 return ret; 886 } 887 888 ret = dvbt2_set_profile(tnr_dmd, tune_param->profile); 889 if (ret) 890 return ret; 891 892 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 893 ret = 894 dvbt2_set_profile(tnr_dmd->diver_sub, tune_param->profile); 895 if (ret) 896 return ret; 897 } 898 899 if (tune_param->data_plp_id == CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO) 900 ret = cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 1, 0); 901 else 902 ret = 903 cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 0, 904 (u8)(tune_param->data_plp_id)); 905 906 return ret; 907 } 908 909 int cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd, 910 struct cxd2880_dvbt2_tune_param 911 *tune_param) 912 { 913 u8 en_fef_intmtnt_ctrl = 1; 914 int ret; 915 916 if (!tnr_dmd || !tune_param) 917 return -EINVAL; 918 919 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) 920 return -EINVAL; 921 922 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP && 923 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) 924 return -EINVAL; 925 926 switch (tune_param->profile) { 927 case CXD2880_DVBT2_PROFILE_BASE: 928 en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_base; 929 break; 930 case CXD2880_DVBT2_PROFILE_LITE: 931 en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_lite; 932 break; 933 case CXD2880_DVBT2_PROFILE_ANY: 934 if (tnr_dmd->en_fef_intmtnt_base && 935 tnr_dmd->en_fef_intmtnt_lite) 936 en_fef_intmtnt_ctrl = 1; 937 else 938 en_fef_intmtnt_ctrl = 0; 939 break; 940 default: 941 return -EINVAL; 942 } 943 944 ret = 945 cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, 946 CXD2880_DTV_SYS_DVBT2, 947 en_fef_intmtnt_ctrl); 948 if (ret) 949 return ret; 950 951 tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE; 952 tnr_dmd->frequency_khz = tune_param->center_freq_khz; 953 tnr_dmd->sys = CXD2880_DTV_SYS_DVBT2; 954 tnr_dmd->bandwidth = tune_param->bandwidth; 955 956 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) { 957 tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE; 958 tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz; 959 tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT2; 960 tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth; 961 } 962 963 return 0; 964 } 965 966 int cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd 967 *tnr_dmd) 968 { 969 int ret; 970 971 if (!tnr_dmd) 972 return -EINVAL; 973 974 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) 975 return -EINVAL; 976 977 if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP && 978 tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) 979 return -EINVAL; 980 981 ret = x_sleep_dvbt2_demod_setting(tnr_dmd); 982 if (ret) 983 return ret; 984 985 if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) 986 ret = x_sleep_dvbt2_demod_setting(tnr_dmd->diver_sub); 987 988 return ret; 989 } 990 991 int cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd 992 *tnr_dmd, 993 enum 994 cxd2880_tnrdmd_lock_result 995 *lock) 996 { 997 int ret; 998 999 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 0; 1028 } 1029 1030 if (sync_stat == 6) { 1031 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; 1032 return 0; 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 0; 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 0; 1088 } 1089 1090 if (ts_lock) { 1091 *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED; 1092 return 0; 1093 } else if (!unlock_detected) { 1094 *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT; 1095 return 0; 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 0; 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 } 1218