Hello Johannes,
The STB0899's interface to the API, this is only the API interface and
not the complete driver.
Thanks,
Manu
/*
STB0899 Multistandard Frontend driver
Copyright (C) 2006 Manu Abraham (abraham.manu@xxxxxxxxx)
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 "stb0899_com.h"
#include "stb0899_hla.h"
static unsigned int verbose;
module_param(verbose, int, 0644);
struct stb0899_tab stb0899_cn_tab[] = {
{ 15, 9600 },
{ 20, 9450 },
{ 30, 9000 },
{ 40, 8250 },
{ 50, 7970 },
{ 60, 7360 },
{ 70, 6770 },
{ 80, 6200 },
{ 90, 5670 },
{ 100, 5190 },
{ 110, 4740 },
{ 120, 4360 },
{ 130, 4010 },
{ 140, 3710 },
{ 150, 3440 },
{ 160, 3210 },
{ 170, 3020 },
{ 180, 2860 },
{ 190, 2700 },
{ 200, 2600 }
};
struct stb0899_tab stb0899_dvbsrf_tab[] = {
{ -5, 79 },
{ -10, 73 },
{ -15, 67 },
{ -20, 62 },
{ -25, 56 },
{ -30, 49 },
{ -33, 44 },
{ -35, 40 },
{ -37, 36 },
{ -38, 33 },
{ -40, 27 },
{ -45, 4 },
{ -47, -11 },
{ -48, -19 },
{ -50, -29 },
{ -55, -43 },
{ -60, -52 },
{ -65, -61 },
{ -67, -65 },
{ -70, -128 }
};
struct stb0899_tab stb0899_dvbs2rf_tab[] = {
{ -5, 2899 },
{ -10, 3330 },
{ -15, 3123 },
{ -20, 3577 },
{ -25, 4004 },
{ -30, 4417 },
{ -35, 4841 },
{ -40, 5300 },
{ -45, 5822 },
{ -50, 6491 },
{ -55, 7516 },
{ -60, 9235 },
{ -65, 11374},
{ -70, 12364},
{ -75, 13063}
};
/**
* bfloatdiv(), float division with int
*/
u32 bfloatdiv(long n1, long n2, int precision)
{
int i = 0;
u32 result = 0;
while (i <= precision) { /* N1 < N2 */
if (n1 < n2) {
result *= 2;
n1 *= 2;
} else {
result = result * 2 + 1;
n1 = (n1 - n2) * 2;
}
i++;
}
return result;
}
static int stb0899_scan_frequency(struct dvb_frontend *fe,
struct dvb_frontend_params *params,
unsigned int mode_flags,
int *delay,
fe_status_t *status)
{
// struct stb0899_state *state = fe->demodulator_priv;
// state->params.modulation =
// state->params.inversion =
stb0899_search(fe, params);
return 0;
}
static void stb0899_release(struct dvb_frontend *fe)
{
struct stb0899_state *state = fe->demodulator_priv;
dprintk(verbose, FE_DEBUG, 1, "Release Frontend");
kfree(state);
}
static int stb0899_init(struct dvb_frontend *fe)
{
struct stb0899_state *state = fe->demodulator_priv;
dprintk(verbose, FE_DEBUG, 1, "Initializing STB0899 ... ");
stb0899_tsintf_init(state);
stb0899_diseqc_init(state);
return 0;
}
static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr)
{
int i, min, max, quant, val;
u8 val_msb, val_lsb, carrier_stat;
struct stb0899_state *state = fe->demodulator_priv;
struct stb0899_tab *cntab = stb0899_cn_tab;
switch (state->delsys) {
case STB0899_DELSYS_DVBS:
case STB0899_DELSYS_DSS:
carrier_stat = STB0899_GETFIELD(stb0899_read_reg(state,
STB0899_DSTATUS),
STB0899_WIDTH_CARRIER_FOUND,
STB0899_OFFST_CARRIER_FOUND);
if (carrier_stat) {
val_lsb = STB0899_GETFIELD(stb0899_read_reg(state,
STB0899_NIRL),
STB0899_WIDTH_NIRL,
STB0899_OFFST_NIRL);
val_msb = STB0899_GETFIELD(stb0899_read_reg(state,
STB0899_NIRM),
STB0899_WIDTH_NIRM,
STB0899_OFFST_NIRM);
val = MAKEWORD16(val_msb, val_lsb);
min = 0;
max = ARRAY_SIZE(stb0899_cn_tab) - 1;
if (INRANGE(val, cntab[min].read, cntab[max].read)) {
while ((max - min) > 1) {
i = (max + min) / 2;
if (INRANGE(val, cntab[min].read, cntab[i].read))
max = i;
else
min = i;
*snr = ((val - cntab[min].read) *
(cntab[max].real - cntab[min].real) /
(cntab[max].read - cntab[min].read)) +
cntab[min].real;
}
} else if (val < cntab[min].read)
*snr = 100;
}
break;
case STB0899_DELSYS_DVBS2:
quant = STB0899_GETFIELD(stb0899_read_s2reg(state,
STB0899_S2DEMOD,
STB0899_BASE_UWP_CNTRL1,
STB0899_OFF0_UWP_CNTRL1),
STB0899_WIDTH_UWP_ESN0_QUANT,
STB0899_OFFST_UWP_ESN0_QUANT);
*snr = STB0899_GETFIELD(stb0899_read_s2reg(state,
STB0899_S2DEMOD,
STB0899_BASE_UWP_STAT2,
STB0899_OFF0_UWP_STAT2),
STB0899_WIDTH_UWP_ESN0_EST,
STB0899_OFFST_UWP_ESN0_EST);
break;
case FE_DELSYS_IGNORE:
default:
break;
}
return 0;
}
static s32 stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
s32 min, max = 0, i, val = 0;
struct stb0899_state *state = fe->demodulator_priv;
struct stb0899_tab *rftab = NULL;
min = 0;
switch (state->delsys) {
case STB0899_DELSYS_DVBS:
case STB0899_DELSYS_DSS:
rftab = stb0899_dvbsrf_tab;
max = ARRAY_SIZE(stb0899_dvbsrf_tab) - 1;
val = STB0899_GETFIELD(stb0899_read_reg(state, STB0899_AGCIQIN),
STB0899_WIDTH_AGCIQVALUE,
STB0899_OFFST_AGCIQVALUE);
break;
case STB0899_DELSYS_DVBS2:
rftab = stb0899_dvbs2rf_tab;
max = ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1;
// val = STB0899_GETFIELD(stb0899_read_s2reg(state,STB0899_S2DEMOD,
// STB0899_BASE_IF_AGC_GAIN,
// STB0899_OFF0_IF_AGC_GAIN),
// STB0899_WIDTH_IF_AGC_GAIN,
// STB0899_OFFST_IF_AGC_GAIN);
break;
case FE_DELSYS_IGNORE:
default:
break;
}
if (INRANGE(val, rftab[min].read, rftab[max].read)) {
while ((max - min) > 1) {
i = (max + min) / 2;
if (INRANGE(val, rftab[min].read, rftab[i].read))
max = i;
else
min = i;
*strength = ((val - rftab[min].read) *
(rftab[max].real - rftab[min].real) /
(rftab[max].read - rftab[min].read)) +
rftab[min].real;
}
} else
*strength = -100;
*strength *= 10;
return 0;
}
static const struct dvb_frontend_cap stb0899_dvbs_caps = {
.name = "STB0899 Multi-standard (DVB-S Mode)",
.frequency_min = 950000,
.frequency_max = 2150000,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
.inversion = FE_INVERSION_IGNORE | FE_INVERSION_OFF |
FE_INVERSION_ON | FE_INVERSION_AUTO,
.delsys.dvbs.modulation = FE_MOD_QPSK,
.delsys.dvbs.coderate = FE_CODERATE_1_2 | FE_CODERATE_2_3 |
FE_CODERATE_3_4 | FE_CODERATE_5_6 |
FE_CODERATE_6_7
};
static const struct dvb_frontend_cap stb0899_dss_caps = {
.name = "STB0899 Multi-standard (DSS Mode)",
.frequency_min = 950000,
.frequency_max = 2150000,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
.inversion = FE_INVERSION_IGNORE | FE_INVERSION_OFF |
FE_INVERSION_ON | FE_INVERSION_AUTO,
.delsys.dvbs.modulation = FE_MOD_QPSK,
.delsys.dvbs.coderate = FE_CODERATE_1_2 | FE_CODERATE_2_3 |
FE_CODERATE_3_4 | FE_CODERATE_5_6 |
FE_CODERATE_6_7
};
static const struct dvb_frontend_cap stb0899_dvbs2_caps = {
.name = "STB0899 Multi-standard (DVB-S2 Mode)",
.frequency_min = 950000,
.frequency_max = 2150000,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
.inversion = FE_INVERSION_IGNORE | FE_INVERSION_OFF |
FE_INVERSION_ON | FE_INVERSION_AUTO,
.delsys.dvbs.modulation = FE_MOD_QPSK | FE_MOD_8PSK | FE_MOD_16APSK,
.delsys.dvbs.coderate = FE_CODERATE_1_4 | FE_CODERATE_1_3 |
FE_CODERATE_2_5 | FE_CODERATE_1_2 |
FE_CODERATE_3_5 | FE_CODERATE_2_3 |
FE_CODERATE_3_4 | FE_CODERATE_4_5 |
FE_CODERATE_5_6 | FE_CODERATE_8_9 |
FE_CODERATE_9_10
};
static int stb0899_get_caps(struct dvb_frontend *fe,
struct dvb_frontend_cap *caps)
{
struct stb0899_state *state = fe->demodulator_priv;
state->delsys = caps->delivery;
switch (caps->delivery) {
case STB0899_DELSYS_DVBS:
memcpy(caps, &stb0899_dvbs_caps, sizeof (stb0899_dvbs_caps));
break;
case STB0899_DELSYS_DSS:
memcpy(caps, &stb0899_dss_caps, sizeof (stb0899_dss_caps));
break;
case STB0899_DELSYS_DVBS2:
memcpy(caps, &stb0899_dvbs2_caps, sizeof (stb0899_dvbs2_caps));
break;
case STB0899_DELSYS_IGNORE:
default:
break;
}
return 0;
}
static int stb0899_set_params(struct dvb_frontend *fe,
struct dvb_frontend_params *params)
{
return 0;
}
static int stb0899_get_params(struct dvb_frontend *fe,
struct dvb_frontend_params *params)
{
return 0;
}
static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
switch (voltage) {
case SEC_VOLTAGE_13:
break;
case SEC_VOLTAGE_18:
break;
default:
break;
}
return 0;
}
static int stb0899_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{
switch (tone) {
case SEC_TONE_ON:
break;
case SEC_TONE_OFF:
break;
default:
break;
}
return 0;
}
static struct dvb_frontend_ops stb0899_ops = {
.release = stb0899_release,
.init = stb0899_init,
.read_signal_strength = stb0899_read_signal_strength,
.read_snr = stb0899_read_snr,
.tune = stb0899_scan_frequency,
.get_caps = stb0899_get_caps,
.set_params = stb0899_set_params,
.get_params = stb0899_get_params,
.set_voltage = stb0899_set_voltage,
.set_tone = stb0899_set_tone
};
struct dvb_frontend *stb0899_attach(const struct stb0899_config *config,
struct i2c_adapter *i2c)
{
struct stb0899_state *state = NULL;
state = kmalloc(sizeof (struct stb0899_state), GFP_KERNEL);
if (state == NULL)
goto error;
state->verbose = verbose;
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &stb0899_ops, sizeof (struct dvb_frontend_ops));
state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
if (stb0899_get_dev_id(state) == -ENODEV) {
printk("%s: Exitting .. !\n", __func__);
goto error;
}
printk("%s: Attaching STB0899 \n", __func__);
return &state->frontend;
error:
kfree(state);
return NULL;
}
EXPORT_SYMBOL(stb0899_attach);
MODULE_PARM_DESC(verbose, "Set Verbosity level");
MODULE_DESCRIPTION("STB0899 Multi-Std frontend");
MODULE_LICENSE("GPL");
_______________________________________________
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb