[linux-dvb] [PATCH] Add support for LGDT3303 VSB/QAM Frontend ( LG 5th Gen Chipset)

Mac Michaels wmichaels1 at earthlink.net
Sun Jul 10 16:40:17 CEST 2005


I glanced at the 3303 part of the driver and I think is 
reasonable to combine them. I have not examined the card 
level stuff yet. Give me a couple of days and I'll post a 
patch everyone can try.

-- Mac

On Sunday 10 July 2005 01:16 am, Michael Krufky wrote:
> Tylor and Mac-
>
> Check out this web page:
>
> http://www.fortetw.com/en/Product_vsb.htm
>
> ... It has the following:
>
> <<
> The VSB/QAM Receiver is a highly upgraded single chip
> that supports both ATSC terrestrial and digital cable
> broadcast environment. The LGDT3302 and LGDT3303 enable
> to demodulate, equalize, and correct signals of ATSC
> compliant 8/16 VSB and ITU-T J.83 Annex B,C compliant
> 64/256 QAM
>
> [ LGDT3302 ]
> - ATSC compliant 8/16 VSB and MMDS 2/4/6/8/16 VSB
> receiver - ITU-T J.83 Annex B compliant 64/256 Qam
> receiver - Integrated 10-bit A/D converter
> - Parallel/serial MPEG-2 transport interface
> - Support I2C bus interface
> - Embedded 64KB SRAM for VSB and 64/256 QAM
> - Supports 44MHz IF input as well as 6MHz IF input
> - 100 TQFP
> [ LGDT3303 ]
> - 5th Generation VSB/QAM receiver
> - Enhanced Multi-Ghost cancellation
> - Pin-to-pin compatable with LGDT3302
>
>
> This last line makes me think that these two drivers can
> be combined into a single LGDT330X module.... What do you
> guys think?
>
> I also saw the following in Google cache, (website
> deleted), if anyone reading the list is interested:
>
> <<
> The VSB/QAM receiver (LGDT3302) is a highly upgraded
> single chip that supports both north American digital
> terrestrial broadcast television and digital cable
> television standards. This LGDT3302 enables to
> demodulate, equalize and correct signals of ATSC
> compliant 8/16 VSB and ITU-T J.83 Annex B compliant
> 64/256 QAM.
>
> The 10-bit ADC is integrated in this chip in order to
> simplify system design and achieve better performance.
> The LGDT3302 accepts a VSB or QAM modulated analog signal
> of 44MHz IF or 6MHz low IF, which is sampled by 25MHz
> clock, and delivers a transport stream by parallel or
> serial.
>
> The 64 KB SRAM is embedded to support all modes of
> de-interleaving in 64/256 QAM. There is no need to use
> external memory for de-interleaver.
>
> The thermal characteristics of the former product,
> Advanced VSB receiver (LGDT3301), has been confirmed
> already in several products and become an unique feature
> of our chips. This attribute is materialized with this
> new chip too.
>
> ATSC compliant 8/16 VSB and MMDS 2/4/8/16 VSB receiver
>
> ITU-T J.83 Annex B compliant 64/256 QAM receiver
>
> Integrated 10-bit A/D converter
>
>    (supports for optional external A/D converter)
>
> All digital demodulation
>
>  Parallel/serial MPEG-2 transport interface
>
>  Supports I2C bus interface
>
>  Boundary Scan test  circuit complies to the IEEE
> Std.1149.1
>
> Highly integrated solution for the lowest system cost
>
>  Embedded 64KB SRAM for VSB and 64/256QAM
>   (No need to use external de-interleaver SRAM)
>
>  Supports 44MHz IF input as well as low IF input(6MHz) 
> 100 pin TQFP
>
>  Operating voltage(I/O, Core): 3.3V, 1.8V
>
> Taylor Jacob wrote:
>  >This patch adds support for the LGDT3303 VSB/QAM
>  > chipset.  I used the
>
> same SNR
>
>  >code as the LGDT3302 chipset that was recently added to
>  > cvs.  Any
>
> questions
>
>  >please feel free to ask.  This will add support for the
>  > BBTI Air2PC
>
> card due to
>
>  >ship very soon that utilizes this chipset.
>  >
>  >Taylor Jacob
>  >
>  >
>  >
>  >/*
>  >    Support for BBTI Technisat Air2PC - ATSC - 3rd Gen
>  >
>  >    Copyright (C) 2005 Taylor Jacob
>  > <rtjacob at earthlink.net>
>  >
>  >    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.
>  >
>  >    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., 675 Mass Ave,
>  > Cambridge, MA 02139, USA.
>  >
>  >*/
>  >
>  >#include <linux/init.h>
>  >#include <linux/module.h>
>  >#include <linux/moduleparam.h>
>  >#include <linux/device.h>
>  >#include <linux/kernel.h>
>  >#include <asm/div64.h>
>  >
>  >#include "dvb_frontend.h"
>  >#include "lgdt3303.h"
>  >
>  >struct lgdt3303_state {
>  >
>  >    struct i2c_adapter* i2c;
>  >    struct dvb_frontend_ops ops;
>  >    const struct lgdt3303_config* config;
>  >    struct dvb_frontend frontend;
>  >    u8 current_modulation;
>  >
>  >    /* demodulator private data */
>  >    u8 initialised:1;
>  >};
>  >
>  >static int debug;
>  >#define dprintk(args...) \
>  >    do { \
>  >        if (debug) printk(KERN_DEBUG "lgdt3303: "
>  > args); \ } while (0)
>  >
>  >static int i2c_writebytes (struct lgdt3303_state*
>  > state, u8 reg, u8
>
> *buf, u8 len)
>
>  >{
>  >    /* probbably a much better way or doing this */
>  >    u8 buf2 [256],x;
>  >    int err;
>  >    struct i2c_msg msg = { .addr =
>  > state->config->demod_address,
>
> .flags = 0, .buf = buf2, .len = len + 1 };
>
>  >    buf2[0] = reg;
>  >    for (x = 0 ; x < len ; x++)
>  >        buf2[x+1] = buf[x];
>  >
>  >    if ((err = i2c_transfer (state->i2c, &msg, 1)) !=
>  > 1) { printk ("%s: i2c write error (addr %02x, err ==
>  > %i)\n", __FUNCTION__, state->config->demod_address,
>  > err); return -EREMOTEIO;
>  >    }
>  >
>  >    return 0;
>  >}
>  >
>  >static int i2c_tunerwritebytes (struct lgdt3303_state*
>  > state, u8 *buf,
>
> u8 len)
>
>  >{
>  >    /* probbably a much better way or doing this */
>  >    int err;
>  >    struct i2c_msg msg = { .addr =
>  > state->config->tuner_address,
>
> .flags = 0, .buf = buf, .len = len };
>
>  >    if ((err = i2c_transfer (state->i2c, &msg, 1)) !=
>  > 1) { printk ("%s: i2c write error (addr %02x, err ==
>  > %i)\n", __FUNCTION__, state->config->demod_address,
>  > err); return -EREMOTEIO;
>  >    }
>  >
>  >    return 0;
>  >}
>  >
>  >static u8 i2c_readbytes (struct lgdt3303_state* state,
>  > u8 reg, u8*
>
> buf, u8 len)
>
>  >{
>  >    u8 reg2 [] = { reg };
>  >
>  >    struct i2c_msg msg [] = { { .addr =
>  > state->config->demod_address,
>
> .flags = 0, .buf = reg2, .len = 1 },
>
>  >            { .addr = state->config->demod_address,
>  > .flags = I2C_M_RD,
>
> .buf = buf, .len = len } };
>
>  >    int err;
>  >
>  >    if ((err = i2c_transfer (state->i2c, msg, 2)) != 2)
>  > { printk ("%s: i2c read error (addr %02x, err ==
>  > %i)\n", __FUNCTION__, state->config->demod_address,
>  > err); return -EREMOTEIO;
>  >    }
>  >
>  >    return 0;
>  >}
>  >
>  >static void lgdt3303_soft_reset(struct lgdt3303_state*
>  > state) {
>  >    u8 buf;
>  >    dprintk("%s\n", __FUNCTION__);
>  >
>  >    buf = 0x00;
>  >    i2c_writebytes(state,0x02,&buf,1);
>  >
>  >    buf = 0x01;
>  >    i2c_writebytes(state,0x02,&buf,1);
>  >
>  >    return;
>  >}
>  >
>  >static int lgdt3303_setup_frontend_parameters (struct
>  > dvb_frontend* fe, struct dvb_frontend_parameters *p) {
>  >    struct lgdt3303_state* state =
>  > fe->demodulator_priv; u32 freq = 0;
>  >    u16 tunerfreq = 0;
>  >    u8 buf[6];
>  >
>  >    freq = 44000000 + p->frequency;
>  >
>  >
>  >    tunerfreq = freq / 62500;
>  >
>  >    buf[0] = (tunerfreq >> 8) & 0x7F;
>  >    buf[1] = (tunerfreq & 0xFF);
>  >    buf[2] = 0x86;
>  >
>  >    if (p->frequency < 160000000) {
>  >        buf[3] = 0x01;
>  >    } else if (p->frequency > 445000000) {
>  >        buf[3] = 0x04;
>  >    } else {
>  >        buf[3] = 0x02;
>  >    }
>  >
>  >    /* Cut and paste from BBTI Windows driver
>  > Important? */ buf[4] = buf[2] | 0x18;
>  >    buf[5] = 0x50;
>  >
>  >    i2c_tunerwritebytes(state,buf,4);
>  >
>  >    i2c_tunerwritebytes(state,&buf[4],2);
>  >
>  >    /* invert clock */
>  >    buf[0] = 0xF3;
>  >    i2c_writebytes(state,0x87,buf,1);
>  >
>  >    state->current_modulation = p->u.vsb.modulation;
>  >
>  >    switch (p->u.vsb.modulation)
>  >    {
>  >        case VSB_8:
>  >                buf[0] = 0x03;
>  >                i2c_writebytes(state,0x00,buf,1);
>  >                buf[0] = 0x40;
>  >                i2c_writebytes(state,0x0d,buf,1);
>  >                buf[0] = 0x87;
>  >                i2c_writebytes(state,0x0e,buf,1);
>  >                buf[0] = 0x8e;
>  >                i2c_writebytes(state,0x0f,buf,1);
>  >                buf[0] = 0x01;
>  >                i2c_writebytes(state,0x10,buf,1);
>  >                buf[0] = 0x88;
>  >                i2c_writebytes(state,0x47,buf,1);
>  >                buf[0] = 0x14;
>  >                i2c_writebytes(state,0x4c,buf,1);
>  >                break;
>  >
>  >        case QAM_64:
>  >                buf[0] = 0x00;
>  >                i2c_writebytes(state,0x00,buf,1);
>  >                i2c_writebytes(state,0x0d,buf,1);
>  >                i2c_writebytes(state,0x0e,buf,1);
>  >                i2c_writebytes(state,0x0f,buf,1);
>  >                i2c_writebytes(state,0x10,buf,1);
>  >                buf[0] = 0x63;
>  >                i2c_writebytes(state,0x51,buf,1);
>  >                buf[0] = 0x66;
>  >                i2c_writebytes(state,0x47,buf,1);
>  >                buf[0] = 0x66;
>  >                i2c_writebytes(state,0x48,buf,1);
>  >                buf[0] = 0x1a;
>  >                i2c_writebytes(state,0x4d,buf,1);
>  >                buf[0] = 0x14;
>  >                i2c_writebytes(state,0x4c,buf,1);
>  >                buf[0] = 0x08;
>  >                i2c_writebytes(state,0x49,buf,1);
>  >                buf[0] = 0x9b;
>  >                i2c_writebytes(state,0x4a,buf,1);
>  >                break;
>  >
>  >        case QAM_256:
>  >                buf[0] = 0x01;
>  >                i2c_writebytes(state,0x00,buf,1);
>  >                buf[0] = 0x00;
>  >                i2c_writebytes(state,0x0d,buf,1);
>  >                i2c_writebytes(state,0x0e,buf,1);
>  >                i2c_writebytes(state,0x0f,buf,1);
>  >                i2c_writebytes(state,0x10,buf,1);
>  >                buf[0] = 0x63;
>  >                i2c_writebytes(state,0x51,buf,1);
>  >                buf[0] = 0x66;
>  >                i2c_writebytes(state,0x47,buf,1);
>  >                buf[0] = 0x66;
>  >                i2c_writebytes(state,0x48,buf,1);
>  >                buf[0] = 0x1a;
>  >                i2c_writebytes(state,0x4d,buf,1);
>  >                buf[0] = 0x14;
>  >                i2c_writebytes(state,0x4c,buf,1);
>  >                buf[0] = 0x08;
>  >                i2c_writebytes(state,0x49,buf,1);
>  >                buf[0] = 0x9b;
>  >                i2c_writebytes(state,0x4a,buf,1);
>  >                break;
>  >        default:
>  >                break;
>  >    }
>  >
>  >    lgdt3303_soft_reset(state);
>  >
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_read_status(struct dvb_frontend*
>  > fe, fe_status_t*
>
> status)
>
>  >{
>  >    struct lgdt3303_state* state =
>  > fe->demodulator_priv; u8 lock;
>  >    *status = 0;
>  >
>  >    i2c_readbytes(state,0x1C,&lock,1);
>  >    if (lock & 0x80) {
>  >        *status |= FE_HAS_SIGNAL;
>  >        *status |= FE_HAS_CARRIER;
>  >    }
>  >
>  >    i2c_readbytes(state,0x58,&lock,1);
>  >    if (lock & 0x01) {
>  >        *status |= FE_HAS_VITERBI;
>  >    }
>  >
>  >    if (lock & 0x02) {
>  >        *status |= FE_HAS_SYNC;
>  >        *status |= FE_HAS_LOCK;
>  >    }
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_read_ber(struct dvb_frontend* fe,
>  > u32* ber) {
>  >
>  >    /* Not implimented in frontend */
>  >    *ber = 0;
>  >
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_read_signal_strength(struct
>  > dvb_frontend* fe, u16*
>
> strength)
>
>  >{
>  >    struct lgdt3303_state* state =
>  > fe->demodulator_priv; u8 b[] = {0,0,0};
>  >    u16 temp = 0;
>  >
>  >    i2c_readbytes(state,0x52,&b[0],1);
>  >    i2c_readbytes(state,0x54,&b[1],1);
>  >
>  >    /* This math was given from example from the
>  > windows bbti driver */ temp = 1700 - ((b[0] & 0x07) <<
>  > 8 | b[1]);
>  >
>  >    *strength = temp * (0xFFFF/1700);
>  >
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_read_snr(struct dvb_frontend* fe,
>  > u16* snr) {
>  >
>  >    struct lgdt3303_state* state =
>  > fe->demodulator_priv; u8 b[] = {0,0,0};
>  >    u32 noise = 0;
>  >
>  >    /* This code cut and pasted from the LGDT3302.C
>  > driver and ought * to be put in a common place at some
>  > point */
>  >
>  >    /*
>  >     * Spec sheet shows formula for SNR_EQ = 10
>  > log10(25 * 24**2 / noise) * and SNR_PH = 10 log10(25 *
>  > 32**2 / noise) for equalizer and
>
> phase tracker
>
>  >     * respectively. The following tables are built on
>  > these formulas. * The usual definition is SNR = 20
>  > log10(signal/noise) * If the specification is wrong
>  > the value retuned is 1/2 the
>
> actual SNR in db.
>
>  >     *
>  >     * This table is a an ordered list of noise values
>  > computed by the * formula from the spec sheet such
>  > that the index into the table * starting at 43 or 45
>  > is the SNR value in db. There are
>
> duplicate noise
>
>  >     * value entries at the beginning because the SNR
>  > varies more than * 1 db for a change of 1 digit in
>  > noise at very small values of
>
> noise.
>
>  >     *
>  >     * Examples from SNR_EQ table:
>  >     * noise SNR
>  >     *   0    43
>  >     *   1    42
>  >     *   2    39
>  >     *   3    37
>  >     *   4    36
>  >     *   5    35
>  >     *   6    34
>  >     *   7    33
>  >     *   8    33
>  >     *   9    32
>  >     *   10   32
>  >     *   11   31
>  >     *   12   31
>  >     *   13   30
>  >     */
>  >
>  >    static const u32 SNR_EQ[] =
>  >        { 1,     2,      2,      2, 3,      3,      4, 
>  >    4,
>
> 5,     7,
>
>  >          9,     11,     13,     17, 21,     26,    
>  > 33,    41,
>
> 52,    65,
>
>  >          81,    102,    129,    162, 204,    257,   
>  > 323,   406,
>
> 511,   644,
>
>  >          810,   1020,   1284,   1616, 2035,   2561,  
>  > 3224,  4059,
>
> 5110,  6433,
>
>  >          8098,  10195,  12835,  16158, 20341,  25608, 
>  > 32238, 40585,
>
> 51094, 64323,
>
>  >          80978, 101945, 128341, 161571, 203406,
>  > 256073, 0x40000 };
>  >
>  >    static const u32 SNR_PH[] =
>  >        { 1,     2,      2,      2,      3,      3,    
>  > 4,     5,
>
> 6,     8,
>
>  >          10,    12,     15,     19,     23,     29,
>  > 37,    46,
>
> 58,    73,
>
>  >          91,    115,    144,    182,    229,    288,
>  > 362,   456,
>
> 574,   722,
>
>  >          909,   1144,   1440,   1813,   2282,   2873,
>  > 3617,  4553,
>
> 5732,  7216,
>
>  >          9084,  11436,  14396,  18124,  22817,  28724,
>  >  36161, 45524,
>
> 57312, 72151,
>
>  >          90833, 114351, 143960, 181235, 228161,
>  > 0x040000 };
>  >
>  >    static u32 snr_db;  /* index into SNR_EQ[] */
>  >
>  >    if (state->current_modulation == VSB_8) {
>  >
>  >        /* Equalizer Mean-Square Error Register for VSB
>  > */
>  >
>  >        i2c_readbytes(state,0x6E,&b[0],1);
>  >        i2c_readbytes(state,0x71,&b[1],1);
>  >        i2c_readbytes(state,0x72,&b[2],1);
>  >
>  >        noise = ((b[0] & 0x07) << 16) | (b[1] << 8) |
>  > b[2];
>  >
>  >        /*
>  >         * Look up noise value in table.
>  >         * A better search algorithm could be used...
>  >         * watch out there are duplicate entries.
>  >         */
>  >        for (snr_db = 0; snr_db < sizeof(SNR_EQ);
>  > snr_db++) { if (noise < SNR_EQ[snr_db]) {
>  >                *snr = (43 - snr_db) * (0xFFFF/43);
>  >
>  >                break;
>  >            }
>  >        }
>  >    } else {
>  >        /* Phase Tracker Mean-Square Error Register for
>  > QAM */
>  >
>  >        i2c_readbytes(state,0x6F,&b[0],1);
>  >        i2c_readbytes(state,0x70,&b[1],1);
>  >        i2c_readbytes(state,0x71,&b[2],1);
>  >        noise = ((b[0] & 7<<3) << 13) | (b[1] << 8) |
>  > b[2];
>  >
>  >        /* Look up noise value in table. */
>  >        for (snr_db = 0; snr_db < sizeof(SNR_PH);
>  > snr_db++) { if (noise < SNR_PH[snr_db]) {
>  >                *snr = (45 - snr_db) * (0xFFFF/45);
>  >                break;
>  >            }
>  >        }
>  >    }
>  >
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_read_ucblocks(struct dvb_frontend*
>  > fe, u32* ucblocks) {
>  >    struct lgdt3303_state* state =
>  > fe->demodulator_priv; u8 b[] = {0,0,0};
>  >
>  >    i2c_readbytes(state,0x8B,&b[0],1);
>  >    i2c_readbytes(state,0x8C,&b[1],1);
>  >
>  >    *ucblocks = (b[0] << 8) | b[1];
>  >
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_sleep(struct dvb_frontend* fe)
>  >{
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_init(struct dvb_frontend* fe)
>  >{
>  >    return 0;
>  >}
>  >
>  >static int lgdt3303_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 lgdt3303_release(struct dvb_frontend* fe)
>  >{
>  >    struct lgdt3303_state* state =
>  > fe->demodulator_priv; kfree(state);
>  >}
>  >
>  >static struct dvb_frontend_ops lgdt3303_ops;
>  >
>  >struct dvb_frontend* lgdt3303_attach(const struct
>  > lgdt3303_config* config, struct i2c_adapter* i2c)
>  >{
>  >    struct lgdt3303_state* state = NULL;
>  >    u8 buf = 0;
>  >
>  >    /* allocate memory for the internal state */
>  >    state = kmalloc(sizeof(struct lgdt3303_state),
>  > GFP_KERNEL); if (state == NULL) goto error;
>  >
>  >    /* setup the state */
>  >    state->config = config;
>  >    state->i2c = i2c;
>  >    state->current_modulation = VSB_8;
>  >    memcpy(&state->ops, &lgdt3303_ops, sizeof(struct
>  > dvb_frontend_ops));
>  >
>  >    i2c_readbytes(state, 0x85, &buf, 1);
>  >    if (buf != 0x20) goto error;
>  >
>  >    i2c_readbytes(state, 0x86, &buf, 1);
>  >    if (buf != 0x40) goto error;
>  >
>  >    /* create dvb_frontend */
>  >    state->frontend.ops = &state->ops;
>  >    state->frontend.demodulator_priv = state;
>  >    return &state->frontend;
>  >
>  >error:
>  >    kfree(state);
>  >    return NULL;
>  >}
>  >
>  >static struct dvb_frontend_ops lgdt3303_ops = {
>  >
>  >    .info = {
>  >        .name = "LGDT3303 VSB/QAM frontend",
>  >        .type = FE_ATSC,
>  >        .frequency_min =  54000000,
>  >        .frequency_max = 860000000,
>  >                /* stepsize is just a guess */
>  >        .frequency_stepsize = 166666,
>  >        .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 | FE_CAN_QAM_64 |
>  > FE_CAN_QAM_256 },
>  >
>  >    .release = lgdt3303_release,
>  >
>  >    .init = lgdt3303_init,
>  >    .sleep = lgdt3303_sleep,
>  >
>  >    .set_frontend = lgdt3303_setup_frontend_parameters,
>  >    .get_tune_settings = lgdt3303_get_tune_settings,
>  >
>  >    .read_status = lgdt3303_read_status,
>  >    .read_ber = lgdt3303_read_ber,
>  >    .read_signal_strength =
>  > lgdt3303_read_signal_strength, .read_snr =
>  > lgdt3303_read_snr,
>  >    .read_ucblocks = lgdt3303_read_ucblocks,
>  >
>  >};
>  >
>  >module_param(debug, int, 0644);
>  >MODULE_PARM_DESC(debug, "Turn on/off frontend debugging
>  > (default:off).");
>  >
>  >MODULE_DESCRIPTION("LGDT3303 ATSC (8VSB & ITU J83
>  > AnnexB FEC
>
> QAM64/256) demodulator driver");
>
>  >MODULE_AUTHOR("Taylor Jacob");
>  >MODULE_LICENSE("GPL");
>  >
>  >EXPORT_SYMBOL(lgdt3303_attach);
>  >
>  >
>  >
>  >/*
>  >   Driver for the LGDT3303 demodulator
>  >*/
>  >
>  >#ifndef LGDT3303_H
>  >#define LGDT3303_H
>  >
>  >#include <linux/dvb/frontend.h>
>  >
>  >struct lgdt3303_config
>  >{
>  >    /* the demodulator's i2c address */
>  >    u8 demod_address;
>  >    u8 tuner_address;
>  >
>  >};
>  >
>  >extern struct dvb_frontend* lgdt3303_attach(const
>  > struct
>
> lgdt3303_config* config,
>
>  >                       struct i2c_adapter* i2c);
>  >
>  >#endif // LGDT3303_H




More information about the linux-dvb mailing list