brintos

brintos / linux-shallow public Read only

0
0
Text · 26.8 KiB · a9ab983 Raw
1218 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * cxd2880_tnrdmd_dvbt2.c4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver5 * control functions for DVB-T26 *7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation8 */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_tnrdmd24				      *tnr_dmd,25				      enum cxd2880_dtv_bandwidth26				      bandwidth,27				      enum cxd2880_tnrdmd_clockmode28				      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, 0x4c34	};35	static const u8 clk_mode_settings_a1[9] = {36		0x52, 0x49, 0x2c, 0x51,	0x51, 0x3d, 0x15, 0x29, 0x0c37	};38 39	static const u8 clk_mode_settings_b1[9] = {40		0x5d, 0x55, 0x32, 0x5c,	0x5c, 0x45, 0x17, 0x2e, 0x0d41	};42 43	static const u8 clk_mode_settings_c1[9] = {44		0x60, 0x00, 0x34, 0x5e,	0x5e, 0x47, 0x18, 0x2f, 0x0e45	};46 47	static const u8 clk_mode_settings_a2[13] = {48		0x04, 0xe7, 0x94, 0x92,	0x09, 0xcf, 0x7e, 0xd0, 0x49,49		0xcd, 0xcd, 0x1f, 0x5b50	};51 52	static const u8 clk_mode_settings_b2[13] = {53		0x05, 0x90, 0x27, 0x55,	0x0b, 0x20, 0x8f, 0xd6, 0xea,54		0xc8, 0xc8, 0x23, 0x9155	};56 57	static const u8 clk_mode_settings_c2[13] = {58		0x05, 0xb8, 0xd8, 0x00,	0x0b, 0x72, 0x93, 0xf3, 0x00,59		0xcd, 0xcd, 0x24, 0x9560	};61 62	static const u8 clk_mode_settings_a3[5] = {63		0x0b, 0x6a, 0xc9, 0x03, 0x3364	};65	static const u8 clk_mode_settings_b3[5] = {66		0x01, 0x02, 0xe4, 0x03, 0x3967	};68	static const u8 clk_mode_settings_c3[5] = {69		0x01, 0x02, 0xeb, 0x03, 0x3b70	};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, 0x0082	};83	static const u8 bw8_mrc_b[9] = {84		0x2d, 0x5e, 0x5a, 0xbd, 0x6c, 0xe3, 0x00, 0xa3, 0x5585	};86	static const u8 bw8_mrc_c[9] = {87		0x2e, 0xaa, 0x5d, 0x55, 0x70, 0x00, 0x00, 0xa8, 0x0088	};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, 0x9297	};98	static const u8 bw7_mrc_b[9] = {99		0x33, 0xda, 0x67, 0xb4,	0x7c, 0x71, 0x00, 0xba, 0xaa100	};101	static const u8 bw7_mrc_c[9] = {102		0x35, 0x55, 0x6a, 0xaa,	0x80, 0x00, 0x00, 0xc0, 0x00103	};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, 0x00112	};113	static const u8 bw6_mrc_b[9] = {114		0x3c, 0x7e, 0x78, 0xfc,	0x91, 0x2f, 0x00, 0xd9, 0xc7115	};116	static const u8 bw6_mrc_c[9] = {117		0x3e, 0x38, 0x7c, 0x71,	0x95, 0x55, 0x00, 0xdf, 0xff118	};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, 0x66127	};128	static const u8 bw5_mrc_b[9] = {129		0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x01, 0x05, 0x55130	};131	static const u8 bw5_mrc_c[9] = {132		0x4a, 0xaa, 0x7c, 0x71, 0x95, 0x55, 0x01, 0x0c, 0xcc133	};134 135	static const u8 bw1_7_nomi_a[6] = {136		0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03137	};138	static const u8 bw1_7_nomi_c[6] = {139		0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03140	};141	static const u8 bw1_7_nomi_b[6] = {142		0x65, 0x2b, 0xa4, 0xcd, 0xd8, 0x03143	};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, 0x8f149	};150	static const u8 bw1_7_mrc_b[9] = {151		0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x03, 0x29, 0x5d152	};153	static const u8 bw1_7_mrc_c[9] = {154		0x4a, 0xaa, 0x7c, 0x71,	0x95, 0x55, 0x03, 0x40, 0x7d155	};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_tnrdmd749				       *tnr_dmd)750{751	static const u8 difint_clip[] = {752		0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32753	};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_param848			       *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	else902		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_param911			       *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		else938			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_tnrdmd967				       *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_tnrdmd992					  *tnr_dmd,993					  enum994					  cxd2880_tnrdmd_lock_result995					  *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		else1025			*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;1026 1027		return 0;1028	}1029 1030	if (sync_stat == 6) {1031		*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;1032		return 0;1033	}1034 1035	ret =1036	    cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,1037						   &unlock_detected_sub);1038	if (ret)1039		return ret;1040 1041	if (sync_stat == 6)1042		*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;1043	else if (unlock_detected && unlock_detected_sub)1044		*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;1045	else1046		*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;1047 1048	return 0;1049}1050 1051int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd1052				       *tnr_dmd,1053				       enum1054				       cxd2880_tnrdmd_lock_result1055				       *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		else1085			*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;1086 1087		return 0;1088	}1089 1090	if (ts_lock) {1091		*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;1092		return 0;1093	} else if (!unlock_detected) {1094		*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;1095		return 0;1096	}1097 1098	ret =1099	    cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,1100						   &unlock_detected_sub);1101	if (ret)1102		return ret;1103 1104	if (unlock_detected && unlock_detected_sub)1105		*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;1106	else1107		*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;1108 1109	return 0;1110}1111 1112int cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd1113				     *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_tnrdmd1148					   *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_tnrdmd1185					    *tnr_dmd,1186					    u8 *l1_post_valid)1187{1188	int ret;1189 1190	u8 data;1191 1192	if (!tnr_dmd || !l1_post_valid)1193		return -EINVAL;1194 1195	if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)1196		return -EINVAL;1197 1198	if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&1199	    tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)1200		return -EINVAL;1201 1202	ret = tnr_dmd->io->write_reg(tnr_dmd->io,1203				     CXD2880_IO_TGT_DMD,1204				     0x00, 0x0b);1205	if (ret)1206		return ret;1207 1208	ret = tnr_dmd->io->read_regs(tnr_dmd->io,1209				     CXD2880_IO_TGT_DMD,1210				     0x86, &data, 1);1211	if (ret)1212		return ret;1213 1214	*l1_post_valid = data & 0x01;1215 1216	return ret;1217}1218