summaryrefslogtreecommitdiffstats
path: root/abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch
diff options
context:
space:
mode:
Diffstat (limited to 'abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch')
-rw-r--r--abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch896
1 files changed, 0 insertions, 896 deletions
diff --git a/abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch b/abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch
deleted file mode 100644
index c54594d..0000000
--- a/abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch
+++ /dev/null
@@ -1,896 +0,0 @@
-[PATCH] Add support for FusionHDTV DVB-T NANO 2 / Dual Digital 4
-
-Firmware required:
-
-Mirror 1: http://konstantin.filtschew.de/v4l-firmware/
-
-Mirror 2: http://www.tuxamito.com.es/em2880/
-
-This patch is for users, and NOT meant to be merged into the kernel.
-
-For AU support, apply Rogers patch afterwards:
-http://linuxtv.org/~mkrufky/pending/xc/dd4.au.patch
-
-From: Michael Krufky <mkrufky@linuxtv.org>
----
- linux/drivers/media/dvb/dvb-usb/cxusb.c | 157 +++++++
- linux/drivers/media/dvb/dvb-usb/cxusb.h | 2
- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2
- linux/drivers/media/dvb/frontends/Kconfig | 7
- linux/drivers/media/dvb/frontends/Makefile | 1
- linux/drivers/media/dvb/frontends/xc3028-fe.c | 532 ++++++++++++++++++++++++++
- linux/drivers/media/dvb/frontends/xc3028.h | 56 ++
- v4l/versions.txt | 1
- 8 files changed, 757 insertions(+), 1 deletion(-)
-
---- v4l-dvb.orig/linux/drivers/media/dvb/dvb-usb/cxusb.c
-+++ v4l-dvb/linux/drivers/media/dvb/dvb-usb/cxusb.c
-@@ -30,6 +30,7 @@
- #include "mt352.h"
- #include "mt352_priv.h"
- #include "zl10353.h"
-+#include "xc3028.h"
-
- /* debug */
- int dvb_usb_cxusb_debug;
-@@ -72,6 +73,28 @@
- st->gpio_write_state[GPIO_TUNER] = onoff;
- }
-
-+static void cxusb_bluebird_gpio(struct dvb_usb_device *d, u8 pin)
-+{
-+ u8 o[2],i;
-+
-+ o[0] = 0xff & ~pin;
-+ o[1] = 0x00;
-+
-+ cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_WRITE, o, 2, &i, 1);
-+ msleep(140);
-+
-+ if ((i & pin) != 0x00)
-+ deb_info("gpio_write failed.\n");
-+
-+ o[1] = pin;
-+
-+ cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_WRITE, o, 2, &i, 1);
-+ msleep(140);
-+
-+ if ((i & pin) != pin)
-+ deb_info("gpio_write failed.\n");
-+}
-+
- /* I2C */
- static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
- int num)
-@@ -351,6 +374,64 @@
- .demod_init = cxusb_mt352_demod_init,
- };
-
-+static struct zl10353_config cxusb_zl10353_dualdig4_config = {
-+ .demod_address = 0x0f,
-+ .no_tuner = 1,
-+ .parallel_ts = 1,
-+};
-+
-+struct bcode {
-+ int reg;
-+ char *txt;
-+ int len;
-+ int delay;
-+};
-+
-+static int cxusb_xc3028_zl353_gpio_reset(struct dvb_frontend* fe, int ptr)
-+{
-+ struct dvb_usb_adapter *adap = fe->dvb->priv;
-+ struct dvb_usb_device *d = adap->dev;
-+ int j;
-+ struct bcode zlconf[] = {
-+ /* borrowed from em2880-dvb
-+ * this should be fixed in zl10353.c instead */
-+ {0x1e,"\x60\x00",2,0},
-+ {0x1e,"\x61\x4d",2,0},
-+
-+ {0x1e,"\x50\x0b",2,0},
-+ {0x1e,"\x51\x44",2,0},
-+ {0x1e,"\x52\x46",2,0},
-+ {0x1e,"\x53\x15",2,0},
-+ {0x1e,"\x54\x0f",2,0},
-+ {0x1e,"\x5e\x00",2,0},
-+ {0x1e,"\x5f\x12",2,0},
-+
-+
-+ {0x1e,"\x55\x80",2,0}, /* reset */
-+ {0x1e,"\xea\x01",2,0},
-+ {0x1e,"\xea\x00",2,0},
-+ {0x1e,"\x5a\xcd",2,0},
-+
-+
-+ {0x1e,"\x6c\xe6",2,0}, // set input frequency
-+ {0x1e,"\x6d\x09",2,0},
-+ {}
-+ };
-+
-+ if (ptr == 0 || ptr == 1)
-+ /* pulse the GPIO tuner reset pin */
-+ cxusb_bluebird_gpio(d,0x01);
-+ else if (ptr == 2)
-+ for(j = 0; zlconf[j].txt; j++)
-+ d->adapter[0].fe->ops.write(d->adapter[0].fe, zlconf[j].txt,zlconf[j].len);
-+
-+ return 0;
-+}
-+
-+static struct xc3028_config cxusb_xc3028_config = {
-+ .gpio_reset = cxusb_xc3028_zl353_gpio_reset,
-+};
-+
- /* Callbacks for DVB USB */
- static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
- {
-@@ -386,6 +467,12 @@
- return 0;
- }
-
-+static int cxusb_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
-+{
-+ dvb_attach(xc3028_attach,adap->fe, &adap->dev->i2c_adap, &cxusb_xc3028_config);
-+ return 0;
-+}
-+
- static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
- {
- u8 b;
-@@ -401,6 +488,24 @@
- return -EIO;
- }
-
-+static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
-+{
-+ if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
-+ err("set interface failed");
-+
-+ cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-+
-+ /* pulse the GPIO demod reset pin */
-+ cxusb_bluebird_gpio(adap->dev,0x02);
-+
-+ if ((adap->fe = dvb_attach(zl10353_attach,
-+ &cxusb_zl10353_dualdig4_config,
-+ &adap->dev->i2c_adap)) != NULL)
-+ return 0;
-+
-+ return -EIO;
-+}
-+
- static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
- {
- if (usb_set_interface(adap->dev->udev, 0, 7) < 0)
-@@ -479,6 +584,7 @@
- static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
- static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
- static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
-+static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
-
- static int cxusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-@@ -487,7 +593,8 @@
- dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
-- dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0) {
-+ dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
-+ dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0) {
- return 0;
- }
-
-@@ -508,6 +615,8 @@
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
-+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
-+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVBT_NANO_2) },
- {} /* Terminating entry */
- };
- MODULE_DEVICE_TABLE (usb, cxusb_table);
-@@ -766,6 +875,52 @@
- }
- };
-
-+static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
-+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-+
-+ .usb_ctrl = CYPRESS_FX2,
-+
-+ .size_of_priv = sizeof(struct cxusb_state),
-+
-+ .num_adapters = 1,
-+ .adapter = {
-+ {
-+ .streaming_ctrl = cxusb_streaming_ctrl,
-+ .frontend_attach = cxusb_dualdig4_frontend_attach,
-+ .tuner_attach = cxusb_xc3028_tuner_attach,
-+ /* parameter for the MPEG2-data transfer */
-+ .stream = {
-+ .type = USB_BULK,
-+ .count = 5,
-+ .endpoint = 0x02,
-+ .u = {
-+ .bulk = {
-+ .buffersize = 8192,
-+ }
-+ }
-+ },
-+ },
-+ },
-+
-+ .power_ctrl = cxusb_bluebird_power_ctrl,
-+
-+ .i2c_algo = &cxusb_i2c_algo,
-+
-+ .generic_bulk_ctrl_endpoint = 0x01,
-+
-+ .num_device_descs = 2,
-+ .devices = {
-+ { "DViCO FusionHDTV DVB-T Dual Digital 4",
-+ { NULL },
-+ { &cxusb_table[13], NULL },
-+ },
-+ { "DViCO FusionHDTV DVB-T NANO2",
-+ { NULL },
-+ { &cxusb_table[14], NULL },
-+ },
-+ }
-+};
-+
- static struct usb_driver cxusb_driver = {
- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
- .owner = THIS_MODULE,
---- v4l-dvb.orig/linux/drivers/media/dvb/dvb-usb/cxusb.h
-+++ v4l-dvb/linux/drivers/media/dvb/dvb-usb/cxusb.h
-@@ -28,6 +28,8 @@
- #define CMD_ANALOG 0x50
- #define CMD_DIGITAL 0x51
-
-+#define CMD_BLUEBIRD_GPIO_WRITE 0x05
-+
- struct cxusb_state {
- u8 gpio_write_state[3];
- };
---- v4l-dvb.orig/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
-+++ v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
-@@ -142,6 +142,8 @@
- #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51
- #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
- #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
-+#define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78
-+#define USB_PID_DVICO_BLUEBIRD_DVBT_NANO_2 0xdb70
- #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
- #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
- #define USB_PID_MEDION_MD95700 0x0932
---- v4l-dvb.orig/linux/drivers/media/dvb/frontends/Kconfig
-+++ v4l-dvb/linux/drivers/media/dvb/frontends/Kconfig
-@@ -353,6 +353,13 @@
- This device is only used inside a SiP called togther with a
- demodulator for now.
-
-+config DVB_XC3028
-+ tristate "Xceive XC3028 silicon tuner"
-+ depends on I2C
-+ default m if DVB_FE_CUSTOMISE
-+ help
-+ A driver for the silicon tuner XC3028 from Xceive.
-+
- comment "Miscellaneous devices"
- depends on DVB_CORE
-
---- v4l-dvb.orig/linux/drivers/media/dvb/frontends/Makefile
-+++ v4l-dvb/linux/drivers/media/dvb/frontends/Makefile
-@@ -4,6 +4,7 @@
-
- EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-
-+obj-$(CONFIG_DVB_XC3028) += xc3028-fe.o
- obj-$(CONFIG_DVB_PLL) += dvb-pll.o
- obj-$(CONFIG_DVB_STV0299) += stv0299.o
- obj-$(CONFIG_DVB_SP8870) += sp8870.o
---- /dev/null
-+++ v4l-dvb/linux/drivers/media/dvb/frontends/xc3028-fe.c
-@@ -0,0 +1,532 @@
-+/*
-+
-+ Xceive - xc3028 tuner interface (Firmware 2.7)
-+
-+ Copyright (c) 2007 Michael Krufky <mkrufky@linuxtv.org>
-+ Copyright (c) 2006 Markus Rechberger <mrechberger@gmail.com>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+*/
-+
-+#include <linux/i2c.h>
-+#include "compat.h"
-+#include <linux/firmware.h>
-+#include <linux/delay.h>
-+#include <media/tuner.h>
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-+#include "i2c-compat.h"
-+#endif
-+#include "dvb_frontend.h"
-+#include "xc3028.h"
-+
-+
-+struct xc3028_priv {
-+ u8 tuning_code[12];
-+ enum v4l2_tuner_type type;
-+ v4l2_std_id std;
-+ // unsigned int mode;
-+
-+ struct xc3028_config *cfg;
-+
-+ struct i2c_adapter *i2c_adap;
-+ u32 frequency;
-+ int bandwidth;
-+};
-+
-+MODULE_DESCRIPTION("Xceive xc3028 dvb frontend driver");
-+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
-+MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
-+MODULE_LICENSE("GPL");
-+
-+
-+/* hack */
-+#define V4L2_TUNER_DVBT_TV 19
-+#define V4L2_TUNER_DVBC_TV 29
-+#define V4L2_TUNER_ATSC_TV 39
-+
-+/* firmware functions */
-+#define XC3028_BYTECODE 0
-+#define XC3028_RESET 1
-+#define XC3028_SLEEP 2
-+
-+#define XC3028_BW8MHZ 0
-+#define XC3028_BW7MHZ 1
-+#define XC3028_BW6MHZ 2
-+#define XC3028_ATSC_BW6MHZ 3
-+#define XC3028_RADIO 4
-+
-+
-+#define XC3028_ANALOGUE_FW "xc3028_init0.i2c.fw"
-+#define XC3028_DIGITAL_FW "xc3028_8MHz_init0.i2c.fw"
-+#define XC3028_RADIO_FW "xc3028_FM_init0.i2c.fw"
-+#define XC3028_SPECIFIC_RADIO_FW "xc3028_specific_radio.fw"
-+
-+#define TUNING_GRANULARITY 15625
-+
-+static int firmware_loader(struct dvb_frontend *fe, const struct firmware *fw);
-+static int upload_firmware(struct dvb_frontend *fe);
-+static int xc3028_set_mode(struct dvb_frontend *fe, enum v4l2_tuner_type type);
-+
-+static struct _analogue_standards{
-+ v4l2_std_id standard;
-+ u8 filename[50];
-+} xc3028_standards[]={
-+ {V4L2_STD_PAL_BG,"xc3028_BG_PAL_A2_A.i2c.fw"},
-+ {V4L2_STD_PAL_I,"xc3028_I_PAL_NICAM.i2c.fw"},
-+ {V4L2_STD_PAL_DK,"xc3028_DK_PAL_A2.i2c.fw"},
-+ {V4L2_STD_MN,"xc3028_MN_NTSCPAL_A2.i2c.fw"},
-+ {V4L2_STD_PAL, "xc3028_BG_PAL_A2_A.i2c.fw"},
-+
-+ {V4L2_STD_SECAM_DK,"xc3028_DK_SECAM_A2_DK1.i2c.fw"},
-+ {V4L2_STD_SECAM_L,"xc3028_L_SECAM_NICAM.i2c.fw"},
-+ {V4L2_STD_SECAM_LC,"xc3028_L'_SECAM_NICAM.i2c.fw"},
-+ {V4L2_STD_SECAM_K1,"xc3028_DK_SECAM_A2_DK1.i2c.fw"},
-+};
-+
-+/* TODO: add the other standards here
-+ The linux DVB framework sends us following values
-+ from 0..2 to set up the correct channel bandwidth
-+
-+ 0 ... 8 mhz
-+ 1 ... 7 mhz
-+ 2 ... 6 mhz
-+
-+ we do not have any settings for 6MHz at least I haven't found one,
-+ feel free to complete this list
-+
-+ */
-+
-+static struct _digital_standards{
-+ unsigned int dvb:1;
-+ unsigned int atsc:1;
-+ int bandwidth;
-+ char filename[50];
-+} xc3028_dtv_standards[]={
-+ {1, 0, XC3028_BW8MHZ /* 8mhz */, "xc3028_DTV8_2633.i2c.fw" },
-+ {1, 0, XC3028_BW7MHZ /* 7mhz */, "xc3028_DTV7_2633.i2c.fw" },
-+ /* 2 6mhz */
-+ {0, 1, 0 /* ???? */, "xc3028_DTV6_ATSC_2620.i2c.fw"},
-+ {0, 1, 1 /* ???? */, "xc3028_DTV6_ATSC_2620.i2c.fw"},
-+ {0, 1, XC3028_ATSC_BW6MHZ, "xc3028_DTV6_ATSC_2620.i2c.fw"},
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+#define XC3028_I2C_ADDR 0x61
-+
-+static int xc3028_i2c_xfer(struct i2c_adapter* adap, char *buf, int len)
-+{
-+ int ret;
-+ struct i2c_msg msg = { .addr = XC3028_I2C_ADDR, .flags = 0,
-+ .buf = buf, .len = len };
-+
-+ ret = i2c_transfer(adap, &msg, 1);
-+
-+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
-+ transmitted, else error code. */
-+ return (ret == 1) ? len : ret;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int xc3028_set_params(struct dvb_frontend *fe,
-+ struct dvb_frontend_parameters *params)
-+{
-+ struct xc3028_priv *priv = fe->tuner_priv;
-+ const struct firmware *fw = NULL;
-+ unsigned char chanbuf[4];
-+ unsigned long frequency=0;
-+ unsigned long value;
-+ int bandwidth;
-+ int i;
-+ enum v4l2_tuner_type type;
-+
-+ if (fe->ops.info.type == FE_ATSC) {
-+ type = V4L2_TUNER_ATSC_TV;
-+ } else { // if (fe->ops.info.type == FE_OFDM)
-+ type = V4L2_TUNER_DVBT_TV;
-+ }
-+
-+ xc3028_set_mode(fe, type);
-+
-+ if (priv->type == V4L2_TUNER_ATSC_TV) {
-+ bandwidth = XC3028_ATSC_BW6MHZ;
-+ } else {
-+ bandwidth = params->u.ofdm.bandwidth;
-+ }
-+
-+ if (priv->bandwidth != bandwidth) {
-+ switch(bandwidth) {
-+ case -1:
-+ /* analogue */
-+ priv->bandwidth = bandwidth;
-+ break;
-+ case XC3028_ATSC_BW6MHZ:
-+ for (i = 0; i < ARRAY_SIZE(xc3028_dtv_standards); i++) {
-+ if (xc3028_dtv_standards[i].bandwidth == XC3028_ATSC_BW6MHZ) {
-+ printk("Loading 6MHz Bandwidth settings: %s\n",xc3028_dtv_standards[i].filename);
-+ if (request_firmware(&fw, xc3028_dtv_standards[i].filename, &priv->i2c_adap->dev) == 0) {
-+ if (firmware_loader(fe,fw) != 0) {
-+ release_firmware(fw);
-+ printk("xc3028-tuner.c: error uploading firmware!\n");
-+ return -EINVAL;
-+ }
-+ release_firmware(fw);
-+ break;
-+ } else
-+ printk("Loading firmware from file failed!\n");
-+ }
-+ }
-+ priv->bandwidth = bandwidth;
-+ break;
-+ case XC3028_BW8MHZ: /* 8 MHz */
-+ for (i = 0; i < ARRAY_SIZE(xc3028_dtv_standards); i++) {
-+ if (xc3028_dtv_standards[i].bandwidth == XC3028_BW8MHZ) {
-+ printk("Loading 8MHz Bandwidth settings: %s\n",xc3028_dtv_standards[i].filename);
-+ if (request_firmware(&fw, xc3028_dtv_standards[i].filename, &priv->i2c_adap->dev) == 0) {
-+ if (firmware_loader(fe,fw) != 0) {
-+ release_firmware(fw);
-+ printk("xc3028-tuner.c: error uploading firmware!\n");
-+ return -EINVAL;
-+ }
-+ release_firmware(fw);
-+ break;
-+ } else
-+ printk("Loading firmware from file failed!\n");
-+ }
-+ }
-+ priv->bandwidth = bandwidth;
-+ break;
-+ case XC3028_BW7MHZ: /* 7 MHz */
-+ for (i = 0; i < ARRAY_SIZE(xc3028_dtv_standards); i++) {
-+ if (xc3028_dtv_standards[i].bandwidth == XC3028_BW7MHZ) {
-+ printk("Loading 7MHz Bandwidth settings: %s\n",xc3028_dtv_standards[i].filename);
-+ if (request_firmware(&fw, xc3028_dtv_standards[i].filename, &priv->i2c_adap->dev) == 0) {
-+ if (firmware_loader(fe,fw) != 0) {
-+ release_firmware(fw);
-+ printk("xc3028-tuner.c: error uploading firmware!\n");
-+ return -EINVAL;
-+ }
-+ release_firmware(fw);
-+ break;
-+ } else
-+ printk("Loading firmware from file failed!\n");
-+ }
-+ }
-+ priv->bandwidth = bandwidth;
-+ break;
-+ default:
-+ printk("xc3028-tuner.c: sorry [%d] bandwidth isn't supported (please report)\n",bandwidth);
-+ }
-+ }
-+ /* TODO: 7 MHz (1) has the same offset as 8 MHz -- this depends on the used firmware */
-+#if 0
-+ if(t->mode == V4L2_TUNER_RADIO){
-+ frequency=(unsigned long long)f->frequency*1000/16;
-+ } else { }
-+#endif
-+ switch(bandwidth) {
-+ case XC3028_BW8MHZ:
-+ case XC3028_BW7MHZ:
-+ frequency=(unsigned long long)params->frequency-2750000;
-+ break;
-+ case XC3028_BW6MHZ:
-+ case XC3028_ATSC_BW6MHZ:
-+ frequency=(unsigned long long)params->frequency-1750000;
-+ break;
-+ default:
-+ frequency=(unsigned long long)params->frequency;
-+ }
-+
-+ value=(frequency+(TUNING_GRANULARITY/2))/TUNING_GRANULARITY;
-+ chanbuf[0]=0;
-+ chanbuf[1]=0;
-+ chanbuf[2]=(value&0xff00)>>8;
-+ chanbuf[3]=value&0x00ff;
-+
-+#if 0
-+ /* seems like it's not needed! */
-+ rc=i2c_master_send(c,"\xa0\x00\x00\x00",4);
-+ if(priv && priv->tuning_code)
-+ i2c_master_send(c,priv->tuning_code,12);
-+ else
-+ printk("ERROR: *** NO TUNING CODE SET **\n");
-+ i2c_master_send(c,"\x00\x8c",2);
-+#endif
-+ xc3028_i2c_xfer(priv->i2c_adap,"\x80\x02\x00\x00",4);
-+ xc3028_i2c_xfer(priv->i2c_adap,chanbuf,4);
-+ return 0;
-+}
-+
-+static int firmware_loader(struct dvb_frontend *fe, const struct firmware *fw)
-+{
-+ int txtlen=0;
-+ int current_ptr=0;
-+ int version;
-+ int function;
-+ int x;
-+ struct xc3028_priv *priv = fe->tuner_priv;
-+
-+ if (fw->size == 0)
-+ return -EINVAL;
-+
-+ version = fw->data[current_ptr++];
-+
-+ switch (version) {
-+ case 1:
-+ while (current_ptr < fw->size) {
-+ function = fw->data[current_ptr++];
-+ switch (function) {
-+ case XC3028_BYTECODE:
-+ txtlen = fw->data[current_ptr++];
-+ if ((current_ptr + txtlen) > fw->size)
-+ return -EINVAL;
-+ if (fw->data[current_ptr]==0x1e && txtlen == 12){
-+ memcpy(priv->tuning_code, &fw->data[current_ptr], 12);
-+ }
-+ if (txtlen != xc3028_i2c_xfer(priv->i2c_adap,&fw->data[current_ptr],txtlen)) {
-+ printk("failed: %02x| ",txtlen);
-+ for(x=0; x < txtlen; x++) {
-+ printk("%02x ",(unsigned char)fw->data[current_ptr+x]);
-+ }
-+ printk("\n");
-+ }
-+
-+ current_ptr += txtlen;
-+ break;
-+ case XC3028_RESET:
-+ x = fw->data[current_ptr++];
-+
-+ if ((priv->cfg) && (priv->cfg->gpio_reset))
-+ priv->cfg->gpio_reset(fe,x);
-+ else
-+ printk("XC3028: NO GPIO CALLBACK FUNCTION PROVIDED - SWITCHING MODES WON'T WORK (GPIO FW ARG: %d)!\n",x);
-+ break;
-+ case XC3028_SLEEP:
-+ msleep(fw->data[current_ptr++]);
-+ break;
-+ default:
-+ printk("xc3028-tuner.c: error while loading firmware!\n");
-+ return -EINVAL;
-+ }
-+ }
-+ break;
-+ default:
-+ printk("xc3028-tuner.c: Firmware Loader: Unknown firmware version (%d)\n",version);
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+static int upload_firmware(struct dvb_frontend *fe) {
-+ struct xc3028_priv *priv = fe->tuner_priv;
-+ const struct firmware *fw = NULL;
-+ int i;
-+
-+ switch (priv->type) {
-+ case V4L2_TUNER_ANALOG_TV:
-+ printk("Loading base firmware: %s\n", XC3028_ANALOGUE_FW);
-+ if (request_firmware(&fw, XC3028_ANALOGUE_FW, &priv->i2c_adap->dev) == 0) {
-+ firmware_loader(fe,fw);
-+ release_firmware(fw);
-+ } else {
-+ printk("xc3028-tuner.c: Unable to load firmware\n");
-+ printk("xc3028-tuner.c: ** PLEASE HAVE A LOOK AT **\n");
-+ printk("xc3028-tuner.c: http://linuxtv.org/v4lwiki/index.php/Talk:Em2880#Firmware\n");
-+ return -EINVAL;
-+ }
-+ for (i = 0; i < ARRAY_SIZE(xc3028_standards); i++) {
-+ if (xc3028_standards[i].standard & priv->std) {
-+ printk("%s, Loading specific analogue TV settings: %s\n",__FUNCTION__, xc3028_standards[i].filename);
-+ if (request_firmware(&fw, xc3028_standards[i].filename, &priv->i2c_adap->dev) == 0){
-+ if(firmware_loader(fe,fw)==0){
-+ release_firmware(fw);
-+ return 0;
-+ }
-+ release_firmware(fw);
-+ } else {
-+ printk("Loading configuration from file failed!\n");
-+ }
-+ break;
-+ }
-+ }
-+ printk("Loading default analogue TV settings: %s\n",xc3028_standards[0].filename);
-+ priv->std=xc3028_standards[0].standard;
-+ if (request_firmware(&fw, xc3028_standards[0].filename, &priv->i2c_adap->dev) == 0) {
-+ if (firmware_loader(fe,fw) == 0) {
-+ release_firmware(fw);
-+ return 0;
-+ }
-+ release_firmware(fw);
-+ }
-+ printk("xc3028-tuner.c: error loading firmware (analogue TV)! (please report -> mrechberger@gmail.com)\n");
-+ break;
-+ case V4L2_TUNER_DVBT_TV:
-+ case V4L2_TUNER_DVBC_TV:
-+ case V4L2_TUNER_ATSC_TV:
-+ printk("Loading base firmware: %s\n", XC3028_DIGITAL_FW);
-+ /* reset analog standard */
-+ priv->std = 0;
-+ if (request_firmware(&fw, XC3028_DIGITAL_FW, &priv->i2c_adap->dev) == 0) {
-+ firmware_loader(fe,fw);
-+ release_firmware(fw);
-+ } else {
-+ printk("xc3028-tuner.c: Unable to load firmware\n");
-+ printk("xc3028-tuner.c: ** PLEASE HAVE A LOOK AT **\n");
-+ printk("xc3028-tuner.c: http://linuxtv.org/v4lwiki/index.php/Talk:Em2880#Firmware\n");
-+ return -EINVAL;
-+ }
-+ for( i = 0; i < ARRAY_SIZE(xc3028_dtv_standards); i++) {
-+ if ((xc3028_dtv_standards[i].dvb==1 &&
-+ xc3028_dtv_standards[i].bandwidth == priv->bandwidth) ||
-+ (priv->type == V4L2_TUNER_ATSC_TV &&
-+ xc3028_dtv_standards[i].atsc == 1)) {
-+ printk("Loading specific dtv settings: %s\n",xc3028_dtv_standards[i].filename);
-+ if (request_firmware(&fw, xc3028_dtv_standards[i].filename, &priv->i2c_adap->dev) == 0) {
-+ if (firmware_loader(fe,fw) == 0) {
-+ release_firmware(fw);
-+ return 0;
-+ }
-+ release_firmware(fw);
-+ }
-+ }
-+ i++;
-+ }
-+
-+ /* this gets accessed if a switchover occures, t->bandwidth will be set to -1 */
-+ printk("Loading default dtv settings: %s\n",xc3028_dtv_standards[0].filename);
-+ priv->bandwidth = xc3028_dtv_standards[0].bandwidth;
-+ if (request_firmware(&fw, xc3028_dtv_standards[0].filename, &priv->i2c_adap->dev) == 0) {
-+ if (firmware_loader(fe,fw) == 0) {
-+ release_firmware(fw);
-+ return 0;
-+ }
-+ release_firmware(fw);
-+ }
-+ printk("xc3028-tuner.c: error loading firmware (analogue TV)! (please report -> mrechberger@gmail.com)\n");
-+ break;
-+ case V4L2_TUNER_RADIO:
-+ printk("Loading base firmware: %s\n", XC3028_RADIO_FW);
-+ if (request_firmware(&fw, XC3028_RADIO_FW, &priv->i2c_adap->dev) == 0) {
-+ firmware_loader(fe,fw);
-+ release_firmware(fw);
-+ } else {
-+ printk("xc3028-tuner.c: Unable to load (radio) firmware\n");
-+ printk("xc3028-tuner.c: ** PLEASE HAVE A LOOK AT **\n");
-+ printk("xc3028-tuner.c: http://linuxtv.org/v4lwiki/index.php/Talk:Em2880#Firmware\n");
-+ return -EINVAL;
-+ }
-+ printk("%s, Loading specific radio firmware: %s\n",__FUNCTION__, XC3028_SPECIFIC_RADIO_FW);
-+ if (request_firmware(&fw, XC3028_SPECIFIC_RADIO_FW, &priv->i2c_adap->dev) == 0) {
-+ if (firmware_loader(fe,fw) == 0) {
-+ release_firmware(fw);
-+ return 0;
-+ }
-+ release_firmware(fw);
-+ } else {
-+ printk("Loading configuration from file failed!\n");
-+ }
-+ return 0;
-+ default:
-+ printk("ERROR TUNER TYPE NOT SUPPORTED (%d)\n",priv->type);
-+ return -EINVAL;
-+ }
-+
-+ printk("xc3028-tuner.c: *********************************************************\n");
-+ printk("xc3028-tuner.c: no firmware uploaded\n" );
-+ printk("xc3028-tuner.c: ** please have a look at: **\n");
-+ printk("xc3028-tuner.c: http://linuxtv.org/v4lwiki/index.php/Talk:Em2880#Firmware\n");
-+ printk("xc3028-tuner.c: *********************************************************\n");
-+
-+ return -EINVAL;
-+}
-+
-+static int xc3028_set_mode(struct dvb_frontend *fe, enum v4l2_tuner_type type)
-+{
-+ struct xc3028_priv *priv = fe->tuner_priv;
-+
-+ priv->type = type;
-+
-+ upload_firmware(fe);
-+
-+ if (priv->cfg && priv->cfg->gpio_reset && (priv->type == V4L2_TUNER_DVBT_TV ||
-+ priv->type == V4L2_TUNER_DVBC_TV ||
-+ priv->type == V4L2_TUNER_ATSC_TV )) {
-+ printk("xc3028-tuner.c: sending extra call for DVB-T\n");
-+ priv->cfg->gpio_reset(fe,2);
-+ }
-+
-+ return 0;
-+}
-+
-+/* dvb tuner api */
-+static int xc3028_release(struct dvb_frontend *fe)
-+{
-+ kfree(fe->tuner_priv);
-+ fe->tuner_priv = NULL;
-+ return 0;
-+}
-+
-+static int xc3028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-+{
-+ struct xc3028_priv *priv = fe->tuner_priv;
-+
-+ *frequency = priv->frequency*1000/16*1000;
-+ return 0;
-+}
-+
-+static int xc3028_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-+{
-+ struct xc3028_priv *priv = fe->tuner_priv;
-+
-+ *bandwidth = priv->bandwidth;
-+ return 0;
-+}
-+
-+static const struct dvb_tuner_ops xc3028_tuner_ops = {
-+ .info = {
-+ .name = "Xceive XC3028",
-+#if 0
-+ .frequency_min = ,
-+ .frequency_max =
-+#endif
-+ },
-+ .release = xc3028_release,
-+ .set_params = xc3028_set_params,
-+ .get_frequency = xc3028_get_frequency,
-+ .get_bandwidth = xc3028_get_bandwidth,
-+};
-+
-+struct dvb_frontend *xc3028_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct xc3028_config *cfg)
-+{
-+ struct xc3028_priv *priv = kzalloc(sizeof(struct xc3028_priv),GFP_KERNEL);
-+
-+ priv->i2c_adap = i2c;
-+ priv->bandwidth=XC3028_BW8MHZ;
-+ priv->cfg = cfg;
-+
-+ memcpy(&fe->ops.tuner_ops, &xc3028_tuner_ops, sizeof(struct dvb_tuner_ops));
-+ fe->tuner_priv = priv;
-+ return fe;
-+}
-+EXPORT_SYMBOL(xc3028_attach);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-basic-offset: 8
-+ * End:
-+ */
---- /dev/null
-+++ v4l-dvb/linux/drivers/media/dvb/frontends/xc3028.h
-@@ -0,0 +1,56 @@
-+ /*
-+ Header for Xceive Silicon tuners
-+
-+ (c) 2007 Michael Krufky
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+ */
-+
-+#ifndef __DVB_XC3028_H__
-+#define __DVB_XC3028_H__
-+
-+#include <linux/i2c.h>
-+#include "dvb_frontend.h"
-+
-+/**
-+ * Attach a xc3028 tuner to the supplied frontend structure.
-+ *
-+ * @param fe Frontend to attach to.
-+ * @param i2c i2c adapter to use.
-+ * @param cfg config struct with gpio reset callback.
-+ * @return FE pointer on success, NULL on failure.
-+ */
-+
-+struct xc3028_config {
-+ int (*gpio_reset) (struct dvb_frontend *fe, int ptr);
-+};
-+
-+#if defined(CONFIG_DVB_XC3028) || (defined(CONFIG_DVB_XC3028_MODULE) && defined(MODULE))
-+extern struct dvb_frontend* xc3028_attach(struct dvb_frontend *fe,
-+ struct i2c_adapter *i2c,
-+ struct xc3028_config *cfg);
-+#else
-+static inline struct dvb_frontend* xc3028_attach(struct dvb_frontend *fe,
-+ struct i2c_adapter *i2c,
-+ struct xc3028_config *cfg)
-+{
-+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
-+ return NULL;
-+}
-+#endif // CONFIG_DVB_XC3028
-+
-+#endif // __DVB_XC3028_H__
---- v4l-dvb.orig/v4l/versions.txt
-+++ v4l-dvb/v4l/versions.txt
-@@ -228,3 +228,4 @@
- USB_ZC0301
- USB_ET61X251
- USB_ZR364XX
-+DVB_XC3028