2019-05-23 12:14:50 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2006-04-28 04:45:01 +04:00
/*
2009-03-03 17:24:18 +03:00
* lnbp21 . c - driver for lnb supply and control ic lnbp21
2006-04-28 04:45:01 +04:00
*
2009-12-13 14:58:38 +03:00
* Copyright ( C ) 2006 , 2009 Oliver Endriss < o . endriss @ gmx . de >
2009-03-03 17:24:18 +03:00
* Copyright ( C ) 2009 Igor M . Liplianin < liplianin @ netup . ru >
2006-04-28 04:45:01 +04:00
*
2015-12-04 15:38:59 +03:00
* the project ' s page is at https : //linuxtv.org
2006-04-28 04:45:01 +04:00
*/
# 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>
2017-12-28 21:03:51 +03:00
# include <media/dvb_frontend.h>
2006-04-28 04:45:01 +04:00
# include "lnbp21.h"
2009-03-03 17:24:18 +03:00
# include "lnbh24.h"
2006-04-28 04:45:01 +04:00
struct lnbp21 {
u8 config ;
u8 override_or ;
u8 override_and ;
struct i2c_adapter * i2c ;
2009-03-03 17:24:18 +03:00
u8 i2c_addr ;
2006-04-28 04:45:01 +04:00
} ;
2009-03-03 17:24:18 +03:00
static int lnbp21_set_voltage ( struct dvb_frontend * fe ,
2015-06-07 20:53:52 +03:00
enum fe_sec_voltage voltage )
2006-04-28 04:45:01 +04:00
{
2006-08-08 16:10:08 +04:00
struct lnbp21 * lnbp21 = ( struct lnbp21 * ) fe - > sec_priv ;
2009-03-03 17:24:18 +03:00
struct i2c_msg msg = { . addr = lnbp21 - > i2c_addr , . flags = 0 ,
2006-04-28 04:45:01 +04:00
. buf = & lnbp21 - > config ,
. len = sizeof ( lnbp21 - > config ) } ;
lnbp21 - > config & = ~ ( LNBP21_VSEL | LNBP21_EN ) ;
switch ( voltage ) {
case SEC_VOLTAGE_OFF :
break ;
case SEC_VOLTAGE_13 :
lnbp21 - > config | = LNBP21_EN ;
break ;
case SEC_VOLTAGE_18 :
lnbp21 - > config | = ( LNBP21_EN | LNBP21_VSEL ) ;
break ;
default :
return - EINVAL ;
2012-09-28 12:37:22 +04:00
}
2006-04-28 04:45:01 +04:00
lnbp21 - > config | = lnbp21 - > override_or ;
lnbp21 - > config & = lnbp21 - > override_and ;
return ( i2c_transfer ( lnbp21 - > i2c , & msg , 1 ) = = 1 ) ? 0 : - EIO ;
}
static int lnbp21_enable_high_lnb_voltage ( struct dvb_frontend * fe , long arg )
{
2006-08-08 16:10:08 +04:00
struct lnbp21 * lnbp21 = ( struct lnbp21 * ) fe - > sec_priv ;
2009-03-03 17:24:18 +03:00
struct i2c_msg msg = { . addr = lnbp21 - > i2c_addr , . flags = 0 ,
2006-04-28 04:45:01 +04:00
. buf = & lnbp21 - > config ,
. len = sizeof ( lnbp21 - > config ) } ;
if ( arg )
lnbp21 - > config | = LNBP21_LLC ;
else
lnbp21 - > config & = ~ LNBP21_LLC ;
lnbp21 - > config | = lnbp21 - > override_or ;
lnbp21 - > config & = lnbp21 - > override_and ;
return ( i2c_transfer ( lnbp21 - > i2c , & msg , 1 ) = = 1 ) ? 0 : - EIO ;
}
2009-12-13 14:58:38 +03:00
static int lnbp21_set_tone ( struct dvb_frontend * fe ,
2015-06-07 20:53:52 +03:00
enum fe_sec_tone_mode tone )
2009-12-13 14:58:38 +03:00
{
struct lnbp21 * lnbp21 = ( struct lnbp21 * ) fe - > sec_priv ;
struct i2c_msg msg = { . addr = lnbp21 - > i2c_addr , . flags = 0 ,
. buf = & lnbp21 - > config ,
. len = sizeof ( lnbp21 - > config ) } ;
switch ( tone ) {
case SEC_TONE_OFF :
lnbp21 - > config & = ~ LNBP21_TEN ;
break ;
case SEC_TONE_ON :
lnbp21 - > config | = LNBP21_TEN ;
break ;
default :
return - EINVAL ;
2012-09-28 12:37:22 +04:00
}
2009-12-13 14:58:38 +03:00
lnbp21 - > config | = lnbp21 - > override_or ;
lnbp21 - > config & = lnbp21 - > override_and ;
return ( i2c_transfer ( lnbp21 - > i2c , & msg , 1 ) = = 1 ) ? 0 : - EIO ;
}
2006-04-28 04:45:01 +04:00
static void lnbp21_release ( struct dvb_frontend * fe )
{
/* LNBP power off */
lnbp21_set_voltage ( fe , SEC_VOLTAGE_OFF ) ;
2006-08-08 16:10:08 +04:00
/* free data */
kfree ( fe - > sec_priv ) ;
fe - > sec_priv = NULL ;
2006-04-28 04:45:01 +04:00
}
2009-03-03 17:24:18 +03:00
static struct dvb_frontend * lnbx2x_attach ( struct dvb_frontend * fe ,
struct i2c_adapter * i2c , u8 override_set ,
u8 override_clear , u8 i2c_addr , u8 config )
2006-04-28 04:45:01 +04:00
{
struct lnbp21 * lnbp21 = kmalloc ( sizeof ( struct lnbp21 ) , GFP_KERNEL ) ;
if ( ! lnbp21 )
2006-08-08 16:10:08 +04:00
return NULL ;
2006-04-28 04:45:01 +04:00
/* default configuration */
2009-03-03 17:24:18 +03:00
lnbp21 - > config = config ;
2006-04-28 04:45:01 +04:00
lnbp21 - > i2c = i2c ;
2009-03-03 17:24:18 +03:00
lnbp21 - > i2c_addr = i2c_addr ;
2006-08-08 16:10:08 +04:00
fe - > sec_priv = lnbp21 ;
2006-04-28 04:45:01 +04:00
/* bits which should be forced to '1' */
lnbp21 - > override_or = override_set ;
/* bits which should be forced to '0' */
lnbp21 - > override_and = ~ override_clear ;
/* detect if it is present or not */
if ( lnbp21_set_voltage ( fe , SEC_VOLTAGE_OFF ) ) {
kfree ( lnbp21 ) ;
2006-08-08 16:10:08 +04:00
return NULL ;
2006-04-28 04:45:01 +04:00
}
/* install release callback */
2006-08-09 02:58:27 +04:00
fe - > ops . release_sec = lnbp21_release ;
2006-04-28 04:45:01 +04:00
/* override frontend ops */
2006-05-14 12:01:31 +04:00
fe - > ops . set_voltage = lnbp21_set_voltage ;
fe - > ops . enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage ;
2010-01-22 22:01:44 +03:00
if ( ! ( override_clear & LNBH24_TEN ) ) /*22kHz logic controlled by demod*/
2010-01-13 11:01:56 +03:00
fe - > ops . set_tone = lnbp21_set_tone ;
2009-05-23 04:07:46 +04:00
printk ( KERN_INFO " LNBx2x attached on addr=%x \n " , lnbp21 - > i2c_addr ) ;
2006-04-28 04:45:01 +04:00
2006-08-08 16:10:08 +04:00
return fe ;
2006-04-28 04:45:01 +04:00
}
2009-03-03 17:24:18 +03:00
2009-03-04 16:40:31 +03:00
struct dvb_frontend * lnbh24_attach ( struct dvb_frontend * fe ,
2009-03-03 17:24:18 +03:00
struct i2c_adapter * i2c , u8 override_set ,
u8 override_clear , u8 i2c_addr )
{
return lnbx2x_attach ( fe , i2c , override_set , override_clear ,
i2c_addr , LNBH24_TTX ) ;
}
EXPORT_SYMBOL ( lnbh24_attach ) ;
struct dvb_frontend * lnbp21_attach ( struct dvb_frontend * fe ,
struct i2c_adapter * i2c , u8 override_set ,
u8 override_clear )
{
return lnbx2x_attach ( fe , i2c , override_set , override_clear ,
0x08 , LNBP21_ISEL ) ;
}
2006-04-28 04:45:01 +04:00
EXPORT_SYMBOL ( lnbp21_attach ) ;
2009-03-03 17:24:18 +03:00
MODULE_DESCRIPTION ( " Driver for lnb supply and control ic lnbp21, lnbh24 " ) ;
MODULE_AUTHOR ( " Oliver Endriss, Igor M. Liplianin " ) ;
2006-04-28 04:45:01 +04:00
MODULE_LICENSE ( " GPL " ) ;