summaryrefslogtreecommitdiff
path: root/drivers/media/dvb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c2
-rw-r--r--drivers/media/dvb/ddbridge/ddbridge-core.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c10
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.h2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c80
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h18
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig13
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c495
-rw-r--r--drivers/media/dvb/dvb-usb/af9035.c1242
-rw-r--r--drivers/media/dvb/dvb-usb/af9035.h113
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c24
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c7
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h12
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c12
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h3
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c76
-rw-r--r--drivers/media/dvb/dvb-usb/it913x.c4
-rw-r--r--drivers/media/dvb/dvb-usb/lmedm04.c5
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-tuner.c1
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf.c850
-rw-r--r--drivers/media/dvb/dvb-usb/rtl28xxu.c28
-rw-r--r--drivers/media/dvb/frontends/Kconfig35
-rw-r--r--drivers/media/dvb/frontends/Makefile7
-rw-r--r--drivers/media/dvb/frontends/af9013.c13
-rw-r--r--drivers/media/dvb/frontends/af9033.c980
-rw-r--r--drivers/media/dvb/frontends/af9033.h75
-rw-r--r--drivers/media/dvb/frontends/af9033_priv.h470
-rw-r--r--drivers/media/dvb/frontends/au8522_common.c259
-rw-r--r--drivers/media/dvb/frontends/au8522_dig.c215
-rw-r--r--drivers/media/dvb/frontends/au8522_priv.h2
-rw-r--r--drivers/media/dvb/frontends/cx24110.c7
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_core.c4
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c5
-rw-r--r--drivers/media/dvb/frontends/dib9000.c131
-rw-r--r--drivers/media/dvb/frontends/drxd.h14
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.c18
-rw-r--r--drivers/media/dvb/frontends/drxk_map.h2
-rw-r--r--drivers/media/dvb/frontends/ds3000.c5
-rw-r--r--drivers/media/dvb/frontends/it913x-fe.c26
-rw-r--r--drivers/media/dvb/frontends/lg2160.c1468
-rw-r--r--drivers/media/dvb/frontends/lg2160.h84
-rw-r--r--drivers/media/dvb/frontends/lgs8gxx.c3
-rw-r--r--drivers/media/dvb/frontends/m88rs2000.c29
-rw-r--r--drivers/media/dvb/frontends/rtl2830.c201
-rw-r--r--drivers/media/dvb/frontends/rtl2830_priv.h1
-rw-r--r--drivers/media/dvb/frontends/stb0899_drv.c8
-rw-r--r--drivers/media/dvb/frontends/stb6100.c3
-rw-r--r--drivers/media/dvb/frontends/stv0297.c2
-rw-r--r--drivers/media/dvb/frontends/stv0900_sw.c2
-rw-r--r--drivers/media/dvb/frontends/stv090x.c2
-rw-r--r--drivers/media/dvb/frontends/zl10353.c5
-rw-r--r--drivers/media/dvb/mantis/hopper_cards.c3
-rw-r--r--drivers/media/dvb/mantis/mantis_cards.c3
-rw-r--r--drivers/media/dvb/mantis/mantis_dma.c4
-rw-r--r--drivers/media/dvb/mantis/mantis_evm.c3
-rw-r--r--drivers/media/dvb/ngene/ngene-core.c4
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c8
-rw-r--r--drivers/media/dvb/siano/smssdio.c4
-rw-r--r--drivers/media/dvb/siano/smsusb.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c72
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c6
62 files changed, 6396 insertions, 792 deletions
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 48e48e8af55a..66f52f116b60 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -477,7 +477,6 @@ static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message
static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
{
int i = 0;
- unsigned int ca_message_header_len;
u32 command = 0;
struct ca_msg *hw_buffer;
@@ -496,7 +495,6 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (p_ca_message->msg) {
- ca_message_header_len = p_ca_message->length; /* Restore it back when you are done */
/* EN50221 tag */
command = 0;
diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c
index d88c4aa7d24d..131b938e9e81 100644
--- a/drivers/media/dvb/ddbridge/ddbridge-core.c
+++ b/drivers/media/dvb/ddbridge/ddbridge-core.c
@@ -31,7 +31,6 @@
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/timer.h>
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/swab.h>
#include <linux/vmalloc.h>
@@ -1696,7 +1695,7 @@ static struct pci_driver ddb_pci_driver = {
.name = "DDBridge",
.id_table = ddb_id_tbl,
.probe = ddb_probe,
- .remove = ddb_remove,
+ .remove = __devexit_p(ddb_remove),
};
static __init int module_init_ddbridge(void)
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index faa3671b649e..d82469f842e2 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -568,6 +568,16 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
+void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+ spin_lock(&demux->lock);
+
+ demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
+
+ spin_unlock(&demux->lock);
+}
+EXPORT_SYMBOL(dvb_dmx_swfilter_raw);
+
static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
{
int i;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index a7d876fd02dd..fa7188a253aa 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -145,5 +145,7 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
size_t count);
+void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
+ size_t count);
#endif /* _DVB_DEMUX_H_ */
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index cb888d835a89..aebcdf221dda 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -182,13 +182,13 @@ static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
case SYS_DMBTH:
return DVBV3_OFDM;
case SYS_ATSC:
+ case SYS_ATSCMH:
case SYS_DVBC_ANNEX_B:
return DVBV3_ATSC;
case SYS_UNDEFINED:
case SYS_ISDBC:
case SYS_DVBH:
case SYS_DAB:
- case SYS_ATSCMH:
default:
/*
* Doesn't know how to emulate those types and/or
@@ -1030,6 +1030,25 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_HIERARCHY, 0, 0),
_DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
+
+ _DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0),
+ _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0),
+
+ _DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_PARADE_ID, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_NOG, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_TNOG, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_SGN, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_PRC, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
+ _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
};
static void dtv_property_dump(struct dtv_property *tvp)
@@ -1121,6 +1140,8 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe,
case DVBV3_ATSC:
dprintk("%s() Preparing ATSC req\n", __func__);
c->modulation = p->u.vsb.modulation;
+ if (c->delivery_system == SYS_ATSCMH)
+ break;
if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
c->delivery_system = SYS_ATSC;
else
@@ -1367,6 +1388,54 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
case DTV_DVBT2_PLP_ID:
tvp->u.data = c->dvbt2_plp_id;
break;
+
+ /* ATSC-MH */
+ case DTV_ATSCMH_FIC_VER:
+ tvp->u.data = fe->dtv_property_cache.atscmh_fic_ver;
+ break;
+ case DTV_ATSCMH_PARADE_ID:
+ tvp->u.data = fe->dtv_property_cache.atscmh_parade_id;
+ break;
+ case DTV_ATSCMH_NOG:
+ tvp->u.data = fe->dtv_property_cache.atscmh_nog;
+ break;
+ case DTV_ATSCMH_TNOG:
+ tvp->u.data = fe->dtv_property_cache.atscmh_tnog;
+ break;
+ case DTV_ATSCMH_SGN:
+ tvp->u.data = fe->dtv_property_cache.atscmh_sgn;
+ break;
+ case DTV_ATSCMH_PRC:
+ tvp->u.data = fe->dtv_property_cache.atscmh_prc;
+ break;
+ case DTV_ATSCMH_RS_FRAME_MODE:
+ tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_mode;
+ break;
+ case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
+ tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_ensemble;
+ break;
+ case DTV_ATSCMH_RS_CODE_MODE_PRI:
+ tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_pri;
+ break;
+ case DTV_ATSCMH_RS_CODE_MODE_SEC:
+ tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_sec;
+ break;
+ case DTV_ATSCMH_SCCC_BLOCK_MODE:
+ tvp->u.data = fe->dtv_property_cache.atscmh_sccc_block_mode;
+ break;
+ case DTV_ATSCMH_SCCC_CODE_MODE_A:
+ tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_a;
+ break;
+ case DTV_ATSCMH_SCCC_CODE_MODE_B:
+ tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_b;
+ break;
+ case DTV_ATSCMH_SCCC_CODE_MODE_C:
+ tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_c;
+ break;
+ case DTV_ATSCMH_SCCC_CODE_MODE_D:
+ tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d;
+ break;
+
default:
return -EINVAL;
}
@@ -1708,6 +1777,15 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
case DTV_DVBT2_PLP_ID:
c->dvbt2_plp_id = tvp->u.data;
break;
+
+ /* ATSC-MH */
+ case DTV_ATSCMH_PARADE_ID:
+ fe->dtv_property_cache.atscmh_parade_id = tvp->u.data;
+ break;
+ case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
+ fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data;
+ break;
+
default:
return -EINVAL;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index d63a8215fe03..e929d5697b87 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -372,6 +372,24 @@ struct dtv_frontend_properties {
/* DVB-T2 specifics */
u32 dvbt2_plp_id;
+
+ /* ATSC-MH specifics */
+ u8 atscmh_fic_ver;
+ u8 atscmh_parade_id;
+ u8 atscmh_nog;
+ u8 atscmh_tnog;
+ u8 atscmh_sgn;
+ u8 atscmh_prc;
+
+ u8 atscmh_rs_frame_mode;
+ u8 atscmh_rs_frame_ensemble;
+ u8 atscmh_rs_code_mode_pri;
+ u8 atscmh_rs_code_mode_sec;
+ u8 atscmh_sccc_block_mode;
+ u8 atscmh_sccc_code_mode_a;
+ u8 atscmh_sccc_code_mode_b;
+ u8 atscmh_sccc_code_mode_c;
+ u8 atscmh_sccc_code_mode_d;
};
struct dvb_frontend {
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 63bf45679f98..a26949336b3d 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -409,6 +409,7 @@ config DVB_USB_MXL111SF
tristate "MxL111SF DTV USB2.0 support"
depends on DVB_USB
select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+ select DVB_LG2160 if !DVB_FE_CUSTOMISE
select VIDEO_TVEEPROM
help
Say Y here to support the MxL111SF USB2.0 DTV receiver.
@@ -422,3 +423,15 @@ config DVB_USB_RTL28XXU
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
help
Say Y here to support the Realtek RTL28xxU DVB USB receiver.
+
+config DVB_USB_AF9035
+ tristate "Afatech AF9035 DVB-T USB2.0 support"
+ depends on DVB_USB
+ select DVB_AF9033
+ select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE
+ help
+ Say Y here to support the Afatech AF9035 based DVB USB receiver.
+
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index b76acb5387e6..b667ac39a4e3 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -110,6 +110,9 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
dvb-usb-rtl28xxu-objs = rtl28xxu.o
obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o
+dvb-usb-af9035-objs = af9035.o
+obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o
+
ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/
# due to tuner-xc3028
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 7e70ea50ef26..677fed79b01e 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -244,8 +244,7 @@ static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
u8 uninitialized_var(mbox), addr_len;
struct req_t req;
-/* TODO: implement bus lock
-
+/*
The bus lock is needed because there is two tuners both using same I2C-address.
Due to that the only way to select correct tuner is use demodulator I2C-gate.
@@ -789,7 +788,7 @@ static void af9015_set_remote_config(struct usb_device *udev,
/* try to load remote based USB ID */
if (!props->rc.core.rc_codes)
props->rc.core.rc_codes = af9015_rc_setup_match(
- (vid << 16) + pid, af9015_rc_setup_usbids);
+ (vid << 16) | pid, af9015_rc_setup_usbids);
/* try to load remote based USB iManufacturer string */
if (!props->rc.core.rc_codes && vid == USB_VID_AFATECH) {
@@ -1220,8 +1219,8 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
}
/* attach demodulator */
- adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
- &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(af9013_attach,
+ &af9015_af9013_config[adap->id], &adap->dev->i2c_adap);
/*
* AF9015 firmware does not like if it gets interrupted by I2C adapter
@@ -1324,14 +1323,15 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
switch (af9015_af9013_config[adap->id].tuner) {
case AF9013_TUNER_MT2060:
case AF9013_TUNER_MT2060_2:
- ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
- &af9015_mt2060_config,
+ ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, &af9015_mt2060_config,
af9015_config.mt2060_if1[adap->id])
== NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_QT1010:
case AF9013_TUNER_QT1010A:
- ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
+ ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap,
&af9015_qt1010_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_TDA18271:
@@ -1434,69 +1434,85 @@ enum af9015_usb_table_entry {
};
static struct usb_device_id af9015_usb_table[] = {
- [AFATECH_9015] =
- {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)},
- [AFATECH_9016] =
- {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)},
- [WINFAST_DTV_GOLD] =
- {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)},
- [PINNACLE_PCTV_71E] =
- {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)},
- [KWORLD_PLUSTV_399U] =
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)},
- [TINYTWIN] = {USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN)},
- [AZUREWAVE_TU700] =
- {USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700)},
- [TERRATEC_AF9015] = {USB_DEVICE(USB_VID_TERRATEC,
+ [AFATECH_9015] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)},
+ [AFATECH_9016] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)},
+ [WINFAST_DTV_GOLD] = {
+ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)},
+ [PINNACLE_PCTV_71E] = {
+ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)},
+ [KWORLD_PLUSTV_399U] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)},
+ [TINYTWIN] = {
+ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN)},
+ [AZUREWAVE_TU700] = {
+ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700)},
+ [TERRATEC_AF9015] = {
+ USB_DEVICE(USB_VID_TERRATEC,
USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
- [KWORLD_PLUSTV_PC160] =
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)},
- [AVERTV_VOLAR_X] =
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
- [XTENSIONS_380U] =
- {USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
- [MSI_DIGIVOX_DUO] =
- {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)},
- [AVERTV_VOLAR_X_REV2] =
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
- [TELESTAR_STARSTICK_2] =
- {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)},
- [AVERMEDIA_A309_USB] =
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
- [MSI_DIGIVOX_MINI_III] =
- {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
- [KWORLD_E396] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
- [KWORLD_E39B] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
- [KWORLD_E395] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
- [TREKSTOR_DVBT] = {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
- [AVERTV_A850] = {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
- [AVERTV_A805] = {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
- [CONCEPTRONIC_CTVDIGRCU] =
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
- [KWORLD_MC810] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
- [GENIUS_TVGO_DVB_T03] =
- {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
- [KWORLD_399U_2] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
- [KWORLD_PC160_T] =
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
- [SVEON_STV20] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
- [TINYTWIN_2] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
- [WINFAST_DTV2000DS] =
- {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
- [KWORLD_UB383_T] =
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
- [KWORLD_E39A] =
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
- [AVERMEDIA_A815M] =
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
- [CINERGY_T_STICK_RC] = {USB_DEVICE(USB_VID_TERRATEC,
+ [KWORLD_PLUSTV_PC160] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)},
+ [AVERTV_VOLAR_X] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
+ [XTENSIONS_380U] = {
+ USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
+ [MSI_DIGIVOX_DUO] = {
+ USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)},
+ [AVERTV_VOLAR_X_REV2] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
+ [TELESTAR_STARSTICK_2] = {
+ USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)},
+ [AVERMEDIA_A309_USB] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
+ [MSI_DIGIVOX_MINI_III] = {
+ USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
+ [KWORLD_E396] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
+ [KWORLD_E39B] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
+ [KWORLD_E395] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
+ [TREKSTOR_DVBT] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
+ [AVERTV_A850] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
+ [AVERTV_A805] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
+ [CONCEPTRONIC_CTVDIGRCU] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
+ [KWORLD_MC810] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
+ [GENIUS_TVGO_DVB_T03] = {
+ USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
+ [KWORLD_399U_2] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
+ [KWORLD_PC160_T] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
+ [SVEON_STV20] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
+ [TINYTWIN_2] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
+ [WINFAST_DTV2000DS] = {
+ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
+ [KWORLD_UB383_T] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
+ [KWORLD_E39A] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
+ [AVERMEDIA_A815M] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
+ [CINERGY_T_STICK_RC] = {
+ USB_DEVICE(USB_VID_TERRATEC,
USB_PID_TERRATEC_CINERGY_T_STICK_RC)},
- [CINERGY_T_DUAL_RC] = {USB_DEVICE(USB_VID_TERRATEC,
+ [CINERGY_T_DUAL_RC] = {
+ USB_DEVICE(USB_VID_TERRATEC,
USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
- [AVERTV_A850T] =
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
- [TINYTWIN_3] = {USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)},
- [SVEON_STV22] = {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)},
+ [AVERTV_A850T] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
+ [TINYTWIN_3] = {
+ USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)},
+ [SVEON_STV22] = {
+ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)},
{ }
};
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1516,43 +1532,44 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
- .num_frontends = 1,
- .fe = {{
- .caps = DVB_USB_ADAP_HAS_PID_FILTER |
- DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
- .pid_filter_count = 32,
- .pid_filter = af9015_pid_filter,
- .pid_filter_ctrl = af9015_pid_filter_ctrl,
-
- .frontend_attach =
- af9015_af9013_frontend_attach,
- .tuner_attach = af9015_tuner_attach,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x84,
+ .num_frontends = 1,
+ .fe = {
+ {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 32,
+ .pid_filter = af9015_pid_filter,
+ .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+ .frontend_attach = af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ },
+ }
},
- }},
},
{
- .num_frontends = 1,
- .fe = {{
- .frontend_attach =
- af9015_af9013_frontend_attach,
- .tuner_attach = af9015_tuner_attach,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x85,
- .u = {
- .bulk = {
- .buffersize =
- TS_USB20_FRAME_SIZE,
- }
+ .num_frontends = 1,
+ .fe = {
+ {
+ .frontend_attach = af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x85,
+ .u = {
+ .bulk = {
+ .buffersize = TS_USB20_FRAME_SIZE,
+ }
+ }
+ },
}
},
- }},
}
},
@@ -1575,102 +1592,67 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.cold_ids = {
&af9015_usb_table[AFATECH_9015],
&af9015_usb_table[AFATECH_9016],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Leadtek WinFast DTV Dongle Gold",
.cold_ids = {
&af9015_usb_table[WINFAST_DTV_GOLD],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Pinnacle PCTV 71e",
.cold_ids = {
&af9015_usb_table[PINNACLE_PCTV_71E],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "KWorld PlusTV Dual DVB-T Stick " \
"(DVB-T 399U)",
.cold_ids = {
&af9015_usb_table[KWORLD_PLUSTV_399U],
&af9015_usb_table[KWORLD_399U_2],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "DigitalNow TinyTwin DVB-T Receiver",
.cold_ids = {
&af9015_usb_table[TINYTWIN],
&af9015_usb_table[TINYTWIN_2],
&af9015_usb_table[TINYTWIN_3],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "TwinHan AzureWave AD-TU700(704J)",
.cold_ids = {
&af9015_usb_table[AZUREWAVE_TU700],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "TerraTec Cinergy T USB XE",
.cold_ids = {
&af9015_usb_table[TERRATEC_AF9015],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "KWorld PlusTV Dual DVB-T PCI " \
"(DVB-T PC160-2T)",
.cold_ids = {
&af9015_usb_table[KWORLD_PLUSTV_PC160],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "AVerMedia AVerTV DVB-T Volar X",
.cold_ids = {
&af9015_usb_table[AVERTV_VOLAR_X],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "TerraTec Cinergy T Stick RC",
.cold_ids = {
&af9015_usb_table[CINERGY_T_STICK_RC],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "TerraTec Cinergy T Stick Dual RC",
.cold_ids = {
&af9015_usb_table[CINERGY_T_DUAL_RC],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "AverMedia AVerTV Red HD+ (A850T)",
.cold_ids = {
&af9015_usb_table[AVERTV_A850T],
- NULL
},
- .warm_ids = {NULL},
},
}
}, {
@@ -1686,43 +1668,44 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
- .num_frontends = 1,
- .fe = {{
- .caps = DVB_USB_ADAP_HAS_PID_FILTER |
- DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
- .pid_filter_count = 32,
- .pid_filter = af9015_pid_filter,
- .pid_filter_ctrl = af9015_pid_filter_ctrl,
-
- .frontend_attach =
- af9015_af9013_frontend_attach,
- .tuner_attach = af9015_tuner_attach,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x84,
+ .num_frontends = 1,
+ .fe = {
+ {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 32,
+ .pid_filter = af9015_pid_filter,
+ .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+ .frontend_attach = af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ },
+ }
},
- }},
},
{
- .num_frontends = 1,
- .fe = {{
- .frontend_attach =
- af9015_af9013_frontend_attach,
- .tuner_attach = af9015_tuner_attach,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x85,
- .u = {
- .bulk = {
- .buffersize =
- TS_USB20_FRAME_SIZE,
- }
+ .num_frontends = 1,
+ .fe = {
+ {
+ .frontend_attach = af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x85,
+ .u = {
+ .bulk = {
+ .buffersize = TS_USB20_FRAME_SIZE,
+ }
+ }
+ },
}
},
- }},
}
},
@@ -1744,51 +1727,33 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.name = "Xtensions XD-380",
.cold_ids = {
&af9015_usb_table[XTENSIONS_380U],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "MSI DIGIVOX Duo",
.cold_ids = {
&af9015_usb_table[MSI_DIGIVOX_DUO],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Fujitsu-Siemens Slim Mobile USB DVB-T",
.cold_ids = {
&af9015_usb_table[AVERTV_VOLAR_X_REV2],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Telestar Starstick 2",
.cold_ids = {
&af9015_usb_table[TELESTAR_STARSTICK_2],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "AVerMedia A309",
.cold_ids = {
&af9015_usb_table[AVERMEDIA_A309_USB],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "MSI Digi VOX mini III",
.cold_ids = {
&af9015_usb_table[MSI_DIGIVOX_MINI_III],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "KWorld USB DVB-T TV Stick II " \
"(VS-DVB-T 395U)",
.cold_ids = {
@@ -1796,34 +1761,23 @@ static struct dvb_usb_device_properties af9015_properties[] = {
&af9015_usb_table[KWORLD_E39B],
&af9015_usb_table[KWORLD_E395],
&af9015_usb_table[KWORLD_E39A],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "TrekStor DVB-T USB Stick",
.cold_ids = {
&af9015_usb_table[TREKSTOR_DVBT],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "AverMedia AVerTV Volar Black HD " \
"(A850)",
.cold_ids = {
&af9015_usb_table[AVERTV_A850],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Sveon STV22 Dual USB DVB-T Tuner HDTV",
.cold_ids = {
&af9015_usb_table[SVEON_STV22],
- NULL
},
- .warm_ids = {NULL},
},
}
}, {
@@ -1839,43 +1793,44 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.num_adapters = 2,
.adapter = {
{
- .num_frontends = 1,
- .fe = {{
- .caps = DVB_USB_ADAP_HAS_PID_FILTER |
- DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
- .pid_filter_count = 32,
- .pid_filter = af9015_pid_filter,
- .pid_filter_ctrl = af9015_pid_filter_ctrl,
-
- .frontend_attach =
- af9015_af9013_frontend_attach,
- .tuner_attach = af9015_tuner_attach,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x84,
+ .num_frontends = 1,
+ .fe = {
+ {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 32,
+ .pid_filter = af9015_pid_filter,
+ .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+ .frontend_attach = af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ },
+ }
},
- }},
},
{
- .num_frontends = 1,
- .fe = {{
- .frontend_attach =
- af9015_af9013_frontend_attach,
- .tuner_attach = af9015_tuner_attach,
- .stream = {
- .type = USB_BULK,
- .count = 6,
- .endpoint = 0x85,
- .u = {
- .bulk = {
- .buffersize =
- TS_USB20_FRAME_SIZE,
- }
+ .num_frontends = 1,
+ .fe = {
+ {
+ .frontend_attach = af9015_af9013_frontend_attach,
+ .tuner_attach = af9015_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x85,
+ .u = {
+ .bulk = {
+ .buffersize = TS_USB20_FRAME_SIZE,
+ }
+ }
+ },
}
},
- }},
}
},
@@ -1897,76 +1852,50 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.name = "AverMedia AVerTV Volar GPS 805 (A805)",
.cold_ids = {
&af9015_usb_table[AVERTV_A805],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
"V3.0",
.cold_ids = {
&af9015_usb_table[CONCEPTRONIC_CTVDIGRCU],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "KWorld Digial MC-810",
.cold_ids = {
&af9015_usb_table[KWORLD_MC810],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Genius TVGo DVB-T03",
.cold_ids = {
&af9015_usb_table[GENIUS_TVGO_DVB_T03],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "KWorld PlusTV DVB-T PCI Pro Card " \
"(DVB-T PC160-T)",
.cold_ids = {
&af9015_usb_table[KWORLD_PC160_T],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Sveon STV20 Tuner USB DVB-T HDTV",
.cold_ids = {
&af9015_usb_table[SVEON_STV20],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "Leadtek WinFast DTV2000DS",
.cold_ids = {
&af9015_usb_table[WINFAST_DTV2000DS],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "KWorld USB DVB-T Stick Mobile " \
"(UB383-T)",
.cold_ids = {
&af9015_usb_table[KWORLD_UB383_T],
- NULL
},
- .warm_ids = {NULL},
- },
- {
+ }, {
.name = "AverMedia AVerTV Volar M (A815Mac)",
.cold_ids = {
&af9015_usb_table[AVERMEDIA_A815M],
- NULL
},
- .warm_ids = {NULL},
},
}
},
@@ -2019,5 +1948,5 @@ static struct usb_driver af9015_usb_driver = {
module_usb_driver(af9015_usb_driver);
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Driver for Afatech AF9015 DVB-T");
+MODULE_DESCRIPTION("Afatech AF9015 driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9035.c b/drivers/media/dvb/dvb-usb/af9035.c
new file mode 100644
index 000000000000..e83b39d3993c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9035.c
@@ -0,0 +1,1242 @@
+/*
+ * Afatech AF9035 DVB USB driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "af9035.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+static DEFINE_MUTEX(af9035_usb_mutex);
+static struct dvb_usb_device_properties af9035_properties[2];
+static int af9035_properties_count = ARRAY_SIZE(af9035_properties);
+
+static u16 af9035_checksum(const u8 *buf, size_t len)
+{
+ size_t i;
+ u16 checksum = 0;
+
+ for (i = 1; i < len; i++) {
+ if (i % 2)
+ checksum += buf[i] << 8;
+ else
+ checksum += buf[i];
+ }
+ checksum = ~checksum;
+
+ return checksum;
+}
+
+static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req)
+{
+#define BUF_LEN 64
+#define REQ_HDR_LEN 4 /* send header size */
+#define ACK_HDR_LEN 3 /* rece header size */
+#define CHECKSUM_LEN 2
+#define USB_TIMEOUT 2000
+
+ int ret, msg_len, act_len;
+ u8 buf[BUF_LEN];
+ static u8 seq; /* packet sequence number */
+ u16 checksum, tmp_checksum;
+
+ /* buffer overflow check */
+ if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
+ req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
+ pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__,
+ req->wlen, req->rlen);
+ return -EINVAL;
+ }
+
+ if (mutex_lock_interruptible(&af9035_usb_mutex) < 0)
+ return -EAGAIN;
+
+ buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
+ buf[1] = req->mbox;
+ buf[2] = req->cmd;
+ buf[3] = seq++;
+ if (req->wlen)
+ memcpy(&buf[4], req->wbuf, req->wlen);
+
+ /* calc and add checksum */
+ checksum = af9035_checksum(buf, buf[0] - 1);
+ buf[buf[0] - 1] = (checksum >> 8);
+ buf[buf[0] - 0] = (checksum & 0xff);
+
+ msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ;
+
+ /* send req */
+ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,
+ &act_len, USB_TIMEOUT);
+ if (ret < 0)
+ err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len);
+ else
+ if (act_len != msg_len)
+ ret = -EIO; /* all data is not send */
+ if (ret < 0)
+ goto err_mutex_unlock;
+
+ /* no ack for those packets */
+ if (req->cmd == CMD_FW_DL)
+ goto exit_mutex_unlock;
+
+ /* receive ack and data if read req */
+ msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
+ ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,
+ &act_len, USB_TIMEOUT);
+ if (ret < 0) {
+ err("recv bulk message failed=%d", ret);
+ ret = -EIO;
+ goto err_mutex_unlock;
+ }
+
+ if (act_len != msg_len) {
+ err("recv bulk message truncated (%d != %d)", act_len, msg_len);
+ ret = -EIO;
+ goto err_mutex_unlock;
+ }
+
+ /* verify checksum */
+ checksum = af9035_checksum(buf, act_len - 2);
+ tmp_checksum = (buf[act_len - 2] << 8) | buf[act_len - 1];
+ if (tmp_checksum != checksum) {
+ err("%s: command=%02x checksum mismatch (%04x != %04x)",
+ __func__, req->cmd, tmp_checksum, checksum);
+ ret = -EIO;
+ goto err_mutex_unlock;
+ }
+
+ /* check status */
+ if (buf[2]) {
+ pr_debug("%s: command=%02x failed fw error=%d\n", __func__,
+ req->cmd, buf[2]);
+ ret = -EIO;
+ goto err_mutex_unlock;
+ }
+
+ /* read request, copy returned data to return buf */
+ if (req->rlen)
+ memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen);
+
+err_mutex_unlock:
+exit_mutex_unlock:
+ mutex_unlock(&af9035_usb_mutex);
+
+ return ret;
+}
+
+/* write multiple registers */
+static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
+{
+ u8 wbuf[6 + len];
+ u8 mbox = (reg >> 16) & 0xff;
+ struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL };
+
+ wbuf[0] = len;
+ wbuf[1] = 2;
+ wbuf[2] = 0;
+ wbuf[3] = 0;
+ wbuf[4] = (reg >> 8) & 0xff;
+ wbuf[5] = (reg >> 0) & 0xff;
+ memcpy(&wbuf[6], val, len);
+
+ return af9035_ctrl_msg(d->udev, &req);
+}
+
+/* read multiple registers */
+static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
+{
+ u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff };
+ u8 mbox = (reg >> 16) & 0xff;
+ struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val };
+
+ return af9035_ctrl_msg(d->udev, &req);
+}
+
+/* write single register */
+static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val)
+{
+ return af9035_wr_regs(d, reg, &val, 1);
+}
+
+/* read single register */
+static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val)
+{
+ return af9035_rd_regs(d, reg, val, 1);
+}
+
+/* write single register with mask */
+static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val,
+ u8 mask)
+{
+ int ret;
+ u8 tmp;
+
+ /* no need for read if whole reg is written */
+ if (mask != 0xff) {
+ ret = af9035_rd_regs(d, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ return af9035_wr_regs(d, reg, &val, 1);
+}
+
+static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg msg[], int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ struct state *state = d->priv;
+ int ret;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ /*
+ * I2C sub header is 5 bytes long. Meaning of those bytes are:
+ * 0: data len
+ * 1: I2C addr << 1
+ * 2: reg addr len
+ * byte 3 and 4 can be used as reg addr
+ * 3: reg addr MSB
+ * used when reg addr len is set to 2
+ * 4: reg addr LSB
+ * used when reg addr len is set to 1 or 2
+ *
+ * For the simplify we do not use register addr at all.
+ * NOTE: As a firmware knows tuner type there is very small possibility
+ * there could be some tuner I2C hacks done by firmware and this may
+ * lead problems if firmware expects those bytes are used.
+ */
+ if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
+ (msg[1].flags & I2C_M_RD)) {
+ if (msg[0].len > 40 || msg[1].len > 40) {
+ /* TODO: correct limits > 40 */
+ ret = -EOPNOTSUPP;
+ } else if (msg[0].addr == state->af9033_config[0].i2c_addr) {
+ /* integrated demod */
+ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+ msg[0].buf[2];
+ ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
+ msg[1].len);
+ } else {
+ /* I2C */
+ u8 buf[5 + msg[0].len];
+ struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf),
+ buf, msg[1].len, msg[1].buf };
+ buf[0] = msg[1].len;
+ buf[1] = msg[0].addr << 1;
+ buf[2] = 0x00; /* reg addr len */
+ buf[3] = 0x00; /* reg addr MSB */
+ buf[4] = 0x00; /* reg addr LSB */
+ memcpy(&buf[5], msg[0].buf, msg[0].len);
+ ret = af9035_ctrl_msg(d->udev, &req);
+ }
+ } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+ if (msg[0].len > 40) {
+ /* TODO: correct limits > 40 */
+ ret = -EOPNOTSUPP;
+ } else if (msg[0].addr == state->af9033_config[0].i2c_addr) {
+ /* integrated demod */
+ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+ msg[0].buf[2];
+ ret = af9035_wr_regs(d, reg, &msg[0].buf[3],
+ msg[0].len - 3);
+ } else {
+ /* I2C */
+ u8 buf[5 + msg[0].len];
+ struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf,
+ 0, NULL };
+ buf[0] = msg[0].len;
+ buf[1] = msg[0].addr << 1;
+ buf[2] = 0x00; /* reg addr len */
+ buf[3] = 0x00; /* reg addr MSB */
+ buf[4] = 0x00; /* reg addr LSB */
+ memcpy(&buf[5], msg[0].buf, msg[0].len);
+ ret = af9035_ctrl_msg(d->udev, &req);
+ }
+ } else {
+ /*
+ * We support only two kind of I2C transactions:
+ * 1) 1 x read + 1 x write
+ * 2) 1 x write
+ */
+ ret = -EOPNOTSUPP;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+
+ if (ret < 0)
+ return ret;
+ else
+ return num;
+}
+
+static u32 af9035_i2c_functionality(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm af9035_i2c_algo = {
+ .master_xfer = af9035_i2c_master_xfer,
+ .functionality = af9035_i2c_functionality,
+};
+
+#define AF9035_POLL 250
+static int af9035_rc_query(struct dvb_usb_device *d)
+{
+ unsigned int key;
+ unsigned char b[4];
+ int ret;
+ struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b };
+
+ ret = af9035_ctrl_msg(d->udev, &req);
+ if (ret < 0)
+ goto err;
+
+ if ((b[2] + b[3]) == 0xff) {
+ if ((b[0] + b[1]) == 0xff) {
+ /* NEC */
+ key = b[0] << 8 | b[2];
+ } else {
+ /* ext. NEC */
+ key = b[0] << 16 | b[1] << 8 | b[2];
+ }
+ } else {
+ key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
+ }
+
+ rc_keydown(d->rc_dev, key, 0);
+
+err:
+ /* ignore errors */
+ return 0;
+}
+
+static int af9035_init(struct dvb_usb_device *d)
+{
+ struct state *state = d->priv;
+ int ret, i;
+ u16 frame_size = 87 * 188 / 4;
+ u8 packet_size = 512 / 4;
+ struct reg_val_mask tab[] = {
+ { 0x80f99d, 0x01, 0x01 },
+ { 0x80f9a4, 0x01, 0x01 },
+ { 0x00dd11, 0x00, 0x20 },
+ { 0x00dd11, 0x00, 0x40 },
+ { 0x00dd13, 0x00, 0x20 },
+ { 0x00dd13, 0x00, 0x40 },
+ { 0x00dd11, 0x20, 0x20 },
+ { 0x00dd88, (frame_size >> 0) & 0xff, 0xff},
+ { 0x00dd89, (frame_size >> 8) & 0xff, 0xff},
+ { 0x00dd0c, packet_size, 0xff},
+ { 0x00dd11, state->dual_mode << 6, 0x40 },
+ { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff},
+ { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff},
+ { 0x00dd0d, packet_size, 0xff },
+ { 0x80f9a3, 0x00, 0x01 },
+ { 0x80f9cd, 0x00, 0x01 },
+ { 0x80f99d, 0x00, 0x01 },
+ { 0x80f9a4, 0x00, 0x01 },
+ };
+
+ pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n",
+ __func__, d->udev->speed, frame_size, packet_size);
+
+ /* init endpoints */
+ for (i = 0; i < ARRAY_SIZE(tab); i++) {
+ ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val,
+ tab[i].mask);
+ if (ret < 0)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9035_identify_state(struct usb_device *udev,
+ struct dvb_usb_device_properties *props,
+ struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ int ret;
+ u8 wbuf[1] = { 1 };
+ u8 rbuf[4];
+ struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf,
+ sizeof(rbuf), rbuf };
+
+ ret = af9035_ctrl_msg(udev, &req);
+ if (ret < 0)
+ goto err;
+
+ pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__,
+ rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
+ if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])
+ *cold = 0;
+ else
+ *cold = 1;
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9035_download_firmware(struct usb_device *udev,
+ const struct firmware *fw)
+{
+ int ret, i, j, len;
+ u8 wbuf[1];
+ u8 rbuf[4];
+ struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
+ struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL };
+ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
+ u8 hdr_core;
+ u16 hdr_addr, hdr_data_len, hdr_checksum;
+ #define MAX_DATA 58
+ #define HDR_SIZE 7
+
+ /*
+ * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info!
+ *
+ * byte 0: MCS 51 core
+ * There are two inside the AF9035 (1=Link and 2=OFDM) with separate
+ * address spaces
+ * byte 1-2: Big endian destination address
+ * byte 3-4: Big endian number of data bytes following the header
+ * byte 5-6: Big endian header checksum, apparently ignored by the chip
+ * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256)
+ */
+
+ for (i = fw->size; i > HDR_SIZE;) {
+ hdr_core = fw->data[fw->size - i + 0];
+ hdr_addr = fw->data[fw->size - i + 1] << 8;
+ hdr_addr |= fw->data[fw->size - i + 2] << 0;
+ hdr_data_len = fw->data[fw->size - i + 3] << 8;
+ hdr_data_len |= fw->data[fw->size - i + 4] << 0;
+ hdr_checksum = fw->data[fw->size - i + 5] << 8;
+ hdr_checksum |= fw->data[fw->size - i + 6] << 0;
+
+ pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n",
+ __func__, hdr_core, hdr_addr, hdr_data_len,
+ hdr_checksum);
+
+ if (((hdr_core != 1) && (hdr_core != 2)) ||
+ (hdr_data_len > i)) {
+ pr_debug("%s: bad firmware\n", __func__);
+ break;
+ }
+
+ /* download begin packet */
+ req.cmd = CMD_FW_DL_BEGIN;
+ ret = af9035_ctrl_msg(udev, &req);
+ if (ret < 0)
+ goto err;
+
+ /* download firmware packet(s) */
+ for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) {
+ len = j;
+ if (len > MAX_DATA)
+ len = MAX_DATA;
+ req_fw_dl.wlen = len;
+ req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i +
+ HDR_SIZE + hdr_data_len - j];
+ ret = af9035_ctrl_msg(udev, &req_fw_dl);
+ if (ret < 0)
+ goto err;
+ }
+
+ /* download end packet */
+ req.cmd = CMD_FW_DL_END;
+ ret = af9035_ctrl_msg(udev, &req);
+ if (ret < 0)
+ goto err;
+
+ i -= hdr_data_len + HDR_SIZE;
+
+ pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i);
+ }
+
+ /* firmware loaded, request boot */
+ req.cmd = CMD_FW_BOOT;
+ ret = af9035_ctrl_msg(udev, &req);
+ if (ret < 0)
+ goto err;
+
+ /* ensure firmware starts */
+ wbuf[0] = 1;
+ ret = af9035_ctrl_msg(udev, &req_fw_ver);
+ if (ret < 0)
+ goto err;
+
+ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
+ info("firmware did not run");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2],
+ rbuf[3]);
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9035_download_firmware_it9135(struct usb_device *udev,
+ const struct firmware *fw)
+{
+ int ret, i, i_prev;
+ u8 wbuf[1];
+ u8 rbuf[4];
+ struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
+ struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL };
+ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
+ #define HDR_SIZE 7
+
+ /*
+ * There seems to be following firmware header. Meaning of bytes 0-3
+ * is unknown.
+ *
+ * 0: 3
+ * 1: 0, 1
+ * 2: 0
+ * 3: 1, 2, 3
+ * 4: addr MSB
+ * 5: addr LSB
+ * 6: count of data bytes ?
+ */
+
+ for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) {
+ if (i == fw->size ||
+ (fw->data[i + 0] == 0x03 &&
+ (fw->data[i + 1] == 0x00 ||
+ fw->data[i + 1] == 0x01) &&
+ fw->data[i + 2] == 0x00)) {
+ req_fw_dl.wlen = i - i_prev;
+ req_fw_dl.wbuf = (u8 *) &fw->data[i_prev];
+ i_prev = i;
+ ret = af9035_ctrl_msg(udev, &req_fw_dl);
+ if (ret < 0)
+ goto err;
+
+ pr_debug("%s: data uploaded=%d\n", __func__, i);
+ }
+ }
+
+ /* firmware loaded, request boot */
+ req.cmd = CMD_FW_BOOT;
+ ret = af9035_ctrl_msg(udev, &req);
+ if (ret < 0)
+ goto err;
+
+ /* ensure firmware starts */
+ wbuf[0] = 1;
+ ret = af9035_ctrl_msg(udev, &req_fw_ver);
+ if (ret < 0)
+ goto err;
+
+ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
+ info("firmware did not run");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2],
+ rbuf[3]);
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+/* abuse that callback as there is no better one for reading eeprom */
+static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+ struct state *state = d->priv;
+ int ret, i, eeprom_shift = 0;
+ u8 tmp;
+ u16 tmp16;
+
+ /* check if there is dual tuners */
+ ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp);
+ if (ret < 0)
+ goto err;
+
+ state->dual_mode = tmp;
+ pr_debug("%s: dual mode=%d\n", __func__, state->dual_mode);
+
+ for (i = 0; i < af9035_properties[0].num_adapters; i++) {
+ /* tuner */
+ ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp);
+ if (ret < 0)
+ goto err;
+
+ state->af9033_config[i].tuner = tmp;
+ pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp);
+
+ switch (tmp) {
+ case AF9033_TUNER_TUA9001:
+ case AF9033_TUNER_FC0011:
+ case AF9033_TUNER_MXL5007T:
+ case AF9033_TUNER_TDA18218:
+ state->af9033_config[i].spec_inv = 1;
+ break;
+ default:
+ warn("tuner ID=%02x not supported, please report!",
+ tmp);
+ };
+
+ /* tuner IF frequency */
+ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp);
+ if (ret < 0)
+ goto err;
+
+ tmp16 = tmp;
+
+ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp);
+ if (ret < 0)
+ goto err;
+
+ tmp16 |= tmp << 8;
+
+ pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16);
+
+ eeprom_shift = 0x10; /* shift for the 2nd tuner params */
+ }
+
+ /* get demod clock */
+ ret = af9035_rd_reg(d, 0x00d800, &tmp);
+ if (ret < 0)
+ goto err;
+
+ tmp = (tmp >> 0) & 0x0f;
+
+ for (i = 0; i < af9035_properties[0].num_adapters; i++)
+ state->af9033_config[i].clock = clock_lut[tmp];
+
+ ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp);
+ if (ret < 0)
+ goto err;
+ pr_debug("%s: ir_mode=%02x\n", __func__, tmp);
+
+ /* don't activate rc if in HID mode or if not available */
+ if (tmp == 5) {
+ ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp);
+ if (ret < 0)
+ goto err;
+ pr_debug("%s: ir_type=%02x\n", __func__, tmp);
+
+ switch (tmp) {
+ case 0: /* NEC */
+ default:
+ d->props.rc.core.protocol = RC_TYPE_NEC;
+ d->props.rc.core.allowed_protos = RC_TYPE_NEC;
+ break;
+ case 1: /* RC6 */
+ d->props.rc.core.protocol = RC_TYPE_RC6;
+ d->props.rc.core.allowed_protos = RC_TYPE_RC6;
+ break;
+ }
+ d->props.rc.core.rc_query = af9035_rc_query;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+/* abuse that callback as there is no better one for reading eeprom */
+static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6])
+{
+ struct state *state = d->priv;
+ int ret, i;
+ u8 tmp;
+
+ state->dual_mode = false;
+
+ /* get demod clock */
+ ret = af9035_rd_reg(d, 0x00d800, &tmp);
+ if (ret < 0)
+ goto err;
+
+ tmp = (tmp >> 0) & 0x0f;
+
+ for (i = 0; i < af9035_properties[0].num_adapters; i++)
+ state->af9033_config[i].clock = clock_lut_it9135[tmp];
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d,
+ int cmd, int arg)
+{
+ int ret;
+
+ switch (cmd) {
+ case FC0011_FE_CALLBACK_POWER:
+ /* Tuner enable */
+ ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1);
+ if (ret < 0)
+ goto err;
+
+ /* LED */
+ ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1);
+ if (ret < 0)
+ goto err;
+
+ usleep_range(10000, 50000);
+ break;
+ case FC0011_FE_CALLBACK_RESET:
+ ret = af9035_wr_reg(d, 0xd8e9, 1);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg(d, 0xd8e8, 1);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg(d, 0xd8e7, 1);
+ if (ret < 0)
+ goto err;
+
+ usleep_range(10000, 20000);
+
+ ret = af9035_wr_reg(d, 0xd8e7, 0);
+ if (ret < 0)
+ goto err;
+
+ usleep_range(10000, 20000);
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
+{
+ struct state *state = d->priv;
+
+ switch (state->af9033_config[0].tuner) {
+ case AF9033_TUNER_FC0011:
+ return af9035_fc0011_tuner_callback(d, cmd, arg);
+ default:
+ break;
+ }
+
+ return -ENODEV;
+}
+
+static int af9035_frontend_callback(void *adapter_priv, int component,
+ int cmd, int arg)
+{
+ struct i2c_adapter *adap = adapter_priv;
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+
+ switch (component) {
+ case DVB_FRONTEND_COMPONENT_TUNER:
+ return af9035_tuner_callback(d, cmd, arg);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct state *state = adap->dev->priv;
+ int ret;
+
+ if (!state->af9033_config[adap->id].tuner) {
+ /* unsupported tuner */
+ ret = -ENODEV;
+ goto err;
+ }
+
+ if (adap->id == 0) {
+ state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB;
+ state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL;
+
+ ret = af9035_wr_reg(adap->dev, 0x00417f,
+ state->af9033_config[1].i2c_addr);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg(adap->dev, 0x00d81a,
+ state->dual_mode);
+ if (ret < 0)
+ goto err;
+ }
+
+ /* attach demodulator */
+ adap->fe_adap[0].fe = dvb_attach(af9033_attach,
+ &state->af9033_config[adap->id], &adap->dev->i2c_adap);
+ if (adap->fe_adap[0].fe == NULL) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ /* disable I2C-gate */
+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
+ adap->fe_adap[0].fe->callback = af9035_frontend_callback;
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static struct tua9001_config af9035_tua9001_config = {
+ .i2c_addr = 0x60,
+};
+
+static const struct fc0011_config af9035_fc0011_config = {
+ .i2c_address = 0x60,
+};
+
+static struct mxl5007t_config af9035_mxl5007t_config = {
+ .xtal_freq_hz = MxL_XTAL_24_MHZ,
+ .if_freq_hz = MxL_IF_4_57_MHZ,
+ .invert_if = 0,
+ .loop_thru_enable = 0,
+ .clk_out_enable = 0,
+ .clk_out_amp = MxL_CLKOUT_AMP_0_94V,
+};
+
+static struct tda18218_config af9035_tda18218_config = {
+ .i2c_address = 0x60,
+ .i2c_wr_max = 21,
+};
+
+static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct state *state = adap->dev->priv;
+ int ret;
+ struct dvb_frontend *fe;
+
+ switch (state->af9033_config[adap->id].tuner) {
+ case AF9033_TUNER_TUA9001:
+ /* AF9035 gpiot3 = TUA9001 RESETN
+ AF9035 gpiot2 = TUA9001 RXEN */
+
+ /* configure gpiot2 and gpiot2 as output */
+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+
+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+
+ /* reset tuner */
+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01);
+ if (ret < 0)
+ goto err;
+
+ usleep_range(2000, 20000);
+
+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+
+ /* activate tuner RX */
+ /* TODO: use callback for TUA9001 RXEN */
+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+
+ /* attach tuner */
+ fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, &af9035_tua9001_config);
+ break;
+ case AF9033_TUNER_FC0011:
+ fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, &af9035_fc0011_config);
+ break;
+ case AF9033_TUNER_MXL5007T:
+ ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1);
+ if (ret < 0)
+ goto err;
+ ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1);
+ if (ret < 0)
+ goto err;
+ ret = af9035_wr_reg(adap->dev, 0x00d8df, 0);
+ if (ret < 0)
+ goto err;
+
+ msleep(30);
+
+ ret = af9035_wr_reg(adap->dev, 0x00d8df, 1);
+ if (ret < 0)
+ goto err;
+
+ msleep(300);
+
+ ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1);
+ if (ret < 0)
+ goto err;
+ ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1);
+ if (ret < 0)
+ goto err;
+ ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0);
+ if (ret < 0)
+ goto err;
+ ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1);
+ if (ret < 0)
+ goto err;
+ ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1);
+ if (ret < 0)
+ goto err;
+ ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1);
+ if (ret < 0)
+ goto err;
+
+ /* attach tuner */
+ fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config);
+ break;
+ case AF9033_TUNER_TDA18218:
+ /* attach tuner */
+ fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, &af9035_tda18218_config);
+ break;
+ default:
+ fe = NULL;
+ }
+
+ if (fe == NULL) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+enum af9035_id_entry {
+ AF9035_15A4_9035,
+ AF9035_15A4_1000,
+ AF9035_15A4_1001,
+ AF9035_15A4_1002,
+ AF9035_15A4_1003,
+ AF9035_0CCD_0093,
+ AF9035_07CA_A835,
+ AF9035_07CA_B835,
+ AF9035_07CA_1867,
+ AF9035_07CA_A867,
+ AF9035_07CA_0825,
+};
+
+static struct usb_device_id af9035_id[] = {
+ [AF9035_15A4_9035] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035)},
+ [AF9035_15A4_1000] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000)},
+ [AF9035_15A4_1001] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001)},
+ [AF9035_15A4_1002] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002)},
+ [AF9035_15A4_1003] = {
+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003)},
+ [AF9035_0CCD_0093] = {
+ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)},
+ [AF9035_07CA_A835] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)},
+ [AF9035_07CA_B835] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)},
+ [AF9035_07CA_1867] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)},
+ [AF9035_07CA_A867] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)},
+ [AF9035_07CA_0825] = {
+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)},
+ {},
+};
+
+MODULE_DEVICE_TABLE(usb, af9035_id);
+
+static struct dvb_usb_device_properties af9035_properties[] = {
+ {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = af9035_download_firmware,
+ .firmware = "dvb-usb-af9035-02.fw",
+ .no_reconnect = 1,
+
+ .size_of_priv = sizeof(struct state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {
+ {
+ .frontend_attach = af9035_frontend_attach,
+ .tuner_attach = af9035_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ .u = {
+ .bulk = {
+ .buffersize = (87 * 188),
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+
+ .identify_state = af9035_identify_state,
+ .read_mac_address = af9035_read_mac_address,
+
+ .i2c_algo = &af9035_i2c_algo,
+
+ .rc.core = {
+ .protocol = RC_TYPE_UNKNOWN,
+ .module_name = "af9035",
+ .rc_query = NULL,
+ .rc_interval = AF9035_POLL,
+ .allowed_protos = RC_TYPE_UNKNOWN,
+ .rc_codes = RC_MAP_EMPTY,
+ },
+ .num_device_descs = 5,
+ .devices = {
+ {
+ .name = "Afatech AF9035 reference design",
+ .cold_ids = {
+ &af9035_id[AF9035_15A4_9035],
+ &af9035_id[AF9035_15A4_1000],
+ &af9035_id[AF9035_15A4_1001],
+ &af9035_id[AF9035_15A4_1002],
+ &af9035_id[AF9035_15A4_1003],
+ },
+ }, {
+ .name = "TerraTec Cinergy T Stick",
+ .cold_ids = {
+ &af9035_id[AF9035_0CCD_0093],
+ },
+ }, {
+ .name = "AVerMedia AVerTV Volar HD/PRO (A835)",
+ .cold_ids = {
+ &af9035_id[AF9035_07CA_A835],
+ &af9035_id[AF9035_07CA_B835],
+ },
+ }, {
+ .name = "AVerMedia HD Volar (A867)",
+ .cold_ids = {
+ &af9035_id[AF9035_07CA_1867],
+ &af9035_id[AF9035_07CA_A867],
+ },
+ }, {
+ .name = "AVerMedia Twinstar (A825)",
+ .cold_ids = {
+ &af9035_id[AF9035_07CA_0825],
+ },
+ },
+ }
+ },
+ {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = af9035_download_firmware_it9135,
+ .firmware = "dvb-usb-it9135-01.fw",
+ .no_reconnect = 1,
+
+ .size_of_priv = sizeof(struct state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {
+ {
+ .frontend_attach = af9035_frontend_attach,
+ .tuner_attach = af9035_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 6,
+ .endpoint = 0x84,
+ .u = {
+ .bulk = {
+ .buffersize = (87 * 188),
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+
+ .identify_state = af9035_identify_state,
+ .read_mac_address = af9035_read_mac_address_it9135,
+
+ .i2c_algo = &af9035_i2c_algo,
+
+ .num_device_descs = 0, /* disabled as no support for IT9135 */
+ .devices = {
+ {
+ .name = "ITE Tech. IT9135 reference design",
+ },
+ }
+ },
+};
+
+static int af9035_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int ret, i;
+ struct dvb_usb_device *d = NULL;
+ struct usb_device *udev;
+ bool found;
+
+ pr_debug("%s: interface=%d\n", __func__,
+ intf->cur_altsetting->desc.bInterfaceNumber);
+
+ /* interface 0 is used by DVB-T receiver and
+ interface 1 is for remote controller (HID) */
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return 0;
+
+ /* Dynamic USB ID support. Replaces first device ID with current one. */
+ udev = interface_to_usbdev(intf);
+
+ for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) {
+ if (af9035_id[i].idVendor ==
+ le16_to_cpu(udev->descriptor.idVendor) &&
+ af9035_id[i].idProduct ==
+ le16_to_cpu(udev->descriptor.idProduct)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ pr_debug("%s: using dynamic ID %04x:%04x\n", __func__,
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+ af9035_properties[0].devices[0].cold_ids[0]->idVendor =
+ le16_to_cpu(udev->descriptor.idVendor);
+ af9035_properties[0].devices[0].cold_ids[0]->idProduct =
+ le16_to_cpu(udev->descriptor.idProduct);
+ }
+
+
+ for (i = 0; i < af9035_properties_count; i++) {
+ ret = dvb_usb_device_init(intf, &af9035_properties[i],
+ THIS_MODULE, &d, adapter_nr);
+
+ if (ret == -ENODEV)
+ continue;
+ else
+ break;
+ }
+
+ if (ret < 0)
+ goto err;
+
+ if (d) {
+ ret = af9035_init(d);
+ if (ret < 0)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver af9035_usb_driver = {
+ .name = "dvb_usb_af9035",
+ .probe = af9035_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = af9035_id,
+};
+
+module_usb_driver(af9035_usb_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Afatech AF9035 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9035.h b/drivers/media/dvb/dvb-usb/af9035.h
new file mode 100644
index 000000000000..481a1a43dd2a
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/af9035.h
@@ -0,0 +1,113 @@
+/*
+ * Afatech AF9035 DVB USB driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef AF9035_H
+#define AF9035_H
+
+/* prefix for dvb-usb log writings */
+#define DVB_USB_LOG_PREFIX "af9035"
+
+#include "dvb-usb.h"
+#include "af9033.h"
+#include "tua9001.h"
+#include "fc0011.h"
+#include "mxl5007t.h"
+#include "tda18218.h"
+
+struct reg_val {
+ u32 reg;
+ u8 val;
+};
+
+struct reg_val_mask {
+ u32 reg;
+ u8 val;
+ u8 mask;
+};
+
+struct usb_req {
+ u8 cmd;
+ u8 mbox;
+ u8 wlen;
+ u8 *wbuf;
+ u8 rlen;
+ u8 *rbuf;
+};
+
+struct state {
+ bool dual_mode;
+
+ struct af9033_config af9033_config[2];
+};
+
+u32 clock_lut[] = {
+ 20480000, /* FPGA */
+ 16384000, /* 16.38 MHz */
+ 20480000, /* 20.48 MHz */
+ 36000000, /* 36.00 MHz */
+ 30000000, /* 30.00 MHz */
+ 26000000, /* 26.00 MHz */
+ 28000000, /* 28.00 MHz */
+ 32000000, /* 32.00 MHz */
+ 34000000, /* 34.00 MHz */
+ 24000000, /* 24.00 MHz */
+ 22000000, /* 22.00 MHz */
+ 12000000, /* 12.00 MHz */
+};
+
+u32 clock_lut_it9135[] = {
+ 12000000, /* 12.00 MHz */
+ 20480000, /* 20.48 MHz */
+ 36000000, /* 36.00 MHz */
+ 30000000, /* 30.00 MHz */
+ 26000000, /* 26.00 MHz */
+ 28000000, /* 28.00 MHz */
+ 32000000, /* 32.00 MHz */
+ 34000000, /* 34.00 MHz */
+ 24000000, /* 24.00 MHz */
+ 22000000, /* 22.00 MHz */
+};
+
+/* EEPROM locations */
+#define EEPROM_IR_MODE 0x430d
+#define EEPROM_DUAL_MODE 0x4326
+#define EEPROM_IR_TYPE 0x4329
+#define EEPROM_1_IFFREQ_L 0x432d
+#define EEPROM_1_IFFREQ_H 0x432e
+#define EEPROM_1_TUNER_ID 0x4331
+#define EEPROM_2_IFFREQ_L 0x433d
+#define EEPROM_2_IFFREQ_H 0x433e
+#define EEPROM_2_TUNER_ID 0x4341
+
+/* USB commands */
+#define CMD_MEM_RD 0x00
+#define CMD_MEM_WR 0x01
+#define CMD_I2C_RD 0x02
+#define CMD_I2C_WR 0x03
+#define CMD_IR_GET 0x18
+#define CMD_FW_DL 0x21
+#define CMD_FW_QUERYINFO 0x22
+#define CMD_FW_BOOT 0x23
+#define CMD_FW_DL_BEGIN 0x24
+#define CMD_FW_DL_END 0x25
+#define CMD_FW_SCATTER_WR 0x29
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 02290c60f72f..7e9e00fae04e 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -32,7 +32,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ return -EINTR;
}
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
@@ -118,7 +118,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ return -EINTR;
}
st->buf[0] = REQUEST_SET_GPIO;
@@ -139,7 +139,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
if (st->fw_version >= 0x10201) {
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ return -EINTR;
}
st->buf[0] = REQUEST_SET_USB_XFER_LEN;
@@ -178,7 +178,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
/* Ensure nobody else hits the i2c bus while we're sending our
sequence of messages, (such as the remote control thread) */
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
- return -EAGAIN;
+ return -EINTR;
for (i = 0; i < num; i++) {
if (i == 0) {
@@ -228,7 +228,8 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
/* Write request */
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ mutex_unlock(&d->i2c_mutex);
+ return -EINTR;
}
st->buf[0] = REQUEST_NEW_I2C_WRITE;
st->buf[1] = msg[i].addr << 1;
@@ -271,10 +272,11 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
int i,len;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
- return -EAGAIN;
+ return -EINTR;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ mutex_unlock(&d->i2c_mutex);
+ return -EINTR;
}
for (i = 0; i < num; i++) {
@@ -369,7 +371,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ return -EINTR;
}
st->buf[0] = REQUEST_SET_CLOCK;
@@ -401,7 +403,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ return -EINTR;
}
st->buf[0] = REQUEST_SET_I2C_PARAM;
@@ -561,7 +563,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ return -EINTR;
}
st->buf[0] = REQUEST_ENABLE_VIDEO;
@@ -611,7 +613,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
- return 0;
+ return -EINTR;
}
st->buf[0] = REQUEST_SET_RC;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index f9e966aa26e7..510001da6e83 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -3569,6 +3569,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090E) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790E) },
/* 80 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE8096P) },
+ { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -3832,7 +3833,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 11,
+ .num_device_descs = 12,
.devices = {
{ "DiBcom STK7070P reference design",
{ &dib0700_usb_id_table[15], NULL },
@@ -3878,6 +3879,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[50], NULL },
{ NULL },
},
+ { "Elgato EyeTV DTT rev. 2",
+ { &dib0700_usb_id_table[81], NULL },
+ { NULL },
+ },
},
.rc.core = {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 397d8f232731..7a6160bf54ba 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -76,6 +76,11 @@
#define USB_PID_AFATECH_AF9005 0x9020
#define USB_PID_AFATECH_AF9015_9015 0x9015
#define USB_PID_AFATECH_AF9015_9016 0x9016
+#define USB_PID_AFATECH_AF9035_1000 0x1000
+#define USB_PID_AFATECH_AF9035_1001 0x1001
+#define USB_PID_AFATECH_AF9035_1002 0x1002
+#define USB_PID_AFATECH_AF9035_1003 0x1003
+#define USB_PID_AFATECH_AF9035_9035 0x9035
#define USB_PID_TREKSTOR_DVBT 0x901b
#define USB_VID_ALINK_DTU 0xf170
#define USB_PID_ANSONIC_DVBT_USB 0x6000
@@ -152,6 +157,7 @@
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069
+#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093
#define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097
#define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
@@ -221,6 +227,11 @@
#define USB_PID_AVERMEDIA_A850T 0x850b
#define USB_PID_AVERMEDIA_A805 0xa805
#define USB_PID_AVERMEDIA_A815M 0x815a
+#define USB_PID_AVERMEDIA_A835 0xa835
+#define USB_PID_AVERMEDIA_B835 0xb835
+#define USB_PID_AVERMEDIA_1867 0x1867
+#define USB_PID_AVERMEDIA_A867 0xa867
+#define USB_PID_AVERMEDIA_TWINSTAR 0x0825
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
@@ -327,6 +338,7 @@
#define USB_PID_MYGICA_D689 0xd811
#define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011
#define USB_PID_ELGATO_EYETV_DTT 0x0021
+#define USB_PID_ELGATO_EYETV_DTT_2 0x003f
#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020
#define USB_PID_ELGATO_EYETV_SAT 0x002a
#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index 53a5c30b51b2..5c8f651344fc 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -80,6 +80,14 @@ static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer
dvb_dmx_swfilter_204(&adap->demux, buffer, length);
}
+static void dvb_usb_data_complete_raw(struct usb_data_stream *stream,
+ u8 *buffer, size_t length)
+{
+ struct dvb_usb_adapter *adap = stream->user_priv;
+ if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
+ dvb_dmx_swfilter_raw(&adap->demux, buffer, length);
+}
+
int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
{
int i, ret = 0;
@@ -90,6 +98,10 @@ int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
adap->fe_adap[i].stream.complete =
dvb_usb_data_complete_204;
else
+ if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD)
+ adap->fe_adap[i].stream.complete =
+ dvb_usb_data_complete_raw;
+ else
adap->fe_adap[i].stream.complete = dvb_usb_data_complete;
adap->fe_adap[i].stream.user_priv = adap;
ret = usb_urb_init(&adap->fe_adap[i].stream,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 6d7d13f9ce68..99f94409efa1 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -141,6 +141,7 @@ struct dvb_usb_adapter_fe_properties {
#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
#define DVB_USB_ADAP_NEED_PID_FILTERING 0x04
#define DVB_USB_ADAP_RECEIVES_204_BYTE_TS 0x08
+#define DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD 0x10
int caps;
int pid_filter_count;
@@ -156,7 +157,7 @@ struct dvb_usb_adapter_fe_properties {
int size_of_priv;
};
-#define MAX_NO_OF_FE_PER_ADAP 2
+#define MAX_NO_OF_FE_PER_ADAP 3
struct dvb_usb_adapter_properties {
int size_of_priv;
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 451c5a7adfb2..9382895b1b88 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -148,7 +148,7 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
- int i = 0, ret = 0;
+ int i = 0;
u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
u16 value;
@@ -162,7 +162,7 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
/* read stv0299 register */
value = msg[0].buf[0];/* register */
for (i = 0; i < msg[1].len; i++) {
- ret = dw210x_op_rw(d->udev, 0xb5, value + i, 0,
+ dw210x_op_rw(d->udev, 0xb5, value + i, 0,
buf6, 2, DW210X_READ_MSG);
msg[1].buf[i] = buf6[0];
}
@@ -174,7 +174,7 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
buf6[0] = 0x2a;
buf6[1] = msg[0].buf[0];
buf6[2] = msg[0].buf[1];
- ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
buf6, 3, DW210X_WRITE_MSG);
break;
case 0x60:
@@ -187,17 +187,17 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
buf6[4] = msg[0].buf[1];
buf6[5] = msg[0].buf[2];
buf6[6] = msg[0].buf[3];
- ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
buf6, 7, DW210X_WRITE_MSG);
} else {
/* read from tuner */
- ret = dw210x_op_rw(d->udev, 0xb5, 0, 0,
+ dw210x_op_rw(d->udev, 0xb5, 0, 0,
buf6, 1, DW210X_READ_MSG);
msg[0].buf[0] = buf6[0];
}
break;
case (DW2102_RC_QUERY):
- ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ dw210x_op_rw(d->udev, 0xb8, 0, 0,
buf6, 2, DW210X_READ_MSG);
msg[0].buf[0] = buf6[0];
msg[0].buf[1] = buf6[1];
@@ -205,7 +205,7 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
case (DW2102_VOLTAGE_CTRL):
buf6[0] = 0x30;
buf6[1] = msg[0].buf[0];
- ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
buf6, 2, DW210X_WRITE_MSG);
break;
}
@@ -221,7 +221,6 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
- int ret = 0;
u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
if (!d)
@@ -235,10 +234,10 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
buf6[2] = msg[0].buf[0];
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
buf6, msg[0].len + 2, DW210X_WRITE_MSG);
/* read si2109 register */
- ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
+ dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
buf6, msg[1].len + 2, DW210X_READ_MSG);
memcpy(msg[1].buf, buf6 + 2, msg[1].len);
@@ -250,11 +249,11 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
memcpy(buf6 + 2, msg[0].buf, msg[0].len);
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
msg[0].len + 2, DW210X_WRITE_MSG);
break;
case(DW2102_RC_QUERY):
- ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ dw210x_op_rw(d->udev, 0xb8, 0, 0,
buf6, 2, DW210X_READ_MSG);
msg[0].buf[0] = buf6[0];
msg[0].buf[1] = buf6[1];
@@ -262,7 +261,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
case(DW2102_VOLTAGE_CTRL):
buf6[0] = 0x30;
buf6[1] = msg[0].buf[0];
- ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
buf6, 2, DW210X_WRITE_MSG);
break;
}
@@ -276,7 +275,6 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
- int ret = 0;
if (!d)
return -ENODEV;
@@ -291,10 +289,10 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
/* second read registers */
- ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
+ dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
ibuf, msg[1].len + 2, DW210X_READ_MSG);
memcpy(msg[1].buf, ibuf + 2, msg[1].len);
@@ -308,7 +306,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
memcpy(obuf + 2, msg[0].buf, msg[0].len);
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
break;
}
@@ -318,13 +316,13 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
memcpy(obuf + 2, msg[0].buf, msg[0].len);
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
break;
}
case(DW2102_RC_QUERY): {
u8 ibuf[2];
- ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[0].buf, ibuf , 2);
break;
@@ -333,7 +331,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
u8 obuf[2];
obuf[0] = 0x30;
obuf[1] = msg[0].buf[0];
- ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
}
@@ -349,7 +347,6 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
- int ret = 0;
int len, i, j;
if (!d)
@@ -361,7 +358,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
switch (msg[j].addr) {
case(DW2102_RC_QUERY): {
u8 ibuf[2];
- ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf , 2);
break;
@@ -370,7 +367,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
u8 obuf[2];
obuf[0] = 0x30;
obuf[1] = msg[j].buf[0];
- ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
}
@@ -382,7 +379,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
if (msg[j].flags == I2C_M_RD) {
/* read registers */
u8 ibuf[msg[j].len + 2];
- ret = dw210x_op_rw(d->udev, 0xc3,
+ dw210x_op_rw(d->udev, 0xc3,
(msg[j].addr << 1) + 1, 0,
ibuf, msg[j].len + 2,
DW210X_READ_MSG);
@@ -402,7 +399,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
do {
memcpy(obuf + 3, msg[j].buf + i,
(len > 16 ? 16 : len));
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, (len > 16 ? 16 : len) + 3,
DW210X_WRITE_MSG);
i += 16;
@@ -414,7 +411,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
obuf[0] = msg[j].addr << 1;
obuf[1] = msg[j].len;
memcpy(obuf + 2, msg[j].buf, msg[j].len);
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[j].len + 2,
DW210X_WRITE_MSG);
}
@@ -432,7 +429,7 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
- int ret = 0, i;
+ int i;
if (!d)
return -ENODEV;
@@ -447,10 +444,10 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
/* second read registers */
- ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
+ dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
ibuf, msg[1].len + 2, DW210X_READ_MSG);
memcpy(msg[1].buf, ibuf + 2, msg[1].len);
@@ -465,13 +462,13 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
memcpy(obuf + 2, msg[0].buf, msg[0].len);
- ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
break;
}
case(DW2102_RC_QUERY): {
u8 ibuf[2];
- ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[0].buf, ibuf , 2);
break;
@@ -496,7 +493,6 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
struct usb_device *udev;
- int ret = 0;
int len, i, j;
if (!d)
@@ -509,7 +505,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
switch (msg[j].addr) {
case (DW2102_RC_QUERY): {
u8 ibuf[5];
- ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 5, DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf + 3, 2);
break;
@@ -519,11 +515,11 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
obuf[0] = 1;
obuf[1] = msg[j].buf[1];/* off-on */
- ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
+ dw210x_op_rw(d->udev, 0x8a, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
obuf[0] = 3;
obuf[1] = msg[j].buf[0];/* 13v-18v */
- ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
+ dw210x_op_rw(d->udev, 0x8a, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
}
@@ -532,7 +528,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
obuf[0] = 5;
obuf[1] = msg[j].buf[0];
- ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
+ dw210x_op_rw(d->udev, 0x8a, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
}
@@ -545,7 +541,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
if (msg[j].flags == I2C_M_RD) {
/* read registers */
u8 ibuf[msg[j].len];
- ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
+ dw210x_op_rw(d->udev, 0x91, 0, 0,
ibuf, msg[j].len,
DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf, msg[j].len);
@@ -563,7 +559,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
do {
memcpy(obuf + 3, msg[j].buf + i,
(len > 16 ? 16 : len));
- ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
+ dw210x_op_rw(d->udev, 0x80, 0, 0,
obuf, (len > 16 ? 16 : len) + 3,
DW210X_WRITE_MSG);
i += 16;
@@ -575,7 +571,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
obuf[0] = msg[j + 1].len;
obuf[1] = (msg[j].addr << 1);
memcpy(obuf + 2, msg[j].buf, msg[j].len);
- ret = dw210x_op_rw(d->udev,
+ dw210x_op_rw(d->udev,
udev->descriptor.idProduct ==
0x7500 ? 0x92 : 0x90, 0, 0,
obuf, msg[j].len + 2,
@@ -587,7 +583,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
obuf[0] = msg[j].len + 1;
obuf[1] = (msg[j].addr << 1);
memcpy(obuf + 2, msg[j].buf, msg[j].len);
- ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
+ dw210x_op_rw(d->udev, 0x80, 0, 0,
obuf, msg[j].len + 2,
DW210X_WRITE_MSG);
break;
diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c
index 482d249ca7f3..6244fe9d1a3a 100644
--- a/drivers/media/dvb/dvb-usb/it913x.c
+++ b/drivers/media/dvb/dvb-usb/it913x.c
@@ -81,7 +81,7 @@ static int it913x_bulk_write(struct usb_device *dev,
for (i = 0; i < IT913X_RETRY; i++) {
ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
snd, len , &actual_l, IT913X_SND_TIMEOUT);
- if (ret == 0 || ret != -EBUSY || ret != -ETIMEDOUT)
+ if (ret != -EBUSY && ret != -ETIMEDOUT)
break;
}
@@ -99,7 +99,7 @@ static int it913x_bulk_read(struct usb_device *dev,
for (i = 0; i < IT913X_RETRY; i++) {
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
rev, len , &actual_l, IT913X_RCV_TIMEOUT);
- if (ret == 0 || ret != -EBUSY || ret != -ETIMEDOUT)
+ if (ret != -EBUSY && ret != -ETIMEDOUT)
break;
}
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c
index 5dde06d066ff..25d1031460f8 100644
--- a/drivers/media/dvb/dvb-usb/lmedm04.c
+++ b/drivers/media/dvb/dvb-usb/lmedm04.c
@@ -373,7 +373,7 @@ static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
struct lme2510_state *st = adap->dev->priv;
static u8 clear_pid_reg[] = LME_ALL_PIDS;
static u8 rbuf[1];
- int ret;
+ int ret = 0;
deb_info(1, "PID Clearing Filter");
@@ -1205,14 +1205,13 @@ static int lme2510_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
- int ret = 0;
usb_reset_configuration(udev);
usb_set_interface(udev, intf->cur_altsetting->desc.bInterfaceNumber, 1);
if (udev->speed != USB_SPEED_HIGH) {
- ret = usb_reset_device(udev);
+ usb_reset_device(udev);
info("DEV Failed to connect in HIGH SPEED mode");
return -ENODEV;
}
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
index 72db6eef4b9c..74da5bb1ce99 100644
--- a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
@@ -284,6 +284,7 @@ static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
switch (delsys) {
case SYS_ATSC:
+ case SYS_ATSCMH:
bw = 0; /* ATSC */
break;
case SYS_DVBC_ANNEX_B:
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c
index 81305de2fea5..cd842798f5af 100644
--- a/drivers/media/dvb/dvb-usb/mxl111sf.c
+++ b/drivers/media/dvb/dvb-usb/mxl111sf.c
@@ -21,6 +21,7 @@
#include "mxl111sf-tuner.h"
#include "lgdt3305.h"
+#include "lg2160.h"
int dvb_usb_mxl111sf_debug;
module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
@@ -31,6 +32,10 @@ int dvb_usb_mxl111sf_isoc;
module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
+int dvb_usb_mxl111sf_spi;
+module_param_named(spi, dvb_usb_mxl111sf_spi, int, 0644);
+MODULE_PARM_DESC(spi, "use spi rather than tp for data xfer (0=tp, 1=spi).");
+
#define ANT_PATH_AUTO 0
#define ANT_PATH_EXTERNAL 1
#define ANT_PATH_INTERNAL 2
@@ -340,7 +345,6 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
struct mxl111sf_state *state = d->priv;
struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
int ret = 0;
- u8 tmp;
deb_info("%s(%d)\n", __func__, onoff);
@@ -361,6 +365,33 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return ret;
}
+static int mxl111sf_ep5_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ int ret = 0;
+
+ deb_info("%s(%d)\n", __func__, onoff);
+
+ if (onoff) {
+ ret = mxl111sf_enable_usb_output(state);
+ mxl_fail(ret);
+
+ ret = mxl111sf_init_i2s_port(state, 200);
+ mxl_fail(ret);
+ ret = mxl111sf_config_i2s(state, 0, 15);
+ mxl_fail(ret);
+ } else {
+ ret = mxl111sf_disable_i2s_port(state);
+ mxl_fail(ret);
+ }
+ if (state->chip_rev > MXL111SF_V6)
+ ret = mxl111sf_config_spi(state, onoff);
+ mxl_fail(ret);
+
+ return ret;
+}
+
static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
struct dvb_usb_device *d = adap->dev;
@@ -453,6 +484,255 @@ fail:
return ret;
}
+static struct lg2160_config hauppauge_lg2160_config = {
+ .lg_chip = LG2160,
+ .i2c_addr = 0x1c >> 1,
+ .deny_i2c_rptr = 1,
+ .spectral_inversion = 0,
+ .if_khz = 6000,
+};
+
+static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ int fe_id = adap->num_frontends_initialized;
+ struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+ int ret;
+
+ deb_adv("%s()\n", __func__);
+
+ /* save a pointer to the dvb_usb_device in device state */
+ state->d = d;
+ adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+ state->alt_mode = adap_state->alt_mode;
+
+ if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+ err("set interface failed");
+
+ state->gpio_mode = MXL111SF_GPIO_MOD_MH;
+ adap_state->gpio_mode = state->gpio_mode;
+ adap_state->device_mode = MXL_TUNER_MODE;
+ adap_state->ep6_clockphase = 1;
+
+ ret = mxl1x1sf_soft_reset(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_init_tuner_demod(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_enable_usb_output(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl1x1sf_top_master_ctrl(state, 1);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_init_port_expander(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = get_chip_info(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
+ &hauppauge_lg2160_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe_adap[fe_id].fe) {
+ adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+ adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+ adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+ adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+ return 0;
+ }
+ ret = -EIO;
+fail:
+ return ret;
+}
+
+static struct lg2160_config hauppauge_lg2161_1019_config = {
+ .lg_chip = LG2161_1019,
+ .i2c_addr = 0x1c >> 1,
+ .deny_i2c_rptr = 1,
+ .spectral_inversion = 0,
+ .if_khz = 6000,
+ .output_if = 2, /* LG2161_OIF_SPI_MAS */
+};
+
+static struct lg2160_config hauppauge_lg2161_1040_config = {
+ .lg_chip = LG2161_1040,
+ .i2c_addr = 0x1c >> 1,
+ .deny_i2c_rptr = 1,
+ .spectral_inversion = 0,
+ .if_khz = 6000,
+ .output_if = 4, /* LG2161_OIF_SPI_MAS */
+};
+
+static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ int fe_id = adap->num_frontends_initialized;
+ struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+ int ret;
+
+ deb_adv("%s()\n", __func__);
+
+ /* save a pointer to the dvb_usb_device in device state */
+ state->d = d;
+ adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+ state->alt_mode = adap_state->alt_mode;
+
+ if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+ err("set interface failed");
+
+ state->gpio_mode = MXL111SF_GPIO_MOD_MH;
+ adap_state->gpio_mode = state->gpio_mode;
+ adap_state->device_mode = MXL_TUNER_MODE;
+ adap_state->ep6_clockphase = 1;
+
+ ret = mxl1x1sf_soft_reset(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_init_tuner_demod(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_enable_usb_output(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl1x1sf_top_master_ctrl(state, 1);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_init_port_expander(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = get_chip_info(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
+ (MXL111SF_V8_200 == state->chip_rev) ?
+ &hauppauge_lg2161_1040_config :
+ &hauppauge_lg2161_1019_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe_adap[fe_id].fe) {
+ adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+ adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+ adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+ adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+ return 0;
+ }
+ ret = -EIO;
+fail:
+ return ret;
+}
+
+static struct lg2160_config hauppauge_lg2161_1019_ep6_config = {
+ .lg_chip = LG2161_1019,
+ .i2c_addr = 0x1c >> 1,
+ .deny_i2c_rptr = 1,
+ .spectral_inversion = 0,
+ .if_khz = 6000,
+ .output_if = 1, /* LG2161_OIF_SERIAL_TS */
+};
+
+static struct lg2160_config hauppauge_lg2161_1040_ep6_config = {
+ .lg_chip = LG2161_1040,
+ .i2c_addr = 0x1c >> 1,
+ .deny_i2c_rptr = 1,
+ .spectral_inversion = 0,
+ .if_khz = 6000,
+ .output_if = 7, /* LG2161_OIF_SERIAL_TS */
+};
+
+static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct mxl111sf_state *state = d->priv;
+ int fe_id = adap->num_frontends_initialized;
+ struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+ int ret;
+
+ deb_adv("%s()\n", __func__);
+
+ /* save a pointer to the dvb_usb_device in device state */
+ state->d = d;
+ adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+ state->alt_mode = adap_state->alt_mode;
+
+ if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+ err("set interface failed");
+
+ state->gpio_mode = MXL111SF_GPIO_MOD_MH;
+ adap_state->gpio_mode = state->gpio_mode;
+ adap_state->device_mode = MXL_TUNER_MODE;
+ adap_state->ep6_clockphase = 0;
+
+ ret = mxl1x1sf_soft_reset(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_init_tuner_demod(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_enable_usb_output(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl1x1sf_top_master_ctrl(state, 1);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = mxl111sf_init_port_expander(state);
+ if (mxl_fail(ret))
+ goto fail;
+ ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+ if (mxl_fail(ret))
+ goto fail;
+
+ ret = get_chip_info(state);
+ if (mxl_fail(ret))
+ goto fail;
+
+ adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
+ (MXL111SF_V8_200 == state->chip_rev) ?
+ &hauppauge_lg2161_1040_ep6_config :
+ &hauppauge_lg2161_1019_ep6_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe_adap[fe_id].fe) {
+ adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+ adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+ adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+ adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+ return 0;
+ }
+ ret = -EIO;
+fail:
+ return ret;
+}
+
static struct mxl111sf_demod_config mxl_demod_config = {
.read_reg = mxl111sf_read_reg,
.write_reg = mxl111sf_write_reg,
@@ -650,6 +930,18 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties;
static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties;
static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties;
static int mxl111sf_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -664,12 +956,50 @@ static int mxl111sf_probe(struct usb_interface *intf,
THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf,
&mxl111sf_atsc_isoc_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_atsc_mh_isoc_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mh_isoc_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ ((dvb_usb_mxl111sf_spi) &&
+ (0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_spi_isoc_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_mh_spi_isoc_properties,
+ THIS_MODULE, &d, adapter_nr))) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_tp_isoc_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_mh_tp_isoc_properties,
THIS_MODULE, &d, adapter_nr))) ||
0 == dvb_usb_device_init(intf,
&mxl111sf_dvbt_bulk_properties,
THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf,
&mxl111sf_atsc_bulk_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_atsc_mh_bulk_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mh_bulk_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ ((dvb_usb_mxl111sf_spi) &&
+ (0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_spi_bulk_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_mh_spi_bulk_properties,
+ THIS_MODULE, &d, adapter_nr))) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_tp_bulk_properties,
+ THIS_MODULE, &d, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf,
+ &mxl111sf_mercury_mh_tp_bulk_properties,
THIS_MODULE, &d, adapter_nr) || 0) {
struct mxl111sf_state *state = d->priv;
@@ -787,6 +1117,36 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
} \
}
+#define MXL111SF_EP5_BULK_STREAMING_CONFIG \
+ .size_of_priv = sizeof(struct mxl111sf_adap_state), \
+ .streaming_ctrl = mxl111sf_ep5_streaming_ctrl, \
+ .stream = { \
+ .type = USB_BULK, \
+ .count = 5, \
+ .endpoint = 0x05, \
+ .u = { \
+ .bulk = { \
+ .buffersize = 8192, \
+ } \
+ } \
+ }
+
+#define MXL111SF_EP5_ISOC_STREAMING_CONFIG \
+ .size_of_priv = sizeof(struct mxl111sf_adap_state), \
+ .streaming_ctrl = mxl111sf_ep5_streaming_ctrl, \
+ .stream = { \
+ .type = USB_ISOC, \
+ .count = 5, \
+ .endpoint = 0x05, \
+ .u = { \
+ .isoc = { \
+ .framesperurb = 96, \
+ .framesize = 200, \
+ .interval = 1, \
+ } \
+ } \
+ }
+
#define MXL111SF_EP6_BULK_STREAMING_CONFIG \
.size_of_priv = sizeof(struct mxl111sf_adap_state), \
.streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
@@ -848,7 +1208,7 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
} },
},
},
- .num_device_descs = 4,
+ .num_device_descs = 3,
.devices = {
{ "Hauppauge 126xxx DVBT (bulk)",
{ NULL },
@@ -866,11 +1226,6 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
&mxl111sf_table[24], &mxl111sf_table[26],
NULL },
},
- { "Hauppauge 126xxx (tp-bulk)",
- { NULL },
- { &mxl111sf_table[28], &mxl111sf_table[30],
- NULL },
- },
}
};
@@ -890,7 +1245,7 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
} },
},
},
- .num_device_descs = 4,
+ .num_device_descs = 3,
.devices = {
{ "Hauppauge 126xxx DVBT (isoc)",
{ NULL },
@@ -908,11 +1263,6 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
&mxl111sf_table[24], &mxl111sf_table[26],
NULL },
},
- { "Hauppauge 126xxx (tp-isoc)",
- { NULL },
- { &mxl111sf_table[28], &mxl111sf_table[30],
- NULL },
- },
}
};
@@ -923,33 +1273,159 @@ static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
.adapter = {
{
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
- .num_frontends = 2,
+ .num_frontends = 1,
.fe = {{
.frontend_attach = mxl111sf_lgdt3305_frontend_attach,
.tuner_attach = mxl111sf_attach_tuner,
MXL111SF_EP6_BULK_STREAMING_CONFIG,
+ }},
},
+ },
+ .num_device_descs = 2,
+ .devices = {
+ { "Hauppauge 126xxx ATSC (bulk)",
+ { NULL },
+ { &mxl111sf_table[1], &mxl111sf_table[5],
+ NULL },
+ },
+ { "Hauppauge 117xxx ATSC (bulk)",
+ { NULL },
+ { &mxl111sf_table[12],
+ NULL },
+ },
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
{
- .frontend_attach = mxl111sf_attach_demod,
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 1,
+ .fe = {{
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
.tuner_attach = mxl111sf_attach_tuner,
- MXL111SF_EP4_BULK_STREAMING_CONFIG,
+ MXL111SF_EP6_ISOC_STREAMING_CONFIG,
}},
},
},
- .num_device_descs = 6,
+ .num_device_descs = 2,
.devices = {
- { "Hauppauge 126xxx ATSC (bulk)",
+ { "Hauppauge 126xxx ATSC (isoc)",
{ NULL },
{ &mxl111sf_table[1], &mxl111sf_table[5],
NULL },
},
- { "Hauppauge 117xxx ATSC (bulk)",
+ { "Hauppauge 117xxx ATSC (isoc)",
{ NULL },
{ &mxl111sf_table[12],
NULL },
},
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 1,
+ .fe = {{
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2160_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_BULK_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 2,
+ .devices = {
+ { "HCW 126xxx (bulk)",
+ { NULL },
+ { &mxl111sf_table[2], &mxl111sf_table[6],
+ NULL },
+ },
+ { "HCW 117xxx (bulk)",
+ { NULL },
+ { &mxl111sf_table[13],
+ NULL },
+ },
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 1,
+ .fe = {{
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2160_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_ISOC_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 2,
+ .devices = {
+ { "HCW 126xxx (isoc)",
+ { NULL },
+ { &mxl111sf_table[2], &mxl111sf_table[6],
+ NULL },
+ },
+ { "HCW 117xxx (isoc)",
+ { NULL },
+ { &mxl111sf_table[13],
+ NULL },
+ },
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 3,
+ .fe = {{
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_BULK_STREAMING_CONFIG,
+ },
+ {
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_BULK_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2160_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_BULK_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 2,
+ .devices = {
{ "Hauppauge 126xxx ATSC+ (bulk)",
{ NULL },
{ &mxl111sf_table[0], &mxl111sf_table[3],
@@ -963,13 +1439,96 @@ static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
&mxl111sf_table[32], &mxl111sf_table[33],
NULL },
},
- { "Hauppauge Mercury (tp-bulk)",
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 3,
+ .fe = {{
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+ },
+ {
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2160_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_ISOC_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 2,
+ .devices = {
+ { "Hauppauge 126xxx ATSC+ (isoc)",
+ { NULL },
+ { &mxl111sf_table[0], &mxl111sf_table[3],
+ &mxl111sf_table[7], &mxl111sf_table[9],
+ &mxl111sf_table[10], NULL },
+ },
+ { "Hauppauge 117xxx ATSC+ (isoc)",
+ { NULL },
+ { &mxl111sf_table[11], &mxl111sf_table[14],
+ &mxl111sf_table[16], &mxl111sf_table[17],
+ &mxl111sf_table[32], &mxl111sf_table[33],
+ NULL },
+ },
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 3,
+ .fe = {{
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_BULK_STREAMING_CONFIG,
+ },
+ {
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_BULK_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_BULK_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 2,
+ .devices = {
+ { "Hauppauge Mercury (spi-bulk)",
{ NULL },
{ &mxl111sf_table[19], &mxl111sf_table[21],
&mxl111sf_table[23], &mxl111sf_table[25],
- &mxl111sf_table[27], NULL },
+ NULL },
},
- { "Hauppauge WinTV-Aero-M",
+ { "Hauppauge WinTV-Aero-M (spi-bulk)",
{ NULL },
{ &mxl111sf_table[29], &mxl111sf_table[31],
NULL },
@@ -977,14 +1536,14 @@ static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
}
};
-static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
+static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties = {
MXL111SF_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
.adapter = {
{
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
- .num_frontends = 2,
+ .num_frontends = 3,
.fe = {{
.frontend_attach = mxl111sf_lgdt3305_frontend_attach,
.tuner_attach = mxl111sf_attach_tuner,
@@ -996,34 +1555,111 @@ static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
.tuner_attach = mxl111sf_attach_tuner,
MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_ISOC_STREAMING_CONFIG,
}},
},
},
- .num_device_descs = 6,
+ .num_device_descs = 2,
.devices = {
- { "Hauppauge 126xxx ATSC (isoc)",
+ { "Hauppauge Mercury (spi-isoc)",
{ NULL },
- { &mxl111sf_table[1], &mxl111sf_table[5],
+ { &mxl111sf_table[19], &mxl111sf_table[21],
+ &mxl111sf_table[23], &mxl111sf_table[25],
NULL },
},
- { "Hauppauge 117xxx ATSC (isoc)",
+ { "Hauppauge WinTV-Aero-M (spi-isoc)",
{ NULL },
- { &mxl111sf_table[12],
+ { &mxl111sf_table[29], &mxl111sf_table[31],
NULL },
},
- { "Hauppauge 126xxx ATSC+ (isoc)",
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 3,
+ .fe = {{
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_BULK_STREAMING_CONFIG,
+ },
+ {
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_BULK_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_BULK_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 2,
+ .devices = {
+ { "Hauppauge Mercury (tp-bulk)",
{ NULL },
- { &mxl111sf_table[0], &mxl111sf_table[3],
- &mxl111sf_table[7], &mxl111sf_table[9],
- &mxl111sf_table[10], NULL },
+ { &mxl111sf_table[19], &mxl111sf_table[21],
+ &mxl111sf_table[23], &mxl111sf_table[25],
+ &mxl111sf_table[27], NULL },
},
- { "Hauppauge 117xxx ATSC+ (isoc)",
+ { "Hauppauge WinTV-Aero-M",
{ NULL },
- { &mxl111sf_table[11], &mxl111sf_table[14],
- &mxl111sf_table[16], &mxl111sf_table[17],
- &mxl111sf_table[32], &mxl111sf_table[33],
+ { &mxl111sf_table[29], &mxl111sf_table[31],
NULL },
},
+ }
+};
+
+static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 3,
+ .fe = {{
+ .frontend_attach = mxl111sf_lgdt3305_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+ },
+ {
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 2,
+ .devices = {
{ "Hauppauge Mercury (tp-isoc)",
{ NULL },
{ &mxl111sf_table[19], &mxl111sf_table[21],
@@ -1038,6 +1674,146 @@ static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
}
};
+static
+struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 2,
+ .fe = {{
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_BULK_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_BULK_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 1,
+ .devices = {
+ { "Hauppauge 126xxx (tp-bulk)",
+ { NULL },
+ { &mxl111sf_table[28], &mxl111sf_table[30],
+ NULL },
+ },
+ }
+};
+
+static
+struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 2,
+ .fe = {{
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 1,
+ .devices = {
+ { "Hauppauge 126xxx (tp-isoc)",
+ { NULL },
+ { &mxl111sf_table[28], &mxl111sf_table[30],
+ NULL },
+ },
+ }
+};
+
+static
+struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 2,
+ .fe = {{
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_BULK_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_BULK_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 1,
+ .devices = {
+ { "Hauppauge 126xxx (spi-bulk)",
+ { NULL },
+ { &mxl111sf_table[28], &mxl111sf_table[30],
+ NULL },
+ },
+ }
+};
+
+static
+struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties = {
+ MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+ .num_frontends = 2,
+ .fe = {{
+ .frontend_attach = mxl111sf_attach_demod,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+ },
+ {
+ .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
+
+ .frontend_attach = mxl111sf_lg2161_frontend_attach,
+ .tuner_attach = mxl111sf_attach_tuner,
+
+ MXL111SF_EP5_ISOC_STREAMING_CONFIG,
+ }},
+ },
+ },
+ .num_device_descs = 1,
+ .devices = {
+ { "Hauppauge 126xxx (spi-isoc)",
+ { NULL },
+ { &mxl111sf_table[28], &mxl111sf_table[30],
+ NULL },
+ },
+ }
+};
+
static struct usb_driver mxl111sf_driver = {
.name = "dvb_usb_mxl111sf",
.probe = mxl111sf_probe,
diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c
index 8f4736a10fc8..41e1f5537f44 100644
--- a/drivers/media/dvb/dvb-usb/rtl28xxu.c
+++ b/drivers/media/dvb/dvb-usb/rtl28xxu.c
@@ -322,6 +322,9 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
* since there is some demod params needed to set according to tuner.
*/
+ /* demod needs some time to wake up */
+ msleep(20);
+
/* open demod I2C gate */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate);
if (ret)
@@ -909,6 +912,8 @@ static int rtl28xxu_probe(struct usb_interface *intf,
int ret, i;
int properties_count = ARRAY_SIZE(rtl28xxu_properties);
struct dvb_usb_device *d;
+ struct usb_device *udev;
+ bool found;
deb_info("%s: interface=%d\n", __func__,
intf->cur_altsetting->desc.bInterfaceNumber);
@@ -916,6 +921,29 @@ static int rtl28xxu_probe(struct usb_interface *intf,
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return 0;
+ /* Dynamic USB ID support. Replaces first device ID with current one .*/
+ udev = interface_to_usbdev(intf);
+
+ for (i = 0, found = false; i < ARRAY_SIZE(rtl28xxu_table) - 1; i++) {
+ if (rtl28xxu_table[i].idVendor ==
+ le16_to_cpu(udev->descriptor.idVendor) &&
+ rtl28xxu_table[i].idProduct ==
+ le16_to_cpu(udev->descriptor.idProduct)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ deb_info("%s: using dynamic ID %04x:%04x\n", __func__,
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+ rtl28xxu_properties[0].devices[0].warm_ids[0]->idVendor =
+ le16_to_cpu(udev->descriptor.idVendor);
+ rtl28xxu_properties[0].devices[0].warm_ids[0]->idProduct =
+ le16_to_cpu(udev->descriptor.idProduct);
+ }
+
for (i = 0; i < properties_count; i++) {
ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i],
THIS_MODULE, &d, adapter_nr);
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 21246707fbfb..b98ebb264e29 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -531,6 +531,14 @@ config DVB_LGDT3305
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+config DVB_LG2160
+ tristate "LG Electronics LG216x based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ An ATSC/MH demodulator module. Say Y when you want
+ to support this frontend.
+
config DVB_S5H1409
tristate "Samsung S5H1409 based"
depends on DVB_CORE && I2C
@@ -540,12 +548,26 @@ config DVB_S5H1409
to support this frontend.
config DVB_AU8522
- tristate "Auvitek AU8522 based"
- depends on DVB_CORE && I2C && VIDEO_V4L2
+ depends on I2C
+ tristate
+
+config DVB_AU8522_DTV
+ tristate "Auvitek AU8522 based DTV demod"
+ depends on DVB_CORE && I2C
+ select DVB_AU8522
default m if DVB_FE_CUSTOMISE
help
- An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
- to support this frontend.
+ An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
+ you want to enable DTV demodulation support for this frontend.
+
+config DVB_AU8522_V4L
+ tristate "Auvitek AU8522 based ATV demod"
+ depends on VIDEO_V4L2 && I2C
+ select DVB_AU8522
+ default m if DVB_FE_CUSTOMISE
+ help
+ An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
+ you want to enable ATV demodulation support for this frontend.
config DVB_S5H1411
tristate "Samsung S5H1411 based"
@@ -713,6 +735,11 @@ config DVB_M88RS2000
A DVB-S tuner module.
Say Y when you want to support this frontend.
+config DVB_AF9033
+ tristate "Afatech AF9033 DVB-T demodulator"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+
comment "Tools to develop new frontends"
config DVB_DUMMY_FE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 86fa808bf589..cd1ac2fd5774 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -7,7 +7,6 @@ ccflags-y += -I$(srctree)/drivers/media/common/tuners/
stb0899-objs = stb0899_drv.o stb0899_algo.o
stv0900-objs = stv0900_core.o stv0900_sw.o
-au8522-objs = au8522_dig.o au8522_decoder.o
drxd-objs = drxd_firm.o drxd_hard.o
cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
drxk-objs := drxk_hard.o
@@ -50,6 +49,7 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
+obj-$(CONFIG_DVB_LG2160) += lg2160.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
@@ -63,7 +63,9 @@ obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
-obj-$(CONFIG_DVB_AU8522) += au8522.o
+obj-$(CONFIG_DVB_AU8522) += au8522_common.o
+obj-$(CONFIG_DVB_AU8522_DTV) += au8522_dig.o
+obj-$(CONFIG_DVB_AU8522_V4L) += au8522_decoder.o
obj-$(CONFIG_DVB_TDA10048) += tda10048.o
obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
@@ -98,4 +100,5 @@ obj-$(CONFIG_DVB_A8293) += a8293.o
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
+obj-$(CONFIG_DVB_AF9033) += af9033.o
diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c
index 6bcbcf543b38..5bc570d77846 100644
--- a/drivers/media/dvb/frontends/af9013.c
+++ b/drivers/media/dvb/frontends/af9013.c
@@ -514,7 +514,6 @@ err:
static void af9013_statistics_work(struct work_struct *work)
{
- int ret;
struct af9013_state *state = container_of(work,
struct af9013_state, statistics_work.work);
unsigned int next_msec;
@@ -530,27 +529,27 @@ static void af9013_statistics_work(struct work_struct *work)
default:
state->statistics_step = 0;
case 0:
- ret = af9013_statistics_signal_strength(&state->fe);
+ af9013_statistics_signal_strength(&state->fe);
state->statistics_step++;
next_msec = 300;
break;
case 1:
- ret = af9013_statistics_snr_start(&state->fe);
+ af9013_statistics_snr_start(&state->fe);
state->statistics_step++;
next_msec = 200;
break;
case 2:
- ret = af9013_statistics_ber_unc_start(&state->fe);
+ af9013_statistics_ber_unc_start(&state->fe);
state->statistics_step++;
next_msec = 1000;
break;
case 3:
- ret = af9013_statistics_snr_result(&state->fe);
+ af9013_statistics_snr_result(&state->fe);
state->statistics_step++;
next_msec = 400;
break;
case 4:
- ret = af9013_statistics_ber_unc_result(&state->fe);
+ af9013_statistics_ber_unc_result(&state->fe);
state->statistics_step++;
next_msec = 100;
break;
@@ -558,8 +557,6 @@ static void af9013_statistics_work(struct work_struct *work)
schedule_delayed_work(&state->statistics_work,
msecs_to_jiffies(next_msec));
-
- return;
}
static int af9013_get_tune_settings(struct dvb_frontend *fe,
diff --git a/drivers/media/dvb/frontends/af9033.c b/drivers/media/dvb/frontends/af9033.c
new file mode 100644
index 000000000000..a38998286260
--- /dev/null
+++ b/drivers/media/dvb/frontends/af9033.c
@@ -0,0 +1,980 @@
+/*
+ * Afatech AF9033 demodulator driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "af9033_priv.h"
+
+struct af9033_state {
+ struct i2c_adapter *i2c;
+ struct dvb_frontend fe;
+ struct af9033_config cfg;
+
+ u32 bandwidth_hz;
+ bool ts_mode_parallel;
+ bool ts_mode_serial;
+
+ u32 ber;
+ u32 ucb;
+ unsigned long last_stat_check;
+};
+
+/* write multiple registers */
+static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val,
+ int len)
+{
+ int ret;
+ u8 buf[3 + len];
+ struct i2c_msg msg[1] = {
+ {
+ .addr = state->cfg.i2c_addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
+
+ buf[0] = (reg >> 16) & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+ buf[2] = (reg >> 0) & 0xff;
+ memcpy(&buf[3], val, len);
+
+ ret = i2c_transfer(state->i2c, msg, 1);
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n",
+ __func__, ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+
+ return ret;
+}
+
+/* read multiple registers */
+static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len)
+{
+ int ret;
+ u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff,
+ (reg >> 0) & 0xff };
+ struct i2c_msg msg[2] = {
+ {
+ .addr = state->cfg.i2c_addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf
+ }, {
+ .addr = state->cfg.i2c_addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = val
+ }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret == 2) {
+ ret = 0;
+ } else {
+ printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n",
+ __func__, ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+
+ return ret;
+}
+
+
+/* write single register */
+static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val)
+{
+ return af9033_wr_regs(state, reg, &val, 1);
+}
+
+/* read single register */
+static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val)
+{
+ return af9033_rd_regs(state, reg, val, 1);
+}
+
+/* write single register with mask */
+static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val,
+ u8 mask)
+{
+ int ret;
+ u8 tmp;
+
+ /* no need for read if whole reg is written */
+ if (mask != 0xff) {
+ ret = af9033_rd_regs(state, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ return af9033_wr_regs(state, reg, &val, 1);
+}
+
+/* read single register with mask */
+static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
+ u8 mask)
+{
+ int ret, i;
+ u8 tmp;
+
+ ret = af9033_rd_regs(state, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ tmp &= mask;
+
+ /* find position of the first bit */
+ for (i = 0; i < 8; i++) {
+ if ((mask >> i) & 0x01)
+ break;
+ }
+ *val = tmp >> i;
+
+ return 0;
+}
+
+static u32 af9033_div(u32 a, u32 b, u32 x)
+{
+ u32 r = 0, c = 0, i;
+
+ pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x);
+
+ if (a > b) {
+ c = a / b;
+ a = a - c * b;
+ }
+
+ for (i = 0; i < x; i++) {
+ if (a >= b) {
+ r += 1;
+ a -= b;
+ }
+ a <<= 1;
+ r <<= 1;
+ }
+ r = (c << (u32)x) + r;
+
+ pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r);
+
+ return r;
+}
+
+static void af9033_release(struct dvb_frontend *fe)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+
+ kfree(state);
+}
+
+static int af9033_init(struct dvb_frontend *fe)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret, i, len;
+ const struct reg_val *init;
+ u8 buf[4];
+ u32 adc_cw, clock_cw;
+ struct reg_val_mask tab[] = {
+ { 0x80fb24, 0x00, 0x08 },
+ { 0x80004c, 0x00, 0xff },
+ { 0x00f641, state->cfg.tuner, 0xff },
+ { 0x80f5ca, 0x01, 0x01 },
+ { 0x80f715, 0x01, 0x01 },
+ { 0x00f41f, 0x04, 0x04 },
+ { 0x00f41a, 0x01, 0x01 },
+ { 0x80f731, 0x00, 0x01 },
+ { 0x00d91e, 0x00, 0x01 },
+ { 0x00d919, 0x00, 0x01 },
+ { 0x80f732, 0x00, 0x01 },
+ { 0x00d91f, 0x00, 0x01 },
+ { 0x00d91a, 0x00, 0x01 },
+ { 0x80f730, 0x00, 0x01 },
+ { 0x80f778, 0x00, 0xff },
+ { 0x80f73c, 0x01, 0x01 },
+ { 0x80f776, 0x00, 0x01 },
+ { 0x00d8fd, 0x01, 0xff },
+ { 0x00d830, 0x01, 0xff },
+ { 0x00d831, 0x00, 0xff },
+ { 0x00d832, 0x00, 0xff },
+ { 0x80f985, state->ts_mode_serial, 0x01 },
+ { 0x80f986, state->ts_mode_parallel, 0x01 },
+ { 0x00d827, 0x00, 0xff },
+ { 0x00d829, 0x00, 0xff },
+ };
+
+ /* program clock control */
+ clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul);
+ buf[0] = (clock_cw >> 0) & 0xff;
+ buf[1] = (clock_cw >> 8) & 0xff;
+ buf[2] = (clock_cw >> 16) & 0xff;
+ buf[3] = (clock_cw >> 24) & 0xff;
+
+ pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock,
+ clock_cw);
+
+ ret = af9033_wr_regs(state, 0x800025, buf, 4);
+ if (ret < 0)
+ goto err;
+
+ /* program ADC control */
+ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
+ if (clock_adc_lut[i].clock == state->cfg.clock)
+ break;
+ }
+
+ adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul);
+ buf[0] = (adc_cw >> 0) & 0xff;
+ buf[1] = (adc_cw >> 8) & 0xff;
+ buf[2] = (adc_cw >> 16) & 0xff;
+
+ pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc,
+ adc_cw);
+
+ ret = af9033_wr_regs(state, 0x80f1cd, buf, 3);
+ if (ret < 0)
+ goto err;
+
+ /* program register table */
+ for (i = 0; i < ARRAY_SIZE(tab); i++) {
+ ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val,
+ tab[i].mask);
+ if (ret < 0)
+ goto err;
+ }
+
+ /* settings for TS interface */
+ if (state->cfg.ts_mode == AF9033_TS_MODE_USB) {
+ ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+ } else {
+ ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01);
+ if (ret < 0)
+ goto err;
+ }
+
+ /* load OFSM settings */
+ pr_debug("%s: load ofsm settings\n", __func__);
+ len = ARRAY_SIZE(ofsm_init);
+ init = ofsm_init;
+ for (i = 0; i < len; i++) {
+ ret = af9033_wr_reg(state, init[i].reg, init[i].val);
+ if (ret < 0)
+ goto err;
+ }
+
+ /* load tuner specific settings */
+ pr_debug("%s: load tuner specific settings\n",
+ __func__);
+ switch (state->cfg.tuner) {
+ case AF9033_TUNER_TUA9001:
+ len = ARRAY_SIZE(tuner_init_tua9001);
+ init = tuner_init_tua9001;
+ break;
+ case AF9033_TUNER_FC0011:
+ len = ARRAY_SIZE(tuner_init_fc0011);
+ init = tuner_init_fc0011;
+ break;
+ case AF9033_TUNER_MXL5007T:
+ len = ARRAY_SIZE(tuner_init_mxl5007t);
+ init = tuner_init_mxl5007t;
+ break;
+ case AF9033_TUNER_TDA18218:
+ len = ARRAY_SIZE(tuner_init_tda18218);
+ init = tuner_init_tda18218;
+ break;
+ default:
+ pr_debug("%s: unsupported tuner ID=%d\n", __func__,
+ state->cfg.tuner);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ for (i = 0; i < len; i++) {
+ ret = af9033_wr_reg(state, init[i].reg, init[i].val);
+ if (ret < 0)
+ goto err;
+ }
+
+ state->bandwidth_hz = 0; /* force to program all parameters */
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9033_sleep(struct dvb_frontend *fe)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret, i;
+ u8 tmp;
+
+ ret = af9033_wr_reg(state, 0x80004c, 1);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg(state, 0x800000, 0);
+ if (ret < 0)
+ goto err;
+
+ for (i = 100, tmp = 1; i && tmp; i--) {
+ ret = af9033_rd_reg(state, 0x80004c, &tmp);
+ if (ret < 0)
+ goto err;
+
+ usleep_range(200, 10000);
+ }
+
+ pr_debug("%s: loop=%d\n", __func__, i);
+
+ if (i == 0) {
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+
+ ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08);
+ if (ret < 0)
+ goto err;
+
+ /* prevent current leak (?) */
+ if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
+ /* enable parallel TS */
+ ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01);
+ if (ret < 0)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9033_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *fesettings)
+{
+ fesettings->min_delay_ms = 800;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+
+ return 0;
+}
+
+static int af9033_set_frontend(struct dvb_frontend *fe)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret, i, spec_inv;
+ u8 tmp, buf[3], bandwidth_reg_val;
+ u32 if_frequency, freq_cw, adc_freq;
+
+ pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency,
+ c->bandwidth_hz);
+
+ /* check bandwidth */
+ switch (c->bandwidth_hz) {
+ case 6000000:
+ bandwidth_reg_val = 0x00;
+ break;
+ case 7000000:
+ bandwidth_reg_val = 0x01;
+ break;
+ case 8000000:
+ bandwidth_reg_val = 0x02;
+ break;
+ default:
+ pr_debug("%s: invalid bandwidth_hz\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* program tuner */
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe);
+
+ /* program CFOE coefficients */
+ if (c->bandwidth_hz != state->bandwidth_hz) {
+ for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
+ if (coeff_lut[i].clock == state->cfg.clock &&
+ coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
+ break;
+ }
+ }
+ ret = af9033_wr_regs(state, 0x800001,
+ coeff_lut[i].val, sizeof(coeff_lut[i].val));
+ }
+
+ /* program frequency control */
+ if (c->bandwidth_hz != state->bandwidth_hz) {
+ spec_inv = state->cfg.spec_inv ? -1 : 1;
+
+ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
+ if (clock_adc_lut[i].clock == state->cfg.clock)
+ break;
+ }
+ adc_freq = clock_adc_lut[i].adc;
+
+ /* get used IF frequency */
+ if (fe->ops.tuner_ops.get_if_frequency)
+ fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
+ else
+ if_frequency = 0;
+
+ while (if_frequency > (adc_freq / 2))
+ if_frequency -= adc_freq;
+
+ if (if_frequency >= 0)
+ spec_inv *= -1;
+ else
+ if_frequency *= -1;
+
+ freq_cw = af9033_div(if_frequency, adc_freq, 23ul);
+
+ if (spec_inv == -1)
+ freq_cw *= -1;
+
+ /* get adc multiplies */
+ ret = af9033_rd_reg(state, 0x800045, &tmp);
+ if (ret < 0)
+ goto err;
+
+ if (tmp == 1)
+ freq_cw /= 2;
+
+ buf[0] = (freq_cw >> 0) & 0xff;
+ buf[1] = (freq_cw >> 8) & 0xff;
+ buf[2] = (freq_cw >> 16) & 0x7f;
+ ret = af9033_wr_regs(state, 0x800029, buf, 3);
+ if (ret < 0)
+ goto err;
+
+ state->bandwidth_hz = c->bandwidth_hz;
+ }
+
+ ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg(state, 0x800040, 0x00);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg(state, 0x800047, 0x00);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01);
+ if (ret < 0)
+ goto err;
+
+ if (c->frequency <= 230000000)
+ tmp = 0x00; /* VHF */
+ else
+ tmp = 0x01; /* UHF */
+
+ ret = af9033_wr_reg(state, 0x80004b, tmp);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_wr_reg(state, 0x800000, 0x00);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9033_get_frontend(struct dvb_frontend *fe)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret;
+ u8 buf[8];
+
+ pr_debug("%s\n", __func__);
+
+ /* read all needed registers */
+ ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf));
+ if (ret < 0)
+ goto err;
+
+ switch ((buf[0] >> 0) & 3) {
+ case 0:
+ c->transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ c->transmission_mode = TRANSMISSION_MODE_8K;
+ break;
+ }
+
+ switch ((buf[1] >> 0) & 3) {
+ case 0:
+ c->guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ c->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ c->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ c->guard_interval = GUARD_INTERVAL_1_4;
+ break;
+ }
+
+ switch ((buf[2] >> 0) & 7) {
+ case 0:
+ c->hierarchy = HIERARCHY_NONE;
+ break;
+ case 1:
+ c->hierarchy = HIERARCHY_1;
+ break;
+ case 2:
+ c->hierarchy = HIERARCHY_2;
+ break;
+ case 3:
+ c->hierarchy = HIERARCHY_4;
+ break;
+ }
+
+ switch ((buf[3] >> 0) & 3) {
+ case 0:
+ c->modulation = QPSK;
+ break;
+ case 1:
+ c->modulation = QAM_16;
+ break;
+ case 2:
+ c->modulation = QAM_64;
+ break;
+ }
+
+ switch ((buf[4] >> 0) & 3) {
+ case 0:
+ c->bandwidth_hz = 6000000;
+ break;
+ case 1:
+ c->bandwidth_hz = 7000000;
+ break;
+ case 2:
+ c->bandwidth_hz = 8000000;
+ break;
+ }
+
+ switch ((buf[6] >> 0) & 7) {
+ case 0:
+ c->code_rate_HP = FEC_1_2;
+ break;
+ case 1:
+ c->code_rate_HP = FEC_2_3;
+ break;
+ case 2:
+ c->code_rate_HP = FEC_3_4;
+ break;
+ case 3:
+ c->code_rate_HP = FEC_5_6;
+ break;
+ case 4:
+ c->code_rate_HP = FEC_7_8;
+ break;
+ case 5:
+ c->code_rate_HP = FEC_NONE;
+ break;
+ }
+
+ switch ((buf[7] >> 0) & 7) {
+ case 0:
+ c->code_rate_LP = FEC_1_2;
+ break;
+ case 1:
+ c->code_rate_LP = FEC_2_3;
+ break;
+ case 2:
+ c->code_rate_LP = FEC_3_4;
+ break;
+ case 3:
+ c->code_rate_LP = FEC_5_6;
+ break;
+ case 4:
+ c->code_rate_LP = FEC_7_8;
+ break;
+ case 5:
+ c->code_rate_LP = FEC_NONE;
+ break;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret;
+ u8 tmp;
+
+ *status = 0;
+
+ /* radio channel status, 0=no result, 1=has signal, 2=no signal */
+ ret = af9033_rd_reg(state, 0x800047, &tmp);
+ if (ret < 0)
+ goto err;
+
+ /* has signal */
+ if (tmp == 0x01)
+ *status |= FE_HAS_SIGNAL;
+
+ if (tmp != 0x02) {
+ /* TPS lock */
+ ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01);
+ if (ret < 0)
+ goto err;
+
+ if (tmp)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI;
+
+ /* full lock */
+ ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01);
+ if (ret < 0)
+ goto err;
+
+ if (tmp)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI | FE_HAS_SYNC |
+ FE_HAS_LOCK;
+ }
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret, i, len;
+ u8 buf[3], tmp;
+ u32 snr_val;
+ const struct val_snr *uninitialized_var(snr_lut);
+
+ /* read value */
+ ret = af9033_rd_regs(state, 0x80002c, buf, 3);
+ if (ret < 0)
+ goto err;
+
+ snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+ /* read current modulation */
+ ret = af9033_rd_reg(state, 0x80f903, &tmp);
+ if (ret < 0)
+ goto err;
+
+ switch ((tmp >> 0) & 3) {
+ case 0:
+ len = ARRAY_SIZE(qpsk_snr_lut);
+ snr_lut = qpsk_snr_lut;
+ break;
+ case 1:
+ len = ARRAY_SIZE(qam16_snr_lut);
+ snr_lut = qam16_snr_lut;
+ break;
+ case 2:
+ len = ARRAY_SIZE(qam64_snr_lut);
+ snr_lut = qam64_snr_lut;
+ break;
+ default:
+ goto err;
+ }
+
+ for (i = 0; i < len; i++) {
+ tmp = snr_lut[i].snr;
+
+ if (snr_val < snr_lut[i].val)
+ break;
+ }
+
+ *snr = tmp * 10; /* dB/10 */
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret;
+ u8 strength2;
+
+ /* read signal strength of 0-100 scale */
+ ret = af9033_rd_reg(state, 0x800048, &strength2);
+ if (ret < 0)
+ goto err;
+
+ /* scale value to 0x0000-0xffff */
+ *strength = strength2 * 0xffff / 100;
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int af9033_update_ch_stat(struct af9033_state *state)
+{
+ int ret = 0;
+ u32 err_cnt, bit_cnt;
+ u16 abort_cnt;
+ u8 buf[7];
+
+ /* only update data every half second */
+ if (time_after(jiffies, state->last_stat_check + msecs_to_jiffies(500))) {
+ ret = af9033_rd_regs(state, 0x800032, buf, sizeof(buf));
+ if (ret < 0)
+ goto err;
+ /* in 8 byte packets? */
+ abort_cnt = (buf[1] << 8) + buf[0];
+ /* in bits */
+ err_cnt = (buf[4] << 16) + (buf[3] << 8) + buf[2];
+ /* in 8 byte packets? always(?) 0x2710 = 10000 */
+ bit_cnt = (buf[6] << 8) + buf[5];
+
+ if (bit_cnt < abort_cnt) {
+ abort_cnt = 1000;
+ state->ber = 0xffffffff;
+ } else {
+ /* 8 byte packets, that have not been rejected already */
+ bit_cnt -= (u32)abort_cnt;
+ if (bit_cnt == 0) {
+ state->ber = 0xffffffff;
+ } else {
+ err_cnt -= (u32)abort_cnt * 8 * 8;
+ bit_cnt *= 8 * 8;
+ state->ber = err_cnt * (0xffffffff / bit_cnt);
+ }
+ }
+ state->ucb += abort_cnt;
+ state->last_stat_check = jiffies;
+ }
+
+ return 0;
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+ return ret;
+}
+
+static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret;
+
+ ret = af9033_update_ch_stat(state);
+ if (ret < 0)
+ return ret;
+
+ *ber = state->ber;
+
+ return 0;
+}
+
+static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret;
+
+ ret = af9033_update_ch_stat(state);
+ if (ret < 0)
+ return ret;
+
+ *ucblocks = state->ucb;
+
+ return 0;
+}
+
+static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct af9033_state *state = fe->demodulator_priv;
+ int ret;
+
+ pr_debug("%s: enable=%d\n", __func__, enable);
+
+ ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+
+err:
+ pr_debug("%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static struct dvb_frontend_ops af9033_ops;
+
+struct dvb_frontend *af9033_attach(const struct af9033_config *config,
+ struct i2c_adapter *i2c)
+{
+ int ret;
+ struct af9033_state *state;
+ u8 buf[8];
+
+ pr_debug("%s:\n", __func__);
+
+ /* allocate memory for the internal state */
+ state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL);
+ if (state == NULL)
+ goto err;
+
+ /* setup the state */
+ state->i2c = i2c;
+ memcpy(&state->cfg, config, sizeof(struct af9033_config));
+
+ if (state->cfg.clock != 12000000) {
+ printk(KERN_INFO "af9033: unsupported clock=%d, only " \
+ "12000000 Hz is supported currently\n",
+ state->cfg.clock);
+ goto err;
+ }
+
+ /* firmware version */
+ ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4);
+ if (ret < 0)
+ goto err;
+
+ ret = af9033_rd_regs(state, 0x804191, &buf[4], 4);
+ if (ret < 0)
+ goto err;
+
+ printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \
+ "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ /* configure internal TS mode */
+ switch (state->cfg.ts_mode) {
+ case AF9033_TS_MODE_PARALLEL:
+ state->ts_mode_parallel = true;
+ break;
+ case AF9033_TS_MODE_SERIAL:
+ state->ts_mode_serial = true;
+ break;
+ case AF9033_TS_MODE_USB:
+ /* usb mode for AF9035 */
+ default:
+ break;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops));
+ state->fe.demodulator_priv = state;
+
+ return &state->fe;
+
+err:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(af9033_attach);
+
+static struct dvb_frontend_ops af9033_ops = {
+ .delsys = { SYS_DVBT },
+ .info = {
+ .name = "Afatech AF9033 (DVB-T)",
+ .frequency_min = 174000000,
+ .frequency_max = 862000000,
+ .frequency_stepsize = 250000,
+ .frequency_tolerance = 0,
+ .caps = FE_CAN_FEC_1_2 |
+ FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_QAM_16 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO |
+ FE_CAN_RECOVER |
+ FE_CAN_MUTE_TS
+ },
+
+ .release = af9033_release,
+
+ .init = af9033_init,
+ .sleep = af9033_sleep,
+
+ .get_tune_settings = af9033_get_tune_settings,
+ .set_frontend = af9033_set_frontend,
+ .get_frontend = af9033_get_frontend,
+
+ .read_status = af9033_read_status,
+ .read_snr = af9033_read_snr,
+ .read_signal_strength = af9033_read_signal_strength,
+ .read_ber = af9033_read_ber,
+ .read_ucblocks = af9033_read_ucblocks,
+
+ .i2c_gate_ctrl = af9033_i2c_gate_ctrl,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/af9033.h b/drivers/media/dvb/frontends/af9033.h
new file mode 100644
index 000000000000..9e302c3f0f7d
--- /dev/null
+++ b/drivers/media/dvb/frontends/af9033.h
@@ -0,0 +1,75 @@
+/*
+ * Afatech AF9033 demodulator driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef AF9033_H
+#define AF9033_H
+
+struct af9033_config {
+ /*
+ * I2C address
+ */
+ u8 i2c_addr;
+
+ /*
+ * clock Hz
+ * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000,
+ * 30000000, 36000000, 20480000, 16384000
+ */
+ u32 clock;
+
+ /*
+ * tuner
+ */
+#define AF9033_TUNER_TUA9001 0x27 /* Infineon TUA 9001 */
+#define AF9033_TUNER_FC0011 0x28 /* Fitipower FC0011 */
+#define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */
+#define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */
+ u8 tuner;
+
+ /*
+ * TS settings
+ */
+#define AF9033_TS_MODE_USB 0
+#define AF9033_TS_MODE_PARALLEL 1
+#define AF9033_TS_MODE_SERIAL 2
+ u8 ts_mode:2;
+
+ /*
+ * input spectrum inversion
+ */
+ bool spec_inv;
+};
+
+
+#if defined(CONFIG_DVB_AF9033) || \
+ (defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE))
+extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *af9033_attach(
+ const struct af9033_config *config, struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
+#endif /* AF9033_H */
diff --git a/drivers/media/dvb/frontends/af9033_priv.h b/drivers/media/dvb/frontends/af9033_priv.h
new file mode 100644
index 000000000000..0b783b9ed75e
--- /dev/null
+++ b/drivers/media/dvb/frontends/af9033_priv.h
@@ -0,0 +1,470 @@
+/*
+ * Afatech AF9033 demodulator driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef AF9033_PRIV_H
+#define AF9033_PRIV_H
+
+#include "dvb_frontend.h"
+#include "af9033.h"
+
+struct reg_val {
+ u32 reg;
+ u8 val;
+};
+
+struct reg_val_mask {
+ u32 reg;
+ u8 val;
+ u8 mask;
+};
+
+struct coeff {
+ u32 clock;
+ u32 bandwidth_hz;
+ u8 val[36];
+};
+
+struct clock_adc {
+ u32 clock;
+ u32 adc;
+};
+
+struct val_snr {
+ u32 val;
+ u8 snr;
+};
+
+/* Xtal clock vs. ADC clock lookup table */
+static const struct clock_adc clock_adc_lut[] = {
+ { 16384000, 20480000 },
+ { 20480000, 20480000 },
+ { 36000000, 20250000 },
+ { 30000000, 20156250 },
+ { 26000000, 20583333 },
+ { 28000000, 20416667 },
+ { 32000000, 20500000 },
+ { 34000000, 20187500 },
+ { 24000000, 20500000 },
+ { 22000000, 20625000 },
+ { 12000000, 20250000 },
+};
+
+/* pre-calculated coeff lookup table */
+static const struct coeff coeff_lut[] = {
+ /* 12.000 MHz */
+ { 12000000, 8000000, {
+ 0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73,
+ 0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5,
+ 0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73,
+ 0x95, 0x72, 0x37, 0x02, 0xce, 0x01 }
+ },
+ { 12000000, 7000000, {
+ 0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65,
+ 0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b,
+ 0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65,
+ 0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 }
+ },
+ { 12000000, 6000000, {
+ 0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56,
+ 0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60,
+ 0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56,
+ 0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 }
+ },
+};
+
+/* QPSK SNR lookup table */
+static const struct val_snr qpsk_snr_lut[] = {
+ { 0x0b4771, 0 },
+ { 0x0c1aed, 1 },
+ { 0x0d0d27, 2 },
+ { 0x0e4d19, 3 },
+ { 0x0e5da8, 4 },
+ { 0x107097, 5 },
+ { 0x116975, 6 },
+ { 0x1252d9, 7 },
+ { 0x131fa4, 8 },
+ { 0x13d5e1, 9 },
+ { 0x148e53, 10 },
+ { 0x15358b, 11 },
+ { 0x15dd29, 12 },
+ { 0x168112, 13 },
+ { 0x170b61, 14 },
+ { 0x17a532, 15 },
+ { 0x180f94, 16 },
+ { 0x186ed2, 17 },
+ { 0x18b271, 18 },
+ { 0x18e118, 19 },
+ { 0x18ff4b, 20 },
+ { 0x190af1, 21 },
+ { 0x191451, 22 },
+ { 0xffffff, 23 },
+};
+
+/* QAM16 SNR lookup table */
+static const struct val_snr qam16_snr_lut[] = {
+ { 0x04f0d5, 0 },
+ { 0x05387a, 1 },
+ { 0x0573a4, 2 },
+ { 0x05a99e, 3 },
+ { 0x05cc80, 4 },
+ { 0x05eb62, 5 },
+ { 0x05fecf, 6 },
+ { 0x060b80, 7 },
+ { 0x062501, 8 },
+ { 0x064865, 9 },
+ { 0x069604, 10 },
+ { 0x06f356, 11 },
+ { 0x07706a, 12 },
+ { 0x0804d3, 13 },
+ { 0x089d1a, 14 },
+ { 0x093e3d, 15 },
+ { 0x09e35d, 16 },
+ { 0x0a7c3c, 17 },
+ { 0x0afaf8, 18 },
+ { 0x0b719d, 19 },
+ { 0x0bda6a, 20 },
+ { 0x0c0c75, 21 },
+ { 0x0c3f7d, 22 },
+ { 0x0c5e62, 23 },
+ { 0x0c6c31, 24 },
+ { 0x0c7925, 25 },
+ { 0xffffff, 26 },
+};
+
+/* QAM64 SNR lookup table */
+static const struct val_snr qam64_snr_lut[] = {
+ { 0x0256d0, 0 },
+ { 0x027a65, 1 },
+ { 0x029873, 2 },
+ { 0x02b7fe, 3 },
+ { 0x02cf1e, 4 },
+ { 0x02e234, 5 },
+ { 0x02f409, 6 },
+ { 0x030046, 7 },
+ { 0x030844, 8 },
+ { 0x030a02, 9 },
+ { 0x030cde, 10 },
+ { 0x031031, 11 },
+ { 0x03144c, 12 },
+ { 0x0315dd, 13 },
+ { 0x031920, 14 },
+ { 0x0322d0, 15 },
+ { 0x0339fc, 16 },
+ { 0x0364a1, 17 },
+ { 0x038bcc, 18 },
+ { 0x03c7d3, 19 },
+ { 0x0408cc, 20 },
+ { 0x043bed, 21 },
+ { 0x048061, 22 },
+ { 0x04be95, 23 },
+ { 0x04fa7d, 24 },
+ { 0x052405, 25 },
+ { 0x05570d, 26 },
+ { 0x059feb, 27 },
+ { 0x05bf38, 28 },
+ { 0xffffff, 29 },
+};
+
+static const struct reg_val ofsm_init[] = {
+ { 0x800051, 0x01 },
+ { 0x800070, 0x0a },
+ { 0x80007e, 0x04 },
+ { 0x800081, 0x0a },
+ { 0x80008a, 0x01 },
+ { 0x80008e, 0x01 },
+ { 0x800092, 0x06 },
+ { 0x800099, 0x01 },
+ { 0x80009f, 0xe1 },
+ { 0x8000a0, 0xcf },
+ { 0x8000a3, 0x01 },
+ { 0x8000a5, 0x01 },
+ { 0x8000a6, 0x01 },
+ { 0x8000a9, 0x00 },
+ { 0x8000aa, 0x01 },
+ { 0x8000ab, 0x01 },
+ { 0x8000b0, 0x01 },
+ { 0x8000c0, 0x05 },
+ { 0x8000c4, 0x19 },
+ { 0x80f000, 0x0f },
+ { 0x80f016, 0x10 },
+ { 0x80f017, 0x04 },
+ { 0x80f018, 0x05 },
+ { 0x80f019, 0x04 },
+ { 0x80f01a, 0x05 },
+ { 0x80f021, 0x03 },
+ { 0x80f022, 0x0a },
+ { 0x80f023, 0x0a },
+ { 0x80f02b, 0x00 },
+ { 0x80f02c, 0x01 },
+ { 0x80f064, 0x03 },
+ { 0x80f065, 0xf9 },
+ { 0x80f066, 0x03 },
+ { 0x80f067, 0x01 },
+ { 0x80f06f, 0xe0 },
+ { 0x80f070, 0x03 },
+ { 0x80f072, 0x0f },
+ { 0x80f073, 0x03 },
+ { 0x80f078, 0x00 },
+ { 0x80f087, 0x00 },
+ { 0x80f09b, 0x3f },
+ { 0x80f09c, 0x00 },
+ { 0x80f09d, 0x20 },
+ { 0x80f09e, 0x00 },
+ { 0x80f09f, 0x0c },
+ { 0x80f0a0, 0x00 },
+ { 0x80f130, 0x04 },
+ { 0x80f132, 0x04 },
+ { 0x80f144, 0x1a },
+ { 0x80f146, 0x00 },
+ { 0x80f14a, 0x01 },
+ { 0x80f14c, 0x00 },
+ { 0x80f14d, 0x00 },
+ { 0x80f14f, 0x04 },
+ { 0x80f158, 0x7f },
+ { 0x80f15a, 0x00 },
+ { 0x80f15b, 0x08 },
+ { 0x80f15d, 0x03 },
+ { 0x80f15e, 0x05 },
+ { 0x80f163, 0x05 },
+ { 0x80f166, 0x01 },
+ { 0x80f167, 0x40 },
+ { 0x80f168, 0x0f },
+ { 0x80f17a, 0x00 },
+ { 0x80f17b, 0x00 },
+ { 0x80f183, 0x01 },
+ { 0x80f19d, 0x40 },
+ { 0x80f1bc, 0x36 },
+ { 0x80f1bd, 0x00 },
+ { 0x80f1cb, 0xa0 },
+ { 0x80f1cc, 0x01 },
+ { 0x80f204, 0x10 },
+ { 0x80f214, 0x00 },
+ { 0x80f40e, 0x0a },
+ { 0x80f40f, 0x40 },
+ { 0x80f410, 0x08 },
+ { 0x80f55f, 0x0a },
+ { 0x80f561, 0x15 },
+ { 0x80f562, 0x20 },
+ { 0x80f5df, 0xfb },
+ { 0x80f5e0, 0x00 },
+ { 0x80f5e3, 0x09 },
+ { 0x80f5e4, 0x01 },
+ { 0x80f5e5, 0x01 },
+ { 0x80f5f8, 0x01 },
+ { 0x80f5fd, 0x01 },
+ { 0x80f600, 0x05 },
+ { 0x80f601, 0x08 },
+ { 0x80f602, 0x0b },
+ { 0x80f603, 0x0e },
+ { 0x80f604, 0x11 },
+ { 0x80f605, 0x14 },
+ { 0x80f606, 0x17 },
+ { 0x80f607, 0x1f },
+ { 0x80f60e, 0x00 },
+ { 0x80f60f, 0x04 },
+ { 0x80f610, 0x32 },
+ { 0x80f611, 0x10 },
+ { 0x80f707, 0xfc },
+ { 0x80f708, 0x00 },
+ { 0x80f709, 0x37 },
+ { 0x80f70a, 0x00 },
+ { 0x80f78b, 0x01 },
+ { 0x80f80f, 0x40 },
+ { 0x80f810, 0x54 },
+ { 0x80f811, 0x5a },
+ { 0x80f905, 0x01 },
+ { 0x80fb06, 0x03 },
+ { 0x80fd8b, 0x00 },
+};
+
+/* Infineon TUA 9001 tuner init
+ AF9033_TUNER_TUA9001 = 0x27 */
+static const struct reg_val tuner_init_tua9001[] = {
+ { 0x800046, 0x27 },
+ { 0x800057, 0x00 },
+ { 0x800058, 0x01 },
+ { 0x80005f, 0x00 },
+ { 0x800060, 0x00 },
+ { 0x80006d, 0x00 },
+ { 0x800071, 0x05 },
+ { 0x800072, 0x02 },
+ { 0x800074, 0x01 },
+ { 0x800075, 0x03 },
+ { 0x800076, 0x02 },
+ { 0x800077, 0x00 },
+ { 0x800078, 0x01 },
+ { 0x800079, 0x00 },
+ { 0x80007a, 0x7e },
+ { 0x80007b, 0x3e },
+ { 0x800093, 0x00 },
+ { 0x800094, 0x01 },
+ { 0x800095, 0x02 },
+ { 0x800096, 0x01 },
+ { 0x800098, 0x0a },
+ { 0x80009b, 0x05 },
+ { 0x80009c, 0x80 },
+ { 0x8000b3, 0x00 },
+ { 0x8000c1, 0x01 },
+ { 0x8000c2, 0x00 },
+ { 0x80f007, 0x00 },
+ { 0x80f01f, 0x82 },
+ { 0x80f020, 0x00 },
+ { 0x80f029, 0x82 },
+ { 0x80f02a, 0x00 },
+ { 0x80f047, 0x00 },
+ { 0x80f054, 0x00 },
+ { 0x80f055, 0x00 },
+ { 0x80f077, 0x01 },
+ { 0x80f1e6, 0x00 },
+};
+
+/* Fitipower fc0011 tuner init
+ AF9033_TUNER_FC0011 = 0x28 */
+static const struct reg_val tuner_init_fc0011[] = {
+ { 0x800046, AF9033_TUNER_FC0011 },
+ { 0x800057, 0x00 },
+ { 0x800058, 0x01 },
+ { 0x80005f, 0x00 },
+ { 0x800060, 0x00 },
+ { 0x800068, 0xa5 },
+ { 0x80006e, 0x01 },
+ { 0x800071, 0x0A },
+ { 0x800072, 0x02 },
+ { 0x800074, 0x01 },
+ { 0x800079, 0x01 },
+ { 0x800093, 0x00 },
+ { 0x800094, 0x00 },
+ { 0x800095, 0x00 },
+ { 0x800096, 0x00 },
+ { 0x80009b, 0x2D },
+ { 0x80009c, 0x60 },
+ { 0x80009d, 0x23 },
+ { 0x8000a4, 0x50 },
+ { 0x8000ad, 0x50 },
+ { 0x8000b3, 0x01 },
+ { 0x8000b7, 0x88 },
+ { 0x8000b8, 0xa6 },
+ { 0x8000c3, 0x01 },
+ { 0x8000c4, 0x01 },
+ { 0x8000c7, 0x69 },
+ { 0x80F007, 0x00 },
+ { 0x80F00A, 0x1B },
+ { 0x80F00B, 0x1B },
+ { 0x80F00C, 0x1B },
+ { 0x80F00D, 0x1B },
+ { 0x80F00E, 0xFF },
+ { 0x80F00F, 0x01 },
+ { 0x80F010, 0x00 },
+ { 0x80F011, 0x02 },
+ { 0x80F012, 0xFF },
+ { 0x80F013, 0x01 },
+ { 0x80F014, 0x00 },
+ { 0x80F015, 0x02 },
+ { 0x80F01B, 0xEF },
+ { 0x80F01C, 0x01 },
+ { 0x80F01D, 0x0f },
+ { 0x80F01E, 0x02 },
+ { 0x80F01F, 0x6E },
+ { 0x80F020, 0x00 },
+ { 0x80F025, 0xDE },
+ { 0x80F026, 0x00 },
+ { 0x80F027, 0x0A },
+ { 0x80F028, 0x03 },
+ { 0x80F029, 0x6E },
+ { 0x80F02A, 0x00 },
+ { 0x80F047, 0x00 },
+ { 0x80F054, 0x00 },
+ { 0x80F055, 0x00 },
+ { 0x80F077, 0x01 },
+ { 0x80F1E6, 0x00 },
+};
+
+/* MaxLinear MxL5007T tuner init
+ AF9033_TUNER_MXL5007T = 0xa0 */
+static const struct reg_val tuner_init_mxl5007t[] = {
+ { 0x800046, 0x1b },
+ { 0x800057, 0x01 },
+ { 0x800058, 0x01 },
+ { 0x80005f, 0x00 },
+ { 0x800060, 0x00 },
+ { 0x800068, 0x96 },
+ { 0x800071, 0x05 },
+ { 0x800072, 0x02 },
+ { 0x800074, 0x01 },
+ { 0x800079, 0x01 },
+ { 0x800093, 0x00 },
+ { 0x800094, 0x00 },
+ { 0x800095, 0x00 },
+ { 0x800096, 0x00 },
+ { 0x8000b3, 0x01 },
+ { 0x8000c1, 0x01 },
+ { 0x8000c2, 0x00 },
+ { 0x80f007, 0x00 },
+ { 0x80f00c, 0x19 },
+ { 0x80f00d, 0x1a },
+ { 0x80f012, 0xda },
+ { 0x80f013, 0x00 },
+ { 0x80f014, 0x00 },
+ { 0x80f015, 0x02 },
+ { 0x80f01f, 0x82 },
+ { 0x80f020, 0x00 },
+ { 0x80f029, 0x82 },
+ { 0x80f02a, 0x00 },
+ { 0x80f077, 0x02 },
+ { 0x80f1e6, 0x00 },
+};
+
+/* NXP TDA 18218HN tuner init
+ AF9033_TUNER_TDA18218 = 0xa1 */
+static const struct reg_val tuner_init_tda18218[] = {
+ {0x800046, 0xa1},
+ {0x800057, 0x01},
+ {0x800058, 0x01},
+ {0x80005f, 0x00},
+ {0x800060, 0x00},
+ {0x800071, 0x05},
+ {0x800072, 0x02},
+ {0x800074, 0x01},
+ {0x800079, 0x01},
+ {0x800093, 0x00},
+ {0x800094, 0x00},
+ {0x800095, 0x00},
+ {0x800096, 0x00},
+ {0x8000b3, 0x01},
+ {0x8000c3, 0x01},
+ {0x8000c4, 0x00},
+ {0x80f007, 0x00},
+ {0x80f00c, 0x19},
+ {0x80f00d, 0x1a},
+ {0x80f012, 0xda},
+ {0x80f013, 0x00},
+ {0x80f014, 0x00},
+ {0x80f015, 0x02},
+ {0x80f01f, 0x82},
+ {0x80f020, 0x00},
+ {0x80f029, 0x82},
+ {0x80f02a, 0x00},
+ {0x80f077, 0x02},
+ {0x80f1e6, 0x00},
+};
+
+#endif /* AF9033_PRIV_H */
+
diff --git a/drivers/media/dvb/frontends/au8522_common.c b/drivers/media/dvb/frontends/au8522_common.c
new file mode 100644
index 000000000000..5cfe151ee394
--- /dev/null
+++ b/drivers/media/dvb/frontends/au8522_common.c
@@ -0,0 +1,259 @@
+/*
+ Auvitek AU8522 QAM/8VSB demodulator driver
+
+ Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
+ Copyright (C) 2008 Devin Heitmueller <dheitmueller@linuxtv.org>
+ Copyright (C) 2005-2008 Auvitek International, Ltd.
+ Copyright (C) 2012 Michael Krufky <mkrufky@linuxtv.org>
+
+ 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 <linux/i2c.h>
+#include "dvb_frontend.h"
+#include "au8522_priv.h"
+
+MODULE_LICENSE("GPL");
+
+static int debug;
+
+#define dprintk(arg...)\
+ do { if (debug)\
+ printk(arg);\
+ } while (0)
+
+/* Despite the name "hybrid_tuner", the framework works just as well for
+ hybrid demodulators as well... */
+static LIST_HEAD(hybrid_tuner_instance_list);
+static DEFINE_MUTEX(au8522_list_mutex);
+
+/* 16 bit registers, 8 bit values */
+int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
+{
+ int ret;
+ u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
+
+ struct i2c_msg msg = { .addr = state->config->demod_address,
+ .flags = 0, .buf = buf, .len = 3 };
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+ "ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+}
+EXPORT_SYMBOL(au8522_writereg);
+
+u8 au8522_readreg(struct au8522_state *state, u16 reg)
+{
+ int ret;
+ u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
+ u8 b1[] = { 0 };
+
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0,
+ .buf = b0, .len = 2 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
+ .buf = b1, .len = 1 } };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+ __func__, ret);
+ return b1[0];
+}
+EXPORT_SYMBOL(au8522_readreg);
+
+int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+
+ dprintk("%s(%d)\n", __func__, enable);
+
+ if (state->operational_mode == AU8522_ANALOG_MODE) {
+ /* We're being asked to manage the gate even though we're
+ not in digital mode. This can occur if we get switched
+ over to analog mode before the dvb_frontend kernel thread
+ has completely shutdown */
+ return 0;
+ }
+
+ if (enable)
+ return au8522_writereg(state, 0x106, 1);
+ else
+ return au8522_writereg(state, 0x106, 0);
+}
+EXPORT_SYMBOL(au8522_i2c_gate_ctrl);
+
+/* Reset the demod hardware and reset all of the configuration registers
+ to a default state. */
+int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
+ u8 client_address)
+{
+ int ret;
+
+ mutex_lock(&au8522_list_mutex);
+ ret = hybrid_tuner_request_state(struct au8522_state, (*state),
+ hybrid_tuner_instance_list,
+ i2c, client_address, "au8522");
+ mutex_unlock(&au8522_list_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(au8522_get_state);
+
+void au8522_release_state(struct au8522_state *state)
+{
+ mutex_lock(&au8522_list_mutex);
+ if (state != NULL)
+ hybrid_tuner_release_state(state);
+ mutex_unlock(&au8522_list_mutex);
+}
+EXPORT_SYMBOL(au8522_release_state);
+
+static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
+{
+ struct au8522_led_config *led_config = state->config->led_cfg;
+ u8 val;
+
+ /* bail out if we can't control an LED */
+ if (!led_config || !led_config->gpio_output ||
+ !led_config->gpio_output_enable || !led_config->gpio_output_disable)
+ return 0;
+
+ val = au8522_readreg(state, 0x4000 |
+ (led_config->gpio_output & ~0xc000));
+ if (onoff) {
+ /* enable GPIO output */
+ val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
+ val |= (led_config->gpio_output_enable & 0xff);
+ } else {
+ /* disable GPIO output */
+ val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
+ val |= (led_config->gpio_output_disable & 0xff);
+ }
+ return au8522_writereg(state, 0x8000 |
+ (led_config->gpio_output & ~0xc000), val);
+}
+
+/* led = 0 | off
+ * led = 1 | signal ok
+ * led = 2 | signal strong
+ * led < 0 | only light led if leds are currently off
+ */
+int au8522_led_ctrl(struct au8522_state *state, int led)
+{
+ struct au8522_led_config *led_config = state->config->led_cfg;
+ int i, ret = 0;
+
+ /* bail out if we can't control an LED */
+ if (!led_config || !led_config->gpio_leds ||
+ !led_config->num_led_states || !led_config->led_states)
+ return 0;
+
+ if (led < 0) {
+ /* if LED is already lit, then leave it as-is */
+ if (state->led_state)
+ return 0;
+ else
+ led *= -1;
+ }
+
+ /* toggle LED if changing state */
+ if (state->led_state != led) {
+ u8 val;
+
+ dprintk("%s: %d\n", __func__, led);
+
+ au8522_led_gpio_enable(state, 1);
+
+ val = au8522_readreg(state, 0x4000 |
+ (led_config->gpio_leds & ~0xc000));
+
+ /* start with all leds off */
+ for (i = 0; i < led_config->num_led_states; i++)
+ val &= ~led_config->led_states[i];
+
+ /* set selected LED state */
+ if (led < led_config->num_led_states)
+ val |= led_config->led_states[led];
+ else if (led_config->num_led_states)
+ val |=
+ led_config->led_states[led_config->num_led_states - 1];
+
+ ret = au8522_writereg(state, 0x8000 |
+ (led_config->gpio_leds & ~0xc000), val);
+ if (ret < 0)
+ return ret;
+
+ state->led_state = led;
+
+ if (led == 0)
+ au8522_led_gpio_enable(state, 0);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(au8522_led_ctrl);
+
+int au8522_init(struct dvb_frontend *fe)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ dprintk("%s()\n", __func__);
+
+ state->operational_mode = AU8522_DIGITAL_MODE;
+
+ /* Clear out any state associated with the digital side of the
+ chip, so that when it gets powered back up it won't think
+ that it is already tuned */
+ state->current_frequency = 0;
+
+ au8522_writereg(state, 0xa4, 1 << 5);
+
+ au8522_i2c_gate_ctrl(fe, 1);
+
+ return 0;
+}
+EXPORT_SYMBOL(au8522_init);
+
+int au8522_sleep(struct dvb_frontend *fe)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ dprintk("%s()\n", __func__);
+
+ /* Only power down if the digital side is currently using the chip */
+ if (state->operational_mode == AU8522_ANALOG_MODE) {
+ /* We're not in one of the expected power modes, which means
+ that the DVB thread is probably telling us to go to sleep
+ even though the analog frontend has already started using
+ the chip. So ignore the request */
+ return 0;
+ }
+
+ /* turn off led */
+ au8522_led_ctrl(state, 0);
+
+ /* Power down the chip */
+ au8522_writereg(state, 0xa4, 1 << 5);
+
+ state->current_frequency = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL(au8522_sleep);
diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c
index 25f650934c73..5fc70d6cd04f 100644
--- a/drivers/media/dvb/frontends/au8522_dig.c
+++ b/drivers/media/dvb/frontends/au8522_dig.c
@@ -30,74 +30,11 @@
static int debug;
-/* Despite the name "hybrid_tuner", the framework works just as well for
- hybrid demodulators as well... */
-static LIST_HEAD(hybrid_tuner_instance_list);
-static DEFINE_MUTEX(au8522_list_mutex);
-
#define dprintk(arg...)\
do { if (debug)\
printk(arg);\
} while (0)
-/* 16 bit registers, 8 bit values */
-int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
-{
- int ret;
- u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
-
- struct i2c_msg msg = { .addr = state->config->demod_address,
- .flags = 0, .buf = buf, .len = 3 };
-
- ret = i2c_transfer(state->i2c, &msg, 1);
-
- if (ret != 1)
- printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
- "ret == %i)\n", __func__, reg, data, ret);
-
- return (ret != 1) ? -1 : 0;
-}
-
-u8 au8522_readreg(struct au8522_state *state, u16 reg)
-{
- int ret;
- u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
- u8 b1[] = { 0 };
-
- struct i2c_msg msg[] = {
- { .addr = state->config->demod_address, .flags = 0,
- .buf = b0, .len = 2 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD,
- .buf = b1, .len = 1 } };
-
- ret = i2c_transfer(state->i2c, msg, 2);
-
- if (ret != 2)
- printk(KERN_ERR "%s: readreg error (ret == %i)\n",
- __func__, ret);
- return b1[0];
-}
-
-static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
- struct au8522_state *state = fe->demodulator_priv;
-
- dprintk("%s(%d)\n", __func__, enable);
-
- if (state->operational_mode == AU8522_ANALOG_MODE) {
- /* We're being asked to manage the gate even though we're
- not in digital mode. This can occur if we get switched
- over to analog mode before the dvb_frontend kernel thread
- has completely shutdown */
- return 0;
- }
-
- if (enable)
- return au8522_writereg(state, 0x106, 1);
- else
- return au8522_writereg(state, 0x106, 0);
-}
-
struct mse2snr_tab {
u16 val;
u16 data;
@@ -609,136 +546,6 @@ static int au8522_set_frontend(struct dvb_frontend *fe)
return 0;
}
-/* Reset the demod hardware and reset all of the configuration registers
- to a default state. */
-int au8522_init(struct dvb_frontend *fe)
-{
- struct au8522_state *state = fe->demodulator_priv;
- dprintk("%s()\n", __func__);
-
- state->operational_mode = AU8522_DIGITAL_MODE;
-
- /* Clear out any state associated with the digital side of the
- chip, so that when it gets powered back up it won't think
- that it is already tuned */
- state->current_frequency = 0;
-
- au8522_writereg(state, 0xa4, 1 << 5);
-
- au8522_i2c_gate_ctrl(fe, 1);
-
- return 0;
-}
-
-static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
-{
- struct au8522_led_config *led_config = state->config->led_cfg;
- u8 val;
-
- /* bail out if we can't control an LED */
- if (!led_config || !led_config->gpio_output ||
- !led_config->gpio_output_enable || !led_config->gpio_output_disable)
- return 0;
-
- val = au8522_readreg(state, 0x4000 |
- (led_config->gpio_output & ~0xc000));
- if (onoff) {
- /* enable GPIO output */
- val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
- val |= (led_config->gpio_output_enable & 0xff);
- } else {
- /* disable GPIO output */
- val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
- val |= (led_config->gpio_output_disable & 0xff);
- }
- return au8522_writereg(state, 0x8000 |
- (led_config->gpio_output & ~0xc000), val);
-}
-
-/* led = 0 | off
- * led = 1 | signal ok
- * led = 2 | signal strong
- * led < 0 | only light led if leds are currently off
- */
-static int au8522_led_ctrl(struct au8522_state *state, int led)
-{
- struct au8522_led_config *led_config = state->config->led_cfg;
- int i, ret = 0;
-
- /* bail out if we can't control an LED */
- if (!led_config || !led_config->gpio_leds ||
- !led_config->num_led_states || !led_config->led_states)
- return 0;
-
- if (led < 0) {
- /* if LED is already lit, then leave it as-is */
- if (state->led_state)
- return 0;
- else
- led *= -1;
- }
-
- /* toggle LED if changing state */
- if (state->led_state != led) {
- u8 val;
-
- dprintk("%s: %d\n", __func__, led);
-
- au8522_led_gpio_enable(state, 1);
-
- val = au8522_readreg(state, 0x4000 |
- (led_config->gpio_leds & ~0xc000));
-
- /* start with all leds off */
- for (i = 0; i < led_config->num_led_states; i++)
- val &= ~led_config->led_states[i];
-
- /* set selected LED state */
- if (led < led_config->num_led_states)
- val |= led_config->led_states[led];
- else if (led_config->num_led_states)
- val |=
- led_config->led_states[led_config->num_led_states - 1];
-
- ret = au8522_writereg(state, 0x8000 |
- (led_config->gpio_leds & ~0xc000), val);
- if (ret < 0)
- return ret;
-
- state->led_state = led;
-
- if (led == 0)
- au8522_led_gpio_enable(state, 0);
- }
-
- return 0;
-}
-
-int au8522_sleep(struct dvb_frontend *fe)
-{
- struct au8522_state *state = fe->demodulator_priv;
- dprintk("%s()\n", __func__);
-
- /* Only power down if the digital side is currently using the chip */
- if (state->operational_mode == AU8522_ANALOG_MODE) {
- /* We're not in one of the expected power modes, which means
- that the DVB thread is probably telling us to go to sleep
- even though the analog frontend has already started using
- the chip. So ignore the request */
- return 0;
- }
-
- /* turn off led */
- au8522_led_ctrl(state, 0);
-
- /* Power down the chip */
- au8522_writereg(state, 0xa4, 1 << 5);
-
- state->current_frequency = 0;
-
- return 0;
-}
-
static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct au8522_state *state = fe->demodulator_priv;
@@ -931,28 +738,6 @@ static int au8522_get_tune_settings(struct dvb_frontend *fe,
static struct dvb_frontend_ops au8522_ops;
-int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
- u8 client_address)
-{
- int ret;
-
- mutex_lock(&au8522_list_mutex);
- ret = hybrid_tuner_request_state(struct au8522_state, (*state),
- hybrid_tuner_instance_list,
- i2c, client_address, "au8522");
- mutex_unlock(&au8522_list_mutex);
-
- return ret;
-}
-
-void au8522_release_state(struct au8522_state *state)
-{
- mutex_lock(&au8522_list_mutex);
- if (state != NULL)
- hybrid_tuner_release_state(state);
- mutex_unlock(&au8522_list_mutex);
-}
-
static void au8522_release(struct dvb_frontend *fe)
{
diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h
index 751e17d692a9..6e4a438732b5 100644
--- a/drivers/media/dvb/frontends/au8522_priv.h
+++ b/drivers/media/dvb/frontends/au8522_priv.h
@@ -81,6 +81,8 @@ int au8522_sleep(struct dvb_frontend *fe);
int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
u8 client_address);
void au8522_release_state(struct au8522_state *state);
+int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+int au8522_led_ctrl(struct au8522_state *state, int led);
/* REGISTERS */
#define AU8522_INPUT_CONTROL_REG081H 0x081
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 5101f10f2d7a..98ecaf0900d6 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -512,14 +512,13 @@ static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct cx24110_state *state = fe->demodulator_priv;
- u32 lastbyer;
if(cx24110_readreg(state,0x10)&0x40) {
/* the RS error counter has finished one counting window */
cx24110_writereg(state,0x10,0x60); /* select the byer reg */
- lastbyer=cx24110_readreg(state,0x12)|
- (cx24110_readreg(state,0x13)<<8)|
- (cx24110_readreg(state,0x14)<<16);
+ cx24110_readreg(state, 0x12) |
+ (cx24110_readreg(state, 0x13) << 8) |
+ (cx24110_readreg(state, 0x14) << 16);
cx24110_writereg(state,0x10,0x70); /* select the bler reg */
state->lastbler=cx24110_readreg(state,0x12)|
(cx24110_readreg(state,0x13)<<8)|
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
index 5c7c2aaf9bf5..3bba37d74f57 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -526,12 +526,12 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
if (ret)
goto error;
- if (status & FE_HAS_SIGNAL)
+ if (status & FE_HAS_LOCK)
break;
}
/* check if we have a valid signal */
- if (status) {
+ if (status & FE_HAS_LOCK) {
priv->last_tune_failed = 0;
return DVBFE_ALGO_SEARCH_SUCCESS;
} else {
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 5ceadc285b3a..3e1eefada0e8 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -2396,11 +2396,6 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
more common) */
st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
- /* FIXME: make sure the dev.parent field is initialized, or else
- request_firmware() will hit an OOPS (this should be moved somewhere
- more common) */
- st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
-
dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
/* init 7090 tuner adapter */
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c
index 80848b4c15d4..6201c59a78dd 100644
--- a/drivers/media/dvb/frontends/dib9000.c
+++ b/drivers/media/dvb/frontends/dib9000.c
@@ -31,13 +31,6 @@ struct i2c_device {
u8 *i2c_write_buffer;
};
-/* lock */
-#define DIB_LOCK struct mutex
-#define DibAcquireLock(lock) mutex_lock_interruptible(lock)
-#define DibReleaseLock(lock) mutex_unlock(lock)
-#define DibInitLock(lock) mutex_init(lock)
-#define DibFreeLock(lock)
-
struct dib9000_pid_ctrl {
#define DIB9000_PID_FILTER_CTRL 0
#define DIB9000_PID_FILTER 1
@@ -82,11 +75,11 @@ struct dib9000_state {
} fe_mm[18];
u8 memcmd;
- DIB_LOCK mbx_if_lock; /* to protect read/write operations */
- DIB_LOCK mbx_lock; /* to protect the whole mailbox handling */
+ struct mutex mbx_if_lock; /* to protect read/write operations */
+ struct mutex mbx_lock; /* to protect the whole mailbox handling */
- DIB_LOCK mem_lock; /* to protect the memory accesses */
- DIB_LOCK mem_mbx_lock; /* to protect the memory-based mailbox */
+ struct mutex mem_lock; /* to protect the memory accesses */
+ struct mutex mem_mbx_lock; /* to protect the memory-based mailbox */
#define MBX_MAX_WORDS (256 - 200 - 2)
#define DIB9000_MSG_CACHE_SIZE 2
@@ -108,7 +101,7 @@ struct dib9000_state {
struct i2c_msg msg[2];
u8 i2c_write_buffer[255];
u8 i2c_read_buffer[255];
- DIB_LOCK demod_lock;
+ struct mutex demod_lock;
u8 get_frontend_internal;
struct dib9000_pid_ctrl pid_ctrl[10];
s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
@@ -446,13 +439,13 @@ static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u1
if (!state->platform.risc.fw_is_running)
return -EIO;
- if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
dib9000_risc_mem_setup(state, cmd | 0x80);
dib9000_risc_mem_read_chunks(state, b, len);
- DibReleaseLock(&state->platform.risc.mem_lock);
+ mutex_unlock(&state->platform.risc.mem_lock);
return 0;
}
@@ -462,13 +455,13 @@ static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8
if (!state->platform.risc.fw_is_running)
return -EIO;
- if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
dib9000_risc_mem_setup(state, cmd);
dib9000_risc_mem_write_chunks(state, b, m->size);
- DibReleaseLock(&state->platform.risc.mem_lock);
+ mutex_unlock(&state->platform.risc.mem_lock);
return 0;
}
@@ -537,7 +530,7 @@ static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data,
if (!state->platform.risc.fw_is_running)
return -EINVAL;
- if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -584,7 +577,7 @@ static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data,
ret = (u8) dib9000_write_word_attr(state, 1043, 1 << 14, attr);
out:
- DibReleaseLock(&state->platform.risc.mbx_if_lock);
+ mutex_unlock(&state->platform.risc.mbx_if_lock);
return ret;
}
@@ -602,7 +595,7 @@ static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id,
if (!state->platform.risc.fw_is_running)
return 0;
- if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
dprintk("could not get the lock");
return 0;
}
@@ -643,7 +636,7 @@ static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id,
/* Update register nb_mes_in_TX */
dib9000_write_word_attr(state, 1028 + mc_base, 1 << 14, attr);
- DibReleaseLock(&state->platform.risc.mbx_if_lock);
+ mutex_unlock(&state->platform.risc.mbx_if_lock);
return size + 1;
}
@@ -708,12 +701,11 @@ static u8 dib9000_mbx_count(struct dib9000_state *state, u8 risc_id, u16 attr)
static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
{
int ret = 0;
- u16 tmp;
if (!state->platform.risc.fw_is_running)
return -1;
- if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mbx_lock) < 0) {
dprintk("could not get the lock");
return -1;
}
@@ -721,10 +713,10 @@ static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */
ret = dib9000_mbx_fetch_to_cache(state, attr);
- tmp = dib9000_read_word_attr(state, 1229, attr); /* Clear the IRQ */
+ dib9000_read_word_attr(state, 1229, attr); /* Clear the IRQ */
/* if (tmp) */
/* dprintk( "cleared IRQ: %x", tmp); */
- DibReleaseLock(&state->platform.risc.mbx_lock);
+ mutex_unlock(&state->platform.risc.mbx_lock);
return ret;
}
@@ -1193,7 +1185,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe)
struct dibDVBTChannel *ch;
int ret = 0;
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -1323,7 +1315,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe)
}
error:
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
return ret;
}
@@ -1678,7 +1670,7 @@ static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2
p[12] = 0;
}
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
dprintk("could not get the lock");
return 0;
}
@@ -1692,7 +1684,7 @@ static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2
/* do the transaction */
if (dib9000_fw_memmbx_sync(state, FE_SYNC_COMPONENT_ACCESS) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
return 0;
}
@@ -1700,7 +1692,7 @@ static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2
if ((num > 1) && (msg[1].flags & I2C_M_RD))
dib9000_risc_mem_read(state, FE_MM_RW_COMPONENT_ACCESS_BUFFER, msg[1].buf, msg[1].len);
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
return num;
}
@@ -1789,7 +1781,7 @@ int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
return 0;
}
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -1799,7 +1791,7 @@ int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
dprintk("PID filter enabled %d", onoff);
ret = dib9000_write_word(state, 294 + 1, val);
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return ret;
}
@@ -1824,14 +1816,14 @@ int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
return 0;
}
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
ret = dib9000_write_word(state, 300 + 1 + id,
onoff ? (1 << 13) | pid : 0);
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return ret;
}
EXPORT_SYMBOL(dib9000_fw_pid_filter);
@@ -1851,11 +1843,6 @@ static void dib9000_release(struct dvb_frontend *demod)
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
dvb_frontend_detach(st->fe[index_frontend]);
- DibFreeLock(&state->platform.risc.mbx_if_lock);
- DibFreeLock(&state->platform.risc.mbx_lock);
- DibFreeLock(&state->platform.risc.mem_lock);
- DibFreeLock(&state->platform.risc.mem_mbx_lock);
- DibFreeLock(&state->demod_lock);
dibx000_exit_i2c_master(&st->i2c_master);
i2c_del_adapter(&st->tuner_adap);
@@ -1875,7 +1862,7 @@ static int dib9000_sleep(struct dvb_frontend *fe)
u8 index_frontend;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -1887,7 +1874,7 @@ static int dib9000_sleep(struct dvb_frontend *fe)
ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
error:
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return ret;
}
@@ -1905,7 +1892,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe)
int ret = 0;
if (state->get_frontend_internal == 0) {
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -1964,7 +1951,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe)
return_value:
if (state->get_frontend_internal == 0)
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return ret;
}
@@ -2012,7 +1999,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe)
}
state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return 0;
}
@@ -2081,7 +2068,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe)
/* check the tune result */
if (exit_condition == 1) { /* tune failed */
dprintk("tune failed");
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
/* tune failed; put all the pid filtering cmd to junk */
state->pid_ctrl_index = -1;
return 0;
@@ -2137,7 +2124,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe)
/* turn off the diversity for the last frontend */
dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
if (state->pid_ctrl_index >= 0) {
u8 index_pid_filter_cmd;
u8 pid_ctrl_index = state->pid_ctrl_index;
@@ -2175,7 +2162,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
u8 index_frontend;
u16 lock = 0, lock_slave = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -2197,7 +2184,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
if ((lock & 0x0008) || (lock_slave & 0x0008))
*stat |= FE_HAS_LOCK;
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return 0;
}
@@ -2208,30 +2195,30 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
u16 *c;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
dprintk("could not get the lock");
ret = -EINTR;
goto error;
}
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
ret = -EIO;
goto error;
}
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
state->i2c_read_buffer, 16 * 2);
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
c = (u16 *)state->i2c_read_buffer;
*ber = c[10] << 16 | c[11];
error:
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return ret;
}
@@ -2243,7 +2230,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
u16 val;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -2256,18 +2243,18 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
*strength += val;
}
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
dprintk("could not get the lock");
ret = -EINTR;
goto error;
}
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
ret = -EIO;
goto error;
}
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
val = 65535 - c[4];
if (val > 65535 - *strength)
@@ -2276,7 +2263,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
*strength += val;
error:
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return ret;
}
@@ -2287,16 +2274,16 @@ static u32 dib9000_get_snr(struct dvb_frontend *fe)
u32 n, s, exp;
u16 val;
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
dprintk("could not get the lock");
return 0;
}
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
return 0;
}
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
val = c[7];
n = (val >> 4) & 0xff;
@@ -2326,7 +2313,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
u8 index_frontend;
u32 snr_master;
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
@@ -2340,7 +2327,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
} else
*snr = 0;
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return 0;
}
@@ -2351,27 +2338,27 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
u16 *c = (u16 *)state->i2c_read_buffer;
int ret = 0;
- if (DibAcquireLock(&state->demod_lock) < 0) {
+ if (mutex_lock_interruptible(&state->demod_lock) < 0) {
dprintk("could not get the lock");
return -EINTR;
}
- if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
+ if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
dprintk("could not get the lock");
ret = -EINTR;
goto error;
}
if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
ret = -EIO;
goto error;
}
dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
- DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+ mutex_unlock(&state->platform.risc.mem_mbx_lock);
*unc = c[12];
error:
- DibReleaseLock(&state->demod_lock);
+ mutex_unlock(&state->demod_lock);
return ret;
}
@@ -2514,11 +2501,11 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c
st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
st->gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS;
- DibInitLock(&st->platform.risc.mbx_if_lock);
- DibInitLock(&st->platform.risc.mbx_lock);
- DibInitLock(&st->platform.risc.mem_lock);
- DibInitLock(&st->platform.risc.mem_mbx_lock);
- DibInitLock(&st->demod_lock);
+ mutex_init(&st->platform.risc.mbx_if_lock);
+ mutex_init(&st->platform.risc.mbx_lock);
+ mutex_init(&st->platform.risc.mem_lock);
+ mutex_init(&st->platform.risc.mem_mbx_lock);
+ mutex_init(&st->demod_lock);
st->get_frontend_internal = 0;
st->pid_ctrl_index = -2;
diff --git a/drivers/media/dvb/frontends/drxd.h b/drivers/media/dvb/frontends/drxd.h
index 34398738f9bc..216c8c3702f8 100644
--- a/drivers/media/dvb/frontends/drxd.h
+++ b/drivers/media/dvb/frontends/drxd.h
@@ -51,9 +51,23 @@ struct drxd_config {
s16(*osc_deviation) (void *priv, s16 dev, int flag);
};
+#if defined(CONFIG_DVB_DRXD) || \
+ (defined(CONFIG_DVB_DRXD_MODULE) && defined(MODULE))
extern
struct dvb_frontend *drxd_attach(const struct drxd_config *config,
void *priv, struct i2c_adapter *i2c,
struct device *dev);
+#else
+static inline
+struct dvb_frontend *drxd_attach(const struct drxd_config *config,
+ void *priv, struct i2c_adapter *i2c,
+ struct device *dev)
+{
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+ __func__);
+ return NULL;
+}
+#endif
+
extern int drxd_config_i2c(struct dvb_frontend *, int);
#endif
diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
index a414b1f2b6a5..60b868faeacf 100644
--- a/drivers/media/dvb/frontends/drxk_hard.c
+++ b/drivers/media/dvb/frontends/drxk_hard.c
@@ -1380,20 +1380,20 @@ static int DownloadMicrocode(struct drxk_state *state,
const u8 pMCImage[], u32 Length)
{
const u8 *pSrc = pMCImage;
- u16 Flags;
- u16 Drain;
u32 Address;
u16 nBlocks;
u16 BlockSize;
- u16 BlockCRC;
u32 offset = 0;
u32 i;
int status = 0;
dprintk(1, "\n");
- /* down the drain (we don care about MAGIC_WORD) */
+ /* down the drain (we don't care about MAGIC_WORD) */
+#if 0
+ /* For future reference */
Drain = (pSrc[0] << 8) | pSrc[1];
+#endif
pSrc += sizeof(u16);
offset += sizeof(u16);
nBlocks = (pSrc[0] << 8) | pSrc[1];
@@ -1410,11 +1410,17 @@ static int DownloadMicrocode(struct drxk_state *state,
pSrc += sizeof(u16);
offset += sizeof(u16);
+#if 0
+ /* For future reference */
Flags = (pSrc[0] << 8) | pSrc[1];
+#endif
pSrc += sizeof(u16);
offset += sizeof(u16);
+#if 0
+ /* For future reference */
BlockCRC = (pSrc[0] << 8) | pSrc[1];
+#endif
pSrc += sizeof(u16);
offset += sizeof(u16);
@@ -5829,7 +5835,7 @@ static int WriteGPIO(struct drxk_state *state)
}
if (state->UIO_mask & 0x0002) { /* UIO-2 */
/* write to io pad configuration register - output mode */
- status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg);
+ status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_GPIOCfg);
if (status < 0)
goto error;
@@ -5848,7 +5854,7 @@ static int WriteGPIO(struct drxk_state *state)
}
if (state->UIO_mask & 0x0004) { /* UIO-3 */
/* write to io pad configuration register - output mode */
- status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg);
+ status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_GPIOCfg);
if (status < 0)
goto error;
diff --git a/drivers/media/dvb/frontends/drxk_map.h b/drivers/media/dvb/frontends/drxk_map.h
index 9b11a8328869..23e16c12f234 100644
--- a/drivers/media/dvb/frontends/drxk_map.h
+++ b/drivers/media/dvb/frontends/drxk_map.h
@@ -432,6 +432,7 @@
#define SIO_PDR_UIO_OUT_LO__A 0x7F0016
#define SIO_PDR_OHW_CFG__A 0x7F001F
#define SIO_PDR_OHW_CFG_FREF_SEL__M 0x3
+#define SIO_PDR_GPIO_CFG__A 0x7F0021
#define SIO_PDR_MSTRT_CFG__A 0x7F0025
#define SIO_PDR_MERR_CFG__A 0x7F0026
#define SIO_PDR_MCLK_CFG__A 0x7F0028
@@ -446,4 +447,5 @@
#define SIO_PDR_MD5_CFG__A 0x7F0030
#define SIO_PDR_MD6_CFG__A 0x7F0031
#define SIO_PDR_MD7_CFG__A 0x7F0032
+#define SIO_PDR_SMA_RX_CFG__A 0x7F0037
#define SIO_PDR_SMA_TX_CFG__A 0x7F0038
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
index af65d013db11..4c8ac2657c4a 100644
--- a/drivers/media/dvb/frontends/ds3000.c
+++ b/drivers/media/dvb/frontends/ds3000.c
@@ -1114,7 +1114,10 @@ static int ds3000_set_frontend(struct dvb_frontend *fe)
ds3000_writereg(state,
ds3000_dvbs2_init_tab[i],
ds3000_dvbs2_init_tab[i + 1]);
- ds3000_writereg(state, 0xfe, 0x98);
+ if (c->symbol_rate >= 30000000)
+ ds3000_writereg(state, 0xfe, 0x54);
+ else
+ ds3000_writereg(state, 0xfe, 0x98);
break;
default:
return 1;
diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c
index 84df03c29179..708cbf197913 100644
--- a/drivers/media/dvb/frontends/it913x-fe.c
+++ b/drivers/media/dvb/frontends/it913x-fe.c
@@ -633,10 +633,9 @@ static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct it913x_fe_state *state = fe->demodulator_priv;
- int ret;
u8 reg[5];
/* Read Aborted Packets and Pre-Viterbi error rate 5 bytes */
- ret = it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
+ it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
state->ucblocks += (u32)(reg[1] << 8) | reg[0];
*ber = (u32)(reg[4] << 16) | (reg[3] << 8) | reg[2];
return 0;
@@ -658,10 +657,9 @@ static int it913x_fe_get_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct it913x_fe_state *state = fe->demodulator_priv;
- int ret;
u8 reg[8];
- ret = it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
+ it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
if (reg[3] < 3)
p->modulation = fe_con[reg[3]];
@@ -691,25 +689,25 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct it913x_fe_state *state = fe->demodulator_priv;
- int ret, i;
+ int i;
u8 empty_ch, last_ch;
state->it913x_status = 0;
/* Set bw*/
- ret = it913x_fe_select_bw(state, p->bandwidth_hz,
+ it913x_fe_select_bw(state, p->bandwidth_hz,
state->adcFrequency);
/* Training Mode Off */
- ret = it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
+ it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
/* Clear Empty Channel */
- ret = it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
+ it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
/* Clear bits */
- ret = it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
+ it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
/* LED on */
- ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+ it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
/* Select Band*/
if ((p->frequency >= 51000000) && (p->frequency <= 230000000))
i = 0;
@@ -720,7 +718,7 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe)
else
return -EOPNOTSUPP;
- ret = it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
+ it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
switch (state->tuner_type) {
@@ -730,7 +728,7 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe)
case IT9135_60:
case IT9135_61:
case IT9135_62:
- ret = it9137_set_tuner(state,
+ it9137_set_tuner(state,
p->bandwidth_hz, p->frequency);
break;
default:
@@ -742,9 +740,9 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe)
break;
}
/* LED off */
- ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+ it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
/* Trigger ofsm */
- ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+ it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
last_ch = 2;
for (i = 0; i < 40; ++i) {
empty_ch = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
diff --git a/drivers/media/dvb/frontends/lg2160.c b/drivers/media/dvb/frontends/lg2160.c
new file mode 100644
index 000000000000..a3ab1a5b6597
--- /dev/null
+++ b/drivers/media/dvb/frontends/lg2160.c
@@ -0,0 +1,1468 @@
+/*
+ * Support for LG2160 - ATSC/MH
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ * 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 <linux/jiffies.h>
+#include <linux/dvb/frontend.h>
+#include "lg2160.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
+
+#define DBG_INFO 1
+#define DBG_REG 2
+
+#define lg_printk(kern, fmt, arg...) \
+ printk(kern "%s: " fmt, __func__, ##arg)
+
+#define lg_info(fmt, arg...) printk(KERN_INFO "lg2160: " fmt, ##arg)
+#define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg)
+#define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg)
+#define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \
+ lg_printk(KERN_DEBUG, fmt, ##arg)
+#define lg_reg(fmt, arg...) if (debug & DBG_REG) \
+ lg_printk(KERN_DEBUG, fmt, ##arg)
+
+#define lg_fail(ret) \
+({ \
+ int __ret; \
+ __ret = (ret < 0); \
+ if (__ret) \
+ lg_err("error %d on line %d\n", ret, __LINE__); \
+ __ret; \
+})
+
+struct lg216x_state {
+ struct i2c_adapter *i2c_adap;
+ const struct lg2160_config *cfg;
+
+ struct dvb_frontend frontend;
+
+ u32 current_frequency;
+ u8 parade_id;
+ u8 fic_ver;
+ unsigned int last_reset;
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_write_reg(struct lg216x_state *state, u16 reg, u8 val)
+{
+ int ret;
+ u8 buf[] = { reg >> 8, reg & 0xff, val };
+ struct i2c_msg msg = {
+ .addr = state->cfg->i2c_addr, .flags = 0,
+ .buf = buf, .len = 3,
+ };
+
+ lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
+
+ ret = i2c_transfer(state->i2c_adap, &msg, 1);
+
+ if (ret != 1) {
+ lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
+ msg.buf[0], msg.buf[1], msg.buf[2], ret);
+ if (ret < 0)
+ return ret;
+ else
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int lg216x_read_reg(struct lg216x_state *state, u16 reg, u8 *val)
+{
+ int ret;
+ u8 reg_buf[] = { reg >> 8, reg & 0xff };
+ struct i2c_msg msg[] = {
+ { .addr = state->cfg->i2c_addr,
+ .flags = 0, .buf = reg_buf, .len = 2 },
+ { .addr = state->cfg->i2c_addr,
+ .flags = I2C_M_RD, .buf = val, .len = 1 },
+ };
+
+ lg_reg("reg: 0x%04x\n", reg);
+
+ ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+ if (ret != 2) {
+ lg_err("error (addr %02x reg %04x error (ret == %i)\n",
+ state->cfg->i2c_addr, reg, ret);
+ if (ret < 0)
+ return ret;
+ else
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+struct lg216x_reg {
+ u16 reg;
+ u8 val;
+};
+
+static int lg216x_write_regs(struct lg216x_state *state,
+ struct lg216x_reg *regs, int len)
+{
+ int i, ret;
+
+ lg_reg("writing %d registers...\n", len);
+
+ for (i = 0; i < len - 1; i++) {
+ ret = lg216x_write_reg(state, regs[i].reg, regs[i].val);
+ if (lg_fail(ret))
+ return ret;
+ }
+ return 0;
+}
+
+static int lg216x_set_reg_bit(struct lg216x_state *state,
+ u16 reg, int bit, int onoff)
+{
+ u8 val;
+ int ret;
+
+ lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
+
+ ret = lg216x_read_reg(state, reg, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= ~(1 << bit);
+ val |= (onoff & 1) << bit;
+
+ ret = lg216x_write_reg(state, reg, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct lg216x_state *state = fe->demodulator_priv;
+ int ret;
+
+ if (state->cfg->deny_i2c_rptr)
+ return 0;
+
+ lg_dbg("(%d)\n", enable);
+
+ ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1);
+
+ msleep(1);
+
+ return ret;
+}
+
+static int lg216x_soft_reset(struct lg216x_state *state)
+{
+ int ret;
+
+ lg_dbg("\n");
+
+ ret = lg216x_write_reg(state, 0x0002, 0x00);
+ if (lg_fail(ret))
+ goto fail;
+
+ msleep(20);
+ ret = lg216x_write_reg(state, 0x0002, 0x01);
+ if (lg_fail(ret))
+ goto fail;
+
+ state->last_reset = jiffies_to_msecs(jiffies);
+fail:
+ return ret;
+}
+
+static int lg216x_initialize(struct lg216x_state *state)
+{
+ int ret;
+
+ static struct lg216x_reg lg2160_init[] = {
+#if 0
+ { .reg = 0x0015, .val = 0xe6 },
+#else
+ { .reg = 0x0015, .val = 0xf7 },
+ { .reg = 0x001b, .val = 0x52 },
+ { .reg = 0x0208, .val = 0x00 },
+ { .reg = 0x0209, .val = 0x82 },
+ { .reg = 0x0210, .val = 0xf9 },
+ { .reg = 0x020a, .val = 0x00 },
+ { .reg = 0x020b, .val = 0x82 },
+ { .reg = 0x020d, .val = 0x28 },
+ { .reg = 0x020f, .val = 0x14 },
+#endif
+ };
+
+ static struct lg216x_reg lg2161_init[] = {
+ { .reg = 0x0000, .val = 0x41 },
+ { .reg = 0x0001, .val = 0xfb },
+ { .reg = 0x0216, .val = 0x00 },
+ { .reg = 0x0219, .val = 0x00 },
+ { .reg = 0x021b, .val = 0x55 },
+ { .reg = 0x0606, .val = 0x0a },
+ };
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_write_regs(state,
+ lg2160_init, ARRAY_SIZE(lg2160_init));
+ break;
+ case LG2161:
+ ret = lg216x_write_regs(state,
+ lg2161_init, ARRAY_SIZE(lg2161_init));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_soft_reset(state);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_set_if(struct lg216x_state *state)
+{
+ u8 val;
+ int ret;
+
+ lg_dbg("%d KHz\n", state->cfg->if_khz);
+
+ ret = lg216x_read_reg(state, 0x0132, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xfb;
+ val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00;
+
+ ret = lg216x_write_reg(state, 0x0132, val);
+ lg_fail(ret);
+
+ /* if NOT zero IF, 6 MHz is the default */
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg2160_agc_fix(struct lg216x_state *state,
+ int if_agc_fix, int rf_agc_fix)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0100, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xf3;
+ val |= (if_agc_fix) ? 0x08 : 0x00;
+ val |= (rf_agc_fix) ? 0x04 : 0x00;
+
+ ret = lg216x_write_reg(state, 0x0100, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+#if 0
+static int lg2160_agc_freeze(struct lg216x_state *state,
+ int if_agc_freeze, int rf_agc_freeze)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0100, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xcf;
+ val |= (if_agc_freeze) ? 0x20 : 0x00;
+ val |= (rf_agc_freeze) ? 0x10 : 0x00;
+
+ ret = lg216x_write_reg(state, 0x0100, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+#endif
+
+static int lg2160_agc_polarity(struct lg216x_state *state,
+ int if_agc_polarity, int rf_agc_polarity)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0100, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xfc;
+ val |= (if_agc_polarity) ? 0x02 : 0x00;
+ val |= (rf_agc_polarity) ? 0x01 : 0x00;
+
+ ret = lg216x_write_reg(state, 0x0100, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+static int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state,
+ int polarity)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0008, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xfe;
+ val |= (polarity) ? 0x01 : 0x00;
+
+ ret = lg216x_write_reg(state, 0x0008, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+static int lg2160_spectrum_polarity(struct lg216x_state *state,
+ int inverted)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0132, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xfd;
+ val |= (inverted) ? 0x02 : 0x00;
+
+ ret = lg216x_write_reg(state, 0x0132, val);
+ lg_fail(ret);
+fail:
+ return lg216x_soft_reset(state);
+}
+
+static int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0007, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xbf;
+ val |= (onoff) ? 0x40 : 0x00;
+
+ ret = lg216x_write_reg(state, 0x0007, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+static int lg216x_set_parade(struct lg216x_state *state, int id)
+{
+ int ret;
+
+ ret = lg216x_write_reg(state, 0x013e, id & 0x7f);
+ if (lg_fail(ret))
+ goto fail;
+
+ state->parade_id = id & 0x7f;
+fail:
+ return ret;
+}
+
+static int lg216x_set_ensemble(struct lg216x_state *state, int id)
+{
+ int ret;
+ u16 reg;
+ u8 val;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ reg = 0x0400;
+ break;
+ case LG2161:
+ default:
+ reg = 0x0500;
+ break;
+ }
+
+ ret = lg216x_read_reg(state, reg, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xfe;
+ val |= (id) ? 0x01 : 0x00;
+
+ ret = lg216x_write_reg(state, reg, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+static int lg2160_set_spi_clock(struct lg216x_state *state)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0014, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0xf3;
+ val |= (state->cfg->spi_clock << 2);
+
+ ret = lg216x_write_reg(state, 0x0014, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+static int lg2161_set_output_interface(struct lg216x_state *state)
+{
+ u8 val;
+ int ret;
+
+ ret = lg216x_read_reg(state, 0x0014, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= ~0x07;
+ val |= state->cfg->output_if; /* FIXME: needs sanity check */
+
+ ret = lg216x_write_reg(state, 0x0014, val);
+ lg_fail(ret);
+fail:
+ return ret;
+}
+
+static int lg216x_enable_fic(struct lg216x_state *state, int onoff)
+{
+ int ret;
+
+ ret = lg216x_write_reg(state, 0x0017, 0x23);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_write_reg(state, 0x0016, 0xfc);
+ if (lg_fail(ret))
+ goto fail;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_write_reg(state, 0x0016,
+ 0xfc | ((onoff) ? 0x02 : 0x00));
+ break;
+ case LG2161:
+ ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00);
+ break;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_initialize(state);
+ if (lg_fail(ret))
+ goto fail;
+
+ if (onoff) {
+ ret = lg216x_write_reg(state, 0x0017, 0x03);
+ lg_fail(ret);
+ }
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver)
+{
+ u8 val;
+ int ret;
+
+ *ficver = 0xff; /* invalid value */
+
+ ret = lg216x_read_reg(state, 0x0128, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *ficver = (val >> 3) & 0x1f;
+fail:
+ return ret;
+}
+
+#if 0
+static int lg2160_get_parade_id(struct lg216x_state *state, u8 *id)
+{
+ u8 val;
+ int ret;
+
+ *id = 0xff; /* invalid value */
+
+ ret = lg216x_read_reg(state, 0x0123, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *id = val & 0x7f;
+fail:
+ return ret;
+}
+#endif
+
+static int lg216x_get_nog(struct lg216x_state *state, u8 *nog)
+{
+ u8 val;
+ int ret;
+
+ *nog = 0xff; /* invalid value */
+
+ ret = lg216x_read_reg(state, 0x0124, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *nog = ((val >> 4) & 0x07) + 1;
+fail:
+ return ret;
+}
+
+static int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog)
+{
+ u8 val;
+ int ret;
+
+ *tnog = 0xff; /* invalid value */
+
+ ret = lg216x_read_reg(state, 0x0125, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *tnog = val & 0x1f;
+fail:
+ return ret;
+}
+
+static int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn)
+{
+ u8 val;
+ int ret;
+
+ *sgn = 0xff; /* invalid value */
+
+ ret = lg216x_read_reg(state, 0x0124, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *sgn = val & 0x0f;
+fail:
+ return ret;
+}
+
+static int lg216x_get_prc(struct lg216x_state *state, u8 *prc)
+{
+ u8 val;
+ int ret;
+
+ *prc = 0xff; /* invalid value */
+
+ ret = lg216x_read_reg(state, 0x0125, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *prc = ((val >> 5) & 0x07) + 1;
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_get_rs_frame_mode(struct lg216x_state *state,
+ enum atscmh_rs_frame_mode *rs_framemode)
+{
+ u8 val;
+ int ret;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_read_reg(state, 0x0410, &val);
+ break;
+ case LG2161:
+ ret = lg216x_read_reg(state, 0x0513, &val);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ switch ((val >> 4) & 0x03) {
+#if 1
+ default:
+#endif
+ case 0x00:
+ *rs_framemode = ATSCMH_RSFRAME_PRI_ONLY;
+ break;
+ case 0x01:
+ *rs_framemode = ATSCMH_RSFRAME_PRI_SEC;
+ break;
+#if 0
+ default:
+ *rs_framemode = ATSCMH_RSFRAME_RES;
+ break;
+#endif
+ }
+fail:
+ return ret;
+}
+
+static
+int lg216x_get_rs_frame_ensemble(struct lg216x_state *state,
+ enum atscmh_rs_frame_ensemble *rs_frame_ens)
+{
+ u8 val;
+ int ret;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_read_reg(state, 0x0400, &val);
+ break;
+ case LG2161:
+ ret = lg216x_read_reg(state, 0x0500, &val);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ val &= 0x01;
+ *rs_frame_ens = (enum atscmh_rs_frame_ensemble) val;
+fail:
+ return ret;
+}
+
+static int lg216x_get_rs_code_mode(struct lg216x_state *state,
+ enum atscmh_rs_code_mode *rs_code_pri,
+ enum atscmh_rs_code_mode *rs_code_sec)
+{
+ u8 val;
+ int ret;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_read_reg(state, 0x0410, &val);
+ break;
+ case LG2161:
+ ret = lg216x_read_reg(state, 0x0513, &val);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ *rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03);
+ *rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03);
+fail:
+ return ret;
+}
+
+static int lg216x_get_sccc_block_mode(struct lg216x_state *state,
+ enum atscmh_sccc_block_mode *sccc_block)
+{
+ u8 val;
+ int ret;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_read_reg(state, 0x0315, &val);
+ break;
+ case LG2161:
+ ret = lg216x_read_reg(state, 0x0511, &val);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ switch (val & 0x03) {
+ case 0x00:
+ *sccc_block = ATSCMH_SCCC_BLK_SEP;
+ break;
+ case 0x01:
+ *sccc_block = ATSCMH_SCCC_BLK_COMB;
+ break;
+ default:
+ *sccc_block = ATSCMH_SCCC_BLK_RES;
+ break;
+ }
+fail:
+ return ret;
+}
+
+static int lg216x_get_sccc_code_mode(struct lg216x_state *state,
+ enum atscmh_sccc_code_mode *mode_a,
+ enum atscmh_sccc_code_mode *mode_b,
+ enum atscmh_sccc_code_mode *mode_c,
+ enum atscmh_sccc_code_mode *mode_d)
+{
+ u8 val;
+ int ret;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_read_reg(state, 0x0316, &val);
+ break;
+ case LG2161:
+ ret = lg216x_read_reg(state, 0x0512, &val);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ switch ((val >> 6) & 0x03) {
+ case 0x00:
+ *mode_a = ATSCMH_SCCC_CODE_HLF;
+ break;
+ case 0x01:
+ *mode_a = ATSCMH_SCCC_CODE_QTR;
+ break;
+ default:
+ *mode_a = ATSCMH_SCCC_CODE_RES;
+ break;
+ }
+
+ switch ((val >> 4) & 0x03) {
+ case 0x00:
+ *mode_b = ATSCMH_SCCC_CODE_HLF;
+ break;
+ case 0x01:
+ *mode_b = ATSCMH_SCCC_CODE_QTR;
+ break;
+ default:
+ *mode_b = ATSCMH_SCCC_CODE_RES;
+ break;
+ }
+
+ switch ((val >> 2) & 0x03) {
+ case 0x00:
+ *mode_c = ATSCMH_SCCC_CODE_HLF;
+ break;
+ case 0x01:
+ *mode_c = ATSCMH_SCCC_CODE_QTR;
+ break;
+ default:
+ *mode_c = ATSCMH_SCCC_CODE_RES;
+ break;
+ }
+
+ switch (val & 0x03) {
+ case 0x00:
+ *mode_d = ATSCMH_SCCC_CODE_HLF;
+ break;
+ case 0x01:
+ *mode_d = ATSCMH_SCCC_CODE_QTR;
+ break;
+ default:
+ *mode_d = ATSCMH_SCCC_CODE_RES;
+ break;
+ }
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+static int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err)
+{
+ u8 fic_err;
+ int ret;
+
+ *err = 0;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg216x_read_reg(state, 0x0012, &fic_err);
+ break;
+ case LG2161:
+ ret = lg216x_read_reg(state, 0x001e, &fic_err);
+ break;
+ }
+ if (lg_fail(ret))
+ goto fail;
+
+ *err = fic_err;
+fail:
+ return ret;
+}
+
+static int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err)
+{
+ u8 crc_err1, crc_err2;
+ int ret;
+
+ *err = 0;
+
+ ret = lg216x_read_reg(state, 0x0411, &crc_err1);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_read_reg(state, 0x0412, &crc_err2);
+ if (lg_fail(ret))
+ goto fail;
+
+ *err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1);
+fail:
+ return ret;
+}
+
+static int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err)
+{
+ u8 crc_err;
+ int ret;
+
+ *err = 0;
+
+ ret = lg216x_read_reg(state, 0x0612, &crc_err);
+ if (lg_fail(ret))
+ goto fail;
+
+ *err = (u16)crc_err;
+fail:
+ return ret;
+}
+
+static int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err)
+{
+ int ret;
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg2160_read_crc_err_count(state, err);
+ break;
+ case LG2161:
+ ret = lg2161_read_crc_err_count(state, err);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err)
+{
+ u8 rs_err1, rs_err2;
+ int ret;
+
+ *err = 0;
+
+ ret = lg216x_read_reg(state, 0x0413, &rs_err1);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_read_reg(state, 0x0414, &rs_err2);
+ if (lg_fail(ret))
+ goto fail;
+
+ *err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1);
+fail:
+ return ret;
+}
+
+static int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err)
+{
+ u8 rs_err1, rs_err2;
+ int ret;
+
+ *err = 0;
+
+ ret = lg216x_read_reg(state, 0x0613, &rs_err1);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_read_reg(state, 0x0614, &rs_err2);
+ if (lg_fail(ret))
+ goto fail;
+
+ *err = (u16)((rs_err1 << 8) | rs_err2);
+fail:
+ return ret;
+}
+
+static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err)
+{
+ int ret;
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg2160_read_rs_err_count(state, err);
+ break;
+ case LG2161:
+ ret = lg2161_read_rs_err_count(state, err);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_get_frontend(struct dvb_frontend *fe)
+{
+ struct lg216x_state *state = fe->demodulator_priv;
+ int ret;
+
+ lg_dbg("\n");
+
+ fe->dtv_property_cache.modulation = VSB_8;
+ fe->dtv_property_cache.frequency = state->current_frequency;
+ fe->dtv_property_cache.delivery_system = SYS_ATSCMH;
+
+ ret = lg216x_get_fic_version(state,
+ &fe->dtv_property_cache.atscmh_fic_ver);
+ if (lg_fail(ret))
+ goto fail;
+ if (state->fic_ver != fe->dtv_property_cache.atscmh_fic_ver) {
+ state->fic_ver = fe->dtv_property_cache.atscmh_fic_ver;
+
+#if 0
+ ret = lg2160_get_parade_id(state,
+ &fe->dtv_property_cache.atscmh_parade_id);
+ if (lg_fail(ret))
+ goto fail;
+/* #else */
+ fe->dtv_property_cache.atscmh_parade_id = state->parade_id;
+#endif
+ ret = lg216x_get_nog(state,
+ &fe->dtv_property_cache.atscmh_nog);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_get_tnog(state,
+ &fe->dtv_property_cache.atscmh_tnog);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_get_sgn(state,
+ &fe->dtv_property_cache.atscmh_sgn);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_get_prc(state,
+ &fe->dtv_property_cache.atscmh_prc);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_get_rs_frame_mode(state,
+ (enum atscmh_rs_frame_mode *)
+ &fe->dtv_property_cache.atscmh_rs_frame_mode);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_get_rs_frame_ensemble(state,
+ (enum atscmh_rs_frame_ensemble *)
+ &fe->dtv_property_cache.atscmh_rs_frame_ensemble);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_get_rs_code_mode(state,
+ (enum atscmh_rs_code_mode *)
+ &fe->dtv_property_cache.atscmh_rs_code_mode_pri,
+ (enum atscmh_rs_code_mode *)
+ &fe->dtv_property_cache.atscmh_rs_code_mode_sec);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_get_sccc_block_mode(state,
+ (enum atscmh_sccc_block_mode *)
+ &fe->dtv_property_cache.atscmh_sccc_block_mode);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_get_sccc_code_mode(state,
+ (enum atscmh_sccc_code_mode *)
+ &fe->dtv_property_cache.atscmh_sccc_code_mode_a,
+ (enum atscmh_sccc_code_mode *)
+ &fe->dtv_property_cache.atscmh_sccc_code_mode_b,
+ (enum atscmh_sccc_code_mode *)
+ &fe->dtv_property_cache.atscmh_sccc_code_mode_c,
+ (enum atscmh_sccc_code_mode *)
+ &fe->dtv_property_cache.atscmh_sccc_code_mode_d);
+ if (lg_fail(ret))
+ goto fail;
+ }
+#if 0
+ ret = lg216x_read_fic_err_count(state,
+ (u8 *)&fe->dtv_property_cache.atscmh_fic_err);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_read_crc_err_count(state,
+ &fe->dtv_property_cache.atscmh_crc_err);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_read_rs_err_count(state,
+ &fe->dtv_property_cache.atscmh_rs_err);
+ if (lg_fail(ret))
+ goto fail;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ if (((fe->dtv_property_cache.atscmh_rs_err >= 240) &&
+ (fe->dtv_property_cache.atscmh_crc_err >= 240)) &&
+ ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000))
+ ret = lg216x_soft_reset(state);
+ break;
+ case LG2161:
+ /* no fix needed here (as far as we know) */
+ ret = 0;
+ break;
+ }
+ lg_fail(ret);
+#endif
+fail:
+ return ret;
+}
+
+static int lg216x_get_property(struct dvb_frontend *fe,
+ struct dtv_property *tvp)
+{
+ return (DTV_ATSCMH_FIC_VER == tvp->cmd) ?
+ lg216x_get_frontend(fe) : 0;
+}
+
+
+static int lg2160_set_frontend(struct dvb_frontend *fe)
+{
+ struct lg216x_state *state = fe->demodulator_priv;
+ int ret;
+
+ lg_dbg("(%d)\n", fe->dtv_property_cache.frequency);
+
+ if (fe->ops.tuner_ops.set_params) {
+ ret = fe->ops.tuner_ops.set_params(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ if (lg_fail(ret))
+ goto fail;
+ state->current_frequency = fe->dtv_property_cache.frequency;
+ }
+
+ ret = lg2160_agc_fix(state, 0, 0);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg2160_agc_polarity(state, 0, 0);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg2160_tuner_pwr_save_polarity(state, 1);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg216x_set_if(state);
+ if (lg_fail(ret))
+ goto fail;
+ ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion);
+ if (lg_fail(ret))
+ goto fail;
+
+ /* be tuned before this point */
+ ret = lg216x_soft_reset(state);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg2160_tuner_pwr_save(state, 0);
+ if (lg_fail(ret))
+ goto fail;
+
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg2160_set_spi_clock(state);
+ if (lg_fail(ret))
+ goto fail;
+ break;
+ case LG2161:
+ ret = lg2161_set_output_interface(state);
+ if (lg_fail(ret))
+ goto fail;
+ break;
+ }
+
+ ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_set_ensemble(state,
+ fe->dtv_property_cache.atscmh_rs_frame_ensemble);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_initialize(state);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_enable_fic(state, 1);
+ lg_fail(ret);
+
+ lg216x_get_frontend(fe);
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg2160_read_lock_status(struct lg216x_state *state,
+ int *acq_lock, int *sync_lock)
+{
+ u8 val;
+ int ret;
+
+ *acq_lock = 0;
+ *sync_lock = 0;
+
+ ret = lg216x_read_reg(state, 0x011b, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *sync_lock = (val & 0x20) ? 0 : 1;
+ *acq_lock = (val & 0x40) ? 0 : 1;
+fail:
+ return ret;
+}
+
+#ifdef USE_LG2161_LOCK_BITS
+static int lg2161_read_lock_status(struct lg216x_state *state,
+ int *acq_lock, int *sync_lock)
+{
+ u8 val;
+ int ret;
+
+ *acq_lock = 0;
+ *sync_lock = 0;
+
+ ret = lg216x_read_reg(state, 0x0304, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *sync_lock = (val & 0x80) ? 0 : 1;
+
+ ret = lg216x_read_reg(state, 0x011b, &val);
+ if (lg_fail(ret))
+ goto fail;
+
+ *acq_lock = (val & 0x40) ? 0 : 1;
+fail:
+ return ret;
+}
+#endif
+
+static int lg216x_read_lock_status(struct lg216x_state *state,
+ int *acq_lock, int *sync_lock)
+{
+#ifdef USE_LG2161_LOCK_BITS
+ int ret;
+ switch (state->cfg->lg_chip) {
+ case LG2160:
+ ret = lg2160_read_lock_status(state, acq_lock, sync_lock);
+ break;
+ case LG2161:
+ ret = lg2161_read_lock_status(state, acq_lock, sync_lock);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+#else
+ return lg2160_read_lock_status(state, acq_lock, sync_lock);
+#endif
+}
+
+static int lg216x_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct lg216x_state *state = fe->demodulator_priv;
+ int ret, acq_lock, sync_lock;
+
+ *status = 0;
+
+ ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock);
+ if (lg_fail(ret))
+ goto fail;
+
+ lg_dbg("%s%s\n",
+ acq_lock ? "SIGNALEXIST " : "",
+ sync_lock ? "SYNCLOCK" : "");
+
+ if (acq_lock)
+ *status |= FE_HAS_SIGNAL;
+ if (sync_lock)
+ *status |= FE_HAS_SYNC;
+
+ if (*status)
+ *status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
+
+fail:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct lg216x_state *state = fe->demodulator_priv;
+ u8 snr1, snr2;
+ int ret;
+
+ *snr = 0;
+
+ ret = lg216x_read_reg(state, 0x0202, &snr1);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_read_reg(state, 0x0203, &snr2);
+ if (lg_fail(ret))
+ goto fail;
+
+ if ((snr1 == 0xba) || (snr2 == 0xdf))
+ *snr = 0;
+ else
+#if 1
+ *snr = ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4);
+#else /* BCD */
+ *snr = (snr2 | (snr1 << 8));
+#endif
+fail:
+ return ret;
+}
+
+static int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct lg216x_state *state = fe->demodulator_priv;
+ u8 snr1, snr2;
+ int ret;
+
+ *snr = 0;
+
+ ret = lg216x_read_reg(state, 0x0302, &snr1);
+ if (lg_fail(ret))
+ goto fail;
+
+ ret = lg216x_read_reg(state, 0x0303, &snr2);
+ if (lg_fail(ret))
+ goto fail;
+
+ if ((snr1 == 0xba) || (snr2 == 0xfd))
+ *snr = 0;
+ else
+
+ *snr = ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f);
+fail:
+ return ret;
+}
+
+static int lg216x_read_signal_strength(struct dvb_frontend *fe,
+ u16 *strength)
+{
+#if 0
+ /* borrowed from lgdt330x.c
+ *
+ * Calculate strength from SNR up to 35dB
+ * Even though the SNR can go higher than 35dB,
+ * there is some comfort factor in having a range of
+ * strong signals that can show at 100%
+ */
+ struct lg216x_state *state = fe->demodulator_priv;
+ u16 snr;
+ int ret;
+#endif
+ *strength = 0;
+#if 0
+ ret = fe->ops.read_snr(fe, &snr);
+ if (lg_fail(ret))
+ goto fail;
+ /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+ /* scale the range 0 - 35*2^24 into 0 - 65535 */
+ if (state->snr >= 8960 * 0x10000)
+ *strength = 0xffff;
+ else
+ *strength = state->snr / 8960;
+fail:
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+#if 0
+ struct lg216x_state *state = fe->demodulator_priv;
+ int ret;
+
+ ret = lg216x_read_rs_err_count(state,
+ &fe->dtv_property_cache.atscmh_rs_err);
+ if (lg_fail(ret))
+ goto fail;
+
+ *ucblocks = fe->dtv_property_cache.atscmh_rs_err;
+fail:
+#else
+ *ucblocks = 0;
+#endif
+ return 0;
+}
+
+static int lg216x_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings
+ *fe_tune_settings)
+{
+ fe_tune_settings->min_delay_ms = 500;
+ lg_dbg("\n");
+ return 0;
+}
+
+static void lg216x_release(struct dvb_frontend *fe)
+{
+ struct lg216x_state *state = fe->demodulator_priv;
+ lg_dbg("\n");
+ kfree(state);
+}
+
+static struct dvb_frontend_ops lg2160_ops = {
+ .delsys = { SYS_ATSCMH },
+ .info = {
+ .name = "LG Electronics LG2160 ATSC/MH Frontend",
+ .frequency_min = 54000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 62500,
+ },
+ .i2c_gate_ctrl = lg216x_i2c_gate_ctrl,
+#if 0
+ .init = lg216x_init,
+ .sleep = lg216x_sleep,
+#endif
+ .get_property = lg216x_get_property,
+
+ .set_frontend = lg2160_set_frontend,
+ .get_frontend = lg216x_get_frontend,
+ .get_tune_settings = lg216x_get_tune_settings,
+ .read_status = lg216x_read_status,
+#if 0
+ .read_ber = lg216x_read_ber,
+#endif
+ .read_signal_strength = lg216x_read_signal_strength,
+ .read_snr = lg2160_read_snr,
+ .read_ucblocks = lg216x_read_ucblocks,
+ .release = lg216x_release,
+};
+
+static struct dvb_frontend_ops lg2161_ops = {
+ .delsys = { SYS_ATSCMH },
+ .info = {
+ .name = "LG Electronics LG2161 ATSC/MH Frontend",
+ .frequency_min = 54000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 62500,
+ },
+ .i2c_gate_ctrl = lg216x_i2c_gate_ctrl,
+#if 0
+ .init = lg216x_init,
+ .sleep = lg216x_sleep,
+#endif
+ .get_property = lg216x_get_property,
+
+ .set_frontend = lg2160_set_frontend,
+ .get_frontend = lg216x_get_frontend,
+ .get_tune_settings = lg216x_get_tune_settings,
+ .read_status = lg216x_read_status,
+#if 0
+ .read_ber = lg216x_read_ber,
+#endif
+ .read_signal_strength = lg216x_read_signal_strength,
+ .read_snr = lg2161_read_snr,
+ .read_ucblocks = lg216x_read_ucblocks,
+ .release = lg216x_release,
+};
+
+struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
+ struct i2c_adapter *i2c_adap)
+{
+ struct lg216x_state *state = NULL;
+
+ lg_dbg("(%d-%04x)\n",
+ i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
+ config ? config->i2c_addr : 0);
+
+ state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
+ if (state == NULL)
+ goto fail;
+
+ state->cfg = config;
+ state->i2c_adap = i2c_adap;
+ state->fic_ver = 0xff;
+ state->parade_id = 0xff;
+
+ switch (config->lg_chip) {
+ default:
+ lg_warn("invalid chip requested, defaulting to LG2160");
+ /* fall-thru */
+ case LG2160:
+ memcpy(&state->frontend.ops, &lg2160_ops,
+ sizeof(struct dvb_frontend_ops));
+ break;
+ case LG2161:
+ memcpy(&state->frontend.ops, &lg2161_ops,
+ sizeof(struct dvb_frontend_ops));
+ break;
+ }
+
+ state->frontend.demodulator_priv = state;
+ state->current_frequency = -1;
+ /* parade 1 by default */
+ state->frontend.dtv_property_cache.atscmh_parade_id = 1;
+
+ return &state->frontend;
+fail:
+ lg_warn("unable to detect LG216x hardware\n");
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(lg2160_attach);
+
+MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.3");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/lg2160.h b/drivers/media/dvb/frontends/lg2160.h
new file mode 100644
index 000000000000..9e2c0f41199a
--- /dev/null
+++ b/drivers/media/dvb/frontends/lg2160.h
@@ -0,0 +1,84 @@
+/*
+ * Support for LG2160 - ATSC/MH
+ *
+ * Copyright (C) 2010 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ * 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 _LG2160_H_
+#define _LG2160_H_
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+enum lg_chip_type {
+ LG2160 = 0,
+ LG2161 = 1,
+};
+
+#define LG2161_1019 LG2161
+#define LG2161_1040 LG2161
+
+enum lg2160_spi_clock {
+ LG2160_SPI_3_125_MHZ = 0,
+ LG2160_SPI_6_25_MHZ = 1,
+ LG2160_SPI_12_5_MHZ = 2,
+};
+
+#if 0
+enum lg2161_oif {
+ LG2161_OIF_EBI2_SLA = 1,
+ LG2161_OIF_SDIO_SLA = 2,
+ LG2161_OIF_SPI_SLA = 3,
+ LG2161_OIF_SPI_MAS = 4,
+ LG2161_OIF_SERIAL_TS = 7,
+};
+#endif
+
+struct lg2160_config {
+ u8 i2c_addr;
+
+ /* user defined IF frequency in KHz */
+ u16 if_khz;
+
+ /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */
+ int deny_i2c_rptr:1;
+
+ /* spectral inversion - 0:disabled 1:enabled */
+ int spectral_inversion:1;
+
+ unsigned int output_if;
+ enum lg2160_spi_clock spi_clock;
+ enum lg_chip_type lg_chip;
+};
+
+#if defined(CONFIG_DVB_LG2160) || (defined(CONFIG_DVB_LG2160_MODULE) && \
+ defined(MODULE))
+extern
+struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
+ struct i2c_adapter *i2c_adap);
+#else
+static inline
+struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
+ struct i2c_adapter *i2c_adap)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_LG2160 */
+
+#endif /* _LG2160_H_ */
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c
index 4de1d3520cd2..568363a10a31 100644
--- a/drivers/media/dvb/frontends/lgs8gxx.c
+++ b/drivers/media/dvb/frontends/lgs8gxx.c
@@ -262,7 +262,6 @@ static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
{
- int ret = 0;
u8 t;
if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
@@ -296,7 +295,7 @@ static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
if (priv->config->prod == LGS8GXX_PROD_LGS8913)
lgs8gxx_write_reg(priv, 0xC1, 0);
- ret = lgs8gxx_read_reg(priv, 0xC5, &t);
+ lgs8gxx_read_reg(priv, 0xC5, &t);
t = (t & 0xE0) | 0x06;
lgs8gxx_write_reg(priv, 0xC5, t);
diff --git a/drivers/media/dvb/frontends/m88rs2000.c b/drivers/media/dvb/frontends/m88rs2000.c
index 045ee5a6f7ae..312588e84dae 100644
--- a/drivers/media/dvb/frontends/m88rs2000.c
+++ b/drivers/media/dvb/frontends/m88rs2000.c
@@ -416,9 +416,25 @@ static int m88rs2000_tab_set(struct m88rs2000_state *state,
static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
{
- deb_info("%s: %s\n", __func__,
- volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
- volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+ struct m88rs2000_state *state = fe->demodulator_priv;
+ u8 data;
+
+ data = m88rs2000_demod_read(state, 0xb2);
+ data |= 0x03; /* bit0 V/H, bit1 off/on */
+
+ switch (volt) {
+ case SEC_VOLTAGE_18:
+ data &= ~0x03;
+ break;
+ case SEC_VOLTAGE_13:
+ data &= ~0x03;
+ data |= 0x01;
+ break;
+ case SEC_VOLTAGE_OFF:
+ break;
+ }
+
+ m88rs2000_demod_write(state, 0xb2, data);
return 0;
}
@@ -654,7 +670,6 @@ static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset)
static int m88rs2000_set_fec(struct m88rs2000_state *state,
fe_code_rate_t fec)
{
- int ret;
u16 fec_set;
switch (fec) {
/* This is not confirmed kept for reference */
@@ -677,7 +692,7 @@ static int m88rs2000_set_fec(struct m88rs2000_state *state,
default:
fec_set = 0x08;
}
- ret = m88rs2000_demod_write(state, 0x76, fec_set);
+ m88rs2000_demod_write(state, 0x76, fec_set);
return 0;
}
@@ -772,13 +787,13 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe)
return -ENODEV;
for (i = 0; i < 25; i++) {
- u8 reg = m88rs2000_demod_read(state, 0x8c);
+ reg = m88rs2000_demod_read(state, 0x8c);
if ((reg & 0x7) == 0x7) {
status = FE_HAS_LOCK;
break;
}
state->no_lock_count++;
- if (state->no_lock_count > 15) {
+ if (state->no_lock_count == 15) {
reg = m88rs2000_demod_read(state, 0x70);
reg ^= 0x4;
m88rs2000_demod_write(state, 0x70, reg);
diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c
index 45196c5b0736..93612ebac519 100644
--- a/drivers/media/dvb/frontends/rtl2830.c
+++ b/drivers/media/dvb/frontends/rtl2830.c
@@ -374,6 +374,118 @@ err:
return ret;
}
+static int rtl2830_get_frontend(struct dvb_frontend *fe)
+{
+ struct rtl2830_priv *priv = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret;
+ u8 buf[3];
+
+ if (priv->sleeping)
+ return 0;
+
+ ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
+ if (ret)
+ goto err;
+
+ ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
+ if (ret)
+ goto err;
+
+ dbg("%s: TPS=%02x %02x %02x", __func__, buf[0], buf[1], buf[2]);
+
+ switch ((buf[0] >> 2) & 3) {
+ case 0:
+ c->modulation = QPSK;
+ break;
+ case 1:
+ c->modulation = QAM_16;
+ break;
+ case 2:
+ c->modulation = QAM_64;
+ break;
+ }
+
+ switch ((buf[2] >> 2) & 1) {
+ case 0:
+ c->transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ c->transmission_mode = TRANSMISSION_MODE_8K;
+ }
+
+ switch ((buf[2] >> 0) & 3) {
+ case 0:
+ c->guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ c->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ c->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ c->guard_interval = GUARD_INTERVAL_1_4;
+ break;
+ }
+
+ switch ((buf[0] >> 4) & 7) {
+ case 0:
+ c->hierarchy = HIERARCHY_NONE;
+ break;
+ case 1:
+ c->hierarchy = HIERARCHY_1;
+ break;
+ case 2:
+ c->hierarchy = HIERARCHY_2;
+ break;
+ case 3:
+ c->hierarchy = HIERARCHY_4;
+ break;
+ }
+
+ switch ((buf[1] >> 3) & 7) {
+ case 0:
+ c->code_rate_HP = FEC_1_2;
+ break;
+ case 1:
+ c->code_rate_HP = FEC_2_3;
+ break;
+ case 2:
+ c->code_rate_HP = FEC_3_4;
+ break;
+ case 3:
+ c->code_rate_HP = FEC_5_6;
+ break;
+ case 4:
+ c->code_rate_HP = FEC_7_8;
+ break;
+ }
+
+ switch ((buf[1] >> 0) & 7) {
+ case 0:
+ c->code_rate_LP = FEC_1_2;
+ break;
+ case 1:
+ c->code_rate_LP = FEC_2_3;
+ break;
+ case 2:
+ c->code_rate_LP = FEC_3_4;
+ break;
+ case 3:
+ c->code_rate_LP = FEC_5_6;
+ break;
+ case 4:
+ c->code_rate_LP = FEC_7_8;
+ break;
+ }
+
+ return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct rtl2830_priv *priv = fe->demodulator_priv;
@@ -404,14 +516,72 @@ err:
static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- *snr = 0;
+ struct rtl2830_priv *priv = fe->demodulator_priv;
+ int ret, hierarchy, constellation;
+ u8 buf[2], tmp;
+ u16 tmp16;
+#define CONSTELLATION_NUM 3
+#define HIERARCHY_NUM 4
+ static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
+ { 70705899, 70705899, 70705899, 70705899 },
+ { 82433173, 82433173, 87483115, 94445660 },
+ { 92888734, 92888734, 95487525, 99770748 },
+ };
+
+ if (priv->sleeping)
+ return 0;
+
+ /* reports SNR in resolution of 0.1 dB */
+
+ ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
+ if (ret)
+ goto err;
+
+ constellation = (tmp >> 2) & 0x03; /* [3:2] */
+ if (constellation > CONSTELLATION_NUM - 1)
+ goto err;
+
+ hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
+ if (hierarchy > HIERARCHY_NUM - 1)
+ goto err;
+
+ ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
+ if (ret)
+ goto err;
+
+ tmp16 = buf[0] << 8 | buf[1];
+
+ if (tmp16)
+ *snr = (snr_constant[constellation][hierarchy] -
+ intlog10(tmp16)) / ((1 << 24) / 100);
+ else
+ *snr = 0;
+
return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
}
static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- *ber = 0;
+ struct rtl2830_priv *priv = fe->demodulator_priv;
+ int ret;
+ u8 buf[2];
+
+ if (priv->sleeping)
+ return 0;
+
+ ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
+ if (ret)
+ goto err;
+
+ *ber = buf[0] << 8 | buf[1];
+
return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
}
static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -422,8 +592,32 @@ static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
- *strength = 0;
+ struct rtl2830_priv *priv = fe->demodulator_priv;
+ int ret;
+ u8 buf[2];
+ u16 if_agc_raw, if_agc;
+
+ if (priv->sleeping)
+ return 0;
+
+ ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
+ if (ret)
+ goto err;
+
+ if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
+
+ if (if_agc_raw & (1 << 9))
+ if_agc = -(~(if_agc_raw - 1) & 0x1ff);
+ else
+ if_agc = if_agc_raw;
+
+ *strength = (u8) (55 - if_agc / 182);
+ *strength |= *strength << 8;
+
return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
}
static struct dvb_frontend_ops rtl2830_ops;
@@ -549,6 +743,7 @@ static struct dvb_frontend_ops rtl2830_ops = {
.get_tune_settings = rtl2830_get_tune_settings,
.set_frontend = rtl2830_set_frontend,
+ .get_frontend = rtl2830_get_frontend,
.read_status = rtl2830_read_status,
.read_snr = rtl2830_read_snr,
diff --git a/drivers/media/dvb/frontends/rtl2830_priv.h b/drivers/media/dvb/frontends/rtl2830_priv.h
index 4a464761b5b8..9b20557ccf6c 100644
--- a/drivers/media/dvb/frontends/rtl2830_priv.h
+++ b/drivers/media/dvb/frontends/rtl2830_priv.h
@@ -22,6 +22,7 @@
#define RTL2830_PRIV_H
#include "dvb_frontend.h"
+#include "dvb_math.h"
#include "rtl2830.h"
#define LOG_PREFIX "rtl2830"
diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
index dd08f4ac64a8..8b0dc74a3298 100644
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/drivers/media/dvb/frontends/stb0899_drv.c
@@ -637,11 +637,9 @@ static void stb0899_init_calc(struct stb0899_state *state)
struct stb0899_internal *internal = &state->internal;
int master_clk;
u8 agc[2];
- u8 agc1cn;
u32 reg;
/* Read registers (in burst mode) */
- agc1cn = stb0899_read_reg(state, STB0899_AGC1CN);
stb0899_read_regs(state, STB0899_AGC1REF, agc, 2); /* AGC1R and AGC2O */
/* Initial calculations */
@@ -823,15 +821,12 @@ static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t
static int stb0899_diseqc_init(struct stb0899_state *state)
{
- struct dvb_diseqc_master_cmd tx_data;
/*
struct dvb_diseqc_slave_reply rx_data;
*/
- u8 f22_tx, f22_rx, reg;
+ u8 f22_tx, reg;
u32 mclk, tx_freq = 22000;/* count = 0, i; */
- tx_data.msg[0] = 0xe2;
- tx_data.msg_len = 3;
reg = stb0899_read_reg(state, STB0899_DISCNTRL2);
STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0);
stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
@@ -849,7 +844,6 @@ static int stb0899_diseqc_init(struct stb0899_state *state)
f22_tx = mclk / (tx_freq * 32);
stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* DiSEqC Tx freq */
state->rx_freq = 20000;
- f22_rx = mclk / (state->rx_freq * 32);
return 0;
}
diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c
index def88abb30bf..2e93e65d2cdb 100644
--- a/drivers/media/dvb/frontends/stb6100.c
+++ b/drivers/media/dvb/frontends/stb6100.c
@@ -158,7 +158,6 @@ static int stb6100_read_regs(struct stb6100_state *state, u8 regs[])
static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
{
u8 regs[STB6100_NUMREGS];
- int rc;
struct i2c_msg msg = {
.addr = state->config->tuner_address + reg,
@@ -167,7 +166,7 @@ static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
.len = 1
};
- rc = i2c_transfer(state->i2c, &msg, 1);
+ i2c_transfer(state->i2c, &msg, 1);
if (unlikely(reg >= STB6100_NUMREGS)) {
dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 85c157a1fe5e..d40f226160ef 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -414,7 +414,6 @@ static int stv0297_set_frontend(struct dvb_frontend *fe)
int delay;
int sweeprate;
int carrieroffset;
- unsigned long starttime;
unsigned long timeout;
fe_spectral_inversion_t inversion;
@@ -543,7 +542,6 @@ static int stv0297_set_frontend(struct dvb_frontend *fe)
stv0297_writereg_mask(state, 0x43, 0x10, 0x10);
/* wait for WGAGC lock */
- starttime = jiffies;
timeout = jiffies + msecs_to_jiffies(2000);
while (time_before(jiffies, timeout)) {
msleep(10);
diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c
index ba0709b2d433..4af20780fb9c 100644
--- a/drivers/media/dvb/frontends/stv0900_sw.c
+++ b/drivers/media/dvb/frontends/stv0900_sw.c
@@ -835,7 +835,6 @@ static void stv0900_track_optimization(struct dvb_frontend *fe)
blind_tun_sw = 0,
modulation;
- enum fe_stv0900_rolloff rolloff;
enum fe_stv0900_modcode foundModcod;
dprintk("%s\n", __func__);
@@ -940,7 +939,6 @@ static void stv0900_track_optimization(struct dvb_frontend *fe)
freq1 = stv0900_read_reg(intp, CFR2);
freq0 = stv0900_read_reg(intp, CFR1);
- rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS);
if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) {
stv0900_write_reg(intp, SFRSTEP, 0x00);
stv0900_write_bits(intp, SCAN_ENABLE, 0);
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index 4aef1877ed42..d79e69f65cbb 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -2842,7 +2842,6 @@ static int stv090x_optimize_track(struct stv090x_state *state)
{
struct dvb_frontend *fe = &state->frontend;
- enum stv090x_rolloff rolloff;
enum stv090x_modcod modcod;
s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0;
@@ -2966,7 +2965,6 @@ static int stv090x_optimize_track(struct stv090x_state *state)
f_1 = STV090x_READ_DEMOD(state, CFR2);
f_0 = STV090x_READ_DEMOD(state, CFR1);
reg = STV090x_READ_DEMOD(state, TMGOBS);
- rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
if (state->algo == STV090x_BLIND_SEARCH) {
STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00);
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index ac7237891374..82946cd517f5 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -525,7 +525,7 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
zl10353_dump_regs(fe);
_snr = zl10353_read_register(state, SNR);
- *snr = (_snr << 8) | _snr;
+ *snr = 10 * _snr / 8;
return 0;
}
@@ -559,7 +559,6 @@ static int zl10353_init(struct dvb_frontend *fe)
{
struct zl10353_state *state = fe->demodulator_priv;
u8 zl10353_reset_attach[6] = { 0x50, 0x03, 0x64, 0x46, 0x15, 0x0F };
- int rc = 0;
if (debug_regs)
zl10353_dump_regs(fe);
@@ -573,7 +572,7 @@ static int zl10353_init(struct dvb_frontend *fe)
/* Do a "hard" reset if not already done */
if (zl10353_read_register(state, 0x50) != zl10353_reset_attach[1] ||
zl10353_read_register(state, 0x51) != zl10353_reset_attach[2]) {
- rc = zl10353_write(fe, zl10353_reset_attach,
+ zl10353_write(fe, zl10353_reset_attach,
sizeof(zl10353_reset_attach));
if (debug_regs)
zl10353_dump_regs(fe);
diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c
index 71622f65c037..cc0251e01077 100644
--- a/drivers/media/dvb/mantis/hopper_cards.c
+++ b/drivers/media/dvb/mantis/hopper_cards.c
@@ -65,7 +65,7 @@ static int devs;
static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
{
- u32 stat = 0, mask = 0, lstat = 0;
+ u32 stat = 0, mask = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
@@ -80,7 +80,6 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
- lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c
index c2bb90b3e529..095cf3a994e2 100644
--- a/drivers/media/dvb/mantis/mantis_cards.c
+++ b/drivers/media/dvb/mantis/mantis_cards.c
@@ -73,7 +73,7 @@ static char *label[10] = {
static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
{
- u32 stat = 0, mask = 0, lstat = 0;
+ u32 stat = 0, mask = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
@@ -88,7 +88,6 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
- lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c
index c61ca7d3daea..566c407175a4 100644
--- a/drivers/media/dvb/mantis/mantis_dma.c
+++ b/drivers/media/dvb/mantis/mantis_dma.c
@@ -199,10 +199,6 @@ void mantis_dma_start(struct mantis_pci *mantis)
void mantis_dma_stop(struct mantis_pci *mantis)
{
- u32 stat = 0, mask = 0;
-
- stat = mmread(MANTIS_INT_STAT);
- mask = mmread(MANTIS_INT_MASK);
dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine");
mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR);
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
index 36f2256ebb0e..71ce52875c38 100644
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -41,10 +41,9 @@ static void mantis_hifevm_work(struct work_struct *work)
struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work);
struct mantis_pci *mantis = ca->ca_priv;
- u32 gpif_stat, gpif_mask;
+ u32 gpif_stat;
gpif_stat = mmread(MANTIS_GPIF_STATUS);
- gpif_mask = mmread(MANTIS_GPIF_IRQCFG);
if (gpif_stat & MANTIS_GPIF_DETSTAT) {
if (gpif_stat & MANTIS_CARD_PLUGIN) {
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
index f129a9303f80..39857384af10 100644
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -1409,10 +1409,8 @@ static int ngene_start(struct ngene *dev)
if (stat < 0)
goto fail;
- if (!stat)
- return stat;
+ return 0;
- /* otherwise error: fall through */
fail:
ngwritel(0, NGENE_INT_ENABLE);
free_irq(dev->pci_dev->irq, dev);
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index e1f20c236989..f148b19a206a 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -481,14 +481,6 @@ static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe)
if (p->bandwidth_hz == 8000000)
buf[3] |= 0x08;
- if (sizeof(buf) == 6) {
- buf[4] = buf[2];
- buf[4] &= ~0x1c;
- buf[4] |= 0x18;
-
- buf[5] = (0 << 7) | (2 << 4);
- }
-
msg.addr = I2C_ADDR_TUA6034 >> 1;
msg.flags = 0;
msg.buf = buf;
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
index 91f8c8291e2b..d6f3f100699a 100644
--- a/drivers/media/dvb/siano/smssdio.c
+++ b/drivers/media/dvb/siano/smssdio.c
@@ -114,7 +114,7 @@ out:
static void smssdio_interrupt(struct sdio_func *func)
{
- int ret, isr;
+ int ret;
struct smssdio_device *smsdev;
struct smscore_buffer_t *cb;
@@ -127,7 +127,7 @@ static void smssdio_interrupt(struct sdio_func *func)
* The interrupt register has no defined meaning. It is just
* a way of turning of the level triggered interrupt.
*/
- isr = sdio_readb(func, SMSSDIO_INT, &ret);
+ (void)sdio_readb(func, SMSSDIO_INT, &ret);
if (ret) {
sms_err("Unable to read interrupt register!\n");
return;
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index b1fe5137df09..63c004a25e0b 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -542,6 +542,8 @@ static const struct usb_device_id smsusb_id_table[] __devinitconst = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xc090),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0xc0a0),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ } /* Terminating entry */
};
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index ee8ee1d481fa..1b2d15140a1d 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -107,7 +107,7 @@ static struct v4l2_input inputs[4] = {
.index = 1,
.name = "Television",
.type = V4L2_INPUT_TYPE_TUNER,
- .audioset = 2,
+ .audioset = 1,
.tuner = 0,
.std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
.status = 0,
@@ -494,7 +494,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
if (!av7110->analog_tuner_flags)
- return 0;
+ return input ? -EINVAL : 0;
if (input >= 4)
return -EINVAL;
@@ -503,19 +503,38 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
return av7110_dvb_c_switch(fh);
}
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+ dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
+ if (a->index != 0)
+ return -EINVAL;
+ *a = msp3400_v4l2_audio;
+ return 0;
+}
+
static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
if (a->index != 0)
return -EINVAL;
- memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
+ if (av7110->current_input >= 2)
+ return -EINVAL;
+ *a = msp3400_v4l2_audio;
return 0;
}
static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
{
+ struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+ struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
- return 0;
+ if (av7110->current_input >= 2)
+ return -EINVAL;
+ return a->index ? -EINVAL : 0;
}
static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
@@ -802,26 +821,39 @@ int av7110_init_v4l(struct av7110 *av7110)
ERR("cannot init capture device. skipping\n");
return -ENODEV;
}
- vv_data->ops.vidioc_enum_input = vidioc_enum_input;
- vv_data->ops.vidioc_g_input = vidioc_g_input;
- vv_data->ops.vidioc_s_input = vidioc_s_input;
- vv_data->ops.vidioc_g_tuner = vidioc_g_tuner;
- vv_data->ops.vidioc_s_tuner = vidioc_s_tuner;
- vv_data->ops.vidioc_g_frequency = vidioc_g_frequency;
- vv_data->ops.vidioc_s_frequency = vidioc_s_frequency;
- vv_data->ops.vidioc_g_audio = vidioc_g_audio;
- vv_data->ops.vidioc_s_audio = vidioc_s_audio;
- vv_data->ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
- vv_data->ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
- vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
+ vv_data->vid_ops.vidioc_enum_input = vidioc_enum_input;
+ vv_data->vid_ops.vidioc_g_input = vidioc_g_input;
+ vv_data->vid_ops.vidioc_s_input = vidioc_s_input;
+ vv_data->vid_ops.vidioc_g_tuner = vidioc_g_tuner;
+ vv_data->vid_ops.vidioc_s_tuner = vidioc_s_tuner;
+ vv_data->vid_ops.vidioc_g_frequency = vidioc_g_frequency;
+ vv_data->vid_ops.vidioc_s_frequency = vidioc_s_frequency;
+ vv_data->vid_ops.vidioc_enumaudio = vidioc_enumaudio;
+ vv_data->vid_ops.vidioc_g_audio = vidioc_g_audio;
+ vv_data->vid_ops.vidioc_s_audio = vidioc_s_audio;
+ vv_data->vid_ops.vidioc_g_fmt_vbi_cap = NULL;
+
+ vv_data->vbi_ops.vidioc_g_tuner = vidioc_g_tuner;
+ vv_data->vbi_ops.vidioc_s_tuner = vidioc_s_tuner;
+ vv_data->vbi_ops.vidioc_g_frequency = vidioc_g_frequency;
+ vv_data->vbi_ops.vidioc_s_frequency = vidioc_s_frequency;
+ vv_data->vbi_ops.vidioc_g_fmt_vbi_cap = NULL;
+ vv_data->vbi_ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
+ vv_data->vbi_ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
+ vv_data->vbi_ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
+
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ vv_data->capabilities &= ~V4L2_CAP_SLICED_VBI_OUTPUT;
if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
ERR("cannot register capture device. skipping\n");
saa7146_vv_release(dev);
return -ENODEV;
}
- if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
- ERR("cannot register vbi v4l2 device. skipping\n");
+ if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+ if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
+ ERR("cannot register vbi v4l2 device. skipping\n");
+ }
return 0;
}
@@ -905,7 +937,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
static struct saa7146_ext_vv av7110_vv_data_st = {
.inputs = 1,
.audios = 1,
- .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
+ .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
.flags = 0,
.stds = &standard[0],
@@ -920,7 +952,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
static struct saa7146_ext_vv av7110_vv_data_c = {
.inputs = 1,
.audios = 1,
- .capabilities = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT,
+ .capabilities = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
.flags = SAA7146_USE_PORT_B_FOR_VBI,
.stds = &standard[0],
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 8b32e282bf5d..12ddb53c58dc 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1483,9 +1483,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
ERR("cannot init vv subsystem\n");
return err;
}
- vv_data.ops.vidioc_enum_input = vidioc_enum_input;
- vv_data.ops.vidioc_g_input = vidioc_g_input;
- vv_data.ops.vidioc_s_input = vidioc_s_input;
+ vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
+ vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
+ vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
/* fixme: proper cleanup here */