diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-09 22:21:16 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-09 22:21:16 -0300 |
commit | 1f45410eb6cd8758691c7782269b3813c5131e39 (patch) | |
tree | 267d5c66e8e58ed48822e7fba64b3a9f98e4fdfa /linux/drivers | |
parent | 53cbcc79992f562a58926c0aeef0f0f710a69d89 (diff) | |
parent | b3e737a176ce96bee38fb7d0ee5cf6def9da8ad1 (diff) | |
download | mediapointer-dvb-s2-1f45410eb6cd8758691c7782269b3813c5131e39.tar.gz mediapointer-dvb-s2-1f45410eb6cd8758691c7782269b3813c5131e39.tar.bz2 |
merge: http://udev.netup.ru/hg/v4l-dvb-netup
From: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers')
25 files changed, 1010 insertions, 1457 deletions
diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index 68674799b..fa9d4f90a 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -294,7 +294,6 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m int i = 0, count = 0; __le32 *buffer = dev->d_i2c.cpu_addr; int err = 0; - int address_err = 0; int short_delay = 0; if (mutex_lock_interruptible(&dev->i2c_lock)) @@ -334,17 +333,10 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m i2c address probing, however, and address errors indicate that a device is really *not* there. retrying in that case increases the time the device needs to probe greatly, so - it should be avoided. because of the fact, that only - analog based cards use irq based i2c transactions (for dvb - cards, this screwes up other interrupt sources), we bail out - completely for analog cards after an address error and trust - the saa7146 address error detection. */ - if ( -EREMOTEIO == err ) { - if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) { - goto out; - } - address_err++; - } + it should be avoided. So we bail out in irq mode after an + address error and trust the saa7146 address error detection. */ + if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) + goto out; DEB_I2C(("error while sending message(s). starting again.\n")); break; } @@ -359,10 +351,9 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m } while (err != num && retries--); - /* if every retry had an address error, exit right away */ - if (address_err == retries) { + /* quit if any error occurred */ + if (err != num) goto out; - } /* if any things had to be read, get the results */ if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) { diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 3e581409f..3763a9c68 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -96,6 +96,7 @@ config DVB_USB_UMT_010 select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select DVB_MT352 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index b5a564086..1fde0e255 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -34,8 +34,8 @@ #include "stv0900_priv.h" #include "stv0900_init.h" -int debug = 1; -module_param(debug, int, 0644); +static int stvdebug = 1; +module_param_named(debug, stvdebug, int, 0644); /* internal params node */ struct stv0900_inode { diff --git a/linux/drivers/media/dvb/frontends/stv0900_priv.h b/linux/drivers/media/dvb/frontends/stv0900_priv.h index 28350fbeb..762d5af62 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_priv.h +++ b/linux/drivers/media/dvb/frontends/stv0900_priv.h @@ -62,11 +62,11 @@ #define dmd_choose(a, b) (demod = STV0900_DEMOD_2 ? b : a)) -extern int debug; +static int stvdebug; #define dprintk(args...) \ do { \ - if (debug) \ + if (stvdebug) \ printk(KERN_DEBUG args); \ } while (0) diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 6c26618b8..534a022c4 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -582,7 +582,6 @@ config VIDEO_SAA5249 config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 - select I2C_ALGO_SGI select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO help Say Y here to build in support for the Vino video input system found diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index 621ec043f..deb00e4ac 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c index ccd170887..bb5c5165d 100644 --- a/linux/drivers/media/video/cx18/cx18-audio.c +++ b/linux/drivers/media/video/cx18/cx18-audio.c @@ -24,6 +24,7 @@ #include "cx18-driver.h" #include "cx18-io.h" #include "cx18-cards.h" +#include "cx18-audio.h" #define CX18_AUDIO_ENABLE 0xc72014 diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index cf256a999..21f4be839 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -292,23 +292,29 @@ void cx18_av_std_setup(struct cx18 *cx) * * vsync: always 6 half-lines of vsync pulses * vactive: half lines of active video - * vblank656: half lines, after line 3, of blanked video - * vblank: half lines, after line 9, of blanked video + * vblank656: half lines, after line 3/mid-266, of blanked video + * vblank: half lines, after line 9/272, of blanked video * + * As far as I can tell: * vblank656 starts counting from the falling edge of the first - * vsync pulse (start of line 4) + * vsync pulse (start of line 4 or mid-266) * vblank starts counting from the after the 6 vsync pulses and - * 6 equalization pulses (start of line 10) + * 6 or 5 equalization pulses (start of line 10 or 272) * * For 525 line systems the driver will extract VBI information - * from lines 10 through 21. To avoid the EAV RP code from - * toggling at the start of hblank at line 22, where sliced VBI - * data from line 21 is stuffed, also treat line 22 as blanked. + * from lines 10-21 and lines 273-284. */ - vblank656 = 38; /* lines 4 through 22 */ - vblank = 26; /* lines 10 through 22 */ - vactive = 481; /* lines 23 through 262.5 */ + vblank656 = 38; /* lines 4 - 22 & 266 - 284 */ + vblank = 26; /* lines 10 - 22 & 272 - 284 */ + vactive = 481; /* lines 23 - 263 & 285 - 525 */ + /* + * For a 13.5 Mpps clock and 15,734.26 Hz line rate, a line is + * is 858 pixels = 720 active + 138 blanking. The Hsync leading + * edge should happen 1.2 us * 13.5 Mpps ~= 16 pixels after the + * end of active video, leaving 122 pixels of hblank to ignore + * before active video starts. + */ hactive = 720; hblank = 122; luma_lpf = 1; @@ -867,8 +873,22 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; - Vlines = pix->height + (is_50Hz ? 4 : 7); + /* + * This adjustment reflects the excess of vactive, set in + * cx18_av_std_setup(), above standard values: + * + * 480 + 1 for 60 Hz systems + * 576 + 4 for 50 Hz systems + */ + Vlines = pix->height + (is_50Hz ? 4 : 1); + /* + * Invalid height and width scaling requests are: + * 1. width less than 1/16 of the source width + * 2. width greater than the source width + * 3. height less than 1/8 of the source height + * 4. height greater than the source height + */ if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h index fd0df4151..2687a2c91 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.h +++ b/linux/drivers/media/video/cx18/cx18-av-core.h @@ -89,16 +89,21 @@ struct cx18_av_state { /* * The VBI slicer starts operating and counting lines, begining at - * slicer line count of 1, at D lines after the deassertion of VRESET - * This staring field line, S, is 6 or 10 for 625 or 525 line systems. - * Sliced ancillary data captured on VBI slicer line M is sent at the - * beginning of the next VBI slicer line, VBI slicer line count N = M+1. - * Thus when the VBI slicer reports a VBI slicer line number with - * ancillary data, the IDID0 byte indicates VBI slicer line N. - * The actual field line that the captured data comes from is + * slicer line count of 1, at D lines after the deassertion of VRESET. + * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525 + * line systems respectively. Sliced ancillary data captured on VBI + * slicer line M is inserted after the VBI slicer is done with line M, + * when VBI slicer line count is N = M+1. Thus when the VBI slicer + * reports a VBI slicer line number with ancillary data, the IDID0 byte + * indicates VBI slicer line N. The actual field line that the captured + * data comes from is + * * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2). * + * L is the line in the field, not frame, from which the VBI data came. + * N is the line reported by the slicer in the ancillary data. * D is the slicer_line_delay value programmed into register 0x47f. + * S is 6 for 625 line systems or 10 for 525 line systems * (S+D-2) is the slicer_line_offset used to convert slicer reported * line counts to actual field lines. */ diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 43267d1af..27699839b 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -142,7 +142,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ - V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 - unlike cx25840 */ + 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ 0, 0, 0, 0 }; int is_pal = !(state->std & V4L2_STD_525_60); @@ -243,7 +243,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) lcr[i] |= 6 << (4 * x); break; case V4L2_SLICED_VPS: - lcr[i] |= 7 << (4 * x); /*'840 differs*/ + lcr[i] |= 9 << (4 * x); break; } } @@ -301,7 +301,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) sdid = V4L2_SLICED_CAPTION_525; err = !odd_parity(p[0]) || !odd_parity(p[1]); break; - case 7: /* Differs from cx25840 */ + case 9: sdid = V4L2_SLICED_VPS; if (decode_vps(p, p) != 0) err = 1; diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 925e01fdb..82fc2f9d4 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -166,15 +166,26 @@ static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) return 0; } -static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt) +static int cx18_setup_vbi_fmt(struct cx18 *cx, + enum v4l2_mpeg_stream_vbi_fmt fmt, + enum v4l2_mpeg_stream_type type) { if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) return -EINVAL; if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; - /* First try to allocate sliced VBI buffers if needed. */ - if (fmt && cx->vbi.sliced_mpeg_data[0] == NULL) { + if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV || + type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { + /* We don't do VBI insertion aside from IVTV format in a PS */ + cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE; + CX18_DEBUG_INFO("disabled insertion of sliced VBI data into " + "the MPEG stream\n"); + return 0; + } + + /* Allocate sliced VBI buffers if needed. */ + if (cx->vbi.sliced_mpeg_data[0] == NULL) { int i; for (i = 0; i < CX18_VBI_FRAMES; i++) { @@ -185,19 +196,27 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt kfree(cx->vbi.sliced_mpeg_data[i]); cx->vbi.sliced_mpeg_data[i] = NULL; } + cx->vbi.insert_mpeg = + V4L2_MPEG_STREAM_VBI_FMT_NONE; + CX18_WARN("Unable to allocate buffers for " + "sliced VBI data insertion\n"); return -ENOMEM; } } } cx->vbi.insert_mpeg = fmt; + CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS," + "when sliced VBI is enabled\n"); - if (cx->vbi.insert_mpeg == 0) - return 0; - /* Need sliced data for mpeg insertion */ + /* + * If our current settings have no lines set for capture, store a valid, + * default set of service lines to capture, in our current settings. + */ if (cx18_get_service_set(cx->vbi.sliced_in) == 0) { if (cx->is_60hz) - cx->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; + cx->vbi.sliced_in->service_set = + V4L2_SLICED_CAPTION_525; else cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz); @@ -284,8 +303,11 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) priv.cx = cx; priv.s = &cx->streams[id->type]; err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p); - if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt) - err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt); + if (!err && + (cx->params.stream_vbi_fmt != p.stream_vbi_fmt || + cx->params.stream_type != p.stream_type)) + err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt, + p.stream_type); cx->params = p; cx->dualwatch_stereo_mode = p.audio_properties & 0x0300; idx = p.audio_properties & 0x03; diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 8f294f436..f688ec7db 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -273,8 +273,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) u8 eedata[256]; memset(&c, 0, sizeof(c)); - strncpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); - c.name[sizeof(c.name)-1] = '\0'; + strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); c.adapter = &cx->i2c_adap[0]; c.addr = 0xA0 >> 1; diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 0605c2d83..7c1db9c18 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -413,9 +413,8 @@ static void cx18_vbi_setup(struct cx18_stream *s) * 0x90 (Task HorizontalBlank) * 0xd0 (Task EvenField HorizontalBlank) * - * We have set the digitzer to consider the first active line - * as part of VerticalBlank as well so we don't have to look for - * these problem codes nor lose the last line of sliced data. + * We have set the digitzer such that we don't have to worry + * about these problem codes. */ data[4] = 0xB0F0B0F0; /* diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index a81fe2e98..355737bff 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -169,7 +169,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, int streamtype) { u8 *p = (u8 *) buf->buf; - u32 *q = (u32 *) buf->buf; + __be32 *q = (__be32 *) buf->buf; u32 size = buf->bytesused; u32 pts; int lines; @@ -178,8 +178,9 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, return; /* - * The CX23418 sends us data that is 32 bit LE swapped, but we want - * the raw VBI bytes in the order they were in the raster line + * The CX23418 sends us data that is 32 bit little-endian swapped, + * but we want the raw VBI bytes in the order they were in the raster + * line. This has a side effect of making the 12 byte header big endian */ cx18_buf_swap(buf); @@ -218,7 +219,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* Sliced VBI data with data insertion */ - pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; + pts = (be32_to_cpu(q[0]) == 0x3fffffff) ? be32_to_cpu(q[2]) : 0; /* * For calls to compress_sliced_buf(), ensure there are an integral diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 4066ca69c..28896aa31 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -20,10 +20,10 @@ config VIDEO_CX23885 select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index c76dbc029..edafe9bde 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -30,9 +30,6 @@ #include "lgdt330x.h" #include "zl10353.h" #include "s5h1409.h" -#ifdef EM28XX_DRX397XD_SUPPORT -#include "drx397xD.h" -#endif MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); diff --git a/linux/drivers/media/video/indycam.c b/linux/drivers/media/video/indycam.c index 84b9e4f2b..f2da0550b 100644 --- a/linux/drivers/media/video/indycam.c +++ b/linux/drivers/media/video/indycam.c @@ -19,10 +19,12 @@ #include <linux/mm.h> #include <linux/slab.h> -#include <linux/videodev.h> /* IndyCam decodes stream of photons into digital image representation ;-) */ -#include <linux/video_decoder.h> +#include <linux/videodev2.h> #include <linux/i2c.h> +#include <media/v4l2-device.h> +#include <media/v4l2-chip-ident.h> +#include <media/v4l2-i2c-drv.h> #include "indycam.h" @@ -33,6 +35,12 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; +#endif + // #define INDYCAM_DEBUG #ifdef INDYCAM_DEBUG @@ -44,11 +52,14 @@ MODULE_LICENSE("GPL"); #endif struct indycam { - struct i2c_client *client; + struct v4l2_subdev sd; u8 version; }; -static struct i2c_driver i2c_driver_indycam; +static inline struct indycam *to_indycam(struct v4l2_subdev *sd) +{ + return container_of(sd, struct indycam, sd); +} static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ @@ -63,8 +74,9 @@ static const u8 initseq[] = { /* IndyCam register handling */ -static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) +static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; if (reg == INDYCAM_REG_RESET) { @@ -87,12 +99,12 @@ static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) return 0; } -static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) +static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int err; - if ((reg == INDYCAM_REG_BRIGHTNESS) - || (reg == INDYCAM_REG_VERSION)) { + if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) { dprintk("indycam_write_reg(): " "skipping read-only register %d\n", reg); return 0; @@ -108,13 +120,13 @@ static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) return err; } -static int indycam_write_block(struct i2c_client *client, u8 reg, +static int indycam_write_block(struct v4l2_subdev *sd, u8 reg, u8 length, u8 *data) { int i, err; for (i = 0; i < length; i++) { - err = indycam_write_reg(client, reg + i, data[i]); + err = indycam_write_reg(sd, reg + i, data[i]); if (err) return err; } @@ -125,79 +137,78 @@ static int indycam_write_block(struct i2c_client *client, u8 reg, /* Helper functions */ #ifdef INDYCAM_DEBUG -static void indycam_regdump_debug(struct i2c_client *client) +static void indycam_regdump_debug(struct v4l2_subdev *sd) { int i; u8 val; for (i = 0; i < 9; i++) { - indycam_read_reg(client, i, &val); + indycam_read_reg(sd, i, &val); dprintk("Reg %d = 0x%02x\n", i, val); } } #endif -static int indycam_get_control(struct i2c_client *client, - struct indycam_control *ctrl) +static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct indycam *camera = i2c_get_clientdata(client); + struct indycam *camera = to_indycam(sd); u8 reg; int ret = 0; - switch (ctrl->type) { - case INDYCAM_CONTROL_AGC: - case INDYCAM_CONTROL_AWB: - ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + switch (ctrl->id) { + case V4L2_CID_AUTOGAIN: + case V4L2_CID_AUTO_WHITE_BALANCE: + ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®); if (ret) return -EIO; - if (ctrl->type == INDYCAM_CONTROL_AGC) + if (ctrl->id == V4L2_CID_AUTOGAIN) ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) ? 1 : 0; else ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) ? 1 : 0; break; - case INDYCAM_CONTROL_SHUTTER: - ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); + case V4L2_CID_EXPOSURE: + ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, ®); if (ret) return -EIO; ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); break; - case INDYCAM_CONTROL_GAIN: - ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); + case V4L2_CID_GAIN: + ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_RED_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); + case V4L2_CID_RED_BALANCE: + ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_BLUE_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); + case V4L2_CID_BLUE_BALANCE: + ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_RED_SATURATION: - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_RED_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_BLUE_SATURATION: - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_GAMMA: + case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_GAMMA, ®); if (ret) return -EIO; @@ -213,21 +224,20 @@ static int indycam_get_control(struct i2c_client *client, return ret; } -static int indycam_set_control(struct i2c_client *client, - struct indycam_control *ctrl) +static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct indycam *camera = i2c_get_clientdata(client); + struct indycam *camera = to_indycam(sd); u8 reg; int ret = 0; - switch (ctrl->type) { - case INDYCAM_CONTROL_AGC: - case INDYCAM_CONTROL_AWB: - ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + switch (ctrl->id) { + case V4L2_CID_AUTOGAIN: + case V4L2_CID_AUTO_WHITE_BALANCE: + ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®); if (ret) break; - if (ctrl->type == INDYCAM_CONTROL_AGC) { + if (ctrl->id == V4L2_CID_AUTOGAIN) { if (ctrl->value) reg |= INDYCAM_CONTROL_AGCENA; else @@ -239,34 +249,34 @@ static int indycam_set_control(struct i2c_client *client, reg &= ~INDYCAM_CONTROL_AWBCTL; } - ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); + ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg); break; - case INDYCAM_CONTROL_SHUTTER: + case V4L2_CID_EXPOSURE: reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); - ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); + ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg); break; - case INDYCAM_CONTROL_GAIN: - ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); + case V4L2_CID_GAIN: + ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value); break; - case INDYCAM_CONTROL_RED_BALANCE: - ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, + case V4L2_CID_RED_BALANCE: + ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE, ctrl->value); break; - case INDYCAM_CONTROL_BLUE_BALANCE: - ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, + case V4L2_CID_BLUE_BALANCE: + ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE, ctrl->value); break; case INDYCAM_CONTROL_RED_SATURATION: - ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, + ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION, ctrl->value); break; case INDYCAM_CONTROL_BLUE_SATURATION: - ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, + ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION, ctrl->value); break; - case INDYCAM_CONTROL_GAMMA: + case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { - ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, + ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA, ctrl->value); } break; @@ -279,192 +289,107 @@ static int indycam_set_control(struct i2c_client *client, /* I2C-interface */ -static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) +static int indycam_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct indycam *camera = to_indycam(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM, + camera->version); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops indycam_core_ops = { + .g_chip_ident = indycam_g_chip_ident, + .g_ctrl = indycam_g_ctrl, + .s_ctrl = indycam_s_ctrl, +}; + +static const struct v4l2_subdev_ops indycam_ops = { + .core = &indycam_core_ops, +}; + +static int indycam_probe(struct i2c_client *client, + const struct i2c_device_id *id) { int err = 0; struct indycam *camera; - struct i2c_client *client; + struct v4l2_subdev *sd; - printk(KERN_INFO "SGI IndyCam driver version %s\n", - INDYCAM_MODULE_VERSION); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; camera = kzalloc(sizeof(struct indycam), GFP_KERNEL); - if (!camera) { - err = -ENOMEM; - goto out_free_client; - } - - client->addr = addr; - client->adapter = adap; - client->driver = &i2c_driver_indycam; - client->flags = 0; - strcpy(client->name, "IndyCam client"); - i2c_set_clientdata(client, camera); - - camera->client = client; + if (!camera) + return -ENOMEM; - err = i2c_attach_client(client); - if (err) - goto out_free_camera; + sd = &camera->sd; + v4l2_i2c_subdev_init(sd, client, &indycam_ops); camera->version = i2c_smbus_read_byte_data(client, INDYCAM_REG_VERSION); if (camera->version != CAMERA_VERSION_INDY && camera->version != CAMERA_VERSION_MOOSE) { - err = -ENODEV; - goto out_detach_client; + kfree(camera); + return -ENODEV; } + printk(KERN_INFO "IndyCam v%d.%d detected\n", INDYCAM_VERSION_MAJOR(camera->version), INDYCAM_VERSION_MINOR(camera->version)); - indycam_regdump(client); + indycam_regdump(sd); // initialize - err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); + err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq); if (err) { printk(KERN_ERR "IndyCam initialization failed\n"); - err = -EIO; - goto out_detach_client; + kfree(camera); + return -EIO; } - indycam_regdump(client); + indycam_regdump(sd); // white balance - err = indycam_write_reg(client, INDYCAM_REG_CONTROL, + err = indycam_write_reg(sd, INDYCAM_REG_CONTROL, INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { printk(KERN_ERR "IndyCam: White balancing camera failed\n"); - err = -EIO; - goto out_detach_client; + kfree(camera); + return -EIO; } - indycam_regdump(client); + indycam_regdump(sd); printk(KERN_INFO "IndyCam initialized\n"); return 0; - -out_detach_client: - i2c_detach_client(client); -out_free_camera: - kfree(camera); -out_free_client: - kfree(client); - return err; -} - -static int indycam_probe(struct i2c_adapter *adap) -{ - /* Indy specific crap */ - if (adap->id == I2C_HW_SGI_VINO) - return indycam_attach(adap, INDYCAM_ADDR, 0); - /* Feel free to add probe here :-) */ - return -ENODEV; } -static int indycam_detach(struct i2c_client *client) +static int indycam_remove(struct i2c_client *client) { - struct indycam *camera = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); - i2c_detach_client(client); - kfree(camera); - kfree(client); + v4l2_device_unregister_subdev(sd); + kfree(to_indycam(sd)); return 0; } -static int indycam_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - // struct indycam *camera = i2c_get_clientdata(client); - - /* The old video_decoder interface just isn't enough, - * so we'll use some custom commands. */ - switch (cmd) { - case DECODER_GET_CAPABILITIES: { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_NTSC; - cap->inputs = 1; - cap->outputs = 1; - break; - } - case DECODER_GET_STATUS: { - int *iarg = arg; - - *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC | - DECODER_STATUS_COLOR; - break; - } - case DECODER_SET_NORM: { - int *iarg = arg; - - switch (*iarg) { - case VIDEO_MODE_NTSC: - break; - default: - return -EINVAL; - } - break; - } - case DECODER_SET_INPUT: { - int *iarg = arg; - - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_SET_OUTPUT: { - int *iarg = arg; - - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_ENABLE_OUTPUT: { - /* Always enabled */ - break; - } - case DECODER_SET_PICTURE: { - // struct video_picture *pic = arg; - /* TODO: convert values for indycam_set_controls() */ - break; - } - case DECODER_INDYCAM_GET_CONTROL: { - return indycam_get_control(client, arg); - } - case DECODER_INDYCAM_SET_CONTROL: { - return indycam_set_control(client, arg); - } - default: - return -EINVAL; - } - - return 0; -} - -static struct i2c_driver i2c_driver_indycam = { - .driver = { - .name = "indycam", - }, - .id = I2C_DRIVERID_INDYCAM, - .attach_adapter = indycam_probe, - .detach_client = indycam_detach, - .command = indycam_command, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id indycam_id[] = { + { "indycam", 0 }, + { } }; +MODULE_DEVICE_TABLE(i2c, indycam_id); -static int __init indycam_init(void) -{ - return i2c_add_driver(&i2c_driver_indycam); -} - -static void __exit indycam_exit(void) -{ - i2c_del_driver(&i2c_driver_indycam); -} - -module_init(indycam_init); -module_exit(indycam_exit); +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "indycam", + .probe = indycam_probe, + .remove = indycam_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = indycam_id, +#endif +}; diff --git a/linux/drivers/media/video/indycam.h b/linux/drivers/media/video/indycam.h index e6ee82063..881f21c47 100644 --- a/linux/drivers/media/video/indycam.h +++ b/linux/drivers/media/video/indycam.h @@ -87,22 +87,7 @@ /* Driver interface definitions */ -#define INDYCAM_CONTROL_AGC 0 /* boolean */ -#define INDYCAM_CONTROL_AWB 1 /* boolean */ -#define INDYCAM_CONTROL_SHUTTER 2 -#define INDYCAM_CONTROL_GAIN 3 -#define INDYCAM_CONTROL_RED_BALANCE 4 -#define INDYCAM_CONTROL_BLUE_BALANCE 5 -#define INDYCAM_CONTROL_RED_SATURATION 6 -#define INDYCAM_CONTROL_BLUE_SATURATION 7 -#define INDYCAM_CONTROL_GAMMA 8 - -struct indycam_control { - u8 type; - s32 value; -}; - -#define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control) -#define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control) +#define INDYCAM_CONTROL_RED_SATURATION (V4L2_CID_PRIVATE_BASE + 0) +#define INDYCAM_CONTROL_BLUE_SATURATION (V4L2_CID_PRIVATE_BASE + 1) #endif diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 7f7b05c40..bb4271393 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE ---help--- This option enables a DVB interface for the pvrusb2 driver. diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index e69d504ac..51f17c82b 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -40,6 +40,8 @@ config VIDEO_SAA7134_DVB select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select DVB_ZL10036 if !DVB_FE_CUSTOMISE select DVB_MT312 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index c4f169c95..9df505e0f 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -19,9 +19,11 @@ #include <linux/mm.h> #include <linux/slab.h> -#include <linux/videodev.h> -#include <linux/video_decoder.h> +#include <linux/videodev2.h> #include <linux/i2c.h> +#include <media/v4l2-device.h> +#include <media/v4l2-chip-ident.h> +#include <media/v4l2-i2c-drv.h> #include "compat.h" #include "saa7191.h" @@ -33,6 +35,12 @@ MODULE_VERSION(SAA7191_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x8a >> 1, 0x8e >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; +#endif + // #define SAA7191_DEBUG #ifdef SAA7191_DEBUG @@ -45,17 +53,20 @@ MODULE_LICENSE("GPL"); #define SAA7191_SYNC_DELAY 100 /* milliseconds */ struct saa7191 { - struct i2c_client *client; + struct v4l2_subdev sd; /* the register values are stored here as the actual * I2C-registers are write-only */ u8 reg[25]; int input; - int norm; + v4l2_std_id norm; }; -static struct i2c_driver i2c_driver_saa7191; +static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7191, sd); +} static const u8 initseq[] = { 0, /* Subaddress */ @@ -101,15 +112,14 @@ static const u8 initseq[] = { /* SAA7191 register handling */ -static u8 saa7191_read_reg(struct i2c_client *client, - u8 reg) +static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg) { - return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg]; + return to_saa7191(sd)->reg[reg]; } -static int saa7191_read_status(struct i2c_client *client, - u8 *value) +static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; ret = i2c_master_recv(client, value, 1); @@ -122,21 +132,23 @@ static int saa7191_read_status(struct i2c_client *client, } -static int saa7191_write_reg(struct i2c_client *client, u8 reg, - u8 value) +static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value) { - ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value; + struct i2c_client *client = v4l2_get_subdevdata(sd); + + to_saa7191(sd)->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } /* the first byte of data must be the first subaddress number (register) */ -static int saa7191_write_block(struct i2c_client *client, +static int saa7191_write_block(struct v4l2_subdev *sd, u8 length, const u8 *data) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7191 *decoder = to_saa7191(sd); int i; int ret; - struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client); for (i = 0; i < (length - 1); i++) { decoder->reg[data[0] + i] = data[i + 1]; } @@ -153,14 +165,15 @@ static int saa7191_write_block(struct i2c_client *client, /* Helper functions */ -static int saa7191_set_input(struct i2c_client *client, int input) +static int saa7191_s_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 luma = saa7191_read_reg(client, SAA7191_REG_LUMA); - u8 iock = saa7191_read_reg(client, SAA7191_REG_IOCK); + struct saa7191 *decoder = to_saa7191(sd); + u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA); + u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK); int err; - switch (input) { + switch (route->input) { case SAA7191_INPUT_COMPOSITE: /* Set Composite input */ iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1 | SAA7191_IOCK_GPSW2); @@ -176,54 +189,50 @@ static int saa7191_set_input(struct i2c_client *client, int input) return -EINVAL; } - err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma); + err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock); + err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock); if (err) return -EIO; - decoder->input = input; + decoder->input = route->input; return 0; } -static int saa7191_set_norm(struct i2c_client *client, int norm) +static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); - u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); - u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); + struct saa7191 *decoder = to_saa7191(sd); + u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); + u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV); int err; - switch(norm) { - case SAA7191_NORM_PAL: + if (norm & V4L2_STD_PAL) { stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); chcv = SAA7191_CHCV_PAL; - break; - case SAA7191_NORM_NTSC: + } else if (norm & V4L2_STD_NTSC) { stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~SAA7191_CTL3_AUFD; ctl3 |= SAA7191_CTL3_FSEL; chcv = SAA7191_CHCV_NTSC; - break; - case SAA7191_NORM_SECAM: + } else if (norm & V4L2_STD_SECAM) { stdc |= SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); chcv = SAA7191_CHCV_PAL; - break; - default: + } else { return -EINVAL; } - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); + err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv); + err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv); if (err) return -EIO; @@ -231,19 +240,19 @@ static int saa7191_set_norm(struct i2c_client *client, int norm) dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3, stdc, chcv); - dprintk("norm: %d\n", norm); + dprintk("norm: %llx\n", norm); return 0; } -static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) +static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status) { int i = 0; dprintk("Checking for signal...\n"); for (i = 0; i < SAA7191_SYNC_COUNT; i++) { - if (saa7191_read_status(client, status)) + if (saa7191_read_status(sd, status)) return -EIO; if (((*status) & SAA7191_STATUS_HLCK) == 0) { @@ -259,31 +268,34 @@ static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) return -EBUSY; } -static int saa7191_autodetect_norm_extended(struct i2c_client *client) +static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) { - u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); - u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); + struct saa7191 *decoder = to_saa7191(sd); + u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); u8 status; + v4l2_std_id old_norm = decoder->norm; int err = 0; dprintk("SAA7191 extended signal auto-detection...\n"); + *norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_FSEL); - err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); + err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); if (err) { err = -EIO; goto out; } - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) { err = -EIO; goto out; } ctl3 |= SAA7191_CTL3_AUFD; - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) { err = -EIO; goto out; @@ -291,53 +303,54 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; if (status & SAA7191_STATUS_FIDT) { /* 60Hz signal -> NTSC */ dprintk("60Hz signal: NTSC\n"); - return saa7191_set_norm(client, SAA7191_NORM_NTSC); + *norm = V4L2_STD_NTSC; + return 0; } /* 50Hz signal */ dprintk("50Hz signal: Trying PAL...\n"); /* try PAL first */ - err = saa7191_set_norm(client, SAA7191_NORM_PAL); + err = saa7191_s_std(sd, V4L2_STD_PAL); if (err) goto out; msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; /* not 50Hz ? */ if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); - err = -EAGAIN; - goto out; + saa7191_s_std(sd, old_norm); + return -EAGAIN; } if (status & SAA7191_STATUS_CODE) { dprintk("PAL\n"); - return 0; + *norm = V4L2_STD_PAL; + return saa7191_s_std(sd, old_norm); } dprintk("No color detected with PAL - Trying SECAM...\n"); /* no color detected ? -> try SECAM */ - err = saa7191_set_norm(client, - SAA7191_NORM_SECAM); + err = saa7191_s_std(sd, V4L2_STD_SECAM); if (err) goto out; msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; @@ -351,32 +364,17 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) if (status & SAA7191_STATUS_CODE) { /* Color detected -> SECAM */ dprintk("SECAM\n"); - return 0; + *norm = V4L2_STD_SECAM; + return saa7191_s_std(sd, old_norm); } dprintk("No color detected with SECAM - Going back to PAL.\n"); - /* still no color detected ? - * -> set norm back to PAL */ - err = saa7191_set_norm(client, - SAA7191_NORM_PAL); - if (err) - goto out; - out: - ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); - if (ctl3 & SAA7191_CTL3_AUFD) { - ctl3 &= ~(SAA7191_CTL3_AUFD); - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); - if (err) { - err = -EIO; - } - } - - return err; + return saa7191_s_std(sd, old_norm); } -static int saa7191_autodetect_norm(struct i2c_client *client) +static int saa7191_autodetect_norm(struct v4l2_subdev *sd) { u8 status; @@ -384,7 +382,7 @@ static int saa7191_autodetect_norm(struct i2c_client *client) dprintk("Reading status...\n"); - if (saa7191_read_status(client, &status)) + if (saa7191_read_status(sd, &status)) return -EIO; dprintk("Checking for signal...\n"); @@ -400,26 +398,25 @@ static int saa7191_autodetect_norm(struct i2c_client *client) if (status & SAA7191_STATUS_FIDT) { /* 60hz signal -> NTSC */ dprintk("NTSC\n"); - return saa7191_set_norm(client, SAA7191_NORM_NTSC); + return saa7191_s_std(sd, V4L2_STD_NTSC); } else { /* 50hz signal -> PAL */ dprintk("PAL\n"); - return saa7191_set_norm(client, SAA7191_NORM_PAL); + return saa7191_s_std(sd, V4L2_STD_PAL); } } -static int saa7191_get_control(struct i2c_client *client, - struct saa7191_control *ctrl) +static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { u8 reg; int ret = 0; - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(client, SAA7191_REG_LUMA); - switch (ctrl->type) { + reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) >> SAA7191_LUMA_BPSS_SHIFT; @@ -436,15 +433,15 @@ static int saa7191_get_control(struct i2c_client *client, break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: - reg = saa7191_read_reg(client, SAA7191_REG_GAIN); - if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) + reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); + if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; else ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) >> SAA7191_GAIN_LFIS_SHIFT; break; - case SAA7191_CONTROL_HUE: - reg = saa7191_read_reg(client, SAA7191_REG_HUEC); + case V4L2_CID_HUE: + reg = saa7191_read_reg(sd, SAA7191_REG_HUEC); if (reg < 0x80) reg += 0x80; else @@ -452,18 +449,18 @@ static int saa7191_get_control(struct i2c_client *client, ctrl->value = (s32)reg; break; case SAA7191_CONTROL_VTRC: - reg = saa7191_read_reg(client, SAA7191_REG_STDC); + reg = saa7191_read_reg(sd, SAA7191_REG_STDC); ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0; break; case SAA7191_CONTROL_LUMA_DELAY: - reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK) >> SAA7191_CTL3_YDEL_SHIFT; if (ctrl->value >= 4) ctrl->value -= 8; break; case SAA7191_CONTROL_VNR: - reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) >> SAA7191_CTL4_VNOI_SHIFT; break; @@ -474,18 +471,17 @@ static int saa7191_get_control(struct i2c_client *client, return ret; } -static int saa7191_set_control(struct i2c_client *client, - struct saa7191_control *ctrl) +static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { u8 reg; int ret = 0; - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(client, SAA7191_REG_LUMA); - switch (ctrl->type) { + reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: reg &= ~SAA7191_LUMA_BPSS_MASK; reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) @@ -502,12 +498,12 @@ static int saa7191_set_control(struct i2c_client *client, & SAA7191_LUMA_CORI_MASK; break; } - ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg); break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: - reg = saa7191_read_reg(client, SAA7191_REG_GAIN); - if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) { + reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); + if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) { if (ctrl->value) reg |= SAA7191_GAIN_COLO; else @@ -517,41 +513,41 @@ static int saa7191_set_control(struct i2c_client *client, reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) & SAA7191_GAIN_LFIS_MASK; } - ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg); break; - case SAA7191_CONTROL_HUE: + case V4L2_CID_HUE: reg = ctrl->value & 0xff; if (reg < 0x80) reg += 0x80; else reg -= 0x80; - ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg); break; case SAA7191_CONTROL_VTRC: - reg = saa7191_read_reg(client, SAA7191_REG_STDC); + reg = saa7191_read_reg(sd, SAA7191_REG_STDC); if (ctrl->value) reg |= SAA7191_STDC_VTRC; else reg &= ~SAA7191_STDC_VTRC; - ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg); break; case SAA7191_CONTROL_LUMA_DELAY: { s32 value = ctrl->value; if (value < 0) value += 8; - reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); reg &= ~SAA7191_CTL3_YDEL_MASK; reg |= (value << SAA7191_CTL3_YDEL_SHIFT) & SAA7191_CTL3_YDEL_MASK; - ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg); break; } case SAA7191_CONTROL_VNR: - reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); reg &= ~SAA7191_CTL4_VNOI_MASK; reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT) & SAA7191_CTL4_VNOI_MASK; - ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg); break; default: ret = -EINVAL; @@ -562,247 +558,111 @@ static int saa7191_set_control(struct i2c_client *client, /* I2C-interface */ -static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) +static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) { - int err = 0; - struct saa7191 *decoder; - struct i2c_client *client; - - printk(KERN_INFO "Philips SAA7191 driver version %s\n", - SAA7191_MODULE_VERSION); - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return -ENOMEM; - decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); - if (!decoder) { - err = -ENOMEM; - goto out_free_client; - } - - client->addr = addr; - client->adapter = adap; - client->driver = &i2c_driver_saa7191; - client->flags = 0; - strcpy(client->name, "saa7191 client"); - i2c_set_clientdata(client, decoder); - - decoder->client = client; - - err = i2c_attach_client(client); - if (err) - goto out_free_decoder; - - err = saa7191_write_block(client, sizeof(initseq), initseq); - if (err) { - printk(KERN_ERR "SAA7191 initialization failed\n"); - goto out_detach_client; - } - - printk(KERN_INFO "SAA7191 initialized\n"); - - decoder->input = SAA7191_INPUT_COMPOSITE; - decoder->norm = SAA7191_NORM_PAL; - - err = saa7191_autodetect_norm(client); - if (err && (err != -EBUSY)) { - printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); - } + u8 status_reg; + int res = V4L2_IN_ST_NO_SIGNAL; + if (saa7191_read_status(sd, &status_reg)) + return -EIO; + if ((status_reg & SAA7191_STATUS_HLCK) == 0) + res = 0; + if (!(status_reg & SAA7191_STATUS_CODE)) + res |= V4L2_IN_ST_NO_COLOR; + *status = res; return 0; - -out_detach_client: - i2c_detach_client(client); -out_free_decoder: - kfree(decoder); -out_free_client: - kfree(client); - return err; } -static int saa7191_probe(struct i2c_adapter *adap) -{ - /* Always connected to VINO */ - if (adap->id == I2C_HW_SGI_VINO) - return saa7191_attach(adap, SAA7191_ADDR, 0); - /* Feel free to add probe here :-) */ - return -ENODEV; -} -static int saa7191_detach(struct i2c_client *client) +static int saa7191_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) { - struct saa7191 *decoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); - i2c_detach_client(client); - kfree(decoder); - kfree(client); - return 0; + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); } -static int saa7191_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - struct saa7191 *decoder = i2c_get_clientdata(client); +/* ----------------------------------------------------------------------- */ - switch (cmd) { - case DECODER_GET_CAPABILITIES: { - struct video_decoder_capability *cap = arg; +static const struct v4l2_subdev_core_ops saa7191_core_ops = { + .g_chip_ident = saa7191_g_chip_ident, + .g_ctrl = saa7191_g_ctrl, + .s_ctrl = saa7191_s_ctrl, +}; - cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; - cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1; - cap->outputs = 1; - break; - } - case DECODER_GET_STATUS: { - int *iarg = arg; - u8 status; - int res = 0; +static const struct v4l2_subdev_tuner_ops saa7191_tuner_ops = { + .s_std = saa7191_s_std, +}; - if (saa7191_read_status(client, &status)) { - return -EIO; - } - if ((status & SAA7191_STATUS_HLCK) == 0) - res |= DECODER_STATUS_GOOD; - if (status & SAA7191_STATUS_CODE) - res |= DECODER_STATUS_COLOR; - switch (decoder->norm) { - case SAA7191_NORM_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case SAA7191_NORM_PAL: - res |= DECODER_STATUS_PAL; - break; - case SAA7191_NORM_SECAM: - res |= DECODER_STATUS_SECAM; - break; - case SAA7191_NORM_AUTO: - default: - if (status & SAA7191_STATUS_FIDT) - res |= DECODER_STATUS_NTSC; - else - res |= DECODER_STATUS_PAL; - break; - } - *iarg = res; - break; - } - case DECODER_SET_NORM: { - int *iarg = arg; - - switch (*iarg) { - case VIDEO_MODE_AUTO: - return saa7191_autodetect_norm(client); - case VIDEO_MODE_PAL: - return saa7191_set_norm(client, SAA7191_NORM_PAL); - case VIDEO_MODE_NTSC: - return saa7191_set_norm(client, SAA7191_NORM_NTSC); - case VIDEO_MODE_SECAM: - return saa7191_set_norm(client, SAA7191_NORM_SECAM); - default: - return -EINVAL; - } - break; - } - case DECODER_SET_INPUT: { - int *iarg = arg; - - switch (client->adapter->id) { - case I2C_HW_SGI_VINO: - return saa7191_set_input(client, *iarg); - default: - if (*iarg != 0) - return -EINVAL; - } - break; - } - case DECODER_SET_OUTPUT: { - int *iarg = arg; +static const struct v4l2_subdev_video_ops saa7191_video_ops = { + .s_routing = saa7191_s_routing, + .querystd = saa7191_querystd, + .g_input_status = saa7191_g_input_status, +}; - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_ENABLE_OUTPUT: { - /* Always enabled */ - break; - } - case DECODER_SET_PICTURE: { - struct video_picture *pic = arg; - unsigned val; - int err; +static const struct v4l2_subdev_ops saa7191_ops = { + .core = &saa7191_core_ops, + .video = &saa7191_video_ops, +}; - val = (pic->hue >> 8) - 0x80; +static int saa7191_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err = 0; + struct saa7191 *decoder; + struct v4l2_subdev *sd; - err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); - if (err) - return -EIO; + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); - break; - } - case DECODER_SAA7191_GET_STATUS: { - struct saa7191_status *status = arg; - u8 status_reg; + decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + if (!decoder) + return -ENOMEM; - if (saa7191_read_status(client, &status_reg)) - return -EIO; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa7191_ops); - status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) - ? 1 : 0; - status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT) - ? 1 : 0; - status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0; + err = saa7191_write_block(sd, sizeof(initseq), initseq); + if (err) { + printk(KERN_ERR "SAA7191 initialization failed\n"); + kfree(decoder); + return err; + } - status->input = decoder->input; - status->norm = decoder->norm; + printk(KERN_INFO "SAA7191 initialized\n"); - break; - } - case DECODER_SAA7191_SET_NORM: { - int *norm = arg; - - switch (*norm) { - case SAA7191_NORM_AUTO: - return saa7191_autodetect_norm(client); - case SAA7191_NORM_AUTO_EXT: - return saa7191_autodetect_norm_extended(client); - default: - return saa7191_set_norm(client, *norm); - } - } - case DECODER_SAA7191_GET_CONTROL: { - return saa7191_get_control(client, arg); - } - case DECODER_SAA7191_SET_CONTROL: { - return saa7191_set_control(client, arg); - } - default: - return -EINVAL; - } + decoder->input = SAA7191_INPUT_COMPOSITE; + decoder->norm = V4L2_STD_PAL; + + err = saa7191_autodetect_norm(sd); + if (err && (err != -EBUSY)) + printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); return 0; } -static struct i2c_driver i2c_driver_saa7191 = { - .driver = { - .name = "saa7191", - }, - .id = I2C_DRIVERID_SAA7191, - .attach_adapter = saa7191_probe, - .detach_client = saa7191_detach, - .command = saa7191_command -}; - -static int saa7191_init(void) +static int saa7191_remove(struct i2c_client *client) { - return i2c_add_driver(&i2c_driver_saa7191); -} + struct v4l2_subdev *sd = i2c_get_clientdata(client); -static void saa7191_exit(void) -{ - i2c_del_driver(&i2c_driver_saa7191); + v4l2_device_unregister_subdev(sd); + kfree(to_saa7191(sd)); + return 0; } -module_init(saa7191_init); -module_exit(saa7191_exit); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id saa7191_id[] = { + { "saa7191", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa7191_id); + +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa7191", + .probe = saa7191_probe, + .remove = saa7191_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = saa7191_id, +#endif +}; diff --git a/linux/drivers/media/video/saa7191.h b/linux/drivers/media/video/saa7191.h index a2310da19..803c74d60 100644 --- a/linux/drivers/media/video/saa7191.h +++ b/linux/drivers/media/video/saa7191.h @@ -176,11 +176,9 @@ #define SAA7191_INPUT_COMPOSITE 0 #define SAA7191_INPUT_SVIDEO 1 -#define SAA7191_NORM_AUTO 0 #define SAA7191_NORM_PAL 1 #define SAA7191_NORM_NTSC 2 #define SAA7191_NORM_SECAM 3 -#define SAA7191_NORM_AUTO_EXT 4 /* extended auto-detection */ struct saa7191_status { /* 0=no signal, 1=signal detected */ @@ -232,24 +230,16 @@ struct saa7191_status { #define SAA7191_VNR_MAX 0x03 #define SAA7191_VNR_DEFAULT 0x00 -#define SAA7191_CONTROL_BANDPASS 0 -#define SAA7191_CONTROL_BANDPASS_WEIGHT 1 -#define SAA7191_CONTROL_CORING 2 -#define SAA7191_CONTROL_FORCE_COLOUR 3 /* boolean */ -#define SAA7191_CONTROL_CHROMA_GAIN 4 -#define SAA7191_CONTROL_HUE 5 -#define SAA7191_CONTROL_VTRC 6 /* boolean */ -#define SAA7191_CONTROL_LUMA_DELAY 7 -#define SAA7191_CONTROL_VNR 8 - -struct saa7191_control { - u8 type; - s32 value; -}; +#define SAA7191_CONTROL_BANDPASS (V4L2_CID_PRIVATE_BASE + 0) +#define SAA7191_CONTROL_BANDPASS_WEIGHT (V4L2_CID_PRIVATE_BASE + 1) +#define SAA7191_CONTROL_CORING (V4L2_CID_PRIVATE_BASE + 2) +#define SAA7191_CONTROL_FORCE_COLOUR (V4L2_CID_PRIVATE_BASE + 3) +#define SAA7191_CONTROL_CHROMA_GAIN (V4L2_CID_PRIVATE_BASE + 4) +#define SAA7191_CONTROL_VTRC (V4L2_CID_PRIVATE_BASE + 5) +#define SAA7191_CONTROL_LUMA_DELAY (V4L2_CID_PRIVATE_BASE + 6) +#define SAA7191_CONTROL_VNR (V4L2_CID_PRIVATE_BASE + 7) #define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status) #define DECODER_SAA7191_SET_NORM _IOW('d', 196, int) -#define DECODER_SAA7191_GET_CONTROL _IOR('d', 197, struct saa7191_control) -#define DECODER_SAA7191_SET_CONTROL _IOW('d', 198, struct saa7191_control) #endif diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index e079a343a..230299801 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -25,7 +25,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-chip-ident.h> -#include <linux/video_decoder.h> #include "compat.h" #define dbgarg(cmd, fmt, arg...) \ @@ -277,19 +276,6 @@ static const char *v4l2_ioctls[] = { #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) static const char *v4l2_int_ioctls[] = { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES", - [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS", - [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM", - [_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT", - [_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT", - [_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT", - [_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE", - [_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO", - [_IOC_NR(DECODER_INIT)] = "DECODER_INIT", - [_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS", - [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", -#endif [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 349ef053f..ba4e8b97d 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -8,6 +8,12 @@ * * Based on the previous version of the driver for 2.4 kernels by: * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> + * + * v4l2_device/v4l2_subdev conversion by: + * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl> + * + * Note: this conversion is untested! Please contact the linux-media + * mailinglist if you can test this, together with the test results. */ /* @@ -33,12 +39,10 @@ #include <linux/kmod.h> #include <linux/i2c.h> -#include <linux/i2c-algo-sgi.h> #include <linux/videodev2.h> -#include <media/v4l2-common.h> +#include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> -#include <linux/video_decoder.h> #include <linux/mutex.h> #include <asm/paccess.h> @@ -139,13 +143,23 @@ MODULE_LICENSE("GPL"); #define VINO_DATA_NORM_PAL 1 #define VINO_DATA_NORM_SECAM 2 #define VINO_DATA_NORM_D1 3 -/* The following are special entries that can be used to - * autodetect the norm. */ -#define VINO_DATA_NORM_AUTO 0xfe -#define VINO_DATA_NORM_AUTO_EXT 0xff #define VINO_DATA_NORM_COUNT 4 +/* I2C controller flags */ +#define SGI_I2C_FORCE_IDLE (0 << 0) +#define SGI_I2C_NOT_IDLE (1 << 0) +#define SGI_I2C_WRITE (0 << 1) +#define SGI_I2C_READ (1 << 1) +#define SGI_I2C_RELEASE_BUS (0 << 2) +#define SGI_I2C_HOLD_BUS (1 << 2) +#define SGI_I2C_XFER_DONE (0 << 4) +#define SGI_I2C_XFER_BUSY (1 << 4) +#define SGI_I2C_ACK (0 << 5) +#define SGI_I2C_NACK (1 << 5) +#define SGI_I2C_BUS_OK (0 << 7) +#define SGI_I2C_BUS_ERR (1 << 7) + /* Internal data structure definitions */ struct vino_input { @@ -289,22 +303,20 @@ struct vino_channel_settings { struct vino_interrupt_data int_data; /* V4L support */ - struct video_device *v4l_device; -}; - -struct vino_client { - /* the channel which owns this client: - * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */ - unsigned int owner; - struct i2c_client *driver; + struct video_device *vdev; }; struct vino_settings { + struct v4l2_device v4l2_dev; struct vino_channel_settings a; struct vino_channel_settings b; - struct vino_client decoder; - struct vino_client camera; + /* the channel which owns this client: + * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */ + unsigned int decoder_owner; + struct v4l2_subdev *decoder; + unsigned int camera_owner; + struct v4l2_subdev *camera; /* a lock for vino register access */ spinlock_t vino_lock; @@ -344,11 +356,16 @@ static struct sgi_vino *vino; static struct vino_settings *vino_drvdata; +#define camera_call(o, f, args...) \ + v4l2_subdev_call(vino_drvdata->camera, o, f, ##args) +#define decoder_call(o, f, args...) \ + v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args) + static const char *vino_driver_name = "vino"; static const char *vino_driver_description = "SGI VINO"; static const char *vino_bus_name = "GIO64 bus"; -static const char *vino_v4l_device_name_a = "SGI VINO Channel A"; -static const char *vino_v4l_device_name_b = "SGI VINO Channel B"; +static const char *vino_vdev_name_a = "SGI VINO Channel A"; +static const char *vino_vdev_name_b = "SGI VINO Channel B"; static void vino_capture_tasklet(unsigned long channel); @@ -360,11 +377,11 @@ static const struct vino_input vino_inputs[] = { .name = "Composite", .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - },{ + }, { .name = "S-Video", .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - },{ + }, { .name = "D1/IndyCam", .std = V4L2_STD_NTSC, } @@ -376,17 +393,17 @@ static const struct vino_data_format vino_data_formats[] = { .bpp = 1, .pixelformat = V4L2_PIX_FMT_GREY, .colorspace = V4L2_COLORSPACE_SMPTE170M, - },{ + }, { .description = "8-bit dithered RGB 3-3-2", .bpp = 1, .pixelformat = V4L2_PIX_FMT_RGB332, .colorspace = V4L2_COLORSPACE_SRGB, - },{ + }, { .description = "32-bit RGB", .bpp = 4, .pixelformat = V4L2_PIX_FMT_RGB32, .colorspace = V4L2_COLORSPACE_SRGB, - },{ + }, { .description = "YUV 4:2:2", .bpp = 2, .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped? @@ -417,7 +434,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_NTSC_HEIGHT / 2 - 1, .right = VINO_NTSC_WIDTH, }, - },{ + }, { .description = "PAL", .std = V4L2_STD_PAL, .fps_min = 5, @@ -439,7 +456,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_PAL_HEIGHT / 2 - 1, .right = VINO_PAL_WIDTH, }, - },{ + }, { .description = "SECAM", .std = V4L2_STD_SECAM, .fps_min = 5, @@ -461,7 +478,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_PAL_HEIGHT / 2 - 1, .right = VINO_PAL_WIDTH, }, - },{ + }, { .description = "NTSC/D1", .std = V4L2_STD_NTSC, .fps_min = 6, @@ -497,9 +514,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = 1, .step = 1, .default_value = INDYCAM_AGC_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_AGC, 0 }, - },{ + }, { .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Automatic White Balance", @@ -507,9 +522,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = 1, .step = 1, .default_value = INDYCAM_AWB_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_AWB, 0 }, - },{ + }, { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gain", @@ -517,29 +530,23 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_GAIN_MAX, .step = 1, .default_value = INDYCAM_GAIN_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_GAIN, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE, + }, { + .id = INDYCAM_CONTROL_RED_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Red Saturation", .minimum = INDYCAM_RED_SATURATION_MIN, .maximum = INDYCAM_RED_SATURATION_MAX, .step = 1, .default_value = INDYCAM_RED_SATURATION_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_RED_SATURATION, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 1, + }, { + .id = INDYCAM_CONTROL_BLUE_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Blue Saturation", .minimum = INDYCAM_BLUE_SATURATION_MIN, .maximum = INDYCAM_BLUE_SATURATION_MAX, .step = 1, .default_value = INDYCAM_BLUE_SATURATION_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_BLUE_SATURATION, 0 }, - },{ + }, { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Red Balance", @@ -547,9 +554,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_RED_BALANCE_MAX, .step = 1, .default_value = INDYCAM_RED_BALANCE_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_RED_BALANCE, 0 }, - },{ + }, { .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Blue Balance", @@ -557,9 +562,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_BLUE_BALANCE_MAX, .step = 1, .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 }, - },{ + }, { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Shutter Control", @@ -567,9 +570,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_SHUTTER_MAX, .step = 1, .default_value = INDYCAM_SHUTTER_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_SHUTTER, 0 }, - },{ + }, { .id = V4L2_CID_GAMMA, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gamma", @@ -577,8 +578,6 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_GAMMA_MAX, .step = 1, .default_value = INDYCAM_GAMMA_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_GAMMA, 0 }, } }; @@ -593,209 +592,73 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { .maximum = SAA7191_HUE_MAX, .step = 1, .default_value = SAA7191_HUE_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_HUE, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE, + }, { + .id = SAA7191_CONTROL_BANDPASS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Bandpass", .minimum = SAA7191_BANDPASS_MIN, .maximum = SAA7191_BANDPASS_MAX, .step = 1, .default_value = SAA7191_BANDPASS_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_BANDPASS, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 1, + }, { + .id = SAA7191_CONTROL_BANDPASS_WEIGHT, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Bandpass Weight", .minimum = SAA7191_BANDPASS_WEIGHT_MIN, .maximum = SAA7191_BANDPASS_WEIGHT_MAX, .step = 1, .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 2, + }, { + .id = SAA7191_CONTROL_CORING, .type = V4L2_CTRL_TYPE_INTEGER, .name = "HF Luminance Coring", .minimum = SAA7191_CORING_MIN, .maximum = SAA7191_CORING_MAX, .step = 1, .default_value = SAA7191_CORING_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_CORING, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 3, + }, { + .id = SAA7191_CONTROL_FORCE_COLOUR, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Force Colour", .minimum = SAA7191_FORCE_COLOUR_MIN, .maximum = SAA7191_FORCE_COLOUR_MAX, .step = 1, .default_value = SAA7191_FORCE_COLOUR_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 4, + }, { + .id = SAA7191_CONTROL_CHROMA_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Chrominance Gain Control", .minimum = SAA7191_CHROMA_GAIN_MIN, .maximum = SAA7191_CHROMA_GAIN_MAX, .step = 1, .default_value = SAA7191_CHROMA_GAIN_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 5, + }, { + .id = SAA7191_CONTROL_VTRC, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "VTR Time Constant", .minimum = SAA7191_VTRC_MIN, .maximum = SAA7191_VTRC_MAX, .step = 1, .default_value = SAA7191_VTRC_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_VTRC, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 6, + }, { + .id = SAA7191_CONTROL_LUMA_DELAY, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Delay Compensation", .minimum = SAA7191_LUMA_DELAY_MIN, .maximum = SAA7191_LUMA_DELAY_MAX, .step = 1, .default_value = SAA7191_LUMA_DELAY_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 7, + }, { + .id = SAA7191_CONTROL_VNR, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Vertical Noise Reduction", .minimum = SAA7191_VNR_MIN, .maximum = SAA7191_VNR_MAX, .step = 1, .default_value = SAA7191_VNR_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_VNR, 0 }, - } -}; - -/* VINO I2C bus functions */ - -unsigned i2c_vino_getctrl(void *data) -{ - return vino->i2c_control; -} - -void i2c_vino_setctrl(void *data, unsigned val) -{ - vino->i2c_control = val; -} - -unsigned i2c_vino_rdata(void *data) -{ - return vino->i2c_data; -} - -void i2c_vino_wdata(void *data, unsigned val) -{ - vino->i2c_data = val; -} - -static struct i2c_algo_sgi_data i2c_sgi_vino_data = -{ - .getctrl = &i2c_vino_getctrl, - .setctrl = &i2c_vino_setctrl, - .rdata = &i2c_vino_rdata, - .wdata = &i2c_vino_wdata, - .xfer_timeout = 200, - .ack_timeout = 1000, -}; - -/* - * There are two possible clients on VINO I2C bus, so we limit usage only - * to them. - */ -static int i2c_vino_client_reg(struct i2c_client *client) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - switch (client->driver->id) { - case I2C_DRIVERID_SAA7191: - if (vino_drvdata->decoder.driver) - ret = -EBUSY; - else - vino_drvdata->decoder.driver = client; - break; - case I2C_DRIVERID_INDYCAM: - if (vino_drvdata->camera.driver) - ret = -EBUSY; - else - vino_drvdata->camera.driver = client; - break; - default: - ret = -ENODEV; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - -static int i2c_vino_client_unreg(struct i2c_client *client) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (client == vino_drvdata->decoder.driver) { - if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL) - ret = -EBUSY; - else - vino_drvdata->decoder.driver = NULL; - } else if (client == vino_drvdata->camera.driver) { - if (vino_drvdata->camera.owner != VINO_NO_CHANNEL) - ret = -EBUSY; - else - vino_drvdata->camera.driver = NULL; } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - -static struct i2c_adapter vino_i2c_adapter = -{ - .name = "VINO I2C bus", - .id = I2C_HW_SGI_VINO, - .algo_data = &i2c_sgi_vino_data, - .client_register = &i2c_vino_client_reg, - .client_unregister = &i2c_vino_client_unreg, }; -static int vino_i2c_add_bus(void) -{ - return i2c_sgi_add_bus(&vino_i2c_adapter); -} - -static int vino_i2c_del_bus(void) -{ - return i2c_del_adapter(&vino_i2c_adapter); -} - -static int i2c_camera_command(unsigned int cmd, void *arg) -{ - return vino_drvdata->camera.driver-> - driver->command(vino_drvdata->camera.driver, - cmd, arg); -} - -static int i2c_decoder_command(unsigned int cmd, void *arg) -{ - return vino_drvdata->decoder.driver-> - driver->command(vino_drvdata->decoder.driver, - cmd, arg); -} - /* VINO framebuffer/DMA descriptor management */ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, @@ -1741,6 +1604,184 @@ static inline void vino_set_default_framerate(struct vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max); } +/* VINO I2C bus functions */ + +struct i2c_algo_sgi_data { + void *data; /* private data for lowlevel routines */ + unsigned (*getctrl)(void *data); + void (*setctrl)(void *data, unsigned val); + unsigned (*rdata)(void *data); + void (*wdata)(void *data, unsigned val); + + int xfer_timeout; + int ack_timeout; +}; + +static int wait_xfer_done(struct i2c_algo_sgi_data *adap) +{ + int i; + + for (i = 0; i < adap->xfer_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int wait_ack(struct i2c_algo_sgi_data *adap) +{ + int i; + + if (wait_xfer_done(adap)) + return -ETIMEDOUT; + for (i = 0; i < adap->ack_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int force_idle(struct i2c_algo_sgi_data *adap) +{ + int i; + + adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE); + for (i = 0; i < adap->xfer_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0) + goto out; + udelay(1); + } + return -ETIMEDOUT; +out: + if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR) + return -EIO; + return 0; +} + +static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr, + int rd) +{ + if (rd) + adap->setctrl(adap->data, SGI_I2C_NOT_IDLE); + /* Check if bus is idle, eventually force it to do so */ + if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) + if (force_idle(adap)) + return -EIO; + /* Write out the i2c chip address and specify operation */ + adap->setctrl(adap->data, + SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE); + if (rd) + addr |= 1; + adap->wdata(adap->data, addr); + if (wait_ack(adap)) + return -EIO; + return 0; +} + +static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + adap->setctrl(adap->data, + SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE); + for (i = 0; i < len; i++) { + if (wait_xfer_done(adap)) + return -EIO; + buf[i] = adap->rdata(adap->data); + } + adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE); + + return 0; + +} + +static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + /* We are already in write state */ + for (i = 0; i < len; i++) { + adap->wdata(adap->data, buf[i]); + if (wait_ack(adap)) + return -EIO; + } + return 0; +} + +static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, + int num) +{ + struct i2c_algo_sgi_data *adap = i2c_adap->algo_data; + struct i2c_msg *p; + int i, err = 0; + + for (i = 0; !err && i < num; i++) { + p = &msgs[i]; + err = do_address(adap, p->addr, p->flags & I2C_M_RD); + if (err || !p->len) + continue; + if (p->flags & I2C_M_RD) + err = i2c_read(adap, p->buf, p->len); + else + err = i2c_write(adap, p->buf, p->len); + } + + return (err < 0) ? err : i; +} + +static u32 sgi_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm sgi_algo = { + .master_xfer = sgi_xfer, + .functionality = sgi_func, +}; + +static unsigned i2c_vino_getctrl(void *data) +{ + return vino->i2c_control; +} + +static void i2c_vino_setctrl(void *data, unsigned val) +{ + vino->i2c_control = val; +} + +static unsigned i2c_vino_rdata(void *data) +{ + return vino->i2c_data; +} + +static void i2c_vino_wdata(void *data, unsigned val) +{ + vino->i2c_data = val; +} + +static struct i2c_algo_sgi_data i2c_sgi_vino_data = { + .getctrl = &i2c_vino_getctrl, + .setctrl = &i2c_vino_setctrl, + .rdata = &i2c_vino_rdata, + .wdata = &i2c_vino_wdata, + .xfer_timeout = 200, + .ack_timeout = 1000, +}; + +static struct i2c_adapter vino_i2c_adapter = { + .name = "VINO I2C bus", + .id = I2C_HW_SGI_VINO, + .algo = &sgi_algo, + .algo_data = &i2c_sgi_vino_data, + .owner = THIS_MODULE, +}; + /* * Prepare VINO for DMA transfer... * (execute only with vino_lock and input_lock locked) @@ -2494,86 +2535,15 @@ static int vino_get_saa7191_input(int input) } } -static int vino_get_saa7191_norm(unsigned int data_norm) -{ - switch (data_norm) { - case VINO_DATA_NORM_AUTO: - return SAA7191_NORM_AUTO; - case VINO_DATA_NORM_AUTO_EXT: - return SAA7191_NORM_AUTO_EXT; - case VINO_DATA_NORM_PAL: - return SAA7191_NORM_PAL; - case VINO_DATA_NORM_NTSC: - return SAA7191_NORM_NTSC; - case VINO_DATA_NORM_SECAM: - return SAA7191_NORM_SECAM; - default: - printk(KERN_ERR "VINO: vino_get_saa7191_norm(): " - "invalid norm!\n"); - return -1; - } -} - -static int vino_get_from_saa7191_norm(int saa7191_norm) -{ - switch (saa7191_norm) { - case SAA7191_NORM_PAL: - return VINO_DATA_NORM_PAL; - case SAA7191_NORM_NTSC: - return VINO_DATA_NORM_NTSC; - case SAA7191_NORM_SECAM: - return VINO_DATA_NORM_SECAM; - default: - printk(KERN_ERR "VINO: vino_get_from_saa7191_norm(): " - "invalid norm!\n"); - return VINO_DATA_NORM_NONE; - } -} - -static int vino_saa7191_set_norm(unsigned int *data_norm) -{ - int saa7191_norm, new_data_norm; - int err = 0; - - saa7191_norm = vino_get_saa7191_norm(*data_norm); - - err = i2c_decoder_command(DECODER_SAA7191_SET_NORM, - &saa7191_norm); - if (err) - goto out; - - if ((*data_norm == VINO_DATA_NORM_AUTO) - || (*data_norm == VINO_DATA_NORM_AUTO_EXT)) { - struct saa7191_status status; - - err = i2c_decoder_command(DECODER_SAA7191_GET_STATUS, - &status); - if (err) - goto out; - - new_data_norm = - vino_get_from_saa7191_norm(status.norm); - if (new_data_norm == VINO_DATA_NORM_NONE) { - err = -EINVAL; - goto out; - } - - *data_norm = (unsigned int)new_data_norm; - } - -out: - return err; -} - /* execute with input_lock locked */ static int vino_is_input_owner(struct vino_channel_settings *vcs) { switch(vcs->input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: - return (vino_drvdata->decoder.owner == vcs->channel); + return vino_drvdata->decoder_owner == vcs->channel; case VINO_INPUT_D1: - return (vino_drvdata->camera.owner == vcs->channel); + return vino_drvdata->camera_owner == vcs->channel; default: return 0; } @@ -2589,23 +2559,22 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) spin_lock_irqsave(&vino_drvdata->input_lock, flags); /* First try D1 and then SAA7191 */ - if (vino_drvdata->camera.driver - && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) { - i2c_use_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = vcs->channel; + if (vino_drvdata->camera + && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) { + vino_drvdata->camera_owner = vcs->channel; vcs->input = VINO_INPUT_D1; vcs->data_norm = VINO_DATA_NORM_D1; - } else if (vino_drvdata->decoder.driver - && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { - int input, data_norm; - int saa7191_input; + } else if (vino_drvdata->decoder + && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) { + int input; + int data_norm; + v4l2_std_id norm; + struct v4l2_routing route = { 0, 0 }; - i2c_use_client(vino_drvdata->decoder.driver); input = VINO_INPUT_COMPOSITE; - saa7191_input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(DECODER_SET_INPUT, - &saa7191_input); + route.input = vino_get_saa7191_input(input); + ret = decoder_call(video, s_routing, &route); if (ret) { ret = -EINVAL; goto out; @@ -2616,12 +2585,15 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - data_norm = VINO_DATA_NORM_AUTO_EXT; - - ret = vino_saa7191_set_norm(&data_norm); - if ((ret == -EBUSY) || (ret == -EAGAIN)) { - data_norm = VINO_DATA_NORM_PAL; - ret = vino_saa7191_set_norm(&data_norm); + ret = decoder_call(video, querystd, &norm); + if (!ret) { + for (data_norm = 0; data_norm < 3; data_norm++) { + if (vino_data_norms[data_norm].std & norm) + break; + } + if (data_norm == 3) + data_norm = VINO_DATA_NORM_PAL; + ret = decoder_call(tuner, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2631,7 +2603,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) goto out; } - vino_drvdata->decoder.owner = vcs->channel; + vino_drvdata->decoder_owner = vcs->channel; vcs->input = input; vcs->data_norm = data_norm; @@ -2676,25 +2648,24 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) switch (input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: - if (!vino_drvdata->decoder.driver) { + if (!vino_drvdata->decoder) { ret = -EINVAL; goto out; } - if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->decoder.driver); - vino_drvdata->decoder.owner = vcs->channel; + if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) { + vino_drvdata->decoder_owner = vcs->channel; } - if (vino_drvdata->decoder.owner == vcs->channel) { + if (vino_drvdata->decoder_owner == vcs->channel) { int data_norm; - int saa7191_input; + v4l2_std_id norm; + struct v4l2_routing route = { 0, 0 }; - saa7191_input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(DECODER_SET_INPUT, - &saa7191_input); + route.input = vino_get_saa7191_input(input); + ret = decoder_call(video, s_routing, &route); if (ret) { - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; ret = -EINVAL; goto out; } @@ -2704,18 +2675,21 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - data_norm = VINO_DATA_NORM_AUTO_EXT; - - ret = vino_saa7191_set_norm(&data_norm); - if ((ret == -EBUSY) || (ret == -EAGAIN)) { - data_norm = VINO_DATA_NORM_PAL; - ret = vino_saa7191_set_norm(&data_norm); + ret = decoder_call(video, querystd, &norm); + if (!ret) { + for (data_norm = 0; data_norm < 3; data_norm++) { + if (vino_data_norms[data_norm].std & norm) + break; + } + if (data_norm == 3) + data_norm = VINO_DATA_NORM_PAL; + ret = decoder_call(tuner, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); if (ret) { - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; ret = -EINVAL; goto out; } @@ -2732,37 +2706,31 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) vcs->data_norm = vcs2->data_norm; } - if (vino_drvdata->camera.owner == vcs->channel) { + if (vino_drvdata->camera_owner == vcs->channel) { /* Transfer the ownership or release the input */ if (vcs2->input == VINO_INPUT_D1) { - vino_drvdata->camera.owner = vcs2->channel; + vino_drvdata->camera_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata-> - camera.driver); - vino_drvdata->camera.owner = VINO_NO_CHANNEL; + vino_drvdata->camera_owner = VINO_NO_CHANNEL; } } break; case VINO_INPUT_D1: - if (!vino_drvdata->camera.driver) { + if (!vino_drvdata->camera) { ret = -EINVAL; goto out; } - if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = vcs->channel; - } + if (vino_drvdata->camera_owner == VINO_NO_CHANNEL) + vino_drvdata->camera_owner = vcs->channel; - if (vino_drvdata->decoder.owner == vcs->channel) { + if (vino_drvdata->decoder_owner == vcs->channel) { /* Transfer the ownership or release the input */ if ((vcs2->input == VINO_INPUT_COMPOSITE) || (vcs2->input == VINO_INPUT_SVIDEO)) { - vino_drvdata->decoder.owner = vcs2->channel; + vino_drvdata->decoder_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata-> - decoder.driver); - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; } } @@ -2799,20 +2767,18 @@ static void vino_release_input(struct vino_channel_settings *vcs) /* Release ownership of the channel * and if the other channel takes input from * the same source, transfer the ownership */ - if (vino_drvdata->camera.owner == vcs->channel) { + if (vino_drvdata->camera_owner == vcs->channel) { if (vcs2->input == VINO_INPUT_D1) { - vino_drvdata->camera.owner = vcs2->channel; + vino_drvdata->camera_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = VINO_NO_CHANNEL; + vino_drvdata->camera_owner = VINO_NO_CHANNEL; } - } else if (vino_drvdata->decoder.owner == vcs->channel) { + } else if (vino_drvdata->decoder_owner == vcs->channel) { if ((vcs2->input == VINO_INPUT_COMPOSITE) || (vcs2->input == VINO_INPUT_SVIDEO)) { - vino_drvdata->decoder.owner = vcs2->channel; + vino_drvdata->decoder_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->decoder.driver); - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; } } vcs->input = VINO_INPUT_NONE; @@ -2833,18 +2799,16 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, switch (vcs->input) { case VINO_INPUT_D1: /* only one "norm" supported */ - if ((data_norm != VINO_DATA_NORM_D1) - && (data_norm != VINO_DATA_NORM_AUTO) - && (data_norm != VINO_DATA_NORM_AUTO_EXT)) + if (data_norm != VINO_DATA_NORM_D1) return -EINVAL; break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { + v4l2_std_id norm; + if ((data_norm != VINO_DATA_NORM_PAL) && (data_norm != VINO_DATA_NORM_NTSC) - && (data_norm != VINO_DATA_NORM_SECAM) - && (data_norm != VINO_DATA_NORM_AUTO) - && (data_norm != VINO_DATA_NORM_AUTO_EXT)) + && (data_norm != VINO_DATA_NORM_SECAM)) return -EINVAL; spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags); @@ -2852,7 +2816,8 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, /* Don't hold spinlocks while setting norm * as it may take a while... */ - err = vino_saa7191_set_norm(&data_norm); + norm = vino_data_norms[data_norm].std; + err = decoder_call(tuner, s_std, norm); spin_lock_irqsave(&vino_drvdata->input_lock, *flags); @@ -2888,41 +2853,13 @@ static int vino_find_data_format(__u32 pixelformat) return VINO_DATA_FMT_NONE; } -static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) -{ - int data_norm = VINO_DATA_NORM_NONE; - unsigned long flags; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - switch(vcs->input) { - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: - if (index == 0) { - data_norm = VINO_DATA_NORM_PAL; - } else if (index == 1) { - data_norm = VINO_DATA_NORM_NTSC; - } else if (index == 2) { - data_norm = VINO_DATA_NORM_SECAM; - } - break; - case VINO_INPUT_D1: - if (index == 0) { - data_norm = VINO_DATA_NORM_D1; - } - break; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return data_norm; -} - -static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) +static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) { int input = VINO_INPUT_NONE; unsigned long flags; spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { + if (vino_drvdata->decoder && vino_drvdata->camera) { switch (index) { case 0: input = VINO_INPUT_COMPOSITE; @@ -2934,7 +2871,7 @@ static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) input = VINO_INPUT_D1; break; } - } else if (vino_drvdata->decoder.driver) { + } else if (vino_drvdata->decoder) { switch (index) { case 0: input = VINO_INPUT_COMPOSITE; @@ -2943,7 +2880,7 @@ static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) input = VINO_INPUT_SVIDEO; break; } - } else if (vino_drvdata->camera.driver) { + } else if (vino_drvdata->camera) { switch (index) { case 0: input = VINO_INPUT_D1; @@ -2961,7 +2898,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) __u32 index = 0; // FIXME: detect when no inputs available - if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { + if (vino_drvdata->decoder && vino_drvdata->camera) { switch (vcs->input) { case VINO_INPUT_COMPOSITE: index = 0; @@ -2973,7 +2910,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) index = 2; break; } - } else if (vino_drvdata->decoder.driver) { + } else if (vino_drvdata->decoder) { switch (vcs->input) { case VINO_INPUT_COMPOSITE: index = 0; @@ -2982,7 +2919,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) index = 1; break; } - } else if (vino_drvdata->camera.driver) { + } else if (vino_drvdata->camera) { switch (vcs->input) { case VINO_INPUT_D1: index = 0; @@ -2995,7 +2932,8 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) /* V4L2 ioctls */ -static void vino_v4l2_querycap(struct v4l2_capability *cap) +static int vino_querycap(struct file *file, void *__fh, + struct v4l2_capability *cap) { memset(cap, 0, sizeof(struct v4l2_capability)); @@ -3007,16 +2945,18 @@ static void vino_v4l2_querycap(struct v4l2_capability *cap) V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE + return 0; } -static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, +static int vino_enum_input(struct file *file, void *__fh, struct v4l2_input *i) { + struct vino_channel_settings *vcs = video_drvdata(file); __u32 index = i->index; int input; dprintk("requested index = %d\n", index); - input = vino_enum_input(vcs, index); + input = vino_int_enum_input(vcs, index); if (input == VINO_INPUT_NONE) return -EINVAL; @@ -3027,20 +2967,15 @@ static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, i->std = vino_inputs[input].std; strcpy(i->name, vino_inputs[input].name); - if ((input == VINO_INPUT_COMPOSITE) - || (input == VINO_INPUT_SVIDEO)) { - struct saa7191_status status; - i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); - i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL; - i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR; - } - + if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO) + decoder_call(video, g_input_status, &i->status); return 0; } -static int vino_v4l2_g_input(struct vino_channel_settings *vcs, +static int vino_g_input(struct file *file, void *__fh, unsigned int *i) { + struct vino_channel_settings *vcs = video_drvdata(file); __u32 index; int input; unsigned long flags; @@ -3061,52 +2996,24 @@ static int vino_v4l2_g_input(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_input(struct vino_channel_settings *vcs, - unsigned int *i) +static int vino_s_input(struct file *file, void *__fh, + unsigned int i) { + struct vino_channel_settings *vcs = video_drvdata(file); int input; - dprintk("requested input = %d\n", *i); + dprintk("requested input = %d\n", i); - input = vino_enum_input(vcs, *i); + input = vino_int_enum_input(vcs, i); if (input == VINO_INPUT_NONE) return -EINVAL; return vino_set_input(vcs, input); } -static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, - struct v4l2_standard *s) -{ - int index = s->index; - int data_norm; - - data_norm = vino_enum_data_norm(vcs, index); - dprintk("standard index = %d\n", index); - - if (data_norm == VINO_DATA_NORM_NONE) - return -EINVAL; - - dprintk("standard name = %s\n", - vino_data_norms[data_norm].description); - - memset(s, 0, sizeof(struct v4l2_standard)); - s->index = index; - - s->id = vino_data_norms[data_norm].std; - s->frameperiod.numerator = 1; - s->frameperiod.denominator = - vino_data_norms[data_norm].fps_max; - s->framelines = - vino_data_norms[data_norm].framelines; - strcpy(s->name, - vino_data_norms[data_norm].description); - - return 0; -} - -static int vino_v4l2_querystd(struct vino_channel_settings *vcs, +static int vino_querystd(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int err = 0; @@ -3118,19 +3025,7 @@ static int vino_v4l2_querystd(struct vino_channel_settings *vcs, break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_status status; - - i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); - - if (status.signal) { - if (status.signal_60hz) { - *std = V4L2_STD_NTSC; - } else { - *std = V4L2_STD_PAL | V4L2_STD_SECAM; - } - } else { - *std = vino_inputs[vcs->input].std; - } + decoder_call(video, querystd, std); break; } default: @@ -3142,9 +3037,10 @@ static int vino_v4l2_querystd(struct vino_channel_settings *vcs, return err; } -static int vino_v4l2_g_std(struct vino_channel_settings *vcs, +static int vino_g_std(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -3157,9 +3053,10 @@ static int vino_v4l2_g_std(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_std(struct vino_channel_settings *vcs, +static int vino_s_std(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int ret = 0; @@ -3180,12 +3077,7 @@ static int vino_v4l2_s_std(struct vino_channel_settings *vcs, if (vcs->input == VINO_INPUT_D1) goto out; - if (((*std) & V4L2_STD_PAL) - && ((*std) & V4L2_STD_NTSC) - && ((*std) & V4L2_STD_SECAM)) { - ret = vino_set_data_norm(vcs, VINO_DATA_NORM_AUTO_EXT, - &flags); - } else if ((*std) & V4L2_STD_PAL) { + if ((*std) & V4L2_STD_PAL) { ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL, &flags); } else if ((*std) & V4L2_STD_NTSC) { @@ -3211,185 +3103,152 @@ out: return ret; } -static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs, +static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_fmtdesc *fd) { enum v4l2_buf_type type = fd->type; int index = fd->index; + dprintk("format index = %d\n", index); - switch (fd->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if ((fd->index < 0) || - (fd->index >= VINO_DATA_FMT_COUNT)) - return -EINVAL; - dprintk("format name = %s\n", - vino_data_formats[index].description); - - memset(fd, 0, sizeof(struct v4l2_fmtdesc)); - fd->index = index; - fd->type = type; - fd->pixelformat = vino_data_formats[index].pixelformat; - strcpy(fd->description, vino_data_formats[index].description); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: + if ((fd->index < 0) || + (fd->index >= VINO_DATA_FMT_COUNT)) return -EINVAL; - } - + dprintk("format name = %s\n", + vino_data_formats[index].description); + + memset(fd, 0, sizeof(struct v4l2_fmtdesc)); + fd->index = index; + fd->type = type; + fd->pixelformat = vino_data_formats[index].pixelformat; + strcpy(fd->description, vino_data_formats[index].description); return 0; } -static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, +static int vino_try_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); struct vino_channel_settings tempvcs; unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; - - dprintk("requested: w = %d, h = %d\n", - pf->width, pf->height); - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + dprintk("requested: w = %d, h = %d\n", + pf->width, pf->height); - tempvcs.data_format = vino_find_data_format(pf->pixelformat); - if (tempvcs.data_format == VINO_DATA_FMT_NONE) { - tempvcs.data_format = VINO_DATA_FMT_GREY; - pf->pixelformat = - vino_data_formats[tempvcs.data_format]. - pixelformat; - } + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - /* data format must be set before clipping/scaling */ - vino_set_scaling(&tempvcs, pf->width, pf->height); + tempvcs.data_format = vino_find_data_format(pf->pixelformat); + if (tempvcs.data_format == VINO_DATA_FMT_NONE) { + tempvcs.data_format = VINO_DATA_FMT_GREY; + pf->pixelformat = + vino_data_formats[tempvcs.data_format]. + pixelformat; + } - dprintk("data format = %s\n", - vino_data_formats[tempvcs.data_format].description); + /* data format must be set before clipping/scaling */ + vino_set_scaling(&tempvcs, pf->width, pf->height); - pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) / - tempvcs.decimation; - pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) / - tempvcs.decimation; + dprintk("data format = %s\n", + vino_data_formats[tempvcs.data_format].description); - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = tempvcs.line_size; - pf->sizeimage = tempvcs.line_size * - (tempvcs.clipping.bottom - tempvcs.clipping.top) / - tempvcs.decimation; - pf->colorspace = - vino_data_formats[tempvcs.data_format].colorspace; + pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) / + tempvcs.decimation; + pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) / + tempvcs.decimation; - pf->priv = 0; - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = tempvcs.line_size; + pf->sizeimage = tempvcs.line_size * + (tempvcs.clipping.bottom - tempvcs.clipping.top) / + tempvcs.decimation; + pf->colorspace = + vino_data_formats[tempvcs.data_format].colorspace; + pf->priv = 0; return 0; } -static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, +static int vino_g_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - pf->width = (vcs->clipping.right - vcs->clipping.left) / - vcs->decimation; - pf->height = (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->pixelformat = - vino_data_formats[vcs->data_format].pixelformat; + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = vcs->line_size; - pf->sizeimage = vcs->line_size * - (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->colorspace = - vino_data_formats[vcs->data_format].colorspace; + pf->width = (vcs->clipping.right - vcs->clipping.left) / + vcs->decimation; + pf->height = (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->pixelformat = + vino_data_formats[vcs->data_format].pixelformat; - pf->priv = 0; + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = vcs->line_size; + pf->sizeimage = vcs->line_size * + (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->colorspace = + vino_data_formats[vcs->data_format].colorspace; - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->priv = 0; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } -static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, +static int vino_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); int data_format; unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - data_format = vino_find_data_format(pf->pixelformat); + data_format = vino_find_data_format(pf->pixelformat); - if (data_format == VINO_DATA_FMT_NONE) { - vcs->data_format = VINO_DATA_FMT_GREY; - pf->pixelformat = - vino_data_formats[vcs->data_format]. - pixelformat; - } else { - vcs->data_format = data_format; - } - - /* data format must be set before clipping/scaling */ - vino_set_scaling(vcs, pf->width, pf->height); + if (data_format == VINO_DATA_FMT_NONE) { + vcs->data_format = VINO_DATA_FMT_GREY; + pf->pixelformat = + vino_data_formats[vcs->data_format]. + pixelformat; + } else { + vcs->data_format = data_format; + } - dprintk("data format = %s\n", - vino_data_formats[vcs->data_format].description); + /* data format must be set before clipping/scaling */ + vino_set_scaling(vcs, pf->width, pf->height); - pf->width = vcs->clipping.right - vcs->clipping.left; - pf->height = vcs->clipping.bottom - vcs->clipping.top; + dprintk("data format = %s\n", + vino_data_formats[vcs->data_format].description); - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = vcs->line_size; - pf->sizeimage = vcs->line_size * - (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->colorspace = - vino_data_formats[vcs->data_format].colorspace; + pf->width = vcs->clipping.right - vcs->clipping.left; + pf->height = vcs->clipping.bottom - vcs->clipping.top; - pf->priv = 0; + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = vcs->line_size; + pf->sizeimage = vcs->line_size * + (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->colorspace = + vino_data_formats[vcs->data_format].colorspace; - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->priv = 0; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } -static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, +static int vino_cropcap(struct file *file, void *__fh, struct v4l2_cropcap *ccap) { + struct vino_channel_settings *vcs = video_drvdata(file); const struct vino_data_norm *norm; unsigned long flags; @@ -3419,9 +3278,10 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, +static int vino_g_crop(struct file *file, void *__fh, struct v4l2_crop *c) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (c->type) { @@ -3443,9 +3303,10 @@ static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, +static int vino_s_crop(struct file *file, void *__fh, struct v4l2_crop *c) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (c->type) { @@ -3465,9 +3326,10 @@ static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, +static int vino_g_parm(struct file *file, void *__fh, struct v4l2_streamparm *sp) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (sp->type) { @@ -3495,9 +3357,10 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, +static int vino_s_parm(struct file *file, void *__fh, struct v4l2_streamparm *sp) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (sp->type) { @@ -3528,9 +3391,10 @@ static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs, +static int vino_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *rb) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3610,9 +3474,10 @@ static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs, fb->id, fb->size, fb->data_size, fb->offset); } -static int vino_v4l2_querybuf(struct vino_channel_settings *vcs, +static int vino_querybuf(struct file *file, void *__fh, struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3645,9 +3510,10 @@ static int vino_v4l2_querybuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_qbuf(struct vino_channel_settings *vcs, +static int vino_qbuf(struct file *file, void *__fh, struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3683,10 +3549,11 @@ static int vino_v4l2_qbuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, - struct v4l2_buffer *b, - unsigned int nonblocking) +static int vino_dqbuf(struct file *file, void *__fh, + struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); + unsigned int nonblocking = file->f_flags & O_NONBLOCK; if (vcs->reading) return -EBUSY; @@ -3758,8 +3625,10 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_streamon(struct vino_channel_settings *vcs) +static int vino_streamon(struct file *file, void *__fh, + enum v4l2_buf_type i) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned int incoming; int ret; if (vcs->reading) @@ -3796,8 +3665,10 @@ static int vino_v4l2_streamon(struct vino_channel_settings *vcs) return 0; } -static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) +static int vino_streamoff(struct file *file, void *__fh, + enum v4l2_buf_type i) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3810,9 +3681,10 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) return 0; } -static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, +static int vino_queryctrl(struct file *file, void *__fh, struct v4l2_queryctrl *queryctrl) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -3859,9 +3731,10 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, return err; } -static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, +static int vino_g_ctrl(struct file *file, void *__fh, struct v4l2_control *control) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -3870,56 +3743,38 @@ static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, switch (vcs->input) { case VINO_INPUT_D1: { - struct indycam_control indycam_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == - control->id) { - goto found1; + if (vino_indycam_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found1: - indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; - - err = i2c_camera_command(DECODER_INDYCAM_GET_CONTROL, - &indycam_ctrl); - if (err) { - err = -EINVAL; + if (err) goto out; - } - control->value = indycam_ctrl.value; + err = camera_call(core, g_ctrl, control); + if (err) + err = -EINVAL; break; } case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_control saa7191_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == - control->id) { - goto found2; + if (vino_saa7191_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found2: - saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; - - err = i2c_decoder_command(DECODER_SAA7191_GET_CONTROL, - &saa7191_ctrl); - if (err) { - err = -EINVAL; + if (err) goto out; - } - control->value = saa7191_ctrl.value; + err = decoder_call(core, g_ctrl, control); + if (err) + err = -EINVAL; break; } default: @@ -3932,9 +3787,10 @@ out: return err; } -static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, +static int vino_s_ctrl(struct file *file, void *__fh, struct v4l2_control *control) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -3948,65 +3804,43 @@ static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, switch (vcs->input) { case VINO_INPUT_D1: { - struct indycam_control indycam_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == - control->id) { - if ((control->value >= - vino_indycam_v4l2_controls[i].minimum) - && (control->value <= - vino_indycam_v4l2_controls[i]. - maximum)) { - goto found1; - } else { - err = -ERANGE; - goto out; - } + if (vino_indycam_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - - err = -EINVAL; - goto out; - -found1: - indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; - indycam_ctrl.value = control->value; - - err = i2c_camera_command(DECODER_INDYCAM_SET_CONTROL, - &indycam_ctrl); + if (err) + goto out; + if (control->value < vino_indycam_v4l2_controls[i].minimum || + control->value > vino_indycam_v4l2_controls[i].maximum) { + err = -ERANGE; + goto out; + } + err = camera_call(core, s_ctrl, control); if (err) err = -EINVAL; break; } case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_control saa7191_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == - control->id) { - if ((control->value >= - vino_saa7191_v4l2_controls[i].minimum) - && (control->value <= - vino_saa7191_v4l2_controls[i]. - maximum)) { - goto found2; - } else { - err = -ERANGE; - goto out; - } + if (vino_saa7191_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found2: - saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; - saa7191_ctrl.value = control->value; + if (err) + goto out; + if (control->value < vino_saa7191_v4l2_controls[i].minimum || + control->value > vino_saa7191_v4l2_controls[i].maximum) { + err = -ERANGE; + goto out; + } - err = i2c_decoder_command(DECODER_SAA7191_SET_CONTROL, - &saa7191_ctrl); + err = decoder_call(core, s_ctrl, control); if (err) err = -EINVAL; break; @@ -4237,116 +4071,9 @@ over: ret = POLLIN | POLLRDNORM; error: - return ret; } -static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - -#ifdef VINO_DEBUG - switch (_IOC_TYPE(cmd)) { - case 'v': - dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd); - break; - case 'V': - dprintk("ioctl(): V4L2 %s (0x%08x)\n", - v4l2_ioctl_names[_IOC_NR(cmd)], cmd); - break; - default: - dprintk("ioctl(): unsupported command 0x%08x\n", cmd); - } -#endif - - switch (cmd) { - /* V4L2 interface */ - case VIDIOC_QUERYCAP: { - vino_v4l2_querycap(arg); - break; - } - case VIDIOC_ENUMINPUT: { - return vino_v4l2_enuminput(vcs, arg); - } - case VIDIOC_G_INPUT: { - return vino_v4l2_g_input(vcs, arg); - } - case VIDIOC_S_INPUT: { - return vino_v4l2_s_input(vcs, arg); - } - case VIDIOC_ENUMSTD: { - return vino_v4l2_enumstd(vcs, arg); - } - case VIDIOC_QUERYSTD: { - return vino_v4l2_querystd(vcs, arg); - } - case VIDIOC_G_STD: { - return vino_v4l2_g_std(vcs, arg); - } - case VIDIOC_S_STD: { - return vino_v4l2_s_std(vcs, arg); - } - case VIDIOC_ENUM_FMT: { - return vino_v4l2_enum_fmt(vcs, arg); - } - case VIDIOC_TRY_FMT: { - return vino_v4l2_try_fmt(vcs, arg); - } - case VIDIOC_G_FMT: { - return vino_v4l2_g_fmt(vcs, arg); - } - case VIDIOC_S_FMT: { - return vino_v4l2_s_fmt(vcs, arg); - } - case VIDIOC_CROPCAP: { - return vino_v4l2_cropcap(vcs, arg); - } - case VIDIOC_G_CROP: { - return vino_v4l2_g_crop(vcs, arg); - } - case VIDIOC_S_CROP: { - return vino_v4l2_s_crop(vcs, arg); - } - case VIDIOC_G_PARM: { - return vino_v4l2_g_parm(vcs, arg); - } - case VIDIOC_S_PARM: { - return vino_v4l2_s_parm(vcs, arg); - } - case VIDIOC_REQBUFS: { - return vino_v4l2_reqbufs(vcs, arg); - } - case VIDIOC_QUERYBUF: { - return vino_v4l2_querybuf(vcs, arg); - } - case VIDIOC_QBUF: { - return vino_v4l2_qbuf(vcs, arg); - } - case VIDIOC_DQBUF: { - return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK); - } - case VIDIOC_STREAMON: { - return vino_v4l2_streamon(vcs); - } - case VIDIOC_STREAMOFF: { - return vino_v4l2_streamoff(vcs); - } - case VIDIOC_QUERYCTRL: { - return vino_v4l2_queryctrl(vcs, arg); - } - case VIDIOC_G_CTRL: { - return vino_v4l2_g_ctrl(vcs, arg); - } - case VIDIOC_S_CTRL: { - return vino_v4l2_s_ctrl(vcs, arg); - } - default: - return -ENOIOCTLCMD; - } - - return 0; -} - static long vino_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -4356,7 +4083,7 @@ static long vino_ioctl(struct file *file, if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; - ret = video_usercopy(file, cmd, arg, vino_do_ioctl); + ret = video_ioctl2(file, cmd, arg); mutex_unlock(&vcs->mutex); @@ -4368,45 +4095,75 @@ static long vino_ioctl(struct file *file, /* __initdata */ static int vino_init_stage; +const struct v4l2_ioctl_ops vino_ioctl_ops = { + .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap, + .vidioc_querycap = vino_querycap, + .vidioc_enum_input = vino_enum_input, + .vidioc_g_input = vino_g_input, + .vidioc_s_input = vino_s_input, + .vidioc_g_std = vino_g_std, + .vidioc_s_std = vino_s_std, + .vidioc_querystd = vino_querystd, + .vidioc_cropcap = vino_cropcap, + .vidioc_s_crop = vino_s_crop, + .vidioc_g_crop = vino_g_crop, + .vidioc_s_parm = vino_s_parm, + .vidioc_g_parm = vino_g_parm, + .vidioc_reqbufs = vino_reqbufs, + .vidioc_querybuf = vino_querybuf, + .vidioc_qbuf = vino_qbuf, + .vidioc_dqbuf = vino_dqbuf, + .vidioc_streamon = vino_streamon, + .vidioc_streamoff = vino_streamoff, + .vidioc_queryctrl = vino_queryctrl, + .vidioc_g_ctrl = vino_g_ctrl, + .vidioc_s_ctrl = vino_s_ctrl, +}; + static const struct v4l2_file_operations vino_fops = { .owner = THIS_MODULE, .open = vino_open, .release = vino_close, - .ioctl = vino_ioctl, + .unlocked_ioctl = vino_ioctl, .mmap = vino_mmap, .poll = vino_poll, }; -static struct video_device v4l_device_template = { +static struct video_device vdev_template = { .name = "NOT SET", .fops = &vino_fops, + .ioctl_ops = &vino_ioctl_ops, + .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, .minor = -1, }; static void vino_module_cleanup(int stage) { switch(stage) { + case 11: + video_unregister_device(vino_drvdata->b.vdev); + vino_drvdata->b.vdev = NULL; case 10: - video_unregister_device(vino_drvdata->b.v4l_device); - vino_drvdata->b.v4l_device = NULL; + video_unregister_device(vino_drvdata->a.vdev); + vino_drvdata->a.vdev = NULL; case 9: - video_unregister_device(vino_drvdata->a.v4l_device); - vino_drvdata->a.v4l_device = NULL; + i2c_del_adapter(&vino_i2c_adapter); case 8: - vino_i2c_del_bus(); - case 7: free_irq(SGI_VINO_IRQ, NULL); + case 7: + if (vino_drvdata->b.vdev) { + video_device_release(vino_drvdata->b.vdev); + vino_drvdata->b.vdev = NULL; + } case 6: - if (vino_drvdata->b.v4l_device) { - video_device_release(vino_drvdata->b.v4l_device); - vino_drvdata->b.v4l_device = NULL; + if (vino_drvdata->a.vdev) { + video_device_release(vino_drvdata->a.vdev); + vino_drvdata->a.vdev = NULL; } case 5: - if (vino_drvdata->a.v4l_device) { - video_device_release(vino_drvdata->a.v4l_device); - vino_drvdata->a.v4l_device = NULL; - } - case 4: /* all entries in dma_cpu dummy table have the same address */ dma_unmap_single(NULL, vino_drvdata->dummy_desc_table.dma_cpu[0], @@ -4416,8 +4173,10 @@ static void vino_module_cleanup(int stage) (void *)vino_drvdata-> dummy_desc_table.dma_cpu, vino_drvdata->dummy_desc_table.dma); - case 3: + case 4: free_page(vino_drvdata->dummy_page); + case 3: + v4l2_device_unregister(&vino_drvdata->v4l2_dev); case 2: kfree(vino_drvdata); case 1: @@ -4472,6 +4231,7 @@ static int vino_probe(void) static int vino_init(void) { dma_addr_t dma_dummy_address; + int err; int i; vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL); @@ -4480,6 +4240,12 @@ static int vino_init(void) return -ENOMEM; } vino_init_stage++; + strlcpy(vino_drvdata->v4l2_dev.name, "vino", + sizeof(vino_drvdata->v4l2_dev.name)); + err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev); + if (err) + return err; + vino_init_stage++; /* create a dummy dma descriptor */ vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA); @@ -4546,25 +4312,27 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, spin_lock_init(&vcs->fb_queue.queue_lock); init_waitqueue_head(&vcs->fb_queue.frame_wait_queue); - vcs->v4l_device = video_device_alloc(); - if (!vcs->v4l_device) { + vcs->vdev = video_device_alloc(); + if (!vcs->vdev) { vino_module_cleanup(vino_init_stage); return -ENOMEM; } vino_init_stage++; - memcpy(vcs->v4l_device, &v4l_device_template, + memcpy(vcs->vdev, &vdev_template, sizeof(struct video_device)); - strcpy(vcs->v4l_device->name, name); - vcs->v4l_device->release = video_device_release; + strcpy(vcs->vdev->name, name); + vcs->vdev->release = video_device_release; + vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev; - video_set_drvdata(vcs->v4l_device, vcs); + video_set_drvdata(vcs->vdev, vcs); return 0; } static int __init vino_module_init(void) { + unsigned short addr[] = { 0, I2C_CLIENT_END }; int ret; printk(KERN_INFO "SGI VINO driver version %s\n", @@ -4584,12 +4352,12 @@ static int __init vino_module_init(void) spin_lock_init(&vino_drvdata->input_lock); ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A, - vino_v4l_device_name_a); + vino_vdev_name_a); if (ret) return ret; ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B, - vino_v4l_device_name_b); + vino_vdev_name_b); if (ret) return ret; @@ -4605,15 +4373,16 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = vino_i2c_add_bus(); + ret = i2c_add_adapter(&vino_i2c_adapter); if (ret) { printk(KERN_ERR "VINO I2C bus registration failed\n"); vino_module_cleanup(vino_init_stage); return ret; } + i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev); vino_init_stage++; - ret = video_register_device(vino_drvdata->a.v4l_device, + ret = video_register_device(vino_drvdata->a.vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { printk(KERN_ERR "VINO channel A Video4Linux-device " @@ -4623,7 +4392,7 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = video_register_device(vino_drvdata->b.v4l_device, + ret = video_register_device(vino_drvdata->b.vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { printk(KERN_ERR "VINO channel B Video4Linux-device " @@ -4633,10 +4402,12 @@ static int __init vino_module_init(void) } vino_init_stage++; -#ifdef MODULE - request_module("saa7191"); - request_module("indycam"); -#endif + addr[0] = 0x45; + vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, + "saa7191", "saa7191", addr); + addr[0] = 0x2b; + vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, + "indycam", "indycam", addr); dprintk("init complete!\n"); diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 8eda83b06..1560c1e4c 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1378,11 +1378,10 @@ setup_overlay (struct file *file, /* get the status of a buffer in the clients buffer queue */ static int -zoran_v4l2_buffer_status (struct file *file, +zoran_v4l2_buffer_status (struct zoran_fh *fh, struct v4l2_buffer *buf, int num) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; buf->flags = V4L2_BUF_FLAG_MAPPED; @@ -2502,7 +2501,7 @@ static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf int res; mutex_lock(&zr->resource_lock); - res = zoran_v4l2_buffer_status(file, buf, buf->index); + res = zoran_v4l2_buffer_status(fh, buf, buf->index); mutex_unlock(&zr->resource_lock); return res; @@ -2603,7 +2602,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) if (res) goto dqbuf_unlock_and_return; zr->v4l_sync_tail++; - res = zoran_v4l2_buffer_status(file, buf, num); + res = zoran_v4l2_buffer_status(fh, buf, num); break; case ZORAN_MAP_MODE_JPG_REC: @@ -2634,7 +2633,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = jpg_sync(file, &bs); if (res) goto dqbuf_unlock_and_return; - res = zoran_v4l2_buffer_status(file, buf, bs.frame); + res = zoran_v4l2_buffer_status(fh, buf, bs.frame); break; } |