diff options
68 files changed, 6293 insertions, 5255 deletions
@@ -44,4 +44,5 @@ v4l2-apps/util/qv4l2/Makefile$ v4l2-apps/util/qv4l2/moc_general-tab.cpp$ v4l2-apps/util/qv4l2/moc_qv4l2.cpp$ v4l2-apps/util/qv4l2/qv4l2$ +v4l2-apps/util/rds/rds-saa6588$ v4l2-apps/util/v4l2-ctl$ diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index dbc19ca9e..6a8469f2b 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -2,7 +2,7 @@ 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2750,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] - 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200] + 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] 5 -> MSI VOX USB 2.0 (em2820/em2840) 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index 29ca16cdb..5d3b6b4d2 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -80,7 +80,7 @@ 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) 80 -> ASUS Digimatrix TV [1043:0210] 81 -> Philips Tiger reference design [1131:2018] - 82 -> MSI TV@Anywhere plus [1462:6231] + 82 -> MSI TV@Anywhere plus [1462:6231,1462:8624] 83 -> Terratec Cinergy 250 PCI TV [153b:1160] 84 -> LifeView FlyDVB Trio [5168:0319] 85 -> AverTV DVB-T 777 [1461:2c05,1461:2c05] @@ -116,3 +116,16 @@ 115 -> Sabrent PCMCIA TV-PCB05 [0919:2003] 116 -> 10MOONS TM300 TV Card [1131:2304] 117 -> Avermedia Super 007 [1461:f01d] +118 -> Beholder BeholdTV 401 [0000:4016] +119 -> Beholder BeholdTV 403 [0000:4036] +120 -> Beholder BeholdTV 403 FM [0000:4037] +121 -> Beholder BeholdTV 405 [0000:4050] +122 -> Beholder BeholdTV 405 FM [0000:4051] +123 -> Beholder BeholdTV 407 [0000:4070] +124 -> Beholder BeholdTV 407 FM [0000:4071] +125 -> Beholder BeholdTV 409 [0000:4090] +126 -> Beholder BeholdTV 505 FM/RDS [0000:5051,0000:505B,5ace:5050] +127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090] +128 -> Beholder BeholdTV Columbus TVFM [0000:5201] +129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093] +130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193] diff --git a/linux/Documentation/video4linux/CARDLIST.usbvision b/linux/Documentation/video4linux/CARDLIST.usbvision index 3d6850ef0..0b72d3fee 100644 --- a/linux/Documentation/video4linux/CARDLIST.usbvision +++ b/linux/Documentation/video4linux/CARDLIST.usbvision @@ -62,3 +62,4 @@ 61 -> Pinnacle Studio Linx Video input cable (PAL) [2304:0301] 62 -> Pinnacle PCTV Bungee USB (PAL) FM [2304:0419] 63 -> Hauppauge WinTv-USB [2400:4200] + 64 -> Pinnacle Studio PCTV USB (NTSC) FM V3 [2304:0113] diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index a15adf834..713d62c85 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -1898,3 +1898,107 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce); + +/* + * Igor Kuznetsov <igk72@ya.ru> + * Andrey J. Melnikov <temnota@kmv.ru> + * + * Keytable is used by BeholdTV 60x series, M6 series at + * least, and probably other cards too. + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ +IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { + + /* 0x1c 0x12 * + * TV/FM POWER * + * */ + [ 0x1c ] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */ + [ 0x12 ] = KEY_POWER, + + /* 0x01 0x02 0x03 * + * 1 2 3 * + * * + * 0x04 0x05 0x06 * + * 4 5 6 * + * * + * 0x07 0x08 0x09 * + * 7 8 9 * + * */ + [ 0x01 ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x03 ] = KEY_3, + [ 0x04 ] = KEY_4, + [ 0x05 ] = KEY_5, + [ 0x06 ] = KEY_6, + [ 0x07 ] = KEY_7, + [ 0x08 ] = KEY_8, + [ 0x09 ] = KEY_9, + + /* 0x0a 0x00 0x17 * + * RECALL 0 MODE * + * */ + [ 0x0a ] = KEY_AGAIN, + [ 0x00 ] = KEY_0, + [ 0x17 ] = KEY_MODE, + + /* 0x14 0x10 * + * ASPECT FULLSCREEN * + * */ + [ 0x14 ] = KEY_SCREEN, + [ 0x10 ] = KEY_ZOOM, + + /* 0x0b * + * Up * + * * + * 0x18 0x16 0x0c * + * Left Ok Right * + * * + * 0x015 * + * Down * + * */ + [ 0x0b ] = KEY_CHANNELUP, /*XXX KEY_UP */ + [ 0x18 ] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */ + [ 0x16 ] = KEY_OK, /*XXX KEY_ENTER */ + [ 0x0c ] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */ + [ 0x15 ] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */ + + /* 0x11 0x0d * + * MUTE INFO * + * */ + [ 0x11 ] = KEY_MUTE, + [ 0x0d ] = KEY_INFO, + + /* 0x0f 0x1b 0x1a * + * RECORD PLAY/PAUSE STOP * + * * + * 0x0e 0x1f 0x1e * + *TELETEXT AUDIO SOURCE * + * RED YELLOW * + * */ + [ 0x0f ] = KEY_RECORD, + [ 0x1b ] = KEY_PLAYPAUSE, + [ 0x1a ] = KEY_STOP, + [ 0x0e ] = KEY_TEXT, + [ 0x1f ] = KEY_RED, /*XXX KEY_AUDIO */ + [ 0x1e ] = KEY_YELLOW, /*XXX KEY_SOURCE */ + + /* 0x1d 0x13 0x19 * + * SLEEP PREVIEW DVB * + * GREEN BLUE * + * */ + [ 0x1d ] = KEY_SLEEP, + [ 0x13 ] = KEY_GREEN, + [ 0x19 ] = KEY_BLUE, /*XXX KEY_SAT */ + + /* 0x58 0x5c * + * FREEZE SNAPSHOT * + * */ + [ 0x58 ] = KEY_SLOW, + [ 0x5c ] = KEY_SAVE, + +}; + +EXPORT_SYMBOL_GPL(ir_codes_behold); diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index 29ec9ac8f..3391777e0 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -750,6 +750,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, struct i2c_adapter* i2c) { struct s5h1409_state* state = NULL; + u16 reg; /* allocate memory for the internal state */ state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL); @@ -763,7 +764,8 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, state->if_freq = S5H1409_VSB_IF_FREQ; /* check if the demod exists */ - if (s5h1409_readreg(state, 0x04) != 0x0066) + reg = s5h1409_readreg(state, 0x04); + if ((reg != 0x0066) && (reg != 0x007f)) goto error; /* create dvb_frontend */ @@ -771,19 +773,15 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; - /* Note: Leaving the I2C gate open here. */ - s5h1409_writereg(state, 0xf3, 1); - -#if 0 - /* Enable GPIO to disable EZ QAM before - * analog tuners try to calibrate. */ - - s5h1409_set_gpio(fe, 1); + if (s5h1409_init(&state->frontend) != 0) { + printk(KERN_ERR "%s: Failed to initialize correctly\n", + __FUNCTION__); + goto error; + } - or ? + /* Note: Leaving the I2C gate open here. */ + s5h1409_i2c_gate_ctrl(&state->frontend, 1); - s5h1409_set_gpio(fe, state->config->gpio); -#endif return &state->frontend; error: diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 89cb1c5f8..35b0814e0 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -2801,12 +2801,12 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr) } -static struct saa7146_extension av7110_extension; +static struct saa7146_extension av7110_extension_driver; #define MAKE_AV7110_INFO(x_var,x_name) \ static struct saa7146_pci_extension_data x_var = { \ .ext_priv = x_name, \ - .ext = &av7110_extension } + .ext = &av7110_extension_driver } MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C"); MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X"); @@ -2844,7 +2844,7 @@ static struct pci_device_id pci_tbl[] = { MODULE_DEVICE_TABLE(pci, pci_tbl); -static struct saa7146_extension av7110_extension = { +static struct saa7146_extension av7110_extension_driver = { .name = "dvb", .flags = SAA7146_USE_I2C_IRQ, @@ -2861,14 +2861,14 @@ static struct saa7146_extension av7110_extension = { static int __init av7110_init(void) { int retval; - retval = saa7146_register_extension(&av7110_extension); + retval = saa7146_register_extension(&av7110_extension_driver); return retval; } static void __exit av7110_exit(void) { - saa7146_unregister_extension(&av7110_extension); + saa7146_unregister_extension(&av7110_extension_driver); } module_init(av7110_init); diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 06e61146a..a61076fb2 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -481,8 +481,7 @@ static int __init fmr2_init(void) return -EBUSY; } - if(video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr)==-1) - { + if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 2); return -EINVAL; } diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 7431f6da5..a2e8987a6 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -821,6 +821,19 @@ config USB_ZR364XX To compile this driver as a module, choose M here: the module will be called zr364xx. +config USB_STKWEBCAM + tristate "USB Syntek DC1125 Camera support" + depends on VIDEO_V4L2 && EXPERIMENTAL + ---help--- + Say Y here if you want to use this type of camera. + Supported devices are typically found in some Asus laptops, + with USB id 174f:a311 and 05e1:0501. Other Syntek cameras + may be supported by the stk11xx driver, from which this is + derived, see http://stk11xx.sourceforge.net + + To compile this driver as a module, choose M here: the + module will be called stkwebcam. + endif # V4L_USB_DRIVERS endif # VIDEO_CAPTURE_DRIVERS diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 74a2a1c45..28ddd146c 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -8,6 +8,8 @@ tuner-objs := tuner-core.o tuner-types.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o +stkwebcam-objs := stk-webcam.o stk-sensor.o + obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \ v4l2-int-device.o @@ -116,6 +118,7 @@ obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_STV680) += stv680.o obj-$(CONFIG_USB_W9968CF) += w9968cf.o obj-$(CONFIG_USB_ZR364XX) += zr364xx.o +obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o obj-$(CONFIG_USB_SN9C102) += sn9c102/ obj-$(CONFIG_USB_ET61X251) += et61x251/ diff --git a/linux/drivers/media/video/bt8xx/bttv-input.c b/linux/drivers/media/video/bt8xx/bttv-input.c index a50be88cd..37954b653 100644 --- a/linux/drivers/media/video/bt8xx/bttv-input.c +++ b/linux/drivers/media/video/bt8xx/bttv-input.c @@ -69,6 +69,11 @@ static void ir_handle_key(struct bttv *btv) (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { ir_input_keydown(ir->dev,&ir->ir,data,data); } else { + /* HACK: Probably, ir->mask_keydown is missing + for this board */ + if (btv->c.type == BTTV_BOARD_WINFAST2000) + ir_input_keydown(ir->dev, &ir->ir, data, data); + ir_input_nokey(ir->dev,&ir->ir); } diff --git a/linux/drivers/media/video/bw-qcam.c b/linux/drivers/media/video/bw-qcam.c index 42df7701a..7c165c7cf 100644 --- a/linux/drivers/media/video/bw-qcam.c +++ b/linux/drivers/media/video/bw-qcam.c @@ -85,11 +85,16 @@ OTHER DEALINGS IN THE SOFTWARE. static unsigned int maxpoll=250; /* Maximum busy-loop count for qcam I/O */ static unsigned int yieldlines=4; /* Yield after this many during capture */ static int video_nr = -1; +static unsigned int force_init; /* Whether to probe aggressively */ module_param(maxpoll, int, 0); module_param(yieldlines, int, 0); module_param(video_nr, int, 0); +/* Set force_init=1 to avoid detection by polling status register and + * immediately attempt to initialize qcam */ +module_param(force_init, int, 0); + static inline int read_lpstatus(struct qcam_device *q) { return parport_read_status(q->pport); @@ -334,6 +339,9 @@ static int qc_detect(struct qcam_device *q) int count = 0; int i; + if (force_init) + return 1; + lastreg = reg = read_lpstatus(q) & 0xf0; for (i = 0; i < 500; i++) @@ -357,12 +365,12 @@ static int qc_detect(struct qcam_device *q) /* Be (even more) liberal in what you accept... */ -/* if (count > 30 && count < 200) */ if (count > 20 && count < 400) { return 1; /* found */ } else { printk(KERN_ERR "No Quickcam found on port %s\n", q->pport->name); + printk(KERN_DEBUG "Quickcam detection counter: %u\n", count); return 0; /* not found */ } } diff --git a/linux/drivers/media/video/cx23885/Makefile b/linux/drivers/media/video/cx23885/Makefile index 665067022..32c90be50 100644 --- a/linux/drivers/media/video/cx23885/Makefile +++ b/linux/drivers/media/video/cx23885/Makefile @@ -1,4 +1,4 @@ -cx23885-objs := cx23885-cards.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o +cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index c14a3f3cd..36d9b6a4a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -23,6 +23,7 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> +#include <media/cx25840.h> #include "compat.h" #include "cx23885.h" @@ -33,6 +34,8 @@ struct cx23885_board cx23885_boards[] = { [CX23885_BOARD_UNKNOWN] = { .name = "UNKNOWN/GENERIC", + /* Ensure safe default for unknown boards */ + .clk_freq = 0, .input = {{ .type = CX23885_VMUX_COMPOSITE1, .vmux = 0, @@ -70,23 +73,29 @@ struct cx23885_board cx23885_boards[] = { }, [CX23885_BOARD_HAUPPAUGE_HVR1800] = { .name = "Hauppauge WinTV-HVR1800", + .porta = CX23885_ANALOG_VIDEO, .portc = CX23885_MPEG_DVB, + .tuner_type = TUNER_PHILIPS_TDA8290, + .tuner_addr = 0x42, /* 0x84 >> 1 */ .input = {{ .type = CX23885_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xff00, - },{ - .type = CX23885_VMUX_DEBUG, - .vmux = 0, - .gpio0 = 0xff01, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN5_CH2 | + CX25840_VIN2_CH1, + .gpio0 = 0, },{ .type = CX23885_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xff02, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN4_CH2 | + CX25840_VIN6_CH1, + .gpio0 = 0, },{ .type = CX23885_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xff02, + .vmux = CX25840_VIN7_CH3 | + CX25840_VIN4_CH2 | + CX25840_VIN8_CH1 | + CX25840_SVIDEO_ON, + .gpio0 = 0, }}, }, [CX23885_BOARD_HAUPPAUGE_HVR1250] = { @@ -269,7 +278,13 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-15-18 cx23417 READY, CS, RD, WR */ /* GPIO-19 IR_RX */ - cx_set(GP0_IO, 0x00040004); /* Bring the tuner out of reset */ + /* Force the TDA8295A into reset and back */ + cx_set(GP0_IO, 0x00040004); + mdelay(20); + cx_clear(GP0_IO, 0x00000004); + mdelay(20); + cx_set(GP0_IO, 0x00040004); + mdelay(20); break; } } diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 205b7b594..1a6d87490 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -37,7 +37,7 @@ MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages"); @@ -45,13 +45,15 @@ static unsigned int card[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card,"card type"); -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/0: " fmt, dev->name , ## arg) +#define dprintk(level, fmt, arg...)\ + do { if (debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ + } while (0) static unsigned int cx23885_devcount; static DEFINE_MUTEX(devlist); -static LIST_HEAD(cx23885_devlist); +LIST_HEAD(cx23885_devlist); #define NO_SYNC_LINE (-1U) @@ -76,12 +78,12 @@ static LIST_HEAD(cx23885_devlist); static struct sram_channel cx23885_sram_channels[] = { [SRAM_CH01] = { - .name = "test ch1", + .name = "VID A", .cmds_start = 0x10000, - .ctrl_start = 0x10500, - .cdt = 0x10900, - .fifo_start = 0x3000, - .fifo_size = 0x1000, + .ctrl_start = 0x105b0, + .cdt = 0x107b0, + .fifo_start = 0x40, + .fifo_size = 0x2800, .ptr1_reg = DMA1_PTR1, .ptr2_reg = DMA1_PTR2, .cnt1_reg = DMA1_CNT1, @@ -103,8 +105,8 @@ static struct sram_channel cx23885_sram_channels[] = { [SRAM_CH03] = { .name = "TS1 B", .cmds_start = 0x100A0, - .ctrl_start = 0x10780, - .cdt = 0x10400, + .ctrl_start = 0x10630, + .cdt = 0x10870, .fifo_start = 0x5000, .fifo_size = 0x1000, .ptr1_reg = DMA3_PTR1, @@ -140,7 +142,7 @@ static struct sram_channel cx23885_sram_channels[] = { .name = "TS2 C", .cmds_start = 0x10140, .ctrl_start = 0x10680, - .cdt = 0x10480, + .cdt = 0x108d0, .fifo_start = 0x6000, .fifo_size = 0x1000, .ptr1_reg = DMA5_PTR1, @@ -208,12 +210,12 @@ static struct sram_channel cx23885_sram_channels[] = { static struct sram_channel cx23887_sram_channels[] = { [SRAM_CH01] = { - .name = "test ch1", - .cmds_start = 0x0, - .ctrl_start = 0x0, - .cdt = 0x0, - .fifo_start = 0x0, - .fifo_size = 0x0, + .name = "VID A", + .cmds_start = 0x10000, + .ctrl_start = 0x105b0, + .cdt = 0x107b0, + .fifo_start = 0x40, + .fifo_size = 0x2800, .ptr1_reg = DMA1_PTR1, .ptr2_reg = DMA1_PTR2, .cnt1_reg = DMA1_CNT1, @@ -232,12 +234,12 @@ static struct sram_channel cx23887_sram_channels[] = { .cnt2_reg = DMA2_CNT2, }, [SRAM_CH03] = { - .name = "ch3", - .cmds_start = 0x0, - .ctrl_start = 0x0, - .cdt = 0x0, - .fifo_start = 0x0, - .fifo_size = 0x0, + .name = "TS1 B", + .cmds_start = 0x100A0, + .ctrl_start = 0x10780, + .cdt = 0x10400, + .fifo_start = 0x5000, + .fifo_size = 0x1000, .ptr1_reg = DMA3_PTR1, .ptr2_reg = DMA3_PTR2, .cnt1_reg = DMA3_CNT1, @@ -357,7 +359,7 @@ static int cx23885_risc_decode(u32 risc) return incr[risc >> 28] ? incr[risc >> 28] : 1; } -static void cx23885_wakeup(struct cx23885_tsport *port, +void cx23885_wakeup(struct cx23885_tsport *port, struct cx23885_dmaqueue *q, u32 count) { struct cx23885_dev *dev = port->dev; @@ -393,7 +395,7 @@ static void cx23885_wakeup(struct cx23885_tsport *port, __FUNCTION__, bc); } -static int cx23885_sram_channel_setup(struct cx23885_dev *dev, +int cx23885_sram_channel_setup(struct cx23885_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc) { @@ -466,7 +468,7 @@ static int cx23885_sram_channel_setup(struct cx23885_dev *dev, return 0; } -static void cx23885_sram_channel_dump(struct cx23885_dev *dev, +void cx23885_sram_channel_dump(struct cx23885_dev *dev, struct sram_channel *ch) { static char *name[] = { @@ -593,15 +595,18 @@ static void cx23885_reset(struct cx23885_dev *dev) mdelay(100); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH01 ], 188*4, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH02 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH03 ], 188*4, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH04 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH05 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH06 ], 188*4, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH07 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH08 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH09 ], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], + 720*4, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03], + 188*4, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06], + 188*4, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0); cx23885_gpio_setup(dev); } @@ -635,7 +640,7 @@ static int get_resources(struct cx23885_dev *dev) } static void cx23885_timeout(unsigned long data); -static int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, +int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value); static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno) @@ -703,6 +708,44 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p return 0; } +static void cx23885_dev_checkrevision(struct cx23885_dev *dev) +{ + switch (cx_read(RDR_CFG2) & 0xff) { + case 0x00: + /* cx23885 */ + dev->hwrevision = 0xa0; + break; + case 0x01: + /* CX23885-12Z */ + dev->hwrevision = 0xa1; + break; + case 0x02: + /* CX23885-13Z */ + dev->hwrevision = 0xb0; + break; + case 0x03: + /* CX23888-22Z */ + dev->hwrevision = 0xc0; + break; + case 0x0e: + /* CX23887-15Z */ + dev->hwrevision = 0xc0; + case 0x0f: + /* CX23887-14Z */ + dev->hwrevision = 0xb1; + break; + default: + printk(KERN_ERR "%s() New hardware revision found 0x%x\n", + __FUNCTION__, dev->hwrevision); + } + if (dev->hwrevision) + printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", + __FUNCTION__, dev->hwrevision); + else + printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n", + __FUNCTION__, dev->hwrevision); +} + static int cx23885_dev_setup(struct cx23885_dev *dev) { int i; @@ -722,10 +765,14 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) if(dev->pci->device == 0x8880) { dev->bridge = CX23885_BRIDGE_887; dev->sram_channels = cx23887_sram_channels; + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 25000000; } else if(dev->pci->device == 0x8852) { dev->bridge = CX23885_BRIDGE_885; dev->sram_channels = cx23885_sram_channels; + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 28000000; } else BUG(); @@ -745,6 +792,10 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_card_list(dev); } + /* If the user specific a clk freq override, apply it */ + if (cx23885_boards[dev->board].clk_freq > 0) + dev->clk_freq = cx23885_boards[dev->board].clk_freq; + dev->pci_bus = dev->pci->bus->number; dev->pci_slot = PCI_SLOT(dev->pci->devfn); dev->pci_irqmask = 0x001f00; @@ -809,6 +860,17 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_pci_quirks(dev); + /* Assume some sensible defaults */ + dev->tuner_type = cx23885_boards[dev->board].tuner_type; + dev->tuner_addr = cx23885_boards[dev->board].tuner_addr; + dev->radio_type = cx23885_boards[dev->board].radio_type; + dev->radio_addr = cx23885_boards[dev->board].radio_addr; + + dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n", + __FUNCTION__, dev->tuner_type, dev->tuner_addr); + dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n", + __FUNCTION__, dev->radio_type, dev->radio_addr); + /* init hardware */ cx23885_reset(dev); @@ -819,20 +881,29 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_card_setup(dev); cx23885_ir_init(dev); - if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { + if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { + if (cx23885_video_register(dev) < 0) { + printk(KERN_ERR "%s() Failed to register analog " + "video adapters on VID_A\n", __FUNCTION__); + } + } + + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { if (cx23885_dvb_register(&dev->ts1) < 0) { printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", __FUNCTION__); } } - if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { + if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { if (cx23885_dvb_register(&dev->ts2) < 0) { printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n", __FUNCTION__); } } + cx23885_dev_checkrevision(dev); + return 0; } @@ -844,6 +915,9 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) if (!atomic_dec_and_test(&dev->refcount)) return; + if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) + cx23885_video_unregister(dev); + if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) cx23885_dvb_unregister(&dev->ts1); @@ -911,7 +985,6 @@ static u32* cx23885_risc_field(u32 *rp, struct scatterlist *sglist, return rp; } -#if 0 int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, struct scatterlist *sglist, unsigned int top_offset, unsigned int bottom_offset, unsigned int bpl, @@ -951,7 +1024,6 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); return 0; } -#endif /* 0 */ static int cx23885_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, @@ -984,7 +1056,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, return 0; } -static int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, +int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value) { u32 *rp; @@ -1017,6 +1089,57 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) buf->vb.state = VIDEOBUF_NEEDS_INIT; } +static void cx23885_tsport_reg_dump(struct cx23885_tsport *port) +{ + struct cx23885_dev *dev = port->dev; + + dprintk(1, "%s() Register Dump\n", __FUNCTION__); + dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __FUNCTION__, + cx_read(DEV_CNTRL2)); + dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __FUNCTION__, + cx_read(PCI_INT_MSK)); + dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __FUNCTION__, + cx_read(AUDIO_INT_INT_MSK)); + dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __FUNCTION__, + cx_read(AUD_INT_DMA_CTL)); + dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __FUNCTION__, + cx_read(AUDIO_EXT_INT_MSK)); + dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __FUNCTION__, + cx_read(AUD_EXT_DMA_CTL)); + dprintk(1, "%s() PAD_CTRL 0x%08X\n", __FUNCTION__, + cx_read(PAD_CTRL)); + dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __FUNCTION__, + cx_read(ALT_PIN_OUT_SEL)); + dprintk(1, "%s() GPIO2 0x%08X\n", __FUNCTION__, + cx_read(GPIO2)); + dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __FUNCTION__, + port->reg_gpcnt, cx_read(port->reg_gpcnt)); + dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl)); + dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_dma_ctl, cx_read(port->reg_dma_ctl)); + dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_src_sel, cx_read(port->reg_src_sel)); + dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_lngth, cx_read(port->reg_lngth)); + dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl)); + dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl)); + dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status)); + dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_sop_status, cx_read(port->reg_sop_status)); + dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat)); + dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_vld_misc, cx_read(port->reg_vld_misc)); + dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en)); + dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk)); +} + static int cx23885_start_dma(struct cx23885_tsport *port, struct cx23885_dmaqueue *q, struct cx23885_buffer *buf) @@ -1079,6 +1202,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port, cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */ + if (debug > 4) + cx23885_tsport_reg_dump(port); + return 0; } @@ -1094,7 +1220,7 @@ static int cx23885_stop_dma(struct cx23885_tsport *port) return 0; } -static int cx23885_restart_queue(struct cx23885_tsport *port, +int cx23885_restart_queue(struct cx23885_tsport *port, struct cx23885_dmaqueue *q) { struct cx23885_dev *dev = port->dev; @@ -1334,12 +1460,15 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) struct cx23885_tsport *ts1 = &dev->ts1; struct cx23885_tsport *ts2 = &dev->ts2; u32 pci_status, pci_mask; + u32 vida_status, vida_mask; u32 ts1_status, ts1_mask; u32 ts2_status, ts2_mask; - int ts1_count = 0, ts2_count = 0, handled = 0; + int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; pci_status = cx_read(PCI_INT_STAT); pci_mask = cx_read(PCI_INT_MSK); + vida_status = cx_read(VID_A_INT_STAT); + vida_mask = cx_read(VID_A_INT_MSK); ts1_status = cx_read(VID_B_INT_STAT); ts1_mask = cx_read(VID_B_INT_MSK); ts2_status = cx_read(VID_C_INT_STAT); @@ -1348,11 +1477,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) ) goto out; + vida_count = cx_read(VID_A_GPCNT); ts1_count = cx_read(ts1->reg_gpcnt); ts2_count = cx_read(ts2->reg_gpcnt); - dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", pci_status, pci_mask ); - dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", ts1_status, ts1_mask, ts1_count ); - dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", ts2_status, ts2_mask, ts2_count ); + dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", + pci_status, pci_mask); + dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n", + vida_status, vida_mask, vida_count); + dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", + ts1_status, ts1_mask, ts1_count); + dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", + ts2_status, ts2_mask, ts2_count); if ( (pci_status & PCI_MSK_RISC_RD) || (pci_status & PCI_MSK_RISC_WR) || @@ -1389,11 +1524,18 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) } - if (ts1_status) - handled += cx23885_irq_ts(ts1, ts1_status); + if (ts1_status) { + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) + handled += cx23885_irq_ts(ts1, ts1_status); + } + + if (ts2_status) { + if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) + handled += cx23885_irq_ts(ts2, ts2_status); + } - if (ts2_status) - handled += cx23885_irq_ts(ts2, ts2_status); + if (vida_status) + handled += cx23885_video_irq(dev, vida_status); if (handled) cx_write(PCI_INT_STAT, pci_status); diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 84598c514..cd935a13f 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -41,10 +41,12 @@ #include "tuner-xc2028.h" #include "tuner-xc2028-types.h" -static unsigned int debug = 0; +static unsigned int debug; -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg) +#define dprintk(level, fmt, arg...)\ + do { if (debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ + } while (0) /* ------------------------------------------------------------------ */ diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index d3dc0d604..c89e458ce 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -30,7 +30,7 @@ #include <media/v4l2-common.h> -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); @@ -38,9 +38,9 @@ static unsigned int i2c_scan = 0; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -#define dprintk(level, fmt, arg...) do { \ - if (i2c_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg); \ +#define dprintk(level, fmt, arg...)\ + do { if (i2c_debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ } while (0) #define I2C_WAIT_DELAY 32 @@ -271,13 +271,58 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, static int attach_inform(struct i2c_client *client) { - struct cx23885_dev *dev = i2c_get_adapdata(client->adapter); + struct cx23885_i2c *bus = i2c_get_adapdata(client->adapter); + struct cx23885_dev *dev = bus->dev; + struct tuner_setup tun_setup; dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", client->driver->driver.name, client->addr, client->name); if (!client->driver->command) return 0; +#if 0 + if (dev->radio_type != UNSET) { + + dprintk(1, "%s (radio) i2c attach [addr=0x%x,client=%s]\n", + client->driver->driver.name, client->addr, + client->name); + + if ((dev->radio_addr == ADDR_UNSET) || + (dev->radio_addr == client->addr)) { + tun_setup.mode_mask = T_RADIO; + tun_setup.type = dev->radio_type; + tun_setup.addr = dev->radio_addr; + + client->driver->command(client, TUNER_SET_TYPE_ADDR, + &tun_setup); + } + } +#endif + + if (dev->tuner_type != UNSET) { + + dprintk(1, "%s (tuner) i2c attach [addr=0x%x,client=%s]\n", + client->driver->driver.name, client->addr, + client->name); + + if ((dev->tuner_addr == ADDR_UNSET) || + (dev->tuner_addr == client->addr)) { + + dprintk(1, "%s (tuner || addr UNSET)\n", + client->driver->driver.name); + + dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", + client->driver->driver.name, + client->addr, client->name); + + tun_setup.mode_mask = T_ANALOG_TV; + tun_setup.type = dev->tuner_type; + tun_setup.addr = dev->tuner_addr; + + client->driver->command(client, TUNER_SET_TYPE_ADDR, + &tun_setup); + } + } return 0; } @@ -319,6 +364,7 @@ static struct i2c_adapter cx23885_i2c_adap_template = { #endif .id = I2C_HW_B_CX23885, .algo = &cx23885_i2c_algo_template, + .class = I2C_CLASS_TV_ANALOG, .client_register = attach_inform, .client_unregister = detach_inform, }; @@ -374,6 +420,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; + i2c_set_adapdata(&bus->i2c_adap, bus); i2c_add_adapter(&bus->i2c_adap); bus->i2c_client.adapter = &bus->i2c_adap; diff --git a/linux/drivers/media/video/cx23885/cx23885-reg.h b/linux/drivers/media/video/cx23885/cx23885-reg.h index 162169f90..bdd11bc51 100644 --- a/linux/drivers/media/video/cx23885/cx23885-reg.h +++ b/linux/drivers/media/video/cx23885/cx23885-reg.h @@ -233,6 +233,17 @@ Channel manager Data Structure entry = 20 DWORD #define VID_A_INT_SSTAT 0x0004002C #define VID_B_INT_MSK 0x00040030 +#define VID_B_MSK_BAD_PKT (1 << 20) +#define VID_B_MSK_VBI_OPC_ERR (1 << 17) +#define VID_B_MSK_OPC_ERR (1 << 16) +#define VID_B_MSK_VBI_SYNC (1 << 13) +#define VID_B_MSK_SYNC (1 << 12) +#define VID_B_MSK_VBI_OF (1 << 9) +#define VID_B_MSK_OF (1 << 8) +#define VID_B_MSK_VBI_RISCI2 (1 << 5) +#define VID_B_MSK_RISCI2 (1 << 4) +#define VID_B_MSK_VBI_RISCI1 (1 << 1) +#define VID_B_MSK_RISCI1 1 #define VID_B_INT_STAT 0x00040034 #define VID_B_INT_MSTAT 0x00040038 #define VID_B_INT_SSTAT 0x0004003C @@ -276,6 +287,7 @@ Channel manager Data Structure entry = 20 DWORD #define RDR_CFG0 0x00050000 #define RDR_CFG1 0x00050004 +#define RDR_CFG2 0x00050008 #define RDR_TLCTL0 0x00050318 /* APB DMAC Current Buffer Pointer */ @@ -335,6 +347,7 @@ Channel manager Data Structure entry = 20 DWORD /* GPIO (417 Microsoftcontroller) Output Enable, Low Active */ #define MC417_OEN 0x00110024 #define MC417_CTL 0x00110028 +#define ALT_PIN_OUT_SEL 0x0011002C #define CLK_DELAY 0x00110048 #define PAD_CTRL 0x0011004C diff --git a/linux/drivers/media/video/cx23885/cx23885-vbi.c b/linux/drivers/media/video/cx23885/cx23885-vbi.c new file mode 100644 index 000000000..a6cf4146d --- /dev/null +++ b/linux/drivers/media/video/cx23885/cx23885-vbi.c @@ -0,0 +1,259 @@ +/* + * Driver for the Conexant CX23885 PCIe bridge + * + * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/slab.h> + +#include "compat.h" +#include "cx23885.h" + +static unsigned int vbibufs = 4; +module_param(vbibufs, int, 0644); +MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); + +static unsigned int vbi_debug; +module_param(vbi_debug, int, 0644); +MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]"); + +#define dprintk(level, fmt, arg...)\ + do { if (vbi_debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ + } while (0) + +/* ------------------------------------------------------------------ */ + +int cx23885_vbi_fmt(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx23885_fh *fh = priv; + struct cx23885_dev *dev = fh->dev; + + if (dev->tvnorm & V4L2_STD_525_60) { + /* ntsc */ + f->fmt.vbi.sampling_rate = 28636363; + f->fmt.vbi.start[0] = 10; + f->fmt.vbi.start[1] = 273; + + } else if (dev->tvnorm & V4L2_STD_625_50) { + /* pal */ + f->fmt.vbi.sampling_rate = 35468950; + f->fmt.vbi.start[0] = 7 - 1; + f->fmt.vbi.start[1] = 319 - 1; + } + return 0; +} + +static int cx23885_start_vbi_dma(struct cx23885_dev *dev, + struct cx23885_dmaqueue *q, + struct cx23885_buffer *buf) +{ + /* setup fifo + format */ + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], + buf->vb.width, buf->risc.dma); + + /* reset counter */ + q->count = 1; + + /* enable irqs */ + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01); + cx_set(VID_A_INT_MSK, 0x000022); + + /* start dma */ + cx_set(DEV_CNTRL2, (1<<5)); + cx_set(VID_A_DMA_CTL, 0x00000022); + + return 0; +} + +int cx23885_stop_vbi_dma(struct cx23885_dev *dev) +{ + /* stop dma */ + cx_clear(VID_A_DMA_CTL, 0x00000022); + + /* disable irqs */ + cx_clear(PCI_INT_MSK, 0x000001); + cx_clear(VID_A_INT_MSK, 0x00000022); + return 0; +} + +int cx23885_restart_vbi_queue(struct cx23885_dev *dev, + struct cx23885_dmaqueue *q) +{ + struct cx23885_buffer *buf; + struct list_head *item; + + if (list_empty(&q->active)) + return 0; + + buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue); + dprintk(2, "restart_queue [%p/%d]: restart dma\n", + buf, buf->vb.i); + cx23885_start_vbi_dma(dev, q, buf); + list_for_each(item, &q->active) { + buf = list_entry(item, struct cx23885_buffer, vb.queue); + buf->count = q->count++; + } + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + return 0; +} + +void cx23885_vbi_timeout(unsigned long data) +{ + struct cx23885_dev *dev = (struct cx23885_dev *)data; + struct cx23885_dmaqueue *q = &dev->vbiq; + struct cx23885_buffer *buf; + unsigned long flags; + + cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH02]); + + cx_clear(VID_A_DMA_CTL, 0x22); + + spin_lock_irqsave(&dev->slock, flags); + while (!list_empty(&q->active)) { + buf = list_entry(q->active.next, struct cx23885_buffer, + vb.queue); + list_del(&buf->vb.queue); + buf->vb.state = VIDEOBUF_ERROR; + wake_up(&buf->vb.done); + printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->name, + buf, buf->vb.i, (unsigned long)buf->risc.dma); + } + cx23885_restart_vbi_queue(dev, q); + spin_unlock_irqrestore(&dev->slock, flags); +} + +/* ------------------------------------------------------------------ */ +#define VBI_LINE_LENGTH 2048 +#define VBI_LINE_COUNT 17 + +static int +vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) +{ + *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2; + if (0 == *count) + *count = vbibufs; + if (*count < 2) + *count = 2; + if (*count > 32) + *count = 32; + return 0; +} + +static int +vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct cx23885_fh *fh = q->priv_data; + struct cx23885_dev *dev = fh->dev; + struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer, vb); + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + unsigned int size; + int rc; + + size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2; + if (0 != buf->vb.baddr && buf->vb.bsize < size) + return -EINVAL; + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + buf->vb.width = VBI_LINE_LENGTH; + buf->vb.height = VBI_LINE_COUNT; + buf->vb.size = size; + buf->vb.field = V4L2_FIELD_SEQ_TB; + + rc = videobuf_iolock(q, &buf->vb, NULL); + if (0 != rc) + goto fail; + cx23885_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + 0, buf->vb.width * buf->vb.height, + buf->vb.width, 0, + buf->vb.height); + } + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + + fail: + cx23885_free_buffer(q, buf); + return rc; +} + +static void +vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx23885_buffer *buf = + container_of(vb, struct cx23885_buffer, vb); + struct cx23885_buffer *prev; + struct cx23885_fh *fh = vq->priv_data; + struct cx23885_dev *dev = fh->dev; + struct cx23885_dmaqueue *q = &dev->vbiq; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx23885_start_vbi_dma(dev, q, buf); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] vbi_queue - first active\n", + buf, buf->vb.i); + + } else { + prev = list_entry(q->active.prev, struct cx23885_buffer, + vb.queue); + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63-32 */ + dprintk(2, "[%p/%d] buffer_queue - append to active\n", + buf, buf->vb.i); + } +} + +static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct cx23885_buffer *buf = + container_of(vb, struct cx23885_buffer, vb); + + cx23885_free_buffer(q, buf); +} + +struct videobuf_queue_ops cx23885_vbi_qops = { + .buf_setup = vbi_setup, + .buf_prepare = vbi_prepare, + .buf_queue = vbi_queue, + .buf_release = vbi_release, +}; + +/* ------------------------------------------------------------------ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c new file mode 100644 index 000000000..7a270f95e --- /dev/null +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -0,0 +1,1869 @@ +/* + * Driver for the Conexant CX23885 PCIe bridge + * + * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kmod.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include "compat.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) +#include <linux/kthread.h> +#endif +#include <asm/div64.h> + +#include "cx23885.h" +#include <media/v4l2-common.h> + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +/* Include V4L1 specific functions. Should be removed soon */ +#include <linux/videodev.h> +#endif + +MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); +MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>"); +MODULE_LICENSE("GPL"); + +/* ------------------------------------------------------------------ */ + +static unsigned int video_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET }; +static unsigned int vbi_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET }; +static unsigned int radio_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET }; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) +MODULE_PARM(video_nr, "1-" __stringify(CX23885_MAXBOARDS) "i"); +MODULE_PARM(vbi_nr, "1-" __stringify(CX23885_MAXBOARDS) "i"); +MODULE_PARM(radio_nr, "1-" __stringify(CX23885_MAXBOARDS) "i"); +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10) +static unsigned int dummy; +module_param_array(video_nr, int, dummy, 0444); +module_param_array(vbi_nr, int, dummy, 0444); +module_param_array(radio_nr, int, dummy, 0444); +#else +module_param_array(video_nr, int, NULL, 0444); +module_param_array(vbi_nr, int, NULL, 0444); +module_param_array(radio_nr, int, NULL, 0444); +#endif +#endif + +MODULE_PARM_DESC(video_nr, "video device numbers"); +MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); +MODULE_PARM_DESC(radio_nr, "radio device numbers"); + +static unsigned int video_debug; +module_param(video_debug, int, 0644); +MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); + +static unsigned int irq_debug; +module_param(irq_debug, int, 0644); +MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); + +static unsigned int vid_limit = 16; +module_param(vid_limit, int, 0644); +MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); + +#define dprintk(level, fmt, arg...)\ + do { if (video_debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ + } while (0) + +/* ------------------------------------------------------------------- */ +/* static data */ + +#define FORMAT_FLAGS_PACKED 0x01 + +static struct cx23885_fmt formats[] = { + { + .name = "8 bpp, gray", + .fourcc = V4L2_PIX_FMT_GREY, +#if 0 + .cxformat = ColorFormatY8, +#endif + .depth = 8, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "15 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_RGB555, +#if 0 + .cxformat = ColorFormatRGB15, +#endif + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "15 bpp RGB, be", + .fourcc = V4L2_PIX_FMT_RGB555X, +#if 0 + .cxformat = ColorFormatRGB15 | ColorFormatBSWAP, +#endif + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "16 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_RGB565, +#if 0 + .cxformat = ColorFormatRGB16, +#endif + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "16 bpp RGB, be", + .fourcc = V4L2_PIX_FMT_RGB565X, +#if 0 + .cxformat = ColorFormatRGB16 | ColorFormatBSWAP, +#endif + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "24 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_BGR24, +#if 0 + .cxformat = ColorFormatRGB24, +#endif + .depth = 24, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "32 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_BGR32, +#if 0 + .cxformat = ColorFormatRGB32, +#endif + .depth = 32, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "32 bpp RGB, be", + .fourcc = V4L2_PIX_FMT_RGB32, +#if 0 + .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | + ColorFormatWSWAP, +#endif + .depth = 32, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, +#if 0 + .cxformat = ColorFormatYUY2, +#endif + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:2:2, packed, UYVY", + .fourcc = V4L2_PIX_FMT_UYVY, +#if 0 + .cxformat = ColorFormatYUY2 | ColorFormatBSWAP, +#endif + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, +}; + +static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (formats[i].fourcc == fourcc) + return formats+i; + + printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc); + return NULL; +} + +/* ------------------------------------------------------------------- */ + +static const struct v4l2_queryctrl no_ctl = { + .name = "42", + .flags = V4L2_CTRL_FLAG_DISABLED, +}; + +static struct cx23885_ctrl cx23885_ctls[] = { + /* --- video --- */ + { + .v = { + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0x00, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = LUMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + .v = { + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = LUMA_CTRL, + .mask = 0xff00, + .shift = 8, + }, { + .v = { + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = CHROMA_CTRL, + .mask = 0xff0000, + .shift = 16, + }, { + /* strictly, this only describes only U saturation. + * V saturation is handled specially through code. + */ + .v = { + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = CHROMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + /* --- audio --- */ + .v = { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, + .reg = PATH1_CTL1, + .mask = (0x1f << 24), + .shift = 24, + }, { + .v = { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 0x3f, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .reg = PATH1_VOL_CTL, + .mask = 0xff, + .shift = 0, + } +}; +static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); + +const u32 cx23885_user_ctrls[] = { + V4L2_CID_USER_CLASS, + V4L2_CID_BRIGHTNESS, + V4L2_CID_CONTRAST, + V4L2_CID_SATURATION, + V4L2_CID_HUE, + V4L2_CID_AUDIO_VOLUME, +#if 0 + V4L2_CID_AUDIO_BALANCE, +#endif + V4L2_CID_AUDIO_MUTE, + 0 +}; +EXPORT_SYMBOL(cx23885_user_ctrls); + +static const u32 *ctrl_classes[] = { + cx23885_user_ctrls, + NULL +}; + +void cx23885_video_wakeup(struct cx23885_dev *dev, + struct cx23885_dmaqueue *q, u32 count) +{ + struct cx23885_buffer *buf; + int bc; + + for (bc = 0;; bc++) { + if (list_empty(&q->active)) + break; + buf = list_entry(q->active.next, + struct cx23885_buffer, vb.queue); + + /* count comes from the hw and is is 16bit wide -- + * this trick handles wrap-arounds correctly for + * up to 32767 buffers in flight... */ + if ((s16) (count - buf->count) < 0) + break; + + do_gettimeofday(&buf->vb.ts); + dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i, + count, buf->count); + buf->vb.state = VIDEOBUF_DONE; + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); + } + if (list_empty(&q->active)) { + del_timer(&q->timeout); + } else { + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + } + if (bc != 1) + printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", + __FUNCTION__, bc); +} + +int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) +{ + dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", + __FUNCTION__, + (unsigned int)norm, + v4l2_norm_to_name(norm)); + + dev->tvnorm = norm; + + /* Tell the analog tuner/demods */ + cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm); + + /* Tell the internal A/V decoder */ + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm); + + return 0; +} + +struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, + struct pci_dev *pci, + struct video_device *template, + char *type) +{ + struct video_device *vfd; + dprintk(1, "%s()\n", __FUNCTION__); + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0) + vfd->dev = &pci->dev; + vfd->release = video_device_release; +#endif + snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", + dev->name, type, cx23885_boards[dev->board].name); + return vfd; +} + +int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) +{ + int i; + + if (qctrl->id < V4L2_CID_BASE || + qctrl->id >= V4L2_CID_LASTP1) + return -EINVAL; + for (i = 0; i < CX23885_CTLS; i++) + if (cx23885_ctls[i].v.id == qctrl->id) + break; + if (i == CX23885_CTLS) { + *qctrl = no_ctl; + return 0; + } + *qctrl = cx23885_ctls[i].v; + return 0; +} +EXPORT_SYMBOL(cx23885_ctrl_query); + +/* ------------------------------------------------------------------- */ +/* resource management */ + +static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh, + unsigned int bit) +{ + dprintk(1, "%s()\n", __FUNCTION__); + if (fh->resources & bit) + /* have it already allocated */ + return 1; + + /* is it free? */ + mutex_lock(&dev->lock); + if (dev->resources & bit) { + /* no, someone else uses it */ + mutex_unlock(&dev->lock); + return 0; + } + /* it's free, grab it */ + fh->resources |= bit; + dev->resources |= bit; + dprintk(1, "res: get %d\n", bit); + mutex_unlock(&dev->lock); + return 1; +} + +static int res_check(struct cx23885_fh *fh, unsigned int bit) +{ + return (fh->resources & bit); +} + +static int res_locked(struct cx23885_dev *dev, unsigned int bit) +{ + return (dev->resources & bit); +} + +static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, + unsigned int bits) +{ + BUG_ON((fh->resources & bits) != bits); + dprintk(1, "%s()\n", __FUNCTION__); + + mutex_lock(&dev->lock); + fh->resources &= ~bits; + dev->resources &= ~bits; + dprintk(1, "res: put %d\n", bits); + mutex_unlock(&dev->lock); +} + +int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) +{ + struct v4l2_routing route; + memset(&route, 0, sizeof(route)); + + dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", + __FUNCTION__, + input, INPUT(input)->vmux, + INPUT(input)->gpio0, INPUT(input)->gpio1, + INPUT(input)->gpio2, INPUT(input)->gpio3); + dev->input = input; + + route.input = INPUT(input)->vmux; + + /* Tell the internal A/V decoder */ + cx23885_call_i2c_clients(&dev->i2c_bus[2], + VIDIOC_INT_S_VIDEO_ROUTING, &route); +#if 0 + route.input = 0; /* Let the AVCore default */ + cx23885_call_i2c_clients(&dev->i2c_bus[2], + VIDIOC_INT_S_AUDIO_ROUTING, &route); +#endif + + return 0; +} +EXPORT_SYMBOL(cx23885_video_mux); + +/* ------------------------------------------------------------------ */ +int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, + unsigned int height, enum v4l2_field field) +{ + dprintk(1, "%s()\n", __FUNCTION__); + return 0; +} + +static int cx23885_start_video_dma(struct cx23885_dev *dev, + struct cx23885_dmaqueue *q, + struct cx23885_buffer *buf) +{ + dprintk(1, "%s()\n", __FUNCTION__); + + /* setup fifo + format */ + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], + buf->bpl, buf->risc.dma); + cx23885_set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field); + + /* reset counter */ + cx_write(VID_A_GPCNT_CTL, 3); + q->count = 1; + + /* enable irq */ + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01); + cx_set(VID_A_INT_MSK, 0x000011); + + /* start dma */ + cx_set(DEV_CNTRL2, (1<<5)); + cx_set(VID_A_DMA_CTL, 0x11); /* FIFO and RISC enable */ + + return 0; +} + +#if 0 +#ifdef CONFIG_PM +static int cx23885_stop_video_dma(struct cx23885_dev *dev) +{ + dprintk(1, "%s()\n", __FUNCTION__); + /* stop dma */ + cx_clear(VID_A_DMA_CTL, 0x11); + + /* disable irqs */ + cx_clear(PCI_INT_MSK, 0x000001); + cx_clear(VID_A_INT_MSK, 0x000011); + + return 0; +} +#endif +#endif + +static int cx23885_restart_video_queue(struct cx23885_dev *dev, + struct cx23885_dmaqueue *q) +{ + struct cx23885_buffer *buf, *prev; + struct list_head *item; + dprintk(1, "%s()\n", __FUNCTION__); + + if (!list_empty(&q->active)) { + buf = list_entry(q->active.next, struct cx23885_buffer, + vb.queue); + dprintk(2, "restart_queue [%p/%d]: restart dma\n", + buf, buf->vb.i); + cx23885_start_video_dma(dev, q, buf); + list_for_each(item, &q->active) { + buf = list_entry(item, struct cx23885_buffer, + vb.queue); + buf->count = q->count++; + } + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + return 0; + } + + prev = NULL; + for (;;) { + if (list_empty(&q->queued)) + return 0; + buf = list_entry(q->queued.next, struct cx23885_buffer, + vb.queue); + if (NULL == prev) { + list_move_tail(&buf->vb.queue, &q->active); + cx23885_start_video_dma(dev, q, buf); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] restart_queue - first active\n", + buf, buf->vb.i); + + } else if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_move_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ + dprintk(2, "[%p/%d] restart_queue - move to active\n", + buf, buf->vb.i); + } else { + return 0; + } + prev = buf; + } +} + +static int buffer_setup(struct videobuf_queue *q, unsigned int *count, + unsigned int *size) +{ + struct cx23885_fh *fh = q->priv_data; + + *size = fh->fmt->depth*fh->width*fh->height >> 3; + if (0 == *count) + *count = 32; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + return 0; +} + +static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct cx23885_fh *fh = q->priv_data; + struct cx23885_dev *dev = fh->dev; + struct cx23885_buffer *buf = + container_of(vb, struct cx23885_buffer, vb); + int rc, init_buffer = 0; + u32 line0_offset, line1_offset; + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + + BUG_ON(NULL == fh->fmt); + if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) || + fh->height < 32 || fh->height > norm_maxh(dev->tvnorm)) + return -EINVAL; + buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + if (buf->fmt != fh->fmt || + buf->vb.width != fh->width || + buf->vb.height != fh->height || + buf->vb.field != field) { + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + init_buffer = 1; + } + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + init_buffer = 1; + rc = videobuf_iolock(q, &buf->vb, NULL); + if (0 != rc) + goto fail; + } + + if (init_buffer) { + buf->bpl = buf->vb.width * buf->fmt->depth >> 3; + switch (buf->vb.field) { + case V4L2_FIELD_TOP: + cx23885_risc_buffer(dev->pci, &buf->risc, + dma->sglist, 0, UNSET, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_BOTTOM: + cx23885_risc_buffer(dev->pci, &buf->risc, + dma->sglist, UNSET, 0, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_INTERLACED: + if (dev->tvnorm & V4L2_STD_NTSC) { + /* cx25840 transmits NTSC bottom field first */ + dprintk(1, "%s() Creating NTSC risc\n", + __FUNCTION__); + line0_offset = buf->bpl; + line1_offset = 0; + } else { + /* All other formats are top field first */ + dprintk(1, "%s() Creating PAL/SECAM risc\n", + __FUNCTION__); + line0_offset = 0; + line1_offset = buf->bpl; + } + cx23885_risc_buffer(dev->pci, &buf->risc, + dma->sglist, line0_offset, + line1_offset, + buf->bpl, buf->bpl, + buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_TB: + cx23885_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + 0, buf->bpl * (buf->vb.height >> 1), + buf->bpl, 0, + buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_BT: + cx23885_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + buf->bpl * (buf->vb.height >> 1), 0, + buf->bpl, 0, + buf->vb.height >> 1); + break; + default: + BUG(); + } + } + dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", + buf, buf->vb.i, + fh->width, fh->height, fh->fmt->depth, fh->fmt->name, + (unsigned long)buf->risc.dma); + + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + + fail: + cx23885_free_buffer(q, buf); + return rc; +} + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer, vb); + struct cx23885_buffer *prev; + struct cx23885_fh *fh = vq->priv_data; + struct cx23885_dev *dev = fh->dev; + struct cx23885_dmaqueue *q = &dev->vidq; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", + buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx23885_start_video_dma(dev, q, buf); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active\n", + buf, buf->vb.i); + + } else { + prev = list_entry(q->active.prev, struct cx23885_buffer, + vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active\n", + buf, buf->vb.i); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", + buf, buf->vb.i); + } + } +} + +static void buffer_release(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + struct cx23885_buffer *buf = container_of(vb, + struct cx23885_buffer, vb); + + cx23885_free_buffer(q, buf); +} + +static struct videobuf_queue_ops cx23885_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +static struct videobuf_queue *get_queue(struct cx23885_fh *fh) +{ + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &fh->vidq; + case V4L2_BUF_TYPE_VBI_CAPTURE: + return &fh->vbiq; + default: + BUG(); + return NULL; + } +} + +static int get_resource(struct cx23885_fh *fh) +{ + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return RESOURCE_VIDEO; + case V4L2_BUF_TYPE_VBI_CAPTURE: + return RESOURCE_VBI; + default: + BUG(); + return 0; + } +} + +static int video_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct cx23885_dev *h, *dev = NULL; + struct cx23885_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + int radio = 0; + + list_for_each(list, &cx23885_devlist) { + h = list_entry(list, struct cx23885_dev, devlist); + if (h->video_dev->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + if (h->vbi_dev && + h->vbi_dev->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VBI_CAPTURE; + } + if (h->radio_dev && + h->radio_dev->minor == minor) { + radio = 1; + dev = h; + } + } + if (NULL == dev) + return -ENODEV; + + dprintk(1, "open minor=%d radio=%d type=%s\n", + minor, radio, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) + return -ENOMEM; + file->private_data = fh; + fh->dev = dev; + fh->radio = radio; + fh->type = type; + fh->width = 320; + fh->height = 240; + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); + + videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops, + dev->pci, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx23885_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + +#if 0 + if (fh->radio) { + int board = dev->board; + dprintk(1, "video_open: setting radio device\n"); + cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); + cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); + cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); + cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); + dev->tvaudio = WW_FM; + cx23885_set_tvaudio(dev); + cx23885_set_stereo(dev, V4L2_TUNER_MODE_STEREO, 1); + cx23885_call_i2c_clients(&dev->i2c_bus[1], + AUDC_SET_RADIO, NULL); + } +#endif + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct cx23885_fh *fh = file->private_data; + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO)) + return -EBUSY; + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (!res_get(fh->dev, fh, RESOURCE_VBI)) + return -EBUSY; + return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1, + file->f_flags & O_NONBLOCK); + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct cx23885_fh *fh = file->private_data; + struct cx23885_buffer *buf; + + if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { + if (!res_get(fh->dev, fh, RESOURCE_VBI)) + return POLLERR; + return videobuf_poll_stream(file, &fh->vbiq, wait); + } + + if (res_check(fh, RESOURCE_VIDEO)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx23885_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx23885_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || + buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + return 0; +} + +static int video_release(struct inode *inode, struct file *file) +{ + struct cx23885_fh *fh = file->private_data; + struct cx23885_dev *dev = fh->dev; + + /* turn off overlay */ + if (res_check(fh, RESOURCE_OVERLAY)) { + /* FIXME */ + res_free(dev, fh, RESOURCE_OVERLAY); + } + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO); + } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + /* stop vbi capture */ + if (res_check(fh, RESOURCE_VBI)) { + if (fh->vbiq.streaming) + videobuf_streamoff(&fh->vbiq); + if (fh->vbiq.reading) + videobuf_read_stop(&fh->vbiq); + res_free(dev, fh, RESOURCE_VBI); + } + + videobuf_mmap_free(&fh->vidq); +#if 0 + videobuf_mmap_free(&fh->vbiq); +#endif + file->private_data = NULL; + kfree(fh); + + /* We are not putting the tuner to sleep here on exit, because + * we want to use the mpeg encoder in another session to capture + * tuner video. Closing this will result in no video to the encoder. + */ +#if 0 + cx23885_call_i2c_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, NULL); +#endif + + return 0; +} + +static int video_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct cx23885_fh *fh = file->private_data; + + return videobuf_mmap_mapper(get_queue(fh), vma); +} + +/* ------------------------------------------------------------------ */ +/* VIDEO CTRL IOCTLS */ + +int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) +{ + dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__); + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); + return 0; +} +EXPORT_SYMBOL(cx23885_get_control); + +int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) +{ + dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" + " (disabled - no action)\n", __FUNCTION__); +#if 0 + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl); +#endif + return 0; +} +EXPORT_SYMBOL(cx23885_set_control); + +static void init_controls(struct cx23885_dev *dev) +{ + struct v4l2_control ctrl; + int i; + + for (i = 0; i < CX23885_CTLS; i++) { + ctrl.id = cx23885_ctls[i].v.id; + ctrl.value = cx23885_ctls[i].v.default_value; + + cx23885_set_control(dev, &ctrl); + } +} + +/* ------------------------------------------------------------------ */ +/* VIDEO IOCTLS */ + +static int vidioc_g_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx23885_fh *fh = priv; + + f->fmt.pix.width = fh->width; + f->fmt.pix.height = fh->height; + f->fmt.pix.field = fh->vidq.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fh->fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int vidioc_try_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + struct cx23885_fmt *fmt; + enum v4l2_field field; + unsigned int maxw, maxh; + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (NULL == fmt) + return -EINVAL; + + field = f->fmt.pix.field; + maxw = norm_maxw(dev->tvnorm); + maxh = norm_maxh(dev->tvnorm); + + if (V4L2_FIELD_ANY == field) { + field = (f->fmt.pix.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_BOTTOM; + } + + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + return -EINVAL; + } + + f->fmt.pix.field = field; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + f->fmt.pix.width &= ~0x03; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int vidioc_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx23885_fh *fh = priv; + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + int err; + + dprintk(2, "%s()\n", __FUNCTION__); + err = vidioc_try_fmt_cap(file, priv, f); + + if (0 != err) + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__, + fh->width, fh->height, fh->vidq.field); + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f); + return 0; +} + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + strcpy(cap->driver, "cx23885"); + strlcpy(cap->card, cx23885_boards[dev->board].name, + sizeof(cap->card)); + sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); + cap->version = CX23885_VERSION_CODE; + cap->capabilities = +#if 0 + V4L2_CAP_VIDEO_OVERLAY | +#endif + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING | + V4L2_CAP_VBI_CAPTURE; + if (UNSET != dev->tuner_type) + cap->capabilities |= V4L2_CAP_TUNER; + return 0; +} + +static int vidioc_enum_fmt_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (unlikely(f->index >= ARRAY_SIZE(formats))) + return -EINVAL; + + strlcpy(f->description, formats[f->index].name, + sizeof(f->description)); + f->pixelformat = formats[f->index].fourcc; + + return 0; +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf(struct file *file, void *priv, + struct video_mbuf *mbuf) +{ + struct cx23885_fh *fh = priv; + struct videobuf_queue *q; + struct v4l2_requestbuffers req; + unsigned int i; + int err; + + q = get_queue(fh); + memset(&req, 0, sizeof(req)); + req.type = q->type; + req.count = 8; + req.memory = V4L2_MEMORY_MMAP; + err = videobuf_reqbufs(q, &req); + if (err < 0) + return err; + + mbuf->frames = req.count; + mbuf->size = 0; + for (i = 0; i < mbuf->frames; i++) { + mbuf->offsets[i] = q->bufs[i]->boff; + mbuf->size += q->bufs[i]->bsize; + } + return 0; +} +#endif + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + struct cx23885_fh *fh = priv; + return (videobuf_reqbufs(get_queue(fh), p)); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct cx23885_fh *fh = priv; + return (videobuf_querybuf(get_queue(fh), p)); +} + +static int vidioc_qbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct cx23885_fh *fh = priv; + return (videobuf_qbuf(get_queue(fh), p)); +} + +static int vidioc_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct cx23885_fh *fh = priv; + return (videobuf_dqbuf(get_queue(fh), p, + file->f_flags & O_NONBLOCK)); +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct cx23885_fh *fh = priv; + struct cx23885_dev *dev = fh->dev; + dprintk(1, "%s()\n", __FUNCTION__); + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + return -EINVAL; + if (unlikely(i != fh->type)) + return -EINVAL; + + if (unlikely(!res_get(dev, fh, get_resource(fh)))) + return -EBUSY; + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx23885_fh *fh = priv; + struct cx23885_dev *dev = fh->dev; + int err, res; + dprintk(1, "%s()\n", __FUNCTION__); + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + dprintk(1, "%s()\n", __FUNCTION__); + + mutex_lock(&dev->lock); + cx23885_set_tvnorm(dev, *tvnorms); + mutex_unlock(&dev->lock); + + return 0; +} + +int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) +{ + static const char *iname[] = { + [CX23885_VMUX_COMPOSITE1] = "Composite1", + [CX23885_VMUX_COMPOSITE2] = "Composite2", + [CX23885_VMUX_COMPOSITE3] = "Composite3", + [CX23885_VMUX_COMPOSITE4] = "Composite4", + [CX23885_VMUX_SVIDEO] = "S-Video", + [CX23885_VMUX_TELEVISION] = "Television", + [CX23885_VMUX_CABLE] = "Cable TV", + [CX23885_VMUX_DVB] = "DVB", + [CX23885_VMUX_DEBUG] = "for debug only", + }; + unsigned int n; + dprintk(1, "%s()\n", __FUNCTION__); + + n = i->index; + if (n >= 4) + return -EINVAL; + + if (0 == INPUT(n)->type) + return -EINVAL; + + memset(i, 0, sizeof(*i)); + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(i->name, iname[INPUT(n)->type]); + if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) || + (CX23885_VMUX_CABLE == INPUT(n)->type)) + i->type = V4L2_INPUT_TYPE_TUNER; + i->std = CX23885_NORMS; + return 0; +} +EXPORT_SYMBOL(cx23885_enum_input); + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + dprintk(1, "%s()\n", __FUNCTION__); + return cx23885_enum_input(dev, i); +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + *i = dev->input; + dprintk(1, "%s() returns %d\n", __FUNCTION__, *i); + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + dprintk(1, "%s(%d)\n", __FUNCTION__, i); + + if (i >= 4) { + dprintk(1, "%s() -EINVAL\n", __FUNCTION__); + return -EINVAL; + } + + mutex_lock(&dev->lock); + cx23885_video_mux(dev, i); + mutex_unlock(&dev->lock); + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qctrl) +{ + qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); + if (unlikely(qctrl->id == 0)) + return -EINVAL; + return cx23885_ctrl_query(qctrl); +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + return cx23885_get_control(dev, ctl); +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + return cx23885_set_control(dev, ctl); +} + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + if (unlikely(UNSET == dev->tuner_type)) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + + strcpy(t->name, "Television"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; +#if 0 + cx23885_get_stereo(dev, t); +#endif + t->signal = 0xffff ; /* LOCKED */ + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + if (UNSET == dev->tuner_type) + return -EINVAL; + if (0 != t->index) + return -EINVAL; +#if 0 + cx23885_set_stereo(dev, t->audmode, 1); +#endif + return 0; +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct cx23885_fh *fh = priv; + struct cx23885_dev *dev = fh->dev; + + if (unlikely(UNSET == dev->tuner_type)) + return -EINVAL; + + /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ + f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + f->frequency = dev->freq; + + cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + + return 0; +} + +int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) +{ + if (unlikely(UNSET == dev->tuner_type)) + return -EINVAL; + if (unlikely(f->tuner != 0)) + return -EINVAL; + + mutex_lock(&dev->lock); + dev->freq = f->frequency; + + cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); + + /* When changing channels it is required to reset TVAUDIO */ + msleep(10); + + mutex_unlock(&dev->lock); + + return 0; +} +EXPORT_SYMBOL(cx23885_set_freq); + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct cx23885_fh *fh = priv; + struct cx23885_dev *dev = fh->dev; + + if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) + return -EINVAL; + if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) + return -EINVAL; + + return + cx23885_set_freq(dev, f); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int vidioc_g_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; + + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg); + + return 0; +} + +static int vidioc_s_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; + + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + + cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg); + + return 0; +} +#endif + +#if 0 +/* ----------------------------------------------------------- */ +/* RADIO ESPECIFIC IOCTLS */ +/* ----------------------------------------------------------- */ + +static int radio_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + strcpy(cap->driver, "cx23885"); + strlcpy(cap->card, cx23885_boards[dev->board].name, + sizeof(cap->card)); + sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); + cap->version = CX23885_VERSION_CODE; + cap->capabilities = V4L2_CAP_TUNER; + return 0; +} + +static int radio_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + if (unlikely(t->index > 0)) + return -EINVAL; + + strcpy(t->name, "Radio"); + t->type = V4L2_TUNER_RADIO; + + cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + return 0; +} + +static int radio_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index != 0) + return -EINVAL; + strcpy(i->name, "Radio"); + i->type = V4L2_INPUT_TYPE_TUNER; + + return 0; +} + +static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + if (unlikely(a->index)) + return -EINVAL; + + memset(a, 0, sizeof(*a)); + strcpy(a->name, "Radio"); + return 0; +} + +/* FIXME: Should add a standard for radio */ + +static int radio_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; + + if (0 != t->index) + return -EINVAL; + + cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); + + return 0; +} + +static int radio_s_audio(struct file *file, void *fh, + struct v4l2_audio *a) +{ + return 0; +} + +static int radio_s_input(struct file *file, void *fh, unsigned int i) +{ + return 0; +} + +static int radio_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *c) +{ + int i; + + if (c->id < V4L2_CID_BASE || + c->id >= V4L2_CID_LASTP1) + return -EINVAL; + if (c->id == V4L2_CID_AUDIO_MUTE) { + for (i = 0; i < CX23885_CTLS; i++) + if (cx23885_ctls[i].v.id == c->id) + break; + *c = cx23885_ctls[i].v; + } else + *c = no_ctl; + return 0; +} +#endif +/* ----------------------------------------------------------- */ + +static void cx23885_vid_timeout(unsigned long data) +{ + struct cx23885_dev *dev = (struct cx23885_dev *)data; + struct cx23885_dmaqueue *q = &dev->vidq; + struct cx23885_buffer *buf; + unsigned long flags; + + cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]); + + cx_clear(VID_A_DMA_CTL, 0x11); + + spin_lock_irqsave(&dev->slock, flags); + while (!list_empty(&q->active)) { + buf = list_entry(q->active.next, + struct cx23885_buffer, vb.queue); + list_del(&buf->vb.queue); + buf->vb.state = VIDEOBUF_ERROR; + wake_up(&buf->vb.done); + printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n", + dev->name, buf, buf->vb.i, + (unsigned long)buf->risc.dma); + } + cx23885_restart_video_queue(dev, q); + spin_unlock_irqrestore(&dev->slock, flags); +} + +int cx23885_video_irq(struct cx23885_dev *dev, u32 status) +{ + u32 mask, count; + int handled = 0; + + mask = cx_read(VID_A_INT_MSK); + if (0 == (status & mask)) + return handled; + cx_write(VID_A_INT_STAT, status); + + dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status); + /* risc op code error */ + if (status & (1 << 16)) { + printk(KERN_WARNING "%s/0: video risc op code error\n", + dev->name); + cx_clear(VID_A_DMA_CTL, 0x11); + cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]); + } + + /* risc1 y */ + if (status & 0x01) { + spin_lock(&dev->slock); + count = cx_read(VID_A_GPCNT); + cx23885_video_wakeup(dev, &dev->vidq, count); + spin_unlock(&dev->slock); + handled++; + } +#if 0 + /* risc1 vbi */ + if (status & 0x08) { + spin_lock(&dev->slock); + count = cx_read(MO_VBI_GPCNT); + cx88_wakeup(core, &dev->vbiq, count); + spin_unlock(&dev->slock); + handled++; + } +#endif + /* risc2 y */ + if (status & 0x10) { + dprintk(2, "stopper video\n"); + spin_lock(&dev->slock); + cx23885_restart_video_queue(dev, &dev->vidq); + spin_unlock(&dev->slock); + handled++; + } +#if 0 + /* risc2 vbi */ + if (status & 0x80) { + dprintk(2, "stopper vbi\n"); + spin_lock(&dev->slock); + cx8800_restart_vbi_queue(dev, &dev->vbiq); + spin_unlock(&dev->slock); + handled++; + } +#endif + + return handled; +} + +/* ----------------------------------------------------------- */ +/* exported stuff */ + +static const struct file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) + .compat_ioctl = v4l_compat_ioctl32, +#endif + .llseek = no_llseek, +}; + +static struct video_device cx23885_vbi_template; +static struct video_device cx23885_video_template = { + .name = "cx23885-video", + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES, + .fops = &video_fops, + .minor = -1, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, + .vidioc_g_fmt_cap = vidioc_g_fmt_cap, + .vidioc_try_fmt_cap = vidioc_try_fmt_cap, + .vidioc_s_fmt_cap = vidioc_s_fmt_cap, + .vidioc_g_fmt_vbi = cx23885_vbi_fmt, + .vidioc_try_fmt_vbi = cx23885_vbi_fmt, + .vidioc_s_fmt_vbi = cx23885_vbi_fmt, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif + .tvnorms = CX23885_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + +static const struct file_operations radio_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .ioctl = video_ioctl2, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) + .compat_ioctl = v4l_compat_ioctl32, +#endif + .llseek = no_llseek, +}; + +#if 0 +static struct video_device cx23885_radio_template = { + .name = "cx23885-radio", + .type = VID_TYPE_TUNER, + .fops = &radio_fops, + .minor = -1, + .vidioc_querycap = radio_querycap, + .vidioc_g_tuner = radio_g_tuner, + .vidioc_enum_input = radio_enum_input, + .vidioc_g_audio = radio_g_audio, + .vidioc_s_tuner = radio_s_tuner, + .vidioc_s_audio = radio_s_audio, + .vidioc_s_input = radio_s_input, + .vidioc_queryctrl = radio_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +}; +#endif + +void cx23885_video_unregister(struct cx23885_dev *dev) +{ + dprintk(1, "%s()\n", __FUNCTION__); + cx_clear(PCI_INT_MSK, 1); + +#if 0 + if (dev->radio_dev) { + if (-1 != dev->radio_dev->minor) + video_unregister_device(dev->radio_dev); + else + video_device_release(dev->radio_dev); + dev->radio_dev = NULL; + } + if (dev->vbi_dev) { + if (-1 != dev->vbi_dev->minor) + video_unregister_device(dev->vbi_dev); + else + video_device_release(dev->vbi_dev); + dev->vbi_dev = NULL; + btcx_riscmem_free(dev->pci, &dev->vbiq.stopper); + } +#endif + if (dev->video_dev) { + if (-1 != dev->video_dev->minor) + video_unregister_device(dev->video_dev); + else + video_device_release(dev->video_dev); + dev->video_dev = NULL; + + btcx_riscmem_free(dev->pci, &dev->vidq.stopper); + } +} + +int cx23885_video_register(struct cx23885_dev *dev) +{ + int err; + + dprintk(1, "%s()\n", __FUNCTION__); + spin_lock_init(&dev->slock); + + /* Initialize VBI template */ + memcpy(&cx23885_vbi_template, &cx23885_video_template, + sizeof(cx23885_vbi_template)); + strcpy(cx23885_vbi_template.name, "cx23885-vbi"); + cx23885_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER; + + dev->tvnorm = cx23885_video_template.current_norm; + + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + INIT_LIST_HEAD(&dev->vidq.queued); + dev->vidq.timeout.function = cx23885_vid_timeout; + dev->vidq.timeout.data = (unsigned long)dev; + init_timer(&dev->vidq.timeout); + cx23885_risc_stopper(dev->pci, &dev->vidq.stopper, + VID_A_DMA_CTL, 0x11, 0x00); + + /* Don't enable VBI yet */ +#if 0 + /* init vbi dma queues */ + INIT_LIST_HEAD(&dev->vbiq.active); + INIT_LIST_HEAD(&dev->vbiq.queued); + dev->vbiq.timeout.function = cx23885_vbi_timeout; + dev->vbiq.timeout.data = (unsigned long)dev; + init_timer(&dev->vbiq.timeout); + cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper, + VID_A_DMA_CTL, 0x88, 0x00); +#endif + cx_set(PCI_INT_MSK, 1); + +#if 0 + /* FIXME: These should be correctly defined */ + /* load and configure helper modules */ + if (TUNER_ABSENT != core->tuner_type) + request_module("tuner"); + + if (cx23885_boards[dev->board].audio_chip == AUDIO_CHIP_WM8775) + request_module("wm8775"); +#endif + + /* register v4l devices */ + dev->video_dev = cx23885_vdev_init(dev, dev->pci, + &cx23885_video_template, "video"); + err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, + video_nr[dev->nr]); + if (err < 0) { + printk(KERN_INFO "%s: can't register video device\n", + dev->name); + goto fail_unreg; + } + printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", + dev->name, dev->video_dev->minor & 0x1f); +#if 0 + dev->vbi_dev = cx23885_vdev_init(dev, dev->pci, + &cx23885_vbi_template, "vbi"); + err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, + vbi_nr[dev->nr]); + if (err < 0) { + printk(KERN_INFO "%s/0: can't register vbi device\n", + dev->name); + goto fail_unreg; + } + printk(KERN_INFO "%s/0: registered device vbi%d\n", + dev->name, dev->vbi_dev->minor & 0x1f); + + if (dev->has_radio) { + dev->radio_dev = cx23885_vdev_init(dev, dev->pci, + &cx23885_radio_template, "radio"); + err = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, + radio_nr[dev->nr]); + if (err < 0) { + printk(KERN_INFO "%s/0: can't register radio device\n", + dev->name); + goto fail_unreg; + } + printk(KERN_INFO "%s/0: registered device radio%d\n", + dev->name, dev->radio_dev->minor & 0x1f); + } +#endif + /* initial device configuration */ + mutex_lock(&dev->lock); + cx23885_set_tvnorm(dev, dev->tvnorm); + init_controls(dev); + cx23885_video_mux(dev, 0); + mutex_unlock(&dev->lock); + + return 0; + +fail_unreg: + cx23885_video_unregister(dev); + return err; +} + diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index fd8828275..4f803d92b 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -47,6 +47,10 @@ /* Max number of inputs by card */ #define MAX_CX23885_INPUT 8 +#define INPUT(nr) (&cx23885_boards[dev->board].input[nr]) +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO 2 +#define RESOURCE_VBI 4 #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ @@ -59,6 +63,60 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5 #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 +/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ +#define CX23885_NORMS (\ + V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443 | \ + V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ + V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \ + V4L2_STD_PAL_60 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK) + +struct cx23885_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; + int flags; + u32 cxformat; +}; + +struct cx23885_ctrl { + struct v4l2_queryctrl v; + u32 off; + u32 reg; + u32 mask; + u32 shift; +}; + +struct cx23885_tvnorm { + char *name; + v4l2_std_id id; + u32 cxiformat; + u32 cxoformat; +}; + +struct cx23885_fh { + struct cx23885_dev *dev; + enum v4l2_buf_type type; + int radio; + u32 resources; + + /* video overlay */ + struct v4l2_window win; + struct v4l2_clip *clips; + unsigned int nclips; + + /* video capture */ + struct cx23885_fmt *fmt; + unsigned int width, height; + + /* vbi capture */ + struct videobuf_queue vidq; + struct videobuf_queue vbiq; + + /* MPEG Encoder specifics ONLY */ + struct videobuf_queue mpegq; + atomic_t v4l_reading; +}; + enum cx23885_itype { CX23885_VMUX_COMPOSITE1 = 1, CX23885_VMUX_COMPOSITE2, @@ -97,12 +155,28 @@ struct cx23885_input { typedef enum { CX23885_MPEG_UNDEFINED = 0, - CX23885_MPEG_DVB + CX23885_MPEG_DVB, + CX23885_ANALOG_VIDEO, } port_t; struct cx23885_board { char *name; - port_t portb, portc; + port_t porta, portb, portc; + unsigned int tuner_type; + unsigned int radio_type; + unsigned char tuner_addr; + unsigned char radio_addr; + + /* Vendors can and do run the PCIe bridge at different + * clock rates, driven physically by crystals on the PCBs. + * The core has to accomodate this. This allows the user + * to add new boards with new frequencys. The value is + * expressed in Hz. + * + * The core framework will default this value based on + * current designs, but it can vary. + */ + u32 clk_freq; struct cx23885_input input[MAX_CX23885_INPUT]; }; @@ -194,6 +268,11 @@ struct cx23885_dev { u32 __iomem *lmmio; u8 __iomem *bmmio; int pci_irqmask; + int hwrevision; + + /* This valud is board specific and is used to configure the + * AV core so we see nice clean and stable video and audio. */ + u32 clk_freq; /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ struct cx23885_i2c i2c_bus[3]; @@ -219,8 +298,31 @@ struct cx23885_dev { CX23885_BRIDGE_885 = 885, CX23885_BRIDGE_887 = 887, } bridge; + + /* Analog video */ + u32 resources; + unsigned int input; + u32 tvaudio; + v4l2_std_id tvnorm; + unsigned int tuner_type; + unsigned char tuner_addr; + unsigned int radio_type; + unsigned char radio_addr; + unsigned int has_radio; + + /* V4l */ + u32 freq; + struct video_device *video_dev; + struct video_device *vbi_dev; + struct video_device *radio_dev; + + struct cx23885_dmaqueue vidq; + struct cx23885_dmaqueue vbiq; + spinlock_t slock; }; +extern struct list_head cx23885_devlist; + #define SRAM_CH01 0 /* Video A */ #define SRAM_CH02 1 /* VBI A */ #define SRAM_CH03 2 /* Video B */ @@ -264,8 +366,34 @@ struct sram_channel { #define cx_clear(reg,bit) cx_andor((reg),(bit),0) /* ----------------------------------------------------------- */ -/* cx23885-cards.c */ +/* cx23885-core.c */ + +extern int cx23885_sram_channel_setup(struct cx23885_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc); + +extern void cx23885_sram_channel_dump(struct cx23885_dev *dev, + struct sram_channel *ch); +extern int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, + u32 reg, u32 mask, u32 value); + +extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int top_offset, unsigned int bottom_offset, + unsigned int bpl, unsigned int padding, unsigned int lines); + +void cx23885_cancel_buffers(struct cx23885_tsport *port); + +extern int cx23885_restart_queue(struct cx23885_tsport *port, + struct cx23885_dmaqueue *q); + +extern void cx23885_wakeup(struct cx23885_tsport *port, + struct cx23885_dmaqueue *q, u32 count); + + +/* ----------------------------------------------------------- */ +/* cx23885-cards.c */ extern struct cx23885_board cx23885_boards[]; extern const unsigned int cx23885_bcount; @@ -285,19 +413,50 @@ extern int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port, struct cx23885_buffer *buf, enum v4l2_field field); - extern void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf); extern void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf); /* ----------------------------------------------------------- */ +/* cx23885-video.c */ +/* Video */ +extern int cx23885_video_register(struct cx23885_dev *dev); +extern void cx23885_video_unregister(struct cx23885_dev *dev); +extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status); + +/* ----------------------------------------------------------- */ +/* cx23885-vbi.c */ +extern int cx23885_vbi_fmt(struct file *file, void *priv, + struct v4l2_format *f); +extern void cx23885_vbi_timeout(unsigned long data); +extern struct videobuf_queue_ops cx23885_vbi_qops; + /* cx23885-i2c.c */ extern int cx23885_i2c_register(struct cx23885_i2c *bus); extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd, void *arg); +/* ----------------------------------------------------------- */ +/* tv norms */ + +static inline unsigned int norm_maxw(v4l2_std_id norm) +{ + return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768; +} + +static inline unsigned int norm_maxh(v4l2_std_id norm) +{ + return (norm & V4L2_STD_625_50) ? 576 : 480; +} + +static inline unsigned int norm_swidth(v4l2_std_id norm) +{ + return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922; +} + + /* * Local variables: * c-basic-offset: 8 diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index 192993041..eda48b596 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -36,11 +36,17 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* common for all inputs and rates */ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ - cx25840_write(client, 0x127, 0x50); + if (!state->is_cx23885) + cx25840_write(client, 0x127, 0x50); if (state->aud_input != CX25840_AUDIO_SERIAL) { switch (freq) { case 32000: + if (state->is_cx23885) { + /* We don't have register values + * so avoid destroying registers. */ + break; + } /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1006040f); @@ -57,6 +63,11 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 44100: + if (state->is_cx23885) { + /* We don't have register values + * so avoid destroying registers. */ + break; + } /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1009040f); @@ -73,6 +84,11 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 48000: + if (state->is_cx23885) { + /* We don't have register values + * so avoid destroying registers. */ + break; + } /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x100a040f); @@ -91,6 +107,11 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } else { switch (freq) { case 32000: + if (state->is_cx23885) { + /* We don't have register values + * so avoid destroying registers. */ + break; + } /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1e08040f); @@ -113,6 +134,12 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 44100: + if (state->is_cx23885) { + /* We don't have register values + * so avoid destroying registers. */ + break; + } + /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1809040f); @@ -132,22 +159,33 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 48000: - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x180a040f); + if (!state->is_cx23885) { + /* VID_PLL and AUX_PLL */ + cx25840_write4(client, 0x108, 0x180a040f); - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x0098d6e5); + /* AUX_PLL_FRAC */ + cx25840_write4(client, 0x110, 0x0098d6e5); + } if (state->is_cx25836) break; - /* src1_ctl = 0x08010000 */ - cx25840_write4(client, 0x8f8, 0x08018000); + if (!state->is_cx23885) { + /* src1_ctl */ + cx25840_write4(client, 0x8f8, 0x08018000); - /* src3/4/6_ctl = 0x08020000 */ - cx25840_write4(client, 0x900, 0x08015555); - cx25840_write4(client, 0x904, 0x08015555); - cx25840_write4(client, 0x90c, 0x08015555); + /* src3/4/6_ctl */ + cx25840_write4(client, 0x900, 0x08015555); + cx25840_write4(client, 0x904, 0x08015555); + cx25840_write4(client, 0x90c, 0x08015555); + } else { + + cx25840_write4(client, 0x8f8, 0x0801867c); + + cx25840_write4(client, 0x900, 0x08014faa); + cx25840_write4(client, 0x904, 0x08014faa); + cx25840_write4(client, 0x90c, 0x08014faa); + } break; } } @@ -192,6 +230,11 @@ void cx25840_audio_set_path(struct i2c_client *client) /* deassert soft reset */ cx25840_and_or(client, 0x810, ~0x1, 0x00); + + if (state->is_cx23885) { + /* Ensure the controller is running when we exit */ + cx25840_and_or(client, 0x803, ~0x10, 0x10); + } } static int get_volume(struct i2c_client *client) diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 9f9bcc539..14d59efd0 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -13,6 +13,8 @@ * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca> * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>. * + * CX23885 support by Steven Toth <stoth@hauppauge.com>. + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -276,6 +278,104 @@ static void cx25840_initialize(struct i2c_client *client) cx25840_and_or(client, 0x803, ~0x10, 0x10); } +static void cx23885_initialize(struct i2c_client *client) +{ + DEFINE_WAIT(wait); + struct cx25840_state *state = i2c_get_clientdata(client); + struct workqueue_struct *q; + + /* Internal Reset */ + cx25840_and_or(client, 0x102, ~0x01, 0x01); + cx25840_and_or(client, 0x102, ~0x01, 0x00); + + /* Stop microcontroller */ + cx25840_and_or(client, 0x803, ~0x10, 0x00); + + /* DIF in reset? */ + cx25840_write(client, 0x398, 0); + + /* Trust the default xtal, no division */ + /* This changes for the cx23888 products */ + cx25840_write(client, 0x2, 0x76); + + /* Bring down the regulator for AUX clk */ + cx25840_write(client, 0x1, 0x40); + + /* Sys PLL frac */ + cx25840_write4(client, 0x11c, 0x01d1744c); + + /* Sys PLL int */ + cx25840_write4(client, 0x118, 0x00000416); + + /* Disable DIF bypass */ + cx25840_write4(client, 0x33c, 0x00000001); + + /* DIF Src phase inc */ + cx25840_write4(client, 0x340, 0x0df7df83); + + /* Vid PLL frac */ + cx25840_write4(client, 0x10c, 0x01b6db7b); + + /* Vid PLL int */ + cx25840_write4(client, 0x108, 0x00000512); + + /* Luma */ + cx25840_write4(client, 0x414, 0x00107d12); + + /* Chroma */ + cx25840_write4(client, 0x420, 0x3d008282); + + /* Aux PLL frac */ + cx25840_write4(client, 0x114, 0x017dbf48); + + /* Aux PLL int */ + cx25840_write4(client, 0x110, 0x000a030e); + + /* ADC2 input select */ + cx25840_write(client, 0x102, 0x10); + + /* VIN1 & VIN5 */ + cx25840_write(client, 0x103, 0x11); + + /* Enable format auto detect */ + cx25840_write(client, 0x400, 0); +#if 0 + /* Force to NTSC-M and Disable autoconf regs */ + cx25840_write(client, 0x400, 0x21); +#endif + /* Fast subchroma lock */ + /* White crush, Chroma AGC & Chroma Killer enabled */ + cx25840_write(client, 0x401, 0xe8); + + /* Select AFE clock pad output source */ + cx25840_write(client, 0x144, 0x05); + + /* Do the firmware load in a work handler to prevent. + Otherwise the kernel is blocked waiting for the + bit-banging i2c interface to finish uploading the + firmware. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) + INIT_WORK(&state->fw_work, cx25840_work_handler); +#else + INIT_WORK(&state->fw_work, cx25840_work_handler, state); +#endif + init_waitqueue_head(&state->fw_wait); + q = create_singlethread_workqueue("cx25840_fw"); + prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); + queue_work(q, &state->fw_work); + schedule(); + finish_wait(&state->fw_wait, &wait); + destroy_workqueue(q); + + cx25840_vbi_setup(client); + + /* (re)set input */ + set_input(client, state->vid_input, state->aud_input); + + /* start microcontroller */ + cx25840_and_or(client, 0x803, ~0x10, 0x10); +} + /* ----------------------------------------------------------------------- */ static void input_change(struct i2c_client *client) @@ -339,9 +439,22 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp vid_input <= CX25840_COMPOSITE8); u8 reg; - v4l_dbg(1, cx25840_debug, client, "decoder set video input %d, audio input %d\n", - vid_input, aud_input); + v4l_dbg(1, cx25840_debug, client, + "decoder set video input %d, audio input %d\n", + vid_input, aud_input); + + if (vid_input >= CX25840_VIN1_CH1) { + v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n", + vid_input); + reg = vid_input & 0xff; + if ((vid_input & CX25840_SVIDEO_ON) == CX25840_SVIDEO_ON) + is_composite = 0; + else + is_composite = 1; + v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", + reg, is_composite); + } else if (is_composite) { reg = 0xf0 + (vid_input - CX25840_COMPOSITE1); } else { @@ -351,7 +464,8 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp if ((vid_input & ~0xff0) || luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 || chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { - v4l_err(client, "0x%04x is not a valid video input!\n", vid_input); + v4l_err(client, "0x%04x is not a valid video input!\n", + vid_input); return -EINVAL; } reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4); @@ -364,31 +478,49 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp } } - switch (aud_input) { - case CX25840_AUDIO_SERIAL: - /* do nothing, use serial audio input */ - break; - case CX25840_AUDIO4: reg &= ~0x30; break; - case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break; - case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break; - case CX25840_AUDIO7: reg &= ~0xc0; break; - case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break; + /* The caller has previously prepared the correct routing + * configuration in reg (for the cx23885) so we have no + * need to attempt to flip bits for earlier av decoders. + */ + if (!state->is_cx23885) { + switch (aud_input) { + case CX25840_AUDIO_SERIAL: + /* do nothing, use serial audio input */ + break; + case CX25840_AUDIO4: reg &= ~0x30; break; + case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break; + case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break; + case CX25840_AUDIO7: reg &= ~0xc0; break; + case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break; - default: - v4l_err(client, "0x%04x is not a valid audio input!\n", aud_input); - return -EINVAL; + default: + v4l_err(client, "0x%04x is not a valid audio input!\n", + aud_input); + return -EINVAL; + } } cx25840_write(client, 0x103, reg); + /* Set INPUT_MODE to Composite (0) or S-Video (1) */ cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); - /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ - cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); - /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ - if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30) - cx25840_and_or(client, 0x102, ~0x4, 4); - else - cx25840_and_or(client, 0x102, ~0x4, 0); + + if (!state->is_cx23885) { + /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ + cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); + /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ + if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30) + cx25840_and_or(client, 0x102, ~0x4, 4); + else + cx25840_and_or(client, 0x102, ~0x4, 0); + } else { + if (is_composite) + /* ADC2 input select channel 2 */ + cx25840_and_or(client, 0x102, ~0x2, 0); + else + /* ADC2 input select channel 3 */ + cx25840_and_or(client, 0x102, ~0x2, 2); + } state->vid_input = vid_input; state->aud_input = aud_input; @@ -396,6 +528,25 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp cx25840_audio_set_path(client); input_change(client); } + + if (state->is_cx23885) { + /* Audio channel 1 src : Parallel 1 */ + cx25840_write(client, 0x124, 0x03); + + /* Select AFE clock pad output source */ + cx25840_write(client, 0x144, 0x05); + + /* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */ + cx25840_write(client, 0x914, 0xa0); + + /* I2S_OUT_CTL: + * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 + * I2S_OUT_MASTER_MODE = Master + */ + cx25840_write(client, 0x918, 0xa0); + cx25840_write(client, 0x919, 0x01); + } + return 0; } @@ -874,6 +1025,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, state->is_initialized = 1; if (state->is_cx25836) cx25836_initialize(client); + else if (state->is_cx23885) + cx23885_initialize(client); else cx25840_initialize(client); } @@ -891,6 +1044,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (cmd == VIDIOC_DBG_G_REGISTER) reg->val = cx25840_read(client, reg->reg & 0x0fff); else @@ -907,14 +1061,26 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, case VIDIOC_STREAMON: v4l_dbg(1, cx25840_debug, client, "enable output\n"); - cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c); - cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07); + if (state->is_cx23885) { + u8 v = (cx25840_read(client, 0x421) | 0x0b); + cx25840_write(client, 0x421, v); + } else { + cx25840_write(client, 0x115, + state->is_cx25836 ? 0x0c : 0x8c); + cx25840_write(client, 0x116, + state->is_cx25836 ? 0x04 : 0x07); + } break; case VIDIOC_STREAMOFF: v4l_dbg(1, cx25840_debug, client, "disable output\n"); - cx25840_write(client, 0x115, 0x00); - cx25840_write(client, 0x116, 0x00); + if (state->is_cx23885) { + u8 v = cx25840_read(client, 0x421) & ~(0x0b); + cx25840_write(client, 0x421, v); + } else { + cx25840_write(client, 0x115, 0x00); + cx25840_write(client, 0x116, 0x00); + } break; case VIDIOC_LOG_STATUS: @@ -1077,6 +1243,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, case VIDIOC_INT_RESET: if (state->is_cx25836) cx25836_initialize(client); + else if (state->is_cx23885) + cx23885_initialize(client); else cx25840_initialize(client); break; @@ -1107,6 +1275,7 @@ static int cx25840_probe(struct i2c_client *client) device_id = cx25840_read(client, 0x101) << 8; device_id |= cx25840_read(client, 0x100); + v4l_dbg(1, cx25840_debug, client, "device_id = 0x%04x\n", device_id); /* The high byte of the device ID should be * 0x83 for the cx2583x and 0x84 for the cx2584x */ @@ -1115,6 +1284,10 @@ static int cx25840_probe(struct i2c_client *client) } else if ((device_id & 0xff00) == 0x8400) { id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); + } else if (device_id == 0x0000) { + id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; + } else if (device_id == 0x1313) { + id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; } else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); @@ -1136,6 +1309,7 @@ static int cx25840_probe(struct i2c_client *client) i2c_set_clientdata(client, state); state->c = client; state->is_cx25836 = ((device_id & 0xff00) == 0x8300); + state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; @@ -1145,6 +1319,7 @@ static int cx25840_probe(struct i2c_client *client) state->vbi_line_offset = 8; state->id = id; state->rev = device_id; + return 0; } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index ae5dbf207..b1316a833 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -48,6 +48,7 @@ struct cx25840_state { u32 id; u32 rev; int is_cx25836; + int is_cx23885; int is_initialized; wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ struct work_struct fw_work; /* work entry for fw load */ diff --git a/linux/drivers/media/video/cx25840/cx25840-firmware.c b/linux/drivers/media/video/cx25840/cx25840-firmware.c index d7ec2b2dc..56f992087 100644 --- a/linux/drivers/media/video/cx25840/cx25840-firmware.c +++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c @@ -25,6 +25,7 @@ #include "cx25840-core.h" #define FWFILE "v4l-cx25840.fw" +#define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw" /* * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the @@ -101,10 +102,14 @@ static int fw_write(struct i2c_client *client, u8 * data, int size) int cx25840_loadfw(struct i2c_client *client) { + struct cx25840_state *state = i2c_get_clientdata(client); const struct firmware *fw = NULL; u8 buffer[4], *ptr; int size, send, retval; + if (state->is_cx23885) + firmware = FWFILE_CX23885; + if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { v4l_err(client, "unable to open firmware %s\n", firmware); return -EINVAL; diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 25344980a..14f8fe91e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -43,12 +43,36 @@ static int tuner = -1; module_param(tuner, int, 0444); MODULE_PARM_DESC(tuner, "tuner type"); +static unsigned int disable_ir; +module_param(disable_ir, int, 0444); +MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); + struct em28xx_hash_table { unsigned long hash; unsigned int model; unsigned int tuner; }; +/* 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 EM2820_BOARD_KWORLD_PVRTV2800RF 12 +#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 +#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 +#define EM2800_BOARD_VGEAR_POCKETTV 15 +#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16 + struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_UNKNOWN] = { .name = "Unknown EM2800 video grabber", @@ -246,26 +270,28 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_MSI_VOX_USB_2] = { - .name = "MSI VOX USB 2.0", - .vchannels = 3, - .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 = SAA7115_COMPOSITE4, - .amux = 0, + .name = "MSI VOX USB 2.0", + .vchannels = 3, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT | + TDA9887_PORT1_ACTIVE | + TDA9887_PORT2_ACTIVE, + .has_tuner = 1, + .max_range_640_480 = 1, + + .decoder = EM28XX_SAA7114, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = SAA7115_COMPOSITE4, + .amux = 0, }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = 1, + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = 1, }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = 1, + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = 1, } }, }, [EM2800_BOARD_TERRATEC_CINERGY_200] = { @@ -420,6 +446,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, + { USB_DEVICE(0x2040, 0x4201), + .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x2304, 0x021a), @@ -486,27 +514,31 @@ static int em28xx_tuner_callback(void *ptr, int command, int arg) switch (command) { case XC2028_TUNER_RESET: { - char gpio0, gpio1, gpio4; - - /* GPIO and initialization codes for analog TV */ - gpio0 = dev->analog_gpio & 0xff; - gpio1 = (dev->analog_gpio >> 8) & 0xff; - gpio4 = dev->analog_gpio >> 24; + /* GPIO and initialization codes for analog TV and radio + This code should be complemented for DTV, since reset + codes are different. + */ dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); - if (gpio4) { - dev->em28xx_write_regs(dev, 0x04, &gpio4, 1); - msleep(140); + if (dev->analog_gpio) { + char gpio0 = dev->analog_gpio & 0xff; + char gpio1 = (dev->analog_gpio >> 8) & 0xff; + char gpio4 = dev->analog_gpio >> 24; + + if (gpio4) { + dev->em28xx_write_regs(dev, 0x04, &gpio4, 1); + msleep(140); + } + + msleep(6); + dev->em28xx_write_regs(dev, 0x08, &gpio0, 1); + msleep(10); + dev->em28xx_write_regs(dev, 0x08, &gpio1, 1); + msleep(5); } - msleep(6); - dev->em28xx_write_regs(dev, 0x08, &gpio0, 1); - msleep(10); - dev->em28xx_write_regs(dev, 0x08, &gpio1, 1); - msleep(5); - break; } } @@ -644,11 +676,54 @@ static void em28xx_set_model(struct em28xx *dev) dev->video_inputs = em28xx_boards[dev->model].vchannels; dev->analog_gpio = em28xx_boards[dev->model].analog_gpio; dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; + dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; if (!em28xx_boards[dev->model].has_tuner) dev->tuner_type = UNSET; } +/* ----------------------------------------------------------------------- */ +void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) +{ + if (disable_ir) { + ir->get_key = NULL; + return ; + } + + /* detect & configure */ + switch (dev->model) { + case (EM2800_BOARD_UNKNOWN): + break; + case (EM2820_BOARD_UNKNOWN): + break; + case (EM2800_BOARD_TERRATEC_CINERGY_200): + case (EM2820_BOARD_TERRATEC_CINERGY_250): + ir->ir_codes = ir_codes_em_terratec; + ir->get_key = em28xx_get_key_terratec; + snprintf(ir->c.name, sizeof(ir->c.name), + "i2c IR (EM28XX Terratec)"); + break; + case (EM2820_BOARD_PINNACLE_USB_2): + ir->ir_codes = ir_codes_pinnacle_grey; + ir->get_key = em28xx_get_key_pinnacle_usb_grey; + snprintf(ir->c.name, sizeof(ir->c.name), + "i2c IR (EM28XX Pinnacle PCTV)"); + break; + case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): + ir->ir_codes = ir_codes_hauppauge_new; + ir->get_key = em28xx_get_key_em_haup; + snprintf(ir->c.name, sizeof(ir->c.name), + "i2c IR (EM2840 Hauppauge)"); + break; + case (EM2820_BOARD_MSI_VOX_USB_2): + break; + case (EM2800_BOARD_LEADTEK_WINFAST_USBII): + break; + case (EM2800_BOARD_KWORLD_USB2800): + break; + } +} + void em28xx_card_setup(struct em28xx *dev) { em28xx_set_model(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index 6959c1789..5c78eceff 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -31,11 +31,7 @@ #include "compat.h" #include "em28xx.h" -static unsigned int disable_ir = 0; -module_param(disable_ir, int, 0444); -MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); - -static unsigned int ir_debug = 0; +static unsigned int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); @@ -44,7 +40,7 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); /* ----------------------------------------------------------------------- */ -static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -73,7 +69,7 @@ static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) } -static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[2]; unsigned char code; @@ -109,7 +105,8 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, + u32 *ir_raw) { unsigned char buf[3]; @@ -131,45 +128,6 @@ static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw return 1; } -/* ----------------------------------------------------------------------- */ -void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir) -{ - if (disable_ir) { - ir->get_key=NULL; - return ; - } - - /* detect & configure */ - switch (dev->model) { - case (EM2800_BOARD_UNKNOWN): - break; - case (EM2820_BOARD_UNKNOWN): - break; - case (EM2800_BOARD_TERRATEC_CINERGY_200): - case (EM2820_BOARD_TERRATEC_CINERGY_250): - ir->ir_codes = ir_codes_em_terratec; - ir->get_key = get_key_terratec; - snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)"); - break; - case (EM2820_BOARD_PINNACLE_USB_2): - ir->ir_codes = ir_codes_pinnacle_grey; - ir->get_key = get_key_pinnacle_usb_grey; - snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)"); - break; - case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): - ir->ir_codes = ir_codes_hauppauge_new; - ir->get_key = get_key_em_haup; - snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2840 Hauppauge)"); - break; - case (EM2820_BOARD_MSI_VOX_USB_2): - break; - case (EM2800_BOARD_LEADTEK_WINFAST_USBII): - break; - case (EM2800_BOARD_KWORLD_USB2800): - break; - } -} - /* ---------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 77d547f81..cfec27b3a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2065,7 +2065,9 @@ static void request_module_async(struct work_struct *work) struct em28xx, request_module_wk); #endif - if (!dev->has_audio_class) + if (dev->has_audio_class) + request_module("snd-usb-audio"); + else request_module("em28xx-alsa"); } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index a483a3668..6d7171a89 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -33,26 +33,6 @@ #endif #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 EM2820_BOARD_KWORLD_PVRTV2800RF 12 -#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 -#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 -#define EM2800_BOARD_VGEAR_POCKETTV 15 -#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16 - #define UNSET -1 /* maximum number of em28xx boards */ @@ -188,6 +168,7 @@ struct em28xx_board { unsigned int has_msp34xx:1; unsigned int mts_firmware:1; unsigned int has_12mhz_i2s:1; + unsigned int max_range_640_480:1; unsigned int analog_gpio; @@ -262,6 +243,7 @@ struct em28xx { unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; unsigned int has_12mhz_i2s:1; + unsigned int max_range_640_480:1; int video_inputs; /* number of video inputs */ struct list_head devlist; @@ -367,10 +349,6 @@ void em28xx_do_i2c_scan(struct em28xx *dev); 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); @@ -408,6 +386,14 @@ 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; +void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); + +/* Provided by em28xx-input.c */ +/* TODO: Check if the standard get_key handlers on ir-common can be used */ +int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); +int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); +int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, + u32 *ir_raw); /* em2800 registers */ #define EM2800_AUDIOSRC_REG 0x08 @@ -565,21 +551,17 @@ inline static int em28xx_gamma_set(struct em28xx *dev, s32 val) /*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: + if (dev->max_range_640_480) return 640; - default: + else return 720; - } } inline static unsigned int norm_maxh(struct em28xx *dev) { - switch (dev->model) { - case EM2820_BOARD_MSI_VOX_USB_2: + if (dev->max_range_640_480) return 480; - default: + else return (dev->norm & V4L2_STD_625_50) ? 576 : 480; - } } #endif diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index 08a68de69..138be506c 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -415,6 +415,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, case 0x7a: case 0x47: case 0x71: + case 0x2d: if (adap->id == I2C_HW_B_CX2388x) { /* Handled by cx88-input */ name = "CX2388x remote"; @@ -525,7 +526,7 @@ static int ir_probe(struct i2c_adapter *adap) */ static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; - static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; + static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, 0x2d, -1 }; static const int probe_em28XX[] = { 0x30, 0x47, -1 }; static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 }; static const int probe_cx23885[] = { 0x6b, -1 }; diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 85dd27e4b..e7741a031 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -1077,10 +1077,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ivtv_process_eeprom(itv); } - /* The mspx4xx chips need a longer delay for some reason */ - if (!(itv->hw_flags & IVTV_HW_MSP34XX)) - itv->i2c_algo.udelay = 5; - if (itv->std == 0) { itv->std = V4L2_STD_NTSC_M; } diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 95e439601..6fc1b8be1 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -5,6 +5,10 @@ config VIDEO_PVRUSB2 select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X + select VIDEO_SAA711X + select VIDEO_CX25840 + select VIDEO_MSP3400 + select VIDEO_WM8775 ---help--- This is a video4linux driver for Conexant 23416 based usb2 personal video recorder devices. diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 7205d47b5..bd7728d64 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3601,6 +3601,356 @@ struct saa7134_board saa7134_boards[] = { .tv = 1, }}, }, + [SAA7134_BOARD_BEHOLD_401] = { + .name = "Beholder BeholdTV 401", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FQ1216ME, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + }}, + .mute = { + .name = name_mute, + .amux = LINE1, + }, + }, + [SAA7134_BOARD_BEHOLD_403] = { + .name = "Beholder BeholdTV 403", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FQ1216ME, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + }}, + }, + [SAA7134_BOARD_BEHOLD_403FM] = { + .name = "Beholder BeholdTV 403 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FQ1216ME, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_405] = { + .name = "Beholder BeholdTV 405", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + }}, + }, + [SAA7134_BOARD_BEHOLD_405FM] = { + /* Sergey <skiv@orel.ru> */ + .name = "Beholder BeholdTV 405 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_407] = { + .name = "Beholder BeholdTV 407", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0xc0c000, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0xc0c000, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + .gpio = 0xc0c000, + },{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + .gpio = 0xc0c000, + }}, + }, + [SAA7134_BOARD_BEHOLD_407FM] = { + .name = "Beholder BeholdTV 407 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0xc0c000, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0xc0c000, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + .gpio = 0xc0c000, + },{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + .gpio = 0xc0c000, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0xc0c000, + }, + }, + [SAA7134_BOARD_BEHOLD_409] = { + .name = "Beholder BeholdTV 409", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + }, + [SAA7134_BOARD_BEHOLD_505FM] = { + .name = "Beholder BeholdTV 505 FM/RDS", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .mute = { + .name = name_mute, + .amux = LINE1, + }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_507_9FM] = { + .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { + .name = "Beholder BeholdTV Columbus TVFM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ALPS_TSBE5_PAL, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_607_9FM] = { + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV 607 / BeholdTV 609", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_M6] = { + /* Igor Kuznetsov <igk@igk.ru> */ + /* Andrey Melnikoff <temnota@kmv.ru> */ + .name = "Beholder BeholdTV M6 / BeholdTV M6 Extra", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + .mpeg = SAA7134_MPEG_EMPRESS, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4081,7 +4431,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1462, - .subdevice = 0x6231, + .subdevice = 0x6231, /* tda8275a, ks003 IR */ + .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1462, + .subdevice = 0x8624, /* tda8275, ks003 IR */ .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -4367,6 +4723,162 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_AVERMEDIA_SUPER_007, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x0000, + .subdevice = 0x4016, + .driver_data = SAA7134_BOARD_BEHOLD_401, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x0000, + .subdevice = 0x4036, + .driver_data = SAA7134_BOARD_BEHOLD_403, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x0000, + .subdevice = 0x4037, + .driver_data = SAA7134_BOARD_BEHOLD_403FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x0000, + .subdevice = 0x4050, + .driver_data = SAA7134_BOARD_BEHOLD_405, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x0000, + .subdevice = 0x4051, + .driver_data = SAA7134_BOARD_BEHOLD_405FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x0000, + .subdevice = 0x4070, + .driver_data = SAA7134_BOARD_BEHOLD_407, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x0000, + .subdevice = 0x4071, + .driver_data = SAA7134_BOARD_BEHOLD_407FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0000, + .subdevice = 0x4090, + .driver_data = SAA7134_BOARD_BEHOLD_409, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x0000, + .subdevice = 0x5051, + .driver_data = SAA7134_BOARD_BEHOLD_505FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x0000, + .subdevice = 0x505B, + .driver_data = SAA7134_BOARD_BEHOLD_505FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x5ace, + .subdevice = 0x5050, + .driver_data = SAA7134_BOARD_BEHOLD_505FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0000, + .subdevice = 0x5071, + .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0000, + .subdevice = 0x507B, + .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x5ace, + .subdevice = 0x5070, + .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, + .subdevice = 0x5090, + .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0000, + .subdevice = 0x5201, + .driver_data = SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x5ace, + .subdevice = 0x6070, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x5ace, + .subdevice = 0x6071, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x5ace, + .subdevice = 0x6072, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x5ace, + .subdevice = 0x6073, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, + .subdevice = 0x6090, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, + .subdevice = 0x6091, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, + .subdevice = 0x6092, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, + .subdevice = 0x6093, + .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, + .subdevice = 0x6190, + .driver_data = SAA7134_BOARD_BEHOLD_M6, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, + .subdevice = 0x6193, + .driver_data = SAA7134_BOARD_BEHOLD_M6, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x4e42, .subdevice = 0x3502, @@ -4549,6 +5061,16 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: case SAA7134_BOARD_10MOONSTVMASTER3: + case SAA7134_BOARD_BEHOLD_401: + case SAA7134_BOARD_BEHOLD_403: + case SAA7134_BOARD_BEHOLD_403FM: + case SAA7134_BOARD_BEHOLD_405: + case SAA7134_BOARD_BEHOLD_405FM: + case SAA7134_BOARD_BEHOLD_407: + case SAA7134_BOARD_BEHOLD_407FM: + case SAA7134_BOARD_BEHOLD_409: + case SAA7134_BOARD_BEHOLD_505FM: + case SAA7134_BOARD_BEHOLD_507_9FM: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: @@ -4588,6 +5110,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); break; case SAA7134_BOARD_AVERMEDIA_CARDBUS: + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); @@ -4609,6 +5132,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_PINNACLE_PCTV_310i: case SAA7134_BOARD_UPMOST_PURPLE_TV: case SAA7134_BOARD_HAUPPAUGE_HVR1110: + case SAA7134_BOARD_BEHOLD_607_9FM: + case SAA7134_BOARD_BEHOLD_M6: dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: @@ -4754,7 +5279,6 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; case SAA7134_BOARD_PHILIPS_TIGER: case SAA7134_BOARD_PHILIPS_TIGER_S: - case SAA7134_BOARD_AVERMEDIA_SUPER_007: { u8 data[] = { 0x3c, 0x33, 0x60}; struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; @@ -4784,6 +5308,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: case SAA7134_BOARD_MEDION_MD8800_QUADRO: + case SAA7134_BOARD_AVERMEDIA_SUPER_007: /* this is a hybrid board, initialize to analog mode * and configure firmware eeprom address */ diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index 15e43bd40..4a275e4d7 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -343,6 +343,7 @@ static int attach_inform(struct i2c_client *client) case 0x7a: case 0x47: case 0x71: + case 0x2d: { struct IR_i2c *ir = i2c_get_clientdata(client); d1printk("%s i2c IR detected (%s).\n", @@ -456,6 +457,7 @@ static char *i2c_devs[128] = { [ 0xa0 >> 1 ] = "eeprom", [ 0xc0 >> 1 ] = "tuner (analog)", [ 0x86 >> 1 ] = "tda9887", + [ 0x5a >> 1 ] = "remote control", }; static void do_i2c_scan(char *name, struct i2c_client *c) diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index fa2d39781..448bc41d0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -52,6 +52,11 @@ module_param(repeat_period, int, 0644); MODULE_PARM_DESC(repeat_period, "repeat period between " "keypresses when key is down"); +static unsigned int disable_other_ir; +module_param(disable_other_ir, int, 0644); +MODULE_PARM_DESC(disable_other_ir, "disable full codes of " + "alternative remotes from other manufacturers"); + #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) #define i2cdprintk(fmt, arg...) if (ir_debug) \ @@ -154,6 +159,45 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } + +static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char data[12]; + u32 gpio; + + struct saa7134_dev *dev = ir->c.adapter->algo_data; + + /* rising SAA7134_GPIO_GPRESCAN reads the status */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + + gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); + + if (0x400000 & ~gpio) + return 0; /* No button press */ + + ir->c.addr = 0x5a >> 1; + + if (12 != i2c_master_recv(&ir->c, data, 12)) { + i2cdprintk("read error\n"); + return -EIO; + } + /* IR of this card normally decode signals NEC-standard from + * - Sven IHOO MT 5.1R remote. xxyye718 + * - Sven DVD HD-10xx remote. xxyyf708 + * - BBK ... + * - mayby others + * So, skip not our, if disable full codes mode. + */ + if (data[10] != 0x6b && data[11] != 0x86 && disable_other_ir) + return 0; + + *ir_key = data[9]; + *ir_raw = data[9]; + + return 1; +} + void saa7134_input_irq(struct saa7134_dev *dev) { struct card_ir *ir = dev->remote; @@ -288,6 +332,16 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: + case SAA7134_BOARD_BEHOLD_401: + case SAA7134_BOARD_BEHOLD_403: + case SAA7134_BOARD_BEHOLD_403FM: + case SAA7134_BOARD_BEHOLD_405: + case SAA7134_BOARD_BEHOLD_405FM: + case SAA7134_BOARD_BEHOLD_407: + case SAA7134_BOARD_BEHOLD_407FM: + case SAA7134_BOARD_BEHOLD_409: + case SAA7134_BOARD_BEHOLD_505FM: + case SAA7134_BOARD_BEHOLD_507_9FM: ir_codes = ir_codes_manli; mask_keycode = 0x001f00; mask_keyup = 0x004000; @@ -468,6 +522,12 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) ir->get_key = get_key_hvr1110; ir->ir_codes = ir_codes_hauppauge_new; break; + case SAA7134_BOARD_BEHOLD_607_9FM: + case SAA7134_BOARD_BEHOLD_M6: + snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV"); + ir->get_key = get_key_beholdm6xx; + ir->ir_codes = ir_codes_behold; + break; default: dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); break; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index a0a59ce12..3a74671a5 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -247,6 +247,19 @@ struct saa7134_format { #define SAA7134_BOARD_SABRENT_TV_PCB05 115 #define SAA7134_BOARD_10MOONSTVMASTER3 116 #define SAA7134_BOARD_AVERMEDIA_SUPER_007 117 +#define SAA7134_BOARD_BEHOLD_401 118 +#define SAA7134_BOARD_BEHOLD_403 119 +#define SAA7134_BOARD_BEHOLD_403FM 120 +#define SAA7134_BOARD_BEHOLD_405 121 +#define SAA7134_BOARD_BEHOLD_405FM 122 +#define SAA7134_BOARD_BEHOLD_407 123 +#define SAA7134_BOARD_BEHOLD_407FM 124 +#define SAA7134_BOARD_BEHOLD_409 125 +#define SAA7134_BOARD_BEHOLD_505FM 126 +#define SAA7134_BOARD_BEHOLD_507_9FM 127 +#define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128 +#define SAA7134_BOARD_BEHOLD_607_9FM 129 +#define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/linux/drivers/media/video/stk-sensor.c b/linux/drivers/media/video/stk-sensor.c new file mode 100644 index 000000000..4a9a0b62e --- /dev/null +++ b/linux/drivers/media/video/stk-sensor.c @@ -0,0 +1,578 @@ +/* stk-sensor.c: Driver for ov96xx sensor (used in some Syntek webcams) + * + * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com> + * + * Some parts derived from ov7670.c: + * Copyright 2006 One Laptop Per Child Association, Inc. Written + * by Jonathan Corbet with substantial inspiration from Mark + * McClelland's ovcamchip code. + * + * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> + * + * This file may be distributed under the terms of the GNU General + * 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. + */ + +/* Controlling the sensor via the STK1125 vendor specific control interface: + * The camera uses an OmniVision sensor and the stk1125 provides an + * SCCB(i2c)-USB bridge which let us program the sensor. + * In my case the sensor id is 0x9652, it can be read from sensor's register + * 0x0A and 0x0B as follows: + * - read register #R: + * output #R to index 0x0208 + * output 0x0070 to index 0x0200 + * input 1 byte from index 0x0201 (some kind of status register) + * until its value is 0x01 + * input 1 byte from index 0x0209. This is the value of #R + * - write value V to register #R + * output #R to index 0x0204 + * output V to index 0x0205 + * output 0x0005 to index 0x0200 + * input 1 byte from index 0x0201 until its value becomes 0x04 + */ + +/* It seems the i2c bus is controlled with these registers */ + +#include "stk-webcam.h" + +#define STK_IIC_BASE (0x0200) +# define STK_IIC_OP (STK_IIC_BASE) +# define STK_IIC_OP_TX (0x05) +# define STK_IIC_OP_RX (0x70) +# define STK_IIC_STAT (STK_IIC_BASE+1) +# define STK_IIC_STAT_TX_OK (0x04) +# define STK_IIC_STAT_RX_OK (0x01) +/* I don't know what does this register. + * when it is 0x00 or 0x01, we cannot talk to the sensor, + * other values work */ +# define STK_IIC_ENABLE (STK_IIC_BASE+2) +# define STK_IIC_ENABLE_NO (0x00) +/* This is what the driver writes in windows */ +# define STK_IIC_ENABLE_YES (0x1e) +/* + * Address of the slave. Seems like the binary driver look for the + * sensor in multiple places, attempting a reset sequence. + * We only know about the ov9650 + */ +# define STK_IIC_ADDR (STK_IIC_BASE+3) +# define STK_IIC_TX_INDEX (STK_IIC_BASE+4) +# define STK_IIC_TX_VALUE (STK_IIC_BASE+5) +# define STK_IIC_RX_INDEX (STK_IIC_BASE+8) +# define STK_IIC_RX_VALUE (STK_IIC_BASE+9) + +#define MAX_RETRIES (50) + +#define SENSOR_ADDRESS (0x60) + +/* From ov7670.c (These registers aren't fully accurate) */ + +/* Registers */ +#define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ +#define REG_BLUE 0x01 /* blue gain */ +#define REG_RED 0x02 /* red gain */ +#define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ +#define REG_COM1 0x04 /* Control 1 */ +#define COM1_CCIR656 0x40 /* CCIR656 enable */ +#define COM1_QFMT 0x20 /* QVGA/QCIF format */ +#define COM1_SKIP_0 0x00 /* Do not skip any row */ +#define COM1_SKIP_2 0x04 /* Skip 2 rows of 4 */ +#define COM1_SKIP_3 0x08 /* Skip 3 rows of 4 */ +#define REG_BAVE 0x05 /* U/B Average level */ +#define REG_GbAVE 0x06 /* Y/Gb Average level */ +#define REG_AECHH 0x07 /* AEC MS 5 bits */ +#define REG_RAVE 0x08 /* V/R Average level */ +#define REG_COM2 0x09 /* Control 2 */ +#define COM2_SSLEEP 0x10 /* Soft sleep mode */ +#define REG_PID 0x0a /* Product ID MSB */ +#define REG_VER 0x0b /* Product ID LSB */ +#define REG_COM3 0x0c /* Control 3 */ +#define COM3_SWAP 0x40 /* Byte swap */ +#define COM3_SCALEEN 0x08 /* Enable scaling */ +#define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */ +#define REG_COM4 0x0d /* Control 4 */ +#define REG_COM5 0x0e /* All "reserved" */ +#define REG_COM6 0x0f /* Control 6 */ +#define REG_AECH 0x10 /* More bits of AEC value */ +#define REG_CLKRC 0x11 /* Clock control */ +#define CLK_PLL 0x80 /* Enable internal PLL */ +#define CLK_EXT 0x40 /* Use external clock directly */ +#define CLK_SCALE 0x3f /* Mask for internal clock scale */ +#define REG_COM7 0x12 /* Control 7 */ +#define COM7_RESET 0x80 /* Register reset */ +#define COM7_FMT_MASK 0x38 +#define COM7_FMT_SXGA 0x00 +#define COM7_FMT_VGA 0x40 +#define COM7_FMT_CIF 0x20 /* CIF format */ +#define COM7_FMT_QVGA 0x10 /* QVGA format */ +#define COM7_FMT_QCIF 0x08 /* QCIF format */ +#define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */ +#define COM7_YUV 0x00 /* YUV */ +#define COM7_BAYER 0x01 /* Bayer format */ +#define COM7_PBAYER 0x05 /* "Processed bayer" */ +#define REG_COM8 0x13 /* Control 8 */ +#define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ +#define COM8_AECSTEP 0x40 /* Unlimited AEC step size */ +#define COM8_BFILT 0x20 /* Band filter enable */ +#define COM8_AGC 0x04 /* Auto gain enable */ +#define COM8_AWB 0x02 /* White balance enable */ +#define COM8_AEC 0x01 /* Auto exposure enable */ +#define REG_COM9 0x14 /* Control 9 - gain ceiling */ +#define REG_COM10 0x15 /* Control 10 */ +#define COM10_HSYNC 0x40 /* HSYNC instead of HREF */ +#define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */ +#define COM10_HREF_REV 0x08 /* Reverse HREF */ +#define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */ +#define COM10_VS_NEG 0x02 /* VSYNC negative */ +#define COM10_HS_NEG 0x01 /* HSYNC negative */ +#define REG_HSTART 0x17 /* Horiz start high bits */ +#define REG_HSTOP 0x18 /* Horiz stop high bits */ +#define REG_VSTART 0x19 /* Vert start high bits */ +#define REG_VSTOP 0x1a /* Vert stop high bits */ +#define REG_PSHFT 0x1b /* Pixel delay after HREF */ +#define REG_MIDH 0x1c /* Manuf. ID high */ +#define REG_MIDL 0x1d /* Manuf. ID low */ +#define REG_MVFP 0x1e /* Mirror / vflip */ +#define MVFP_MIRROR 0x20 /* Mirror image */ +#define MVFP_FLIP 0x10 /* Vertical flip */ + +#define REG_AEW 0x24 /* AGC upper limit */ +#define REG_AEB 0x25 /* AGC lower limit */ +#define REG_VPT 0x26 /* AGC/AEC fast mode op region */ +#define REG_ADVFL 0x2d /* Insert dummy lines (LSB) */ +#define REG_ADVFH 0x2e /* Insert dummy lines (MSB) */ +#define REG_HSYST 0x30 /* HSYNC rising edge delay */ +#define REG_HSYEN 0x31 /* HSYNC falling edge delay */ +#define REG_HREF 0x32 /* HREF pieces */ +#define REG_TSLB 0x3a /* lots of stuff */ +#define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */ +#define TSLB_BYTEORD 0x08 /* swap bytes in 16bit mode? */ +#define REG_COM11 0x3b /* Control 11 */ +#define COM11_NIGHT 0x80 /* NIght mode enable */ +#define COM11_NMFR 0x60 /* Two bit NM frame rate */ +#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ +#define COM11_50HZ 0x08 /* Manual 50Hz select */ +#define COM11_EXP 0x02 +#define REG_COM12 0x3c /* Control 12 */ +#define COM12_HREF 0x80 /* HREF always */ +#define REG_COM13 0x3d /* Control 13 */ +#define COM13_GAMMA 0x80 /* Gamma enable */ +#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ +#define COM13_CMATRIX 0x10 /* Enable color matrix for RGB or YUV */ +#define COM13_UVSWAP 0x01 /* V before U - w/TSLB */ +#define REG_COM14 0x3e /* Control 14 */ +#define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */ +#define REG_EDGE 0x3f /* Edge enhancement factor */ +#define REG_COM15 0x40 /* Control 15 */ +#define COM15_R10F0 0x00 /* Data range 10 to F0 */ +#define COM15_R01FE 0x80 /* 01 to FE */ +#define COM15_R00FF 0xc0 /* 00 to FF */ +#define COM15_RGB565 0x10 /* RGB565 output */ +#define COM15_RGBFIXME 0x20 /* FIXME */ +#define COM15_RGB555 0x30 /* RGB555 output */ +#define REG_COM16 0x41 /* Control 16 */ +#define COM16_AWBGAIN 0x08 /* AWB gain enable */ +#define REG_COM17 0x42 /* Control 17 */ +#define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */ +#define COM17_CBAR 0x08 /* DSP Color bar */ + +/* + * This matrix defines how the colors are generated, must be + * tweaked to adjust hue and saturation. + * + * Order: v-red, v-green, v-blue, u-red, u-green, u-blue + * + * They are nine-bit signed quantities, with the sign bit + * stored in 0x58. Sign for v-red is bit 0, and up from there. + */ +#define REG_CMATRIX_BASE 0x4f +#define CMATRIX_LEN 6 +#define REG_CMATRIX_SIGN 0x58 + + +#define REG_BRIGHT 0x55 /* Brightness */ +#define REG_CONTRAS 0x56 /* Contrast control */ + +#define REG_GFIX 0x69 /* Fix gain control */ + +#define REG_RGB444 0x8c /* RGB 444 control */ +#define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */ +#define R444_RGBX 0x01 /* Empty nibble at end */ + +#define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ +#define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ + +#define REG_BD50MAX 0xa5 /* 50hz banding step limit */ +#define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ +#define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ +#define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ +#define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ +#define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ +#define REG_BD60MAX 0xab /* 60hz banding step limit */ + + + + +/* Returns 0 if OK */ +int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val) +{ + int i = 0; + int tmpval = 0; + + if (stk_camera_write_reg(dev, STK_IIC_TX_INDEX, reg)) + return 1; + if (stk_camera_write_reg(dev, STK_IIC_TX_VALUE, val)) + return 1; + if (stk_camera_write_reg(dev, STK_IIC_OP, STK_IIC_OP_TX)) + return 1; + do { + if (stk_camera_read_reg(dev, STK_IIC_STAT, &tmpval)) + return 1; + i++; + } while (tmpval == 0 && i < MAX_RETRIES); + if (tmpval != STK_IIC_STAT_TX_OK) { + if (tmpval) + STK_ERROR("stk_sensor_outb failed, status=0x%02x\n", + tmpval); + return 1; + } else + return 0; +} + +int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val) +{ + int i = 0; + int tmpval = 0; + + if (stk_camera_write_reg(dev, STK_IIC_RX_INDEX, reg)) + return 1; + if (stk_camera_write_reg(dev, STK_IIC_OP, STK_IIC_OP_RX)) + return 1; + do { + if (stk_camera_read_reg(dev, STK_IIC_STAT, &tmpval)) + return 1; + i++; + } while (tmpval == 0 && i < MAX_RETRIES); + if (tmpval != STK_IIC_STAT_RX_OK) { + if (tmpval) + STK_ERROR("stk_sensor_inb failed, status=0x%02x\n", + tmpval); + return 1; + } + + if (stk_camera_read_reg(dev, STK_IIC_RX_VALUE, &tmpval)) + return 1; + + *val = (u8) tmpval; + return 0; +} + +static int stk_sensor_write_regvals(struct stk_camera *dev, + struct regval *rv) +{ + int ret; + if (rv == NULL) + return 0; + while (rv->reg != 0xff || rv->val != 0xff) { + ret = stk_sensor_outb(dev, rv->reg, rv->val); + if (ret != 0) + return ret; + rv++; + } + return 0; +} + +int stk_sensor_sleep(struct stk_camera *dev) +{ + u8 tmp; + return stk_sensor_inb(dev, REG_COM2, &tmp) + || stk_sensor_outb(dev, REG_COM2, tmp|COM2_SSLEEP); +} + +int stk_sensor_wakeup(struct stk_camera *dev) +{ + u8 tmp; + return stk_sensor_inb(dev, REG_COM2, &tmp) + || stk_sensor_outb(dev, REG_COM2, tmp&~COM2_SSLEEP); +} + +static struct regval ov_initvals[] = { + {REG_CLKRC, CLK_PLL}, + {REG_COM11, 0x01}, + {0x6a, 0x7d}, + {REG_AECH, 0x40}, + {REG_GAIN, 0x00}, + {REG_BLUE, 0x80}, + {REG_RED, 0x80}, + /* Do not enable fast AEC for now */ + /*{REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC},*/ + {REG_COM8, COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC}, + {0x39, 0x50}, {0x38, 0x93}, + {0x37, 0x00}, {0x35, 0x81}, + {REG_COM5, 0x20}, + {REG_COM1, 0x00}, + {REG_COM3, 0x00}, + {REG_COM4, 0x00}, + {REG_PSHFT, 0x00}, + {0x16, 0x07}, + {0x33, 0xe2}, {0x34, 0xbf}, + {REG_COM16, 0x00}, + {0x96, 0x04}, + /* Gamma curve values */ +/* { 0x7a, 0x20 }, { 0x7b, 0x10 }, + { 0x7c, 0x1e }, { 0x7d, 0x35 }, + { 0x7e, 0x5a }, { 0x7f, 0x69 }, + { 0x80, 0x76 }, { 0x81, 0x80 }, + { 0x82, 0x88 }, { 0x83, 0x8f }, + { 0x84, 0x96 }, { 0x85, 0xa3 }, + { 0x86, 0xaf }, { 0x87, 0xc4 }, + { 0x88, 0xd7 }, { 0x89, 0xe8 }, +*/ + {REG_GFIX, 0x40}, + {0x8e, 0x00}, + {REG_COM12, 0x73}, + {0x8f, 0xdf}, {0x8b, 0x06}, + {0x8c, 0x20}, + {0x94, 0x88}, {0x95, 0x88}, +/* {REG_COM15, 0xc1}, TODO */ + {0x29, 0x3f}, + {REG_COM6, 0x42}, + {REG_BD50MAX, 0x80}, + {REG_HAECC6, 0xb8}, {REG_HAECC7, 0x92}, + {REG_BD60MAX, 0x0a}, + {0x90, 0x00}, {0x91, 0x00}, + {REG_HAECC1, 0x00}, {REG_HAECC2, 0x00}, + {REG_AEW, 0x68}, {REG_AEB, 0x5c}, + {REG_VPT, 0xc3}, + {REG_COM9, 0x2e}, + {0x2a, 0x00}, {0x2b, 0x00}, + + {0xff, 0xff}, /* END MARKER */ +}; + +/* Probe the I2C bus and initialise the sensor chip */ +int stk_sensor_init(struct stk_camera *dev) +{ + u8 idl = 0; + u8 idh = 0; + + if (stk_camera_write_reg(dev, STK_IIC_ENABLE, STK_IIC_ENABLE_YES) + || stk_camera_write_reg(dev, STK_IIC_ADDR, SENSOR_ADDRESS) + || stk_sensor_outb(dev, REG_COM7, COM7_RESET)) { + STK_ERROR("Sensor resetting failed\n"); + return -ENODEV; + } + msleep(10); + /* Read the manufacturer ID: ov = 0x7FA2 */ + if (stk_sensor_inb(dev, REG_MIDH, &idh) + || stk_sensor_inb(dev, REG_MIDL, &idl)) { + STK_ERROR("Strange error reading sensor ID\n"); + return -ENODEV; + } + if (idh != 0x7F || idl != 0xA2) { + STK_ERROR("Huh? you don't have a sensor from ovt\n"); + return -ENODEV; + } + if (stk_sensor_inb(dev, REG_PID, &idh) + || stk_sensor_inb(dev, REG_VER, &idl)) { + STK_ERROR("Could not read sensor model\n"); + return -ENODEV; + } + stk_sensor_write_regvals(dev, ov_initvals); + msleep(10); + STK_INFO("OmniVision sensor detected, id %02X%02X" + " at address %x\n", idh, idl, SENSOR_ADDRESS); + return 0; +} + +/* V4L2_PIX_FMT_UYVY */ +static struct regval ov_fmt_uyvy[] = { + {REG_TSLB, TSLB_YLAST|0x08 }, + { 0x4f, 0x80 }, /* "matrix coefficient 1" */ + { 0x50, 0x80 }, /* "matrix coefficient 2" */ + { 0x51, 0 }, /* vb */ + { 0x52, 0x22 }, /* "matrix coefficient 4" */ + { 0x53, 0x5e }, /* "matrix coefficient 5" */ + { 0x54, 0x80 }, /* "matrix coefficient 6" */ + {REG_COM13, COM13_UVSAT|COM13_CMATRIX}, + {REG_COM15, COM15_R00FF }, + {0xff, 0xff}, /* END MARKER */ +}; + +/* V4L2_PIX_FMT_RGB565X rrrrrggg gggbbbbb */ +static struct regval ov_fmt_rgbr[] = { + { REG_RGB444, 0 }, /* No RGB444 please */ + {REG_TSLB, 0x00}, + { REG_COM1, 0x0 }, + { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ + { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ + { 0x50, 0xb3 }, /* "matrix coefficient 2" */ + { 0x51, 0 }, /* vb */ + { 0x52, 0x3d }, /* "matrix coefficient 4" */ + { 0x53, 0xa7 }, /* "matrix coefficient 5" */ + { 0x54, 0xe4 }, /* "matrix coefficient 6" */ + { REG_COM13, COM13_GAMMA }, + { REG_COM15, COM15_RGB565|COM15_R00FF }, + { 0xff, 0xff }, +}; + +/* V4L2_PIX_FMT_RGB565 gggbbbbb rrrrrggg */ +static struct regval ov_fmt_rgbp[] = { + { REG_RGB444, 0 }, /* No RGB444 please */ + {REG_TSLB, TSLB_BYTEORD }, + { REG_COM1, 0x0 }, + { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ + { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ + { 0x50, 0xb3 }, /* "matrix coefficient 2" */ + { 0x51, 0 }, /* vb */ + { 0x52, 0x3d }, /* "matrix coefficient 4" */ + { 0x53, 0xa7 }, /* "matrix coefficient 5" */ + { 0x54, 0xe4 }, /* "matrix coefficient 6" */ + { REG_COM13, COM13_GAMMA }, + { REG_COM15, COM15_RGB565|COM15_R00FF }, + { 0xff, 0xff }, +}; + +/* V4L2_PIX_FMT_SRGGB8 */ +static struct regval ov_fmt_bayer[] = { + /* This changes color order */ + {REG_TSLB, 0x40}, /* BGGR */ + /* {REG_TSLB, 0x08}, */ /* BGGR with vertical image flipping */ + {REG_COM15, COM15_R00FF }, + {0xff, 0xff}, /* END MARKER */ +}; +/* + * Store a set of start/stop values into the camera. + */ +static int stk_sensor_set_hw(struct stk_camera *dev, + int hstart, int hstop, int vstart, int vstop) +{ + int ret; + unsigned char v; +/* + * Horizontal: 11 bits, top 8 live in hstart and hstop. Bottom 3 of + * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is + * a mystery "edge offset" value in the top two bits of href. + */ + ret = stk_sensor_outb(dev, REG_HSTART, (hstart >> 3) & 0xff); + ret += stk_sensor_outb(dev, REG_HSTOP, (hstop >> 3) & 0xff); + ret += stk_sensor_inb(dev, REG_HREF, &v); + v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); + msleep(10); + ret += stk_sensor_outb(dev, REG_HREF, v); +/* + * Vertical: similar arrangement (note: this is different from ov7670.c) + */ + ret += stk_sensor_outb(dev, REG_VSTART, (vstart >> 3) & 0xff); + ret += stk_sensor_outb(dev, REG_VSTOP, (vstop >> 3) & 0xff); + ret += stk_sensor_inb(dev, REG_VREF, &v); + v = (v & 0xc0) | ((vstop & 0x7) << 3) | (vstart & 0x7); + msleep(10); + ret += stk_sensor_outb(dev, REG_VREF, v); + return ret; +} + + +int stk_sensor_configure(struct stk_camera *dev) +{ + int com7; + /* + * We setup the sensor to output dummy lines in low-res modes, + * so we don't get absurdly hight framerates. + */ + unsigned dummylines; + int flip; + struct regval *rv; + + switch (dev->vsettings.mode) { + case MODE_QCIF: com7 = COM7_FMT_QCIF; + dummylines = 604; + break; + case MODE_QVGA: com7 = COM7_FMT_QVGA; + dummylines = 267; + break; + case MODE_CIF: com7 = COM7_FMT_CIF; + dummylines = 412; + break; + case MODE_VGA: com7 = COM7_FMT_VGA; + dummylines = 11; + break; + case MODE_SXGA: com7 = COM7_FMT_SXGA; + dummylines = 0; + break; + default: STK_ERROR("Unsupported mode %d\n", dev->vsettings.mode); + return -EFAULT; + } + switch (dev->vsettings.palette) { + case V4L2_PIX_FMT_UYVY: + com7 |= COM7_YUV; + rv = ov_fmt_uyvy; + break; + case V4L2_PIX_FMT_RGB565: + com7 |= COM7_RGB; + rv = ov_fmt_rgbp; + break; + case V4L2_PIX_FMT_RGB565X: + com7 |= COM7_RGB; + rv = ov_fmt_rgbr; + break; + case V4L2_PIX_FMT_SBGGR8: + com7 |= COM7_PBAYER; + rv = ov_fmt_bayer; + break; + default: STK_ERROR("Unsupported colorspace\n"); + return -EFAULT; + } + /*FIXME sometimes the sensor go to a bad state + stk_sensor_write_regvals(dev, ov_initvals); */ + stk_sensor_outb(dev, REG_COM7, com7); + msleep(50); + stk_sensor_write_regvals(dev, rv); + flip = (dev->vsettings.vflip?MVFP_FLIP:0) + | (dev->vsettings.hflip?MVFP_MIRROR:0); + stk_sensor_outb(dev, REG_MVFP, flip); + if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8 + && !dev->vsettings.vflip) + stk_sensor_outb(dev, REG_TSLB, 0x08); + stk_sensor_outb(dev, REG_ADVFH, dummylines >> 8); + stk_sensor_outb(dev, REG_ADVFL, dummylines & 0xff); + msleep(50); + switch (dev->vsettings.mode) { + case MODE_VGA: + if (stk_sensor_set_hw(dev, 302, 1582, 6, 486)) + STK_ERROR("stk_sensor_set_hw failed (VGA)\n"); + break; + case MODE_SXGA: + case MODE_CIF: + case MODE_QVGA: + case MODE_QCIF: + /*FIXME These settings seem ignored by the sensor + if (stk_sensor_set_hw(dev, 220, 1500, 10, 1034)) + STK_ERROR("stk_sensor_set_hw failed (SXGA)\n"); + */ + break; + } + msleep(10); + return 0; +} + +int stk_sensor_set_brightness(struct stk_camera *dev, int br) +{ + if (br < 0 || br > 0xff) + return -EINVAL; + stk_sensor_outb(dev, REG_AEB, max(0x00, br - 6)); + stk_sensor_outb(dev, REG_AEW, min(0xff, br + 6)); + return 0; +} + diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c new file mode 100644 index 000000000..f300eca3c --- /dev/null +++ b/linux/drivers/media/video/stk-webcam.c @@ -0,0 +1,1465 @@ +/* + * stk-webcam.c : Driver for Syntek 1125 USB webcam controller + * + * Copyright (C) 2006 Nicolas VIVIEN + * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com> + * + * Some parts are inspired from cafe_ccic.c + * Copyright 2006-2007 Jonathan Corbet + * + * 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 + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/kref.h> + +#include <linux/usb.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <linux/vmalloc.h> + +#include "stk-webcam.h" + + +static int hflip = 1; +module_param(hflip, bool, 0444); +MODULE_PARM_DESC(hflip, "Horizontal image flip (mirror). Defaults to 1"); + +static int vflip = 1; +module_param(vflip, bool, 0444); +MODULE_PARM_DESC(vflip, "Vertical image flip. Defaults to 1"); + +static int debug; +module_param(debug, int, 0444); +MODULE_PARM_DESC(debug, "Debug v4l ioctls. Defaults to 0"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN"); +MODULE_DESCRIPTION("Syntek DC1125 webcam driver"); + + + +/* Some cameras have audio interfaces, we aren't interested in those */ +static struct usb_device_id stkwebcam_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x174f, 0xa311, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x05e1, 0x0501, 0xff, 0xff, 0xff) }, + { } +}; +MODULE_DEVICE_TABLE(usb, stkwebcam_table); + +void stk_camera_cleanup(struct kref *kref) +{ + struct stk_camera *dev = to_stk_camera(kref); + + STK_INFO("Syntek USB2.0 Camera release resources" + " video device /dev/video%d\n", dev->vdev.minor); + video_unregister_device(&dev->vdev); + dev->vdev.priv = NULL; + + if (dev->sio_bufs != NULL || dev->isobufs != NULL) + STK_ERROR("We are leaking memory\n"); + usb_put_intf(dev->interface); + kfree(dev); +} + + +/* + * Basic stuff + */ +int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value) +{ + struct usb_device *udev = dev->udev; + int ret; + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x01, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + index, + NULL, + 0, + 500); + if (ret < 0) + return ret; + else + return 0; +} + +int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value) +{ + struct usb_device *udev = dev->udev; + int ret; + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x00, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, + index, + (u8 *) value, + sizeof(u8), + 500); + if (ret < 0) + return ret; + else + return 0; +} + +static int stk_start_stream(struct stk_camera *dev) +{ + int value; + int i, ret; + int value_116, value_117; + + if (!is_present(dev)) + return -ENODEV; + if (!is_memallocd(dev) || !is_initialised(dev)) { + STK_ERROR("FIXME: Buffers are not allocated\n"); + return -EFAULT; + } + ret = usb_set_interface(dev->udev, 0, 5); + + if (ret < 0) + STK_ERROR("usb_set_interface failed !\n"); + if (stk_sensor_wakeup(dev)) + STK_ERROR("error awaking the sensor\n"); + + stk_camera_read_reg(dev, 0x0116, &value_116); + stk_camera_read_reg(dev, 0x0117, &value_117); + + stk_camera_write_reg(dev, 0x0116, 0x0000); + stk_camera_write_reg(dev, 0x0117, 0x0000); + + stk_camera_read_reg(dev, 0x0100, &value); + stk_camera_write_reg(dev, 0x0100, value | 0x80); + + stk_camera_write_reg(dev, 0x0116, value_116); + stk_camera_write_reg(dev, 0x0117, value_117); + for (i = 0; i < MAX_ISO_BUFS; i++) { + if (dev->isobufs[i].urb) { + ret = usb_submit_urb(dev->isobufs[i].urb, GFP_KERNEL); + atomic_inc(&dev->urbs_used); + if (ret) + return ret; + } + } + set_streaming(dev); + return 0; +} + +static int stk_stop_stream(struct stk_camera *dev) +{ + int value; + int i; + if (is_present(dev)) { + stk_camera_read_reg(dev, 0x0100, &value); + stk_camera_write_reg(dev, 0x0100, value & ~0x80); + if (dev->isobufs != NULL) { + for (i = 0; i < MAX_ISO_BUFS; i++) { + if (dev->isobufs[i].urb) + usb_kill_urb(dev->isobufs[i].urb); + } + } + unset_streaming(dev); + + if (usb_set_interface(dev->udev, 0, 0)) + STK_ERROR("usb_set_interface failed !\n"); + if (stk_sensor_sleep(dev)) + STK_ERROR("error suspending the sensor\n"); + } + return 0; +} + +/* + * This seems to be the shortest init sequence we + * must do in order to find the sensor + * Bit 5 of reg. 0x0000 here is important, when reset to 0 the sensor + * is also reset. Maybe powers down it? + * Rest of values don't make a difference + */ + +static struct regval stk1125_initvals[] = { + /*TODO: What means this sequence? */ + {0x0000, 0x24}, + {0x0100, 0x21}, + {0x0002, 0x68}, + {0x0003, 0x80}, + {0x0005, 0x00}, + {0x0007, 0x03}, + {0x000d, 0x00}, + {0x000f, 0x02}, + {0x0300, 0x12}, + {0x0350, 0x41}, + {0x0351, 0x00}, + {0x0352, 0x00}, + {0x0353, 0x00}, + {0x0018, 0x10}, + {0x0019, 0x00}, + {0x001b, 0x0e}, + {0x001c, 0x46}, + {0x0300, 0x80}, + {0x001a, 0x04}, + {0x0110, 0x00}, + {0x0111, 0x00}, + {0x0112, 0x00}, + {0x0113, 0x00}, + + {0xffff, 0xff}, +}; + + +static int stk_initialise(struct stk_camera *dev) +{ + struct regval *rv; + int ret; + if (!is_present(dev)) + return -ENODEV; + if (is_initialised(dev)) + return 0; + rv = stk1125_initvals; + while (rv->reg != 0xffff) { + ret = stk_camera_write_reg(dev, rv->reg, rv->val); + if (ret) + return ret; + rv++; + } + if (stk_sensor_init(dev) == 0) { + set_initialised(dev); + return 0; + } else + return -1; +} + +/* sysfs functions */ +/*FIXME cleanup this */ + +static ssize_t show_brightness(struct device *class, + struct device_attribute *attr, char *buf) +{ + struct video_device *vdev = to_video_device(class); + struct stk_camera *dev = vdev_to_camera(vdev); + + return sprintf(buf, "%X\n", dev->vsettings.brightness); +} + +static ssize_t store_brightness(struct device *class, + struct device_attribute *attr, const char *buf, size_t count) +{ + char *endp; + unsigned long value; + int ret; + + struct video_device *vdev = to_video_device(class); + struct stk_camera *dev = vdev_to_camera(vdev); + + value = simple_strtoul(buf, &endp, 16); + + dev->vsettings.brightness = (int) value; + + ret = stk_sensor_set_brightness(dev, value >> 8); + if (ret) + return ret; + else + return count; +} + +static ssize_t show_hflip(struct device *class, + struct device_attribute *attr, char *buf) +{ + struct video_device *vdev = to_video_device(class); + struct stk_camera *dev = vdev_to_camera(vdev); + + return sprintf(buf, "%d\n", dev->vsettings.hflip); +} + +static ssize_t store_hflip(struct device *class, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct video_device *vdev = to_video_device(class); + struct stk_camera *dev = vdev_to_camera(vdev); + + if (strncmp(buf, "1", 1) == 0) + dev->vsettings.hflip = 1; + else if (strncmp(buf, "0", 1) == 0) + dev->vsettings.hflip = 0; + else + return -EINVAL; + + return strlen(buf); +} + +static ssize_t show_vflip(struct device *class, + struct device_attribute *attr, char *buf) +{ + struct video_device *vdev = to_video_device(class); + struct stk_camera *dev = vdev_to_camera(vdev); + + return sprintf(buf, "%d\n", dev->vsettings.vflip); +} + +static ssize_t store_vflip(struct device *class, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct video_device *vdev = to_video_device(class); + struct stk_camera *dev = vdev_to_camera(vdev); + + if (strncmp(buf, "1", 1) == 0) + dev->vsettings.vflip = 1; + else if (strncmp(buf, "0", 1) == 0) + dev->vsettings.vflip = 0; + else + return -EINVAL; + + return strlen(buf); +} + +static DEVICE_ATTR(brightness, S_IRUGO | S_IWUGO, + show_brightness, store_brightness); +static DEVICE_ATTR(hflip, S_IRUGO | S_IWUGO, show_hflip, store_hflip); +static DEVICE_ATTR(vflip, S_IRUGO | S_IWUGO, show_vflip, store_vflip); + +static int stk_create_sysfs_files(struct video_device *vdev) +{ + int ret; + + ret = video_device_create_file(vdev, &dev_attr_brightness); + ret += video_device_create_file(vdev, &dev_attr_hflip); + ret += video_device_create_file(vdev, &dev_attr_vflip); + return ret; +} + +static void stk_remove_sysfs_files(struct video_device *vdev) +{ + video_device_remove_file(vdev, &dev_attr_brightness); + video_device_remove_file(vdev, &dev_attr_hflip); + video_device_remove_file(vdev, &dev_attr_vflip); +} + + +/* *********************************************** */ +/* + * This function is called as an URB transfert is complete (Isochronous pipe). + * So, the traitement is done in interrupt time, so it has be fast, not crash, + * and not stall. Neat. + */ +static void stk_isoc_handler(struct urb *urb) +{ + int i; + int ret; + int framelen; + unsigned long flags; + + unsigned char *fill = NULL; + unsigned char *iso_buf = NULL; + + struct stk_camera *dev; + struct stk_sio_buffer *fb; + + dev = (struct stk_camera *) urb->context; + + if (dev == NULL) { + STK_ERROR("isoc_handler called with NULL device !\n"); + return; + } + + if (urb->status == -ENOENT || urb->status == -ECONNRESET + || urb->status == -ESHUTDOWN) { + atomic_dec(&dev->urbs_used); + return; + } + + spin_lock_irqsave(&dev->spinlock, flags); + + if (urb->status != -EINPROGRESS && urb->status != 0) { + STK_ERROR("isoc_handler: urb->status == %d\n", urb->status); + goto resubmit; + } + + if (list_empty(&dev->sio_avail)) { + /*FIXME Stop streaming after a while */ + (void) (printk_ratelimit() && + STK_ERROR("isoc_handler without available buffer!\n")); + goto resubmit; + } + fb = list_first_entry(&dev->sio_avail, + struct stk_sio_buffer, list); + fill = fb->buffer + fb->v4lbuf.bytesused; + + for (i = 0; i < urb->number_of_packets; i++) { + if (urb->iso_frame_desc[i].status != 0) { + if (urb->iso_frame_desc[i].status != -EXDEV) + STK_ERROR("Frame %d has error %d\n", i, + urb->iso_frame_desc[i].status); + continue; + } + framelen = urb->iso_frame_desc[i].actual_length; + iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + + if (framelen <= 4) + continue; /* no data */ + + /* + * we found something informational from there + * the isoc frames have to type of headers + * type1: 00 xx 00 00 or 20 xx 00 00 + * type2: 80 xx 00 00 00 00 00 00 or a0 xx 00 00 00 00 00 00 + * xx is a sequencer which has never been seen over 0x3f + * imho data written down looks like bayer, i see similarities + * after every 640 bytes + */ + if (*iso_buf & 0x80) { + framelen -= 8; + iso_buf += 8; + /* This marks a new frame */ + if (fb->v4lbuf.bytesused != 0 + && fb->v4lbuf.bytesused != dev->frame_size) { + (void) (printk_ratelimit() && + STK_ERROR("frame %d, " + "bytesused=%d, skipping\n", + i, fb->v4lbuf.bytesused)); + fb->v4lbuf.bytesused = 0; + fill = fb->buffer; + } else if (fb->v4lbuf.bytesused == dev->frame_size) { + list_move_tail(dev->sio_avail.next, + &dev->sio_full); + wake_up(&dev->wait_frame); + if (list_empty(&dev->sio_avail)) { + (void) (printk_ratelimit() && + STK_ERROR("No buffer available\n")); + goto resubmit; + } + fb = list_first_entry(&dev->sio_avail, + struct stk_sio_buffer, list); + fb->v4lbuf.bytesused = 0; + fill = fb->buffer; + } + } else { + framelen -= 4; + iso_buf += 4; + } + + /* Our buffer is full !!! */ + if (framelen + fb->v4lbuf.bytesused > dev->frame_size) { + (void) (printk_ratelimit() && + STK_ERROR("Frame buffer overflow, lost sync\n")); + /*FIXME Do something here? */ + continue; + } + spin_unlock_irqrestore(&dev->spinlock, flags); + memcpy(fill, iso_buf, framelen); + spin_lock_irqsave(&dev->spinlock, flags); + fill += framelen; + + /* New size of our buffer */ + fb->v4lbuf.bytesused += framelen; + } + +resubmit: + spin_unlock_irqrestore(&dev->spinlock, flags); + urb->dev = dev->udev; + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret != 0) { + STK_ERROR("Error (%d) re-submitting urb in stk_isoc_handler.\n", + ret); + } +} + +/* -------------------------------------------- */ + +static int stk_prepare_iso(struct stk_camera *dev) +{ + void *kbuf; + int i, j; + struct urb *urb; + struct usb_device *udev; + + if (dev == NULL) + return -ENXIO; + udev = dev->udev; + + if (dev->isobufs) + STK_ERROR("isobufs already allocated. Bad\n"); + else + dev->isobufs = kzalloc(MAX_ISO_BUFS * sizeof(*dev->isobufs), + GFP_KERNEL); + if (dev->isobufs == NULL) { + STK_ERROR("Unable to allocate iso buffers\n"); + return -ENOMEM; + } + for (i = 0; i < MAX_ISO_BUFS; i++) { + if (dev->isobufs[i].data == NULL) { + kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL); + if (kbuf == NULL) { + STK_ERROR("Failed to allocate iso buffer %d\n", + i); + goto isobufs_out; + } + dev->isobufs[i].data = kbuf; + } else + STK_ERROR("isobuf data already allocated\n"); + if (dev->isobufs[i].urb == NULL) { + urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); + if (urb == NULL) { + STK_ERROR("Failed to allocate URB %d\n", i); + goto isobufs_out; + } + dev->isobufs[i].urb = urb; + } else { + STK_ERROR("Killing URB\n"); + usb_kill_urb(dev->isobufs[i].urb); + urb = dev->isobufs[i].urb; + } + urb->interval = 1; + urb->dev = udev; + urb->pipe = usb_rcvisocpipe(udev, dev->isoc_ep); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = dev->isobufs[i].data; + urb->transfer_buffer_length = ISO_BUFFER_SIZE; + urb->complete = stk_isoc_handler; + urb->context = dev; + urb->start_frame = 0; + urb->number_of_packets = ISO_FRAMES_PER_DESC; + + for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { + urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; + urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; + } + } + set_memallocd(dev); + return 0; + +isobufs_out: + for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].data; i++) + kfree(dev->isobufs[i].data); + for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].urb; i++) + usb_free_urb(dev->isobufs[i].urb); + kfree(dev->isobufs); + dev->isobufs = NULL; + return -ENOMEM; +} + +static void stk_clean_iso(struct stk_camera *dev) +{ + int i; + + if (dev == NULL || dev->isobufs == NULL) + return; + + for (i = 0; i < MAX_ISO_BUFS; i++) { + struct urb *urb; + + urb = dev->isobufs[i].urb; + if (urb) { + if (atomic_read(&dev->urbs_used)) + usb_kill_urb(urb); + usb_free_urb(urb); + } + kfree(dev->isobufs[i].data); + } + kfree(dev->isobufs); + dev->isobufs = NULL; + unset_memallocd(dev); +} + +static int stk_setup_siobuf(struct stk_camera *dev, int index) +{ + struct stk_sio_buffer *buf = dev->sio_bufs + index; + INIT_LIST_HEAD(&buf->list); + buf->v4lbuf.length = PAGE_ALIGN(dev->frame_size); + buf->buffer = vmalloc_user(buf->v4lbuf.length); + if (buf->buffer == NULL) + return -ENOMEM; + buf->mapcount = 0; + buf->dev = dev; + buf->v4lbuf.index = index; + buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf->v4lbuf.field = V4L2_FIELD_NONE; + buf->v4lbuf.memory = V4L2_MEMORY_MMAP; + buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length; + return 0; +} + +static int stk_free_sio_buffers(struct stk_camera *dev) +{ + int i; + int nbufs; + unsigned long flags; + if (dev->n_sbufs == 0 || dev->sio_bufs == NULL) + return 0; + /* + * If any buffers are mapped, we cannot free them at all. + */ + for (i = 0; i < dev->n_sbufs; i++) { + if (dev->sio_bufs[i].mapcount > 0) + return -EBUSY; + } + /* + * OK, let's do it. + */ + spin_lock_irqsave(&dev->spinlock, flags); + INIT_LIST_HEAD(&dev->sio_avail); + INIT_LIST_HEAD(&dev->sio_full); + nbufs = dev->n_sbufs; + dev->n_sbufs = 0; + spin_unlock_irqrestore(&dev->spinlock, flags); + for (i = 0; i < nbufs; i++) { + if (dev->sio_bufs[i].buffer != NULL) + vfree(dev->sio_bufs[i].buffer); + } + kfree(dev->sio_bufs); + dev->sio_bufs = NULL; + return 0; +} + +static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs) +{ + int i; + if (dev->sio_bufs != NULL) + STK_ERROR("sio_bufs already allocated\n"); + else { + dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer), + GFP_KERNEL); + if (dev->sio_bufs == NULL) + return -ENOMEM; + for (i = 0; i < n_sbufs; i++) { + if (stk_setup_siobuf(dev, i)) + return (dev->n_sbufs > 1)? 0 : -ENOMEM; + dev->n_sbufs = i+1; + } + } + return 0; +} + +static int stk_allocate_buffers(struct stk_camera *dev, unsigned n_sbufs) +{ + int err; + err = stk_prepare_iso(dev); + if (err) { + stk_clean_iso(dev); + return err; + } + err = stk_prepare_sio_buffers(dev, n_sbufs); + if (err) { + stk_free_sio_buffers(dev); + return err; + } + return 0; +} + +static void stk_free_buffers(struct stk_camera *dev) +{ + stk_clean_iso(dev); + stk_free_sio_buffers(dev); +} +/* -------------------------------------------- */ + +/* v4l file operations */ + +static int v4l_stk_open(struct inode *inode, struct file *fp) +{ + struct stk_camera *dev; + struct video_device *vdev; + + vdev = video_devdata(fp); + dev = vdev_to_camera(vdev); + + if (dev == NULL || !is_present(dev)) + return -ENXIO; + fp->private_data = vdev; + kref_get(&dev->kref); + + return 0; +} + +static int v4l_stk_release(struct inode *inode, struct file *fp) +{ + struct stk_camera *dev; + struct video_device *vdev; + + vdev = video_devdata(fp); + if (vdev == NULL) { + STK_ERROR("v4l_release called w/o video devdata\n"); + return -EFAULT; + } + dev = vdev_to_camera(vdev); + if (dev == NULL) { + STK_ERROR("v4l_release called on removed device\n"); + return -ENODEV; + } + + if (dev->owner != fp) { + kref_put(&dev->kref, stk_camera_cleanup); + return 0; + } + + stk_stop_stream(dev); + + stk_free_buffers(dev); + + dev->owner = NULL; + + kref_put(&dev->kref, stk_camera_cleanup); + + return 0; +} + +static ssize_t v4l_stk_read(struct file *fp, char __user *buf, + size_t count, loff_t *f_pos) +{ + int i; + int ret; + unsigned long flags; + struct stk_camera *dev; + struct video_device *vdev; + struct stk_sio_buffer *sbuf; + + vdev = video_devdata(fp); + if (vdev == NULL) + return -EFAULT; + dev = vdev_to_camera(vdev); + + if (dev == NULL) + return -EIO; + + if (!is_present(dev)) + return -EIO; + if (dev->owner && dev->owner != fp) + return -EBUSY; + dev->owner = fp; + if (!is_streaming(dev)) { + if (stk_initialise(dev) + || stk_allocate_buffers(dev, 3) + || stk_start_stream(dev)) + return -ENOMEM; + spin_lock_irqsave(&dev->spinlock, flags); + for (i = 0; i < dev->n_sbufs; i++) { + list_add_tail(&dev->sio_bufs[i].list, &dev->sio_avail); + dev->sio_bufs[i].v4lbuf.flags = V4L2_BUF_FLAG_QUEUED; + } + spin_unlock_irqrestore(&dev->spinlock, flags); + } + if (*f_pos == 0) { + if (fp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) + return -EWOULDBLOCK; + ret = wait_event_interruptible(dev->wait_frame, + !list_empty(&dev->sio_full) || !is_present(dev)); + if (ret) + return ret; + if (!is_present(dev)) + return -EIO; + } + if (count + *f_pos > dev->frame_size) + count = dev->frame_size - *f_pos; + spin_lock_irqsave(&dev->spinlock, flags); + if (list_empty(&dev->sio_full)) { + spin_unlock_irqrestore(&dev->spinlock, flags); + STK_ERROR("BUG: No siobufs ready\n"); + return 0; + } + sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list); + spin_unlock_irqrestore(&dev->spinlock, flags); + + if (copy_to_user(buf, sbuf->buffer + *f_pos, count)) + return -EFAULT; + + *f_pos += count; + + if (*f_pos >= dev->frame_size) { + *f_pos = 0; + spin_lock_irqsave(&dev->spinlock, flags); + list_move_tail(&sbuf->list, &dev->sio_avail); + spin_unlock_irqrestore(&dev->spinlock, flags); + } + return count; +} + +static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) +{ + struct stk_camera *dev; + struct video_device *vdev; + + vdev = video_devdata(fp); + + if (vdev == NULL) + return -EFAULT; + + dev = vdev_to_camera(vdev); + if (dev == NULL) + return -ENODEV; + + poll_wait(fp, &dev->wait_frame, wait); + + if (!is_present(dev)) + return POLLERR; + + if (!list_empty(&dev->sio_full)) + return (POLLIN | POLLRDNORM); + + return 0; +} + + +static void stk_v4l_vm_open(struct vm_area_struct *vma) +{ + struct stk_sio_buffer *sbuf = vma->vm_private_data; + sbuf->mapcount++; +} +static void stk_v4l_vm_close(struct vm_area_struct *vma) +{ + struct stk_sio_buffer *sbuf = vma->vm_private_data; + sbuf->mapcount--; + if (sbuf->mapcount == 0) + sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED; +} +static struct vm_operations_struct stk_v4l_vm_ops = { + .open = stk_v4l_vm_open, + .close = stk_v4l_vm_close +}; + +static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) +{ + unsigned int i; + int ret; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + struct stk_camera *dev; + struct video_device *vdev; + struct stk_sio_buffer *sbuf = NULL; + + if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + vdev = video_devdata(fp); + dev = vdev_to_camera(vdev); + + for (i = 0; i < dev->n_sbufs; i++) { + if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { + sbuf = dev->sio_bufs + i; + break; + } + } + if (sbuf == NULL) + return -EINVAL; + ret = remap_vmalloc_range(vma, sbuf->buffer, 0); + if (ret) + return ret; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_private_data = sbuf; + vma->vm_ops = &stk_v4l_vm_ops; + sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED; + stk_v4l_vm_open(vma); + return 0; +} + +/* v4l ioctl handlers */ + +static int stk_vidioc_querycap(struct file *filp, + void *priv, struct v4l2_capability *cap) +{ + strcpy(cap->driver, "stk"); + strcpy(cap->card, "stk"); + cap->version = DRIVER_VERSION_NUM; + + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE + | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + return 0; +} + +static int stk_vidioc_enum_input(struct file *filp, + void *priv, struct v4l2_input *input) +{ + if (input->index != 0) + return -EINVAL; + + strcpy(input->name, "Syntek USB Camera"); + input->type = V4L2_INPUT_TYPE_CAMERA; + return 0; +} + + +static int stk_vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int stk_vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + else + return 0; +} + +/* from vivi.c */ +static int stk_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a) +{ + return 0; +} + +/* List of all V4Lv2 controls supported by the driver */ +static struct v4l2_queryctrl stk_controls[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 0xffff, + .step = 0x0100, + .default_value = 0x6000, + }, + /*TODO: get more controls to work */ +}; + +static int stk_vidioc_queryctrl(struct file *filp, + void *priv, struct v4l2_queryctrl *c) +{ + int i; + int nbr; + nbr = ARRAY_SIZE(stk_controls); + + for (i = 0; i < nbr; i++) { + if (stk_controls[i].id == c->id) { + memcpy(c, &stk_controls[i], + sizeof(struct v4l2_queryctrl)); + return 0; + } + } + return -EINVAL; +} + +static int stk_vidioc_g_ctrl(struct file *filp, + void *priv, struct v4l2_control *c) +{ + struct stk_camera *dev = priv; + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + c->value = dev->vsettings.brightness; + break; + default: + return -EINVAL; + } + return 0; +} + +static int stk_vidioc_s_ctrl(struct file *filp, + void *priv, struct v4l2_control *c) +{ + struct stk_camera *dev = priv; + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + dev->vsettings.brightness = c->value; + return stk_sensor_set_brightness(dev, c->value >> 8); + default: + return -EINVAL; + } + return 0; +} + + +static int stk_vidioc_enum_fmt_cap(struct file *filp, + void *priv, struct v4l2_fmtdesc *fmtd) +{ + fmtd->flags = 0; + + switch (fmtd->index) { + case 0: + fmtd->pixelformat = V4L2_PIX_FMT_RGB565; + strcpy(fmtd->description, "r5g6b5"); + break; + case 1: + fmtd->pixelformat = V4L2_PIX_FMT_RGB565X; + strcpy(fmtd->description, "r5g6b5BE"); + break; + case 2: + fmtd->pixelformat = V4L2_PIX_FMT_UYVY; + strcpy(fmtd->description, "yuv4:2:2"); + break; + case 3: + fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8; + strcpy(fmtd->description, "Raw bayer"); + break; + default: + return -EINVAL; + } + return 0; +} + +static struct stk_size { + unsigned w; + unsigned h; + enum stk_mode m; +} stk_sizes[] = { + { .w = 1280, .h = 1024, .m = MODE_SXGA, }, + { .w = 640, .h = 480, .m = MODE_VGA, }, + { .w = 352, .h = 288, .m = MODE_CIF, }, + { .w = 320, .h = 240, .m = MODE_QVGA, }, + { .w = 176, .h = 144, .m = MODE_QCIF, }, +}; + +static int stk_vidioc_g_fmt_cap(struct file *filp, + void *priv, struct v4l2_format *f) +{ + struct v4l2_pix_format *pix_format = &f->fmt.pix; + struct stk_camera *dev = priv; + int i; + + for (i = 0; i < ARRAY_SIZE(stk_sizes) + && stk_sizes[i].m != dev->vsettings.mode; + i++); + if (i == ARRAY_SIZE(stk_sizes)) { + STK_ERROR("ERROR: mode invalid\n"); + return -EINVAL; + } + pix_format->width = stk_sizes[i].w; + pix_format->height = stk_sizes[i].h; + pix_format->field = V4L2_FIELD_NONE; + pix_format->colorspace = V4L2_COLORSPACE_SRGB; + pix_format->priv = 0; + pix_format->pixelformat = dev->vsettings.palette; + if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) + pix_format->bytesperline = pix_format->width; + else + pix_format->bytesperline = 2 * pix_format->width; + pix_format->sizeimage = pix_format->bytesperline + * pix_format->height; + return 0; +} + +static int stk_vidioc_try_fmt_cap(struct file *filp, + void *priv, struct v4l2_format *fmtd) +{ + int i; + switch (fmtd->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_SBGGR8: + break; + default: + return -EINVAL; + } + for (i = 1; i < ARRAY_SIZE(stk_sizes); i++) { + if (fmtd->fmt.pix.width > stk_sizes[i].w) + break; + } + if (i == ARRAY_SIZE(stk_sizes) + || (abs(fmtd->fmt.pix.width - stk_sizes[i-1].w) + < abs(fmtd->fmt.pix.width - stk_sizes[i].w))) { + fmtd->fmt.pix.height = stk_sizes[i-1].h; + fmtd->fmt.pix.width = stk_sizes[i-1].w; + fmtd->fmt.pix.priv = i - 1; + } else { + fmtd->fmt.pix.height = stk_sizes[i].h; + fmtd->fmt.pix.width = stk_sizes[i].w; + fmtd->fmt.pix.priv = i; + } + + fmtd->fmt.pix.field = V4L2_FIELD_NONE; + fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + if (fmtd->fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8) + fmtd->fmt.pix.bytesperline = fmtd->fmt.pix.width; + else + fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width; + fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline + * fmtd->fmt.pix.height; + return 0; +} + +static int stk_vidioc_s_fmt_cap(struct file *filp, + void *priv, struct v4l2_format *fmtd) +{ + int ret; + struct stk_camera *dev = priv; + + if (dev == NULL) + return -ENODEV; + if (!is_present(dev)) + return -ENODEV; + if (is_streaming(dev)) + return -EBUSY; + if (dev->owner && dev->owner != filp) + return -EBUSY; + dev->owner = filp; + ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd); + if (ret) + return ret; + + dev->vsettings.palette = fmtd->fmt.pix.pixelformat; + stk_free_buffers(dev); + dev->frame_size = fmtd->fmt.pix.sizeimage; + dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m; + + stk_initialise(dev); + /* This registers controls some timings, not sure of what. */ + stk_camera_write_reg(dev, 0x001b, 0x0e); + if (dev->vsettings.mode == MODE_SXGA) + stk_camera_write_reg(dev, 0x001c, 0x0e); + else + stk_camera_write_reg(dev, 0x001c, 0x46); + /* + * Registers 0x0115 0x0114 are the size of each line (bytes), + * regs 0x0117 0x0116 are the heigth of the image. + */ + stk_camera_write_reg(dev, 0x0115, + (fmtd->fmt.pix.bytesperline >> 8) & 0xff); + stk_camera_write_reg(dev, 0x0114, + fmtd->fmt.pix.bytesperline & 0xff); + stk_camera_write_reg(dev, 0x0117, + (fmtd->fmt.pix.height >> 8) & 0xff); + stk_camera_write_reg(dev, 0x0116, + fmtd->fmt.pix.height & 0xff); + return stk_sensor_configure(dev); +} + +static int stk_vidioc_reqbufs(struct file *filp, + void *priv, struct v4l2_requestbuffers *rb) +{ + struct stk_camera *dev = priv; + + if (dev == NULL) + return -ENODEV; + if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (rb->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + if (is_streaming(dev) + || (dev->owner && dev->owner != filp)) + return -EBUSY; + dev->owner = filp; + + /*FIXME If they ask for zero, we must stop streaming and free */ + if (rb->count < 3) + rb->count = 3; + /* Arbitrary limit */ + else if (rb->count > 5) + rb->count = 5; + + stk_allocate_buffers(dev, rb->count); + rb->count = dev->n_sbufs; + return 0; +} + +static int stk_vidioc_querybuf(struct file *filp, + void *priv, struct v4l2_buffer *buf) +{ + int index; + struct stk_camera *dev = priv; + struct stk_sio_buffer *sbuf; + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + index = buf->index; + + if (index < 0 || index >= dev->n_sbufs) + return -EINVAL; + sbuf = dev->sio_bufs + buf->index; + *buf = sbuf->v4lbuf; + return 0; +} + +static int stk_vidioc_qbuf(struct file *filp, + void *priv, struct v4l2_buffer *buf) +{ + struct stk_camera *dev = priv; + struct stk_sio_buffer *sbuf; + unsigned long flags; + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (buf->index < 0 || buf->index >= dev->n_sbufs) + return -EINVAL; + sbuf = dev->sio_bufs + buf->index; + if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) + return 0; + sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED; + sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE; + spin_lock_irqsave(&dev->spinlock, flags); + list_add_tail(&sbuf->list, &dev->sio_avail); + *buf = sbuf->v4lbuf; + spin_unlock_irqrestore(&dev->spinlock, flags); + return 0; +} + +static int stk_vidioc_dqbuf(struct file *filp, + void *priv, struct v4l2_buffer *buf) +{ + struct stk_camera *dev = priv; + struct stk_sio_buffer *sbuf; + unsigned long flags; + int ret; + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE + || !is_streaming(dev)) + return -EINVAL; + + if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) + return -EWOULDBLOCK; + ret = wait_event_interruptible(dev->wait_frame, + !list_empty(&dev->sio_full) || !is_present(dev)); + if (ret) + return ret; + if (!is_present(dev)) + return -EIO; + + spin_lock_irqsave(&dev->spinlock, flags); + sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list); + list_del_init(&sbuf->list); + spin_unlock_irqrestore(&dev->spinlock, flags); + sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED; + sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE; + sbuf->v4lbuf.sequence = ++dev->sequence; + do_gettimeofday(&sbuf->v4lbuf.timestamp); + + *buf = sbuf->v4lbuf; + return 0; +} + +static int stk_vidioc_streamon(struct file *filp, + void *priv, enum v4l2_buf_type type) +{ + struct stk_camera *dev = priv; + if (is_streaming(dev)) + return 0; + if (dev->sio_bufs == NULL) + return -EINVAL; + dev->sequence = 0; + return stk_start_stream(dev); +} + +static int stk_vidioc_streamoff(struct file *filp, + void *priv, enum v4l2_buf_type type) +{ + struct stk_camera *dev = priv; + unsigned long flags; + int i; + stk_stop_stream(dev); + spin_lock_irqsave(&dev->spinlock, flags); + INIT_LIST_HEAD(&dev->sio_avail); + INIT_LIST_HEAD(&dev->sio_full); + for (i = 0; i < dev->n_sbufs; i++) { + INIT_LIST_HEAD(&dev->sio_bufs[i].list); + dev->sio_bufs[i].v4lbuf.flags = 0; + } + spin_unlock_irqrestore(&dev->spinlock, flags); + return 0; +} + + +static int stk_vidioc_g_parm(struct file *filp, + void *priv, struct v4l2_streamparm *sp) +{ + if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp->parm.capture.capability = 0; + sp->parm.capture.capturemode = 0; + /*FIXME This is not correct */ + sp->parm.capture.timeperframe.numerator = 1; + sp->parm.capture.timeperframe.denominator = 30; + sp->parm.capture.readbuffers = 2; + sp->parm.capture.extendedmode = 0; + return 0; +} + +static struct file_operations v4l_stk_fops = { + .owner = THIS_MODULE, + .open = v4l_stk_open, + .release = v4l_stk_release, + .read = v4l_stk_read, + .poll = v4l_stk_poll, + .mmap = v4l_stk_mmap, + .ioctl = video_ioctl2, + .llseek = no_llseek +}; + +static void stk_v4l_dev_release(struct video_device *vd) +{ +} + +static struct video_device stk_v4l_data = { + .name = "stkwebcam", + .type = VFL_TYPE_GRABBER, + .type2 = VID_TYPE_CAPTURE, + .minor = -1, + .tvnorms = V4L2_STD_UNKNOWN, + .current_norm = V4L2_STD_UNKNOWN, + .fops = &v4l_stk_fops, + .release = stk_v4l_dev_release, + + .vidioc_querycap = stk_vidioc_querycap, + .vidioc_enum_fmt_cap = stk_vidioc_enum_fmt_cap, + .vidioc_try_fmt_cap = stk_vidioc_try_fmt_cap, + .vidioc_s_fmt_cap = stk_vidioc_s_fmt_cap, + .vidioc_g_fmt_cap = stk_vidioc_g_fmt_cap, + .vidioc_enum_input = stk_vidioc_enum_input, + .vidioc_s_input = stk_vidioc_s_input, + .vidioc_g_input = stk_vidioc_g_input, + .vidioc_s_std = stk_vidioc_s_std, + .vidioc_reqbufs = stk_vidioc_reqbufs, + .vidioc_querybuf = stk_vidioc_querybuf, + .vidioc_qbuf = stk_vidioc_qbuf, + .vidioc_dqbuf = stk_vidioc_dqbuf, + .vidioc_streamon = stk_vidioc_streamon, + .vidioc_streamoff = stk_vidioc_streamoff, + .vidioc_queryctrl = stk_vidioc_queryctrl, + .vidioc_g_ctrl = stk_vidioc_g_ctrl, + .vidioc_s_ctrl = stk_vidioc_s_ctrl, + .vidioc_g_parm = stk_vidioc_g_parm, +}; + + +static int stk_register_video_device(struct stk_camera *dev) +{ + int err; + + dev->vdev = stk_v4l_data; + dev->vdev.debug = debug; + dev->vdev.dev = &dev->interface->dev; + dev->vdev.priv = dev; + err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); + if (err) + STK_ERROR("v4l registration failed\n"); + else + STK_INFO("Syntek USB2.0 Camera is now controlling video device" + " /dev/video%d\n", dev->vdev.minor); + return err; +} + + +/* USB Stuff */ + +static int stk_camera_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + int i; + int err; + + struct stk_camera *dev = NULL; + struct usb_device *udev = interface_to_usbdev(interface); + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + + dev = kzalloc(sizeof(struct stk_camera), GFP_KERNEL); + if (dev == NULL) { + STK_ERROR("Out of memory !\n"); + return -ENOMEM; + } + + kref_init(&dev->kref); + spin_lock_init(&dev->spinlock); + init_waitqueue_head(&dev->wait_frame); + + dev->udev = udev; + dev->interface = interface; + usb_get_intf(interface); + + dev->vsettings.vflip = vflip; + dev->vsettings.hflip = hflip; + dev->n_sbufs = 0; + set_present(dev); + + /* Set up the endpoint information + * use only the first isoc-in endpoint + * for the current alternate setting */ + iface_desc = interface->cur_altsetting; + + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!dev->isoc_ep + && ((endpoint->bEndpointAddress + & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) + && ((endpoint->bmAttributes + & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) { + /* we found an isoc in endpoint */ + dev->isoc_ep = (endpoint->bEndpointAddress & 0xF); + break; + } + } + if (!dev->isoc_ep) { + STK_ERROR("Could not find isoc-in endpoint"); + kref_put(&dev->kref, stk_camera_cleanup); + return -ENODEV; + } + dev->vsettings.brightness = 0x7fff; + dev->vsettings.palette = V4L2_PIX_FMT_RGB565; + dev->vsettings.mode = MODE_VGA; + dev->frame_size = 640*480*2; + + INIT_LIST_HEAD(&dev->sio_avail); + INIT_LIST_HEAD(&dev->sio_full); + + usb_set_intfdata(interface, dev); + + err = stk_register_video_device(dev); + if (err) { + kref_put(&dev->kref, stk_camera_cleanup); + return err; + } + + stk_create_sysfs_files(&dev->vdev); + + return 0; +} + +static void stk_camera_disconnect(struct usb_interface *interface) +{ + struct stk_camera *dev = usb_get_intfdata(interface); + + usb_set_intfdata(interface, NULL); + unset_present(dev); + + wake_up_interruptible(&dev->wait_frame); + stk_remove_sysfs_files(&dev->vdev); + + kref_put(&dev->kref, stk_camera_cleanup); +} + +static struct usb_driver stk_camera_driver = { + .name = "stkwebcam", + .probe = stk_camera_probe, + .disconnect = stk_camera_disconnect, + .id_table = stkwebcam_table, +}; + + +static int __init stk_camera_init(void) +{ + int result; + + result = usb_register(&stk_camera_driver); + if (result) + STK_ERROR("usb_register failed ! Error number %d\n", result); + + + return result; +} + +static void __exit stk_camera_exit(void) +{ + usb_deregister(&stk_camera_driver); +} + +module_init(stk_camera_init); +module_exit(stk_camera_exit); + + diff --git a/linux/drivers/media/video/stk-webcam.h b/linux/drivers/media/video/stk-webcam.h new file mode 100644 index 000000000..7e989d1ac --- /dev/null +++ b/linux/drivers/media/video/stk-webcam.h @@ -0,0 +1,138 @@ +/* + * stk-webcam.h : Driver for Syntek 1125 USB webcam controller + * + * Copyright (C) 2006 Nicolas VIVIEN + * Copyright 2007-2008 Jaime Velasco Juan <jsagarribay@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef STKWEBCAM_H +#define STKWEBCAM_H + +#include <linux/usb.h> +#include <media/v4l2-common.h> + +#define DRIVER_VERSION "v0.0.1" +#define DRIVER_VERSION_NUM 0x000001 + +#define MAX_ISO_BUFS 3 +#define ISO_FRAMES_PER_DESC 16 +#define ISO_MAX_FRAME_SIZE 3 * 1024 +#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) + + +#define PREFIX "stkwebcam: " +#define STK_INFO(str, args...) printk(KERN_INFO PREFIX str, ##args) +#define STK_ERROR(str, args...) printk(KERN_ERR PREFIX str, ##args) +#define STK_WARNING(str, args...) printk(KERN_WARNING PREFIX str, ##args) + +struct stk_iso_buf { + void *data; + int length; + int read; + struct urb *urb; +}; + +/* Streaming IO buffers */ +struct stk_sio_buffer { + struct v4l2_buffer v4lbuf; + char *buffer; + int mapcount; + struct stk_camera *dev; + struct list_head list; +}; + +enum stk_mode {MODE_VGA, MODE_SXGA, MODE_CIF, MODE_QVGA, MODE_QCIF}; + +struct stk_video { + enum stk_mode mode; + int brightness; + __u32 palette; + int hflip; + int vflip; +}; + +enum stk_status { + S_PRESENT = 1, + S_INITIALISED = 2, + S_MEMALLOCD = 4, + S_STREAMING = 8, +}; +#define is_present(dev) ((dev)->status & S_PRESENT) +#define is_initialised(dev) ((dev)->status & S_INITIALISED) +#define is_streaming(dev) ((dev)->status & S_STREAMING) +#define is_memallocd(dev) ((dev)->status & S_MEMALLOCD) +#define set_present(dev) ((dev)->status = S_PRESENT) +#define unset_present(dev) ((dev)->status &= \ + ~(S_PRESENT|S_INITIALISED|S_STREAMING)) +#define set_initialised(dev) ((dev)->status |= S_INITIALISED) +#define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD) +#define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD) +#define set_streaming(dev) ((dev)->status |= S_STREAMING) +#define unset_streaming(dev) ((dev)->status &= ~S_STREAMING) + +struct regval { + unsigned reg; + unsigned val; +}; + +struct stk_camera { + struct video_device vdev; + struct usb_device *udev; + struct usb_interface *interface; + int webcam_model; + struct file *owner; + + u8 isoc_ep; + + struct kref kref; + /* Not sure if this is right */ + atomic_t urbs_used; + + struct stk_video vsettings; + + enum stk_status status; + + spinlock_t spinlock; + wait_queue_head_t wait_frame; + + struct stk_iso_buf *isobufs; + + int frame_size; + /* Streaming buffers */ + unsigned int n_sbufs; + struct stk_sio_buffer *sio_bufs; + struct list_head sio_avail; + struct list_head sio_full; + unsigned sequence; +}; + +#define to_stk_camera(d) container_of(d, struct stk_camera, kref) +#define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) + +void stk_camera_delete(struct kref *); +int stk_camera_write_reg(struct stk_camera *, u16, u8); +int stk_camera_read_reg(struct stk_camera *, u16, int *); + +int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val); +int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val); +int stk_sensor_init(struct stk_camera *); +int stk_sensor_configure(struct stk_camera *); +int stk_sensor_sleep(struct stk_camera *dev); +int stk_sensor_wakeup(struct stk_camera *dev); +int stk_sensor_set_brightness(struct stk_camera *dev, int br); + +#endif diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c index dbaf0ce8d..1700b97ea 100644 --- a/linux/drivers/media/video/tuner-xc2028.c +++ b/linux/drivers/media/video/tuner-xc2028.c @@ -678,7 +678,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, return rc; } - if (priv->ctrl.mts && ! (type & FM) ) + if (priv->ctrl.mts && !(type & FM)) type |= MTS; retry: diff --git a/linux/drivers/media/video/usbvision/usbvision-cards.c b/linux/drivers/media/video/usbvision/usbvision-cards.c index f09eb1027..503b13beb 100644 --- a/linux/drivers/media/video/usbvision/usbvision-cards.c +++ b/linux/drivers/media/video/usbvision/usbvision-cards.c @@ -901,6 +901,20 @@ struct usbvision_device_data_st usbvision_device_data[] = { .Y_Offset = -1, .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM", }, + [PINNA_PCTV_USB_NTSC_FM_V3] = { + .Interface = -1, + .Codec = CODEC_SAA7111, + .VideoChannels = 3, + .VideoNorm = V4L2_STD_NTSC, + .AudioChannels = 1, + .Radio = 1, + .vbi = 1, + .Tuner = 1, + .TunerType = TUNER_PHILIPS_NTSC_M, + .X_Offset = -1, + .Y_Offset = -1, + .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM V3", + }, [PINNA_PCTV_USB_PAL_FM_V2] = { .Interface = -1, .Codec = CODEC_SAA7113, @@ -1044,7 +1058,7 @@ struct usb_device_id usbvision_table [] = { { USB_DEVICE(0x0573, 0x4d2a), .driver_info=HPG_WINTV_PRO_NTSC_MN }, { USB_DEVICE(0x0573, 0x4d2b), .driver_info=HPG_WINTV_PRO_NTSC_MN_V2 }, { USB_DEVICE(0x0573, 0x4d2c), .driver_info=HPG_WINTV_PRO_PAL }, - { USB_DEVICE(0x0573, 0x4d20), .driver_info=HPG_WINTV_PRO_NTSC_MN_V3 }, + { USB_DEVICE(0x0573, 0x4d20), .driver_info = HPG_WINTV_PRO_NTSC_MN_V3 }, { USB_DEVICE(0x0573, 0x4d21), .driver_info=HPG_WINTV_PRO_PAL_BG }, { USB_DEVICE(0x0573, 0x4d22), .driver_info=HPG_WINTV_PRO_PAL_I }, { USB_DEVICE(0x0573, 0x4d23), .driver_info=HPG_WINTV_PRO_PAL_SECAM_L }, @@ -1074,6 +1088,8 @@ struct usb_device_id usbvision_table [] = { { USB_DEVICE(0x2304, 0x0110), .driver_info=PINNA_PCTV_USB_PAL_FM }, { USB_DEVICE(0x2304, 0x0111), .driver_info=MIRO_PCTV_USB }, { USB_DEVICE(0x2304, 0x0112), .driver_info=PINNA_PCTV_USB_NTSC_FM }, + { USB_DEVICE(0x2304, 0x0113), + .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, { USB_DEVICE(0x2304, 0x0210), .driver_info=PINNA_PCTV_USB_PAL_FM_V2 }, { USB_DEVICE(0x2304, 0x0212), .driver_info=PINNA_PCTV_USB_NTSC_FM_V2 }, { USB_DEVICE(0x2304, 0x0214), .driver_info=PINNA_PCTV_USB_PAL_FM_V3 }, diff --git a/linux/drivers/media/video/usbvision/usbvision-cards.h b/linux/drivers/media/video/usbvision/usbvision-cards.h index 512c5cee4..9c6ad2296 100644 --- a/linux/drivers/media/video/usbvision/usbvision-cards.h +++ b/linux/drivers/media/video/usbvision/usbvision-cards.h @@ -62,5 +62,6 @@ #define PINNA_LINX_VD_IN_CAB_PAL 61 #define PINNA_PCTV_BUNGEE_PAL_FM 62 #define HPG_WINTV 63 +#define PINNA_PCTV_USB_NTSC_FM_V3 64 extern const int usbvision_device_data_size; diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 96fcd5987..fd6f8667e 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -75,6 +75,15 @@ static int SwitchSVideoInput = 0; // To help people with Black and White outpu module_param(SwitchSVideoInput, int, 0444); MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); +static unsigned int adjust_X_Offset = -1; +module_param(adjust_X_Offset, int, 0644); +MODULE_PARM_DESC(adjust_X_Offset, "adjust X offset display [core]"); + +static unsigned int adjust_Y_Offset = -1; +module_param(adjust_Y_Offset, int, 0644); +MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); + + #define ENABLE_HEXDUMP 0 /* Enable if you need it */ @@ -663,25 +672,29 @@ static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); - *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = bv; - *f++ = gv; - *f++ = rv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = bv; - *f++ = gv; - *f++ = rv; - f++; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); - *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); - break; + case V4L2_PIX_FMT_RGB565: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x07 & (gv >> 3)) | + (0xF8 & bv); + break; + case V4L2_PIX_FMT_RGB24: + *f++ = rv; + *f++ = gv; + *f++ = bv; + break; + case V4L2_PIX_FMT_RGB32: + *f++ = rv; + *f++ = gv; + *f++ = bv; + f++; + break; + case V4L2_PIX_FMT_RGB555: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x03 & (gv >> 3)) | + (0x7C & (bv << 2)); + break; } } clipmask_index += clipmask_add; @@ -695,25 +708,29 @@ static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); - *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = bv; - *f++ = gv; - *f++ = rv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = bv; - *f++ = gv; - *f++ = rv; - f++; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); - *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); - break; + case V4L2_PIX_FMT_RGB565: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x07 & (gv >> 3)) | + (0xF8 & bv); + break; + case V4L2_PIX_FMT_RGB24: + *f++ = rv; + *f++ = gv; + *f++ = bv; + break; + case V4L2_PIX_FMT_RGB32: + *f++ = rv; + *f++ = gv; + *f++ = bv; + f++; + break; + case V4L2_PIX_FMT_RGB555: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x03 & (gv >> 3)) | + (0x7C & (bv << 2)); + break; } } clipmask_index += clipmask_add; @@ -981,22 +998,26 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, *f++ = Y[Idx]; break; case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2)); - *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1)); + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x03 & (gv >> 3)) | + (0x7C & (bv << 2)); break; case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3)); - *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv); + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x07 & (gv >> 3)) | + (0xF8 & bv); break; case V4L2_PIX_FMT_RGB24: - *f++ = bv; - *f++ = gv; *f++ = rv; + *f++ = gv; + *f++ = bv; break; case V4L2_PIX_FMT_RGB32: - *f++ = bv; - *f++ = gv; *f++ = rv; + *f++ = gv; + *f++ = bv; f++; break; } @@ -1110,28 +1131,33 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - f_even++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_even++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; + case V4L2_PIX_FMT_RGB565: + g = LIMIT_RGB(g_); + *f_even++ = + (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_even++ = + (0x07 & (g >> 3)) | + (0xF8 & LIMIT_RGB(b_)); + break; + case V4L2_PIX_FMT_RGB24: + *f_even++ = LIMIT_RGB(r_); + *f_even++ = LIMIT_RGB(g_); + *f_even++ = LIMIT_RGB(b_); + break; + case V4L2_PIX_FMT_RGB32: + *f_even++ = LIMIT_RGB(r_); + *f_even++ = LIMIT_RGB(g_); + *f_even++ = LIMIT_RGB(b_); + f_even++; + break; + case V4L2_PIX_FMT_RGB555: + g = LIMIT_RGB(g_); + *f_even++ = (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_even++ = (0x03 & (g >> 3)) | + (0x7C & (LIMIT_RGB(b_) << 2)); + break; } } clipmask_even_index += clipmask_add; @@ -1149,28 +1175,33 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_even++ = LIMIT_RGB(b_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(r_); - f_even++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_even++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; + case V4L2_PIX_FMT_RGB565: + g = LIMIT_RGB(g_); + *f_even++ = + (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_even++ = + (0x07 & (g >> 3)) | + (0xF8 & LIMIT_RGB(b_)); + break; + case V4L2_PIX_FMT_RGB24: + *f_even++ = LIMIT_RGB(r_); + *f_even++ = LIMIT_RGB(g_); + *f_even++ = LIMIT_RGB(b_); + break; + case V4L2_PIX_FMT_RGB32: + *f_even++ = LIMIT_RGB(r_); + *f_even++ = LIMIT_RGB(g_); + *f_even++ = LIMIT_RGB(b_); + f_even++; + break; + case V4L2_PIX_FMT_RGB555: + g = LIMIT_RGB(g_); + *f_even++ = (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_even++ = (0x03 & (g >> 3)) | + (0x7C & (LIMIT_RGB(b_) << 2)); + break; } } clipmask_even_index += clipmask_add; @@ -1190,28 +1221,33 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - f_odd++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_odd++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; + case V4L2_PIX_FMT_RGB565: + g = LIMIT_RGB(g_); + *f_odd++ = + (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_odd++ = + (0x07 & (g >> 3)) | + (0xF8 & LIMIT_RGB(b_)); + break; + case V4L2_PIX_FMT_RGB24: + *f_odd++ = LIMIT_RGB(r_); + *f_odd++ = LIMIT_RGB(g_); + *f_odd++ = LIMIT_RGB(b_); + break; + case V4L2_PIX_FMT_RGB32: + *f_odd++ = LIMIT_RGB(r_); + *f_odd++ = LIMIT_RGB(g_); + *f_odd++ = LIMIT_RGB(b_); + f_odd++; + break; + case V4L2_PIX_FMT_RGB555: + g = LIMIT_RGB(g_); + *f_odd++ = (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_odd++ = (0x03 & (g >> 3)) | + (0x7C & (LIMIT_RGB(b_) << 2)); + break; } } clipmask_odd_index += clipmask_add; @@ -1229,28 +1265,33 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3)); - *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - break; - case V4L2_PIX_FMT_RGB32: - *f_odd++ = LIMIT_RGB(b_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(r_); - f_odd++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2)); - *f_odd++ = (0x03 & ( g >> 6)) | - (0x7C & (LIMIT_RGB(r_) >> 1)); - break; + case V4L2_PIX_FMT_RGB565: + g = LIMIT_RGB(g_); + *f_odd++ = + (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_odd++ = + (0x07 & (g >> 3)) | + (0xF8 & LIMIT_RGB(b_)); + break; + case V4L2_PIX_FMT_RGB24: + *f_odd++ = LIMIT_RGB(r_); + *f_odd++ = LIMIT_RGB(g_); + *f_odd++ = LIMIT_RGB(b_); + break; + case V4L2_PIX_FMT_RGB32: + *f_odd++ = LIMIT_RGB(r_); + *f_odd++ = LIMIT_RGB(g_); + *f_odd++ = LIMIT_RGB(b_); + f_odd++; + break; + case V4L2_PIX_FMT_RGB555: + g = LIMIT_RGB(g_); + *f_odd++ = (0x1F & LIMIT_RGB(r_)) | + (0xE0 & (g << 5)); + *f_odd++ = (0x03 & (g >> 3)) | + (0x7C & (LIMIT_RGB(b_) << 2)); + break; } } clipmask_odd_index += clipmask_add; @@ -2159,11 +2200,21 @@ int usbvision_set_input(struct usb_usbvision *usbvision) value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; } + if (adjust_X_Offset != -1) { + value[4] = adjust_X_Offset & 0xff; + value[5] = (adjust_X_Offset & 0x0300) >> 8; + } + if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; } + if (adjust_Y_Offset != -1) { + value[6] = adjust_Y_Offset & 0xff; + value[7] = (adjust_Y_Offset & 0x0300) >> 8; + } + rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, /* USBVISION specific code */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.h b/linux/drivers/media/video/usbvision/usbvision-i2c.h deleted file mode 100644 index e69de29bb..000000000 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.h +++ /dev/null diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index 1f6f20f46..cf5033b68 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -99,13 +99,19 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, MAGIC_CHECK(vb->magic, MAGIC_BUFFER); MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - /* FIXME: This is required to avoid OOPS on some cases, + /* This is required to avoid OOPS on some cases, since mmap_mapper() method should be called before _iolock. On some cases, the mmap_mapper() is called only after scheduling. - - However, this way is just too dirty! Better to wait for some event. */ - schedule_timeout(HZ); + if (vb->memory == V4L2_MEMORY_MMAP) { + wait_event_timeout(vb->done, q->is_mmapped, + msecs_to_jiffies(100)); + if (!q->is_mmapped) { + printk(KERN_ERR + "Error: mmap_mapper() never called!\n"); + return -EINVAL; + } + } return CALL(q, iolock, q, vb, fbuf); } @@ -301,7 +307,11 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); + rc = CALL(q, mmap_free, q); + + q->is_mmapped = 0; + if (rc < 0) return rc; @@ -1023,6 +1033,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, mutex_lock(&q->lock); retval = CALL(q, mmap_mapper, q, vma); + q->is_mmapped = 1; mutex_unlock(&q->lock); return retval; diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 0305589d1..4222abbfc 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -190,7 +190,8 @@ struct vivi_dev { struct vivi_dmaqueue vidq; /* Several counters */ - int h, m, s, us, jiffies; + int h, m, s, ms; + unsigned long jiffies; char timestr[13]; int mv_count; /* Controls bars movement */ @@ -365,10 +366,10 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) /* Updates stream time */ - dev->us += jiffies_to_usecs(jiffies-dev->jiffies); + dev->ms += jiffies_to_msecs(jiffies-dev->jiffies); dev->jiffies = jiffies; - if (dev->us >= 1000000) { - dev->us -= 1000000; + if (dev->ms >= 1000) { + dev->ms -= 1000; dev->s++; if (dev->s >= 60) { dev->s -= 60; @@ -382,7 +383,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) } } sprintf(dev->timestr, "%02d:%02d:%02d:%03d", - dev->h, dev->m, dev->s, (dev->us + 500) / 1000); + dev->h, dev->m, dev->s, dev->ms); dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n", dev->timestr, (unsigned long)tmpbuf, pos); @@ -1147,11 +1148,11 @@ found: dev->h = 0; dev->m = 0; dev->s = 0; - dev->us = 0; + dev->ms = 0; dev->mv_count = 0; dev->jiffies = jiffies; sprintf(dev->timestr, "%02d:%02d:%02d:%03d", - dev->h, dev->m, dev->s, (dev->us + 500) / 1000); + dev->h, dev->m, dev->s, dev->ms); videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops, NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, diff --git a/linux/drivers/media/video/xc3028.c b/linux/drivers/media/video/xc3028.c deleted file mode 100644 index a2d5df4c0..000000000 --- a/linux/drivers/media/video/xc3028.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - - 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("xc3028: 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[4]; - freq<<=2; - chanbuf[0]=0; - chanbuf[1]=0; - chanbuf[2]=(freq&0xff00)>>8; - chanbuf[3]=freq&0x00ff; - 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); - struct em28xx *dev; - const struct firmware *fw = NULL; - size_t firmware_size; - int ret=-1; - int i=0; - int d=0; - int txtlen; - long fwoff; - u8 *firmware; - u8 linebuffer[100]; - char *fwoffset; - - /* - 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("xc3028: firmware offset doesn't match!\n"); - release_firmware(fw); - return(-1); - } - - 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); - dev->em28xx_write_regs(dev, 0x08, "\x7d", 1); - - /* - 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)){ - 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); - /* at least 100 ms delay here, if less terratec FW won't work */ - msleep(100); - /* another reset here */ - dev->em28xx_write_regs(dev, 0x08, "\x6d", 1); - dev->em28xx_write_regs(dev, 0x08, "\x7d", 1); - - } - linebuffer[0]=0x2a; - d=1; - } - i++; - } - printk("xc3024: Firmware uploaded\n"); - release_firmware(fw); - - /* MAGIC VALUES Hauppauge */ - 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 - /* MAGIC Values Terratec - dvb init*/ - i2c_master_send(c,"\x13\x39",0x02); - 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",0x02); - i2c_master_send(c,"\x10\x13",0x02); - i2c_master_send(c,"\x16\x12",0x02); - i2c_master_send(c,"\x1f\x02",0x02); - i2c_master_send(c,"\x21\x02",0x02); - i2c_master_send(c,"\x01\x02",0x02); - i2c_master_send(c,"\x2b\x10",0x02); - i2c_master_send(c,"\x02\x02",0x02); - i2c_master_send(c,"\x02\x03",0x02); - i2c_master_send(c,"\x00\x8c",0x02); -#endif -#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); - 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 */ - /* codeblock hauppauge/terratec - analog */ - 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); /* just wonder no sleep here regarding the logs */ - 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: - */ diff --git a/linux/include/media/cx25840.h b/linux/include/media/cx25840.h index 8e7e52d65..cd599ad29 100644 --- a/linux/include/media/cx25840.h +++ b/linux/include/media/cx25840.h @@ -49,6 +49,25 @@ enum cx25840_video_input { CX25840_SVIDEO2 = 0x620, CX25840_SVIDEO3 = 0x730, CX25840_SVIDEO4 = 0x840, + + /* Allow frames to specify specific input configurations */ + CX25840_VIN1_CH1 = 0x80000000, + CX25840_VIN2_CH1 = 0x80000001, + CX25840_VIN3_CH1 = 0x80000002, + CX25840_VIN4_CH1 = 0x80000003, + CX25840_VIN5_CH1 = 0x80000004, + CX25840_VIN6_CH1 = 0x80000005, + CX25840_VIN7_CH1 = 0x80000006, + CX25840_VIN8_CH1 = 0x80000007, + CX25840_VIN4_CH2 = 0x80000000, + CX25840_VIN5_CH2 = 0x80000010, + CX25840_VIN6_CH2 = 0x80000020, + CX25840_NONE_CH2 = 0x80000030, + CX25840_VIN7_CH3 = 0x80000000, + CX25840_VIN8_CH3 = 0x80000040, + CX25840_NONE0_CH3 = 0x80000080, + CX25840_NONE1_CH3 = 0x800000c0, + CX25840_SVIDEO_ON = 0x80000100, }; enum cx25840_audio_input { diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h index b904d3257..9c2fc09a7 100644 --- a/linux/include/media/ir-common.h +++ b/linux/include/media/ir-common.h @@ -140,6 +140,7 @@ extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; #endif diff --git a/linux/include/media/videobuf-core.h b/linux/include/media/videobuf-core.h index dea9c53fe..9bb244716 100644 --- a/linux/include/media/videobuf-core.h +++ b/linux/include/media/videobuf-core.h @@ -168,6 +168,8 @@ struct videobuf_queue { unsigned int streaming:1; unsigned int reading:1; + unsigned int is_mmapped:1; + /* capture via mmap() + ioctl(QBUF/DQBUF) */ struct list_head stream; diff --git a/mailimport b/mailimport index 6895fc32d..b13f4c662 100755 --- a/mailimport +++ b/mailimport @@ -18,32 +18,8 @@ head=v4l/scripts/hghead.pl -if [ "$1" == "" ]; then - echo "Usage: $0 <mbox>" - exit -fi -MBOX=$1 - -if [ "$TMPDIR" == "" ]; then - TMPDIR=/tmp -fi - -if [ "$EDITOR" == "" ]; then - EDITOR="nano -w" -fi - -if [ "$CHECKPATCH" == "" ]; then - CHECKPATCH="/lib/modules/`uname -r`/build/scripts/checkpatch.pl" -fi - -DIR=$TMPDIR/mailimport$$ -mkdir $DIR -if [ "$?" != "0" ]; then - echo "*** Error at mkdir $DIR" - exit; -fi -trap "rm -rf $DIR" EXIT -TMP2=$DIR/patchheader +#################################################################### +# Tries to apply a patch at the tree apply_patch () { next=$1 @@ -134,13 +110,12 @@ apply_patch () { fi # Commit the changed files - CARDLIST="`hg status -n -m|grep ^CARDLIST. |cut -b 3-`" + CARDLIST="`hg status -n -m|grep CARDLIST.`" FILES="" for i in `diffstat -p1 -l $next`; do FILES="$FILES `pwd`/$i" done - if [ "$FILES" == "" ]; then echo "*** ERROR nothing to commit" cd $cur @@ -159,26 +134,20 @@ apply_patch () { hg log -r -1 -v } -grep -v $MBOX >$DIR/tmpbox <<EOF -^Content-Type: -^--Boundary- -^Content-Disposition: inline -^Content-Transfer-Encoding: 8bit -EOF +#################################################################### +# Proccess a new patch -echo git-mailsplit -b $MBOX/tmpbox $DIR -echo -n "Number of patches at file: " -git-mailsplit -b $MBOX $DIR -echo +proccess_patch () +{ + i="$_" -for i in $DIR/*; do if [ "`diffstat -p1 -l $i`" == "" ]; then echo "*** ERROR nothing to commit" cd $cur exit fi - cat $i| git-mailinfo $DIR/msg $DIR/patch>$DIR/author + cat $i| git-mailinfo $DIR/msg $DIR/patch >$DIR/author cat $DIR/msg|grep -vi ^CC: >$DIR/msg2 cat $DIR/author|perl -ne "if (m/Author[:]\\s*(.*)\\n/) { \$auth=\$1; } else \ @@ -195,12 +164,79 @@ for i in $DIR/*; do cat $DIR/author2 - echo "Signed-off-by: $CHANGE_LOG_NAME <$CHANGE_LOG_EMAIL_ADDRESS>" >>$DIR/msg2 + sob="Signed-off-by: $CHANGE_LOG_NAME <$CHANGE_LOG_EMAIL_ADDRESS>" + + if [ "$(perl -ne 'if (m/$sob/) { print $_; }' $DIR/msg2)" == "" ]; then + echo $sob >>$DIR/msg2 + fi echo "cat $DIR/author2 $DIR/msg2 $DIR/patch >$out" $CHECKPATCH -q --notree $i|perl -ne '{ print "# $_"; }' >$out cat $DIR/author2 $DIR/msg2 $DIR/patch >>$out - apply_patch $out -done +} + +#################################################################### +# Main + +if [ "$1" == "" ]; then + echo "Usage: $0 <mbox>" + exit +fi + +if [ "$TMPDIR" == "" ]; then + TMPDIR=/tmp +fi + +if [ "$EDITOR" == "" ]; then + EDITOR="nano -w" +fi + +if [ "$CHECKPATCH" == "" ]; then + CHECKPATCH="/lib/modules/`uname -r`/build/scripts/checkpatch.pl" +fi + +DIR=$TMPDIR/mailimport$$ +mkdir $DIR +if [ "$?" != "0" ]; then + echo "*** Error at mkdir $DIR" + exit; +fi +trap "rm -rf $DIR" EXIT + +if [ -d "$1" ]; then + TMP2=$DIR/patchheader + + if [ -e "$1/series" ]; then + for i in `cat "$1/series"|grep -v "^#"`; do + echo $1/$i + proccess_patch "$1/$i" + done + else + for i in $1/*; do + proccess_patch $i + done + fi +else + MBOX="$1" + TMP2=$DIR/patchheader + + grep -v -f - $MBOX >$DIR/tmpbox <<EOF +^Content-Type: +^--Boundary- +^Content-Disposition: inline +^Content-Transfer-Encoding: 8bit +EOF + + echo git-mailsplit -b $DIR/tmpbox $DIR + echo -n "Number of patches at file: " + git-mailsplit -b $DIR/tmpbox $DIR + echo + + for i in $DIR/0*; do + echo $i + proccess_patch $i + done +fi + diff --git a/v4l/scripts/cardlist b/v4l/scripts/cardlist index 0f25a4b81..3e5213975 100755 --- a/v4l/scripts/cardlist +++ b/v4l/scripts/cardlist @@ -6,7 +6,7 @@ scripts/bttv.pl ../linux/drivers/media/video/bt8xx/bttv.h ../linux/drivers/medi scripts/cx88.pl ../linux/drivers/media/video/cx88/cx88.h ../linux/drivers/media/video/cx88/cx88-cards.c \ | perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.cx88 -scripts/em28xx.pl ../linux/drivers/media/video/em28xx/em28xx.h ../linux/drivers/media/video/em28xx/em28xx-cards.c \ +scripts/em28xx.pl ../linux/drivers/media/video/em28xx/em28xx-cards.c \ | perl -ne 's/[ \t]+$//; print' > ../linux/Documentation/video4linux/CARDLIST.em28xx scripts/tuner.pl ../linux/include/media/tuner.h ../linux/drivers/media/video/tuner-types.c \ diff --git a/v4l/scripts/hghead.pl b/v4l/scripts/hghead.pl index 7b3f3106d..9a6389311 100755 --- a/v4l/scripts/hghead.pl +++ b/v4l/scripts/hghead.pl @@ -45,15 +45,23 @@ while ($line = <IN>) { last; } + if ($line =~ m/^# Date\s*(.*)/) { + print "#Date: $1\n"; + } + if ($line =~ m/^Date:\s*(.*)/) { my $time = str2time($1); if ($time) { + print "#Date: $time 0\n"; + } else { print "#Date: $1\n"; } next; } + $line =~ s/^#\sUser/From:/; + my $tag=$line; my $arg=$line; $tag =~ s/\s*([^\s]+:)(.*)\n/\1/; @@ -139,6 +147,9 @@ while ($line = <IN>) { next; } if ($sub_ok == 0) { + if ($line =~ m/^\s*\n/) { + next; + } $sub_ok=1; substr( $subject, 0, 1 ) = uc (substr ($subject, 0, 1)); if ($subject =~ m|V4L\/DVB\s*(.+)|) { @@ -180,10 +191,11 @@ if (!$signed =~ m/$from/) { die; } +$body="$from\n$body"; $body=~s/[\n\s]+$//; $body=~s/^[\n\s]+//; # First from is used by hg to recognize commiter name print "#Committer: $maintainer_name <$maintainer_email>\n"; -print "$subject\n$from\n$body\n\n$signed"; +print "$subject\n$body\n\n$signed"; diff --git a/v4l/scripts/usbvision.pl b/v4l/scripts/usbvision.pl index 3976e8bd1..b31df4f78 100755 --- a/v4l/scripts/usbvision.pl +++ b/v4l/scripts/usbvision.pl @@ -20,13 +20,15 @@ while (<>) { next unless defined($id); - if (/USB_DEVICE.*0x([0-9a-fA-F]*).*0x([0-9a-fA-F]*).*driver_info\s*=\s*([\w\d_]+)/) -{ + if (/USB_DEVICE.*0x([0-9a-fA-F]*).*0x([0-9a-fA-F]*).*/) + { $subvendor=$1; $subdevice=$2; - push @{$data{$3}->{subid}}, "$subvendor:$subdevice"; } - + if(/driver_info\s*=\s*([\w\d_]+)/) + { + push @{$data{$1}->{subid}}, "$subvendor:$subdevice"; + } if (!defined($data{$id}) || !defined($data{$id}->{name})) { $data{$id}->{name} = $1 if (/\.ModelString\s*=\s*\"([^\"]+)\"/); } diff --git a/v4l2-apps/util/rds/Makefile b/v4l2-apps/util/rds/Makefile new file mode 100644 index 000000000..4f6ebd9f2 --- /dev/null +++ b/v4l2-apps/util/rds/Makefile @@ -0,0 +1,16 @@ +# Makefile for linuxtv.org v4l2-apps/util/xc3028-firmware + +CPPFLAGS += -I../../../linux/include + +binaries = rds-saa6588 + +.PHONY: all clean install qv4l2 + +all: $(binaries) + +clean:: + rm -f $(binaries) + +install: + +include ../../Make.rules diff --git a/v4l_experimental/rds-saa6588.c b/v4l2-apps/util/rds/rds-saa6588.c index 69d66e5f1..69d66e5f1 100644 --- a/v4l_experimental/rds-saa6588.c +++ b/v4l2-apps/util/rds/rds-saa6588.c diff --git a/v4l2-apps/util/xc3028-firmware/Makefile b/v4l2-apps/util/xc3028-firmware/Makefile index 508575e16..102f712fd 100644 --- a/v4l2-apps/util/xc3028-firmware/Makefile +++ b/v4l2-apps/util/xc3028-firmware/Makefile @@ -12,7 +12,7 @@ clean:: rm -f $(binaries) firmware-tool: firmware-tool.o standards.o - $(CXX) $^ -o $@ + $(CC) $^ -o $@ install: diff --git a/v4l_experimental/cx88-ivtv.c b/v4l_experimental/cx88-ivtv.c deleted file mode 100644 index 8247d4286..000000000 --- a/v4l_experimental/cx88-ivtv.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * $Id: cx88-ivtv.c,v 1.1 2005/11/30 17:26:37 mchehab Exp $ - * - * IVTV API emulation for the "blackbird" reference design. - * - * (c) 2005 Catalin Climov <catalin@climov.com> - * - * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), - * - * 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/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include "compat.h" -#include <media/v4l2-common.h> -#include "cx88.h" - -MODULE_DESCRIPTION("ivtv ioctl emulation module for blackbird TV cards"); -MODULE_AUTHOR("Catalin Climov <catalin@climov.com>"); -MODULE_LICENSE("GPL"); - -static unsigned int debug = 0; -module_param(debug,int,0644); -MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); - -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) - -static int (*prev_ioctl_hook)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg); -static unsigned int (*prev_ioctl_translator)(unsigned int cmd); - -/* --- IVTV data structs -------------------------------------------- */ - -struct ivtv_ioctl_codec { - uint32_t aspect; - uint32_t audio_bitmask; - uint32_t bframes; - uint32_t bitrate_mode; - uint32_t bitrate; - uint32_t bitrate_peak; - uint32_t dnr_mode; - uint32_t dnr_spatial; - uint32_t dnr_temporal; - uint32_t dnr_type; - uint32_t framerate; /* read only, ignored on write */ - uint32_t framespergop; /* read only, ignored on write */ - uint32_t gop_closure; - uint32_t pulldown; - uint32_t stream_type; -}; - -struct ivtv_sliced_vbi_format { - unsigned long service_set; /* one or more of the IVTV_SLICED_ defines */ - unsigned long packet_size; /* the size in bytes of the ivtv_sliced_data packet */ - unsigned long io_size; /* maximum number of bytes passed by one read() call */ - unsigned long reserved; -}; - -#define IVTV_IOC_G_CODEC _IOR ('@', 48, struct ivtv_ioctl_codec) -#define IVTV_IOC_S_CODEC _IOW ('@', 49, struct ivtv_ioctl_codec) -#define IVTV_IOC_S_VBI_MODE _IOWR('@', 35, struct ivtv_sliced_vbi_format) -#define IVTV_IOC_G_VBI_MODE _IOR ('@', 36, struct ivtv_sliced_vbi_format) -#define IVTV_IOC_S_VBI_EMBED _IOW ('@', 54, int) - -/* ------------------------------------------------------------------ */ - -static unsigned int ivtv_translate_ioctl(unsigned int cmd) -{ -#if 0 - printk( KERN_INFO "ivtv_translate_ioctl\n" ); -#endif - switch( cmd ) - { - case 0xFFEE7703: cmd = IVTV_IOC_G_CODEC; break; - case 0xFFEE7704: cmd = IVTV_IOC_S_CODEC; break; - case 0xFFEE7781: /*cmd = IVTV_IOC_PLAY; break;*/ - case 0xFFEE7782: /*cmd = IVTV_IOC_PAUSE; break;*/ - case 0xFFEE7783: /*cmd = IVTV_IOC_FRAMESYNC; break;*/ - case 0xFFEE7784: /*cmd = IVTV_IOC_GET_TIMING; break;*/ - case 0xFFEE7785: /*cmd = IVTV_IOC_S_SLOW_FAST; break;*/ - case 0xFFEE7786: /*cmd = IVTV_IOC_S_START_DECODE; break;*/ - case 0xFFEE7787: /*cmd = IVTV_IOC_S_STOP_DECODE; break;*/ - case 0xFFEE7789: /*cmd = IVTV_IOC_GET_FB; break;*/ - printk( KERN_INFO "IVTV: 0x%x\n", cmd ); - } - return prev_ioctl_translator( cmd ); -} - -static int ivtv_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct cx8802_fh *fh = file->private_data; - struct cx8802_dev *dev = fh->dev; - /* struct cx88_core *core = dev->core; */ - - /* int err; */ - - if (debug > 1) - v4l_print_ioctl(dev->core->name,cmd); -#if 1 - printk( KERN_INFO "IVTV IOCTL: 0x%x\n", cmd ); - v4l_print_ioctl(dev->core->name,cmd); -#endif - dprintk( 1, "IVTV IOCTL: 0x%x\n", cmd ); - - switch (cmd) { - - /* --- IVTV emulation layer --------------------------- */ - case IVTV_IOC_S_CODEC: - printk( KERN_INFO "IVTV_IOC_S_CODEC\n" ); - case IVTV_IOC_G_CODEC: - { - struct ivtv_ioctl_codec *codec = arg; -#if 1 - printk( KERN_INFO "IVTV_IOC_G/S_CODEC\n" ); - printk( KERN_INFO "CODEC: aspect: %d\n", codec->aspect ); - printk( KERN_INFO "CODEC: audio : %d\n", codec->audio_bitmask ); - printk( KERN_INFO "CODEC: bfrms : %d\n", codec->bframes ); - printk( KERN_INFO "CODEC: br_mod: %d\n", codec->bitrate_mode ); - printk( KERN_INFO "CODEC: btrate: %d\n", codec->bitrate ); - printk( KERN_INFO "CODEC: btr_pk: %d\n", codec->bitrate_peak ); - printk( KERN_INFO "CODEC: dnr_md: %d\n", codec->dnr_mode ); - printk( KERN_INFO "CODEC: dnr_sp: %d\n", codec->dnr_spatial ); - printk( KERN_INFO "CODEC: dnr_tp: %d\n", codec->dnr_temporal ); - printk( KERN_INFO "CODEC: dnr_ty: %d\n", codec->dnr_type ); - printk( KERN_INFO "CODEC: framer: %d\n", codec->framerate ); - printk( KERN_INFO "CODEC: grmgop: %d\n", codec->framespergop ); - printk( KERN_INFO "CODEC: gop_cl: %d\n", codec->gop_closure ); - printk( KERN_INFO "CODEC: pulldn: %d\n", codec->pulldown ); - printk( KERN_INFO "CODEC: strtyp: %d\n\n", codec->stream_type ); -#endif - - codec->aspect = 2; /* 4:3 */ - codec->audio_bitmask = (2 << 2) | (14 << 4); /* layer II | 384kbps */ - codec->bframes = 2; - codec->bitrate_mode = 1; /* cbr */ - codec->bitrate = 4500000; /* bps */ - codec->bitrate_peak = 6000000; /* peak */ - codec->dnr_mode = 0; /* spatial=manual | temporal=manual */ - codec->dnr_spatial = 0; - codec->dnr_temporal = 0; - codec->dnr_type = 0; /* disabled */ - codec->framerate = 1; /* 25fps */ - codec->framespergop = 15; - codec->gop_closure = 0; /* open */ - codec->pulldown = 0; /* enabled */ - codec->stream_type = 0; /* program stream */ -#if 1 - printk( KERN_INFO "CODEC: aspect: %d\n", codec->aspect ); - printk( KERN_INFO "CODEC: audio : %d\n", codec->audio_bitmask ); - printk( KERN_INFO "CODEC: bfrms : %d\n", codec->bframes ); - printk( KERN_INFO "CODEC: br_mod: %d\n", codec->bitrate_mode ); - printk( KERN_INFO "CODEC: btrate: %d\n", codec->bitrate ); - printk( KERN_INFO "CODEC: btr_pk: %d\n", codec->bitrate_peak ); - printk( KERN_INFO "CODEC: dnr_md: %d\n", codec->dnr_mode ); - printk( KERN_INFO "CODEC: dnr_sp: %d\n", codec->dnr_spatial ); - printk( KERN_INFO "CODEC: dnr_tp: %d\n", codec->dnr_temporal ); - printk( KERN_INFO "CODEC: dnr_ty: %d\n", codec->dnr_type ); - printk( KERN_INFO "CODEC: framer: %d\n", codec->framerate ); - printk( KERN_INFO "CODEC: grmgop: %d\n", codec->framespergop ); - printk( KERN_INFO "CODEC: gop_cl: %d\n", codec->gop_closure ); - printk( KERN_INFO "CODEC: pulldn: %d\n", codec->pulldown ); - printk( KERN_INFO "CODEC: strtyp: %d\n", codec->stream_type ); -#endif - return 0; - } - case IVTV_IOC_S_VBI_MODE: - { - struct ivtv_sliced_vbi_format *fmt = arg; - printk( KERN_INFO "IVTV_IOC_S_VBI_MODE: ss: %ld, ps: %ld, is: %ld\n", - fmt->service_set, fmt->packet_size, fmt->io_size ); -#if 0 - fmt->service_set = 0; /* one or more of the IVTV_SLICED_ defines */ - fmt->packet_size = 0; /* the size in bytes of the ivtv_sliced_data packet */ - fmt->io_size = 0; /* maximum number of bytes passed by one read() call */ -#endif - return 0; - } - case IVTV_IOC_G_VBI_MODE: - { - struct ivtv_sliced_vbi_format *fmt = arg; - - fmt->service_set = 1; /* one or more of the IVTV_SLICED_ defines */ - fmt->packet_size = 0; /* the size in bytes of the ivtv_sliced_data packet */ - fmt->io_size = 0; /* maximum number of bytes passed by one read() call */ - return 0; - } - case IVTV_IOC_S_VBI_EMBED: - { - int *embed = arg; - printk( KERN_INFO "IVTV_IOC_S_VBI_EMBED: %d\n", *embed ); - return 0; - } - - default: - if( prev_ioctl_hook ) - return prev_ioctl_hook( inode, file, cmd, arg ); - else - return -EINVAL; - } - return 0; -} - -static int __init cx88_ivtv_init(void) -{ - printk(KERN_INFO "ivtv emulation for blackbird version %d.%d.%d loaded\n", - (CX88_VERSION_CODE >> 16) & 0xff, - (CX88_VERSION_CODE >> 8) & 0xff, - CX88_VERSION_CODE & 0xff); -#ifdef SNAPSHOT - printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", - SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); -#endif - request_module( "cx88-blackbird" ); - prev_ioctl_translator = cx88_ioctl_translator; - cx88_ioctl_translator = ivtv_translate_ioctl; - prev_ioctl_hook = cx88_ioctl_hook; - cx88_ioctl_hook = ivtv_do_ioctl; - return 0; -} - -static void __exit cx88_ivtv_fini(void) -{ - cx88_ioctl_hook = prev_ioctl_hook; - cx88_ioctl_translator = prev_ioctl_translator; -} - -module_init(cx88_ivtv_init); -module_exit(cx88_ivtv_fini); - -/* - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/v4l_experimental/xc3028/Makefile b/v4l_experimental/xc3028/Makefile deleted file mode 100644 index 6efcded1d..000000000 --- a/v4l_experimental/xc3028/Makefile +++ /dev/null @@ -1,534 +0,0 @@ -ifeq ($(obj),) -obj = . -endif - -################################################# -# configuration - -include $(obj)/Make.config - -# symbol exports -export-objs := video-buf.o v4l1-compat.o v4l2-common.o -export-objs += ir-common.o -ifeq ($(CONFIG_VIDEO_DEV),m) -export-objs += videodev.o -endif -export-objs += bttv-if.o btcx-risc.o -export-objs += cx88-cards.o cx88-core.o -export-objs += saa7134-core.o saa7134-tvaudio.o - -# drivers objects -ir-common-objs := ir-keymaps.o ir-functions.o -bttv-objs := bttv-driver.o bttv-cards.o bttv-risc.o bttv-if.o \ - bttv-vbi.o bttv-i2c.o bttv-input.o -saa7134-objs := saa7134-core.o saa7134-i2c.o saa7134-video.o \ - saa7134-vbi.o saa7134-tvaudio.o \ - saa7134-cards.o saa7134-ts.o saa7134-input.o - - -cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \ - cx88-input.o -cx8800-objs := cx88-video.o cx88-vbi.o -cx8802-objs := cx88-mpeg.o -tuner-objs := tuner-core.o tuner-types.o tuner-simple.o mt20xx.o tda8290.o tea5767.o xc3028.o -msp3400-objs := msp3400-driver.o msp3400-kthreads.o -list-multi := bttv.o saa7134.o cx88xx.o cx8800.o cx88-alsa.o cx8802.o -em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \ - em28xx-input.o -cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ - cx25840-vbi.o -dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_frontend.o \ - dvb_net.o dvb_ringbuffer.o -b2c2-flexcop-objs := flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ - flexcop-sram.o flexcop-eeprom.o flexcop-misc.o \ - flexcop-hw-filter.o flexcop-dma.o -b2c2-flexcop-pci-objs := flexcop-pci.o -b2c2-flexcop-usb-objs := flexcop-usb.o -dvb-usb-objs := dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o \ - dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o -dvb-usb-vp7045-objs := vp7045.o vp7045-fe.o -dvb-usb-vp702x-objs := vp702x.o vp702x-fe.o -dvb-usb-dtt200u-objs := dtt200u.o dtt200u-fe.o -dvb-usb-dibusb-common-objs := dibusb-common.o -dvb-usb-a800-objs := a800.o -dvb-usb-dibusb-mb-objs := dibusb-mb.o -dvb-usb-dibusb-mc-objs := dibusb-mc.o -dvb-usb-nova-t-usb2-objs := nova-t-usb2.o -dvb-usb-umt-010-objs := umt-010.o -dvb-usb-digitv-objs := digitv.o -dvb-usb-cxusb-objs := cxusb.o -dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o \ - av7110_ca.o av7110.o av7110_ipack.o av7110_ir.o -saa7146-objs := saa7146_i2c.o saa7146_core.o -saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o \ - saa7146_video.o saa7146_hlp.o saa7146_vbi.o -pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ - pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ - pvrusb2-encoder.o pvrusb2-video-v4l.o \ - pvrusb2-eeprom.o pvrusb2-tuner.o pvrusb2-demod.o \ - pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ - pvrusb2-sysfs.o pvrusb2-context.o pvrusb2-io.o \ - pvrusb2-ioread.o pvrusb2-debugifc.o - -obj-m := video-buf.o v4l1-compat.o v4l2-common.o -obj-m += compat_ioctl32.o -ifeq ($(CONFIG_VIDEO_DEV),m) -obj-m += videodev.o -endif - -obj-$(CONFIG_VIDEO_BTTV) += btcx-risc.o ir-common.o bttv.o tveeprom.o -obj-$(CONFIG_VIDEO_CX88) += btcx-risc.o cx88xx.o cx8800.o cx8802.o \ - cx88-blackbird.o tveeprom.o -obj-$(CONFIG_TVP5150) += tvp5150.o -obj-$(CONFIG_SAA711X) += saa711x.o -obj-$(CONFIG_EM28XX) += em28xx.o tveeprom.o -obj-$(CONFIG_VIDEO_DECODER) += saa7115.o cx25840.o saa7127.o bt832.o - -ifeq ($(CONFIG_VIDEO_ALSA),y) - EXTRA_CFLAGS += -DUSING_CX88_ALSA=1 - obj-$(CONFIG_VIDEO_CX88) += cx88-alsa.o - obj-$(CONFIG_VIDEO_SAA7134) += saa7134-alsa.o -## This one is installed by ALSA as snd_bt87x -# obj-$(CONFIG_VIDEO_BTTV) += bt87x.o -endif - -obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o saa6752hs.o -obj-$(CONFIG_VIDEO_SAA7134) += saa7134-oss.o -obj-$(CONFIG_VIDEO_IR) += ir-common.o -obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o saa6588.o -obj-$(CONFIG_VIDEO_TVAUDIO) += msp3400.o tvaudio.o tvmixer.o wm8775.o \ - cs53l32a.o tda7432.o tda9875.o - -obj-$(CONFIG_VIDEO_CX88_DVB) += video-buf-dvb.o cx88-dvb.o cx88-vp3054-i2c.o -obj-$(CONFIG_VIDEO_SAA7134_DVB) += video-buf-dvb.o saa7134-dvb.o -obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o -obj-$(CONFIG_DVB_FRONTENDS) += dvb-pll.o cx22702.o or51132.o lgdt330x.o \ - mt352.o tda1004x.o sp887x.o nxt6000.o \ - cx24110.o or51211.o nxt200x.o cx24123.o \ - mt312.o stv0299.o bcm3510.o \ - dib3000-common.o dib3000mb.o dib3000mc.o \ - ves1820.o cx22700.o tda8083.o ves1x93.o \ - stv0297.o sp8870.o l64781.o s5h1420.o \ - tda10021.o at76c651.o tda80xx.o -obj-$(CONFIG_DVB_CORE) += dvb-core.o -obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o -obj-$(CONFIG_DVB_B2C2_FLEXCOP) += stv0297_cs2.o -obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o -obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o -obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o -obj-$(CONFIG_DVB_PLUTO2) += pluto2.o -obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o -obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o -obj-$(CONFIG_DVB_USB) += dvb-usb.o -obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o -obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o -obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o -obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o -obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o -obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o -obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o \ - dvb-usb-nova-t-usb2.o -obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o -obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o -obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o -obj-$(CONFIG_DVB_BUDGET) += budget-core.o budget.o ttpci-eeprom.o -obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o budget-av.o ttpci-eeprom.o -obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o -obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o -obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o -obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o -obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o -obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o - -# 2.6-only stuff -ifeq ($(VERSION).$(PATCHLEVEL),2.6) - ifeq ($(CONFIG_VIDEO_BTTV),m) - bttv-objs += bttv-gpio.o - obj-$(CONFIG_VIDEO_IR) += ir-kbd-i2c.o - endif - ifeq ($(CONFIG_VIDEO_SAA7134),m) - obj-$(CONFIG_VIDEO_IR) += ir-kbd-i2c.o - endif -endif - -ifeq ($(CONFIG_VIDEO_ADV_DEBUG),y) - EXTRA_CFLAGS += -DCONFIG_VIDEO_ADV_DEBUG=1 -endif - -# for DVB -EXTRA_CFLAGS += -DDVB_CVS=1 -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core/ -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends/ -ifeq ($(CONFIG_VIDEO_CX88_DVB),m) - EXTRA_CFLAGS += -DCONFIG_VIDEO_CX88_DVB_MODULE=1 - EXTRA_CFLAGS += -DHAVE_CX22702=1 - EXTRA_CFLAGS += -DHAVE_OR51132=1 - EXTRA_CFLAGS += -DHAVE_LGDT330X=1 - EXTRA_CFLAGS += -DHAVE_MT352=1 - EXTRA_CFLAGS += -DHAVE_NXT200X=1 - EXTRA_CFLAGS += -DHAVE_CX24123=1 - EXTRA_CFLAGS += -DHAVE_VP3054_I2C=1 -endif -ifeq ($(CONFIG_VIDEO_SAA7134_DVB),m) - EXTRA_CFLAGS += -DHAVE_MT352=1 - EXTRA_CFLAGS += -DHAVE_TDA1004X=1 - EXTRA_CFLAGS += -DHAVE_NXT200X=1 -endif -ifeq ($(CONFIG_VIDEO_BUF_DVB),m) - EXTRA_CFLAGS += -DHAVE_VIDEO_BUF_DVB=1 -endif -ifeq ($(CONFIG_DVB_AV7110_OSD),y) - EXTRA_CFLAGS += -DCONFIG_DVB_AV7110_OSD=1 -endif -ifeq ($(CONFIG_DVB_AV7110_FIRMWARE),y) -src := $(PWD) - -$(src)/av7110.c: $(obj)/av7110_firm.h - -$(obj)/fdump: - $(CC) -o $@ $(src)/fdump.c - -$(obj)/av7110_firm.h: $(obj)/fdump - $(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@ -endif - - -################################################# -# compile modules - -ifneq ($(KERNELRELEASE),) - -ifeq ($(VERSION).$(PATCHLEVEL),2.6) - export-objs := - list-multi := -else - multi-m := $(filter $(list-multi), $(obj-m)) - int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) - export-objs := $(filter $(int-m) $(obj-m),$(export-objs)) -endif - -CC += -I$(obj) -EXTRA_CFLAGS += -g - -EXTRA_CFLAGS += $(if $(wildcard $(srctree)/.mm), -DMM_KERNEL) - -snapshot := $(wildcard $(obj)/.snapshot) -ifneq ($(snapshot),) -SNAPSHOT_CFLAGS := -DSNAPSHOT='$(shell cat $(snapshot))' -EXTRA_CFLAGS += $(SNAPSHOT_CFLAGS) -endif - -# -# Need to compile with kernel 2.4 -# -bttv.o: $(bttv-objs) - $(LD) -r -o $@ $(bttv-objs) - -cx25840.o: $(cx25840-objs) - $(LD) -g -r -o $@ $(cx25840-objs) - -cx8800.o: $(cx8800-objs) - $(LD) -g -r -o $@ $(cx8800-objs) - -cx8802.o: $(cx8802-objs) - $(LD) -g -r -o $@ $(cx8802-objs) - -cx88xx.o: $(cx88xx-objs) - $(LD) -g -r -o $@ $(cx88xx-objs) - -em28xx.o: $(em28xx-objs) - $(LD) -g -r -o $@ $(em28xx-objs) - -saa7134.o: $(saa7134-objs) - $(LD) -g -r -o $@ $(saa7134-objs) - -tuner.o: $(tuner-objs) - $(LD) -g -r -o $@ $(tuner-objs) - --include $(TOPDIR)/Rules.make -else -# take version info from last module build if available --include $(obj)/.version -endif - -KDIR := /lib/modules/$(KERNELRELEASE)/build -PWD := $(shell pwd) -DEST := /lib/modules/$(KERNELRELEASE)/$(MDIR) -KDIR26 := /lib/modules/$(KERNELRELEASE)/kernel/drivers/media -KDIRUSB := /lib/modules/$(KERNELRELEASE)/kernel/drivers/usb/media - -ifeq ($(VERSION).$(PATCHLEVEL),2.6) - CPPFLAGS := -I$(SUBDIRS)/../linux/include $(CPPFLAGS) -I$(SUBDIRS)/ - MYCFLAGS := -else - MYCFLAGS := CFLAGS="-I../linux/include -D__KERNEL__ -I$(KDIR)/include -DEXPORT_SYMTAB" -endif - -# which files to install? -inst-m := $(wildcard *.ko) -ifeq ($(inst-m),) - inst-m := $(obj-m) -endif - -inst_common := ir-common.ko -inst_video := btcx-risc.ko bttv.ko tda9887.ko tuner.ko tvaudio.ko tveeprom.ko saa6588.ko -#inst_video += bt87x.ko -inst_video += tvmixer.ko v4l1-compat.ko v4l2-common.ko wm8775.ko cs53l32a.ko -inst_video += video-buf.ko video-buf-dvb.ko -ifeq ($(CONFIG_VIDEO_DEV),m) -inst_video += videodev.ko -endif -inst_video += ir-kbd-i2c.ko msp3400.ko -inst_video += tvp5150.ko saa711x.ko saa7134-alsa.ko saa7134-oss.ko -inst_video += saa7115.ko cx25840.ko saa7127.ko compat_ioctl32.ko -inst_cx88 := cx8800.ko cx8802.ko cx88-alsa.ko -inst_cx88 += cx88-blackbird.ko cx88xx.ko cx88-dvb.ko cx88-vp3054-i2c.ko -inst_saa7134 := saa6752hs.ko saa7134.ko saa7134-empress.ko saa7134-dvb.ko -inst_em28xx := em28xx.ko -inst_bt8xx := bt878.ko dvb-bt8xx.ko dst.ko dst_ca.ko -inst_frontends := cx22702.ko dvb-pll.ko lgdt330x.ko or51132.ko tda1004x.ko -inst_frontends += mt352.ko sp887x.ko nxt6000.ko cx24110.ko or51211.ko -inst_frontends += nxt200x.ko cx24123.ko mt312.ko stv0299.ko -inst_frontends += bcm3510.ko dib3000mb.ko dib3000mc.ko ves1820.ko -inst_frontends += cx22700.ko tda8083.ko ves1x93.ko stv0297.ko sp8870.ko -inst_frontends += l64781.ko s5h1420.ko tda10021.ko at76c651.ko tda80xx.ko -inst_frontends += stv0297_cs2.ko -inst_dvb-core := dvb-core.ko -inst_saa7146 := saa7146.ko saa7146_vv.ko -inst_b2c2 := b2c2-flexcop.ko b2c2-flexcop-pci.ko b2c2-flexcop-usb.ko -inst_cinergyT2 := cinergyT2.ko -inst_dvb-usb := dvb-usb.ko dvb-usb-vp7045.ko dvb-usb-vp702x.ko -inst_dvb-usb += dvb-usb-dtt200u.ko dvb-usb-a800.ko dvb-usb-dibusb-mb.ko -inst_dvb-usb += dvb-usb-dibusb-mc.ko dvb-usb-nova-t-usb2.ko -inst_dvb-usb += dvb-usb-umt-010.ko dvb-usb-digitv.ko dvb-usb-cxusb.ko -inst_pluto2 := pluto2.ko -inst_ttpci := budget-core.ko budget.ko ttpci-eeprom.ko budget-av.ko -inst_ttpci += budget-ci.ko budget-patch.ko dvb-ttpci.ko -inst_ttusb-budget := dvb-ttusb-budget.ko -inst_ttusb-dec := ttusb_dec.ko ttusbdecfe.ko -inst_pvrusb2 := pvrusb2.ko - -v4l_modules := $(shell /sbin/lsmod|cut -d' ' -f1 ) $(patsubst %.ko,%,$(inst-m)) - -# locales seem to cause trouble sometimes. -LC_ALL = POSIX -export LC_ALL - -default:: links .version - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $(MYCFLAGS) modules - -pvrusb2:: - @scripts/merge-pvrusb2.sh - -pvrusb2-unmerge:: -# patch -R -p1 < scripts/merge-pvrusb2.sh - -links:: - @echo creating symbolic links... - @find ../linux/drivers/media -name '*.[c,h]' -type f -exec ln -sf '{}' . \; - @find ../linux/sound -name '*.[c,h]' -type f -exec ln -sf '{}' . \; - -# @find ../linux/include -name '*.[h]' -type f -exec ln -sf '{}' . \; - -kernel-links makelinks:: - cd ..; v4l/scripts/makelinks.sh $(KDIR) - -install:: v4l-install dvb-install - -v4l-install:: v4l-rminstall - @echo -e "\nInstalling new V4L modules at corresponding Kernel dir..." - - @strip --strip-debug $(inst-m) - - -install -d $(KDIR26)/common - -install -m 644 -c $(inst_common) $(KDIR26)/common - - -install -d $(KDIR26)/video - -install -m 644 -c $(inst_video) $(KDIR26)/video - - -install -d $(KDIR26)/video/cx88 - -install -m 644 -c $(inst_cx88) $(KDIR26)/video/cx88 - - -install -d $(KDIR26)/video/saa7134 - -install -m 644 -c $(inst_saa7134) $(KDIR26)/video/saa7134 - - -install -d $(KDIR26)/video/em28xx - -install -m 644 -c $(inst_em28xx) $(KDIR26)/video/em28xx - - -install -d $(KDIR26)/video/pvrusb2 - -install -m 644 -c $(inst_pvrusb2) $(KDIR26)/video/pvrusb2 - -# -install -d $(KDIRUSB) -# -install -m 644 -c $(inst_usb) $(KDIRUSB)/ - - /sbin/depmod -a ${KERNELRELEASE} - -dvb-install:: dvb-rminstall - @echo -e "\nInstalling new DVB modules at corresponding Kernel dir..." - - @strip --strip-debug $(inst-m) - - -install -d $(KDIR26)/common - -install -m 644 -c $(inst_saa7146) $(KDIR26)/common - - -install -d $(KDIR26)/dvb/frontends - -install -m 644 -c $(inst_frontends) $(KDIR26)/dvb/frontends - - -install -d $(KDIR26)/dvb/bt8xx - -install -m 644 -c $(inst_bt8xx) $(KDIR26)/dvb/bt8xx - - -install -d $(KDIR26)/dvb/dvb-core - -install -m 644 -c $(inst_dvb-core) $(KDIR26)/dvb/dvb-core - - -install -d $(KDIR26)/dvb/b2c2 - -install -m 644 -c $(inst_b2c2) $(KDIR26)/dvb/b2c2 - - -install -d $(KDIR26)/dvb/cinergyT2 - -install -m 644 -c $(inst_cinergyT2) $(KDIR26)/dvb/cinergyT2 - - -install -d $(KDIR26)/dvb/dvb-usb - -install -m 644 -c $(inst_dvb-usb) $(KDIR26)/dvb/dvb-usb - - -install -d $(KDIR26)/dvb/pluto2 - -install -m 644 -c $(inst_pluto2) $(KDIR26)/dvb/pluto2 - - -install -d $(KDIR26)/dvb/ttpci - -install -m 644 -c $(inst_ttpci) $(KDIR26)/dvb/ttpci - - -install -d $(KDIR26)/dvb/ttusb-budget - -install -m 644 -c $(inst_ttusb-budget) $(KDIR26)/dvb/ttusb-budget - - -install -d $(KDIR26)/dvb/ttusb-dec - -install -m 644 -c $(inst_ttusb-dec) $(KDIR26)/dvb/ttusb-dec - - /sbin/depmod -a ${KERNELRELEASE} - -old-install:: rminstall - @echo -e "\nInstalling new V4L modules at $(DEST)..." - - @strip --strip-debug $(inst-m) - - -install -d $(DEST) - -install -m 644 -c $(inst-m) $(DEST) - - /sbin/depmod -a ${KERNELRELEASE} - -rminstall:: v4l-rminstall dvb-rminstall - -v4l-rminstall:: - @echo -e "\nEliminating old V4L modules (errors on this step is not a problem).." - - -@rm -r $(DEST) \ - $(addprefix $(KDIR26)/common/, $(inst_common)) \ - $(addprefix $(KDIR26)/video/, $(inst_video)) \ - $(addprefix $(KDIR26)/video/cx88/, $(inst_cx88)) \ - $(addprefix $(KDIR26)/video/saa7134/, $(inst_saa7134)) \ - $(addprefix $(KDIR26)/video/em28xx/, $(inst_em28xx)) \ - $(addprefix $(KDIRUSB)/, $(inst_em28xx)) \ - $(addprefix $(KDIR26)/common/, $(addsuffix .gz,$(inst_common))) \ - $(addprefix $(KDIR26)/video/, $(addsuffix .gz,$(inst_video))) \ - $(addprefix $(KDIR26)/video/cx88/, $(addsuffix .gz,$(inst_cx88))) \ - $(addprefix $(KDIR26)/video/saa7134/, $(addsuffix .gz,$(inst_saa7134))) 2>/dev/null \ - $(addprefix $(KDIR26)/video/pvrusb2/, $(addsuffix .gz,$(inst_pvrusb2))) 2>/dev/null \ - $(addprefix $(KDIR26)/video/em28xx/, $(addsuffix .gz,$(inst_em28xx))) 2>/dev/null \ - $(addprefix $(KDIRUSB)/, $(addsuffix .gz,$(inst_em28xx))) 2>/dev/null - @echo - -dvb-rminstall:: - @echo -e "\nEliminating old DVB modules (errors on this step is not a problem).." - - -@rm -r $(DEST) \ - $(addprefix $(KDIR26)/dvb/bt8xx/, $(inst_bt8xx)) \ - $(addprefix $(KDIR26)/dvb/frontends/, $(inst_frontends)) \ - $(addprefix $(KDIR26)/dvb/dvb-core/, $(inst_dvb-core)) \ - $(addprefix $(KDIR26)/dvb/b2c2/, $(inst_b2c2)) \ - $(addprefix $(KDIR26)/dvb/cinergyT2/, $(inst_cinergyT2)) \ - $(addprefix $(KDIR26)/dvb/dvb-usb/, $(inst_dvb-usb)) \ - $(addprefix $(KDIR26)/dvb/pluto2/, $(inst_pluto2)) \ - $(addprefix $(KDIR26)/dvb/ttpci/, $(inst_ttpci)) \ - $(addprefix $(KDIR26)/dvb/ttusb-budget/, $(inst_ttusb-budget)) \ - $(addprefix $(KDIR26)/dvb/ttusb-dec/, $(inst_ttusb-dec)) \ - $(addprefix $(KDIR26)/dvb/bt8xx/, $(addsuffix .gz,$(inst_bt8xx))) \ - $(addprefix $(KDIR26)/dvb/frontends/, $(addsuffix .gz,$(inst_frontends))) \ - $(addprefix $(KDIR26)/dvb/dvb-core/, $(addsuffix .gz,$(inst_dvb-core))) \ - $(addprefix $(KDIR26)/dvb/b2c2/, $(addsuffix .gz,$(inst_b2c2))) \ - $(addprefix $(KDIR26)/dvb/cinergyT2/, $(addsuffix .gz,$(inst_cinergyT2))) \ - $(addprefix $(KDIR26)/dvb/dvb-usb/, $(addsuffix .gz,$(inst_dvb-usb))) \ - $(addprefix $(KDIR26)/dvb/pluto2/, $(addsuffix .gz,$(inst_pluto2))) \ - $(addprefix $(KDIR26)/dvb/ttpci/, $(addsuffix .gz,$(inst_ttpci))) \ - $(addprefix $(KDIR26)/dvb/ttusb-budget/, $(addsuffix .gz,$(inst_ttusb-budget))) \ - $(addprefix $(KDIR26)/dvb/ttusb-dec/, $(addsuffix .gz,$(inst_ttusb-dec))) 2>/dev/null - @echo - -rmmodules:: - rmmod -w $(shell echo "$(v4l_modules)"|sed s,' ','\n',g|sed s,'-','_',g|sort|uniq -d) - -clean:: - @find . -name '*.c' -type l -exec rm '{}' \; - @find . -name '*.h' -type l -exec rm '{}' \; - -rm -f *~ *.o *.ko .*.o.cmd .*.ko.cmd *.mod.c av7110_firm.h fdump - -distclean:: clean - -rm -f .version .*.o.flags .*.o.d - -rm -rf .tmp_versions - @find .. -name '*.orig' -exec rm '{}' \; - @find .. -name '*.rej' -exec rm '{}' \; - -change changes changelog:: - make -C .. changelog - -cvscommit cvs commit:: - cd ..; cvs commit - -update v4l-update:: - cd ..; cvs update - -insmod load:: - scripts/insmod.sh load - -rmmod unload:: - scripts/insmod.sh unload - -reload:: - scripts/insmod.sh reload - -.version: -ifneq ($(KERNELRELEASE),) - echo -e VERSION=$(VERSION)\\nPATCHLEVEL:=$(PATCHLEVEL)\\nSUBLEVEL:=$(SUBLEVEL)\\nKERNELRELEASE:=$(KERNELRELEASE) > $(obj)/.version -else - echo "No version yet." - uname -r|perl -ne 'if (/^([0-9]*)\.([0-9])*\.([0-9]*)(.*)$$/) { printf ("VERSION=%s\nPATCHLEVEL:=%s\nSUBLEVEL:=%s\nKERNELRELEASE:=%s.%s.%s%s\n",$$1,$$2,$$3,$$1,$$2,$$3,$$4); };' > $(obj)/.version - -endif - -################################################# -# build tarballs - -RPWD := $(shell cd .. && pwd) -thisdir := $(notdir $(RPWD)) -name := $(thisdir) -date := $(shell date +%Y%m%d) -tardest ?= . - -snapdir := $(HOME)/snapshot -snap := $(name) - -snapshot snap tarball: update distclean - echo $(thisdir) - echo $(name) - echo $(date) > .snapshot - (cd ..; tar czf $(snapdir)/$(snap)-$(date).tar.gz .) - cp ChangeLog /$(snapdir)/$(snap)-ChangeLog-$(date) - $(MAKE) -C $(snapdir) - - -################################################# -# other stuff - -%.asm: %.o - objdump -S $< > $@ - -card cardlist cardlists: - scripts/cardlist - diff --git a/v4l_experimental/xc3028/README b/v4l_experimental/xc3028/README deleted file mode 100644 index b55cef10c..000000000 --- a/v4l_experimental/xc3028/README +++ /dev/null @@ -1,37 +0,0 @@ -== Hauppauge HVR 900 == - -==== Installation ==== - -1. get the v4l-dvb repository from linuxtv and type make for generating all symlinks in v4l-dvb/v4l -2. copy tuner.h into v4l-dvb/linux/include/media/ in your v4l directory -3. simply replace following files in the repository - * Makefile - * em28xx-cards.c - * em28xx.h - * tuner-core.c - * tuner-types.c - * xc3028.c -with the files in this directory and simply recompile (copy these files to v4l-dvb/v4l) - -==== 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 > /lib/firmware/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 deleted file mode 100644 index 9d3be0c29..000000000 --- a/v4l_experimental/xc3028/convert.c +++ /dev/null @@ -1,90 +0,0 @@ -#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\xbc\xe0\x00\x07\xb0\xf1\x05\x01\x67\x82\x02\x82",2480,3890}, - {"Terratec 2006-02-08","\x2a\x03\x9a\xe0\x00\x07\xf4\xd0\x01\xc0\x70\xe0\x00\x07","\x2a\x00\xcf\xe0\x00\x07\xb0\xf1\x05\x01\x78\x82\x02\x82",2632,3852}, - {"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"); - if(!file){ - printf("unable to open file\n"); - exit(1); - } - 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 deleted file mode 100644 index ebf451ae0..000000000 --- a/v4l_experimental/xc3028/em28xx-cards.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - 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 deleted file mode 100644 index 74fe6a047..000000000 --- a/v4l_experimental/xc3028/em28xx.h +++ /dev/null @@ -1,518 +0,0 @@ -/* - 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/setup.sh b/v4l_experimental/xc3028/setup.sh deleted file mode 100644 index c0a697b59..000000000 --- a/v4l_experimental/xc3028/setup.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -cp tuner.h ../../linux/include/media/ -cp em28xx-cards.c ../../linux/drivers/media/video/em28xx/ -cp em28xx.h ../../linux/drivers/media/video/em28xx/ -cp tuner-types.c ../../linux/drivers/media/video/tuner-types.c -cp tuner-core.c ../../linux/drivers/media/video/tuner-core.c -cp xc3028.c ../../v4l -cp Makefile ../../v4l - diff --git a/v4l_experimental/xc3028/tuner-core.c b/v4l_experimental/xc3028/tuner-core.c deleted file mode 100644 index 54f3b4ae3..000000000 --- a/v4l_experimental/xc3028/tuner-core.c +++ /dev/null @@ -1,946 +0,0 @@ -/* - * $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 deleted file mode 100644 index 8cf44e666..000000000 --- a/v4l_experimental/xc3028/tuner-types.c +++ /dev/null @@ -1,1354 +0,0 @@ -/* - * $Id: tuner-types.c,v 1.2 2006/01/25 13:35:25 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*/, 0x8e, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */ - -static struct tuner_range tuner_philips_pal_i_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */ - -static struct tuner_range tuner_philips_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 451.25 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - .cb_first_if_lower_freq = 1, - }, -}; - -/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */ - -static struct tuner_range tuner_philips_secam_ranges[] = { - { 16 * 168.25 /*MHz*/, 0x8e, 0xa7, }, - { 16 * 447.25 /*MHz*/, 0x8e, 0x97, }, - { 16 * 999.99 , 0x8e, 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), - .cb_first_if_lower_freq = 1, - }, -}; - -/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */ - -static struct tuner_range tuner_philips_pal_ranges[] = { - { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 447.25 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - .cb_first_if_lower_freq = 1, - }, -}; - -/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */ - -static struct tuner_range tuner_temic_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */ - -static struct tuner_range tuner_temic_pal_i_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 450.00 /*MHz*/, 0x8e, 0x04, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */ - -static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */ - -static struct tuner_range tuner_alps_tsb_1_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 385.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* 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), - }, -}; - -/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */ - -static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = { - { 16 * 133.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 351.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */ - -static struct tuner_range tuner_lg_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 0x30, }, -}; - -static struct tuner_params tuner_temic_4006fh5_params[] = { - { - .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_lg_pal_ranges, - .count = ARRAY_SIZE(tuner_lg_pal_ranges), - }, -}; - -/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */ - -static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x8e, 0x14, }, - { 16 * 385.25 /*MHz*/, 0x8e, 0x12, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */ - -static struct tuner_range tuner_temic_pal_dk_ranges[] = { - { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 456.25 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */ - -static struct tuner_range tuner_philips_ntsc_m_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */ - -static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = { - { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* 20-29 */ -/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */ - -static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = { - { 16 * 141.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 464.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */ - -static struct tuner_range tuner_temic_4x3x_f_5_ntsc_ranges[] = { - { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 0x30, }, -}; - -static struct tuner_params tuner_temic_4039fr5_params[] = { - { - .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_temic_4x3x_f_5_ntsc_ranges, - .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges), - }, -}; - -/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */ - -static struct tuner_params tuner_temic_4046fm5_params[] = { - { - .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_temic_40x6f_5_pal_ranges, - .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), - }, -}; - -/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */ - -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), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */ - -static struct tuner_range tuner_lg_ntsc_fm_ranges[] = { - { 16 * 210.00 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 497.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* 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), - }, -}; - -/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */ - -static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 317.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */ - -static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = { - { 16 * 169 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 464 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */ - -static struct tuner_params tuner_temic_4012fy5_params[] = { - { - .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_temic_pal_ranges, - .count = ARRAY_SIZE(tuner_temic_pal_ranges), - }, -}; - -/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */ - -static struct tuner_params tuner_temic_4136_fy5_params[] = { - { - .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_temic_4x3x_f_5_ntsc_ranges, - .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges), - }, -}; - -/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */ - -static struct tuner_range tuner_lg_new_tapc_ranges[] = { - { 16 * 170.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */ - -static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = { - { 16 * 158.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - .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), - }, -}; - -/* 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), - }, -}; - -/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */ - -static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = { - { 16 * 140.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 463.25 /*MHz*/, 0x8e, 0xc2, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */ - -static struct tuner_range tuner_philips_atsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */ - -static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - .cb_first_if_lower_freq = 1, - }, -}; - -/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */ - -static struct tuner_params tuner_philips_4in1_params[] = { - { - .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_fm1236_mk3_ntsc_ranges, - .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), - }, -}; - -/* ------------ 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), - }, -}; - -/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */ - -static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, - { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, - { 16 * 999.99 , 0xce, 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), - }, -}; - -/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ - -static struct tuner_params tuner_lg_ntsc_tape_params[] = { - { - .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_fm1236_mk3_ntsc_ranges, - .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), - }, -}; - -/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ - -static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { - { 16 * 161.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */ - -static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = { - { 16 * 162.00 /*MHz*/, 0x8e, 0xa2, }, - { 16 * 457.00 /*MHz*/, 0x8e, 0x94, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* 50-59 */ -/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */ - -static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = { - { 16 * 172.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 448.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - .cb_first_if_lower_freq = 1, - }, -}; - -/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */ - -static struct tuner_params tuner_philips_fm1256_ih3_params[] = { - { - .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_fm1236_mk3_ntsc_ranges, - .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), - }, -}; - -/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */ - -static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0x39, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */ - -static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x41, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x42, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */ - -static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = { - { 16 * 170.00 /*MHz*/, 0xce, 0x01, }, - { 16 * 450.00 /*MHz*/, 0xce, 0x02, }, - { 16 * 999.99 , 0xce, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */ - -static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, - { 16 * 442.00 /*MHz*/, 0xce, 0x02, }, - { 16 * 999.99 , 0xce, 0x04, }, -}; - -static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = { - { - .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_philips_fq12_6a___mk4_pal_ranges, - .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges), - }, -}; - -/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */ - -static struct tuner_params tuner_philips_fq1236a_mk4_params[] = { - { - .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_fm1236_mk3_ntsc_ranges, - .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), - }, -}; - -/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */ - -static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { - { - .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_philips_ntsc_m_ranges, - .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), - }, -}; - -/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */ - -static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* 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*/, 0x8e, 0x39, }, - { 16 * 415.25 /*MHz*/, 0x8e, 0x3a, }, - { 16 * 999.99 , 0x8e, 0x3c, }, -}; - -#if 0 -static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = { - { 16 * 147.00 /*MHz*/, 0x8e, 0x39, }, - { 16 * 417.00 /*MHz*/, 0x8e, 0x3a, }, - { 16 * 999.99 , 0x8e, 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), - }, -#if 0 - { - .type = TUNER_PARAM_TYPE_ATSC, - .ranges = tuner_thomson_dtt761x_atsc_ranges, - .count = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges), - }, -#endif -}; - -/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ - -static struct tuner_range tuner_tena_9533_di_pal_ranges[] = { - { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x04, }, -}; - -static struct tuner_params tuner_tena_9533_di_params[] = { - { - .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_tena_9533_di_pal_ranges, - .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges), - }, -}; - -/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */ - -static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x86, 0x51, }, - { 16 * 442.00 /*MHz*/, 0x86, 0x52, }, - { 16 * 999.99 , 0x86, 0x54, }, -}; - -#if 0 -static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = { -}; -#endif - -static struct tuner_params 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), - }, -#if 0 - { - .type = TUNER_PARAM_TYPE_DVB, - .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges, - .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges), - }, -#endif -}; - - -/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ - -static struct tuner_range tuner_tua6034_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01 }, - { 16 * 455.00 /*MHz*/, 0x8e, 0x02 }, - { 16 * 999.99 , 0x8e, 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), - }, -#if 0 - { - .type = TUNER_PARAM_TYPE_ATSC, - .ranges = tuner_tua6034_atsc_ranges, - .count = ARRAY_SIZE(tuner_tua6034_atsc_ranges), - }, -#endif -}; - -/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ - -static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { - { - .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_tena_9533_di_pal_ranges, - .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges), - }, -}; - -/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ - -static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = { - { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 373.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */ - -static struct tuner_range tuner_philips_td1316_pal_ranges[] = { - { 16 * 160.00 /*MHz*/, 0xc8, 0xa1, }, - { 16 * 442.00 /*MHz*/, 0xc8, 0xa2, }, - { 16 * 999.99 , 0xc8, 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), - }, -}; - -/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */ - -static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0xce, 0x01, }, - { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, - { 16 * 999.99 , 0xce, 0x04, }, -}; - -#if 0 -static struct tuner_range tuner_tuv1236d_atsc_ranges[] = { -}; -#endif - -static struct tuner_params tuner_tuv1236d_params[] = { - { - .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_tuv1236d_ntsc_ranges, - .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges), - }, -#if 0 - { - .type = TUNER_PARAM_TYPE_ATSC, - .ranges = tuner_tuv1236d_atsc_ranges, - .count = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges), - }, -#endif -}; - -/* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */ - -static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { - { 16 * 157.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 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), - }, -}; - -/* 70-79 */ -/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ - -static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { - { 16 * 175.75 /*MHz*/, 0xce, 0x01, }, - { 16 * 410.25 /*MHz*/, 0xce, 0x02, }, - { 16 * 999.99 , 0xce, 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), - }, -}; - -/* ------------ 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), - }, -}; - -/* --------------------------------------------------------------------- */ - -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_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_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 deleted file mode 100644 index 6a8e840c5..000000000 --- a/v4l_experimental/xc3028/tuner.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - $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 deleted file mode 100644 index 5db6107eb..000000000 --- a/v4l_experimental/xc3028/xc3028.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - - 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("xc3028: 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[4]; - freq<<=2; - chanbuf[0]=0; - chanbuf[1]=0; - chanbuf[2]=(freq&0xff00)>>8; - chanbuf[3]=freq&0x00ff; - 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; - - // 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("xc3028: firmware offset doesn't match!\n"); - release_firmware(fw); - return(-1); - } - - 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)){ - 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("xc3024: Firmware uploaded\n"); - - firmware[firmware_size-1]=0; - - 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); - 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: - */ |