cregit-Linux how code gets into the kernel

Release 4.11 drivers/media/dvb-frontends/si21xx.c

/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
*
* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
*
*       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.
*
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <asm/div64.h>

#include "dvb_frontend.h"
#include "si21xx.h"


#define	REVISION_REG			0x00

#define	SYSTEM_MODE_REG			0x01

#define	TS_CTRL_REG_1			0x02

#define	TS_CTRL_REG_2			0x03

#define	PIN_CTRL_REG_1			0x04

#define	PIN_CTRL_REG_2			0x05

#define	LOCK_STATUS_REG_1		0x0f

#define	LOCK_STATUS_REG_2		0x10

#define	ACQ_STATUS_REG			0x11

#define	ACQ_CTRL_REG_1			0x13

#define	ACQ_CTRL_REG_2			0x14

#define	PLL_DIVISOR_REG			0x15

#define	COARSE_TUNE_REG			0x16

#define	FINE_TUNE_REG_L			0x17

#define	FINE_TUNE_REG_H			0x18


#define	ANALOG_AGC_POWER_LEVEL_REG	0x28

#define	CFO_ESTIMATOR_CTRL_REG_1	0x29

#define	CFO_ESTIMATOR_CTRL_REG_2	0x2a

#define	CFO_ESTIMATOR_CTRL_REG_3	0x2b


#define	SYM_RATE_ESTIMATE_REG_L		0x31

#define	SYM_RATE_ESTIMATE_REG_M		0x32

#define	SYM_RATE_ESTIMATE_REG_H		0x33


#define	CFO_ESTIMATOR_OFFSET_REG_L	0x36

#define	CFO_ESTIMATOR_OFFSET_REG_H	0x37

#define	CFO_ERROR_REG_L			0x38

#define	CFO_ERROR_REG_H			0x39

#define	SYM_RATE_ESTIMATOR_CTRL_REG	0x3a


#define	SYM_RATE_REG_L			0x3f

#define	SYM_RATE_REG_M			0x40

#define	SYM_RATE_REG_H			0x41

#define	SYM_RATE_ESTIMATOR_MAXIMUM_REG	0x42

#define	SYM_RATE_ESTIMATOR_MINIMUM_REG	0x43


#define	C_N_ESTIMATOR_CTRL_REG		0x7c

#define	C_N_ESTIMATOR_THRSHLD_REG	0x7d

#define	C_N_ESTIMATOR_LEVEL_REG_L	0x7e

#define	C_N_ESTIMATOR_LEVEL_REG_H	0x7f


#define	BLIND_SCAN_CTRL_REG		0x80


#define	LSA_CTRL_REG_1			0x8D

#define	SPCTRM_TILT_CORR_THRSHLD_REG	0x8f

#define	ONE_DB_BNDWDTH_THRSHLD_REG	0x90

#define	TWO_DB_BNDWDTH_THRSHLD_REG	0x91

#define	THREE_DB_BNDWDTH_THRSHLD_REG	0x92

#define	INBAND_POWER_THRSHLD_REG	0x93

#define	REF_NOISE_LVL_MRGN_THRSHLD_REG	0x94


#define	VIT_SRCH_CTRL_REG_1		0xa0

#define	VIT_SRCH_CTRL_REG_2		0xa1

#define	VIT_SRCH_CTRL_REG_3		0xa2

#define	VIT_SRCH_STATUS_REG		0xa3

#define	VITERBI_BER_COUNT_REG_L		0xab

#define	REED_SOLOMON_CTRL_REG		0xb0

#define	REED_SOLOMON_ERROR_COUNT_REG_L	0xb1

#define	PRBS_CTRL_REG			0xb5


#define	LNB_CTRL_REG_1			0xc0

#define	LNB_CTRL_REG_2			0xc1

#define	LNB_CTRL_REG_3			0xc2

#define	LNB_CTRL_REG_4			0xc3

#define	LNB_CTRL_STATUS_REG		0xc4

#define	LNB_FIFO_REGS_0			0xc5

#define	LNB_FIFO_REGS_1			0xc6

#define	LNB_FIFO_REGS_2			0xc7

#define	LNB_FIFO_REGS_3			0xc8

#define	LNB_FIFO_REGS_4			0xc9

#define	LNB_FIFO_REGS_5			0xca

#define	LNB_SUPPLY_CTRL_REG_1		0xcb

#define	LNB_SUPPLY_CTRL_REG_2		0xcc

#define	LNB_SUPPLY_CTRL_REG_3		0xcd

#define	LNB_SUPPLY_CTRL_REG_4		0xce

#define	LNB_SUPPLY_STATUS_REG		0xcf


#define FAIL	-1

#define PASS	0


#define ALLOWABLE_FS_COUNT	10

#define STATUS_BER		0

#define STATUS_UCBLOCKS		1


static int debug;

#define dprintk(args...) \
	do { \
                if (debug) \
                        printk(KERN_DEBUG "si21xx: " args); \
        } while (0)

enum {
	
ACTIVE_HIGH,
	
ACTIVE_LOW
};
enum {
	
BYTE_WIDE,
	
BIT_WIDE
};
enum {
	
CLK_GAPPED_MODE,
	
CLK_CONTINUOUS_MODE
};
enum {
	
RISING_EDGE,
	
FALLING_EDGE
};
enum {
	
MSB_FIRST,
	
LSB_FIRST
};
enum {
	
SERIAL,
	
PARALLEL
};


struct si21xx_state {
	
struct i2c_adapter *i2c;
	
const struct si21xx_config *config;
	
struct dvb_frontend frontend;
	
u8 initialised:1;
	
int errmode;
	
int fs;			/*Sampling rate of the ADC in MHz*/
};

/*      register default initialization */

static u8 serit_sp1511lhb_inittab[] = {
	0x01, 0x28,	/* set i2c_inc_disable */
	0x20, 0x03,
	0x27, 0x20,
	0xe0, 0x45,
	0xe1, 0x08,
	0xfe, 0x01,
	0x01, 0x28,
	0x89, 0x09,
	0x04, 0x80,
	0x05, 0x01,
	0x06, 0x00,
	0x20, 0x03,
	0x24, 0x88,
	0x29, 0x09,
	0x2a, 0x0f,
	0x2c, 0x10,
	0x2d, 0x19,
	0x2e, 0x08,
	0x2f, 0x10,
	0x30, 0x19,
	0x34, 0x20,
	0x35, 0x03,
	0x45, 0x02,
	0x46, 0x45,
	0x47, 0xd0,
	0x48, 0x00,
	0x49, 0x40,
	0x4a, 0x03,
	0x4c, 0xfd,
	0x4f, 0x2e,
	0x50, 0x2e,
	0x51, 0x10,
	0x52, 0x10,
	0x56, 0x92,
	0x59, 0x00,
	0x5a, 0x2d,
	0x5b, 0x33,
	0x5c, 0x1f,
	0x5f, 0x76,
	0x62, 0xc0,
	0x63, 0xc0,
	0x64, 0xf3,
	0x65, 0xf3,
	0x79, 0x40,
	0x6a, 0x40,
	0x6b, 0x0a,
	0x6c, 0x80,
	0x6d, 0x27,
	0x71, 0x06,
	0x75, 0x60,
	0x78, 0x00,
	0x79, 0xb5,
	0x7c, 0x05,
	0x7d, 0x1a,
	0x87, 0x55,
	0x88, 0x72,
	0x8f, 0x08,
	0x90, 0xe0,
	0x94, 0x40,
	0xa0, 0x3f,
	0xa1, 0xc0,
	0xa4, 0xcc,
	0xa5, 0x66,
	0xa6, 0x66,
	0xa7, 0x7b,
	0xa8, 0x7b,
	0xa9, 0x7b,
	0xaa, 0x9a,
	0xed, 0x04,
	0xad, 0x00,
	0xae, 0x03,
	0xcc, 0xab,
	0x01, 0x08,
	0xff, 0xff
};

