18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* Common methods for dibusb-based-receivers.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "dibusb.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/* 3000MC/P stuff */
148c2ecf20Sopenharmony_ci// Config Adjacent channels  Perf -cal22
158c2ecf20Sopenharmony_cistatic struct dibx000_agc_config dib3000p_mt2060_agc_config = {
168c2ecf20Sopenharmony_ci	.band_caps = BAND_VHF | BAND_UHF,
178c2ecf20Sopenharmony_ci	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	.agc1_max = 48497,
208c2ecf20Sopenharmony_ci	.agc1_min = 23593,
218c2ecf20Sopenharmony_ci	.agc2_max = 46531,
228c2ecf20Sopenharmony_ci	.agc2_min = 24904,
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	.agc1_pt1 = 0x65,
258c2ecf20Sopenharmony_ci	.agc1_pt2 = 0x69,
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	.agc1_slope1 = 0x51,
288c2ecf20Sopenharmony_ci	.agc1_slope2 = 0x27,
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	.agc2_pt1 = 0,
318c2ecf20Sopenharmony_ci	.agc2_pt2 = 0x33,
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	.agc2_slope1 = 0x35,
348c2ecf20Sopenharmony_ci	.agc2_slope2 = 0x37,
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic struct dib3000mc_config stk3000p_dib3000p_config = {
388c2ecf20Sopenharmony_ci	&dib3000p_mt2060_agc_config,
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	.max_time     = 0x196,
418c2ecf20Sopenharmony_ci	.ln_adc_level = 0x1cc7,
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	.output_mpeg2_in_188_bytes = 1,
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	.agc_command1 = 1,
468c2ecf20Sopenharmony_ci	.agc_command2 = 1,
478c2ecf20Sopenharmony_ci};
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic struct dibx000_agc_config dib3000p_panasonic_agc_config = {
508c2ecf20Sopenharmony_ci	.band_caps = BAND_VHF | BAND_UHF,
518c2ecf20Sopenharmony_ci	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	.agc1_max = 56361,
548c2ecf20Sopenharmony_ci	.agc1_min = 22282,
558c2ecf20Sopenharmony_ci	.agc2_max = 47841,
568c2ecf20Sopenharmony_ci	.agc2_min = 36045,
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	.agc1_pt1 = 0x3b,
598c2ecf20Sopenharmony_ci	.agc1_pt2 = 0x6b,
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	.agc1_slope1 = 0x55,
628c2ecf20Sopenharmony_ci	.agc1_slope2 = 0x1d,
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	.agc2_pt1 = 0,
658c2ecf20Sopenharmony_ci	.agc2_pt2 = 0x0a,
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	.agc2_slope1 = 0x95,
688c2ecf20Sopenharmony_ci	.agc2_slope2 = 0x1e,
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic struct dib3000mc_config mod3000p_dib3000p_config = {
728c2ecf20Sopenharmony_ci	&dib3000p_panasonic_agc_config,
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	.max_time     = 0x51,
758c2ecf20Sopenharmony_ci	.ln_adc_level = 0x1cc7,
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	.output_mpeg2_in_188_bytes = 1,
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	.agc_command1 = 1,
808c2ecf20Sopenharmony_ci	.agc_command2 = 1,
818c2ecf20Sopenharmony_ci};
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciint dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	if (le16_to_cpu(adap->dev->udev->descriptor.idVendor) == USB_VID_LITEON &&
868c2ecf20Sopenharmony_ci	    le16_to_cpu(adap->dev->udev->descriptor.idProduct) ==
878c2ecf20Sopenharmony_ci			USB_PID_LITEON_DVB_T_WARM) {
888c2ecf20Sopenharmony_ci		msleep(1000);
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
928c2ecf20Sopenharmony_ci					 &adap->dev->i2c_adap,
938c2ecf20Sopenharmony_ci					 DEFAULT_DIB3000P_I2C_ADDRESS,
948c2ecf20Sopenharmony_ci					 &mod3000p_dib3000p_config);
958c2ecf20Sopenharmony_ci	if ((adap->fe_adap[0].fe) == NULL)
968c2ecf20Sopenharmony_ci		adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
978c2ecf20Sopenharmony_ci						 &adap->dev->i2c_adap,
988c2ecf20Sopenharmony_ci						 DEFAULT_DIB3000MC_I2C_ADDRESS,
998c2ecf20Sopenharmony_ci						 &mod3000p_dib3000p_config);
1008c2ecf20Sopenharmony_ci	if ((adap->fe_adap[0].fe) != NULL) {
1018c2ecf20Sopenharmony_ci		if (adap->priv != NULL) {
1028c2ecf20Sopenharmony_ci			struct dibusb_state *st = adap->priv;
1038c2ecf20Sopenharmony_ci			st->ops.pid_parse = dib3000mc_pid_parse;
1048c2ecf20Sopenharmony_ci			st->ops.pid_ctrl  = dib3000mc_pid_control;
1058c2ecf20Sopenharmony_ci		}
1068c2ecf20Sopenharmony_ci		return 0;
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci	return -ENODEV;
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic struct mt2060_config stk3000p_mt2060_config = {
1138c2ecf20Sopenharmony_ci	0x60
1148c2ecf20Sopenharmony_ci};
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciint dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	struct dibusb_state *st = adap->priv;
1198c2ecf20Sopenharmony_ci	u8 a,b;
1208c2ecf20Sopenharmony_ci	u16 if1 = 1220;
1218c2ecf20Sopenharmony_ci	struct i2c_adapter *tun_i2c;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	// First IF calibration for Liteon Sticks
1248c2ecf20Sopenharmony_ci	if (le16_to_cpu(adap->dev->udev->descriptor.idVendor) == USB_VID_LITEON &&
1258c2ecf20Sopenharmony_ci	    le16_to_cpu(adap->dev->udev->descriptor.idProduct) == USB_PID_LITEON_DVB_T_WARM) {
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci		dibusb_read_eeprom_byte(adap->dev,0x7E,&a);
1288c2ecf20Sopenharmony_ci		dibusb_read_eeprom_byte(adap->dev,0x7F,&b);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci		if (a == 0x00)
1318c2ecf20Sopenharmony_ci			if1 += b;
1328c2ecf20Sopenharmony_ci		else if (a == 0x80)
1338c2ecf20Sopenharmony_ci			if1 -= b;
1348c2ecf20Sopenharmony_ci		else
1358c2ecf20Sopenharmony_ci			warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	} else if (le16_to_cpu(adap->dev->udev->descriptor.idVendor) == USB_VID_DIBCOM &&
1388c2ecf20Sopenharmony_ci		   le16_to_cpu(adap->dev->udev->descriptor.idProduct) == USB_PID_DIBCOM_MOD3001_WARM) {
1398c2ecf20Sopenharmony_ci		u8 desc;
1408c2ecf20Sopenharmony_ci		dibusb_read_eeprom_byte(adap->dev, 7, &desc);
1418c2ecf20Sopenharmony_ci		if (desc == 2) {
1428c2ecf20Sopenharmony_ci			a = 127;
1438c2ecf20Sopenharmony_ci			do {
1448c2ecf20Sopenharmony_ci				dibusb_read_eeprom_byte(adap->dev, a, &desc);
1458c2ecf20Sopenharmony_ci				a--;
1468c2ecf20Sopenharmony_ci			} while (a > 7 && (desc == 0xff || desc == 0x00));
1478c2ecf20Sopenharmony_ci			if (desc & 0x80)
1488c2ecf20Sopenharmony_ci				if1 -= (0xff - desc);
1498c2ecf20Sopenharmony_ci			else
1508c2ecf20Sopenharmony_ci				if1 += desc;
1518c2ecf20Sopenharmony_ci		}
1528c2ecf20Sopenharmony_ci	}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
1558c2ecf20Sopenharmony_ci	if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
1568c2ecf20Sopenharmony_ci		/* not found - use panasonic pll parameters */
1578c2ecf20Sopenharmony_ci		if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
1588c2ecf20Sopenharmony_ci			return -ENOMEM;
1598c2ecf20Sopenharmony_ci	} else {
1608c2ecf20Sopenharmony_ci		st->mt2060_present = 1;
1618c2ecf20Sopenharmony_ci		/* set the correct parameters for the dib3000p */
1628c2ecf20Sopenharmony_ci		dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci	return 0;
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
167