Commit 83808c23 authored by Abylay Ospan's avatar Abylay Ospan Committed by Mauro Carvalho Chehab

[media] Add support Sony CXD2854ER demodulator

CXD2854ER is identical to CXD2841ER except ISDB-T/S added.
New method 'cxd2841er_attach_i' is added
xtal frequency now configurable. Available options:
20.5MHz, 24MHz, 41MHz
Signed-off-by: default avatarAbylay Ospan <aospan@netup.ru>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 2dc1ed4e
/* /*
* cxd2841er.c * cxd2841er.c
* *
* Sony CXD2441ER digital demodulator driver * Sony digital demodulator driver for
* CXD2441ER - DVB-S/S2/T/T2/C/C2
* CXD2454ER - DVB-S/S2/T/T2/C/C2, ISDB-T/S
* *
* Copyright 2012 Sony Corporation * Copyright 2012 Sony Corporation
* Copyright (C) 2014 NetUP Inc. * Copyright (C) 2014 NetUP Inc.
...@@ -51,6 +53,7 @@ struct cxd2841er_priv { ...@@ -51,6 +53,7 @@ struct cxd2841er_priv {
const struct cxd2841er_config *config; const struct cxd2841er_config *config;
enum cxd2841er_state state; enum cxd2841er_state state;
u8 system; u8 system;
enum cxd2841er_xtal xtal;
}; };
static const struct cxd2841er_cnr_data s_cn_data[] = { static const struct cxd2841er_cnr_data s_cn_data[] = {
...@@ -188,6 +191,9 @@ static const struct cxd2841er_cnr_data s2_cn_data[] = { ...@@ -188,6 +191,9 @@ static const struct cxd2841er_cnr_data s2_cn_data[] = {
}; };
#define MAKE_IFFREQ_CONFIG(iffreq) ((u32)(((iffreq)/41.0)*16777216.0 + 0.5)) #define MAKE_IFFREQ_CONFIG(iffreq) ((u32)(((iffreq)/41.0)*16777216.0 + 0.5))
#define MAKE_IFFREQ_CONFIG_XTAL(xtal, iffreq) ((xtal == SONY_XTAL_24000) ? \
(u32)(((iffreq)/48.0)*16777216.0 + 0.5) : \
(u32)(((iffreq)/41.0)*16777216.0 + 0.5))
static void cxd2841er_i2c_debug(struct cxd2841er_priv *priv, static void cxd2841er_i2c_debug(struct cxd2841er_priv *priv,
u8 addr, u8 reg, u8 write, u8 addr, u8 reg, u8 write,
...@@ -217,7 +223,7 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv, ...@@ -217,7 +223,7 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv,
}; };
if (len + 1 >= sizeof(buf)) { if (len + 1 >= sizeof(buf)) {
dev_warn(&priv->i2c->dev,"wr reg=%04x: len=%d is too big!\n", dev_warn(&priv->i2c->dev, "wr reg=%04x: len=%d is too big!\n",
reg, len + 1); reg, len + 1);
return -E2BIG; return -E2BIG;
} }
...@@ -669,6 +675,45 @@ static int cxd2841er_active_c_to_sleep_tc(struct cxd2841er_priv *priv) ...@@ -669,6 +675,45 @@ static int cxd2841er_active_c_to_sleep_tc(struct cxd2841er_priv *priv)
return 0; return 0;
} }
static int cxd2841er_active_i_to_sleep_tc(struct cxd2841er_priv *priv)
{
dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
if (priv->state != STATE_ACTIVE_TC) {
dev_err(&priv->i2c->dev, "%s(): invalid state %d\n",
__func__, priv->state);
return -EINVAL;
}
/* Set SLV-T Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00);
/* disable TS output */
cxd2841er_write_reg(priv, I2C_SLVT, 0xc3, 0x01);
/* enable Hi-Z setting 1 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x80, 0x3f);
/* enable Hi-Z setting 2 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x81, 0xff);
/* TODO: Cancel demod parameter */
/* Set SLV-X Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00);
/* disable ADC 1 */
cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x01);
/* Set SLV-T Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00);
/* Disable ADC 2 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x43, 0x0a);
/* Disable ADC 3 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x0a);
/* Disable ADC clock */
cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00);
/* Disable RF level monitor */
cxd2841er_write_reg(priv, I2C_SLVT, 0x2f, 0x00);
/* Disable demod clock */
cxd2841er_write_reg(priv, I2C_SLVT, 0x2c, 0x00);
priv->state = STATE_SLEEP_TC;
return 0;
}
static int cxd2841er_shutdown_to_sleep_s(struct cxd2841er_priv *priv) static int cxd2841er_shutdown_to_sleep_s(struct cxd2841er_priv *priv)
{ {
dev_dbg(&priv->i2c->dev, "%s()\n", __func__); dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
...@@ -686,8 +731,25 @@ static int cxd2841er_shutdown_to_sleep_s(struct cxd2841er_priv *priv) ...@@ -686,8 +731,25 @@ static int cxd2841er_shutdown_to_sleep_s(struct cxd2841er_priv *priv)
cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00); cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00);
/* Set demod SW reset */ /* Set demod SW reset */
cxd2841er_write_reg(priv, I2C_SLVX, 0x10, 0x01); cxd2841er_write_reg(priv, I2C_SLVX, 0x10, 0x01);
/* Set X'tal clock to 20.5Mhz */
cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x00); switch (priv->xtal) {
case SONY_XTAL_20500:
cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x00);
break;
case SONY_XTAL_24000:
/* Select demod frequency */
cxd2841er_write_reg(priv, I2C_SLVX, 0x12, 0x00);
cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x03);
break;
case SONY_XTAL_41000:
cxd2841er_write_reg(priv, I2C_SLVX, 0x14, 0x01);
break;
default:
dev_dbg(&priv->i2c->dev, "%s(): invalid demod xtal %d\n",
__func__, priv->xtal);
return -EINVAL;
}
/* Set demod mode */ /* Set demod mode */
cxd2841er_write_reg(priv, I2C_SLVX, 0x17, 0x0a); cxd2841er_write_reg(priv, I2C_SLVX, 0x17, 0x0a);
/* Clear demod SW reset */ /* Clear demod SW reset */
...@@ -809,11 +871,14 @@ static void cxd2841er_set_ts_clock_mode(struct cxd2841er_priv *priv, ...@@ -809,11 +871,14 @@ static void cxd2841er_set_ts_clock_mode(struct cxd2841er_priv *priv,
static u8 cxd2841er_chip_id(struct cxd2841er_priv *priv) static u8 cxd2841er_chip_id(struct cxd2841er_priv *priv)
{ {
u8 chip_id; u8 chip_id = 0;
dev_dbg(&priv->i2c->dev, "%s()\n", __func__); dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
cxd2841er_write_reg(priv, I2C_SLVT, 0, 0); if (cxd2841er_write_reg(priv, I2C_SLVT, 0, 0) == 0)
cxd2841er_read_reg(priv, I2C_SLVT, 0xfd, &chip_id); cxd2841er_read_reg(priv, I2C_SLVT, 0xfd, &chip_id);
else if (cxd2841er_write_reg(priv, I2C_SLVX, 0, 0) == 0)
cxd2841er_read_reg(priv, I2C_SLVX, 0xfd, &chip_id);
return chip_id; return chip_id;
} }
...@@ -896,6 +961,25 @@ static int cxd2841er_read_status_c(struct cxd2841er_priv *priv, u8 *tslock) ...@@ -896,6 +961,25 @@ static int cxd2841er_read_status_c(struct cxd2841er_priv *priv, u8 *tslock)
return 0; return 0;
} }
static int cxd2841er_read_status_i(struct cxd2841er_priv *priv,
u8 *sync, u8 *tslock, u8 *unlock)
{
u8 data = 0;
dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
if (priv->state != STATE_ACTIVE_TC)
return -EINVAL;
/* Set SLV-T Bank : 0x60 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60);
cxd2841er_read_reg(priv, I2C_SLVT, 0x10, &data);
dev_dbg(&priv->i2c->dev,
"%s(): lock=0x%x\n", __func__, data);
*sync = ((data & 0x02) ? 1 : 0);
*tslock = ((data & 0x01) ? 1 : 0);
*unlock = ((data & 0x10) ? 1 : 0);
return 0;
}
static int cxd2841er_read_status_tc(struct dvb_frontend *fe, static int cxd2841er_read_status_tc(struct dvb_frontend *fe,
enum fe_status *status) enum fe_status *status)
{ {
...@@ -921,6 +1005,20 @@ static int cxd2841er_read_status_tc(struct dvb_frontend *fe, ...@@ -921,6 +1005,20 @@ static int cxd2841er_read_status_tc(struct dvb_frontend *fe,
FE_HAS_SYNC; FE_HAS_SYNC;
if (tslock) if (tslock)
*status |= FE_HAS_LOCK; *status |= FE_HAS_LOCK;
} else if (priv->system == SYS_ISDBT) {
ret = cxd2841er_read_status_i(
priv, &sync, &tslock, &unlock);
if (ret)
goto done;
if (unlock)
goto done;
if (sync)
*status = FE_HAS_SIGNAL |
FE_HAS_CARRIER |
FE_HAS_VITERBI |
FE_HAS_SYNC;
if (tslock)
*status |= FE_HAS_LOCK;
} else if (priv->system == SYS_DVBC_ANNEX_A) { } else if (priv->system == SYS_DVBC_ANNEX_A) {
ret = cxd2841er_read_status_c(priv, &tslock); ret = cxd2841er_read_status_c(priv, &tslock);
if (ret) if (ret)
...@@ -1096,6 +1194,38 @@ static int cxd2841er_read_packet_errors_t2( ...@@ -1096,6 +1194,38 @@ static int cxd2841er_read_packet_errors_t2(
return 0; return 0;
} }
static int cxd2841er_read_packet_errors_i(
struct cxd2841er_priv *priv, u32 *penum)
{
u8 data[2];
*penum = 0;
if (priv->state != STATE_ACTIVE_TC) {
dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n",
__func__, priv->state);
return -EINVAL;
}
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60);
cxd2841er_read_regs(priv, I2C_SLVT, 0xA1, data, 1);
if (!(data[0] & 0x01))
return 0;
/* Layer A */
cxd2841er_read_regs(priv, I2C_SLVT, 0xA2, data, sizeof(data));
*penum = ((u32)data[0] << 8) | (u32)data[1];
/* Layer B */
cxd2841er_read_regs(priv, I2C_SLVT, 0xA4, data, sizeof(data));
*penum += ((u32)data[0] << 8) | (u32)data[1];
/* Layer C */
cxd2841er_read_regs(priv, I2C_SLVT, 0xA6, data, sizeof(data));
*penum += ((u32)data[0] << 8) | (u32)data[1];
return 0;
}
static u32 cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv) static u32 cxd2841er_mon_read_ber_s(struct cxd2841er_priv *priv)
{ {
u8 data[11]; u8 data[11];
...@@ -1391,6 +1521,37 @@ static int cxd2841er_read_snr_t2(struct cxd2841er_priv *priv, u32 *snr) ...@@ -1391,6 +1521,37 @@ static int cxd2841er_read_snr_t2(struct cxd2841er_priv *priv, u32 *snr)
return 0; return 0;
} }
static int cxd2841er_read_snr_i(struct cxd2841er_priv *priv, u32 *snr)
{
u32 reg;
u8 data[2];
*snr = 0;
if (priv->state != STATE_ACTIVE_TC) {
dev_dbg(&priv->i2c->dev,
"%s(): invalid state %d\n", __func__,
priv->state);
return -EINVAL;
}
/* Freeze all registers */
cxd2841er_write_reg(priv, I2C_SLVT, 0x01, 0x01);
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60);
cxd2841er_read_regs(priv, I2C_SLVT, 0x28, data, sizeof(data));
reg = ((u32)data[0] << 8) | (u32)data[1];
if (reg == 0) {
dev_dbg(&priv->i2c->dev,
"%s(): reg value out of range\n", __func__);
return 0;
}
if (reg > 4996)
reg = 4996;
*snr = 100 * intlog10(reg) - 9031;
return 0;
}
static u16 cxd2841er_read_agc_gain_t_t2(struct cxd2841er_priv *priv, static u16 cxd2841er_read_agc_gain_t_t2(struct cxd2841er_priv *priv,
u8 delsys) u8 delsys)
{ {
...@@ -1402,6 +1563,22 @@ static u16 cxd2841er_read_agc_gain_t_t2(struct cxd2841er_priv *priv, ...@@ -1402,6 +1563,22 @@ static u16 cxd2841er_read_agc_gain_t_t2(struct cxd2841er_priv *priv,
return ((((u16)data[0] & 0x0F) << 8) | (u16)(data[1] & 0xFF)) << 4; return ((((u16)data[0] & 0x0F) << 8) | (u16)(data[1] & 0xFF)) << 4;
} }
static u16 cxd2841er_read_agc_gain_i(struct cxd2841er_priv *priv,
u8 delsys)
{
u8 data[2];
cxd2841er_write_reg(
priv, I2C_SLVT, 0x00, 0x60);
cxd2841er_read_regs(priv, I2C_SLVT, 0x26, data, 2);
dev_dbg(&priv->i2c->dev,
"%s(): AGC value=%u\n",
__func__, (((u16)data[0] & 0x0F) << 8) |
(u16)(data[1] & 0xFF));
return ((((u16)data[0] & 0x0F) << 8) | (u16)(data[1] & 0xFF)) << 4;
}
static u16 cxd2841er_read_agc_gain_s(struct cxd2841er_priv *priv) static u16 cxd2841er_read_agc_gain_s(struct cxd2841er_priv *priv)
{ {
u8 data[2]; u8 data[2];
...@@ -1455,6 +1632,10 @@ static int cxd2841er_read_signal_strength(struct dvb_frontend *fe, ...@@ -1455,6 +1632,10 @@ static int cxd2841er_read_signal_strength(struct dvb_frontend *fe,
*strength = 65535 - cxd2841er_read_agc_gain_t_t2( *strength = 65535 - cxd2841er_read_agc_gain_t_t2(
priv, p->delivery_system); priv, p->delivery_system);
break; break;
case SYS_ISDBT:
*strength = 65535 - cxd2841er_read_agc_gain_i(
priv, p->delivery_system);
break;
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
*strength = 65535 - cxd2841er_read_agc_gain_s(priv); *strength = 65535 - cxd2841er_read_agc_gain_s(priv);
...@@ -1480,6 +1661,9 @@ static int cxd2841er_read_snr(struct dvb_frontend *fe, u16 *snr) ...@@ -1480,6 +1661,9 @@ static int cxd2841er_read_snr(struct dvb_frontend *fe, u16 *snr)
case SYS_DVBT2: case SYS_DVBT2:
cxd2841er_read_snr_t2(priv, &tmp); cxd2841er_read_snr_t2(priv, &tmp);
break; break;
case SYS_ISDBT:
cxd2841er_read_snr_i(priv, &tmp);
break;
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
tmp = cxd2841er_dvbs_read_snr(priv, p->delivery_system); tmp = cxd2841er_dvbs_read_snr(priv, p->delivery_system);
...@@ -1506,6 +1690,9 @@ static int cxd2841er_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ...@@ -1506,6 +1690,9 @@ static int cxd2841er_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
case SYS_DVBT2: case SYS_DVBT2:
cxd2841er_read_packet_errors_t2(priv, ucblocks); cxd2841er_read_packet_errors_t2(priv, ucblocks);
break; break;
case SYS_ISDBT:
cxd2841er_read_packet_errors_i(priv, ucblocks);
break;
default: default:
*ucblocks = 0; *ucblocks = 0;
break; break;
...@@ -1734,94 +1921,382 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv, ...@@ -1734,94 +1921,382 @@ static int cxd2841er_sleep_tc_to_active_t2_band(struct cxd2841er_priv *priv,
static int cxd2841er_sleep_tc_to_active_t_band( static int cxd2841er_sleep_tc_to_active_t_band(
struct cxd2841er_priv *priv, u32 bandwidth) struct cxd2841er_priv *priv, u32 bandwidth)
{ {
u8 b13_9c[2] = { 0x01, 0x14 }; u8 data[MAX_WRITE_REGSIZE];
u8 bw8mhz_b10_9f[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 };
u8 bw8mhz_b10_a6[] = { 0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB,
0x28, 0xBA, 0x23, 0xA9, 0x1F, 0xA8, 0x2C, 0xC8 };
u8 bw8mhz_b10_d9[] = { 0x01, 0xE0 };
u8 bw8mhz_b17_38[] = { 0x01, 0x02 };
u8 bw7mhz_b10_9f[] = { 0x14, 0x80, 0x00, 0x00, 0x00 };
u8 bw7mhz_b10_a6[] = { 0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8,
0x23, 0xA6, 0x29, 0xB0, 0x26, 0xA9, 0x21, 0xA5 };
u8 bw7mhz_b10_d9[] = { 0x12, 0xF8 };
u8 bw7mhz_b17_38[] = { 0x00, 0x03 };
u8 bw6mhz_b10_9f[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA };
u8 bw6mhz_b10_a6[] = { 0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0,
0x01, 0xE8, 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4 };
u8 bw6mhz_b10_d9[] = { 0x1F, 0xDC };
u8 bw6mhz_b17_38[] = { 0x00, 0x03 };
u8 bw5mhz_b10_9f[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 };
u8 bw5mhz_b10_a6[] = { 0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0,
0x01, 0xE8, 0x00, 0xCF, 0x00, 0xE6, 0x23, 0xA4 };
u8 bw5mhz_b10_d9[] = { 0x26, 0x3C };
u8 bw5mhz_b17_38[] = { 0x00, 0x03 };
u8 b10_b6[3];
u8 d7val;
u32 iffreq; u32 iffreq;
u8 *b10_9f; u8 nominalRate8bw[3][5] = {
u8 *b10_a6; /* TRCG Nominal Rate [37:0] */
u8 *b10_d9; {0x11, 0xF0, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */
u8 *b17_38; {0x15, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */
{0x11, 0xF0, 0x00, 0x00, 0x00} /* 41MHz XTal */
};
u8 nominalRate7bw[3][5] = {
/* TRCG Nominal Rate [37:0] */
{0x14, 0x80, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */
{0x18, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */
{0x14, 0x80, 0x00, 0x00, 0x00} /* 41MHz XTal */
};
u8 nominalRate6bw[3][5] = {
/* TRCG Nominal Rate [37:0] */
{0x17, 0xEA, 0xAA, 0xAA, 0xAA}, /* 20.5MHz XTal */
{0x1C, 0x00, 0x00, 0x00, 0x00}, /* 24MHz XTal */
{0x17, 0xEA, 0xAA, 0xAA, 0xAA} /* 41MHz XTal */
};
u8 nominalRate5bw[3][5] = {
/* TRCG Nominal Rate [37:0] */
{0x1C, 0xB3, 0x33, 0x33, 0x33}, /* 20.5MHz XTal */
{0x21, 0x99, 0x99, 0x99, 0x99}, /* 24MHz XTal */
{0x1C, 0xB3, 0x33, 0x33, 0x33} /* 41MHz XTal */
};
dev_dbg(&priv->i2c->dev, "%s()\n", __func__); u8 itbCoef8bw[3][14] = {
{0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB, 0x28, 0xBA, 0x23, 0xA9,
0x1F, 0xA8, 0x2C, 0xC8}, /* 20.5MHz XTal */
{0x2F, 0xBA, 0x28, 0x9B, 0x28, 0x9D, 0x28, 0xA1, 0x29, 0xA5,
0x2A, 0xAC, 0x29, 0xB5}, /* 24MHz XTal */
{0x26, 0xAF, 0x06, 0xCD, 0x13, 0xBB, 0x28, 0xBA, 0x23, 0xA9,
0x1F, 0xA8, 0x2C, 0xC8} /* 41MHz XTal */
};
u8 itbCoef7bw[3][14] = {
{0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8, 0x23, 0xA6, 0x29, 0xB0,
0x26, 0xA9, 0x21, 0xA5}, /* 20.5MHz XTal */
{0x30, 0xB1, 0x29, 0x9A, 0x28, 0x9C, 0x28, 0xA0, 0x29, 0xA2,
0x2B, 0xA6, 0x2B, 0xAD}, /* 24MHz XTal */
{0x2C, 0xBD, 0x02, 0xCF, 0x04, 0xF8, 0x23, 0xA6, 0x29, 0xB0,
0x26, 0xA9, 0x21, 0xA5} /* 41MHz XTal */
};
u8 itbCoef6bw[3][14] = {
{0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF,
0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */
{0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, 0x29, 0xA4,
0x29, 0xA2, 0x29, 0xA8}, /* 24MHz XTal */
{0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF,
0x00, 0xE6, 0x23, 0xA4} /* 41MHz XTal */
};
u8 itbCoef5bw[3][14] = {
{0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF,
0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */
{0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, 0x29, 0xA4,
0x29, 0xA2, 0x29, 0xA8}, /* 24MHz XTal */
{0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00, 0xCF,
0x00, 0xE6, 0x23, 0xA4} /* 41MHz XTal */
};
/* Set SLV-T Bank : 0x13 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x13); cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x13);
/* Echo performance optimization setting */ /* Echo performance optimization setting */
cxd2841er_write_regs(priv, I2C_SLVT, 0x9c, b13_9c, sizeof(b13_9c)); data[0] = 0x01;
data[1] = 0x14;
cxd2841er_write_regs(priv, I2C_SLVT, 0x9C, data, 2);
/* Set SLV-T Bank : 0x10 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10); cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10);
switch (bandwidth) { switch (bandwidth) {
case 8000000: case 8000000:
b10_9f = bw8mhz_b10_9f; /* <Timing Recovery setting> */
b10_a6 = bw8mhz_b10_a6; cxd2841er_write_regs(priv, I2C_SLVT,
b10_d9 = bw8mhz_b10_d9; 0x9F, nominalRate8bw[priv->xtal], 5);
b17_38 = bw8mhz_b17_38; /* Group delay equaliser settings for
d7val = 0; * ASCOT2D, ASCOT2E and ASCOT3 tuners
iffreq = MAKE_IFFREQ_CONFIG(4.80); */
cxd2841er_write_regs(priv, I2C_SLVT,
0xA6, itbCoef8bw[priv->xtal], 14);
/* <IF freq setting> */
iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.80);
data[0] = (u8) ((iffreq >> 16) & 0xff);
data[1] = (u8)((iffreq >> 8) & 0xff);
data[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3);
/* System bandwidth setting */
cxd2841er_set_reg_bits(
priv, I2C_SLVT, 0xD7, 0x00, 0x07);
/* Demod core latency setting */
if (priv->xtal == SONY_XTAL_24000) {
data[0] = 0x15;
data[1] = 0x28;
} else {
data[0] = 0x01;
data[1] = 0xE0;
}
cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2);
/* Notch filter setting */
data[0] = 0x01;
data[1] = 0x02;
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17);
cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2);
break; break;
case 7000000: case 7000000:
b10_9f = bw7mhz_b10_9f; /* <Timing Recovery setting> */
b10_a6 = bw7mhz_b10_a6; cxd2841er_write_regs(priv, I2C_SLVT,
b10_d9 = bw7mhz_b10_d9; 0x9F, nominalRate7bw[priv->xtal], 5);
b17_38 = bw7mhz_b17_38; /* Group delay equaliser settings for
d7val = 2; * ASCOT2D, ASCOT2E and ASCOT3 tuners
iffreq = MAKE_IFFREQ_CONFIG(4.20); */
cxd2841er_write_regs(priv, I2C_SLVT,
0xA6, itbCoef7bw[priv->xtal], 14);
/* <IF freq setting> */
iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.20);
data[0] = (u8) ((iffreq >> 16) & 0xff);
data[1] = (u8)((iffreq >> 8) & 0xff);
data[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3);
/* System bandwidth setting */
cxd2841er_set_reg_bits(
priv, I2C_SLVT, 0xD7, 0x02, 0x07);
/* Demod core latency setting */
if (priv->xtal == SONY_XTAL_24000) {
data[0] = 0x1F;
data[1] = 0xF8;
} else {
data[0] = 0x12;
data[1] = 0xF8;
}
cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2);
/* Notch filter setting */
data[0] = 0x00;
data[1] = 0x03;
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17);
cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2);
break; break;
case 6000000: case 6000000:
b10_9f = bw6mhz_b10_9f; /* <Timing Recovery setting> */
b10_a6 = bw6mhz_b10_a6; cxd2841er_write_regs(priv, I2C_SLVT,
b10_d9 = bw6mhz_b10_d9; 0x9F, nominalRate6bw[priv->xtal], 5);
b17_38 = bw6mhz_b17_38; /* Group delay equaliser settings for
d7val = 4; * ASCOT2D, ASCOT2E and ASCOT3 tuners
iffreq = MAKE_IFFREQ_CONFIG(3.60); */
cxd2841er_write_regs(priv, I2C_SLVT,
0xA6, itbCoef6bw[priv->xtal], 14);
/* <IF freq setting> */
iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60);
data[0] = (u8) ((iffreq >> 16) & 0xff);
data[1] = (u8)((iffreq >> 8) & 0xff);
data[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3);
/* System bandwidth setting */
cxd2841er_set_reg_bits(
priv, I2C_SLVT, 0xD7, 0x04, 0x07);
/* Demod core latency setting */
if (priv->xtal == SONY_XTAL_24000) {
data[0] = 0x25;
data[1] = 0x4C;
} else {
data[0] = 0x1F;
data[1] = 0xDC;
}
cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2);
/* Notch filter setting */
data[0] = 0x00;
data[1] = 0x03;
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17);
cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2);
break; break;
case 5000000: case 5000000:
b10_9f = bw5mhz_b10_9f; /* <Timing Recovery setting> */
b10_a6 = bw5mhz_b10_a6; cxd2841er_write_regs(priv, I2C_SLVT,
b10_d9 = bw5mhz_b10_d9; 0x9F, nominalRate5bw[priv->xtal], 5);
b17_38 = bw5mhz_b17_38; /* Group delay equaliser settings for
d7val = 6; * ASCOT2D, ASCOT2E and ASCOT3 tuners
iffreq = MAKE_IFFREQ_CONFIG(3.60); */
cxd2841er_write_regs(priv, I2C_SLVT,
0xA6, itbCoef5bw[priv->xtal], 14);
/* <IF freq setting> */
iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.60);
data[0] = (u8) ((iffreq >> 16) & 0xff);
data[1] = (u8)((iffreq >> 8) & 0xff);
data[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3);
/* System bandwidth setting */
cxd2841er_set_reg_bits(
priv, I2C_SLVT, 0xD7, 0x06, 0x07);
/* Demod core latency setting */
if (priv->xtal == SONY_XTAL_24000) {
data[0] = 0x2C;
data[1] = 0xC2;
} else {
data[0] = 0x26;
data[1] = 0x3C;
}
cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2);
/* Notch filter setting */
data[0] = 0x00;
data[1] = 0x03;
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17);
cxd2841er_write_regs(priv, I2C_SLVT, 0x38, data, 2);
break;
}
return 0;
}
static int cxd2841er_sleep_tc_to_active_i_band(
struct cxd2841er_priv *priv, u32 bandwidth)
{
u32 iffreq;
u8 data[3];
/* TRCG Nominal Rate */
u8 nominalRate8bw[3][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */
{0x11, 0xB8, 0x00, 0x00, 0x00}, /* 24MHz XTal */
{0x00, 0x00, 0x00, 0x00, 0x00} /* 41MHz XTal */
};
u8 nominalRate7bw[3][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */
{0x14, 0x40, 0x00, 0x00, 0x00}, /* 24MHz XTal */
{0x00, 0x00, 0x00, 0x00, 0x00} /* 41MHz XTal */
};
u8 nominalRate6bw[3][5] = {
{0x14, 0x2E, 0x00, 0x00, 0x00}, /* 20.5MHz XTal */
{0x17, 0xA0, 0x00, 0x00, 0x00}, /* 24MHz XTal */
{0x14, 0x2E, 0x00, 0x00, 0x00} /* 41MHz XTal */
};
u8 itbCoef8bw[3][14] = {
{0x00}, /* 20.5MHz XTal */
{0x2F, 0xBA, 0x28, 0x9B, 0x28, 0x9D, 0x28, 0xA1, 0x29,
0xA5, 0x2A, 0xAC, 0x29, 0xB5}, /* 24MHz Xtal */
{0x0}, /* 41MHz XTal */
};
u8 itbCoef7bw[3][14] = {
{0x00}, /* 20.5MHz XTal */
{0x30, 0xB1, 0x29, 0x9A, 0x28, 0x9C, 0x28, 0xA0, 0x29,
0xA2, 0x2B, 0xA6, 0x2B, 0xAD}, /* 24MHz Xtal */
{0x00}, /* 41MHz XTal */
};
u8 itbCoef6bw[3][14] = {
{0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00,
0xCF, 0x00, 0xE6, 0x23, 0xA4}, /* 20.5MHz XTal */
{0x31, 0xA8, 0x29, 0x9B, 0x27, 0x9C, 0x28, 0x9E, 0x29,
0xA4, 0x29, 0xA2, 0x29, 0xA8}, /* 24MHz Xtal */
{0x27, 0xA7, 0x28, 0xB3, 0x02, 0xF0, 0x01, 0xE8, 0x00,
0xCF, 0x00, 0xE6, 0x23, 0xA4}, /* 41MHz XTal */
};
dev_dbg(&priv->i2c->dev, "%s() bandwidth=%u\n", __func__, bandwidth);
/* Set SLV-T Bank : 0x10 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10);
/* 20.5/41MHz Xtal support is not available
* on ISDB-T 7MHzBW and 8MHzBW
*/
if (priv->xtal != SONY_XTAL_24000 && bandwidth > 6000000) {
dev_err(&priv->i2c->dev,
"%s(): bandwidth %d supported only for 24MHz xtal\n",
__func__, bandwidth);
return -EINVAL;
}
switch (bandwidth) {
case 8000000:
/* TRCG Nominal Rate */
cxd2841er_write_regs(priv, I2C_SLVT,
0x9F, nominalRate8bw[priv->xtal], 5);
/* Group delay equaliser settings for ASCOT tuners optimized */
cxd2841er_write_regs(priv, I2C_SLVT,
0xA6, itbCoef8bw[priv->xtal], 14);
/* IF freq setting */
iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.75);
data[0] = (u8) ((iffreq >> 16) & 0xff);
data[1] = (u8)((iffreq >> 8) & 0xff);
data[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3);
/* System bandwidth setting */
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, 0x0, 0x7);
/* Demod core latency setting */
data[0] = 0x13;
data[1] = 0xFC;
cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2);
/* Acquisition optimization setting */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x12);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x71, 0x03, 0x07);
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15);
cxd2841er_write_reg(priv, I2C_SLVT, 0xBE, 0x03);
break;
case 7000000:
/* TRCG Nominal Rate */
cxd2841er_write_regs(priv, I2C_SLVT,
0x9F, nominalRate7bw[priv->xtal], 5);
/* Group delay equaliser settings for ASCOT tuners optimized */
cxd2841er_write_regs(priv, I2C_SLVT,
0xA6, itbCoef7bw[priv->xtal], 14);
/* IF freq setting */
iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 4.15);
data[0] = (u8) ((iffreq >> 16) & 0xff);
data[1] = (u8)((iffreq >> 8) & 0xff);
data[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3);
/* System bandwidth setting */
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, 0x02, 0x7);
/* Demod core latency setting */
data[0] = 0x1A;
data[1] = 0xFA;
cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2);
/* Acquisition optimization setting */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x12);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x71, 0x03, 0x07);
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15);
cxd2841er_write_reg(priv, I2C_SLVT, 0xBE, 0x02);
break;
case 6000000:
/* TRCG Nominal Rate */
cxd2841er_write_regs(priv, I2C_SLVT,
0x9F, nominalRate6bw[priv->xtal], 5);
/* Group delay equaliser settings for ASCOT tuners optimized */
cxd2841er_write_regs(priv, I2C_SLVT,
0xA6, itbCoef6bw[priv->xtal], 14);
/* IF freq setting */
iffreq = MAKE_IFFREQ_CONFIG_XTAL(priv->xtal, 3.55);
data[0] = (u8) ((iffreq >> 16) & 0xff);
data[1] = (u8)((iffreq >> 8) & 0xff);
data[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(priv, I2C_SLVT, 0xB6, data, 3);
/* System bandwidth setting */
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, 0x04, 0x7);
/* Demod core latency setting */
if (priv->xtal == SONY_XTAL_24000) {
data[0] = 0x1F;
data[1] = 0x79;
} else {
data[0] = 0x1A;
data[1] = 0xE2;
}
cxd2841er_write_regs(priv, I2C_SLVT, 0xD9, data, 2);
/* Acquisition optimization setting */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x12);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x71, 0x07, 0x07);
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15);
cxd2841er_write_reg(priv, I2C_SLVT, 0xBE, 0x02);
break; break;
default: default:
dev_dbg(&priv->i2c->dev, "%s(): invalid bandwidth %d\n", dev_dbg(&priv->i2c->dev, "%s(): invalid bandwidth %d\n",
__func__, bandwidth); __func__, bandwidth);
return -EINVAL; return -EINVAL;
} }
/* <IF freq setting> */
b10_b6[0] = (u8) ((iffreq >> 16) & 0xff);
b10_b6[1] = (u8)((iffreq >> 8) & 0xff);
b10_b6[2] = (u8)(iffreq & 0xff);
cxd2841er_write_regs(
priv, I2C_SLVT, 0x9f, b10_9f, sizeof(bw8mhz_b10_9f));
cxd2841er_write_regs(
priv, I2C_SLVT, 0xa6, b10_a6, sizeof(bw8mhz_b10_a6));
cxd2841er_write_regs(priv, I2C_SLVT, 0xb6, b10_b6, sizeof(b10_b6));
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xd7, d7val, 0x7);
cxd2841er_write_regs(
priv, I2C_SLVT, 0xd9, b10_d9, sizeof(bw8mhz_b10_d9));
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x17);
cxd2841er_write_regs(
priv, I2C_SLVT, 0x38, b17_38, sizeof(bw8mhz_b17_38));
return 0; return 0;
} }
...@@ -1902,6 +2377,7 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, ...@@ -1902,6 +2377,7 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv,
u32 bandwidth) u32 bandwidth)
{ {
u8 data[2] = { 0x09, 0x54 }; u8 data[2] = { 0x09, 0x54 };
u8 data24m[3] = {0xDC, 0x6C, 0x00};
dev_dbg(&priv->i2c->dev, "%s()\n", __func__); dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
cxd2841er_set_ts_clock_mode(priv, SYS_DVBT); cxd2841er_set_ts_clock_mode(priv, SYS_DVBT);
...@@ -1919,7 +2395,11 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, ...@@ -1919,7 +2395,11 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv,
cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00); cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00);
/* Enable ADC 1 */ /* Enable ADC 1 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x1a); cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x1a);
/* xtal freq 20.5MHz */ /* Enable ADC 2 & 3 */
if (priv->xtal == SONY_XTAL_41000) {
data[0] = 0x0A;
data[1] = 0xD4;
}
cxd2841er_write_regs(priv, I2C_SLVT, 0x43, data, 2); cxd2841er_write_regs(priv, I2C_SLVT, 0x43, data, 2);
/* Enable ADC 4 */ /* Enable ADC 4 */
cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x00); cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x00);
...@@ -1947,6 +2427,15 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv, ...@@ -1947,6 +2427,15 @@ static int cxd2841er_sleep_tc_to_active_t(struct cxd2841er_priv *priv,
/* TSIF setting */ /* TSIF setting */
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xce, 0x01, 0x01); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xce, 0x01, 0x01);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcf, 0x01, 0x01); cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcf, 0x01, 0x01);
if (priv->xtal == SONY_XTAL_24000) {
/* Set SLV-T Bank : 0x10 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10);
cxd2841er_write_reg(priv, I2C_SLVT, 0xBF, 0x60);
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x18);
cxd2841er_write_regs(priv, I2C_SLVT, 0x24, data24m, 3);
}
cxd2841er_sleep_tc_to_active_t_band(priv, bandwidth); cxd2841er_sleep_tc_to_active_t_band(priv, bandwidth);
/* Set SLV-T Bank : 0x00 */ /* Set SLV-T Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00); cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00);
...@@ -2032,6 +2521,84 @@ static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv, ...@@ -2032,6 +2521,84 @@ static int cxd2841er_sleep_tc_to_active_t2(struct cxd2841er_priv *priv,
return 0; return 0;
} }
/* ISDB-Tb part */
static int cxd2841er_sleep_tc_to_active_i(struct cxd2841er_priv *priv,
u32 bandwidth)
{
u8 data[2] = { 0x09, 0x54 };
u8 data24m[2] = {0x60, 0x00};
u8 data24m2[3] = {0xB7, 0x1B, 0x00};
dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
cxd2841er_set_ts_clock_mode(priv, SYS_DVBT);
/* Set SLV-X Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVX, 0x00, 0x00);
/* Set demod mode */
cxd2841er_write_reg(priv, I2C_SLVX, 0x17, 0x06);
/* Set SLV-T Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00);
/* Enable demod clock */
cxd2841er_write_reg(priv, I2C_SLVT, 0x2c, 0x01);
/* Enable RF level monitor */
cxd2841er_write_reg(priv, I2C_SLVT, 0x2f, 0x01);
cxd2841er_write_reg(priv, I2C_SLVT, 0x59, 0x01);
/* Enable ADC clock */
cxd2841er_write_reg(priv, I2C_SLVT, 0x30, 0x00);
/* Enable ADC 1 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x41, 0x1a);
/* xtal freq 20.5MHz or 24M */
cxd2841er_write_regs(priv, I2C_SLVT, 0x43, data, 2);
/* Enable ADC 4 */
cxd2841er_write_reg(priv, I2C_SLVX, 0x18, 0x00);
/* ASCOT setting ON */
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xa5, 0x01, 0x01);
/* FEC Auto Recovery setting */
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x30, 0x01, 0x01);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x31, 0x00, 0x01);
/* ISDB-T initial setting */
/* Set SLV-T Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xce, 0x00, 0x01);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xcf, 0x00, 0x01);
/* Set SLV-T Bank : 0x10 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x69, 0x04, 0x07);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x6B, 0x03, 0x07);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x9D, 0x50, 0xFF);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xD3, 0x06, 0x1F);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xED, 0x00, 0x01);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xE2, 0xCE, 0x80);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xF2, 0x13, 0x10);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xDE, 0x2E, 0x3F);
/* Set SLV-T Bank : 0x15 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x15);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0xDE, 0x02, 0x03);
/* Set SLV-T Bank : 0x1E */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x1E);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x73, 0x68, 0xFF);
/* Set SLV-T Bank : 0x63 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x63);
cxd2841er_set_reg_bits(priv, I2C_SLVT, 0x81, 0x00, 0x01);
/* for xtal 24MHz */
/* Set SLV-T Bank : 0x10 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x10);
cxd2841er_write_regs(priv, I2C_SLVT, 0xBF, data24m, 2);
/* Set SLV-T Bank : 0x60 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x60);
cxd2841er_write_regs(priv, I2C_SLVT, 0xA8, data24m2, 3);
cxd2841er_sleep_tc_to_active_i_band(priv, bandwidth);
/* Set SLV-T Bank : 0x00 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x00, 0x00);
/* Disable HiZ Setting 1 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x80, 0x28);
/* Disable HiZ Setting 2 */
cxd2841er_write_reg(priv, I2C_SLVT, 0x81, 0x00);
priv->state = STATE_ACTIVE_TC;
return 0;
}
static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv, static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv,
u32 bandwidth) u32 bandwidth)
{ {
...@@ -2142,10 +2709,10 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe) ...@@ -2142,10 +2709,10 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe)
struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 symbol_rate = p->symbol_rate/1000; u32 symbol_rate = p->symbol_rate/1000;
dev_dbg(&priv->i2c->dev, "%s(): %s frequency=%d symbol_rate=%d\n", dev_dbg(&priv->i2c->dev, "%s(): %s frequency=%d symbol_rate=%d xtal=%d\n",
__func__, __func__,
(p->delivery_system == SYS_DVBS ? "DVB-S" : "DVB-S2"), (p->delivery_system == SYS_DVBS ? "DVB-S" : "DVB-S2"),
p->frequency, symbol_rate); p->frequency, symbol_rate, priv->xtal);
switch (priv->state) { switch (priv->state) {
case STATE_SLEEP_S: case STATE_SLEEP_S:
ret = cxd2841er_sleep_s_to_active_s( ret = cxd2841er_sleep_s_to_active_s(
...@@ -2233,6 +2800,21 @@ static int cxd2841er_set_frontend_tc(struct dvb_frontend *fe) ...@@ -2233,6 +2800,21 @@ static int cxd2841er_set_frontend_tc(struct dvb_frontend *fe)
__func__, priv->state); __func__, priv->state);
ret = -EINVAL; ret = -EINVAL;
} }
} else if (p->delivery_system == SYS_ISDBT) {
priv->system = SYS_ISDBT;
switch (priv->state) {
case STATE_SLEEP_TC:
ret = cxd2841er_sleep_tc_to_active_i(
priv, p->bandwidth_hz);
break;
case STATE_ACTIVE_TC:
ret = cxd2841er_retune_active(priv, p);
break;
default:
dev_dbg(&priv->i2c->dev, "%s(): invalid state %d\n",
__func__, priv->state);
ret = -EINVAL;
}
} else if (p->delivery_system == SYS_DVBC_ANNEX_A || } else if (p->delivery_system == SYS_DVBC_ANNEX_A ||
p->delivery_system == SYS_DVBC_ANNEX_C) { p->delivery_system == SYS_DVBC_ANNEX_C) {
priv->system = SYS_DVBC_ANNEX_A; priv->system = SYS_DVBC_ANNEX_A;
...@@ -2382,6 +2964,9 @@ static int cxd2841er_sleep_tc(struct dvb_frontend *fe) ...@@ -2382,6 +2964,9 @@ static int cxd2841er_sleep_tc(struct dvb_frontend *fe)
case SYS_DVBT2: case SYS_DVBT2:
cxd2841er_active_t2_to_sleep_tc(priv); cxd2841er_active_t2_to_sleep_tc(priv);
break; break;
case SYS_ISDBT:
cxd2841er_active_i_to_sleep_tc(priv);
break;
case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_A:
cxd2841er_active_c_to_sleep_tc(priv); cxd2841er_active_c_to_sleep_tc(priv);
break; break;
...@@ -2544,6 +3129,7 @@ static int cxd2841er_init_tc(struct dvb_frontend *fe) ...@@ -2544,6 +3129,7 @@ static int cxd2841er_init_tc(struct dvb_frontend *fe)
static struct dvb_frontend_ops cxd2841er_dvbs_s2_ops; static struct dvb_frontend_ops cxd2841er_dvbs_s2_ops;
static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops; static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops;
static struct dvb_frontend_ops cxd2841er_dvbc_ops; static struct dvb_frontend_ops cxd2841er_dvbc_ops;
static struct dvb_frontend_ops cxd2841er_isdbt_ops;
static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg,
struct i2c_adapter *i2c, struct i2c_adapter *i2c,
...@@ -2561,6 +3147,7 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, ...@@ -2561,6 +3147,7 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg,
priv->config = cfg; priv->config = cfg;
priv->i2c_addr_slvx = (cfg->i2c_addr + 4) >> 1; priv->i2c_addr_slvx = (cfg->i2c_addr + 4) >> 1;
priv->i2c_addr_slvt = (cfg->i2c_addr) >> 1; priv->i2c_addr_slvt = (cfg->i2c_addr) >> 1;
priv->xtal = cfg->xtal;
/* create dvb_frontend */ /* create dvb_frontend */
switch (system) { switch (system) {
case SYS_DVBS: case SYS_DVBS:
...@@ -2575,6 +3162,12 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, ...@@ -2575,6 +3162,12 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg,
sizeof(struct dvb_frontend_ops)); sizeof(struct dvb_frontend_ops));
type = "T/T2"; type = "T/T2";
break; break;
case SYS_ISDBT:
memcpy(&priv->frontend.ops,
&cxd2841er_isdbt_ops,
sizeof(struct dvb_frontend_ops));
type = "ISDBT";
break;
case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_A:
memcpy(&priv->frontend.ops, memcpy(&priv->frontend.ops,
&cxd2841er_dvbc_ops, &cxd2841er_dvbc_ops,
...@@ -2594,7 +3187,7 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg, ...@@ -2594,7 +3187,7 @@ static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg,
__func__, priv->i2c, __func__, priv->i2c,
priv->i2c_addr_slvx, priv->i2c_addr_slvt); priv->i2c_addr_slvx, priv->i2c_addr_slvt);
chip_id = cxd2841er_chip_id(priv); chip_id = cxd2841er_chip_id(priv);
if (chip_id != CXD2841ER_CHIP_ID) { if (chip_id != CXD2841ER_CHIP_ID && chip_id != CXD2854ER_CHIP_ID) {
dev_err(&priv->i2c->dev, "%s(): invalid chip ID 0x%02x\n", dev_err(&priv->i2c->dev, "%s(): invalid chip ID 0x%02x\n",
__func__, chip_id); __func__, chip_id);
priv->frontend.demodulator_priv = NULL; priv->frontend.demodulator_priv = NULL;
...@@ -2620,6 +3213,13 @@ struct dvb_frontend *cxd2841er_attach_t(struct cxd2841er_config *cfg, ...@@ -2620,6 +3213,13 @@ struct dvb_frontend *cxd2841er_attach_t(struct cxd2841er_config *cfg,
} }
EXPORT_SYMBOL(cxd2841er_attach_t); EXPORT_SYMBOL(cxd2841er_attach_t);
struct dvb_frontend *cxd2841er_attach_i(struct cxd2841er_config *cfg,
struct i2c_adapter *i2c)
{
return cxd2841er_attach(cfg, i2c, SYS_ISDBT);
}
EXPORT_SYMBOL(cxd2841er_attach_i);
struct dvb_frontend *cxd2841er_attach_c(struct cxd2841er_config *cfg, struct dvb_frontend *cxd2841er_attach_c(struct cxd2841er_config *cfg,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
...@@ -2691,6 +3291,42 @@ static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops = { ...@@ -2691,6 +3291,42 @@ static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops = {
.get_frontend_algo = cxd2841er_get_algo .get_frontend_algo = cxd2841er_get_algo
}; };
static struct dvb_frontend_ops cxd2841er_isdbt_ops = {
.delsys = { SYS_ISDBT },
.info = {
.name = "Sony CXD2854ER ISDBT demodulator",
.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_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_QAM_16 |
FE_CAN_QAM_32 |
FE_CAN_QAM_64 |
FE_CAN_QAM_128 |
FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO |
FE_CAN_MUTE_TS |
FE_CAN_2G_MODULATION,
.frequency_min = 42000000,
.frequency_max = 1002000000
},
.init = cxd2841er_init_tc,
.sleep = cxd2841er_sleep_tc,
.release = cxd2841er_release,
.set_frontend = cxd2841er_set_frontend_tc,
.get_frontend = cxd2841er_get_frontend,
.read_status = cxd2841er_read_status_tc,
.tune = cxd2841er_tune_tc,
.i2c_gate_ctrl = cxd2841er_i2c_gate_ctrl,
.get_frontend_algo = cxd2841er_get_algo
};
static struct dvb_frontend_ops cxd2841er_dvbc_ops = { static struct dvb_frontend_ops cxd2841er_dvbc_ops = {
.delsys = { SYS_DVBC_ANNEX_A }, .delsys = { SYS_DVBC_ANNEX_A },
.info = { .info = {
...@@ -2722,6 +3358,6 @@ static struct dvb_frontend_ops cxd2841er_dvbc_ops = { ...@@ -2722,6 +3358,6 @@ static struct dvb_frontend_ops cxd2841er_dvbc_ops = {
.get_frontend_algo = cxd2841er_get_algo, .get_frontend_algo = cxd2841er_get_algo,
}; };
MODULE_DESCRIPTION("Sony CXD2841ER DVB-C/C2/T/T2/S/S2 demodulator driver"); MODULE_DESCRIPTION("Sony CXD2841ER/CXD2854ER DVB-C/C2/T/T2/S/S2 demodulator driver");
MODULE_AUTHOR("Sergey Kozlov <serjk@netup.ru>"); MODULE_AUTHOR("Sergey Kozlov <serjk@netup.ru>, Abylay Ospan <aospan@netup.ru>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -25,8 +25,15 @@ ...@@ -25,8 +25,15 @@
#include <linux/kconfig.h> #include <linux/kconfig.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
enum cxd2841er_xtal {
SONY_XTAL_20500, /* 20.5 MHz */
SONY_XTAL_24000, /* 24 MHz */
SONY_XTAL_41000 /* 41 MHz */
};
struct cxd2841er_config { struct cxd2841er_config {
u8 i2c_addr; u8 i2c_addr;
enum cxd2841er_xtal xtal;
}; };
#if IS_REACHABLE(CONFIG_DVB_CXD2841ER) #if IS_REACHABLE(CONFIG_DVB_CXD2841ER)
...@@ -38,28 +45,38 @@ extern struct dvb_frontend *cxd2841er_attach_t(struct cxd2841er_config *cfg, ...@@ -38,28 +45,38 @@ extern struct dvb_frontend *cxd2841er_attach_t(struct cxd2841er_config *cfg,
extern struct dvb_frontend *cxd2841er_attach_c(struct cxd2841er_config *cfg, extern struct dvb_frontend *cxd2841er_attach_c(struct cxd2841er_config *cfg,
struct i2c_adapter *i2c); struct i2c_adapter *i2c);
extern struct dvb_frontend *cxd2841er_attach_i(struct cxd2841er_config *cfg,
struct i2c_adapter *i2c);
#else #else
static inline struct dvb_frontend *cxd2841er_attach_s( static inline struct dvb_frontend *cxd2841er_attach_s(
struct cxd2841er_config *cfg, struct cxd2841er_config *cfg,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL; return NULL;
} }
static inline struct dvb_frontend *cxd2841er_attach_t( static inline struct dvb_frontend *cxd2841er_attach_t(
struct cxd2841er_config *cfg, struct i2c_adapter *i2c) struct cxd2841er_config *cfg, struct i2c_adapter *i2c)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL; return NULL;
} }
static inline struct dvb_frontend *cxd2841er_attach_c( static inline struct dvb_frontend *cxd2841er_attach_c(
struct cxd2841er_config *cfg, struct i2c_adapter *i2c) struct cxd2841er_config *cfg, struct i2c_adapter *i2c)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct dvb_frontend *cxd2841er_attach_i(
struct cxd2841er_config *cfg, struct i2c_adapter *i2c)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL; return NULL;
} }
#endif #endif
#endif #endif
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define I2C_SLVT 1 #define I2C_SLVT 1
#define CXD2841ER_CHIP_ID 0xa7 #define CXD2841ER_CHIP_ID 0xa7
#define CXD2854ER_CHIP_ID 0xc1
#define CXD2841ER_DVBS_POLLING_INVL 10 #define CXD2841ER_DVBS_POLLING_INVL 10
......
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