Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba8fc399 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (4270): Add tda9887-specific tuner configuration



Many tda9887 settings depend on the chosen tuner. Expand the tuner parameters
to include these tda9887 settings.

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 0a115373
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -416,7 +416,7 @@ static void tuner_status(struct i2c_client *client)

/* ---------------------------------------------------------------------- */

/* static var Used only in tuner_attach and tuner_probe */
/* static vars: used only in tuner_attach and tuner_probe */
static unsigned default_mode_mask;

/* During client attach, set_type is called by adapter's attach_inform callback.
+64 −10
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/i2c.h>
#include <linux/videodev.h>
#include <media/tuner.h>
#include <media/v4l2-common.h>

static int offset = 0;
module_param(offset, int, 0666);
@@ -128,6 +129,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
	u8 buffer[4];
	int rc, IFPCoff, i, j;
	enum param_type desired_type;
	struct tuner_params *params;

	tun = &tuners[t->type];

@@ -169,19 +171,20 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
			  IFPCoff,t->type);
		j = 0;
	}
	params = &tun->params[j];

	for (i = 0; i < tun->params[j].count; i++) {
		if (freq > tun->params[j].ranges[i].limit)
	for (i = 0; i < params->count; i++) {
		if (freq > params->ranges[i].limit)
			continue;
		break;
	}
	if (i == tun->params[j].count) {
	if (i == params->count) {
		tuner_dbg("TV frequency out of range (%d > %d)",
				freq, tun->params[j].ranges[i - 1].limit);
		freq = tun->params[j].ranges[--i].limit;
				freq, params->ranges[i - 1].limit);
		freq = params->ranges[--i].limit;
	}
	config = tun->params[j].ranges[i].config;
	cb     = tun->params[j].ranges[i].cb;
	config = params->ranges[i].config;
	cb     = params->ranges[i].cb;
	/*  i == 0 -> VHF_LO
	 *  i == 1 -> VHF_HI
	 *  i == 2 -> UHF     */
@@ -281,7 +284,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
		break;
	}

	if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
	if (params->cb_first_if_lower_freq && div < t->last_div) {
		buffer[0] = config;
		buffer[1] = cb;
		buffer[2] = (div>>8) & 0x7f;
@@ -293,6 +296,43 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
		buffer[3] = cb;
	}
	t->last_div = div;
	if (params->has_tda9887) {
		int config = 0;
		int is_secam_l = (t->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&
			!(t->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));

		if (t->std == V4L2_STD_SECAM_LC) {
			if (params->port1_active ^ params->port1_invert_for_secam_lc)
				config |= TDA9887_PORT1_ACTIVE;
			if (params->port2_active ^ params->port2_invert_for_secam_lc)
				config |= TDA9887_PORT2_ACTIVE;
		}
		else {
			if (params->port1_active)
				config |= TDA9887_PORT1_ACTIVE;
			if (params->port2_active)
				config |= TDA9887_PORT2_ACTIVE;
		}
		if (params->intercarrier_mode)
			config |= TDA9887_INTERCARRIER;
		if (is_secam_l) {
			if (i == 0 && params->default_top_secam_low)
				config |= TDA9887_TOP(params->default_top_secam_low);
			else if (i == 1 && params->default_top_secam_mid)
				config |= TDA9887_TOP(params->default_top_secam_mid);
			else if (params->default_top_secam_high)
				config |= TDA9887_TOP(params->default_top_secam_high);
		}
		else {
			if (i == 0 && params->default_top_low)
				config |= TDA9887_TOP(params->default_top_low);
			else if (i == 1 && params->default_top_mid)
				config |= TDA9887_TOP(params->default_top_mid);
			else if (params->default_top_high)
				config |= TDA9887_TOP(params->default_top_high);
		}
		i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
	}
	tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
		  buffer[0],buffer[1],buffer[2],buffer[3]);

@@ -339,6 +379,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
	u16 div;
	int rc, j;
	enum param_type desired_type = TUNER_PARAM_TYPE_RADIO;
	struct tuner_params *params;

	tun = &tuners[t->type];

@@ -352,7 +393,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
		j = 0;

	div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */
	buffer[2] = (tun->params[j].ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
	params = &tun->params[j];
	buffer[2] = (params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */

	switch (t->type) {
	case TUNER_TENA_9533_DI:
@@ -384,7 +426,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
	}
	buffer[0] = (div>>8) & 0x7f;
	buffer[1] = div      & 0xff;
	if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
	if (params->cb_first_if_lower_freq && div < t->last_div) {
		buffer[0] = buffer[2];
		buffer[1] = buffer[3];
		buffer[2] = (div>>8) & 0x7f;
@@ -398,6 +440,18 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
	       buffer[0],buffer[1],buffer[2],buffer[3]);
	t->last_div = div;

	if (params->has_tda9887) {
		int config = 0;
		if (params->port1_active && !params->port1_fm_high_sensitivity)
			config |= TDA9887_PORT1_ACTIVE;
		if (params->port2_active && !params->port2_fm_high_sensitivity)
			config |= TDA9887_PORT2_ACTIVE;
		if (params->intercarrier_mode)
			config |= TDA9887_INTERCARRIER;
/*		if (params->port1_set_for_fm_mono)
			config &= ~TDA9887_PORT1_ACTIVE;*/
		i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
	}
	if (4 != (rc = i2c_master_send(c,buffer,4)))
		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
}
+38 −0
Original line number Diff line number Diff line
@@ -380,6 +380,10 @@ static struct tuner_params tuner_philips_fq1216me_params[] = {
		.type   = TUNER_PARAM_TYPE_PAL,
		.ranges = tuner_lg_pal_ranges,
		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
		.has_tda9887 = 1,
		.port1_active = 1,
		.port2_active = 1,
		.port2_invert_for_secam_lc = 1,
	},
};

@@ -542,6 +546,14 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = {
		.ranges = tuner_fm1216me_mk3_pal_ranges,
		.count  = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
		.cb_first_if_lower_freq = 1,
		.has_tda9887 = 1,
		.port1_active = 1,
		.port2_active = 1,
		.port2_invert_for_secam_lc = 1,
		.port1_fm_high_sensitivity = 1,
		.default_top_mid = -2,
		.default_top_secam_mid = -2,
		.default_top_secam_high = -2,
	},
};

@@ -612,6 +624,10 @@ static struct tuner_params tuner_fm1236_mk3_params[] = {
		.ranges = tuner_fm1236_mk3_ntsc_ranges,
		.count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
		.cb_first_if_lower_freq = 1,
		.has_tda9887 = 1,
		.port1_active = 1,
		.port2_active = 1,
		.port1_fm_high_sensitivity = 1,
	},
};

@@ -632,6 +648,8 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = {
		.type   = TUNER_PARAM_TYPE_PAL,
		.ranges = tuner_temic_4009f_5_pal_ranges,
		.count  = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
		.has_tda9887 = 1,
		.port1_invert_for_secam_lc = 1,
	},
};

@@ -648,6 +666,8 @@ static struct tuner_params tuner_panasonic_vp27_params[] = {
		.type   = TUNER_PARAM_TYPE_NTSC,
		.ranges = tuner_panasonic_vp27_ntsc_ranges,
		.count  = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
		.has_tda9887 = 1,
		.intercarrier_mode = 1,
	},
};

@@ -782,6 +802,13 @@ static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
		.type   = TUNER_PARAM_TYPE_PAL,
		.ranges = tuner_philips_fq12_6a___mk4_pal_ranges,
		.count  = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges),
		.has_tda9887 = 1,
		.port1_active = 1,
		.port2_invert_for_secam_lc = 1,
		.default_top_mid = -2,
		.default_top_secam_low = -2,
		.default_top_secam_mid = -2,
		.default_top_secam_high = -2,
	},
};

@@ -870,6 +897,12 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
		.type   = TUNER_PARAM_TYPE_PAL,
		.ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
		.has_tda9887 = 1,
		.port1_active = 1,
		.port2_active = 1,
		.port2_fm_high_sensitivity = 1,
		.port2_invert_for_secam_lc = 1,
		.port1_set_for_fm_mono = 1,
	},
};

