mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
linux: added lnbp22.c rotor patch
moved
This commit is contained in:
parent
a2750f5bfd
commit
16f12f05db
@ -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;
|
Loading…
x
Reference in New Issue
Block a user