diff options
author | Markus Rechberger <devnull@localhost> | 2006-01-25 09:48:37 +0000 |
---|---|---|
committer | Markus Rechberger <devnull@localhost> | 2006-01-25 09:48:37 +0000 |
commit | 8c995fe9b63c4e6b6c8d95a6ad3457c2e6751b20 (patch) | |
tree | ea72625b9fce3183864de7a4fe015b8f747ed337 /v4l_experimental/xc3028 | |
parent | a25dd947a39d66c4d6f78b18df1e9c07185546c3 (diff) | |
download | mediapointer-dvb-s2-8c995fe9b63c4e6b6c8d95a6ad3457c2e6751b20.tar.gz mediapointer-dvb-s2-8c995fe9b63c4e6b6c8d95a6ad3457c2e6751b20.tar.bz2 |
Hauppauge HVR 900 driver support
From: Markus Rechberger <mrechberger@gmail.com>
Signed-off-by: Markus Rechberger <mrechberger@gmail.com>
Diffstat (limited to 'v4l_experimental/xc3028')
-rw-r--r-- | v4l_experimental/xc3028/README | 35 | ||||
-rw-r--r-- | v4l_experimental/xc3028/convert.c | 84 | ||||
-rw-r--r-- | v4l_experimental/xc3028/em28xx-cards.c | 355 | ||||
-rw-r--r-- | v4l_experimental/xc3028/em28xx.h | 518 | ||||
-rw-r--r-- | v4l_experimental/xc3028/tuner-core.c | 946 | ||||
-rw-r--r-- | v4l_experimental/xc3028/tuner-types.c | 1480 | ||||
-rw-r--r-- | v4l_experimental/xc3028/tuner.h | 259 | ||||
-rw-r--r-- | v4l_experimental/xc3028/xc3028.c | 225 |
8 files changed, 3902 insertions, 0 deletions
diff --git a/v4l_experimental/xc3028/README b/v4l_experimental/xc3028/README new file mode 100644 index 000000000..c2ed2e7c1 --- /dev/null +++ b/v4l_experimental/xc3028/README @@ -0,0 +1,35 @@ +== Hauppauge HVR 900 == + +==== Installation ==== + +1. copy tuner.h into ./linux/include/media/ in your v4l directory +2. simply replace following files in the repository + * em28xx-cards.c + * em28xx.h + * tuner-core.c + * tuner-types.c + * xc3028.c +with the files in this directory and simply recompile + +==== Firmware ==== + +this device needs a firmware, which is stored in emBDA.sys +build the firmwareextractor with +$ gcc convert.c -o convert +and extract the firmware +$ ./convert emBDA.sys > /var/lib/xceive_xc_3028.fw +(I only tested that tool with Hauppauge HVR 900, Terratec might work too but without any guarantee - please send me BDA files of other xc3028 devices) + +==== General ==== + + * the xc3028 works very reliable and the frequencies are correct for europe + * Please add your email, product name, vendor/product id to the discussion in the v4l wiki at www.linuxtv.org + * I'll not be responsible for any damage caused by this driver, use it with your own risk + +==== TODO ==== + + * some cleanup + * figuring out channel locks + + +Markus Rechberger <mrechberger@gmail.com> diff --git a/v4l_experimental/xc3028/convert.c b/v4l_experimental/xc3028/convert.c new file mode 100644 index 000000000..00b1f7d9d --- /dev/null +++ b/v4l_experimental/xc3028/convert.c @@ -0,0 +1,84 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#define ARRAY_SIZE(fw) sizeof(fw)/sizeof(fw[0]) +struct{ + char *fwname; + char *fwstart; + char *fwstart2; + int length1; + int length2; +} xc_firmware[]={{"Terratec","\x2a\x03\xe5\xe0\x00\x07\xf4\xd0\x01\xc0\x70\xe0\x00\x07","\x2a\x00\xc3\xe0\x00\x07\xb9\xf1\x05\x01\x6e\x82\x02\x82",2480,3876}, + {"Hauppauge","\x2a\x03\xcc\xe0\x00\x07\xf4\xd0\x01\xc0\x70\xe0\x00\x07","\x2a\x00\xbe\xe0\x00\x07\xb9\xf1\x05\x01\x69\x82\x02\x82",2532,3886}}; + +int main(int argc, char **argv){ + FILE *file; + char buffer[1024]; + char *fwmem=0; + int len; + long fleng=0; + int i; + int n=0; + int x; + int done=0; + int d=0; + int e=0; + if(argc!=2){ + printf("./convert <filename>\n"); + exit(1); + } + file=fopen(argv[1],"r"); + fprintf(stderr,"Firmware extractor 0.1\n"); + while((len=fread(buffer,1,1024,file))){ + fleng+=len; + fwmem=realloc(fwmem,fleng); + memcpy(&fwmem[fleng-len],buffer,len); + } + fprintf(stderr,"Stored in memory: %ld\n",fleng); + for(n=0;n<ARRAY_SIZE(xc_firmware);n++){ + for(i=0;i<fleng&&done!=2;i++){ + if(xc_firmware[n].fwstart[d]==fwmem[i]&&done!=1){ + if(d==13){ + fprintf(stderr,"==== %s ====\n",xc_firmware[n].fwname); + printf("%d\n",xc_firmware[n].length1); + fprintf(stderr,"FW part 1 found!\n"); + fprintf(stderr,"Length: %d bytes\n",xc_firmware[n].length1); + for(x=1;x<=xc_firmware[n].length1;x++){ + fprintf(stderr,"%02x ",((unsigned char*)fwmem)[i-13+x]); + printf("%c",((unsigned char*)fwmem)[i-13+x]); + if(x%63==0){ + fprintf(stderr,"\n"); + } + } + fprintf(stderr,"\n"); + done++; + } + d++; + } else { + d=0; + } + if(xc_firmware[n].fwstart2[e]==fwmem[i]){ + if(e==13){ + fprintf(stderr,"-------------------------------------------\n"); + fprintf(stderr,"FW part 2 found!\n"); + fprintf(stderr,"Length: %d bytes\n",xc_firmware[n].length2); + for(x=1;x<=xc_firmware[n].length2;x++){ + printf("%c",((unsigned char*)fwmem)[i-13+x]); + fprintf(stderr,"%02x ",((unsigned char*)fwmem)[i-13+x]); + if(x%63==0){ + fprintf(stderr,"\n"); + } + } + done++; + } + e++; + } else { + e=0; + } + } + } + free(fwmem); + fclose(file); + exit(0); +} diff --git a/v4l_experimental/xc3028/em28xx-cards.c b/v4l_experimental/xc3028/em28xx-cards.c new file mode 100644 index 000000000..ebf451ae0 --- /dev/null +++ b/v4l_experimental/xc3028/em28xx-cards.c @@ -0,0 +1,355 @@ +/* + em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + + Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> + Markus Rechberger <mrechberger@gmail.com> + Mauro Carvalho Chehab <mchehab@brturbo.com.br> + Sascha Sommer <saschasommer@freenet.de> + + 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/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/usb.h> +#include "compat.h" +#include <media/tuner.h> +#include <media/audiochip.h> +#include <media/tveeprom.h> +#include <media/v4l2-common.h> +#include "msp3400.h" + +#include "em28xx.h" + +struct em28xx_board em28xx_boards[] = { + [EM2800_BOARD_UNKNOWN] = { + .name = "Unknown EM2800 video grabber", + .is_em2800 = 1, + .vchannels = 2, + .norm = VIDEO_MODE_PAL, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_UNKNOWN] = { + .name = "Unknown EM2820/2840 video grabber", + .is_em2800 = 0, + .vchannels = 2, + .norm = VIDEO_MODE_PAL, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_TERRATEC_CINERGY_250] = { + .name = "Terratec Cinergy 250 USB", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_PINNACLE_USB_2] = { + .name = "Pinnacle PCTV USB 2", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = { + .name = "Hauppauge WinTV USB 2", + .vchannels = 3, + .norm = VIDEO_MODE_NTSC, + .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, + .has_tuner = 1, + .decoder = EM28XX_TVP5150, + .has_msp34xx = 1, + /*FIXME: S-Video not tested */ + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 0, + .amux = 6, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 2, + .amux = 1, + }}, + }, + [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { + .name = "WinTV HVR 900", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .has_tuner = 1, + .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XCEIVE_XC3028, + .has_tuner = 1, + .decoder = EM28XX_TVP5150, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 0, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2880_BOARD_TERRATEC_HYBRID_XS] = { + .name = "Terratec Hybrid XS", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .has_tuner = 1, + .tda9887_conf = TDA9887_PRESENT, + .tuner_type = TUNER_XCEIVE_XC3028, + .has_tuner = 1, + .decoder = EM28XX_TVP5150, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 0, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_MSI_VOX_USB_2] = { + .name = "MSI VOX USB 2.0", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, + .has_tuner = 1, + .decoder = EM28XX_SAA7114, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 4, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2800_BOARD_TERRATEC_CINERGY_200] = { + .name = "Terratec Cinergy 200 USB", + .is_em2800 = 1, + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { + .name = "Leadtek Winfast USB II", + .is_em2800 = 1, + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2800_BOARD_KWORLD_USB2800] = { + .name = "Kworld USB2800", + .is_em2800 = 1, + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_PHILIPS_ATSC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_PINNACLE_DVC_90] = { + .name = "Pinnacle Dazzle DVC 90", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .has_tuner = 0, + .decoder = EM28XX_SAA7113, + .input = {{ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM28XX_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, +}; +const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); + +/* table of devices that work with this driver */ +struct usb_device_id em28xx_id_table [] = { + { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 }, + { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, + { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, + { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, + { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, + { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, + { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, + { }, +}; + +void em28xx_pre_card_setup(struct em28xx *dev) +{ + /* request some modules */ + switch(dev->model){ + case EM2880_BOARD_TERRATEC_HYBRID_XS: + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + { + em28xx_write_regs_req(dev, 0x00, 0x08, "\x7d", 1); // reset through GPIO? + break; + } + } +} + +void em28xx_card_setup(struct em28xx *dev) +{ + /* request some modules */ + switch(dev->model){ + case EM2880_BOARD_TERRATEC_HYBRID_XS: + case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: + { + struct tveeprom tv; +#ifdef CONFIG_MODULES + request_module("tveeprom"); + request_module("ir-kbd-i2c"); + request_module("msp3400"); +#endif + /* Call first TVeeprom */ + + dev->i2c_client.addr = 0xa0 >> 1; + tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); + + dev->tuner_type= tv.tuner_type; + if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { + dev->i2s_speed=2048000; + dev->has_msp34xx=1; + } else + dev->has_msp34xx=0; + break; + } + } +} + +EXPORT_SYMBOL(em28xx_boards); +EXPORT_SYMBOL(em28xx_bcount); +EXPORT_SYMBOL(em28xx_id_table); + +MODULE_DEVICE_TABLE (usb, em28xx_id_table); diff --git a/v4l_experimental/xc3028/em28xx.h b/v4l_experimental/xc3028/em28xx.h new file mode 100644 index 000000000..74fe6a047 --- /dev/null +++ b/v4l_experimental/xc3028/em28xx.h @@ -0,0 +1,518 @@ +/* + em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices + + Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> + Ludovico Cavedon <cavedon@sssup.it> + Mauro Carvalho Chehab <mchehab@brturbo.com.br> + + Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de> + + 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 _EM28XX_H +#define _EM28XX_H + +#include "compat.h" +#include <linux/videodev.h> +#include <linux/i2c.h> +#include <media/ir-kbd-i2c.h> + +/* Boards supported by driver */ + +#define EM2800_BOARD_UNKNOWN 0 +#define EM2820_BOARD_UNKNOWN 1 +#define EM2820_BOARD_TERRATEC_CINERGY_250 2 +#define EM2820_BOARD_PINNACLE_USB_2 3 +#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 +#define EM2820_BOARD_MSI_VOX_USB_2 5 +#define EM2800_BOARD_TERRATEC_CINERGY_200 6 +#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 +#define EM2800_BOARD_KWORLD_USB2800 8 +#define EM2820_BOARD_PINNACLE_DVC_90 9 +#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 +#define EM2880_BOARD_TERRATEC_HYBRID_XS 11 + +#define UNSET -1 + +/* maximum number of em28xx boards */ +#define EM28XX_MAXBOARDS 1 /*FIXME: should be bigger */ + +/* maximum number of frames that can be queued */ +#define EM28XX_NUM_FRAMES 5 +/* number of frames that get used for v4l2_read() */ +#define EM28XX_NUM_READ_FRAMES 2 + +/* number of buffers for isoc transfers */ +#define EM28XX_NUM_BUFS 5 + +/* number of packets for each buffer + windows requests only 40 packets .. so we better do the same + this is what I found out for all alternate numbers there! + */ +#define EM28XX_NUM_PACKETS 40 + +/* default alternate; 0 means choose the best */ +#define EM28XX_PINOUT 0 + +#define EM28XX_INTERLACED_DEFAULT 1 + +/* +#define (use usbview if you want to get the other alternate number infos) +#define +#define alternate number 2 +#define Endpoint Address: 82 + Direction: in + Attribute: 1 + Type: Isoc + Max Packet Size: 1448 + Interval: 125us + + alternate number 7 + + Endpoint Address: 82 + Direction: in + Attribute: 1 + Type: Isoc + Max Packet Size: 3072 + Interval: 125us +*/ + +/* time to wait when stopping the isoc transfer */ +#define EM28XX_URB_TIMEOUT msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) + +/* time in msecs to wait for i2c writes to finish */ +#define EM2800_I2C_WRITE_TIMEOUT 20 + +/* the various frame states */ +enum em28xx_frame_state { + F_UNUSED = 0, + F_QUEUED, + F_GRABBING, + F_DONE, + F_ERROR, +}; + +/* stream states */ +enum em28xx_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +/* frames */ +struct em28xx_frame_t { + void *bufmem; + struct v4l2_buffer buf; + enum em28xx_frame_state state; + struct list_head frame; + unsigned long vma_use_count; + int top_field; + int fieldbytesused; +}; + +/* io methods */ +enum em28xx_io_method { + IO_NONE, + IO_READ, + IO_MMAP, +}; + +/* inputs */ + +#define MAX_EM28XX_INPUT 4 +enum enum28xx_itype { + EM28XX_VMUX_COMPOSITE1 = 1, + EM28XX_VMUX_COMPOSITE2, + EM28XX_VMUX_COMPOSITE3, + EM28XX_VMUX_COMPOSITE4, + EM28XX_VMUX_SVIDEO, + EM28XX_VMUX_TELEVISION, + EM28XX_VMUX_CABLE, + EM28XX_VMUX_DVB, + EM28XX_VMUX_DEBUG, + EM28XX_RADIO, +}; + +struct em28xx_input { + enum enum28xx_itype type; + unsigned int vmux; + unsigned int amux; +}; + +#define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) + +enum em28xx_decoder { + EM28XX_TVP5150, + EM28XX_SAA7113, + EM28XX_SAA7114 +}; + +struct em28xx_board { + char *name; + int vchannels; + int norm; + int tuner_type; + + /* i2c flags */ + unsigned int is_em2800; + unsigned int tda9887_conf; + + unsigned int has_tuner:1; + unsigned int has_msp34xx:1; + + enum em28xx_decoder decoder; + + struct em28xx_input input[MAX_EM28XX_INPUT]; +}; + +struct em28xx_eeprom { + u32 id; /* 0x9567eb1a */ + u16 vendor_ID; + u16 product_ID; + + u16 chip_conf; + + u16 board_conf; + + u16 string1, string2, string3; + + u8 string_idx_table; +}; + +/* device states */ +enum em28xx_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +/* tvnorms */ +struct em28xx_tvnorm { + char *name; + v4l2_std_id id; + /* mode for saa7113h */ + int mode; +}; + +/* main device struct */ +struct em28xx { + /* generic device properties */ + char name[30]; /* name (including minor) of the device */ + int model; /* index in the device_data struct */ + int devno; /* marks the number of this device */ + unsigned int is_em2800; + int video_inputs; /* number of video inputs */ + struct list_head devlist; + unsigned int has_tuner:1; + unsigned int has_msp34xx:1; + unsigned int has_tda9887:1; + + u32 i2s_speed; /* I2S speed for audio digital stream */ + + enum em28xx_decoder decoder; + + int tuner_type; /* type of the tuner */ + int tuner_addr; /* tuner address */ + int tda9887_conf; + /* i2c i/o */ + struct i2c_adapter i2c_adap; + struct i2c_client i2c_client; + /* video for linux */ + int users; /* user count for exclusive use */ + struct video_device *vdev; /* video for linux device struct */ + struct video_picture vpic; /* picture settings only used to init saa7113h */ + struct em28xx_tvnorm *tvnorm; /* selected tv norm */ + int ctl_freq; /* selected frequency */ + unsigned int ctl_input; /* selected input */ + unsigned int ctl_ainput; /* slected audio input */ + int mute; + int volume; + /* frame properties */ + struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */ + int num_frames; /* number of frames currently in use */ + unsigned int frame_count; /* total number of transfered frames */ + struct em28xx_frame_t *frame_current; /* the frame that is being filled */ + int width; /* current frame width */ + int height; /* current frame height */ + int frame_size; /* current frame size */ + int field_size; /* current field size */ + int bytesperline; + int hscale; /* horizontal scale factor (see datasheet) */ + int vscale; /* vertical scale factor (see datasheet) */ + int interlaced; /* 1=interlace fileds, 0=just top fileds */ + int type; + + /* states */ + enum em28xx_dev_state state; + enum em28xx_stream_state stream; + enum em28xx_io_method io; + /* locks */ + struct semaphore lock, fileop_lock; + spinlock_t queue_lock; + struct list_head inqueue, outqueue; + wait_queue_head_t open, wait_frame, wait_stream; + struct video_device *vbi_dev; + + unsigned char eedata[256]; + + /* usb transfer */ + struct usb_device *udev; /* the usb device */ + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ + char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ + /* helper funcs that call usb_control_msg */ + int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf, + int len); + int (*em28xx_read_reg) (struct em28xx * dev, u16 reg); + int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg, + char *buf, int len); + int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg, + char *buf, int len); + int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg); +}; + +/* Provided by em28xx-i2c.c */ + +void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg); +int em28xx_i2c_register(struct em28xx *dev); +int em28xx_i2c_unregister(struct em28xx *dev); + +/* Provided by em28xx-input.c */ + +void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir); + +/* Provided by em28xx-core.c */ + +u32 em28xx_request_buffers(struct em28xx *dev, u32 count); +void em28xx_queue_unusedframes(struct em28xx *dev); +void em28xx_release_buffers(struct em28xx *dev); + +int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, + char *buf, int len); +int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg); +int em28xx_read_reg(struct em28xx *dev, u16 reg); +int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, + int len); +int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); +int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, + u8 bitmask); +int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val); +int em28xx_audio_analog_set(struct em28xx *dev); +int em28xx_colorlevels_set_default(struct em28xx *dev); +int em28xx_capture_start(struct em28xx *dev, int start); +int em28xx_outfmt_set_yuv422(struct em28xx *dev); +int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, + u8 ymax); +int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, + u16 width, u16 height); +int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v); +int em28xx_resolution_set(struct em28xx *dev); +void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs); +int em28xx_init_isoc(struct em28xx *dev); +void em28xx_uninit_isoc(struct em28xx *dev); +int em28xx_set_alternate(struct em28xx *dev); + +/* Provided by em28xx-cards.c */ +extern int em2800_variant_detect(struct usb_device* udev,int model); +extern void em28xx_pre_card_setup(struct em28xx *dev); +extern void em28xx_card_setup(struct em28xx *dev); +extern struct em28xx_board em28xx_boards[]; +extern struct usb_device_id em28xx_id_table[]; +extern const unsigned int em28xx_bcount; + +/* em28xx registers */ +#define CHIPID_REG 0x0a +#define USBSUSP_REG 0x0c /* */ + +#define AUDIOSRC_REG 0x0e +#define XCLK_REG 0x0f + +#define VINMODE_REG 0x10 +#define VINCTRL_REG 0x11 +#define VINENABLE_REG 0x12 /* */ + +#define GAMMA_REG 0x14 +#define RGAIN_REG 0x15 +#define GGAIN_REG 0x16 +#define BGAIN_REG 0x17 +#define ROFFSET_REG 0x18 +#define GOFFSET_REG 0x19 +#define BOFFSET_REG 0x1a + +#define OFLOW_REG 0x1b +#define HSTART_REG 0x1c +#define VSTART_REG 0x1d +#define CWIDTH_REG 0x1e +#define CHEIGHT_REG 0x1f + +#define YGAIN_REG 0x20 +#define YOFFSET_REG 0x21 +#define UVGAIN_REG 0x22 +#define UOFFSET_REG 0x23 +#define VOFFSET_REG 0x24 +#define SHARPNESS_REG 0x25 + +#define COMPR_REG 0x26 +#define OUTFMT_REG 0x27 + +#define XMIN_REG 0x28 +#define XMAX_REG 0x29 +#define YMIN_REG 0x2a +#define YMAX_REG 0x2b + +#define HSCALELOW_REG 0x30 +#define HSCALEHIGH_REG 0x31 +#define VSCALELOW_REG 0x32 +#define VSCALEHIGH_REG 0x33 + +#define AC97LSB_REG 0x40 +#define AC97MSB_REG 0x41 +#define AC97ADDR_REG 0x42 +#define AC97BUSY_REG 0x43 + +/* em202 registers */ +#define MASTER_AC97 0x02 +#define VIDEO_AC97 0x14 + +/* register settings */ +#define EM28XX_AUDIO_SRC_TUNER 0xc0 +#define EM28XX_AUDIO_SRC_LINE 0x80 + +/* printk macros */ + +#define em28xx_err(fmt, arg...) do {\ + printk(KERN_ERR fmt , ##arg); } while (0) + +#define em28xx_errdev(fmt, arg...) do {\ + printk(KERN_ERR "%s: "fmt,\ + dev->name , ##arg); } while (0) + +#define em28xx_info(fmt, arg...) do {\ + printk(KERN_INFO "%s: "fmt,\ + dev->name , ##arg); } while (0) +#define em28xx_warn(fmt, arg...) do {\ + printk(KERN_WARNING "%s: "fmt,\ + dev->name , ##arg); } while (0) + +inline static int em28xx_audio_source(struct em28xx *dev, int input) +{ + return em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); +} + +inline static int em28xx_audio_usb_mute(struct em28xx *dev, int mute) +{ + return em28xx_write_reg_bits(dev, XCLK_REG, mute ? 0x00 : 0x80, 0x80); +} + +inline static int em28xx_audio_analog_setup(struct em28xx *dev) +{ + /* unmute video mixer with default volume level */ + return em28xx_write_ac97(dev, VIDEO_AC97, "\x08\x08"); +} + +inline static int em28xx_compression_disable(struct em28xx *dev) +{ + /* side effect of disabling scaler and mixer */ + return em28xx_write_regs(dev, COMPR_REG, "\x00", 1); +} + +inline static int em28xx_contrast_get(struct em28xx *dev) +{ + return em28xx_read_reg(dev, YGAIN_REG) & 0x1f; +} + +inline static int em28xx_brightness_get(struct em28xx *dev) +{ + return em28xx_read_reg(dev, YOFFSET_REG); +} + +inline static int em28xx_saturation_get(struct em28xx *dev) +{ + return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f; +} + +inline static int em28xx_u_balance_get(struct em28xx *dev) +{ + return em28xx_read_reg(dev, UOFFSET_REG); +} + +inline static int em28xx_v_balance_get(struct em28xx *dev) +{ + return em28xx_read_reg(dev, VOFFSET_REG); +} + +inline static int em28xx_gamma_get(struct em28xx *dev) +{ + return em28xx_read_reg(dev, GAMMA_REG) & 0x3f; +} + +inline static int em28xx_contrast_set(struct em28xx *dev, s32 val) +{ + u8 tmp = (u8) val; + return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1); +} + +inline static int em28xx_brightness_set(struct em28xx *dev, s32 val) +{ + u8 tmp = (u8) val; + return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1); +} + +inline static int em28xx_saturation_set(struct em28xx *dev, s32 val) +{ + u8 tmp = (u8) val; + return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1); +} + +inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val) +{ + u8 tmp = (u8) val; + return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1); +} + +inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val) +{ + u8 tmp = (u8) val; + return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1); +} + +inline static int em28xx_gamma_set(struct em28xx *dev, s32 val) +{ + u8 tmp = (u8) val; + return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1); +} + +/*FIXME: maxw should be dependent of alt mode */ +inline static unsigned int norm_maxw(struct em28xx *dev) +{ + switch(dev->model){ + case (EM2820_BOARD_MSI_VOX_USB_2): return(640); + default: return(720); + } +} + +inline static unsigned int norm_maxh(struct em28xx *dev) +{ + switch(dev->model){ + case (EM2820_BOARD_MSI_VOX_USB_2): return(480); + default: return (dev->tvnorm->id & V4L2_STD_625_50) ? 576 : 480; + } +} + +#endif diff --git a/v4l_experimental/xc3028/tuner-core.c b/v4l_experimental/xc3028/tuner-core.c new file mode 100644 index 000000000..54f3b4ae3 --- /dev/null +++ b/v4l_experimental/xc3028/tuner-core.c @@ -0,0 +1,946 @@ +/* + * $Id: tuner-core.c,v 1.1 2006/01/25 09:48:37 mrechberger Exp $ + * + * i2c tv tuner chip device driver + * core core, i.e. kernel interfaces, registering and so on + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/poll.h> +#include <linux/i2c.h> +#include <linux/types.h> +#include "compat.h" +#include <linux/videodev.h> +#include <linux/init.h> + +#include <media/tuner.h> +#include <media/v4l2-common.h> +#include <media/audiochip.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include "i2c-compat.h" +#endif + +#define UNSET (-1U) + +/* standard i2c insmod options */ +static unsigned short normal_i2c[] = { + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + I2C_CLIENT_END +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; +#endif +I2C_CLIENT_INSMOD; + +/* insmod options used at init time => read/only */ +static unsigned int addr = 0; +static unsigned int no_autodetect = 0; +static unsigned int show_i2c = 0; + +/* insmod options used at runtime => read/write */ +static unsigned int tuner_debug_old = 0; +int tuner_debug = 0; + +static unsigned int tv_range[2] = { 44, 958 }; +static unsigned int radio_range[2] = { 65, 108 }; + +static char pal[] = "--"; +static char secam[] = "--"; +static char ntsc[] = "-"; + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +MODULE_PARM(pal,"s"); +MODULE_PARM(secam,"s"); +MODULE_PARM(ntsc,"s"); +MODULE_PARM(tv_range,"2i"); +MODULE_PARM(radio_range,"2i"); +MODULE_PARM(no_autodetect, "i"); +MODULE_PARM(tuner_debug, "i"); +MODULE_PARM(tuner_debug_old, "i"); +MODULE_PARM(addr, "i"); +MODULE_PARM(show_i2c, "i"); +#else +module_param(addr, int, 0444); +module_param(no_autodetect, int, 0444); +module_param(show_i2c, int, 0444); +/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */ +module_param_named(tuner_debug,tuner_debug_old, int, 0444); +module_param_named(debug,tuner_debug, int, 0644); +module_param_string(pal, pal, sizeof(pal), 0644); +module_param_string(secam, secam, sizeof(secam), 0644); +module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +static unsigned int dummy; +module_param_array(tv_range, int, dummy, 0644); +module_param_array(radio_range, int, dummy, 0644); +#else +module_param_array(tv_range, int, NULL, 0644); +module_param_array(radio_range, int, NULL, 0644); +#endif +#endif + +MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); +MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); +MODULE_LICENSE("GPL"); + +static struct i2c_driver driver; +static struct i2c_client client_template; + +/* ---------------------------------------------------------------------- */ + +/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */ +static void set_tv_freq(struct i2c_client *c, unsigned int freq) +{ + struct tuner *t = i2c_get_clientdata(c); + + printk("tuner set frequency %d\n",freq); + + if (t->type == UNSET) { + printk("tuner type not set!\n"); + tuner_warn ("tuner type not set\n"); + return; + } + if (NULL == t->set_tv_freq) { + printk("Tuner has no way to set tv freq!\n"); + tuner_warn ("Tuner has no way to set tv freq\n"); + return; + } + if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) { + tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n", + freq / 16, freq % 16 * 100 / 16, tv_range[0], + tv_range[1]); + /* V4L2 spec: if the freq is not possible then the closest + possible value should be selected */ + if (freq < tv_range[0] * 16) + freq = tv_range[0] * 16; + else + freq = tv_range[1] * 16; + } + t->set_tv_freq(c, freq); +} + +static void set_radio_freq(struct i2c_client *c, unsigned int freq) +{ + struct tuner *t = i2c_get_clientdata(c); + + if (t->type == UNSET) { + tuner_warn ("tuner type not set\n"); + return; + } + if (NULL == t->set_radio_freq) { + tuner_warn ("tuner has no way to set radio frequency\n"); + return; + } + if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) { + tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n", + freq / 16000, freq % 16000 * 100 / 16000, + radio_range[0], radio_range[1]); + /* V4L2 spec: if the freq is not possible then the closest + possible value should be selected */ + if (freq < radio_range[0] * 16000) + freq = radio_range[0] * 16000; + else + freq = radio_range[1] * 16000; + } + + t->set_radio_freq(c, freq); +} + +static void set_freq(struct i2c_client *c, unsigned long freq) +{ + struct tuner *t = i2c_get_clientdata(c); + printk("set freq!!!\n"); + + switch (t->mode) { + case V4L2_TUNER_RADIO: + tuner_dbg("radio freq set to %lu.%02lu\n", + freq / 16000, freq % 16000 * 100 / 16000); + set_radio_freq(c, freq); + t->radio_freq = freq; + break; + case V4L2_TUNER_ANALOG_TV: + case V4L2_TUNER_DIGITAL_TV: + tuner_dbg("tv freq set to %lu.%02lu\n", + freq / 16, freq % 16 * 100 / 16); + set_tv_freq(c, freq); + t->tv_freq = freq; + break; + } +} + +static void set_type(struct i2c_client *c, unsigned int type, + unsigned int new_mode_mask) +{ + struct tuner *t = i2c_get_clientdata(c); + unsigned char buffer[4]; + + if (type == UNSET || type == TUNER_ABSENT) { + tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr); + return; + } + + if (type >= tuner_count) { + tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count); + return; + } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + /* This code detects calls by card attach_inform */ + if (NULL == t->i2c.dev.driver) { + tuner_dbg ("tuner 0x%02x: called during i2c_client register by adapter's attach_inform\n", c->addr); + + t->type=type; + return; + } +#endif + + t->type = type; + + switch (t->type) { + case TUNER_MT2032: + microtune_init(c); + break; + case TUNER_PHILIPS_TDA8290: + tda8290_init(c); + break; + case TUNER_TEA5767: + if (tea5767_tuner_init(c) == EINVAL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } + t->mode_mask = T_RADIO; + break; + case TUNER_PHILIPS_FMD1216ME_MK3: + buffer[0] = 0x0b; + buffer[1] = 0xdc; + buffer[2] = 0x9c; + buffer[3] = 0x60; + i2c_master_send(c, buffer, 4); + mdelay(1); + buffer[2] = 0x86; + buffer[3] = 0x54; + i2c_master_send(c, buffer, 4); + default_tuner_init(c); + break; + case TUNER_LG_TDVS_H062F: + /* Set the Auxiliary Byte. */ + buffer[2] &= ~0x20; + buffer[2] |= 0x18; + buffer[3] = 0x20; + i2c_master_send(c, buffer, 4); + default_tuner_init(c); + break; + case TUNER_PHILIPS_TD1316: + buffer[0] = 0x0b; + buffer[1] = 0xdc; + buffer[2] = 0x86; + buffer[3] = 0xa4; + i2c_master_send(c,buffer,4); + default_tuner_init(c); + break; + case TUNER_XCEIVE_XC3028: + printk("initializing XC3028!\n"); + xc3028_init(c); + break; + default: + default_tuner_init(c); + break; + } + + if (t->mode_mask == T_UNINITIALIZED) + t->mode_mask = new_mode_mask; + + set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq); + tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) + c->adapter->name, c->driver->name, c->addr << 1, type, +#else + c->adapter->name, c->driver->driver.name, c->addr << 1, type, +#endif + t->mode_mask); +} + +/* + * This function apply tuner config to tuner specified + * by tun_setup structure. I addr is unset, then admin status + * and tun addr status is more precise then current status, + * it's applied. Otherwise status and type are applied only to + * tuner with exactly the same addr. +*/ + +static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup) +{ + struct tuner *t = i2c_get_clientdata(c); + + if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET && + (t->mode_mask & tun_setup->mode_mask)) || + tun_setup->addr == c->addr)) { + set_type(c, tun_setup->type, tun_setup->mode_mask); + } +} + +static inline int check_mode(struct tuner *t, char *cmd) +{ + if ((1 << t->mode & t->mode_mask) == 0) { +#if 0 + tuner_dbg("Cmd %s rejected for mode %i\n", cmd,t->mode); +#endif + return EINVAL; + } + + switch (t->mode) { + case V4L2_TUNER_RADIO: + tuner_dbg("Cmd %s accepted for radio\n", cmd); + break; + case V4L2_TUNER_ANALOG_TV: + tuner_dbg("Cmd %s accepted for analog TV\n", cmd); + break; + case V4L2_TUNER_DIGITAL_TV: + tuner_dbg("Cmd %s accepted for digital TV\n", cmd); + break; + } + return 0; +} + +/* get more precise norm info from insmod option */ +static int tuner_fixup_std(struct tuner *t) +{ + if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { + switch (pal[0]) { + case 'b': + case 'B': + case 'g': + case 'G': + tuner_dbg ("insmod fixup: PAL => PAL-BG\n"); + t->std = V4L2_STD_PAL_BG; + break; + case 'i': + case 'I': + tuner_dbg ("insmod fixup: PAL => PAL-I\n"); + t->std = V4L2_STD_PAL_I; + break; + case 'd': + case 'D': + case 'k': + case 'K': + tuner_dbg ("insmod fixup: PAL => PAL-DK\n"); + t->std = V4L2_STD_PAL_DK; + break; + case 'M': + case 'm': + tuner_dbg ("insmod fixup: PAL => PAL-M\n"); + t->std = V4L2_STD_PAL_M; + break; + case 'N': + case 'n': + if (pal[1] == 'c' || pal[1] == 'C') { + tuner_dbg("insmod fixup: PAL => PAL-Nc\n"); + t->std = V4L2_STD_PAL_Nc; + } else { + tuner_dbg ("insmod fixup: PAL => PAL-N\n"); + t->std = V4L2_STD_PAL_N; + } + break; + case '-': + /* default parameter, do nothing */ + break; + default: + tuner_warn ("pal= argument not recognised\n"); + break; + } + } + if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { + switch (secam[0]) { + case 'b': + case 'B': + case 'g': + case 'G': + case 'h': + case 'H': + tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n"); + t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; + break; + case 'd': + case 'D': + case 'k': + case 'K': + tuner_dbg ("insmod fixup: SECAM => SECAM-DK\n"); + t->std = V4L2_STD_SECAM_DK; + break; + case 'l': + case 'L': + if ((secam[1]=='C')||(secam[1]=='c')) { + tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n"); + t->std = V4L2_STD_SECAM_LC; + } else { + tuner_dbg ("insmod fixup: SECAM => SECAM-L\n"); + t->std = V4L2_STD_SECAM_L; + } + break; + case '-': + /* default parameter, do nothing */ + break; + default: + tuner_warn ("secam= argument not recognised\n"); + break; + } + } + + if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { + switch (ntsc[0]) { + case 'm': + case 'M': + tuner_dbg("insmod fixup: NTSC => NTSC-M\n"); + t->std = V4L2_STD_NTSC_M; + break; + case 'j': + case 'J': + tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); + t->std = V4L2_STD_NTSC_M_JP; + break; + case '-': + /* default parameter, do nothing */ + break; + default: + tuner_info("ntsc= argument not recognised\n"); + break; + } + } + return 0; +} + +static void tuner_status(struct i2c_client *client) +{ + struct tuner *t = i2c_get_clientdata(client); + unsigned long freq, freq_fraction; + const char *p; + + switch (t->mode) { + case V4L2_TUNER_RADIO: p = "radio"; break; + case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break; + case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break; + default: p = "undefined"; break; + } + if (t->mode == V4L2_TUNER_RADIO) { + freq = t->radio_freq / 16000; + freq_fraction = (t->radio_freq % 16000) * 100 / 16000; + } else { + freq = t->tv_freq / 16; + freq_fraction = (t->tv_freq % 16) * 100 / 16; + } + tuner_info("Tuner mode: %s\n", p); + tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); + tuner_info("Standard: 0x%08llx\n", t->std); + if (t->mode != V4L2_TUNER_RADIO) + return; + if (t->has_signal) { + tuner_info("Signal strength: %d\n", t->has_signal(client)); + } + if (t->is_stereo) { + tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); + } +} + +/* ---------------------------------------------------------------------- */ + +/* static var Used only in tuner_attach and tuner_probe */ +static unsigned default_mode_mask; + +/* During client attach, set_type is called by adapter's attach_inform callback. + set_type must then be completed by tuner_attach. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) +#else +static int tuner_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +#endif +{ + struct tuner *t; + + client_template.adapter = adap; + client_template.addr = addr; + + printk(" --- TUNER attach! --\n"); + t = kzalloc(sizeof(struct tuner), GFP_KERNEL); + if (NULL == t) + return -ENOMEM; + memcpy(&t->i2c, &client_template, sizeof(struct i2c_client)); + i2c_set_clientdata(&t->i2c, t); + t->type = UNSET; + t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ + t->audmode = V4L2_TUNER_MODE_STEREO; + t->mode_mask = T_UNINITIALIZED; + if (tuner_debug_old) { + tuner_debug = tuner_debug_old; + printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n"); + printk(KERN_ERR "tuner: use the debug option instead.\n"); + } + + if (show_i2c) { + unsigned char buffer[16]; + int i,rc; + + memset(buffer, 0, sizeof(buffer)); + rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); + tuner_info("I2C RECV = "); + for (i=0;i<rc;i++) + printk("%02x ",buffer[i]); + printk("\n"); + } + /* autodetection code based on the i2c addr */ + if (!no_autodetect) { + switch (addr) { + case 0x42: + case 0x43: + case 0x4a: + case 0x4b: + /* If chip is not tda8290, don't register. + since it can be tda9887*/ + if (tda8290_probe(&t->i2c) != 0) { + tuner_dbg("chip at addr %x is not a tda8290\n", addr); + kfree(t); + return 0; + } + break; + case 0x60: + if (tea5767_autodetection(&t->i2c) != EINVAL) { + t->type = TUNER_TEA5767; + t->mode_mask = T_RADIO; + t->mode = T_STANDBY; + t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ + default_mode_mask &= ~T_RADIO; + + goto register_client; + } + break; + } + } + + /* Initializes only the first adapter found */ + if (default_mode_mask != T_UNINITIALIZED) { + tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask); + t->mode_mask = default_mode_mask; + t->tv_freq = 400 * 16; /* Sets freq to VHF High */ + t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ + default_mode_mask = T_UNINITIALIZED; + } + + /* Should be just before return */ +register_client: + tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + i2c_attach_client (&t->i2c); + set_type (&t->i2c,t->type, t->mode_mask); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int tuner_probe(struct i2c_adapter *adap) +{ + printk("--- TUner PROBE here ---\n"); + if (0 != addr) { + normal_i2c[0] = addr; + normal_i2c[1] = I2C_CLIENT_END; + } + + default_mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + +#ifdef I2C_CLASS_TV_ANALOG + if (adap->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, tuner_attach); +#else + if (adap->id == I2C_HW_B_BT848) + return i2c_probe(adap, &addr_data, tuner_attach); +#endif + printk(" --- RETURN --\n"); + return 0; +} + +static int tuner_detach(struct i2c_client *client) +{ + struct tuner *t = i2c_get_clientdata(client); + int err; + + err = i2c_detach_client(&t->i2c); + if (err) { + tuner_warn + ("Client deregistration failed, client not detached.\n"); + return err; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +MOD_DEC_USE_COUNT; +#endif + kfree(t); + return 0; +} + +/* + * Switch tuner to other mode. If tuner support both tv and radio, + * set another frequency to some value (This is needed for some pal + * tuners to avoid locking). Otherwise, just put second tuner in + * standby mode. + */ + +static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) +{ + if (mode == t->mode) + return 0; + + t->mode = mode; + + if (check_mode(t, cmd) == EINVAL) { + t->mode = T_STANDBY; + if (t->standby) + t->standby (client); + return EINVAL; + } + return 0; +} + +#define switch_v4l2() if (!t->using_v4l2) \ + tuner_dbg("switching to v4l2\n"); \ + t->using_v4l2 = 1; + +static inline int check_v4l2(struct tuner *t) +{ + if (t->using_v4l2) { + tuner_dbg ("ignore v4l1 call\n"); + return EINVAL; + } + return 0; +} + +static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + struct tuner *t = i2c_get_clientdata(client); + + if (tuner_debug>1) + v4l_i2c_print_ioctl(&(t->i2c),cmd); + + switch (cmd) { + /* --- configuration --- */ + case TUNER_SET_TYPE_ADDR: + tuner_dbg ("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x\n", + ((struct tuner_setup *)arg)->type, + ((struct tuner_setup *)arg)->addr, + ((struct tuner_setup *)arg)->mode_mask); + + set_addr(client, (struct tuner_setup *)arg); + break; + case AUDC_SET_RADIO: + if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") + == EINVAL) + return 0; + if (t->radio_freq) + set_freq(client, t->radio_freq); + break; + case TUNER_SET_STANDBY: + if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) + return 0; + if (t->standby) + t->standby (client); + break; + case VIDIOCSAUDIO: + if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; + + /* Should be implemented, since bttv calls it */ + tuner_dbg("VIDIOCSAUDIO not implemented.\n"); + break; + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOCSCHAN: + { + static const v4l2_std_id map[] = { + [VIDEO_MODE_PAL] = V4L2_STD_PAL, + [VIDEO_MODE_NTSC] = V4L2_STD_NTSC_M, + [VIDEO_MODE_SECAM] = V4L2_STD_SECAM, + [4 /* bttv */ ] = V4L2_STD_PAL_M, + [5 /* bttv */ ] = V4L2_STD_PAL_N, + [6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, + }; + struct video_channel *vc = arg; + + if (check_v4l2(t) == EINVAL) + return 0; + + if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL) + return 0; + + if (vc->norm < ARRAY_SIZE(map)) + t->std = map[vc->norm]; + tuner_fixup_std(t); + if (t->tv_freq) + set_tv_freq(client, t->tv_freq); + return 0; + } + case VIDIOCSFREQ: + { + unsigned long *v = arg; + + if (check_mode(t, "VIDIOCSFREQ") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; + + set_freq(client, *v); + return 0; + } + case VIDIOCGTUNER: + { + struct video_tuner *vt = arg; + + if (check_mode(t, "VIDIOCGTUNER") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; + + if (V4L2_TUNER_RADIO == t->mode) { + if (t->has_signal) + vt->signal = t->has_signal(client); + if (t->is_stereo) { + if (t->is_stereo(client)) + vt->flags |= + VIDEO_TUNER_STEREO_ON; + else + vt->flags &= + ~VIDEO_TUNER_STEREO_ON; + } + vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ + + vt->rangelow = radio_range[0] * 16000; + vt->rangehigh = radio_range[1] * 16000; + + } else { + vt->rangelow = tv_range[0] * 16; + vt->rangehigh = tv_range[1] * 16; + } + + return 0; + } + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + + if (check_mode(t, "VIDIOCGAUDIO") == EINVAL) + return 0; + if (check_v4l2(t) == EINVAL) + return 0; + + if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) + va->mode = t->is_stereo(client) + ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; + return 0; + } + + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + + if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") + == EINVAL) + return 0; + + switch_v4l2(); + + t->std = *id; + tuner_fixup_std(t); + if (t->tv_freq) + set_freq(client, t->tv_freq); + break; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + switch_v4l2(); + if (V4L2_TUNER_RADIO == f->type && + V4L2_TUNER_RADIO != t->mode) { + if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") + == EINVAL) + return 0; + } + set_freq(client,f->frequency); + + break; + } + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL) + return 0; + switch_v4l2(); + f->type = t->mode; + f->frequency = (V4L2_TUNER_RADIO == t->mode) ? + t->radio_freq : t->tv_freq; + break; + } + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *tuner = arg; + + if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL) + return 0; + switch_v4l2(); + + tuner->type = t->mode; + if (t->mode != V4L2_TUNER_RADIO) { + tuner->rangelow = tv_range[0] * 16; + tuner->rangehigh = tv_range[1] * 16; + break; + } + + /* radio mode */ + if (t->has_signal) + tuner->signal = t->has_signal(client); + + tuner->rxsubchans = + V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + if (t->is_stereo) { + tuner->rxsubchans = t->is_stereo(client) ? + V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + } + + tuner->capability |= + V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + tuner->audmode = t->audmode; + tuner->rangelow = radio_range[0] * 16000; + tuner->rangehigh = radio_range[1] * 16000; + break; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *tuner = arg; + + if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL) + return 0; + + switch_v4l2(); + + /* do nothing unless we're a radio tuner */ + if (t->mode != V4L2_TUNER_RADIO) + break; + t->audmode = tuner->audmode; + set_radio_freq(client, t->radio_freq); + break; + } + case VIDIOC_LOG_STATUS: + tuner_status(client); + break; + } + + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14) +static int tuner_suspend(struct device *dev, pm_message_t state) +#else +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) +static int tuner_suspend(struct device *dev, pm_message_t state, u32 level) +#else +static int tuner_suspend(struct device *dev, u32 state, u32 level) +#endif +#endif +{ + struct i2c_client *c = container_of (dev, struct i2c_client, dev); + struct tuner *t = i2c_get_clientdata (c); + + tuner_dbg ("suspend\n"); + /* FIXME: power down ??? */ + return 0; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14) +static int tuner_resume(struct device *dev) +#else +static int tuner_resume(struct device *dev, u32 level) +#endif +{ + struct i2c_client *c = container_of (dev, struct i2c_client, dev); + struct tuner *t = i2c_get_clientdata (c); + + tuner_dbg ("resume\n"); + if (V4L2_TUNER_RADIO == t->mode) { + if (t->radio_freq) + set_freq(c, t->radio_freq); + } else { + if (t->tv_freq) + set_freq(c, t->tv_freq); + } + return 0; +} +#endif + +/* ----------------------------------------------------------------------- */ + +static struct i2c_driver driver = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))&&(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) + .owner = THIS_MODULE, +#endif +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) + .name = "tuner", + .flags = I2C_DF_NOTIFY, +#endif + .id = I2C_DRIVERID_TUNER, + .attach_adapter = tuner_probe, + .detach_client = tuner_detach, + .command = tuner_command, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + .driver = { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) + .name = "tuner", +#endif + .suspend = tuner_suspend, + .resume = tuner_resume, + }, +#endif +}; +static struct i2c_client client_template = { + .name = "(tuner unset)", +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) + .flags = I2C_CLIENT_ALLOW_USE, +#endif + .driver = &driver, +}; + +static int __init tuner_init_module(void) +{ + return i2c_add_driver(&driver); +} + +static void __exit tuner_cleanup_module(void) +{ + i2c_del_driver(&driver); +} + +module_init(tuner_init_module); +module_exit(tuner_cleanup_module); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/v4l_experimental/xc3028/tuner-types.c b/v4l_experimental/xc3028/tuner-types.c new file mode 100644 index 000000000..f344c03dc --- /dev/null +++ b/v4l_experimental/xc3028/tuner-types.c @@ -0,0 +1,1480 @@ +/* + * $Id: tuner-types.c,v 1.1 2006/01/25 09:48:37 mrechberger Exp $ + * + * i2c tv tuner chip device type database. + * + */ + +#include "compat.h" +#include <linux/i2c.h> +#include <media/tuner.h> +#include <media/tuner-types.h> + +/* ---------------------------------------------------------------------- */ + +/* + * The floats in the tuner struct are computed at compile time + * by gcc and cast back to integers. Thus we don't violate the + * "no float in kernel" rule. + * + * A tuner_range may be referenced by multiple tuner_params structs. + * There are many duplicates in here. Reusing tuner_range structs, + * rather than defining new ones for each tuner, will cut down on + * memory usage, and is preferred when possible. + * + * Each tuner_params array may contain one or more elements, one + * for each video standard. + * + * FIXME: Some tuner_range definitions are duplicated, and + * should be eliminated. + * + * FIXME: tunertype struct contains an element, has_tda988x. + * We must set this for all tunertypes that contain a tda988x + * chip, and then we can remove this setting from the various + * card structs. + */ + +/* 0-9 */ +/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_pal_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_pal_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */ + +static struct tuner_range tuner_philips_pal_i_ranges[] = { + { 16 * 140.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_pal_i_ranges, + .count = ARRAY_SIZE(tuner_philips_pal_i_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 451.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_ntsc_ranges), + .config = 0x8e, + .cb_first_if_lower_freq = 1, + }, +}; + +/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */ + +static struct tuner_range tuner_philips_secam_ranges[] = { + { 16 * 168.25 /*MHz*/, 0xa7, }, + { 16 * 447.25 /*MHz*/, 0x97, }, + { 16 * 999.99 , 0x37, }, +}; + +static struct tuner_params tuner_philips_secam_params[] = { + { + .type = TUNER_PARAM_TYPE_SECAM, + .ranges = tuner_philips_secam_ranges, + .count = ARRAY_SIZE(tuner_philips_secam_ranges), + .config = 0x8e, + .cb_first_if_lower_freq = 1, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_pal_ranges[] = { + { 16 * 168.25 /*MHz*/, 0xa0, }, + { 16 * 447.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_pal_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_pal_ranges), + .config = 0x8e, + .cb_first_if_lower_freq = 1, + }, +}; + +/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */ + +static struct tuner_range tuner_temic_pal_i_ranges[] = { + { 16 * 170.00 /*MHz*/, 0x02, }, + { 16 * 450.00 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_pal_i_ranges, + .count = ARRAY_SIZE(tuner_temic_pal_i_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_4036fy5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_alps_tsb_1_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 385.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_alps_tsb_1_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), + .config = 0x8e, + }, +}; + +/* 10-19 */ +/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */ + +static struct tuner_params tuner_alps_tsb_1_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_1_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */ + +static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = { + { 16 * 133.25 /*MHz*/, 0x01, }, + { 16 * 351.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_alps_tsbb5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_5_pal_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */ + +static struct tuner_params tuner_alps_tsbe5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_5_pal_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */ + +static struct tuner_params tuner_alps_tsbc5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_5_pal_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4006fh5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4006fh5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */ + +static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x14, }, + { 16 * 385.25 /*MHz*/, 0x12, }, + { 16 * 999.99 , 0x11, }, +}; + +static struct tuner_params tuner_alps_tshc6_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_alps_tshc6_ntsc_ranges, + .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_pal_dk_ranges[] = { + { 16 * 168.25 /*MHz*/, 0xa0, }, + { 16 * 456.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_pal_dk_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_pal_dk_ranges, + .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_ntsc_m_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_ntsc_m_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_ntsc_m_ranges, + .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */ + +static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = { + { 16 * 169.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_40x6f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */ + +static struct tuner_params tuner_temic_4006fn5_multi_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_40x6f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* 20-29 */ +/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = { + { 16 * 141.00 /*MHz*/, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4009f_5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = { + { 16 * 158.00 /*MHz*/, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4039fr5_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_4039fr5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = { + { 16 * 169.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4046fm5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4046fm5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */ + +static struct tuner_range tuner_lg_pal_ranges[] = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_pal_dk_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */ + +static struct tuner_params tuner_philips_fq1216me_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */ + +static struct tuner_params tuner_lg_pal_i_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */ + +static struct tuner_params tuner_lg_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */ + +static struct tuner_range tuner_lg_ntsc_fm_ranges[] = { + { 16 * 210.00 /*MHz*/, 0xa0, }, + { 16 * 497.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_lg_ntsc_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_ntsc_fm_ranges, + .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */ + +static struct tuner_params tuner_lg_pal_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */ + +static struct tuner_params tuner_lg_pal_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* 30-39 */ +/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */ + +static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */ + +static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 317.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_sharp_2u5jf5540_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_sharp_2u5jf5540_ntsc_ranges, + .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */ + +static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = { + { 16 * 169 /*MHz*/, 0xa0, }, + { 16 * 464 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_samsung_pal_tcpm9091pd27_ranges, + .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */ + +static struct tuner_params tuner_temic_4106fh5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_4012fy5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4012fy5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = { + { 16 * 158.00 /*MHz*/, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4136_fy5_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_4136_fy5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */ + +static struct tuner_range tuner_lg_new_tapc_ranges[] = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_lg_pal_new_tapc_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_new_tapc_ranges, + .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */ + +static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = { + { 16 * 158.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_fm1216me_mk3_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_fm1216me_mk3_pal_ranges, + .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges), + .config = 0x8e, + .cb_first_if_lower_freq = 1, + }, +}; + +/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */ + +static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_new_tapc_ranges, + .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), + .config = 0x8e, + }, +}; + +/* 40-49 */ +/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */ + +static struct tuner_params tuner_hitachi_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_new_tapc_ranges, + .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x01, }, + { 16 * 463.25 /*MHz*/, 0xc2, }, + { 16 * 999.99 , 0xcf, }, +}; + +static struct tuner_params tuner_philips_pal_mk_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_pal_mk_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */ + +static struct tuner_range tuner_philips_atsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_atsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_atsc_ranges, + .count = ARRAY_SIZE(tuner_philips_atsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */ + +static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_fm1236_mk3_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_fm1236_mk3_ntsc_ranges, + .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), + .config = 0x8e, + .cb_first_if_lower_freq = 1, + }, +}; + +/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_4in1_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_4in1_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */ + +static struct tuner_params tuner_microtune_4049_fm5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */ + +static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_panasonic_vp27_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_panasonic_vp27_ntsc_ranges, + .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ + +static struct tuner_range tuner_lg_ntsc_tape_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_lg_ntsc_tape_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_ntsc_tape_ranges, + .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ + +static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { + { 16 * 161.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_tnf_8831bgff_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_tnf_8831bgff_pal_ranges, + .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */ + +static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = { + { 16 * 162.00 /*MHz*/, 0xa2, }, + { 16 * 457.00 /*MHz*/, 0x94, }, + { 16 * 999.99 , 0x31, }, +}; + +static struct tuner_params tuner_microtune_4042fi5_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_microtune_4042fi5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* 50-59 */ +/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */ + +static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = { + { 16 * 172.00 /*MHz*/, 0x01, }, + { 16 * 448.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_tcl_2002n_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tcl_2002n_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges), + .config = 0x8e, + .cb_first_if_lower_freq = 1, + }, +}; + +/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_fm1256_ih3_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_fm1256_ih3_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */ + +static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x39, }, + { 16 * 454.00 /*MHz*/, 0x3a, }, + { 16 * 999.99 , 0x3c, }, +}; + +static struct tuner_params tuner_thomson_dtt7610_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_thomson_dtt7610_ntsc_ranges, + .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x41, }, + { 16 * 454.00 /*MHz*/, 0x42, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_fq1286_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_fq1286_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */ + +static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_tcl_2002mb_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_tcl_2002mb_pal_ranges, + .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_fq12_6a___mk4_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_fq12_6a___mk4_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */ + +static struct tuner_params tuner_philips_fq1236a_mk4_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_fq12_6a___mk4_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */ + +static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges, + .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */ + +static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges, + .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* 60-69 */ +/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */ +/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ + +static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = { + { 16 * 145.25 /*MHz*/, 0x39, }, + { 16 * 415.25 /*MHz*/, 0x3a, }, + { 16 * 999.99 , 0x3c, }, +}; + +#if 0 +static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = { + { 16 * 147.00 /*MHz*/, 0x39, }, + { 16 * 417.00 /*MHz*/, 0x3a, }, + { 16 * 999.99 , 0x3c, }, +}; +#endif + +static struct tuner_params tuner_thomson_dtt761x_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_thomson_dtt761x_ntsc_ranges, + .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges), + .config = 0x8e, + }, +#if 0 + { + .type = TUNER_PARAM_TYPE_ATSC, + .ranges = tuner_thomson_dtt761x_atsc_ranges, + .count = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges), + .config = 0x8e, + }, +#endif +}; + +/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ + +static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = { + { 16 * 160.25 /*MHz*/, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_tena_9533_di_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_tuner_tena_9533_di_pal_ranges, + .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x51, }, + { 16 * 442.00 /*MHz*/, 0x52, }, + { 16 * 999.99 , 0x54, }, +}; + +#if 0 +static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = { +}; +#endif + +static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_fmd1216me_mk3_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges), + .config = 0x86, + }, +#if 0 + { + .type = TUNER_PARAM_TYPE_DVB, + .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges, + .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges), + .config = , + }, +#endif +}; + + +/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ + +static struct tuner_range tuner_tua6034_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01 }, + { 16 * 455.00 /*MHz*/, 0x02 }, + { 16 * 999.99 , 0x04 }, +}; + +#if 0 +static struct tuner_range tuner_tua6034_atsc_ranges[] = { +}; +#endif + +static struct tuner_params tuner_tua6034_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tua6034_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges), + .config = 0x8e, + }, +#if 0 + { + .type = TUNER_PARAM_TYPE_ATSC, + .ranges = tuner_tua6034_atsc_ranges, + .count = ARRAY_SIZE(tuner_tua6034_atsc_ranges), + .config = 0x8e, + }, +#endif +}; + +/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ + +static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = { + { 16 * 160.25 /*MHz*/, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges, + .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ + +static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 373.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_lg_taln_mini_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_taln_mini_ntsc_ranges, + .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_td1316_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xa1, }, + { 16 * 442.00 /*MHz*/, 0xa2, }, + { 16 * 999.99 , 0xa4, }, +}; + +static struct tuner_params tuner_philips_td1316_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_td1316_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges), + .config = 0xc8, + }, +}; + +/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */ + +static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +#if 0 +static struct tuner_range tuner_tuv1236d_atsc_ranges[] = { +}; +#endif + +static struct tuner_params tuner_tuner_tuv1236d_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tuv1236d_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges), + .config = 0xce, + }, +#if 0 + { + .type = TUNER_PARAM_TYPE_ATSC, + .ranges = tuner_tuv1236d_atsc_ranges, + .count = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges), + .config = , + }, +#endif +}; + +/* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */ + +static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_tnf_5335mf_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tnf_5335mf_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* 70-79 */ +/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ + +static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { + { 16 * 175.75 /*MHz*/, 0x01, }, + { 16 * 410.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges, + .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_XCEIVE_XC3028 - Xceive xc3028 ------------ */ + +static struct tuner_range tuner_xceive_xc3028_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_xceive_xc3028_params[] = { + { + .type = TUNER_XCEIVE_XC3028, + .ranges = tuner_xceive_xc3028_ranges, + .count = ARRAY_SIZE(tuner_xceive_xc3028_ranges), + .config = 0xce, + }, +}; + +/* --------------------------------------------------------------------- */ + +struct tunertype tuners[] = { + /* 0-9 */ + [TUNER_TEMIC_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL (4002 FH5)", + .params = tuner_temic_pal_params, + }, + [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */ + .name = "Philips PAL_I (FI1246 and compatibles)", + .params = tuner_philips_pal_i_params, + }, + [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */ + .name = "Philips NTSC (FI1236,FM1236 and compatibles)", + .params = tuner_philips_ntsc_params, + }, + [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */ + .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", + .params = tuner_philips_secam_params, + }, + [TUNER_ABSENT] = { /* Tuner Absent */ + .name = "NoTuner", + }, + [TUNER_PHILIPS_PAL] = { /* Philips PAL */ + .name = "Philips PAL_BG (FI1216 and compatibles)", + .params = tuner_philips_pal_params, + }, + [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4032 FY5)", + .params = tuner_temic_ntsc_params, + }, + [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */ + .name = "Temic PAL_I (4062 FY5)", + .params = tuner_temic_pal_i_params, + }, + [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4036 FY5)", + .params = tuner_temic_4036fy5_ntsc_params, + }, + [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */ + .name = "Alps HSBH1", + .params = tuner_alps_tsbh1_ntsc_params, + }, + + /* 10-19 */ + [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */ + .name = "Alps TSBE1", + .params = tuner_alps_tsb_1_params, + }, + [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */ + .name = "Alps TSBB5", + .params = tuner_alps_tsbb5_params, + }, + [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */ + .name = "Alps TSBE5", + .params = tuner_alps_tsbe5_params, + }, + [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */ + .name = "Alps TSBC5", + .params = tuner_alps_tsbc5_params, + }, + [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4006FH5)", + .params = tuner_temic_4006fh5_params, + }, + [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */ + .name = "Alps TSCH6", + .params = tuner_alps_tshc6_params, + }, + [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */ + .name = "Temic PAL_DK (4016 FY5)", + .params = tuner_temic_pal_dk_params, + }, + [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */ + .name = "Philips NTSC_M (MK2)", + .params = tuner_philips_ntsc_m_params, + }, + [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */ + .name = "Temic PAL_I (4066 FY5)", + .params = tuner_temic_4066fy5_pal_i_params, + }, + [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL* auto (4006 FN5)", + .params = tuner_temic_4006fn5_multi_params, + }, + + /* 20-29 */ + [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", + .params = tuner_temic_4009f_5_params, + }, + [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4039 FR5)", + .params = tuner_temic_4039fr5_params, + }, + [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */ + .name = "Temic PAL/SECAM multi (4046 FM5)", + .params = tuner_temic_4046fm5_params, + }, + [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */ + .name = "Philips PAL_DK (FI1256 and compatibles)", + .params = tuner_philips_pal_dk_params, + }, + [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FQ1216ME)", + .params = tuner_philips_fq1216me_params, + }, + [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */ + .name = "LG PAL_I+FM (TAPC-I001D)", + .params = tuner_lg_pal_i_fm_params, + }, + [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */ + .name = "LG PAL_I (TAPC-I701D)", + .params = tuner_lg_pal_i_params, + }, + [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC+FM (TPI8NSR01F)", + .params = tuner_lg_ntsc_fm_params, + }, + [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */ + .name = "LG PAL_BG+FM (TPI8PSB01D)", + .params = tuner_lg_pal_fm_params, + }, + [TUNER_LG_PAL] = { /* LGINNOTEK PAL */ + .name = "LG PAL_BG (TPI8PSB11D)", + .params = tuner_lg_pal_params, + }, + + /* 30-39 */ + [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */ + .name = "Temic PAL* auto + FM (4009 FN5)", + .params = tuner_temic_4009_fn5_multi_pal_fm_params, + }, + [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */ + .name = "SHARP NTSC_JP (2U5JF5540)", + .params = tuner_sharp_2u5jf5540_params, + }, + [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */ + .name = "Samsung PAL TCPM9091PD27", + .params = tuner_samsung_pal_tcpm9091pd27_params, + }, + [TUNER_MT2032] = { /* Microtune PAL|NTSC */ + .name = "MT20xx universal", + /* see mt20xx.c for details */ }, + [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4106 FH5)", + .params = tuner_temic_4106fh5_params, + }, + [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */ + .name = "Temic PAL_DK/SECAM_L (4012 FY5)", + .params = tuner_temic_4012fy5_params, + }, + [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4136 FY5)", + .params = tuner_temic_4136_fy5_params, + }, + [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */ + .name = "LG PAL (newer TAPC series)", + .params = tuner_lg_pal_new_tapc_params, + }, + [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FM1216ME MK3)", + .params = tuner_fm1216me_mk3_params, + }, + [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (newer TAPC series)", + .params = tuner_lg_ntsc_new_tapc_params, + }, + + /* 40-49 */ + [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */ + .name = "HITACHI V7-J180AT", + .params = tuner_hitachi_ntsc_params, + }, + [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */ + .name = "Philips PAL_MK (FI1216 MK)", + .params = tuner_philips_pal_mk_params, + }, + [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ + .name = "Philips 1236D ATSC/NTSC dual in", + .params = tuner_philips_atsc_params, + }, + [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ + .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", + .params = tuner_fm1236_mk3_params, + }, + [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */ + .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", + .params = tuner_philips_4in1_params, + }, + [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */ + .name = "Microtune 4049 FM5", + .params = tuner_microtune_4049_fm5_params, + }, + [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */ + .name = "Panasonic VP27s/ENGE4324D", + .params = tuner_panasonic_vp27_params, + }, + [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (TAPE series)", + .params = tuner_lg_ntsc_tape_params, + }, + [TUNER_TNF_8831BGFF] = { /* Philips PAL */ + .name = "Tenna TNF 8831 BGFF)", + .params = tuner_tnf_8831bgff_params, + }, + [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */ + .name = "Microtune 4042 FI5 ATSC/NTSC dual in", + .params = tuner_microtune_4042fi5_params, + }, + + /* 50-59 */ + [TUNER_TCL_2002N] = { /* TCL NTSC */ + .name = "TCL 2002N", + .params = tuner_tcl_2002n_params, + }, + [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */ + .name = "Philips PAL/SECAM_D (FM 1256 I-H3)", + .params = tuner_philips_fm1256_ih3_params, + }, + [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */ + .name = "Thomson DTT 7610 (ATSC/NTSC)", + .params = tuner_thomson_dtt7610_params, + }, + [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ + .name = "Philips FQ1286", + .params = tuner_philips_fq1286_params, + }, + [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ + .name = "tda8290+75", + /* see tda8290.c for details */ }, + [TUNER_TCL_2002MB] = { /* TCL PAL */ + .name = "TCL 2002MB", + .params = tuner_tcl_2002mb_params, + }, + [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FQ1216AME MK4)", + .params = tuner_philips_fq1216ame_mk4_params, + }, + [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */ + .name = "Philips FQ1236A MK4", + .params = tuner_philips_fq1236a_mk4_params, + }, + [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */ + .name = "Ymec TVision TVF-8531MF/8831MF/8731MF", + .params = tuner_ymec_tvf_8531mf_params, + }, + [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */ + .name = "Ymec TVision TVF-5533MF", + .params = tuner_ymec_tvf_5533mf_params, + }, + + /* 60-69 */ + [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */ + /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ + .name = "Thomson DTT 761X (ATSC/NTSC)", + .params = tuner_thomson_dtt761x_params, + }, + [TUNER_TENA_9533_DI] = { /* Philips PAL */ + .name = "Tena TNF9533-D/IF/TNF9533-B/DF", + .params = tuner_tena_9533_di_params, + }, + [TUNER_TEA5767] = { /* Philips RADIO */ + .name = "Philips TEA5767HN FM Radio", + /* see tea5767.c for details */ + }, + [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ + .name = "Philips FMD1216ME MK3 Hybrid Tuner", + .params = tuner_tuner_philips_fmd1216me_mk3_params, + }, + [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ + .name = "LG TDVS-H062F/TUA6034", + .params = tuner_tua6034_params, + }, + [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ + .name = "Ymec TVF66T5-B/DFF", + .params = tuner_ymec_tvf66t5_b_dff_params, + }, + [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (TALN mini series)", + .params = tuner_lg_taln_mini_params, + }, + [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ + .name = "Philips TD1316 Hybrid Tuner", + .params = tuner_philips_td1316_params, + }, + [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ + .name = "Philips TUV1236D ATSC/NTSC dual in", + .params = tuner_tuner_tuv1236d_params, + }, + [TUNER_TNF_5335MF] = { /* Philips NTSC */ + .name = "Tena TNF 5335 MF", + .params = tuner_tnf_5335mf_params, + }, + + /* 70-79 */ + [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */ + .name = "Samsung TCPN 2121P30A", + .params = tuner_samsung_tcpn_2121p30a_params, + }, + [TUNER_XCEIVE_XC3028] = { /* Xceive 3028 */ + .name = "Xceive xc3028", + .params = tuner_xceive_xc3028_params, + }, +}; + +unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/v4l_experimental/xc3028/tuner.h b/v4l_experimental/xc3028/tuner.h new file mode 100644 index 000000000..6a8e840c5 --- /dev/null +++ b/v4l_experimental/xc3028/tuner.h @@ -0,0 +1,259 @@ +/* + $Id: tuner.h,v 1.1 2006/01/25 09:48:37 mrechberger Exp $ + tuner.h - definition for different tuners + + Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de) + minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de) + + 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 _TUNER_H +#define _TUNER_H + +#include <linux/videodev2.h> +#include <media/tuner-types.h> + +#define ADDR_UNSET (255) + +#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */ +#define TUNER_PHILIPS_PAL_I 1 +#define TUNER_PHILIPS_NTSC 2 +#define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */ + +#define TUNER_ABSENT 4 +#define TUNER_PHILIPS_PAL 5 +#define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */ +#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */ + +#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */ +#define TUNER_ALPS_TSBH1_NTSC 9 +#define TUNER_ALPS_TSBE1_PAL 10 +#define TUNER_ALPS_TSBB5_PAL_I 11 + +#define TUNER_ALPS_TSBE5_PAL 12 +#define TUNER_ALPS_TSBC5_PAL 13 +#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */ +#define TUNER_ALPS_TSHC6_NTSC 15 + +#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */ +#define TUNER_PHILIPS_NTSC_M 17 +#define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */ +#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657) */ + +#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711) */ +#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732) */ +#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104) */ +#define TUNER_PHILIPS_PAL_DK 23 + +#define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */ +#define TUNER_LG_PAL_I_FM 25 +#define TUNER_LG_PAL_I 26 +#define TUNER_LG_NTSC_FM 27 + +#define TUNER_LG_PAL_FM 28 +#define TUNER_LG_PAL 29 +#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163) */ +#define TUNER_SHARP_2U5JF5540_NTSC 31 + +#define TUNER_Samsung_PAL_TCPM9091PD27 32 +#define TUNER_MT2032 33 +#define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865) */ +#define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099) */ + +#define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746) */ +#define TUNER_LG_PAL_NEW_TAPC 37 +#define TUNER_PHILIPS_FM1216ME_MK3 38 +#define TUNER_LG_NTSC_NEW_TAPC 39 + +#define TUNER_HITACHI_NTSC 40 +#define TUNER_PHILIPS_PAL_MK 41 +#define TUNER_PHILIPS_ATSC 42 +#define TUNER_PHILIPS_FM1236_MK3 43 + +#define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */ +/* Microtune merged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */ +#define TUNER_MICROTUNE_4049FM5 45 +#define TUNER_PANASONIC_VP27 46 +#define TUNER_LG_NTSC_TAPE 47 + +#define TUNER_TNF_8831BGFF 48 +#define TUNER_MICROTUNE_4042FI5 49 /* DViCO FusionHDTV 3 Gold-Q - 4042 FI5 (3X 8147) */ +#define TUNER_TCL_2002N 50 +#define TUNER_PHILIPS_FM1256_IH3 51 + +#define TUNER_THOMSON_DTT7610 52 +#define TUNER_PHILIPS_FQ1286 53 +#define TUNER_PHILIPS_TDA8290 54 +#define TUNER_TCL_2002MB 55 /* Hauppauge PVR-150 PAL */ + +#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */ +#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */ +#define TUNER_YMEC_TVF_8531MF 58 +#define TUNER_YMEC_TVF_5533MF 59 /* Pixelview Pro Ultra NTSC */ + +#define TUNER_THOMSON_DTT761X 60 /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ +#define TUNER_TENA_9533_DI 61 +#define TUNER_TEA5767 62 /* Only FM Radio Tuner */ +#define TUNER_PHILIPS_FMD1216ME_MK3 63 + +#define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */ +#define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */ +#define TUNER_LG_NTSC_TALN_MINI 66 +#define TUNER_PHILIPS_TD1316 67 + +#define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ +#define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ +#define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ + +#define TUNER_XCEIVE_XC3028 71 + +/* tv card specific */ +#define TDA9887_PRESENT (1<<0) +#define TDA9887_PORT1_INACTIVE (1<<1) +#define TDA9887_PORT2_INACTIVE (1<<2) +#define TDA9887_QSS (1<<3) +#define TDA9887_INTERCARRIER (1<<4) +#define TDA9887_PORT1_ACTIVE (1<<5) +#define TDA9887_PORT2_ACTIVE (1<<6) +#define TDA9887_INTERCARRIER_NTSC (1<<7) +/* Tuner takeover point adjustment, in dB, -16 <= top <= 15 */ +#define TDA9887_TOP_MASK (0x3f << 8) +#define TDA9887_TOP_SET (1 << 13) +#define TDA9887_TOP(top) (TDA9887_TOP_SET | (((16 + (top)) & 0x1f) << 8)) + +/* config options */ +#define TDA9887_DEEMPHASIS_MASK (3<<16) +#define TDA9887_DEEMPHASIS_NONE (1<<16) +#define TDA9887_DEEMPHASIS_50 (2<<16) +#define TDA9887_DEEMPHASIS_75 (3<<16) +#define TDA9887_AUTOMUTE (1<<18) + + +#ifdef __KERNEL__ + +enum tuner_mode { + T_UNINITIALIZED = 0, + T_RADIO = 1 << V4L2_TUNER_RADIO, + T_ANALOG_TV = 1 << V4L2_TUNER_ANALOG_TV, + T_DIGITAL_TV = 1 << V4L2_TUNER_DIGITAL_TV, + T_STANDBY = 1 << 31 +}; + +/* Older boards only had a single tuner device. Nowadays multiple tuner + devices may be present on a single board. Using TUNER_SET_TYPE_ADDR + to pass the tuner_setup structure it is possible to setup each tuner + device in turn. + + Since multiple devices may be present it is no longer sufficient to + send a command to a single i2c device. Instead you should broadcast + the command to all i2c devices. + + By setting the mode_mask correctly you can select which commands are + accepted by a specific tuner device. For example, set mode_mask to + T_RADIO if the device is a radio-only tuner. That specific tuner will + only accept commands when the tuner is in radio mode and ignore them + when the tuner is set to TV mode. + */ + +struct tuner_setup { + unsigned short addr; /* I2C address */ + unsigned int type; /* Tuner type */ + unsigned int mode_mask; /* Allowed tuner modes */ +}; + +struct tuner { + /* device */ + struct i2c_client i2c; + + unsigned int type; /* chip type */ + + unsigned int mode; + unsigned int mode_mask; /* Combination of allowable modes */ + + unsigned int tv_freq; /* keep track of the current settings */ + unsigned int radio_freq; + u16 last_div; + unsigned int audmode; + v4l2_std_id std; + + int using_v4l2; + + /* used by MT2032 */ + unsigned int xogc; + unsigned int radio_if2; + + /* used by tda8290 */ + unsigned char tda8290_easy_mode; + unsigned char tda827x_lpsel; + unsigned char tda827x_addr; + unsigned char tda827x_ver; + unsigned int sgIF; + + /* function ptrs */ + void (*set_tv_freq)(struct i2c_client *c, unsigned int freq); + void (*set_radio_freq)(struct i2c_client *c, unsigned int freq); + int (*has_signal)(struct i2c_client *c); + int (*is_stereo)(struct i2c_client *c); + void (*standby)(struct i2c_client *c); +}; + +extern unsigned const int tuner_count; + +extern int microtune_init(struct i2c_client *c); +extern int tda8290_init(struct i2c_client *c); +extern int xc3028_init(struct i2c_client *c); +extern int tda8290_probe(struct i2c_client *c); +extern int tea5767_tuner_init(struct i2c_client *c); +extern int default_tuner_init(struct i2c_client *c); +extern int tea5767_autodetection(struct i2c_client *c); + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) +#define tuner_warn(fmt, arg...) do {\ + printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#define tuner_info(fmt, arg...) do {\ + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#define tuner_dbg(fmt, arg...) do {\ + extern int tuner_debug; \ + if (tuner_debug) \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#else +#define tuner_warn(fmt, arg...) do {\ + printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#define tuner_info(fmt, arg...) do {\ + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#define tuner_dbg(fmt, arg...) do {\ + extern int tuner_debug; \ + if (tuner_debug) \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#endif + +#endif /* __KERNEL__ */ + +#endif /* _TUNER_H */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/v4l_experimental/xc3028/xc3028.c b/v4l_experimental/xc3028/xc3028.c new file mode 100644 index 000000000..b6395396f --- /dev/null +++ b/v4l_experimental/xc3028/xc3028.c @@ -0,0 +1,225 @@ +/* + + Xceive - xc3028 tuner interface + + Copyright (c) 2006 Markus Rechberger <mrechberger@gmail.com> + + +TODO: - remove em28xx dependency + - add channel locking (requires some more reverse engineering) + - try to get the datasheet from Xceive :) + + 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 <linux/usb.h> +#include "compat.h" +#include <linux/videodev.h> +#include "em28xx.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 + +#define XC3028_DEFAULT_FIRMWARE "xceive_xc_3028.fw" + +int xceive_set_color(struct i2c_client *c); + +/* ---------------------------------------------------------------------- */ + +int xc3028_probe(struct i2c_client *c) +{ + printk("probe function unknown\n"); + return -1; +} + +static void xc3028_set_tv_freq(struct i2c_client *c, unsigned int freq){ + // the frequency is just shifted and there's a 1:1 relation for all frequencies + // E11 is Das Erste in Germany/Ulm all other channels match their frequency too + + unsigned char chanbuf[10]; + freq<<=2; + printk("setting channel: 0x%02x%02x\n",(freq&0xff00)>>8,freq&0x00ff); + sprintf(chanbuf," %c%c",(freq&0xff00)>>8,freq&0x00ff); // extract the highest & lowest byte + chanbuf[0]=0; + chanbuf[1]=0; + i2c_master_send(c,"\xa0\x00\x00\x00",4); + i2c_master_send(c,"\x1e\x1f\x13\x87\x18\x02\x93\x91\x44\x86\x96\x8c",12); + i2c_master_send(c,"\x00\x8c",2); + i2c_master_send(c,"\x80\x02\x00\x00",4); + i2c_master_send(c,chanbuf,4); +} + +int xc3028_init(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + int ret; + const struct firmware *fw = NULL; + u8 *firmware; + char *fwoffset; + u8 initoffset[8]; + u8 linebuffer[100]; + int splitrange; + struct em28xx *dev; + int i=0; + int d=0; + int txtlen; + long fwoff; + size_t firmware_size = 5000; + printk("Xceive 3028 tuner init()\n"); + printk("reached first firmwareoffset!\n"); + printk("--- request firmware here --\n"); + + // request firmware from /lib/firmware, note that the file got extracted by the convert application I wrote and which is available + // on linuxtv.org / xc3028 + + ret = request_firmware(&fw, XC3028_DEFAULT_FIRMWARE, &t->i2c.dev); + if (ret) { + printk("xc3028: no firmware uploaded please check %s\n",XC3028_DEFAULT_FIRMWARE); + return ret; + } + firmware = fw->data; + firmware_size = fw->size; + + // small firmware check, both firmwares I have are between 6 and 7k bytes + + if(fw->size>7000||fw->size<6000){ + printk("xc3028: wrong firmware provided!\n"); + release_firmware(fw); + return(ret); + } + for(i=0;i<8&&firmware[i]!='\n';i++); + txtlen=i; + firmware[i++]=0; + fwoff=simple_strtol(firmware,&fwoffset,10); + if(fwoff>fw->size){ + printk("firmware offset doesn't match!\n"); + release_firmware(fw); + return(-1); + } + + printk("strtol: %ld\n",fwoff); + linebuffer[d++]=0x2a; + dev=c->adapter->algo_data; + + // 0x08 is a GPIO address of the em28xx has to get replaced with something generic here + + dev->em28xx_write_regs(dev, 0x08, "\x6d", 1); + mdelay(100); + dev->em28xx_write_regs(dev, 0x08, "\x7d", 1); + mdelay(100); + + // the firmware always starts with 0x2a + 0x40 bytes payload I use to add the offset of the first part + // as the first line into the firmware binary + + while(i!=fw->size){ + linebuffer[d++]=firmware[i]; + if((d%64==0&&d!=0)||i==fwoff+txtlen){ + i2c_master_send(c,linebuffer,d); + if(i==(fwoff+txtlen)){ + printk("\n\n --- FWINIT REACHED!! --\n\n"); + i2c_master_send(c,"\x02\x02",2); + i2c_master_send(c,"\x02\x03",2); + i2c_master_send(c,"\x00\x8c",2); + i2c_master_send(c,"\x00\x00\x00\x00",4); + // another reset here + dev->em28xx_write_regs(dev, 0x08, "\x6d", 1); + mdelay(100); + dev->em28xx_write_regs(dev, 0x08, "\x7d", 1); + mdelay(100); + + } + linebuffer[0]=0x2a; + d=1; + } + i++; + } + + printk("Firmware looks ok!\n"); + firmware[firmware_size-1]=0; + printk("loaded firmware size: %u\n",firmware_size); + + release_firmware(fw); + + /* MAGIC VALUES */ + i2c_master_send(c,"\x13\x39",2); + i2c_master_send(c,"\x0c\x80\xf0\xf7\x3e\x75\xc1\x8a\xe4\x02\x00",11); + i2c_master_send(c,"\x05\x0f\xee\xaa\x5f\xea\x90",7); + i2c_master_send(c,"\x06\x00\x0a\x4d\x8c\xf2\xd8\xcf\x30\x79\x9f",11); + i2c_master_send(c,"\x0b\x0d\xa4\x6c",4); + i2c_master_send(c,"\x0a\x01\x67\x24\x40\x08\xc3\x20\x10\x64\x3c\xfa\xf7\xe1\x0c\x2c",0x10); + i2c_master_send(c,"\x09\x0b",0x2); + i2c_master_send(c,"\x10\x13",0x2); + i2c_master_send(c,"\x16\x12",0x2); + i2c_master_send(c,"\x1f\x02",0x2); + i2c_master_send(c,"\x21\x02",0x2); + i2c_master_send(c,"\x01\x02",0x2); + i2c_master_send(c,"\x2b\x10",0x2); + i2c_master_send(c,"\x02\x02",0x2); + i2c_master_send(c,"\x02\x03",0x2); + i2c_master_send(c,"\x00\x8c",0x2); + +#if 0 + // if set video will mostly be black/white - if set_color is called instead the video will have color + i2c_master_send(c,"\x80\x01\x00\x00",0x4); + i2c_master_send(c,"\x00\x5e\x00\x29",0x4); + i2c_master_send(c,"\x2b\x1a",0x2); +#endif + xceive_set_color(c); + printk("setting set_tv_freq!\n"); + t->set_tv_freq = xc3028_set_tv_freq; + return(0); +} + +int xceive_set_color(struct i2c_client *c){ + // I found this codeblock within the sniffed logfile it got called as it is a several times after 0x00 0x04 tuner settings are made + i2c_master_send(c,"\x80\x01\x00\x00",4); + i2c_master_send(c,"\x00\x5e\x00\x29",4); + i2c_master_send(c,"\x2b\x1a",2); + i2c_master_send(c,"\x2b\x1b",2); + i2c_master_send(c,"\x14\x01\x6c\x25\x82\x38\xa4\x49\xa9\x24\x96\x69",0x0c); + i2c_master_send(c,"\x13\x14\x08\x30\x10\x6c\x18\x12\x0d\x19\x32\xad",0x0c); + i2c_master_send(c,"\x0d\x01\x4b\x03\x97\x55\xc7\xd7\x00\xa1\xeb\x8f\x5c",0x0d); + i2c_master_send(c,"\x1a\x00\x00\x16\x8a\x40\x00\x00\x00\x20",0x0a); + i2c_master_send(c,"\x2d\x01",2); + i2c_master_send(c,"\x18\x01",2); + i2c_master_send(c,"\x1b\x01\xb6\x15\x16\xb1\xa6\xd2\xa9\x12\x41\x66",0x0c); + i2c_master_send(c,"\x1d\x00",2); + i2c_master_send(c,"\x0f\x00\x29\x56\xb0\x00\xb6",0x07); + i2c_master_send(c,"\x20\x00",0x02); + i2c_master_send(c,"\x1e\x10\x32\x00\x00\x02\xe4\x81\x00\x06\xa9\x04",0x0c); + i2c_master_send(c,"\x22\x29",0x02); + i2c_master_send(c,"\x23\x06",0x02); + i2c_master_send(c,"\x25\x00\x09\x90\x09\x06\x64\x02\x41",0x09); + i2c_master_send(c,"\x26\xcc",0x02); + i2c_master_send(c,"\x29\x40",0x02); + i2c_master_send(c,"\x21\x03",0x02); + i2c_master_send(c,"\x00\x8c",0x02); + i2c_master_send(c,"\x00\x00\x00\x00",0x04); + i2c_master_send(c,"\x00\x04",0x02); + return(0); +} + + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ |