#define SP887X_DEFAULT_FIRMWARE …
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <media/dvb_frontend.h>
#include "sp887x.h"
struct sp887x_state { … };
static int debug;
#define dprintk(args...) …
static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
{ … }
static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
{ … }
static int sp887x_readreg (struct sp887x_state* state, u16 reg)
{ … }
static void sp887x_microcontroller_stop (struct sp887x_state* state)
{ … }
static void sp887x_microcontroller_start (struct sp887x_state* state)
{ … }
static void sp887x_setup_agc (struct sp887x_state* state)
{ … }
#define BLOCKSIZE …
#define FW_SIZE …
static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw)
{
struct sp887x_state* state = fe->demodulator_priv;
u8 buf [BLOCKSIZE + 2];
int i;
int fw_size = fw->size;
const unsigned char *mem = fw->data + 10;
dprintk("%s\n", __func__);
if (fw_size < FW_SIZE + 10)
return -ENODEV;
sp887x_writereg(state, 0xf1a, 0x000);
sp887x_microcontroller_stop (state);
printk ("%s: firmware upload... ", __func__);
sp887x_writereg(state, 0x8f08, 0x1fff);
sp887x_writereg(state, 0x8f0a, 0x0000);
for (i = 0; i < FW_SIZE; i += BLOCKSIZE) {
int c = BLOCKSIZE;
int err;
if (c > FW_SIZE - i)
c = FW_SIZE - i;
buf[0] = 0xcf;
buf[1] = 0x0a;
memcpy(&buf[2], mem + i, c);
if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
printk ("failed.\n");
printk ("%s: i2c error (err == %i)\n", __func__, err);
return err;
}
}
sp887x_writereg(state, 0xc13, 0x001);
sp887x_writereg(state, 0xc14, 0x000);
sp887x_writereg(state, 0xc1a, 0x872);
sp887x_writereg(state, 0xc1b, 0x001);
sp887x_writereg(state, 0xc1c, 0x000);
sp887x_writereg(state, 0xc1a, 0x871);
sp887x_writereg(state, 0x301, 0x002);
sp887x_setup_agc(state);
sp887x_writereg(state, 0xd00, 0x010);
sp887x_writereg(state, 0x0d1, 0x000);
return 0;
};
static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
{ … }
static void divide (int n, int d, int *quotient_i, int *quotient_f)
{ … }
static void sp887x_correct_offsets (struct sp887x_state* state,
struct dtv_frontend_properties *p,
int actual_freq)
{ … }
static int sp887x_setup_frontend_parameters(struct dvb_frontend *fe)
{ … }
static int sp887x_read_status(struct dvb_frontend *fe, enum fe_status *status)
{ … }
static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
{ … }
static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{ … }
static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
{ … }
static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{ … }
static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{ … }
static int sp887x_sleep(struct dvb_frontend* fe)
{ … }
static int sp887x_init(struct dvb_frontend* fe)
{ … }
static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{ … }
static void sp887x_release(struct dvb_frontend* fe)
{ … }
static const struct dvb_frontend_ops sp887x_ops;
struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
struct i2c_adapter* i2c)
{ … }
static const struct dvb_frontend_ops sp887x_ops = …;
module_param(debug, int, 0644);
MODULE_PARM_DESC(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
EXPORT_SYMBOL_GPL(…);