2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-17 02:20:36 +04:00
/*
* Support for OR51211 ( pcHDTV HD - 2000 ) - VSB
*
* Copyright ( C ) 2005 Kirk Lapray < kirk_lapray @ bigfoot . com >
*
* Based on code from Jack Kelliher ( kelliher @ xmission . com )
* Copyright ( C ) 2002 & pcHDTV , inc .
*/
2012-12-18 17:20:28 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
2005-04-17 02:20:36 +04:00
/*
* This driver needs external firmware . Please use the command
2018-05-09 00:10:05 +03:00
* " <kerneldir>/scripts/get_dvb_firmware or51211 " to
2006-01-09 20:25:38 +03:00
* download / extract it , and then copy it to / usr / lib / hotplug / firmware
* or / lib / firmware ( depending on configuration of firmware hotplug ) .
2005-04-17 02:20:36 +04:00
*/
# define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/device.h>
# include <linux/firmware.h>
2005-10-31 02:03:48 +03:00
# include <linux/string.h>
# include <linux/slab.h>
2005-04-17 02:20:36 +04:00
# include <asm/byteorder.h>
2017-12-28 21:03:51 +03:00
# include <media/dvb_math.h>
# include <media/dvb_frontend.h>
2005-04-17 02:20:36 +04:00
# include "or51211.h"
static int debug ;
# define dprintk(args...) \
2012-12-18 17:20:28 +04:00
do { if ( debug ) pr_debug ( args ) ; } while ( 0 )
2005-04-17 02:20:36 +04:00
static u8 run_buf [ ] = { 0x7f , 0x01 } ;
static u8 cmd_buf [ ] = { 0x04 , 0x01 , 0x50 , 0x80 , 0x06 } ; // ATSC
struct or51211_state {
struct i2c_adapter * i2c ;
/* Configuration settings */
const struct or51211_config * config ;
struct dvb_frontend frontend ;
struct bt878 * bt ;
/* Demodulator private data */
u8 initialized : 1 ;
2019-02-18 22:28:55 +03:00
u32 snr ; /* Result of last SNR calculation */
2005-04-17 02:20:36 +04:00
/* Tuner private data */
u32 current_frequency ;
} ;
2008-05-24 03:12:23 +04:00
static int i2c_writebytes ( struct or51211_state * state , u8 reg , const u8 * buf ,
2005-04-17 02:20:36 +04:00
int len )
{
int err ;
struct i2c_msg msg ;
msg . addr = reg ;
msg . flags = 0 ;
msg . len = len ;
2008-05-24 03:12:23 +04:00
msg . buf = ( u8 * ) buf ;
2005-04-17 02:20:36 +04:00
if ( ( err = i2c_transfer ( state - > i2c , & msg , 1 ) ) ! = 1 ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error (addr %02x, err == %i) \n " , reg , err ) ;
2005-04-17 02:20:36 +04:00
return - EREMOTEIO ;
}
return 0 ;
}
2008-08-23 00:12:08 +04:00
static int i2c_readbytes ( struct or51211_state * state , u8 reg , u8 * buf , int len )
2005-04-17 02:20:36 +04:00
{
int err ;
struct i2c_msg msg ;
msg . addr = reg ;
msg . flags = I2C_M_RD ;
msg . len = len ;
msg . buf = buf ;
if ( ( err = i2c_transfer ( state - > i2c , & msg , 1 ) ) ! = 1 ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error (addr %02x, err == %i) \n " , reg , err ) ;
2005-04-17 02:20:36 +04:00
return - EREMOTEIO ;
}
return 0 ;
}
static int or51211_load_firmware ( struct dvb_frontend * fe ,
const struct firmware * fw )
{
struct or51211_state * state = fe - > demodulator_priv ;
u8 tudata [ 585 ] ;
int i ;
2014-09-25 03:35:12 +04:00
dprintk ( " Firmware is %zu bytes \n " , fw - > size ) ;
2005-04-17 02:20:36 +04:00
/* Get eprom data */
tudata [ 0 ] = 17 ;
if ( i2c_writebytes ( state , 0x50 , tudata , 1 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error eprom addr \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
if ( i2c_readbytes ( state , 0x50 , & tudata [ 145 ] , 192 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error eprom \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
/* Create firmware buffer */
for ( i = 0 ; i < 145 ; i + + )
tudata [ i ] = fw - > data [ i ] ;
for ( i = 0 ; i < 248 ; i + + )
tudata [ i + 337 ] = fw - > data [ 145 + i ] ;
state - > config - > reset ( fe ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address , tudata , 585 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 1 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 1 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address ,
& fw - > data [ 393 ] , 8125 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 2 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 1 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address , run_buf , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 3 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
/* Wait at least 5 msec */
msleep ( 10 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address , run_buf , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 4 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 10 ) ;
2012-12-18 17:20:28 +04:00
pr_info ( " Done. \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
} ;
static int or51211_setmode ( struct dvb_frontend * fe , int mode )
{
struct or51211_state * state = fe - > demodulator_priv ;
u8 rec_buf [ 14 ] ;
state - > config - > setmode ( fe , mode ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address , run_buf , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 1 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
/* Wait at least 5 msec */
msleep ( 10 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address , run_buf , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 2 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 10 ) ;
/* Set operation mode in Receiver 1 register;
* type 1 :
* data 0x50 h Automatic sets receiver channel conditions
* Automatic NTSC rejection filter
* Enable MPEG serial data output
* MPEG2tr
* High tuner phase noise
* normal + / - 150 kHz Carrier acquisition range
*/
if ( i2c_writebytes ( state , state - > config - > demod_address , cmd_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 3 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
rec_buf [ 0 ] = 0x04 ;
rec_buf [ 1 ] = 0x00 ;
rec_buf [ 2 ] = 0x03 ;
rec_buf [ 3 ] = 0x00 ;
msleep ( 20 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address , rec_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 5 \n " ) ;
2005-04-17 02:20:36 +04:00
}
msleep ( 3 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address , & rec_buf [ 10 ] , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error 6 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
2012-12-18 17:20:28 +04:00
dprintk ( " rec status %02x %02x \n " , rec_buf [ 10 ] , rec_buf [ 11 ] ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2011-12-26 22:02:20 +04:00
static int or51211_set_parameters ( struct dvb_frontend * fe )
2005-04-17 02:20:36 +04:00
{
2011-12-26 22:02:20 +04:00
struct dtv_frontend_properties * p = & fe - > dtv_property_cache ;
2005-04-17 02:20:36 +04:00
struct or51211_state * state = fe - > demodulator_priv ;
/* Change only if we are actually changing the channel */
2011-12-26 22:02:20 +04:00
if ( state - > current_frequency ! = p - > frequency ) {
2007-06-25 01:14:52 +04:00
if ( fe - > ops . tuner_ops . set_params ) {
2011-12-24 19:24:33 +04:00
fe - > ops . tuner_ops . set_params ( fe ) ;
2007-06-25 01:14:52 +04:00
if ( fe - > ops . i2c_gate_ctrl ) fe - > ops . i2c_gate_ctrl ( fe , 0 ) ;
2005-04-17 02:20:36 +04:00
}
/* Set to ATSC mode */
or51211_setmode ( fe , 0 ) ;
/* Update current frequency */
2011-12-26 22:02:20 +04:00
state - > current_frequency = p - > frequency ;
2005-04-17 02:20:36 +04:00
}
return 0 ;
}
2015-06-07 20:53:52 +03:00
static int or51211_read_status ( struct dvb_frontend * fe , enum fe_status * status )
2005-04-17 02:20:36 +04:00
{
struct or51211_state * state = fe - > demodulator_priv ;
unsigned char rec_buf [ 2 ] ;
unsigned char snd_buf [ ] = { 0x04 , 0x00 , 0x03 , 0x00 } ;
* status = 0 ;
/* Receiver Status */
if ( i2c_writebytes ( state , state - > config - > demod_address , snd_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " write error \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 3 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address , rec_buf , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " read error \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
2012-12-18 17:20:28 +04:00
dprintk ( " %x %x \n " , rec_buf [ 0 ] , rec_buf [ 1 ] ) ;
2005-04-17 02:20:36 +04:00
if ( rec_buf [ 0 ] & 0x01 ) { /* Receiver Lock */
* status | = FE_HAS_SIGNAL ;
* status | = FE_HAS_CARRIER ;
* status | = FE_HAS_VITERBI ;
* status | = FE_HAS_SYNC ;
* status | = FE_HAS_LOCK ;
}
return 0 ;
}
2006-12-05 00:04:16 +03:00
/* Calculate SNR estimation (scaled by 2^24)
2005-04-17 02:20:36 +04:00
2006-12-05 00:04:16 +03:00
8 - VSB SNR equation from Oren datasheets
2005-04-17 02:20:36 +04:00
2006-12-05 00:04:16 +03:00
For 8 - VSB :
SNR [ dB ] = 10 * log10 ( 219037.9454 / MSE ^ 2 )
2005-04-17 02:20:36 +04:00
2006-12-05 00:04:16 +03:00
We re - write the snr equation as :
SNR * 2 ^ 24 = 10 * ( c - 2 * intlog10 ( MSE ) )
Where for 8 - VSB , c = log10 ( 219037.9454 ) * 2 ^ 24 */
2005-04-17 02:20:36 +04:00
2006-12-05 00:04:16 +03:00
static u32 calculate_snr ( u32 mse , u32 c )
{
if ( mse = = 0 ) /* No signal */
return 0 ;
mse = 2 * intlog10 ( mse ) ;
if ( mse > c ) {
/* Negative SNR, which is possible, but realisticly the
demod will lose lock before the signal gets this bad . The
API only allows for unsigned values , so just return 0 */
return 0 ;
}
return 10 * ( c - mse ) ;
2005-04-17 02:20:36 +04:00
}
2006-12-05 00:04:16 +03:00
static int or51211_read_snr ( struct dvb_frontend * fe , u16 * snr )
2005-04-17 02:20:36 +04:00
{
struct or51211_state * state = fe - > demodulator_priv ;
u8 rec_buf [ 2 ] ;
2006-12-05 00:04:16 +03:00
u8 snd_buf [ 3 ] ;
2005-04-17 02:20:36 +04:00
/* SNR after Equalizer */
snd_buf [ 0 ] = 0x04 ;
snd_buf [ 1 ] = 0x00 ;
snd_buf [ 2 ] = 0x04 ;
if ( i2c_writebytes ( state , state - > config - > demod_address , snd_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " error writing snr reg \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
if ( i2c_readbytes ( state , state - > config - > demod_address , rec_buf , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " read_status read error \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
2006-12-05 00:04:16 +03:00
state - > snr = calculate_snr ( rec_buf [ 0 ] , 89599047 ) ;
* snr = ( state - > snr ) > > 16 ;
2012-12-18 17:20:28 +04:00
dprintk ( " noise = 0x%02x, snr = %d.%02d dB \n " , rec_buf [ 0 ] ,
2006-12-05 00:04:16 +03:00
state - > snr > > 24 , ( ( ( state - > snr > > 8 ) & 0xffff ) * 100 ) > > 16 ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-12-05 00:04:16 +03:00
static int or51211_read_signal_strength ( struct dvb_frontend * fe , u16 * strength )
2005-04-17 02:20:36 +04:00
{
2006-12-05 00:04:16 +03:00
/* Calculate Strength from SNR up to 35dB */
/* Even though the SNR can go higher than 35dB, there is some comfort */
/* factor in having a range of strong signals that can show at 100% */
struct or51211_state * state = ( struct or51211_state * ) fe - > demodulator_priv ;
u16 snr ;
int ret ;
ret = fe - > ops . read_snr ( fe , & snr ) ;
if ( ret ! = 0 )
return ret ;
/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
/* scale the range 0 - 35*2^24 into 0 - 65535 */
if ( state - > snr > = 8960 * 0x10000 )
* strength = 0xffff ;
else
* strength = state - > snr / 8960 ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int or51211_read_ber ( struct dvb_frontend * fe , u32 * ber )
{
* ber = - ENOSYS ;
return 0 ;
}
static int or51211_read_ucblocks ( struct dvb_frontend * fe , u32 * ucblocks )
{
* ucblocks = - ENOSYS ;
return 0 ;
}
static int or51211_sleep ( struct dvb_frontend * fe )
{
return 0 ;
}
static int or51211_init ( struct dvb_frontend * fe )
{
struct or51211_state * state = fe - > demodulator_priv ;
const struct or51211_config * config = state - > config ;
const struct firmware * fw ;
unsigned char get_ver_buf [ ] = { 0x04 , 0x00 , 0x30 , 0x00 , 0x00 } ;
unsigned char rec_buf [ 14 ] ;
int ret , i ;
if ( ! state - > initialized ) {
/* Request the firmware, this will block until it uploads */
2012-12-18 17:20:28 +04:00
pr_info ( " Waiting for firmware upload (%s)... \n " ,
OR51211_DEFAULT_FIRMWARE ) ;
2005-04-17 02:20:36 +04:00
ret = config - > request_firmware ( fe , & fw ,
OR51211_DEFAULT_FIRMWARE ) ;
2012-12-18 17:20:28 +04:00
pr_info ( " Got Hotplug firmware \n " ) ;
2005-04-17 02:20:36 +04:00
if ( ret ) {
[media] dvb-frontends: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 22:44:22 +03:00
pr_warn ( " No firmware uploaded (timeout or file not found?) \n " ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
ret = or51211_load_firmware ( fe , fw ) ;
2006-07-10 15:44:09 +04:00
release_firmware ( fw ) ;
2005-04-17 02:20:36 +04:00
if ( ret ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Writing firmware to device failed! \n " ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
2012-12-18 17:20:28 +04:00
pr_info ( " Firmware upload complete. \n " ) ;
2005-04-17 02:20:36 +04:00
/* Set operation mode in Receiver 1 register;
* type 1 :
* data 0x50 h Automatic sets receiver channel conditions
* Automatic NTSC rejection filter
* Enable MPEG serial data output
* MPEG2tr
* High tuner phase noise
* normal + / - 150 kHz Carrier acquisition range
*/
if ( i2c_writebytes ( state , state - > config - > demod_address ,
cmd_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error 5 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
/* Read back ucode version to besure we loaded correctly */
/* and are really up and running */
rec_buf [ 0 ] = 0x04 ;
rec_buf [ 1 ] = 0x00 ;
rec_buf [ 2 ] = 0x03 ;
rec_buf [ 3 ] = 0x00 ;
msleep ( 30 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address ,
rec_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error A \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 3 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address ,
& rec_buf [ 10 ] , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error B \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
rec_buf [ 0 ] = 0x04 ;
rec_buf [ 1 ] = 0x00 ;
rec_buf [ 2 ] = 0x01 ;
rec_buf [ 3 ] = 0x00 ;
msleep ( 20 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address ,
rec_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error C \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 3 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address ,
& rec_buf [ 12 ] , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error D \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
for ( i = 0 ; i < 8 ; i + + )
rec_buf [ i ] = 0xed ;
for ( i = 0 ; i < 5 ; i + + ) {
msleep ( 30 ) ;
get_ver_buf [ 4 ] = i + 1 ;
if ( i2c_writebytes ( state , state - > config - > demod_address ,
get_ver_buf , 5 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error 6 - %d \n " , i ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 3 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address ,
& rec_buf [ i * 2 ] , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error 7 - %d \n " , i ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
/* If we didn't receive the right index, try again */
if ( ( int ) rec_buf [ i * 2 + 1 ] ! = i + 1 ) {
i - - ;
}
}
2012-12-18 05:10:00 +04:00
dprintk ( " read_fwbits %10ph \n " , rec_buf ) ;
2005-04-17 02:20:36 +04:00
2012-12-18 17:20:28 +04:00
pr_info ( " ver TU%02x%02x%02x VSB mode %02x Status %02x \n " ,
rec_buf [ 2 ] , rec_buf [ 4 ] , rec_buf [ 6 ] , rec_buf [ 12 ] ,
rec_buf [ 10 ] ) ;
2005-04-17 02:20:36 +04:00
rec_buf [ 0 ] = 0x04 ;
rec_buf [ 1 ] = 0x00 ;
rec_buf [ 2 ] = 0x03 ;
rec_buf [ 3 ] = 0x00 ;
msleep ( 20 ) ;
if ( i2c_writebytes ( state , state - > config - > demod_address ,
rec_buf , 3 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error 8 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
msleep ( 20 ) ;
if ( i2c_readbytes ( state , state - > config - > demod_address ,
& rec_buf [ 8 ] , 2 ) ) {
2012-12-18 17:20:28 +04:00
pr_warn ( " Load DVR Error 9 \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
state - > initialized = 1 ;
}
return 0 ;
}
static int or51211_get_tune_settings ( struct dvb_frontend * fe ,
struct dvb_frontend_tune_settings * fesettings )
{
fesettings - > min_delay_ms = 500 ;
fesettings - > step_size = 0 ;
fesettings - > max_drift = 0 ;
return 0 ;
}
static void or51211_release ( struct dvb_frontend * fe )
{
struct or51211_state * state = fe - > demodulator_priv ;
state - > config - > sleep ( fe ) ;
kfree ( state ) ;
}
2016-08-10 00:32:21 +03:00
static const struct dvb_frontend_ops or51211_ops ;
2005-04-17 02:20:36 +04:00
struct dvb_frontend * or51211_attach ( const struct or51211_config * config ,
struct i2c_adapter * i2c )
{
struct or51211_state * state = NULL ;
/* Allocate memory for the internal state */
2009-08-11 05:51:01 +04:00
state = kzalloc ( sizeof ( struct or51211_state ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( state = = NULL )
2008-01-07 16:45:47 +03:00
return NULL ;
2005-04-17 02:20:36 +04:00
/* Setup the state */
state - > config = config ;
state - > i2c = i2c ;
state - > initialized = 0 ;
state - > current_frequency = 0 ;
/* Create dvb_frontend */
2006-05-14 12:01:31 +04:00
memcpy ( & state - > frontend . ops , & or51211_ops , sizeof ( struct dvb_frontend_ops ) ) ;
2005-04-17 02:20:36 +04:00
state - > frontend . demodulator_priv = state ;
return & state - > frontend ;
}
2016-08-10 00:32:21 +03:00
static const struct dvb_frontend_ops or51211_ops = {
2011-12-26 22:02:20 +04:00
. delsys = { SYS_ATSC , SYS_DVBC_ANNEX_B } ,
2005-04-17 02:20:36 +04:00
. info = {
2018-07-06 01:59:36 +03:00
. name = " Oren OR51211 VSB Frontend " ,
. frequency_min_hz = 44 * MHz ,
. frequency_max_hz = 958 * MHz ,
. frequency_stepsize_hz = 166666 ,
2005-04-17 02:20:36 +04:00
. caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_8VSB
} ,
. release = or51211_release ,
. init = or51211_init ,
. sleep = or51211_sleep ,
2011-12-26 22:02:20 +04:00
. set_frontend = or51211_set_parameters ,
2005-04-17 02:20:36 +04:00
. get_tune_settings = or51211_get_tune_settings ,
. read_status = or51211_read_status ,
. read_ber = or51211_read_ber ,
. read_signal_strength = or51211_read_signal_strength ,
. read_snr = or51211_read_snr ,
. read_ucblocks = or51211_read_ucblocks ,
} ;
module_param ( debug , int , 0644 ) ;
MODULE_PARM_DESC ( debug , " Turn on/off frontend debugging (default:off). " ) ;
MODULE_DESCRIPTION ( " Oren OR51211 VSB [pcHDTV HD-2000] Demodulator Driver " ) ;
MODULE_AUTHOR ( " Kirk Lapray " ) ;
MODULE_LICENSE ( " GPL " ) ;
EXPORT_SYMBOL ( or51211_attach ) ;