2015-08-05 17:22:42 +02:00
|
|
|
/*
|
|
|
|
* Driver for the ST LNBH25
|
|
|
|
*
|
|
|
|
* Copyright (C) 2014 Digital Devices GmbH
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* version 2 only, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301, USA
|
|
|
|
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
|
2020-08-29 15:32:42 +02:00
|
|
|
#include <media/dvb_frontend.h>
|
2015-08-05 17:22:42 +02:00
|
|
|
#include "lnbh25.h"
|
|
|
|
|
|
|
|
struct lnbh25 {
|
|
|
|
struct i2c_adapter *i2c;
|
|
|
|
u8 adr;
|
|
|
|
u8 reg[4];
|
|
|
|
u8 boost;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
|
|
|
|
{
|
|
|
|
struct i2c_msg msg = {.addr = adr, .flags = 0,
|
|
|
|
.buf = data, .len = len};
|
|
|
|
|
|
|
|
if (i2c_transfer(adap, &msg, 1) != 1) {
|
|
|
|
pr_err("lnbh25: i2c_write error\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lnbh25_write_regs(struct lnbh25 *lnbh, int reg, int len)
|
|
|
|
{
|
|
|
|
u8 d[5];
|
|
|
|
|
|
|
|
memcpy(&d[1], &lnbh->reg[reg], len);
|
|
|
|
d[0] = reg + 2;
|
|
|
|
return i2c_write(lnbh->i2c, lnbh->adr, d, len + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lnbh25_set_voltage(struct dvb_frontend *fe,
|
2017-09-26 21:18:04 +02:00
|
|
|
enum fe_sec_voltage voltage)
|
2015-08-05 17:22:42 +02:00
|
|
|
{
|
|
|
|
struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv;
|
|
|
|
u8 oldreg0 = lnbh->reg[0];
|
|
|
|
|
|
|
|
switch (voltage) {
|
|
|
|
case SEC_VOLTAGE_OFF:
|
|
|
|
lnbh->reg[0] = 0x00;
|
|
|
|
lnbh->reg[1] &= ~0x01; /* Disable Tone */
|
|
|
|
lnbh->reg[2] = 0x00;
|
|
|
|
return lnbh25_write_regs(lnbh, 0, 3);
|
|
|
|
case SEC_VOLTAGE_13:
|
|
|
|
lnbh->reg[0] = lnbh->boost + 1;
|
|
|
|
break;
|
|
|
|
case SEC_VOLTAGE_18:
|
|
|
|
lnbh->reg[0] = lnbh->boost + 8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (lnbh->reg[0] == 0x00) {
|
|
|
|
lnbh->reg[2] = 4;
|
|
|
|
lnbh25_write_regs(lnbh, 2, 2);
|
|
|
|
} else if (lnbh->reg[2] != 0x00) {
|
|
|
|
lnbh->reg[2] = 0;
|
|
|
|
lnbh25_write_regs(lnbh, 2, 2);
|
|
|
|
}
|
|
|
|
lnbh->reg[1] |= 0x01;
|
|
|
|
lnbh25_write_regs(lnbh, 0, 3);
|
|
|
|
if (oldreg0 == 0)
|
|
|
|
msleep(100);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
|
|
|
{
|
|
|
|
struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv;
|
|
|
|
|
|
|
|
lnbh->boost = arg ? 3 : 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-14 20:53:10 +01:00
|
|
|
#if 0
|
2015-08-05 17:22:42 +02:00
|
|
|
static int lnbh25_set_tone(struct dvb_frontend *fe,
|
2017-09-26 21:18:04 +02:00
|
|
|
enum fe_sec_tone_mode tone)
|
2015-08-05 17:22:42 +02:00
|
|
|
{
|
|
|
|
/* struct lnbh25 *lnbh = (struct lnbh25 *) fe->sec_priv; */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2019-02-14 20:53:10 +01:00
|
|
|
#endif
|
2015-08-05 17:22:42 +02:00
|
|
|
|
|
|
|
static int lnbh25_init(struct lnbh25 *lnbh)
|
|
|
|
{
|
|
|
|
return lnbh25_write_regs(lnbh, 0, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lnbh25_release(struct dvb_frontend *fe)
|
|
|
|
{
|
|
|
|
kfree(fe->sec_priv);
|
|
|
|
fe->sec_priv = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe,
|
|
|
|
struct i2c_adapter *i2c,
|
|
|
|
u8 adr)
|
|
|
|
{
|
|
|
|
struct lnbh25 *lnbh = kzalloc(sizeof(struct lnbh25), GFP_KERNEL);
|
|
|
|
if (!lnbh)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
lnbh->i2c = i2c;
|
|
|
|
lnbh->adr = adr;
|
|
|
|
lnbh->boost = 3;
|
|
|
|
|
|
|
|
if (lnbh25_init(lnbh)) {
|
|
|
|
kfree(lnbh);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
fe->sec_priv = lnbh;
|
|
|
|
fe->ops.set_voltage = lnbh25_set_voltage;
|
|
|
|
fe->ops.enable_high_lnb_voltage = lnbh25_enable_high_lnb_voltage;
|
|
|
|
fe->ops.release_sec = lnbh25_release;
|
|
|
|
|
2017-04-07 12:22:29 +02:00
|
|
|
pr_info("LNBH25 on %02x\n", lnbh->adr);
|
2015-08-05 17:22:42 +02:00
|
|
|
|
|
|
|
return fe;
|
|
|
|
}
|
2023-09-12 14:57:09 +02:00
|
|
|
EXPORT_SYMBOL_GPL(lnbh25_attach);
|
2015-08-05 17:22:42 +02:00
|
|
|
|
|
|
|
MODULE_DESCRIPTION("LNBH25");
|
|
|
|
MODULE_AUTHOR("Ralph Metzler");
|
2018-03-22 19:32:17 +01:00
|
|
|
MODULE_LICENSE("GPL v2");
|