Commit 3c4e0415 authored by Daniel Scheller's avatar Daniel Scheller Committed by Mauro Carvalho Chehab

media: dvb-frontends: MaxLinear MxL5xx DVB-S/S2 tuner-demodulator driver

This adds the frontend driver for the MaxLinear MxL5xx family of tuner-
demodulators, as used on Digital Devices MaxS4/8 four/eight-tuner cards.

The driver was picked from the dddvb vendor driver package and - judging
solely from the diff - has undergone a 100% rework:

 - Silly #define's used to pass multiple values to functions were
   expanded. This resulted in macro/register names not being usable
   anymore for such occurences, but makes the code WAY more read-,
   understand- and maintainable.
 - CamelCase was changed to kernel_case
 - All typedef were removed
 - Overall code style was fixed, besides >80char lines in _defs.h and
   _regs.h, checkpatch is happy.
 - Also, signal stat acquisition was made to comply with the DVB API
   ways to do these things.

Permission to reuse and mainline the driver code was formally granted by
Ralph Metzler <rjkm@metzlerbros.de>.
Signed-off-by: default avatarDaniel Scheller <d.scheller@gmx.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 20e671df
...@@ -53,6 +53,15 @@ config DVB_STV6111 ...@@ -53,6 +53,15 @@ config DVB_STV6111
Say Y when you want to support these frontends. Say Y when you want to support these frontends.
config DVB_MXL5XX
tristate "MaxLinear MxL5xx based tuner-demodulators"
depends on DVB_CORE && I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
MaxLinear MxL5xx family of DVB-S/S2 tuners/demodulators.
Say Y when you want to support these frontends.
config DVB_M88DS3103 config DVB_M88DS3103
tristate "Montage Technology M88DS3103" tristate "Montage Technology M88DS3103"
depends on DVB_CORE && I2C && I2C_MUX depends on DVB_CORE && I2C && I2C_MUX
......
...@@ -112,6 +112,7 @@ obj-$(CONFIG_DVB_DRXK) += drxk.o ...@@ -112,6 +112,7 @@ obj-$(CONFIG_DVB_DRXK) += drxk.o
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
obj-$(CONFIG_DVB_STV0910) += stv0910.o obj-$(CONFIG_DVB_STV0910) += stv0910.o
obj-$(CONFIG_DVB_STV6111) += stv6111.o obj-$(CONFIG_DVB_STV6111) += stv6111.o
obj-$(CONFIG_DVB_MXL5XX) += mxl5xx.o
obj-$(CONFIG_DVB_SI2165) += si2165.o obj-$(CONFIG_DVB_SI2165) += si2165.o
obj-$(CONFIG_DVB_A8293) += a8293.o obj-$(CONFIG_DVB_A8293) += a8293.o
obj-$(CONFIG_DVB_SP2) += sp2.o obj-$(CONFIG_DVB_SP2) += sp2.o
......
/*
* Driver for the MaxLinear MxL5xx family of tuners/demods
*
* Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de>
* Marcus Metzler <mocm@metzlerbros.de>
* developed for Digital Devices GmbH
*
* based on code:
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
* which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*
* 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 <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/version.h>
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <asm/div64.h>
#include <asm/unaligned.h>
#include "dvb_frontend.h"
#include "mxl5xx.h"
#include "mxl5xx_regs.h"
#include "mxl5xx_defs.h"
#define BYTE0(v) ((v >> 0) & 0xff)
#define BYTE1(v) ((v >> 8) & 0xff)
#define BYTE2(v) ((v >> 16) & 0xff)
#define BYTE3(v) ((v >> 24) & 0xff)
LIST_HEAD(mxllist);
struct mxl_base {
struct list_head mxllist;
struct list_head mxls;
u8 adr;
struct i2c_adapter *i2c;
u32 count;
u32 type;
u32 sku_type;
u32 chipversion;
u32 clock;
u32 fwversion;
u8 *ts_map;
u8 can_clkout;
u8 chan_bond;
u8 demod_num;
u8 tuner_num;
unsigned long next_tune;
struct mutex i2c_lock;
struct mutex status_lock;
struct mutex tune_lock;
u8 buf[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
u32 cmd_size;
u8 cmd_data[MAX_CMD_DATA];
};
struct mxl {
struct list_head mxl;
struct mxl_base *base;
struct dvb_frontend fe;
struct device *i2cdev;
u32 demod;
u32 tuner;
u32 tuner_in_use;
u8 xbar[3];
unsigned long tune_time;
};
static void convert_endian(u8 flag, u32 size, u8 *d)
{
u32 i;
if (!flag)
return;
for (i = 0; i < (size & ~3); i += 4) {
d[i + 0] ^= d[i + 3];
d[i + 3] ^= d[i + 0];
d[i + 0] ^= d[i + 3];
d[i + 1] ^= d[i + 2];
d[i + 2] ^= d[i + 1];
d[i + 1] ^= d[i + 2];
}
switch (size & 3) {
case 0:
case 1:
/* do nothing */
break;
case 2:
d[i + 0] ^= d[i + 1];
d[i + 1] ^= d[i + 0];
d[i + 0] ^= d[i + 1];
break;
case 3:
d[i + 0] ^= d[i + 2];
d[i + 2] ^= d[i + 0];
d[i + 0] ^= d[i + 2];
break;
}
}
static int i2c_write(struct i2c_adapter *adap, u8 adr,
u8 *data, u32 len)
{
struct i2c_msg msg = {.addr = adr, .flags = 0,
.buf = data, .len = len};
return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
}
static int i2c_read(struct i2c_adapter *adap, u8 adr,
u8 *data, u32 len)
{
struct i2c_msg msg = {.addr = adr, .flags = I2C_M_RD,
.buf = data, .len = len};
return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
}
static int i2cread(struct mxl *state, u8 *data, int len)
{
return i2c_read(state->base->i2c, state->base->adr, data, len);
}
static int i2cwrite(struct mxl *state, u8 *data, int len)
{
return i2c_write(state->base->i2c, state->base->adr, data, len);
}
static int read_register_unlocked(struct mxl *state, u32 reg, u32 *val)
{
int stat;
u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = {
MXL_HYDRA_PLID_REG_READ, 0x04,
GET_BYTE(reg, 0), GET_BYTE(reg, 1),
GET_BYTE(reg, 2), GET_BYTE(reg, 3),
};
stat = i2cwrite(state, data,
MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE);
if (stat)
dev_err(state->i2cdev, "i2c read error 1\n");
if (!stat)
stat = i2cread(state, (u8 *) val,
MXL_HYDRA_REG_SIZE_IN_BYTES);
le32_to_cpus(val);
if (stat)
dev_err(state->i2cdev, "i2c read error 2\n");
return stat;
}
#define DMA_I2C_INTERRUPT_ADDR 0x8000011C
#define DMA_INTR_PROT_WR_CMP 0x08
static int send_command(struct mxl *state, u32 size, u8 *buf)
{
int stat;
u32 val, count = 10;
mutex_lock(&state->base->i2c_lock);
if (state->base->fwversion > 0x02010109) {
read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, &val);
if (DMA_INTR_PROT_WR_CMP & val)
dev_info(state->i2cdev, "%s busy\n", __func__);
while ((DMA_INTR_PROT_WR_CMP & val) && --count) {
mutex_unlock(&state->base->i2c_lock);
usleep_range(1000, 2000);
mutex_lock(&state->base->i2c_lock);
read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR,
&val);
}
if (!count) {
dev_info(state->i2cdev, "%s busy\n", __func__);
mutex_unlock(&state->base->i2c_lock);
return -EBUSY;
}
}
stat = i2cwrite(state, buf, size);
mutex_unlock(&state->base->i2c_lock);
return stat;
}
static int write_register(struct mxl *state, u32 reg, u32 val)
{
int stat;
u8 data[MXL_HYDRA_REG_WRITE_LEN] = {
MXL_HYDRA_PLID_REG_WRITE, 0x08,
BYTE0(reg), BYTE1(reg), BYTE2(reg), BYTE3(reg),
BYTE0(val), BYTE1(val), BYTE2(val), BYTE3(val),
};
mutex_lock(&state->base->i2c_lock);
stat = i2cwrite(state, data, sizeof(data));
mutex_unlock(&state->base->i2c_lock);
if (stat)
dev_err(state->i2cdev, "i2c write error\n");
return stat;
}
static int write_firmware_block(struct mxl *state,
u32 reg, u32 size, u8 *reg_data_ptr)
{
int stat;
u8 *buf = state->base->buf;
mutex_lock(&state->base->i2c_lock);
buf[0] = MXL_HYDRA_PLID_REG_WRITE;
buf[1] = size + 4;
buf[2] = GET_BYTE(reg, 0);
buf[3] = GET_BYTE(reg, 1);
buf[4] = GET_BYTE(reg, 2);
buf[5] = GET_BYTE(reg, 3);
memcpy(&buf[6], reg_data_ptr, size);
stat = i2cwrite(state, buf,
MXL_HYDRA_I2C_HDR_SIZE +
MXL_HYDRA_REG_SIZE_IN_BYTES + size);
mutex_unlock(&state->base->i2c_lock);
if (stat)
dev_err(state->i2cdev, "fw block write failed\n");
return stat;
}
static int read_register(struct mxl *state, u32 reg, u32 *val)
{
int stat;
u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = {
MXL_HYDRA_PLID_REG_READ, 0x04,
GET_BYTE(reg, 0), GET_BYTE(reg, 1),
GET_BYTE(reg, 2), GET_BYTE(reg, 3),
};
mutex_lock(&state->base->i2c_lock);
stat = i2cwrite(state, data,
MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE);
if (stat)
dev_err(state->i2cdev, "i2c read error 1\n");
if (!stat)
stat = i2cread(state, (u8 *) val,
MXL_HYDRA_REG_SIZE_IN_BYTES);
mutex_unlock(&state->base->i2c_lock);
le32_to_cpus(val);
if (stat)
dev_err(state->i2cdev, "i2c read error 2\n");
return stat;
}
static int read_register_block(struct mxl *state, u32 reg, u32 size, u8 *data)
{
int stat;
u8 *buf = state->base->buf;
mutex_lock(&state->base->i2c_lock);
buf[0] = MXL_HYDRA_PLID_REG_READ;
buf[1] = size + 4;
buf[2] = GET_BYTE(reg, 0);
buf[3] = GET_BYTE(reg, 1);
buf[4] = GET_BYTE(reg, 2);
buf[5] = GET_BYTE(reg, 3);
stat = i2cwrite(state, buf,
MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES);
if (!stat) {
stat = i2cread(state, data, size);
convert_endian(MXL_ENABLE_BIG_ENDIAN, size, data);
}
mutex_unlock(&state->base->i2c_lock);
return stat;
}
static int read_by_mnemonic(struct mxl *state,
u32 reg, u8 lsbloc, u8 numofbits, u32 *val)
{
u32 data = 0, mask = 0;
int stat;
stat = read_register(state, reg, &data);
if (stat)
return stat;
mask = MXL_GET_REG_MASK_32(lsbloc, numofbits);
data &= mask;
data >>= lsbloc;
*val = data;
return 0;
}
static int update_by_mnemonic(struct mxl *state,
u32 reg, u8 lsbloc, u8 numofbits, u32 val)
{
u32 data, mask;
int stat;
stat = read_register(state, reg, &data);
if (stat)
return stat;
mask = MXL_GET_REG_MASK_32(lsbloc, numofbits);
data = (data & ~mask) | ((val << lsbloc) & mask);
stat = write_register(state, reg, data);
return stat;
}
static int firmware_is_alive(struct mxl *state)
{
u32 hb0, hb1;
if (read_register(state, HYDRA_HEAR_BEAT, &hb0))
return 0;
msleep(20);
if (read_register(state, HYDRA_HEAR_BEAT, &hb1))
return 0;
if (hb1 == hb0)
return 0;
return 1;
}
static int init(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
/* init fe stats */
p->strength.len = 1;
p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->cnr.len = 1;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_error.len = 1;
p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_count.len = 1;
p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_error.len = 1;
p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_count.len = 1;
p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
return 0;
}
static void release(struct dvb_frontend *fe)
{
struct mxl *state = fe->demodulator_priv;
list_del(&state->mxl);
/* Release one frontend, two more shall take its place! */
state->base->count--;
if (state->base->count == 0) {
list_del(&state->base->mxllist);
kfree(state->base);
}
kfree(state);
}
static int get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}
static int cfg_demod_abort_tune(struct mxl *state)
{
struct MXL_HYDRA_DEMOD_ABORT_TUNE_T abort_tune_cmd;
u8 cmd_size = sizeof(abort_tune_cmd);
u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
abort_tune_cmd.demod_id = state->demod;
BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE,
cmd_size, &abort_tune_cmd, cmd_buff);
return send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE,
&cmd_buff[0]);
}
static int send_master_cmd(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd)
{
/*struct mxl *state = fe->demodulator_priv;*/
return 0; /*CfgDemodAbortTune(state);*/
}
static int set_parameters(struct dvb_frontend *fe)
{
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct MXL_HYDRA_DEMOD_PARAM_T demod_chan_cfg;
u8 cmd_size = sizeof(demod_chan_cfg);
u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
u32 srange = 10;
int stat;
if (p->frequency < 950000 || p->frequency > 2150000)
return -EINVAL;
if (p->symbol_rate < 1000000 || p->symbol_rate > 45000000)
return -EINVAL;
/* CfgDemodAbortTune(state); */
switch (p->delivery_system) {
case SYS_DSS:
demod_chan_cfg.standard = MXL_HYDRA_DSS;
demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO;
break;
case SYS_DVBS:
srange = p->symbol_rate / 1000000;
if (srange > 10)
srange = 10;
demod_chan_cfg.standard = MXL_HYDRA_DVBS;
demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_0_35;
demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_QPSK;
demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_OFF;
break;
case SYS_DVBS2:
demod_chan_cfg.standard = MXL_HYDRA_DVBS2;
demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO;
demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_AUTO;
demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_AUTO;
/* cfg_scrambler(state); */
break;
default:
return -EINVAL;
}
demod_chan_cfg.tuner_index = state->tuner;
demod_chan_cfg.demod_index = state->demod;
demod_chan_cfg.frequency_in_hz = p->frequency * 1000;
demod_chan_cfg.symbol_rate_in_hz = p->symbol_rate;
demod_chan_cfg.max_carrier_offset_in_mhz = srange;
demod_chan_cfg.spectrum_inversion = MXL_HYDRA_SPECTRUM_AUTO;
demod_chan_cfg.fec_code_rate = MXL_HYDRA_FEC_AUTO;
mutex_lock(&state->base->tune_lock);
if (time_after(jiffies + msecs_to_jiffies(200),
state->base->next_tune))
while (time_before(jiffies, state->base->next_tune))
usleep_range(10000, 11000);
state->base->next_tune = jiffies + msecs_to_jiffies(100);
state->tuner_in_use = state->tuner;
BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE,
cmd_size, &demod_chan_cfg, cmd_buff);
stat = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE,
&cmd_buff[0]);
mutex_unlock(&state->base->tune_lock);
return stat;
}
static int enable_tuner(struct mxl *state, u32 tuner, u32 enable);
static int sleep(struct dvb_frontend *fe)
{
struct mxl *state = fe->demodulator_priv;
struct mxl *p;
cfg_demod_abort_tune(state);
if (state->tuner_in_use != 0xffffffff) {
mutex_lock(&state->base->tune_lock);
state->tuner_in_use = 0xffffffff;
list_for_each_entry(p, &state->base->mxls, mxl) {
if (p->tuner_in_use == state->tuner)
break;
}
if (&p->mxl == &state->base->mxls)
enable_tuner(state, state->tuner, 0);
mutex_unlock(&state->base->tune_lock);
}
return 0;
}
static int read_snr(struct dvb_frontend *fe)
{
struct mxl *state = fe->demodulator_priv;
int stat;
u32 reg_data = 0;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
stat = read_register(state, (HYDRA_DMD_SNR_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
&reg_data);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].svalue = (s16)reg_data * 10;
return stat;
}
static int read_ber(struct dvb_frontend *fe)
{
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg[8];
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
read_register_block(state,
(HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(4 * sizeof(u32)),
(u8 *) &reg[0]);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
switch (p->delivery_system) {
case SYS_DSS:
case SYS_DVBS:
p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_error.stat[0].uvalue = reg[2];
p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->pre_bit_count.stat[0].uvalue = reg[3];
break;
default:
break;
}
read_register_block(state,
(HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(7 * sizeof(u32)),
(u8 *) &reg[0]);
switch (p->delivery_system) {
case SYS_DSS:
case SYS_DVBS:
p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_error.stat[0].uvalue = reg[5];
p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_count.stat[0].uvalue = reg[6];
break;
case SYS_DVBS2:
p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_error.stat[0].uvalue = reg[1];
p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
p->post_bit_count.stat[0].uvalue = reg[2];
break;
default:
break;
}
mutex_unlock(&state->base->status_lock);
return 0;
}
static int read_signal_strength(struct dvb_frontend *fe)
{
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int stat;
u32 reg_data = 0;
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
stat = read_register(state, (HYDRA_DMD_STATUS_INPUT_POWER_ADDR +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
&reg_data);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
p->strength.stat[0].svalue = (s16) reg_data * 10; /* fix scale */
return stat;
}
static int read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 reg_data = 0;
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
read_register(state, (HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
&reg_data);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
*status = (reg_data == 1) ? 0x1f : 0;
/* signal statistics */
/* signal strength is always available */
read_signal_strength(fe);
if (*status & FE_HAS_CARRIER)
read_snr(fe);
else
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
if (*status & FE_HAS_SYNC)
read_ber(fe);
else {
p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
return 0;
}
static int tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags,
unsigned int *delay, enum fe_status *status)
{
struct mxl *state = fe->demodulator_priv;
int r = 0;
*delay = HZ / 2;
if (re_tune) {
r = set_parameters(fe);
if (r)
return r;
state->tune_time = jiffies;
return 0;
}
if (*status & FE_HAS_LOCK)
return 0;
r = read_status(fe, status);
if (r)
return r;
return 0;
}
static enum fe_code_rate conv_fec(enum MXL_HYDRA_FEC_E fec)
{
enum fe_code_rate fec2fec[11] = {
FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3,
FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7,
FEC_7_8, FEC_8_9, FEC_9_10
};
if (fec > MXL_HYDRA_FEC_9_10)
return FEC_NONE;
return fec2fec[fec];
}
static int get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct mxl *state = fe->demodulator_priv;
u32 reg_data[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE];
u32 freq;
mutex_lock(&state->base->status_lock);
HYDRA_DEMOD_STATUS_LOCK(state, state->demod);
read_register_block(state,
(HYDRA_DMD_STANDARD_ADDR_OFFSET +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), /* 25 * 4 bytes */
(u8 *) &reg_data[0]);
/* read demod channel parameters */
read_register_block(state,
(HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR +
HYDRA_DMD_STATUS_OFFSET(state->demod)),
(4), /* 4 bytes */
(u8 *) &freq);
HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod);
mutex_unlock(&state->base->status_lock);
dev_dbg(state->i2cdev, "freq=%u delsys=%u srate=%u\n",
freq * 1000, reg_data[DMD_STANDARD_ADDR],
reg_data[DMD_SYMBOL_RATE_ADDR]);
p->symbol_rate = reg_data[DMD_SYMBOL_RATE_ADDR];
p->frequency = freq;
/*
* p->delivery_system =
* (MXL_HYDRA_BCAST_STD_E) regData[DMD_STANDARD_ADDR];
* p->inversion =
* (MXL_HYDRA_SPECTRUM_E) regData[DMD_SPECTRUM_INVERSION_ADDR];
* freqSearchRangeKHz =
* (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]);
*/
p->fec_inner = conv_fec(reg_data[DMD_FEC_CODE_RATE_ADDR]);
switch (p->delivery_system) {
case SYS_DSS:
break;
case SYS_DVBS2:
switch ((enum MXL_HYDRA_PILOTS_E)
reg_data[DMD_DVBS2_PILOT_ON_OFF_ADDR]) {
case MXL_HYDRA_PILOTS_OFF:
p->pilot = PILOT_OFF;
break;
case MXL_HYDRA_PILOTS_ON:
p->pilot = PILOT_ON;
break;
default:
break;
}
case SYS_DVBS:
switch ((enum MXL_HYDRA_MODULATION_E)
reg_data[DMD_MODULATION_SCHEME_ADDR]) {
case MXL_HYDRA_MOD_QPSK:
p->modulation = QPSK;
break;
case MXL_HYDRA_MOD_8PSK:
p->modulation = PSK_8;
break;
default:
break;
}
switch ((enum MXL_HYDRA_ROLLOFF_E)
reg_data[DMD_SPECTRUM_ROLL_OFF_ADDR]) {
case MXL_HYDRA_ROLLOFF_0_20:
p->rolloff = ROLLOFF_20;
break;
case MXL_HYDRA_ROLLOFF_0_35:
p->rolloff = ROLLOFF_35;
break;
case MXL_HYDRA_ROLLOFF_0_25:
p->rolloff = ROLLOFF_25;
break;
default:
break;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int set_input(struct dvb_frontend *fe, int input)
{
struct mxl *state = fe->demodulator_priv;
state->tuner = input;
return 0;
}
static struct dvb_frontend_ops mxl_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.info = {
.name = "MaxLinear MxL5xx DVB-S/S2 tuner-demodulator",
.frequency_min = 300000,
.frequency_max = 2350000,
.frequency_stepsize = 0,
.frequency_tolerance = 0,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_2G_MODULATION
},
.init = init,
.release = release,
.get_frontend_algo = get_algo,
.tune = tune,
.read_status = read_status,
.sleep = sleep,
.get_frontend = get_frontend,
.diseqc_send_master_cmd = send_master_cmd,
};
static struct mxl_base *match_base(struct i2c_adapter *i2c, u8 adr)
{
struct mxl_base *p;
list_for_each_entry(p, &mxllist, mxllist)
if (p->i2c == i2c && p->adr == adr)
return p;
return NULL;
}
static void cfg_dev_xtal(struct mxl *state, u32 freq, u32 cap, u32 enable)
{
if (state->base->can_clkout || !enable)
update_by_mnemonic(state, 0x90200054, 23, 1, enable);
if (freq == 24000000)
write_register(state, HYDRA_CRYSTAL_SETTING, 0);
else
write_register(state, HYDRA_CRYSTAL_SETTING, 1);
write_register(state, HYDRA_CRYSTAL_CAP, cap);
}
static u32 get_big_endian(u8 num_of_bits, const u8 buf[])
{
u32 ret_value = 0;
switch (num_of_bits) {
case 24:
ret_value = (((u32) buf[0]) << 16) |
(((u32) buf[1]) << 8) | buf[2];
break;
case 32:
ret_value = (((u32) buf[0]) << 24) |
(((u32) buf[1]) << 16) |
(((u32) buf[2]) << 8) | buf[3];
break;
default:
break;
}
return ret_value;
}
static int write_fw_segment(struct mxl *state,
u32 mem_addr, u32 total_size, u8 *data_ptr)
{
int status;
u32 data_count = 0;
u32 size = 0;
u32 orig_size = 0;
u8 *w_buf_ptr = NULL;
u32 block_size = ((MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH -
(MXL_HYDRA_I2C_HDR_SIZE +
MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4;
u8 w_msg_buffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH -
(MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)];
do {
size = orig_size = (((u32)(data_count + block_size)) > total_size) ?
(total_size - data_count) : block_size;
if (orig_size & 3)
size = (orig_size + 4) & ~3;
w_buf_ptr = &w_msg_buffer[0];
memset((void *) w_buf_ptr, 0, size);
memcpy((void *) w_buf_ptr, (void *) data_ptr, orig_size);
convert_endian(1, size, w_buf_ptr);
status = write_firmware_block(state, mem_addr, size, w_buf_ptr);
if (status)
return status;
data_count += size;
mem_addr += size;
data_ptr += size;
} while (data_count < total_size);
return status;
}
static int do_firmware_download(struct mxl *state, u8 *mbin_buffer_ptr,
u32 mbin_buffer_size)
{
int status;
u32 index = 0;
u32 seg_length = 0;
u32 seg_address = 0;
struct MBIN_FILE_T *mbin_ptr = (struct MBIN_FILE_T *)mbin_buffer_ptr;
struct MBIN_SEGMENT_T *segment_ptr;
enum MXL_BOOL_E xcpu_fw_flag = MXL_FALSE;
if (mbin_ptr->header.id != MBIN_FILE_HEADER_ID) {
dev_err(state->i2cdev, "%s: Invalid file header ID (%c)\n",
__func__, mbin_ptr->header.id);
return -EINVAL;
}
status = write_register(state, FW_DL_SIGN_ADDR, 0);
if (status)
return status;
segment_ptr = (struct MBIN_SEGMENT_T *) (&mbin_ptr->data[0]);
for (index = 0; index < mbin_ptr->header.num_segments; index++) {
if (segment_ptr->header.id != MBIN_SEGMENT_HEADER_ID) {
dev_err(state->i2cdev, "%s: Invalid segment header ID (%c)\n",
__func__, segment_ptr->header.id);
return -EINVAL;
}
seg_length = get_big_endian(24,
&(segment_ptr->header.len24[0]));
seg_address = get_big_endian(32,
&(segment_ptr->header.address[0]));
if (state->base->type == MXL_HYDRA_DEVICE_568) {
if ((((seg_address & 0x90760000) == 0x90760000) ||
((seg_address & 0x90740000) == 0x90740000)) &&
(xcpu_fw_flag == MXL_FALSE)) {
update_by_mnemonic(state, 0x8003003C, 0, 1, 1);
msleep(200);
write_register(state, 0x90720000, 0);
usleep_range(10000, 11000);
xcpu_fw_flag = MXL_TRUE;
}
status = write_fw_segment(state, seg_address,
seg_length,
(u8 *) segment_ptr->data);
} else {
if (((seg_address & 0x90760000) != 0x90760000) &&
((seg_address & 0x90740000) != 0x90740000))
status = write_fw_segment(state, seg_address,
seg_length, (u8 *) segment_ptr->data);
}
if (status)
return status;
segment_ptr = (struct MBIN_SEGMENT_T *)
&(segment_ptr->data[((seg_length + 3) / 4) * 4]);
}
return status;
}
static int check_fw(struct mxl *state, u8 *mbin, u32 mbin_len)
{
struct MBIN_FILE_HEADER_T *fh = (struct MBIN_FILE_HEADER_T *) mbin;
u32 flen = (fh->image_size24[0] << 16) |
(fh->image_size24[1] << 8) | fh->image_size24[2];
u8 *fw, cs = 0;
u32 i;
if (fh->id != 'M' || fh->fmt_version != '1' || flen > 0x3FFF0) {
dev_info(state->i2cdev, "Invalid FW Header\n");
return -1;
}
fw = mbin + sizeof(struct MBIN_FILE_HEADER_T);
for (i = 0; i < flen; i += 1)
cs += fw[i];
if (cs != fh->image_checksum) {
dev_info(state->i2cdev, "Invalid FW Checksum\n");
return -1;
}
return 0;
}
static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len)
{
int status;
u32 reg_data = 0;
struct MXL_HYDRA_SKU_COMMAND_T dev_sku_cfg;
u8 cmd_size = sizeof(struct MXL_HYDRA_SKU_COMMAND_T);
u8 cmd_buff[sizeof(struct MXL_HYDRA_SKU_COMMAND_T) + 6];
if (check_fw(state, mbin, mbin_len))
return -1;
/* put CPU into reset */
status = update_by_mnemonic(state, 0x8003003C, 0, 1, 0);
if (status)
return status;
usleep_range(1000, 2000);
/* Reset TX FIFO's, BBAND, XBAR */
status = write_register(state, HYDRA_RESET_TRANSPORT_FIFO_REG,
HYDRA_RESET_TRANSPORT_FIFO_DATA);
if (status)
return status;
status = write_register(state, HYDRA_RESET_BBAND_REG,
HYDRA_RESET_BBAND_DATA);
if (status)
return status;
status = write_register(state, HYDRA_RESET_XBAR_REG,
HYDRA_RESET_XBAR_DATA);
if (status)
return status;
/* Disable clock to Baseband, Wideband, SerDes,
* Alias ext & Transport modules
*/
status = write_register(state, HYDRA_MODULES_CLK_2_REG,
HYDRA_DISABLE_CLK_2);
if (status)
return status;
/* Clear Software & Host interrupt status - (Clear on read) */
status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, &reg_data);
if (status)
return status;
status = do_firmware_download(state, mbin, mbin_len);
if (status)
return status;
if (state->base->type == MXL_HYDRA_DEVICE_568) {
usleep_range(10000, 11000);
/* bring XCPU out of reset */
status = write_register(state, 0x90720000, 1);
if (status)
return status;
msleep(500);
/* Enable XCPU UART message processing in MCPU */
status = write_register(state, 0x9076B510, 1);
if (status)
return status;
} else {
/* Bring CPU out of reset */
status = update_by_mnemonic(state, 0x8003003C, 0, 1, 1);
if (status)
return status;
/* Wait until FW boots */
msleep(150);
}
/* Initialize XPT XBAR */
status = write_register(state, XPT_DMD0_BASEADDR, 0x76543210);
if (status)
return status;
if (!firmware_is_alive(state))
return -1;
dev_info(state->i2cdev, "Hydra FW alive. Hail!\n");
/* sometimes register values are wrong shortly
* after first heart beats
*/
msleep(50);
dev_sku_cfg.sku_type = state->base->sku_type;
BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE,
cmd_size, &dev_sku_cfg, cmd_buff);
status = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE,
&cmd_buff[0]);
return status;
}
static int cfg_ts_pad_mux(struct mxl *state, enum MXL_BOOL_E enable_serial_ts)
{
int status = 0;
u32 pad_mux_value = 0;
if (enable_serial_ts == MXL_TRUE) {
pad_mux_value = 0;
if ((state->base->type == MXL_HYDRA_DEVICE_541) ||
(state->base->type == MXL_HYDRA_DEVICE_541S))
pad_mux_value = 2;
} else {
if ((state->base->type == MXL_HYDRA_DEVICE_581) ||
(state->base->type == MXL_HYDRA_DEVICE_581S))
pad_mux_value = 2;
else
pad_mux_value = 3;
}
switch (state->base->type) {
case MXL_HYDRA_DEVICE_561:
case MXL_HYDRA_DEVICE_581:
case MXL_HYDRA_DEVICE_541:
case MXL_HYDRA_DEVICE_541S:
case MXL_HYDRA_DEVICE_561S:
case MXL_HYDRA_DEVICE_581S:
status |= update_by_mnemonic(state, 0x90000170, 24, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000170, 28, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 0, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 4, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 8, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 12, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 16, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 20, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 24, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000174, 28, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000178, 0, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000178, 4, 3,
pad_mux_value);
status |= update_by_mnemonic(state, 0x90000178, 8, 3,
pad_mux_value);
break;
case MXL_HYDRA_DEVICE_544:
case MXL_HYDRA_DEVICE_542:
status |= update_by_mnemonic(state, 0x9000016C, 4, 3, 1);
status |= update_by_mnemonic(state, 0x9000016C, 8, 3, 0);
status |= update_by_mnemonic(state, 0x9000016C, 12, 3, 0);
status |= update_by_mnemonic(state, 0x9000016C, 16, 3, 0);
status |= update_by_mnemonic(state, 0x90000170, 0, 3, 0);
status |= update_by_mnemonic(state, 0x90000178, 12, 3, 1);
status |= update_by_mnemonic(state, 0x90000178, 16, 3, 1);
status |= update_by_mnemonic(state, 0x90000178, 20, 3, 1);
status |= update_by_mnemonic(state, 0x90000178, 24, 3, 1);
status |= update_by_mnemonic(state, 0x9000017C, 0, 3, 1);
status |= update_by_mnemonic(state, 0x9000017C, 4, 3, 1);
if (enable_serial_ts == MXL_ENABLE) {
status |= update_by_mnemonic(state,
0x90000170, 4, 3, 0);
status |= update_by_mnemonic(state,
0x90000170, 8, 3, 0);
status |= update_by_mnemonic(state,
0x90000170, 12, 3, 0);
status |= update_by_mnemonic(state,
0x90000170, 16, 3, 0);
status |= update_by_mnemonic(state,
0x90000170, 20, 3, 1);
status |= update_by_mnemonic(state,
0x90000170, 24, 3, 1);
status |= update_by_mnemonic(state,
0x90000170, 28, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 0, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 4, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 8, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 12, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 16, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 20, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 24, 3, 2);
status |= update_by_mnemonic(state,
0x90000174, 28, 3, 2);
status |= update_by_mnemonic(state,
0x90000178, 0, 3, 2);
status |= update_by_mnemonic(state,
0x90000178, 4, 3, 2);
status |= update_by_mnemonic(state,
0x90000178, 8, 3, 2);
} else {
status |= update_by_mnemonic(state,
0x90000170, 4, 3, 3);
status |= update_by_mnemonic(state,
0x90000170, 8, 3, 3);
status |= update_by_mnemonic(state,
0x90000170, 12, 3, 3);
status |= update_by_mnemonic(state,
0x90000170, 16, 3, 3);
status |= update_by_mnemonic(state,
0x90000170, 20, 3, 3);
status |= update_by_mnemonic(state,
0x90000170, 24, 3, 3);
status |= update_by_mnemonic(state,
0x90000170, 28, 3, 3);
status |= update_by_mnemonic(state,
0x90000174, 0, 3, 3);
status |= update_by_mnemonic(state,
0x90000174, 4, 3, 3);
status |= update_by_mnemonic(state,
0x90000174, 8, 3, 3);
status |= update_by_mnemonic(state,
0x90000174, 12, 3, 3);
status |= update_by_mnemonic(state,
0x90000174, 16, 3, 3);
status |= update_by_mnemonic(state,
0x90000174, 20, 3, 1);
status |= update_by_mnemonic(state,
0x90000174, 24, 3, 1);
status |= update_by_mnemonic(state,
0x90000174, 28, 3, 1);
status |= update_by_mnemonic(state,
0x90000178, 0, 3, 1);
status |= update_by_mnemonic(state,
0x90000178, 4, 3, 1);
status |= update_by_mnemonic(state,
0x90000178, 8, 3, 1);
}
break;
case MXL_HYDRA_DEVICE_568:
if (enable_serial_ts == MXL_FALSE) {
status |= update_by_mnemonic(state,
0x9000016C, 8, 3, 5);
status |= update_by_mnemonic(state,
0x9000016C, 12, 3, 5);
status |= update_by_mnemonic(state,
0x9000016C, 16, 3, 5);
status |= update_by_mnemonic(state,
0x9000016C, 20, 3, 5);
status |= update_by_mnemonic(state,
0x9000016C, 24, 3, 5);
status |= update_by_mnemonic(state,
0x9000016C, 28, 3, 5);
status |= update_by_mnemonic(state,
0x90000170, 0, 3, 5);
status |= update_by_mnemonic(state,
0x90000170, 4, 3, 5);
status |= update_by_mnemonic(state,
0x90000170, 8, 3, 5);
status |= update_by_mnemonic(state,
0x90000170, 12, 3, 5);
status |= update_by_mnemonic(state,
0x90000170, 16, 3, 5);
status |= update_by_mnemonic(state,
0x90000170, 20, 3, 5);
status |= update_by_mnemonic(state,
0x90000170, 24, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 0, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 4, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 8, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 12, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 16, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 20, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 24, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 28, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000178, 0, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000178, 4, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000178, 8, 3, 5);
status |= update_by_mnemonic(state,
0x90000178, 12, 3, 5);
status |= update_by_mnemonic(state,
0x90000178, 16, 3, 5);
status |= update_by_mnemonic(state,
0x90000178, 20, 3, 5);
status |= update_by_mnemonic(state,
0x90000178, 24, 3, 5);
status |= update_by_mnemonic(state,
0x90000178, 28, 3, 5);
status |= update_by_mnemonic(state,
0x9000017C, 0, 3, 5);
status |= update_by_mnemonic(state,
0x9000017C, 4, 3, 5);
} else {
status |= update_by_mnemonic(state,
0x90000170, 4, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 8, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 12, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 16, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 20, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 24, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 28, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 0, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 4, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 8, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 12, 3, pad_mux_value);
}
break;
case MXL_HYDRA_DEVICE_584:
default:
status |= update_by_mnemonic(state,
0x90000170, 4, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 8, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 12, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 16, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 20, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 24, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000170, 28, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 0, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 4, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 8, 3, pad_mux_value);
status |= update_by_mnemonic(state,
0x90000174, 12, 3, pad_mux_value);
break;
}
return status;
}
static int set_drive_strength(struct mxl *state,
enum MXL_HYDRA_TS_DRIVE_STRENGTH_E ts_drive_strength)
{
int stat = 0;
u32 val;
read_register(state, 0x90000194, &val);
dev_info(state->i2cdev, "DIGIO = %08x\n", val);
dev_info(state->i2cdev, "set drive_strength = %u\n", ts_drive_strength);
stat |= update_by_mnemonic(state, 0x90000194, 0, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x90000194, 20, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x90000194, 24, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x90000198, 12, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x90000198, 16, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x90000198, 20, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x90000198, 24, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x9000019C, 0, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x9000019C, 4, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x9000019C, 8, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x9000019C, 24, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x9000019C, 28, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x900001A0, 0, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x900001A0, 4, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x900001A0, 20, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x900001A0, 24, 3, ts_drive_strength);
stat |= update_by_mnemonic(state, 0x900001A0, 28, 3, ts_drive_strength);
return stat;
}
static int enable_tuner(struct mxl *state, u32 tuner, u32 enable)
{
int stat = 0;
struct MXL_HYDRA_TUNER_CMD ctrl_tuner_cmd;
u8 cmd_size = sizeof(ctrl_tuner_cmd);
u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
u32 val, count = 10;
ctrl_tuner_cmd.tuner_id = tuner;
ctrl_tuner_cmd.enable = enable;
BUILD_HYDRA_CMD(MXL_HYDRA_TUNER_ACTIVATE_CMD, MXL_CMD_WRITE,
cmd_size, &ctrl_tuner_cmd, cmd_buff);
stat = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE,
&cmd_buff[0]);
if (stat)
return stat;
read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val);
while (--count && ((val >> tuner) & 1) != enable) {
msleep(20);
read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val);
}
if (!count)
return -1;
read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val);
dev_dbg(state->i2cdev, "tuner %u ready = %u\n",
tuner, (val >> tuner) & 1);
return 0;
}
static int config_ts(struct mxl *state, enum MXL_HYDRA_DEMOD_ID_E demod_id,
struct MXL_HYDRA_MPEGOUT_PARAM_T *mpeg_out_param_ptr)
{
int status = 0;
u32 nco_count_min = 0;
u32 clk_type = 0;
struct MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = {
{0x90700010, 8, 1}, {0x90700010, 9, 1},
{0x90700010, 10, 1}, {0x90700010, 11, 1},
{0x90700010, 12, 1}, {0x90700010, 13, 1},
{0x90700010, 14, 1}, {0x90700010, 15, 1} };
struct MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = {
{0x90700010, 16, 1}, {0x90700010, 17, 1},
{0x90700010, 18, 1}, {0x90700010, 19, 1},
{0x90700010, 20, 1}, {0x90700010, 21, 1},
{0x90700010, 22, 1}, {0x90700010, 23, 1} };
struct MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = {
{0x90700014, 0, 1}, {0x90700014, 1, 1},
{0x90700014, 2, 1}, {0x90700014, 3, 1},
{0x90700014, 4, 1}, {0x90700014, 5, 1},
{0x90700014, 6, 1}, {0x90700014, 7, 1} };
struct MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = {
{0x90700018, 0, 3}, {0x90700018, 4, 3},
{0x90700018, 8, 3}, {0x90700018, 12, 3},
{0x90700018, 16, 3}, {0x90700018, 20, 3},
{0x90700018, 24, 3}, {0x90700018, 28, 3} };
struct MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = {
{0x9070000C, 16, 1}, {0x9070000C, 17, 1},
{0x9070000C, 18, 1}, {0x9070000C, 19, 1},
{0x9070000C, 20, 1}, {0x9070000C, 21, 1},
{0x9070000C, 22, 1}, {0x9070000C, 23, 1} };
struct MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = {
{0x90700010, 0, 1}, {0x90700010, 1, 1},
{0x90700010, 2, 1}, {0x90700010, 3, 1},
{0x90700010, 4, 1}, {0x90700010, 5, 1},
{0x90700010, 6, 1}, {0x90700010, 7, 1} };
struct MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = {
{0x9070000C, 0, 1}, {0x9070000C, 1, 1},
{0x9070000C, 2, 1}, {0x9070000C, 3, 1},
{0x9070000C, 4, 1}, {0x9070000C, 5, 1},
{0x9070000C, 6, 1}, {0x9070000C, 7, 1} };
struct MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = {
{0x9070000C, 24, 1}, {0x9070000C, 25, 1},
{0x9070000C, 26, 1}, {0x9070000C, 27, 1},
{0x9070000C, 28, 1}, {0x9070000C, 29, 1},
{0x9070000C, 30, 1}, {0x9070000C, 31, 1} };
struct MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = {
{0x90700014, 8, 1}, {0x90700014, 9, 1},
{0x90700014, 10, 1}, {0x90700014, 11, 1},
{0x90700014, 12, 1}, {0x90700014, 13, 1},
{0x90700014, 14, 1}, {0x90700014, 15, 1} };
struct MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = {
{0x907001D4, 0, 1}, {0x907001D4, 1, 1},
{0x907001D4, 2, 1}, {0x907001D4, 3, 1},
{0x907001D4, 4, 1}, {0x907001D4, 5, 1},
{0x907001D4, 6, 1}, {0x907001D4, 7, 1} };
struct MXL_REG_FIELD_T xpt_nco_clock_rate[MXL_HYDRA_DEMOD_MAX] = {
{0x90700044, 16, 80}, {0x90700044, 16, 81},
{0x90700044, 16, 82}, {0x90700044, 16, 83},
{0x90700044, 16, 84}, {0x90700044, 16, 85},
{0x90700044, 16, 86}, {0x90700044, 16, 87} };
demod_id = state->base->ts_map[demod_id];
if (mpeg_out_param_ptr->enable == MXL_ENABLE) {
if (mpeg_out_param_ptr->mpeg_mode ==
MXL_HYDRA_MPEG_MODE_PARALLEL) {
} else {
cfg_ts_pad_mux(state, MXL_TRUE);
update_by_mnemonic(state,
0x90700010, 27, 1, MXL_FALSE);
}
}
nco_count_min =
(u32)(MXL_HYDRA_NCO_CLK / mpeg_out_param_ptr->max_mpeg_clk_rate);
if (state->base->chipversion >= 2) {
status |= update_by_mnemonic(state,
xpt_nco_clock_rate[demod_id].reg_addr, /* Reg Addr */
xpt_nco_clock_rate[demod_id].lsb_pos, /* LSB pos */
xpt_nco_clock_rate[demod_id].num_of_bits, /* Num of bits */
nco_count_min); /* Data */
} else
update_by_mnemonic(state, 0x90700044, 16, 8, nco_count_min);
if (mpeg_out_param_ptr->mpeg_clk_type == MXL_HYDRA_MPEG_CLK_CONTINUOUS)
clk_type = 1;
if (mpeg_out_param_ptr->mpeg_mode < MXL_HYDRA_MPEG_MODE_PARALLEL) {
status |= update_by_mnemonic(state,
xpt_continuous_clock[demod_id].reg_addr,
xpt_continuous_clock[demod_id].lsb_pos,
xpt_continuous_clock[demod_id].num_of_bits,
clk_type);
} else
update_by_mnemonic(state, 0x907001D4, 8, 1, clk_type);
status |= update_by_mnemonic(state,
xpt_sync_polarity[demod_id].reg_addr,
xpt_sync_polarity[demod_id].lsb_pos,
xpt_sync_polarity[demod_id].num_of_bits,
mpeg_out_param_ptr->mpeg_sync_pol);
status |= update_by_mnemonic(state,
xpt_valid_polarity[demod_id].reg_addr,
xpt_valid_polarity[demod_id].lsb_pos,
xpt_valid_polarity[demod_id].num_of_bits,
mpeg_out_param_ptr->mpeg_valid_pol);
status |= update_by_mnemonic(state,
xpt_clock_polarity[demod_id].reg_addr,
xpt_clock_polarity[demod_id].lsb_pos,
xpt_clock_polarity[demod_id].num_of_bits,
mpeg_out_param_ptr->mpeg_clk_pol);
status |= update_by_mnemonic(state,
xpt_sync_byte[demod_id].reg_addr,
xpt_sync_byte[demod_id].lsb_pos,
xpt_sync_byte[demod_id].num_of_bits,
mpeg_out_param_ptr->mpeg_sync_pulse_width);
status |= update_by_mnemonic(state,
xpt_ts_clock_phase[demod_id].reg_addr,
xpt_ts_clock_phase[demod_id].lsb_pos,
xpt_ts_clock_phase[demod_id].num_of_bits,
mpeg_out_param_ptr->mpeg_clk_phase);
status |= update_by_mnemonic(state,
xpt_lsb_first[demod_id].reg_addr,
xpt_lsb_first[demod_id].lsb_pos,
xpt_lsb_first[demod_id].num_of_bits,
mpeg_out_param_ptr->lsb_or_msb_first);
switch (mpeg_out_param_ptr->mpeg_error_indication) {
case MXL_HYDRA_MPEG_ERR_REPLACE_SYNC:
status |= update_by_mnemonic(state,
xpt_err_replace_sync[demod_id].reg_addr,
xpt_err_replace_sync[demod_id].lsb_pos,
xpt_err_replace_sync[demod_id].num_of_bits,
MXL_TRUE);
status |= update_by_mnemonic(state,
xpt_err_replace_valid[demod_id].reg_addr,
xpt_err_replace_valid[demod_id].lsb_pos,
xpt_err_replace_valid[demod_id].num_of_bits,
MXL_FALSE);
break;
case MXL_HYDRA_MPEG_ERR_REPLACE_VALID:
status |= update_by_mnemonic(state,
xpt_err_replace_sync[demod_id].reg_addr,
xpt_err_replace_sync[demod_id].lsb_pos,
xpt_err_replace_sync[demod_id].num_of_bits,
MXL_FALSE);
status |= update_by_mnemonic(state,
xpt_err_replace_valid[demod_id].reg_addr,
xpt_err_replace_valid[demod_id].lsb_pos,
xpt_err_replace_valid[demod_id].num_of_bits,
MXL_TRUE);
break;
case MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED:
default:
status |= update_by_mnemonic(state,
xpt_err_replace_sync[demod_id].reg_addr,
xpt_err_replace_sync[demod_id].lsb_pos,
xpt_err_replace_sync[demod_id].num_of_bits,
MXL_FALSE);
status |= update_by_mnemonic(state,
xpt_err_replace_valid[demod_id].reg_addr,
xpt_err_replace_valid[demod_id].lsb_pos,
xpt_err_replace_valid[demod_id].num_of_bits,
MXL_FALSE);
break;
}
if (mpeg_out_param_ptr->mpeg_mode != MXL_HYDRA_MPEG_MODE_PARALLEL) {
status |= update_by_mnemonic(state,
xpt_enable_output[demod_id].reg_addr,
xpt_enable_output[demod_id].lsb_pos,
xpt_enable_output[demod_id].num_of_bits,
mpeg_out_param_ptr->enable);
}
return status;
}
static int config_mux(struct mxl *state)
{
update_by_mnemonic(state, 0x9070000C, 0, 1, 0);
update_by_mnemonic(state, 0x9070000C, 1, 1, 0);
update_by_mnemonic(state, 0x9070000C, 2, 1, 0);
update_by_mnemonic(state, 0x9070000C, 3, 1, 0);
update_by_mnemonic(state, 0x9070000C, 4, 1, 0);
update_by_mnemonic(state, 0x9070000C, 5, 1, 0);
update_by_mnemonic(state, 0x9070000C, 6, 1, 0);
update_by_mnemonic(state, 0x9070000C, 7, 1, 0);
update_by_mnemonic(state, 0x90700008, 0, 2, 1);
update_by_mnemonic(state, 0x90700008, 2, 2, 1);
return 0;
}
static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg)
{
int stat = 0;
u8 *buf;
if (cfg->fw)
return firmware_download(state, cfg->fw, cfg->fw_len);
if (!cfg->fw_read)
return -1;
buf = vmalloc(0x40000);
if (!buf)
return -ENOMEM;
cfg->fw_read(cfg->fw_priv, buf, 0x40000);
stat = firmware_download(state, buf, 0x40000);
vfree(buf);
return stat;
}
static int validate_sku(struct mxl *state)
{
u32 pad_mux_bond = 0, prcm_chip_id = 0, prcm_so_cid = 0;
int status;
u32 type = state->base->type;
status = read_by_mnemonic(state, 0x90000190, 0, 3, &pad_mux_bond);
status |= read_by_mnemonic(state, 0x80030000, 0, 12, &prcm_chip_id);
status |= read_by_mnemonic(state, 0x80030004, 24, 8, &prcm_so_cid);
if (status)
return -1;
dev_info(state->i2cdev, "padMuxBond=%08x, prcmChipId=%08x, prcmSoCId=%08x\n",
pad_mux_bond, prcm_chip_id, prcm_so_cid);
if (prcm_chip_id != 0x560) {
switch (pad_mux_bond) {
case MXL_HYDRA_SKU_ID_581:
if (type == MXL_HYDRA_DEVICE_581)
return 0;
if (type == MXL_HYDRA_DEVICE_581S) {
state->base->type = MXL_HYDRA_DEVICE_581;
return 0;
}
break;
case MXL_HYDRA_SKU_ID_584:
if (type == MXL_HYDRA_DEVICE_584)
return 0;
break;
case MXL_HYDRA_SKU_ID_544:
if (type == MXL_HYDRA_DEVICE_544)
return 0;
if (type == MXL_HYDRA_DEVICE_542)
return 0;
break;
case MXL_HYDRA_SKU_ID_582:
if (type == MXL_HYDRA_DEVICE_582)
return 0;
break;
default:
return -1;
}
} else {
}
return -1;
}
static int get_fwinfo(struct mxl *state)
{
int status;
u32 val = 0;
status = read_by_mnemonic(state, 0x90000190, 0, 3, &val);
if (status)
return status;
dev_info(state->i2cdev, "chipID=%08x\n", val);
status = read_by_mnemonic(state, 0x80030004, 8, 8, &val);
if (status)
return status;
dev_info(state->i2cdev, "chipVer=%08x\n", val);
status = read_register(state, HYDRA_FIRMWARE_VERSION, &val);
if (status)
return status;
dev_info(state->i2cdev, "FWVer=%08x\n", val);
state->base->fwversion = val;
return status;
}
static u8 ts_map1_to_1[MXL_HYDRA_DEMOD_MAX] = {
MXL_HYDRA_DEMOD_ID_0,
MXL_HYDRA_DEMOD_ID_1,
MXL_HYDRA_DEMOD_ID_2,
MXL_HYDRA_DEMOD_ID_3,
MXL_HYDRA_DEMOD_ID_4,
MXL_HYDRA_DEMOD_ID_5,
MXL_HYDRA_DEMOD_ID_6,
MXL_HYDRA_DEMOD_ID_7,
};
static u8 ts_map54x[MXL_HYDRA_DEMOD_MAX] = {
MXL_HYDRA_DEMOD_ID_2,
MXL_HYDRA_DEMOD_ID_3,
MXL_HYDRA_DEMOD_ID_4,
MXL_HYDRA_DEMOD_ID_5,
MXL_HYDRA_DEMOD_MAX,
MXL_HYDRA_DEMOD_MAX,
MXL_HYDRA_DEMOD_MAX,
MXL_HYDRA_DEMOD_MAX,
};
static int probe(struct mxl *state, struct mxl5xx_cfg *cfg)
{
u32 chipver;
int fw, status, j;
struct MXL_HYDRA_MPEGOUT_PARAM_T mpeg_interface_cfg;
state->base->ts_map = ts_map1_to_1;
switch (state->base->type) {
case MXL_HYDRA_DEVICE_581:
case MXL_HYDRA_DEVICE_581S:
state->base->can_clkout = 1;
state->base->demod_num = 8;
state->base->tuner_num = 1;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_581;
break;
case MXL_HYDRA_DEVICE_582:
state->base->can_clkout = 1;
state->base->demod_num = 8;
state->base->tuner_num = 3;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_582;
break;
case MXL_HYDRA_DEVICE_585:
state->base->can_clkout = 0;
state->base->demod_num = 8;
state->base->tuner_num = 4;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_585;
break;
case MXL_HYDRA_DEVICE_544:
state->base->can_clkout = 0;
state->base->demod_num = 4;
state->base->tuner_num = 4;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_544;
state->base->ts_map = ts_map54x;
break;
case MXL_HYDRA_DEVICE_541:
case MXL_HYDRA_DEVICE_541S:
state->base->can_clkout = 0;
state->base->demod_num = 4;
state->base->tuner_num = 1;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_541;
state->base->ts_map = ts_map54x;
break;
case MXL_HYDRA_DEVICE_561:
case MXL_HYDRA_DEVICE_561S:
state->base->can_clkout = 0;
state->base->demod_num = 6;
state->base->tuner_num = 1;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_561;
break;
case MXL_HYDRA_DEVICE_568:
state->base->can_clkout = 0;
state->base->demod_num = 8;
state->base->tuner_num = 1;
state->base->chan_bond = 1;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_568;
break;
case MXL_HYDRA_DEVICE_542:
state->base->can_clkout = 1;
state->base->demod_num = 4;
state->base->tuner_num = 3;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_542;
state->base->ts_map = ts_map54x;
break;
case MXL_HYDRA_DEVICE_TEST:
case MXL_HYDRA_DEVICE_584:
default:
state->base->can_clkout = 0;
state->base->demod_num = 8;
state->base->tuner_num = 4;
state->base->sku_type = MXL_HYDRA_SKU_TYPE_584;
break;
}
status = validate_sku(state);
if (status)
return status;
update_by_mnemonic(state, 0x80030014, 9, 1, 1);
update_by_mnemonic(state, 0x8003003C, 12, 1, 1);
status = read_by_mnemonic(state, 0x80030000, 12, 4, &chipver);
if (status)
state->base->chipversion = 0;
else
state->base->chipversion = (chipver == 2) ? 2 : 1;
dev_info(state->i2cdev, "Hydra chip version %u\n",
state->base->chipversion);
cfg_dev_xtal(state, cfg->clk, cfg->cap, 0);
fw = firmware_is_alive(state);
if (!fw) {
status = load_fw(state, cfg);
if (status)
return status;
}
get_fwinfo(state);
config_mux(state);
mpeg_interface_cfg.enable = MXL_ENABLE;
mpeg_interface_cfg.lsb_or_msb_first = MXL_HYDRA_MPEG_SERIAL_MSB_1ST;
/* supports only (0-104&139)MHz */
if (cfg->ts_clk)
mpeg_interface_cfg.max_mpeg_clk_rate = cfg->ts_clk;
else
mpeg_interface_cfg.max_mpeg_clk_rate = 69; /* 139; */
mpeg_interface_cfg.mpeg_clk_phase = MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG;
mpeg_interface_cfg.mpeg_clk_pol = MXL_HYDRA_MPEG_CLK_IN_PHASE;
/* MXL_HYDRA_MPEG_CLK_GAPPED; */
mpeg_interface_cfg.mpeg_clk_type = MXL_HYDRA_MPEG_CLK_CONTINUOUS;
mpeg_interface_cfg.mpeg_error_indication =
MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED;
mpeg_interface_cfg.mpeg_mode = MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE;
mpeg_interface_cfg.mpeg_sync_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH;
mpeg_interface_cfg.mpeg_sync_pulse_width = MXL_HYDRA_MPEG_SYNC_WIDTH_BIT;
mpeg_interface_cfg.mpeg_valid_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH;
for (j = 0; j < state->base->demod_num; j++) {
status = config_ts(state, (enum MXL_HYDRA_DEMOD_ID_E) j,
&mpeg_interface_cfg);
if (status)
return status;
}
set_drive_strength(state, 1);
return 0;
}
struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg, u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{
struct mxl *state;
struct mxl_base *base;
state = kzalloc(sizeof(struct mxl), GFP_KERNEL);
if (!state)
return NULL;
state->demod = demod;
state->tuner = tuner;
state->tuner_in_use = 0xffffffff;
state->i2cdev = &i2c->dev;
base = match_base(i2c, cfg->adr);
if (base) {
base->count++;
if (base->count > base->demod_num)
goto fail;
state->base = base;
} else {
base = kzalloc(sizeof(struct mxl_base), GFP_KERNEL);
if (!base)
goto fail;
base->i2c = i2c;
base->adr = cfg->adr;
base->type = cfg->type;
base->count = 1;
mutex_init(&base->i2c_lock);
mutex_init(&base->status_lock);
mutex_init(&base->tune_lock);
INIT_LIST_HEAD(&base->mxls);
state->base = base;
if (probe(state, cfg) < 0) {
kfree(base);
goto fail;
}
list_add(&base->mxllist, &mxllist);
}
state->fe.ops = mxl_ops;
state->xbar[0] = 4;
state->xbar[1] = demod;
state->xbar[2] = 8;
state->fe.demodulator_priv = state;
*fn_set_input = set_input;
list_add(&state->mxl, &base->mxls);
return &state->fe;
fail:
kfree(state);
return NULL;
}
EXPORT_SYMBOL_GPL(mxl5xx_attach);
MODULE_DESCRIPTION("MaxLinear MxL5xx DVB-S/S2 tuner-demodulator driver");
MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR");
MODULE_LICENSE("GPL");
#ifndef _MXL5XX_H_
#define _MXL5XX_H_
#include <linux/types.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
struct mxl5xx_cfg {
u8 adr;
u8 type;
u32 cap;
u32 clk;
u32 ts_clk;
u8 *fw;
u32 fw_len;
int (*fw_read)(void *priv, u8 *buf, u32 len);
void *fw_priv;
};
#if IS_REACHABLE(CONFIG_DVB_MXL5XX)
extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg, u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int));
#else
static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg, u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_MXL5XX */
#endif /* _MXL5XX_H_ */
/*
* Defines for the Maxlinear MX58x family of tuners/demods
*
* Copyright (C) 2014 Digital Devices GmbH
*
* based on code:
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
* which was released under GPL V2
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, as published by the Free Software Foundation.
*/
enum MXL_BOOL_E {
MXL_DISABLE = 0,
MXL_ENABLE = 1,
MXL_FALSE = 0,
MXL_TRUE = 1,
MXL_INVALID = 0,
MXL_VALID = 1,
MXL_NO = 0,
MXL_YES = 1,
MXL_OFF = 0,
MXL_ON = 1
};
/* Firmware-Host Command IDs */
enum MXL_HYDRA_HOST_CMD_ID_E {
/* --Device command IDs-- */
MXL_HYDRA_DEV_NO_OP_CMD = 0, /* No OP */
MXL_HYDRA_DEV_SET_POWER_MODE_CMD = 1,
MXL_HYDRA_DEV_SET_OVERWRITE_DEF_CMD = 2,
/* Host-used CMD, not used by firmware */
MXL_HYDRA_DEV_FIRMWARE_DOWNLOAD_CMD = 3,
/* Additional CONTROL types from DTV */
MXL_HYDRA_DEV_SET_BROADCAST_PID_STB_ID_CMD = 4,
MXL_HYDRA_DEV_GET_PMM_SLEEP_CMD = 5,
/* --Tuner command IDs-- */
MXL_HYDRA_TUNER_TUNE_CMD = 6,
MXL_HYDRA_TUNER_GET_STATUS_CMD = 7,
/* --Demod command IDs-- */
MXL_HYDRA_DEMOD_SET_PARAM_CMD = 8,
MXL_HYDRA_DEMOD_GET_STATUS_CMD = 9,
MXL_HYDRA_DEMOD_RESET_FEC_COUNTER_CMD = 10,
MXL_HYDRA_DEMOD_SET_PKT_NUM_CMD = 11,
MXL_HYDRA_DEMOD_SET_IQ_SOURCE_CMD = 12,
MXL_HYDRA_DEMOD_GET_IQ_DATA_CMD = 13,
MXL_HYDRA_DEMOD_GET_M68HC05_VER_CMD = 14,
MXL_HYDRA_DEMOD_SET_ERROR_COUNTER_MODE_CMD = 15,
/* --- ABORT channel tune */
MXL_HYDRA_ABORT_TUNE_CMD = 16, /* Abort current tune command. */
/* --SWM/FSK command IDs-- */
MXL_HYDRA_FSK_RESET_CMD = 17,
MXL_HYDRA_FSK_MSG_CMD = 18,
MXL_HYDRA_FSK_SET_OP_MODE_CMD = 19,
/* --DiSeqC command IDs-- */
MXL_HYDRA_DISEQC_MSG_CMD = 20,
MXL_HYDRA_DISEQC_COPY_MSG_TO_MAILBOX = 21,
MXL_HYDRA_DISEQC_CFG_MSG_CMD = 22,
/* --- FFT Debug Command IDs-- */
MXL_HYDRA_REQ_FFT_SPECTRUM_CMD = 23,
/* -- Demod scramblle code */
MXL_HYDRA_DEMOD_SCRAMBLE_CODE_CMD = 24,
/* ---For host to know how many commands in total */
MXL_HYDRA_LAST_HOST_CMD = 25,
MXL_HYDRA_DEMOD_INTR_TYPE_CMD = 47,
MXL_HYDRA_DEV_INTR_CLEAR_CMD = 48,
MXL_HYDRA_TUNER_SPECTRUM_REQ_CMD = 53,
MXL_HYDRA_TUNER_ACTIVATE_CMD = 55,
MXL_HYDRA_DEV_CFG_POWER_MODE_CMD = 56,
MXL_HYDRA_DEV_XTAL_CAP_CMD = 57,
MXL_HYDRA_DEV_CFG_SKU_CMD = 58,
MXL_HYDRA_TUNER_SPECTRUM_MIN_GAIN_CMD = 59,
MXL_HYDRA_DISEQC_CONT_TONE_CFG = 60,
MXL_HYDRA_DEV_RF_WAKE_UP_CMD = 61,
MXL_HYDRA_DEMOD_CFG_EQ_CTRL_PARAM_CMD = 62,
MXL_HYDRA_DEMOD_FREQ_OFFSET_SEARCH_RANGE_CMD = 63,
MXL_HYDRA_DEV_REQ_PWR_FROM_ADCRSSI_CMD = 64,
MXL_XCPU_PID_FLT_CFG_CMD = 65,
MXL_XCPU_SHMEM_TEST_CMD = 66,
MXL_XCPU_ABORT_TUNE_CMD = 67,
MXL_XCPU_CHAN_TUNE_CMD = 68,
MXL_XCPU_FLT_BOND_HDRS_CMD = 69,
MXL_HYDRA_DEV_BROADCAST_WAKE_UP_CMD = 70,
MXL_HYDRA_FSK_CFG_FSK_FREQ_CMD = 71,
MXL_HYDRA_FSK_POWER_DOWN_CMD = 72,
MXL_XCPU_CLEAR_CB_STATS_CMD = 73,
MXL_XCPU_CHAN_BOND_RESTART_CMD = 74
};
#define MXL_ENABLE_BIG_ENDIAN (0)
#define MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH 248
#define MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN (248)
#define MXL_HYDRA_CAP_MIN 10
#define MXL_HYDRA_CAP_MAX 33
#define MXL_HYDRA_PLID_REG_READ 0xFB /* Read register PLID */
#define MXL_HYDRA_PLID_REG_WRITE 0xFC /* Write register PLID */
#define MXL_HYDRA_PLID_CMD_READ 0xFD /* Command Read PLID */
#define MXL_HYDRA_PLID_CMD_WRITE 0xFE /* Command Write PLID */
#define MXL_HYDRA_REG_SIZE_IN_BYTES 4 /* Hydra register size in bytes */
#define MXL_HYDRA_I2C_HDR_SIZE (2 * sizeof(u8)) /* PLID + LEN(0xFF) */
#define MXL_HYDRA_CMD_HEADER_SIZE (MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE)
#define MXL_HYDRA_SKU_ID_581 0
#define MXL_HYDRA_SKU_ID_584 1
#define MXL_HYDRA_SKU_ID_585 2
#define MXL_HYDRA_SKU_ID_544 3
#define MXL_HYDRA_SKU_ID_561 4
#define MXL_HYDRA_SKU_ID_582 5
#define MXL_HYDRA_SKU_ID_568 6
/* macro for register write data buffer size
* (PLID + LEN (0xFF) + RegAddr + RegData)
*/
#define MXL_HYDRA_REG_WRITE_LEN (MXL_HYDRA_I2C_HDR_SIZE + (2 * MXL_HYDRA_REG_SIZE_IN_BYTES))
/* macro to extract a single byte from 4-byte(32-bit) data */
#define GET_BYTE(x, n) (((x) >> (8*(n))) & 0xFF)
#define MAX_CMD_DATA 512
#define MXL_GET_REG_MASK_32(lsb_loc, num_of_bits) ((0xFFFFFFFF >> (32 - (num_of_bits))) << (lsb_loc))
#define FW_DL_SIGN (0xDEADBEEF)
#define MBIN_FORMAT_VERSION '1'
#define MBIN_FILE_HEADER_ID 'M'
#define MBIN_SEGMENT_HEADER_ID 'S'
#define MBIN_MAX_FILE_LENGTH (1<<23)
struct MBIN_FILE_HEADER_T {
u8 id;
u8 fmt_version;
u8 header_len;
u8 num_segments;
u8 entry_address[4];
u8 image_size24[3];
u8 image_checksum;
u8 reserved[4];
};
struct MBIN_FILE_T {
struct MBIN_FILE_HEADER_T header;
u8 data[1];
};
struct MBIN_SEGMENT_HEADER_T {
u8 id;
u8 len24[3];
u8 address[4];
};
struct MBIN_SEGMENT_T {
struct MBIN_SEGMENT_HEADER_T header;
u8 data[1];
};
enum MXL_CMD_TYPE_E { MXL_CMD_WRITE = 0, MXL_CMD_READ };
#define BUILD_HYDRA_CMD(cmd_id, req_type, size, data_ptr, cmd_buff) \
do { \
cmd_buff[0] = ((req_type == MXL_CMD_WRITE) ? MXL_HYDRA_PLID_CMD_WRITE : MXL_HYDRA_PLID_CMD_READ); \
cmd_buff[1] = (size > 251) ? 0xff : (u8) (size + 4); \
cmd_buff[2] = size; \
cmd_buff[3] = cmd_id; \
cmd_buff[4] = 0x00; \
cmd_buff[5] = 0x00; \
convert_endian(MXL_ENABLE_BIG_ENDIAN, size, (u8 *)data_ptr); \
memcpy((void *)&cmd_buff[6], data_ptr, size); \
} while (0)
struct MXL_REG_FIELD_T {
u32 reg_addr;
u8 lsb_pos;
u8 num_of_bits;
};
struct MXL_DEV_CMD_DATA_T {
u32 data_size;
u8 data[MAX_CMD_DATA];
};
enum MXL_HYDRA_SKU_TYPE_E {
MXL_HYDRA_SKU_TYPE_MIN = 0x00,
MXL_HYDRA_SKU_TYPE_581 = 0x00,
MXL_HYDRA_SKU_TYPE_584 = 0x01,
MXL_HYDRA_SKU_TYPE_585 = 0x02,
MXL_HYDRA_SKU_TYPE_544 = 0x03,
MXL_HYDRA_SKU_TYPE_561 = 0x04,
MXL_HYDRA_SKU_TYPE_5XX = 0x05,
MXL_HYDRA_SKU_TYPE_5YY = 0x06,
MXL_HYDRA_SKU_TYPE_511 = 0x07,
MXL_HYDRA_SKU_TYPE_561_DE = 0x08,
MXL_HYDRA_SKU_TYPE_582 = 0x09,
MXL_HYDRA_SKU_TYPE_541 = 0x0A,
MXL_HYDRA_SKU_TYPE_568 = 0x0B,
MXL_HYDRA_SKU_TYPE_542 = 0x0C,
MXL_HYDRA_SKU_TYPE_MAX = 0x0D,
};
struct MXL_HYDRA_SKU_COMMAND_T {
enum MXL_HYDRA_SKU_TYPE_E sku_type;
};
enum MXL_HYDRA_DEMOD_ID_E {
MXL_HYDRA_DEMOD_ID_0 = 0,
MXL_HYDRA_DEMOD_ID_1,
MXL_HYDRA_DEMOD_ID_2,
MXL_HYDRA_DEMOD_ID_3,
MXL_HYDRA_DEMOD_ID_4,
MXL_HYDRA_DEMOD_ID_5,
MXL_HYDRA_DEMOD_ID_6,
MXL_HYDRA_DEMOD_ID_7,
MXL_HYDRA_DEMOD_MAX
};
#define MXL_DEMOD_SCRAMBLE_SEQ_LEN 12
#define MAX_STEP_SIZE_24_XTAL_102_05_KHZ 195
#define MAX_STEP_SIZE_24_XTAL_204_10_KHZ 215
#define MAX_STEP_SIZE_24_XTAL_306_15_KHZ 203
#define MAX_STEP_SIZE_24_XTAL_408_20_KHZ 177
#define MAX_STEP_SIZE_27_XTAL_102_05_KHZ 195
#define MAX_STEP_SIZE_27_XTAL_204_10_KHZ 215
#define MAX_STEP_SIZE_27_XTAL_306_15_KHZ 203
#define MAX_STEP_SIZE_27_XTAL_408_20_KHZ 177
#define MXL_HYDRA_SPECTRUM_MIN_FREQ_KHZ 300000
#define MXL_HYDRA_SPECTRUM_MAX_FREQ_KHZ 2350000
enum MXL_DEMOD_CHAN_PARAMS_OFFSET_E {
DMD_STANDARD_ADDR = 0,
DMD_SPECTRUM_INVERSION_ADDR,
DMD_SPECTRUM_ROLL_OFF_ADDR,
DMD_SYMBOL_RATE_ADDR,
DMD_MODULATION_SCHEME_ADDR,
DMD_FEC_CODE_RATE_ADDR,
DMD_SNR_ADDR,
DMD_FREQ_OFFSET_ADDR,
DMD_CTL_FREQ_OFFSET_ADDR,
DMD_STR_FREQ_OFFSET_ADDR,
DMD_FTL_FREQ_OFFSET_ADDR,
DMD_STR_NBC_SYNC_LOCK_ADDR,
DMD_CYCLE_SLIP_COUNT_ADDR,
DMD_DISPLAY_IQ_ADDR,
DMD_DVBS2_CRC_ERRORS_ADDR,
DMD_DVBS2_PER_COUNT_ADDR,
DMD_DVBS2_PER_WINDOW_ADDR,
DMD_DVBS_CORR_RS_ERRORS_ADDR,
DMD_DVBS_UNCORR_RS_ERRORS_ADDR,
DMD_DVBS_BER_COUNT_ADDR,
DMD_DVBS_BER_WINDOW_ADDR,
DMD_TUNER_ID_ADDR,
DMD_DVBS2_PILOT_ON_OFF_ADDR,
DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR,
MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE,
};
enum MXL_HYDRA_TUNER_ID_E {
MXL_HYDRA_TUNER_ID_0 = 0,
MXL_HYDRA_TUNER_ID_1,
MXL_HYDRA_TUNER_ID_2,
MXL_HYDRA_TUNER_ID_3,
MXL_HYDRA_TUNER_MAX
};
enum MXL_HYDRA_BCAST_STD_E {
MXL_HYDRA_DSS = 0,
MXL_HYDRA_DVBS,
MXL_HYDRA_DVBS2,
};
enum MXL_HYDRA_FEC_E {
MXL_HYDRA_FEC_AUTO = 0,
MXL_HYDRA_FEC_1_2,
MXL_HYDRA_FEC_3_5,
MXL_HYDRA_FEC_2_3,
MXL_HYDRA_FEC_3_4,
MXL_HYDRA_FEC_4_5,
MXL_HYDRA_FEC_5_6,
MXL_HYDRA_FEC_6_7,
MXL_HYDRA_FEC_7_8,
MXL_HYDRA_FEC_8_9,
MXL_HYDRA_FEC_9_10,
};
enum MXL_HYDRA_MODULATION_E {
MXL_HYDRA_MOD_AUTO = 0,
MXL_HYDRA_MOD_QPSK,
MXL_HYDRA_MOD_8PSK
};
enum MXL_HYDRA_SPECTRUM_E {
MXL_HYDRA_SPECTRUM_AUTO = 0,
MXL_HYDRA_SPECTRUM_INVERTED,
MXL_HYDRA_SPECTRUM_NON_INVERTED,
};
enum MXL_HYDRA_ROLLOFF_E {
MXL_HYDRA_ROLLOFF_AUTO = 0,
MXL_HYDRA_ROLLOFF_0_20,
MXL_HYDRA_ROLLOFF_0_25,
MXL_HYDRA_ROLLOFF_0_35
};
enum MXL_HYDRA_PILOTS_E {
MXL_HYDRA_PILOTS_OFF = 0,
MXL_HYDRA_PILOTS_ON,
MXL_HYDRA_PILOTS_AUTO
};
enum MXL_HYDRA_CONSTELLATION_SRC_E {
MXL_HYDRA_FORMATTER = 0,
MXL_HYDRA_LEGACY_FEC,
MXL_HYDRA_FREQ_RECOVERY,
MXL_HYDRA_NBC,
MXL_HYDRA_CTL,
MXL_HYDRA_EQ,
};
struct MXL_HYDRA_DEMOD_LOCK_T {
int agc_lock; /* AGC lock info */
int fec_lock; /* Demod FEC block lock info */
};
struct MXL_HYDRA_DEMOD_STATUS_DVBS_T {
u32 rs_errors; /* RS decoder err counter */
u32 ber_window; /* Ber Windows */
u32 ber_count; /* BER count */
u32 ber_window_iter1; /* Ber Windows - post viterbi */
u32 ber_count_iter1; /* BER count - post viterbi */
};
struct MXL_HYDRA_DEMOD_STATUS_DSS_T {
u32 rs_errors; /* RS decoder err counter */
u32 ber_window; /* Ber Windows */
u32 ber_count; /* BER count */
};
struct MXL_HYDRA_DEMOD_STATUS_DVBS2_T {
u32 crc_errors; /* CRC error counter */
u32 packet_error_count; /* Number of packet errors */
u32 total_packets; /* Total packets */
};
struct MXL_HYDRA_DEMOD_STATUS_T {
enum MXL_HYDRA_BCAST_STD_E standard_mask; /* Standard DVB-S, DVB-S2 or DSS */
union {
struct MXL_HYDRA_DEMOD_STATUS_DVBS_T demod_status_dvbs; /* DVB-S demod status */
struct MXL_HYDRA_DEMOD_STATUS_DVBS2_T demod_status_dvbs2; /* DVB-S2 demod status */
struct MXL_HYDRA_DEMOD_STATUS_DSS_T demod_status_dss; /* DSS demod status */
} u;
};
struct MXL_HYDRA_DEMOD_SIG_OFFSET_INFO_T {
s32 carrier_offset_in_hz; /* CRL offset info */
s32 symbol_offset_in_symbol; /* SRL offset info */
};
struct MXL_HYDRA_DEMOD_SCRAMBLE_INFO_T {
u8 scramble_sequence[MXL_DEMOD_SCRAMBLE_SEQ_LEN]; /* scramble sequence */
u32 scramble_code; /* scramble gold code */
};
enum MXL_HYDRA_SPECTRUM_STEP_SIZE_E {
MXL_HYDRA_STEP_SIZE_24_XTAL_102_05KHZ, /* 102.05 KHz for 24 MHz XTAL */
MXL_HYDRA_STEP_SIZE_24_XTAL_204_10KHZ, /* 204.10 KHz for 24 MHz XTAL */
MXL_HYDRA_STEP_SIZE_24_XTAL_306_15KHZ, /* 306.15 KHz for 24 MHz XTAL */
MXL_HYDRA_STEP_SIZE_24_XTAL_408_20KHZ, /* 408.20 KHz for 24 MHz XTAL */
MXL_HYDRA_STEP_SIZE_27_XTAL_102_05KHZ, /* 102.05 KHz for 27 MHz XTAL */
MXL_HYDRA_STEP_SIZE_27_XTAL_204_35KHZ, /* 204.35 KHz for 27 MHz XTAL */
MXL_HYDRA_STEP_SIZE_27_XTAL_306_52KHZ, /* 306.52 KHz for 27 MHz XTAL */
MXL_HYDRA_STEP_SIZE_27_XTAL_408_69KHZ, /* 408.69 KHz for 27 MHz XTAL */
};
enum MXL_HYDRA_SPECTRUM_RESOLUTION_E {
MXL_HYDRA_SPECTRUM_RESOLUTION_00_1_DB, /* 0.1 dB */
MXL_HYDRA_SPECTRUM_RESOLUTION_01_0_DB, /* 1.0 dB */
MXL_HYDRA_SPECTRUM_RESOLUTION_05_0_DB, /* 5.0 dB */
MXL_HYDRA_SPECTRUM_RESOLUTION_10_0_DB, /* 10 dB */
};
enum MXL_HYDRA_SPECTRUM_ERROR_CODE_E {
MXL_SPECTRUM_NO_ERROR,
MXL_SPECTRUM_INVALID_PARAMETER,
MXL_SPECTRUM_INVALID_STEP_SIZE,
MXL_SPECTRUM_BW_CANNOT_BE_COVERED,
MXL_SPECTRUM_DEMOD_BUSY,
MXL_SPECTRUM_TUNER_NOT_ENABLED,
};
struct MXL_HYDRA_SPECTRUM_REQ_T {
u32 tuner_index; /* TUNER Ctrl: one of MXL58x_TUNER_ID_E */
u32 demod_index; /* DEMOD Ctrl: one of MXL58x_DEMOD_ID_E */
enum MXL_HYDRA_SPECTRUM_STEP_SIZE_E step_size_in_khz;
u32 starting_freq_ink_hz;
u32 total_steps;
enum MXL_HYDRA_SPECTRUM_RESOLUTION_E spectrum_division;
};
enum MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E {
MXL_HYDRA_SEARCH_MAX_OFFSET = 0, /* DMD searches for max freq offset (i.e. 5MHz) */
MXL_HYDRA_SEARCH_BW_PLUS_ROLLOFF, /* DMD searches for BW + ROLLOFF/2 */
};
struct MXL58X_CFG_FREQ_OFF_SEARCH_RANGE_T {
u32 demod_index;
enum MXL_HYDRA_SEARCH_FREQ_OFFSET_TYPE_E search_type;
};
/* there are two slices
* slice0 - TS0, TS1, TS2 & TS3
* slice1 - TS4, TS5, TS6 & TS7
*/
#define MXL_HYDRA_TS_SLICE_MAX 2
#define MAX_FIXED_PID_NUM 32
#define MXL_HYDRA_NCO_CLK 418 /* 418 MHz */
#define MXL_HYDRA_MAX_TS_CLOCK 139 /* 139 MHz */
#define MXL_HYDRA_TS_FIXED_PID_FILT_SIZE 32
#define MXL_HYDRA_SHARED_PID_FILT_SIZE_DEFAULT 33 /* Shared PID filter size in 1-1 mux mode */
#define MXL_HYDRA_SHARED_PID_FILT_SIZE_2_TO_1 66 /* Shared PID filter size in 2-1 mux mode */
#define MXL_HYDRA_SHARED_PID_FILT_SIZE_4_TO_1 132 /* Shared PID filter size in 4-1 mux mode */
enum MXL_HYDRA_PID_BANK_TYPE_E {
MXL_HYDRA_SOFTWARE_PID_BANK = 0,
MXL_HYDRA_HARDWARE_PID_BANK,
};
enum MXL_HYDRA_TS_MUX_MODE_E {
MXL_HYDRA_TS_MUX_PID_REMAP = 0,
MXL_HYDRA_TS_MUX_PREFIX_EXTRA_HEADER = 1,
};
enum MXL_HYDRA_TS_MUX_TYPE_E {
MXL_HYDRA_TS_MUX_DISABLE = 0, /* No Mux ( 1 TSIF to 1 TSIF) */
MXL_HYDRA_TS_MUX_2_TO_1, /* Mux 2 TSIF to 1 TSIF */
MXL_HYDRA_TS_MUX_4_TO_1, /* Mux 4 TSIF to 1 TSIF */
};
enum MXL_HYDRA_TS_GROUP_E {
MXL_HYDRA_TS_GROUP_0_3 = 0, /* TS group 0 to 3 (TS0, TS1, TS2 & TS3) */
MXL_HYDRA_TS_GROUP_4_7, /* TS group 0 to 3 (TS4, TS5, TS6 & TS7) */
};
enum MXL_HYDRA_TS_PID_FLT_CTRL_E {
MXL_HYDRA_TS_PIDS_ALLOW_ALL = 0, /* Allow all pids */
MXL_HYDRA_TS_PIDS_DROP_ALL, /* Drop all pids */
MXL_HYDRA_TS_INVALIDATE_PID_FILTER, /* Delete current PD filter in the device */
};
enum MXL_HYDRA_TS_PID_TYPE_E {
MXL_HYDRA_TS_PID_FIXED = 0,
MXL_HYDRA_TS_PID_REGULAR,
};
struct MXL_HYDRA_TS_PID_T {
u16 original_pid; /* pid from TS */
u16 remapped_pid; /* remapped pid */
enum MXL_BOOL_E enable; /* enable or disable pid */
enum MXL_BOOL_E allow_or_drop; /* allow or drop pid */
enum MXL_BOOL_E enable_pid_remap; /* enable or disable pid remap */
u8 bond_id; /* Bond ID in A0 always 0 - Only for 568 Sku */
u8 dest_id; /* Output port ID for the PID - Only for 568 Sku */
};
struct MXL_HYDRA_TS_MUX_PREFIX_HEADER_T {
enum MXL_BOOL_E enable;
u8 num_byte;
u8 header[12];
};
enum MXL_HYDRA_PID_FILTER_BANK_E {
MXL_HYDRA_PID_BANK_A = 0,
MXL_HYDRA_PID_BANK_B,
};
enum MXL_HYDRA_MPEG_DATA_FMT_E {
MXL_HYDRA_MPEG_SERIAL_MSB_1ST = 0,
MXL_HYDRA_MPEG_SERIAL_LSB_1ST,
MXL_HYDRA_MPEG_SYNC_WIDTH_BIT = 0,
MXL_HYDRA_MPEG_SYNC_WIDTH_BYTE
};
enum MXL_HYDRA_MPEG_MODE_E {
MXL_HYDRA_MPEG_MODE_SERIAL_4_WIRE = 0, /* MPEG 4 Wire serial mode */
MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE, /* MPEG 3 Wire serial mode */
MXL_HYDRA_MPEG_MODE_SERIAL_2_WIRE, /* MPEG 2 Wire serial mode */
MXL_HYDRA_MPEG_MODE_PARALLEL /* MPEG parallel mode - valid only for MxL581 */
};
enum MXL_HYDRA_MPEG_CLK_TYPE_E {
MXL_HYDRA_MPEG_CLK_CONTINUOUS = 0, /* Continuous MPEG clock */
MXL_HYDRA_MPEG_CLK_GAPPED, /* Gapped (gated) MPEG clock */
};
enum MXL_HYDRA_MPEG_CLK_FMT_E {
MXL_HYDRA_MPEG_ACTIVE_LOW = 0,
MXL_HYDRA_MPEG_ACTIVE_HIGH,
MXL_HYDRA_MPEG_CLK_NEGATIVE = 0,
MXL_HYDRA_MPEG_CLK_POSITIVE,
MXL_HYDRA_MPEG_CLK_IN_PHASE = 0,
MXL_HYDRA_MPEG_CLK_INVERTED,
};
enum MXL_HYDRA_MPEG_CLK_PHASE_E {
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG = 0,
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_90_DEG,
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_180_DEG,
MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_270_DEG
};
enum MXL_HYDRA_MPEG_ERR_INDICATION_E {
MXL_HYDRA_MPEG_ERR_REPLACE_SYNC = 0,
MXL_HYDRA_MPEG_ERR_REPLACE_VALID,
MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED
};
struct MXL_HYDRA_MPEGOUT_PARAM_T {
int enable; /* Enable or Disable MPEG OUT */
enum MXL_HYDRA_MPEG_CLK_TYPE_E mpeg_clk_type; /* Continuous or gapped */
enum MXL_HYDRA_MPEG_CLK_FMT_E mpeg_clk_pol; /* MPEG Clk polarity */
u8 max_mpeg_clk_rate; /* Max MPEG Clk rate (0 - 104 MHz, 139 MHz) */
enum MXL_HYDRA_MPEG_CLK_PHASE_E mpeg_clk_phase; /* MPEG Clk phase */
enum MXL_HYDRA_MPEG_DATA_FMT_E lsb_or_msb_first; /* LSB first or MSB first in TS transmission */
enum MXL_HYDRA_MPEG_DATA_FMT_E mpeg_sync_pulse_width; /* MPEG SYNC pulse width (1-bit or 1-byte) */
enum MXL_HYDRA_MPEG_CLK_FMT_E mpeg_valid_pol; /* MPEG VALID polarity */
enum MXL_HYDRA_MPEG_CLK_FMT_E mpeg_sync_pol; /* MPEG SYNC polarity */
enum MXL_HYDRA_MPEG_MODE_E mpeg_mode; /* config 4/3/2-wire serial or parallel TS out */
enum MXL_HYDRA_MPEG_ERR_INDICATION_E mpeg_error_indication; /* Enable or Disable MPEG error indication */
};
enum MXL_HYDRA_EXT_TS_IN_ID_E {
MXL_HYDRA_EXT_TS_IN_0 = 0,
MXL_HYDRA_EXT_TS_IN_1,
MXL_HYDRA_EXT_TS_IN_2,
MXL_HYDRA_EXT_TS_IN_3,
MXL_HYDRA_EXT_TS_IN_MAX
};
enum MXL_HYDRA_TS_OUT_ID_E {
MXL_HYDRA_TS_OUT_0 = 0,
MXL_HYDRA_TS_OUT_1,
MXL_HYDRA_TS_OUT_2,
MXL_HYDRA_TS_OUT_3,
MXL_HYDRA_TS_OUT_4,
MXL_HYDRA_TS_OUT_5,
MXL_HYDRA_TS_OUT_6,
MXL_HYDRA_TS_OUT_7,
MXL_HYDRA_TS_OUT_MAX
};
enum MXL_HYDRA_TS_DRIVE_STRENGTH_E {
MXL_HYDRA_TS_DRIVE_STRENGTH_1X = 0,
MXL_HYDRA_TS_DRIVE_STRENGTH_2X,
MXL_HYDRA_TS_DRIVE_STRENGTH_3X,
MXL_HYDRA_TS_DRIVE_STRENGTH_4X,
MXL_HYDRA_TS_DRIVE_STRENGTH_5X,
MXL_HYDRA_TS_DRIVE_STRENGTH_6X,
MXL_HYDRA_TS_DRIVE_STRENGTH_7X,
MXL_HYDRA_TS_DRIVE_STRENGTH_8X
};
enum MXL_HYDRA_DEVICE_E {
MXL_HYDRA_DEVICE_581 = 0,
MXL_HYDRA_DEVICE_584,
MXL_HYDRA_DEVICE_585,
MXL_HYDRA_DEVICE_544,
MXL_HYDRA_DEVICE_561,
MXL_HYDRA_DEVICE_TEST,
MXL_HYDRA_DEVICE_582,
MXL_HYDRA_DEVICE_541,
MXL_HYDRA_DEVICE_568,
MXL_HYDRA_DEVICE_542,
MXL_HYDRA_DEVICE_541S,
MXL_HYDRA_DEVICE_561S,
MXL_HYDRA_DEVICE_581S,
MXL_HYDRA_DEVICE_MAX
};
/* Demod IQ data */
struct MXL_HYDRA_DEMOD_IQ_SRC_T {
u32 demod_id;
u32 source_of_iq; /* == 0, it means I/Q comes from Formatter
* == 1, Legacy FEC
* == 2, Frequency Recovery
* == 3, NBC
* == 4, CTL
* == 5, EQ
* == 6, FPGA
*/
};
struct MXL_HYDRA_DEMOD_ABORT_TUNE_T {
u32 demod_id;
};
struct MXL_HYDRA_TUNER_CMD {
u8 tuner_id;
u8 enable;
};
/* Demod Para for Channel Tune */
struct MXL_HYDRA_DEMOD_PARAM_T {
u32 tuner_index;
u32 demod_index;
u32 frequency_in_hz; /* Frequency */
u32 standard; /* one of MXL_HYDRA_BCAST_STD_E */
u32 spectrum_inversion; /* Input : Spectrum inversion. */
u32 roll_off; /* rollOff (alpha) factor */
u32 symbol_rate_in_hz; /* Symbol rate */
u32 pilots; /* TRUE = pilots enabled */
u32 modulation_scheme; /* Input : Modulation Scheme is one of MXL_HYDRA_MODULATION_E */
u32 fec_code_rate; /* Input : Forward error correction rate. Is one of MXL_HYDRA_FEC_E */
u32 max_carrier_offset_in_mhz; /* Maximum carrier freq offset in MHz. Same as freqSearchRangeKHz, but in unit of MHz. */
};
struct MXL_HYDRA_DEMOD_SCRAMBLE_CODE_T {
u32 demod_index;
u8 scramble_sequence[12]; /* scramble sequence */
u32 scramble_code; /* scramble gold code */
};
struct MXL_INTR_CFG_T {
u32 intr_type;
u32 intr_duration_in_nano_secs;
u32 intr_mask;
};
struct MXL_HYDRA_POWER_MODE_CMD {
u8 power_mode; /* enumeration values are defined in MXL_HYDRA_PWR_MODE_E (device API.h) */
};
struct MXL_HYDRA_RF_WAKEUP_PARAM_T {
u32 time_interval_in_seconds; /* in seconds */
u32 tuner_index;
s32 rssi_threshold;
};
struct MXL_HYDRA_RF_WAKEUP_CFG_T {
u32 tuner_count;
struct MXL_HYDRA_RF_WAKEUP_PARAM_T params;
};
enum MXL_HYDRA_AUX_CTRL_MODE_E {
MXL_HYDRA_AUX_CTRL_MODE_FSK = 0, /* Select FSK controller */
MXL_HYDRA_AUX_CTRL_MODE_DISEQC, /* Select DiSEqC controller */
};
enum MXL_HYDRA_DISEQC_OPMODE_E {
MXL_HYDRA_DISEQC_ENVELOPE_MODE = 0,
MXL_HYDRA_DISEQC_TONE_MODE,
};
enum MXL_HYDRA_DISEQC_VER_E {
MXL_HYDRA_DISEQC_1_X = 0, /* Config DiSEqC 1.x mode */
MXL_HYDRA_DISEQC_2_X, /* Config DiSEqC 2.x mode */
MXL_HYDRA_DISEQC_DISABLE /* Disable DiSEqC */
};
enum MXL_HYDRA_DISEQC_CARRIER_FREQ_E {
MXL_HYDRA_DISEQC_CARRIER_FREQ_22KHZ = 0, /* DiSEqC signal frequency of 22 KHz */
MXL_HYDRA_DISEQC_CARRIER_FREQ_33KHZ, /* DiSEqC signal frequency of 33 KHz */
MXL_HYDRA_DISEQC_CARRIER_FREQ_44KHZ /* DiSEqC signal frequency of 44 KHz */
};
enum MXL_HYDRA_DISEQC_ID_E {
MXL_HYDRA_DISEQC_ID_0 = 0,
MXL_HYDRA_DISEQC_ID_1,
MXL_HYDRA_DISEQC_ID_2,
MXL_HYDRA_DISEQC_ID_3
};
enum MXL_HYDRA_FSK_OP_MODE_E {
MXL_HYDRA_FSK_CFG_TYPE_39KPBS = 0, /* 39.0kbps */
MXL_HYDRA_FSK_CFG_TYPE_39_017KPBS, /* 39.017kbps */
MXL_HYDRA_FSK_CFG_TYPE_115_2KPBS /* 115.2kbps */
};
struct MXL58X_DSQ_OP_MODE_T {
u32 diseqc_id; /* DSQ 0, 1, 2 or 3 */
u32 op_mode; /* Envelope mode (0) or internal tone mode (1) */
u32 version; /* 0: 1.0, 1: 1.1, 2: Disable */
u32 center_freq; /* 0: 22KHz, 1: 33KHz and 2: 44 KHz */
};
struct MXL_HYDRA_DISEQC_CFG_CONT_TONE_T {
u32 diseqc_id;
u32 cont_tone_flag; /* 1: Enable , 0: Disable */
};
/*
* Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved
*
* License type: GPLv2
*
* 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.
*
* 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.
*
* This program may alternatively be licensed under a proprietary license from
* MaxLinear, Inc.
*
*/
#ifndef __MXL58X_REGISTERS_H__
#define __MXL58X_REGISTERS_H__
#define HYDRA_INTR_STATUS_REG 0x80030008
#define HYDRA_INTR_MASK_REG 0x8003000C
#define HYDRA_CRYSTAL_SETTING 0x3FFFC5F0 /* 0 - 24 MHz & 1 - 27 MHz */
#define HYDRA_CRYSTAL_CAP 0x3FFFEDA4 /* 0 - 24 MHz & 1 - 27 MHz */
#define HYDRA_CPU_RESET_REG 0x8003003C
#define HYDRA_CPU_RESET_DATA 0x00000400
#define HYDRA_RESET_TRANSPORT_FIFO_REG 0x80030028
#define HYDRA_RESET_TRANSPORT_FIFO_DATA 0x00000000
#define HYDRA_RESET_BBAND_REG 0x80030024
#define HYDRA_RESET_BBAND_DATA 0x00000000
#define HYDRA_RESET_XBAR_REG 0x80030020
#define HYDRA_RESET_XBAR_DATA 0x00000000
#define HYDRA_MODULES_CLK_1_REG 0x80030014
#define HYDRA_DISABLE_CLK_1 0x00000000
#define HYDRA_MODULES_CLK_2_REG 0x8003001C
#define HYDRA_DISABLE_CLK_2 0x0000000B
#define HYDRA_PRCM_ROOT_CLK_REG 0x80030018
#define HYDRA_PRCM_ROOT_CLK_DISABLE 0x00000000
#define HYDRA_CPU_RESET_CHECK_REG 0x80030008
#define HYDRA_CPU_RESET_CHECK_OFFSET 0x40000000 /* <bit 30> */
#define HYDRA_SKU_ID_REG 0x90000190
#define FW_DL_SIGN_ADDR 0x3FFFEAE0
/* Register to check if FW is running or not */
#define HYDRA_HEAR_BEAT 0x3FFFEDDC
/* Firmware version */
#define HYDRA_FIRMWARE_VERSION 0x3FFFEDB8
#define HYDRA_FW_RC_VERSION 0x3FFFCFAC
/* Firmware patch version */
#define HYDRA_FIRMWARE_PATCH_VERSION 0x3FFFEDC2
/* SOC operating temperature in C */
#define HYDRA_TEMPARATURE 0x3FFFEDB4
/* Demod & Tuner status registers */
/* Demod 0 status base address */
#define HYDRA_DEMOD_0_BASE_ADDR 0x3FFFC64C
/* Tuner 0 status base address */
#define HYDRA_TUNER_0_BASE_ADDR 0x3FFFCE4C
#define POWER_FROM_ADCRSSI_READBACK 0x3FFFEB6C
/* Macros to determine base address of respective demod or tuner */
#define HYDRA_DMD_STATUS_OFFSET(demodID) ((demodID) * 0x100)
#define HYDRA_TUNER_STATUS_OFFSET(tunerID) ((tunerID) * 0x40)
/* Demod status address offset from respective demod's base address */
#define HYDRA_DMD_AGC_DIG_LEVEL_ADDR_OFFSET 0x3FFFC64C
#define HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET 0x3FFFC650
#define HYDRA_DMD_ACQ_STATUS_ADDR_OFFSET 0x3FFFC654
#define HYDRA_DMD_STANDARD_ADDR_OFFSET 0x3FFFC658
#define HYDRA_DMD_SPECTRUM_INVERSION_ADDR_OFFSET 0x3FFFC65C
#define HYDRA_DMD_SPECTRUM_ROLL_OFF_ADDR_OFFSET 0x3FFFC660
#define HYDRA_DMD_SYMBOL_RATE_ADDR_OFFSET 0x3FFFC664
#define HYDRA_DMD_MODULATION_SCHEME_ADDR_OFFSET 0x3FFFC668
#define HYDRA_DMD_FEC_CODE_RATE_ADDR_OFFSET 0x3FFFC66C
#define HYDRA_DMD_SNR_ADDR_OFFSET 0x3FFFC670
#define HYDRA_DMD_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC674
#define HYDRA_DMD_CTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC678
#define HYDRA_DMD_STR_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC67C
#define HYDRA_DMD_FTL_FREQ_OFFSET_ADDR_OFFSET 0x3FFFC680
#define HYDRA_DMD_STR_NBC_SYNC_LOCK_ADDR_OFFSET 0x3FFFC684
#define HYDRA_DMD_CYCLE_SLIP_COUNT_ADDR_OFFSET 0x3FFFC688
#define HYDRA_DMD_DISPLAY_I_ADDR_OFFSET 0x3FFFC68C
#define HYDRA_DMD_DISPLAY_Q_ADDR_OFFSET 0x3FFFC68E
#define HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET 0x3FFFC690
#define HYDRA_DMD_DVBS2_PER_COUNT_ADDR_OFFSET 0x3FFFC694
#define HYDRA_DMD_DVBS2_PER_WINDOW_ADDR_OFFSET 0x3FFFC698
#define HYDRA_DMD_DVBS_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC69C
#define HYDRA_DMD_DVBS_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6A0
#define HYDRA_DMD_DVBS_BER_COUNT_ADDR_OFFSET 0x3FFFC6A4
#define HYDRA_DMD_DVBS_BER_WINDOW_ADDR_OFFSET 0x3FFFC6A8
/* Debug-purpose DVB-S DMD 0 */
#define HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6C8 /* corrected RS Errors: 1st iteration */
#define HYDRA_DMD_DVBS_1ST_UNCORR_RS_ERRORS_ADDR_OFFSET 0x3FFFC6CC /* uncorrected RS Errors: 1st iteration */
#define HYDRA_DMD_DVBS_BER_COUNT_1ST_ADDR_OFFSET 0x3FFFC6D0
#define HYDRA_DMD_DVBS_BER_WINDOW_1ST_ADDR_OFFSET 0x3FFFC6D4
#define HYDRA_DMD_TUNER_ID_ADDR_OFFSET 0x3FFFC6AC
#define HYDRA_DMD_DVBS2_PILOT_ON_OFF_ADDR_OFFSET 0x3FFFC6B0
#define HYDRA_DMD_FREQ_SEARCH_RANGE_KHZ_ADDR_OFFSET 0x3FFFC6B4
#define HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET 0x3FFFC6B8
#define HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR 0x3FFFC704
#define HYDRA_DMD_STATUS_INPUT_POWER_ADDR 0x3FFFC708
/* DVB-S new scaled_BER_count for a new BER API, see HYDRA-1343 "DVB-S post viterbi information" */
#define DMD0_STATUS_DVBS_1ST_SCALED_BER_COUNT_ADDR 0x3FFFC710 /* DMD 0: 1st iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR */
#define DMD0_STATUS_DVBS_SCALED_BER_COUNT_ADDR 0x3FFFC714 /* DMD 0: 2nd iteration BER count scaled by HYDRA_BER_COUNT_SCALING_FACTOR */
#define DMD0_SPECTRUM_MIN_GAIN_STATUS 0x3FFFC73C
#define DMD0_SPECTRUM_MIN_GAIN_WB_SAGC_VALUE 0x3FFFC740
#define DMD0_SPECTRUM_MIN_GAIN_NB_SAGC_VALUE 0x3FFFC744
#define HYDRA_DMD_STATUS_END_ADDR_OFFSET 0x3FFFC748
/* Tuner status address offset from respective tuners's base address */
#define HYDRA_TUNER_DEMOD_ID_ADDR_OFFSET 0x3FFFCE4C
#define HYDRA_TUNER_AGC_LOCK_OFFSET 0x3FFFCE50
#define HYDRA_TUNER_SPECTRUM_STATUS_OFFSET 0x3FFFCE54
#define HYDRA_TUNER_SPECTRUM_BIN_SIZE_OFFSET 0x3FFFCE58
#define HYDRA_TUNER_SPECTRUM_ADDRESS_OFFSET 0x3FFFCE5C
#define HYDRA_TUNER_ENABLE_COMPLETE 0x3FFFEB78
#define HYDRA_DEMOD_STATUS_LOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_YES)
#define HYDRA_DEMOD_STATUS_UNLOCK(devId, demodId) write_register(devId, (HYDRA_DMD_STATUS_LOCK_ADDR_OFFSET + HYDRA_DMD_STATUS_OFFSET(demodId)), MXL_NO)
#define HYDRA_VERSION 0x3FFFEDB8
#define HYDRA_DEMOD0_VERSION 0x3FFFEDBC
#define HYDRA_DEMOD1_VERSION 0x3FFFEDC0
#define HYDRA_DEMOD2_VERSION 0x3FFFEDC4
#define HYDRA_DEMOD3_VERSION 0x3FFFEDC8
#define HYDRA_DEMOD4_VERSION 0x3FFFEDCC
#define HYDRA_DEMOD5_VERSION 0x3FFFEDD0
#define HYDRA_DEMOD6_VERSION 0x3FFFEDD4
#define HYDRA_DEMOD7_VERSION 0x3FFFEDD8
#define HYDRA_HEAR_BEAT 0x3FFFEDDC
#define HYDRA_SKU_MGMT 0x3FFFEBC0
#define MXL_HYDRA_FPGA_A_ADDRESS 0x91C00000
#define MXL_HYDRA_FPGA_B_ADDRESS 0x91D00000
/* TS control base address */
#define HYDRA_TS_CTRL_BASE_ADDR 0x90700000
#define MPEG_MUX_MODE_SLICE0_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x08)
#define MPEG_MUX_MODE_SLICE1_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x08)
#define PID_BANK_SEL_SLICE0_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x190)
#define PID_BANK_SEL_SLICE1_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x1B0)
#define MPEG_CLK_GATED_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x20)
#define MPEG_CLK_ALWAYS_ON_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x1D4)
#define HYDRA_REGULAR_PID_BANK_A_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x190)
#define HYDRA_FIXED_PID_BANK_A_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x190)
#define HYDRA_REGULAR_PID_BANK_B_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x1B0)
#define HYDRA_FIXED_PID_BANK_B_REG (HYDRA_TS_CTRL_BASE_ADDR + 0x1B0)
#define FIXED_PID_TBL_REG_ADDRESS_0 (HYDRA_TS_CTRL_BASE_ADDR + 0x9000)
#define FIXED_PID_TBL_REG_ADDRESS_1 (HYDRA_TS_CTRL_BASE_ADDR + 0x9100)
#define FIXED_PID_TBL_REG_ADDRESS_2 (HYDRA_TS_CTRL_BASE_ADDR + 0x9200)
#define FIXED_PID_TBL_REG_ADDRESS_3 (HYDRA_TS_CTRL_BASE_ADDR + 0x9300)
#define FIXED_PID_TBL_REG_ADDRESS_4 (HYDRA_TS_CTRL_BASE_ADDR + 0xB000)
#define FIXED_PID_TBL_REG_ADDRESS_5 (HYDRA_TS_CTRL_BASE_ADDR + 0xB100)
#define FIXED_PID_TBL_REG_ADDRESS_6 (HYDRA_TS_CTRL_BASE_ADDR + 0xB200)
#define FIXED_PID_TBL_REG_ADDRESS_7 (HYDRA_TS_CTRL_BASE_ADDR + 0xB300)
#define REGULAR_PID_TBL_REG_ADDRESS_0 (HYDRA_TS_CTRL_BASE_ADDR + 0x8000)
#define REGULAR_PID_TBL_REG_ADDRESS_1 (HYDRA_TS_CTRL_BASE_ADDR + 0x8200)
#define REGULAR_PID_TBL_REG_ADDRESS_2 (HYDRA_TS_CTRL_BASE_ADDR + 0x8400)
#define REGULAR_PID_TBL_REG_ADDRESS_3 (HYDRA_TS_CTRL_BASE_ADDR + 0x8600)
#define REGULAR_PID_TBL_REG_ADDRESS_4 (HYDRA_TS_CTRL_BASE_ADDR + 0xA000)
#define REGULAR_PID_TBL_REG_ADDRESS_5 (HYDRA_TS_CTRL_BASE_ADDR + 0xA200)
#define REGULAR_PID_TBL_REG_ADDRESS_6 (HYDRA_TS_CTRL_BASE_ADDR + 0xA400)
#define REGULAR_PID_TBL_REG_ADDRESS_7 (HYDRA_TS_CTRL_BASE_ADDR + 0xA600)
/***************************************************************************/
#define PAD_MUX_GPIO_00_SYNC_BASEADDR 0x90000188
#define PAD_MUX_UART_RX_C_PINMUX_BASEADDR 0x9000001C
#define XPT_PACKET_GAP_MIN_BASEADDR 0x90700044
#define XPT_NCO_COUNT_BASEADDR 0x90700238
#define XPT_NCO_COUNT_BASEADDR1 0x9070023C
/* V2 DigRF status register */
#define XPT_PID_BASEADDR 0x90708000
#define XPT_PID_REMAP_BASEADDR 0x90708004
#define XPT_KNOWN_PID_BASEADDR 0x90709000
#define XPT_PID_BASEADDR1 0x9070A000
#define XPT_PID_REMAP_BASEADDR1 0x9070A004
#define XPT_KNOWN_PID_BASEADDR1 0x9070B000
#define XPT_BERT_LOCK_BASEADDR 0x907000B8
#define XPT_BERT_BASEADDR 0x907000BC
#define XPT_BERT_INVERT_BASEADDR 0x907000C0
#define XPT_BERT_HEADER_BASEADDR 0x907000C4
#define XPT_BERT_BASEADDR1 0x907000C8
#define XPT_BERT_BIT_COUNT0_BASEADDR 0x907000CC
#define XPT_BERT_BIT_COUNT0_BASEADDR1 0x907000D0
#define XPT_BERT_BIT_COUNT1_BASEADDR 0x907000D4
#define XPT_BERT_BIT_COUNT1_BASEADDR1 0x907000D8
#define XPT_BERT_BIT_COUNT2_BASEADDR 0x907000DC
#define XPT_BERT_BIT_COUNT2_BASEADDR1 0x907000E0
#define XPT_BERT_BIT_COUNT3_BASEADDR 0x907000E4
#define XPT_BERT_BIT_COUNT3_BASEADDR1 0x907000E8
#define XPT_BERT_BIT_COUNT4_BASEADDR 0x907000EC
#define XPT_BERT_BIT_COUNT4_BASEADDR1 0x907000F0
#define XPT_BERT_BIT_COUNT5_BASEADDR 0x907000F4
#define XPT_BERT_BIT_COUNT5_BASEADDR1 0x907000F8
#define XPT_BERT_BIT_COUNT6_BASEADDR 0x907000FC
#define XPT_BERT_BIT_COUNT6_BASEADDR1 0x90700100
#define XPT_BERT_BIT_COUNT7_BASEADDR 0x90700104
#define XPT_BERT_BIT_COUNT7_BASEADDR1 0x90700108
#define XPT_BERT_ERR_COUNT0_BASEADDR 0x9070010C
#define XPT_BERT_ERR_COUNT0_BASEADDR1 0x90700110
#define XPT_BERT_ERR_COUNT1_BASEADDR 0x90700114
#define XPT_BERT_ERR_COUNT1_BASEADDR1 0x90700118
#define XPT_BERT_ERR_COUNT2_BASEADDR 0x9070011C
#define XPT_BERT_ERR_COUNT2_BASEADDR1 0x90700120
#define XPT_BERT_ERR_COUNT3_BASEADDR 0x90700124
#define XPT_BERT_ERR_COUNT3_BASEADDR1 0x90700128
#define XPT_BERT_ERR_COUNT4_BASEADDR 0x9070012C
#define XPT_BERT_ERR_COUNT4_BASEADDR1 0x90700130
#define XPT_BERT_ERR_COUNT5_BASEADDR 0x90700134
#define XPT_BERT_ERR_COUNT5_BASEADDR1 0x90700138
#define XPT_BERT_ERR_COUNT6_BASEADDR 0x9070013C
#define XPT_BERT_ERR_COUNT6_BASEADDR1 0x90700140
#define XPT_BERT_ERR_COUNT7_BASEADDR 0x90700144
#define XPT_BERT_ERR_COUNT7_BASEADDR1 0x90700148
#define XPT_BERT_ERROR_BASEADDR 0x9070014C
#define XPT_BERT_ANALYZER_BASEADDR 0x90700150
#define XPT_BERT_ANALYZER_BASEADDR1 0x90700154
#define XPT_BERT_ANALYZER_BASEADDR2 0x90700158
#define XPT_BERT_ANALYZER_BASEADDR3 0x9070015C
#define XPT_BERT_ANALYZER_BASEADDR4 0x90700160
#define XPT_BERT_ANALYZER_BASEADDR5 0x90700164
#define XPT_BERT_ANALYZER_BASEADDR6 0x90700168
#define XPT_BERT_ANALYZER_BASEADDR7 0x9070016C
#define XPT_BERT_ANALYZER_BASEADDR8 0x90700170
#define XPT_BERT_ANALYZER_BASEADDR9 0x90700174
#define XPT_DMD0_BASEADDR 0x9070024C
/* V2 AGC Gain Freeze & step */
#define DBG_ENABLE_DISABLE_AGC (0x3FFFCF60) /* 1: DISABLE, 0:ENABLE */
#define WB_DFE0_DFE_FB_RF1_BASEADDR 0x903004A4
#define WB_DFE1_DFE_FB_RF1_BASEADDR 0x904004A4
#define WB_DFE2_DFE_FB_RF1_BASEADDR 0x905004A4
#define WB_DFE3_DFE_FB_RF1_BASEADDR 0x906004A4
#define AFE_REG_D2A_TA_RFFE_LNA_BO_1P8_BASEADDR 0x90200104
#define AFE_REG_AFE_REG_SPARE_BASEADDR 0x902000A0
#define AFE_REG_AFE_REG_SPARE_BASEADDR1 0x902000B4
#define AFE_REG_AFE_REG_SPARE_BASEADDR2 0x902000C4
#define AFE_REG_AFE_REG_SPARE_BASEADDR3 0x902000D4
#define WB_DFE0_DFE_FB_AGC_BASEADDR 0x90300498
#define WB_DFE1_DFE_FB_AGC_BASEADDR 0x90400498
#define WB_DFE2_DFE_FB_AGC_BASEADDR 0x90500498
#define WB_DFE3_DFE_FB_AGC_BASEADDR 0x90600498
#define WDT_WD_INT_BASEADDR 0x8002000C
#define FSK_TX_FTM_BASEADDR 0x80090000
#define FSK_TX_FTM_TX_CNT_BASEADDR 0x80090018
#define AFE_REG_D2A_FSK_BIAS_BASEADDR 0x90200040
#define DMD_TEI_BASEADDR 0x3FFFEBE0
#endif /* __MXL58X_REGISTERS_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment