linux: added lnbp22.c rotor patch

moved
This commit is contained in:
Ognian Tschakalov 2017-01-02 14:44:41 +01:00
parent a2750f5bfd
commit 16f12f05db

View File

@ -0,0 +1,166 @@
This patch is from the original driver author and allows minimal power on time,
so that capacitors of secondary equipment like dish motors can be properly loaded and equipment properly initialized
see https://www.spinics.net/lists/linux-media/msg38226.html
and https://github.com/LibreELEC/LibreELEC.tv/pull/1118
tested with TT S2-3650CI and a HH90 rotor
diff -Naur linux-4.9.orig/drivers/media/dvb-frontends/lnbp22.c linux-4.9/drivers/media/dvb-frontends/lnbp22.c
--- linux-4.9.orig/drivers/media/dvb-frontends/lnbp22.c 2017-01-07 18:58:55.306001049 +0100
+++ linux-4.9/drivers/media/dvb-frontends/lnbp22.c 2017-01-07 19:39:06.204887989 +0100
@@ -48,47 +48,95 @@
struct i2c_adapter *i2c;
};
+static int lnbp22_read_config(struct dvb_frontend *fe, u8 *config) {
+ struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
+ struct i2c_msg msg = { .addr = 0x08, .flags = I2C_M_RD,
+ .buf = (char*)config,
+ .len = sizeof(lnbp22->config) };
+
+ if (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) {
+ dprintk(2, "%s: %02X %02X %02X %02X\n", __FUNCTION__,
+ config[0], config[1], config[2], config[3]);
+ return 0;
+ }
+ return -EIO;
+}
+
+static int lnbp22_write_config(struct dvb_frontend *fe, u8 *config) {
+ struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0,
+ .buf = (char*)config,
+ .len = sizeof(lnbp22->config) };
+
+ if (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) {
+ dprintk(2, "%s: %02X %02X %02X %02X\n", __FUNCTION__,
+ config[0], config[1], config[2], config[3]);
+ return 0;
+ }
+ return -EIO;
+}
+
static int lnbp22_set_voltage(struct dvb_frontend *fe,
enum fe_sec_voltage voltage)
{
struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
- struct i2c_msg msg = {
- .addr = 0x08,
- .flags = 0,
- .buf = (char *)&lnbp22->config,
- .len = sizeof(lnbp22->config),
- };
+ int status;
dprintk(1, "%s: %d (18V=%d 13V=%d)\n", __func__, voltage,
SEC_VOLTAGE_18, SEC_VOLTAGE_13);
- lnbp22->config[3] = 0x60; /* Power down */
switch (voltage) {
- case SEC_VOLTAGE_OFF:
- break;
- case SEC_VOLTAGE_13:
- lnbp22->config[3] |= LNBP22_EN;
- break;
- case SEC_VOLTAGE_18:
- lnbp22->config[3] |= (LNBP22_EN | LNBP22_VSEL);
- break;
- default:
- return -EINVAL;
- }
+ case SEC_VOLTAGE_OFF:
+ lnbp22->config[3] &= ~LNBP22_EN;
+ return lnbp22_write_config(fe, lnbp22->config);
+ case SEC_VOLTAGE_13:
+ lnbp22->config[3] |= LNBP22_EN;
+ lnbp22->config[3] &= ~LNBP22_VSEL;
+ break;
+ case SEC_VOLTAGE_18:
+ lnbp22->config[3] |= LNBP22_EN|LNBP22_VSEL;
+ break;
+ default:
+ return -EINVAL; }
+
+ status = lnbp22_write_config(fe, lnbp22->config);
+ if( status == 0 ) {
+ u8 config[4];
+ int retries = 20;
+
+ /* byte 0: status
+ bit 3: open loop
+ bit 2: in progress/not ready
+ bit 1: over current limit
+ bit 0: over voltage limit */
+
+ /* wait up to 2 seconds for voltage to stablize.
+ It is important to wait that long, especially if there is a
+ rotor to power on, as DC/DC converter capacitors can take a
+ while to charge up and could cause a temporary overload */
+ do
+ {
+ msleep(50);
+ status = lnbp22_read_config(fe, config);
+ if( status < 0 )
+ return status;
+ }
+ while( (config[0] & (1<<2)) && retries-- );
- dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
- return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+ dprintk(1, "%s status=0x%02X\n", __FUNCTION__, config[0]);
+
+ if( retries < 0 )
+ return -EAGAIN; /* temporary overload ? */
+
+ if( config[0] & (1<<3) )
+ return -ENOLINK; /* open loop */
+ }
+ return status;
}
static int lnbp22_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
{
struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
- struct i2c_msg msg = {
- .addr = 0x08,
- .flags = 0,
- .buf = (char *)&lnbp22->config,
- .len = sizeof(lnbp22->config),
- };
dprintk(1, "%s: %d\n", __func__, (int)arg);
if (arg)
@@ -96,7 +144,7 @@
else
lnbp22->config[3] &= ~LNBP22_LLC;
- return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+ return lnbp22_write_config(fe, lnbp22->config);
}
static void lnbp22_release(struct dvb_frontend *fe)
@@ -118,20 +166,14 @@
return NULL;
/* default configuration */
- lnbp22->config[0] = 0x00; /* ? */
+ lnbp22->config[0] = 0x00; /* status */
lnbp22->config[1] = 0x28; /* ? */
- lnbp22->config[2] = 0x48; /* ? */
+ lnbp22->config[2] = 0x49; /* ? */
lnbp22->config[3] = 0x60; /* Power down */
lnbp22->i2c = i2c;
fe->sec_priv = lnbp22;
- /* detect if it is present or not */
- if (lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF)) {
- dprintk(0, "%s LNBP22 not found\n", __func__);
- kfree(lnbp22);
- fe->sec_priv = NULL;
- return NULL;
- }
+ lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF);
/* install release callback */
fe->ops.release_sec = lnbp22_release;