diff --git a/packages/linux-driver-addons/dvb/hauppauge/package.mk b/packages/linux-driver-addons/dvb/hauppauge/package.mk deleted file mode 100644 index efd0a1a1cc..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/package.mk +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-or-later -# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) - -PKG_NAME="hauppauge" -PKG_VERSION="f5a5e5e" -PKG_SHA256="6a3167c9990fa96838f4746861edb4d4e656739ea08d4f993e54becb9f2e9ab2" -PKG_ARCH="any" -PKG_LICENSE="GPL" -PKG_SITE="http://git.linuxtv.org/media_build.git" -PKG_URL="https://git.linuxtv.org/media_build.git/snapshot/${PKG_VERSION}.tar.gz" -PKG_SOURCE_DIR="${PKG_VERSION}" -PKG_DEPENDS_TARGET="toolchain linux media_tree" -PKG_NEED_UNPACK="$LINUX_DEPENDS media_tree" -PKG_SECTION="driver.dvb" -PKG_LONGDESC="DVB drivers for Hauppauge" - -PKG_IS_ADDON="embedded" -PKG_IS_KERNEL_PKG="yes" -PKG_ADDON_IS_STANDALONE="yes" -PKG_ADDON_NAME="DVB drivers for Hauppauge" -PKG_ADDON_TYPE="xbmc.service" -PKG_ADDON_VERSION="${ADDON_VERSION}.${PKG_REV}" - -if [ $LINUX = "amlogic-3.14" -o $LINUX = "amlogic-3.10" ]; then - PKG_PATCH_DIRS="amlogic" -fi - -pre_make_target() { - export KERNEL_VER=$(get_module_dir) - export LDFLAGS="" -} - -make_target() { - cp -RP $(get_build_dir media_tree)/* $PKG_BUILD/linux - kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) stagingconfig - - # hack to workaround media_build bug - if [ $LINUX = "amlogic-3.14" -o $LINUX = "amlogic-3.10" ]; then - sed -e 's/CONFIG_VIDEO_TVP5150=m/# CONFIG_VIDEO_TVP5150 is not set/g' -i v4l/.config - sed -e 's/CONFIG_DVB_LGDT3306A=m/# CONFIG_DVB_LGDT3306A is not set/g' -i v4l/.config - sed -e 's/CONFIG_VIDEO_S5C73M3=m/# CONFIG_VIDEO_S5C73M3 is not set/g' -i v4l/.config - fi - - kernel_make VER=$KERNEL_VER SRCDIR=$(kernel_path) -} - -makeinstall_target() { - install_driver_addon_files "$PKG_BUILD/v4l/" -} diff --git a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-01-add-AML-specific-to-backports.patch b/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-01-add-AML-specific-to-backports.patch deleted file mode 100644 index 3555acd3b5..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-01-add-AML-specific-to-backports.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff -Naur a/backports/backports.txt b/backports/backports.txt ---- a/backports/backports.txt 2017-12-30 22:14:58.000000000 +0200 -+++ b/backports/backports.txt 2018-02-23 13:50:01.327967293 +0200 -@@ -21,6 +21,12 @@ - - # All supported versions need those patches - [9.255.255] -+add linux-301-AML-videobuf-resource.patch -+add linux-302-AML-amlogic-video-dev.patch -+add linux-303-AML-meson-ir.patch -+add linux-304-AML-wetekplay.patch -+add linux-305-AML-dmx_h.patch -+add linux-306-AML-build-dvb-avl.patch - add api_version.patch - add pr_fmt.patch - add debug.patch diff --git a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-02-media_build-fix.patch b/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-02-media_build-fix.patch deleted file mode 100644 index 53f90509f8..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-02-media_build-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/v4l/compat.h -+++ b/v4l/compat.h -@@ -1588,7 +1588,7 @@ - #endif - - #ifdef NEED_WRITEL_RELAXED --#define writel_relaxed writel -+// #define writel_relaxed writel - #endif - - #ifdef NEED_GET_USER_PAGES_UNLOCKED diff --git a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-03-frame_vector_workaround.patch b/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-03-frame_vector_workaround.patch deleted file mode 100644 index 0d5dd1a588..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-03-frame_vector_workaround.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/v4l/Makefile -+++ b/v4l/Makefile -@@ -92,9 +92,6 @@ ifneq ($(filter $(no-makefile-media-targets), $(MAKECMDGOALS)),) - endif - - makefile-mm := 1 --ifeq ($(wildcard ../linux/mm/frame_vector.c),) -- makefile-mm := 0 --endif - - # If version not yet detected, we can't create/have these files yet - ifeq ($(KERNELRELEASE),) diff --git a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-05-compat_h-fix.patch b/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-05-compat_h-fix.patch deleted file mode 100644 index d3bab57223..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/patches/amlogic/driver.dvb.hauppauge-05-compat_h-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/v4l/compat.h -+++ b/v4l/compat.h -@@ -1456,7 +1456,6 @@ - #endif - - #ifdef NEED_SMP_MB_AFTER_ATOMIC --#define smp_mb__after_atomic smp_mb__after_clear_bit - #endif - - #ifdef NEED_DEVM_KMALLOC_ARRAY - diff --git a/packages/linux-driver-addons/dvb/hauppauge/patches/driver.dvb.hauppauge-02-add-to-backports.patch b/packages/linux-driver-addons/dvb/hauppauge/patches/driver.dvb.hauppauge-02-add-to-backports.patch deleted file mode 100644 index e5c1152a5c..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/patches/driver.dvb.hauppauge-02-add-to-backports.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/backports/backports.txt -+++ b/backports/backports.txt -@@ -25,6 +25,8 @@ add api_version.patch - add pr_fmt.patch - add debug.patch - add drx39xxj.patch -+add temp_revert.patch -+add hauppauge.patch - - [4.10.255] - add v4.10_sched_signal.patch diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/hauppauge.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/hauppauge.patch deleted file mode 100644 index 1a3520f02f..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/hauppauge.patch +++ /dev/null @@ -1,3214 +0,0 @@ -Combined patches from https://github.com/b-rad-NDi/Ubuntu-media-tree-kernel-builder -to support all kind of Hauppauge DVB cards. - -diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c -index 724e9aa..c4fefc2 100644 ---- a/drivers/media/dvb-frontends/lgdt3306a.c -+++ b/drivers/media/dvb-frontends/lgdt3306a.c -@@ -30,6 +30,17 @@ static int debug; - module_param(debug, int, 0644); - MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); - -+/* -+ * Older drivers treated QAM64 and QAM256 the same; that is the HW always -+ * used "Auto" mode during detection. Setting "forced_manual"=1 allows -+ * the user to treat these modes as separate. For backwards compatibility, -+ * it's off by default. QAM_AUTO can now be specified to achive that -+ * effect even if "forced_manual"=1 -+ */ -+static int forced_manual; -+module_param(forced_manual, int, 0644); -+MODULE_PARM_DESC(forced_manual, "if set, QAM64 and QAM256 will only lock to modulation specified"); -+ - #define DBG_INFO 1 - #define DBG_REG 2 - #define DBG_DUMP 4 /* FGR - comment out to remove dump code */ -@@ -566,7 +577,12 @@ static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation) - /* 3. : 64QAM/256QAM detection(manual, auto) */ - ret = lgdt3306a_read_reg(state, 0x0009, &val); - val &= 0xfc; -- val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */ -+ /* Check for forced Manual modulation modes; otherwise always "auto" */ -+ if(forced_manual && (modulation != QAM_AUTO)){ -+ val |= 0x01; /* STDOPDETCMODE[1:0]= 1=Manual */ -+ } else { -+ val |= 0x02; /* STDOPDETCMODE[1:0]= 2=Auto */ -+ } - ret = lgdt3306a_write_reg(state, 0x0009, val); - if (lg_chkerr(ret)) - goto fail; -@@ -598,6 +614,28 @@ static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation) - if (lg_chkerr(ret)) - goto fail; - -+ /* 5.1 V0.36 SRDCHKALWAYS : For better QAM detection */ -+ ret = lgdt3306a_read_reg(state, 0x000A, &val); -+ val &= 0xFD; -+ val |= 0x02; -+ ret = lgdt3306a_write_reg(state, 0x000A, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 5.2 V0.36 Control of "no signal" detector function */ -+ ret = lgdt3306a_read_reg(state, 0x2849, &val); -+ val &= 0xDF; -+ ret = lgdt3306a_write_reg(state, 0x2849, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ -+ /* 5.3 Fix for Blonder Tongue HDE-2H-QAM and AQM modulators */ -+ ret = lgdt3306a_read_reg(state, 0x302B, &val); -+ val &= 0x7F; /* SELFSYNCFINDEN_CQS=0; disable auto reset */ -+ ret = lgdt3306a_write_reg(state, 0x302B, val); -+ if (lg_chkerr(ret)) -+ goto fail; -+ - /* 6. Reset */ - ret = lgdt3306a_soft_reset(state); - if (lg_chkerr(ret)) -@@ -620,10 +658,9 @@ static int lgdt3306a_set_modulation(struct lgdt3306a_state *state, - ret = lgdt3306a_set_vsb(state); - break; - case QAM_64: -- ret = lgdt3306a_set_qam(state, QAM_64); -- break; - case QAM_256: -- ret = lgdt3306a_set_qam(state, QAM_256); -+ case QAM_AUTO: -+ ret = lgdt3306a_set_qam(state, p->modulation); - break; - default: - return -EINVAL; -@@ -650,6 +687,7 @@ static int lgdt3306a_agc_setup(struct lgdt3306a_state *state, - break; - case QAM_64: - case QAM_256: -+ case QAM_AUTO: - break; - default: - return -EINVAL; -@@ -704,6 +742,7 @@ static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state, - break; - case QAM_64: - case QAM_256: -+ case QAM_AUTO: - /* Auto ok for QAM */ - ret = lgdt3306a_set_inversion_auto(state, 1); - break; -@@ -727,6 +766,7 @@ static int lgdt3306a_set_if(struct lgdt3306a_state *state, - break; - case QAM_64: - case QAM_256: -+ case QAM_AUTO: - if_freq_khz = state->cfg->qam_if_khz; - break; - default: -@@ -1585,6 +1625,7 @@ static int lgdt3306a_read_status(struct dvb_frontend *fe, - switch (state->current_modulation) { - case QAM_256: - case QAM_64: -+ case QAM_AUTO: - if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) { - *status |= FE_HAS_VITERBI; - *status |= FE_HAS_SYNC; -@@ -1628,6 +1669,7 @@ static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe, - * Calculate some sort of "strength" from SNR - */ - struct lgdt3306a_state *state = fe->demodulator_priv; -+ u8 val; - u16 snr; /* snr_x10 */ - int ret; - u32 ref_snr; /* snr*100 */ -@@ -1640,11 +1682,15 @@ static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe, - ref_snr = 1600; /* 16dB */ - break; - case QAM_64: -- ref_snr = 2200; /* 22dB */ -- break; - case QAM_256: -- ref_snr = 2800; /* 28dB */ -- break; -+ case QAM_AUTO: -+ /* need to know actual modulation to set proper SNR baseline */ -+ lgdt3306a_read_reg(state, 0x00a6, &val); -+ if(val & 0x04) -+ ref_snr = 2800; /* QAM-256 28dB */ -+ else -+ ref_snr = 2200; /* QAM-64 22dB */ -+ break; - default: - return -EINVAL; - } -@@ -2114,7 +2160,7 @@ static const struct dvb_frontend_ops lgdt3306a_ops = { - .frequency_min = 54000000, - .frequency_max = 858000000, - .frequency_stepsize = 62500, -- .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB -+ .caps = FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB - }, - .i2c_gate_ctrl = lgdt3306a_i2c_gate_ctrl, - .init = lgdt3306a_init, -@@ -2177,6 +2223,7 @@ static int lgdt3306a_probe(struct i2c_client *client, - - i2c_set_clientdata(client, fe->demodulator_priv); - state = fe->demodulator_priv; -+ state->frontend.ops.release = NULL; - - /* create mux i2c adapter for tuner */ - state->muxc = i2c_mux_alloc(client->adapter, &client->dev, -diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c -index 41d9c51..3752bb2 100644 ---- a/drivers/media/dvb-frontends/si2168.c -+++ b/drivers/media/dvb-frontends/si2168.c -@@ -85,7 +85,7 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) - struct i2c_client *client = fe->demodulator_priv; - struct si2168_dev *dev = i2c_get_clientdata(client); - struct dtv_frontend_properties *c = &fe->dtv_property_cache; -- int ret, i; -+ int ret, i, sys; - unsigned int utmp, utmp1, utmp2; - struct si2168_cmd cmd; - -@@ -96,7 +96,21 @@ static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status) - goto err; - } - -- switch (c->delivery_system) { -+ memcpy(cmd.args, "\x87\x01", 2); -+ cmd.wlen = 2; -+ cmd.rlen = 8; -+ ret = si2168_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ sys = c->delivery_system; -+ /* check if we found DVBT2 during DVBT tuning */ -+ if (sys == SYS_DVBT) { -+ if ((cmd.args[3] & 0x0f) == 7) { -+ sys = SYS_DVBT2; -+ } -+ } -+ switch (sys) { - case SYS_DVBT: - memcpy(cmd.args, "\xa0\x01", 2); - cmd.wlen = 2; -@@ -211,6 +225,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) - struct i2c_client *client = fe->demodulator_priv; - struct si2168_dev *dev = i2c_get_clientdata(client); - struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ struct si2168_config *config = client->dev.platform_data; - int ret; - struct si2168_cmd cmd; - u8 bandwidth, delivery_system; -@@ -228,7 +243,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe) - - switch (c->delivery_system) { - case SYS_DVBT: -- delivery_system = 0x20; -+ delivery_system = 0xf0; /* T/T2 auto-detect is user friendly */ - break; - case SYS_DVBC_ANNEX_A: - delivery_system = 0x30; -@@ -298,6 +313,16 @@ static int si2168_set_frontend(struct dvb_frontend *fe) - ret = si2168_cmd_execute(client, &cmd); - if (ret) - goto err; -+ } else if (c->delivery_system == SYS_DVBT) { -+ /* select Auto PLP */ -+ cmd.args[0] = 0x52; -+ cmd.args[1] = 0; -+ cmd.args[2] = 0; /* Auto PLP */ -+ cmd.wlen = 3; -+ cmd.rlen = 1; -+ ret = si2168_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; - } - - memcpy(cmd.args, "\x51\x03", 2); -@@ -337,6 +362,10 @@ static int si2168_set_frontend(struct dvb_frontend *fe) - - memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6); - cmd.args[4] = delivery_system | bandwidth; -+ if (delivery_system == 0xf0) -+ cmd.args[5] |= 2; /* Auto detect DVB-T/T2 */ -+ if (config->inversion) /* inverted spectrum, eg si2157 */ -+ cmd.args[5] |= 1; - cmd.wlen = 6; - cmd.rlen = 4; - ret = si2168_cmd_execute(client, &cmd); -@@ -356,6 +385,8 @@ static int si2168_set_frontend(struct dvb_frontend *fe) - } - - memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6); -+ /* BUGBUG? FW defaults to 1, but windows driver uses 30; above is 0? */ -+ cmd.args[5] = 30; - cmd.wlen = 6; - cmd.rlen = 4; - ret = si2168_cmd_execute(client, &cmd); -diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h -index 3225d0c..0f71233 100644 ---- a/drivers/media/dvb-frontends/si2168.h -+++ b/drivers/media/dvb-frontends/si2168.h -@@ -45,6 +45,9 @@ struct si2168_config { - - /* TS clock gapped */ - bool ts_clock_gapped; -+ -+ /* Spectral Inversion */ -+ bool inversion; - }; - - #endif -diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c -index 940c8b1..9d2bb6d 100644 ---- a/drivers/media/i2c/cx25840/cx25840-core.c -+++ b/drivers/media/i2c/cx25840/cx25840-core.c -@@ -668,14 +668,14 @@ static void cx23885_initialize(struct i2c_client *client) - */ - cx25840_write4(client, 0x404, 0x0010253e); - -- /* CC on - Undocumented Register */ -+ /* CC on - VBI_LINE_CTRL3, FLD_VBI_MD_LINE12 */ - cx25840_write(client, state->vbi_regs_offset + 0x42f, 0x66); - - /* HVR-1250 / HVR1850 DIF related */ - /* Power everything up */ - cx25840_write4(client, 0x130, 0x0); - -- /* Undocumented */ -+ /* SRC_COMB_CFG */ - if (is_cx23888(state)) - cx25840_write4(client, 0x454, 0x6628021F); - else -@@ -1111,16 +1111,25 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp - cx25840_write4(client, 0x410, 0xffff0dbf); - cx25840_write4(client, 0x414, 0x00137d03); - -- cx25840_write4(client, state->vbi_regs_offset + 0x42c, 0x42600000); -- cx25840_write4(client, state->vbi_regs_offset + 0x430, 0x0000039b); -- cx25840_write4(client, state->vbi_regs_offset + 0x438, 0x00000000); -- -- cx25840_write4(client, state->vbi_regs_offset + 0x440, 0xF8E3E824); -- cx25840_write4(client, state->vbi_regs_offset + 0x444, 0x401040dc); -- cx25840_write4(client, state->vbi_regs_offset + 0x448, 0xcd3f02a0); -- cx25840_write4(client, state->vbi_regs_offset + 0x44c, 0x161f1000); -- cx25840_write4(client, state->vbi_regs_offset + 0x450, 0x00000802); -- -+ /* These are not VBI controls */ -+ if (is_cx23888(state)) { -+ /* 888 MISC_TIM_CTRL */ -+ cx25840_write4(client, 0x42c, 0x42600000); -+ /* 888 FIELD_COUNT */ -+ cx25840_write4(client, 0x430, 0x0000039b); -+ /* 888 VSCALE_CTRL */ -+ cx25840_write4(client, 0x438, 0x00000000); -+ /* 888 DFE_CTRL1 */ -+ cx25840_write4(client, 0x440, 0xF8E3E824); -+ /* 888 DFE_CTRL2 */ -+ cx25840_write4(client, 0x444, 0x401040dc); -+ /* 888 DFE_CTRL3 */ -+ cx25840_write4(client, 0x448, 0xcd3f02a0); -+ /* 888 PLL_CTRL */ -+ cx25840_write4(client, 0x44c, 0x161f1000); -+ /* 888 HTL_CTRL */ -+ cx25840_write4(client, 0x450, 0x00000802); -+ } - cx25840_write4(client, 0x91c, 0x01000000); - cx25840_write4(client, 0x8e0, 0x03063870); - cx25840_write4(client, 0x8d4, 0x7FFF0024); -@@ -1398,8 +1407,9 @@ static int cx25840_set_fmt(struct v4l2_subdev *sd, - if ((fmt->width == 0) || (Vlines == 0) || - (fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) || - (Vlines * 8 < Vsrc) || (Vsrc + 1 < Vlines)) { -- v4l_err(client, "%dx%d is not a valid size!\n", -- fmt->width, fmt->height); -+ v4l_err(client, "%dx%d is not a valid size! (Hsrc=%d, Vsrc=%d, Vlines=%d, is_50Hz=%u)\n", -+ fmt->width, fmt->height, Hsrc, Vsrc, -+ Vlines, is_50Hz); - return -ERANGE; - } - if (format->which == V4L2_SUBDEV_FORMAT_TRY) -@@ -1727,6 +1737,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) - if (is_cx2388x(state) || is_cx231xx(state)) - return 0; - -+ /* PIN_CTRL1 */ - if (enable) { - v = cx25840_read(client, 0x115) | 0x0c; - cx25840_write(client, 0x115, v); -diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c -index 28eab9c..9b6c1f1 100644 ---- a/drivers/media/pci/cx23885/cx23885-cards.c -+++ b/drivers/media/pci/cx23885/cx23885-cards.c -@@ -325,8 +325,7 @@ struct cx23885_board cx23885_boards[] = { - .name = "Hauppauge WinTV-HVR1255", - .porta = CX23885_ANALOG_VIDEO, - .portc = CX23885_MPEG_DVB, -- .tuner_type = TUNER_ABSENT, -- .tuner_addr = 0x42, /* 0x84 >> 1 */ -+ .tuner_type = TUNER_NXP_TDA18271, - .force_bff = 1, - .input = {{ - .type = CX23885_VMUX_TELEVISION, -@@ -354,8 +353,7 @@ struct cx23885_board cx23885_boards[] = { - .name = "Hauppauge WinTV-HVR1255", - .porta = CX23885_ANALOG_VIDEO, - .portc = CX23885_MPEG_DVB, -- .tuner_type = TUNER_ABSENT, -- .tuner_addr = 0x42, /* 0x84 >> 1 */ -+ .tuner_type = TUNER_NXP_TDA18271, - .force_bff = 1, - .input = {{ - .type = CX23885_VMUX_TELEVISION, -@@ -767,14 +765,80 @@ struct cx23885_board cx23885_boards[] = { - } }, - }, - [CX23885_BOARD_HAUPPAUGE_QUADHD_DVB] = { -- .name = "Hauppauge WinTV-QuadHD-DVB", -+ .name = "Hauppauge WinTV-QuadHD-DVB", -+ .porta = CX23885_ANALOG_VIDEO, -+ .portb = CX23885_MPEG_DVB, -+ .portc = CX23885_MPEG_DVB, -+ .tuner_type = TUNER_ABSENT, -+ .force_bff = 1, -+ .input = {{ -+ .type = CX23885_VMUX_TELEVISION, -+ .vmux = CX25840_VIN7_CH3 | -+ CX25840_VIN5_CH2 | -+ CX25840_VIN2_CH1 | -+ CX25840_DIF_ON, -+ .amux = CX25840_AUDIO8, -+ } }, -+ }, -+ [CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885] = { -+ .name = "Hauppauge WinTV-QuadHD-DVB(885)", - .portb = CX23885_MPEG_DVB, - .portc = CX23885_MPEG_DVB, -+ .tuner_type = TUNER_ABSENT, - }, - [CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC] = { -- .name = "Hauppauge WinTV-QuadHD-ATSC", -+ .name = "Hauppauge WinTV-QuadHD-ATSC", -+ .porta = CX23885_ANALOG_VIDEO, -+ .portb = CX23885_MPEG_DVB, -+ .portc = CX23885_MPEG_DVB, -+ .tuner_type = TUNER_ABSENT, -+ .force_bff = 1, -+ .input = {{ -+ .type = CX23885_VMUX_TELEVISION, -+ .vmux = CX25840_VIN7_CH3 | -+ CX25840_VIN5_CH2 | -+ CX25840_VIN2_CH1 | -+ CX25840_DIF_ON, -+ .amux = CX25840_AUDIO8, -+ } }, -+ }, -+ [CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885] = { -+ .name = "Hauppauge WinTV-QuadHD-ATSC(885)", - .portb = CX23885_MPEG_DVB, - .portc = CX23885_MPEG_DVB, -+ .tuner_type = TUNER_ABSENT, -+ }, -+ [CX23885_BOARD_HAUPPAUGE_HVR1265_K4] = { -+ .name = "Hauppauge WinTV-HVR-1265(161111)", -+ .porta = CX23885_ANALOG_VIDEO, -+ .portc = CX23885_MPEG_DVB, -+ .tuner_type = TUNER_SILABS_SI2157, -+ .force_bff = 1, -+ .input = {{ -+ .type = CX23885_VMUX_TELEVISION, -+ .vmux = CX25840_VIN7_CH3 | -+ CX25840_VIN5_CH2 | -+ CX25840_VIN2_CH1 | -+ CX25840_DIF_ON, -+ .amux = CX25840_AUDIO8, -+ }, { -+ .type = CX23885_VMUX_COMPOSITE1, -+ .vmux = CX25840_VIN7_CH3 | -+ CX25840_VIN4_CH2 | -+ CX25840_VIN6_CH1, -+ .amux = CX25840_AUDIO7, -+ }, { -+ .type = CX23885_VMUX_SVIDEO, -+ .vmux = CX25840_VIN7_CH3 | -+ CX25840_VIN4_CH2 | -+ CX25840_VIN8_CH1 | -+ CX25840_SVIDEO_ON, -+ .amux = CX25840_AUDIO7, -+ } }, -+ }, -+ [CX23885_BOARD_HAUPPAUGE_STARBURST2] = { -+ .name = "Hauppauge WinTV-Starburst2", -+ .portb = CX23885_MPEG_DVB, - }, - }; - const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); -@@ -1027,6 +1091,10 @@ struct cx23885_subid cx23885_subids[] = { - .subvendor = 0x0070, - .subdevice = 0x7133, - .card = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE, -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x7137, -+ .card = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE, - }, { - .subvendor = 0x18ac, - .subdevice = 0xdb98, -@@ -1087,7 +1155,16 @@ struct cx23885_subid cx23885_subids[] = { - .subvendor = 0x0070, - .subdevice = 0x6b18, - .card = CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC, /* Tuner Pair 2 */ -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x2a18, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1265_K4, /* Hauppauge WinTV HVR-1265 (Model 161xx1, Hybrid ATSC/QAM-B) */ -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0xf02a, -+ .card = CX23885_BOARD_HAUPPAUGE_STARBURST2, - }, -+ - }; - const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); - -@@ -1287,25 +1364,28 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) - case 150329: - /* WinTV-HVR5525 (PCIe, DVB-S/S2, DVB-T/T2/C) */ - break; -- case 166100: -+ case 161111: -+ /* WinTV-HVR-1265 (PCIe, Analog/ATSC/QAM-B) */ -+ break; -+ case 166100: /* 888 version, hybrid */ -+ case 166200: /* 885 version, DVB only */ - /* WinTV-QuadHD (DVB) Tuner Pair 1 (PCIe, IR, half height, - DVB-T/T2/C, DVB-T/T2/C */ - break; -- case 166101: -+ case 166101: /* 888 version, hybrid */ -+ case 166201: /* 885 version, DVB only */ - /* WinTV-QuadHD (DVB) Tuner Pair 2 (PCIe, IR, half height, - DVB-T/T2/C, DVB-T/T2/C */ - break; -- case 165100: -- /* -- * WinTV-QuadHD (ATSC) Tuner Pair 1 (PCIe, IR, half height, -- * ATSC, ATSC -- */ -+ case 165100: /* 888 version, hybrid */ -+ case 165200: /* 885 version, digital only */ -+ /* WinTV-QuadHD (ATSC) Tuner Pair 1 (PCIe, IR, half height, -+ * ATSC/QAM-B, ATSC/QAM-B */ - break; -- case 165101: -- /* -- * WinTV-QuadHD (DVB) Tuner Pair 2 (PCIe, IR, half height, -- * ATSC, ATSC -- */ -+ case 165101: /* 888 version, hybrid */ -+ case 165201: /* 885 version, digital only */ -+ /* WinTV-QuadHD (ATSC) Tuner Pair 2 (PCIe, IR, half height, -+ * ATSC/QAM-B, ATSC/QAM-B */ - break; - default: - pr_warn("%s: warning: unknown hauppauge model #%d\n", -@@ -1778,8 +1858,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) - cx23885_gpio_set(dev, GPIO_2); - break; - case CX23885_BOARD_HAUPPAUGE_HVR5525: -- case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: -- case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: -+ case CX23885_BOARD_HAUPPAUGE_STARBURST2: - /* - * HVR5525 GPIO Details: - * GPIO-00 IR_WIDE -@@ -1809,6 +1888,22 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) - * card does not have any GPIO's connected to subcomponents. - */ - break; -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885: -+ /* -+ * GPIO-08 TER1_RESN -+ * GPIO-09 TER2_RESN -+ */ -+ /* Put the parts into reset and back */ -+ cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1); -+ cx23885_gpio_clear(dev, GPIO_8 | GPIO_9); -+ msleep(100); -+ cx23885_gpio_set(dev, GPIO_8 | GPIO_9); -+ msleep(100); -+ break; - } - } - -@@ -2054,8 +2149,13 @@ void cx23885_card_setup(struct cx23885_dev *dev) - case CX23885_BOARD_HAUPPAUGE_STARBURST: - case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE: - case CX23885_BOARD_HAUPPAUGE_HVR5525: -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: -+ case CX23885_BOARD_HAUPPAUGE_STARBURST2: - case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885: - case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885: -+ - if (dev->i2c_bus[0].i2c_rc == 0) - hauppauge_eeprom(dev, eeprom+0xc0); - break; -@@ -2194,6 +2294,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) - ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; - break; - case CX23885_BOARD_HAUPPAUGE_HVR5525: -+ case CX23885_BOARD_HAUPPAUGE_STARBURST2: - ts1->gen_ctrl_val = 0x5; /* Parallel */ - ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ - ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; -@@ -2201,8 +2302,11 @@ void cx23885_card_setup(struct cx23885_dev *dev) - ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ - ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; - break; -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: - case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885: - case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885: - ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ - ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ - ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; -@@ -2259,6 +2363,9 @@ void cx23885_card_setup(struct cx23885_dev *dev) - case CX23885_BOARD_COMPRO_VIDEOMATE_E800: - case CX23885_BOARD_HAUPPAUGE_HVR1255: - case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: - case CX23885_BOARD_HAUPPAUGE_HVR1270: - case CX23885_BOARD_HAUPPAUGE_HVR1850: - case CX23885_BOARD_MYGICA_X8506: -diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c -index 8f63df1..8afddd6 100644 ---- a/drivers/media/pci/cx23885/cx23885-core.c -+++ b/drivers/media/pci/cx23885/cx23885-core.c -@@ -869,6 +869,14 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) - cx23885_card_list(dev); - } - -+ if (dev->pci->device == 0x8852) { -+ /* no DIF on cx23885, so no analog tuner support possible */ -+ if (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC) -+ dev->board = CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885; -+ else if (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) -+ dev->board = CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885; -+ } -+ - /* If the user specific a clk freq override, apply it */ - if (cx23885_boards[dev->board].clk_freq > 0) - dev->clk_freq = cx23885_boards[dev->board].clk_freq; -diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c -index 67ad041..53e59e4 100644 ---- a/drivers/media/pci/cx23885/cx23885-dvb.c -+++ b/drivers/media/pci/cx23885/cx23885-dvb.c -@@ -930,6 +930,18 @@ static const struct m88ds3103_config hauppauge_hvr5525_m88ds3103_config = { - .agc = 0x99, - }; - -+static struct lgdt3306a_config hauppauge_hvr1265k4_config = { -+ .i2c_addr = 0x59, -+ .qam_if_khz = 4000, -+ .vsb_if_khz = 3250, -+ .deny_i2c_rptr = 1, /* Disabled */ -+ .spectral_inversion = 0, /* Disabled */ -+ .mpeg_mode = LGDT3306A_MPEG_SERIAL, -+ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, -+ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, -+ .xtalMHz = 25, /* 24 or 25 */ -+}; -+ - static int netup_altera_fpga_rw(void *device, int flag, int data, int read) - { - struct cx23885_dev *dev = (struct cx23885_dev *)device; -@@ -2217,10 +2229,15 @@ static int dvb_register(struct cx23885_tsport *port) - } - port->i2c_client_tuner = client_tuner; - break; -- case CX23885_BOARD_HAUPPAUGE_HVR5525: { -+ case CX23885_BOARD_HAUPPAUGE_STARBURST2: -+ case CX23885_BOARD_HAUPPAUGE_HVR5525: -+ i2c_bus = &dev->i2c_bus[0]; -+ i2c_bus2 = &dev->i2c_bus[1]; -+ - struct m88rs6000t_config m88rs6000t_config; - struct a8293_platform_data a8293_pdata = {}; - -+ pr_info("%s(): port=%d\n", __func__, port->nr); - switch (port->nr) { - - /* port b - satellite */ -@@ -2228,7 +2245,7 @@ static int dvb_register(struct cx23885_tsport *port) - /* attach frontend */ - fe0->dvb.frontend = dvb_attach(m88ds3103_attach, - &hauppauge_hvr5525_m88ds3103_config, -- &dev->i2c_bus[0].i2c_adap, &adapter); -+ &i2c_bus->i2c_adap, &adapter); - if (fe0->dvb.frontend == NULL) - break; - -@@ -2239,7 +2256,7 @@ static int dvb_register(struct cx23885_tsport *port) - info.addr = 0x0b; - info.platform_data = &a8293_pdata; - request_module("a8293"); -- client_sec = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info); -+ client_sec = i2c_new_device(&i2c_bus->i2c_adap, &info); - if (!client_sec || !client_sec->dev.driver) - goto frontend_detach; - if (!try_module_get(client_sec->dev.driver->owner)) { -@@ -2281,7 +2298,7 @@ static int dvb_register(struct cx23885_tsport *port) - info.addr = 0x64; - info.platform_data = &si2168_config; - request_module("%s", info.type); -- client_demod = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info); -+ client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info); - if (!client_demod || !client_demod->dev.driver) - goto frontend_detach; - if (!try_module_get(client_demod->dev.driver->owner)) { -@@ -2299,7 +2316,7 @@ static int dvb_register(struct cx23885_tsport *port) - info.addr = 0x60; - info.platform_data = &si2157_config; - request_module("%s", info.type); -- client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, &info); -+ client_tuner = i2c_new_device(&i2c_bus2->i2c_adap, &info); - if (!client_tuner || !client_tuner->dev.driver) { - module_put(client_demod->dev.driver->owner); - i2c_unregister_device(client_demod); -@@ -2317,8 +2334,10 @@ static int dvb_register(struct cx23885_tsport *port) - break; - } - break; -- } - case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885: -+ pr_info("%s(): board=%d port=%d\n", __func__, -+ dev->board, port->nr); - switch (port->nr) { - /* port b - Terrestrial/cable */ - case 1: -@@ -2365,6 +2384,16 @@ static int dvb_register(struct cx23885_tsport *port) - goto frontend_detach; - } - port->i2c_client_tuner = client_tuner; -+ -+ /* we only attach tuner for analog on the 888 version */ -+ if (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) { -+ pr_info("%s(): QUADHD_DVB analog setup\n", -+ __func__); -+ dev->ts1.analog_fe.tuner_priv = client_tuner; -+ dvb_attach(si2157_attach, &dev->ts1.analog_fe, -+ info.addr, &dev->i2c_bus[1].i2c_adap, -+ &si2157_config); -+ } - break; - - /* port c - terrestrial/cable */ -@@ -2416,6 +2445,9 @@ static int dvb_register(struct cx23885_tsport *port) - } - break; - case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885: -+ pr_info("%s(): board=%d port=%d\n", __func__, -+ dev->board, port->nr); - switch (port->nr) { - /* port b - Terrestrial/cable */ - case 1: -@@ -2451,6 +2483,16 @@ static int dvb_register(struct cx23885_tsport *port) - goto frontend_detach; - } - port->i2c_client_tuner = client_tuner; -+ -+ /* we only attach tuner for analog on the 888 version */ -+ if (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC) { -+ pr_info("%s(): QUADHD_ATSC analog setup\n", -+ __func__); -+ dev->ts1.analog_fe.tuner_priv = client_tuner; -+ dvb_attach(si2157_attach, &dev->ts1.analog_fe, -+ info.addr, &dev->i2c_bus[1].i2c_adap, -+ &si2157_config); -+ } - break; - - /* port c - terrestrial/cable */ -@@ -2490,6 +2532,47 @@ static int dvb_register(struct cx23885_tsport *port) - break; - } - break; -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: -+ pr_info("%s(): port=%d\n", __func__, port->nr); -+ switch (port->nr) { -+ /* port c - Terrestrial/cable */ -+ case 2: -+ /* attach frontend */ -+ i2c_bus = &dev->i2c_bus[0]; -+ fe0->dvb.frontend = dvb_attach(lgdt3306a_attach, -+ &hauppauge_hvr1265k4_config, &i2c_bus->i2c_adap); -+ if (fe0->dvb.frontend == NULL) -+ break; -+ -+ /* attach tuner */ -+ si2157_config.fe = fe0->dvb.frontend; -+ si2157_config.if_port = 1; -+ si2157_config.inversion = 1; -+ memset(&info, 0, sizeof(struct i2c_board_info)); -+ strlcpy(info.type, "si2157", I2C_NAME_SIZE); -+ info.addr = 0x60; -+ info.platform_data = &si2157_config; -+ request_module("%s", info.type); -+ client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, &info); -+ if (!client_tuner || !client_tuner->dev.driver) { -+ goto frontend_detach; -+ } -+ if (!try_module_get(client_tuner->dev.driver->owner)) { -+ i2c_unregister_device(client_tuner); -+ client_tuner = NULL; -+ goto frontend_detach; -+ } -+ port->i2c_client_tuner = client_tuner; -+ -+ dev->ts1.analog_fe.tuner_priv = client_tuner; -+ dvb_attach(si2157_attach, &dev->ts1.analog_fe, -+ 0x60, &dev->i2c_bus[1].i2c_adap, -+ &si2157_config); -+ pr_info("%s(): HVR1265_K4 setup\n", __func__); -+ break; -+ } -+ break; -+ - - default: - pr_info("%s: The frontend of your DVB/ATSC card isn't supported yet\n", -diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c -index 0f4e542..be49589 100644 ---- a/drivers/media/pci/cx23885/cx23885-input.c -+++ b/drivers/media/pci/cx23885/cx23885-input.c -@@ -94,6 +94,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) - case CX23885_BOARD_DVBSKY_S950: - case CX23885_BOARD_DVBSKY_S952: - case CX23885_BOARD_DVBSKY_T982: -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: - /* - * The only boards we handle right now. However other boards - * using the CX2388x integrated IR controller should be similar -@@ -153,6 +154,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev) - case CX23885_BOARD_DVBSKY_S950: - case CX23885_BOARD_DVBSKY_S952: - case CX23885_BOARD_DVBSKY_T982: -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: - /* - * The IR controller on this board only returns pulse widths. - * Any other mode setting will fail to set up the device. -@@ -283,6 +285,7 @@ int cx23885_input_init(struct cx23885_dev *dev) - case CX23885_BOARD_HAUPPAUGE_HVR1850: - case CX23885_BOARD_HAUPPAUGE_HVR1290: - case CX23885_BOARD_HAUPPAUGE_HVR1250: -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: - /* Integrated CX2388[58] IR controller */ - allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER; - /* The grey Hauppauge RC-5 remote */ -diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c -index ecc580a..afa383f 100644 ---- a/drivers/media/pci/cx23885/cx23885-video.c -+++ b/drivers/media/pci/cx23885/cx23885-video.c -@@ -263,6 +263,9 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) - (dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE) || - (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || - (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || -+ (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4) || -+ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC) || -+ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) || - (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || - (dev->board == CX23885_BOARD_MYGICA_X8507) || - (dev->board == CX23885_BOARD_AVERMEDIA_HC81R) || -@@ -993,7 +996,10 @@ static int cx23885_set_freq_via_ops(struct cx23885_dev *dev, - - if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || - (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || -- (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111)) -+ (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || -+ (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4) || -+ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) || -+ (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC)) - fe = &dev->ts1.analog_fe; - - if (fe && fe->ops.tuner_ops.set_analog_params) { -@@ -1022,7 +1028,10 @@ int cx23885_set_frequency(struct file *file, void *priv, - switch (dev->board) { - case CX23885_BOARD_HAUPPAUGE_HVR1255: - case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: -+ case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: - case CX23885_BOARD_HAUPPAUGE_HVR1850: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: -+ case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: - ret = cx23885_set_freq_via_ops(dev, f); - break; - default: -diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h -index 6aab713..6e659be 100644 ---- a/drivers/media/pci/cx23885/cx23885.h -+++ b/drivers/media/pci/cx23885/cx23885.h -@@ -107,6 +107,10 @@ - #define CX23885_BOARD_VIEWCAST_460E 55 - #define CX23885_BOARD_HAUPPAUGE_QUADHD_DVB 56 - #define CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC 57 -+#define CX23885_BOARD_HAUPPAUGE_HVR1265_K4 58 -+#define CX23885_BOARD_HAUPPAUGE_STARBURST2 59 -+#define CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885 60 -+#define CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885 61 - - #define GPIO_0 0x00000001 - #define GPIO_1 0x00000002 -diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c -index e76d3ba..9522c6c 100644 ---- a/drivers/media/pci/saa7164/saa7164-dvb.c -+++ b/drivers/media/pci/saa7164/saa7164-dvb.c -@@ -110,8 +110,9 @@ static struct si2157_config hauppauge_hvr2255_tuner_config = { - .if_port = 1, - }; - --static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter, -- struct dvb_frontend *fe, u8 addr8bit, struct si2157_config *cfg) -+static int si2157_attach_priv(struct saa7164_port *port, -+ struct i2c_adapter *adapter, struct dvb_frontend *fe, -+ u8 addr8bit, struct si2157_config *cfg) - { - struct i2c_board_info bi; - struct i2c_client *tuner; -@@ -624,11 +625,13 @@ int saa7164_dvb_register(struct saa7164_port *port) - if (port->dvb.frontend != NULL) { - - if (port->nr == 0) { -- si2157_attach(port, &dev->i2c_bus[0].i2c_adap, -+ si2157_attach_priv(port, -+ &dev->i2c_bus[0].i2c_adap, - port->dvb.frontend, 0xc0, - &hauppauge_hvr2255_tuner_config); - } else { -- si2157_attach(port, &dev->i2c_bus[1].i2c_adap, -+ si2157_attach_priv(port, -+ &dev->i2c_bus[1].i2c_adap, - port->dvb.frontend, 0xc0, - &hauppauge_hvr2255_tuner_config); - } -diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c -index e35b1fa..2f79bdb 100644 ---- a/drivers/media/tuners/si2157.c -+++ b/drivers/media/tuners/si2157.c -@@ -1,5 +1,5 @@ - /* -- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver -+ * Silicon Labs Si2141/2146/2147/2148/2157/2158 silicon tuner driver - * - * Copyright (C) 2014 Antti Palosaari - * -@@ -18,6 +18,11 @@ - - static const struct dvb_tuner_ops si2157_ops; - -+static DEFINE_MUTEX(si2157_list_mutex); -+static LIST_HEAD(hybrid_tuner_instance_list); -+ -+/*---------------------------------------------------------------------*/ -+ - /* execute firmware command */ - static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd) - { -@@ -52,18 +57,25 @@ static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd) - } - - /* firmware ready? */ -- if ((cmd->args[0] >> 7) & 0x01) -+ if (cmd->args[0] & 0x80) - break; -+ usleep_range(5000, 10000); - } - -- dev_dbg(&client->dev, "cmd execution took %d ms\n", -+ dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n", - jiffies_to_msecs(jiffies) - -- (jiffies_to_msecs(timeout) - TIMEOUT)); -+ (jiffies_to_msecs(timeout) - TIMEOUT), -+ cmd->args[0]); - -- if (!((cmd->args[0] >> 7) & 0x01)) { -+ if (!(cmd->args[0] & 0x80)) { - ret = -ETIMEDOUT; - goto err_mutex_unlock; - } -+ /* check error status bit */ -+ if (cmd->args[0] & 0x40) { -+ ret = -EAGAIN; -+ goto err_mutex_unlock; -+ } - } - - mutex_unlock(&dev->i2c_mutex); -@@ -84,24 +96,25 @@ static int si2157_init(struct dvb_frontend *fe) - struct si2157_cmd cmd; - const struct firmware *fw; - const char *fw_name; -- unsigned int uitmp, chip_id; -+ unsigned int chip_id, xtal_trim; - - dev_dbg(&client->dev, "\n"); - -- /* Returned IF frequency is garbage when firmware is not running */ -- memcpy(cmd.args, "\x15\x00\x06\x07", 4); -+ /* Try to get Xtal trim property setting, to verify tuner still running; -+ * replaces previous test of IF freq -+ */ -+ memcpy(cmd.args, "\x15\x00\x04\x02", 4); - cmd.wlen = 4; - cmd.rlen = 4; - ret = si2157_cmd_execute(client, &cmd); -- if (ret) -- goto err; - -- uitmp = cmd.args[2] << 0 | cmd.args[3] << 8; -- dev_dbg(&client->dev, "if_frequency kHz=%u\n", uitmp); -+ xtal_trim = cmd.args[2] | (cmd.args[3] << 8); - -- if (uitmp == dev->if_frequency / 1000) -+ if ((ret == 0) && (xtal_trim < 16)) - goto warm; - -+ dev->if_frequency = 0; /* we no longer know current tuner state */ -+ - /* power up */ - if (dev->chiptype == SI2157_CHIPTYPE_SI2146) { - memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9); -@@ -230,6 +243,45 @@ skip_fw_download: - - dev_info(&client->dev, "firmware version: %c.%c.%d\n", - cmd.args[6], cmd.args[7], cmd.args[8]); -+ -+ if (dev->chiptype == SI2157_CHIPTYPE_SI2141) { -+ /* set clock */ -+ memcpy(cmd.args, "\xc0\x00\x0d", 3); -+ cmd.wlen = 3; -+ cmd.rlen = 1; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ /* setup PIN */ -+ memcpy(cmd.args, "\x12\x80\x80\x85\x00\x81\x00", 7); -+ cmd.wlen = 7; -+ cmd.rlen = 7; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ } -+ -+ /* enable tuner status flags, for si2157_tune_wait() */ -+ memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6); -+ cmd.wlen = 6; -+ cmd.rlen = 1; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ memcpy(cmd.args, "\x14\x00\x01\x06\x01\x00", 6); -+ cmd.wlen = 6; -+ cmd.rlen = 1; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ memcpy(cmd.args, "\x14\x00\x01\x07\x01\x00", 6); -+ cmd.wlen = 6; -+ cmd.rlen = 1; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; - warm: - /* init statistics in order signal app which are supported */ - c->strength.len = 1; -@@ -250,7 +302,7 @@ static int si2157_sleep(struct dvb_frontend *fe) - { - struct i2c_client *client = fe->tuner_priv; - struct si2157_dev *dev = i2c_get_clientdata(client); -- int ret; -+ int ret = 0; - struct si2157_cmd cmd; - - dev_dbg(&client->dev, "\n"); -@@ -274,6 +326,84 @@ err: - return ret; - } - -+static int si2157_tune_wait(struct i2c_client *client, u8 is_digital) -+{ -+#define TUN_TIMEOUT 40 -+#define DIG_TIMEOUT 30 -+#define ANALOG_TIMEOUT 150 -+ struct si2157_dev *dev = i2c_get_clientdata(client); -+ int ret; -+ unsigned long timeout; -+ unsigned long start_time; -+ u8 wait_status; -+ u8 tune_lock_mask; -+ -+ if (is_digital) -+ tune_lock_mask = 0x04; -+ else -+ tune_lock_mask = 0x02; -+ -+ mutex_lock(&dev->i2c_mutex); -+ -+ /* wait tuner command complete */ -+ start_time = jiffies; -+ timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT); -+ while (!time_after(jiffies, timeout)) { -+ ret = i2c_master_recv(client, &wait_status, -+ sizeof(wait_status)); -+ if (ret < 0) { -+ goto err_mutex_unlock; -+ } else if (ret != sizeof(wait_status)) { -+ ret = -EREMOTEIO; -+ goto err_mutex_unlock; -+ } -+ -+ /* tuner done? */ -+ if ((wait_status & 0x81) == 0x81) -+ break; -+ usleep_range(5000, 10000); -+ } -+ /* if we tuned ok, wait a bit for tuner lock */ -+ if ((wait_status & 0x81) == 0x81) { -+ if (is_digital) -+ timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT); -+ else -+ timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT); -+ while (!time_after(jiffies, timeout)) { -+ ret = i2c_master_recv(client, &wait_status, -+ sizeof(wait_status)); -+ if (ret < 0) { -+ goto err_mutex_unlock; -+ } else if (ret != sizeof(wait_status)) { -+ ret = -EREMOTEIO; -+ goto err_mutex_unlock; -+ } -+ -+ /* tuner locked? */ -+ if (wait_status & tune_lock_mask) -+ break; -+ usleep_range(5000, 10000); -+ } -+ } -+ -+ dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n", -+ jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time), -+ wait_status); -+ -+ if ((wait_status & 0xc0) != 0x80) { -+ ret = -ETIMEDOUT; -+ goto err_mutex_unlock; -+ } -+ -+ mutex_unlock(&dev->i2c_mutex); -+ return 0; -+ -+err_mutex_unlock: -+ mutex_unlock(&dev->i2c_mutex); -+ dev_dbg(&client->dev, "failed=%d\n", ret); -+ return ret; -+} -+ - static int si2157_set_params(struct dvb_frontend *fe) - { - struct i2c_client *client = fe->tuner_priv; -@@ -344,7 +474,7 @@ static int si2157_set_params(struct dvb_frontend *fe) - if (ret) - goto err; - -- /* set if frequency if needed */ -+ /* set digital if frequency if needed */ - if (if_frequency != dev->if_frequency) { - memcpy(cmd.args, "\x14\x00\x06\x07", 4); - cmd.args[4] = (if_frequency / 1000) & 0xff; -@@ -358,7 +488,7 @@ static int si2157_set_params(struct dvb_frontend *fe) - dev->if_frequency = if_frequency; - } - -- /* set frequency */ -+ /* set digital frequency */ - memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8); - cmd.args[4] = (c->frequency >> 0) & 0xff; - cmd.args[5] = (c->frequency >> 8) & 0xff; -@@ -370,24 +500,319 @@ static int si2157_set_params(struct dvb_frontend *fe) - if (ret) - goto err; - -+ /* wait for tuning to complete, ignore any errors */ -+ si2157_tune_wait(client, 1); -+ -+ dev->bandwidth = bandwidth; -+ dev->frequency = c->frequency; -+ -+ return 0; -+err: -+ dev->bandwidth = 0; -+ dev->frequency = 0; -+ dev->if_frequency = 0; -+ dev_dbg(&client->dev, "failed=%d\n", ret); -+ return ret; -+} -+ -+static int si2157_set_analog_params(struct dvb_frontend *fe, -+ struct analog_parameters *params) -+{ -+ struct i2c_client *client = fe->tuner_priv; -+ struct si2157_dev *dev = i2c_get_clientdata(client); -+ char *std; /* for debugging */ -+ int ret; -+ struct si2157_cmd cmd; -+ u32 bandwidth = 0; -+ u32 if_frequency = 0; -+ u32 freq = 0; -+ u64 tmp_lval = 0; -+ u8 system = 0; -+ u8 color = 0; /* 0=NTSC/PAL, 0x10=SECAM */ -+ u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */ -+ -+ if (dev->chiptype != SI2157_CHIPTYPE_SI2157) { -+ dev_info(&client->dev, "%s: Analog tuning not supported for chiptype=%u\n", -+ __func__, dev->chiptype); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ if (!dev->active) -+ si2157_init(fe); -+ -+ if (!dev->active) { -+ ret = -EAGAIN; -+ goto err; -+ } -+ if (params->mode == V4L2_TUNER_RADIO) { -+ /* -+ * std = "fm"; -+ * bandwidth = 1700000; //best can do for FM, AGC will be a mess though -+ * if_frequency = 1250000; //HVR-225x(saa7164), HVR-12xx(cx23885) -+ * if_frequency = 6600000; //HVR-9xx(cx231xx) -+ * if_frequency = 5500000; //HVR-19xx(pvrusb2) -+ */ -+ dev_dbg(&client->dev, "si2157 does not currently support FM radio\n"); -+ ret = -EINVAL; -+ goto err; -+ } -+ tmp_lval = params->frequency * 625LL; -+ do_div(tmp_lval, 10); /* convert to HZ */ -+ freq = (u32)tmp_lval; -+ -+ if (freq < 1000000) /* is freq in KHz */ -+ freq = freq * 1000; -+ dev->frequency = freq; -+ -+ if (params->std & (V4L2_STD_B|V4L2_STD_GH)) { -+ if (freq >= 470000000) { -+ std = "palGH"; -+ bandwidth = 8000000; -+ if_frequency = 6000000; /* matches tda18271C2, works w/cx23885 */ -+ system = 1; -+ if (params->std & (V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)) { -+ std = "secamGH"; -+ color = 0x10; -+ } -+ } else { -+ std = "palB"; -+ bandwidth = 7000000; -+ if_frequency = 6000000; /* matches tda18271C2, works w/cx23885 */; -+ system = 0; -+ if (params->std & V4L2_STD_SECAM_B) { -+ std = "secamB"; -+ color = 0x10; -+ } -+ } -+ } else if (params->std & V4L2_STD_MN) { -+ std = "MN"; -+ bandwidth = 6000000; -+ if_frequency = 5400000; /* matches tda18271C2, works w/cx23885 */ -+ system = 2; -+ } else if (params->std & V4L2_STD_PAL_I) { -+ std = "palI"; -+ bandwidth = 8000000; -+ if_frequency = 7250000; /* matches tda18271C2, does not work yet w/cx23885 */ -+ system = 4; -+ } else if (params->std & V4L2_STD_DK) { -+ std = "palDK"; -+ bandwidth = 8000000; -+ if_frequency = 6900000; /* matches tda18271C2, does not work yet w/cx23885 */ -+ system = 5; -+ if (params->std & V4L2_STD_SECAM_DK) { -+ std = "secamDK"; -+ color = 0x10; -+ } -+ } else if (params->std & V4L2_STD_SECAM_L) { -+ std = "secamL"; -+ bandwidth = 8000000; -+ if_frequency = 6750000; /* not tested yet w/cx23885 */ -+ system = 6; color = 0x10; -+ } else if (params->std & V4L2_STD_SECAM_LC) { -+ std = "secamL'"; -+ bandwidth = 7000000; -+ if_frequency = 1250000; /* not tested yet w/cx23885 */ -+ system = 7; color = 0x10; -+ } else { -+ std = "unknown"; -+ } -+ /* calc channel center freq */ -+ freq = freq - 1250000 + (bandwidth/2); -+ -+ dev_dbg(&client->dev, -+ "mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n", -+ params->mode, system, std, params->frequency, -+ freq, if_frequency, bandwidth); -+ -+ /* set analog IF port */ -+ memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6); -+ /* in using dev->if_port, we assume analog and digital IF's */ -+ /* are always on different ports */ -+ /* assumes if_port definition is 0 or 1 for digital out */ -+ cmd.args[4] = (dev->if_port == 1)?8:10; -+ cmd.args[5] = (dev->if_port == 1)?2:1; /* Analog AGC assumed external */ -+ cmd.wlen = 6; -+ cmd.rlen = 4; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ /* set analog IF output config */ -+ memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6); -+ cmd.wlen = 6; -+ cmd.rlen = 4; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ /* make this distinct from a digital IF */ -+ dev->if_frequency = if_frequency | 1; -+ -+ /* calc and set tuner analog if center frequency */ -+ if_frequency = if_frequency + 1250000 - (bandwidth/2); -+ dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency); -+ -+ memcpy(cmd.args, "\x14\x00\x0C\x06", 4); -+ cmd.args[4] = (if_frequency / 1000) & 0xff; -+ cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff; -+ cmd.wlen = 6; -+ cmd.rlen = 4; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ /* set analog AGC config */ -+ memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6); -+ cmd.wlen = 6; -+ cmd.rlen = 4; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ /* set analog video mode */ -+ memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6); -+ cmd.args[4] = system | color; -+#if 1 /* can use dev->inversion if assumed it applies to both digital/analog */ -+ if (invert_analog) -+ cmd.args[5] |= 0x02; -+#else -+ if (dev->inversion) -+ cmd.args[5] |= 0x02; -+#endif -+ cmd.wlen = 6; -+ cmd.rlen = 1; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ /* set analog frequency */ -+ memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8); -+ cmd.args[4] = (freq >> 0) & 0xff; -+ cmd.args[5] = (freq >> 8) & 0xff; -+ cmd.args[6] = (freq >> 16) & 0xff; -+ cmd.args[7] = (freq >> 24) & 0xff; -+ cmd.wlen = 8; -+ cmd.rlen = 1; -+ ret = si2157_cmd_execute(client, &cmd); -+ if (ret) -+ goto err; -+ -+ /* wait for tuning to complete, ignore any errors */ -+ si2157_tune_wait(client, 0); -+ -+#if 1 /* testing */ -+ /* get tuner status, RSSI values */ -+ memcpy(cmd.args, "\x42\x01", 2); -+ cmd.wlen = 2; -+ cmd.rlen = 12; -+ ret = si2157_cmd_execute(client, &cmd); -+ -+ dev_info(&client->dev, "%s: tuner status: ret=%d rssi=%d mode=%x freq=%d\n", -+ __func__, ret, cmd.args[3], cmd.args[8], -+ (cmd.args[7]<<24 | cmd.args[6]<<16 | -+ cmd.args[5]<<8 | cmd.args[4])); -+#endif -+ -+ dev->bandwidth = bandwidth; -+ - return 0; - err: -+ dev->bandwidth = 0; -+ dev->frequency = 0; -+ dev->if_frequency = 0; - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; - } - -+static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency) -+{ -+ struct i2c_client *client = fe->tuner_priv; -+ struct si2157_dev *dev = i2c_get_clientdata(client); -+ -+ *frequency = dev->frequency; -+ dev_info(&client->dev, "%s: freq=%u\n", __func__, dev->frequency); -+ return 0; -+} -+ -+static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) -+{ -+ struct i2c_client *client = fe->tuner_priv; -+ struct si2157_dev *dev = i2c_get_clientdata(client); -+ -+ *bandwidth = dev->bandwidth; -+ dev_info(&client->dev, "%s: bandwidth=%u\n", __func__, dev->bandwidth); -+ return 0; -+} -+ - static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) - { - struct i2c_client *client = fe->tuner_priv; - struct si2157_dev *dev = i2c_get_clientdata(client); - -- *frequency = dev->if_frequency; -+ *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */ -+ dev_info(&client->dev, "%s: if_frequency=%u\n", __func__, *frequency); -+ return 0; -+} -+ -+static void si2157_release(struct dvb_frontend *fe) -+{ -+ struct i2c_client *client = fe->tuner_priv; -+ struct si2157_dev *dev = NULL; -+ -+ pr_info("%s: client=%p\n", __func__, client); -+ if (client == NULL) -+ return; -+ -+ dev = i2c_get_clientdata(client); -+ pr_info("%s: dev=%p\n", __func__, dev); -+ if (dev == NULL) -+ return; -+ -+ /* only remove dev reference from final instance */ -+ if (hybrid_tuner_report_instance_count(dev) == 1) -+ i2c_set_clientdata(client, NULL); -+ -+ mutex_lock(&si2157_list_mutex); -+ hybrid_tuner_release_state(dev); -+ mutex_unlock(&si2157_list_mutex); -+ -+ fe->tuner_priv = NULL; -+} -+ -+static int si2157_setup_configuration(struct dvb_frontend *fe, -+ struct si2157_config *cfg) -+{ -+ struct i2c_client *client = fe->tuner_priv; -+ struct si2157_dev *dev = NULL; -+ -+ pr_info("%s: client=%p\n", __func__, client); -+ if (client == NULL) -+ return -1; -+ -+ dev = i2c_get_clientdata(client); -+ pr_info("%s: dev=%p\n", __func__, dev); -+ if (dev == NULL) -+ return -1; -+ -+ if (cfg) { -+ pr_info("%s(0x%02X): dvb driver submitted configuration; port=%d invert=%d\n", -+ __func__, dev->addr, -+ cfg->if_port, cfg->inversion); -+ dev->inversion = cfg->inversion; -+ dev->if_port = cfg->if_port; -+ } else { -+ pr_info("%s(0x%02X): default configuration\n", -+ __func__, dev->addr); -+ dev->inversion = true; -+ dev->if_port = 1; -+ } - return 0; - } - - static const struct dvb_tuner_ops si2157_ops = { - .info = { -- .name = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158", -+ .name = "Silicon Labs Si2141/2146/2147/2148/2157/2158", - .frequency_min = 42000000, - .frequency_max = 870000000, - }, -@@ -395,6 +820,10 @@ static const struct dvb_tuner_ops si2157_ops = { - .init = si2157_init, - .sleep = si2157_sleep, - .set_params = si2157_set_params, -+ .set_analog_params = si2157_set_analog_params, -+ .release = si2157_release, -+ .get_frequency = si2157_get_frequency, -+ .get_bandwidth = si2157_get_bandwidth, - .get_if_frequency = si2157_get_if_frequency, - }; - -@@ -417,7 +846,7 @@ static void si2157_stat_work(struct work_struct *work) - goto err; - - c->strength.stat[0].scale = FE_SCALE_DECIBEL; -- c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000; -+ c->strength.stat[0].svalue = ((s8) cmd.args[3]) * 1000; - - schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000)); - return; -@@ -431,60 +860,23 @@ static int si2157_probe(struct i2c_client *client, - { - struct si2157_config *cfg = client->dev.platform_data; - struct dvb_frontend *fe = cfg->fe; -- struct si2157_dev *dev; -- struct si2157_cmd cmd; -- int ret; -+ struct si2157_dev *dev = NULL; -+ unsigned short addr = client->addr; -+ int ret = 0; -+ -+ pr_info("%s: probing si2157 tuner fe=%p cfg=%p addr=0X%2x\n", -+ __func__, fe, cfg, addr); -+ fe->tuner_priv = client; -+ si2157_setup_configuration(fe, cfg); - -- dev = kzalloc(sizeof(*dev), GFP_KERNEL); -- if (!dev) { -- ret = -ENOMEM; -- dev_err(&client->dev, "kzalloc() failed\n"); -+ if (!dvb_attach(si2157_attach, fe, (u8)addr, client->adapter, cfg)) { -+ dev_err(&client->dev, "%s: attaching si2157 tuner failed\n", -+ __func__); - goto err; - } - -- i2c_set_clientdata(client, dev); -- dev->fe = cfg->fe; -- dev->inversion = cfg->inversion; -- dev->if_port = cfg->if_port; -+ dev = i2c_get_clientdata(client); - dev->chiptype = (u8)id->driver_data; -- dev->if_frequency = 5000000; /* default value of property 0x0706 */ -- mutex_init(&dev->i2c_mutex); -- INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work); -- -- /* check if the tuner is there */ -- cmd.wlen = 0; -- cmd.rlen = 1; -- ret = si2157_cmd_execute(client, &cmd); -- if (ret) -- goto err_kfree; -- -- memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops)); -- fe->tuner_priv = client; -- --#ifdef CONFIG_MEDIA_CONTROLLER -- if (cfg->mdev) { -- dev->mdev = cfg->mdev; -- -- dev->ent.name = KBUILD_MODNAME; -- dev->ent.function = MEDIA_ENT_F_TUNER; -- -- dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; -- dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; -- dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; -- -- ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS, -- &dev->pad[0]); -- -- if (ret) -- goto err_kfree; -- -- ret = media_device_register_entity(cfg->mdev, &dev->ent); -- if (ret) { -- media_entity_cleanup(&dev->ent); -- goto err_kfree; -- } -- } --#endif - - dev_info(&client->dev, "Silicon Labs %s successfully attached\n", - dev->chiptype == SI2157_CHIPTYPE_SI2141 ? "Si2141" : -@@ -493,8 +885,6 @@ static int si2157_probe(struct i2c_client *client, - - return 0; - --err_kfree: -- kfree(dev); - err: - dev_dbg(&client->dev, "failed=%d\n", ret); - return ret; -@@ -503,7 +893,13 @@ err: - static int si2157_remove(struct i2c_client *client) - { - struct si2157_dev *dev = i2c_get_clientdata(client); -- struct dvb_frontend *fe = dev->fe; -+ struct dvb_frontend *fe = NULL; -+ -+ if (dev == NULL) { -+ pr_info("dev is NULL\n"); -+ return 0; -+ } -+ fe = dev->fe; - - dev_dbg(&client->dev, "\n"); - -@@ -516,8 +912,7 @@ static int si2157_remove(struct i2c_client *client) - #endif - - memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); -- fe->tuner_priv = NULL; -- kfree(dev); -+ si2157_release(fe); - - return 0; - } -@@ -542,7 +937,129 @@ static struct i2c_driver si2157_driver = { - - module_i2c_driver(si2157_driver); - --MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver"); -+struct dvb_frontend *si2157_attach(struct dvb_frontend *fe, u8 addr, -+ struct i2c_adapter *i2c, -+ struct si2157_config *cfg) -+{ -+ struct i2c_client *client = NULL; -+ struct si2157_dev *dev = NULL; -+ struct si2157_cmd cmd; -+ int instance = 0, ret; -+ -+ pr_info("%s (%d-%04x)\n", __func__, -+ i2c ? i2c_adapter_id(i2c) : 0, -+ addr); -+ -+ mutex_lock(&si2157_list_mutex); -+ -+ if (!cfg) { -+ pr_info("no configuration submitted\n"); -+ goto fail; -+ } -+ -+ if (!fe) { -+ pr_info("fe is NULL\n"); -+ goto fail; -+ } -+ -+ client = fe->tuner_priv; -+ if (!client) { -+ pr_info("client is NULL\n"); -+ goto fail; -+ } -+ -+ instance = hybrid_tuner_request_state(struct si2157_dev, dev, -+ hybrid_tuner_instance_list, -+ i2c, addr, "si2157"); -+ -+ pr_info("%s: instance=%d\n", __func__, instance); -+ switch (instance) { -+ case 0: -+ goto fail; -+ case 1: -+ /* new tuner instance */ -+ pr_info("%s(): new instance for tuner @0x%02x\n", -+ __func__, addr); -+ dev->addr = addr; -+ i2c_set_clientdata(client, dev); -+ -+ si2157_setup_configuration(fe, cfg); -+ -+ dev->fe = fe; -+ /* BUGBUG - should chiptype come from config? */ -+ dev->chiptype = (u8)SI2157_CHIPTYPE_SI2157; -+ dev->if_frequency = 0; -+ -+ mutex_init(&dev->i2c_mutex); -+ INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work); -+ -+ break; -+ default: -+ /* existing tuner instance */ -+ pr_info("%s(): using existing instance for tuner @0x%02x\n", -+ __func__, addr); -+ -+ /* allow dvb driver to override configuration settings */ -+ if (cfg) -+ si2157_setup_configuration(fe, cfg); -+ -+ break; -+ } -+ -+ /* check if the tuner is there */ -+ cmd.wlen = 0; -+ cmd.rlen = 1; -+ ret = si2157_cmd_execute(client, &cmd); -+ /* verify no i2c error and CTS is set */ -+ if (ret && (ret != -EAGAIN)) { -+ pr_info("no HW found ret=%d\n", ret); -+ goto fail; -+ } -+ -+ memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops)); -+ -+#ifdef CONFIG_MEDIA_CONTROLLER -+ if (instance == 1 && cfg->mdev) { -+ pr_info("cfg->mdev=%p\n", cfg->mdev); -+ dev->mdev = cfg->mdev; -+ -+ dev->ent.name = KBUILD_MODNAME; -+ dev->ent.function = MEDIA_ENT_F_TUNER; -+ -+ dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; -+ dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; -+ dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; -+ -+ ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS, -+ &dev->pad[0]); -+ -+ if (ret) -+ goto fail; -+ -+ ret = media_device_register_entity(cfg->mdev, &dev->ent); -+ if (ret) { -+ pr_info("media_device_regiser_entity returns %d\n", ret); -+ media_entity_cleanup(&dev->ent); -+ goto fail; -+ } -+ } -+#endif -+ -+ mutex_unlock(&si2157_list_mutex); -+ -+ return fe; -+ -+fail: -+ pr_info("%s: Failed\n", __func__); -+ mutex_unlock(&si2157_list_mutex); -+ -+ if (fe && (instance == 1)) -+ si2157_release(fe); -+ return NULL; -+} -+EXPORT_SYMBOL(si2157_attach); -+ -+MODULE_DESCRIPTION("Silicon Labs Si2141/2146/2147/2148/2157/2158 silicon tuner driver"); - MODULE_AUTHOR("Antti Palosaari "); - MODULE_LICENSE("GPL"); - MODULE_FIRMWARE(SI2158_A20_FIRMWARE); -diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h -index 76807f5..fd008cc 100644 ---- a/drivers/media/tuners/si2157.h -+++ b/drivers/media/tuners/si2157.h -@@ -46,4 +46,18 @@ struct si2157_config { - u8 if_port; - }; - -+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_SI2157) -+extern struct dvb_frontend *si2157_attach(struct dvb_frontend *fe, u8 addr, -+ struct i2c_adapter *i2c, -+ struct si2157_config *cfg); -+#else -+static inline struct dvb_frontend *si2157_attach(struct dvb_frontend *fe, -+ u8 addr, -+ struct i2c_adapter *i2c, -+ struct si2157_config *cfg) -+{ -+ pr_err("%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif - #endif -diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h -index e6436f7..b51259b 100644 ---- a/drivers/media/tuners/si2157_priv.h -+++ b/drivers/media/tuners/si2157_priv.h -@@ -19,17 +19,24 @@ - - #include - #include -+#include "tuner-i2c.h" - #include "si2157.h" - - /* state struct */ - struct si2157_dev { -+ struct list_head hybrid_tuner_instance_list; -+ struct tuner_i2c_props i2c_props; -+ - struct mutex i2c_mutex; - struct dvb_frontend *fe; - bool active; - bool inversion; - u8 chiptype; -+ u8 addr; - u8 if_port; - u32 if_frequency; -+ u32 bandwidth; -+ u32 frequency; - struct delayed_work stat_work; - - #if defined(CONFIG_MEDIA_CONTROLLER) -diff --git a/drivers/media/tuners/tuner-types.c b/drivers/media/tuners/tuner-types.c -index 98bc15a..e022ab8 100644 ---- a/drivers/media/tuners/tuner-types.c -+++ b/drivers/media/tuners/tuner-types.c -@@ -1433,6 +1433,16 @@ static struct tuner_params tuner_sony_btf_pg463z_params[] = { - }, - }; - -+/* ------------ TUNER_SILABS_SI2157 NTSC/PAL/Digital ------------ */ -+ -+static struct tuner_params tuner_silabs_si2157_params[] = { -+ { -+ .type = TUNER_PARAM_TYPE_DIGITAL, -+ .ranges = tuner_fm1236_mk3_ntsc_ranges, -+ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), -+ }, -+}; -+ - /* --------------------------------------------------------------------- */ - - struct tunertype tuners[] = { -@@ -1941,6 +1951,11 @@ struct tunertype tuners[] = { - .params = tuner_sony_btf_pg463z_params, - .count = ARRAY_SIZE(tuner_sony_btf_pg463z_params), - }, -+ [TUNER_SILABS_SI2157] = { -+ .name = "Silicon Labs Si2157 terrestrial/cable multistandard", -+ .params = tuner_silabs_si2157_params, -+ .count = ARRAY_SIZE(tuner_silabs_si2157_params), -+ }, - }; - EXPORT_SYMBOL(tuners); - -diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c -index 99c8b1a..e85ec3c 100644 ---- a/drivers/media/usb/cx231xx/cx231xx-cards.c -+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c -@@ -922,6 +922,84 @@ struct cx231xx_board cx231xx_boards[] = { - .gpio = NULL, - } }, - }, -+ [CX231XX_BOARD_HAUPPAUGE_935C] = { -+ .name = "Hauppauge WinTV-HVR-935C", -+ .tuner_type = TUNER_ABSENT, -+ .tuner_addr = 0x60, -+ .tuner_gpio = RDE250_XCV_TUNER, -+ .tuner_sif_gpio = 0x05, -+ .tuner_scl_gpio = 0x1a, -+ .tuner_sda_gpio = 0x1b, -+ .decoder = CX231XX_AVDECODER, -+ .output_mode = OUT_MODE_VIP11, -+ .demod_xfer_mode = 0, -+ .ctl_pin_status_mask = 0xFFFFFFC4, -+ .agc_analog_digital_select_gpio = 0x0c, -+ .gpio_pin_status_mask = 0x4001000, -+ .tuner_i2c_master = I2C_1_MUX_3, -+ .demod_i2c_master = I2C_1_MUX_3, -+ .has_dvb = 1, -+ .demod_addr = 0x64, /* 0xc8 >> 1 */ -+ .norm = V4L2_STD_PAL, -+ -+ .input = {{ -+ .type = CX231XX_VMUX_TELEVISION, -+ .vmux = CX231XX_VIN_3_1, -+ .amux = CX231XX_AMUX_VIDEO, -+ .gpio = NULL, -+ }, { -+ .type = CX231XX_VMUX_COMPOSITE1, -+ .vmux = CX231XX_VIN_2_1, -+ .amux = CX231XX_AMUX_LINE_IN, -+ .gpio = NULL, -+ }, { -+ .type = CX231XX_VMUX_SVIDEO, -+ .vmux = CX231XX_VIN_1_1 | -+ (CX231XX_VIN_1_2 << 8) | -+ CX25840_SVIDEO_ON, -+ .amux = CX231XX_AMUX_LINE_IN, -+ .gpio = NULL, -+ } }, -+ }, -+ [CX231XX_BOARD_HAUPPAUGE_975] = { -+ .name = "Hauppauge WinTV-HVR-975", -+ .tuner_type = TUNER_ABSENT, -+ .tuner_addr = 0x60, -+ .tuner_gpio = RDE250_XCV_TUNER, -+ .tuner_sif_gpio = 0x05, -+ .tuner_scl_gpio = 0x1a, -+ .tuner_sda_gpio = 0x1b, -+ .decoder = CX231XX_AVDECODER, -+ .output_mode = OUT_MODE_VIP11, -+ .demod_xfer_mode = 0, -+ .ctl_pin_status_mask = 0xFFFFFFC4, -+ .agc_analog_digital_select_gpio = 0x0c, -+ .gpio_pin_status_mask = 0x4001000, -+ .tuner_i2c_master = I2C_1_MUX_3, -+ .demod_i2c_master = I2C_1_MUX_3, -+ .has_dvb = 1, -+ .demod_addr = 0x64, /* 0xc8 >> 1 */ -+ .norm = V4L2_STD_ALL, -+ -+ .input = {{ -+ .type = CX231XX_VMUX_TELEVISION, -+ .vmux = CX231XX_VIN_3_1, -+ .amux = CX231XX_AMUX_VIDEO, -+ .gpio = NULL, -+ }, { -+ .type = CX231XX_VMUX_COMPOSITE1, -+ .vmux = CX231XX_VIN_2_1, -+ .amux = CX231XX_AMUX_LINE_IN, -+ .gpio = NULL, -+ }, { -+ .type = CX231XX_VMUX_SVIDEO, -+ .vmux = CX231XX_VIN_1_1 | -+ (CX231XX_VIN_1_2 << 8) | -+ CX25840_SVIDEO_ON, -+ .amux = CX231XX_AMUX_LINE_IN, -+ .gpio = NULL, -+ } }, -+ }, - }; - const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); - -@@ -953,6 +1031,10 @@ struct usb_device_id cx231xx_id_table[] = { - .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, - {USB_DEVICE(0x2040, 0xb123), - .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q}, -+ {USB_DEVICE(0x2040, 0xb151), -+ .driver_info = CX231XX_BOARD_HAUPPAUGE_935C}, -+ {USB_DEVICE(0x2040, 0xb150), -+ .driver_info = CX231XX_BOARD_HAUPPAUGE_975}, - {USB_DEVICE(0x2040, 0xb130), - .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx}, - {USB_DEVICE(0x2040, 0xb131), -diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c -index fb56540..20af416 100644 ---- a/drivers/media/usb/cx231xx/cx231xx-dvb.c -+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c -@@ -55,7 +55,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - #define CX231XX_DVB_MAX_PACKETS 64 - - struct cx231xx_dvb { -- struct dvb_frontend *frontend; -+ struct dvb_frontend *frontend[2]; - - /* feed count management */ - struct mutex lock; -@@ -386,17 +386,17 @@ static int attach_xc5000(u8 addr, struct cx231xx *dev) - cfg.i2c_adap = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master); - cfg.i2c_addr = addr; - -- if (!dev->dvb->frontend) { -+ if (!dev->dvb->frontend[0]) { - dev_err(dev->dev, "%s/2: dvb frontend not attached. Can't attach xc5000\n", - dev->name); - return -EINVAL; - } - -- fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg); -+ fe = dvb_attach(xc5000_attach, dev->dvb->frontend[0], &cfg); - if (!fe) { - dev_err(dev->dev, "%s/2: xc5000 attach failed\n", dev->name); -- dvb_frontend_detach(dev->dvb->frontend); -- dev->dvb->frontend = NULL; -+ dvb_frontend_detach(dev->dvb->frontend[0]); -+ dev->dvb->frontend[0] = NULL; - return -EINVAL; - } - -@@ -408,9 +408,9 @@ static int attach_xc5000(u8 addr, struct cx231xx *dev) - - int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq) - { -- if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { -+ if ((dev->dvb != NULL) && (dev->dvb->frontend[0] != NULL)) { - -- struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; -+ struct dvb_tuner_ops *dops = &dev->dvb->frontend[0]->ops.tuner_ops; - - if (dops->set_analog_params != NULL) { - struct analog_parameters params; -@@ -421,7 +421,7 @@ int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq) - /*params.audmode = ; */ - - /* Set the analog parameters to set the frequency */ -- dops->set_analog_params(dev->dvb->frontend, ¶ms); -+ dops->set_analog_params(dev->dvb->frontend[0], ¶ms); - } - - } -@@ -433,15 +433,15 @@ int cx231xx_reset_analog_tuner(struct cx231xx *dev) - { - int status = 0; - -- if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { -+ if ((dev->dvb != NULL) && (dev->dvb->frontend[0] != NULL)) { - -- struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; -+ struct dvb_tuner_ops *dops = &dev->dvb->frontend[0]->ops.tuner_ops; - - if (dops->init != NULL && !dev->xc_fw_load_done) { - - dev_dbg(dev->dev, - "Reloading firmware for XC5000\n"); -- status = dops->init(dev->dvb->frontend); -+ status = dops->init(dev->dvb->frontend[0]); - if (status == 0) { - dev->xc_fw_load_done = 1; - dev_dbg(dev->dev, -@@ -481,19 +481,32 @@ static int register_dvb(struct cx231xx_dvb *dvb, - dvb_register_media_controller(&dvb->adapter, dev->media_dev); - - /* Ensure all frontends negotiate bus access */ -- dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; -+ dvb->frontend[0]->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; -+ if (dvb->frontend[1]) -+ dvb->frontend[1]->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; - - dvb->adapter.priv = dev; - - /* register frontend */ -- result = dvb_register_frontend(&dvb->adapter, dvb->frontend); -+ result = dvb_register_frontend(&dvb->adapter, dvb->frontend[0]); - if (result < 0) { - dev_warn(dev->dev, - "%s: dvb_register_frontend failed (errno = %d)\n", - dev->name, result); -- goto fail_frontend; -+ goto fail_frontend0; - } - -+ if (dvb->frontend[1]) { -+ result = dvb_register_frontend(&dvb->adapter, dvb->frontend[1]); -+ if (result < 0) { -+ dev_warn(dev->dev, -+ "%s: 2nd dvb_register_frontend failed (errno = %d)\n", -+ dev->name, result); -+ goto fail_frontend1; -+ } -+ } -+ -+ - /* register demux stuff */ - dvb->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | -@@ -569,9 +582,14 @@ fail_fe_hw: - fail_dmxdev: - dvb_dmx_release(&dvb->demux); - fail_dmx: -- dvb_unregister_frontend(dvb->frontend); --fail_frontend: -- dvb_frontend_detach(dvb->frontend); -+ if (dvb->frontend[1]) -+ dvb_unregister_frontend(dvb->frontend[1]); -+ dvb_unregister_frontend(dvb->frontend[0]); -+fail_frontend1: -+ if (dvb->frontend[1]) -+ dvb_frontend_detach(dvb->frontend[1]); -+fail_frontend0: -+ dvb_frontend_detach(dvb->frontend[0]); - dvb_unregister_adapter(&dvb->adapter); - fail_adapter: - return result; -@@ -585,8 +603,12 @@ static void unregister_dvb(struct cx231xx_dvb *dvb) - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); -- dvb_unregister_frontend(dvb->frontend); -- dvb_frontend_detach(dvb->frontend); -+ if (dvb->frontend[1]) -+ dvb_unregister_frontend(dvb->frontend[1]); -+ dvb_unregister_frontend(dvb->frontend[0]); -+ if (dvb->frontend[1]) -+ dvb_frontend_detach(dvb->frontend[1]); -+ dvb_frontend_detach(dvb->frontend[0]); - dvb_unregister_adapter(&dvb->adapter); - /* remove I2C tuner */ - client = dvb->i2c_client_tuner; -@@ -635,11 +657,11 @@ static int dvb_init(struct cx231xx *dev) - case CX231XX_BOARD_CNXT_CARRAERA: - case CX231XX_BOARD_CNXT_RDE_250: - -- dev->dvb->frontend = dvb_attach(s5h1432_attach, -+ dev->dvb->frontend[0] = dvb_attach(s5h1432_attach, - &dvico_s5h1432_config, - demod_i2c); - -- if (dev->dvb->frontend == NULL) { -+ if (dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach s5h1432 front end\n"); - result = -EINVAL; -@@ -647,9 +669,9 @@ static int dvb_init(struct cx231xx *dev) - } - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - -- if (!dvb_attach(xc5000_attach, dev->dvb->frontend, -+ if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0], - tuner_i2c, - &cnxt_rde250_tunerconfig)) { - result = -EINVAL; -@@ -660,11 +682,11 @@ static int dvb_init(struct cx231xx *dev) - case CX231XX_BOARD_CNXT_SHELBY: - case CX231XX_BOARD_CNXT_RDU_250: - -- dev->dvb->frontend = dvb_attach(s5h1411_attach, -+ dev->dvb->frontend[0] = dvb_attach(s5h1411_attach, - &xc5000_s5h1411_config, - demod_i2c); - -- if (dev->dvb->frontend == NULL) { -+ if (dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach s5h1411 front end\n"); - result = -EINVAL; -@@ -672,9 +694,9 @@ static int dvb_init(struct cx231xx *dev) - } - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - -- if (!dvb_attach(xc5000_attach, dev->dvb->frontend, -+ if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0], - tuner_i2c, - &cnxt_rdu250_tunerconfig)) { - result = -EINVAL; -@@ -683,11 +705,11 @@ static int dvb_init(struct cx231xx *dev) - break; - case CX231XX_BOARD_CNXT_RDE_253S: - -- dev->dvb->frontend = dvb_attach(s5h1432_attach, -+ dev->dvb->frontend[0] = dvb_attach(s5h1432_attach, - &dvico_s5h1432_config, - demod_i2c); - -- if (dev->dvb->frontend == NULL) { -+ if (dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach s5h1432 front end\n"); - result = -EINVAL; -@@ -695,9 +717,9 @@ static int dvb_init(struct cx231xx *dev) - } - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - -- if (!dvb_attach(tda18271_attach, dev->dvb->frontend, -+ if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, - &cnxt_rde253s_tunerconfig)) { - result = -EINVAL; -@@ -707,11 +729,11 @@ static int dvb_init(struct cx231xx *dev) - case CX231XX_BOARD_CNXT_RDU_253S: - case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID: - -- dev->dvb->frontend = dvb_attach(s5h1411_attach, -+ dev->dvb->frontend[0] = dvb_attach(s5h1411_attach, - &tda18271_s5h1411_config, - demod_i2c); - -- if (dev->dvb->frontend == NULL) { -+ if (dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach s5h1411 front end\n"); - result = -EINVAL; -@@ -719,9 +741,9 @@ static int dvb_init(struct cx231xx *dev) - } - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - -- if (!dvb_attach(tda18271_attach, dev->dvb->frontend, -+ if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, - &cnxt_rde253s_tunerconfig)) { - result = -EINVAL; -@@ -734,11 +756,11 @@ static int dvb_init(struct cx231xx *dev) - "%s: looking for tuner / demod on i2c bus: %d\n", - __func__, i2c_adapter_id(tuner_i2c)); - -- dev->dvb->frontend = dvb_attach(lgdt3305_attach, -+ dev->dvb->frontend[0] = dvb_attach(lgdt3305_attach, - &hcw_lgdt3305_config, - demod_i2c); - -- if (dev->dvb->frontend == NULL) { -+ if (dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach LG3305 front end\n"); - result = -EINVAL; -@@ -746,9 +768,9 @@ static int dvb_init(struct cx231xx *dev) - } - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - -- dvb_attach(tda18271_attach, dev->dvb->frontend, -+ dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, - &hcw_tda18271_config); - break; -@@ -761,7 +783,7 @@ static int dvb_init(struct cx231xx *dev) - - /* attach demod */ - memset(&si2165_pdata, 0, sizeof(si2165_pdata)); -- si2165_pdata.fe = &dev->dvb->frontend; -+ si2165_pdata.fe = &dev->dvb->frontend[0]; - si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL; - si2165_pdata.ref_freq_hz = 16000000; - -@@ -771,7 +793,7 @@ static int dvb_init(struct cx231xx *dev) - info.platform_data = &si2165_pdata; - request_module(info.type); - client = i2c_new_device(demod_i2c, &info); -- if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) { -+ if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach SI2165 front end\n"); - result = -EINVAL; -@@ -786,12 +808,12 @@ static int dvb_init(struct cx231xx *dev) - - dvb->i2c_client_demod = client; - -- dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; -+ dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - -- dvb_attach(tda18271_attach, dev->dvb->frontend, -+ dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, - tuner_i2c, - &hcw_tda18271_config); -@@ -808,7 +830,7 @@ static int dvb_init(struct cx231xx *dev) - - /* attach demod */ - memset(&si2165_pdata, 0, sizeof(si2165_pdata)); -- si2165_pdata.fe = &dev->dvb->frontend; -+ si2165_pdata.fe = &dev->dvb->frontend[0]; - si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT; - si2165_pdata.ref_freq_hz = 24000000; - -@@ -818,7 +840,7 @@ static int dvb_init(struct cx231xx *dev) - info.platform_data = &si2165_pdata; - request_module(info.type); - client = i2c_new_device(demod_i2c, &info); -- if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) { -+ if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach SI2165 front end\n"); - result = -EINVAL; -@@ -835,14 +857,14 @@ static int dvb_init(struct cx231xx *dev) - - memset(&info, 0, sizeof(struct i2c_board_info)); - -- dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; -+ dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - - /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); -- si2157_config.fe = dev->dvb->frontend; -+ si2157_config.fe = dev->dvb->frontend[0]; - #ifdef CONFIG_MEDIA_CONTROLLER_DVB - si2157_config.mdev = dev->media_dev; - #endif -@@ -857,14 +879,14 @@ static int dvb_init(struct cx231xx *dev) - tuner_i2c, - &info); - if (client == NULL || client->dev.driver == NULL) { -- dvb_frontend_detach(dev->dvb->frontend); -+ dvb_frontend_detach(dev->dvb->frontend[0]); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); -- dvb_frontend_detach(dev->dvb->frontend); -+ dvb_frontend_detach(dev->dvb->frontend[0]); - result = -ENODEV; - goto out_free; - } -@@ -882,26 +904,26 @@ static int dvb_init(struct cx231xx *dev) - - memset(&info, 0, sizeof(struct i2c_board_info)); - -- dev->dvb->frontend = dvb_attach(lgdt3306a_attach, -+ dev->dvb->frontend[0] = dvb_attach(lgdt3306a_attach, - &hauppauge_955q_lgdt3306a_config, - demod_i2c - ); - -- if (dev->dvb->frontend == NULL) { -+ if (dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach LGDT3306A frontend.\n"); - result = -EINVAL; - goto out_free; - } - -- dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; -+ dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - - /* attach tuner */ - memset(&si2157_config, 0, sizeof(si2157_config)); -- si2157_config.fe = dev->dvb->frontend; -+ si2157_config.fe = dev->dvb->frontend[0]; - #ifdef CONFIG_MEDIA_CONTROLLER_DVB - si2157_config.mdev = dev->media_dev; - #endif -@@ -916,14 +938,14 @@ static int dvb_init(struct cx231xx *dev) - tuner_i2c, - &info); - if (client == NULL || client->dev.driver == NULL) { -- dvb_frontend_detach(dev->dvb->frontend); -+ dvb_frontend_detach(dev->dvb->frontend[0]); - result = -ENODEV; - goto out_free; - } - - if (!try_module_get(client->dev.driver->owner)) { - i2c_unregister_device(client); -- dvb_frontend_detach(dev->dvb->frontend); -+ dvb_frontend_detach(dev->dvb->frontend[0]); - result = -ENODEV; - goto out_free; - } -@@ -933,6 +955,182 @@ static int dvb_init(struct cx231xx *dev) - dev->dvb->i2c_client_tuner = client; - break; - } -+ case CX231XX_BOARD_HAUPPAUGE_935C: -+ { -+ struct i2c_client *client; -+ struct i2c_board_info info; -+ struct si2157_config si2157_config = {}; -+ struct si2168_config si2168_config = {}; -+ struct i2c_adapter *adapter; -+ -+ memset(&info, 0, sizeof(struct i2c_board_info)); -+ -+ /* attach demodulator chip */ -+ memset(&si2168_config, 0, sizeof(si2168_config)); -+ si2168_config.ts_mode = SI2168_TS_SERIAL; -+ si2168_config.fe = &dev->dvb->frontend[0]; -+ si2168_config.i2c_adapter = &adapter; -+ si2168_config.ts_clock_inv = true; -+ -+ strlcpy(info.type, "si2168", sizeof(info.type)); -+ info.addr = dev->board.demod_addr; -+ info.platform_data = &si2168_config; -+ -+ request_module(info.type); -+ client = i2c_new_device(demod_i2c, &info); -+ -+ if (client == NULL || client->dev.driver == NULL) { -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ if (!try_module_get(client->dev.driver->owner)) { -+ i2c_unregister_device(client); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ dvb->i2c_client_demod = client; -+ dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; -+ -+ /* define general-purpose callback pointer */ -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; -+ -+ /* attach tuner */ -+ memset(&si2157_config, 0, sizeof(si2157_config)); -+ si2157_config.fe = dev->dvb->frontend[0]; -+#ifdef CONFIG_MEDIA_CONTROLLER_DVB -+ si2157_config.mdev = dev->media_dev; -+#endif -+ si2157_config.if_port = 1; -+ si2157_config.inversion = true; -+ strlcpy(info.type, "si2157", I2C_NAME_SIZE); -+ info.addr = 0x60; -+ info.platform_data = &si2157_config; -+ request_module("si2157"); -+ -+ client = i2c_new_device(tuner_i2c, &info); -+ if (client == NULL || client->dev.driver == NULL) { -+ module_put(dvb->i2c_client_demod->dev.driver->owner); -+ i2c_unregister_device(dvb->i2c_client_demod); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ if (!try_module_get(client->dev.driver->owner)) { -+ i2c_unregister_device(client); -+ module_put(dvb->i2c_client_demod->dev.driver->owner); -+ i2c_unregister_device(dvb->i2c_client_demod); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ dev->cx231xx_reset_analog_tuner = NULL; -+ dev->dvb->i2c_client_tuner = client; -+ break; -+ } -+ case CX231XX_BOARD_HAUPPAUGE_975: -+ { -+ struct i2c_client *client; -+ struct i2c_board_info info; -+ struct si2157_config si2157_config = {}; -+ struct si2168_config si2168_config = {}; -+ struct i2c_adapter *adapter; -+ -+ memset(&info, 0, sizeof(struct i2c_board_info)); -+ -+ /* attach demodulator chip */ -+ dev->dvb->frontend[0] = dvb_attach(lgdt3306a_attach, -+ &hauppauge_955q_lgdt3306a_config, -+ demod_i2c -+ ); -+ -+ if (dev->dvb->frontend[0] == NULL) { -+ dev_err(dev->dev, -+ "Failed to attach LGDT3306A frontend.\n"); -+ result = -EINVAL; -+ goto out_free; -+ } -+ -+ /* attach demodulator chip */ -+ memset(&si2168_config, 0, sizeof(si2168_config)); -+ si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */ -+ si2168_config.fe = &dev->dvb->frontend[1]; -+ si2168_config.i2c_adapter = &adapter; -+ si2168_config.ts_clock_inv = true; -+ -+ strlcpy(info.type, "si2168", sizeof(info.type)); -+ info.addr = dev->board.demod_addr; -+ info.platform_data = &si2168_config; -+ -+ request_module(info.type); -+ client = i2c_new_device(demod_i2c, &info); -+ if (client == NULL || client->dev.driver == NULL) { -+ dvb_frontend_detach(dev->dvb->frontend[0]); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ if (!try_module_get(client->dev.driver->owner)) { -+ dvb_frontend_detach(dev->dvb->frontend[0]); -+ i2c_unregister_device(client); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ dvb->i2c_client_demod = client; -+ dev->dvb->frontend[1]->id = 1; -+ -+ /* TODO: INSPECT THIS! Required for multiple frontends? */ -+ dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; -+ dev->dvb->frontend[1]->ops.i2c_gate_ctrl = NULL; -+ -+ /* define general-purpose callback pointer */ -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; -+ dvb->frontend[1]->callback = cx231xx_tuner_callback; -+ -+ /* attach tuner */ -+ memset(&si2157_config, 0, sizeof(si2157_config)); -+ si2157_config.fe = dev->dvb->frontend[0]; -+#ifdef CONFIG_MEDIA_CONTROLLER_DVB -+ si2157_config.mdev = dev->media_dev; -+#endif -+ si2157_config.if_port = 1; -+ si2157_config.inversion = true; -+ strlcpy(info.type, "si2157", I2C_NAME_SIZE); -+ info.addr = 0x60; -+ info.platform_data = &si2157_config; -+ request_module("si2157"); -+ -+ client = i2c_new_device(tuner_i2c, &info); -+ if (client == NULL || client->dev.driver == NULL) { -+ module_put(dvb->i2c_client_demod->dev.driver->owner); -+ i2c_unregister_device(dvb->i2c_client_demod); -+ dvb_frontend_detach(dev->dvb->frontend[0]); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ if (!try_module_get(client->dev.driver->owner)) { -+ i2c_unregister_device(client); -+ module_put(dvb->i2c_client_demod->dev.driver->owner); -+ i2c_unregister_device(dvb->i2c_client_demod); -+ dvb_frontend_detach(dev->dvb->frontend[0]); -+ result = -ENODEV; -+ goto out_free; -+ } -+ -+ dev->dvb->frontend[1]->tuner_priv = -+ dev->dvb->frontend[0]->tuner_priv; -+ -+ dvb_attach(si2157_attach, dev->dvb->frontend[1], info.addr, -+ client->adapter, &si2157_config); -+ -+ dev->cx231xx_reset_analog_tuner = NULL; -+ -+ dev->dvb->i2c_client_tuner = client; -+ break; -+ } - case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: - case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: - -@@ -940,11 +1138,11 @@ static int dvb_init(struct cx231xx *dev) - "%s: looking for demod on i2c bus: %d\n", - __func__, i2c_adapter_id(tuner_i2c)); - -- dev->dvb->frontend = dvb_attach(mb86a20s_attach, -+ dev->dvb->frontend[0] = dvb_attach(mb86a20s_attach, - &pv_mb86a20s_config, - demod_i2c); - -- if (dev->dvb->frontend == NULL) { -+ if (dev->dvb->frontend[0] == NULL) { - dev_err(dev->dev, - "Failed to attach mb86a20s demod\n"); - result = -EINVAL; -@@ -952,9 +1150,9 @@ static int dvb_init(struct cx231xx *dev) - } - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - -- dvb_attach(tda18271_attach, dev->dvb->frontend, -+ dvb_attach(tda18271_attach, dev->dvb->frontend[0], - 0x60, tuner_i2c, - &pv_tda18271_config); - break; -@@ -969,7 +1167,7 @@ static int dvb_init(struct cx231xx *dev) - - /* attach demodulator chip */ - si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */ -- si2168_config.fe = &dev->dvb->frontend; -+ si2168_config.fe = &dev->dvb->frontend[0]; - si2168_config.i2c_adapter = &adapter; - si2168_config.ts_clock_inv = true; - -@@ -994,7 +1192,7 @@ static int dvb_init(struct cx231xx *dev) - dvb->i2c_client_demod = client; - - /* attach tuner chip */ -- si2157_config.fe = dev->dvb->frontend; -+ si2157_config.fe = dev->dvb->frontend[0]; - #ifdef CONFIG_MEDIA_CONTROLLER_DVB - si2157_config.mdev = dev->media_dev; - #endif -@@ -1037,7 +1235,7 @@ static int dvb_init(struct cx231xx *dev) - /* attach demodulator chip */ - mn88473_config.i2c_wr_max = 16; - mn88473_config.xtal = 25000000; -- mn88473_config.fe = &dev->dvb->frontend; -+ mn88473_config.fe = &dev->dvb->frontend[0]; - - strlcpy(info.type, "mn88473", sizeof(info.type)); - info.addr = dev->board.demod_addr; -@@ -1060,10 +1258,10 @@ static int dvb_init(struct cx231xx *dev) - dvb->i2c_client_demod = client; - - /* define general-purpose callback pointer */ -- dvb->frontend->callback = cx231xx_tuner_callback; -+ dvb->frontend[0]->callback = cx231xx_tuner_callback; - - /* attach tuner chip */ -- dvb_attach(r820t_attach, dev->dvb->frontend, -+ dvb_attach(r820t_attach, dev->dvb->frontend[0], - tuner_i2c, - &astrometa_t2hybrid_r820t_config); - break; -@@ -1074,7 +1272,7 @@ static int dvb_init(struct cx231xx *dev) - dev->name); - break; - } -- if (NULL == dvb->frontend) { -+ if (NULL == dvb->frontend[0]) { - dev_err(dev->dev, - "%s/2: frontend initialization failed\n", dev->name); - result = -EINVAL; -diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h -index 65b039c..fa993f7 100644 ---- a/drivers/media/usb/cx231xx/cx231xx.h -+++ b/drivers/media/usb/cx231xx/cx231xx.h -@@ -81,6 +81,8 @@ - #define CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD 23 - #define CX231XX_BOARD_ASTROMETA_T2HYBRID 24 - #define CX231XX_BOARD_THE_IMAGING_SOURCE_DFG_USB2_PRO 25 -+#define CX231XX_BOARD_HAUPPAUGE_935C 26 -+#define CX231XX_BOARD_HAUPPAUGE_975 27 - - /* Limits minimum and default number of buffers */ - #define CX231XX_MIN_BUF 4 -diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c -index 4c57fd7..82c7f8a 100644 ---- a/drivers/media/usb/em28xx/em28xx-cards.c -+++ b/drivers/media/usb/em28xx/em28xx-cards.c -@@ -508,8 +508,10 @@ static struct em28xx_reg_seq plex_px_bcud[] = { - }; - - /* -- * 2040:0265 Hauppauge WinTV-dualHD DVB -- * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM -+ * 2040:0265 Hauppauge WinTV-dualHD DVB Isoc -+ * 2040:8265 Hauppauge WinTV-dualHD DVB Bulk -+ * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM Isoc -+ * 2040:826d Hauppauge WinTV-dualHD ATSC/QAM Bulk - * reg 0x80/0x84: - * GPIO_0: Yellow LED tuner 1, 0=on, 1=off - * GPIO_1: Green LED tuner 1, 0=on, 1=off -@@ -2392,7 +2394,8 @@ struct em28xx_board em28xx_boards[] = { - .has_dvb = 1, - }, - /* -- * 2040:0265 Hauppauge WinTV-dualHD (DVB version). -+ * 2040:0265 Hauppauge WinTV-dualHD (DVB version) Isoc. -+ * 2040:8265 Hauppauge WinTV-dualHD (DVB version) Bulk. - * Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157 - */ - [EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = { -@@ -2403,11 +2406,13 @@ struct em28xx_board em28xx_boards[] = { - .tuner_type = TUNER_ABSENT, - .tuner_gpio = hauppauge_dualhd_dvb, - .has_dvb = 1, -+ .has_dual_ts = 1, - .ir_codes = RC_MAP_HAUPPAUGE, - .leds = hauppauge_dualhd_leds, - }, - /* -- * 2040:026d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM). -+ * 2040:026d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM) Isoc. -+ * 2040:826d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM) Bulk. - * Empia EM28274, 2x LG LGDT3306A, 2x Silicon Labs Si2157 - */ - [EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595] = { -@@ -2418,6 +2423,7 @@ struct em28xx_board em28xx_boards[] = { - .tuner_type = TUNER_ABSENT, - .tuner_gpio = hauppauge_dualhd_dvb, - .has_dvb = 1, -+ .has_dual_ts = 1, - .ir_codes = RC_MAP_HAUPPAUGE, - .leds = hauppauge_dualhd_leds, - }, -@@ -2548,8 +2554,12 @@ struct usb_device_id em28xx_id_table[] = { - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, - { USB_DEVICE(0x2040, 0x0265), - .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB }, -+ { USB_DEVICE(0x2040, 0x8265), -+ .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB }, - { USB_DEVICE(0x2040, 0x026d), - .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 }, -+ { USB_DEVICE(0x2040, 0x826d), -+ .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 }, - { USB_DEVICE(0x0438, 0xb002), - .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, - { USB_DEVICE(0x2001, 0xf112), -@@ -2610,7 +2620,13 @@ struct usb_device_id em28xx_id_table[] = { - .driver_info = EM28178_BOARD_PCTV_461E }, - { USB_DEVICE(0x2013, 0x025f), - .driver_info = EM28178_BOARD_PCTV_292E }, -- { USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD */ -+ { USB_DEVICE(0x2013, 0x0264), /* Hauppauge WinTV-soloHD 292e SE */ -+ .driver_info = EM28178_BOARD_PCTV_292E }, -+ { USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD Isoc */ -+ .driver_info = EM28178_BOARD_PCTV_292E }, -+ { USB_DEVICE(0x2040, 0x8264), /* Hauppauge OEM Generic WinTV-soloHD Bulk */ -+ .driver_info = EM28178_BOARD_PCTV_292E }, -+ { USB_DEVICE(0x2040, 0x8268), /* Hauppauge Retail WinTV-soloHD Bulk */ - .driver_info = EM28178_BOARD_PCTV_292E }, - { USB_DEVICE(0x0413, 0x6f07), - .driver_info = EM2861_BOARD_LEADTEK_VC100 }, -@@ -3240,7 +3256,8 @@ static void em28xx_release_resources(struct em28xx *dev) - em28xx_i2c_unregister(dev, 1); - em28xx_i2c_unregister(dev, 0); - -- usb_put_dev(udev); -+ if (dev->ts == PRIMARY_TS) -+ usb_put_dev(udev); - - /* Mark device as unused */ - clear_bit(dev->devno, em28xx_devused); -@@ -3433,6 +3450,35 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, - return 0; - } - -+int em28xx_duplicate_dev(struct em28xx *dev) -+{ -+ int nr; -+ struct em28xx *sec_dev = kzalloc(sizeof(*sec_dev), GFP_KERNEL); -+ -+ if (sec_dev == NULL) { -+ dev->dev_next = NULL; -+ return -ENOMEM; -+ } -+ memcpy(sec_dev, dev, sizeof(sizeof(*sec_dev))); -+ /* Check to see next free device and mark as used */ -+ do { -+ nr = find_first_zero_bit(em28xx_devused, EM28XX_MAXBOARDS); -+ if (nr >= EM28XX_MAXBOARDS) { -+ /* No free device slots */ -+ printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", -+ EM28XX_MAXBOARDS); -+ kfree(sec_dev); -+ dev->dev_next = NULL; -+ return -ENOMEM; -+ } -+ } while (test_and_set_bit(nr, em28xx_devused)); -+ sec_dev->devno = nr; -+ snprintf(sec_dev->name, 28, "em28xx #%d", nr); -+ sec_dev->dev_next = NULL; -+ dev->dev_next = sec_dev; -+ return 0; -+} -+ - /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ - #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) - -@@ -3552,6 +3598,17 @@ static int em28xx_usb_probe(struct usb_interface *interface, - } - } - break; -+ case 0x85: -+ if (usb_endpoint_xfer_isoc(e)) { -+ if (size > dev->dvb_max_pkt_size_isoc_ts2) { -+ dev->dvb_ep_isoc_ts2 = e->bEndpointAddress; -+ dev->dvb_max_pkt_size_isoc_ts2 = size; -+ dev->dvb_alt_isoc = i; -+ } -+ } else { -+ dev->dvb_ep_bulk_ts2 = e->bEndpointAddress; -+ } -+ break; - } - } - /* NOTE: -@@ -3566,6 +3623,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, - * 0x83 isoc* => audio - * 0x84 isoc => digital - * 0x84 bulk => analog or digital** -+ * 0x85 isoc => digital TS2 -+ * 0x85 bulk => digital TS2 - * (*: audio should always be isoc) - * (**: analog, if ep 0x82 is isoc, otherwise digital) - * -@@ -3633,6 +3692,10 @@ static int em28xx_usb_probe(struct usb_interface *interface, - dev->has_video = has_video; - dev->ifnum = ifnum; - -+ dev->ts = PRIMARY_TS; -+ snprintf(dev->name, 28, "em28xx"); -+ dev->dev_next = NULL; -+ - if (has_vendor_audio) { - dev_err(&interface->dev, - "Audio interface %i found (Vendor Class)\n", ifnum); -@@ -3712,6 +3775,65 @@ static int em28xx_usb_probe(struct usb_interface *interface, - dev->dvb_xfer_bulk ? "bulk" : "isoc"); - } - -+ if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) { -+ dev->dev_next->ts = SECONDARY_TS; -+ dev->dev_next->alt = -1; -+ dev->dev_next->is_audio_only = has_vendor_audio && -+ !(has_video || has_dvb); -+ dev->dev_next->has_video = false; -+ dev->dev_next->ifnum = ifnum; -+ dev->dev_next->model = id->driver_info; -+ -+ mutex_init(&dev->dev_next->lock); -+ retval = em28xx_init_dev(dev->dev_next, udev, interface, -+ dev->dev_next->devno); -+ if (retval) -+ goto err_free; -+ -+ dev->dev_next->board.ir_codes = NULL; /* No IR for 2nd tuner */ -+ dev->dev_next->board.has_ir_i2c = 0; /* No IR for 2nd tuner */ -+ -+ if (usb_xfer_mode < 0) { -+ if (dev->dev_next->board.is_webcam) -+ try_bulk = 1; -+ else -+ try_bulk = 0; -+ } else { -+ try_bulk = usb_xfer_mode > 0; -+ } -+ -+ /* Select USB transfer types to use */ -+ if (has_dvb) { -+ if (!dev->dvb_ep_isoc_ts2 || -+ (try_bulk && dev->dvb_ep_bulk_ts2)) -+ dev->dev_next->dvb_xfer_bulk = 1; -+ dev_info(&dev->intf->dev, "dvb ts2 set to %s mode.\n", -+ dev->dev_next->dvb_xfer_bulk ? "bulk" : "isoc"); -+ } -+ -+ dev->dev_next->dvb_ep_isoc = dev->dvb_ep_isoc_ts2; -+ dev->dev_next->dvb_ep_bulk = dev->dvb_ep_bulk_ts2; -+ dev->dev_next->dvb_max_pkt_size_isoc = dev->dvb_max_pkt_size_isoc_ts2; -+ dev->dev_next->dvb_alt_isoc = dev->dvb_alt_isoc; -+ -+ /* Configuare hardware to support TS2*/ -+ if (dev->dvb_xfer_bulk) { -+ /* The ep4 and ep5 are configuared for BULK */ -+ em28xx_write_reg(dev, 0x0b, 0x96); -+ mdelay(100); -+ em28xx_write_reg(dev, 0x0b, 0x80); -+ mdelay(100); -+ } else { -+ /* The ep4 and ep5 are configuared for ISO */ -+ em28xx_write_reg(dev, 0x0b, 0x96); -+ mdelay(100); -+ em28xx_write_reg(dev, 0x0b, 0x82); -+ mdelay(100); -+ } -+ -+ kref_init(&dev->dev_next->ref); -+ } -+ - kref_init(&dev->ref); - - request_modules(dev); -@@ -3754,15 +3876,29 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) - if (!dev) - return; - -+ if (dev->dev_next != NULL) { -+ dev->dev_next->disconnected = 1; -+ dev_info(&dev->intf->dev, "Disconnecting %s\n", -+ dev->dev_next->name); -+ flush_request_modules(dev->dev_next); -+ } -+ - dev->disconnected = 1; - -- dev_err(&dev->intf->dev, "Disconnecting\n"); -+ dev_err(&dev->intf->dev, "Disconnecting %s\n", dev->name); - - flush_request_modules(dev); - - em28xx_close_extension(dev); - -+ if (dev->dev_next != NULL) -+ em28xx_release_resources(dev->dev_next); - em28xx_release_resources(dev); -+ -+ if (dev->dev_next != NULL) { -+ kref_put(&dev->dev_next->ref, em28xx_free_device); -+ dev->dev_next = NULL; -+ } - kref_put(&dev->ref, em28xx_free_device); - } - -diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c -index 1d0d8cc..b72335e 100644 ---- a/drivers/media/usb/em28xx/em28xx-core.c -+++ b/drivers/media/usb/em28xx/em28xx-core.c -@@ -638,10 +638,30 @@ int em28xx_capture_start(struct em28xx *dev, int start) - dev->chip_id == CHIP_ID_EM28174 || - dev->chip_id == CHIP_ID_EM28178) { - /* The Transport Stream Enable Register moved in em2874 */ -- rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, -- start ? -- EM2874_TS1_CAPTURE_ENABLE : 0x00, -- EM2874_TS1_CAPTURE_ENABLE); -+ if (dev->dvb_xfer_bulk) { -+ /* Max Tx Size = 188 * EM28XX_DVB_BULK_PACKET_MULTIPLIER */ -+ em28xx_write_reg(dev, (dev->ts == PRIMARY_TS) ? -+ EM2874_R5D_TS1_PKT_SIZE : -+ EM2874_R5E_TS2_PKT_SIZE, -+ EM28XX_DVB_BULK_PACKET_MULTIPLIER); -+ } else { -+ /* TS2 Maximum Transfer Size = 188 * 5 */ -+ em28xx_write_reg(dev, (dev->ts == PRIMARY_TS) ? -+ EM2874_R5D_TS1_PKT_SIZE : -+ EM2874_R5E_TS2_PKT_SIZE, 0x05); -+ } -+ if (dev->ts == PRIMARY_TS) -+ rc = em28xx_write_reg_bits(dev, -+ EM2874_R5F_TS_ENABLE, -+ start ? -+ EM2874_TS1_CAPTURE_ENABLE : 0x00, -+ EM2874_TS1_CAPTURE_ENABLE); -+ else -+ rc = em28xx_write_reg_bits(dev, -+ EM2874_R5F_TS_ENABLE, -+ start ? -+ EM2874_TS2_CAPTURE_ENABLE : 0x00, -+ EM2874_TS2_CAPTURE_ENABLE); - } else { - /* FIXME: which is the best order? */ - /* video registers are sampled by VREF */ -@@ -1077,7 +1097,11 @@ int em28xx_register_extension(struct em28xx_ops *ops) - mutex_lock(&em28xx_devlist_mutex); - list_add_tail(&ops->next, &em28xx_extension_devlist); - list_for_each_entry(dev, &em28xx_devlist, devlist) { -- ops->init(dev); -+ if (ops->init) { -+ ops->init(dev); -+ if (dev->dev_next != NULL) -+ ops->init(dev->dev_next); -+ } - } - mutex_unlock(&em28xx_devlist_mutex); - pr_info("em28xx: Registered (%s) extension\n", ops->name); -@@ -1091,7 +1115,11 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(dev, &em28xx_devlist, devlist) { -- ops->fini(dev); -+ if (ops->fini) { -+ if (dev->dev_next != NULL) -+ ops->fini(dev->dev_next); -+ ops->fini(dev); -+ } - } - list_del(&ops->next); - mutex_unlock(&em28xx_devlist_mutex); -@@ -1106,8 +1134,11 @@ void em28xx_init_extension(struct em28xx *dev) - mutex_lock(&em28xx_devlist_mutex); - list_add_tail(&dev->devlist, &em28xx_devlist); - list_for_each_entry(ops, &em28xx_extension_devlist, next) { -- if (ops->init) -+ if (ops->init) { - ops->init(dev); -+ if (dev->dev_next != NULL) -+ ops->init(dev->dev_next); -+ } - } - mutex_unlock(&em28xx_devlist_mutex); - } -@@ -1118,8 +1149,11 @@ void em28xx_close_extension(struct em28xx *dev) - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(ops, &em28xx_extension_devlist, next) { -- if (ops->fini) -+ if (ops->fini) { -+ if (dev->dev_next != NULL) -+ ops->fini(dev->dev_next); - ops->fini(dev); -+ } - } - list_del(&dev->devlist); - mutex_unlock(&em28xx_devlist_mutex); -@@ -1134,6 +1168,8 @@ int em28xx_suspend_extension(struct em28xx *dev) - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->suspend) - ops->suspend(dev); -+ if (dev->dev_next != NULL) -+ ops->suspend(dev->dev_next); - } - mutex_unlock(&em28xx_devlist_mutex); - return 0; -@@ -1148,6 +1184,8 @@ int em28xx_resume_extension(struct em28xx *dev) - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->resume) - ops->resume(dev); -+ if (dev->dev_next != NULL) -+ ops->resume(dev->dev_next); - } - mutex_unlock(&em28xx_devlist_mutex); - return 0; -diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c -index c4abf51..a7447e9 100644 ---- a/drivers/media/usb/em28xx/em28xx-dvb.c -+++ b/drivers/media/usb/em28xx/em28xx-dvb.c -@@ -199,13 +199,12 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) - int rc; - struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv; - struct em28xx *dev = i2c_bus->dev; -- struct usb_device *udev = interface_to_usbdev(dev->intf); - int dvb_max_packet_size, packet_multiplier, dvb_alt; - - if (dev->dvb_xfer_bulk) { - if (!dev->dvb_ep_bulk) - return -ENODEV; -- dvb_max_packet_size = 512; /* USB 2.0 spec */ -+ dvb_max_packet_size = 188; - packet_multiplier = EM28XX_DVB_BULK_PACKET_MULTIPLIER; - dvb_alt = 0; - } else { /* isoc */ -@@ -218,7 +217,6 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) - dvb_alt = dev->dvb_alt_isoc; - } - -- usb_set_interface(udev, dev->ifnum, dvb_alt); - rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); - if (rc < 0) - return rc; -@@ -1128,8 +1126,9 @@ static void em28xx_unregister_dvb(struct em28xx_dvb *dvb) - - static int em28xx_dvb_init(struct em28xx *dev) - { -- int result = 0; -+ int result = 0, dvb_alt = 0; - struct em28xx_dvb *dvb; -+ struct usb_device *udev; - - if (dev->is_audio_only) { - /* Shouldn't initialize IR for this interface */ -@@ -1155,7 +1154,7 @@ static int em28xx_dvb_init(struct em28xx *dev) - result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, - dev->dvb_xfer_bulk, - EM28XX_DVB_NUM_BUFS, -- 512, -+ 188, - EM28XX_DVB_BULK_PACKET_MULTIPLIER); - } else { - result = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, -@@ -1728,6 +1727,7 @@ static int em28xx_dvb_init(struct em28xx *dev) - si2168_config.i2c_adapter = &adapter; - si2168_config.fe = &dvb->fe[0]; - si2168_config.ts_mode = SI2168_TS_PARALLEL; -+ si2168_config.inversion = true; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); - info.addr = 0x64; -@@ -1912,9 +1912,13 @@ static int em28xx_dvb_init(struct em28xx *dev) - si2168_config.i2c_adapter = &adapter; - si2168_config.fe = &dvb->fe[0]; - si2168_config.ts_mode = SI2168_TS_SERIAL; -+ si2168_config.inversion = true; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); -- info.addr = 0x64; -+ if (dev->ts == PRIMARY_TS) -+ info.addr = 0x64; -+ else -+ info.addr = 0x67; - info.platform_data = &si2168_config; - request_module(info.type); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); -@@ -1940,7 +1944,10 @@ static int em28xx_dvb_init(struct em28xx *dev) - #endif - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); -- info.addr = 0x60; -+ if (dev->ts == PRIMARY_TS) -+ info.addr = 0x60; -+ else -+ info.addr = 0x63; - info.platform_data = &si2157_config; - request_module(info.type); - client = i2c_new_device(adapter, &info); -@@ -1976,7 +1983,10 @@ static int em28xx_dvb_init(struct em28xx *dev) - lgdt3306a_config.fe = &dvb->fe[0]; - lgdt3306a_config.i2c_adapter = &adapter; - strlcpy(info.type, "lgdt3306a", sizeof(info.type)); -- info.addr = 0x59; -+ if (dev->ts == PRIMARY_TS) -+ info.addr = 0x59; -+ else -+ info.addr = 0x0e; - info.platform_data = &lgdt3306a_config; - request_module(info.type); - client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], -@@ -2003,7 +2013,10 @@ static int em28xx_dvb_init(struct em28xx *dev) - #endif - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", sizeof(info.type)); -- info.addr = 0x60; -+ if (dev->ts == PRIMARY_TS) -+ info.addr = 0x60; -+ else -+ info.addr = 0x62; - info.platform_data = &si2157_config; - request_module(info.type); - -@@ -2046,6 +2059,14 @@ static int em28xx_dvb_init(struct em28xx *dev) - if (result < 0) - goto out_free; - -+ if (dev->dvb_xfer_bulk) { -+ dvb_alt = 0; -+ } else { /* isoc */ -+ dvb_alt = dev->dvb_alt_isoc; -+ } -+ -+ udev = interface_to_usbdev(dev->intf); -+ usb_set_interface(udev, dev->ifnum, dvb_alt); - dev_info(&dev->intf->dev, "DVB extension successfully initialized\n"); - - kref_get(&dev->ref); -diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h -index 88084f2..7dcf0cb 100644 ---- a/drivers/media/usb/em28xx/em28xx.h -+++ b/drivers/media/usb/em28xx/em28xx.h -@@ -166,7 +166,7 @@ - #define EM28XX_STOP_AUDIO 0 - - /* maximum number of em28xx boards */ --#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ -+#define EM28XX_MAXBOARDS DVB_MAX_ADAPTERS /* All adapters could be em28xx */ - - /* maximum number of frames that can be queued */ - #define EM28XX_NUM_FRAMES 5 -@@ -191,7 +191,7 @@ - USB 2.0 spec says bulk packet size is always 512 bytes - */ - #define EM28XX_BULK_PACKET_MULTIPLIER 384 --#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 384 -+#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 240 - - #define EM28XX_INTERLACED_DEFAULT 1 - -@@ -217,6 +217,9 @@ - /* max. number of button state polling addresses */ - #define EM28XX_NUM_BUTTON_ADDRESSES_MAX 5 - -+#define PRIMARY_TS 0 -+#define SECONDARY_TS 1 -+ - enum em28xx_mode { - EM28XX_SUSPEND, - EM28XX_ANALOG_MODE, -@@ -457,6 +460,7 @@ struct em28xx_board { - unsigned int mts_firmware:1; - unsigned int max_range_640_480:1; - unsigned int has_dvb:1; -+ unsigned int has_dual_ts:1; - unsigned int is_webcam:1; - unsigned int valid:1; - unsigned int has_ir_i2c:1; -@@ -621,6 +625,7 @@ struct em28xx { - unsigned int is_audio_only:1; - enum em28xx_int_audio_type int_audio_type; - enum em28xx_usb_audio_type usb_audio_type; -+ unsigned char name[32]; - - struct em28xx_board board; - -@@ -682,6 +687,8 @@ struct em28xx { - u8 ifnum; /* number of the assigned usb interface */ - u8 analog_ep_isoc; /* address of isoc endpoint for analog */ - u8 analog_ep_bulk; /* address of bulk endpoint for analog */ -+ u8 dvb_ep_isoc_ts2; /* address of isoc endpoint for DVB TS2*/ -+ u8 dvb_ep_bulk_ts2; /* address of bulk endpoint for DVB TS2*/ - u8 dvb_ep_isoc; /* address of isoc endpoint for DVB */ - u8 dvb_ep_bulk; /* address of bulk endpoint for DVB */ - int alt; /* alternate setting */ -@@ -695,6 +702,8 @@ struct em28xx { - int dvb_alt_isoc; /* alternate setting for DVB isoc transfers */ - unsigned int dvb_max_pkt_size_isoc; /* isoc max packet size of the - selected DVB ep at dvb_alt */ -+ unsigned int dvb_max_pkt_size_isoc_ts2; /* isoc max packet size of the -+ selected DVB ep at dvb_alt */ - unsigned int dvb_xfer_bulk:1; /* use bulk instead of isoc - transfers for DVB */ - char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ -@@ -726,6 +735,9 @@ struct em28xx { - struct media_entity input_ent[MAX_EM28XX_INPUT]; - struct media_pad input_pad[MAX_EM28XX_INPUT]; - #endif -+ -+ struct em28xx *dev_next; -+ int ts; - }; - - #define kref_to_dev(d) container_of(d, struct em28xx, ref) -diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c -index 82852f2..f5d442d 100644 ---- a/drivers/media/v4l2-core/tuner-core.c -+++ b/drivers/media/v4l2-core/tuner-core.c -@@ -40,6 +40,7 @@ - #include "xc5000.h" - #include "tda18271.h" - #include "xc4000.h" -+#include "si2157.h" - - #define UNSET (-1U) - -@@ -396,6 +397,26 @@ static void set_type(struct i2c_client *c, unsigned int type, - tune_now = 0; - break; - } -+ case TUNER_SILABS_SI2157: -+ { -+ static struct si2157_config silabs_config = { -+ .inversion = true, -+ .if_port = 1, /* selects the digital IF port */ -+ /* analog assumed to be other port */ -+ }; -+ -+ dprintk("%s: looking for si2157 tuner on i2c bus: %d\n", -+ __func__, i2c_adapter_id(t->i2c->adapter)); -+ -+ if (!dvb_attach(si2157_attach, &t->fe, t->i2c->addr, -+ t->i2c->adapter, &silabs_config)) { -+ dprintk("%s: attaching si2157 tuner failed\n", __func__); -+ goto attach_failed; -+ } -+ dprintk("%s: si2157 tuner attached\n", __func__); -+ tune_now = 0; -+ break; -+ } - default: - if (!dvb_attach(simple_tuner_attach, &t->fe, - t->i2c->adapter, t->i2c->addr, t->type)) -diff --git a/include/media/tuner.h b/include/media/tuner.h -index b3edc14..cab980a 100644 ---- a/include/media/tuner.h -+++ b/include/media/tuner.h -@@ -142,6 +142,8 @@ - #define TUNER_SONY_BTF_PK467Z 90 /* NTSC_JP */ - #define TUNER_SONY_BTF_PB463Z 91 /* NTSC */ - -+#define TUNER_SILABS_SI2157 92 /* Silicon Labs terrestrial/cable tuner series */ -+ - /* tv card specific */ - #define TDA9887_PRESENT (1<<0) - #define TDA9887_PORT1_INACTIVE (1<<1) --- -2.14.1 - diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-301-AML-videobuf-resource.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-301-AML-videobuf-resource.patch deleted file mode 100644 index 9f4b802fd6..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-301-AML-videobuf-resource.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/media/v4l2-core/Kconfig -+++ b/drivers/media/v4l2-core/Kconfig -@@ -73,6 +73,10 @@ - depends on HAS_DMA - select VIDEOBUF_GEN - -+config VIDEOBUF_RESOURCE -+ select VIDEOBUF_GEN -+ tristate -+ - config VIDEOBUF_DVB - tristate - select VIDEOBUF_GEN ---- a/drivers/media/v4l2-core/Makefile -+++ b/drivers/media/v4l2-core/Makefile -@@ -33,6 +33,7 @@ - obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o - obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o - obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o -+obj-$(CONFIG_VIDEOBUF_RESOURCE) += videobuf-res.o - - obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o videobuf2-v4l2.o - obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-302-AML-amlogic-video-dev.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-302-AML-amlogic-video-dev.patch deleted file mode 100644 index 0b85e2d7d0..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-302-AML-amlogic-video-dev.patch +++ /dev/null @@ -1,39 +0,0 @@ ---- a/drivers/media/Kconfig -+++ b/drivers/media/Kconfig -@@ -235,5 +235,6 @@ source "drivers/media/i2c/Kconfig" - source "drivers/media/spi/Kconfig" - source "drivers/media/tuners/Kconfig" - source "drivers/media/dvb-frontends/Kconfig" -+source "drivers/media/amlogic/Kconfig" - - endif # MEDIA_SUPPORT ---- a/drivers/media/Makefile -+++ b/drivers/media/Makefile -@@ -25,7 +25,7 @@ - obj-y += rc/ - - obj-$(CONFIG_CEC_CORE) += cec/ -- -+obj-y += amlogic/ - # - # Finally, merge the drivers that require the core - # ---- /dev/null -+++ b/drivers/media/amlogic/Kconfig -@@ -0,0 +1,8 @@ -+# -+# Amlogic driver configuration -+# -+menu "Amlogic Device Drivers" -+ -+source "drivers/media/amlogic/video_dev/Kconfig" -+ -+endmenu ---- /dev/null -+++ b/drivers/media/amlogic/Makefile -@@ -0,0 +1,5 @@ -+########################################## -+########## Amlogic Drivers ############### -+########################################## -+ -+obj-$(CONFIG_V4L_AMLOGIC_VIDEO) += video_dev/ diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-303-AML-meson-ir.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-303-AML-meson-ir.patch deleted file mode 100644 index a34f7896b6..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-303-AML-meson-ir.patch +++ /dev/null @@ -1,216 +0,0 @@ ---- a/drivers/media/rc/meson-ir.c -+++ b/drivers/media/rc/meson-ir.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - #include - -@@ -69,6 +70,7 @@ - void __iomem *reg; - struct rc_dev *rc; - spinlock_t lock; -+ struct timer_list flush_timer; - }; - - static void meson_ir_set_mask(struct meson_ir *ir, unsigned int reg, -@@ -98,6 +100,10 @@ - rawir.pulse = !!(status & STATUS_IR_DEC_IN); - - ir_raw_event_store(ir->rc, &rawir); -+ -+ mod_timer(&ir->flush_timer, -+ jiffies + nsecs_to_jiffies(ir->rc->timeout)); -+ - ir_raw_event_handle(ir->rc); - - spin_unlock(&ir->lock); -@@ -105,6 +111,17 @@ - return IRQ_HANDLED; - } - -+static void flush_timer(unsigned long arg) -+{ -+ struct meson_ir *ir = (struct meson_ir *)arg; -+ DEFINE_IR_RAW_EVENT(rawir); -+ -+ rawir.timeout = true; -+ rawir.duration = ir->rc->timeout; -+ ir_raw_event_store(ir->rc, &rawir); -+ ir_raw_event_handle(ir->rc); -+} -+ - static int meson_ir_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -113,6 +130,7 @@ - const char *map_name; - struct meson_ir *ir; - int irq, ret; -+ struct pinctrl *pinctrl; - - ir = devm_kzalloc(dev, sizeof(struct meson_ir), GFP_KERNEL); - if (!ir) -@@ -125,6 +143,14 @@ - return PTR_ERR(ir->reg); - } - -+ if (of_get_property(node, "pinctrl-names", NULL)) { -+ pinctrl = devm_pinctrl_get_select_default(dev); -+ if (IS_ERR(pinctrl)) { -+ dev_err(dev, "failed to get pinctrl\n"); -+ ret = PTR_ERR(pinctrl); -+ } -+ } -+ - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq resource\n"); -@@ -145,7 +171,9 @@ - ir->rc->map_name = map_name ? map_name : RC_MAP_EMPTY; - ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; - ir->rc->rx_resolution = US_TO_NS(MESON_TRATE); -+ ir->rc->min_timeout = 1; - ir->rc->timeout = MS_TO_NS(200); -+ ir->rc->max_timeout = MS_TO_NS(1000); - ir->rc->driver_name = DRIVER_NAME; - - spin_lock_init(&ir->lock); -@@ -157,6 +185,8 @@ - return ret; - } - -+ setup_timer(&ir->flush_timer, flush_timer, (unsigned long) ir); -+ - ret = devm_request_irq(dev, irq, meson_ir_irq, 0, NULL, ir); - if (ret) { - dev_err(dev, "failed to request irq\n"); -@@ -197,6 +227,7 @@ - spin_lock_irqsave(&ir->lock, flags); - meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0); - spin_unlock_irqrestore(&ir->lock, flags); -+ del_timer_sync(&ir->flush_timer); - - return 0; - } ---- a/drivers/media/rc/Kconfig -+++ b/drivers/media/rc/Kconfig -@@ -227,7 +227,6 @@ - config IR_MESON - tristate "Amlogic Meson IR remote receiver" - depends on RC_CORE -- depends on ARCH_MESON || COMPILE_TEST - ---help--- - Say Y if you want to use the IR remote receiver available - on Amlogic Meson SoCs. ---- /dev/null -+++ b/include/linux/bitfield.h -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (C) 2014 Felix Fietkau -+ * Copyright (C) 2004 - 2009 Ivo van Doorn -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 -+ * as published by the Free Software Foundation -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef _LINUX_BITFIELD_H -+#define _LINUX_BITFIELD_H -+ -+#include -+ -+/* -+ * Bitfield access macros -+ * -+ * FIELD_{GET,PREP} macros take as first parameter shifted mask -+ * from which they extract the base mask and shift amount. -+ * Mask must be a compilation time constant. -+ * -+ * Example: -+ * -+ * #define REG_FIELD_A GENMASK(6, 0) -+ * #define REG_FIELD_B BIT(7) -+ * #define REG_FIELD_C GENMASK(15, 8) -+ * #define REG_FIELD_D GENMASK(31, 16) -+ * -+ * Get: -+ * a = FIELD_GET(REG_FIELD_A, reg); -+ * b = FIELD_GET(REG_FIELD_B, reg); -+ * -+ * Set: -+ * reg = FIELD_PREP(REG_FIELD_A, 1) | -+ * FIELD_PREP(REG_FIELD_B, 0) | -+ * FIELD_PREP(REG_FIELD_C, c) | -+ * FIELD_PREP(REG_FIELD_D, 0x40); -+ * -+ * Modify: -+ * reg &= ~REG_FIELD_C; -+ * reg |= FIELD_PREP(REG_FIELD_C, c); -+ */ -+ -+#define __bf_shf(x) (__builtin_ffsll(x) - 1) -+ -+#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \ -+ ({ \ -+ BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \ -+ _pfx "mask is not constant"); \ -+ BUILD_BUG_ON_MSG(!(_mask), _pfx "mask is zero"); \ -+ BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ -+ ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \ -+ _pfx "value too large for the field"); \ -+ BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \ -+ _pfx "type of reg too small for mask"); \ -+ __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \ -+ (1ULL << __bf_shf(_mask))); \ -+ }) -+ -+/** -+ * FIELD_FIT() - check if value fits in the field -+ * @_mask: shifted mask defining the field's length and position -+ * @_val: value to test against the field -+ * -+ * Return: true if @_val can fit inside @_mask, false if @_val is too big. -+ */ -+#define FIELD_FIT(_mask, _val) \ -+ ({ \ -+ __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: "); \ -+ !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \ -+ }) -+ -+/** -+ * FIELD_PREP() - prepare a bitfield element -+ * @_mask: shifted mask defining the field's length and position -+ * @_val: value to put in the field -+ * -+ * FIELD_PREP() masks and shifts up the value. The result should -+ * be combined with other fields of the bitfield using logical OR. -+ */ -+#define FIELD_PREP(_mask, _val) \ -+ ({ \ -+ __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \ -+ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ -+ }) -+ -+/** -+ * FIELD_GET() - extract a bitfield element -+ * @_mask: shifted mask defining the field's length and position -+ * @_reg: 32bit value of entire bitfield -+ * -+ * FIELD_GET() extracts the field specified by @_mask from the -+ * bitfield passed in as @_reg by masking and shifting it down. -+ */ -+#define FIELD_GET(_mask, _reg) \ -+ ({ \ -+ __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \ -+ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ -+ }) -+ -+#endif diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-304-AML-wetekplay.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-304-AML-wetekplay.patch deleted file mode 100644 index dd676f9f7f..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-304-AML-wetekplay.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/drivers/media/amlogic/Kconfig b/drivers/media/amlogic/Kconfig -index 5203702..7af18b7 100644 ---- a/drivers/media/amlogic/Kconfig -+++ b/drivers/media/amlogic/Kconfig -@@ -5,4 +5,6 @@ menu "Amlogic Device Drivers" - - source "drivers/media/amlogic/video_dev/Kconfig" - -+source "drivers/media/amlogic/wetek/Kconfig" -+ - endmenu -diff --git a/drivers/media/amlogic/Makefile b/drivers/media/amlogic/Makefile -index 049cb81..99bbb31 100644 ---- a/drivers/media/amlogic/Makefile -+++ b/drivers/media/amlogic/Makefile -@@ -3,3 +3,5 @@ - ########################################## - - obj-$(CONFIG_V4L_AMLOGIC_VIDEO) += video_dev/ -+ -+obj-$(CONFIG_WETEK) += wetek/ diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-305-AML-dmx_h.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-305-AML-dmx_h.patch deleted file mode 100644 index 46bd6f9e75..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-305-AML-dmx_h.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/include/uapi/linux/dvb/dmx.h 2017-01-23 18:15:29.000000000 +0100 -+++ b/include/uapi/linux/dvb/dmx.h 2017-02-08 14:12:07.802477417 +0100 -@@ -197,6 +197,20 @@ - __u32 flags; - }; - -+typedef enum dmx_source { -+ DMX_SOURCE_FRONT0 = 0, -+ DMX_SOURCE_FRONT1, -+ DMX_SOURCE_FRONT2, -+ DMX_SOURCE_FRONT3, -+ DMX_SOURCE_DVR0 = 16, -+ DMX_SOURCE_DVR1, -+ DMX_SOURCE_DVR2, -+ DMX_SOURCE_DVR3, -+ DMX_SOURCE_FRONT0_OFFSET = 100, -+ DMX_SOURCE_FRONT1_OFFSET, -+ DMX_SOURCE_FRONT2_OFFSET -+} dmx_source_t; -+ - /** - * struct dmx_stc - Stores System Time Counter (STC) information. - * --- diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-306-AML-build-dvb-avl.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-306-AML-build-dvb-avl.patch deleted file mode 100644 index 86613f0c64..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/linux-306-AML-build-dvb-avl.patch +++ /dev/null @@ -1,39 +0,0 @@ ---- a/drivers/media/dvb-avl/aml_dmx.c 2017-12-10 19:34:57.000000000 +0100 -+++ b/drivers/media/dvb-avl/aml_dmx.c 2017-12-12 12:55:21.255063140 +0100 -@@ -547,7 +547,7 @@ - struct dvb_demux_feed *feed = dmx->channel[f->chan_id].feed; - - if (feed && feed->cb.sec) -- feed->cb.sec(p, sec_len, NULL, 0, f->filter, DMX_OK); -+ feed->cb.sec(p, sec_len, NULL, 0, f->filter); - } - - static void hardware_match_section(struct aml_dmx *dmx, -@@ -968,7 +968,7 @@ - if (dmx->channel[2].feed && dmx->channel[2].feed->cb.ts) { - dmx->channel[2].feed->cb.ts(buffer1_virt, len1, - buffer2_virt, len2, -- &dmx->channel[2].feed->feed.ts, DMX_OK); -+ &dmx->channel[2].feed->feed.ts); - } - } - WRITE_MPEG_REG(PARSER_SUB_RP, rd_ptr); -@@ -1167,7 +1167,7 @@ - channel->dvr_feed->cb.ts( - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size, NULL, 0, -- &channel->dvr_feed->feed.ts, DMX_OK); -+ &channel->dvr_feed->feed.ts); - afifo->buf_read = 0; - } - -@@ -1186,7 +1186,7 @@ - channel->dvr_feed->cb.ts( - (u8 *)afifo->pages+afifo->buf_read*size, - cnt*size, NULL, 0, -- &channel->dvr_feed->feed.ts, DMX_OK); -+ &channel->dvr_feed->feed.ts); - afifo->buf_read = afifo->buf_toggle; - } - --- diff --git a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/temp_revert.patch b/packages/linux-driver-addons/dvb/hauppauge/sources/backports/temp_revert.patch deleted file mode 100644 index 1ebe3ac3f6..0000000000 --- a/packages/linux-driver-addons/dvb/hauppauge/sources/backports/temp_revert.patch +++ /dev/null @@ -1,30 +0,0 @@ -reverted: pvrusb2: properly check endpoint types - ---- b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c -+++ a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c -@@ -3648,12 +3648,6 @@ - hdw); - hdw->ctl_write_urb->actual_length = 0; - hdw->ctl_write_pend_flag = !0; -- if (usb_urb_ep_type_check(hdw->ctl_write_urb)) { -- pvr2_trace( -- PVR2_TRACE_ERROR_LEGS, -- "Invalid write control endpoint"); -- return -EINVAL; -- } - status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL); - if (status < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, -@@ -3678,12 +3672,6 @@ - hdw); - hdw->ctl_read_urb->actual_length = 0; - hdw->ctl_read_pend_flag = !0; -- if (usb_urb_ep_type_check(hdw->ctl_read_urb)) { -- pvr2_trace( -- PVR2_TRACE_ERROR_LEGS, -- "Invalid read control endpoint"); -- return -EINVAL; -- } - status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL); - if (status < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, diff --git a/projects/Amlogic/options b/projects/Amlogic/options index 3211b794f0..3f6b1f0d3c 100644 --- a/projects/Amlogic/options +++ b/projects/Amlogic/options @@ -152,4 +152,4 @@ # driver addons to install: # for a list of additinoal drivers see packages/linux-driver-addons # Space separated list is supported, - DRIVER_ADDONS="crazycat hauppauge" + DRIVER_ADDONS="crazycat" diff --git a/projects/Generic/options b/projects/Generic/options index 34a29593fd..b1d76b6c64 100644 --- a/projects/Generic/options +++ b/projects/Generic/options @@ -97,4 +97,4 @@ # driver addons to install: # for a list of additional drivers see packages/linux-driver-addons # Space separated list is supported, - DRIVER_ADDONS="crazycat digital_devices hauppauge" + DRIVER_ADDONS="crazycat digital_devices" diff --git a/projects/RPi/options b/projects/RPi/options index 712e489601..af054f501d 100644 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -166,4 +166,4 @@ fi # driver addons to install: # for a list of additional drivers see packages/linux-driver-addons # Space separated list is supported, - DRIVER_ADDONS="crazycat hauppauge" + DRIVER_ADDONS="crazycat" diff --git a/projects/Rockchip/options b/projects/Rockchip/options index 73f6628e69..ff95516c72 100644 --- a/projects/Rockchip/options +++ b/projects/Rockchip/options @@ -81,4 +81,4 @@ # driver addons to install: # for a list of additinoal drivers see packages/linux-driver-addons # Space separated list is supported, - DRIVER_ADDONS="crazycat hauppauge" + DRIVER_ADDONS="crazycat"