162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* Common methods for dibusb-based-receivers.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "dibusb.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/* 3000MC/P stuff */
1462306a36Sopenharmony_ci// Config Adjacent channels  Perf -cal22
1562306a36Sopenharmony_cistatic struct dibx000_agc_config dib3000p_mt2060_agc_config = {
1662306a36Sopenharmony_ci	.band_caps = BAND_VHF | BAND_UHF,
1762306a36Sopenharmony_ci	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	.agc1_max = 48497,
2062306a36Sopenharmony_ci	.agc1_min = 23593,
2162306a36Sopenharmony_ci	.agc2_max = 46531,
2262306a36Sopenharmony_ci	.agc2_min = 24904,
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	.agc1_pt1 = 0x65,
2562306a36Sopenharmony_ci	.agc1_pt2 = 0x69,
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	.agc1_slope1 = 0x51,
2862306a36Sopenharmony_ci	.agc1_slope2 = 0x27,
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	.agc2_pt1 = 0,
3162306a36Sopenharmony_ci	.agc2_pt2 = 0x33,
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	.agc2_slope1 = 0x35,
3462306a36Sopenharmony_ci	.agc2_slope2 = 0x37,
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic struct dib3000mc_config stk3000p_dib3000p_config = {
3862306a36Sopenharmony_ci	&dib3000p_mt2060_agc_config,
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	.max_time     = 0x196,
4162306a36Sopenharmony_ci	.ln_adc_level = 0x1cc7,
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	.output_mpeg2_in_188_bytes = 1,
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	.agc_command1 = 1,
4662306a36Sopenharmony_ci	.agc_command2 = 1,
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic struct dibx000_agc_config dib3000p_panasonic_agc_config = {
5062306a36Sopenharmony_ci	.band_caps = BAND_VHF | BAND_UHF,
5162306a36Sopenharmony_ci	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	.agc1_max = 56361,
5462306a36Sopenharmony_ci	.agc1_min = 22282,
5562306a36Sopenharmony_ci	.agc2_max = 47841,
5662306a36Sopenharmony_ci	.agc2_min = 36045,
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	.agc1_pt1 = 0x3b,
5962306a36Sopenharmony_ci	.agc1_pt2 = 0x6b,
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	.agc1_slope1 = 0x55,
6262306a36Sopenharmony_ci	.agc1_slope2 = 0x1d,
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	.agc2_pt1 = 0,
6562306a36Sopenharmony_ci	.agc2_pt2 = 0x0a,
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	.agc2_slope1 = 0x95,
6862306a36Sopenharmony_ci	.agc2_slope2 = 0x1e,
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic struct dib3000mc_config mod3000p_dib3000p_config = {
7262306a36Sopenharmony_ci	&dib3000p_panasonic_agc_config,
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	.max_time     = 0x51,
7562306a36Sopenharmony_ci	.ln_adc_level = 0x1cc7,
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	.output_mpeg2_in_188_bytes = 1,
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	.agc_command1 = 1,
8062306a36Sopenharmony_ci	.agc_command2 = 1,
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciint dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	if (le16_to_cpu(adap->dev->udev->descriptor.idVendor) == USB_VID_LITEON &&
8662306a36Sopenharmony_ci	    le16_to_cpu(adap->dev->udev->descriptor.idProduct) ==
8762306a36Sopenharmony_ci			USB_PID_LITEON_DVB_T_WARM) {
8862306a36Sopenharmony_ci		msleep(1000);
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
9262306a36Sopenharmony_ci					 &adap->dev->i2c_adap,
9362306a36Sopenharmony_ci					 DEFAULT_DIB3000P_I2C_ADDRESS,
9462306a36Sopenharmony_ci					 &mod3000p_dib3000p_config);
9562306a36Sopenharmony_ci	if ((adap->fe_adap[0].fe) == NULL)
9662306a36Sopenharmony_ci		adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
9762306a36Sopenharmony_ci						 &adap->dev->i2c_adap,
9862306a36Sopenharmony_ci						 DEFAULT_DIB3000MC_I2C_ADDRESS,
9962306a36Sopenharmony_ci						 &mod3000p_dib3000p_config);
10062306a36Sopenharmony_ci	if ((adap->fe_adap[0].fe) != NULL) {
10162306a36Sopenharmony_ci		if (adap->priv != NULL) {
10262306a36Sopenharmony_ci			struct dibusb_state *st = adap->priv;
10362306a36Sopenharmony_ci			st->ops.pid_parse = dib3000mc_pid_parse;
10462306a36Sopenharmony_ci			st->ops.pid_ctrl  = dib3000mc_pid_control;
10562306a36Sopenharmony_ci		}
10662306a36Sopenharmony_ci		return 0;
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci	return -ENODEV;
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic struct mt2060_config stk3000p_mt2060_config = {
11362306a36Sopenharmony_ci	0x60
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciint dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	struct dibusb_state *st = adap->priv;
11962306a36Sopenharmony_ci	u8 a,b;
12062306a36Sopenharmony_ci	u16 if1 = 1220;
12162306a36Sopenharmony_ci	struct i2c_adapter *tun_i2c;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	// First IF calibration for Liteon Sticks
12462306a36Sopenharmony_ci	if (le16_to_cpu(adap->dev->udev->descriptor.idVendor) == USB_VID_LITEON &&
12562306a36Sopenharmony_ci	    le16_to_cpu(adap->dev->udev->descriptor.idProduct) == USB_PID_LITEON_DVB_T_WARM) {
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci		dibusb_read_eeprom_byte(adap->dev,0x7E,&a);
12862306a36Sopenharmony_ci		dibusb_read_eeprom_byte(adap->dev,0x7F,&b);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci		if (a == 0x00)
13162306a36Sopenharmony_ci			if1 += b;
13262306a36Sopenharmony_ci		else if (a == 0x80)
13362306a36Sopenharmony_ci			if1 -= b;
13462306a36Sopenharmony_ci		else
13562306a36Sopenharmony_ci			warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	} else if (le16_to_cpu(adap->dev->udev->descriptor.idVendor) == USB_VID_DIBCOM &&
13862306a36Sopenharmony_ci		   le16_to_cpu(adap->dev->udev->descriptor.idProduct) == USB_PID_DIBCOM_MOD3001_WARM) {
13962306a36Sopenharmony_ci		u8 desc;
14062306a36Sopenharmony_ci		dibusb_read_eeprom_byte(adap->dev, 7, &desc);
14162306a36Sopenharmony_ci		if (desc == 2) {
14262306a36Sopenharmony_ci			a = 127;
14362306a36Sopenharmony_ci			do {
14462306a36Sopenharmony_ci				dibusb_read_eeprom_byte(adap->dev, a, &desc);
14562306a36Sopenharmony_ci				a--;
14662306a36Sopenharmony_ci			} while (a > 7 && (desc == 0xff || desc == 0x00));
14762306a36Sopenharmony_ci			if (desc & 0x80)
14862306a36Sopenharmony_ci				if1 -= (0xff - desc);
14962306a36Sopenharmony_ci			else
15062306a36Sopenharmony_ci				if1 += desc;
15162306a36Sopenharmony_ci		}
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
15562306a36Sopenharmony_ci	if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
15662306a36Sopenharmony_ci		/* not found - use panasonic pll parameters */
15762306a36Sopenharmony_ci		if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
15862306a36Sopenharmony_ci			return -ENOMEM;
15962306a36Sopenharmony_ci	} else {
16062306a36Sopenharmony_ci		st->mt2060_present = 1;
16162306a36Sopenharmony_ci		/* set the correct parameters for the dib3000p */
16262306a36Sopenharmony_ci		dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
16362306a36Sopenharmony_ci	}
16462306a36Sopenharmony_ci	return 0;
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
167