Commit f23e6616 authored by Malcolm Priestley's avatar Malcolm Priestley Committed by Mauro Carvalho Chehab
Browse files

[media] lmed04: Improve frontend handling



Improved frontend handling.

Frontend now remains open at all times, with signal lock, snr & signal level
polled from Interupt.

Updated driver for DM04/QQBOX USB DVB-S BOXES to version 1.70.

Signed-off-by: default avatarMalcolm Priestley <tvboxspy@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ea7c681e
Loading
Loading
Loading
Loading
+71 −82
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ struct lme2510_state {
	u8 i2c_tuner_gate_r;
	u8 i2c_tuner_addr;
	u8 stream_on;
	u8 one_tune;
	void *buffer;
	struct urb *lme_urb;
	void *usb_buffer;
@@ -182,15 +181,13 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
	return (ret < 0) ? -ENODEV : 0;
}

static int lme2510_usb_talk_restart(struct dvb_usb_device *d,
		u8 *wbuf, int wlen, u8 *rbuf, int rlen) {
static int lme2510_stream_restart(struct dvb_usb_device *d)
{
	static u8 stream_on[] = LME_ST_ON_W;
	int ret;
	u8 rbuff[10];
	/*Send Normal Command*/
	ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
	/*Restart Stream Command*/
	ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on),
	ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on),
			rbuff, sizeof(rbuff));
	return ret;
}
@@ -254,11 +251,16 @@ static void lme2510_int_response(struct urb *lme_urb)
			case TUNER_S7395:
				/* Tweak for earlier firmware*/
				if (ibuf[1] == 0x03) {
					if (ibuf[2] > 1)
						st->signal_lock = ibuf[2];
					st->signal_level = ibuf[3];
					st->signal_sn = ibuf[4];
				} else {
					st->signal_level = ibuf[4];
					st->signal_sn = ibuf[5];
					st->signal_lock =
						(st->signal_lock & 0xf7) +
						((ibuf[2] & 0x01) << 0x03);
				}
				break;
			default:
@@ -341,8 +343,7 @@ static int lme2510_msg(struct dvb_usb_device *d,
					st->signal_lock = rbuf[1];
					if ((st->stream_on & 1) &&
						(st->signal_lock & 0x10)) {
						lme2510_usb_talk_restart(d,
							wbuf, wlen, rbuf, rlen);
						lme2510_stream_restart(d);
						st->i2c_talk_onoff = 0;
					}
					msleep(80);
@@ -355,15 +356,12 @@ static int lme2510_msg(struct dvb_usb_device *d,
					st->signal_lock = rbuf[1];
					if ((st->stream_on & 1) &&
						(st->signal_lock & 0x8)) {
						lme2510_usb_talk_restart(d,
							wbuf, wlen, rbuf, rlen);
						lme2510_stream_restart(d);
						st->i2c_talk_onoff = 0;
					}
				}
				if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5))
					msleep(5);


			}
			break;
		default:
@@ -385,18 +383,16 @@ static int lme2510_msg(struct dvb_usb_device *d,
				rbuf[0] = 0x55;
				rbuf[1] = st->signal_sn;
				break;
			/*DiSEqC functions as per TDA10086*/
			case 0x36:
			case 0x48:
			case 0x49:
			case 0x4a:
			case 0x4b:
			case 0x4c:
			case 0x4d:
			if (wbuf[2] == 0x1c)
					lme2510_usb_talk_restart(d,
						wbuf, wlen, rbuf, rlen);
			case 0x15:
			case 0x16:
			case 0x17:
			case 0x18:
				rbuf[0] = 0x55;
				rbuf[1] = 0x00;
				break;
			default:
				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
				st->i2c_talk_onoff = 1;
				break;
			}
			break;
@@ -413,39 +409,22 @@ static int lme2510_msg(struct dvb_usb_device *d,
				break;
			case 0x24:
				rbuf[0] = 0x55;
				rbuf[1] = (st->signal_level & 0x80)
						? 0 : st->signal_lock;
				break;
			case 0x6:
				if (wbuf[2] == 0xd0)
					lme2510_usb_talk(d,
						wbuf, wlen, rbuf, rlen);
				break;
			case 0x1:
				if (st->one_tune > 0)
					break;
				st->one_tune++;
				st->i2c_talk_onoff = 1;
			/*DiSEqC functions as per STV0288*/
			case 0x5:
			case 0x7:
			case 0x8:
			case 0x9:
			case 0xa:
			case 0xb:
				if (wbuf[2] == 0xd0)
					lme2510_usb_talk_restart(d,
						wbuf, wlen, rbuf, rlen);
				rbuf[1] = st->signal_lock;
				break;
			default:
			case 0x2e:
			case 0x26:
			case 0x27:
				rbuf[0] = 0x55;
				rbuf[1] = 0x00;
				break;
			default:
				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
				st->i2c_talk_onoff = 1;
				break;
			}
			break;
		default:
			break;

		}

		deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)",
