From fa8bae102fbbabe9ecc4381ace3b74a199684594 Mon Sep 17 00:00:00 2001
From: "Igor M. Liplianin" <liplianin@me.by>
Date: Fri, 25 Feb 2011 18:41:22 -0300
Subject: [PATCH] [media] dw2102: Prof 7500: Lock LED implemented

Code changed for dw2102, stv0900 in order to achieve that.

Signed-off-by: Igor M. Liplianin <liplianin@me.by>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/dvb/dvb-usb/dw2102.c         | 29 ++++++++++++++++++++++
 drivers/media/dvb/frontends/stv0900.h      |  2 ++
 drivers/media/dvb/frontends/stv0900_core.c | 23 ++++++++++++++++-
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 57af4c17d54f..4ae4fb02164d 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -70,6 +70,7 @@
 #define DW2102_VOLTAGE_CTRL (0x1800)
 #define SU3000_STREAM_CTRL (0x1900)
 #define DW2102_RC_QUERY (0x1a00)
+#define DW2102_LED_CTRL (0x1b00)
 
 #define	err_str "did not find the firmware file. (%s) " \
 		"Please see linux/Documentation/dvb/ for more details " \
@@ -509,6 +510,15 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 					obuf, 2, DW210X_WRITE_MSG);
 			break;
 		}
+		case (DW2102_LED_CTRL): {
+			u8 obuf[2];
+
+			obuf[0] = 5;
+			obuf[1] = msg[j].buf[0];
+			ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
+					obuf, 2, DW210X_WRITE_MSG);
+			break;
+		}
 		/*case 0x55: cx24116
 		case 0x6a: stv0903
 		case 0x68: ds3000, stv0903
@@ -844,6 +854,24 @@ static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 	return 0;
 }
 
+static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
+{
+	static u8 led_off[] = { 0 };
+	static u8 led_on[] = { 1 };
+	struct i2c_msg msg = {
+		.addr = DW2102_LED_CTRL,
+		.flags = 0,
+		.buf = led_off,
+		.len = 1
+	};
+	struct dvb_usb_adapter *udev_adap =
+		(struct dvb_usb_adapter *)(fe->dvb->priv);
+
+	if (offon)
+		msg.buf = led_on;
+	i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
+}
+
 static struct stv0299_config sharp_z0194a_config = {
 	.demod_address = 0x68,
 	.inittab = sharp_z0194a_inittab,
@@ -923,6 +951,7 @@ static struct stv0900_config prof_7500_stv0900_config = {
 	.tun1_adc = 0,/* 2 Vpp */
 	.path1_mode = 3,
 	.tun1_type = 3,
+	.set_lock_led = dw210x_led_ctrl,
 };
 
 static struct ds3000_config su3000_ds3000_config = {
diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h
index e3e35d1ce838..91c7ee8b2313 100644
--- a/drivers/media/dvb/frontends/stv0900.h
+++ b/drivers/media/dvb/frontends/stv0900.h
@@ -53,6 +53,8 @@ struct stv0900_config {
 	u8 tun2_type;
 	/* Set device param to start dma */
 	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+	/* Hook for Lock LED */
+	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
 #if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c
index 4f5e7d3a0e61..1ca1c835048f 100644
--- a/drivers/media/dvb/frontends/stv0900_core.c
+++ b/drivers/media/dvb/frontends/stv0900_core.c
@@ -1660,8 +1660,13 @@ static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status)
 			| FE_HAS_VITERBI
 			| FE_HAS_SYNC
 			| FE_HAS_LOCK;
-	} else
+		if (state->config->set_lock_led)
+			state->config->set_lock_led(fe, 1);
+	} else {
+		if (state->config->set_lock_led)
+			state->config->set_lock_led(fe, 0);
 		dprintk("DEMOD LOCK FAIL\n");
+	}
 
 	return 0;
 }
@@ -1831,6 +1836,9 @@ static void stv0900_release(struct dvb_frontend *fe)
 
 	dprintk("%s\n", __func__);
 
+	if (state->config->set_lock_led)
+		state->config->set_lock_led(fe, 0);
+
 	if ((--(state->internal->dmds_used)) <= 0) {
 
 		dprintk("%s: Actually removing\n", __func__);
@@ -1842,6 +1850,18 @@ static void stv0900_release(struct dvb_frontend *fe)
 	kfree(state);
 }
 
+static int stv0900_sleep(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (state->config->set_lock_led)
+		state->config->set_lock_led(fe, 0);
+
+	return 0;
+}
+
 static int stv0900_get_frontend(struct dvb_frontend *fe,
 				struct dvb_frontend_parameters *p)
 {
@@ -1876,6 +1896,7 @@ static struct dvb_frontend_ops stv0900_ops = {
 	.release			= stv0900_release,
 	.init				= stv0900_init,
 	.get_frontend                   = stv0900_get_frontend,
+	.sleep				= stv0900_sleep,
 	.get_frontend_algo		= stv0900_frontend_algo,
 	.i2c_gate_ctrl			= stv0900_i2c_gate_ctrl,
 	.diseqc_send_master_cmd		= stv0900_send_master_cmd,
-- 
2.34.1