/*      low level read/writes */

static int si21_writeregs(struct si21xx_state *state, u8 reg1, u8 *data, int len) { int ret; u8 buf[60];/* = { reg1, data };*/ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = len + 1 }; if (len > sizeof(buf) - 1) return -EINVAL; msg.buf[0] = reg1; memcpy(msg.buf + 1, data, len); ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, ret == %i)\n", __func__, reg1, data[0], ret); return (ret != 1) ? -EREMOTEIO : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin13289.19%133.33%
Dan Carpenter1510.14%133.33%
Mauro Carvalho Chehab10.68%133.33%
Total148100.00%3100.00%


static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data) { int ret; u8 buf[] = { reg, data }; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, ret == %i)\n", __func__, reg, data, ret); return (ret != 1) ? -EREMOTEIO : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin10499.05%150.00%
Mauro Carvalho Chehab10.95%150.00%
Total105100.00%2100.00%


static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len) { struct si21xx_state *state = fe->demodulator_priv; if (len != 2) return -EINVAL; return si21_writereg(state, buf[0], buf[1]); }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin5296.30%150.00%
Lawrence Rust23.70%150.00%
Total54100.00%2100.00%


static u8 si21_readreg(struct si21xx_state *state, u8 reg) { int ret; u8 b0[] = { reg }; u8 b1[] = { 0 }; struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret); return b1[0]; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin128100.00%1100.00%
Total128100.00%1100.00%


static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len) { int ret; struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } }; ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (ret == %i)\n", __func__, ret); return ret == 2 ? 0 : -1; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin122100.00%1100.00%
Total122100.00%1100.00%


static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout) { unsigned long start = jiffies; dprintk("%s\n", __func__); while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) { if (jiffies - start > timeout) { dprintk("%s: timeout!!\n", __func__); return -ETIMEDOUT; } msleep(10); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin73100.00%1100.00%
Total73100.00%1100.00%


static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate) { struct si21xx_state *state = fe->demodulator_priv; u32 sym_rate, data_rate; int i; u8 sym_rate_bytes[3]; dprintk("%s : srate = %i\n", __func__ , srate); if ((srate < 1000000) || (srate > 45000000)) return -EINVAL; data_rate = srate; sym_rate = 0; for (i = 0; i < 4; ++i) { sym_rate /= 100; sym_rate = sym_rate + ((data_rate % 100) * 0x800000) / state->fs; data_rate /= 100; } for (i = 0; i < 3; ++i) sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff); si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin162100.00%1100.00%
Total162100.00%1100.00%


static int si21xx_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *m) { struct si21xx_state *state = fe->demodulator_priv; u8 lnb_status; u8 LNB_CTRL_1; int status; dprintk("%s\n", __func__); status = PASS; LNB_CTRL_1 = 0; status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01); status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01); /*fill the FIFO*/ status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len); LNB_CTRL_1 = (lnb_status & 0x70); LNB_CTRL_1 |= m->msg_len; LNB_CTRL_1 |= 0x80; /* begin LNB signaling */ status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01); return status; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin131100.00%1100.00%
Total131100.00%1100.00%


static int si21xx_send_diseqc_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst) { struct si21xx_state *state = fe->demodulator_priv; u8 val; dprintk("%s\n", __func__); if (si21xx_wait_diseqc_idle(state, 100) < 0) return -ETIMEDOUT; val = (0x80 | si21_readreg(state, 0xc1)); if (si21_writereg(state, LNB_CTRL_REG_1, burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10))) return -EREMOTEIO; if (si21xx_wait_diseqc_idle(state, 100) < 0) return -ETIMEDOUT; if (si21_writereg(state, LNB_CTRL_REG_1, val)) return -EREMOTEIO; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin12398.40%150.00%
Mauro Carvalho Chehab21.60%150.00%
Total125100.00%2100.00%

/* 30.06.2008 */
static int si21xx_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) { struct si21xx_state *state = fe->demodulator_priv; u8 val; dprintk("%s\n", __func__); val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1)); switch (tone) { case SEC_TONE_ON: return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20); case SEC_TONE_OFF: return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20)); default: return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin8997.80%150.00%
Mauro Carvalho Chehab22.20%150.00%
Total91100.00%2100.00%


static int si21xx_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage volt) { struct si21xx_state *state = fe->demodulator_priv; u8 val; dprintk("%s: %s\n", __func__, volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1)); switch (volt) { case SEC_VOLTAGE_18: return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40); break; case SEC_VOLTAGE_13: return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40)); break; default: return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin10598.13%150.00%
Mauro Carvalho Chehab21.87%150.00%
Total107100.00%2100.00%


static int si21xx_init(struct dvb_frontend *fe) { struct si21xx_state *state = fe->demodulator_priv; int i; int status = 0; u8 reg1; u8 val; u8 reg2[2]; dprintk("%s\n", __func__); for (i = 0; ; i += 2) { reg1 = serit_sp1511lhb_inittab[i]; val = serit_sp1511lhb_inittab[i+1]; if (reg1 == 0xff && val == 0xff) break; si21_writeregs(state, reg1, &val, 1); } /*DVB QPSK SYSTEM MODE REG*/ reg1 = 0x08; si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01); /*transport stream config*/ /* mode = PARALLEL; sdata_form = LSB_FIRST; clk_edge = FALLING_EDGE; clk_mode = CLK_GAPPED_MODE; strt_len = BYTE_WIDE; sync_pol = ACTIVE_HIGH; val_pol = ACTIVE_HIGH; err_pol = ACTIVE_HIGH; sclk_rate = 0x00; parity = 0x00 ; data_delay = 0x00; clk_delay = 0x00; pclk_smooth = 0x00; */ reg2[0] = PARALLEL + (LSB_FIRST << 1) + (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3) + (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5) + (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7); reg2[1] = 0; /* sclk_rate + (parity << 2) + (data_delay << 3) + (clk_delay << 4) + (pclk_smooth << 5); */ status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02); if (status != 0) dprintk(" %s : TS Set Error\n", __func__); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin204100.00%1100.00%
Total204100.00%1100.00%


static int si21_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct si21xx_state *state = fe->demodulator_priv; u8 regs_read[2]; u8 reg_read; u8 i; u8 lock; u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG); si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02); reg_read = 0; for (i = 0; i < 7; ++i) reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i); lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80)); dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock); *status = 0; if (signal > 10) *status |= FE_HAS_SIGNAL; if (lock & 0x2) *status |= FE_HAS_CARRIER; if (lock & 0x20) *status |= FE_HAS_VITERBI; if (lock & 0x40) *status |= FE_HAS_SYNC; if ((lock & 0x7b) == 0x7b) *status |= FE_HAS_LOCK; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin19298.97%150.00%
Mauro Carvalho Chehab21.03%150.00%
Total194100.00%2100.00%


static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct si21xx_state *state = fe->demodulator_priv; /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG, (u8*)agclevel, 0x01);*/ u16 signal = (3 * si21_readreg(state, 0x27) * si21_readreg(state, 0x28)); dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__, si21_readreg(state, 0x27), si21_readreg(state, 0x28), (int) signal); signal <<= 4; *strength = signal; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin84100.00%1100.00%
Total84100.00%1100.00%


static int si21_read_ber(struct dvb_frontend *fe, u32 *ber) { struct si21xx_state *state = fe->demodulator_priv; dprintk("%s\n", __func__); if (state->errmode != STATUS_BER) return 0; *ber = (si21_readreg(state, 0x1d) << 8) | si21_readreg(state, 0x1e); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin66100.00%1100.00%
Total66100.00%1100.00%


static int si21_read_snr(struct dvb_frontend *fe, u16 *snr) { struct si21xx_state *state = fe->demodulator_priv; s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) | si21_readreg(state, 0x25)); xsnr = 3 * (xsnr - 0xa100); *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr; dprintk("%s\n", __func__); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin90100.00%1100.00%
Total90100.00%1100.00%


