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

Commit ad976187 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] dib8000: improves the auto search mode check logic



The logic that detects if auto search mode should be used is too
complex.

Also, it doesn't cover all cases, as the dib8000_tune logic
requires either auto mode or a fully specified manual mode.
So, move it to a separate function and add some extra debug
data to help identifying when it falled back to auto mode,
because the manual settings are invalid.

Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
Acked-by: default avatarPatrick Boettcher <pboettcher@kernellabs.com>
parent 70315b3e
Loading
Loading
Loading
Loading
+90 −28
Original line number Diff line number Diff line
@@ -2873,6 +2873,91 @@ static int dib8090p_init_sdram(struct dib8000_state *state)
	return 0;
}

/**
 * is_manual_mode - Check if TMCC should be used for parameters settings
 * @c:	struct dvb_frontend_properties
 *
 * By default, TMCC table should be used for parameter settings on most
 * usercases. However, sometimes it is desirable to lock the demod to
 * use the manual parameters.
 *
 * On manual mode, the current dib8000_tune state machine is very restrict:
 * It requires that both per-layer and per-transponder parameters to be
 * properly specified, otherwise the device won't lock.
 *
 * Check if all those conditions are properly satisfied before allowing
 * the device to use the manual frequency lock mode.
 */
static int is_manual_mode(struct dtv_frontend_properties *c)
{
	int i, n_segs = 0;

	/* Use auto mode on DVB-T compat mode */
	if (c->delivery_system != SYS_ISDBT)
		return 0;

	/*
	 * Transmission mode is only detected on auto mode, currently
	 */
	if (c->transmission_mode == TRANSMISSION_MODE_AUTO) {
		dprintk("transmission mode auto");
		return 0;
	}

	/*
	 * Guard interval is only detected on auto mode, currently
	 */
	if (c->guard_interval == GUARD_INTERVAL_AUTO) {
		dprintk("guard interval auto");
		return 0;
	}

	/*
	 * If no layer is enabled, assume auto mode, as at least one
	 * layer should be enabled
	 */
	if (!c->isdbt_layer_enabled) {
		dprintk("no layer modulation specified");
		return 0;
	}

	/*
	 * Check if the per-layer parameters aren't auto and
	 * disable a layer if segment count is 0 or invalid.
	 */
	for (i = 0; i < 3; i++) {
		if (!(c->isdbt_layer_enabled & 1 << i))
			continue;

		if ((c->layer[i].segment_count > 13) ||
		    (c->layer[i].segment_count == 0)) {
			c->isdbt_layer_enabled &= ~(1 << i);
			continue;
		}

		n_segs += c->layer[i].segment_count;

		if ((c->layer[i].modulation == QAM_AUTO) ||
		    (c->layer[i].fec == FEC_AUTO)) {
			dprintk("layer %c has either modulation or FEC auto",
				'A' + i);
			return 0;
		}
	}

	/*
	 * Userspace specified a wrong number of segments.
	 *	fallback to auto mode.
	 */
	if (n_segs == 0 || n_segs > 13) {
		dprintk("number of segments is invalid");
		return 0;
	}

	/* Everything looks ok for manual mode */
	return 1;
}

static int dib8000_tune(struct dvb_frontend *fe)
{
	struct dib8000_state *state = fe->demodulator_priv;
@@ -2901,37 +2986,14 @@ static int dib8000_tune(struct dvb_frontend *fe)
			if (state->revision == 0x8090)
				dib8090p_init_sdram(state);
			state->status = FE_STATUS_TUNE_PENDING;
			if ((c->delivery_system != SYS_ISDBT) ||
					(c->inversion == INVERSION_AUTO) ||
					(c->transmission_mode == TRANSMISSION_MODE_AUTO) ||
					(c->guard_interval == GUARD_INTERVAL_AUTO) ||
					(((c->isdbt_layer_enabled & (1 << 0)) != 0) &&
					 (c->layer[0].segment_count != 0xff) &&
					 (c->layer[0].segment_count != 0) &&
					 ((c->layer[0].modulation == QAM_AUTO) ||
					  (c->layer[0].fec == FEC_AUTO))) ||
					(((c->isdbt_layer_enabled & (1 << 1)) != 0) &&
					 (c->layer[1].segment_count != 0xff) &&
					 (c->layer[1].segment_count != 0) &&
					 ((c->layer[1].modulation == QAM_AUTO) ||
					  (c->layer[1].fec == FEC_AUTO))) ||
					(((c->isdbt_layer_enabled & (1 << 2)) != 0) &&
					 (c->layer[2].segment_count != 0xff) &&
					 (c->layer[2].segment_count != 0) &&
					 ((c->layer[2].modulation == QAM_AUTO) ||
					  (c->layer[2].fec == FEC_AUTO))) ||
					(((c->layer[0].segment_count == 0) ||
					  ((c->isdbt_layer_enabled & (1 << 0)) == 0)) &&
					 ((c->layer[1].segment_count == 0) ||
					  ((c->isdbt_layer_enabled & (2 << 0)) == 0)) &&
					 ((c->layer[2].segment_count == 0) || ((c->isdbt_layer_enabled & (3 << 0)) == 0))))
				state->channel_parameters_set = 0; /* auto search */
			else
				state->channel_parameters_set = 1; /* channel parameters are known */
			state->channel_parameters_set = is_manual_mode(c);

			dprintk("Tuning channel on %s search mode",
				state->channel_parameters_set ? "manual" : "auto");

			dib8000_viterbi_state(state, 0); /* force chan dec in restart */

			/* Layer monit */
			/* Layer monitor */
			dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);

			dib8000_set_frequency_offset(state);