Path: blob/master/drivers/media/dvb/frontends/cxd2820r_core.c
15112 views
/*1* Sony CXD2820R demodulator driver2*3* Copyright (C) 2010 Antti Palosaari <[email protected]>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License along16* with this program; if not, write to the Free Software Foundation, Inc.,17* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.18*/192021#include "cxd2820r_priv.h"2223int cxd2820r_debug;24module_param_named(debug, cxd2820r_debug, int, 0644);25MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");2627/* write multiple registers */28static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,29u8 *val, int len)30{31int ret;32u8 buf[len+1];33struct i2c_msg msg[1] = {34{35.addr = i2c,36.flags = 0,37.len = sizeof(buf),38.buf = buf,39}40};4142buf[0] = reg;43memcpy(&buf[1], val, len);4445ret = i2c_transfer(priv->i2c, msg, 1);46if (ret == 1) {47ret = 0;48} else {49warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);50ret = -EREMOTEIO;51}52return ret;53}5455/* read multiple registers */56static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,57u8 *val, int len)58{59int ret;60u8 buf[len];61struct i2c_msg msg[2] = {62{63.addr = i2c,64.flags = 0,65.len = 1,66.buf = ®,67}, {68.addr = i2c,69.flags = I2C_M_RD,70.len = sizeof(buf),71.buf = buf,72}73};7475ret = i2c_transfer(priv->i2c, msg, 2);76if (ret == 2) {77memcpy(val, buf, len);78ret = 0;79} else {80warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);81ret = -EREMOTEIO;82}8384return ret;85}8687/* write multiple registers */88int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,89int len)90{91int ret;92u8 i2c_addr;93u8 reg = (reginfo >> 0) & 0xff;94u8 bank = (reginfo >> 8) & 0xff;95u8 i2c = (reginfo >> 16) & 0x01;9697/* select I2C */98if (i2c)99i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */100else101i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */102103/* switch bank if needed */104if (bank != priv->bank[i2c]) {105ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);106if (ret)107return ret;108priv->bank[i2c] = bank;109}110return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len);111}112113/* read multiple registers */114int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,115int len)116{117int ret;118u8 i2c_addr;119u8 reg = (reginfo >> 0) & 0xff;120u8 bank = (reginfo >> 8) & 0xff;121u8 i2c = (reginfo >> 16) & 0x01;122123/* select I2C */124if (i2c)125i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */126else127i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */128129/* switch bank if needed */130if (bank != priv->bank[i2c]) {131ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);132if (ret)133return ret;134priv->bank[i2c] = bank;135}136return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len);137}138139/* write single register */140int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val)141{142return cxd2820r_wr_regs(priv, reg, &val, 1);143}144145/* read single register */146int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val)147{148return cxd2820r_rd_regs(priv, reg, val, 1);149}150151/* write single register with mask */152int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,153u8 mask)154{155int ret;156u8 tmp;157158/* no need for read if whole reg is written */159if (mask != 0xff) {160ret = cxd2820r_rd_reg(priv, reg, &tmp);161if (ret)162return ret;163164val &= mask;165tmp &= ~mask;166val |= tmp;167}168169return cxd2820r_wr_reg(priv, reg, val);170}171172int cxd2820r_gpio(struct dvb_frontend *fe)173{174struct cxd2820r_priv *priv = fe->demodulator_priv;175int ret, i;176u8 *gpio, tmp0, tmp1;177dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);178179switch (fe->dtv_property_cache.delivery_system) {180case SYS_DVBT:181gpio = priv->cfg.gpio_dvbt;182break;183case SYS_DVBT2:184gpio = priv->cfg.gpio_dvbt2;185break;186case SYS_DVBC_ANNEX_AC:187gpio = priv->cfg.gpio_dvbc;188break;189default:190ret = -EINVAL;191goto error;192}193194/* update GPIOs only when needed */195if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio)))196return 0;197198tmp0 = 0x00;199tmp1 = 0x00;200for (i = 0; i < sizeof(priv->gpio); i++) {201/* enable / disable */202if (gpio[i] & CXD2820R_GPIO_E)203tmp0 |= (2 << 6) >> (2 * i);204else205tmp0 |= (1 << 6) >> (2 * i);206207/* input / output */208if (gpio[i] & CXD2820R_GPIO_I)209tmp1 |= (1 << (3 + i));210else211tmp1 |= (0 << (3 + i));212213/* high / low */214if (gpio[i] & CXD2820R_GPIO_H)215tmp1 |= (1 << (0 + i));216else217tmp1 |= (0 << (0 + i));218219dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1);220}221222dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1);223224/* write bits [7:2] */225ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc);226if (ret)227goto error;228229/* write bits [5:0] */230ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f);231if (ret)232goto error;233234memcpy(priv->gpio, gpio, sizeof(priv->gpio));235236return ret;237error:238dbg("%s: failed:%d", __func__, ret);239return ret;240}241242/* lock FE */243static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe)244{245int ret = 0;246dbg("%s: active_fe=%d", __func__, active_fe);247248mutex_lock(&priv->fe_lock);249250/* -1=NONE, 0=DVB-T/T2, 1=DVB-C */251if (priv->active_fe == active_fe)252;253else if (priv->active_fe == -1)254priv->active_fe = active_fe;255else256ret = -EBUSY;257258mutex_unlock(&priv->fe_lock);259260return ret;261}262263/* unlock FE */264static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe)265{266dbg("%s: active_fe=%d", __func__, active_fe);267268mutex_lock(&priv->fe_lock);269270/* -1=NONE, 0=DVB-T/T2, 1=DVB-C */271if (priv->active_fe == active_fe)272priv->active_fe = -1;273274mutex_unlock(&priv->fe_lock);275276return;277}278279/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */280u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)281{282return div_u64(dividend + (divisor / 2), divisor);283}284285static int cxd2820r_set_frontend(struct dvb_frontend *fe,286struct dvb_frontend_parameters *p)287{288struct cxd2820r_priv *priv = fe->demodulator_priv;289struct dtv_frontend_properties *c = &fe->dtv_property_cache;290int ret;291dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);292293if (fe->ops.info.type == FE_OFDM) {294/* DVB-T/T2 */295ret = cxd2820r_lock(priv, 0);296if (ret)297return ret;298299switch (priv->delivery_system) {300case SYS_UNDEFINED:301if (c->delivery_system == SYS_DVBT) {302/* SLEEP => DVB-T */303ret = cxd2820r_set_frontend_t(fe, p);304} else {305/* SLEEP => DVB-T2 */306ret = cxd2820r_set_frontend_t2(fe, p);307}308break;309case SYS_DVBT:310if (c->delivery_system == SYS_DVBT) {311/* DVB-T => DVB-T */312ret = cxd2820r_set_frontend_t(fe, p);313} else if (c->delivery_system == SYS_DVBT2) {314/* DVB-T => DVB-T2 */315ret = cxd2820r_sleep_t(fe);316ret = cxd2820r_set_frontend_t2(fe, p);317}318break;319case SYS_DVBT2:320if (c->delivery_system == SYS_DVBT2) {321/* DVB-T2 => DVB-T2 */322ret = cxd2820r_set_frontend_t2(fe, p);323} else if (c->delivery_system == SYS_DVBT) {324/* DVB-T2 => DVB-T */325ret = cxd2820r_sleep_t2(fe);326ret = cxd2820r_set_frontend_t(fe, p);327}328break;329default:330dbg("%s: error state=%d", __func__,331priv->delivery_system);332ret = -EINVAL;333}334} else {335/* DVB-C */336ret = cxd2820r_lock(priv, 1);337if (ret)338return ret;339340ret = cxd2820r_set_frontend_c(fe, p);341}342343return ret;344}345346static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)347{348struct cxd2820r_priv *priv = fe->demodulator_priv;349int ret;350dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);351352if (fe->ops.info.type == FE_OFDM) {353/* DVB-T/T2 */354ret = cxd2820r_lock(priv, 0);355if (ret)356return ret;357358switch (fe->dtv_property_cache.delivery_system) {359case SYS_DVBT:360ret = cxd2820r_read_status_t(fe, status);361break;362case SYS_DVBT2:363ret = cxd2820r_read_status_t2(fe, status);364break;365default:366ret = -EINVAL;367}368} else {369/* DVB-C */370ret = cxd2820r_lock(priv, 1);371if (ret)372return ret;373374ret = cxd2820r_read_status_c(fe, status);375}376377return ret;378}379380static int cxd2820r_get_frontend(struct dvb_frontend *fe,381struct dvb_frontend_parameters *p)382{383struct cxd2820r_priv *priv = fe->demodulator_priv;384int ret;385dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);386387if (fe->ops.info.type == FE_OFDM) {388/* DVB-T/T2 */389ret = cxd2820r_lock(priv, 0);390if (ret)391return ret;392393switch (fe->dtv_property_cache.delivery_system) {394case SYS_DVBT:395ret = cxd2820r_get_frontend_t(fe, p);396break;397case SYS_DVBT2:398ret = cxd2820r_get_frontend_t2(fe, p);399break;400default:401ret = -EINVAL;402}403} else {404/* DVB-C */405ret = cxd2820r_lock(priv, 1);406if (ret)407return ret;408409ret = cxd2820r_get_frontend_c(fe, p);410}411412return ret;413}414415static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)416{417struct cxd2820r_priv *priv = fe->demodulator_priv;418int ret;419dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);420421if (fe->ops.info.type == FE_OFDM) {422/* DVB-T/T2 */423ret = cxd2820r_lock(priv, 0);424if (ret)425return ret;426427switch (fe->dtv_property_cache.delivery_system) {428case SYS_DVBT:429ret = cxd2820r_read_ber_t(fe, ber);430break;431case SYS_DVBT2:432ret = cxd2820r_read_ber_t2(fe, ber);433break;434default:435ret = -EINVAL;436}437} else {438/* DVB-C */439ret = cxd2820r_lock(priv, 1);440if (ret)441return ret;442443ret = cxd2820r_read_ber_c(fe, ber);444}445446return ret;447}448449static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)450{451struct cxd2820r_priv *priv = fe->demodulator_priv;452int ret;453dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);454455if (fe->ops.info.type == FE_OFDM) {456/* DVB-T/T2 */457ret = cxd2820r_lock(priv, 0);458if (ret)459return ret;460461switch (fe->dtv_property_cache.delivery_system) {462case SYS_DVBT:463ret = cxd2820r_read_signal_strength_t(fe, strength);464break;465case SYS_DVBT2:466ret = cxd2820r_read_signal_strength_t2(fe, strength);467break;468default:469ret = -EINVAL;470}471} else {472/* DVB-C */473ret = cxd2820r_lock(priv, 1);474if (ret)475return ret;476477ret = cxd2820r_read_signal_strength_c(fe, strength);478}479480return ret;481}482483static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)484{485struct cxd2820r_priv *priv = fe->demodulator_priv;486int ret;487dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);488489if (fe->ops.info.type == FE_OFDM) {490/* DVB-T/T2 */491ret = cxd2820r_lock(priv, 0);492if (ret)493return ret;494495switch (fe->dtv_property_cache.delivery_system) {496case SYS_DVBT:497ret = cxd2820r_read_snr_t(fe, snr);498break;499case SYS_DVBT2:500ret = cxd2820r_read_snr_t2(fe, snr);501break;502default:503ret = -EINVAL;504}505} else {506/* DVB-C */507ret = cxd2820r_lock(priv, 1);508if (ret)509return ret;510511ret = cxd2820r_read_snr_c(fe, snr);512}513514return ret;515}516517static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)518{519struct cxd2820r_priv *priv = fe->demodulator_priv;520int ret;521dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);522523if (fe->ops.info.type == FE_OFDM) {524/* DVB-T/T2 */525ret = cxd2820r_lock(priv, 0);526if (ret)527return ret;528529switch (fe->dtv_property_cache.delivery_system) {530case SYS_DVBT:531ret = cxd2820r_read_ucblocks_t(fe, ucblocks);532break;533case SYS_DVBT2:534ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);535break;536default:537ret = -EINVAL;538}539} else {540/* DVB-C */541ret = cxd2820r_lock(priv, 1);542if (ret)543return ret;544545ret = cxd2820r_read_ucblocks_c(fe, ucblocks);546}547548return ret;549}550551static int cxd2820r_init(struct dvb_frontend *fe)552{553struct cxd2820r_priv *priv = fe->demodulator_priv;554int ret;555dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);556557priv->delivery_system = SYS_UNDEFINED;558/* delivery system is unknown at that (init) phase */559560if (fe->ops.info.type == FE_OFDM) {561/* DVB-T/T2 */562ret = cxd2820r_lock(priv, 0);563if (ret)564return ret;565566ret = cxd2820r_init_t(fe);567} else {568/* DVB-C */569ret = cxd2820r_lock(priv, 1);570if (ret)571return ret;572573ret = cxd2820r_init_c(fe);574}575576return ret;577}578579static int cxd2820r_sleep(struct dvb_frontend *fe)580{581struct cxd2820r_priv *priv = fe->demodulator_priv;582int ret;583dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);584585if (fe->ops.info.type == FE_OFDM) {586/* DVB-T/T2 */587ret = cxd2820r_lock(priv, 0);588if (ret)589return ret;590591switch (fe->dtv_property_cache.delivery_system) {592case SYS_DVBT:593ret = cxd2820r_sleep_t(fe);594break;595case SYS_DVBT2:596ret = cxd2820r_sleep_t2(fe);597break;598default:599ret = -EINVAL;600}601602cxd2820r_unlock(priv, 0);603} else {604/* DVB-C */605ret = cxd2820r_lock(priv, 1);606if (ret)607return ret;608609ret = cxd2820r_sleep_c(fe);610611cxd2820r_unlock(priv, 1);612}613614return ret;615}616617static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,618struct dvb_frontend_tune_settings *s)619{620struct cxd2820r_priv *priv = fe->demodulator_priv;621int ret;622dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);623624if (fe->ops.info.type == FE_OFDM) {625/* DVB-T/T2 */626ret = cxd2820r_lock(priv, 0);627if (ret)628return ret;629630switch (fe->dtv_property_cache.delivery_system) {631case SYS_DVBT:632ret = cxd2820r_get_tune_settings_t(fe, s);633break;634case SYS_DVBT2:635ret = cxd2820r_get_tune_settings_t2(fe, s);636break;637default:638ret = -EINVAL;639}640} else {641/* DVB-C */642ret = cxd2820r_lock(priv, 1);643if (ret)644return ret;645646ret = cxd2820r_get_tune_settings_c(fe, s);647}648649return ret;650}651652static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,653struct dvb_frontend_parameters *p)654{655struct cxd2820r_priv *priv = fe->demodulator_priv;656struct dtv_frontend_properties *c = &fe->dtv_property_cache;657int ret, i;658fe_status_t status = 0;659dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);660661/* switch between DVB-T and DVB-T2 when tune fails */662if (priv->last_tune_failed) {663if (priv->delivery_system == SYS_DVBT)664c->delivery_system = SYS_DVBT2;665else666c->delivery_system = SYS_DVBT;667}668669/* set frontend */670ret = cxd2820r_set_frontend(fe, p);671if (ret)672goto error;673674675/* frontend lock wait loop count */676switch (priv->delivery_system) {677case SYS_DVBT:678i = 20;679break;680case SYS_DVBT2:681i = 40;682break;683case SYS_UNDEFINED:684default:685i = 0;686break;687}688689/* wait frontend lock */690for (; i > 0; i--) {691dbg("%s: LOOP=%d", __func__, i);692msleep(50);693ret = cxd2820r_read_status(fe, &status);694if (ret)695goto error;696697if (status & FE_HAS_SIGNAL)698break;699}700701/* check if we have a valid signal */702if (status) {703priv->last_tune_failed = 0;704return DVBFE_ALGO_SEARCH_SUCCESS;705} else {706priv->last_tune_failed = 1;707return DVBFE_ALGO_SEARCH_AGAIN;708}709710error:711dbg("%s: failed:%d", __func__, ret);712return DVBFE_ALGO_SEARCH_ERROR;713}714715static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)716{717return DVBFE_ALGO_CUSTOM;718}719720static void cxd2820r_release(struct dvb_frontend *fe)721{722struct cxd2820r_priv *priv = fe->demodulator_priv;723dbg("%s", __func__);724725if (fe->ops.info.type == FE_OFDM) {726i2c_del_adapter(&priv->tuner_i2c_adapter);727kfree(priv);728}729730return;731}732733static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)734{735return I2C_FUNC_I2C;736}737738static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,739struct i2c_msg msg[], int num)740{741struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);742u8 obuf[msg[0].len + 2];743struct i2c_msg msg2[2] = {744{745.addr = priv->cfg.i2c_address,746.flags = 0,747.len = sizeof(obuf),748.buf = obuf,749}, {750.addr = priv->cfg.i2c_address,751.flags = I2C_M_RD,752.len = msg[1].len,753.buf = msg[1].buf,754}755};756757obuf[0] = 0x09;758obuf[1] = (msg[0].addr << 1);759if (num == 2) { /* I2C read */760obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */761msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */762}763memcpy(&obuf[2], msg[0].buf, msg[0].len);764765return i2c_transfer(priv->i2c, msg2, num);766}767768static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {769.master_xfer = cxd2820r_tuner_i2c_xfer,770.functionality = cxd2820r_tuner_i2c_func,771};772773struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)774{775struct cxd2820r_priv *priv = fe->demodulator_priv;776return &priv->tuner_i2c_adapter;777}778EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);779780static struct dvb_frontend_ops cxd2820r_ops[2];781782struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,783struct i2c_adapter *i2c, struct dvb_frontend *fe)784{785int ret;786struct cxd2820r_priv *priv = NULL;787u8 tmp;788789if (fe == NULL) {790/* FE0 */791/* allocate memory for the internal priv */792priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);793if (priv == NULL)794goto error;795796/* setup the priv */797priv->i2c = i2c;798memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config));799mutex_init(&priv->fe_lock);800801priv->active_fe = -1; /* NONE */802803/* check if the demod is there */804priv->bank[0] = priv->bank[1] = 0xff;805ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);806dbg("%s: chip id=%02x", __func__, tmp);807if (ret || tmp != 0xe1)808goto error;809810/* create frontends */811memcpy(&priv->fe[0].ops, &cxd2820r_ops[0],812sizeof(struct dvb_frontend_ops));813memcpy(&priv->fe[1].ops, &cxd2820r_ops[1],814sizeof(struct dvb_frontend_ops));815816priv->fe[0].demodulator_priv = priv;817priv->fe[1].demodulator_priv = priv;818819/* create tuner i2c adapter */820strlcpy(priv->tuner_i2c_adapter.name,821"CXD2820R tuner I2C adapter",822sizeof(priv->tuner_i2c_adapter.name));823priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;824priv->tuner_i2c_adapter.algo_data = NULL;825i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);826if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {827err("tuner I2C bus could not be initialized");828goto error;829}830831return &priv->fe[0];832833} else {834/* FE1: FE0 given as pointer, just return FE1 we have835* already created */836priv = fe->demodulator_priv;837return &priv->fe[1];838}839840error:841kfree(priv);842return NULL;843}844EXPORT_SYMBOL(cxd2820r_attach);845846static struct dvb_frontend_ops cxd2820r_ops[2] = {847{848/* DVB-T/T2 */849.info = {850.name = "Sony CXD2820R (DVB-T/T2)",851.type = FE_OFDM,852.caps =853FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |854FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |855FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |856FE_CAN_QPSK | FE_CAN_QAM_16 |857FE_CAN_QAM_64 | FE_CAN_QAM_256 |858FE_CAN_QAM_AUTO |859FE_CAN_TRANSMISSION_MODE_AUTO |860FE_CAN_GUARD_INTERVAL_AUTO |861FE_CAN_HIERARCHY_AUTO |862FE_CAN_MUTE_TS |863FE_CAN_2G_MODULATION864},865866.release = cxd2820r_release,867.init = cxd2820r_init,868.sleep = cxd2820r_sleep,869870.get_tune_settings = cxd2820r_get_tune_settings,871872.get_frontend = cxd2820r_get_frontend,873874.get_frontend_algo = cxd2820r_get_frontend_algo,875.search = cxd2820r_search,876877.read_status = cxd2820r_read_status,878.read_snr = cxd2820r_read_snr,879.read_ber = cxd2820r_read_ber,880.read_ucblocks = cxd2820r_read_ucblocks,881.read_signal_strength = cxd2820r_read_signal_strength,882},883{884/* DVB-C */885.info = {886.name = "Sony CXD2820R (DVB-C)",887.type = FE_QAM,888.caps =889FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |890FE_CAN_QAM_128 | FE_CAN_QAM_256 |891FE_CAN_FEC_AUTO892},893894.release = cxd2820r_release,895.init = cxd2820r_init,896.sleep = cxd2820r_sleep,897898.get_tune_settings = cxd2820r_get_tune_settings,899900.set_frontend = cxd2820r_set_frontend,901.get_frontend = cxd2820r_get_frontend,902903.read_status = cxd2820r_read_status,904.read_snr = cxd2820r_read_snr,905.read_ber = cxd2820r_read_ber,906.read_ucblocks = cxd2820r_read_ucblocks,907.read_signal_strength = cxd2820r_read_signal_strength,908},909};910911912MODULE_AUTHOR("Antti Palosaari <[email protected]>");913MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");914MODULE_LICENSE("GPL");915916917