@@ -548,35 +527,26 @@ static int lme2510_identify_state(struct usb_device *udev,
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
	struct lme2510_state *st = adap->dev->priv;
	static u8 stream_on[] = LME_ST_ON_W;
	static u8 clear_reg_3[] =  LME_CLEAR_PID;
	static u8 rbuf[1];
	static u8 timeout;
	int ret = 0, len = 2, rlen = sizeof(rbuf);
	int ret = 0, rlen = sizeof(rbuf);

	deb_info(1, "STM  (%02x)", onoff);

	if (onoff == 1)	{
		st->i2c_talk_onoff = 0;
		timeout = 0;
		/* wait for i2C to be free */
		while (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) {
			timeout++;
			if (timeout > 5)
				return -ENODEV;
		}
		msleep(100);
		ret |= lme2510_usb_talk(adap->dev,
				 stream_on,  len, rbuf, rlen);
	/* Streaming is started by FE_HAS_LOCK */
	if (onoff == 1)
		st->stream_on = 1;
		st->one_tune = 0;
		mutex_unlock(&adap->dev->i2c_mutex);
	} else {
	else {
		deb_info(1, "STM Steam Off");
		/* mutex is here only to avoid collision with I2C */
		ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);

		ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
				sizeof(clear_reg_3), rbuf, rlen);
		st->stream_on = 0;
		st->i2c_talk_onoff = 1;

		mutex_unlock(&adap->dev->i2c_mutex);
	}

	return (ret < 0) ? -ENODEV : 0;
@@ -619,6 +589,7 @@ static int lme2510_int_service(struct dvb_usb_adapter *adap)
		ir_input_unregister(input_dev);
		input_free_device(input_dev);
	}

	return (ret < 0) ? -ENODEV : 0;
}

@@ -668,6 +639,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
		ret |= (data[0] == 0x88) ? 0 : -1;
		}
	}

	usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
			0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);

@@ -701,6 +673,7 @@ static void lme_coldreset(struct usb_device *dev)
	info("FRM Firmware Cold Reset");
	ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
	ret |= lme2510_bulk_read(dev, data, len_in, 1);

	return;
}

@@ -712,6 +685,8 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
	char *firm_msg[] = {"Loading", "Switching to"};
	int ret;

	cold = (cold > 0) ? (cold & 1) : 0;

	if (udev->descriptor.idProduct == 0x1122)
		return;

@@ -740,22 +715,26 @@ static void lme_firmware_switch(struct usb_device *udev, int cold)
		cold = 0;
		break;
	}

	release_firmware(fw);

	if (cold)
		lme_coldreset(udev);

	return;
}

static int lme2510_kill_urb(struct usb_data_stream *stream)
{
	int i;

	for (i = 0; i < stream->urbs_submitted; i++) {
		deb_info(3, "killing URB no. %d.", i);

		/* stop the URB */
		usb_kill_urb(stream->urb_list[i]);
	}
	stream->urbs_submitted = 0;

	return 0;
}

@@ -783,18 +762,13 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
					fe_sec_voltage_t voltage)
{
	struct dvb_usb_adapter *adap = fe->dvb->priv;
	struct lme2510_state *st = adap->dev->priv;
	static u8 voltage_low[]	= LME_VOLTAGE_L;
	static u8 voltage_high[] = LME_VOLTAGE_H;
	static u8 lnb_on[] = LNB_ON;
	static u8 lnb_off[] = LNB_OFF;
	static u8 rbuf[1];
	int ret = 0, len = 3, rlen = 1;

	if (st->stream_on == 1)
		return 0;

	ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen);
	if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
			return -EAGAIN;

	switch (voltage) {
	case SEC_VOLTAGE_18:
@@ -803,17 +777,15 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
		break;

	case SEC_VOLTAGE_OFF:
		ret |= lme2510_usb_talk(adap->dev,
					lnb_off, len, rbuf, rlen);
	case SEC_VOLTAGE_13:
	default:
		ret |= lme2510_usb_talk(adap->dev,
				voltage_low, len, rbuf, rlen);
		break;
	}

	mutex_unlock(&adap->dev->i2c_mutex);

	};
	st->i2c_talk_onoff = 1;
	return (ret < 0) ? -ENODEV : 0;
}

@@ -850,12 +822,14 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
			if (dvb_usb_lme2510_firmware != 1) {
				dvb_usb_lme2510_firmware = 1;
				lme_firmware_switch(adap->dev->udev, 1);
			}
			} else /*stops LG/Sharp multi tuner problems*/
				dvb_usb_lme2510_firmware = 0;
			return 0;
		}
		kfree(adap->fe);
		adap->fe = NULL;
	}

	st->i2c_gate = 5;
	adap->fe = dvb_attach(stv0288_attach, &lme_config,
			&adap->dev->i2c_adap);
@@ -889,8 +863,23 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
{
	struct lme2510_state *st = d->priv;
	static u8 lnb_on[] = LNB_ON;
	static u8 lnb_off[] = LNB_OFF;
	static u8 rbuf[1];
	int ret, len = 3, rlen = 1;

	ret = mutex_lock_interruptible(&d->i2c_mutex);

	if (onoff)
		ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
	else
		ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);

	st->i2c_talk_onoff = 1;
	return 0;

	mutex_unlock(&d->i2c_mutex);

	return ret;
}

/* DVB USB Driver stuff */
@@ -1084,5 +1073,5 @@ module_exit(lme2510_module_exit);

MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0");
MODULE_VERSION("1.60");
MODULE_VERSION("1.70");
MODULE_LICENSE("GPL");