static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { struct si21xx_state *state = fe->demodulator_priv; dprintk("%s\n", __func__); if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; else *ucblocks = (si21_readreg(state, 0x1d) << 8) | si21_readreg(state, 0x1e); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin69100.00%1100.00%
Total69100.00%1100.00%

/* initiates a channel acquisition sequence using the specified symbol rate and code rate */
static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate, enum fe_code_rate crate) { struct si21xx_state *state = fe->demodulator_priv; u8 coderates[] = { 0x0, 0x01, 0x02, 0x04, 0x00, 0x8, 0x10, 0x20, 0x00, 0x3f }; u8 coderate_ptr; int status; u8 start_acq = 0x80; u8 reg, regs[3]; dprintk("%s\n", __func__); status = PASS; coderate_ptr = coderates[crate]; si21xx_set_symbolrate(fe, symbrate); /* write code rates to use in the Viterbi search */ status |= si21_writeregs(state, VIT_SRCH_CTRL_REG_1, &coderate_ptr, 0x01); /* clear acq_start bit */ status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01); reg &= ~start_acq; status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01); /* use new Carrier Frequency Offset Estimator (QuickLock) */ regs[0] = 0xCB; regs[1] = 0x40; regs[2] = 0xCB; status |= si21_writeregs(state, TWO_DB_BNDWDTH_THRSHLD_REG, &regs[0], 0x03); reg = 0x56; status |= si21_writeregs(state, LSA_CTRL_REG_1, &reg, 1); reg = 0x05; status |= si21_writeregs(state, BLIND_SCAN_CTRL_REG, &reg, 1); /* start automatic acq */ status |= si21_writeregs(state, ACQ_CTRL_REG_2, &start_acq, 0x01); return status; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin23799.16%150.00%
Mauro Carvalho Chehab20.84%150.00%
Total239100.00%2100.00%


static int si21xx_set_frontend(struct dvb_frontend *fe) { struct si21xx_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz) datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/ /* in MHz */ unsigned char coarse_tune_freq; int fine_tune_freq; unsigned char sample_rate = 0; /* boolean */ bool inband_interferer_ind; /* INTERMEDIATE VALUES */ int icoarse_tune_freq; /* MHz */ int ifine_tune_freq; /* MHz */ unsigned int band_high; unsigned int band_low; unsigned int x1; unsigned int x2; int i; bool inband_interferer_div2[ALLOWABLE_FS_COUNT]; bool inband_interferer_div4[ALLOWABLE_FS_COUNT]; int status; /* allowable sample rates for ADC in MHz */ int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195, 196, 204, 205, 206, 207 }; /* in MHz */ int if_limit_high; int if_limit_low; int lnb_lo; int lnb_uncertanity; int rf_freq; int data_rate; unsigned char regs[4]; dprintk("%s : FE_SET_FRONTEND\n", __func__); if (c->delivery_system != SYS_DVBS) { dprintk("%s: unsupported delivery system selected (%d)\n", __func__, c->delivery_system); return -EOPNOTSUPP; } for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) inband_interferer_div2[i] = inband_interferer_div4[i] = false; if_limit_high = -700000; if_limit_low = -100000; /* in MHz */ lnb_lo = 0; lnb_uncertanity = 0; rf_freq = 10 * c->frequency ; data_rate = c->symbol_rate / 100; status = PASS; band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200) + (data_rate * 135)) / 200; band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200) + (data_rate * 135)) / 200; icoarse_tune_freq = 100000 * (((rf_freq - lnb_lo) - (if_limit_low + if_limit_high) / 2) / 100000); ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ; for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) * (afs[i] * 2500) + afs[i] * 2500; x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) * (afs[i] * 2500); if (((band_low < x1) && (x1 < band_high)) || ((band_low < x2) && (x2 < band_high))) inband_interferer_div4[i] = true; } for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) * (afs[i] * 5000) + afs[i] * 5000; x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) * (afs[i] * 5000); if (((band_low < x1) && (x1 < band_high)) || ((band_low < x2) && (x2 < band_high))) inband_interferer_div2[i] = true; } inband_interferer_ind = true; for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { if (inband_interferer_div2[i] || inband_interferer_div4[i]) { inband_interferer_ind = false; break; } } if (inband_interferer_ind) { for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { if (!inband_interferer_div2[i]) { sample_rate = (u8) afs[i]; break; } } } else { for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { if ((inband_interferer_div2[i] || !inband_interferer_div4[i])) { sample_rate = (u8) afs[i]; break; } } } if (sample_rate > 207 || sample_rate < 192) sample_rate = 200; fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) / ((sample_rate) * 1000)); coarse_tune_freq = (u8)(icoarse_tune_freq / 100000); regs[0] = sample_rate; regs[1] = coarse_tune_freq; regs[2] = fine_tune_freq & 0xFF; regs[3] = fine_tune_freq >> 8 & 0xFF; status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04); state->fs = sample_rate;/*ADC MHz*/ si21xx_setacquire(fe, c->symbol_rate, c->fec_inner); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin78097.26%150.00%
Joe Perches222.74%150.00%
Total802100.00%2100.00%


static int si21xx_sleep(struct dvb_frontend *fe) { struct si21xx_state *state = fe->demodulator_priv; u8 regdata; dprintk("%s\n", __func__); si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01); regdata |= 1 << 6; si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01); state->initialised = 0; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin69100.00%1100.00%
Total69100.00%1100.00%


static void si21xx_release(struct dvb_frontend *fe) { struct si21xx_state *state = fe->demodulator_priv; dprintk("%s\n", __func__); kfree(state); }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin32100.00%1100.00%
Total32100.00%1100.00%

static const struct dvb_frontend_ops si21xx_ops = { .delsys = { SYS_DVBS }, .info = { .name = "SL SI21XX DVB-S", .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = 125, /* kHz for QPSK frontends */ .frequency_tolerance = 0, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, .symbol_rate_tolerance = 500, /* ppm */ .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_QPSK | FE_CAN_FEC_AUTO }, .release = si21xx_release, .init = si21xx_init, .sleep = si21xx_sleep, .write = si21_write, .read_status = si21_read_status, .read_ber = si21_read_ber, .read_signal_strength = si21_read_signal_strength, .read_snr = si21_read_snr, .read_ucblocks = si21_read_ucblocks, .diseqc_send_master_cmd = si21xx_send_diseqc_msg, .diseqc_send_burst = si21xx_send_diseqc_burst, .set_tone = si21xx_set_tone, .set_voltage = si21xx_set_voltage, .set_frontend = si21xx_set_frontend, };
struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, struct i2c_adapter *i2c) { struct si21xx_state *state = NULL; int id; dprintk("%s\n", __func__); /* allocate memory for the internal state */ state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ state->config = config; state->i2c = i2c; state->initialised = 0; state->errmode = STATUS_BER; /* check if the demod is there */ id = si21_readreg(state, SYSTEM_MODE_REG); si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */ msleep(200); id = si21_readreg(state, 0x00); /* register 0x00 contains: 0x34 for SI2107 0x24 for SI2108 0x14 for SI2109 0x04 for SI2110 */ if (id != 0x04 && id != 0x14) goto error; /* create dvb_frontend */ memcpy(&state->frontend.ops, &si21xx_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; error: kfree(state); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin17699.44%150.00%
Matthias Schwarzott10.56%150.00%
Total177100.00%2100.00%

EXPORT_SYMBOL(si21xx_attach); module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver"); MODULE_AUTHOR("Igor M. Liplianin"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Igor M. Liplianin411198.54%111.11%
Joe Perches220.53%111.11%
Mauro Carvalho Chehab200.48%333.33%
Dan Carpenter150.36%111.11%
Lawrence Rust20.05%111.11%
Matthias Schwarzott10.02%111.11%
Max Kellermann10.02%111.11%
Total4172100.00%9100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.