brintos

brintos / linux-shallow public Read only

0
0
Text · 21.1 KiB · c7e79da Raw
920 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * cxd2880_tnrdmd_dvbt.c4 * Sony CXD2880 DVB-T2/T tuner + demodulator driver5 * control functions for DVB-T6 *7 * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation8 */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_tnrdmd45				     *tnr_dmd,46				     enum cxd2880_dtv_bandwidth47				     bandwidth,48				     enum cxd2880_tnrdmd_clockmode49				     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_tnrdmd654						   *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_param700			      *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_param741			      *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_tnrdmd801					 *tnr_dmd,802					 enum803					 cxd2880_tnrdmd_lock_result804					 *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		else834			*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;835 836		return 0;837	}838 839	if (sync_stat == 6) {840		*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;841		return 0;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	else855		*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;856 857	return 0;858}859 860int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd861				      *tnr_dmd,862				      enum863				      cxd2880_tnrdmd_lock_result864				      *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		else894			*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;895 896		return 0;897	}898 899	if (ts_lock) {900		*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;901		return 0;902	} else if (!unlock_detected) {903		*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;904		return 0;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	else916		*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;917 918	return 0;919}920