2006-04-27 21:45:01 -03:00
/*
2009-03-03 11:24:18 -03:00
* lnbp21 . c - driver for lnb supply and control ic lnbp21
2006-04-27 21:45:01 -03:00
*
2009-12-13 08:58:38 -03:00
* Copyright ( C ) 2006 , 2009 Oliver Endriss < o . endriss @ gmx . de >
2009-03-03 11:24:18 -03:00
* Copyright ( C ) 2009 Igor M . Liplianin < liplianin @ netup . ru >
2006-04-27 21:45:01 -03:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
*
* 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 .
*
2016-10-28 09:31:20 -02:00
* To obtain the license , point your browser to
* http : //www.gnu.org/copyleft/gpl.html
2006-04-27 21:45:01 -03:00
*
*
2015-12-04 10:38:59 -02:00
* the project ' s page is at https : //linuxtv.org
2006-04-27 21:45:01 -03: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>
# include "dvb_frontend.h"
# include "lnbp21.h"
2009-03-03 11:24:18 -03:00
# include "lnbh24.h"
2006-04-27 21:45:01 -03:00
struct lnbp21 {
u8 config ;
u8 override_or ;
u8 override_and ;
struct i2c_adapter * i2c ;
2009-03-03 11:24:18 -03:00
u8 i2c_addr ;
2006-04-27 21:45:01 -03:00
} ;
2009-03-03 11:24:18 -03:00
static int lnbp21_set_voltage ( struct dvb_frontend * fe ,
2015-06-07 14:53:52 -03:00
enum fe_sec_voltage voltage )
2006-04-27 21:45:01 -03:00
{
2006-08-08 09:10:08 -03:00
struct lnbp21 * lnbp21 = ( struct lnbp21 * ) fe - > sec_priv ;
2009-03-03 11:24:18 -03:00
struct i2c_msg msg = { . addr = lnbp21 - > i2c_addr , . flags = 0 ,
2006-04-27 21:45:01 -03: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 05:37:22 -03:00
}
2006-04-27 21:45:01 -03: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 09:10:08 -03:00
struct lnbp21 * lnbp21 = ( struct lnbp21 * ) fe - > sec_priv ;
2009-03-03 11:24:18 -03:00
struct i2c_msg msg = { . addr = lnbp21 - > i2c_addr , . flags = 0 ,
2006-04-27 21:45:01 -03: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 08:58:38 -03:00
static int lnbp21_set_tone ( struct dvb_frontend * fe ,
2015-06-07 14:53:52 -03:00
enum fe_sec_tone_mode tone )
2009-12-13 08: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 05:37:22 -03:00
}
2009-12-13 08: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-27 21:45:01 -03:00
static void lnbp21_release ( struct dvb_frontend * fe )
{
/* LNBP power off */
lnbp21_set_voltage ( fe , SEC_VOLTAGE_OFF ) ;
2006-08-08 09:10:08 -03:00
/* free data */
kfree ( fe - > sec_priv ) ;
fe - > sec_priv = NULL ;
2006-04-27 21:45:01 -03:00
}
2009-03-03 11: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-27 21:45:01 -03:00
{
struct lnbp21 * lnbp21 = kmalloc ( sizeof ( struct lnbp21 ) , GFP_KERNEL ) ;
if ( ! lnbp21 )
2006-08-08 09:10:08 -03:00
return NULL ;
2006-04-27 21:45:01 -03:00
/* default configuration */
2009-03-03 11:24:18 -03:00
lnbp21 - > config = config ;
2006-04-27 21:45:01 -03:00
lnbp21 - > i2c = i2c ;
2009-03-03 11:24:18 -03:00
lnbp21 - > i2c_addr = i2c_addr ;
2006-08-08 09:10:08 -03:00
fe - > sec_priv = lnbp21 ;
2006-04-27 21:45:01 -03: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 09:10:08 -03:00
return NULL ;
2006-04-27 21:45:01 -03:00
}
/* install release callback */
2006-08-08 19:58:27 -03:00
fe - > ops . release_sec = lnbp21_release ;
2006-04-27 21:45:01 -03:00
/* override frontend ops */
2006-05-14 05:01:31 -03:00
fe - > ops . set_voltage = lnbp21_set_voltage ;
fe - > ops . enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage ;
2010-01-22 16:01:44 -03:00
if ( ! ( override_clear & LNBH24_TEN ) ) /*22kHz logic controlled by demod*/
2010-01-13 05:01:56 -03:00
fe - > ops . set_tone = lnbp21_set_tone ;
2009-05-22 21:07:46 -03:00
printk ( KERN_INFO " LNBx2x attached on addr=%x \n " , lnbp21 - > i2c_addr ) ;
2006-04-27 21:45:01 -03:00
2006-08-08 09:10:08 -03:00
return fe ;
2006-04-27 21:45:01 -03:00
}
2009-03-03 11:24:18 -03:00
2009-03-04 10:40:31 -03:00
struct dvb_frontend * lnbh24_attach ( struct dvb_frontend * fe ,
2009-03-03 11: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-27 21:45:01 -03:00
EXPORT_SYMBOL ( lnbp21_attach ) ;
2009-03-03 11:24:18 -03:00
MODULE_DESCRIPTION ( " Driver for lnb supply and control ic lnbp21, lnbh24 " ) ;
MODULE_AUTHOR ( " Oliver Endriss, Igor M. Liplianin " ) ;
2006-04-27 21:45:01 -03:00
MODULE_LICENSE ( " GPL " ) ;