HDIC HD29L2 DMB-TH demodulator driver
Mauro,
Please PULL that new driver to the Kernel 3.3!
Antti
The following changes since commit 6dbc13e364ad49deb9dd93c4ab84af53ffb52435:
mxl5007t: implement .get_if_frequency() (2011-10-10 00:57:07 +0300)
are available in the git repository at:
git://linuxtv.org/anttip/media_tree.git hdic
Antti Palosaari (1):
HDIC HD29L2 DMB-TH demodulator driver
drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/hd29l2.c | 863 +++++++++++++++++++++++++++++ drivers/media/dvb/frontends/hd29l2.h | 66 +++ drivers/media/dvb/frontends/hd29l2_priv.h | 314 +++++++++++ 5 files changed, 1251 insertions(+), 0 deletions(-) create mode 100644 drivers/media/dvb/frontends/hd29l2.c create mode 100644 drivers/media/dvb/frontends/hd29l2.h create mode 100644 drivers/media/dvb/frontends/hd29l2_priv.h
Signature · 1 line
http://palosaari.fi/
Quoted 91 lines · Antti Palosaari
Mauro,
Please PULL that new driver to the Kernel 3.3!
Antti
The following changes since commit
6dbc13e364ad49deb9dd93c4ab84af53ffb52435:mxl5007t: implement .get_if_frequency() (2011-10-10 00:57:07 +0300)
are available in the git repository at:
git://linuxtv.org/anttip/media_tree.githdicAntti Palosaari (1):
HDIC HD29L2 DMB-TH demodulator driverFrom: Antti Palosaari <[email protected]>
Date: Mon, 7 Nov 2011 01:01:13 +0200
Subject: HDIC HD29L2 DMB-TH demodulator driverSigned-off-by Antti Palosaari <[email protected]>--- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/hd29l2.c | 863 +++++++++++++++++++++++++++++ drivers/media/dvb/frontends/hd29l2.h | 66 +++ drivers/media/dvb/frontends/hd29l2_priv.h | 314 +++++++++++ 5 files changed, 1251 insertions(+), 0 deletions(-) create mode 100644 drivers/media/dvb/frontends/hd29l2.c create mode 100644 drivers/media/dvb/frontends/hd29l2.h create mode 100644 drivers/media/dvb/frontends/hd29l2_priv.hdrivers/media/dvb/frontends/Kconfig +7
-0@@ -404,6 +404,13 @@ config DVB_EC100 help Say Y when you want to support this frontend. +config DVB_HD29L2 + tristate "HDIC HD29L2" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. + config DVB_STV0367 tristate "ST STV0367 based" depends on DVB_CORE && I2Cdrivers/media/dvb/frontends/Makefile +1
-0@@ -84,6 +84,7 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o obj-$(CONFIG_DVB_STV6110x) += stv6110x.o obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_EC100) += ec100.o +obj-$(CONFIG_DVB_HD29L2) += hd29l2.o obj-$(CONFIG_DVB_DS3000) += ds3000.o obj-$(CONFIG_DVB_MB86A16) += mb86a16.o obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.odrivers/media/dvb/frontends/hd29l2.c new file +23
-0@@ -0,0 +1,863 @@ +/* +* HDIC HD29L2 DMB-TH demodulator driver +* +* Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D +* +* Author: Antti Palosaari <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "hd29l2_priv.h"
drivers/media/dvb/frontends/hd29l2.c line 33
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ +int hd29l2_debug; +module_param_named (debug, hd29l2_debug, int,0644 ); +MODULE_PARM_DESC (debug,"Turn on/off frontend debugging (default:off)." ); + +/* write multiple registers */ +static int hd29l2_wr_regs (struct hd29l2_priv *priv,u8 reg,u8 *val,int len) +{ +int ret; +u8 buf[2 +len];
CodingStyle. It should be, instead:
u8 buf[2 + len]
Quoted 93 lines
drivers/media/dvb/frontends/hd29l2.c new file +93
-0+struct i2c_msg msg[1 ] = { + { + .addr = priv->cfg.i2c_addr, + .flags =0 , + .len =sizeof (buf), + .buf = buf, + } + }; + + buf[0 ] =0x00 ; + buf[1 ] = reg; +memcpy (&buf[2 ], val, len); + + ret =i2c_transfer (priv->i2c, msg,1 ); +if (ret ==1 ) { + ret =0 ; + }else { +warn ("i2c wr failed=%d reg=%02x len=%d" , ret, reg, len); + ret = -EREMOTEIO ; + } + +return ret; +} + +/* read multiple registers */ +static int hd29l2_rd_regs (struct hd29l2_priv *priv,u8 reg,u8 *val,int len) +{ +int ret; +u8 buf[2 ] = {0x00 , reg }; +struct i2c_msg msg[2 ] = { + { + .addr = priv->cfg.i2c_addr, + .flags =0 , + .len =2 , + .buf = buf, + }, { + .addr = priv->cfg.i2c_addr, + .flags =I2C_M_RD , + .len = len, + .buf = val, + } + }; + + ret =i2c_transfer (priv->i2c, msg,2 ); +if (ret ==2 ) { + ret =0 ; + }else { +warn ("i2c rd failed=%d reg=%02x len=%d" , ret, reg, len); + ret = -EREMOTEIO ; + } + +return ret; +} + +/* write single register */ +static int hd29l2_wr_reg (struct hd29l2_priv *priv,u8 reg,u8 val) +{ +return hd29l2_wr_regs (priv, reg, &val,1 ); +} + +/* read single register */ +static int hd29l2_rd_reg (struct hd29l2_priv *priv,u8 reg,u8 *val) +{ +return hd29l2_rd_regs (priv, reg, val,1 ); +} + +/* write single register with mask */ +static int hd29l2_wr_reg_mask (struct hd29l2_priv *priv,u8 reg,u8 val,u8 mask) +{ +int ret; +u8 tmp; + +/* no need for read if whole reg is written */ +if (mask !=0xff ) { + ret =hd29l2_rd_regs (priv, reg, &tmp,1 ); +if (ret) +return ret; + + val &= mask; + tmp &= ~mask; + val |= tmp; + } + +return hd29l2_wr_regs (priv, reg, &val,1 ); +} + +/* read single register with mask */ +int hd29l2_rd_reg_mask (struct hd29l2_priv *priv,u8 reg,u8 *val,u8 mask) +{ +int ret, i; +u8 tmp; + + ret =hd29l2_rd_regs (priv, reg, &tmp,1 );
drivers/media/dvb/frontends/hd29l2.c line 136
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+if (ret) +return ret; + + tmp &= mask; + +/* find position of the first bit */ +for (i =0 ; i <8 ; i++) { +if ((mask >> i) &0x01 ) +break ; + }
Don't re-invent the wheel. Instead, please use the existing macros for it, defined at linux/bitmap.h. In this case, it should likely be:
find_first_bit()
Quoted 314 lines
drivers/media/dvb/frontends/hd29l2.c new file +314
-0+ *val = tmp >> i; + +return 0 ; +} + +static int hd29l2_soft_reset (struct hd29l2_priv *priv) +{ +int ret; +u8 tmp; + + ret =hd29l2_rd_reg (priv,0x26 , &tmp); +if (ret) + goto err; + + ret =hd29l2_wr_reg (priv,0x26 ,0x0d ); +if (ret) + goto err; + +usleep_range (10000 ,20000 ); + + ret =hd29l2_wr_reg (priv,0x26 , tmp); +if (ret) + goto err; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_i2c_gate_ctrl (struct dvb_frontend *fe,int enable) +{ +int ret, i; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 tmp; + +dbg ("%s: enable=%d" , __func__, enable); + +/* set tuner address for demod */ +if (!priv->tuner_i2c_addr_programmed && enable) { +/* no need to set tuner address every time, once is enough */ + ret =hd29l2_wr_reg (priv,0x9d , priv->cfg.tuner_i2c_addr <<1 ); +if (ret) + goto err; + + priv->tuner_i2c_addr_programmed = true; + } + +/* open / close gate */ + ret =hd29l2_wr_reg (priv,0x9f , enable); +if (ret) + goto err; + +/* wait demod ready */ +for (i =10 ; i; i--) { + ret =hd29l2_rd_reg (priv,0x9e , &tmp); +if (ret) + goto err; + +if (tmp == enable) +break ; + +usleep_range (5000 ,10000 ); + } + +dbg ("%s: loop=%d" , __func__, i); + +return ret; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_status (struct dvb_frontend *fe,fe_status_t *status) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; + + *status =0 ; + + ret =hd29l2_rd_reg (priv,0x05 , &buf[0 ]); +if (ret) + goto err; + +if (buf[0 ] &0x01 ) { +/* full lock */ + *status |=FE_HAS_SIGNAL |FE_HAS_CARRIER |FE_HAS_VITERBI | +FE_HAS_SYNC |FE_HAS_LOCK ; + }else { + ret =hd29l2_rd_reg (priv,0x0d , &buf[1 ]); +if (ret) + goto err; + +if ((buf[1 ] &0xfe ) ==0x78 ) +/* partial lock */ + *status |=FE_HAS_SIGNAL |FE_HAS_CARRIER | +FE_HAS_VITERBI |FE_HAS_SYNC ; + } + + priv->fe_status = *status; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_snr (struct dvb_frontend *fe,u16 *snr) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; +u16 tmp; + +if (!(priv->fe_status &FE_HAS_LOCK )) { + *snr =0 ; + ret =0 ; + goto err; + } + + ret =hd29l2_rd_regs (priv,0x0b , buf,2 ); +if (ret) + goto err; + + tmp = (buf[0 ] <<8 ) | buf[1 ]; + +/* report SNR in dB * 10 */ +#define LOG10_20736_24 72422627/* log10(20736) << 24 */ +if (tmp) + *snr = (LOG10_20736_24 -intlog10 (tmp)) / ((1 <<24 ) /100 ); +else + *snr =0 ; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_signal_strength (struct dvb_frontend *fe,u16 *strength) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; +u16 tmp; + + *strength =0 ; + + ret =hd29l2_rd_regs (priv,0xd5 , buf,2 ); +if (ret) + goto err; + + tmp = buf[0 ] <<8 | buf[1 ]; + tmp = ~tmp &0x0fff ; + +/* scale value to 0x0000-0xffff from 0x0000-0x0fff */ + *strength = tmp *0xffff /0x0fff ; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_ber (struct dvb_frontend *fe,u32 *ber) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; + +if (!(priv->fe_status &FE_HAS_SYNC )) { + *ber =0 ; + ret =0 ; + goto err; + } + + ret =hd29l2_rd_regs (priv,0xd9 , buf,2 ); +if (ret) { + *ber =0 ; + goto err; + } + +/* LDPC BER */ + *ber = ((buf[0 ] &0x0f ) <<8 ) | buf[1 ]; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_ucblocks (struct dvb_frontend *fe,u32 *ucblocks) +{ +/* no way to read? */ + *ucblocks =0 ; +return 0 ; +} + +static enum dvbfe_search hd29l2_search (struct dvb_frontend *fe, +struct dvb_frontend_parameters *p) +{ +int ret, i; +struct hd29l2_priv *priv = fe->demodulator_priv; +struct dtv_frontend_properties *c = &fe->dtv_property_cache; +u8 tmp, buf[3 ]; +u8 modulation, carrier, guard_interval, interleave, code_rate; +u64 num64; +u32 if_freq, if_ctl; +bool auto_mode; + +dbg ("%s: delivery_system=%d frequency=%d bandwidth_hz=%d " \ +"modulation=%d inversion=%d fec_inner=%d guard_interval=%d" , + __func__, + c->delivery_system, c->frequency, c->bandwidth_hz, + c->modulation, c->inversion, c->fec_inner, c->guard_interval); + +/* as for now we detect always params automatically */ + auto_mode = true; + +/* program tuner */ +if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params (fe, p); + +/* get and program IF */ +if (fe->ops.tuner_ops.get_if_frequency) + fe->ops.tuner_ops.get_if_frequency (fe, &if_freq); +else + if_freq =0 ; + +if (if_freq) { +/* normal IF */ + +/* calc IF control value */ + num64 = if_freq; + num64 *=0x800000 ; + num64 =div_u64 (num64,HD29L2_XTAL ); + num64 -=0x800000 ; + if_ctl = num64; + + tmp =0xfc ;/* tuner type normal */ + }else { +/* zero IF */ + if_ctl =0 ; + tmp =0xfe ;/* tuner type Zero-IF */ + } + + buf[0 ] = ((if_ctl >>0 ) &0xff ); + buf[1 ] = ((if_ctl >>8 ) &0xff ); + buf[2 ] = ((if_ctl >>16 ) &0xff ); + +/* program IF control */ + ret =hd29l2_wr_regs (priv,0x14 , buf,3 ); +if (ret) + goto err; + +/* program tuner type */ + ret =hd29l2_wr_reg (priv,0xab , tmp); +if (ret) + goto err; + +dbg ("%s: if_ctl=%x" , __func__, if_ctl); + +if (auto_mode) { +/* +* use auto mode +*/ + +/* disable quick mode */ + ret =hd29l2_wr_reg_mask (priv,0xac ,0 <<7 ,0x80 ); +if (ret) + goto err; + + ret =hd29l2_wr_reg_mask (priv,0x82 ,1 <<1 ,0x02 ); +if (ret) + goto err; + +/* enable auto mode */ + ret =hd29l2_wr_reg_mask (priv,0x7d ,1 <<6 ,0x40 ); +if (ret) + goto err; + + ret =hd29l2_wr_reg_mask (priv,0x81 ,1 <<3 ,0x08 ); +if (ret) + goto err; + +/* soft reset */ + ret =hd29l2_soft_reset (priv); +if (ret) + goto err; + +/* detect modulation */ +for (i =30 ; i; i--) { +msleep (100 ); + + ret =hd29l2_rd_reg (priv,0x0d , &tmp); +if (ret) + goto err; + +if ((((tmp &0xf0 ) >=0x10 ) && + ((tmp &0x0f ) ==0x08 )) || (tmp >=0x2c )) +break ; + } + +dbg ("%s: loop=%d" , __func__, i); + +if (i ==0 ) +/* detection failed */ +return DVBFE_ALGO_SEARCH_FAILED ; + +/* read modulation */ + ret =hd29l2_rd_reg_mask (priv,0x7d , &modulation,0x07 ); +if (ret) + goto err;
drivers/media/dvb/frontends/hd29l2.c line 460
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ }else { +/* +* use manual mode +*/ + + modulation =HD29L2_QAM64 ; + carrier =HD29L2_CARRIER_MULTI ; + guard_interval =HD29L2_PN945 ; + interleave =HD29L2_INTERLEAVER_420 ; + code_rate =HD29L2_CODE_RATE_08 ;
Hmm... all DMB-TH properties are already available at the DVB core? It would be great if you could document what properties are valid for this delivery system at the DocBook specs.
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ + tmp = (code_rate <<3 ) | modulation; + ret =hd29l2_wr_reg_mask (priv,0x7d , tmp,0x5f ); +if (ret) + goto err; + + tmp = (carrier <<2 ) | guard_interval; + ret =hd29l2_wr_reg_mask (priv,0x81 , tmp,0x0f ); +if (ret) + goto err;
drivers/media/dvb/frontends/hd29l2.c line 480
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ + tmp = interleave; + ret =hd29l2_wr_reg_mask (priv,0x82 , tmp,0x03 ); +if (ret) + goto err; + } + +/* ensure modulation validy */ +/* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */ +if (modulation >4 ) {
Please, don't use magic values.
Instead, it should be something like:
ARRAY_SIZE(reg_mod_vals_tab[0].val)
Still, I don't understand why modulation should be QAM64 when the auto_mode is disabled. Shouldn't it be provided via a DVB property?
Quoted 89 lines
drivers/media/dvb/frontends/hd29l2.c new file +89
-0+dbg ("%s: modulation=%d not valid" , __func__, modulation); + goto err; + } + +/* program registers according to modulation */ +for (i =0 ; i <ARRAY_SIZE (reg_mod_vals_tab); i++) { + ret =hd29l2_wr_reg (priv, reg_mod_vals_tab[i].reg, + reg_mod_vals_tab[i].val[modulation]); +if (ret) + goto err; + } + +/* read guard interval */ + ret =hd29l2_rd_reg_mask (priv,0x81 , &guard_interval,0x03 ); +if (ret) + goto err; + +/* read carrier mode */ + ret =hd29l2_rd_reg_mask (priv,0x81 , &carrier,0x04 ); +if (ret) + goto err; + +dbg ("%s: modulation=%d guard_interval=%d carrier=%d" , + __func__, modulation, guard_interval, carrier); + +if ((carrier ==HD29L2_CARRIER_MULTI ) && (modulation ==HD29L2_QAM64 ) && + (guard_interval ==HD29L2_PN945 )) { +dbg ("%s: C=3780 && QAM64 && PN945" , __func__); + + ret =hd29l2_wr_reg (priv,0x42 ,0x33 ); +if (ret) + goto err; + + ret =hd29l2_wr_reg (priv,0xdd ,0x01 ); +if (ret) + goto err; + } + +usleep_range (10000 ,20000 ); + +/* soft reset */ + ret =hd29l2_soft_reset (priv); +if (ret) + goto err; + +/* wait demod lock */ +for (i =30 ; i; i--) { +msleep (100 ); + +/* read lock bit */ + ret =hd29l2_rd_reg_mask (priv,0x05 , &tmp,0x01 ); +if (ret) + goto err; + +if (tmp) +break ; + } + +dbg ("%s: loop=%d" , __func__, i); + +if (i ==0 ) +return DVBFE_ALGO_SEARCH_AGAIN ; + +return DVBFE_ALGO_SEARCH_SUCCESS ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return DVBFE_ALGO_SEARCH_ERROR ; +} + +static int hd29l2_get_frontend_algo (struct dvb_frontend *fe) +{ +return DVBFE_ALGO_CUSTOM ; +} + +static int hd29l2_get_frontend (struct dvb_frontend *fe, +struct dvb_frontend_parameters *p) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +struct dtv_frontend_properties *c = &fe->dtv_property_cache; +u8 buf[3 ]; +u32 if_ctl; +char *str_constellation, *str_code_rate, *str_constellation_code_rate, + *str_guard_interval, *str_carrier, *str_guard_interval_carrier, + *str_interleave, *str_interleave_; + + ret =hd29l2_rd_reg (priv,0x7d , &buf[0 ]); +if (ret) + goto err;
drivers/media/dvb/frontends/hd29l2.c line 579
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ + ret =hd29l2_rd_regs (priv,0x81 , &buf[1 ],2 ); +if (ret) + goto err; + +/* constellation, 0x7d[2:0] */ +switch ((buf[0 ] >>0 ) &0x07 ) { +case 0 :/* QAM4NR */ + str_constellation ="QAM4NR" ; + c->modulation =QAM_AUTO ;/* FIXME */
Please, don't abuse QAM_AUTO.
drivers/media/dvb/frontends/hd29l2.c line 583
Quoted 4 lines
drivers/media/dvb/frontends/hd29l2.c new file +4
-0+break ; +case 1 :/* QAM4 */ + str_constellation ="QAM4" ; + c->modulation =QPSK ;/* FIXME */
QPSK and QAM4 are two names for the same encoding.
drivers/media/dvb/frontends/hd29l2.c line 596
Quoted 13 lines
drivers/media/dvb/frontends/hd29l2.c new file +13
-0+break ; +case 2 : + str_constellation ="QAM16" ; + c->modulation =QAM_16 ; +break ; +case 3 : + str_constellation ="QAM32" ; + c->modulation =QAM_32 ; +break ; +case 4 : + str_constellation ="QAM64" ; + c->modulation =QAM_64 ; +break ;
Please, avoid magic numbers. Instead, use macros for each value.
drivers/media/dvb/frontends/hd29l2.c line 605
Quoted 9 lines
drivers/media/dvb/frontends/hd29l2.c new file +9
-0+default : + str_constellation ="?" ; + } + +/* LDPC code rate, 0x7d[4:3] */ +switch ((buf[0 ] >>3 ) &0x03 ) { +case 0 :/* 0.4 */ + str_code_rate ="0.4" ; + c->fec_inner =FEC_AUTO ;/* FIXME */
Also, please don't abuse FEC_AUTO. Should likely be FEC_2_5, and you'll likely need to add it to the API.
Quoted 29 lines
drivers/media/dvb/frontends/hd29l2.c new file +29
-0+break ; +case 1 :/* 0.6 */ + str_code_rate ="0.6" ; + c->fec_inner =FEC_3_5 ; +break ; +case 2 :/* 0.8 */ + str_code_rate ="0.8" ; + c->fec_inner =FEC_4_5 ; +break ; +default : + str_code_rate ="?" ; + } + +/* constellation & code rate set, 0x7d[6] */ +switch ((buf[0 ] >>6 ) &0x01 ) { +case 0 : + str_constellation_code_rate ="manual" ; +break ; +case 1 : + str_constellation_code_rate ="auto" ; +break ; +default : + str_constellation_code_rate ="?" ; + } + +/* frame header, 0x81[1:0] */ +switch ((buf[1 ] >>0 ) &0x03 ) { +case 0 :/* PN945 */ + str_guard_interval ="PN945" ;
drivers/media/dvb/frontends/hd29l2.c line 644
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ c->guard_interval =GUARD_INTERVAL_AUTO ;/* FIXME */ +break ; +case 1 :/* PN595 */ + str_guard_interval ="PN595" ; + c->guard_interval =GUARD_INTERVAL_AUTO ;/* FIXME */ +break ; +case 2 :/* PN420 */ + str_guard_interval ="PN420" ; + c->guard_interval =GUARD_INTERVAL_AUTO ;/* FIXME */ +break ;
Again, don't abuse over the API. Instead, add the proper guard intervals into it.
Quoted 5 lines
drivers/media/dvb/frontends/hd29l2.c new file +5
-0+default : + str_guard_interval ="?" ; + } + +/* carrier, 0x81[2] */
drivers/media/dvb/frontends/hd29l2.c line 659
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+switch ((buf[1 ] >>2 ) &0x01 ) { +case 0 : + str_carrier ="C=1" ; +break ; +case 1 : + str_carrier ="C=3780" ; +break ; +default : + str_carrier ="?" ; + }
Probably, API needs to support it. I'm not familiar with DMB specs, but I think you need to first send a patch adding support for it at the DocBook and linux/dvb/frontends.h, and then add the driver.
Quoted 71 lines
drivers/media/dvb/frontends/hd29l2.c new file +71
-0+ +/* frame header & carrier set, 0x81[3] */ +switch ((buf[1 ] >>3 ) &0x01 ) { +case 0 : + str_guard_interval_carrier ="manual" ; +break ; +case 1 : + str_guard_interval_carrier ="auto" ; +break ; +default : + str_guard_interval_carrier ="?" ; + } + +/* interleave, 0x82[0] */ +switch ((buf[2 ] >>0 ) &0x01 ) { +case 0 : + str_interleave ="M=720" ; +break ; +case 1 : + str_interleave ="M=240" ; +break ; +default : + str_interleave ="?" ; + } + +/* interleave set, 0x82[1] */ +switch ((buf[2 ] >>1 ) &0x01 ) { +case 0 : + str_interleave_ ="manual" ; +break ; +case 1 : + str_interleave_ ="auto" ; +break ; +default : + str_interleave_ ="?" ; + } + +/* +* We can read out current detected NCO and use that value next +* time instead of calculating new value from targed IF. +* I think it will not effect receiver sensitivity but gaining lock +* after tune could be easier... +*/ + ret =hd29l2_rd_regs (priv,0xb1 , &buf[0 ],3 ); +if (ret) + goto err; + + if_ctl = (buf[0 ] <<16 ) | ((buf[1 ] -7 ) <<8 ) | buf[2 ]; + +dbg ("%s: %s %s %s | %s %s %s | %s %s | NCO=%06x" , __func__, + str_constellation, str_code_rate, str_constellation_code_rate, + str_guard_interval, str_carrier, str_guard_interval_carrier, + str_interleave, str_interleave_, if_ctl); + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_init (struct dvb_frontend *fe) +{ +int ret, i; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 tmp; +static const struct reg_val tab[] = { + {0x3a ,0x06 }, + {0x3b ,0x03 }, + {0x3c ,0x04 }, + {0xaf ,0x06 }, + {0xb0 ,0x1b },
drivers/media/dvb/frontends/hd29l2.c line 740
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ { 0x80, 0x64 }, + { 0x10, 0x38 }, + }; + +dbg ("%s:" , __func__); + +/* reset demod */ +/* it is recommended to HW reset chip using RST_N pin */ +if (fe->callback) { + ret = fe->callback (fe,0 ,0 ,0 );
This looks weird on my eyes. The fe->callback is tuner-dependent. So, the command you should use there requires a test for the tuner type.
In other words, if you're needing to use it, the code should be doing something similar to:
if (fe->callback && priv->tuner_type == TUNER_XC2028) ret = fe->callback(fe, 0, XC2028_TUNER_RESET, 0);
(the actual coding will depend on how do you store the tuner type, and what are the commands for the tuner you're using)
That's said, it probably makes sense to deprecate fe->callback in favor or a more generic set of callbacks, like fe->tuner_reset().
Quoted 518 lines
drivers/media/dvb/frontends/hd29l2.c new file +123
-0+if (ret) + goto err; + +/* reprogramming needed because HW reset clears registers */ + priv->tuner_i2c_addr_programmed = false; + } + +/* init */ +for (i =0 ; i <ARRAY_SIZE (tab); i++) { + ret =hd29l2_wr_reg (priv, tab[i].reg, tab[i].val); +if (ret) + goto err; + } + +/* TS params */ + ret =hd29l2_rd_reg (priv,0x36 , &tmp); +if (ret) + goto err; + + tmp &=0x1b ; + tmp |= priv->cfg.ts_mode; + ret =hd29l2_wr_reg (priv,0x36 , tmp); +if (ret) + goto err; + + ret =hd29l2_rd_reg (priv,0x31 , &tmp); + tmp &=0xef ; + +if (!(priv->cfg.ts_mode >>7 )) +/* set b4 for serial TS */ + tmp |=0x10 ; + + ret =hd29l2_wr_reg (priv,0x31 , tmp); +if (ret) + goto err; + +return ret; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static void hd29l2_release (struct dvb_frontend *fe) +{ +struct hd29l2_priv *priv = fe->demodulator_priv; +kfree (priv); +} + +static struct dvb_frontend_ops hd29l2_ops; + +struct dvb_frontend *hd29l2_attach (const struct hd29l2_config *config, +struct i2c_adapter *i2c) +{ +int ret; +struct hd29l2_priv *priv =NULL ; +u8 tmp; + +/* allocate memory for the internal state */ + priv =kzalloc (sizeof (struct hd29l2_priv ),GFP_KERNEL ); +if (priv ==NULL ) + goto err; + +/* setup the state */ + priv->i2c = i2c; +memcpy (&priv->cfg, config,sizeof (struct hd29l2_config )); + + +/* check if the demod is there */ + ret =hd29l2_rd_reg (priv,0x00 , &tmp); +if (ret) + goto err; + +/* create dvb_frontend */ +memcpy (&priv->fe.ops, &hd29l2_ops,sizeof (struct dvb_frontend_ops )); + priv->fe.demodulator_priv = priv; + +return &priv->fe; +err: +kfree (priv); +return NULL ; +} +EXPORT_SYMBOL (hd29l2_attach); + +static struct dvb_frontend_ops hd29l2_ops = { + .info = { + .name ="HDIC HD29L2 DMB-TH" , + .type =FE_OFDM , + .frequency_min =474000000 , + .frequency_max =858000000 , + .frequency_stepsize =10000 , + .caps =FE_CAN_FEC_AUTO | +FE_CAN_QPSK | +FE_CAN_QAM_16 | +FE_CAN_QAM_32 | +FE_CAN_QAM_64 | +FE_CAN_QAM_AUTO | +FE_CAN_TRANSMISSION_MODE_AUTO | +FE_CAN_BANDWIDTH_AUTO | +FE_CAN_GUARD_INTERVAL_AUTO | +FE_CAN_HIERARCHY_AUTO | +FE_CAN_RECOVER + }, + + .release = hd29l2_release, + + .init = hd29l2_init, + + .get_frontend_algo = hd29l2_get_frontend_algo, + .search = hd29l2_search, + .get_frontend = hd29l2_get_frontend, + + .read_status = hd29l2_read_status, + .read_snr = hd29l2_read_snr, + .read_signal_strength = hd29l2_read_signal_strength, + .read_ber = hd29l2_read_ber, + .read_ucblocks = hd29l2_read_ucblocks, + + .i2c_gate_ctrl = hd29l2_i2c_gate_ctrl, +}; + +MODULE_AUTHOR ("Antti Palosaari <[email protected]>" ); +MODULE_DESCRIPTION ("HDIC HD29L2 DMB-TH demodulator driver" ); +MODULE_LICENSE ("GPL" );drivers/media/dvb/frontends/hd29l2.h new file +66
-0@@ -0,0 +1,66 @@ +/* +* HDIC HD29L2 DMB-TH demodulator driver +* +* Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D +* +* Author: Antti Palosaari <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef HD29L2_H +#define HD29L2_H + +#include <linux/dvb/frontend.h> + +struct hd29l2_config { +/* +* demodulator I2C address +*/ +u8 i2c_addr; + +/* +* tuner I2C address +* only needed when tuner is behind demod I2C-gate +*/ +u8 tuner_i2c_addr; + +/* +* TS settings +*/ +#define HD29L2_TS_SERIAL 0x00 +#define HD29L2_TS_PARALLEL 0x80 +#define HD29L2_TS_CLK_NORMAL 0x40 +#define HD29L2_TS_CLK_INVERTED 0x00 +#define HD29L2_TS_CLK_GATED 0x20 +#define HD29L2_TS_CLK_FREE 0x00 +u8 ts_mode; +}; + + +#if defined(CONFIG_DVB_HD29L2 ) || \ + (defined(CONFIG_DVB_HD29L2_MODULE ) && defined(MODULE )) +extern struct dvb_frontend *hd29l2_attach (const struct hd29l2_config *config, +struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *hd29l2_attach ( +const struct hd29l2_config *config,struct i2c_adapter *i2c) +{ +printk (KERN_WARNING "%s: driver disabled by Kconfig\n" , __func__); +return NULL ; +} +#endif + +#endif /* HD29L2_H */ drivers/media/dvb/frontends/hd29l2_priv.h new file +314
-0@@ -0,0 +1,314 @@ +/* +* HDIC HD29L2 DMB-TH demodulator driver +* +* Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D +* +* Author: Antti Palosaari <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef HD29L2_PRIV +#define HD29L2_PRIV + +#include <linux/dvb/version.h> +#include "dvb_frontend.h" +#include "dvb_math.h" +#include "hd29l2.h" + +#define LOG_PREFIX "hd29l2" + +#undef dbg +#define dbg(f, arg...) \ + if (hd29l2_debug) \ + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + +#define HD29L2_XTAL 30400000/* Hz */ + + +#define HD29L2_QAM4NR 0x00 +#define HD29L2_QAM4 0x01 +#define HD29L2_QAM16 0x02 +#define HD29L2_QAM32 0x03 +#define HD29L2_QAM64 0x04 + +#define HD29L2_CODE_RATE_04 0x00 +#define HD29L2_CODE_RATE_06 0x08 +#define HD29L2_CODE_RATE_08 0x10 + +#define HD29L2_PN945 0x00 +#define HD29L2_PN595 0x01 +#define HD29L2_PN420 0x02 + +#define HD29L2_CARRIER_SINGLE 0x00 +#define HD29L2_CARRIER_MULTI 0x01 + +#define HD29L2_INTERLEAVER_720 0x00 +#define HD29L2_INTERLEAVER_420 0x01 + +struct reg_val { +u8 reg; +u8 val; +}; + +struct reg_mod_vals { +u8 reg; +u8 val[5 ]; +}; + +struct hd29l2_priv { +struct i2c_adapter *i2c; +struct dvb_frontend fe; +struct hd29l2_config cfg; +u8 tuner_i2c_addr_programmed:1 ; + +fe_status_t fe_status; +}; + +static const struct reg_mod_vals reg_mod_vals_tab[] = { +/* REG, QAM4NR, QAM4,QAM16,QAM32,QAM64 */ + {0x01 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x02 , {0x07 ,0x07 ,0x07 ,0x07 ,0x07 } }, + {0x03 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x04 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x05 , {0x61 ,0x60 ,0x60 ,0x61 ,0x60 } }, + {0x06 , {0xff ,0xff ,0xff ,0xff ,0xff } }, + {0x07 , {0xff ,0xff ,0xff ,0xff ,0xff } }, + {0x08 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x09 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x0a , {0x15 ,0x15 ,0x03 ,0x03 ,0x03 } }, + {0x0d , {0x78 ,0x78 ,0x88 ,0x78 ,0x78 } }, + {0x0e , {0xa0 ,0x90 ,0xa0 ,0xa0 ,0xa0 } }, + {0x0f , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x10 , {0xa0 ,0xa0 ,0x58 ,0x38 ,0x38 } }, + {0x11 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x12 , {0x5a ,0x5a ,0x5a ,0x5a ,0x5a } }, + {0x13 , {0xa2 ,0xa2 ,0xa2 ,0xa2 ,0xa2 } }, + {0x17 , {0x40 ,0x40 ,0x40 ,0x40 ,0x40 } }, + {0x18 , {0x21 ,0x21 ,0x42 ,0x52 ,0x42 } }, + {0x19 , {0x21 ,0x21 ,0x62 ,0x72 ,0x62 } }, + {0x1a , {0x32 ,0x43 ,0xa9 ,0xb9 ,0xa9 } }, + {0x1b , {0x32 ,0x43 ,0xb9 ,0xd8 ,0xb9 } }, + {0x1c , {0x02 ,0x02 ,0x03 ,0x02 ,0x03 } }, + {0x1d , {0x0c ,0x0c ,0x01 ,0x02 ,0x02 } }, + {0x1e , {0x02 ,0x02 ,0x02 ,0x01 ,0x02 } }, + {0x1f , {0x02 ,0x02 ,0x01 ,0x02 ,0x04 } }, + {0x20 , {0x01 ,0x02 ,0x01 ,0x01 ,0x01 } }, + {0x21 , {0x08 ,0x08 ,0x0a ,0x0a ,0x0a } }, + {0x22 , {0x06 ,0x06 ,0x04 ,0x05 ,0x05 } }, + {0x23 , {0x06 ,0x06 ,0x05 ,0x03 ,0x05 } }, + {0x24 , {0x08 ,0x08 ,0x05 ,0x07 ,0x07 } }, + {0x25 , {0x16 ,0x10 ,0x10 ,0x0a ,0x10 } }, + {0x26 , {0x14 ,0x14 ,0x04 ,0x04 ,0x04 } }, + {0x27 , {0x58 ,0x58 ,0x58 ,0x5c ,0x58 } }, + {0x28 , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0x29 , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0x2a , {0x08 ,0x0a ,0x08 ,0x08 ,0x08 } }, + {0x2b , {0x08 ,0x08 ,0x08 ,0x08 ,0x08 } }, + {0x2c , {0x06 ,0x06 ,0x06 ,0x06 ,0x06 } }, + {0x2d , {0x05 ,0x06 ,0x06 ,0x06 ,0x06 } }, + {0x2e , {0x21 ,0x21 ,0x21 ,0x21 ,0x21 } }, + {0x2f , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x30 , {0x14 ,0x14 ,0x14 ,0x14 ,0x14 } }, + {0x33 , {0xb7 ,0xb7 ,0xb7 ,0xb7 ,0xb7 } }, + {0x34 , {0x81 ,0x81 ,0x81 ,0x81 ,0x81 } }, + {0x35 , {0x80 ,0x80 ,0x80 ,0x80 ,0x80 } }, + {0x37 , {0x70 ,0x70 ,0x70 ,0x70 ,0x70 } }, + {0x38 , {0x04 ,0x04 ,0x02 ,0x02 ,0x02 } }, + {0x39 , {0x07 ,0x07 ,0x05 ,0x05 ,0x05 } }, + {0x3a , {0x06 ,0x06 ,0x06 ,0x06 ,0x06 } }, + {0x3b , {0x03 ,0x03 ,0x03 ,0x03 ,0x03 } }, + {0x3c , {0x07 ,0x06 ,0x04 ,0x04 ,0x04 } }, + {0x3d , {0xf0 ,0xf0 ,0xf0 ,0xf0 ,0x80 } }, + {0x3e , {0x60 ,0x60 ,0x60 ,0x60 ,0xff } }, + {0x3f , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x40 , {0x5b ,0x5b ,0x5b ,0x57 ,0x50 } }, + {0x41 , {0x30 ,0x30 ,0x30 ,0x30 ,0x18 } }, + {0x42 , {0x20 ,0x20 ,0x20 ,0x00 ,0x30 } }, + {0x43 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x44 , {0x3f ,0x3f ,0x3f ,0x3f ,0x3f } }, + {0x45 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x46 , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0x47 , {0x00 ,0x00 ,0x95 ,0x00 ,0x95 } }, + {0x48 , {0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0 } }, + {0x49 , {0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0 } }, + {0x4a , {0x40 ,0x40 ,0x33 ,0x11 ,0x11 } }, + {0x4b , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x4c , {0x40 ,0x40 ,0x99 ,0x11 ,0x11 } }, + {0x4d , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x4e , {0x40 ,0x40 ,0x66 ,0x77 ,0x77 } }, + {0x4f , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x50 , {0x40 ,0x40 ,0x88 ,0x33 ,0x11 } }, + {0x51 , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x52 , {0x40 ,0x40 ,0x88 ,0x02 ,0x02 } }, + {0x53 , {0x40 ,0x40 ,0x00 ,0x02 ,0x02 } }, + {0x54 , {0x00 ,0x00 ,0x88 ,0x33 ,0x33 } }, + {0x55 , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x56 , {0x00 ,0x00 ,0x00 ,0x0b ,0x00 } }, + {0x57 , {0x40 ,0x40 ,0x0a ,0x0b ,0x0a } }, + {0x58 , {0xaa ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x59 , {0x7a ,0x40 ,0x02 ,0x02 ,0x02 } }, + {0x5a , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5b , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5c , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5d , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5e , {0xc0 ,0xc0 ,0xc0 ,0xff ,0xc0 } }, + {0x5f , {0xc0 ,0xc0 ,0xc0 ,0xff ,0xc0 } }, + {0x60 , {0x40 ,0x40 ,0x00 ,0x30 ,0x30 } }, + {0x61 , {0x40 ,0x40 ,0x10 ,0x30 ,0x30 } }, + {0x62 , {0x40 ,0x40 ,0x00 ,0x30 ,0x30 } }, + {0x63 , {0x40 ,0x40 ,0x05 ,0x30 ,0x30 } }, + {0x64 , {0x40 ,0x40 ,0x06 ,0x00 ,0x30 } }, + {0x65 , {0x40 ,0x40 ,0x06 ,0x08 ,0x30 } }, + {0x66 , {0x40 ,0x40 ,0x00 ,0x00 ,0x20 } }, + {0x67 , {0x40 ,0x40 ,0x01 ,0x04 ,0x20 } }, + {0x68 , {0x00 ,0x00 ,0x30 ,0x00 ,0x20 } }, + {0x69 , {0xa0 ,0xa0 ,0x00 ,0x08 ,0x20 } }, + {0x6a , {0x00 ,0x00 ,0x30 ,0x00 ,0x25 } }, + {0x6b , {0xa0 ,0xa0 ,0x00 ,0x06 ,0x25 } }, + {0x6c , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x6d , {0xa0 ,0x60 ,0x0c ,0x03 ,0x0c } }, + {0x6e , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x6f , {0xa0 ,0x60 ,0x04 ,0x01 ,0x04 } }, + {0x70 , {0x58 ,0x58 ,0xaa ,0xaa ,0xaa } }, + {0x71 , {0x58 ,0x58 ,0xaa ,0xaa ,0xaa } }, + {0x72 , {0x58 ,0x58 ,0xff ,0xff ,0xff } }, + {0x73 , {0x58 ,0x58 ,0xff ,0xff ,0xff } }, + {0x74 , {0x06 ,0x06 ,0x09 ,0x05 ,0x05 } }, + {0x75 , {0x06 ,0x06 ,0x0a ,0x10 ,0x10 } }, + {0x76 , {0x10 ,0x10 ,0x06 ,0x0a ,0x0a } }, + {0x77 , {0x12 ,0x18 ,0x28 ,0x10 ,0x28 } }, + {0x78 , {0xf8 ,0xf8 ,0xf8 ,0xf8 ,0xf8 } }, + {0x79 , {0x15 ,0x15 ,0x03 ,0x03 ,0x03 } }, + {0x7a , {0x02 ,0x02 ,0x01 ,0x04 ,0x03 } }, + {0x7b , {0x01 ,0x02 ,0x03 ,0x03 ,0x03 } }, + {0x7c , {0x28 ,0x28 ,0x28 ,0x28 ,0x28 } }, + {0x7f , {0x25 ,0x92 ,0x5f ,0x17 ,0x2d } }, + {0x80 , {0x64 ,0x64 ,0x64 ,0x74 ,0x64 } }, + {0x83 , {0x06 ,0x03 ,0x04 ,0x04 ,0x04 } }, + {0x84 , {0xff ,0xff ,0xff ,0xff ,0xff } }, + {0x85 , {0x05 ,0x05 ,0x05 ,0x05 ,0x05 } }, + {0x86 , {0x00 ,0x00 ,0x11 ,0x11 ,0x11 } }, + {0x87 , {0x03 ,0x03 ,0x03 ,0x03 ,0x03 } }, + {0x88 , {0x09 ,0x09 ,0x09 ,0x09 ,0x09 } }, + {0x89 , {0x20 ,0x20 ,0x30 ,0x20 ,0x20 } }, + {0x8a , {0x03 ,0x03 ,0x02 ,0x03 ,0x02 } }, + {0x8b , {0x00 ,0x07 ,0x09 ,0x00 ,0x09 } }, + {0x8c , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x8d , {0x4f ,0x4f ,0x4f ,0x3f ,0x4f } }, + {0x8e , {0xf0 ,0xf0 ,0x60 ,0xf0 ,0xa0 } }, + {0x8f , {0xe8 ,0xe8 ,0xe8 ,0xe8 ,0xe8 } }, + {0x90 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x91 , {0x40 ,0x40 ,0x70 ,0x70 ,0x10 } }, + {0x92 , {0x00 ,0x00 ,0x00 ,0x00 ,0x04 } }, + {0x93 , {0x60 ,0x60 ,0x60 ,0x60 ,0x60 } }, + {0x94 , {0x00 ,0x00 ,0x00 ,0x00 ,0x03 } }, + {0x95 , {0x09 ,0x09 ,0x47 ,0x47 ,0x47 } }, + {0x96 , {0x80 ,0xa0 ,0xa0 ,0x40 ,0xa0 } }, + {0x97 , {0x60 ,0x60 ,0x60 ,0x60 ,0x60 } }, + {0x98 , {0x50 ,0x50 ,0x50 ,0x30 ,0x50 } }, + {0x99 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x9a , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x9b , {0x40 ,0x40 ,0x40 ,0x30 ,0x40 } }, + {0x9c , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa0 , {0xf0 ,0xf0 ,0xf0 ,0xf0 ,0xf0 } }, + {0xa1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa2 , {0x30 ,0x30 ,0x00 ,0x30 ,0x00 } }, + {0xa3 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa4 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa5 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa6 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa7 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa8 , {0x77 ,0x77 ,0x77 ,0x77 ,0x77 } }, + {0xa9 , {0x02 ,0x02 ,0x02 ,0x02 ,0x02 } }, + {0xaa , {0x40 ,0x40 ,0x40 ,0x40 ,0x40 } }, + {0xac , {0x1f ,0x1f ,0x1f ,0x1f ,0x1f } }, + {0xad , {0x14 ,0x14 ,0x14 ,0x14 ,0x14 } }, + {0xae , {0x78 ,0x78 ,0x78 ,0x78 ,0x78 } }, + {0xaf , {0x06 ,0x06 ,0x06 ,0x06 ,0x07 } }, + {0xb0 , {0x1b ,0x1b ,0x1b ,0x19 ,0x1b } }, + {0xb1 , {0x18 ,0x17 ,0x17 ,0x18 ,0x17 } }, + {0xb2 , {0x35 ,0x82 ,0x82 ,0x38 ,0x82 } }, + {0xb3 , {0xb6 ,0xce ,0xc7 ,0x5c ,0xb0 } }, + {0xb4 , {0x3f ,0x3e ,0x3e ,0x3f ,0x3e } }, + {0xb5 , {0x70 ,0x58 ,0x50 ,0x68 ,0x50 } }, + {0xb6 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xb7 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xb8 , {0x03 ,0x03 ,0x01 ,0x01 ,0x01 } }, + {0xb9 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xba , {0x06 ,0x06 ,0x0a ,0x05 ,0x0a } }, + {0xbb , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbc , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbd , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbe , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbf , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc0 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc2 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc3 , {0x00 ,0x00 ,0x88 ,0x66 ,0x88 } }, + {0xc4 , {0x10 ,0x10 ,0x00 ,0x00 ,0x00 } }, + {0xc5 , {0x00 ,0x00 ,0x44 ,0x60 ,0x44 } }, + {0xc6 , {0x10 ,0x0a ,0x00 ,0x00 ,0x00 } }, + {0xc7 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc8 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc9 , {0x90 ,0x04 ,0x00 ,0x00 ,0x00 } }, + {0xca , {0x90 ,0x08 ,0x01 ,0x01 ,0x01 } }, + {0xcb , {0xa0 ,0x04 ,0x00 ,0x44 ,0x00 } }, + {0xcc , {0xa0 ,0x10 ,0x03 ,0x00 ,0x03 } }, + {0xcd , {0x06 ,0x06 ,0x06 ,0x05 ,0x06 } }, + {0xce , {0x05 ,0x05 ,0x01 ,0x01 ,0x01 } }, + {0xcf , {0x40 ,0x20 ,0x18 ,0x18 ,0x18 } }, + {0xd0 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd2 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd3 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd4 , {0x05 ,0x05 ,0x05 ,0x05 ,0x05 } }, + {0xd5 , {0x05 ,0x05 ,0x05 ,0x03 ,0x05 } }, + {0xd6 , {0xac ,0x22 ,0xca ,0x8f ,0xca } }, + {0xd7 , {0x20 ,0x20 ,0x20 ,0x20 ,0x20 } }, + {0xd8 , {0x01 ,0x01 ,0x01 ,0x01 ,0x01 } }, + {0xd9 , {0x00 ,0x00 ,0x0f ,0x00 ,0x0f } }, + {0xda , {0x00 ,0xff ,0xff ,0x0e ,0xff } }, + {0xdb , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0xdc , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0xdd , {0x05 ,0x05 ,0x05 ,0x05 ,0x05 } }, + {0xde , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0xdf , {0x42 ,0x42 ,0x44 ,0x44 ,0x04 } }, + {0xe0 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe2 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe3 , {0x00 ,0x00 ,0x26 ,0x06 ,0x26 } }, + {0xe4 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe5 , {0x01 ,0x0a ,0x01 ,0x01 ,0x01 } }, + {0xe6 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe7 , {0x08 ,0x08 ,0x08 ,0x08 ,0x08 } }, + {0xe8 , {0x63 ,0x63 ,0x63 ,0x63 ,0x63 } }, + {0xe9 , {0x59 ,0x59 ,0x59 ,0x59 ,0x59 } }, + {0xea , {0x80 ,0x80 ,0x20 ,0x80 ,0x80 } }, + {0xeb , {0x37 ,0x37 ,0x78 ,0x37 ,0x77 } }, + {0xec , {0x1f ,0x1f ,0x25 ,0x25 ,0x25 } }, + {0xed , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0xee , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xef , {0x70 ,0x70 ,0x58 ,0x38 ,0x58 } }, + {0xf0 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, +}; + +#endif /* HD29L2_PRIV */ Signature · 1 line
1.7.7.4
Quoted 104 lines · Mauro Carvalho Chehab
Quoted 91 lines · Antti Palosaari
Mauro,
Please PULL that new driver to the Kernel 3.3!
Antti
The following changes since commit
6dbc13e364ad49deb9dd93c4ab84af53ffb52435:mxl5007t: implement .get_if_frequency() (2011-10-10 00:57:07 +0300)are available in the git repository at:
git://linuxtv.org/anttip/media_tree.githdicAntti Palosaari (1):
HDIC HD29L2 DMB-TH demodulator driverFrom: Antti Palosaari<[email protected]>
Date: Mon, 7 Nov 2011 01:01:13 +0200
Subject: HDIC HD29L2 DMB-TH demodulator driverSigned-off-by Antti Palosaari<[email protected]>--- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/hd29l2.c | 863 +++++++++++++++++++++++++++++ drivers/media/dvb/frontends/hd29l2.h | 66 +++ drivers/media/dvb/frontends/hd29l2_priv.h | 314 +++++++++++ 5 files changed, 1251 insertions(+), 0 deletions(-)create mode 100644
drivers/media/dvb/frontends/hd29l2.ccreate mode 100644drivers/media/dvb/frontends/hd29l2.hcreate mode 100644drivers/media/dvb/frontends/hd29l2_priv.hdrivers/media/dvb/frontends/Kconfig +7
-0@@ -404,6 +404,13 @@ config DVB_EC100 help Say Y when you want to support this frontend. +config DVB_HD29L2 + tristate "HDIC HD29L2" + depends on DVB_CORE&& I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. + config DVB_STV0367 tristate "ST STV0367 based" depends on DVB_CORE&& I2Cdrivers/media/dvb/frontends/Makefile +1
-0@@ -84,6 +84,7 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o obj-$(CONFIG_DVB_STV6110x) += stv6110x.o obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_EC100) += ec100.o +obj-$(CONFIG_DVB_HD29L2) += hd29l2.o obj-$(CONFIG_DVB_DS3000) += ds3000.o obj-$(CONFIG_DVB_MB86A16) += mb86a16.o obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.odrivers/media/dvb/frontends/hd29l2.c new file +23
-0@@ -0,0 +1,863 @@ +/* +* HDIC HD29L2 DMB-TH demodulator driver +* +* Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D +* +* Author: Antti Palosaari<[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "hd29l2_priv.h" drivers/media/dvb/frontends/hd29l2.c line 33
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ +int hd29l2_debug; +module_param_named (debug, hd29l2_debug, int,0644 ); +MODULE_PARM_DESC (debug,"Turn on/off frontend debugging (default:off)." ); + +/* write multiple registers */ +static int hd29l2_wr_regs (struct hd29l2_priv *priv,u8 reg,u8 *val,int len) +{ +int ret; +u8 buf[2 +len];CodingStyle. It should be, instead:
Quoted 2 lines
u8 buf[2 + len]
OK.
Quoted 100 lines
Quoted 100 lines
drivers/media/dvb/frontends/hd29l2.c new file +100
-0+struct i2c_msg msg[1 ] = { + { + .addr = priv->cfg.i2c_addr, + .flags =0 , + .len =sizeof (buf), + .buf = buf, + } + }; + + buf[0 ] =0x00 ; + buf[1 ] = reg; +memcpy (&buf[2 ], val, len); + + ret =i2c_transfer (priv->i2c, msg,1 ); +if (ret ==1 ) { + ret =0 ; + }else { +warn ("i2c wr failed=%d reg=%02x len=%d" , ret, reg, len); + ret = -EREMOTEIO ; + } + +return ret; +} + +/* read multiple registers */ +static int hd29l2_rd_regs (struct hd29l2_priv *priv,u8 reg,u8 *val,int len) +{ +int ret; +u8 buf[2 ] = {0x00 , reg }; +struct i2c_msg msg[2 ] = { + { + .addr = priv->cfg.i2c_addr, + .flags =0 , + .len =2 , + .buf = buf, + }, { + .addr = priv->cfg.i2c_addr, + .flags =I2C_M_RD , + .len = len, + .buf = val, + } + }; + + ret =i2c_transfer (priv->i2c, msg,2 ); +if (ret ==2 ) { + ret =0 ; + }else { +warn ("i2c rd failed=%d reg=%02x len=%d" , ret, reg, len); + ret = -EREMOTEIO ; + } + +return ret; +} + +/* write single register */ +static int hd29l2_wr_reg (struct hd29l2_priv *priv,u8 reg,u8 val) +{ +return hd29l2_wr_regs (priv, reg,&val,1 ); +} + +/* read single register */ +static int hd29l2_rd_reg (struct hd29l2_priv *priv,u8 reg,u8 *val) +{ +return hd29l2_rd_regs (priv, reg, val,1 ); +} + +/* write single register with mask */ +static int hd29l2_wr_reg_mask (struct hd29l2_priv *priv,u8 reg,u8 val,u8 mask) +{ +int ret; +u8 tmp; + +/* no need for read if whole reg is written */ +if (mask !=0xff ) { + ret =hd29l2_rd_regs (priv, reg,&tmp,1 ); +if (ret) +return ret; + + val&= mask; + tmp&= ~mask; + val |= tmp; + } + +return hd29l2_wr_regs (priv, reg,&val,1 ); +} + +/* read single register with mask */ +int hd29l2_rd_reg_mask (struct hd29l2_priv *priv,u8 reg,u8 *val,u8 mask) +{ +int ret, i; +u8 tmp; + + ret =hd29l2_rd_regs (priv, reg,&tmp,1 ); +if (ret) +return ret; + + tmp&= mask; + +/* find position of the first bit */ +for (i =0 ; i<8 ; i++) {
Quoted 9 lines
drivers/media/dvb/frontends/hd29l2.c line 136
Quoted 3 lines
drivers/media/dvb/frontends/hd29l2.c new file +3
-0+if ((mask>> i)&0x01 ) +break ; + }Don't re-invent the wheel. Instead, please use the existing macros for it, defined at
linux/bitmap.h. In this case, it should likely be:
find_first_bit()
OK. I wasn't aware those bimacros.
Quoted 320 lines
Quoted 320 lines
drivers/media/dvb/frontends/hd29l2.c new file +320
-0+ *val = tmp>> i; + +return 0 ; +} + +static int hd29l2_soft_reset (struct hd29l2_priv *priv) +{ +int ret; +u8 tmp; + + ret =hd29l2_rd_reg (priv,0x26 ,&tmp); +if (ret) + goto err; + + ret =hd29l2_wr_reg (priv,0x26 ,0x0d ); +if (ret) + goto err; + +usleep_range (10000 ,20000 ); + + ret =hd29l2_wr_reg (priv,0x26 , tmp); +if (ret) + goto err; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_i2c_gate_ctrl (struct dvb_frontend *fe,int enable) +{ +int ret, i; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 tmp; + +dbg ("%s: enable=%d" , __func__, enable); + +/* set tuner address for demod */ +if (!priv->tuner_i2c_addr_programmed&& enable) { +/* no need to set tuner address every time, once is enough */ + ret =hd29l2_wr_reg (priv,0x9d , priv->cfg.tuner_i2c_addr<<1 ); +if (ret) + goto err; + + priv->tuner_i2c_addr_programmed = true; + } + +/* open / close gate */ + ret =hd29l2_wr_reg (priv,0x9f , enable); +if (ret) + goto err; + +/* wait demod ready */ +for (i =10 ; i; i--) { + ret =hd29l2_rd_reg (priv,0x9e ,&tmp); +if (ret) + goto err; + +if (tmp == enable) +break ; + +usleep_range (5000 ,10000 ); + } + +dbg ("%s: loop=%d" , __func__, i); + +return ret; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_status (struct dvb_frontend *fe,fe_status_t *status) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; + + *status =0 ; + + ret =hd29l2_rd_reg (priv,0x05 ,&buf[0 ]); +if (ret) + goto err; + +if (buf[0 ]&0x01 ) { +/* full lock */ + *status |=FE_HAS_SIGNAL |FE_HAS_CARRIER |FE_HAS_VITERBI | +FE_HAS_SYNC |FE_HAS_LOCK ; + }else { + ret =hd29l2_rd_reg (priv,0x0d ,&buf[1 ]); +if (ret) + goto err; + +if ((buf[1 ]&0xfe ) ==0x78 ) +/* partial lock */ + *status |=FE_HAS_SIGNAL |FE_HAS_CARRIER | +FE_HAS_VITERBI |FE_HAS_SYNC ; + } + + priv->fe_status = *status; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_snr (struct dvb_frontend *fe,u16 *snr) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; +u16 tmp; + +if (!(priv->fe_status&FE_HAS_LOCK )) { + *snr =0 ; + ret =0 ; + goto err; + } + + ret =hd29l2_rd_regs (priv,0x0b , buf,2 ); +if (ret) + goto err; + + tmp = (buf[0 ]<<8 ) | buf[1 ]; + +/* report SNR in dB * 10 */ +#define LOG10_20736_24 72422627/* log10(20736)<< 24 */ +if (tmp) + *snr = (LOG10_20736_24 -intlog10 (tmp)) / ((1 <<24 ) /100 ); +else + *snr =0 ; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_signal_strength (struct dvb_frontend *fe,u16 *strength) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; +u16 tmp; + + *strength =0 ; + + ret =hd29l2_rd_regs (priv,0xd5 , buf,2 ); +if (ret) + goto err; + + tmp = buf[0 ]<<8 | buf[1 ]; + tmp = ~tmp&0x0fff ; + +/* scale value to 0x0000-0xffff from 0x0000-0x0fff */ + *strength = tmp *0xffff /0x0fff ; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_ber (struct dvb_frontend *fe,u32 *ber) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 buf[2 ]; + +if (!(priv->fe_status&FE_HAS_SYNC )) { + *ber =0 ; + ret =0 ; + goto err; + } + + ret =hd29l2_rd_regs (priv,0xd9 , buf,2 ); +if (ret) { + *ber =0 ; + goto err; + } + +/* LDPC BER */ + *ber = ((buf[0 ]&0x0f )<<8 ) | buf[1 ]; + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_read_ucblocks (struct dvb_frontend *fe,u32 *ucblocks) +{ +/* no way to read? */ + *ucblocks =0 ; +return 0 ; +} + +static enum dvbfe_search hd29l2_search (struct dvb_frontend *fe, +struct dvb_frontend_parameters *p) +{ +int ret, i; +struct hd29l2_priv *priv = fe->demodulator_priv; +struct dtv_frontend_properties *c =&fe->dtv_property_cache; +u8 tmp, buf[3 ]; +u8 modulation, carrier, guard_interval, interleave, code_rate; +u64 num64; +u32 if_freq, if_ctl; +bool auto_mode; + +dbg ("%s: delivery_system=%d frequency=%d bandwidth_hz=%d " \ +"modulation=%d inversion=%d fec_inner=%d guard_interval=%d" , + __func__, + c->delivery_system, c->frequency, c->bandwidth_hz, + c->modulation, c->inversion, c->fec_inner, c->guard_interval); + +/* as for now we detect always params automatically */ + auto_mode = true; + +/* program tuner */ +if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params (fe, p); + +/* get and program IF */ +if (fe->ops.tuner_ops.get_if_frequency) + fe->ops.tuner_ops.get_if_frequency (fe,&if_freq); +else + if_freq =0 ; + +if (if_freq) { +/* normal IF */ + +/* calc IF control value */ + num64 = if_freq; + num64 *=0x800000 ; + num64 =div_u64 (num64,HD29L2_XTAL ); + num64 -=0x800000 ; + if_ctl = num64; + + tmp =0xfc ;/* tuner type normal */ + }else { +/* zero IF */ + if_ctl =0 ; + tmp =0xfe ;/* tuner type Zero-IF */ + } + + buf[0 ] = ((if_ctl>>0 )&0xff ); + buf[1 ] = ((if_ctl>>8 )&0xff ); + buf[2 ] = ((if_ctl>>16 )&0xff ); + +/* program IF control */ + ret =hd29l2_wr_regs (priv,0x14 , buf,3 ); +if (ret) + goto err; + +/* program tuner type */ + ret =hd29l2_wr_reg (priv,0xab , tmp); +if (ret) + goto err; + +dbg ("%s: if_ctl=%x" , __func__, if_ctl); + +if (auto_mode) { +/* +* use auto mode +*/ + +/* disable quick mode */ + ret =hd29l2_wr_reg_mask (priv,0xac ,0 <<7 ,0x80 ); +if (ret) + goto err; + + ret =hd29l2_wr_reg_mask (priv,0x82 ,1 <<1 ,0x02 ); +if (ret) + goto err; + +/* enable auto mode */ + ret =hd29l2_wr_reg_mask (priv,0x7d ,1 <<6 ,0x40 ); +if (ret) + goto err; + + ret =hd29l2_wr_reg_mask (priv,0x81 ,1 <<3 ,0x08 ); +if (ret) + goto err; + +/* soft reset */ + ret =hd29l2_soft_reset (priv); +if (ret) + goto err; + +/* detect modulation */ +for (i =30 ; i; i--) { +msleep (100 ); + + ret =hd29l2_rd_reg (priv,0x0d ,&tmp); +if (ret) + goto err; + +if ((((tmp&0xf0 )>=0x10 )&& + ((tmp&0x0f ) ==0x08 )) || (tmp>=0x2c )) +break ; + } + +dbg ("%s: loop=%d" , __func__, i); + +if (i ==0 ) +/* detection failed */ +return DVBFE_ALGO_SEARCH_FAILED ; + +/* read modulation */ + ret =hd29l2_rd_reg_mask (priv,0x7d ,&modulation,0x07 ); +if (ret) + goto err; + }else { +/* +* use manual mode +*/ + + modulation =HD29L2_QAM64 ;
Quoted 9 lines
drivers/media/dvb/frontends/hd29l2.c line 460
Quoted 4 lines
drivers/media/dvb/frontends/hd29l2.c new file +4
-0+ carrier =HD29L2_CARRIER_MULTI ; + guard_interval =HD29L2_PN945 ; + interleave =HD29L2_INTERLEAVER_420 ; + code_rate =HD29L2_CODE_RATE_08 ;Hmm... all DMB-TH properties are already available at the DVB core? It would be great if you could document what properties are valid for this delivery system at the DocBook specs.
API does not know DMB-TH. I added those like documentation purposes that can be easily taken use when API supports. Now there is both AUTO and MANUAL implemented by driver, but it is forced as AUTO always since API does not support DMB-TH paramters.
Quoted 23 lines
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ + tmp = (code_rate<<3 ) | modulation; + ret =hd29l2_wr_reg_mask (priv,0x7d , tmp,0x5f ); +if (ret) + goto err; + + tmp = (carrier<<2 ) | guard_interval; + ret =hd29l2_wr_reg_mask (priv,0x81 , tmp,0x0f ); +if (ret) + goto err;drivers/media/dvb/frontends/hd29l2.c line 480
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ + tmp = interleave; + ret =hd29l2_wr_reg_mask (priv,0x82 , tmp,0x03 ); +if (ret) + goto err; + } + +/* ensure modulation validy */ +/* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */ +if (modulation>4 ) {Please, don't use magic values.
Quoted 2 lines
Instead, it should be something like:
ARRAY_SIZE(reg_mod_vals_tab[0].val)
?
Quoted 3 lines
Still, I don't understand why modulation should be QAM64 when the
auto_modeis disabled. Shouldn't it be provided via a DVB property?
API does not support DMB-TH params. See my earlier comment.
Quoted 94 lines
Quoted 94 lines
drivers/media/dvb/frontends/hd29l2.c new file +93
-0+dbg ("%s: modulation=%d not valid" , __func__, modulation); + goto err; + } + +/* program registers according to modulation */ +for (i =0 ; i<ARRAY_SIZE (reg_mod_vals_tab); i++) { + ret =hd29l2_wr_reg (priv, reg_mod_vals_tab[i].reg, + reg_mod_vals_tab[i].val[modulation]); +if (ret) + goto err; + } + +/* read guard interval */ + ret =hd29l2_rd_reg_mask (priv,0x81 ,&guard_interval,0x03 ); +if (ret) + goto err; + +/* read carrier mode */ + ret =hd29l2_rd_reg_mask (priv,0x81 ,&carrier,0x04 ); +if (ret) + goto err; + +dbg ("%s: modulation=%d guard_interval=%d carrier=%d" , + __func__, modulation, guard_interval, carrier); + +if ((carrier ==HD29L2_CARRIER_MULTI )&& (modulation ==HD29L2_QAM64 )&& + (guard_interval ==HD29L2_PN945 )) { +dbg ("%s: C=3780&& QAM64&& PN945" , __func__); + + ret =hd29l2_wr_reg (priv,0x42 ,0x33 ); +if (ret) + goto err; + + ret =hd29l2_wr_reg (priv,0xdd ,0x01 ); +if (ret) + goto err; + } + +usleep_range (10000 ,20000 ); + +/* soft reset */ + ret =hd29l2_soft_reset (priv); +if (ret) + goto err; + +/* wait demod lock */ +for (i =30 ; i; i--) { +msleep (100 ); + +/* read lock bit */ + ret =hd29l2_rd_reg_mask (priv,0x05 ,&tmp,0x01 ); +if (ret) + goto err; + +if (tmp) +break ; + } + +dbg ("%s: loop=%d" , __func__, i); + +if (i ==0 ) +return DVBFE_ALGO_SEARCH_AGAIN ; + +return DVBFE_ALGO_SEARCH_SUCCESS ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return DVBFE_ALGO_SEARCH_ERROR ; +} + +static int hd29l2_get_frontend_algo (struct dvb_frontend *fe) +{ +return DVBFE_ALGO_CUSTOM ; +} + +static int hd29l2_get_frontend (struct dvb_frontend *fe, +struct dvb_frontend_parameters *p) +{ +int ret; +struct hd29l2_priv *priv = fe->demodulator_priv; +struct dtv_frontend_properties *c =&fe->dtv_property_cache; +u8 buf[3 ]; +u32 if_ctl; +char *str_constellation, *str_code_rate, *str_constellation_code_rate, + *str_guard_interval, *str_carrier, *str_guard_interval_carrier, + *str_interleave, *str_interleave_; + + ret =hd29l2_rd_reg (priv,0x7d ,&buf[0 ]); +if (ret) + goto err; + + ret =hd29l2_rd_regs (priv,0x81 ,&buf[1 ],2 ); +if (ret) + goto err;
Quoted 8 lines
drivers/media/dvb/frontends/hd29l2.c line 579
Quoted 6 lines
drivers/media/dvb/frontends/hd29l2.c new file +6
-0+ +/* constellation, 0x7d[2:0] */ +switch ((buf[0 ]>>0 )&0x07 ) { +case 0 :/* QAM4NR */ + str_constellation ="QAM4NR" ; + c->modulation =QAM_AUTO ;/* FIXME */ Please, don't abuse
QAM_AUTO.
API does not support DMB-TH.
Quoted 7 lines
drivers/media/dvb/frontends/hd29l2.c line 583
Quoted 5 lines
drivers/media/dvb/frontends/hd29l2.c new file +4
-0+break ; +case 1 :/* QAM4 */ + str_constellation ="QAM4" ; + c->modulation =QPSK ;/* FIXME */ QPSK and QAM4 are two names for the same encoding.
I wasn't 100% sure if those are same or not, thats why added comment.
Maybe we should add #define QAM4 QPSK to API since QAM4 is much more commonly used. I think QPSK is seen mostly when dealing with DVB-T.
Quoted 17 lines
Quoted 4 lines
drivers/media/dvb/frontends/hd29l2.c new file +3
-0+break ; +case 2 : + str_constellation ="QAM16" ;drivers/media/dvb/frontends/hd29l2.c line 596
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ c->modulation =QAM_16 ; +break ; +case 3 : + str_constellation ="QAM32" ; + c->modulation =QAM_32 ; +break ; +case 4 : + str_constellation ="QAM64" ; + c->modulation =QAM_64 ; +break ;Please, avoid magic numbers. Instead, use macros for each value.
I disagree that. Those numbers are coming from demodulator register value. Same way is used almost every driver that supports reading current transmission params from the demod.
Quoted 14 lines
drivers/media/dvb/frontends/hd29l2.c line 605
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +9
-0+default : + str_constellation ="?" ; + } + +/* LDPC code rate, 0x7d[4:3] */ +switch ((buf[0 ]>>3 )&0x03 ) { +case 0 :/* 0.4 */ + str_code_rate ="0.4" ; + c->fec_inner =FEC_AUTO ;/* FIXME */ Also, please don't abuse
FEC_AUTO. Should likely beFEC_2_5, and you'll likely need to add it to the API.
True. It is same API issue again :)
Quoted 35 lines
Quoted 35 lines
drivers/media/dvb/frontends/hd29l2.c new file +34
-0+break ; +case 1 :/* 0.6 */ + str_code_rate ="0.6" ; + c->fec_inner =FEC_3_5 ; +break ; +case 2 :/* 0.8 */ + str_code_rate ="0.8" ; + c->fec_inner =FEC_4_5 ; +break ; +default : + str_code_rate ="?" ; + } + +/* constellation& code rate set, 0x7d[6] */ +switch ((buf[0 ]>>6 )&0x01 ) { +case 0 : + str_constellation_code_rate ="manual" ; +break ; +case 1 : + str_constellation_code_rate ="auto" ; +break ; +default : + str_constellation_code_rate ="?" ; + } + +/* frame header, 0x81[1:0] */ +switch ((buf[1 ]>>0 )&0x03 ) { +case 0 :/* PN945 */ + str_guard_interval ="PN945" ; + c->guard_interval =GUARD_INTERVAL_AUTO ;/* FIXME */ +break ; +case 1 :/* PN595 */ + str_guard_interval ="PN595" ; + c->guard_interval =GUARD_INTERVAL_AUTO ;/* FIXME */
Quoted 9 lines
drivers/media/dvb/frontends/hd29l2.c line 644
Quoted 5 lines
drivers/media/dvb/frontends/hd29l2.c new file +5
-0+break ; +case 2 :/* PN420 */ + str_guard_interval ="PN420" ; + c->guard_interval =GUARD_INTERVAL_AUTO ;/* FIXME */ +break ;Again, don't abuse over the API. Instead, add the proper guard intervals into it.
API issue again. I did that because DMB-TH was not supported.
Anyhow, I would like to ask why you even mention those as those are commented clearly to be not correctly?
That is very commonly used method of our demod drivers. Look all existing DMB-TH drivers and you can see same.
Quoted 11 lines
Quoted 11 lines
drivers/media/dvb/frontends/hd29l2.c new file +11
-0+default : + str_guard_interval ="?" ; + } + +/* carrier, 0x81[2] */ +switch ((buf[1 ]>>2 )&0x01 ) { +case 0 : + str_carrier ="C=1" ; +break ; +case 1 : + str_carrier ="C=3780" ;
Quoted 8 lines
drivers/media/dvb/frontends/hd29l2.c line 659
Quoted 4 lines
drivers/media/dvb/frontends/hd29l2.c new file +4
-0+break ; +default : + str_carrier ="?" ; + }Probably, API needs to support it. I'm not familiar with DMB specs, but I think you need to first send a patch adding support for it at the DocBook and
linux/dvb/frontends.h, and then add the driver.
API issue. There is no interleaver defined.
Quoted 90 lines
Quoted 72 lines
drivers/media/dvb/frontends/hd29l2.c new file +71
-0+ +/* frame header& carrier set, 0x81[3] */ +switch ((buf[1 ]>>3 )&0x01 ) { +case 0 : + str_guard_interval_carrier ="manual" ; +break ; +case 1 : + str_guard_interval_carrier ="auto" ; +break ; +default : + str_guard_interval_carrier ="?" ; + } + +/* interleave, 0x82[0] */ +switch ((buf[2 ]>>0 )&0x01 ) { +case 0 : + str_interleave ="M=720" ; +break ; +case 1 : + str_interleave ="M=240" ; +break ; +default : + str_interleave ="?" ; + } + +/* interleave set, 0x82[1] */ +switch ((buf[2 ]>>1 )&0x01 ) { +case 0 : + str_interleave_ ="manual" ; +break ; +case 1 : + str_interleave_ ="auto" ; +break ; +default : + str_interleave_ ="?" ; + } + +/* +* We can read out current detected NCO and use that value next +* time instead of calculating new value from targed IF. +* I think it will not effect receiver sensitivity but gaining lock +* after tune could be easier... +*/ + ret =hd29l2_rd_regs (priv,0xb1 ,&buf[0 ],3 ); +if (ret) + goto err; + + if_ctl = (buf[0 ]<<16 ) | ((buf[1 ] -7 )<<8 ) | buf[2 ]; + +dbg ("%s: %s %s %s | %s %s %s | %s %s | NCO=%06x" , __func__, + str_constellation, str_code_rate, str_constellation_code_rate, + str_guard_interval, str_carrier, str_guard_interval_carrier, + str_interleave, str_interleave_, if_ctl); + +return 0 ; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static int hd29l2_init (struct dvb_frontend *fe) +{ +int ret, i; +struct hd29l2_priv *priv = fe->demodulator_priv; +u8 tmp; +static const struct reg_val tab[] = { + {0x3a ,0x06 }, + {0x3b ,0x03 }, + {0x3c ,0x04 }, + {0xaf ,0x06 }, + {0xb0 ,0x1b },drivers/media/dvb/frontends/hd29l2.c line 740
Quoted 10 lines
drivers/media/dvb/frontends/hd29l2.c new file +10
-0+ { 0x80, 0x64 }, + { 0x10, 0x38 }, + }; + +dbg ("%s:" , __func__); + +/* reset demod */ +/* it is recommended to HW reset chip using RST_N pin */ +if (fe->callback) { + ret = fe->callback (fe,0 ,0 ,0 );This looks weird on my eyes. The
fe->callbackis tuner-dependent. So, the command you should use there requires a test for the tuner type.In other words, if you're needing to use it, the code should be doing something similar to:
Quoted 8 lines
if (fe->callback&& priv->tuner_type == TUNER_XC2028) ret = fe->callback(fe, 0, XC2028_TUNER_RESET, 0);(the actual coding will depend on how do you store the tuner type, and what are the commands for the tuner you're using)
That's said, it probably makes sense to deprecate
fe->callbackin favor or a more generic set of callbacks, likefe->tuner_reset().
Yes it is wrong because there was no DEMOD defined. But, the callback itself is correctly. IIRC there was only TUNER defined and no DEMOD. Look callback definition from the API. It is very simply to fix. But at the time left it like that, because I wanted to avoid touching one file more. I will fix it properly later (2 line change).
And it was not a bug, it was just my known decision. I just forget to comment it as FIXME or TODO.
Quoted 510 lines
Quoted 510 lines
drivers/media/dvb/frontends/hd29l2.c new file +123
-0+if (ret) + goto err; + +/* reprogramming needed because HW reset clears registers */ + priv->tuner_i2c_addr_programmed = false; + } + +/* init */ +for (i =0 ; i<ARRAY_SIZE (tab); i++) { + ret =hd29l2_wr_reg (priv, tab[i].reg, tab[i].val); +if (ret) + goto err; + } + +/* TS params */ + ret =hd29l2_rd_reg (priv,0x36 ,&tmp); +if (ret) + goto err; + + tmp&=0x1b ; + tmp |= priv->cfg.ts_mode; + ret =hd29l2_wr_reg (priv,0x36 , tmp); +if (ret) + goto err; + + ret =hd29l2_rd_reg (priv,0x31 ,&tmp); + tmp&=0xef ; + +if (!(priv->cfg.ts_mode>>7 )) +/* set b4 for serial TS */ + tmp |=0x10 ; + + ret =hd29l2_wr_reg (priv,0x31 , tmp); +if (ret) + goto err; + +return ret; +err: +dbg ("%s: failed=%d" , __func__, ret); +return ret; +} + +static void hd29l2_release (struct dvb_frontend *fe) +{ +struct hd29l2_priv *priv = fe->demodulator_priv; +kfree (priv); +} + +static struct dvb_frontend_ops hd29l2_ops; + +struct dvb_frontend *hd29l2_attach (const struct hd29l2_config *config, +struct i2c_adapter *i2c) +{ +int ret; +struct hd29l2_priv *priv =NULL ; +u8 tmp; + +/* allocate memory for the internal state */ + priv =kzalloc (sizeof (struct hd29l2_priv ),GFP_KERNEL ); +if (priv ==NULL ) + goto err; + +/* setup the state */ + priv->i2c = i2c; +memcpy (&priv->cfg, config,sizeof (struct hd29l2_config )); + + +/* check if the demod is there */ + ret =hd29l2_rd_reg (priv,0x00 ,&tmp); +if (ret) + goto err; + +/* create dvb_frontend */ +memcpy (&priv->fe.ops,&hd29l2_ops,sizeof (struct dvb_frontend_ops )); + priv->fe.demodulator_priv = priv; + +return &priv->fe; +err: +kfree (priv); +return NULL ; +} +EXPORT_SYMBOL (hd29l2_attach); + +static struct dvb_frontend_ops hd29l2_ops = { + .info = { + .name ="HDIC HD29L2 DMB-TH" , + .type =FE_OFDM , + .frequency_min =474000000 , + .frequency_max =858000000 , + .frequency_stepsize =10000 , + .caps =FE_CAN_FEC_AUTO | +FE_CAN_QPSK | +FE_CAN_QAM_16 | +FE_CAN_QAM_32 | +FE_CAN_QAM_64 | +FE_CAN_QAM_AUTO | +FE_CAN_TRANSMISSION_MODE_AUTO | +FE_CAN_BANDWIDTH_AUTO | +FE_CAN_GUARD_INTERVAL_AUTO | +FE_CAN_HIERARCHY_AUTO | +FE_CAN_RECOVER + }, + + .release = hd29l2_release, + + .init = hd29l2_init, + + .get_frontend_algo = hd29l2_get_frontend_algo, + .search = hd29l2_search, + .get_frontend = hd29l2_get_frontend, + + .read_status = hd29l2_read_status, + .read_snr = hd29l2_read_snr, + .read_signal_strength = hd29l2_read_signal_strength, + .read_ber = hd29l2_read_ber, + .read_ucblocks = hd29l2_read_ucblocks, + + .i2c_gate_ctrl = hd29l2_i2c_gate_ctrl, +}; + +MODULE_AUTHOR ("Antti Palosaari<[email protected]>" ); +MODULE_DESCRIPTION ("HDIC HD29L2 DMB-TH demodulator driver" ); +MODULE_LICENSE ("GPL" );drivers/media/dvb/frontends/hd29l2.h new file +66
-0@@ -0,0 +1,66 @@ +/* +* HDIC HD29L2 DMB-TH demodulator driver +* +* Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D +* +* Author: Antti Palosaari<[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef HD29L2_H +#define HD29L2_H + +#include <linux/dvb/frontend.h> + +struct hd29l2_config { +/* +* demodulator I2C address +*/ +u8 i2c_addr; + +/* +* tuner I2C address +* only needed when tuner is behind demod I2C-gate +*/ +u8 tuner_i2c_addr; + +/* +* TS settings +*/ +#define HD29L2_TS_SERIAL 0x00 +#define HD29L2_TS_PARALLEL 0x80 +#define HD29L2_TS_CLK_NORMAL 0x40 +#define HD29L2_TS_CLK_INVERTED 0x00 +#define HD29L2_TS_CLK_GATED 0x20 +#define HD29L2_TS_CLK_FREE 0x00 +u8 ts_mode; +}; + + +#if defined(CONFIG_DVB_HD29L2 ) || \ + (defined(CONFIG_DVB_HD29L2_MODULE )&& defined(MODULE )) +extern struct dvb_frontend *hd29l2_attach (const struct hd29l2_config *config, +struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *hd29l2_attach ( +const struct hd29l2_config *config,struct i2c_adapter *i2c) +{ +printk (KERN_WARNING "%s: driver disabled by Kconfig\n" , __func__); +return NULL ; +} +#endif + +#endif /* HD29L2_H */ drivers/media/dvb/frontends/hd29l2_priv.h new file +309
-0@@ -0,0 +1,314 @@ +/* +* HDIC HD29L2 DMB-TH demodulator driver +* +* Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D +* +* Author: Antti Palosaari<[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef HD29L2_PRIV +#define HD29L2_PRIV + +#include <linux/dvb/version.h> +#include "dvb_frontend.h" +#include "dvb_math.h" +#include "hd29l2.h" + +#define LOG_PREFIX "hd29l2" + +#undef dbg +#define dbg(f, arg...) \ + if (hd29l2_debug) \ + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + +#define HD29L2_XTAL 30400000/* Hz */ + + +#define HD29L2_QAM4NR 0x00 +#define HD29L2_QAM4 0x01 +#define HD29L2_QAM16 0x02 +#define HD29L2_QAM32 0x03 +#define HD29L2_QAM64 0x04 + +#define HD29L2_CODE_RATE_04 0x00 +#define HD29L2_CODE_RATE_06 0x08 +#define HD29L2_CODE_RATE_08 0x10 + +#define HD29L2_PN945 0x00 +#define HD29L2_PN595 0x01 +#define HD29L2_PN420 0x02 + +#define HD29L2_CARRIER_SINGLE 0x00 +#define HD29L2_CARRIER_MULTI 0x01 + +#define HD29L2_INTERLEAVER_720 0x00 +#define HD29L2_INTERLEAVER_420 0x01 + +struct reg_val { +u8 reg; +u8 val; +}; + +struct reg_mod_vals { +u8 reg; +u8 val[5 ]; +}; + +struct hd29l2_priv { +struct i2c_adapter *i2c; +struct dvb_frontend fe; +struct hd29l2_config cfg; +u8 tuner_i2c_addr_programmed:1 ; + +fe_status_t fe_status; +}; + +static const struct reg_mod_vals reg_mod_vals_tab[] = { +/* REG, QAM4NR, QAM4,QAM16,QAM32,QAM64 */ + {0x01 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x02 , {0x07 ,0x07 ,0x07 ,0x07 ,0x07 } }, + {0x03 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x04 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x05 , {0x61 ,0x60 ,0x60 ,0x61 ,0x60 } }, + {0x06 , {0xff ,0xff ,0xff ,0xff ,0xff } }, + {0x07 , {0xff ,0xff ,0xff ,0xff ,0xff } }, + {0x08 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x09 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x0a , {0x15 ,0x15 ,0x03 ,0x03 ,0x03 } }, + {0x0d , {0x78 ,0x78 ,0x88 ,0x78 ,0x78 } }, + {0x0e , {0xa0 ,0x90 ,0xa0 ,0xa0 ,0xa0 } }, + {0x0f , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x10 , {0xa0 ,0xa0 ,0x58 ,0x38 ,0x38 } }, + {0x11 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x12 , {0x5a ,0x5a ,0x5a ,0x5a ,0x5a } }, + {0x13 , {0xa2 ,0xa2 ,0xa2 ,0xa2 ,0xa2 } }, + {0x17 , {0x40 ,0x40 ,0x40 ,0x40 ,0x40 } }, + {0x18 , {0x21 ,0x21 ,0x42 ,0x52 ,0x42 } }, + {0x19 , {0x21 ,0x21 ,0x62 ,0x72 ,0x62 } }, + {0x1a , {0x32 ,0x43 ,0xa9 ,0xb9 ,0xa9 } }, + {0x1b , {0x32 ,0x43 ,0xb9 ,0xd8 ,0xb9 } }, + {0x1c , {0x02 ,0x02 ,0x03 ,0x02 ,0x03 } }, + {0x1d , {0x0c ,0x0c ,0x01 ,0x02 ,0x02 } }, + {0x1e , {0x02 ,0x02 ,0x02 ,0x01 ,0x02 } }, + {0x1f , {0x02 ,0x02 ,0x01 ,0x02 ,0x04 } }, + {0x20 , {0x01 ,0x02 ,0x01 ,0x01 ,0x01 } }, + {0x21 , {0x08 ,0x08 ,0x0a ,0x0a ,0x0a } }, + {0x22 , {0x06 ,0x06 ,0x04 ,0x05 ,0x05 } }, + {0x23 , {0x06 ,0x06 ,0x05 ,0x03 ,0x05 } }, + {0x24 , {0x08 ,0x08 ,0x05 ,0x07 ,0x07 } }, + {0x25 , {0x16 ,0x10 ,0x10 ,0x0a ,0x10 } }, + {0x26 , {0x14 ,0x14 ,0x04 ,0x04 ,0x04 } }, + {0x27 , {0x58 ,0x58 ,0x58 ,0x5c ,0x58 } }, + {0x28 , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0x29 , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0x2a , {0x08 ,0x0a ,0x08 ,0x08 ,0x08 } }, + {0x2b , {0x08 ,0x08 ,0x08 ,0x08 ,0x08 } }, + {0x2c , {0x06 ,0x06 ,0x06 ,0x06 ,0x06 } }, + {0x2d , {0x05 ,0x06 ,0x06 ,0x06 ,0x06 } }, + {0x2e , {0x21 ,0x21 ,0x21 ,0x21 ,0x21 } }, + {0x2f , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x30 , {0x14 ,0x14 ,0x14 ,0x14 ,0x14 } }, + {0x33 , {0xb7 ,0xb7 ,0xb7 ,0xb7 ,0xb7 } }, + {0x34 , {0x81 ,0x81 ,0x81 ,0x81 ,0x81 } }, + {0x35 , {0x80 ,0x80 ,0x80 ,0x80 ,0x80 } }, + {0x37 , {0x70 ,0x70 ,0x70 ,0x70 ,0x70 } }, + {0x38 , {0x04 ,0x04 ,0x02 ,0x02 ,0x02 } }, + {0x39 , {0x07 ,0x07 ,0x05 ,0x05 ,0x05 } }, + {0x3a , {0x06 ,0x06 ,0x06 ,0x06 ,0x06 } }, + {0x3b , {0x03 ,0x03 ,0x03 ,0x03 ,0x03 } }, + {0x3c , {0x07 ,0x06 ,0x04 ,0x04 ,0x04 } }, + {0x3d , {0xf0 ,0xf0 ,0xf0 ,0xf0 ,0x80 } }, + {0x3e , {0x60 ,0x60 ,0x60 ,0x60 ,0xff } }, + {0x3f , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x40 , {0x5b ,0x5b ,0x5b ,0x57 ,0x50 } }, + {0x41 , {0x30 ,0x30 ,0x30 ,0x30 ,0x18 } }, + {0x42 , {0x20 ,0x20 ,0x20 ,0x00 ,0x30 } }, + {0x43 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x44 , {0x3f ,0x3f ,0x3f ,0x3f ,0x3f } }, + {0x45 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x46 , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0x47 , {0x00 ,0x00 ,0x95 ,0x00 ,0x95 } }, + {0x48 , {0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0 } }, + {0x49 , {0xc0 ,0xc0 ,0xc0 ,0xc0 ,0xc0 } }, + {0x4a , {0x40 ,0x40 ,0x33 ,0x11 ,0x11 } }, + {0x4b , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x4c , {0x40 ,0x40 ,0x99 ,0x11 ,0x11 } }, + {0x4d , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x4e , {0x40 ,0x40 ,0x66 ,0x77 ,0x77 } }, + {0x4f , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x50 , {0x40 ,0x40 ,0x88 ,0x33 ,0x11 } }, + {0x51 , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x52 , {0x40 ,0x40 ,0x88 ,0x02 ,0x02 } }, + {0x53 , {0x40 ,0x40 ,0x00 ,0x02 ,0x02 } }, + {0x54 , {0x00 ,0x00 ,0x88 ,0x33 ,0x33 } }, + {0x55 , {0x40 ,0x40 ,0x00 ,0x00 ,0x00 } }, + {0x56 , {0x00 ,0x00 ,0x00 ,0x0b ,0x00 } }, + {0x57 , {0x40 ,0x40 ,0x0a ,0x0b ,0x0a } }, + {0x58 , {0xaa ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x59 , {0x7a ,0x40 ,0x02 ,0x02 ,0x02 } }, + {0x5a , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5b , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5c , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5d , {0x18 ,0x18 ,0x01 ,0x01 ,0x01 } }, + {0x5e , {0xc0 ,0xc0 ,0xc0 ,0xff ,0xc0 } }, + {0x5f , {0xc0 ,0xc0 ,0xc0 ,0xff ,0xc0 } }, + {0x60 , {0x40 ,0x40 ,0x00 ,0x30 ,0x30 } }, + {0x61 , {0x40 ,0x40 ,0x10 ,0x30 ,0x30 } }, + {0x62 , {0x40 ,0x40 ,0x00 ,0x30 ,0x30 } }, + {0x63 , {0x40 ,0x40 ,0x05 ,0x30 ,0x30 } }, + {0x64 , {0x40 ,0x40 ,0x06 ,0x00 ,0x30 } }, + {0x65 , {0x40 ,0x40 ,0x06 ,0x08 ,0x30 } }, + {0x66 , {0x40 ,0x40 ,0x00 ,0x00 ,0x20 } }, + {0x67 , {0x40 ,0x40 ,0x01 ,0x04 ,0x20 } }, + {0x68 , {0x00 ,0x00 ,0x30 ,0x00 ,0x20 } }, + {0x69 , {0xa0 ,0xa0 ,0x00 ,0x08 ,0x20 } }, + {0x6a , {0x00 ,0x00 ,0x30 ,0x00 ,0x25 } }, + {0x6b , {0xa0 ,0xa0 ,0x00 ,0x06 ,0x25 } }, + {0x6c , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x6d , {0xa0 ,0x60 ,0x0c ,0x03 ,0x0c } }, + {0x6e , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x6f , {0xa0 ,0x60 ,0x04 ,0x01 ,0x04 } }, + {0x70 , {0x58 ,0x58 ,0xaa ,0xaa ,0xaa } }, + {0x71 , {0x58 ,0x58 ,0xaa ,0xaa ,0xaa } }, + {0x72 , {0x58 ,0x58 ,0xff ,0xff ,0xff } }, + {0x73 , {0x58 ,0x58 ,0xff ,0xff ,0xff } }, + {0x74 , {0x06 ,0x06 ,0x09 ,0x05 ,0x05 } }, + {0x75 , {0x06 ,0x06 ,0x0a ,0x10 ,0x10 } }, + {0x76 , {0x10 ,0x10 ,0x06 ,0x0a ,0x0a } }, + {0x77 , {0x12 ,0x18 ,0x28 ,0x10 ,0x28 } }, + {0x78 , {0xf8 ,0xf8 ,0xf8 ,0xf8 ,0xf8 } }, + {0x79 , {0x15 ,0x15 ,0x03 ,0x03 ,0x03 } }, + {0x7a , {0x02 ,0x02 ,0x01 ,0x04 ,0x03 } }, + {0x7b , {0x01 ,0x02 ,0x03 ,0x03 ,0x03 } }, + {0x7c , {0x28 ,0x28 ,0x28 ,0x28 ,0x28 } }, + {0x7f , {0x25 ,0x92 ,0x5f ,0x17 ,0x2d } }, + {0x80 , {0x64 ,0x64 ,0x64 ,0x74 ,0x64 } }, + {0x83 , {0x06 ,0x03 ,0x04 ,0x04 ,0x04 } }, + {0x84 , {0xff ,0xff ,0xff ,0xff ,0xff } }, + {0x85 , {0x05 ,0x05 ,0x05 ,0x05 ,0x05 } }, + {0x86 , {0x00 ,0x00 ,0x11 ,0x11 ,0x11 } }, + {0x87 , {0x03 ,0x03 ,0x03 ,0x03 ,0x03 } }, + {0x88 , {0x09 ,0x09 ,0x09 ,0x09 ,0x09 } }, + {0x89 , {0x20 ,0x20 ,0x30 ,0x20 ,0x20 } }, + {0x8a , {0x03 ,0x03 ,0x02 ,0x03 ,0x02 } }, + {0x8b , {0x00 ,0x07 ,0x09 ,0x00 ,0x09 } }, + {0x8c , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x8d , {0x4f ,0x4f ,0x4f ,0x3f ,0x4f } }, + {0x8e , {0xf0 ,0xf0 ,0x60 ,0xf0 ,0xa0 } }, + {0x8f , {0xe8 ,0xe8 ,0xe8 ,0xe8 ,0xe8 } }, + {0x90 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x91 , {0x40 ,0x40 ,0x70 ,0x70 ,0x10 } }, + {0x92 , {0x00 ,0x00 ,0x00 ,0x00 ,0x04 } }, + {0x93 , {0x60 ,0x60 ,0x60 ,0x60 ,0x60 } }, + {0x94 , {0x00 ,0x00 ,0x00 ,0x00 ,0x03 } }, + {0x95 , {0x09 ,0x09 ,0x47 ,0x47 ,0x47 } }, + {0x96 , {0x80 ,0xa0 ,0xa0 ,0x40 ,0xa0 } }, + {0x97 , {0x60 ,0x60 ,0x60 ,0x60 ,0x60 } }, + {0x98 , {0x50 ,0x50 ,0x50 ,0x30 ,0x50 } }, + {0x99 , {0x10 ,0x10 ,0x10 ,0x10 ,0x10 } }, + {0x9a , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0x9b , {0x40 ,0x40 ,0x40 ,0x30 ,0x40 } }, + {0x9c , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa0 , {0xf0 ,0xf0 ,0xf0 ,0xf0 ,0xf0 } }, + {0xa1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa2 , {0x30 ,0x30 ,0x00 ,0x30 ,0x00 } }, + {0xa3 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa4 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa5 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa6 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa7 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xa8 , {0x77 ,0x77 ,0x77 ,0x77 ,0x77 } }, + {0xa9 , {0x02 ,0x02 ,0x02 ,0x02 ,0x02 } }, + {0xaa , {0x40 ,0x40 ,0x40 ,0x40 ,0x40 } }, + {0xac , {0x1f ,0x1f ,0x1f ,0x1f ,0x1f } }, + {0xad , {0x14 ,0x14 ,0x14 ,0x14 ,0x14 } }, + {0xae , {0x78 ,0x78 ,0x78 ,0x78 ,0x78 } }, + {0xaf , {0x06 ,0x06 ,0x06 ,0x06 ,0x07 } }, + {0xb0 , {0x1b ,0x1b ,0x1b ,0x19 ,0x1b } }, + {0xb1 , {0x18 ,0x17 ,0x17 ,0x18 ,0x17 } }, + {0xb2 , {0x35 ,0x82 ,0x82 ,0x38 ,0x82 } }, + {0xb3 , {0xb6 ,0xce ,0xc7 ,0x5c ,0xb0 } }, + {0xb4 , {0x3f ,0x3e ,0x3e ,0x3f ,0x3e } }, + {0xb5 , {0x70 ,0x58 ,0x50 ,0x68 ,0x50 } }, + {0xb6 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xb7 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xb8 , {0x03 ,0x03 ,0x01 ,0x01 ,0x01 } }, + {0xb9 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xba , {0x06 ,0x06 ,0x0a ,0x05 ,0x0a } }, + {0xbb , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbc , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbd , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbe , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xbf , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc0 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc2 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc3 , {0x00 ,0x00 ,0x88 ,0x66 ,0x88 } }, + {0xc4 , {0x10 ,0x10 ,0x00 ,0x00 ,0x00 } }, + {0xc5 , {0x00 ,0x00 ,0x44 ,0x60 ,0x44 } }, + {0xc6 , {0x10 ,0x0a ,0x00 ,0x00 ,0x00 } }, + {0xc7 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc8 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xc9 , {0x90 ,0x04 ,0x00 ,0x00 ,0x00 } }, + {0xca , {0x90 ,0x08 ,0x01 ,0x01 ,0x01 } }, + {0xcb , {0xa0 ,0x04 ,0x00 ,0x44 ,0x00 } }, + {0xcc , {0xa0 ,0x10 ,0x03 ,0x00 ,0x03 } }, + {0xcd , {0x06 ,0x06 ,0x06 ,0x05 ,0x06 } }, + {0xce , {0x05 ,0x05 ,0x01 ,0x01 ,0x01 } }, + {0xcf , {0x40 ,0x20 ,0x18 ,0x18 ,0x18 } }, + {0xd0 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd2 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd3 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xd4 , {0x05 ,0x05 ,0x05 ,0x05 ,0x05 } }, + {0xd5 , {0x05 ,0x05 ,0x05 ,0x03 ,0x05 } }, + {0xd6 , {0xac ,0x22 ,0xca ,0x8f ,0xca } }, + {0xd7 , {0x20 ,0x20 ,0x20 ,0x20 ,0x20 } }, + {0xd8 , {0x01 ,0x01 ,0x01 ,0x01 ,0x01 } }, + {0xd9 , {0x00 ,0x00 ,0x0f ,0x00 ,0x0f } }, + {0xda , {0x00 ,0xff ,0xff ,0x0e ,0xff } }, + {0xdb , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0xdc , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0xdd , {0x05 ,0x05 ,0x05 ,0x05 ,0x05 } }, + {0xde , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + {0xdf , {0x42 ,0x42 ,0x44 ,0x44 ,0x04 } }, + {0xe0 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe1 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe2 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe3 , {0x00 ,0x00 ,0x26 ,0x06 ,0x26 } }, + {0xe4 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe5 , {0x01 ,0x0a ,0x01 ,0x01 ,0x01 } }, + {0xe6 , {0x00 ,0x00 ,0x00 ,0x00 ,0x00 } }, + {0xe7 , {0x08 ,0x08 ,0x08 ,0x08 ,0x08 } }, + {0xe8 , {0x63 ,0x63 ,0x63 ,0x63 ,0x63 } }, + {0xe9 , {0x59 ,0x59 ,0x59 ,0x59 ,0x59 } }, + {0xea , {0x80 ,0x80 ,0x20 ,0x80 ,0x80 } }, + {0xeb , {0x37 ,0x37 ,0x78 ,0x37 ,0x77 } }, + {0xec , {0x1f ,0x1f ,0x25 ,0x25 ,0x25 } }, + {0xed , {0x0a ,0x0a ,0x0a ,0x0a ,0x0a } }, + { 0xee, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
Quoted 9 lines
Quoted 8 lines
drivers/media/dvb/frontends/hd29l2_priv.h new file +5
-1+ { 0xef, { 0x70, 0x70, 0x58, 0x38, 0x58 } }, + { 0xf0, { 0x00, 0x00, 0x00, 0x00, 0x00 } }, +}; + +#endif /* HD29L2_PRIV */ --1.7.7.4
After all as I see there is no big bugs. Those findings are mostly related of missing DMB-TH API support (and was even commented clearly). And 1-2 CodingStyle issues.
As there is still few other DMB-TH drivers having similar issues already in the master I don't see why not to add that too. Anyhow, if you see that must be put to staging until DMB-TH is defined to API it is OK for me.
regards
Antti
Signature · 1 line
http://palosaari.fi/
Quoted 11 lines · Antti Palosaari
Quoted 9 lines · Mauro Carvalho Chehab
Review
Quoted 4 lines
(quoted diff) +4
-0+ + /* ensure modulation validy */ + /* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */ + if (modulation> 4) {Please, don't use magic values.
Instead, it should be something like:
ARRAY_SIZE(reg_mod_vals_tab[0].val)?
Why "4" and not "8" (or whatever)? You're using 4 to avoid a buffer overflow on your table. As such, please explicitly code it with ARRAY_SIZE, instead of using a 4 "magic" number.
Quoted 6 lines
Quoted 4 lines
Still, I don't understand why modulation should be QAM64 when the
auto_modeis disabled. Shouldn't it be provided via a DVB property?API does not support DMB-TH params. See my earlier comment.
Ok, add support for it then ;)
Quoted 11 lines
Quoted 6 lines
Review
Quoted 4 lines
(quoted diff) +4
-0+ break; + case 1: /* QAM4 */ + str_constellation = "QAM4"; + c->modulation = QPSK; /* FIXME */QPSK and QAM4 are two names for the same encoding.
I wasn't 100% sure if those are same or not, thats why added comment.
Maybe we should add #define QAM4 QPSK to API since QAM4 is much more commonly used. I think QPSK is seen mostly when dealing with DVB-T.
I would just add a comment at the frontends.h file. Otherwise, we would need to replace it on every place.
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
(quoted diff) +13
-0+ break; + case 2: + str_constellation = "QAM16"; + c->modulation = QAM_16; + break; + case 3: + str_constellation = "QAM32"; + c->modulation = QAM_32; + break; + case 4: + str_constellation = "QAM64"; + c->modulation = QAM_64; + break;
Quoted 6 lines
Quoted 2 lines
Please, avoid magic numbers. Instead, use macros for each value.
I disagree that. Those numbers are coming from demodulator register value. Same way is used almost every driver that supports reading current transmission params from the demod.
There are drivers that don't code it well, but it is always preferred to use macros for register values. Good drivers have it.
Quoted 8 lines
Quoted 3 lines
Again, don't abuse over the API. Instead, add the proper guard intervals into it.
API issue again. I did that because DMB-TH was not supported.
Anyhow, I would like to ask why you even mention those as those are commented clearly to be not correctly?
That is very commonly used method of our demod drivers. Look all existing DMB-TH drivers and you can see same.
The other DMB drivers are ugly and only support whatever they call "auto". I won't doubt that they implement only a subset of the existing modulations, FEC's, etc.
I wouldn't be surprised if they only support whatever someone discovered from sniffing the i2c traffic.
Quoted 21 lines
Quoted 12 lines
Review
Quoted 4 lines
(quoted diff) +4
-0+ /* reset demod */ + /* it is recommended to HW reset chip using RST_N pin */ + if (fe->callback) { + ret = fe->callback(fe, 0, 0, 0);This looks weird on my eyes. The
fe->callbackis tuner-dependent. So, the command you should use there requires a test for the tuner type.In other words, if you're needing to use it, the code should be doing something similar to:
Quoted 8 lines
if (fe->callback&& priv->tuner_type == TUNER_XC2028) ret = fe->callback(fe, 0, XC2028_TUNER_RESET, 0);(the actual coding will depend on how do you store the tuner type, and what are the commands for the tuner you're using)
That's said, it probably makes sense to deprecate
fe->callbackin favor or a more generic set of callbacks, likefe->tuner_reset().
Quoted 7 lines
Yes it is wrong because there was no DEMOD defined. But, the callback itself is correctly. IIRC there was only TUNER defined and no DEMOD. Look callback definition from the API. It is very simply to fix. But at the time left it like that, because I wanted to avoid touching one file more. I will fix it properly later (2 line change).
And it was not a bug, it was just my known decision. I just forget to comment it as FIXME or TODO.
Feel free to touch on other files, provided that you fix that. There's no default behavior for fe->callback, as it were written in order to provide ways for the tuner to call the bridge driver for some device-specific reasons. So, the commands are defined with macros, and the callback code should be device-specific.
Quoted 2 lines
After all as I see there is no big bugs. Those findings are mostly related of missing DMB-TH API support (and was even commented clearly). And 1-2 CodingStyle issues.
One issue is pure CodingStyle. The other no-API related aren't.
Quoted 3 lines
As there is still few other DMB-TH drivers having similar issues already in the master I don't see why not to add that too. Anyhow, if you see that must be put to staging until DMB-TH is defined to API it is OK for me.
Please fix the non-API related issues. If you ack to provide us the API improvements for DMB for 3.4, and get rid of "auto_mode = true" for all cases, I'm ok on merging it after the fixes at drivers/media/dvb.
Regards,
Mauro
Quoted 20 lines · Mauro Carvalho Chehab
Quoted 19 lines · Antti Palosaari
Quoted 16 lines · Mauro Carvalho Chehab
Review
Quoted 13 lines
(quoted diff) +13
-0+ break; + case 2: + str_constellation = "QAM16"; + c->modulation = QAM_16; + break; + case 3: + str_constellation = "QAM32"; + c->modulation = QAM_32; + break; + case 4: + str_constellation = "QAM64"; + c->modulation = QAM_64; + break;Please, avoid magic numbers. Instead, use macros for each value.
Quoted 6 lines
Quoted 3 lines
I disagree that. Those numbers are coming from demodulator register value. Same way is used almost every driver that supports reading current transmission params from the demod.
There are drivers that don't code it well, but it is always preferred to use macros for register values. Good drivers have it.
I still disagree. Are we speaking same issue?
val = read_reg(rgister)
switch (val) {
case 2:
c->modulation = QAM_16; break; case 3: c->modulation = QAM_32; break; }
Why I should define macros here?
Or do you mean I should define macros for the selecting correct bits from the register?
Anyhow, for me that piece of code looks very clear. And it is used similarly very many drivers.
Quoted 5 lines
Quoted 2 lines
After all as I see there is no big bugs. Those findings are mostly related of missing DMB-TH API support (and was even commented clearly). And 1-2 CodingStyle issues.
One issue is pure CodingStyle. The other no-API related aren't.
Quoted 7 lines
Quoted 3 lines
As there is still few other DMB-TH drivers having similar issues already in the master I don't see why not to add that too. Anyhow, if you see that must be put to staging until DMB-TH is defined to API it is OK for me.
Please fix the non-API related issues. If you ack to provide us the API improvements for DMB for 3.4, and get rid of "
auto_mode= true" for all cases, I'm ok on merging it after the fixes atdrivers/media/dvb.
If I don't add DMB-TH support to API you will push that to the staging?
Adding those to API is not mission impossible. Interleaver is only new parameter and all the rest are just extending values. But my time is limited... and I really would like to finally got Anysee smart card reader integrated to USB serial first.
regards
Antti
Signature · 1 line
http://palosaari.fi/
Hi all,
Quoted 4 lines · On Tuesday 20 December 2011 16:42:53 Antti Palosaari wrote:
Adding those to API is not mission impossible. Interleaver is only new parameter and all the rest are just extending values. But my time is limited... and I really would like to finally got Anysee smart card reader integrated to USB serial first.
And if it is added we should not forget to discuess whether DMB-TH is the "right" name. (If this has already been addressed in another thread please point me to it).
I know this standard under at least 2 different names: CTTB and DTMB.
Which is the one to choose?
best regards,
--
Patrick
Kernel Labs Inc.
http://www.kernellabs.com/
Re: [GIT PULL FOR 3.3] HDIC HD29L2 DMB-TH demodulator driv
Quoted 8 lines · Patrick Boettcher
Hi all,
Quoted 4 lines · On Tuesday 20 December 2011 16:42:53 Antti Palosaari wrote:
Adding those to API is not mission impossible. Interleaver is only new parameter and all the rest are just extending values. But my time is limited... and I really would like to finally got Anysee smart card reader integrated to USB serial first.
Quoted 7 lines
And if it is added we should not forget to discuess whether DMB-TH is the "right" name. (If this has already been addressed in another thread please point me to it).
I know this standard under at least 2 different names: CTTB and DTMB.
Which is the one to choose?
Yes, there is many names and it is not even clear for me what are differences between names. I called it DMB-TH since existing Kernel drivers have selected that name.
http://en.wikipedia.org/wiki/CMMB
http://en.wikipedia.org/wiki/DTMB
http://en.wikipedia.org/wiki/Digital_Multimedia_Broadcasting
http://en.wikipedia.org/wiki/Digital_Terrestrial_Multimedia_Broadcast
CMMB
CTTB
DTMB (DTMB-T/H, DMB-T/H)
DMB (T-DMB)
Antti
Signature · 1 line
http://palosaari.fi/
Re: [GIT PULL FOR 3.3] HDIC HD29L2 DMB-TH demodulator driv
Quoted 26 lines · Antti Palosaari
Quoted 8 lines · Patrick Boettcher
Hi all,
Quoted 4 lines · On Tuesday 20 December 2011 16:42:53 Antti Palosaari wrote:
Adding those to API is not mission impossible. Interleaver is only new parameter and all the rest are just extending values. But my time is limited... and I really would like to finally got Anysee smart card reader integrated to USB serial first.
Quoted 7 lines
And if it is added we should not forget to discuess whether DMB-TH is the "right" name. (If this has already been addressed in another thread please point me to it).
I know this standard under at least 2 different names: CTTB and DTMB.
Which is the one to choose?
Yes, there is many names and it is not even clear for me what are differences between names. I called it DMB-TH since existing Kernel drivers have selected that name.
http://en.wikipedia.org/wiki/CMMB
http://en.wikipedia.org/wiki/DTMB
http://en.wikipedia.org/wiki/Digital_Multimedia_Broadcasting
http://en.wikipedia.org/wiki/Digital_Terrestrial_Multimedia_Broadcast
Quoted 4 lines
CMMB
CTTB
DTMB (DTMB-T/H, DMB-T/H)
DMB (T-DMB)
DMB seems to be much different so drop it out. DTMB seems to be official term for DMB-T/H. CMMB seems to be for small devices (mobile), maybe subset of DTMB. Finally I have CTTB and DTMB which seems to be equivalents. DTMB is more common.
So I end up for the DTMB. I give my vote for that.
regards
Antti
Signature · 1 line
http://palosaari.fi/
Re: [GIT PULL FOR 3.3] HDIC HD29L2 DMB-TH demodulator driv
Quoted 27 lines · Antti Palosaari
Quoted 26 lines · Antti Palosaari
Quoted 8 lines · Patrick Boettcher
Hi all,
Quoted 4 lines · On Tuesday 20 December 2011 16:42:53 Antti Palosaari wrote:
Adding those to API is not mission impossible. Interleaver is only new parameter and all the rest are just extending values. But my time is limited... and I really would like to finally got Anysee smart card reader integrated to USB serial first.
Quoted 7 lines
And if it is added we should not forget to discuess whether DMB-TH is the "right" name. (If this has already been addressed in another thread please point me to it).
I know this standard under at least 2 different names: CTTB and DTMB.
Which is the one to choose?
Yes, there is many names and it is not even clear for me what are differences between names. I called it DMB-TH since existing Kernel drivers have selected that name.
http://en.wikipedia.org/wiki/CMMB
http://en.wikipedia.org/wiki/DTMB
http://en.wikipedia.org/wiki/Digital_Multimedia_Broadcasting
http://en.wikipedia.org/wiki/Digital_Terrestrial_Multimedia_Broadcast
Quoted 8 lines
Quoted 4 lines
CMMB
CTTB
DTMB (DTMB-T/H, DMB-T/H)
DMB (T-DMB)DMB seems to be much different so drop it out. DTMB seems to be official term for DMB-T/H. CMMB seems to be for small devices (mobile), maybe subset of DTMB. Finally I have CTTB and DTMB which seems to be equivalents. DTMB is more common.
So I end up for the DTMB. I give my vote for that.
I also vote for DTMB. It seems to be the more adequate one.
Regards,
Mauro
Re: [GIT PULL FOR 3.3] HDIC HD29L2 DMB-TH demodulator driv
Quoted 35 lines · On Tuesday 20 December 2011 19:09:14 Mauro Carvalho Chehab wrote:
Quoted 34 lines · Antti Palosaari
Quoted 32 lines · Antti Palosaari
Quoted 8 lines · Patrick Boettcher
Hi all,
Quoted 4 lines · On Tuesday 20 December 2011 16:42:53 Antti Palosaari wrote:
Adding those to API is not mission impossible. Interleaver is only new parameter and all the rest are just extending values. But my time is limited... and I really would like to finally got Anysee smart card reader integrated to USB serial first.
Quoted 8 lines
And if it is added we should not forget to discuess whether DMB-TH is the "right" name. (If this has already been addressed in another thread please point me to it).
I know this standard under at least 2 different names: CTTB and DTMB.
Which is the one to choose?
Yes, there is many names and it is not even clear for me what are differences between names. I called it DMB-TH since existing Kernel drivers have selected that name.
http://en.wikipedia.org/wiki/CMMB
http://en.wikipedia.org/wiki/DTMB
http://en.wikipedia.org/wiki/Digital_Multimedia_Broadcasting
http://en.wikipedia.org/wiki/Digital_Terrestrial_Multimedia_Broadc
astCMMB
CTTB
DTMB (DTMB-T/H, DMB-T/H)
DMB (T-DMB)
Quoted 6 lines
Quoted 6 lines
DMB seems to be much different so drop it out. DTMB seems to be official term for DMB-T/H. CMMB seems to be for small devices (mobile), maybe subset of DTMB. Finally I have CTTB and DTMB which seems to be equivalents. DTMB is more common.
So I end up for the DTMB. I give my vote for that.
CMMB has nothing to do with DTMB/CTTB. It modulations parameters and physical/link layers are completely different compared to CMMB.
I'll vote for CTTB as this is the (latest) official name. At least this is what DiBcom's Chinese representatives state.
Maybe there are some Chinese on this list to enlighten this situation?
--
Patrick Boettcher
Kernel Labs Inc.
http://www.kernellabs.com/
A message that is not in the archive (sent off-list or not yet received): CAOcJUbygkw-UJ4=V3vsRT8VtdrjhNwng9KQr_FFe=CdsybUBXQ@mail.gmail.com
Quoted 57 lines · Michael Krufky
Quoted 28 lines · Mauro Carvalho Chehab
Quoted 27 lines · Antti Palosaari
Quoted 12 lines
Review
Quoted 4 lines
(quoted diff) +4
-0+ /* reset demod */ + /* it is recommended to HW reset chip using RST_N pin */ + if (fe->callback) { + ret = fe->callback(fe, 0, 0, 0);This looks weird on my eyes. The
fe->callbackis tuner-dependent. So, the command you should use there requires a test for the tuner type.In other words, if you're needing to use it, the code should be doing something similar to:
Quoted 8 lines
if (fe->callback&& priv->tuner_type == TUNER_XC2028) ret = fe->callback(fe, 0, XC2028_TUNER_RESET, 0);(the actual coding will depend on how do you store the tuner type, and what are the commands for the tuner you're using)
That's said, it probably makes sense to deprecate
fe->callbackin favor or a more generic set of callbacks, likefe->tuner_reset().Yes it is wrong because there was no DEMOD defined. But, the callback itself is correctly. IIRC there was only TUNER defined and no DEMOD. Look callback definition from the API. It is very simply to fix. But at the time left it like that, because I wanted to avoid touching one file more. I will fix it properly later (2 line change).
Quoted 7 lines
Quoted 1 line
And it was not a bug, it was just my known decision. I just forget to comment it as FIXME or TODO.
Feel free to touch on other files, provided that you fix that. There's no default behavior for
fe->callback, as it were written in order to provide ways for the tuner to call the bridge driver for some device-specific reasons. So, the commands are defined with macros, and the callback code should be device-specific.This generic callback was written for the BRIDGE driver to be called by any frontend COMPONENT, not specifically the tuner, perhaps a demod or LNB, but at the time of writing, we only needed it from the tuner so the
DVB_FRONTEND_COMPONENT_TUNER(0)was the only #define created at the time. This was written with forward-compatibility in mind, so lets please not deprecate it unless we actually have to -- I see additional uses for this coming in the future.In order to use fe callback properly, please add "#define
DVB_FRONTEND_COMPONENT_DEMOD1" todvb-core/dvb_frontend.h, and simply call your callback asfe->callback(adap_state, DVB_FRONTEND_COMPONENT_DEMOD, CMD, ARG)... This way, the callback knows that it is being called by the demod and not the tuner, it is receiving command CMD with argument ARG.I can imagine a need one day to perhaps convert the "int arg" into a "void* arg", but such a need doesn't exist today. I don't think it gets any more generic than this.
Quoted 5 lines
int (*callback)(void *adapter_priv, int component, int cmd, int arg);Cheers,
Mike
+1 for that. It was just what I also was thinking :) I will add that demod component define to the internal API and it is fixed properly.
regards
Antti
Signature · 1 line
http://palosaari.fi/