From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail.kapsi.fi ([217.30.184.167]:53846 "EHLO mail.kapsi.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751534AbaIWMEM (ORCPT ); Tue, 23 Sep 2014 08:04:12 -0400 Message-ID: <542161B7.501@iki.fi> Date: Tue, 23 Sep 2014 15:04:07 +0300 From: Antti Palosaari MIME-Version: 1.0 To: Mauro Carvalho Chehab CC: linux-media@vger.kernel.org Subject: Re: [PATCH 3/4] cxd2843: Sony CXD2843 DVB-C/C2/T/T2 demodulator driver References: <1406845988-2871-1-git-send-email-crope@iki.fi> <1406845988-2871-3-git-send-email-crope@iki.fi> <20140923084719.7bb990f1@recife.lan> In-Reply-To: <20140923084719.7bb990f1@recife.lan> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-media-owner@vger.kernel.org List-ID: Consider it is a RFC. There is tons of things to do, review and fix issues. There is issues like missing DVB-C2 API, I2C model, style issues etc. regards Antti On 09/23/2014 02:47 PM, Mauro Carvalho Chehab wrote: > Em Fri, 1 Aug 2014 01:33:07 +0300 > Antti Palosaari escreveu: > >> Sony CXD2843 DVB-C/C2/T/T2 demodulator driver. >> Driver taken from Digital Devices Linux driver package >> dddvb-0.9.15a. > > Tried to ping you about that todad on IRC. For now, I'm seeing this as a > RFC patch, right? > > It seems that there are some work to be done to make this to follow our > CodingStyle, like CamelCase enums and integers in uppercase, removing the > GNU address, etc. > > Also, you'll likely want to convert it to use the REGMAP API. > > So, for now I'll be tagging this as RFC at patchwork, together with the > corresponding patch series. > > Regards, > Mauro > >> >> Signed-off-by: Antti Palosaari >> --- >> drivers/media/dvb-frontends/Kconfig | 8 + >> drivers/media/dvb-frontends/Makefile | 1 + >> drivers/media/dvb-frontends/cxd2843.c | 2025 +++++++++++++++++++++++++++++++++ >> drivers/media/dvb-frontends/cxd2843.h | 30 + >> 4 files changed, 2064 insertions(+) >> create mode 100644 drivers/media/dvb-frontends/cxd2843.c >> create mode 100644 drivers/media/dvb-frontends/cxd2843.h >> >> diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig >> index fe0ddcc..5475f59 100644 >> --- a/drivers/media/dvb-frontends/Kconfig >> +++ b/drivers/media/dvb-frontends/Kconfig >> @@ -72,6 +72,14 @@ config DVB_SI2165 >> >> Say Y when you want to support this frontend. >> >> +config DVB_CXD2843 >> + tristate "Sony CXD2843" >> + depends on DVB_CORE && I2C >> + default m if !MEDIA_SUBDRV_AUTOSELECT >> + help >> + Sony CXD2843 DVB-C/C2/T/T2 demodulator driver. >> + Say Y when you want to support this frontend. >> + >> comment "DVB-S (satellite) frontends" >> depends on DVB_CORE >> >> diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile >> index edf103d..9a9f131 100644 >> --- a/drivers/media/dvb-frontends/Makefile >> +++ b/drivers/media/dvb-frontends/Makefile >> @@ -103,6 +103,7 @@ obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o >> obj-$(CONFIG_DVB_IX2505V) += ix2505v.o >> obj-$(CONFIG_DVB_STV0367) += stv0367.o >> obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o >> +obj-$(CONFIG_DVB_CXD2843) += cxd2843.o >> obj-$(CONFIG_DVB_DRXK) += drxk.o >> obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o >> obj-$(CONFIG_DVB_SI2165) += si2165.o >> diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c >> new file mode 100644 >> index 0000000..10fc240 >> --- /dev/null >> +++ b/drivers/media/dvb-frontends/cxd2843.c >> @@ -0,0 +1,2025 @@ >> +/* >> + * Driver for the Sony CXD2843ER DVB-T/T2/C/C2 demodulator. >> + * Also supports the CXD2837ER DVB-T/T2/C and the >> + * CXD2838ER ISDB-T demodulator. >> + * >> + * Copyright (C) 2013-2014 Digital Devices GmbH >> + * >> + * This program is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU General Public License >> + * version 2 only, 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. >> + * >> + * >> + * You should have received a copy of the GNU General Public License >> + * along with this program; if not, write to the Free Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA >> + * 02110-1301, USA >> + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "dvb_frontend.h" >> +#include "cxd2843.h" >> + >> +#define USE_ALGO 1 >> + >> +enum EDemodType { CXD2843, CXD2837, CXD2838 }; >> +enum EDemodState { Unknown, Shutdown, Sleep, ActiveT, >> + ActiveT2, ActiveC, ActiveC2, ActiveIT }; >> +enum ET2Profile { T2P_Base, T2P_Lite }; >> +enum omode { OM_NONE, OM_DVBT, OM_DVBT2, OM_DVBC, >> + OM_QAM_ITU_C, OM_DVBC2, OM_ISDBT }; > > > >> + >> +struct cxd_state { >> + struct dvb_frontend frontend; >> + struct i2c_adapter *i2c; >> + struct mutex mutex; >> + >> + u8 adrt; >> + u8 curbankt; >> + >> + u8 adrx; >> + u8 curbankx; >> + >> + enum EDemodType type; >> + enum EDemodState state; >> + enum ET2Profile T2Profile; >> + enum omode omode; >> + >> + u8 IF_FS; >> + int ContinuousClock; >> + int SerialMode; >> + u8 SerialClockFrequency; >> + >> + u32 LockTimeout; >> + u32 TSLockTimeout; >> + u32 L1PostTimeout; >> + u32 DataSliceID; >> + int FirstTimeLock; >> + u32 plp; >> + u32 last_status; >> + >> + u32 bandwidth; >> + u32 bw; >> + >> + unsigned long tune_time; >> + >> + u32 LastBERNominator; >> + u32 LastBERDenominator; >> + u8 BERScaleMax; >> +}; >> + >> +static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) >> +{ >> + struct i2c_msg msg = { >> + .addr = adr, .flags = 0, .buf = data, .len = len}; >> + >> + if (i2c_transfer(adap, &msg, 1) != 1) { >> + pr_err("cxd2843: i2c_write error\n"); >> + return -1; >> + } >> + return 0; >> +} >> + >> +static int writeregs(struct cxd_state *state, u8 adr, u8 reg, >> + u8 *regd, u16 len) >> +{ >> + u8 data[len + 1]; >> + >> + data[0] = reg; >> + memcpy(data + 1, regd, len); >> + return i2c_write(state->i2c, adr, data, len + 1); >> +} >> + >> +static int writereg(struct cxd_state *state, u8 adr, u8 reg, u8 dat) >> +{ >> + u8 mm[2] = {reg, dat}; >> + >> + return i2c_write(state->i2c, adr, mm, 2); >> +} >> + >> +static int i2c_read(struct i2c_adapter *adap, >> + u8 adr, u8 *msg, int len, u8 *answ, int alen) >> +{ >> + struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, >> + .buf = msg, .len = len}, >> + { .addr = adr, .flags = I2C_M_RD, >> + .buf = answ, .len = alen } }; >> + if (i2c_transfer(adap, msgs, 2) != 2) { >> + pr_err("cxd2843: i2c_read error\n"); >> + return -1; >> + } >> + return 0; >> +} >> + >> +static int readregs(struct cxd_state *state, u8 adr, u8 reg, >> + u8 *val, int count) >> +{ >> + return i2c_read(state->i2c, adr, ®, 1, val, count); >> +} >> + >> +static int readregst_unlocked(struct cxd_state *cxd, u8 bank, >> + u8 Address, u8 *pValue, u16 count) >> +{ >> + int status = 0; >> + >> + if (bank != 0xFF && cxd->curbankt != bank) { >> + status = writereg(cxd, cxd->adrt, 0, bank); >> + if (status < 0) { >> + cxd->curbankt = 0xFF; >> + return status; >> + } >> + cxd->curbankt = bank; >> + } >> + status = readregs(cxd, cxd->adrt, Address, pValue, count); >> + return status; >> +} >> + >> +static int readregst(struct cxd_state *cxd, u8 Bank, >> + u8 Address, u8 *pValue, u16 count) >> +{ >> + int status; >> + >> + mutex_lock(&cxd->mutex); >> + status = readregst_unlocked(cxd, Bank, Address, pValue, count); >> + mutex_unlock(&cxd->mutex); >> + return status; >> +} >> + >> +static int readregsx_unlocked(struct cxd_state *cxd, u8 Bank, >> + u8 Address, u8 *pValue, u16 count) >> +{ >> + int status = 0; >> + >> + if (Bank != 0xFF && cxd->curbankx != Bank) { >> + status = writereg(cxd, cxd->adrx, 0, Bank); >> + if (status < 0) { >> + cxd->curbankx = 0xFF; >> + return status; >> + } >> + cxd->curbankx = Bank; >> + } >> + status = readregs(cxd, cxd->adrx, Address, pValue, count); >> + return status; >> +} >> + >> +static int readregsx(struct cxd_state *cxd, u8 Bank, >> + u8 Address, u8 *pValue, u16 count) >> +{ >> + int status; >> + >> + mutex_lock(&cxd->mutex); >> + status = readregsx_unlocked(cxd, Bank, Address, pValue, count); >> + mutex_unlock(&cxd->mutex); >> + return status; >> +} >> + >> +static int writeregsx_unlocked(struct cxd_state *cxd, u8 Bank, >> + u8 Address, u8 *pValue, u16 count) >> +{ >> + int status = 0; >> + >> + if (Bank != 0xFF && cxd->curbankx != Bank) { >> + status = writereg(cxd, cxd->adrx, 0, Bank); >> + if (status < 0) { >> + cxd->curbankx = 0xFF; >> + return status; >> + } >> + cxd->curbankx = Bank; >> + } >> + status = writeregs(cxd, cxd->adrx, Address, pValue, count); >> + return status; >> +} >> + >> +static int writeregsx(struct cxd_state *cxd, u8 Bank, u8 Address, >> + u8 *pValue, u16 count) >> +{ >> + int status; >> + >> + mutex_lock(&cxd->mutex); >> + status = writeregsx_unlocked(cxd, Bank, Address, pValue, count); >> + mutex_unlock(&cxd->mutex); >> + return status; >> +} >> + >> +static int writeregx(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) >> +{ >> + return writeregsx(cxd, Bank, Address, &val, 1); >> +} >> + >> +static int writeregst_unlocked(struct cxd_state *cxd, u8 Bank, >> + u8 Address, u8 *pValue, u16 count) >> +{ >> + int status = 0; >> + >> + if (Bank != 0xFF && cxd->curbankt != Bank) { >> + status = writereg(cxd, cxd->adrt, 0, Bank); >> + if (status < 0) { >> + cxd->curbankt = 0xFF; >> + return status; >> + } >> + cxd->curbankt = Bank; >> + } >> + status = writeregs(cxd, cxd->adrt, Address, pValue, count); >> + return status; >> +} >> + >> +static int writeregst(struct cxd_state *cxd, u8 Bank, u8 Address, >> + u8 *pValue, u16 count) >> +{ >> + int status; >> + >> + mutex_lock(&cxd->mutex); >> + status = writeregst_unlocked(cxd, Bank, Address, pValue, count); >> + mutex_unlock(&cxd->mutex); >> + return status; >> +} >> + >> +static int writeregt(struct cxd_state *cxd, u8 Bank, u8 Address, u8 val) >> +{ >> + return writeregst(cxd, Bank, Address, &val, 1); >> +} >> + >> +static int writebitsx(struct cxd_state *cxd, u8 Bank, u8 Address, >> + u8 Value, u8 Mask) >> +{ >> + int status = 0; >> + u8 tmp; >> + >> + mutex_lock(&cxd->mutex); >> + status = readregsx_unlocked(cxd, Bank, Address, &tmp, 1); >> + if (status < 0) >> + return status; >> + tmp = (tmp & ~Mask) | Value; >> + status = writeregsx_unlocked(cxd, Bank, Address, &tmp, 1); >> + mutex_unlock(&cxd->mutex); >> + return status; >> +} >> + >> +static int writebitst(struct cxd_state *cxd, u8 Bank, u8 Address, >> + u8 Value, u8 Mask) >> +{ >> + int status = 0; >> + u8 Tmp = 0x00; >> + >> + mutex_lock(&cxd->mutex); >> + status = readregst_unlocked(cxd, Bank, Address, &Tmp, 1); >> + if (status < 0) >> + return status; >> + Tmp = (Tmp & ~Mask) | Value; >> + status = writeregst_unlocked(cxd, Bank, Address, &Tmp, 1); >> + mutex_unlock(&cxd->mutex); >> + return status; >> +} >> + >> +static int freeze_regst(struct cxd_state *cxd) >> +{ >> + mutex_lock(&cxd->mutex); >> + return writereg(cxd, cxd->adrt, 1, 1); >> +} >> + >> +static int unfreeze_regst(struct cxd_state *cxd) >> +{ >> + int status = 0; >> + >> + status = writereg(cxd, cxd->adrt, 1, 0); >> + mutex_unlock(&cxd->mutex); >> + return status; >> +} >> + >> +static inline u32 MulDiv32(u32 a, u32 b, u32 c) >> +{ >> + u64 tmp64; >> + >> + tmp64 = (u64)a * (u64)b; >> + do_div(tmp64, c); >> + >> + return (u32) tmp64; >> +} >> + >> +/* TPSData[0] [7:6] CNST[1:0] */ >> +/* TPSData[0] [5:3] HIER[2:0] */ >> +/* TPSData[0] [2:0] HRATE[2:0] */ >> +/* TPSData[1] [7:5] LRATE[2:0] */ >> +/* TPSData[1] [4:3] GI[1:0] */ >> +/* TPSData[1] [2:1] MODE[1:0] */ >> +/* TPSData[2] [7:6] FNUM[1:0] */ >> +/* TPSData[2] [5:0] LENGTH_INDICATOR[5:0] */ >> +/* TPSData[3] [7:0] CELLID[15:8] */ >> +/* TPSData[4] [7:0] CELLID[7:0] */ >> +/* TPSData[5] [5:0] RESERVE_EVEN[5:0] */ >> +/* TPSData[6] [5:0] RESERVE_ODD[5:0] */ >> + >> +static int read_tps(struct cxd_state *state, u8 *tps) >> +{ >> + if (state->last_status != 0x1f) >> + return 0; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x10, 0x2f, tps, 7); >> + unfreeze_regst(state); >> + return 0; >> +} >> + >> +static void Active_to_Sleep(struct cxd_state *state) >> +{ >> + if (state->state <= Sleep) >> + return; >> + >> + writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ >> + writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ >> + writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ >> + writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ >> + writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ >> + writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ >> + writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ >> + state->state = Sleep; >> +} >> + >> +static void ActiveT2_to_Sleep(struct cxd_state *state) >> +{ >> + if (state->state <= Sleep) >> + return; >> + >> + writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ >> + writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ >> + writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ >> + >> + writeregt(state, 0x13, 0x83, 0x40); >> + writeregt(state, 0x13, 0x86, 0x21); >> + writebitst(state, 0x13, 0x9E, 0x09, 0x0F); >> + writeregt(state, 0x13, 0x9F, 0xFB); >> + >> + writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ >> + writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ >> + writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ >> + writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ >> + state->state = Sleep; >> +} >> + >> +static void ActiveC2_to_Sleep(struct cxd_state *state) >> +{ >> + if (state->state <= Sleep) >> + return; >> + >> + writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ >> + writeregt(state, 0x00, 0x80, 0x3F); /* Enable HighZ 1 */ >> + writeregt(state, 0x00, 0x81, 0xFF); /* Enable HighZ 2 */ >> + >> + writeregt(state, 0x20, 0xC2, 0x11); >> + writebitst(state, 0x25, 0x6A, 0x02, 0x03); >> + { >> + static u8 data[3] = { 0x07, 0x61, 0x36 }; >> + writeregst(state, 0x25, 0x89, data, sizeof(data)); >> + } >> + writebitst(state, 0x25, 0xCB, 0x05, 0x07); >> + { >> + static u8 data[4] = { 0x2E, 0xE0, 0x2E, 0xE0 }; >> + writeregst(state, 0x25, 0xDC, data, sizeof(data)); >> + } >> + writeregt(state, 0x25, 0xE2, 0x2F); >> + writeregt(state, 0x25, 0xE5, 0x2F); >> + writebitst(state, 0x27, 0x20, 0x00, 0x01); >> + writebitst(state, 0x27, 0x35, 0x00, 0x01); >> + writebitst(state, 0x27, 0xD9, 0x19, 0x3F); >> + writebitst(state, 0x2A, 0x78, 0x01, 0x07); >> + writeregt(state, 0x2A, 0x86, 0x08); >> + writeregt(state, 0x2A, 0x88, 0x14); >> + writebitst(state, 0x2B, 0x2B, 0x00, 0x1F); >> + { >> + u8 data[2] = { 0x75, 0x75 }; >> + writeregst(state, 0x2D, 0x24, data, sizeof(data)); >> + } >> + >> + writeregx(state, 0x00, 0x18, 0x01); /* Disable ADC 4 */ >> + writeregt(state, 0x00, 0x43, 0x0A); /* Disable ADC 2 */ >> + writeregt(state, 0x00, 0x41, 0x0A); /* Disable ADC 1 */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Disable ADC Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF level Monitor */ >> + writeregt(state, 0x00, 0x2C, 0x00); /* Disable Demod Clock */ >> + state->state = Sleep; >> +} >> + >> +static int ConfigureTS(struct cxd_state *state, >> + enum EDemodState newDemodState) >> +{ >> + int status = 0; >> + u8 OSERCKMODE = state->SerialMode ? 1 : 0; >> + u8 OSERDUTYMODE = state->SerialMode ? 1 : 0; >> + u8 OTSCKPERIOD = 8; >> + u8 OREG_CKSEL_TSIF = state->SerialMode ? >> + state->SerialClockFrequency : 0; >> + >> + if (state->SerialMode && state->SerialClockFrequency >= 3) { >> + OSERCKMODE = 2; >> + OSERDUTYMODE = 2; >> + OTSCKPERIOD = 16; >> + OREG_CKSEL_TSIF = state->SerialClockFrequency - 3; >> + } >> + writebitst(state, 0x00, 0xC4, OSERCKMODE, 0x03); /* OSERCKMODE */ >> + writebitst(state, 0x00, 0xD1, OSERDUTYMODE, 0x03); /* OSERDUTYMODE */ >> + writeregt(state, 0x00, 0xD9, OTSCKPERIOD); /* OTSCKPERIOD */ >> + writebitst(state, 0x00, 0x32, 0x00, 0x01); /* Disable TS IF */ >> + /* OREG_CKSEL_TSIF */ >> + writebitst(state, 0x00, 0x33, OREG_CKSEL_TSIF, 0x03); >> + writebitst(state, 0x00, 0x32, 0x01, 0x01); /* Enable TS IF */ >> + >> + if (newDemodState == ActiveT) >> + writebitst(state, 0x10, 0x66, 0x01, 0x01); >> + if (newDemodState == ActiveC) >> + writebitst(state, 0x40, 0x66, 0x01, 0x01); >> + >> + return status; >> +} >> + >> +static void BandSettingT(struct cxd_state *state, u32 iffreq) >> +{ >> + u8 IF_data[3] = { (iffreq >> 16) & 0xff, >> + (iffreq >> 8) & 0xff, iffreq & 0xff}; >> + >> + switch (state->bw) { >> + default: >> + case 8: >> + { >> + u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; >> + u8 CL_data[] = { 0x01, 0xE0 }; >> + u8 NF_data[] = { 0x01, 0x02 }; >> + >> + writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x00, 0x07); >> + writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); >> + writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); >> + break; >> + } >> + case 7: >> + { >> + u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; >> + u8 CL_data[] = { 0x12, 0xF8 }; >> + u8 NF_data[] = { 0x00, 0x03 }; >> + >> + writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x02, 0x07); >> + writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); >> + writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); >> + break; >> + } >> + case 6: >> + { >> + u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; >> + u8 CL_data[] = { 0x1F, 0xDC }; >> + u8 NF_data[] = { 0x00, 0x03 }; >> + >> + writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x04, 0x07); >> + writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); >> + writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); >> + break; >> + } >> + case 5: >> + { >> + static u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; >> + static u8 CL_data[] = { 0x26, 0x3C }; >> + static u8 NF_data[] = { 0x00, 0x03 }; >> + >> + writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x06, 0x07); >> + writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); >> + writeregst(state, 0x17, 0x38, NF_data, sizeof(NF_data)); >> + break; >> + } >> + } >> +} >> + >> +static void Sleep_to_ActiveT(struct cxd_state *state, u32 iffreq) >> +{ >> + ConfigureTS(state, ActiveT); >> + writeregx(state, 0x00, 0x17, 0x01); /* Mode */ >> + writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ >> + writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ >> + { >> + u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ >> + /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ >> + writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ >> + } >> + writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ >> + >> + writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IF AGC Gain */ >> + writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ >> + >> + writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ >> + >> + writebitst(state, 0x18, 0x36, 0x40, 0x07); /* Pre RS Monitoring */ >> + writebitst(state, 0x18, 0x30, 0x01, 0x01); /* FEC Autorecover */ >> + writebitst(state, 0x18, 0x31, 0x01, 0x01); /* FEC Autorecover */ >> + >> + writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ >> + writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ >> + >> + BandSettingT(state, iffreq); >> + >> + writebitst(state, 0x10, 0x60, 0x11, 0x1f); /* BER scaling */ >> + >> + writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ >> + writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ >> +} >> + >> +static void BandSettingT2(struct cxd_state *state, u32 iffreq) >> +{ >> + u8 IF_data[3] = {(iffreq >> 16) & 0xff, (iffreq >> 8) & 0xff, >> + iffreq & 0xff}; >> + >> + switch (state->bw) { >> + default: >> + case 8: >> + { >> + u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; >> + /* Timing recovery */ >> + writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); >> + /* Add EQ Optimisation for tuner here */ >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + /* System Bandwidth */ >> + writebitst(state, 0x10, 0xD7, 0x00, 0x07); >> + } >> + break; >> + case 7: >> + { >> + u8 TR_data[] = { 0x14, 0x80, 0x00, 0x00, 0x00 }; >> + writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x02, 0x07); >> + } >> + break; >> + case 6: >> + { >> + u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; >> + writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x04, 0x07); >> + } >> + break; >> + case 5: >> + { >> + u8 TR_data[] = { 0x1C, 0xB3, 0x33, 0x33, 0x33 }; >> + writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x06, 0x07); >> + } >> + break; >> + case 2: /* 1.7 MHz */ >> + { >> + u8 TR_data[] = { 0x58, 0xE2, 0xAF, 0xE0, 0xBC }; >> + writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x03, 0x07); >> + } >> + break; >> + } >> +} >> + >> + >> +static void Sleep_to_ActiveT2(struct cxd_state *state, u32 iffreq) >> +{ >> + ConfigureTS(state, ActiveT2); >> + >> + writeregx(state, 0x00, 0x17, 0x02); /* Mode */ >> + writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ >> + writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ >> + >> + { >> + u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ >> + /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ >> + writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ >> + } >> + writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ >> + >> + writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ >> + writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ >> + writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ >> + >> + writeregt(state, 0x20, 0x8B, 0x3C); /* SNR Good count */ >> + writebitst(state, 0x2B, 0x76, 0x20, 0x70); /* Noise Gain ACQ */ >> + >> + writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ >> + writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ >> + >> + writeregt(state, 0x13, 0x83, 0x10); /* T2 Inital settings */ >> + writeregt(state, 0x13, 0x86, 0x34); >> + writebitst(state, 0x13, 0x9E, 0x09, 0x0F); >> + writeregt(state, 0x13, 0x9F, 0xD8); >> + >> + BandSettingT2(state, iffreq); >> + >> + writebitst(state, 0x20, 0x72, 0x08, 0x0f); /* BER scaling */ >> + >> + writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ >> + writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ >> +} >> + >> + >> +static void BandSettingC(struct cxd_state *state, u32 iffreq) >> +{ >> + u8 data[3]; >> + >> + data[0] = (iffreq >> 16) & 0xFF; >> + data[1] = (iffreq >> 8) & 0xFF; >> + data[2] = (iffreq) & 0xFF; >> + writeregst(state, 0x10, 0xB6, data, 3); >> +} >> + >> +static void Sleep_to_ActiveC(struct cxd_state *state, u32 iffreq) >> +{ >> + ConfigureTS(state, ActiveC); >> + >> + writeregx(state, 0x00, 0x17, 0x04); /* Mode */ >> + writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ >> + writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ >> + >> + { >> + u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ >> + /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ >> + writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ >> + } >> + writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ >> + >> + writebitst(state, 0x10, 0xD2, 0x09, 0x1F); /* IF AGC Gain */ >> + writeregt(state, 0x11, 0x6A, 0x48); /* BB AGC Target Level */ >> + writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ >> + >> + writebitst(state, 0x40, 0xC3, 0x00, 0x04); /* OREG_BNDET_EN_64 */ >> + >> + writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ >> + writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ >> + >> + BandSettingC(state, iffreq); >> + >> + writebitst(state, 0x40, 0x60, 0x11, 0x1f); /* BER scaling */ >> + >> + writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ >> + writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ >> +} >> + >> +static void BandSettingC2(struct cxd_state *state, u32 iffreq) >> +{ >> + u8 IF_data[3] = { (iffreq >> 16) & 0xff, >> + (iffreq >> 8) & 0xff, iffreq & 0xff}; >> + >> + switch (state->bw) { >> + default: >> + case 8: >> + { >> + u8 TR_data[] = { 0x11, 0xF0, 0x00, 0x00, 0x00 }; >> + u8 data[2] = { 0x11, 0x9E }; >> + >> + writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x00, 0x07); >> + writeregst(state, 0x50, 0xEC, data, sizeof(data)); >> + writeregt(state, 0x50, 0xEF, 0x11); >> + writeregt(state, 0x50, 0xF1, 0x9E); >> + } >> + break; >> + case 6: >> + { >> + u8 TR_data[] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA }; >> + u8 data[2] = { 0x17, 0x70 }; >> + >> + writeregst(state, 0x20, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writebitst(state, 0x10, 0xD7, 0x04, 0x07); >> + writeregst(state, 0x50, 0xEC, data, sizeof(data)); >> + writeregt(state, 0x50, 0xEF, 0x17); >> + writeregt(state, 0x50, 0xF1, 0x70); >> + } >> + break; >> + } >> +} >> + >> +static void Sleep_to_ActiveC2(struct cxd_state *state, u32 iffreq) >> +{ >> + ConfigureTS(state, ActiveC2); >> + >> + writeregx(state, 0x00, 0x17, 0x05); /* Mode */ >> + writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ >> + writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ >> + >> + { >> + u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz */ >> + /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ >> + writeregst(state, 0x00, 0x43, data, sizeof(data)); >> + /* Enable ADC 2+3 */ >> + } >> + writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ >> + >> + writebitst(state, 0x10, 0xD2, 0x0C, 0x1F); /* IFAGC coarse gain */ >> + writeregt(state, 0x11, 0x6A, 0x50); /* BB AGC Target Level */ >> + writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ >> + >> + writebitst(state, 0x00, 0xCE, 0x01, 0x01); /* TSIF ONOPARITY */ >> + writebitst(state, 0x00, 0xCF, 0x01, 0x01);/*TSIF ONOPARITY_MANUAL_ON*/ >> + >> + writeregt(state, 0x20, 0xC2, 0x00); >> + writebitst(state, 0x25, 0x6A, 0x00, 0x03); >> + { >> + u8 data[3] = { 0x0C, 0xD1, 0x40 }; >> + writeregst(state, 0x25, 0x89, data, sizeof(data)); >> + } >> + writebitst(state, 0x25, 0xCB, 0x01, 0x07); >> + { >> + u8 data[4] = { 0x7B, 0x00, 0x7B, 0x00 }; >> + writeregst(state, 0x25, 0xDC, data, sizeof(data)); >> + } >> + writeregt(state, 0x25, 0xE2, 0x30); >> + writeregt(state, 0x25, 0xE5, 0x30); >> + writebitst(state, 0x27, 0x20, 0x01, 0x01); >> + writebitst(state, 0x27, 0x35, 0x01, 0x01); >> + writebitst(state, 0x27, 0xD9, 0x18, 0x3F); >> + writebitst(state, 0x2A, 0x78, 0x00, 0x07); >> + writeregt(state, 0x2A, 0x86, 0x20); >> + writeregt(state, 0x2A, 0x88, 0x32); >> + writebitst(state, 0x2B, 0x2B, 0x10, 0x1F); >> + { >> + u8 data[2] = { 0x01, 0x01 }; >> + writeregst(state, 0x2D, 0x24, data, sizeof(data)); >> + } >> + >> + BandSettingC2(state, iffreq); >> + >> + writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ >> + writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ >> +} >> + >> + >> +static void BandSettingIT(struct cxd_state *state, u32 iffreq) >> +{ >> + u8 IF_data[3] = { (iffreq >> 16) & 0xff, >> + (iffreq >> 8) & 0xff, iffreq & 0xff}; >> + >> + switch (state->bw) { >> + default: >> + case 8: >> + { >> + u8 TR_data[] = { 0x0F, 0x22, 0x80, 0x00, 0x00 }; /* 20.5/41 */ >> + u8 CL_data[] = { 0x15, 0xA8 }; >> + >> + /*u8 TR_data[] = { 0x11, 0xB8, 0x00, 0x00, 0x00 }; */ /* 24 */ >> + writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); >> + /* Add EQ Optimisation for tuner here */ >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + >> + writeregt(state, 0x10, 0xD7, 0x00); /* System Bandwidth */ >> + /*u8 CL_data[] = { 0x13, 0xFC }; */ >> + writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); >> + } >> + break; >> + case 7: >> + { >> + u8 TR_data[] = { 0x11, 0x4c, 0x00, 0x00, 0x00 }; >> + u8 CL_data[] = { 0x1B, 0x5D }; >> + >> + /*u8 TR_data[] = { 0x14, 0x40, 0x00, 0x00, 0x00 }; */ >> + writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + >> + writeregt(state, 0x10, 0xD7, 0x02); >> + /*static u8 CL_data[] = { 0x1A, 0xFA };*/ >> + writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); >> + } >> + break; >> + case 6: >> + { >> + u8 TR_data[] = { 0x14, 0x2E, 0x00, 0x00, 0x00 }; >> + u8 CL_data[] = { 0x1F, 0xEC }; >> + /*u8 TR_data[] = { 0x17, 0xA0, 0x00, 0x00, 0x00 }; */ >> + /*u8 CL_data[] = { 0x1F, 0x79 }; */ >> + >> + writeregst(state, 0x10, 0x9F, TR_data, sizeof(TR_data)); >> + writeregst(state, 0x10, 0xB6, IF_data, sizeof(IF_data)); >> + writeregt(state, 0x10, 0xD7, 0x04); >> + writeregst(state, 0x10, 0xD9, CL_data, sizeof(CL_data)); >> + } >> + break; >> + } >> +} >> + >> +static void Sleep_to_ActiveIT(struct cxd_state *state, u32 iffreq) >> +{ >> + u8 data2[3] = { 0xB9, 0xBA, 0x63 }; /* 20.5/41 MHz */ >> + /*u8 data2[3] = { 0xB7,0x1B,0x00 }; */ /* 24 MHz */ >> + u8 TSIF_data[2] = { 0x61, 0x60 } ; /* 20.5/41 MHz */ >> + /*u8 TSIF_data[2] = { 0x60,0x00 } ; */ /* 24 MHz */ >> + >> + pr_info("%s\n", __func__); >> + >> + ConfigureTS(state, ActiveIT); >> + >> + /* writeregx(state, 0x00,0x17,0x01); */ /* 2838 has only one Mode */ >> + writeregt(state, 0x00, 0x2C, 0x01); /* Demod Clock */ >> + writeregt(state, 0x00, 0x2F, 0x00); /* Disable RF Monitor */ >> + writeregt(state, 0x00, 0x30, 0x00); /* Enable ADC Clock */ >> + writeregt(state, 0x00, 0x41, 0x1A); /* Enable ADC1 */ >> + >> + { >> + u8 data[2] = { 0x09, 0x54 }; /* 20.5 MHz, 24 MHz */ >> + /*u8 data[2] = { 0x0A, 0xD4 }; */ /* 41 MHz */ >> + writeregst(state, 0x00, 0x43, data, 2); /* Enable ADC 2+3 */ >> + } >> + writeregx(state, 0x00, 0x18, 0x00); /* Enable ADC 4 */ >> + >> + writeregst(state, 0x60, 0xA8, data2, sizeof(data2)); >> + >> + writeregst(state, 0x10, 0xBF, TSIF_data, sizeof(TSIF_data)); >> + >> + writeregt(state, 0x10, 0xE2, 0xCE); /* OREG_PNC_DISABLE */ >> + writebitst(state, 0x10, 0xA5, 0x00, 0x01); /* ASCOT Off */ >> + >> + BandSettingIT(state, iffreq); >> + >> + writeregt(state, 0x00, 0x80, 0x28); /* Disable HiZ Setting 1 */ >> + writeregt(state, 0x00, 0x81, 0x00); /* Disable HiZ Setting 2 */ >> +} >> + >> +static void T2_SetParameters(struct cxd_state *state) >> +{ >> + u8 Profile = 0x01; /* Profile Base */ >> + u8 notT2time = 12; /* early unlock detection time */ >> + >> + if (state->T2Profile == T2P_Lite) { >> + Profile = 0x05; >> + notT2time = 40; >> + } >> + >> + if (state->plp != 0xffffffff) { >> + state->T2Profile = ((state->plp & 0x100) != 0) ? >> + T2P_Lite : T2P_Base; >> + writeregt(state, 0x23, 0xAF, state->plp); >> + writeregt(state, 0x23, 0xAD, 0x01); >> + } else { >> + state->T2Profile = T2P_Base; >> + writeregt(state, 0x23, 0xAD, 0x00); >> + } >> + >> + writebitst(state, 0x2E, 0x10, Profile, 0x07); >> + writeregt(state, 0x2B, 0x19, notT2time); >> +} >> + >> +static void C2_ReleasePreset(struct cxd_state *state) >> +{ >> + { >> + static u8 data[2] = { 0x02, 0x80}; >> + writeregst(state, 0x27, 0xF4, data, sizeof(data)); >> + } >> + writebitst(state, 0x27, 0x51, 0x40, 0xF0); >> + writebitst(state, 0x27, 0x73, 0x07, 0x0F); >> + writebitst(state, 0x27, 0x74, 0x19, 0x3F); >> + writebitst(state, 0x27, 0x75, 0x19, 0x3F); >> + writebitst(state, 0x27, 0x76, 0x19, 0x3F); >> + if (state->bw == 6) { >> + static u8 data[5] = { 0x17, 0xEA, 0xAA, 0xAA, 0xAA}; >> + writeregst(state, 0x20, 0x9F, data, sizeof(data)); >> + } else { >> + static u8 data[5] = { 0x11, 0xF0, 0x00, 0x00, 0x00}; >> + writeregst(state, 0x20, 0x9F, data, sizeof(data)); >> + } >> + writebitst(state, 0x27, 0xC9, 0x07, 0x07); >> + writebitst(state, 0x20, 0xC2, 0x11, 0x33); >> + { >> + static u8 data[10] = { 0x16, 0xF0, 0x2B, 0xD8, >> + 0x16, 0x16, 0xF0, 0x2C, 0xD8, 0x16 }; >> + writeregst(state, 0x2A, 0x20, data, sizeof(data)); >> + } >> + { >> + static u8 data[4] = { 0x00, 0x00, 0x00, 0x00 }; >> + writeregst(state, 0x50, 0x6B, data, sizeof(data)); >> + } >> + writebitst(state, 0x50, 0x6F, 0x00, 0x40); /* Disable Preset */ >> +} >> + >> +static void C2_DemodSetting2(struct cxd_state *state) >> +{ >> + u8 data[6]; >> + u32 TunePosition = >> + state->frontend.dtv_property_cache.frequency / 1000; >> + >> + if (state->bw == 6) >> + TunePosition = ((TunePosition * 1792) / 3) / 1000; >> + else >> + TunePosition = (TunePosition * 448) / 1000; >> + >> + TunePosition = ((TunePosition + 6) / 12) * 12; >> + >> + pr_info("TunePosition = %u\n", TunePosition); >> + >> + data[0] = ((TunePosition >> 16) & 0xFF); >> + data[1] = ((TunePosition >> 8) & 0xFF); >> + data[2] = (TunePosition & 0xFF); >> + data[3] = 0x02; >> + data[4] = (state->DataSliceID & 0xFF); >> + data[5] = (state->plp & 0xFF); >> + writeregst(state, 0x50, 0x7A, data, sizeof(data)); >> + writebitst(state, 0x50, 0x87, 0x01, 0x01); /* Preset Clear */ >> +} >> + >> +static void Stop(struct cxd_state *state) >> +{ >> + >> + writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS */ >> +} >> + >> +static void ShutDown(struct cxd_state *state) >> +{ >> + switch (state->state) { >> + case ActiveT2: >> + ActiveT2_to_Sleep(state); >> + break; >> + case ActiveC2: >> + ActiveC2_to_Sleep(state); >> + break; >> + default: >> + Active_to_Sleep(state); >> + break; >> + } >> +} >> + >> +static int gate_ctrl(struct dvb_frontend *fe, int enable) >> +{ >> + struct cxd_state *state = fe->demodulator_priv; >> + >> + return writebitsx(state, 0xFF, 0x08, enable ? 0x01 : 0x00, 0x01); >> +} >> + >> +static void release(struct dvb_frontend *fe) >> +{ >> + struct cxd_state *state = fe->demodulator_priv; >> + >> + Stop(state); >> + ShutDown(state); >> + kfree(state); >> +} >> + >> +static int Start(struct cxd_state *state, u32 IntermediateFrequency) >> +{ >> + enum EDemodState newDemodState = Unknown; >> + u32 iffreq; >> + >> + if (state->state < Sleep) >> + return -EINVAL; >> + >> + iffreq = MulDiv32(IntermediateFrequency, 16777216, 41000000); >> + >> + switch (state->omode) { >> + case OM_DVBT: >> + if (state->type == CXD2838) >> + return -EINVAL; >> + newDemodState = ActiveT; >> + break; >> + case OM_DVBT2: >> + if (state->type == CXD2838) >> + return -EINVAL; >> + newDemodState = ActiveT2; >> + break; >> + case OM_DVBC: >> + case OM_QAM_ITU_C: >> + if (state->type == CXD2838) >> + return -EINVAL; >> + newDemodState = ActiveC; >> + break; >> + case OM_DVBC2: >> + if (state->type != CXD2843) >> + return -EINVAL; >> + newDemodState = ActiveC2; >> + break; >> + case OM_ISDBT: >> + if (state->type != CXD2838) >> + return -EINVAL; >> + newDemodState = ActiveIT; >> + break; >> + default: >> + return -EINVAL; >> + } >> + >> + state->LockTimeout = 0; >> + state->TSLockTimeout = 0; >> + state->L1PostTimeout = 0; >> + state->last_status = 0; >> + state->FirstTimeLock = 1; >> + state->LastBERNominator = 0; >> + state->LastBERDenominator = 1; >> + state->BERScaleMax = 19; >> + >> + if (state->state == newDemodState) { >> + writeregt(state, 0x00, 0xC3, 0x01); /* Disable TS Output */ >> + switch (newDemodState) { >> + case ActiveT: >> + /* Stick with HP ( 0x01 = LP ) */ >> + writeregt(state, 0x10, 0x67, 0x00); >> + BandSettingT(state, iffreq); >> + state->BERScaleMax = 18; >> + break; >> + case ActiveT2: >> + T2_SetParameters(state); >> + BandSettingT2(state, iffreq); >> + state->BERScaleMax = 12; >> + break; >> + case ActiveC: >> + BandSettingC(state, iffreq); >> + state->BERScaleMax = 19; >> + break; >> + case ActiveC2: >> + BandSettingC2(state, iffreq); >> + C2_ReleasePreset(state); >> + C2_DemodSetting2(state); >> + break; >> + case ActiveIT: >> + BandSettingIT(state, iffreq); >> + break; >> + default: >> + break; >> + } >> + } else { >> + if (state->state > Sleep) { >> + switch (state->state) { >> + case ActiveT2: >> + ActiveT2_to_Sleep(state); >> + break; >> + case ActiveC2: >> + ActiveC2_to_Sleep(state); >> + break; >> + default: >> + Active_to_Sleep(state); >> + break; >> + } >> + } >> + switch (newDemodState) { >> + case ActiveT: >> + /* Stick with HP ( 0x01 = LP ) */ >> + writeregt(state, 0x10, 0x67, 0x00); >> + Sleep_to_ActiveT(state, iffreq); >> + state->BERScaleMax = 18; >> + break; >> + case ActiveT2: >> + T2_SetParameters(state); >> + Sleep_to_ActiveT2(state, iffreq); >> + state->BERScaleMax = 12; >> + break; >> + case ActiveC: >> + Sleep_to_ActiveC(state, iffreq); >> + state->BERScaleMax = 19; >> + break; >> + case ActiveC2: >> + Sleep_to_ActiveC2(state, iffreq); >> + C2_ReleasePreset(state); >> + C2_DemodSetting2(state); >> + break; >> + case ActiveIT: >> + Sleep_to_ActiveIT(state, iffreq); >> + break; >> + default: >> + break; >> + } >> + } >> + state->state = newDemodState; >> + writeregt(state, 0x00, 0xFE, 0x01); /* SW Reset */ >> + writeregt(state, 0x00, 0xC3, 0x00); /* Enable TS Output */ >> + >> + return 0; >> +} >> + >> +static int set_parameters(struct dvb_frontend *fe) >> +{ >> + int stat; >> + struct cxd_state *state = fe->demodulator_priv; >> + u32 IF; >> + >> + switch (fe->dtv_property_cache.delivery_system) { >> + case SYS_DVBC_ANNEX_A: >> + state->omode = OM_DVBC; >> + break; >> + case SYS_DVBC2: >> + state->omode = OM_DVBC2; >> + break; >> + case SYS_DVBT: >> + state->omode = OM_DVBT; >> + break; >> + case SYS_DVBT2: >> + state->omode = OM_DVBT2; >> + break; >> + case SYS_ISDBT: >> + state->omode = OM_ISDBT; >> + break; >> + default: >> + return -EINVAL; >> + } >> + if (fe->ops.tuner_ops.set_params) >> + fe->ops.tuner_ops.set_params(fe); >> + state->bandwidth = fe->dtv_property_cache.bandwidth_hz; >> + state->bw = (fe->dtv_property_cache.bandwidth_hz + 999999) / 1000000; >> + if (fe->dtv_property_cache.stream_id == 0xffffffff) { >> + state->DataSliceID = 0xffffffff; >> + state->plp = 0xffffffff; >> + } else { >> + state->DataSliceID = (fe->dtv_property_cache.stream_id >> 8) >> + & 0xff; >> + state->plp = fe->dtv_property_cache.stream_id & 0xff; >> + } >> + /* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */ >> + fe->ops.tuner_ops.get_if_frequency(fe, &IF); >> + stat = Start(state, IF); >> + return stat; >> +} >> + >> + >> +static void init(struct cxd_state *state) >> +{ >> + u8 data[2] = {0x00, 0x00}; /* 20.5 MHz */ >> + >> + state->omode = OM_NONE; >> + state->state = Unknown; >> + >> + writeregx(state, 0xFF, 0x02, 0x00); >> + usleep_range(4000, 5000); >> + writeregx(state, 0x00, 0x15, 0x01); >> + if (state->type != CXD2838) >> + writeregx(state, 0x00, 0x17, 0x01); >> + usleep_range(4000, 5000); >> + >> + writeregx(state, 0x00, 0x10, 0x01); >> + >> + writeregsx(state, 0x00, 0x13, data, 2); >> + writeregx(state, 0x00, 0x15, 0x00); >> + usleep_range(3000, 4000); >> + writeregx(state, 0x00, 0x10, 0x00); >> + usleep_range(2000, 3000); >> + >> + state->curbankx = 0xFF; >> + state->curbankt = 0xFF; >> + >> + writeregt(state, 0x00, 0x43, 0x0A); >> + writeregt(state, 0x00, 0x41, 0x0A); >> + if (state->type == CXD2838) >> + writeregt(state, 0x60, 0x5A, 0x00); >> + >> + writebitst(state, 0x10, 0xCB, 0x00, 0x40); >> + writeregt(state, 0x10, 0xCD, state->IF_FS); >> + >> + writebitst(state, 0x00, 0xC4, state->SerialMode ? 0x80 : 0x00, 0x98); >> + writebitst(state, 0x00, 0xC5, 0x01, 0x07); >> + writebitst(state, 0x00, 0xCB, 0x00, 0x01); >> + writebitst(state, 0x00, 0xC6, 0x00, 0x1D); >> + writebitst(state, 0x00, 0xC8, 0x01, 0x1D); >> + writebitst(state, 0x00, 0xC9, 0x00, 0x1D); >> + writebitst(state, 0x00, 0x83, 0x00, 0x07); >> + writeregt(state, 0x00, 0x84, 0x00); >> + writebitst(state, 0x00, 0xD3, >> + (state->type == CXD2838) ? 0x01 : 0x00, 0x01); >> + writebitst(state, 0x00, 0xDE, 0x00, 0x01); >> + >> + state->state = Sleep; >> +} >> + >> + >> +static void init_state(struct cxd_state *state, struct cxd2843_cfg *cfg) >> +{ >> + state->adrt = cfg->adr; >> + state->adrx = cfg->adr + 0x02; >> + state->curbankt = 0xff; >> + state->curbankx = 0xff; >> + mutex_init(&state->mutex); >> + >> + state->SerialMode = cfg->parallel ? 0 : 1; >> + state->ContinuousClock = 1; >> + state->SerialClockFrequency = >> + (cfg->ts_clock >= 1 && cfg->ts_clock <= 5) ? >> + cfg->ts_clock : 1; /* 1 = fastest (82 MBit/s), 5 = slowest */ >> + state->SerialClockFrequency = 1; >> + /* IF Fullscale 0x50 = 1.4V, 0x39 = 1V, 0x28 = 0.7V */ >> + state->IF_FS = 0x50; >> +} >> + >> +static int get_tune_settings(struct dvb_frontend *fe, >> + struct dvb_frontend_tune_settings *sets) >> +{ >> + switch (fe->dtv_property_cache.delivery_system) { >> + case SYS_DVBC_ANNEX_A: >> + case SYS_DVBC_ANNEX_C: >> + /*return c_get_tune_settings(fe, sets);*/ >> + default: >> + /* DVB-T: Use info.frequency_stepsize. */ >> + return -EINVAL; >> + } >> +} >> + >> +static int read_status(struct dvb_frontend *fe, fe_status_t *status) >> +{ >> + struct cxd_state *state = fe->demodulator_priv; >> + u8 rdata; >> + >> + *status = 0; >> + switch (state->state) { >> + case ActiveC: >> + readregst(state, 0x40, 0x88, &rdata, 1); >> + if (rdata & 0x02) >> + break; >> + if (rdata & 0x01) { >> + *status |= 0x07; >> + readregst(state, 0x40, 0x10, &rdata, 1); >> + if (rdata & 0x20) >> + *status |= 0x1f; >> + } >> + break; >> + case ActiveT: >> + readregst(state, 0x10, 0x10, &rdata, 1); >> + if (rdata & 0x10) >> + break; >> + if ((rdata & 0x07) == 0x06) { >> + *status |= 0x07; >> + if (rdata & 0x20) >> + *status |= 0x1f; >> + } >> + break; >> + case ActiveT2: >> + readregst(state, 0x20, 0x10, &rdata, 1); >> + if (rdata & 0x10) >> + break; >> + if ((rdata & 0x07) == 0x06) { >> + *status |= 0x07; >> + if (rdata & 0x20) >> + *status |= 0x08; >> + } >> + if (*status & 0x08) { >> + readregst(state, 0x22, 0x12, &rdata, 1); >> + if (rdata & 0x01) >> + *status |= 0x10; >> + } >> + break; >> + case ActiveC2: >> + readregst(state, 0x20, 0x10, &rdata, 1); >> + if (rdata & 0x10) >> + break; >> + if ((rdata & 0x07) == 0x06) { >> + *status |= 0x07; >> + if (rdata & 0x20) >> + *status |= 0x18; >> + } >> + if ((*status & 0x10) && state->FirstTimeLock) { >> + u8 data; >> + >> + /* Change1stTrial */ >> + readregst(state, 0x28, 0xE6, &rdata, 1); >> + data = rdata & 1; >> + readregst(state, 0x50, 0x15, &rdata, 1); >> + data |= ((rdata & 0x18) >> 2); >> + /*writebitst(state, 0x50,0x6F,rdata,0x07);*/ >> + state->FirstTimeLock = 0; >> + } >> + break; >> + case ActiveIT: >> + readregst(state, 0x60, 0x10, &rdata, 1); >> + if (rdata & 0x10) >> + break; >> + if (rdata & 0x02) { >> + *status |= 0x07; >> + if (rdata & 0x01) >> + *status |= 0x18; >> + } >> + break; >> + default: >> + break; >> + } >> + state->last_status = *status; >> + return 0; >> +} >> + >> +static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d) >> +{ >> + u8 BERRegs[3]; >> + u8 Scale; >> + >> + *n = 0; >> + *d = 1; >> + >> + readregst(state, 0x10, 0x62, BERRegs, 3); >> + readregst(state, 0x10, 0x60, &Scale, 1); >> + Scale &= 0x1F; >> + >> + if (BERRegs[0] & 0x80) { >> + state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | >> + (((u32) BERRegs[1]) << 8) | BERRegs[2]; >> + state->LastBERDenominator = 1632 << Scale; >> + if (state->LastBERNominator < 256 && >> + Scale < state->BERScaleMax) { >> + writebitst(state, 0x10, 0x60, Scale + 1, 0x1F); >> + } else if (state->LastBERNominator > 512 && Scale > 11) >> + writebitst(state, 0x10, 0x60, Scale - 1, 0x1F); >> + } >> + *n = state->LastBERNominator; >> + *d = state->LastBERDenominator; >> + >> + return 0; >> +} >> + >> +static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d) >> +{ >> + *n = 0; >> + *d = 1; >> + return 0; >> +} >> + >> +static int get_ber_c(struct cxd_state *state, u32 *n, u32 *d) >> +{ >> + u8 BERRegs[3]; >> + u8 Scale; >> + >> + *n = 0; >> + *d = 1; >> + >> + readregst(state, 0x40, 0x62, BERRegs, 3); >> + readregst(state, 0x40, 0x60, &Scale, 1); >> + Scale &= 0x1F; >> + >> + if (BERRegs[0] & 0x80) { >> + state->LastBERNominator = (((u32) BERRegs[0] & 0x3F) << 16) | >> + (((u32) BERRegs[1]) << 8) | BERRegs[2]; >> + state->LastBERDenominator = 1632 << Scale; >> + if (state->LastBERNominator < 256 && >> + Scale < state->BERScaleMax) { >> + writebitst(state, 0x40, 0x60, Scale + 1, 0x1F); >> + } else if (state->LastBERNominator > 512 && Scale > 11) >> + writebitst(state, 0x40, 0x60, Scale - 1, 0x1F); >> + } >> + *n = state->LastBERNominator; >> + *d = state->LastBERDenominator; >> + >> + return 0; >> +} >> + >> +static int get_ber_c2(struct cxd_state *state, u32 *n, u32 *d) >> +{ >> + *n = 0; >> + *d = 1; >> + return 0; >> +} >> + >> +static int get_ber_it(struct cxd_state *state, u32 *n, u32 *d) >> +{ >> + *n = 0; >> + *d = 1; >> + return 0; >> +} >> + >> +static int read_ber(struct dvb_frontend *fe, u32 *ber) >> +{ >> + struct cxd_state *state = fe->demodulator_priv; >> + u32 n, d; >> + int s = 0; >> + >> + *ber = 0; >> + switch (state->state) { >> + case ActiveT: >> + s = get_ber_t(state, &n, &d); >> + break; >> + case ActiveT2: >> + s = get_ber_t2(state, &n, &d); >> + break; >> + case ActiveC: >> + s = get_ber_c(state, &n, &d); >> + break; >> + case ActiveC2: >> + s = get_ber_c2(state, &n, &d); >> + break; >> + case ActiveIT: >> + s = get_ber_it(state, &n, &d); >> + break; >> + default: >> + break; >> + } >> + if (s) >> + return s; >> + >> + return 0; >> +} >> + >> +static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) >> +{ >> + if (fe->ops.tuner_ops.get_rf_strength) >> + fe->ops.tuner_ops.get_rf_strength(fe, strength); >> + else >> + *strength = 0; >> + return 0; >> +} >> + >> +static s32 Log10x100(u32 x) >> +{ >> + static u32 LookupTable[100] = { >> + 101157945, 103514217, 105925373, 108392691, 110917482, >> + 113501082, 116144861, 118850223, 121618600, 124451461, >> + 127350308, 130316678, 133352143, 136458314, 139636836, >> + 142889396, 146217717, 149623566, 153108746, 156675107, >> + 160324539, 164058977, 167880402, 171790839, 175792361, >> + 179887092, 184077200, 188364909, 192752491, 197242274, >> + 201836636, 206538016, 211348904, 216271852, 221309471, >> + 226464431, 231739465, 237137371, 242661010, 248313311, >> + 254097271, 260015956, 266072506, 272270131, 278612117, >> + 285101827, 291742701, 298538262, 305492111, 312607937, >> + 319889511, 327340695, 334965439, 342767787, 350751874, >> + 358921935, 367282300, 375837404, 384591782, 393550075, >> + 402717034, 412097519, 421696503, 431519077, 441570447, >> + 451855944, 462381021, 473151259, 484172368, 495450191, >> + 506990708, 518800039, 530884444, 543250331, 555904257, >> + 568852931, 582103218, 595662144, 609536897, 623734835, >> + 638263486, 653130553, 668343918, 683911647, 699841996, >> + 716143410, 732824533, 749894209, 767361489, 785235635, >> + 803526122, 822242650, 841395142, 860993752, 881048873, >> + 901571138, 922571427, 944060876, 966050879, 988553095, >> + }; >> + s32 y; >> + int i; >> + >> + if (x == 0) >> + return 0; >> + y = 800; >> + if (x >= 1000000000) { >> + x /= 10; >> + y += 100; >> + } >> + >> + while (x < 100000000) { >> + x *= 10; >> + y -= 100; >> + } >> + i = 0; >> + while (i < 100 && x > LookupTable[i]) >> + i += 1; >> + y += i; >> + return y; >> +} >> + >> +#if 0 >> +static void GetPLPIds(struct cxd_state *state, u32 nValues, >> + u8 *Values, u32 *Returned) >> +{ >> + u8 nPids = 0; >> + >> + *Returned = 0; >> + if (state->state != ActiveT2) >> + return; >> + if (state->last_status != 0x1f) >> + return; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x22, 0x7F, &nPids, 1); >> + >> + Values[0] = nPids; >> + if (nPids >= nValues) >> + nPids = nValues - 1; >> + >> + readregst_unlocked(state, 0x22, 0x80, &Values[1], >> + nPids > 128 ? 128 : nPids); >> + >> + if (nPids > 128) >> + readregst_unlocked(state, 0x23, 0x10, &Values[129], >> + nPids - 128); >> + >> + *Returned = nPids + 1; >> + >> + unfreeze_regst(state); >> +} >> +#endif >> + >> +static void GetSignalToNoiseIT(struct cxd_state *state, u32 *SignalToNoise) >> +{ >> + u8 Data[2]; >> + u32 reg; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x60, 0x28, Data, sizeof(Data)); >> + unfreeze_regst(state); >> + >> + reg = (Data[0] << 8) | Data[1]; >> + if (reg > 51441) >> + reg = 51441; >> + >> + if (state->bw == 8) { >> + if (reg > 1143) >> + reg = 1143; >> + *SignalToNoise = (Log10x100(reg) - >> + Log10x100(1200 - reg)) + 220; >> + } else >> + *SignalToNoise = Log10x100(reg) - 90; >> +} >> + >> +static void GetSignalToNoiseC2(struct cxd_state *state, u32 *SignalToNoise) >> +{ >> + u8 Data[2]; >> + u32 reg; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); >> + unfreeze_regst(state); >> + >> + reg = (Data[0] << 8) | Data[1]; >> + if (reg > 51441) >> + reg = 51441; >> + >> + *SignalToNoise = (Log10x100(reg) - Log10x100(55000 - reg)) + 384; >> +} >> + >> + >> +static void GetSignalToNoiseT2(struct cxd_state *state, u32 *SignalToNoise) >> +{ >> + u8 Data[2]; >> + u32 reg; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x20, 0x28, Data, sizeof(Data)); >> + unfreeze_regst(state); >> + >> + reg = (Data[0] << 8) | Data[1]; >> + if (reg > 10876) >> + reg = 10876; >> + >> + *SignalToNoise = (Log10x100(reg) - Log10x100(12600 - reg)) + 320; >> +} >> + >> +static void GetSignalToNoiseT(struct cxd_state *state, u32 *SignalToNoise) >> +{ >> + u8 Data[2]; >> + u32 reg; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x10, 0x28, Data, sizeof(Data)); >> + unfreeze_regst(state); >> + >> + reg = (Data[0] << 8) | Data[1]; >> + if (reg > 4996) >> + reg = 4996; >> + >> + *SignalToNoise = (Log10x100(reg) - Log10x100(5350 - reg)) + 285; >> +} >> + >> +static void GetSignalToNoiseC(struct cxd_state *state, u32 *SignalToNoise) >> +{ >> + u8 Data[2]; >> + u8 Constellation = 0; >> + u32 reg; >> + >> + *SignalToNoise = 0; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x40, 0x19, &Constellation, 1); >> + readregst_unlocked(state, 0x40, 0x4C, Data, sizeof(Data)); >> + unfreeze_regst(state); >> + >> + reg = ((u32)(Data[0] & 0x1F) << 8) | (Data[1]); >> + if (reg == 0) >> + return; >> + >> + switch (Constellation & 0x07) { >> + case 0: /* QAM 16 */ >> + case 2: /* QAM 64 */ >> + case 4: /* QAM 256 */ >> + if (reg < 126) >> + reg = 126; >> + *SignalToNoise = ((439 - Log10x100(reg)) * 2134 + 500) / 1000; >> + break; >> + case 1: /* QAM 32 */ >> + case 3: /* QAM 128 */ >> + if (reg < 69) >> + reg = 69; >> + *SignalToNoise = ((432 - Log10x100(reg)) * 2015 + 500) / 1000; >> + break; >> + } >> +} >> + >> +static int read_snr(struct dvb_frontend *fe, u16 *snr) >> +{ >> + struct cxd_state *state = fe->demodulator_priv; >> + u32 SNR = 0; >> + >> + *snr = 0; >> + if (state->last_status != 0x1f) >> + return 0; >> + >> + switch (state->state) { >> + case ActiveC: >> + GetSignalToNoiseC(state, &SNR); >> + break; >> + case ActiveC2: >> + GetSignalToNoiseC2(state, &SNR); >> + break; >> + case ActiveT: >> + GetSignalToNoiseT(state, &SNR); >> + break; >> + case ActiveT2: >> + GetSignalToNoiseT2(state, &SNR); >> + break; >> + case ActiveIT: >> + GetSignalToNoiseIT(state, &SNR); >> + break; >> + default: >> + break; >> + } >> + *snr = SNR; >> + return 0; >> +} >> + >> +static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) >> +{ >> + *ucblocks = 0; >> + return 0; >> +} >> + >> +static int tune(struct dvb_frontend *fe, bool re_tune, >> + unsigned int mode_flags, >> + unsigned int *delay, fe_status_t *status) >> +{ >> + struct cxd_state *state = fe->demodulator_priv; >> + int r; >> + >> + if (re_tune) { >> + r = set_parameters(fe); >> + if (r) >> + return r; >> + state->tune_time = jiffies; >> + >> + } >> + if (*status & FE_HAS_LOCK) >> + return 0; >> + /* *delay = 50; */ >> + r = read_status(fe, status); >> + if (r) >> + return r; >> + return 0; >> +} >> + >> +static enum dvbfe_search search(struct dvb_frontend *fe) >> +{ >> + int r; >> + u32 loops = 20, i; >> + fe_status_t status; >> + >> + r = set_parameters(fe); >> + >> + for (i = 0; i < loops; i++) { >> + msleep(50); >> + r = read_status(fe, &status); >> + if (r) >> + return DVBFE_ALGO_SEARCH_ERROR; >> + if (status & FE_HAS_LOCK) >> + break; >> + } >> + >> + if (status & FE_HAS_LOCK) >> + return DVBFE_ALGO_SEARCH_SUCCESS; >> + else >> + return DVBFE_ALGO_SEARCH_AGAIN; >> +} >> + >> +static int get_algo(struct dvb_frontend *fe) >> +{ >> + return DVBFE_ALGO_HW; >> +} >> + >> +static int get_fe_t(struct cxd_state *state) >> +{ >> + struct dvb_frontend *fe = &state->frontend; >> + struct dtv_frontend_properties *p = &fe->dtv_property_cache; >> + u8 tps[7]; >> + >> + read_tps(state, tps); >> + >> +/* TPSData[0] [7:6] CNST[1:0] >> + TPSData[0] [5:3] HIER[2:0] >> + TPSData[0] [2:0] HRATE[2:0] >> +*/ >> + switch ((tps[0] >> 6) & 0x03) { >> + case 0: >> + p->modulation = QPSK; >> + break; >> + case 1: >> + p->modulation = QAM_16; >> + break; >> + case 2: >> + p->modulation = QAM_64; >> + break; >> + } >> + switch ((tps[0] >> 3) & 0x07) { >> + case 0: >> + p->hierarchy = HIERARCHY_NONE; >> + break; >> + case 1: >> + p->hierarchy = HIERARCHY_1; >> + break; >> + case 2: >> + p->hierarchy = HIERARCHY_2; >> + break; >> + case 3: >> + p->hierarchy = HIERARCHY_4; >> + break; >> + } >> + switch ((tps[0] >> 0) & 0x07) { >> + case 0: >> + p->code_rate_HP = FEC_1_2; >> + break; >> + case 1: >> + p->code_rate_HP = FEC_2_3; >> + break; >> + case 2: >> + p->code_rate_HP = FEC_3_4; >> + break; >> + case 3: >> + p->code_rate_HP = FEC_5_6; >> + break; >> + case 4: >> + p->code_rate_HP = FEC_7_8; >> + break; >> + } >> + >> +/* TPSData[1] [7:5] LRATE[2:0] >> + TPSData[1] [4:3] GI[1:0] >> + TPSData[1] [2:1] MODE[1:0] >> +*/ >> + switch ((tps[1] >> 5) & 0x07) { >> + case 0: >> + p->code_rate_LP = FEC_1_2; >> + break; >> + case 1: >> + p->code_rate_LP = FEC_2_3; >> + break; >> + case 2: >> + p->code_rate_LP = FEC_3_4; >> + break; >> + case 3: >> + p->code_rate_LP = FEC_5_6; >> + break; >> + case 4: >> + p->code_rate_LP = FEC_7_8; >> + break; >> + } >> + switch ((tps[1] >> 3) & 0x03) { >> + case 0: >> + p->guard_interval = GUARD_INTERVAL_1_32; >> + break; >> + case 1: >> + p->guard_interval = GUARD_INTERVAL_1_16; >> + break; >> + case 2: >> + p->guard_interval = GUARD_INTERVAL_1_8; >> + break; >> + case 3: >> + p->guard_interval = GUARD_INTERVAL_1_4; >> + break; >> + } >> + switch ((tps[1] >> 1) & 0x03) { >> + case 0: >> + p->transmission_mode = TRANSMISSION_MODE_2K; >> + break; >> + case 1: >> + p->transmission_mode = TRANSMISSION_MODE_8K; >> + break; >> + } >> + >> + return 0; >> +} >> + >> +static int get_fe_c(struct cxd_state *state) >> +{ >> + struct dvb_frontend *fe = &state->frontend; >> + struct dtv_frontend_properties *p = &fe->dtv_property_cache; >> + u8 qam; >> + >> + freeze_regst(state); >> + readregst_unlocked(state, 0x40, 0x19, &qam, 1); >> + unfreeze_regst(state); >> + p->modulation = qam & 0x07; >> + return 0; >> +} >> + >> +static int get_frontend(struct dvb_frontend *fe) >> +{ >> + struct cxd_state *state = fe->demodulator_priv; >> + >> + if (state->last_status != 0x1f) >> + return 0; >> + >> + switch (state->state) { >> + case ActiveT: >> + get_fe_t(state); >> + break; >> + case ActiveT2: >> + break; >> + case ActiveC: >> + get_fe_c(state); >> + break; >> + case ActiveC2: >> + break; >> + case ActiveIT: >> + break; >> + default: >> + break; >> + } >> + return 0; >> +} >> + >> +static struct dvb_frontend_ops common_ops_2843 = { >> + .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 }, >> + .info = { >> + .name = "CXD2843 DVB-C/C2 DVB-T/T2", >> + .frequency_stepsize = 166667, /* DVB-T only */ >> + .frequency_min = 47000000, /* DVB-T: 47125000 */ >> + .frequency_max = 865000000, /* DVB-C: 862000000 */ >> + .symbol_rate_min = 870000, >> + .symbol_rate_max = 11700000, >> + .caps = /* DVB-C */ >> + FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | >> + FE_CAN_QAM_128 | FE_CAN_QAM_256 | >> + FE_CAN_FEC_AUTO | >> + /* DVB-T */ >> + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | >> + 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_TRANSMISSION_MODE_AUTO | >> + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | >> + FE_CAN_RECOVER | FE_CAN_MUTE_TS >> + }, >> + .release = release, >> + .i2c_gate_ctrl = gate_ctrl, >> + .set_frontend = set_parameters, >> + >> + .get_tune_settings = get_tune_settings, >> + .read_status = read_status, >> + .read_ber = read_ber, >> + .read_signal_strength = read_signal_strength, >> + .read_snr = read_snr, >> + .read_ucblocks = read_ucblocks, >> + .get_frontend = get_frontend, >> +#ifdef USE_ALGO >> + .get_frontend_algo = get_algo, >> + .search = search, >> + .tune = tune, >> +#endif >> +}; >> + >> +static struct dvb_frontend_ops common_ops_2837 = { >> + .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 }, >> + .info = { >> + .name = "CXD2837 DVB-C DVB-T/T2", >> + .frequency_stepsize = 166667, /* DVB-T only */ >> + .frequency_min = 47000000, /* DVB-T: 47125000 */ >> + .frequency_max = 865000000, /* DVB-C: 862000000 */ >> + .symbol_rate_min = 870000, >> + .symbol_rate_max = 11700000, >> + .caps = /* DVB-C */ >> + FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | >> + FE_CAN_QAM_128 | FE_CAN_QAM_256 | >> + FE_CAN_FEC_AUTO | >> + /* DVB-T */ >> + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | >> + 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_TRANSMISSION_MODE_AUTO | >> + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | >> + FE_CAN_RECOVER | FE_CAN_MUTE_TS >> + }, >> + .release = release, >> + .i2c_gate_ctrl = gate_ctrl, >> + .set_frontend = set_parameters, >> + >> + .get_tune_settings = get_tune_settings, >> + .read_status = read_status, >> + .read_ber = read_ber, >> + .read_signal_strength = read_signal_strength, >> + .read_snr = read_snr, >> + .read_ucblocks = read_ucblocks, >> + .get_frontend = get_frontend, >> +#ifdef USE_ALGO >> + .get_frontend_algo = get_algo, >> + .search = search, >> + .tune = tune, >> +#endif >> +}; >> + >> +static struct dvb_frontend_ops common_ops_2838 = { >> + .delsys = { SYS_ISDBT }, >> + .info = { >> + .name = "CXD2838 ISDB-T", >> + .frequency_stepsize = 166667, >> + .frequency_min = 47000000, >> + .frequency_max = 865000000, >> + .symbol_rate_min = 870000, >> + .symbol_rate_max = 11700000, >> + .caps = FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | >> + 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_TRANSMISSION_MODE_AUTO | >> + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | >> + FE_CAN_RECOVER | FE_CAN_MUTE_TS >> + }, >> + .release = release, >> + .i2c_gate_ctrl = gate_ctrl, >> + .set_frontend = set_parameters, >> + >> + .get_tune_settings = get_tune_settings, >> + .read_status = read_status, >> + .read_ber = read_ber, >> + .read_signal_strength = read_signal_strength, >> + .read_snr = read_snr, >> + .read_ucblocks = read_ucblocks, >> +#ifdef USE_ALGO >> + .get_frontend_algo = get_algo, >> + .search = search, >> + .tune = tune, >> +#endif >> +}; >> + >> +static int probe(struct cxd_state *state) >> +{ >> + u8 ChipID = 0x00; >> + int status; >> + >> + status = readregst(state, 0x00, 0xFD, &ChipID, 1); >> + >> + if (status) >> + status = readregsx(state, 0x00, 0xFD, &ChipID, 1); >> + if (status) >> + return status; >> + >> + /*printk("ChipID = %02X\n", ChipID);*/ >> + switch (ChipID) { >> + case 0xa4: >> + state->type = CXD2843; >> + memcpy(&state->frontend.ops, &common_ops_2843, >> + sizeof(struct dvb_frontend_ops)); >> + break; >> + case 0xb1: >> + state->type = CXD2837; >> + memcpy(&state->frontend.ops, &common_ops_2837, >> + sizeof(struct dvb_frontend_ops)); >> + break; >> + case 0xb0: >> + state->type = CXD2838; >> + memcpy(&state->frontend.ops, &common_ops_2838, >> + sizeof(struct dvb_frontend_ops)); >> + break; >> + default: >> + return -1; >> + } >> + state->frontend.demodulator_priv = state; >> + return 0; >> +} >> + >> +struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, >> + struct cxd2843_cfg *cfg) >> +{ >> + struct cxd_state *state = NULL; >> + >> + state = kzalloc(sizeof(struct cxd_state), GFP_KERNEL); >> + if (!state) >> + return NULL; >> + >> + state->i2c = i2c; >> + init_state(state, cfg); >> + if (probe(state) == 0) { >> + init(state); >> + return &state->frontend; >> + } >> + pr_err("cxd2843: not found\n"); >> + kfree(state); >> + return NULL; >> +} >> +EXPORT_SYMBOL(cxd2843_attach); >> + >> +MODULE_DESCRIPTION("CXD2843/37/38 driver"); >> +MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); >> +MODULE_LICENSE("GPL"); >> diff --git a/drivers/media/dvb-frontends/cxd2843.h b/drivers/media/dvb-frontends/cxd2843.h >> new file mode 100644 >> index 0000000..f3e355b >> --- /dev/null >> +++ b/drivers/media/dvb-frontends/cxd2843.h >> @@ -0,0 +1,30 @@ >> +#ifndef _CXD2843_H_ >> +#define _CXD2843_H_ >> + >> +#include >> +#include >> + >> +struct cxd2843_cfg { >> + u8 adr; >> + u32 ts_clock; >> + u8 parallel; >> +}; >> + >> +#if defined(CONFIG_DVB_CXD2843) || \ >> + (defined(CONFIG_DVB_CXD2843_MODULE) && defined(MODULE)) >> + >> +extern struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, >> + struct cxd2843_cfg *cfg); >> + >> +#else >> + >> +static inline struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c, >> + struct cxd2843_cfg *cfg) >> +{ >> + pr_warn("%s: driver disabled by Kconfig\n", __func__); >> + return NULL; >> +} >> + >> +#endif >> + >> +#endif -- http://palosaari.fi/