/*
* Afatech AF9013 demodulator driver
*
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
*
* Thanks to Afatech who kindly provided information.
*
* 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.
*
*/
#include "af9013_priv.h"
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 64
struct af9013_state {
struct i2c_client *client;
struct dvb_frontend fe;
u32 clk;
u8 tuner;
u32 if_frequency;
u8 ts_mode;
bool spec_inv;
u8 api_version[4];
u8 gpio[4];
/* tuner/demod RF and IF AGC limits used for signal strength calc */
u8 signal_strength_en, rf_50, rf_80, if_50, if_80;
u16 signal_strength;
u32 ber;
u32 ucblocks;
u16 snr;
u32 bandwidth_hz;
enum fe_status fe_status;
unsigned long set_frontend_jiffies;
unsigned long read_status_jiffies;
bool first_tune;
bool i2c_gate_state;
unsigned int statistics_step:3;
struct delayed_work statistics_work;
};
/* write multiple registers */
static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
const u8 *val, int len)
{
int ret;
u8 buf[MAX_XFER_SIZE];
struct i2c_msg msg[1] = {
{
.addr = priv->client->addr,
.flags = 0,
.len = 3 + len,
.buf = buf,
}
};
if (3 + len > sizeof(buf)) {
dev_warn(&priv->client->dev,
"%s: i2c wr reg=%04x: len=%d is too big!\n",
KBUILD_MODNAME, reg, len);
return -EINVAL;
}
buf[0] = (reg >> 8) & 0xff;
buf[1] = (reg >> 0) & 0xff;
buf[2] = mbox;
memcpy(&buf[3], val, len);
ret = i2c_transfer(priv->client->adapter, msg, 1);
if (ret == 1) {
ret = 0;
} else {
dev_warn(&priv->client->dev, "%s: i2c wr failed=%d reg=%04x " \
"len=%d\n", KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
}
/* read multiple registers */
static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
u8 *val, int len)
{
int ret;
u8 buf[3];
struct i2c_msg msg[2] = {
{
.addr = priv->client->addr,
.flags = 0,
.len = 3,
.buf = buf,
}, {
.addr = priv->client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = val,
}
};
buf[0]
|