Linux Audio

Check our new training course

Loading...
   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}
   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}