linux/drivers/media/dvb-frontends/cxd2880/cxd2880_tnrdmd_dvbt2.c
<<
>>
Prefs
   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
  15static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = {
  16        {0x00, 0x00}, {0x31, 0x02},
  17};
  18
  19static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = {
  20        {0x00, 0x04}, {0x5d, 0x0b},
  21};
  22
  23static 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
 748static 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
 774static 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
 846int 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
 909int 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
 966int 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
 991int 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 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
1051int 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
1112int 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
1147int 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
1184int 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