diff options
Diffstat (limited to 'abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch')
-rw-r--r-- | abs/extra-testing/v4l-dvb-dvico/xc-bluebird.patch | 896 |
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 |