@@ -1005,6 +1038,7 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
		.type   = TUNER_PARAM_TYPE_NTSC,
		.ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
		.count  = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
		.has_tda9887 = 1,
	},
};

@@ -1037,6 +1071,10 @@ static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
		.type   = TUNER_PARAM_TYPE_PAL,
		.ranges = tuner_samsung_tcpg_6121p30a_pal_ranges,
		.count  = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges),
		.has_tda9887 = 1,
		.port1_active = 1,
		.port2_active = 1,
		.port2_invert_for_secam_lc = 1,
	},
};

+55 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ struct tuner_range {

struct tuner_params {
	enum param_type type;

	/* Many Philips based tuners have a comment like this in their
	 * datasheet:
	 *
@@ -39,6 +40,60 @@ struct tuner_params {
	 * static unless the control byte was sent first.
	 */
	unsigned int cb_first_if_lower_freq:1;
	/* Set to 1 if this tuner uses a tda9887 */
	unsigned int has_tda9887:1;
	/* Many Philips tuners use tda9887 PORT1 to select the FM radio
	   sensitivity. If this setting is 1, then set PORT1 to 1 to
	   get proper FM reception. */
	unsigned int port1_fm_high_sensitivity:1;
	/* Some Philips tuners use tda9887 PORT2 to select the FM radio
	   sensitivity. If this setting is 1, then set PORT2 to 1 to
	   get proper FM reception. */
	unsigned int port2_fm_high_sensitivity:1;
	/* Most tuners with a tda9887 use QSS mode. Some (cheaper) tuners
	   use Intercarrier mode. If this setting is 1, then the tuner
	   needs to be set to intercarrier mode. */
	unsigned int intercarrier_mode:1;
	/* This setting sets the default value for PORT1.
	   0 means inactive, 1 means active. Note: the actual bit
	   value written to the tda9887 is inverted. So a 0 here
	   means a 1 in the B6 bit. */
	unsigned int port1_active:1;
	/* This setting sets the default value for PORT2.
	   0 means inactive, 1 means active. Note: the actual bit
	   value written to the tda9887 is inverted. So a 0 here
	   means a 1 in the B7 bit. */
	unsigned int port2_active:1;
	/* Sometimes PORT1 is inverted when the SECAM-L' standard is selected.
	   Set this bit to 1 if this is needed. */
	unsigned int port1_invert_for_secam_lc:1;
	/* Sometimes PORT2 is inverted when the SECAM-L' standard is selected.
	   Set this bit to 1 if this is needed. */
	unsigned int port2_invert_for_secam_lc:1;
	/* Some cards require PORT1 to be 1 for mono Radio FM and 0 for stereo. */
	unsigned int port1_set_for_fm_mono:1;
	/* Default tda9887 TOP value in dB for the low band. Default is 0.
	   Range: -16:+15 */
	signed int default_top_low:5;
	/* Default tda9887 TOP value in dB for the mid band. Default is 0.
	   Range: -16:+15 */
	signed int default_top_mid:5;
	/* Default tda9887 TOP value in dB for the high band. Default is 0.
	   Range: -16:+15 */
	signed int default_top_high:5;
	/* Default tda9887 TOP value in dB for SECAM-L/L' for the low band.
	   Default is 0. Several tuners require a different TOP value for
	   the SECAM-L/L' standards. Range: -16:+15 */
	signed int default_top_secam_low:5;
	/* Default tda9887 TOP value in dB for SECAM-L/L' for the mid band.
	   Default is 0. Several tuners require a different TOP value for
	   the SECAM-L/L' standards. Range: -16:+15 */
	signed int default_top_secam_mid:5;
	/* Default tda9887 TOP value in dB for SECAM-L/L' for the high band.
	   Default is 0. Several tuners require a different TOP value for
	   the SECAM-L/L' standards. Range: -16:+15 */
	signed int default_top_secam_high:5;


	unsigned int count;
	struct tuner_range *ranges;
+2 −2

File changed.

Contains only whitespace changes.