cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cxd2880_tnrdmd_dvbt.c (21576B)


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