Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb

* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (33 commits)
  V4L/DVB (3604): V4l printk fix
  V4L/DVB (3599c): Whitespace cleanups under Documentation/video4linux
  V4L/DVB (3599b): Whitespace cleanups under drivers/media
  V4L/DVB (3599a): Move drivers/usb/media to drivers/media/video
  V4L/DVB (3599): Implement new routing commands for wm8775 and cs53l32a.
  V4L/DVB (3598): Add bit algorithm adapter for the Conexant CX2341X boards.
  V4L/DVB (3597): Vivi: fix warning: implicit declaration of function 'in_interrupt'
  V4L/DVB (3588): Remove VIDIOC_G/S_AUDOUT from msp3400
  V4L/DVB (3587): Always wake thread after routing change.
  V4L/DVB (3584): Implement V4L2_TUNER_MODE_LANG1_LANG2 audio mode
  V4L/DVB (3582): Implement correct msp3400 input/output routing
  V4L/DVB (3581): Add new media/msp3400.h header containing the routing macros
  V4L/DVB (3580): Last round of msp3400 cleanups before adding routing commands
  V4L/DVB (3579): Move msp_modus to msp3400-kthreads, add JP and KR std detection
  V4L/DVB (3578): Make scart definitions easier to handle
  V4L/DVB (3577): Cleanup audio input handling
  V4L/DVB (3575): Cxusb: fix i2c debug messages for bluebird devices
  V4L/DVB (3574): Cxusb: fix debug messages
  V4L/DVB (3573): Cxusb: remove FIXME: comment in bluebird_patch_dvico_firmware_download
  V4L/DVB (3572): Cxusb: conditionalize gpio write for the medion box
  ...
This commit is contained in:
Linus Torvalds 2006-03-25 08:37:36 -08:00
commit 368d17e068
206 changed files with 7248 additions and 4786 deletions

View file

@ -1,7 +1,7 @@
c-qcam - Connectix Color QuickCam video4linux kernel driver c-qcam - Connectix Color QuickCam video4linux kernel driver
Copyright (C) 1999 Dave Forrest <drf5n@virginia.edu> Copyright (C) 1999 Dave Forrest <drf5n@virginia.edu>
released under GNU GPL. released under GNU GPL.
1999-12-08 Dave Forrest, written with kernel version 2.2.12 in mind 1999-12-08 Dave Forrest, written with kernel version 2.2.12 in mind
@ -45,21 +45,21 @@ configuration. The appropriate flags are:
CONFIG_PNP_PARPORT M for autoprobe.o IEEE1284 readback module CONFIG_PNP_PARPORT M for autoprobe.o IEEE1284 readback module
CONFIG_PRINTER_READBACK M for parport_probe.o IEEE1284 readback module CONFIG_PRINTER_READBACK M for parport_probe.o IEEE1284 readback module
CONFIG_VIDEO_DEV M for videodev.o video4linux module CONFIG_VIDEO_DEV M for videodev.o video4linux module
CONFIG_VIDEO_CQCAM M for c-qcam.o Color Quickcam module CONFIG_VIDEO_CQCAM M for c-qcam.o Color Quickcam module
With these flags, the kernel should compile and install the modules. With these flags, the kernel should compile and install the modules.
To record and monitor the compilation, I use: To record and monitor the compilation, I use:
(make zlilo ; \ (make zlilo ; \
make modules; \ make modules; \
make modules_install ; make modules_install ;
depmod -a ) &>log & depmod -a ) &>log &
less log # then a capital 'F' to watch the progress less log # then a capital 'F' to watch the progress
But that is my personal preference. But that is my personal preference.
2.2 Configuration 2.2 Configuration
The configuration requires module configuration and device The configuration requires module configuration and device
configuration. I like kmod or kerneld process with the configuration. I like kmod or kerneld process with the
/etc/modprobe.conf file so the modules can automatically load/unload as /etc/modprobe.conf file so the modules can automatically load/unload as
@ -68,7 +68,7 @@ using MAKEDEV, or need to be created. The following sections detail
these procedures. these procedures.
2.1 Module Configuration 2.1 Module Configuration
Using modules requires a bit of work to install and pass the Using modules requires a bit of work to install and pass the
parameters. Understand that entries in /etc/modprobe.conf of: parameters. Understand that entries in /etc/modprobe.conf of:
@ -128,9 +128,9 @@ system (CONFIG_PROC_FS), the parallel printer support
(CONFIG_PRINTER), the IEEE 1284 system,(CONFIG_PRINTER_READBACK), you (CONFIG_PRINTER), the IEEE 1284 system,(CONFIG_PRINTER_READBACK), you
should be able to read some identification from your quickcam with should be able to read some identification from your quickcam with
modprobe -v parport modprobe -v parport
modprobe -v parport_probe modprobe -v parport_probe
cat /proc/parport/PORTNUMBER/autoprobe cat /proc/parport/PORTNUMBER/autoprobe
Returns: Returns:
CLASS:MEDIA; CLASS:MEDIA;
MODEL:Color QuickCam 2.0; MODEL:Color QuickCam 2.0;
@ -140,7 +140,7 @@ Returns:
and well. A common problem is that the current driver does not and well. A common problem is that the current driver does not
reliably detect a c-qcam, even though one is attached. In this case, reliably detect a c-qcam, even though one is attached. In this case,
modprobe -v c-qcam modprobe -v c-qcam
or or
insmod -v c-qcam insmod -v c-qcam
@ -152,16 +152,16 @@ video4linux mailing list and archive for more current information.
3.1 Checklist: 3.1 Checklist:
Can you get an image? Can you get an image?
v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm
Is a working c-qcam connected to the port? Is a working c-qcam connected to the port?
grep ^ /proc/parport/?/autoprobe grep ^ /proc/parport/?/autoprobe
Do the /dev/video* files exist? Do the /dev/video* files exist?
ls -lad /dev/video ls -lad /dev/video
Is the c-qcam module loaded? Is the c-qcam module loaded?
modprobe -v c-qcam ; lsmod modprobe -v c-qcam ; lsmod
Does the camera work with alternate programs? cqcam, etc? Does the camera work with alternate programs? cqcam, etc?
@ -174,7 +174,7 @@ video4linux mailing list and archive for more current information.
isn't, you might try patching the c-qcam module to add a parport=xxx isn't, you might try patching the c-qcam module to add a parport=xxx
option as in the bw-qcam module so you can specify the parallel port: option as in the bw-qcam module so you can specify the parallel port:
insmod -v c-qcam parport=0 insmod -v c-qcam parport=0
And bypass the detection code, see ../../drivers/char/c-qcam.c and And bypass the detection code, see ../../drivers/char/c-qcam.c and
look for the 'qc_detect' code and call. look for the 'qc_detect' code and call.
@ -183,12 +183,12 @@ look for the 'qc_detect' code and call.
this work is documented at the video4linux2 site listed below. this work is documented at the video4linux2 site listed below.
9.0 --- A sample program using v4lgrabber, 9.0 --- A sample program using v4lgrabber,
This program is a simple image grabber that will copy a frame from the This program is a simple image grabber that will copy a frame from the
first video device, /dev/video0 to standard output in portable pixmap first video device, /dev/video0 to standard output in portable pixmap
format (.ppm) Using this like: 'v4lgrab | convert - c-qcam.jpg' format (.ppm) Using this like: 'v4lgrab | convert - c-qcam.jpg'
produced this picture of me at produced this picture of me at
http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
-------------------- 8< ---------------- 8< ----------------------------- -------------------- 8< ---------------- 8< -----------------------------
@ -202,8 +202,8 @@ produced this picture of me at
* Use as: * Use as:
* v4lgrab >image.ppm * v4lgrab >image.ppm
* *
* Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org> * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
* Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
* with minor modifications (Dave Forrest, drf5n@virginia.edu). * with minor modifications (Dave Forrest, drf5n@virginia.edu).
* *
*/ */
@ -225,55 +225,55 @@ produced this picture of me at
#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ #define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \
{ \ { \
switch (format) \ switch (format) \
{ \ { \
case VIDEO_PALETTE_GREY: \ case VIDEO_PALETTE_GREY: \
switch (depth) \ switch (depth) \
{ \ { \
case 4: \ case 4: \
case 6: \ case 6: \
case 8: \ case 8: \
(r) = (g) = (b) = (*buf++ << 8);\ (r) = (g) = (b) = (*buf++ << 8);\
break; \ break; \
\ \
case 16: \ case 16: \
(r) = (g) = (b) = \ (r) = (g) = (b) = \
*((unsigned short *) buf); \ *((unsigned short *) buf); \
buf += 2; \ buf += 2; \
break; \ break; \
} \ } \
break; \ break; \
\ \
\ \
case VIDEO_PALETTE_RGB565: \ case VIDEO_PALETTE_RGB565: \
{ \ { \
unsigned short tmp = *(unsigned short *)buf; \ unsigned short tmp = *(unsigned short *)buf; \
(r) = tmp&0xF800; \ (r) = tmp&0xF800; \
(g) = (tmp<<5)&0xFC00; \ (g) = (tmp<<5)&0xFC00; \
(b) = (tmp<<11)&0xF800; \ (b) = (tmp<<11)&0xF800; \
buf += 2; \ buf += 2; \
} \ } \
break; \ break; \
\ \
case VIDEO_PALETTE_RGB555: \ case VIDEO_PALETTE_RGB555: \
(r) = (buf[0]&0xF8)<<8; \ (r) = (buf[0]&0xF8)<<8; \
(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \
(b) = ((buf[1] << 2 ) & 0xF8)<<8; \ (b) = ((buf[1] << 2 ) & 0xF8)<<8; \
buf += 2; \ buf += 2; \
break; \ break; \
\ \
case VIDEO_PALETTE_RGB24: \ case VIDEO_PALETTE_RGB24: \
(r) = buf[0] << 8; (g) = buf[1] << 8; \ (r) = buf[0] << 8; (g) = buf[1] << 8; \
(b) = buf[2] << 8; \ (b) = buf[2] << 8; \
buf += 3; \ buf += 3; \
break; \ break; \
\ \
default: \ default: \
fprintf(stderr, \ fprintf(stderr, \
"Format %d not yet supported\n", \ "Format %d not yet supported\n", \
format); \ format); \
} \ } \
} }
int get_brightness_adj(unsigned char *image, long size, int *brightness) { int get_brightness_adj(unsigned char *image, long size, int *brightness) {
long i, tot = 0; long i, tot = 0;
@ -324,40 +324,40 @@ int main(int argc, char ** argv)
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.depth=6; vpic.depth=6;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.depth=4; vpic.depth=4;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
fprintf(stderr, "Unable to find a supported capture format.\n"); fprintf(stderr, "Unable to find a supported capture format.\n");
close(fd); close(fd);
exit(1); exit(1);
} }
} }
} }
} else { } else {
vpic.depth=24; vpic.depth=24;
vpic.palette=VIDEO_PALETTE_RGB24; vpic.palette=VIDEO_PALETTE_RGB24;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.palette=VIDEO_PALETTE_RGB565; vpic.palette=VIDEO_PALETTE_RGB565;
vpic.depth=16; vpic.depth=16;
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
vpic.palette=VIDEO_PALETTE_RGB555; vpic.palette=VIDEO_PALETTE_RGB555;
vpic.depth=15; vpic.depth=15;
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
fprintf(stderr, "Unable to find a supported capture format.\n"); fprintf(stderr, "Unable to find a supported capture format.\n");
return -1; return -1;
} }
} }
} }
} }
buffer = malloc(win.width * win.height * bpp); buffer = malloc(win.width * win.height * bpp);
if (!buffer) { if (!buffer) {
fprintf(stderr, "Out of memory.\n"); fprintf(stderr, "Out of memory.\n");
exit(1); exit(1);
} }
do { do {
int newbright; int newbright;
read(fd, buffer, win.width * win.height * bpp); read(fd, buffer, win.width * win.height * bpp);
@ -365,8 +365,8 @@ int main(int argc, char ** argv)
if (f) { if (f) {
vpic.brightness += (newbright << 8); vpic.brightness += (newbright << 8);
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
perror("VIDIOSPICT"); perror("VIDIOSPICT");
break; break;
} }
} }
} while (f); } while (f);
@ -381,7 +381,7 @@ int main(int argc, char ** argv)
fputc(g>>8, stdout); fputc(g>>8, stdout);
fputc(b>>8, stdout); fputc(b>>8, stdout);
} }
close(fd); close(fd);
return 0; return 0;
} }

View file

@ -87,7 +87,7 @@ hardware configuration of the parport. You can give the boot-parameter
at the LILO-prompt or specify it in lilo.conf. I use the following at the LILO-prompt or specify it in lilo.conf. I use the following
append-line in lilo.conf: append-line in lilo.conf:
append="parport=0x378,7,3" append="parport=0x378,7,3"
See Documentation/parport.txt for more information about the See Documentation/parport.txt for more information about the
configuration of the parport and the values given above. Do not simply configuration of the parport and the values given above. Do not simply
@ -175,7 +175,7 @@ THANKS (in no particular order):
- Manuel J. Petit de Gabriel <mpetit@dit.upm.es> for providing help - Manuel J. Petit de Gabriel <mpetit@dit.upm.es> for providing help
with Isabel (http://isabel.dit.upm.es/) with Isabel (http://isabel.dit.upm.es/)
- Bas Huisman <bhuism@cs.utwente.nl> for writing the initial parport code - Bas Huisman <bhuism@cs.utwente.nl> for writing the initial parport code
- Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list - Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list
and maintaining the web-server[3] and maintaining the web-server[3]
- Chris Whiteford <Chris@informinteractive.com> for fixes related to the - Chris Whiteford <Chris@informinteractive.com> for fixes related to the
1.02 firmware 1.02 firmware

View file

@ -28,7 +28,7 @@ Iomega Buz:
* Philips saa7111 TV decoder * Philips saa7111 TV decoder
* Philips saa7185 TV encoder * Philips saa7185 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit, Drivers to use: videodev, i2c-core, i2c-algo-bit,
videocodec, saa7111, saa7185, zr36060, zr36067 videocodec, saa7111, saa7185, zr36060, zr36067
Inputs/outputs: Composite and S-video Inputs/outputs: Composite and S-video
Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 7 Card number: 7
@ -39,7 +39,7 @@ Linux Media Labs LML33:
* Brooktree bt819 TV decoder * Brooktree bt819 TV decoder
* Brooktree bt856 TV encoder * Brooktree bt856 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit, Drivers to use: videodev, i2c-core, i2c-algo-bit,
videocodec, bt819, bt856, zr36060, zr36067 videocodec, bt819, bt856, zr36060, zr36067
Inputs/outputs: Composite and S-video Inputs/outputs: Composite and S-video
Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 5 Card number: 5
@ -50,7 +50,7 @@ Linux Media Labs LML33R10:
* Philips saa7114 TV decoder * Philips saa7114 TV decoder
* Analog Devices adv7170 TV encoder * Analog Devices adv7170 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit, Drivers to use: videodev, i2c-core, i2c-algo-bit,
videocodec, saa7114, adv7170, zr36060, zr36067 videocodec, saa7114, adv7170, zr36060, zr36067
Inputs/outputs: Composite and S-video Inputs/outputs: Composite and S-video
Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 6 Card number: 6
@ -61,7 +61,7 @@ Pinnacle/Miro DC10(new):
* Philips saa7110a TV decoder * Philips saa7110a TV decoder
* Analog Devices adv7176 TV encoder * Analog Devices adv7176 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit, Drivers to use: videodev, i2c-core, i2c-algo-bit,
videocodec, saa7110, adv7175, zr36060, zr36067 videocodec, saa7110, adv7175, zr36060, zr36067
Inputs/outputs: Composite, S-video and Internal Inputs/outputs: Composite, S-video and Internal
Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps)
Card number: 1 Card number: 1
@ -84,7 +84,7 @@ Pinnacle/Miro DC10(old): *
* Micronas vpx3220a TV decoder * Micronas vpx3220a TV decoder
* mse3000 TV encoder or Analog Devices adv7176 TV encoder * * mse3000 TV encoder or Analog Devices adv7176 TV encoder *
Drivers to use: videodev, i2c-core, i2c-algo-bit, Drivers to use: videodev, i2c-core, i2c-algo-bit,
videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zr36067 videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zr36067
Inputs/outputs: Composite, S-video and Internal Inputs/outputs: Composite, S-video and Internal
Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps)
Card number: 0 Card number: 0
@ -96,7 +96,7 @@ Pinnacle/Miro DC30: *
* Micronas vpx3225d/vpx3220a/vpx3216b TV decoder * Micronas vpx3225d/vpx3220a/vpx3216b TV decoder
* Analog Devices adv7176 TV encoder * Analog Devices adv7176 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit, Drivers to use: videodev, i2c-core, i2c-algo-bit,
videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zr36067 videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zr36067
Inputs/outputs: Composite, S-video and Internal Inputs/outputs: Composite, S-video and Internal
Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps)
Card number: 3 Card number: 3
@ -123,11 +123,11 @@ Note: use encoder=X or decoder=X for non-default i2c chips (see i2c-id.h)
The best know TV standards are NTSC/PAL/SECAM. but for decoding a frame that The best know TV standards are NTSC/PAL/SECAM. but for decoding a frame that
information is not enough. There are several formats of the TV standards. information is not enough. There are several formats of the TV standards.
And not every TV decoder is able to handle every format. Also the every And not every TV decoder is able to handle every format. Also the every
combination is supported by the driver. There are currently 11 different combination is supported by the driver. There are currently 11 different
tv broadcast formats all aver the world. tv broadcast formats all aver the world.
The CCIR defines parameters needed for broadcasting the signal. The CCIR defines parameters needed for broadcasting the signal.
The CCIR has defined different standards: A,B,D,E,F,G,D,H,I,K,K1,L,M,N,... The CCIR has defined different standards: A,B,D,E,F,G,D,H,I,K,K1,L,M,N,...
The CCIR says not much about about the colorsystem used !!! The CCIR says not much about about the colorsystem used !!!
And talking about a colorsystem says not to much about how it is broadcast. And talking about a colorsystem says not to much about how it is broadcast.
@ -136,18 +136,18 @@ The CCIR standards A,E,F are not used any more.
When you speak about NTSC, you usually mean the standard: CCIR - M using When you speak about NTSC, you usually mean the standard: CCIR - M using
the NTSC colorsystem which is used in the USA, Japan, Mexico, Canada the NTSC colorsystem which is used in the USA, Japan, Mexico, Canada
and a few others. and a few others.
When you talk about PAL, you usually mean: CCIR - B/G using the PAL When you talk about PAL, you usually mean: CCIR - B/G using the PAL
colorsystem which is used in many Countries. colorsystem which is used in many Countries.
When you talk about SECAM, you mean: CCIR - L using the SECAM Colorsystem When you talk about SECAM, you mean: CCIR - L using the SECAM Colorsystem
which is used in France, and a few others. which is used in France, and a few others.
There the other version of SECAM, CCIR - D/K is used in Bulgaria, China, There the other version of SECAM, CCIR - D/K is used in Bulgaria, China,
Slovakai, Hungary, Korea (Rep.), Poland, Rumania and a others. Slovakai, Hungary, Korea (Rep.), Poland, Rumania and a others.
The CCIR - H uses the PAL colorsystem (sometimes SECAM) and is used in The CCIR - H uses the PAL colorsystem (sometimes SECAM) and is used in
Egypt, Libya, Sri Lanka, Syrain Arab. Rep. Egypt, Libya, Sri Lanka, Syrain Arab. Rep.
The CCIR - I uses the PAL colorsystem, and is used in Great Britain, Hong Kong, The CCIR - I uses the PAL colorsystem, and is used in Great Britain, Hong Kong,
@ -158,30 +158,30 @@ and is used in Argentinia, Uruguay, an a few others
We do not talk about how the audio is broadcast ! We do not talk about how the audio is broadcast !
A rather good sites about the TV standards are: A rather good sites about the TV standards are:
http://www.sony.jp/ServiceArea/Voltage_map/ http://www.sony.jp/ServiceArea/Voltage_map/
http://info.electronicwerkstatt.de/bereiche/fernsehtechnik/frequenzen_und_normen/Fernsehnormen/ http://info.electronicwerkstatt.de/bereiche/fernsehtechnik/frequenzen_und_normen/Fernsehnormen/
and http://www.cabl.com/restaurant/channel.html and http://www.cabl.com/restaurant/channel.html
Other weird things around: NTSC 4.43 is a modificated NTSC, which is mainly Other weird things around: NTSC 4.43 is a modificated NTSC, which is mainly
used in PAL VCR's that are able to play back NTSC. PAL 60 seems to be the same used in PAL VCR's that are able to play back NTSC. PAL 60 seems to be the same
as NTSC 4.43 . The Datasheets also talk about NTSC 44, It seems as if it would as NTSC 4.43 . The Datasheets also talk about NTSC 44, It seems as if it would
be the same as NTSC 4.43. be the same as NTSC 4.43.
NTSC Combs seems to be a decoder mode where the decoder uses a comb filter NTSC Combs seems to be a decoder mode where the decoder uses a comb filter
to split coma and luma instead of a Delay line. to split coma and luma instead of a Delay line.
But I did not defiantly find out what NTSC Comb is. But I did not defiantly find out what NTSC Comb is.
Philips saa7111 TV decoder Philips saa7111 TV decoder
was introduced in 1997, is used in the BUZ and was introduced in 1997, is used in the BUZ and
can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC N, NTSC 4.43 and SECAM can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC N, NTSC 4.43 and SECAM
Philips saa7110a TV decoder Philips saa7110a TV decoder
was introduced in 1995, is used in the Pinnacle/Miro DC10(new), DC10+ and was introduced in 1995, is used in the Pinnacle/Miro DC10(new), DC10+ and
can handle: PAL B/G, NTSC M and SECAM can handle: PAL B/G, NTSC M and SECAM
Philips saa7114 TV decoder Philips saa7114 TV decoder
was introduced in 2000, is used in the LML33R10 and was introduced in 2000, is used in the LML33R10 and
can handle: PAL B/G/D/H/I/N, PAL N, PAL M, NTSC M, NTSC 4.43 and SECAM can handle: PAL B/G/D/H/I/N, PAL N, PAL M, NTSC M, NTSC 4.43 and SECAM
Brooktree bt819 TV decoder Brooktree bt819 TV decoder
@ -206,7 +206,7 @@ was introduced in 1996, is used in the BUZ
can generate: PAL B/G, NTSC M can generate: PAL B/G, NTSC M
Brooktree bt856 TV Encoder Brooktree bt856 TV Encoder
was introduced in 1994, is used in the LML33 was introduced in 1994, is used in the LML33
can generate: PAL B/D/G/H/I/N, PAL M, NTSC M, PAL-N (Argentina) can generate: PAL B/D/G/H/I/N, PAL M, NTSC M, PAL-N (Argentina)
Analog Devices adv7170 TV Encoder Analog Devices adv7170 TV Encoder
@ -221,9 +221,9 @@ ITT mse3000 TV encoder
was introduced in 1991, is used in the DC10 old was introduced in 1991, is used in the DC10 old
can generate: PAL , NTSC , SECAM can generate: PAL , NTSC , SECAM
The adv717x, should be able to produce PAL N. But you find nothing PAL N The adv717x, should be able to produce PAL N. But you find nothing PAL N
specific in the registers. Seem that you have to reuse a other standard specific in the registers. Seem that you have to reuse a other standard
to generate PAL N, maybe it would work if you use the PAL M settings. to generate PAL N, maybe it would work if you use the PAL M settings.
========================== ==========================
@ -261,7 +261,7 @@ Here's my experience of using LML33 and Buz on various motherboards:
VIA MVP3 VIA MVP3
Forget it. Pointless. Doesn't work. Forget it. Pointless. Doesn't work.
Intel 430FX (Pentium 200) Intel 430FX (Pentium 200)
LML33 perfect, Buz tolerable (3 or 4 frames dropped per movie) LML33 perfect, Buz tolerable (3 or 4 frames dropped per movie)
Intel 440BX (early stepping) Intel 440BX (early stepping)
LML33 tolerable. Buz starting to get annoying (6-10 frames/hour) LML33 tolerable. Buz starting to get annoying (6-10 frames/hour)
@ -438,52 +438,52 @@ importance of buffer sizes:
> -q 25 -b 128 : 24.655.992 > -q 25 -b 128 : 24.655.992
> -q 25 -b 256 : 25.859.820 > -q 25 -b 256 : 25.859.820
I woke up, and can't go to sleep again. I'll kill some time explaining why I woke up, and can't go to sleep again. I'll kill some time explaining why
this doesn't look strange to me. this doesn't look strange to me.
Let's do some math using a width of 704 pixels. I'm not sure whether the Buz Let's do some math using a width of 704 pixels. I'm not sure whether the Buz
actually use that number or not, but that's not too important right now. actually use that number or not, but that's not too important right now.
704x288 pixels, one field, is 202752 pixels. Divided by 64 pixels per block; 704x288 pixels, one field, is 202752 pixels. Divided by 64 pixels per block;
3168 blocks per field. Each pixel consist of two bytes; 128 bytes per block; 3168 blocks per field. Each pixel consist of two bytes; 128 bytes per block;
1024 bits per block. 100% in the new driver mean 1:2 compression; the maximum 1024 bits per block. 100% in the new driver mean 1:2 compression; the maximum
output becomes 512 bits per block. Actually 510, but 512 is simpler to use output becomes 512 bits per block. Actually 510, but 512 is simpler to use
for calculations. for calculations.
Let's say that we specify d1q50. We thus want 256 bits per block; times 3168 Let's say that we specify d1q50. We thus want 256 bits per block; times 3168
becomes 811008 bits; 101376 bytes per field. We're talking raw bits and bytes becomes 811008 bits; 101376 bytes per field. We're talking raw bits and bytes
here, so we don't need to do any fancy corrections for bits-per-pixel or such here, so we don't need to do any fancy corrections for bits-per-pixel or such
things. 101376 bytes per field. things. 101376 bytes per field.
d1 video contains two fields per frame. Those sum up to 202752 bytes per d1 video contains two fields per frame. Those sum up to 202752 bytes per
frame, and one of those frames goes into each buffer. frame, and one of those frames goes into each buffer.
But wait a second! -b128 gives 128kB buffers! It's not possible to cram But wait a second! -b128 gives 128kB buffers! It's not possible to cram
202752 bytes of JPEG data into 128kB! 202752 bytes of JPEG data into 128kB!
This is what the driver notice and automatically compensate for in your This is what the driver notice and automatically compensate for in your
examples. Let's do some math using this information: examples. Let's do some math using this information:
128kB is 131072 bytes. In this buffer, we want to store two fields, which 128kB is 131072 bytes. In this buffer, we want to store two fields, which
leaves 65536 bytes for each field. Using 3168 blocks per field, we get leaves 65536 bytes for each field. Using 3168 blocks per field, we get
20.68686868... available bytes per block; 165 bits. We can't allow the 20.68686868... available bytes per block; 165 bits. We can't allow the
request for 256 bits per block when there's only 165 bits available! The -q50 request for 256 bits per block when there's only 165 bits available! The -q50
option is silently overridden, and the -b128 option takes precedence, leaving option is silently overridden, and the -b128 option takes precedence, leaving
us with the equivalence of -q32. us with the equivalence of -q32.
This gives us a data rate of 165 bits per block, which, times 3168, sums up This gives us a data rate of 165 bits per block, which, times 3168, sums up
to 65340 bytes per field, out of the allowed 65536. The current driver has to 65340 bytes per field, out of the allowed 65536. The current driver has
another level of rate limiting; it won't accept -q values that fill more than another level of rate limiting; it won't accept -q values that fill more than
6/8 of the specified buffers. (I'm not sure why. "Playing it safe" seem to be 6/8 of the specified buffers. (I'm not sure why. "Playing it safe" seem to be
a safe bet. Personally, I think I would have lowered requested-bits-per-block a safe bet. Personally, I think I would have lowered requested-bits-per-block
by one, or something like that.) We can't use 165 bits per block, but have to by one, or something like that.) We can't use 165 bits per block, but have to
lower it again, to 6/8 of the available buffer space: We end up with 124 bits lower it again, to 6/8 of the available buffer space: We end up with 124 bits
per block, the equivalence of -q24. With 128kB buffers, you can't use greater per block, the equivalence of -q24. With 128kB buffers, you can't use greater
than -q24 at -d1. (And PAL, and 704 pixels width...) than -q24 at -d1. (And PAL, and 704 pixels width...)
The third example is limited to -q24 through the same process. The second The third example is limited to -q24 through the same process. The second
example, using very similar calculations, is limited to -q48. The only example, using very similar calculations, is limited to -q48. The only
example that actually grab at the specified -q value is the last one, which example that actually grab at the specified -q value is the last one, which
is clearly visible, looking at the file size. is clearly visible, looking at the file size.
-- --

View file

@ -14,13 +14,13 @@ Hauppauge Win/TV pci (version 405):
Microchip 24LC02B or Microchip 24LC02B or
Philips 8582E2Y: 256 Byte EEPROM with configuration information Philips 8582E2Y: 256 Byte EEPROM with configuration information
I2C 0xa0-0xa1, (24LC02B also responds to 0xa2-0xaf) I2C 0xa0-0xa1, (24LC02B also responds to 0xa2-0xaf)
Philips SAA5246AGP/E: Videotext decoder chip, I2C 0x22-0x23 Philips SAA5246AGP/E: Videotext decoder chip, I2C 0x22-0x23
TDA9800: sound decoder TDA9800: sound decoder
Winbond W24257AS-35: 32Kx8 CMOS static RAM (Videotext buffer mem) Winbond W24257AS-35: 32Kx8 CMOS static RAM (Videotext buffer mem)
14052B: analog switch for selection of sound source 14052B: analog switch for selection of sound source
PAL: PAL:
TDA5737: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners TDA5737: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
TSA5522: 1.4 GHz I2C-bus controlled synthesizer, I2C 0xc2-0xc3 TSA5522: 1.4 GHz I2C-bus controlled synthesizer, I2C 0xc2-0xc3

View file

@ -3,7 +3,7 @@
- Start capturing by pressing "c" or by selecting it via a menu!!! - Start capturing by pressing "c" or by selecting it via a menu!!!
- The memory of some S3 cards is not recognized right: - The memory of some S3 cards is not recognized right:
First of all, if you are not using XFree-3.2 or newer, upgrade AT LEAST to First of all, if you are not using XFree-3.2 or newer, upgrade AT LEAST to
XFree-3.2A! This solved the problem for most people. XFree-3.2A! This solved the problem for most people.
@ -31,23 +31,23 @@
(mostly with Trio 64 but also with some others) (mostly with Trio 64 but also with some others)
Get the free demo version of Accelerated X from www.xinside.com and try Get the free demo version of Accelerated X from www.xinside.com and try
bttv with it. bttv seems to work with most S3 cards with Accelerated X. bttv with it. bttv seems to work with most S3 cards with Accelerated X.
Since I do not know much (better make that almost nothing) about VGA card Since I do not know much (better make that almost nothing) about VGA card
programming I do not know the reason for this. programming I do not know the reason for this.
Looks like XFree does something different when setting up the video memory? Looks like XFree does something different when setting up the video memory?
Maybe somebody can enlighten me? Maybe somebody can enlighten me?
Would be nice if somebody could get this to work with XFree since Would be nice if somebody could get this to work with XFree since
Accelerated X costs more than some of the grabber cards ... Accelerated X costs more than some of the grabber cards ...
Better linear frame buffer support for S3 cards will probably be in Better linear frame buffer support for S3 cards will probably be in
XFree 4.0. XFree 4.0.
- Grabbing is not switched off when changing consoles with XFree. - Grabbing is not switched off when changing consoles with XFree.
That's because XFree and some AcceleratedX versions do not send unmap That's because XFree and some AcceleratedX versions do not send unmap
events. events.
- Some popup windows (e.g. of the window manager) are not refreshed. - Some popup windows (e.g. of the window manager) are not refreshed.
Disable backing store by starting X with the option "-bs" Disable backing store by starting X with the option "-bs"
- When using 32 bpp in XFree or 24+8bpp mode in AccelX 3.1 the system - When using 32 bpp in XFree or 24+8bpp mode in AccelX 3.1 the system

View file

@ -38,9 +38,9 @@ tolerate.
------------------------ ------------------------
When using the 430FX PCI, the following rules will ensure When using the 430FX PCI, the following rules will ensure
compatibility: compatibility:
(1) Deassert REQ at the same time as asserting FRAME. (1) Deassert REQ at the same time as asserting FRAME.
(2) Do not reassert REQ to request another bus transaction until after (2) Do not reassert REQ to request another bus transaction until after
finish-ing the previous transaction. finish-ing the previous transaction.

View file

@ -1,6 +1,6 @@
Many thanks to: Many thanks to:
- Markus Schroeder <schroedm@uni-duesseldorf.de> for information on the Bt848 - Markus Schroeder <schroedm@uni-duesseldorf.de> for information on the Bt848
and tuner programming and his control program xtvc. and tuner programming and his control program xtvc.
- Martin Buck <martin-2.buck@student.uni-ulm.de> for his great Videotext - Martin Buck <martin-2.buck@student.uni-ulm.de> for his great Videotext
@ -16,7 +16,7 @@ Many thanks to:
- MIRO for providing a free PCTV card and detailed information about the - MIRO for providing a free PCTV card and detailed information about the
components on their cards. (E.g. how the tuner type is detected) components on their cards. (E.g. how the tuner type is detected)
Without their card I could not have debugged the NTSC mode. Without their card I could not have debugged the NTSC mode.
- Hauppauge for telling how the sound input is selected and what components - Hauppauge for telling how the sound input is selected and what components
they do and will use on their radio cards. they do and will use on their radio cards.
Also many thanks for faxing me the FM1216 data sheet. Also many thanks for faxing me the FM1216 data sheet.

View file

@ -131,17 +131,17 @@ Check Stereo: BASE <-- 0xd8 (current volume, stereo detect,
x=0xff ==> "not stereo", x=0xfd ==> "stereo detected" x=0xff ==> "not stereo", x=0xfd ==> "stereo detected"
Set Frequency: code = (freq*40) + 10486188 Set Frequency: code = (freq*40) + 10486188
foreach of the 24 bits in code, foreach of the 24 bits in code,
(from Least to Most Significant): (from Least to Most Significant):
to write a "zero" bit, to write a "zero" bit,
BASE <-- 0x01 (audio mute, no stereo detect, radio BASE <-- 0x01 (audio mute, no stereo detect, radio
disable, "zero" bit phase 1, tuner adjust) disable, "zero" bit phase 1, tuner adjust)
BASE <-- 0x03 (audio mute, no stereo detect, radio BASE <-- 0x03 (audio mute, no stereo detect, radio
disable, "zero" bit phase 2, tuner adjust) disable, "zero" bit phase 2, tuner adjust)
to write a "one" bit, to write a "one" bit,
BASE <-- 0x05 (audio mute, no stereo detect, radio BASE <-- 0x05 (audio mute, no stereo detect, radio
disable, "one" bit phase 1, tuner adjust) disable, "one" bit phase 1, tuner adjust)
BASE <-- 0x07 (audio mute, no stereo detect, radio BASE <-- 0x07 (audio mute, no stereo detect, radio
disable, "one" bit phase 2, tuner adjust) disable, "one" bit phase 2, tuner adjust)
---------------------------------------------------------------------------- ----------------------------------------------------------------------------

View file

@ -26,7 +26,7 @@ is called VIDEO_PALETTE_YUV422 (16 bpp).
A minimal test application (with source) is available from: A minimal test application (with source) is available from:
http://hem.fyristorg.com/mogul/w9966.html http://hem.fyristorg.com/mogul/w9966.html
The slow framerate is due to missing DMA ECP read support in the The slow framerate is due to missing DMA ECP read support in the
parport drivers. I might add working EPP support later. parport drivers. I might add working EPP support later.
Good luck! Good luck!

View file

@ -2,7 +2,7 @@ Driver for Trust Computer Products Framegrabber, version 0.6.1
------ --- ----- -------- -------- ------------ ------- - - - ------ --- ----- -------- -------- ------------ ------- - - -
- ZORAN ------------------------------------------------------ - ZORAN ------------------------------------------------------
Author: Pauline Middelink <middelin@polyware.nl> Author: Pauline Middelink <middelin@polyware.nl>
Date: 18 September 1999 Date: 18 September 1999
Version: 0.6.1 Version: 0.6.1
@ -115,7 +115,7 @@ After making/checking the devices do:
<n> is the cardtype of the card you have. The cardnumber can <n> is the cardtype of the card you have. The cardnumber can
be found in the source of zr36120. Look for tvcards. If your be found in the source of zr36120. Look for tvcards. If your
card is not there, please try if any other card gives some card is not there, please try if any other card gives some
response, and mail me if you got a working tvcard addition. response, and mail me if you got a working tvcard addition.
PS. <TVCard editors behold!) PS. <TVCard editors behold!)
Dont forget to set video_input to the number of inputs Dont forget to set video_input to the number of inputs

View file

@ -50,5 +50,19 @@ config VIDEO_IR
config VIDEO_TVEEPROM config VIDEO_TVEEPROM
tristate tristate
config USB_DABUSB
tristate "DABUSB driver"
depends on USB
---help---
A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
brought to you by the DAB-Team
<http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
as an example for URB-based bulk, control, and isochronous
transactions. URB's are explained in
<Documentation/usb/URB.txt>.
To compile this driver as a module, choose M here: the
module will be called dabusb.
endmenu endmenu

View file

@ -50,14 +50,15 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
/********************************************************************************/ /********************************************************************************/
/* common dma functions */ /* common dma functions */
void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf) void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
struct saa7146_buf *buf)
{ {
DEB_EE(("dev:%p, buf:%p\n",dev,buf)); DEB_EE(("dev:%p, buf:%p\n",dev,buf));
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0); videobuf_waiton(&buf->vb,0,0);
videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); videobuf_dma_unmap(q, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma); videobuf_dma_free(&buf->vb.dma);
buf->vb.state = STATE_NEEDS_INIT; buf->vb.state = STATE_NEEDS_INIT;
} }

View file

@ -236,7 +236,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
} }
if (buf->vb.size != size) if (buf->vb.size != size)
saa7146_dma_free(dev,buf); saa7146_dma_free(dev,q,buf);
if (STATE_NEEDS_INIT == buf->vb.state) { if (STATE_NEEDS_INIT == buf->vb.state) {
buf->vb.width = llength; buf->vb.width = llength;
@ -247,7 +247,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
saa7146_pgtable_free(dev->pci, &buf->pt[2]); saa7146_pgtable_free(dev->pci, &buf->pt[2]);
saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
err = videobuf_iolock(dev->pci,&buf->vb, NULL); err = videobuf_iolock(q,&buf->vb, NULL);
if (err) if (err)
goto oops; goto oops;
err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen); err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
@ -261,7 +261,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
oops: oops:
DEB_VBI(("error out.\n")); DEB_VBI(("error out.\n"));
saa7146_dma_free(dev,buf); saa7146_dma_free(dev,q,buf);
return err; return err;
} }
@ -301,7 +301,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_buf *buf = (struct saa7146_buf *)vb; struct saa7146_buf *buf = (struct saa7146_buf *)vb;
DEB_VBI(("vb:%p\n",vb)); DEB_VBI(("vb:%p\n",vb));
saa7146_dma_free(dev,buf); saa7146_dma_free(dev,q,buf);
} }
static struct videobuf_queue_ops vbi_qops = { static struct videobuf_queue_ops vbi_qops = {

View file

@ -1275,7 +1275,7 @@ static int buffer_prepare(struct videobuf_queue *q,
buf->vb.field != field || buf->vb.field != field ||
buf->vb.field != fh->video_fmt.field || buf->vb.field != fh->video_fmt.field ||
buf->fmt != &fh->video_fmt) { buf->fmt != &fh->video_fmt) {
saa7146_dma_free(dev,buf); saa7146_dma_free(dev,q,buf);
} }
if (STATE_NEEDS_INIT == buf->vb.state) { if (STATE_NEEDS_INIT == buf->vb.state) {
@ -1304,7 +1304,7 @@ static int buffer_prepare(struct videobuf_queue *q,
saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
} }
err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb); err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
if (err) if (err)
goto oops; goto oops;
err = saa7146_pgtable_build(dev,buf); err = saa7146_pgtable_build(dev,buf);
@ -1318,7 +1318,7 @@ static int buffer_prepare(struct videobuf_queue *q,
oops: oops:
DEB_D(("error out.\n")); DEB_D(("error out.\n"));
saa7146_dma_free(dev,buf); saa7146_dma_free(dev,q,buf);
return err; return err;
} }
@ -1363,7 +1363,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_buf *buf = (struct saa7146_buf *)vb; struct saa7146_buf *buf = (struct saa7146_buf *)vb;
DEB_CAP(("vbuf:%p\n",vb)); DEB_CAP(("vbuf:%p\n",vb));
saa7146_dma_free(dev,buf); saa7146_dma_free(dev,q,buf);
} }
static struct videobuf_queue_ops video_qops = { static struct videobuf_queue_ops video_qops = {

View file

@ -541,6 +541,7 @@ static struct usb_device_id flexcop_usb_table [] = {
{ USB_DEVICE(0x0af7, 0x0101) }, { USB_DEVICE(0x0af7, 0x0101) },
{ } { }
}; };
MODULE_DEVICE_TABLE (usb, flexcop_usb_table);
/* usb specific object needed to register this driver with the usb subsystem */ /* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver flexcop_usb_driver = { static struct usb_driver flexcop_usb_driver = {

View file

@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends

View file

@ -81,18 +81,19 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
return -EAGAIN; return -EAGAIN;
if (num > 2) if (num > 2)
warn("more than 2 i2c messages at a time is not handled yet. TODO."); warn("more than two i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
switch (msg[i].addr) { if (d->udev->descriptor.idVendor == USB_VID_MEDION)
case 0x63: switch (msg[i].addr) {
cxusb_gpio_tuner(d,0); case 0x63:
break; cxusb_gpio_tuner(d,0);
default: break;
cxusb_gpio_tuner(d,1); default:
break; cxusb_gpio_tuner(d,1);
} break;
}
/* read request */ /* read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
@ -108,7 +109,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
break; break;
if (ibuf[0] != 0x08) if (ibuf[0] != 0x08)
deb_info("i2c read could have been failed\n"); deb_i2c("i2c read may have failed\n");
memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len); memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len);
@ -122,7 +123,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0) if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0)
break; break;
if (ibuf != 0x08) if (ibuf != 0x08)
deb_info("i2c write could have been failed\n"); deb_i2c("i2c write may have failed\n");
} }
} }
@ -410,7 +411,6 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const
if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) && if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
/* FIXME: are we allowed to change the fw-data ? */
fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1; fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8; fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;

View file

@ -6,6 +6,8 @@
extern int dvb_usb_cxusb_debug; extern int dvb_usb_cxusb_debug;
#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args) #define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
dprintk(dvb_usb_cxusb_debug,0x01,args)
/* usb commands - some of it are guesses, don't have a reference yet */ /* usb commands - some of it are guesses, don't have a reference yet */
#define CMD_I2C_WRITE 0x08 #define CMD_I2C_WRITE 0x08

View file

@ -369,6 +369,11 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
fm_matrix = 0x3001; // stereo fm_matrix = 0x3001; // stereo
src = 0x0020; src = 0x0020;
break; break;
case V4L2_TUNER_MODE_LANG1_LANG2:
dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
fm_matrix = 0x3000; // bilingual
src = 0x0020;
break;
case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG1:
dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"); dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
fm_matrix = 0x3000; // mono fm_matrix = 0x3000; // mono

View file

@ -16,31 +16,7 @@ config VIDEO_ADV_DEBUG
V4L devices. V4L devices.
In doubt, say N. In doubt, say N.
config VIDEO_BT848 source "drivers/media/video/bt8xx/Kconfig"
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
select VIDEO_BUF
select VIDEO_IR
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_MSP3400
---help---
Support for BT848 based frame grabber/overlay boards. This includes
the Miro, Hauppauge and STB boards. Please read the material in
<file:Documentation/video4linux/bttv/> for more information.
To compile this driver as a module, choose M here: the
module will be called bttv.
config VIDEO_BT848_DVB
bool "DVB/ATSC Support for bt878 based TV cards"
depends on VIDEO_BT848 && DVB_CORE
select DVB_BT8XX
---help---
This adds support for DVB/ATSC cards based on the BT878 chip.
config VIDEO_SAA6588 config VIDEO_SAA6588
tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
@ -315,8 +291,6 @@ config VIDEO_HEXIUM_GEMINI
source "drivers/media/video/cx88/Kconfig" source "drivers/media/video/cx88/Kconfig"
source "drivers/media/video/em28xx/Kconfig"
config VIDEO_OVCAMCHIP config VIDEO_OVCAMCHIP
tristate "OmniVision Camera Chip support" tristate "OmniVision Camera Chip support"
depends on VIDEO_DEV && I2C depends on VIDEO_DEV && I2C
@ -391,4 +365,234 @@ config VIDEO_SAA7127
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called saa7127 module will be called saa7127
#
# USB Multimedia device configuration
#
menu "V4L USB devices"
depends on USB && VIDEO_DEV
source "drivers/media/video/em28xx/Kconfig"
config USB_VICAM
tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
depends on USB && VIDEO_DEV && EXPERIMENTAL
---help---
Say Y here if you have 3com homeconnect camera (vicam).
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
at <file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called vicam.
config USB_DSBR
tristate "D-Link USB FM radio support (EXPERIMENTAL)"
depends on USB && VIDEO_DEV && EXPERIMENTAL
---help---
Say Y here if you want to connect this type of radio to your
computer's USB port. Note that the audio is not digital, and
you must connect the line out connector to a sound card or a
set of speakers.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found at
<file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called dsbr100.
config USB_ET61X251
tristate "USB ET61X[12]51 PC Camera Controller support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want support for cameras based on Etoms ET61X151
or ET61X251 PC Camera Controllers.
See <file:Documentation/usb/et61x251.txt> for more informations.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" to use this driver.
To compile this driver as a module, choose M here: the
module will be called et61x251.
config USB_IBMCAM
tristate "USB IBM (Xirlink) C-it Camera support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want to connect a IBM "C-It" camera, also known as
"Xirlink PC Camera" to your computer's USB port. For more
information, read <file:Documentation/usb/ibmcam.txt>.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found at
<file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called ibmcam.
This camera has several configuration options which
can be specified when you load the module. Read
<file:Documentation/usb/ibmcam.txt> to learn more.
config USB_KONICAWC
tristate "USB Konica Webcam support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want support for webcams based on a Konica
chipset. This is known to work with the Intel YC76 webcam.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found at
<file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called konicawc.
config USB_OV511
tristate "USB OV511 Camera support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/ov511.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
at <file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called ov511.
config USB_SE401
tristate "USB SE401 Camera support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/se401.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
at <file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called se401.
config USB_SN9C102
tristate "USB SN9C10x PC Camera Controller support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want support for cameras based on SONiX SN9C101,
SN9C102 or SN9C103 PC Camera Controllers.
See <file:Documentation/usb/sn9c102.txt> for more informations.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" to use this driver.
To compile this driver as a module, choose M here: the
module will be called sn9c102.
config USB_STV680
tristate "USB STV680 (Pencam) Camera support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want to connect this type of camera to your
computer's USB port. This includes the Pencam line of cameras.
See <file:Documentation/usb/stv680.txt> for more information and for
a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
at <file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called stv680.
config USB_W9968CF
tristate "USB W996[87]CF JPEG Dual Mode Camera support"
depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP
---help---
Say Y here if you want support for cameras based on OV681 or
Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
This driver has an optional plugin, which is distributed as a
separate module only (released under GPL). It allows to use higher
resolutions and framerates, but cannot be included in the official
Linux kernel for performance purposes.
See <file:Documentation/usb/w9968cf.txt> for more informations.
This driver uses the Video For Linux and the I2C APIs. It needs the
OmniVision Camera Chip support as well. You must say Y or M to
"Video For Linux", "I2C Support" and "OmniVision Camera Chip
support" to use this driver.
To compile this driver as a module, choose M here: the
module will be called w9968cf.
config USB_ZC0301
tristate "USB ZC0301 Image Processor and Control Chip support"
depends on USB && VIDEO_DEV
---help---
Say Y here if you want support for cameras based on the ZC0301
Image Processor and Control Chip.
See <file:Documentation/usb/zc0301.txt> for more informations.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" to use this driver.
To compile this driver as a module, choose M here: the
module will be called zc0301.
config USB_PWC
tristate "USB Philips Cameras"
depends on USB && VIDEO_DEV
---help---
Say Y or M here if you want to use one of these Philips & OEM
webcams:
* Philips PCA645, PCA646
* Philips PCVC675, PCVC680, PCVC690
* Philips PCVC720/40, PCVC730, PCVC740, PCVC750
* Askey VC010
* Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
and 'Orbit'/'Sphere'
* Samsung MPC-C10, MPC-C30
* Creative Webcam 5, Pro Ex
* SOTEC Afina Eye
* Visionite VCS-UC300, VCS-UM100
The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
and never will be, but the 665 and 720/20 are supported by other
drivers.
See <file:Documentation/usb/philips.txt> for more information and
installation instructions.
The built-in microphone is enabled by selecting USB Audio support.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
at <file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called pwc.
endmenu # V4L USB devices
endmenu endmenu

View file

@ -2,9 +2,6 @@
# Makefile for the video capture/playback device drivers. # Makefile for the video capture/playback device drivers.
# #
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
bttv-input.o
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
zr36067-objs := zoran_procfs.o zoran_device.o \ zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o zoran_driver.o zoran_card.o
@ -15,8 +12,8 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o tvaudio.o \ obj-$(CONFIG_VIDEO_BT848) += bt8xx/
tda7432.o tda9875.o ir-kbd-i2c.o obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
@ -68,4 +65,23 @@ obj-$(CONFIG_VIDEO_CX25840) += cx25840/
obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
obj-$(CONFIG_USB_STV680) += stv680.o
obj-$(CONFIG_USB_W9968CF) += w9968cf.o
obj-$(CONFIG_USB_SN9C102) += sn9c102/
obj-$(CONFIG_USB_ET61X251) += et61x251/
obj-$(CONFIG_USB_PWC) += pwc/
obj-$(CONFIG_USB_ZC0301) += zc0301/
obj-$(CONFIG_USB_IBMCAM) += usbvideo/
obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core

View file

@ -1,9 +1,9 @@
/* /*
* adv7170 - adv7170, adv7171 video encoder driver version 0.0.1 * adv7170 - adv7170, adv7171 video encoder driver version 0.0.1
* *
* Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com> * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
* *
* Based on adv7176 driver by: * Based on adv7176 driver by:
* *
* Copyright (C) 1998 Dave Perks <dperks@ibm.net> * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
* Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net> * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
@ -173,7 +173,7 @@ adv7170_write_block (struct i2c_client *client,
static const unsigned char init_NTSC[] = { static const unsigned char init_NTSC[] = {
0x00, 0x10, // MR0 0x00, 0x10, // MR0
0x01, 0x20, // MR1 0x01, 0x20, // MR1
0x02, 0x0e, // MR2 RTC control: bits 2 and 1 0x02, 0x0e, // MR2 RTC control: bits 2 and 1
0x03, 0x80, // MR3 0x03, 0x80, // MR3
0x04, 0x30, // MR4 0x04, 0x30, // MR4
0x05, 0x00, // Reserved 0x05, 0x00, // Reserved
@ -196,7 +196,7 @@ static const unsigned char init_NTSC[] = {
0x16, 0x00, // CGMS_WSS_0 0x16, 0x00, // CGMS_WSS_0
0x17, 0x00, // CGMS_WSS_1 0x17, 0x00, // CGMS_WSS_1
0x18, 0x00, // CGMS_WSS_2 0x18, 0x00, // CGMS_WSS_2
0x19, 0x00, // Teletext Ctl 0x19, 0x00, // Teletext Ctl
}; };
static const unsigned char init_PAL[] = { static const unsigned char init_PAL[] = {
@ -381,7 +381,7 @@ static unsigned short normal_i2c[] =
}; };
static unsigned short ignore = I2C_CLIENT_END; static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = { static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c, .normal_i2c = normal_i2c,
.probe = &ignore, .probe = &ignore,

View file

@ -1,4 +1,4 @@
/* /*
* adv7175 - adv7175a video encoder driver version 0.0.3 * adv7175 - adv7175a video encoder driver version 0.0.3
* *
* Copyright (C) 1998 Dave Perks <dperks@ibm.net> * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
@ -233,7 +233,7 @@ adv7175_command (struct i2c_client *client,
sizeof(init_common)); sizeof(init_common));
adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE | TR0RST);
adv7175_write(client, 0x07, TR0MODE); adv7175_write(client, 0x07, TR0MODE);
break; break;
case ENCODER_GET_CAPABILITIES: case ENCODER_GET_CAPABILITIES:
{ {
@ -399,7 +399,7 @@ static unsigned short normal_i2c[] =
}; };
static unsigned short ignore = I2C_CLIENT_END; static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = { static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c, .normal_i2c = normal_i2c,
.probe = &ignore, .probe = &ignore,

View file

@ -161,39 +161,39 @@ void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2,
{ {
int i; int i;
/* Slave Address */ /* Slave Address */
ar_outl(addr, PLDI2CDATA); ar_outl(addr, PLDI2CDATA);
wait_for_vsync(); wait_for_vsync();
/* Start */ /* Start */
ar_outl(1, PLDI2CCND); ar_outl(1, PLDI2CCND);
wait_acknowledge(); wait_acknowledge();
/* Transfer data 1 */ /* Transfer data 1 */
ar_outl(data1, PLDI2CDATA); ar_outl(data1, PLDI2CDATA);
wait_for_vsync(); wait_for_vsync();
ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
wait_acknowledge(); wait_acknowledge();
/* Transfer data 2 */ /* Transfer data 2 */
ar_outl(data2, PLDI2CDATA); ar_outl(data2, PLDI2CDATA);
wait_for_vsync(); wait_for_vsync();
ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
wait_acknowledge(); wait_acknowledge();
if (n == 3) { if (n == 3) {
/* Transfer data 3 */ /* Transfer data 3 */
ar_outl(data3, PLDI2CDATA); ar_outl(data3, PLDI2CDATA);
wait_for_vsync(); wait_for_vsync();
ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
wait_acknowledge(); wait_acknowledge();
} }
/* Stop */ /* Stop */
for (i = 0; i < 100; i++) for (i = 0; i < 100; i++)
cpu_relax(); cpu_relax();
ar_outl(2, PLDI2CCND); ar_outl(2, PLDI2CCND);
ar_outl(2, PLDI2CCND); ar_outl(2, PLDI2CCND);
while (ar_inl(PLDI2CSTS) & PLDI2CSTS_BB) while (ar_inl(PLDI2CSTS) & PLDI2CSTS_BB)
cpu_relax(); cpu_relax();
@ -204,24 +204,24 @@ void init_iic(void)
{ {
DEBUG(1, "init_iic:\n"); DEBUG(1, "init_iic:\n");
/* /*
* ICU Setting (iic) * ICU Setting (iic)
*/ */
/* I2C Setting */ /* I2C Setting */
ar_outl(0x0, PLDI2CCR); /* I2CCR Disable */ ar_outl(0x0, PLDI2CCR); /* I2CCR Disable */
ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */ ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */
ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */ ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */
/* I2C CLK */ /* I2C CLK */
/* 50MH-100k */ /* 50MH-100k */
if (freq == 75) { if (freq == 75) {
ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */
} else if (freq == 50) { } else if (freq == 50) {
ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */ ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */
} else { } else {
ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */ ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */
} }
ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */ ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */
} }
/************************************************************************** /**************************************************************************
@ -253,7 +253,7 @@ static inline void wait_for_vertical_sync(int exp_line)
/* /*
* check HCOUNT because we cannot check vertical sync. * check HCOUNT because we cannot check vertical sync.
*/ */
for (; tmout >= 0; tmout--) { for (; tmout >= 0; tmout--) {
l = ar_inl(ARVHCOUNT); l = ar_inl(ARVHCOUNT);
if (l == exp_line) if (l == exp_line)
@ -562,8 +562,8 @@ static void ar_interrupt(int irq, void *dev, struct pt_regs *regs)
/* operations for interlace mode */ /* operations for interlace mode */
if ( line_count < (AR_HEIGHT_VGA/2) ) /* even line */ if ( line_count < (AR_HEIGHT_VGA/2) ) /* even line */
line_number = (line_count << 1); line_number = (line_count << 1);
else /* odd line */ else /* odd line */
line_number = line_number =
(((line_count - (AR_HEIGHT_VGA/2)) << 1) + 1); (((line_count - (AR_HEIGHT_VGA/2)) << 1) + 1);
} else { } else {
line_number = line_count; line_number = line_count;
@ -651,7 +651,7 @@ static int ar_initialize(struct video_device *dev)
cr |= ARVCR1_NORMAL; cr |= ARVCR1_NORMAL;
ar_outl(cr, ARVCR1); ar_outl(cr, ARVCR1);
/* /*
* Initialize IIC so that CPU can communicate with AR LSI, * Initialize IIC so that CPU can communicate with AR LSI,
* and send boot commands to AR LSI. * and send boot commands to AR LSI.
*/ */
@ -846,7 +846,7 @@ static int __init ar_init(void)
* so register video device as a frame grabber type. * so register video device as a frame grabber type.
* device is named "video[0-64]". * device is named "video[0-64]".
* video_register_device() initializes h/w using ar_initialize(). * video_register_device() initializes h/w using ar_initialize().
*/ */
if (video_register_device(ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { if (video_register_device(ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) {
/* return -1, -ENFILE(full) or others */ /* return -1, -ENFILE(full) or others */
printk("arv: register video (Colour AR) failed.\n"); printk("arv: register video (Colour AR) failed.\n");

View file

@ -1,4 +1,4 @@
/* /*
* bt819 - BT819A VideoStream Decoder (Rockwell Part) * bt819 - BT819A VideoStream Decoder (Rockwell Part)
* *
* Copyright (C) 1999 Mike Bernson <mike@mlb.org> * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
@ -6,7 +6,7 @@
* *
* Modifications for LML33/DC10plus unified driver * Modifications for LML33/DC10plus unified driver
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
* *
* Changes by Ronald Bultje <rbultje@ronald.bitfreak.net> * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
* - moved over to linux>=2.4.x i2c protocol (9/9/2002) * - moved over to linux>=2.4.x i2c protocol (9/9/2002)
* *
@ -206,9 +206,9 @@ bt819_init (struct i2c_client *client)
Bug in the bt819 stepping on my board? Bug in the bt819 stepping on my board?
*/ */
0x14, 0x00, /* 0x14 Vertial Scaling lsb */ 0x14, 0x00, /* 0x14 Vertial Scaling lsb */
0x16, 0x07, /* 0x16 Video Timing Polarity 0x16, 0x07, /* 0x16 Video Timing Polarity
ACTIVE=active low ACTIVE=active low
FIELD: high=odd, FIELD: high=odd,
vreset=active high, vreset=active high,
hreset=active high */ hreset=active high */
0x18, 0x68, /* 0x18 AGC Delay */ 0x18, 0x68, /* 0x18 AGC Delay */
@ -497,7 +497,7 @@ static unsigned short normal_i2c[] = {
}; };
static unsigned short ignore = I2C_CLIENT_END; static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = { static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c, .normal_i2c = normal_i2c,
.probe = &ignore, .probe = &ignore,

View file

@ -1,4 +1,4 @@
/* /*
* bt856 - BT856A Digital Video Encoder (Rockwell Part) * bt856 - BT856A Digital Video Encoder (Rockwell Part)
* *
* Copyright (C) 1999 Mike Bernson <mike@mlb.org> * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
@ -285,7 +285,7 @@ bt856_command (struct i2c_client *client,
static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END }; static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
static unsigned short ignore = I2C_CLIENT_END; static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = { static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c, .normal_i2c = normal_i2c,
.probe = &ignore, .probe = &ignore,

View file

@ -0,0 +1,25 @@
config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
select VIDEO_BUF
select VIDEO_IR
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_MSP3400
---help---
Support for BT848 based frame grabber/overlay boards. This includes
the Miro, Hauppauge and STB boards. Please read the material in
<file:Documentation/video4linux/bttv/> for more information.
To compile this driver as a module, choose M here: the
module will be called bttv.
config VIDEO_BT848_DVB
bool "DVB/ATSC Support for bt878 based TV cards"
depends on VIDEO_BT848 && DVB_CORE
select DVB_BT8XX
---help---
This adds support for DVB/ATSC cards based on the BT878 chip.

View file

@ -0,0 +1,12 @@
#
# Makefile for the video capture/playback device drivers.
#
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
bttv-input.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core

View file

@ -30,7 +30,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "bttv.h" #include "bttv.h"
@ -39,7 +38,7 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, static unsigned short normal_i2c[] = { I2C_ADDR_BT832_ALT1>>1, I2C_ADDR_BT832_ALT2>>1,
I2C_CLIENT_END }; I2C_CLIENT_END };
I2C_CLIENT_INSMOD; I2C_CLIENT_INSMOD;

View file

@ -36,13 +36,15 @@
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include "bttvp.h" #include "bttvp.h"
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/tvaudio.h>
#include <media/msp3400.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include "rds.h" #include <media/rds.h>
unsigned int bttv_num; /* number of Bt848s in use */ unsigned int bttv_num; /* number of Bt848s in use */
@ -926,45 +928,98 @@ video_mux(struct bttv *btv, unsigned int input)
static char *audio_modes[] = { static char *audio_modes[] = {
"audio: tuner", "audio: radio", "audio: extern", "audio: tuner", "audio: radio", "audio: extern",
"audio: intern", "audio: off" "audio: intern", "audio: mute"
}; };
static int static int
audio_mux(struct bttv *btv, int mode) audio_mux(struct bttv *btv, int input, int mute)
{ {
int val,mux,i2c_mux,signal; int gpio_val, signal;
struct v4l2_control ctrl;
struct i2c_client *c;
gpio_inout(bttv_tvcards[btv->c.type].gpiomask, gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
bttv_tvcards[btv->c.type].gpiomask); bttv_tvcards[btv->c.type].gpiomask);
signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
switch (mode) { btv->mute = mute;
case AUDIO_MUTE: btv->audio = input;
btv->audio |= AUDIO_MUTE;
break;
case AUDIO_UNMUTE:
btv->audio &= ~AUDIO_MUTE;
break;
case AUDIO_TUNER:
case AUDIO_RADIO:
case AUDIO_EXTERN:
case AUDIO_INTERN:
btv->audio &= AUDIO_MUTE;
btv->audio |= mode;
}
i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio;
if (btv->opt_automute && !signal && !btv->radio_user)
mux = AUDIO_OFF;
val = bttv_tvcards[btv->c.type].audiomux[mux]; /* automute */
gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val); mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
if (mute)
gpio_val = bttv_tvcards[btv->c.type].gpiomute;
else
gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
if (bttv_gpio) if (bttv_gpio)
bttv_gpio_tracking(btv,audio_modes[mux]); bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
if (!in_interrupt()) if (in_interrupt())
bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux)); return 0;
ctrl.id = V4L2_CID_AUDIO_MUTE;
ctrl.value = btv->mute;
bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl);
c = btv->i2c_msp34xx_client;
if (c) {
struct v4l2_routing route;
/* Note: the inputs tuner/radio/extern/intern are translated
to msp routings. This assumes common behavior for all msp3400
based TV cards. When this assumption fails, then the
specific MSP routing must be added to the card table.
For now this is sufficient. */
switch (input) {
case TVAUDIO_INPUT_RADIO:
route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
break;
case TVAUDIO_INPUT_EXTERN:
route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
break;
case TVAUDIO_INPUT_INTERN:
/* Yes, this is the same input as for RADIO. I doubt
if this is ever used. The only board with an INTERN
input is the BTTV_BOARD_AVERMEDIA98. I wonder how
that was tested. My guess is that the whole INTERN
input does not work. */
route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
break;
case TVAUDIO_INPUT_TUNER:
default:
route.input = MSP_INPUT_DEFAULT;
break;
}
route.output = MSP_OUTPUT_DEFAULT;
c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
}
c = btv->i2c_tvaudio_client;
if (c) {
struct v4l2_routing route;
route.input = input;
route.output = 0;
c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
}
return 0; return 0;
} }
static inline int
audio_mute(struct bttv *btv, int mute)
{
return audio_mux(btv, btv->audio, mute);
}
static inline int
audio_input(struct bttv *btv, int input)
{
return audio_mux(btv, input, btv->mute);
}
static void static void
i2c_vidiocschan(struct bttv *btv) i2c_vidiocschan(struct bttv *btv)
{ {
@ -1023,8 +1078,8 @@ set_input(struct bttv *btv, unsigned int input)
} else { } else {
video_mux(btv,input); video_mux(btv,input);
} }
audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ? audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
AUDIO_TUNER : AUDIO_EXTERN)); TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
set_tvnorm(btv,btv->tvnorm); set_tvnorm(btv,btv->tvnorm);
i2c_vidiocschan(btv); i2c_vidiocschan(btv);
} }
@ -1236,10 +1291,10 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
if (c->value) { if (c->value) {
va.flags |= VIDEO_AUDIO_MUTE; va.flags |= VIDEO_AUDIO_MUTE;
audio_mux(btv, AUDIO_MUTE); audio_mute(btv, 1);
} else { } else {
va.flags &= ~VIDEO_AUDIO_MUTE; va.flags &= ~VIDEO_AUDIO_MUTE;
audio_mux(btv, AUDIO_UNMUTE); audio_mute(btv, 0);
} }
break; break;
@ -1397,7 +1452,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
free_btres(btv,fh,RESOURCE_OVERLAY); free_btres(btv,fh,RESOURCE_OVERLAY);
if (NULL != old) { if (NULL != old) {
dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state); dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
bttv_dma_free(btv, old); bttv_dma_free(&fh->cap,btv, old);
kfree(old); kfree(old);
} }
dprintk("switch_overlay: done\n"); dprintk("switch_overlay: done\n");
@ -1407,7 +1462,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* video4linux (1) interface */ /* video4linux (1) interface */
static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
struct bttv_buffer *buf,
const struct bttv_format *fmt, const struct bttv_format *fmt,
unsigned int width, unsigned int height, unsigned int width, unsigned int height,
enum v4l2_field field) enum v4l2_field field)
@ -1450,7 +1506,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
/* alloc risc memory */ /* alloc risc memory */
if (STATE_NEEDS_INIT == buf->vb.state) { if (STATE_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1; redo_dma_risc = 1;
if (0 != (rc = videobuf_iolock(btv->c.pci,&buf->vb,&btv->fbuf))) if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
goto fail; goto fail;
} }
@ -1462,7 +1518,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
return 0; return 0;
fail: fail:
bttv_dma_free(btv,buf); bttv_dma_free(q,btv,buf);
return rc; return rc;
} }
@ -1486,7 +1542,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
struct bttv_fh *fh = q->priv_data; struct bttv_fh *fh = q->priv_data;
return bttv_prepare_buffer(fh->btv, buf, fh->fmt, return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
fh->width, fh->height, field); fh->width, fh->height, field);
} }
@ -1510,7 +1566,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
struct bttv_fh *fh = q->priv_data; struct bttv_fh *fh = q->priv_data;
bttv_dma_free(fh->btv,buf); bttv_dma_free(&fh->cap,fh->btv,buf);
} }
static struct videobuf_queue_ops bttv_video_qops = { static struct videobuf_queue_ops bttv_video_qops = {
@ -1653,7 +1709,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL; return -EINVAL;
mutex_lock(&btv->lock); mutex_lock(&btv->lock);
audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE); audio_mute(btv, (v->flags&VIDEO_AUDIO_MUTE) ? 1 : 0);
bttv_call_i2c_clients(btv,cmd,v); bttv_call_i2c_clients(btv,cmd,v);
/* card specific hooks */ /* card specific hooks */
@ -1822,7 +1878,8 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
if (t->audmode == V4L2_TUNER_MODE_MONO) if (t->audmode == V4L2_TUNER_MODE_MONO)
va.mode = VIDEO_SOUND_MONO; va.mode = VIDEO_SOUND_MONO;
else if (t->audmode == V4L2_TUNER_MODE_STEREO) else if (t->audmode == V4L2_TUNER_MODE_STEREO ||
t->audmode == V4L2_TUNER_MODE_LANG1_LANG2)
va.mode = VIDEO_SOUND_STEREO; va.mode = VIDEO_SOUND_STEREO;
else if (t->audmode == V4L2_TUNER_MODE_LANG1) else if (t->audmode == V4L2_TUNER_MODE_LANG1)
va.mode = VIDEO_SOUND_LANG1; va.mode = VIDEO_SOUND_LANG1;
@ -2496,7 +2553,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2) field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
? V4L2_FIELD_INTERLACED ? V4L2_FIELD_INTERLACED
: V4L2_FIELD_BOTTOM; : V4L2_FIELD_BOTTOM;
retval = bttv_prepare_buffer(btv,buf, retval = bttv_prepare_buffer(&fh->cap,btv,buf,
format_by_palette(vm->format), format_by_palette(vm->format),
vm->width,vm->height,field); vm->width,vm->height,field);
if (0 != retval) if (0 != retval)
@ -2528,8 +2585,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
retval = -EIO; retval = -EIO;
/* fall through */ /* fall through */
case STATE_DONE: case STATE_DONE:
videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma); videobuf_dma_sync(&fh->cap,&buf->vb.dma);
bttv_dma_free(btv,buf); bttv_dma_free(&fh->cap,btv,buf);
break; break;
default: default:
retval = -EINVAL; retval = -EINVAL;
@ -3162,8 +3219,8 @@ static int radio_open(struct inode *inode, struct file *file)
file->private_data = btv; file->private_data = btv;
bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL);
audio_mux(btv,AUDIO_RADIO); audio_input(btv,TVAUDIO_INPUT_RADIO);
mutex_unlock(&btv->lock); mutex_unlock(&btv->lock);
return 0; return 0;
@ -3749,7 +3806,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
bttv_irq_switch_video(btv); bttv_irq_switch_video(btv);
if ((astat & BT848_INT_HLOCK) && btv->opt_automute) if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
audio_mux(btv, -1); audio_mute(btv, btv->mute); /* trigger automute */
if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) { if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr, printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
@ -4050,7 +4107,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
bt848_contrast(btv,32768); bt848_contrast(btv,32768);
bt848_hue(btv,32768); bt848_hue(btv,32768);
bt848_sat(btv,32768); bt848_sat(btv,32768);
audio_mux(btv,AUDIO_MUTE); audio_mute(btv, 1);
set_input(btv,0); set_input(btv,0);
} }

View file

@ -302,6 +302,10 @@ static int attach_inform(struct i2c_client *client)
if (!client->driver->command) if (!client->driver->command)
return 0; return 0;
if (client->driver->id == I2C_DRIVERID_MSP3400)
btv->i2c_msp34xx_client = client;
if (client->driver->id == I2C_DRIVERID_TVAUDIO)
btv->i2c_tvaudio_client = client;
if (btv->tuner_type != UNSET) { if (btv->tuner_type != UNSET) {
struct tuner_setup tun_setup; struct tuner_setup tun_setup;

View file

@ -509,11 +509,11 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
} }
void void
bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf) bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
{ {
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0); videobuf_waiton(&buf->vb,0,0);
videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma); videobuf_dma_unmap(q, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma); videobuf_dma_free(&buf->vb.dma);
btcx_riscmem_free(btv->c.pci,&buf->bottom); btcx_riscmem_free(btv->c.pci,&buf->bottom);
btcx_riscmem_free(btv->c.pci,&buf->top); btcx_riscmem_free(btv->c.pci,&buf->top);

View file

@ -96,7 +96,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
return -EINVAL; return -EINVAL;
if (STATE_NEEDS_INIT == buf->vb.state) { if (STATE_NEEDS_INIT == buf->vb.state) {
if (0 != (rc = videobuf_iolock(btv->c.pci, &buf->vb, NULL))) if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
goto fail; goto fail;
if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines))) if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines)))
goto fail; goto fail;
@ -109,7 +109,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
return 0; return 0;
fail: fail:
bttv_dma_free(btv,buf); bttv_dma_free(q,btv,buf);
return rc; return rc;
} }
@ -136,7 +136,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
dprintk("free %p\n",vb); dprintk("free %p\n",vb);
bttv_dma_free(fh->btv,buf); bttv_dma_free(&fh->cap,fh->btv,buf);
} }
struct videobuf_queue_ops bttv_vbi_qops = { struct videobuf_queue_ops bttv_vbi_qops = {

View file

@ -18,6 +18,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <media/ir-common.h> #include <media/ir-common.h>
#include <media/ir-kbd-i2c.h> #include <media/ir-kbd-i2c.h>
#include <media/i2c-addr.h>
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
/* exported by bttv-cards.c */ /* exported by bttv-cards.c */
@ -168,25 +169,6 @@
#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f #define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f
#define BTTV_BOARD_MACHTV_MAGICTV 0x90 #define BTTV_BOARD_MACHTV_MAGICTV 0x90
/* i2c address list */
#define I2C_TSA5522 0xc2
#define I2C_TDA7432 0x8a
#define I2C_BT832_ALT1 0x88
#define I2C_BT832_ALT2 0x8a // alternate setting
#define I2C_TDA8425 0x82
#define I2C_TDA9840 0x84
#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */
#define I2C_TDA9874 0xb0 /* also used by 9875 */
#define I2C_TDA9875 0xb0
#define I2C_HAUPEE 0xa0
#define I2C_STBEE 0xae
#define I2C_VHX 0xc0
#define I2C_MSP3400 0x80
#define I2C_MSP3400_ALT 0x88
#define I2C_TEA6300 0x80 /* also used by 6320 */
#define I2C_DPL3518 0x84
#define I2C_TDA9887 0x86
/* more card-specific defines */ /* more card-specific defines */
#define PT2254_L_CHANNEL 0x10 #define PT2254_L_CHANNEL 0x10
#define PT2254_R_CHANNEL 0x08 #define PT2254_R_CHANNEL 0x08
@ -252,7 +234,8 @@ struct tvcard
unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
u32 gpiomask; u32 gpiomask;
u32 muxsel[16]; u32 muxsel[16];
u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ u32 gpiomux[4]; /* Tuner, Radio, external, internal */
u32 gpiomute; /* GPIO mute setting */
u32 gpiomask2; /* GPIO MUX mask */ u32 gpiomask2; /* GPIO MUX mask */
/* i2c audio flags */ /* i2c audio flags */

View file

@ -41,7 +41,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <media/video-buf.h> #include <media/video-buf.h>
#include <media/audiochip.h>
#include <media/tuner.h> #include <media/tuner.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/ir-common.h> #include <media/ir-common.h>
@ -190,7 +189,8 @@ int bttv_buffer_activate_video(struct bttv *btv,
struct bttv_buffer_set *set); struct bttv_buffer_set *set);
int bttv_buffer_activate_vbi(struct bttv *btv, int bttv_buffer_activate_vbi(struct bttv *btv,
struct bttv_buffer *vbi); struct bttv_buffer *vbi);
void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf); void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
struct bttv_buffer *buf);
/* overlay handling */ /* overlay handling */
int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
@ -298,6 +298,8 @@ struct bttv {
int i2c_state, i2c_rc; int i2c_state, i2c_rc;
int i2c_done; int i2c_done;
wait_queue_head_t i2c_queue; wait_queue_head_t i2c_queue;
struct i2c_client *i2c_msp34xx_client;
struct i2c_client *i2c_tvaudio_client;
/* video4linux (1) */ /* video4linux (1) */
struct video_device *video_dev; struct video_device *video_dev;
@ -320,6 +322,7 @@ struct bttv {
/* video state */ /* video state */
unsigned int input; unsigned int input;
unsigned int audio; unsigned int audio;
unsigned int mute;
unsigned long freq; unsigned long freq;
int tvnorm,hue,contrast,bright,saturation; int tvnorm,hue,contrast,bright,saturation;
struct v4l2_framebuffer fbuf; struct v4l2_framebuffer fbuf;

View file

@ -150,7 +150,7 @@ static int qc_calibrate(struct qcam_device *q)
static struct qcam_device *qcam_init(struct parport *port) static struct qcam_device *qcam_init(struct parport *port)
{ {
struct qcam_device *q; struct qcam_device *q;
q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
if(q==NULL) if(q==NULL)
return NULL; return NULL;
@ -158,16 +158,16 @@ static struct qcam_device *qcam_init(struct parport *port)
q->pport = port; q->pport = port;
q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
NULL, 0, NULL); NULL, 0, NULL);
if (q->pdev == NULL) if (q->pdev == NULL)
{ {
printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
port->name); port->name);
kfree(q); kfree(q);
return NULL; return NULL;
} }
memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
mutex_init(&q->lock); mutex_init(&q->lock);
q->port_mode = (QC_ANY | QC_NOTSET); q->port_mode = (QC_ANY | QC_NOTSET);
@ -236,12 +236,12 @@ static int qc_waithand(struct qcam_device *q, int val)
while (!((status = read_lpstatus(q)) & 8)) while (!((status = read_lpstatus(q)) & 8))
{ {
/* 1000 is enough spins on the I/O for all normal /* 1000 is enough spins on the I/O for all normal
cases, at that point we start to poll slowly cases, at that point we start to poll slowly
until the camera wakes up. However, we are until the camera wakes up. However, we are
busy blocked until the camera responds, so busy blocked until the camera responds, so
setting it lower is much better for interactive setting it lower is much better for interactive
response. */ response. */
if(runs++>maxpoll) if(runs++>maxpoll)
{ {
msleep_interruptible(5); msleep_interruptible(5);
@ -255,12 +255,12 @@ static int qc_waithand(struct qcam_device *q, int val)
while (((status = read_lpstatus(q)) & 8)) while (((status = read_lpstatus(q)) & 8))
{ {
/* 1000 is enough spins on the I/O for all normal /* 1000 is enough spins on the I/O for all normal
cases, at that point we start to poll slowly cases, at that point we start to poll slowly
until the camera wakes up. However, we are until the camera wakes up. However, we are
busy blocked until the camera responds, so busy blocked until the camera responds, so
setting it lower is much better for interactive setting it lower is much better for interactive
response. */ response. */
if(runs++>maxpoll) if(runs++>maxpoll)
{ {
msleep_interruptible(5); msleep_interruptible(5);
@ -282,17 +282,17 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
{ {
unsigned int status; unsigned int status;
int runs=0; int runs=0;
do do
{ {
status = read_lpdata(q); status = read_lpdata(q);
/* 1000 is enough spins on the I/O for all normal /* 1000 is enough spins on the I/O for all normal
cases, at that point we start to poll slowly cases, at that point we start to poll slowly
until the camera wakes up. However, we are until the camera wakes up. However, we are
busy blocked until the camera responds, so busy blocked until the camera responds, so
setting it lower is much better for interactive setting it lower is much better for interactive
response. */ response. */
if(runs++>maxpoll) if(runs++>maxpoll)
{ {
msleep_interruptible(5); msleep_interruptible(5);
@ -321,7 +321,7 @@ static int qc_detect(struct qcam_device *q)
lastreg = reg = read_lpstatus(q) & 0xf0; lastreg = reg = read_lpstatus(q) & 0xf0;
for (i = 0; i < 500; i++) for (i = 0; i < 500; i++)
{ {
reg = read_lpstatus(q) & 0xf0; reg = read_lpstatus(q) & 0xf0;
if (reg != lastreg) if (reg != lastreg)
@ -357,7 +357,7 @@ static int qc_detect(struct qcam_device *q)
static void qc_reset(struct qcam_device *q) static void qc_reset(struct qcam_device *q)
{ {
switch (q->port_mode & QC_FORCE_MASK) switch (q->port_mode & QC_FORCE_MASK)
{ {
case QC_FORCE_UNIDIR: case QC_FORCE_UNIDIR:
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
@ -370,7 +370,7 @@ static void qc_reset(struct qcam_device *q)
case QC_ANY: case QC_ANY:
write_lpcontrol(q, 0x20); write_lpcontrol(q, 0x20);
write_lpdata(q, 0x75); write_lpdata(q, 0x75);
if (read_lpdata(q) != 0x75) { if (read_lpdata(q) != 0x75) {
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
} else { } else {
@ -398,8 +398,8 @@ static void qc_reset(struct qcam_device *q)
static int qc_setscanmode(struct qcam_device *q) static int qc_setscanmode(struct qcam_device *q)
{ {
int old_mode = q->mode; int old_mode = q->mode;
switch (q->transfer_scale) switch (q->transfer_scale)
{ {
case 1: case 1:
q->mode = 0; q->mode = 0;
@ -412,7 +412,7 @@ static int qc_setscanmode(struct qcam_device *q)
break; break;
} }
switch (q->bpp) switch (q->bpp)
{ {
case 4: case 4:
break; break;
@ -421,7 +421,7 @@ static int qc_setscanmode(struct qcam_device *q)
break; break;
} }
switch (q->port_mode & QC_MODE_MASK) switch (q->port_mode & QC_MODE_MASK)
{ {
case QC_BIDIR: case QC_BIDIR:
q->mode += 1; q->mode += 1;
@ -430,10 +430,10 @@ static int qc_setscanmode(struct qcam_device *q)
case QC_UNIDIR: case QC_UNIDIR:
break; break;
} }
if (q->mode != old_mode) if (q->mode != old_mode)
q->status |= QC_PARAM_CHANGE; q->status |= QC_PARAM_CHANGE;
return 0; return 0;
} }
@ -451,7 +451,7 @@ static void qc_set(struct qcam_device *q)
/* Set the brightness. Yes, this is repetitive, but it works. /* Set the brightness. Yes, this is repetitive, but it works.
* Shorter versions seem to fail subtly. Feel free to try :-). */ * Shorter versions seem to fail subtly. Feel free to try :-). */
/* I think the problem was in qc_command, not here -- bls */ /* I think the problem was in qc_command, not here -- bls */
qc_command(q, 0xb); qc_command(q, 0xb);
qc_command(q, q->brightness); qc_command(q, q->brightness);
@ -502,13 +502,13 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
unsigned int hi2, lo2; unsigned int hi2, lo2;
static int state = 0; static int state = 0;
if (buffer == NULL) if (buffer == NULL)
{ {
state = 0; state = 0;
return 0; return 0;
} }
switch (q->port_mode & QC_MODE_MASK) switch (q->port_mode & QC_MODE_MASK)
{ {
case QC_BIDIR: /* Bi-directional Port */ case QC_BIDIR: /* Bi-directional Port */
write_lpcontrol(q, 0x26); write_lpcontrol(q, 0x26);
@ -517,7 +517,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
write_lpcontrol(q, 0x2e); write_lpcontrol(q, 0x2e);
lo2 = (qc_waithand2(q, 0) >> 1); lo2 = (qc_waithand2(q, 0) >> 1);
hi2 = (read_lpstatus(q) >> 3) & 0x1f; hi2 = (read_lpstatus(q) >> 3) & 0x1f;
switch (q->bpp) switch (q->bpp)
{ {
case 4: case 4:
buffer[0] = lo & 0xf; buffer[0] = lo & 0xf;
@ -544,7 +544,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
write_lpcontrol(q, 0xe); write_lpcontrol(q, 0xe);
hi = (qc_waithand(q, 0) & 0xf0) >> 4; hi = (qc_waithand(q, 0) & 0xf0) >> 4;
switch (q->bpp) switch (q->bpp)
{ {
case 4: case 4:
buffer[0] = lo; buffer[0] = lo;
@ -552,7 +552,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
ret = 2; ret = 2;
break; break;
case 6: case 6:
switch (state) switch (state)
{ {
case 0: case 0:
buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
@ -604,13 +604,13 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
int shift=8-q->bpp; int shift=8-q->bpp;
char invert; char invert;
if (q->mode == -1) if (q->mode == -1)
return -ENXIO; return -ENXIO;
qc_command(q, 0x7); qc_command(q, 0x7);
qc_command(q, q->mode); qc_command(q, q->mode);
if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
{ {
write_lpcontrol(q, 0x2e); /* turn port around */ write_lpcontrol(q, 0x2e); /* turn port around */
write_lpcontrol(q, 0x26); write_lpcontrol(q, 0x26);
@ -618,7 +618,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
write_lpcontrol(q, 0x2e); write_lpcontrol(q, 0x2e);
(void) qc_waithand(q, 0); (void) qc_waithand(q, 0);
} }
/* strange -- should be 15:63 below, but 4bpp is odd */ /* strange -- should be 15:63 below, but 4bpp is odd */
invert = (q->bpp == 4) ? 16 : 63; invert = (q->bpp == 4) ? 16 : 63;
@ -629,15 +629,15 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
q->transfer_scale; q->transfer_scale;
transperline = (transperline + divisor - 1) / divisor; transperline = (transperline + divisor - 1) / divisor;
for (i = 0, yield = yieldlines; i < linestotrans; i++) for (i = 0, yield = yieldlines; i < linestotrans; i++)
{ {
for (pixels_read = j = 0; j < transperline; j++) for (pixels_read = j = 0; j < transperline; j++)
{ {
bytes = qc_readbytes(q, buffer); bytes = qc_readbytes(q, buffer);
for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++)
{ {
int o; int o;
if (buffer[k] == 0 && invert == 16) if (buffer[k] == 0 && invert == 16)
{ {
/* 4bpp is odd (again) -- inverter is 16, not 15, but output /* 4bpp is odd (again) -- inverter is 16, not 15, but output
must be 0-15 -- bls */ must be 0-15 -- bls */
@ -653,7 +653,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
pixels_read += bytes; pixels_read += bytes;
} }
(void) qc_readbytes(q, NULL); /* reset state machine */ (void) qc_readbytes(q, NULL); /* reset state machine */
/* Grabbing an entire frame from the quickcam is a lengthy /* Grabbing an entire frame from the quickcam is a lengthy
process. We don't (usually) want to busy-block the process. We don't (usually) want to busy-block the
processor for the entire frame. yieldlines is a module processor for the entire frame. yieldlines is a module
@ -666,7 +666,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
} }
} }
if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
{ {
write_lpcontrol(q, 2); write_lpcontrol(q, 2);
write_lpcontrol(q, 6); write_lpcontrol(q, 6);
@ -687,7 +687,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
{ {
struct video_device *dev = video_devdata(file); struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev; struct qcam_device *qcam=(struct qcam_device *)dev;
switch(cmd) switch(cmd)
{ {
case VIDIOCGCAP: case VIDIOCGCAP:
@ -762,7 +762,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
if(p->depth!=4 && p->depth!=6) if(p->depth!=4 && p->depth!=6)
return -EINVAL; return -EINVAL;
/* /*
* Now load the camera. * Now load the camera.
*/ */
@ -790,11 +790,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
if(vw->width<80||vw->width>320) if(vw->width<80||vw->width>320)
return -EINVAL; return -EINVAL;
qcam->width = 320; qcam->width = 320;
qcam->height = 240; qcam->height = 240;
qcam->transfer_scale = 4; qcam->transfer_scale = 4;
if(vw->width>=160 && vw->height>=120) if(vw->width>=160 && vw->height>=120)
{ {
qcam->transfer_scale = 2; qcam->transfer_scale = 2;
@ -808,11 +808,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
mutex_lock(&qcam->lock); mutex_lock(&qcam->lock);
qc_setscanmode(qcam); qc_setscanmode(qcam);
mutex_unlock(&qcam->lock); mutex_unlock(&qcam->lock);
/* We must update the camera before we grab. We could /* We must update the camera before we grab. We could
just have changed the grab size */ just have changed the grab size */
qcam->status |= QC_PARAM_CHANGE; qcam->status |= QC_PARAM_CHANGE;
/* Ok we figured out what to use from our wide choice */ /* Ok we figured out what to use from our wide choice */
return 0; return 0;
} }
@ -853,9 +853,9 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
struct qcam_device *qcam=(struct qcam_device *)v; struct qcam_device *qcam=(struct qcam_device *)v;
int len; int len;
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
mutex_lock(&qcam->lock); mutex_lock(&qcam->lock);
qc_reset(qcam); qc_reset(qcam);
/* Update the camera parameters if we need to */ /* Update the camera parameters if we need to */
@ -863,13 +863,13 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
qc_set(qcam); qc_set(qcam);
len=qc_capture(qcam, buf,count); len=qc_capture(qcam, buf,count);
mutex_unlock(&qcam->lock); mutex_unlock(&qcam->lock);
parport_release(qcam->pdev); parport_release(qcam->pdev);
return len; return len;
} }
static struct file_operations qcam_fops = { static struct file_operations qcam_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = video_exclusive_open, .open = video_exclusive_open,
@ -905,11 +905,11 @@ static int init_bwqcam(struct parport *port)
qcam=qcam_init(port); qcam=qcam_init(port);
if(qcam==NULL) if(qcam==NULL)
return -ENODEV; return -ENODEV;
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
qc_reset(qcam); qc_reset(qcam);
if(qc_detect(qcam)==0) if(qc_detect(qcam)==0)
{ {
parport_release(qcam->pdev); parport_release(qcam->pdev);
@ -920,9 +920,9 @@ static int init_bwqcam(struct parport *port)
qc_calibrate(qcam); qc_calibrate(qcam);
parport_release(qcam->pdev); parport_release(qcam->pdev);
printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1) if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
{ {
parport_unregister_device(qcam->pdev); parport_unregister_device(qcam->pdev);
@ -1013,7 +1013,7 @@ static int __init init_bw_qcams(void)
printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n"); printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n");
maxpoll = 5000; maxpoll = 5000;
} }
if (yieldlines < 1) { if (yieldlines < 1) {
printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n"); printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n");
yieldlines = 1; yieldlines = 1;

View file

@ -16,7 +16,7 @@
* *
* The parport parameter controls which parports will be scanned. * The parport parameter controls which parports will be scanned.
* Scanning all parports causes some printers to print a garbage page. * Scanning all parports causes some printers to print a garbage page.
* -- March 14, 1999 Billy Donahue <billy@escape.com> * -- March 14, 1999 Billy Donahue <billy@escape.com>
* *
* Fixed data format to BGR, added force_rgb parameter. Added missing * Fixed data format to BGR, added force_rgb parameter. Added missing
* parport_unregister_driver() on module removal. * parport_unregister_driver() on module removal.
@ -88,7 +88,7 @@ static inline unsigned int qcam_ready2(struct qcam_device *qcam)
return (parport_read_data(qcam->pport) & 0x1)?1:0; return (parport_read_data(qcam->pport) & 0x1)?1:0;
} }
static unsigned int qcam_await_ready1(struct qcam_device *qcam, static unsigned int qcam_await_ready1(struct qcam_device *qcam,
int value) int value)
{ {
unsigned long oldjiffies = jiffies; unsigned long oldjiffies = jiffies;
@ -98,7 +98,7 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
if (qcam_ready1(qcam) == value) if (qcam_ready1(qcam) == value)
return 0; return 0;
/* If the camera didn't respond within 1/25 second, poll slowly /* If the camera didn't respond within 1/25 second, poll slowly
for a while. */ for a while. */
for (i = 0; i < 50; i++) for (i = 0; i < 50; i++)
{ {
@ -123,7 +123,7 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
if (qcam_ready2(qcam) == value) if (qcam_ready2(qcam) == value)
return 0; return 0;
/* If the camera didn't respond within 1/25 second, poll slowly /* If the camera didn't respond within 1/25 second, poll slowly
for a while. */ for a while. */
for (i = 0; i < 50; i++) for (i = 0; i < 50; i++)
{ {
@ -157,12 +157,12 @@ static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
unsigned int idata; unsigned int idata;
parport_write_data(qcam->pport, data); parport_write_data(qcam->pport, data);
idata = qcam_read_data(qcam); idata = qcam_read_data(qcam);
if (data != idata) if (data != idata)
{ {
printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
idata); idata);
return 1; return 1;
} }
return 0; return 0;
} }
@ -193,12 +193,12 @@ static int qc_detect(struct qcam_device *qcam)
no device was found". Fix this one day. */ no device was found". Fix this one day. */
if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
&& qcam->pport->probe_info[0].model && qcam->pport->probe_info[0].model
&& !strcmp(qcam->pdev->port->probe_info[0].model, && !strcmp(qcam->pdev->port->probe_info[0].model,
"Color QuickCam 2.0")) { "Color QuickCam 2.0")) {
printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n"); printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
return 1; return 1;
} }
if (probe < 2) if (probe < 2)
return 0; return 0;
@ -206,11 +206,11 @@ static int qc_detect(struct qcam_device *qcam)
/* look for a heartbeat */ /* look for a heartbeat */
ostat = stat = parport_read_status(qcam->pport); ostat = stat = parport_read_status(qcam->pport);
for (i=0; i<250; i++) for (i=0; i<250; i++)
{ {
mdelay(1); mdelay(1);
stat = parport_read_status(qcam->pport); stat = parport_read_status(qcam->pport);
if (ostat != stat) if (ostat != stat)
{ {
if (++count >= 3) return 1; if (++count >= 3) return 1;
ostat = stat; ostat = stat;
@ -226,11 +226,11 @@ static int qc_detect(struct qcam_device *qcam)
count = 0; count = 0;
ostat = stat = parport_read_status(qcam->pport); ostat = stat = parport_read_status(qcam->pport);
for (i=0; i<250; i++) for (i=0; i<250; i++)
{ {
mdelay(1); mdelay(1);
stat = parport_read_status(qcam->pport); stat = parport_read_status(qcam->pport);
if (ostat != stat) if (ostat != stat)
{ {
if (++count >= 3) return 1; if (++count >= 3) return 1;
ostat = stat; ostat = stat;
@ -247,7 +247,7 @@ static void qc_reset(struct qcam_device *qcam)
parport_write_control(qcam->pport, 0x8); parport_write_control(qcam->pport, 0x8);
mdelay(1); mdelay(1);
parport_write_control(qcam->pport, 0xc); parport_write_control(qcam->pport, 0xc);
mdelay(1); mdelay(1);
} }
/* Reset the QuickCam and program for brightness, contrast, /* Reset the QuickCam and program for brightness, contrast,
@ -258,7 +258,7 @@ static void qc_setup(struct qcam_device *q)
qc_reset(q); qc_reset(q);
/* Set the brightness. */ /* Set the brightness. */
qcam_set(q, 11, q->brightness); qcam_set(q, 11, q->brightness);
/* Set the height and width. These refer to the actual /* Set the height and width. These refer to the actual
CCD area *before* applying the selected decimation. */ CCD area *before* applying the selected decimation. */
@ -272,12 +272,12 @@ static void qc_setup(struct qcam_device *q)
/* Set contrast and white balance. */ /* Set contrast and white balance. */
qcam_set(q, 0x19, q->contrast); qcam_set(q, 0x19, q->contrast);
qcam_set(q, 0x1f, q->whitebal); qcam_set(q, 0x1f, q->whitebal);
/* Set the speed. */ /* Set the speed. */
qcam_set(q, 45, 2); qcam_set(q, 45, 2);
} }
/* Read some bytes from the camera and put them in the buffer. /* Read some bytes from the camera and put them in the buffer.
nbytes should be a multiple of 3, because bidirectional mode gives nbytes should be a multiple of 3, because bidirectional mode gives
us three bytes at a time. */ us three bytes at a time. */
@ -383,7 +383,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1)) if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
return -EIO; return -EIO;
lines = q->height; lines = q->height;
pixelsperline = q->width; pixelsperline = q->width;
bitsperxfer = (is_bi_dir) ? 24 : 8; bitsperxfer = (is_bi_dir) ? 24 : 8;
@ -499,7 +499,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
{ {
struct video_device *dev = video_devdata(file); struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev; struct qcam_device *qcam=(struct qcam_device *)dev;
switch(cmd) switch(cmd)
{ {
case VIDIOCGCAP: case VIDIOCGCAP:
@ -574,7 +574,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
*/ */
if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24) if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
return -EINVAL; return -EINVAL;
/* /*
* Now load the camera. * Now load the camera.
*/ */
@ -584,7 +584,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
mutex_lock(&qcam->lock); mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
qc_setup(qcam); qc_setup(qcam);
parport_release(qcam->pdev); parport_release(qcam->pdev);
mutex_unlock(&qcam->lock); mutex_unlock(&qcam->lock);
return 0; return 0;
@ -601,11 +601,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
if(vw->width<80||vw->width>320) if(vw->width<80||vw->width>320)
return -EINVAL; return -EINVAL;
qcam->width = 80; qcam->width = 80;
qcam->height = 60; qcam->height = 60;
qcam->mode = QC_DECIMATION_4; qcam->mode = QC_DECIMATION_4;
if(vw->width>=160 && vw->height>=120) if(vw->width>=160 && vw->height>=120)
{ {
qcam->width = 160; qcam->width = 160;
@ -627,7 +627,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
qcam->mode = QC_BILLIONS | QC_DECIMATION_1; qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
} }
#endif #endif
/* Ok we figured out what to use from our /* Ok we figured out what to use from our
wide choice */ wide choice */
mutex_lock(&qcam->lock); mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
@ -676,7 +676,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
mutex_lock(&qcam->lock); mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
/* Probably should have a semaphore against multiple users */ /* Probably should have a semaphore against multiple users */
len = qc_capture(qcam, buf,count); len = qc_capture(qcam, buf,count);
parport_release(qcam->pdev); parport_release(qcam->pdev);
mutex_unlock(&qcam->lock); mutex_unlock(&qcam->lock);
return len; return len;
@ -707,7 +707,7 @@ static struct video_device qcam_template=
static struct qcam_device *qcam_init(struct parport *port) static struct qcam_device *qcam_init(struct parport *port)
{ {
struct qcam_device *q; struct qcam_device *q;
q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
if(q==NULL) if(q==NULL)
return NULL; return NULL;
@ -718,14 +718,14 @@ static struct qcam_device *qcam_init(struct parport *port)
q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0; q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0;
if (q->pdev == NULL) if (q->pdev == NULL)
{ {
printk(KERN_ERR "c-qcam: couldn't register for %s.\n", printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
port->name); port->name);
kfree(q); kfree(q);
return NULL; return NULL;
} }
memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
mutex_init(&q->lock); mutex_init(&q->lock);
@ -766,11 +766,11 @@ static int init_cqcam(struct parport *port)
qcam = qcam_init(port); qcam = qcam_init(port);
if (qcam==NULL) if (qcam==NULL)
return -ENODEV; return -ENODEV;
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
qc_reset(qcam); qc_reset(qcam);
if (probe && qc_detect(qcam)==0) if (probe && qc_detect(qcam)==0)
{ {
parport_release(qcam->pdev); parport_release(qcam->pdev);
@ -782,7 +782,7 @@ static int init_cqcam(struct parport *port)
qc_setup(qcam); qc_setup(qcam);
parport_release(qcam->pdev); parport_release(qcam->pdev);
if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1) if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
{ {
printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
@ -792,9 +792,9 @@ static int init_cqcam(struct parport *port)
return -ENODEV; return -ENODEV;
} }
printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
qcam->vdev.minor, qcam->pport->name); qcam->vdev.minor, qcam->pport->name);
qcams[num_cams++] = qcam; qcams[num_cams++] = qcam;
return 0; return 0;

File diff suppressed because it is too large Load diff

View file

@ -52,10 +52,10 @@
struct cpia_camera_ops struct cpia_camera_ops
{ {
/* open sets privdata to point to structure for this camera. /* open sets privdata to point to structure for this camera.
* Returns negative value on error, otherwise 0. * Returns negative value on error, otherwise 0.
*/ */
int (*open)(void *privdata); int (*open)(void *privdata);
/* Registers callback function cb to be called with cbdata /* Registers callback function cb to be called with cbdata
* when an image is ready. If cb is NULL, only single image grabs * when an image is ready. If cb is NULL, only single image grabs
* should be used. cb should immediately call streamRead to read * should be used. cb should immediately call streamRead to read
@ -63,8 +63,8 @@ struct cpia_camera_ops
* otherwise 0. * otherwise 0.
*/ */
int (*registerCallback)(void *privdata, void (*cb)(void *cbdata), int (*registerCallback)(void *privdata, void (*cb)(void *cbdata),
void *cbdata); void *cbdata);
/* transferCmd sends commands to the camera. command MUST point to /* transferCmd sends commands to the camera. command MUST point to
* an 8 byte buffer in kernel space. data can be NULL if no extra * an 8 byte buffer in kernel space. data can be NULL if no extra
* data is needed. The size of the data is given by the last 2 * data is needed. The size of the data is given by the last 2
@ -77,30 +77,30 @@ struct cpia_camera_ops
* Returns negative value on error, otherwise 0. * Returns negative value on error, otherwise 0.
*/ */
int (*streamStart)(void *privdata); int (*streamStart)(void *privdata);
/* streamStop terminates stream capture mode. /* streamStop terminates stream capture mode.
* Returns negative value on error, otherwise 0. * Returns negative value on error, otherwise 0.
*/ */
int (*streamStop)(void *privdata); int (*streamStop)(void *privdata);
/* streamRead reads a frame from the camera. buffer points to a /* streamRead reads a frame from the camera. buffer points to a
* buffer large enough to hold a complete frame in kernel space. * buffer large enough to hold a complete frame in kernel space.
* noblock indicates if this should be a non blocking read. * noblock indicates if this should be a non blocking read.
* Returns the number of bytes read, or negative value on error. * Returns the number of bytes read, or negative value on error.
*/ */
int (*streamRead)(void *privdata, u8 *buffer, int noblock); int (*streamRead)(void *privdata, u8 *buffer, int noblock);
/* close disables the device until open() is called again. /* close disables the device until open() is called again.
* Returns negative value on error, otherwise 0. * Returns negative value on error, otherwise 0.
*/ */
int (*close)(void *privdata); int (*close)(void *privdata);
/* If wait_for_stream_ready is non-zero, wait until the streamState /* If wait_for_stream_ready is non-zero, wait until the streamState
* is STREAM_READY before calling streamRead. * is STREAM_READY before calling streamRead.
*/ */
int wait_for_stream_ready; int wait_for_stream_ready;
/* /*
* Used to maintain lowlevel module usage counts * Used to maintain lowlevel module usage counts
*/ */
struct module *owner; struct module *owner;
@ -215,14 +215,14 @@ struct cam_params {
u8 videoSize; /* CIF/QCIF */ u8 videoSize; /* CIF/QCIF */
u8 subSample; u8 subSample;
u8 yuvOrder; u8 yuvOrder;
} format; } format;
struct { /* Intel QX3 specific data */ struct { /* Intel QX3 specific data */
u8 qx3_detected; /* a QX3 is present */ u8 qx3_detected; /* a QX3 is present */
u8 toplight; /* top light lit , R/W */ u8 toplight; /* top light lit , R/W */
u8 bottomlight; /* bottom light lit, R/W */ u8 bottomlight; /* bottom light lit, R/W */
u8 button; /* snapshot button pressed (R/O) */ u8 button; /* snapshot button pressed (R/O) */
u8 cradled; /* microscope is in cradle (R/O) */ u8 cradled; /* microscope is in cradle (R/O) */
} qx3; } qx3;
struct { struct {
u8 colStart; /* skip first 8*colStart pixels */ u8 colStart; /* skip first 8*colStart pixels */
u8 colEnd; /* finish at 8*colEnd pixels */ u8 colEnd; /* finish at 8*colEnd pixels */
@ -247,13 +247,13 @@ enum v4l_camstates {
struct cam_data { struct cam_data {
struct list_head cam_data_list; struct list_head cam_data_list;
struct mutex busy_lock; /* guard against SMP multithreading */ struct mutex busy_lock; /* guard against SMP multithreading */
struct cpia_camera_ops *ops; /* lowlevel driver operations */ struct cpia_camera_ops *ops; /* lowlevel driver operations */
void *lowlevel_data; /* private data for lowlevel driver */ void *lowlevel_data; /* private data for lowlevel driver */
u8 *raw_image; /* buffer for raw image data */ u8 *raw_image; /* buffer for raw image data */
struct cpia_frame decompressed_frame; struct cpia_frame decompressed_frame;
/* buffer to hold decompressed frame */ /* buffer to hold decompressed frame */
int image_size; /* sizeof last decompressed image */ int image_size; /* sizeof last decompressed image */
int open_count; /* # of process that have camera open */ int open_count; /* # of process that have camera open */
/* camera status */ /* camera status */
@ -265,7 +265,7 @@ struct cam_data {
struct mutex param_lock; /* params lock for this camera */ struct mutex param_lock; /* params lock for this camera */
struct cam_params params; /* camera settings */ struct cam_params params; /* camera settings */
struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */ struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */
/* v4l */ /* v4l */
int video_size; /* VIDEO_SIZE_ */ int video_size; /* VIDEO_SIZE_ */
volatile enum v4l_camstates camstate; /* v4l layer status */ volatile enum v4l_camstates camstate; /* v4l layer status */
@ -277,7 +277,7 @@ struct cam_data {
/* mmap interface */ /* mmap interface */
int curframe; /* the current frame to grab into */ int curframe; /* the current frame to grab into */
u8 *frame_buf; /* frame buffer data */ u8 *frame_buf; /* frame buffer data */
struct cpia_frame frame[FRAME_NUM]; struct cpia_frame frame[FRAME_NUM];
/* FRAME_NUM-buffering, so we need a array */ /* FRAME_NUM-buffering, so we need a array */
int first_frame; int first_frame;
@ -424,7 +424,7 @@ void cpia_unregister_camera(struct cam_data *cam);
#define DEB_BYTE(p)\ #define DEB_BYTE(p)\
DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\ DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\
(p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\ (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\
(p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0); (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */

View file

@ -381,7 +381,7 @@ struct cpia2_fh {
struct camera_data { struct camera_data {
/* locks */ /* locks */
struct semaphore busy_lock; /* guard against SMP multithreading */ struct mutex busy_lock; /* guard against SMP multithreading */
struct v4l2_prio_state prio; struct v4l2_prio_state prio;
/* camera status */ /* camera status */

View file

@ -2238,7 +2238,7 @@ struct camera_data *cpia2_init_camera_struct(void)
memset(cam, 0, sizeof(struct camera_data)); memset(cam, 0, sizeof(struct camera_data));
cam->present = 1; cam->present = 1;
init_MUTEX(&cam->busy_lock); mutex_init(&cam->busy_lock);
init_waitqueue_head(&cam->wq_stream); init_waitqueue_head(&cam->wq_stream);
return cam; return cam;
@ -2371,12 +2371,12 @@ long cpia2_read(struct camera_data *cam,
} }
/* make this _really_ smp and multithread-safe */ /* make this _really_ smp and multithread-safe */
if (down_interruptible(&cam->busy_lock)) if (mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
if (!cam->present) { if (!cam->present) {
LOG("%s: camera removed\n",__FUNCTION__); LOG("%s: camera removed\n",__FUNCTION__);
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return 0; /* EOF */ return 0; /* EOF */
} }
@ -2389,34 +2389,34 @@ long cpia2_read(struct camera_data *cam,
/* Copy cam->curbuff in case it changes while we're processing */ /* Copy cam->curbuff in case it changes while we're processing */
frame = cam->curbuff; frame = cam->curbuff;
if (noblock && frame->status != FRAME_READY) { if (noblock && frame->status != FRAME_READY) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -EAGAIN; return -EAGAIN;
} }
if(frame->status != FRAME_READY) { if(frame->status != FRAME_READY) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
wait_event_interruptible(cam->wq_stream, wait_event_interruptible(cam->wq_stream,
!cam->present || !cam->present ||
(frame = cam->curbuff)->status == FRAME_READY); (frame = cam->curbuff)->status == FRAME_READY);
if (signal_pending(current)) if (signal_pending(current))
return -ERESTARTSYS; return -ERESTARTSYS;
/* make this _really_ smp and multithread-safe */ /* make this _really_ smp and multithread-safe */
if (down_interruptible(&cam->busy_lock)) { if (mutex_lock_interruptible(&cam->busy_lock)) {
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if(!cam->present) { if(!cam->present) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return 0; return 0;
} }
} }
/* copy data to user space */ /* copy data to user space */
if (frame->length > count) { if (frame->length > count) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -EFAULT; return -EFAULT;
} }
if (copy_to_user(buf, frame->data, frame->length)) { if (copy_to_user(buf, frame->data, frame->length)) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -EFAULT; return -EFAULT;
} }
@ -2424,7 +2424,7 @@ long cpia2_read(struct camera_data *cam,
frame->status = FRAME_EMPTY; frame->status = FRAME_EMPTY;
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return count; return count;
} }
@ -2443,10 +2443,10 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
return POLLERR; return POLLERR;
} }
down(&cam->busy_lock); mutex_lock(&cam->busy_lock);
if(!cam->present) { if(!cam->present) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return POLLHUP; return POLLHUP;
} }
@ -2456,16 +2456,16 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
cam->params.camera_state.stream_mode); cam->params.camera_state.stream_mode);
} }
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
poll_wait(filp, &cam->wq_stream, wait); poll_wait(filp, &cam->wq_stream, wait);
down(&cam->busy_lock); mutex_lock(&cam->busy_lock);
if(!cam->present) if(!cam->present)
status = POLLHUP; status = POLLHUP;
else if(cam->curbuff->status == FRAME_READY) else if(cam->curbuff->status == FRAME_READY)
status = POLLIN | POLLRDNORM; status = POLLIN | POLLRDNORM;
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return status; return status;
} }
@ -2488,18 +2488,18 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
DBG("mmap offset:%ld size:%ld\n", start_offset, size); DBG("mmap offset:%ld size:%ld\n", start_offset, size);
/* make this _really_ smp-safe */ /* make this _really_ smp-safe */
if (down_interruptible(&cam->busy_lock)) if (mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
if (!cam->present) { if (!cam->present) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -ENODEV; return -ENODEV;
} }
if (size > cam->frame_size*cam->num_frames || if (size > cam->frame_size*cam->num_frames ||
(start_offset % cam->frame_size) != 0 || (start_offset % cam->frame_size) != 0 ||
(start_offset+size > cam->frame_size*cam->num_frames)) { (start_offset+size > cam->frame_size*cam->num_frames)) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -EINVAL; return -EINVAL;
} }
@ -2507,7 +2507,7 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
while (size > 0) { while (size > 0) {
page = kvirt_to_pa(pos); page = kvirt_to_pa(pos);
if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) { if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -EAGAIN; return -EAGAIN;
} }
start += PAGE_SIZE; start += PAGE_SIZE;
@ -2519,7 +2519,7 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
} }
cam->mmapped = true; cam->mmapped = true;
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return 0; return 0;
} }

View file

@ -255,7 +255,7 @@ static int cpia2_open(struct inode *inode, struct file *file)
return -ENODEV; return -ENODEV;
} }
if(down_interruptible(&cam->busy_lock)) if(mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
if(!cam->present) { if(!cam->present) {
@ -299,7 +299,7 @@ static int cpia2_open(struct inode *inode, struct file *file)
cpia2_dbg_dump_registers(cam); cpia2_dbg_dump_registers(cam);
err_return: err_return:
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return retval; return retval;
} }
@ -314,7 +314,7 @@ static int cpia2_close(struct inode *inode, struct file *file)
struct camera_data *cam = video_get_drvdata(dev); struct camera_data *cam = video_get_drvdata(dev);
struct cpia2_fh *fh = file->private_data; struct cpia2_fh *fh = file->private_data;
down(&cam->busy_lock); mutex_lock(&cam->busy_lock);
if (cam->present && if (cam->present &&
(cam->open_count == 1 (cam->open_count == 1
@ -347,7 +347,7 @@ static int cpia2_close(struct inode *inode, struct file *file)
} }
} }
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return 0; return 0;
} }
@ -523,11 +523,11 @@ static int sync(struct camera_data *cam, int frame_nr)
return 0; return 0;
} }
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
wait_event_interruptible(cam->wq_stream, wait_event_interruptible(cam->wq_stream,
!cam->streaming || !cam->streaming ||
frame->status == FRAME_READY); frame->status == FRAME_READY);
down(&cam->busy_lock); mutex_lock(&cam->busy_lock);
if (signal_pending(current)) if (signal_pending(current))
return -ERESTARTSYS; return -ERESTARTSYS;
if(!cam->present) if(!cam->present)
@ -1544,11 +1544,11 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
if(frame < 0) { if(frame < 0) {
/* Wait for a frame to become available */ /* Wait for a frame to become available */
struct framebuf *cb=cam->curbuff; struct framebuf *cb=cam->curbuff;
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
wait_event_interruptible(cam->wq_stream, wait_event_interruptible(cam->wq_stream,
!cam->present || !cam->present ||
(cb=cam->curbuff)->status == FRAME_READY); (cb=cam->curbuff)->status == FRAME_READY);
down(&cam->busy_lock); mutex_lock(&cam->busy_lock);
if (signal_pending(current)) if (signal_pending(current))
return -ERESTARTSYS; return -ERESTARTSYS;
if(!cam->present) if(!cam->present)
@ -1591,11 +1591,11 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
return -ENOTTY; return -ENOTTY;
/* make this _really_ smp-safe */ /* make this _really_ smp-safe */
if (down_interruptible(&cam->busy_lock)) if (mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
if (!cam->present) { if (!cam->present) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -ENODEV; return -ENODEV;
} }
@ -1608,7 +1608,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
struct cpia2_fh *fh = file->private_data; struct cpia2_fh *fh = file->private_data;
retval = v4l2_prio_check(&cam->prio, &fh->prio); retval = v4l2_prio_check(&cam->prio, &fh->prio);
if(retval) { if(retval) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return retval; return retval;
} }
break; break;
@ -1618,7 +1618,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
{ {
struct cpia2_fh *fh = file->private_data; struct cpia2_fh *fh = file->private_data;
if(fh->prio != V4L2_PRIORITY_RECORD) { if(fh->prio != V4L2_PRIORITY_RECORD) {
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -EBUSY; return -EBUSY;
} }
break; break;
@ -1847,7 +1847,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
break; break;
} }
up(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return retval; return retval;
} }
@ -1924,14 +1924,15 @@ static void reset_camera_struct_v4l(struct camera_data *cam)
* The v4l video device structure initialized for this device * The v4l video device structure initialized for this device
***/ ***/
static struct file_operations fops_template = { static struct file_operations fops_template = {
.owner= THIS_MODULE, .owner = THIS_MODULE,
.open= cpia2_open, .open = cpia2_open,
.release= cpia2_close, .release = cpia2_close,
.read= cpia2_v4l_read, .read = cpia2_v4l_read,
.poll= cpia2_v4l_poll, .poll = cpia2_v4l_poll,
.ioctl= cpia2_ioctl, .ioctl = cpia2_ioctl,
.llseek= no_llseek, .llseek = no_llseek,
.mmap= cpia2_mmap, .compat_ioctl = v4l_compat_ioctl32,
.mmap = cpia2_mmap,
}; };
static struct video_device cpia2_template = { static struct video_device cpia2_template = {

View file

@ -23,7 +23,7 @@
*/ */
/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ /* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
/* #define _CPIA_DEBUG_ 1 */ /* #define _CPIA_DEBUG_ 1 */
#include <linux/config.h> #include <linux/config.h>
@ -45,7 +45,7 @@
static int cpia_pp_open(void *privdata); static int cpia_pp_open(void *privdata);
static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata), static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
void *cbdata); void *cbdata);
static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data); static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
static int cpia_pp_streamStart(void *privdata); static int cpia_pp_streamStart(void *privdata);
static int cpia_pp_streamStop(void *privdata); static int cpia_pp_streamStop(void *privdata);
@ -93,7 +93,7 @@ struct pp_cam_entry {
int stream_irq; int stream_irq;
}; };
static struct cpia_camera_ops cpia_pp_ops = static struct cpia_camera_ops cpia_pp_ops =
{ {
cpia_pp_open, cpia_pp_open,
cpia_pp_registerCallback, cpia_pp_registerCallback,
@ -123,7 +123,7 @@ static void cpia_parport_disable_irq( struct parport *port ) {
} }
/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility /* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility
* Link Flag during negotiation */ * Link Flag during negotiation */
#define UPLOAD_FLAG 0x08 #define UPLOAD_FLAG 0x08
#define NIBBLE_TRANSFER 0x01 #define NIBBLE_TRANSFER 0x01
#define ECP_TRANSFER 0x03 #define ECP_TRANSFER 0x03
@ -139,17 +139,17 @@ static void cpia_parport_disable_irq( struct parport *port ) {
/* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */ /* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */
/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */ /* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */
static size_t cpia_read_nibble (struct parport *port, static size_t cpia_read_nibble (struct parport *port,
void *buffer, size_t len, void *buffer, size_t len,
int flags) int flags)
{ {
/* adapted verbatim, with one change, from /* adapted verbatim, with one change, from
parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */ parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */
unsigned char *buf = buffer; unsigned char *buf = buffer;
int i; int i;
unsigned char byte = 0; unsigned char byte = 0;
len *= 2; /* in nibbles */ len *= 2; /* in nibbles */
for (i=0; i < len; i++) { for (i=0; i < len; i++) {
unsigned char nibble; unsigned char nibble;
@ -158,12 +158,12 @@ static size_t cpia_read_nibble (struct parport *port,
* after every second nibble to signal that more * after every second nibble to signal that more
* data is available. (the total number of Bytes that * data is available. (the total number of Bytes that
* should be sent is known; if too few are received, an error * should be sent is known; if too few are received, an error
* will be recorded after a timeout). * will be recorded after a timeout).
* This is incompatible with parport_ieee1284_read_nibble(), * This is incompatible with parport_ieee1284_read_nibble(),
* which expects to find nFault LO after every second nibble. * which expects to find nFault LO after every second nibble.
*/ */
/* Solution: modify cpia_read_nibble to only check for /* Solution: modify cpia_read_nibble to only check for
* nDataAvail before the first nibble is sent. * nDataAvail before the first nibble is sent.
*/ */
@ -216,7 +216,7 @@ static size_t cpia_read_nibble (struct parport *port,
/* Second nibble */ /* Second nibble */
byte |= nibble << 4; byte |= nibble << 4;
*buf++ = byte; *buf++ = byte;
} else } else
byte = nibble; byte = nibble;
} }
@ -238,18 +238,18 @@ static size_t cpia_read_nibble (struct parport *port,
} }
/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1) /* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
* (See CPiA Data sheet p. 31) * (See CPiA Data sheet p. 31)
* *
* "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a
* nonstandard variant of nibble mode which allows the same (mediocre) * nonstandard variant of nibble mode which allows the same (mediocre)
* data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable
* parallel ports, but works also for non-TRISTATE-capable ports. * parallel ports, but works also for non-TRISTATE-capable ports.
* (Standard nibble mode only send 4 bits per cycle) * (Standard nibble mode only send 4 bits per cycle)
* *
*/ */
static size_t cpia_read_nibble_stream(struct parport *port, static size_t cpia_read_nibble_stream(struct parport *port,
void *buffer, size_t len, void *buffer, size_t len,
int flags) int flags)
{ {
int i; int i;
@ -260,7 +260,7 @@ static size_t cpia_read_nibble_stream(struct parport *port,
unsigned char nibble[2], byte = 0; unsigned char nibble[2], byte = 0;
int j; int j;
/* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */
if (endseen > 3 ) if (endseen > 3 )
break; break;
@ -268,7 +268,7 @@ static size_t cpia_read_nibble_stream(struct parport *port,
parport_frob_control (port, parport_frob_control (port,
PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD,
PARPORT_CONTROL_AUTOFD); PARPORT_CONTROL_AUTOFD);
/* Event 9: nAck goes low. */ /* Event 9: nAck goes low. */
port->ieee1284.phase = IEEE1284_PH_REV_DATA; port->ieee1284.phase = IEEE1284_PH_REV_DATA;
if (parport_wait_peripheral (port, if (parport_wait_peripheral (port,
@ -282,7 +282,7 @@ static size_t cpia_read_nibble_stream(struct parport *port,
/* Read lower nibble */ /* Read lower nibble */
nibble[0] = parport_read_status (port) >>3; nibble[0] = parport_read_status (port) >>3;
/* Event 10: Set nAutoFd high. */ /* Event 10: Set nAutoFd high. */
parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
@ -295,10 +295,10 @@ static size_t cpia_read_nibble_stream(struct parport *port,
port->name); port->name);
break; break;
} }
/* Read upper nibble */ /* Read upper nibble */
nibble[1] = parport_read_status (port) >>3; nibble[1] = parport_read_status (port) >>3;
/* reassemble the byte */ /* reassemble the byte */
for (j = 0; j < 2 ; j++ ) { for (j = 0; j < 2 ; j++ ) {
nibble[j] &= ~8; nibble[j] &= ~8;
@ -335,8 +335,8 @@ static void EndTransferMode(struct pp_cam_entry *cam)
static int ForwardSetup(struct pp_cam_entry *cam) static int ForwardSetup(struct pp_cam_entry *cam)
{ {
int retry; int retry;
/* The CPiA uses ECP protocol for Downloads from the Host to the camera. /* The CPiA uses ECP protocol for Downloads from the Host to the camera.
* This will be software-emulated if ECP hardware is not present * This will be software-emulated if ECP hardware is not present
*/ */
@ -375,9 +375,9 @@ static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
upload_mode = mode; upload_mode = mode;
if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK; if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;
/* the usual camera maximum response time is 10ms, but after /* the usual camera maximum response time is 10ms, but after
* receiving some commands, it needs up to 40ms. */ * receiving some commands, it needs up to 40ms. */
for(retry = 0; retry < 4; ++retry) { for(retry = 0; retry < 4; ++retry) {
if(!parport_negotiate(cam->port, mode)) { if(!parport_negotiate(cam->port, mode)) {
break; break;
@ -439,10 +439,10 @@ static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
/* support for CPiA variant nibble reads */ /* support for CPiA variant nibble reads */
if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) { if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) {
if(cpia_read_nibble(cam->port, packet, size, 0) != size) if(cpia_read_nibble(cam->port, packet, size, 0) != size)
retval = -EIO; retval = -EIO;
} else { } else {
if(parport_read(cam->port, packet, size) != size) if(parport_read(cam->port, packet, size) != size)
retval = -EIO; retval = -EIO;
} }
EndTransferMode(cam); EndTransferMode(cam);
@ -542,18 +542,18 @@ static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
block_size = PARPORT_CHUNK_SIZE; block_size = PARPORT_CHUNK_SIZE;
while( !cam->image_complete ) { while( !cam->image_complete ) {
cond_resched(); cond_resched();
new_bytes = cpia_pp_read(cam->port, buffer, block_size ); new_bytes = cpia_pp_read(cam->port, buffer, block_size );
if( new_bytes <= 0 ) { if( new_bytes <= 0 ) {
break; break;
} }
i=-1; i=-1;
while(++i<new_bytes && endseen<4) { while(++i<new_bytes && endseen<4) {
if(*buffer==EOI) { if(*buffer==EOI) {
endseen++; endseen++;
} else { } else {
endseen=0; endseen=0;
} }
buffer++; buffer++;
} }
read_bytes += i; read_bytes += i;
@ -601,7 +601,7 @@ static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
} }
if((err = ReadPacket(cam, buffer, 8)) < 0) { if((err = ReadPacket(cam, buffer, 8)) < 0) {
DBG("Error reading command result\n"); DBG("Error reading command result\n");
return err; return err;
} }
memcpy(data, buffer, databytes); memcpy(data, buffer, databytes);
} else if(command[0] == DATA_OUT) { } else if(command[0] == DATA_OUT) {
@ -631,10 +631,10 @@ static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
static int cpia_pp_open(void *privdata) static int cpia_pp_open(void *privdata)
{ {
struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata; struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;
if (cam == NULL) if (cam == NULL)
return -EINVAL; return -EINVAL;
if(cam->open_count == 0) { if(cam->open_count == 0) {
if (parport_claim(cam->pdev)) { if (parport_claim(cam->pdev)) {
DBG("failed to claim the port\n"); DBG("failed to claim the port\n");
@ -645,12 +645,12 @@ static int cpia_pp_open(void *privdata)
parport_write_control(cam->port, PARPORT_CONTROL_SELECT); parport_write_control(cam->port, PARPORT_CONTROL_SELECT);
udelay(50); udelay(50);
parport_write_control(cam->port, parport_write_control(cam->port,
PARPORT_CONTROL_SELECT PARPORT_CONTROL_SELECT
| PARPORT_CONTROL_INIT); | PARPORT_CONTROL_INIT);
} }
++cam->open_count; ++cam->open_count;
return 0; return 0;
} }
@ -663,7 +663,7 @@ static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), vo
{ {
struct pp_cam_entry *cam = privdata; struct pp_cam_entry *cam = privdata;
int retval = 0; int retval = 0;
if(cam->port->irq != PARPORT_IRQ_NONE) { if(cam->port->irq != PARPORT_IRQ_NONE) {
INIT_WORK(&cam->cb_task, cb, cbdata); INIT_WORK(&cam->cb_task, cb, cbdata);
} else { } else {
@ -707,9 +707,9 @@ static int cpia_pp_register(struct parport *port)
LOG("failed to allocate camera structure\n"); LOG("failed to allocate camera structure\n");
return -ENOMEM; return -ENOMEM;
} }
pdev = parport_register_device(port, "cpia_pp", NULL, NULL, pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
NULL, 0, cam); NULL, 0, cam);
if (!pdev) { if (!pdev) {
LOG("failed to parport_register_device\n"); LOG("failed to parport_register_device\n");
@ -753,19 +753,19 @@ static void cpia_pp_detach (struct parport *port)
} }
cpia = NULL; cpia = NULL;
} }
spin_unlock( &cam_list_lock_pp ); spin_unlock( &cam_list_lock_pp );
if (!cpia) { if (!cpia) {
DBG("cpia_pp_detach failed to find cam_data in cam_list\n"); DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
return; return;
} }
cam = (struct pp_cam_entry *) cpia->lowlevel_data; cam = (struct pp_cam_entry *) cpia->lowlevel_data;
cpia_unregister_camera(cpia); cpia_unregister_camera(cpia);
if(cam->open_count > 0) if(cam->open_count > 0)
cpia_pp_close(cam); cpia_pp_close(cam);
parport_unregister_device(cam->pdev); parport_unregister_device(cam->pdev);
cpia->lowlevel_data = NULL; cpia->lowlevel_data = NULL;
kfree(cam); kfree(cam);
} }
@ -805,14 +805,14 @@ static struct parport_driver cpia_pp_driver = {
int cpia_pp_init(void) int cpia_pp_init(void)
{ {
printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
if(parport_nr[0] == PPCPIA_PARPORT_OFF) { if(parport_nr[0] == PPCPIA_PARPORT_OFF) {
printk(" disabled\n"); printk(" disabled\n");
return 0; return 0;
} }
spin_lock_init( &cam_list_lock_pp ); spin_lock_init( &cam_list_lock_pp );
if (parport_register_driver (&cpia_pp_driver)) { if (parport_register_driver (&cpia_pp_driver)) {

View file

@ -22,7 +22,7 @@
*/ */
/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ /* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
/* #define _CPIA_DEBUG_ 1 */ /* #define _CPIA_DEBUG_ 1 */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -85,7 +85,7 @@ struct usb_cpia {
static int cpia_usb_open(void *privdata); static int cpia_usb_open(void *privdata);
static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
void *cbdata); void *cbdata);
static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data); static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data);
static int cpia_usb_streamStart(void *privdata); static int cpia_usb_streamStart(void *privdata);
static int cpia_usb_streamStop(void *privdata); static int cpia_usb_streamStop(void *privdata);
@ -127,7 +127,7 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
ucpia->workbuff->status = FRAME_READING; ucpia->workbuff->status = FRAME_READING;
ucpia->workbuff->length = 0; ucpia->workbuff->length = 0;
} }
for (i = 0; i < urb->number_of_packets; i++) { for (i = 0; i < urb->number_of_packets; i++) {
int n = urb->iso_frame_desc[i].actual_length; int n = urb->iso_frame_desc[i].actual_length;
int st = urb->iso_frame_desc[i].status; int st = urb->iso_frame_desc[i].status;
@ -141,9 +141,9 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n); printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n);
return; return;
} }
if (n) { if (n) {
if ((ucpia->workbuff->length > 0) || if ((ucpia->workbuff->length > 0) ||
(0x19 == cdata[0] && 0x68 == cdata[1])) { (0x19 == cdata[0] && 0x68 == cdata[1])) {
memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n); memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n);
ucpia->workbuff->length += n; ucpia->workbuff->length += n;
@ -160,7 +160,7 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
ucpia->workbuff = ucpia->workbuff->next; ucpia->workbuff = ucpia->workbuff->next;
ucpia->workbuff->status = FRAME_EMPTY; ucpia->workbuff->status = FRAME_EMPTY;
ucpia->workbuff->length = 0; ucpia->workbuff->length = 0;
if (waitqueue_active(&ucpia->wq_stream)) if (waitqueue_active(&ucpia->wq_stream))
wake_up_interruptible(&ucpia->wq_stream); wake_up_interruptible(&ucpia->wq_stream);
} }
@ -178,7 +178,7 @@ static int cpia_usb_open(void *privdata)
struct usb_cpia *ucpia = (struct usb_cpia *) privdata; struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
struct urb *urb; struct urb *urb;
int ret, retval = 0, fx, err; int ret, retval = 0, fx, err;
if (!ucpia) if (!ucpia)
return -EINVAL; return -EINVAL;
@ -191,7 +191,7 @@ static int cpia_usb_open(void *privdata)
retval = -EINVAL; retval = -EINVAL;
goto error_0; goto error_0;
} }
ret = usb_set_interface(ucpia->dev, ucpia->iface, 3); ret = usb_set_interface(ucpia->dev, ucpia->iface, 3);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret); printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret);
@ -286,7 +286,7 @@ static int cpia_usb_open(void *privdata)
error_0: error_0:
kfree (ucpia->sbuf[0].data); kfree (ucpia->sbuf[0].data);
ucpia->sbuf[0].data = NULL; ucpia->sbuf[0].data = NULL;
return retval; return retval;
} }
@ -307,7 +307,7 @@ static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
packet[1] + (packet[0] << 8), packet[1] + (packet[0] << 8),
USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8), packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), buf, size, 1000); packet[4] + (packet[5] << 8), buf, size, 1000);
} }
@ -324,7 +324,7 @@ static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size)
return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
packet[1] + (packet[0] << 8), packet[1] + (packet[0] << 8),
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8), packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), buf, size, 1000); packet[4] + (packet[5] << 8), buf, size, 1000);
} }
@ -393,7 +393,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
if (!ucpia || !ucpia->present) if (!ucpia || !ucpia->present)
return -1; return -1;
if (ucpia->curbuff->status != FRAME_READY) if (ucpia->curbuff->status != FRAME_READY)
interruptible_sleep_on(&ucpia->wq_stream); interruptible_sleep_on(&ucpia->wq_stream);
else else
@ -403,7 +403,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
if (!mybuff) if (!mybuff)
return -1; return -1;
if (mybuff->status != FRAME_READY || mybuff->length < 4) { if (mybuff->status != FRAME_READY || mybuff->length < 4) {
DBG("Something went wrong!\n"); DBG("Something went wrong!\n");
return -1; return -1;
@ -411,7 +411,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
memcpy(frame, mybuff->data, mybuff->length); memcpy(frame, mybuff->data, mybuff->length);
mybuff->status = FRAME_EMPTY; mybuff->status = FRAME_EMPTY;
/* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */ /* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */
/* mybuff->length, frame[0], frame[1], */ /* mybuff->length, frame[0], frame[1], */
/* frame[mybuff->length-4], frame[mybuff->length-3], */ /* frame[mybuff->length-4], frame[mybuff->length-3], */
@ -447,7 +447,7 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
kfree(ucpia->sbuf[1].data); kfree(ucpia->sbuf[1].data);
ucpia->sbuf[1].data = NULL; ucpia->sbuf[1].data = NULL;
if (ucpia->sbuf[0].urb) { if (ucpia->sbuf[0].urb) {
usb_kill_urb(ucpia->sbuf[0].urb); usb_kill_urb(ucpia->sbuf[0].urb);
usb_free_urb(ucpia->sbuf[0].urb); usb_free_urb(ucpia->sbuf[0].urb);
@ -490,7 +490,7 @@ static int cpia_probe(struct usb_interface *intf,
struct usb_cpia *ucpia; struct usb_cpia *ucpia;
struct cam_data *cam; struct cam_data *cam;
int ret; int ret;
/* A multi-config CPiA camera? */ /* A multi-config CPiA camera? */
if (udev->descriptor.bNumConfigurations != 1) if (udev->descriptor.bNumConfigurations != 1)
return -ENODEV; return -ENODEV;
@ -539,7 +539,7 @@ static int cpia_probe(struct usb_interface *intf,
/* Before register_camera, important */ /* Before register_camera, important */
ucpia->present = 1; ucpia->present = 1;
cam = cpia_register_camera(&cpia_usb_ops, ucpia); cam = cpia_register_camera(&cpia_usb_ops, ucpia);
if (!cam) { if (!cam) {
LOG("failed to cpia_register_camera\n"); LOG("failed to cpia_register_camera\n");
@ -591,7 +591,7 @@ static void cpia_disconnect(struct usb_interface *intf)
struct cam_data *cam = usb_get_intfdata(intf); struct cam_data *cam = usb_get_intfdata(intf);
struct usb_cpia *ucpia; struct usb_cpia *ucpia;
struct usb_device *udev; struct usb_device *udev;
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
if (!cam) if (!cam)
return; return;
@ -600,7 +600,7 @@ static void cpia_disconnect(struct usb_interface *intf)
spin_lock( &cam_list_lock_usb ); spin_lock( &cam_list_lock_usb );
list_del(&cam->cam_data_list); list_del(&cam->cam_data_list);
spin_unlock( &cam_list_lock_usb ); spin_unlock( &cam_list_lock_usb );
ucpia->present = 0; ucpia->present = 0;
cpia_unregister_camera(cam); cpia_unregister_camera(cam);
@ -631,7 +631,7 @@ static void cpia_disconnect(struct usb_interface *intf)
static int __init usb_cpia_init(void) static int __init usb_cpia_init(void)
{ {
printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER); CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER);
spin_lock_init(&cam_list_lock_usb); spin_lock_init(&cam_list_lock_usb);

View file

@ -59,25 +59,25 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg)
static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
void *arg) void *arg)
{ {
struct v4l2_audio *input = arg; struct v4l2_routing *route = arg;
struct v4l2_control *ctrl = arg; struct v4l2_control *ctrl = arg;
switch (cmd) { switch (cmd) {
case VIDIOC_S_AUDIO: case VIDIOC_INT_G_AUDIO_ROUTING:
route->input = (cs53l32a_read(client, 0x01) >> 4) & 3;
route->output = 0;
break;
case VIDIOC_INT_S_AUDIO_ROUTING:
/* There are 2 physical inputs, but the second input can be /* There are 2 physical inputs, but the second input can be
placed in two modes, the first mode bypasses the PGA (gain), placed in two modes, the first mode bypasses the PGA (gain),
the second goes through the PGA. Hence there are three the second goes through the PGA. Hence there are three
possible inputs to choose from. */ possible inputs to choose from. */
if (input->index > 2) { if (route->input > 2) {
v4l_err(client, "Invalid input %d.\n", input->index); v4l_err(client, "Invalid input %d.\n", route->input);
return -EINVAL; return -EINVAL;
} }
cs53l32a_write(client, 0x01, 0x01 + (input->index << 4)); cs53l32a_write(client, 0x01, 0x01 + (route->input << 4));
break;
case VIDIOC_G_AUDIO:
memset(input, 0, sizeof(*input));
input->index = (cs53l32a_read(client, 0x01) >> 4) & 3;
break; break;
case VIDIOC_G_CTRL: case VIDIOC_G_CTRL:

View file

@ -20,7 +20,7 @@
#define __CS8420_H__ #define __CS8420_H__
/* Initialization Sequence */ /* Initialization Sequence */
static __u8 init8420[] = { static __u8 init8420[] = {
1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46, 1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46,
5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13, 5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13,

View file

@ -18,7 +18,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "cx25840.h" #include "cx25840.h"

View file

@ -31,7 +31,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "cx25840.h" #include "cx25840.h"
@ -176,9 +175,9 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw)
cx25840_write(client, 0x4a5, 0x00); cx25840_write(client, 0x4a5, 0x00);
cx25840_write(client, 0x402, 0x00); cx25840_write(client, 0x402, 0x00);
/* 8. */ /* 8. */
cx25840_write(client, 0x401, 0x18); cx25840_and_or(client, 0x401, ~0x18, 0);
cx25840_write(client, 0x4a2, 0x10); cx25840_and_or(client, 0x4a2, ~0x10, 0x10);
cx25840_write(client, 0x402, 0x04); /* steps 8c and 8d are done in change_input() */
/* 10. */ /* 10. */
cx25840_write(client, 0x8d3, 0x1f); cx25840_write(client, 0x8d3, 0x1f);
cx25840_write(client, 0x8e3, 0x03); cx25840_write(client, 0x8e3, 0x03);
@ -209,6 +208,17 @@ static void input_change(struct i2c_client *client)
struct cx25840_state *state = i2c_get_clientdata(client); struct cx25840_state *state = i2c_get_clientdata(client);
v4l2_std_id std = cx25840_get_v4lstd(client); v4l2_std_id std = cx25840_get_v4lstd(client);
/* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
if (std & V4L2_STD_SECAM) {
cx25840_write(client, 0x402, 0);
}
else {
cx25840_write(client, 0x402, 0x04);
cx25840_write(client, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
}
cx25840_and_or(client, 0x401, ~0x60, 0);
cx25840_and_or(client, 0x401, ~0x60, 0x60);
/* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC /* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC
instead of V4L2_STD_PAL. Someone needs to test this. */ instead of V4L2_STD_PAL. Someone needs to test this. */
if (std & V4L2_STD_PAL) { if (std & V4L2_STD_PAL) {
@ -343,6 +353,15 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
} }
} }
/* Follow step 9 of section 3.16 in the cx25840 datasheet.
Without this PAL may display a vertical ghosting effect.
This happens for example with the Yuan MPC622. */
if (fmt >= 4 && fmt < 8) {
/* Set format to NTSC-M */
cx25840_and_or(client, 0x400, ~0xf, 1);
/* Turn off LCOMB */
cx25840_and_or(client, 0x47b, ~6, 0);
}
cx25840_and_or(client, 0x400, ~0xf, fmt); cx25840_and_or(client, 0x400, ~0xf, fmt);
cx25840_vbi_setup(client); cx25840_vbi_setup(client);
return 0; return 0;
@ -359,7 +378,14 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
} }
switch (fmt) { switch (fmt) {
case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR; case 0x1:
{
/* if the audio std is A2-M, then this is the South Korean
NTSC standard */
if (cx25840_read(client, 0x805) == 2)
return V4L2_STD_NTSC_M_KR;
return V4L2_STD_NTSC_M;
}
case 0x2: return V4L2_STD_NTSC_M_JP; case 0x2: return V4L2_STD_NTSC_M_JP;
case 0x3: return V4L2_STD_NTSC_443; case 0x3: return V4L2_STD_NTSC_443;
case 0x4: return V4L2_STD_PAL; case 0x4: return V4L2_STD_PAL;
@ -737,16 +763,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
return set_input(client, state->vid_input, input->index); return set_input(client, state->vid_input, input->index);
} }
case VIDIOC_G_AUDIO:
{
struct v4l2_audio *input = arg;
memset(input, 0, sizeof(*input));
input->index = state->aud_input;
input->capability = V4L2_AUDCAP_STEREO;
break;
}
case VIDIOC_S_FREQUENCY: case VIDIOC_S_FREQUENCY:
input_change(client); input_change(client);
break; break;
@ -794,13 +810,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
bilingual -> lang1 */ bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x00); cx25840_and_or(client, 0x809, ~0xf, 0x00);
break; break;
case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG1:
/* mono -> mono /* mono -> mono
stereo -> stereo stereo -> stereo
bilingual -> lang1 */ bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x04); cx25840_and_or(client, 0x809, ~0xf, 0x04);
break; break;
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1_LANG2:
/* mono -> mono /* mono -> mono
stereo -> stereo stereo -> stereo
bilingual -> lang1/lang2 */ bilingual -> lang1/lang2 */
@ -808,7 +825,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break; break;
case V4L2_TUNER_MODE_LANG2: case V4L2_TUNER_MODE_LANG2:
/* mono -> mono /* mono -> mono
stereo ->stereo stereo -> stereo
bilingual -> lang2 */ bilingual -> lang2 */
cx25840_and_or(client, 0x809, ~0xf, 0x01); cx25840_and_or(client, 0x809, ~0xf, 0x01);
break; break;

View file

@ -16,12 +16,13 @@ config VIDEO_CX88
module will be called cx8800 module will be called cx8800
config VIDEO_CX88_ALSA config VIDEO_CX88_ALSA
tristate "ALSA DMA audio support" tristate "Conexant 2388x DMA audio support"
depends on VIDEO_CX88 && SND && EXPERIMENTAL depends on VIDEO_CX88 && SND && EXPERIMENTAL
select SND_PCM select SND_PCM
---help--- ---help---
This is a video4linux driver for direct (DMA) audio on This is a video4linux driver for direct (DMA) audio on
Conexant 2388x based TV cards. Conexant 2388x based TV cards using ALSA.
It only works with boards with function 01 enabled. It only works with boards with function 01 enabled.
To check if your board supports, use lspci -n. To check if your board supports, use lspci -n.
If supported, you should see 1471:8801 or 1471:8811 If supported, you should see 1471:8801 or 1471:8811

View file

@ -303,7 +303,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
BUG_ON(!chip->dma_size); BUG_ON(!chip->dma_size);
dprintk(2,"Freeing buffer\n"); dprintk(2,"Freeing buffer\n");
videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); videobuf_pci_dma_unmap(chip->pci, &chip->dma_risc);
videobuf_dma_free(&chip->dma_risc); videobuf_dma_free(&chip->dma_risc);
btcx_riscmem_free(chip->pci,&chip->buf->risc); btcx_riscmem_free(chip->pci,&chip->buf->risc);
kfree(chip->buf); kfree(chip->buf);
@ -429,7 +429,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE,
(PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
videobuf_dma_pci_map(chip->pci,&buf->vb.dma); videobuf_pci_dma_map(chip->pci,&buf->vb.dma);
cx88_risc_databuffer(chip->pci, &buf->risc, cx88_risc_databuffer(chip->pci, &buf->risc,

View file

@ -1341,7 +1341,7 @@ bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field) enum v4l2_field field)
{ {
struct cx8802_fh *fh = q->priv_data; struct cx8802_fh *fh = q->priv_data;
return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb, field); return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
} }
static void static void
@ -1354,8 +1354,7 @@ bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void static void
bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{ {
struct cx8802_fh *fh = q->priv_data; cx88_free_buffer(q, (struct cx88_buffer*)vb);
cx88_free_buffer(fh->dev->pci, (struct cx88_buffer*)vb);
} }
static struct videobuf_queue_ops blackbird_qops = { static struct videobuf_queue_ops blackbird_qops = {

View file

@ -213,13 +213,13 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
} }
void void
cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
{ {
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0); videobuf_waiton(&buf->vb,0,0);
videobuf_dma_pci_unmap(pci, &buf->vb.dma); videobuf_dma_unmap(q, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma); videobuf_dma_free(&buf->vb.dma);
btcx_riscmem_free(pci, &buf->risc); btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
buf->vb.state = STATE_NEEDS_INIT; buf->vb.state = STATE_NEEDS_INIT;
} }

View file

@ -90,7 +90,7 @@ static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field) enum v4l2_field field)
{ {
struct cx8802_dev *dev = q->priv_data; struct cx8802_dev *dev = q->priv_data;
return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb,field); return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
} }
static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
@ -101,8 +101,7 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{ {
struct cx8802_dev *dev = q->priv_data; cx88_free_buffer(q, (struct cx88_buffer*)vb);
cx88_free_buffer(dev->pci, (struct cx88_buffer*)vb);
} }
static struct videobuf_queue_ops dvb_qops = { static struct videobuf_queue_ops dvb_qops = {

View file

@ -163,8 +163,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
enum v4l2_field field) struct cx88_buffer *buf, enum v4l2_field field)
{ {
int size = dev->ts_packet_size * dev->ts_packet_count; int size = dev->ts_packet_size * dev->ts_packet_count;
int rc; int rc;
@ -179,7 +179,7 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf,
buf->vb.size = size; buf->vb.size = size;
buf->vb.field = field /*V4L2_FIELD_TOP*/; buf->vb.field = field /*V4L2_FIELD_TOP*/;
if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail; goto fail;
cx88_risc_databuffer(dev->pci, &buf->risc, cx88_risc_databuffer(dev->pci, &buf->risc,
buf->vb.dma.sglist, buf->vb.dma.sglist,
@ -189,36 +189,36 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf,
return 0; return 0;
fail: fail:
cx88_free_buffer(dev->pci,buf); cx88_free_buffer(q,buf);
return rc; return rc;
} }
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
{ {
struct cx88_buffer *prev; struct cx88_buffer *prev;
struct cx88_dmaqueue *q = &dev->mpegq; struct cx88_dmaqueue *cx88q = &dev->mpegq;
dprintk( 1, "cx8802_buf_queue\n" ); dprintk( 1, "cx8802_buf_queue\n" );
/* add jump to stopper */ /* add jump to stopper */
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
if (list_empty(&q->active)) { if (list_empty(&cx88q->active)) {
dprintk( 0, "queue is empty - first active\n" ); dprintk( 0, "queue is empty - first active\n" );
list_add_tail(&buf->vb.queue,&q->active); list_add_tail(&buf->vb.queue,&cx88q->active);
cx8802_start_dma(dev, q, buf); cx8802_start_dma(dev, cx88q, buf);
buf->vb.state = STATE_ACTIVE; buf->vb.state = STATE_ACTIVE;
buf->count = q->count++; buf->count = cx88q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(0,"[%p/%d] %s - first active\n", dprintk(0,"[%p/%d] %s - first active\n",
buf, buf->vb.i, __FUNCTION__); buf, buf->vb.i, __FUNCTION__);
} else { } else {
dprintk( 1, "queue is not empty - append to active\n" ); dprintk( 1, "queue is not empty - append to active\n" );
prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
list_add_tail(&buf->vb.queue,&q->active); list_add_tail(&buf->vb.queue,&cx88q->active);
buf->vb.state = STATE_ACTIVE; buf->vb.state = STATE_ACTIVE;
buf->count = q->count++; buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n", dprintk( 1, "[%p/%d] %s - append to active\n",
buf, buf->vb.i, __FUNCTION__); buf, buf->vb.i, __FUNCTION__);

View file

@ -885,6 +885,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP); set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
break; break;
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO); set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
break; break;
} }
@ -905,6 +906,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
EN_NICAM_FORCE_MONO2); EN_NICAM_FORCE_MONO2);
break; break;
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
set_audio_standard_NICAM(core, set_audio_standard_NICAM(core,
EN_NICAM_FORCE_STEREO); EN_NICAM_FORCE_STEREO);
break; break;
@ -926,6 +928,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
EN_A2_FORCE_MONO2); EN_A2_FORCE_MONO2);
break; break;
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
set_audio_standard_A2(core, set_audio_standard_A2(core,
EN_A2_FORCE_STEREO); EN_A2_FORCE_STEREO);
break; break;

View file

@ -175,7 +175,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
buf->vb.size = size; buf->vb.size = size;
buf->vb.field = V4L2_FIELD_SEQ_TB; buf->vb.field = V4L2_FIELD_SEQ_TB;
if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail; goto fail;
cx88_risc_buffer(dev->pci, &buf->risc, cx88_risc_buffer(dev->pci, &buf->risc,
buf->vb.dma.sglist, buf->vb.dma.sglist,
@ -187,7 +187,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return 0; return 0;
fail: fail:
cx88_free_buffer(dev->pci,buf); cx88_free_buffer(q,buf);
return rc; return rc;
} }
@ -227,9 +227,8 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{ {
struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
struct cx8800_fh *fh = q->priv_data;
cx88_free_buffer(fh->dev->pci,buf); cx88_free_buffer(q,buf);
} }
struct videobuf_queue_ops cx8800_vbi_qops = { struct videobuf_queue_ops cx8800_vbi_qops = {

View file

@ -564,7 +564,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (STATE_NEEDS_INIT == buf->vb.state) { if (STATE_NEEDS_INIT == buf->vb.state) {
init_buffer = 1; init_buffer = 1;
if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail; goto fail;
} }
@ -614,7 +614,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return 0; return 0;
fail: fail:
cx88_free_buffer(dev->pci,buf); cx88_free_buffer(q,buf);
return rc; return rc;
} }
@ -671,9 +671,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{ {
struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
struct cx8800_fh *fh = q->priv_data;
cx88_free_buffer(fh->dev->pci,buf); cx88_free_buffer(q,buf);
} }
static struct videobuf_queue_ops cx8800_video_qops = { static struct videobuf_queue_ops cx8800_video_qops = {
@ -1251,9 +1250,17 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
{ {
int err; int err;
dprintk(2, "CORE IOCTL: 0x%x\n", cmd ); if (video_debug) {
if (video_debug > 1) if (video_debug > 1) {
v4l_print_ioctl(core->name,cmd); if (_IOC_DIR(cmd) & _IOC_WRITE)
v4l_printk_ioctl_arg("cx88(w)",cmd, arg);
else if (!_IOC_DIR(cmd) & _IOC_READ) {
v4l_print_ioctl("cx88", cmd);
}
} else
v4l_print_ioctl(core->name,cmd);
}
switch (cmd) { switch (cmd) {
/* ---------- tv norms ---------- */ /* ---------- tv norms ---------- */
@ -1460,7 +1467,19 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
static int video_ioctl(struct inode *inode, struct file *file, static int video_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
return video_usercopy(inode, file, cmd, arg, video_do_ioctl); int retval;
retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl);
if (video_debug > 1) {
if (retval < 0) {
v4l_print_ioctl("cx88(err)", cmd);
printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval);
} else if (_IOC_DIR(cmd) & _IOC_READ)
v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg);
}
return retval;
} }
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */

View file

@ -27,7 +27,6 @@
#include <media/tuner.h> #include <media/tuner.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/audiochip.h>
#include <media/video-buf.h> #include <media/video-buf.h>
#include <media/video-buf-dvb.h> #include <media/video-buf-dvb.h>
@ -485,7 +484,7 @@ extern int
cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value); u32 reg, u32 mask, u32 value);
extern void extern void
cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf); cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
extern void cx88_risc_disasm(struct cx88_core *core, extern void cx88_risc_disasm(struct cx88_core *core,
struct btcx_riscmem *risc); struct btcx_riscmem *risc);
@ -577,8 +576,8 @@ void cx88_ir_irq(struct cx88_core *core);
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* cx88-mpeg.c */ /* cx88-mpeg.c */
int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
enum v4l2_field field); struct cx88_buffer *buf, enum v4l2_field field);
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
void cx8802_cancel_buffers(struct cx8802_dev *dev); void cx8802_cancel_buffers(struct cx8802_dev *dev);

View file

@ -86,7 +86,7 @@ static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_
return ret; return ret;
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
#ifdef DEBUG #ifdef DEBUG
static void dump_urb (struct urb *urb) static void dump_urb (struct urb *urb)
{ {
dbg("urb :%p", urb); dbg("urb :%p", urb);
@ -136,7 +136,7 @@ static int dabusb_free_queue (struct list_head *q)
for (p = q->next; p != q;) { for (p = q->next; p != q;) {
b = list_entry (p, buff_t, buff_list); b = list_entry (p, buff_t, buff_list);
#ifdef DEBUG #ifdef DEBUG
dump_urb(b->purb); dump_urb(b->purb);
#endif #endif
kfree(b->purb->transfer_buffer); kfree(b->purb->transfer_buffer);
@ -287,7 +287,7 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
} }
} }
if( ret == -EPIPE ) { if( ret == -EPIPE ) {
warn("CLEAR_FEATURE request to remove STALL condition."); warn("CLEAR_FEATURE request to remove STALL condition.");
if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
@ -328,7 +328,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname)
PINTEL_HEX_RECORD ptr = firmware; PINTEL_HEX_RECORD ptr = firmware;
dbg("Enter dabusb_loadmem (internal)"); dbg("Enter dabusb_loadmem (internal)");
ret = dabusb_8051_reset (s, 1); ret = dabusb_8051_reset (s, 1);
while (ptr->Type == 0) { while (ptr->Type == 0) {
@ -449,7 +449,7 @@ static int dabusb_startrek (pdabusb_t s)
if (!list_empty (&s->free_buff_list)) { if (!list_empty (&s->free_buff_list)) {
pbuff_t end; pbuff_t end;
int ret; int ret;
while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
@ -506,7 +506,7 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l
err("error: rec_buf_list is empty"); err("error: rec_buf_list is empty");
goto err; goto err;
} }
b = list_entry (s->rec_buff_list.next, buff_t, buff_list); b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
purb = b->purb; purb = b->purb;
@ -783,9 +783,9 @@ static void dabusb_disconnect (struct usb_interface *intf)
pdabusb_t s = usb_get_intfdata (intf); pdabusb_t s = usb_get_intfdata (intf);
dbg("dabusb_disconnect"); dbg("dabusb_disconnect");
init_waitqueue_entry(&__wait, current); init_waitqueue_entry(&__wait, current);
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
if (s) { if (s) {
usb_deregister_dev (intf, &dabusb_class); usb_deregister_dev (intf, &dabusb_class);
@ -797,7 +797,7 @@ static void dabusb_disconnect (struct usb_interface *intf)
schedule(); schedule();
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
remove_wait_queue(&s->remove_ok, &__wait); remove_wait_queue(&s->remove_ok, &__wait);
s->usbdev = NULL; s->usbdev = NULL;
s->overruns = 0; s->overruns = 0;
} }

View file

@ -10,7 +10,7 @@ typedef struct
#define DABUSB_VERSION 0x1000 #define DABUSB_VERSION 0x1000
#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) #define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t)
#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) #define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int)
#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) #define IOCTL_DAB_VERSION _IOR('d', 0x3f, int)
#ifdef __KERNEL__ #ifdef __KERNEL__
@ -36,7 +36,7 @@ typedef struct
struct list_head rec_buff_list; struct list_head rec_buff_list;
} dabusb_t,*pdabusb_t; } dabusb_t,*pdabusb_t;
typedef struct typedef struct
{ {
pdabusb_t s; pdabusb_t s;
struct urb *purb; struct urb *purb;

View file

@ -37,28 +37,28 @@
Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
Version 0.30: Version 0.30:
Markus: Updates for 2.5.x kernel and more ISO compliant source Markus: Updates for 2.5.x kernel and more ISO compliant source
Version 0.25: Version 0.25:
PSL and Markus: Cleanup, radio now doesn't stop on device close PSL and Markus: Cleanup, radio now doesn't stop on device close
Version 0.24: Version 0.24:
Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
right. Some minor cleanup, improved standalone compilation right. Some minor cleanup, improved standalone compilation
Version 0.23: Version 0.23:
Markus: Sign extension bug fixed by declaring transfer_buffer unsigned Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
Version 0.22: Version 0.22:
Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
thanks to Mike Cox for pointing the problem out. thanks to Mike Cox for pointing the problem out.
Version 0.21: Version 0.21:
Markus: Minor cleanup, warnings if something goes wrong, lame attempt Markus: Minor cleanup, warnings if something goes wrong, lame attempt
to adhere to Documentation/CodingStyle to adhere to Documentation/CodingStyle
Version 0.2: Version 0.2:
Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
Markus: Copyright clarification Markus: Copyright clarification
Version 0.01: Markus: initial release Version 0.01: Markus: initial release
@ -163,11 +163,11 @@ static struct usb_driver usb_dsbr100_driver = {
static int dsbr100_start(dsbr100_device *radio) static int dsbr100_start(dsbr100_device *radio)
{ {
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS, USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_ONOFF, DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x01, 0x00, radio->transfer_buffer, 8, 300)<0) 0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
return -1; return -1;
@ -179,11 +179,11 @@ static int dsbr100_start(dsbr100_device *radio)
static int dsbr100_stop(dsbr100_device *radio) static int dsbr100_stop(dsbr100_device *radio)
{ {
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS, USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_ONOFF, DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00, 0x00, radio->transfer_buffer, 8, 300)<0) 0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
return -1; return -1;
@ -195,16 +195,16 @@ static int dsbr100_setfreq(dsbr100_device *radio, int freq)
{ {
freq = (freq/16*80)/1000+856; freq = (freq/16*80)/1000+856;
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_TUNE, DSB100_TUNE,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
(freq>>8)&0x00ff, freq&0xff, (freq>>8)&0x00ff, freq&0xff,
radio->transfer_buffer, 8, 300)<0 || radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS, USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS, USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
radio->stereo = -1; radio->stereo = -1;
@ -219,7 +219,7 @@ sees a stereo signal or not. Pity. */
static void dsbr100_getstat(dsbr100_device *radio) static void dsbr100_getstat(dsbr100_device *radio)
{ {
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS, USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
radio->stereo = -1; radio->stereo = -1;
@ -232,7 +232,7 @@ static void dsbr100_getstat(dsbr100_device *radio)
/* check if the device is present and register with v4l and /* check if the device is present and register with v4l and
usb if it is */ usb if it is */
static int usb_dsbr100_probe(struct usb_interface *intf, static int usb_dsbr100_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
dsbr100_device *radio; dsbr100_device *radio;
@ -243,7 +243,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
kfree(radio); kfree(radio);
return -ENOMEM; return -ENOMEM;
} }
memcpy(radio->videodev, &dsbr100_videodev_template, memcpy(radio->videodev, &dsbr100_videodev_template,
sizeof(dsbr100_videodev_template)); sizeof(dsbr100_videodev_template));
radio->removed = 0; radio->removed = 0;
radio->users = 0; radio->users = 0;
@ -310,7 +310,7 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
struct video_tuner *v = arg; struct video_tuner *v = arg;
dsbr100_getstat(radio); dsbr100_getstat(radio);
if(v->tuner) /* Only 1 tuner */ if(v->tuner) /* Only 1 tuner */
return -EINVAL; return -EINVAL;
v->rangelow = FREQ_MIN*FREQ_MUL; v->rangelow = FREQ_MIN*FREQ_MUL;
v->rangehigh = FREQ_MAX*FREQ_MUL; v->rangehigh = FREQ_MAX*FREQ_MUL;
@ -355,12 +355,12 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
v->volume = 1; v->volume = 1;
v->step = 1; v->step = 1;
strcpy(v->name, "Radio"); strcpy(v->name, "Radio");
return 0; return 0;
} }
case VIDIOCSAUDIO: { case VIDIOCSAUDIO: {
struct video_audio *v = arg; struct video_audio *v = arg;
if (v->audio) if (v->audio)
return -EINVAL; return -EINVAL;
if (v->flags&VIDEO_AUDIO_MUTE) { if (v->flags&VIDEO_AUDIO_MUTE) {
if (dsbr100_stop(radio)==-1) if (dsbr100_stop(radio)==-1)

View file

@ -28,10 +28,10 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <media/tuner.h> #include <media/tuner.h>
#include <media/audiochip.h> #include <media/msp3400.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/audiochip.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "msp3400.h"
#include "em28xx.h" #include "em28xx.h"
@ -147,11 +147,12 @@ struct em28xx_board em28xx_boards[] = {
.input = {{ .input = {{
.type = EM28XX_VMUX_TELEVISION, .type = EM28XX_VMUX_TELEVISION,
.vmux = 0, .vmux = 0,
.amux = 6, .amux = MSP_INPUT_DEFAULT,
},{ },{
.type = EM28XX_VMUX_SVIDEO, .type = EM28XX_VMUX_SVIDEO,
.vmux = 2, .vmux = 2,
.amux = 1, .amux = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART),
}}, }},
}, },
[EM2820_BOARD_MSI_VOX_USB_2] = { [EM2820_BOARD_MSI_VOX_USB_2] = {

View file

@ -38,6 +38,7 @@
#include "em28xx.h" #include "em28xx.h"
#include <media/tuner.h> #include <media/tuner.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/msp3400.h>
#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
"Markus Rechberger <mrechberger@gmail.com>, " \ "Markus Rechberger <mrechberger@gmail.com>, " \
@ -216,9 +217,14 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);
if (dev->has_msp34xx) { if (dev->has_msp34xx) {
struct v4l2_routing route;
if (dev->i2s_speed) if (dev->i2s_speed)
em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput); route.input = dev->ctl_ainput;
route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA);
/* Note: this is msp3400 specific */
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
ainput = EM28XX_AUDIO_SRC_TUNER; ainput = EM28XX_AUDIO_SRC_TUNER;
em28xx_audio_source(dev, ainput); em28xx_audio_source(dev, ainput);
} else { } else {

View file

@ -0,0 +1,4 @@
et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
obj-$(CONFIG_USB_ET61X251) += et61x251.o

View file

@ -180,7 +180,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
void void
et61x251_attach_sensor(struct et61x251_device* cam, et61x251_attach_sensor(struct et61x251_device* cam,
struct et61x251_sensor* sensor) struct et61x251_sensor* sensor)
{ {
memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor));
} }
@ -199,7 +199,7 @@ do { \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \ else if ((level) >= 3) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
__FUNCTION__, __LINE__ , ## args); \ __FUNCTION__, __LINE__ , ## args); \
} \ } \
} while (0) } while (0)
# define KDBG(level, fmt, args...) \ # define KDBG(level, fmt, args...) \
@ -209,7 +209,7 @@ do { \
pr_info("et61x251: " fmt "\n", ## args); \ pr_info("et61x251: " fmt "\n", ## args); \
else if ((level) == 3) \ else if ((level) == 3) \
pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \ pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \
__LINE__ , ## args); \ __LINE__ , ## args); \
} \ } \
} while (0) } while (0)
# define V4LDBG(level, name, cmd) \ # define V4LDBG(level, name, cmd) \
@ -226,7 +226,7 @@ do { \
#undef PDBG #undef PDBG
#define PDBG(fmt, args...) \ #define PDBG(fmt, args...) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
__FUNCTION__, __LINE__ , ## args) __FUNCTION__, __LINE__ , ## args)
#undef PDBGG #undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */

View file

@ -44,7 +44,7 @@
/*****************************************************************************/ /*****************************************************************************/
#define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ #define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \
"PC Camera Controllers" "PC Camera Controllers"
#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia"
#define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define ET61X251_MODULE_LICENSE "GPL" #define ET61X251_MODULE_LICENSE "GPL"
@ -63,68 +63,68 @@ MODULE_LICENSE(ET61X251_MODULE_LICENSE);
static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1}; static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1};
module_param_array(video_nr, short, NULL, 0444); module_param_array(video_nr, short, NULL, 0444);
MODULE_PARM_DESC(video_nr, MODULE_PARM_DESC(video_nr,
"\n<-1|n[,...]> Specify V4L2 minor mode number." "\n<-1|n[,...]> Specify V4L2 minor mode number."
"\n -1 = use next available (default)" "\n -1 = use next available (default)"
"\n n = use minor number n (integer >= 0)" "\n n = use minor number n (integer >= 0)"
"\nYou can specify up to " "\nYou can specify up to "
__MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way." __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way."
"\nFor example:" "\nFor example:"
"\nvideo_nr=-1,2,-1 would assign minor number 2 to" "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
"\nthe second registered camera and use auto for the first" "\nthe second registered camera and use auto for the first"
"\none and for every other camera." "\none and for every other camera."
"\n"); "\n");
static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] = static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] =
ET61X251_FORCE_MUNMAP}; ET61X251_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444); module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap, MODULE_PARM_DESC(force_munmap,
"\n<0|1[,...]> Force the application to unmap previously" "\n<0|1[,...]> Force the application to unmap previously"
"\nmapped buffer memory before calling any VIDIOC_S_CROP or" "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
"\nVIDIOC_S_FMT ioctl's. Not all the applications support" "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
"\nthis feature. This parameter is specific for each" "\nthis feature. This parameter is specific for each"
"\ndetected camera." "\ndetected camera."
"\n 0 = do not force memory unmapping" "\n 0 = do not force memory unmapping"
"\n 1 = force memory unmapping (save memory)" "\n 1 = force memory unmapping (save memory)"
"\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
"\n"); "\n");
static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] =
ET61X251_FRAME_TIMEOUT}; ET61X251_FRAME_TIMEOUT};
module_param_array(frame_timeout, uint, NULL, 0644); module_param_array(frame_timeout, uint, NULL, 0644);
MODULE_PARM_DESC(frame_timeout, MODULE_PARM_DESC(frame_timeout,
"\n<n[,...]> Timeout for a video frame in seconds." "\n<n[,...]> Timeout for a video frame in seconds."
"\nThis parameter is specific for each detected camera." "\nThis parameter is specific for each detected camera."
"\nDefault value is " "\nDefault value is "
__MODULE_STRING(ET61X251_FRAME_TIMEOUT)"." __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"."
"\n"); "\n");
#ifdef ET61X251_DEBUG #ifdef ET61X251_DEBUG
static unsigned short debug = ET61X251_DEBUG_LEVEL; static unsigned short debug = ET61X251_DEBUG_LEVEL;
module_param(debug, ushort, 0644); module_param(debug, ushort, 0644);
MODULE_PARM_DESC(debug, MODULE_PARM_DESC(debug,
"\n<n> Debugging information level, from 0 to 3:" "\n<n> Debugging information level, from 0 to 3:"
"\n0 = none (use carefully)" "\n0 = none (use carefully)"
"\n1 = critical errors" "\n1 = critical errors"
"\n2 = significant informations" "\n2 = significant informations"
"\n3 = more verbose messages" "\n3 = more verbose messages"
"\nLevel 3 is useful for testing only, when only " "\nLevel 3 is useful for testing only, when only "
"one device is used." "one device is used."
"\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"." "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"."
"\n"); "\n");
#endif #endif
/*****************************************************************************/ /*****************************************************************************/
static u32 static u32
et61x251_request_buffers(struct et61x251_device* cam, u32 count, et61x251_request_buffers(struct et61x251_device* cam, u32 count,
enum et61x251_io_method io) enum et61x251_io_method io)
{ {
struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_pix_format* p = &(cam->sensor.pix_format);
struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
const size_t imagesize = cam->module_param.force_munmap || const size_t imagesize = cam->module_param.force_munmap ||
io == IO_READ ? io == IO_READ ?
(p->width * p->height * p->priv) / 8 : (p->width * p->height * p->priv) / 8 :
(r->width * r->height * p->priv) / 8; (r->width * r->height * p->priv) / 8;
void* buff = NULL; void* buff = NULL;
u32 i; u32 i;
@ -216,7 +216,7 @@ int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index)
*buff = value; *buff = value;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
0, index, buff, 1, ET61X251_CTRL_TIMEOUT); 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0) { if (res < 0) {
DBG(3, "Failed to write a register (value 0x%02X, index " DBG(3, "Failed to write a register (value 0x%02X, index "
"0x%02X, error %d)", value, index, res); "0x%02X, error %d)", value, index, res);
@ -234,7 +234,7 @@ int et61x251_read_reg(struct et61x251_device* cam, u16 index)
int res; int res;
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
0, index, buff, 1, ET61X251_CTRL_TIMEOUT); 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
DBG(3, "Failed to read a register (index 0x%02X, error %d)", DBG(3, "Failed to read a register (index 0x%02X, error %d)",
index, res); index, res);
@ -269,7 +269,7 @@ et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor)
int int
et61x251_i2c_try_read(struct et61x251_device* cam, et61x251_i2c_try_read(struct et61x251_device* cam,
struct et61x251_sensor* sensor, u8 address) struct et61x251_sensor* sensor, u8 address)
{ {
struct usb_device* udev = cam->usbdev; struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer; u8* data = cam->control_buffer;
@ -280,14 +280,14 @@ et61x251_i2c_try_read(struct et61x251_device* cam,
data[2] = cam->sensor.rsta | 0x10; data[2] = cam->sensor.rsta | 0x10;
data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02);
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
err += res; err += res;
err += et61x251_i2c_wait(cam, sensor); err += et61x251_i2c_wait(cam, sensor);
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT); 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
err += res; err += res;
@ -302,7 +302,7 @@ et61x251_i2c_try_read(struct et61x251_device* cam,
int int
et61x251_i2c_try_write(struct et61x251_device* cam, et61x251_i2c_try_write(struct et61x251_device* cam,
struct et61x251_sensor* sensor, u8 address, u8 value) struct et61x251_sensor* sensor, u8 address, u8 value)
{ {
struct usb_device* udev = cam->usbdev; struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer; u8* data = cam->control_buffer;
@ -312,13 +312,13 @@ et61x251_i2c_try_write(struct et61x251_device* cam,
data[1] = cam->sensor.i2c_slave_id; data[1] = cam->sensor.i2c_slave_id;
data[2] = cam->sensor.rsta | 0x12; data[2] = cam->sensor.rsta | 0x12;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
err += res; err += res;
data[0] = value; data[0] = value;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
err += res; err += res;
@ -335,8 +335,8 @@ et61x251_i2c_try_write(struct et61x251_device* cam,
int int
et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2, et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, u8 data3, u8 data4, u8 data5, u8 data6, u8 data7,
u8 data8, u8 address) u8 data8, u8 address)
{ {
struct usb_device* udev = cam->usbdev; struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer; u8* data = cam->control_buffer;
@ -350,7 +350,7 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
data[5] = data7; data[5] = data7;
data[6] = data8; data[6] = data8;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT); 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
err += res; err += res;
@ -358,14 +358,14 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
data[1] = cam->sensor.i2c_slave_id; data[1] = cam->sensor.i2c_slave_id;
data[2] = cam->sensor.rsta | 0x02 | (n << 4); data[2] = cam->sensor.rsta | 0x02 | (n << 4);
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
err += res; err += res;
/* Start writing through the serial interface */ /* Start writing through the serial interface */
data[0] = data1; data[0] = data1;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT); 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0) if (res < 0)
err += res; err += res;
@ -432,11 +432,11 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
if (!(*f)) if (!(*f))
(*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t, (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t,
frame); frame);
imagesize = (cam->sensor.pix_format.width * imagesize = (cam->sensor.pix_format.width *
cam->sensor.pix_format.height * cam->sensor.pix_format.height *
cam->sensor.pix_format.priv) / 8; cam->sensor.pix_format.priv) / 8;
for (i = 0; i < urb->number_of_packets; i++) { for (i = 0; i < urb->number_of_packets; i++) {
unsigned int len, status; unsigned int len, status;
@ -476,7 +476,7 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
if ((*f)->state == F_GRABBING) { if ((*f)->state == F_GRABBING) {
if (sof && (*f)->buf.bytesused) { if (sof && (*f)->buf.bytesused) {
if (cam->sensor.pix_format.pixelformat == if (cam->sensor.pix_format.pixelformat ==
V4L2_PIX_FMT_ET61X251) V4L2_PIX_FMT_ET61X251)
goto end_of_frame; goto end_of_frame;
else { else {
DBG(3, "Not expected SOF detected " DBG(3, "Not expected SOF detected "
@ -508,8 +508,8 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
list_move_tail(&(*f)->frame, &cam->outqueue); list_move_tail(&(*f)->frame, &cam->outqueue);
if (!list_empty(&cam->inqueue)) if (!list_empty(&cam->inqueue))
(*f) = list_entry(cam->inqueue.next, (*f) = list_entry(cam->inqueue.next,
struct et61x251_frame_t, struct et61x251_frame_t,
frame); frame);
else else
(*f) = NULL; (*f) = NULL;
spin_unlock(&cam->queue_lock); spin_unlock(&cam->queue_lock);
@ -521,7 +521,7 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
if (sof && if (sof &&
cam->sensor.pix_format.pixelformat == cam->sensor.pix_format.pixelformat ==
V4L2_PIX_FMT_ET61X251) V4L2_PIX_FMT_ET61X251)
goto start_of_frame; goto start_of_frame;
} }
} }
@ -544,15 +544,15 @@ static int et61x251_start_transfer(struct et61x251_device* cam)
struct usb_device *udev = cam->usbdev; struct usb_device *udev = cam->usbdev;
struct urb* urb; struct urb* urb;
const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832,
864, 896, 920, 956, 980, 1000, 864, 896, 920, 956, 980, 1000,
1022}; 1022};
const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING];
s8 i, j; s8 i, j;
int err = 0; int err = 0;
for (i = 0; i < ET61X251_URBS; i++) { for (i = 0; i < ET61X251_URBS; i++) {
cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz, cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz,
GFP_KERNEL); GFP_KERNEL);
if (!cam->transfer_buffer[i]) { if (!cam->transfer_buffer[i]) {
err = -ENOMEM; err = -ENOMEM;
DBG(1, "Not enough memory"); DBG(1, "Not enough memory");
@ -653,9 +653,9 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam)
cam->stream = STREAM_INTERRUPT; cam->stream = STREAM_INTERRUPT;
timeout = wait_event_timeout(cam->wait_stream, timeout = wait_event_timeout(cam->wait_stream,
(cam->stream == STREAM_OFF) || (cam->stream == STREAM_OFF) ||
(cam->state & DEV_DISCONNECTED), (cam->state & DEV_DISCONNECTED),
ET61X251_URB_TIMEOUT); ET61X251_URB_TIMEOUT);
if (cam->state & DEV_DISCONNECTED) if (cam->state & DEV_DISCONNECTED)
return -ENODEV; return -ENODEV;
else if (cam->stream != STREAM_OFF) { else if (cam->stream != STREAM_OFF) {
@ -699,7 +699,7 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count)
/* /*
NOTE 1: being inside one of the following methods implies that the v4l NOTE 1: being inside one of the following methods implies that the v4l
device exists for sure (see kobjects and reference counters) device exists for sure (see kobjects and reference counters)
NOTE 2: buffers are PAGE_SIZE long NOTE 2: buffers are PAGE_SIZE long
*/ */
@ -964,13 +964,13 @@ et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
et61x251_show_reg, et61x251_store_reg); et61x251_show_reg, et61x251_store_reg);
static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
et61x251_show_val, et61x251_store_val); et61x251_show_val, et61x251_store_val);
static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
et61x251_show_i2c_reg, et61x251_store_i2c_reg); et61x251_show_i2c_reg, et61x251_store_i2c_reg);
static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
et61x251_show_i2c_val, et61x251_store_i2c_val); et61x251_show_i2c_val, et61x251_store_i2c_val);
static void et61x251_create_sysfs(struct et61x251_device* cam) static void et61x251_create_sysfs(struct et61x251_device* cam)
@ -990,7 +990,7 @@ static void et61x251_create_sysfs(struct et61x251_device* cam)
static int static int
et61x251_set_pix_format(struct et61x251_device* cam, et61x251_set_pix_format(struct et61x251_device* cam,
struct v4l2_pix_format* pix) struct v4l2_pix_format* pix)
{ {
int r, err = 0; int r, err = 0;
@ -1007,7 +1007,7 @@ et61x251_set_pix_format(struct et61x251_device* cam,
static int static int
et61x251_set_compression(struct et61x251_device* cam, et61x251_set_compression(struct et61x251_device* cam,
struct v4l2_jpegcompression* compression) struct v4l2_jpegcompression* compression)
{ {
int r, err = 0; int r, err = 0;
@ -1049,9 +1049,9 @@ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect)
{ {
struct et61x251_sensor* s = &cam->sensor; struct et61x251_sensor* s = &cam->sensor;
u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left +
s->active_pixel.left), s->active_pixel.left),
fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + fmw_sy = (u16)(rect->top - s->cropcap.bounds.top +
s->active_pixel.top), s->active_pixel.top),
fmw_length = (u16)(rect->width), fmw_length = (u16)(rect->width),
fmw_height = (u16)(rect->height); fmw_height = (u16)(rect->height);
int err = 0; int err = 0;
@ -1061,8 +1061,8 @@ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect)
err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b); err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b);
err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c); err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c);
err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6) err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6)
| ((fmw_length & 0x300) >> 4) | ((fmw_length & 0x300) >> 4)
| ((fmw_height & 0x300) >> 2), 0x6d); | ((fmw_height & 0x300) >> 2), 0x6d);
if (err) if (err)
return -EIO; return -EIO;
@ -1203,8 +1203,8 @@ static int et61x251_open(struct inode* inode, struct file* filp)
} }
mutex_unlock(&cam->dev_mutex); mutex_unlock(&cam->dev_mutex);
err = wait_event_interruptible_exclusive(cam->open, err = wait_event_interruptible_exclusive(cam->open,
cam->state & DEV_DISCONNECTED cam->state & DEV_DISCONNECTED
|| !cam->users); || !cam->users);
if (err) { if (err) {
up_read(&et61x251_disconnect); up_read(&et61x251_disconnect);
return err; return err;
@ -1277,7 +1277,7 @@ static int et61x251_release(struct inode* inode, struct file* filp)
static ssize_t static ssize_t
et61x251_read(struct file* filp, char __user * buf, et61x251_read(struct file* filp, char __user * buf,
size_t count, loff_t* f_pos) size_t count, loff_t* f_pos)
{ {
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
struct et61x251_frame_t* f, * i; struct et61x251_frame_t* f, * i;
@ -1310,7 +1310,7 @@ et61x251_read(struct file* filp, char __user * buf,
if (cam->io == IO_NONE) { if (cam->io == IO_NONE) {
if (!et61x251_request_buffers(cam, cam->nreadbuffers, if (!et61x251_request_buffers(cam, cam->nreadbuffers,
IO_READ)) { IO_READ)) {
DBG(1, "read() failed, not enough memory"); DBG(1, "read() failed, not enough memory");
mutex_unlock(&cam->fileop_mutex); mutex_unlock(&cam->fileop_mutex);
return -ENOMEM; return -ENOMEM;
@ -1336,12 +1336,12 @@ et61x251_read(struct file* filp, char __user * buf,
return -EAGAIN; return -EAGAIN;
} }
timeout = wait_event_interruptible_timeout timeout = wait_event_interruptible_timeout
( cam->wait_frame, ( cam->wait_frame,
(!list_empty(&cam->outqueue)) || (!list_empty(&cam->outqueue)) ||
(cam->state & DEV_DISCONNECTED) || (cam->state & DEV_DISCONNECTED) ||
(cam->state & DEV_MISCONFIGURED), (cam->state & DEV_MISCONFIGURED),
cam->module_param.frame_timeout * cam->module_param.frame_timeout *
1000 * msecs_to_jiffies(1) ); 1000 * msecs_to_jiffies(1) );
if (timeout < 0) { if (timeout < 0) {
mutex_unlock(&cam->fileop_mutex); mutex_unlock(&cam->fileop_mutex);
return timeout; return timeout;
@ -1408,7 +1408,7 @@ static unsigned int et61x251_poll(struct file *filp, poll_table *wait)
if (cam->io == IO_NONE) { if (cam->io == IO_NONE) {
if (!et61x251_request_buffers(cam, cam->nreadbuffers, if (!et61x251_request_buffers(cam, cam->nreadbuffers,
IO_READ)) { IO_READ)) {
DBG(1, "poll() failed, not enough memory"); DBG(1, "poll() failed, not enough memory");
goto error; goto error;
} }
@ -1465,7 +1465,7 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
{ {
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
unsigned long size = vma->vm_end - vma->vm_start, unsigned long size = vma->vm_end - vma->vm_start,
start = vma->vm_start; start = vma->vm_start;
void *pos; void *pos;
u32 i; u32 i;
@ -1533,13 +1533,13 @@ et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg)
.driver = "et61x251", .driver = "et61x251",
.version = ET61X251_MODULE_VERSION_CODE, .version = ET61X251_MODULE_VERSION_CODE,
.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING, V4L2_CAP_STREAMING,
}; };
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
sizeof(cap.bus_info)); sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap))) if (copy_to_user(arg, &cap, sizeof(cap)))
return -EFAULT; return -EFAULT;
@ -1871,7 +1871,7 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
return -EINVAL; return -EINVAL;
pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251)
? 0 : (pfmt->width * pfmt->priv) / 8; ? 0 : (pfmt->width * pfmt->priv) / 8;
pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
pfmt->field = V4L2_FIELD_NONE; pfmt->field = V4L2_FIELD_NONE;
memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
@ -1885,7 +1885,7 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
static int static int
et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
void __user * arg) void __user * arg)
{ {
struct et61x251_sensor* s = &cam->sensor; struct et61x251_sensor* s = &cam->sensor;
struct v4l2_format format; struct v4l2_format format;
@ -1947,7 +1947,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
pix->priv = pfmt->priv; /* bpp */ pix->priv = pfmt->priv; /* bpp */
pix->colorspace = pfmt->colorspace; pix->colorspace = pfmt->colorspace;
pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251)
? 0 : (pix->width * pix->priv) / 8; ? 0 : (pix->width * pix->priv) / 8;
pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
pix->field = V4L2_FIELD_NONE; pix->field = V4L2_FIELD_NONE;
@ -2020,7 +2020,7 @@ static int
et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg) et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg)
{ {
if (copy_to_user(arg, &cam->compression, if (copy_to_user(arg, &cam->compression,
sizeof(cam->compression))) sizeof(cam->compression)))
return -EFAULT; return -EFAULT;
return 0; return 0;
@ -2169,7 +2169,7 @@ et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg)
static int static int
et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp, et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp,
void __user * arg) void __user * arg)
{ {
struct v4l2_buffer b; struct v4l2_buffer b;
struct et61x251_frame_t *f; struct et61x251_frame_t *f;
@ -2188,12 +2188,12 @@ et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp,
if (filp->f_flags & O_NONBLOCK) if (filp->f_flags & O_NONBLOCK)
return -EAGAIN; return -EAGAIN;
timeout = wait_event_interruptible_timeout timeout = wait_event_interruptible_timeout
( cam->wait_frame, ( cam->wait_frame,
(!list_empty(&cam->outqueue)) || (!list_empty(&cam->outqueue)) ||
(cam->state & DEV_DISCONNECTED) || (cam->state & DEV_DISCONNECTED) ||
(cam->state & DEV_MISCONFIGURED), (cam->state & DEV_MISCONFIGURED),
cam->module_param.frame_timeout * cam->module_param.frame_timeout *
1000 * msecs_to_jiffies(1) ); 1000 * msecs_to_jiffies(1) );
if (timeout < 0) if (timeout < 0)
return timeout; return timeout;
if (cam->state & DEV_DISCONNECTED) if (cam->state & DEV_DISCONNECTED)
@ -2317,7 +2317,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
unsigned int cmd, void __user * arg) unsigned int cmd, void __user * arg)
{ {
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
@ -2411,7 +2411,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
static int et61x251_ioctl(struct inode* inode, struct file* filp, static int et61x251_ioctl(struct inode* inode, struct file* filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
int err = 0; int err = 0;
@ -2518,7 +2518,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
mutex_lock(&cam->dev_mutex); mutex_lock(&cam->dev_mutex);
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
video_nr[dev_nr]); video_nr[dev_nr]);
if (err) { if (err) {
DBG(1, "V4L2 device registration failed"); DBG(1, "V4L2 device registration failed");
if (err == -ENFILE && video_nr[dev_nr] == -1) if (err == -ENFILE && video_nr[dev_nr] == -1)

View file

@ -47,7 +47,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id);
extern void extern void
et61x251_attach_sensor(struct et61x251_device* cam, et61x251_attach_sensor(struct et61x251_device* cam,
struct et61x251_sensor* sensor); struct et61x251_sensor* sensor);
/*****************************************************************************/ /*****************************************************************************/
@ -56,13 +56,13 @@ extern int et61x251_read_reg(struct et61x251_device*, u16 index);
extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value);
extern int et61x251_i2c_read(struct et61x251_device*, u8 address); extern int et61x251_i2c_read(struct et61x251_device*, u8 address);
extern int et61x251_i2c_try_write(struct et61x251_device*, extern int et61x251_i2c_try_write(struct et61x251_device*,
struct et61x251_sensor*, u8 address, struct et61x251_sensor*, u8 address,
u8 value); u8 value);
extern int et61x251_i2c_try_read(struct et61x251_device*, extern int et61x251_i2c_try_read(struct et61x251_device*,
struct et61x251_sensor*, u8 address); struct et61x251_sensor*, u8 address);
extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1,
u8 data2, u8 data3, u8 data4, u8 data5, u8 data2, u8 data3, u8 data4, u8 data5,
u8 data6, u8 data7, u8 data8, u8 address); u8 data6, u8 data7, u8 data8, u8 address);
/*****************************************************************************/ /*****************************************************************************/
@ -100,13 +100,13 @@ struct et61x251_sensor {
int (*init)(struct et61x251_device* cam); int (*init)(struct et61x251_device* cam);
int (*get_ctrl)(struct et61x251_device* cam, int (*get_ctrl)(struct et61x251_device* cam,
struct v4l2_control* ctrl); struct v4l2_control* ctrl);
int (*set_ctrl)(struct et61x251_device* cam, int (*set_ctrl)(struct et61x251_device* cam,
const struct v4l2_control* ctrl); const struct v4l2_control* ctrl);
int (*set_crop)(struct et61x251_device* cam, int (*set_crop)(struct et61x251_device* cam,
const struct v4l2_rect* rect); const struct v4l2_rect* rect);
int (*set_pix_format)(struct et61x251_device* cam, int (*set_pix_format)(struct et61x251_device* cam,
const struct v4l2_pix_format* pix); const struct v4l2_pix_format* pix);
/* Private */ /* Private */
struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS]; struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS];

View file

@ -46,20 +46,20 @@ static int tas5130d1b_init(struct et61x251_device* cam)
static int tas5130d1b_set_ctrl(struct et61x251_device* cam, static int tas5130d1b_set_ctrl(struct et61x251_device* cam,
const struct v4l2_control* ctrl) const struct v4l2_control* ctrl)
{ {
int err = 0; int err = 0;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_GAIN: case V4L2_CID_GAIN:
err += et61x251_i2c_raw_write(cam, 2, 0x20, err += et61x251_i2c_raw_write(cam, 2, 0x20,
0xf6-ctrl->value, 0, 0, 0, 0xf6-ctrl->value, 0, 0, 0,
0, 0, 0, 0); 0, 0, 0, 0);
break; break;
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
err += et61x251_i2c_raw_write(cam, 2, 0x40, err += et61x251_i2c_raw_write(cam, 2, 0x40,
0x47-ctrl->value, 0, 0, 0, 0x47-ctrl->value, 0, 0, 0,
0, 0, 0, 0); 0, 0, 0, 0);
break; break;
default: default:
return -EINVAL; return -EINVAL;

407
drivers/media/video/font.h Normal file
View file

@ -0,0 +1,407 @@
static unsigned char rom8x16_bits[] = {
/* Character 0 (0x30):
ht=16, width=8
+--------+
| |
| |
| ***** |
|** ** |
|** ** |
|** *** |
|** **** |
|**** ** |
|*** ** |
|** ** |
|** ** |
| ***** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x7c,
0xc6,
0xc6,
0xce,
0xde,
0xf6,
0xe6,
0xc6,
0xc6,
0x7c,
0x00,
0x00,
0x00,
0x00,
/* Character 1 (0x31):
ht=16, width=8
+--------+
| |
| |
| ** |
| **** |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** |
| ****** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x18,
0x78,
0x18,
0x18,
0x18,
0x18,
0x18,
0x18,
0x18,
0x7e,
0x00,
0x00,
0x00,
0x00,
/* Character 2 (0x32):
ht=16, width=8
+--------+
| |
| |
| ***** |
|** ** |
|** ** |
| ** |
| ** |
| ** |
| ** |
| ** |
|** ** |
|******* |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x7c,
0xc6,
0xc6,
0x06,
0x0c,
0x18,
0x30,
0x60,
0xc6,
0xfe,
0x00,
0x00,
0x00,
0x00,
/* Character 3 (0x33):
ht=16, width=8
+--------+
| |
| |
| ***** |
|** ** |
| ** |
| ** |
| **** |
| ** |
| ** |
| ** |
|** ** |
| ***** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x7c,
0xc6,
0x06,
0x06,
0x3c,
0x06,
0x06,
0x06,
0xc6,
0x7c,
0x00,
0x00,
0x00,
0x00,
/* Character 4 (0x34):
ht=16, width=8
+--------+
| |
| |
| ** |
| *** |
| **** |
| ** ** |
|** ** |
|** ** |
|******* |
| ** |
| ** |
| **** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x0c,
0x1c,
0x3c,
0x6c,
0xcc,
0xcc,
0xfe,
0x0c,
0x0c,
0x1e,
0x00,
0x00,
0x00,
0x00,
/* Character 5 (0x35):
ht=16, width=8
+--------+
| |
| |
|******* |
|** |
|** |
|** |
|****** |
| ** |
| ** |
| ** |
|** ** |
| ***** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0xfe,
0xc0,
0xc0,
0xc0,
0xfc,
0x06,
0x06,
0x06,
0xc6,
0x7c,
0x00,
0x00,
0x00,
0x00,
/* Character 6 (0x36):
ht=16, width=8
+--------+
| |
| |
| ***** |
|** ** |
|** |
|** |
|****** |
|** ** |
|** ** |
|** ** |
|** ** |
| ***** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x7c,
0xc6,
0xc0,
0xc0,
0xfc,
0xc6,
0xc6,
0xc6,
0xc6,
0x7c,
0x00,
0x00,
0x00,
0x00,
/* Character 7 (0x37):
ht=16, width=8
+--------+
| |
| |
|******* |
|** ** |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0xfe,
0xc6,
0x06,
0x0c,
0x18,
0x30,
0x30,
0x30,
0x30,
0x30,
0x00,
0x00,
0x00,
0x00,
/* Character 8 (0x38):
ht=16, width=8
+--------+
| |
| |
| ***** |
|** ** |
|** ** |
|** ** |
| ***** |
|** ** |
|** ** |
|** ** |
|** ** |
| ***** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x7c,
0xc6,
0xc6,
0xc6,
0x7c,
0xc6,
0xc6,
0xc6,
0xc6,
0x7c,
0x00,
0x00,
0x00,
0x00,
/* Character 9 (0x39):
ht=16, width=8
+--------+
| |
| |
| ***** |
|** ** |
|** ** |
|** ** |
|** ** |
| ****** |
| ** |
| ** |
|** ** |
| ***** |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x7c,
0xc6,
0xc6,
0xc6,
0xc6,
0x7e,
0x06,
0x06,
0xc6,
0x7c,
0x00,
0x00,
0x00,
0x00,
/* Character : (0x3a):
ht=16, width=8
+--------+
| |
| |
| |
| |
| |
| ** |
| ** |
| |
| |
| ** |
| ** |
| |
| |
| |
| |
| |
+--------+ */
0x00,
0x00,
0x00,
0x00,
0x00,
0x0c,
0x0c,
0x00,
0x00,
0x0c,
0x0c,
0x00,
0x00,
0x00,
0x00,
0x00,
};

View file

@ -53,10 +53,11 @@
#include <linux/videodev.h> #include <linux/videodev.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/audiochip.h> #include <media/tvaudio.h>
#include <media/msp3400.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include "msp3400.h" #include "msp3400-driver.h"
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -245,31 +246,31 @@ int msp_write_dsp(struct i2c_client *client, int addr, int val)
* ----------------------------------------------------------------------- */ * ----------------------------------------------------------------------- */
static int scarts[3][9] = { static int scarts[3][9] = {
/* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */
/* SCART DSP Input select */ /* SCART DSP Input select */
{ 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 },
/* SCART1 Output select */ /* SCART1 Output select */
{ 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 },
/* SCART2 Output select */ /* SCART2 Output select */
{ 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 },
}; };
static char *scart_names[] = { static char *scart_names[] = {
"mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute"
}; };
void msp_set_scart(struct i2c_client *client, int in, int out) void msp_set_scart(struct i2c_client *client, int in, int out)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
state->in_scart=in; state->in_scart = in;
if (in >= 1 && in <= 8 && out >= 0 && out <= 2) { if (in >= 0 && in <= 7 && out >= 0 && out <= 2) {
if (-1 == scarts[out][in]) if (-1 == scarts[out][in + 1])
return; return;
state->acb &= ~scarts[out][SCART_MASK]; state->acb &= ~scarts[out][0];
state->acb |= scarts[out][in]; state->acb |= scarts[out][in + 1];
} else } else
state->acb = 0xf60; /* Mute Input and SCART 1 Output */ state->acb = 0xf60; /* Mute Input and SCART 1 Output */
@ -336,37 +337,6 @@ void msp_set_audio(struct i2c_client *client)
msp_write_dsp(client, 0x0033, loudness); msp_write_dsp(client, 0x0033, loudness);
} }
int msp_modus(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
if (state->radio) {
v4l_dbg(1, msp_debug, client, "video mode selected to Radio\n");
return 0x0003;
}
if (state->v4l2_std & V4L2_STD_PAL) {
v4l_dbg(1, msp_debug, client, "video mode selected to PAL\n");
#if 1
/* experimental: not sure this works with all chip versions */
return 0x7003;
#else
/* previous value, try this if it breaks ... */
return 0x1003;
#endif
}
if (state->v4l2_std & V4L2_STD_NTSC) {
v4l_dbg(1, msp_debug, client, "video mode selected to NTSC\n");
return 0x2003;
}
if (state->v4l2_std & V4L2_STD_SECAM) {
v4l_dbg(1, msp_debug, client, "video mode selected to SECAM\n");
return 0x0003;
}
return 0x0003;
}
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
@ -585,51 +555,11 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
u16 *sarg = arg;
int scart = 0;
if (msp_debug >= 2) if (msp_debug >= 2)
v4l_i2c_print_ioctl(client, cmd); v4l_i2c_print_ioctl(client, cmd);
switch (cmd) { switch (cmd) {
case AUDC_SET_INPUT:
if (*sarg == state->input)
break;
state->input = *sarg;
switch (*sarg) {
case AUDIO_RADIO:
/* Hauppauge uses IN2 for the radio */
state->mode = MSP_MODE_FM_RADIO;
scart = SCART_IN2;
break;
case AUDIO_EXTERN_1:
/* IN1 is often used for external input ... */
state->mode = MSP_MODE_EXTERN;
scart = SCART_IN1;
break;
case AUDIO_EXTERN_2:
/* ... sometimes it is IN2 through ;) */
state->mode = MSP_MODE_EXTERN;
scart = SCART_IN2;
break;
case AUDIO_TUNER:
state->mode = -1;
break;
default:
if (*sarg & AUDIO_MUTE)
msp_set_scart(client, SCART_MUTE, 0);
break;
}
if (scart) {
state->rxsubchans = V4L2_TUNER_SUB_STEREO;
msp_set_scart(client, scart, 0);
msp_write_dsp(client, 0x000d, 0x1900);
if (state->opmode != OPMODE_AUTOSELECT)
msp_set_audmode(client);
}
msp_wake_thread(client);
break;
case AUDC_SET_RADIO: case AUDC_SET_RADIO:
if (state->radio) if (state->radio)
return 0; return 0;
@ -692,6 +622,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (va->mode != 0 && state->radio == 0) { if (va->mode != 0 && state->radio == 0) {
state->audmode = msp_mode_v4l1_to_v4l2(va->mode); state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
msp_set_audmode(client);
} }
break; break;
} }
@ -728,15 +659,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
break; break;
} }
/* msp34xx specific */
case MSP_SET_MATRIX:
{
struct msp_matrix *mspm = arg;
msp_set_scart(client, mspm->input, mspm->output);
break;
}
/* --- v4l2 ioctls --- */ /* --- v4l2 ioctls --- */
case VIDIOC_S_STD: case VIDIOC_S_STD:
{ {
@ -750,90 +672,34 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0; return 0;
} }
case VIDIOC_ENUMINPUT: case VIDIOC_INT_G_AUDIO_ROUTING:
{ {
struct v4l2_input *i = arg; struct v4l2_routing *rt = arg;
if (i->index != 0) *rt = state->routing;
return -EINVAL;
i->type = V4L2_INPUT_TYPE_TUNER;
switch (i->index) {
case AUDIO_RADIO:
strcpy(i->name, "Radio");
break;
case AUDIO_EXTERN_1:
strcpy(i->name, "Extern 1");
break;
case AUDIO_EXTERN_2:
strcpy(i->name, "Extern 2");
break;
case AUDIO_TUNER:
strcpy(i->name, "Television");
break;
default:
return -EINVAL;
}
return 0;
}
case VIDIOC_G_AUDIO:
{
struct v4l2_audio *a = arg;
memset(a, 0, sizeof(*a));
switch (a->index) {
case AUDIO_RADIO:
strcpy(a->name, "Radio");
break;
case AUDIO_EXTERN_1:
strcpy(a->name, "Extern 1");
break;
case AUDIO_EXTERN_2:
strcpy(a->name, "Extern 2");
break;
case AUDIO_TUNER:
strcpy(a->name, "Television");
break;
default:
return -EINVAL;
}
a->capability = V4L2_AUDCAP_STEREO;
a->mode = 0; /* TODO: add support for AVL */
break; break;
} }
case VIDIOC_S_AUDIO: case VIDIOC_INT_S_AUDIO_ROUTING:
{ {
struct v4l2_audio *sarg = arg; struct v4l2_routing *rt = arg;
int tuner = (rt->input >> 3) & 1;
int sc_in = rt->input & 0x7;
int sc1_out = rt->output & 0xf;
int sc2_out = (rt->output >> 4) & 0xf;
u16 val;
switch (sarg->index) { state->routing = *rt;
case AUDIO_RADIO: if (state->opmode == OPMODE_AUTOSELECT) {
/* Hauppauge uses IN2 for the radio */ val = msp_read_dem(client, 0x30) & ~0x100;
state->mode = MSP_MODE_FM_RADIO; msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
scart = SCART_IN2; } else {
break; val = msp_read_dem(client, 0xbb) & ~0x100;
case AUDIO_EXTERN_1: msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
/* IN1 is often used for external input ... */
state->mode = MSP_MODE_EXTERN;
scart = SCART_IN1;
break;
case AUDIO_EXTERN_2:
/* ... sometimes it is IN2 through ;) */
state->mode = MSP_MODE_EXTERN;
scart = SCART_IN2;
break;
case AUDIO_TUNER:
state->mode = -1;
break;
}
if (scart) {
state->rxsubchans = V4L2_TUNER_SUB_STEREO;
msp_set_scart(client, scart, 0);
msp_write_dsp(client, 0x000d, 0x1900);
} }
msp_set_scart(client, sc_in, 0);
msp_set_scart(client, sc1_out, 1);
msp_set_scart(client, sc2_out, 2);
msp_set_audmode(client); msp_set_audmode(client);
msp_wake_thread(client); msp_wake_thread(client);
break; break;
@ -866,42 +732,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
break; break;
} }
case VIDIOC_G_AUDOUT:
{
struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
int idx = a->index;
memset(a, 0, sizeof(*a));
switch (idx) {
case 0:
strcpy(a->name, "Scart1 Out");
break;
case 1:
strcpy(a->name, "Scart2 Out");
break;
case 2:
strcpy(a->name, "I2S Out");
break;
default:
return -EINVAL;
}
break;
}
case VIDIOC_S_AUDOUT:
{
struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
if (a->index < 0 || a->index > 2)
return -EINVAL;
v4l_dbg(1, msp_debug, client, "Setting audio out on msp34xx to input %i\n", a->index);
msp_set_scart(client, state->in_scart, a->index + 1);
break;
}
case VIDIOC_INT_I2S_CLOCK_FREQ: case VIDIOC_INT_I2S_CLOCK_FREQ:
{ {
u32 *a = (u32 *)arg; u32 *a = (u32 *)arg;
@ -979,12 +809,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
} else { } else {
v4l_info(client, "Mode: %s\n", p); if (state->opmode == OPMODE_AUTODETECT)
v4l_info(client, "Mode: %s\n", p);
v4l_info(client, "Standard: %s (%s%s)\n", v4l_info(client, "Standard: %s (%s%s)\n",
msp_standard_std_name(state->std), msp_standard_std_name(state->std),
(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
} }
v4l_info(client, "Audmode: 0x%04x\n", state->audmode);
v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n",
state->routing.input, state->routing.output);
v4l_info(client, "ACB: 0x%04x\n", state->acb); v4l_info(client, "ACB: 0x%04x\n", state->acb);
break; break;
} }
@ -1063,6 +897,9 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
state->muted = 0; state->muted = 0;
state->i2s_mode = 0; state->i2s_mode = 0;
init_waitqueue_head(&state->wq); init_waitqueue_head(&state->wq);
/* These are the reset input/output positions */
state->routing.input = MSP_INPUT_DEFAULT;
state->routing.output = MSP_OUTPUT_DEFAULT;
state->rev1 = msp_read_dsp(client, 0x1e); state->rev1 = msp_read_dsp(client, 0x1e);
if (state->rev1 != -1) if (state->rev1 != -1)

View file

@ -1,8 +1,10 @@
/* /*
*/ */
#ifndef MSP3400_H #ifndef MSP3400_DRIVER_H
#define MSP3400_H #define MSP3400_DRIVER_H
#include <media/msp3400.h>
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -20,15 +22,14 @@
#define MSP_MODE_BTSC 8 #define MSP_MODE_BTSC 8
#define MSP_MODE_EXTERN 9 #define MSP_MODE_EXTERN 9
#define SCART_MASK 0 #define SCART_IN1 0
#define SCART_IN1 1 #define SCART_IN2 1
#define SCART_IN2 2 #define SCART_IN3 2
#define SCART_IN1_DA 3 #define SCART_IN4 3
#define SCART_IN2_DA 4 #define SCART_IN1_DA 4
#define SCART_IN3 5 #define SCART_IN2_DA 5
#define SCART_IN4 6 #define SCART_MONO 6
#define SCART_MONO 7 #define SCART_MUTE 7
#define SCART_MUTE 8
#define SCART_DSP_IN 0 #define SCART_DSP_IN 0
#define SCART1_OUT 1 #define SCART1_OUT 1
@ -73,7 +74,7 @@ struct msp_state {
int i2s_mode; int i2s_mode;
int main, second; /* sound carrier */ int main, second; /* sound carrier */
int input; int input;
int source; /* see msp34xxg_set_source */ struct v4l2_routing routing;
/* v4l2 */ /* v4l2 */
int audmode; int audmode;
@ -99,17 +100,16 @@ int msp_reset(struct i2c_client *client);
void msp_set_scart(struct i2c_client *client, int in, int out); void msp_set_scart(struct i2c_client *client, int in, int out);
void msp_set_mute(struct i2c_client *client); void msp_set_mute(struct i2c_client *client);
void msp_set_audio(struct i2c_client *client); void msp_set_audio(struct i2c_client *client);
int msp_modus(struct i2c_client *client);
int msp_sleep(struct msp_state *state, int timeout); int msp_sleep(struct msp_state *state, int timeout);
/* msp3400-kthreads.c */ /* msp3400-kthreads.c */
const char *msp_standard_std_name(int std); const char *msp_standard_std_name(int std);
void msp_set_audmode(struct i2c_client *client); void msp_set_audmode(struct i2c_client *client);
void msp_detect_stereo(struct i2c_client *client); int msp_detect_stereo(struct i2c_client *client);
int msp3400c_thread(void *data); int msp3400c_thread(void *data);
int msp3410d_thread(void *data); int msp3410d_thread(void *data);
int msp34xxg_thread(void *data); int msp34xxg_thread(void *data);
void msp3400c_set_mode(struct i2c_client *client, int mode); void msp3400c_set_mode(struct i2c_client *client, int mode);
void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2); void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2);
#endif /* MSP3400_H */ #endif /* MSP3400_DRIVER_H */

View file

@ -26,10 +26,10 @@
#include <linux/videodev.h> #include <linux/videodev.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/audiochip.h> #include <media/msp3400.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include "msp3400.h" #include "msp3400-driver.h"
/* this one uses the automatic sound standard detection of newer msp34xx /* this one uses the automatic sound standard detection of newer msp34xx
chip versions */ chip versions */
@ -45,11 +45,13 @@ static struct {
{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" },
{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" },
{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" },
{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74 D/K3 Dual FM-Stereo" },
{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" },
{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" },
{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" },
{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" },
{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" },
{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV3)" },
{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" },
{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" },
{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" },
@ -185,13 +187,14 @@ void msp3400c_set_mode(struct i2c_client *client, int mode)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode];
int tuner = (state->routing.input >> 3) & 1;
int i; int i;
v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode);
state->mode = mode; state->mode = mode;
state->rxsubchans = V4L2_TUNER_SUB_MONO; state->rxsubchans = V4L2_TUNER_SUB_MONO;
msp_write_dem(client, 0x00bb, data->ad_cv); msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0));
for (i = 5; i >= 0; i--) /* fir 1 */ for (i = 5; i >= 0; i--) /* fir 1 */
msp_write_dem(client, 0x0001, data->fir1[i]); msp_write_dem(client, 0x0001, data->fir1[i]);
@ -207,21 +210,22 @@ void msp3400c_set_mode(struct i2c_client *client, int mode)
msp3400c_set_carrier(client, data->cdo1, data->cdo2); msp3400c_set_carrier(client, data->cdo1, data->cdo2);
msp_set_source(client, data->dsp_src); msp_set_source(client, data->dsp_src);
msp_write_dsp(client, 0x000e, data->dsp_matrix); /* set prescales */
if (state->has_nicam) { /* volume prescale for SCART (AM mono input) */
/* nicam prescale */ msp_write_dsp(client, 0x000d, 0x1900);
msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */ msp_write_dsp(client, 0x000e, data->dsp_matrix);
} if (state->has_nicam) /* nicam prescale */
msp_write_dsp(client, 0x0010, 0x5a00);
} }
/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, /* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP,
nor do they support stereo BTSC. */ nor do they support stereo BTSC. */
static void msp3400c_set_audmode(struct i2c_client *client) static void msp3400c_set_audmode(struct i2c_client *client)
{ {
static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; static char *strmode[] = { "mono", "stereo", "lang2", "lang1", "lang1+lang2" };
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
char *modestr = (state->audmode >= 0 && state->audmode < 4) ? char *modestr = (state->audmode >= 0 && state->audmode < 5) ?
strmode[state->audmode] : "unknown"; strmode[state->audmode] : "unknown";
int src = 0; /* channel source: FM/AM, nicam or SCART */ int src = 0; /* channel source: FM/AM, nicam or SCART */
@ -246,6 +250,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG1:
case V4L2_TUNER_MODE_LANG2: case V4L2_TUNER_MODE_LANG2:
case V4L2_TUNER_MODE_LANG1_LANG2:
msp_write_dsp(client, 0x000e, 0x3000); msp_write_dsp(client, 0x000e, 0x3000);
break; break;
} }
@ -257,6 +262,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
break; break;
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
break; break;
case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG1:
@ -271,7 +277,6 @@ static void msp3400c_set_audmode(struct i2c_client *client)
case MSP_MODE_FM_NICAM2: case MSP_MODE_FM_NICAM2:
case MSP_MODE_AM_NICAM: case MSP_MODE_AM_NICAM:
v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr); v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr);
msp3400c_set_carrier(client, state->second, state->main);
if (state->nicam_on) if (state->nicam_on)
src = 0x0100; /* NICAM */ src = 0x0100; /* NICAM */
break; break;
@ -293,6 +298,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
/* switch audio */ /* switch audio */
switch (state->audmode) { switch (state->audmode) {
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
src |= 0x0020; src |= 0x0020;
break; break;
case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_MONO:
@ -427,8 +433,8 @@ static void watch_stereo(struct i2c_client *client)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
if (msp3400c_detect_stereo(client)) { if (msp_detect_stereo(client)) {
msp3400c_set_audmode(client); msp_set_audmode(client);
} }
if (msp_once) if (msp_once)
@ -464,7 +470,7 @@ int msp3400c_thread(void *data)
/* mute */ /* mute */
msp_set_mute(client); msp_set_mute(client);
msp3400c_set_mode(client, MSP_MODE_AM_DETECT /* +1 */ ); msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
val1 = val2 = 0; val1 = val2 = 0;
max1 = max2 = -1; max1 = max2 = -1;
state->watch_stereo = 0; state->watch_stereo = 0;
@ -572,8 +578,6 @@ int msp3400c_thread(void *data)
state->second = msp3400c_carrier_detect_65[max2].cdo; state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_AM_NICAM); msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
msp3400c_set_carrier(client, state->second, state->main); msp3400c_set_carrier(client, state->second, state->main);
/* volume prescale for SCART (AM mono input) */
msp_write_dsp(client, 0x000d, 0x1900);
state->watch_stereo = 1; state->watch_stereo = 1;
} else if (max2 == 0 && state->has_nicam) { } else if (max2 == 0 && state->has_nicam) {
/* D/K NICAM */ /* D/K NICAM */
@ -651,7 +655,8 @@ int msp3410d_thread(void *data)
if (msp_sleep(state,200)) if (msp_sleep(state,200))
goto restart; goto restart;
/* start autodetect */ /* start autodetect. Note: autodetect is not supported for
NTSC-M and radio, hence we force the standard in those cases. */
if (state->radio) if (state->radio)
std = 0x40; std = 0x40;
else else
@ -695,23 +700,19 @@ int msp3410d_thread(void *data)
v4l_dbg(1, msp_debug, client, "autodetection failed," v4l_dbg(1, msp_debug, client, "autodetection failed,"
" switching to backup standard: %s (0x%04x)\n", " switching to backup standard: %s (0x%04x)\n",
msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val); msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val);
val = 0x0009; state->std = val = 0x0009;
msp_write_dem(client, 0x20, val); msp_write_dem(client, 0x20, val);
} }
/* set various prescales */
msp_write_dsp(client, 0x0d, 0x1900); /* scart */
msp_write_dsp(client, 0x0e, 0x2403); /* FM */
msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
/* set stereo */ /* set stereo */
switch (val) { switch (val) {
case 0x0008: /* B/G NICAM */ case 0x0008: /* B/G NICAM */
case 0x000a: /* I NICAM */ case 0x000a: /* I NICAM */
if (val == 0x0008) case 0x000b: /* D/K NICAM */
state->mode = MSP_MODE_FM_NICAM1; if (val == 0x000a)
else
state->mode = MSP_MODE_FM_NICAM2; state->mode = MSP_MODE_FM_NICAM2;
else
state->mode = MSP_MODE_FM_NICAM1;
/* just turn on stereo */ /* just turn on stereo */
state->rxsubchans = V4L2_TUNER_SUB_STEREO; state->rxsubchans = V4L2_TUNER_SUB_STEREO;
state->nicam_on = 1; state->nicam_on = 1;
@ -739,6 +740,7 @@ int msp3410d_thread(void *data)
/* scart routing (this doesn't belong here I think) */ /* scart routing (this doesn't belong here I think) */
msp_set_scart(client,SCART_IN2,0); msp_set_scart(client,SCART_IN2,0);
break; break;
case 0x0002:
case 0x0003: case 0x0003:
case 0x0004: case 0x0004:
case 0x0005: case 0x0005:
@ -748,12 +750,19 @@ int msp3410d_thread(void *data)
break; break;
} }
/* unmute, restore misc registers */ /* set various prescales */
msp_set_audio(client); msp_write_dsp(client, 0x0d, 0x1900); /* scart */
msp_write_dsp(client, 0x13, state->acb); msp_write_dsp(client, 0x0e, 0x3000); /* FM */
if (state->has_nicam)
msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
if (state->has_i2s_conf) if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode); msp_write_dem(client, 0x40, state->i2s_mode);
/* unmute, restore misc registers */
msp_set_audio(client);
msp_write_dsp(client, 0x13, state->acb);
msp3400c_set_audmode(client); msp3400c_set_audmode(client);
/* monitor tv audio mode, the first time don't wait /* monitor tv audio mode, the first time don't wait
@ -772,97 +781,154 @@ int msp3410d_thread(void *data)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* msp34xxG + (autoselect no-thread) */ /* msp34xxG + (autoselect no-thread)
/* this one uses both automatic standard detection and automatic sound */ * this one uses both automatic standard detection and automatic sound
/* select which are available in the newer G versions */ * select which are available in the newer G versions
/* struct msp: only norm, acb and source are really used in this mode */ * struct msp: only norm, acb and source are really used in this mode
/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
* the value for source is the same as bit 15:8 of DSP registers 0x08,
* 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
*
* this function replaces msp3400c_set_audmode
*/ */
static void msp34xxg_set_source(struct i2c_client *client, int source)
static int msp34xxg_modus(struct i2c_client *client)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
/* fix matrix mode to stereo and let the msp choose what if (state->radio) {
* to output according to 'source', as recommended v4l_dbg(1, msp_debug, client, "selected radio modus\n");
* for MONO (source==0) downmixing set bit[7:0] to 0x30 return 0x0001;
*/ }
int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20);
v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value); if (state->v4l2_std & V4L2_STD_PAL) {
msp_set_source(client, value); v4l_dbg(1, msp_debug, client, "selected PAL modus\n");
/* return 0x7001;
* set identification threshold. Personally, I }
* I set it to a higher value that the default if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
* of 0x190 to ignore noisy stereo signals. v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
* this needs tuning. (recommended range 0x00a0-0x03c0) return 0x4001;
* 0x7f0 = forced mono mode }
*/ if (state->v4l2_std == V4L2_STD_NTSC_M_KR) {
/* a2 threshold for stereo/bilingual */ v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
msp_write_dem(client, 0x22, msp_stereo_thresh); return 0x0001;
state->source = source; }
if (state->v4l2_std & V4L2_STD_MN) {
v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
return 0x2001;
}
if (state->v4l2_std & V4L2_STD_SECAM) {
v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");
return 0x6001;
}
return 0x0001;
} }
/* (re-)initialize the msp34xxg, according to the current norm in state->norm static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
* return 0 if it worked, -1 if it failed {
*/ struct msp_state *state = i2c_get_clientdata(client);
static int msp34xxg_reset(struct i2c_client *client) int source, matrix;
switch (state->audmode) {
case V4L2_TUNER_MODE_MONO:
source = 0; /* mono only */
matrix = 0x30;
break;
case V4L2_TUNER_MODE_LANG1:
source = 3; /* stereo or A */
matrix = 0x00;
break;
case V4L2_TUNER_MODE_LANG2:
source = 4; /* stereo or B */
matrix = 0x10;
break;
case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
default:
source = 1; /* stereo or A|B */
matrix = 0x20;
break;
}
if (in == MSP_DSP_OUT_TUNER)
source = (source << 8) | 0x20;
/* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
instead of 11, 12, 13. So we add one for that msp version. */
else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic)
source = ((in + 1) << 8) | matrix;
else
source = (in << 8) | matrix;
v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n",
in, source, reg);
msp_write_dsp(client, reg, source);
}
static void msp34xxg_set_sources(struct i2c_client *client)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
int modus, std; u32 in = state->routing.input;
if (msp_reset(client)) msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf);
return -1; /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */
msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
if (state->has_scart23_in_scart2_out)
msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
}
/* (re-)initialize the msp34xxg */
static void msp34xxg_reset(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
int tuner = (state->routing.input >> 3) & 1;
int modus;
/* initialize std to 1 (autodetect) to signal that no standard is
selected yet. */
state->std = 1;
msp_reset(client);
/* make sure that input/output is muted (paranoid mode) */ /* make sure that input/output is muted (paranoid mode) */
/* ACB, mute DSP input, mute SCART 1 */ /* ACB, mute DSP input, mute SCART 1 */
if (msp_write_dsp(client, 0x13, 0x0f20)) msp_write_dsp(client, 0x13, 0x0f20);
return -1;
if (state->has_i2s_conf) if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode); msp_write_dem(client, 0x40, state->i2s_mode);
/* step-by-step initialisation, as described in the manual */ /* step-by-step initialisation, as described in the manual */
modus = msp_modus(client); modus = msp34xxg_modus(client);
if (state->radio) modus |= tuner ? 0x100 : 0;
std = 0x40; msp_write_dem(client, 0x30, modus);
else
std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
modus &= ~0x03; /* STATUS_CHANGE = 0 */
modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */
if (msp_write_dem(client, 0x30, modus))
return -1;
if (msp_write_dem(client, 0x20, std))
return -1;
/* write the dsps that may have an influence on /* write the dsps that may have an influence on
standard/audio autodetection right now */ standard/audio autodetection right now */
msp34xxg_set_source(client, state->source); msp34xxg_set_sources(client);
/* AM/FM Prescale [15:8] 75khz deviation */ msp_write_dsp(client, 0x0d, 0x1900); /* scart */
if (msp_write_dsp(client, 0x0e, 0x3000)) msp_write_dsp(client, 0x0e, 0x3000); /* FM */
return -1; if (state->has_nicam)
msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
/* NICAM Prescale 9db gain (as recommended) */ /* set identification threshold. Personally, I
if (msp_write_dsp(client, 0x10, 0x5a00)) * I set it to a higher value than the default
return -1; * of 0x190 to ignore noisy stereo signals.
* this needs tuning. (recommended range 0x00a0-0x03c0)
return 0; * 0x7f0 = forced mono mode
*
* a2 threshold for stereo/bilingual.
* Note: this register is part of the Manual/Compatibility mode.
* It is supported by all 'G'-family chips.
*/
msp_write_dem(client, 0x22, msp_stereo_thresh);
} }
int msp34xxg_thread(void *data) int msp34xxg_thread(void *data)
{ {
struct i2c_client *client = data; struct i2c_client *client = data;
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
int val, std, i; int val, i;
v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
state->source = 1; /* default */
for (;;) { for (;;) {
v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
msp_sleep(state, -1); msp_sleep(state, -1);
@ -876,12 +942,14 @@ int msp34xxg_thread(void *data)
/* setup the chip*/ /* setup the chip*/
msp34xxg_reset(client); msp34xxg_reset(client);
std = msp_standard; state->std = state->radio ? 0x40 : msp_standard;
if (std != 0x01) if (state->std != 1)
goto unmute; goto unmute;
/* start autodetect */
msp_write_dem(client, 0x20, state->std);
/* watch autodetect */ /* watch autodetect */
v4l_dbg(1, msp_debug, client, "triggered autodetect, waiting for result\n"); v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n");
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
if (msp_sleep(state, 100)) if (msp_sleep(state, 100))
goto restart; goto restart;
@ -889,20 +957,19 @@ int msp34xxg_thread(void *data)
/* check results */ /* check results */
val = msp_read_dem(client, 0x7e); val = msp_read_dem(client, 0x7e);
if (val < 0x07ff) { if (val < 0x07ff) {
std = val; state->std = val;
break; break;
} }
v4l_dbg(2, msp_debug, client, "detection still in progress\n"); v4l_dbg(2, msp_debug, client, "detection still in progress\n");
} }
if (std == 1) { if (state->std == 1) {
v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n"); v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n");
continue; continue;
} }
unmute: unmute:
state->std = std; v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n",
v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n", msp_standard_std_name(state->std), state->std);
msp_standard_std_name(std), std);
/* unmute: dispatch sound to scart output, set scart volume */ /* unmute: dispatch sound to scart output, set scart volume */
msp_set_audio(client); msp_set_audio(client);
@ -911,20 +978,33 @@ int msp34xxg_thread(void *data)
if (msp_write_dsp(client, 0x13, state->acb)) if (msp_write_dsp(client, 0x13, state->acb))
return -1; return -1;
if (state->has_i2s_conf) /* the periodic stereo/SAP check is only relevant for
msp_write_dem(client, 0x40, state->i2s_mode); the 0x20 standard (BTSC) */
if (state->std != 0x20)
continue;
state->watch_stereo = 1;
/* monitor tv audio mode, the first time don't wait
in order to get a quick stereo/SAP update */
watch_stereo(client);
while (state->watch_stereo) {
watch_stereo(client);
if (msp_sleep(state, 5000))
goto restart;
}
} }
v4l_dbg(1, msp_debug, client, "thread: exit\n"); v4l_dbg(1, msp_debug, client, "thread: exit\n");
return 0; return 0;
} }
static void msp34xxg_detect_stereo(struct i2c_client *client) static int msp34xxg_detect_stereo(struct i2c_client *client)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
int status = msp_read_dem(client, 0x0200); int status = msp_read_dem(client, 0x0200);
int is_bilingual = status & 0x100; int is_bilingual = status & 0x100;
int is_stereo = status & 0x40; int is_stereo = status & 0x40;
int oldrx = state->rxsubchans;
state->rxsubchans = 0; state->rxsubchans = 0;
if (is_stereo) if (is_stereo)
@ -932,42 +1012,31 @@ static void msp34xxg_detect_stereo(struct i2c_client *client)
else else
state->rxsubchans = V4L2_TUNER_SUB_MONO; state->rxsubchans = V4L2_TUNER_SUB_MONO;
if (is_bilingual) { if (is_bilingual) {
state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; if (state->std == 0x20)
/* I'm supposed to check whether it's SAP or not state->rxsubchans |= V4L2_TUNER_SUB_SAP;
* and set only LANG2/SAP in this case. Yet, the MSP else
* does a lot of work to hide this and handle everything state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
* the same way. I don't want to work around it so unless
* this is a problem, I'll handle SAP just like lang1/lang2.
*/
} }
v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
status, is_stereo, is_bilingual, state->rxsubchans); status, is_stereo, is_bilingual, state->rxsubchans);
return (oldrx != state->rxsubchans);
} }
static void msp34xxg_set_audmode(struct i2c_client *client) static void msp34xxg_set_audmode(struct i2c_client *client)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
int source;
switch (state->audmode) { if (state->std == 0x20) {
case V4L2_TUNER_MODE_MONO: if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
source = 0; /* mono only */ (state->audmode == V4L2_TUNER_MODE_STEREO ||
break; state->audmode == V4L2_TUNER_MODE_LANG2)) {
case V4L2_TUNER_MODE_STEREO: msp_write_dem(client, 0x20, 0x21);
source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ } else {
/* problem: that could also mean 2 (scart input) */ msp_write_dem(client, 0x20, 0x20);
break; }
case V4L2_TUNER_MODE_LANG1:
source = 3; /* stereo or A */
break;
case V4L2_TUNER_MODE_LANG2:
source = 4; /* stereo or B */
break;
default:
source = 1;
break;
} }
msp34xxg_set_source(client, source);
msp34xxg_set_sources(client);
} }
void msp_set_audmode(struct i2c_client *client) void msp_set_audmode(struct i2c_client *client)
@ -977,7 +1046,6 @@ void msp_set_audmode(struct i2c_client *client)
switch (state->opmode) { switch (state->opmode) {
case OPMODE_MANUAL: case OPMODE_MANUAL:
case OPMODE_AUTODETECT: case OPMODE_AUTODETECT:
state->watch_stereo = 0;
msp3400c_set_audmode(client); msp3400c_set_audmode(client);
break; break;
case OPMODE_AUTOSELECT: case OPMODE_AUTOSELECT:
@ -986,18 +1054,17 @@ void msp_set_audmode(struct i2c_client *client)
} }
} }
void msp_detect_stereo(struct i2c_client *client) int msp_detect_stereo(struct i2c_client *client)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
switch (state->opmode) { switch (state->opmode) {
case OPMODE_MANUAL: case OPMODE_MANUAL:
case OPMODE_AUTODETECT: case OPMODE_AUTODETECT:
msp3400c_detect_stereo(client); return msp3400c_detect_stereo(client);
break;
case OPMODE_AUTOSELECT: case OPMODE_AUTOSELECT:
msp34xxg_detect_stereo(client); return msp34xxg_detect_stereo(client);
break;
} }
return 0;
} }

View file

@ -198,13 +198,13 @@ static int mxb_probe(struct saa7146_dev* dev)
/* loop through all i2c-devices on the bus and look who is there */ /* loop through all i2c-devices on the bus and look who is there */
list_for_each(item,&mxb->i2c_adapter.clients) { list_for_each(item,&mxb->i2c_adapter.clients) {
client = list_entry(item, struct i2c_client, list); client = list_entry(item, struct i2c_client, list);
if( I2C_TEA6420_1 == client->addr ) if( I2C_ADDR_TEA6420_1 == client->addr )
mxb->tea6420_1 = client; mxb->tea6420_1 = client;
if( I2C_TEA6420_2 == client->addr ) if( I2C_ADDR_TEA6420_2 == client->addr )
mxb->tea6420_2 = client; mxb->tea6420_2 = client;
if( I2C_TEA6415C_2 == client->addr ) if( I2C_TEA6415C_2 == client->addr )
mxb->tea6415c = client; mxb->tea6415c = client;
if( I2C_TDA9840 == client->addr ) if( I2C_ADDR_TDA9840 == client->addr )
mxb->tda9840 = client; mxb->tda9840 = client;
if( I2C_SAA7111 == client->addr ) if( I2C_SAA7111 == client->addr )
mxb->saa7111a = client; mxb->saa7111a = client;
@ -790,6 +790,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
break; break;
} }
case V4L2_TUNER_MODE_LANG1_LANG2: {
mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2;
byte = TDA9840_SET_BOTH;
DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"));
break;
}
case V4L2_TUNER_MODE_LANG1: { case V4L2_TUNER_MODE_LANG1: {
mxb->cur_mode = V4L2_TUNER_MODE_LANG1; mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
byte = TDA9840_SET_LANG1; byte = TDA9840_SET_LANG1;

View file

@ -15,7 +15,7 @@
* *
* Based on the Linux CPiA driver written by Peter Pregler, * Based on the Linux CPiA driver written by Peter Pregler,
* Scott J. Bertin and Johannes Erdfelt. * Scott J. Bertin and Johannes Erdfelt.
* *
* Please see the file: Documentation/usb/ov511.txt * Please see the file: Documentation/usb/ov511.txt
* and the website at: http://alpha.dyndns.org/ov511 * and the website at: http://alpha.dyndns.org/ov511
* for more info. * for more info.
@ -433,7 +433,7 @@ reg_w_mask(struct usb_ov511 *ov,
return (reg_w(ov, reg, newval)); return (reg_w(ov, reg, newval));
} }
/* /*
* Writes multiple (n) byte value to a single register. Only valid with certain * Writes multiple (n) byte value to a single register. Only valid with certain
* registers (0x30 and 0xc4 - 0xce). * registers (0x30 and 0xc4 - 0xce).
*/ */
@ -629,7 +629,7 @@ ov511_i2c_write_internal(struct usb_ov511 *ov,
/* Retry until idle */ /* Retry until idle */
do do
rc = reg_r(ov, R511_I2C_CTL); rc = reg_r(ov, R511_I2C_CTL);
while (rc > 0 && ((rc&1) == 0)); while (rc > 0 && ((rc&1) == 0));
if (rc < 0) if (rc < 0)
break; break;
@ -1752,7 +1752,7 @@ sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
ov->whiteness = p->whiteness; ov->whiteness = p->whiteness;
/* Don't return error if a setting is unsupported, or rest of settings /* Don't return error if a setting is unsupported, or rest of settings
* will not be performed */ * will not be performed */
rc = sensor_set_contrast(ov, p->contrast); rc = sensor_set_contrast(ov, p->contrast);
if (FATAL_ERROR(rc)) if (FATAL_ERROR(rc))
@ -1781,7 +1781,7 @@ sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
PDEBUG(4, "sensor_get_picture"); PDEBUG(4, "sensor_get_picture");
/* Don't return error if a setting is unsupported, or rest of settings /* Don't return error if a setting is unsupported, or rest of settings
* will not be performed */ * will not be performed */
rc = sensor_get_contrast(ov, &(p->contrast)); rc = sensor_get_contrast(ov, &(p->contrast));
if (FATAL_ERROR(rc)) if (FATAL_ERROR(rc))
@ -2251,7 +2251,7 @@ mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
/******** Clock programming ********/ /******** Clock programming ********/
/* The OV6620 needs special handling. This prevents the /* The OV6620 needs special handling. This prevents the
* severe banding that normally occurs */ * severe banding that normally occurs */
if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630)
{ {
@ -2326,7 +2326,7 @@ set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,
int sub_flag) int sub_flag)
{ {
int ret; int ret;
int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize;
int hoffset, voffset, hwscale = 0, vwscale = 0; int hoffset, voffset, hwscale = 0, vwscale = 0;
/* The different sensor ICs handle setting up of window differently. /* The different sensor ICs handle setting up of window differently.
@ -2575,7 +2575,7 @@ ov518_mode_init_regs(struct usb_ov511 *ov,
/* OV518 needs U and V swapped */ /* OV518 needs U and V swapped */
i2c_w_mask(ov, 0x15, 0x00, 0x01); i2c_w_mask(ov, 0x15, 0x00, 0x01);
if (mode == VIDEO_PALETTE_GREY) { if (mode == VIDEO_PALETTE_GREY) {
/* Set 16-bit input format (UV data are ignored) */ /* Set 16-bit input format (UV data are ignored) */
reg_w_mask(ov, 0x20, 0x00, 0x08); reg_w_mask(ov, 0x20, 0x00, 0x08);
@ -2894,7 +2894,7 @@ make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
* ... ... ... * ... ... ...
* 56 57 ... 63 120 121 ... 127 248 249 ... 255 * 56 57 ... 63 120 121 ... 127 248 249 ... 255
* *
*/ */
static void static void
yuv400raw_to_yuv400p(struct ov511_frame *frame, yuv400raw_to_yuv400p(struct ov511_frame *frame,
unsigned char *pIn0, unsigned char *pOut0) unsigned char *pIn0, unsigned char *pOut0)
@ -2923,7 +2923,7 @@ yuv400raw_to_yuv400p(struct ov511_frame *frame,
* *
* 0 1 ... 7 * 0 1 ... 7
* 8 9 ... 15 * 8 9 ... 15
* ... * ...
* 56 57 ... 63 * 56 57 ... 63
* *
* U and V are shipped at half resolution (1 U,V sample -> one 2x2 block). * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
@ -3034,7 +3034,7 @@ decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
*/ */
static void static void
deinterlace(struct ov511_frame *frame, int rawformat, deinterlace(struct ov511_frame *frame, int rawformat,
unsigned char *pIn0, unsigned char *pOut0) unsigned char *pIn0, unsigned char *pOut0)
{ {
const int fieldheight = frame->rawheight / 2; const int fieldheight = frame->rawheight / 2;
const int fieldpix = fieldheight * frame->rawwidth; const int fieldpix = fieldheight * frame->rawwidth;
@ -3112,7 +3112,7 @@ ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame)
frame->tempdata); frame->tempdata);
deinterlace(frame, RAWFMT_YUV400, frame->tempdata, deinterlace(frame, RAWFMT_YUV400, frame->tempdata,
frame->data); frame->data);
} else { } else {
if (frame->compressed) if (frame->compressed)
decompress(ov, frame, frame->rawdata, decompress(ov, frame, frame->rawdata,
@ -3136,7 +3136,7 @@ ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame)
frame->tempdata); frame->tempdata);
deinterlace(frame, RAWFMT_YUV420, frame->tempdata, deinterlace(frame, RAWFMT_YUV420, frame->tempdata,
frame->data); frame->data);
} else { } else {
if (frame->compressed) if (frame->compressed)
decompress(ov, frame, frame->rawdata, frame->data); decompress(ov, frame, frame->rawdata, frame->data);
@ -3226,7 +3226,7 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
frame->rawwidth = ((int)(in[9]) + 1) * 8; frame->rawwidth = ((int)(in[9]) + 1) * 8;
frame->rawheight = ((int)(in[10]) + 1) * 8; frame->rawheight = ((int)(in[10]) + 1) * 8;
PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d", PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d",
ov->curframe, pnum, frame->rawwidth, frame->rawheight, ov->curframe, pnum, frame->rawwidth, frame->rawheight,
frame->bytes_recvd); frame->bytes_recvd);
@ -3527,10 +3527,10 @@ ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs)
return; return;
} }
if (urb->status == -ENOENT || urb->status == -ECONNRESET) { if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
PDEBUG(4, "URB unlinked"); PDEBUG(4, "URB unlinked");
return; return;
} }
if (urb->status != -EINPROGRESS && urb->status != 0) { if (urb->status != -EINPROGRESS && urb->status != 0) {
err("ERROR: urb->status=%d: %s", urb->status, err("ERROR: urb->status=%d: %s", urb->status,
@ -4627,8 +4627,8 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
if (size > (((OV511_NUMFRAMES if (size > (((OV511_NUMFRAMES
* MAX_DATA_SIZE(ov->maxwidth, ov->maxheight) * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)
+ PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
return -EINVAL; return -EINVAL;
if (mutex_lock_interruptible(&ov->lock)) if (mutex_lock_interruptible(&ov->lock))
@ -5062,7 +5062,7 @@ ov6xx0_configure(struct usb_ov511 *ov)
} }
/* This initializes the KS0127 and KS0127B video decoders. */ /* This initializes the KS0127 and KS0127B video decoders. */
static int static int
ks0127_configure(struct usb_ov511 *ov) ks0127_configure(struct usb_ov511 *ov)
{ {
int rc; int rc;
@ -5193,7 +5193,7 @@ saa7111a_configure(struct usb_ov511 *ov)
return -1; return -1;
/* Detect version of decoder. This must be done after writing the /* Detect version of decoder. This must be done after writing the
* initial regs or the decoder will lock up. */ * initial regs or the decoder will lock up. */
rc = i2c_r(ov, 0x00); rc = i2c_r(ov, 0x00);
if (rc < 0) { if (rc < 0) {
@ -5216,13 +5216,13 @@ saa7111a_configure(struct usb_ov511 *ov)
} }
/* This initializes the OV511/OV511+ and the sensor */ /* This initializes the OV511/OV511+ and the sensor */
static int static int
ov511_configure(struct usb_ov511 *ov) ov511_configure(struct usb_ov511 *ov)
{ {
static struct ov511_regvals aRegvalsInit511[] = { static struct ov511_regvals aRegvalsInit511[] = {
{ OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, { OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
{ OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
{ OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, { OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
{ OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
{ OV511_REG_BUS, R51x_SYS_RESET, 0x3f }, { OV511_REG_BUS, R51x_SYS_RESET, 0x3f },
{ OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
@ -5269,7 +5269,7 @@ ov511_configure(struct usb_ov511 *ov)
err("Please notify " EMAIL " of the name,"); err("Please notify " EMAIL " of the name,");
err("manufacturer, model, and this number of your camera."); err("manufacturer, model, and this number of your camera.");
err("Also include the output of the detection process."); err("Also include the output of the detection process.");
} }
if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */ if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */
ov->pal = 1; ov->pal = 1;
@ -5336,17 +5336,17 @@ ov511_configure(struct usb_ov511 *ov)
if (i2c_w(ov, 0x10, 0x00) < 0) { if (i2c_w(ov, 0x10, 0x00) < 0) {
err("Can't determine sensor slave IDs"); err("Can't determine sensor slave IDs");
goto error; goto error;
} else { } else {
if (ks0127_configure(ov) < 0) { if (ks0127_configure(ov) < 0) {
err("Failed to configure KS0127"); err("Failed to configure KS0127");
goto error; goto error;
} }
} }
} else { } else {
if (saa7111a_configure(ov) < 0) { if (saa7111a_configure(ov) < 0) {
err("Failed to configure SAA7111A"); err("Failed to configure SAA7111A");
goto error; goto error;
} }
} }
} else { } else {
@ -5356,13 +5356,13 @@ ov511_configure(struct usb_ov511 *ov)
} else { } else {
if (ov6xx0_configure(ov) < 0) { if (ov6xx0_configure(ov) < 0) {
err("Failed to configure OV6xx0"); err("Failed to configure OV6xx0");
goto error; goto error;
} }
} }
} else { } else {
if (ov7xx0_configure(ov) < 0) { if (ov7xx0_configure(ov) < 0) {
err("Failed to configure OV7xx0"); err("Failed to configure OV7xx0");
goto error; goto error;
} }
} }
@ -5381,12 +5381,12 @@ ov518_configure(struct usb_ov511 *ov)
/* For 518 and 518+ */ /* For 518 and 518+ */
static struct ov511_regvals aRegvalsInit518[] = { static struct ov511_regvals aRegvalsInit518[] = {
{ OV511_REG_BUS, R51x_SYS_RESET, 0x40 }, { OV511_REG_BUS, R51x_SYS_RESET, 0x40 },
{ OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
{ OV511_REG_BUS, R51x_SYS_RESET, 0x3e }, { OV511_REG_BUS, R51x_SYS_RESET, 0x3e },
{ OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
{ OV511_REG_BUS, R51x_SYS_RESET, 0x00 }, { OV511_REG_BUS, R51x_SYS_RESET, 0x00 },
{ OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
{ OV511_REG_BUS, 0x46, 0x00 }, { OV511_REG_BUS, 0x46, 0x00 },
{ OV511_REG_BUS, 0x5d, 0x03 }, { OV511_REG_BUS, 0x5d, 0x03 },
{ OV511_DONE_BUS, 0x0, 0x00}, { OV511_DONE_BUS, 0x0, 0x00},
}; };
@ -5517,7 +5517,7 @@ ov518_configure(struct usb_ov511 *ov)
if (init_ov_sensor(ov) < 0) { if (init_ov_sensor(ov) < 0) {
err("Can't determine sensor slave IDs"); err("Can't determine sensor slave IDs");
goto error; goto error;
} else { } else {
err("Detected unsupported OV8xx0 sensor"); err("Detected unsupported OV8xx0 sensor");
goto error; goto error;
@ -5525,13 +5525,13 @@ ov518_configure(struct usb_ov511 *ov)
} else { } else {
if (ov6xx0_configure(ov) < 0) { if (ov6xx0_configure(ov) < 0) {
err("Failed to configure OV6xx0"); err("Failed to configure OV6xx0");
goto error; goto error;
} }
} }
} else { } else {
if (ov7xx0_configure(ov) < 0) { if (ov7xx0_configure(ov) < 0) {
err("Failed to configure OV7xx0"); err("Failed to configure OV7xx0");
goto error; goto error;
} }
} }
@ -5564,28 +5564,28 @@ static ssize_t show_custom_id(struct class_device *cd, char *buf)
{ {
struct usb_ov511 *ov = cd_to_ov(cd); struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%d\n", ov->customid); return sprintf(buf, "%d\n", ov->customid);
} }
static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL);
static ssize_t show_model(struct class_device *cd, char *buf) static ssize_t show_model(struct class_device *cd, char *buf)
{ {
struct usb_ov511 *ov = cd_to_ov(cd); struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", ov->desc); return sprintf(buf, "%s\n", ov->desc);
} }
static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
static ssize_t show_bridge(struct class_device *cd, char *buf) static ssize_t show_bridge(struct class_device *cd, char *buf)
{ {
struct usb_ov511 *ov = cd_to_ov(cd); struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge));
} }
static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL);
static ssize_t show_sensor(struct class_device *cd, char *buf) static ssize_t show_sensor(struct class_device *cd, char *buf)
{ {
struct usb_ov511 *ov = cd_to_ov(cd); struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor));
} }
static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL);
static ssize_t show_brightness(struct class_device *cd, char *buf) static ssize_t show_brightness(struct class_device *cd, char *buf)
@ -5597,7 +5597,7 @@ static ssize_t show_brightness(struct class_device *cd, char *buf)
return -ENODEV; return -ENODEV;
sensor_get_brightness(ov, &x); sensor_get_brightness(ov, &x);
return sprintf(buf, "%d\n", x >> 8); return sprintf(buf, "%d\n", x >> 8);
} }
static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
static ssize_t show_saturation(struct class_device *cd, char *buf) static ssize_t show_saturation(struct class_device *cd, char *buf)
@ -5609,7 +5609,7 @@ static ssize_t show_saturation(struct class_device *cd, char *buf)
return -ENODEV; return -ENODEV;
sensor_get_saturation(ov, &x); sensor_get_saturation(ov, &x);
return sprintf(buf, "%d\n", x >> 8); return sprintf(buf, "%d\n", x >> 8);
} }
static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
static ssize_t show_contrast(struct class_device *cd, char *buf) static ssize_t show_contrast(struct class_device *cd, char *buf)
@ -5621,7 +5621,7 @@ static ssize_t show_contrast(struct class_device *cd, char *buf)
return -ENODEV; return -ENODEV;
sensor_get_contrast(ov, &x); sensor_get_contrast(ov, &x);
return sprintf(buf, "%d\n", x >> 8); return sprintf(buf, "%d\n", x >> 8);
} }
static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
static ssize_t show_hue(struct class_device *cd, char *buf) static ssize_t show_hue(struct class_device *cd, char *buf)
@ -5633,7 +5633,7 @@ static ssize_t show_hue(struct class_device *cd, char *buf)
return -ENODEV; return -ENODEV;
sensor_get_hue(ov, &x); sensor_get_hue(ov, &x);
return sprintf(buf, "%d\n", x >> 8); return sprintf(buf, "%d\n", x >> 8);
} }
static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
static ssize_t show_exposure(struct class_device *cd, char *buf) static ssize_t show_exposure(struct class_device *cd, char *buf)
@ -5645,7 +5645,7 @@ static ssize_t show_exposure(struct class_device *cd, char *buf)
return -ENODEV; return -ENODEV;
sensor_get_exposure(ov, &exp); sensor_get_exposure(ov, &exp);
return sprintf(buf, "%d\n", exp >> 8); return sprintf(buf, "%d\n", exp >> 8);
} }
static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
static void ov_create_sysfs(struct video_device *vdev) static void ov_create_sysfs(struct video_device *vdev)

View file

@ -130,7 +130,7 @@
#define R511_COMP_QVY 0x76 #define R511_COMP_QVY 0x76
#define R511_COMP_QVUV 0x77 #define R511_COMP_QVUV 0x77
#define R511_COMP_EN 0x78 #define R511_COMP_EN 0x78
#define R511_COMP_LUT_EN 0x79 #define R511_COMP_LUT_EN 0x79
#define R511_COMP_LUT_BEGIN 0x80 #define R511_COMP_LUT_BEGIN 0x80
/* --------------------------------- */ /* --------------------------------- */
@ -459,14 +459,14 @@ struct usb_ov511 {
int subh; /* Pix Array subcapture height */ int subh; /* Pix Array subcapture height */
int curframe; /* Current receiving sbuf */ int curframe; /* Current receiving sbuf */
struct ov511_frame frame[OV511_NUMFRAMES]; struct ov511_frame frame[OV511_NUMFRAMES];
struct ov511_sbuf sbuf[OV511_NUMSBUF]; struct ov511_sbuf sbuf[OV511_NUMSBUF];
wait_queue_head_t wq; /* Processes waiting */ wait_queue_head_t wq; /* Processes waiting */
int snap_enabled; /* Snapshot mode enabled */ int snap_enabled; /* Snapshot mode enabled */
int bridge; /* Type of bridge (BRG_*) */ int bridge; /* Type of bridge (BRG_*) */
int bclass; /* Class of bridge (BCL_*) */ int bclass; /* Class of bridge (BCL_*) */
int sensor; /* Type of image sensor chip (SEN_*) */ int sensor; /* Type of image sensor chip (SEN_*) */
@ -512,7 +512,7 @@ struct symbolic_list {
/* Returns the name of the matching element in the symbolic_list array. The /* Returns the name of the matching element in the symbolic_list array. The
* end of the list must be marked with an element that has a NULL name. * end of the list must be marked with an element that has a NULL name.
*/ */
static inline char * static inline char *
symbolic(struct symbolic_list list[], int num) symbolic(struct symbolic_list list[], int num)
{ {
int i; int i;

View file

@ -1,4 +1,4 @@
ovcamchip-objs := ovcamchip_core.o ov6x20.o ov6x30.o ov7x10.o ov7x20.o \ ovcamchip-objs := ovcamchip_core.o ov6x20.o ov6x30.o ov7x10.o ov7x20.o \
ov76be.o ov76be.o
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip.o

View file

@ -266,17 +266,17 @@ static int ovcamchip_detect(struct i2c_client *c)
PDEBUG(3, "Testing for 0V6xx0"); PDEBUG(3, "Testing for 0V6xx0");
c->addr = OV6xx0_SID; c->addr = OV6xx0_SID;
if (init_camchip(c) < 0) { if (init_camchip(c) < 0) {
return -ENODEV; return -ENODEV;
} else { } else {
if (ov6xx0_detect(c) < 0) { if (ov6xx0_detect(c) < 0) {
PERROR("Failed to init OV6xx0"); PERROR("Failed to init OV6xx0");
return -EIO; return -EIO;
} }
} }
} else { } else {
if (ov7xx0_detect(c) < 0) { if (ov7xx0_detect(c) < 0) {
PERROR("Failed to init OV7xx0"); PERROR("Failed to init OV7xx0");
return -EIO; return -EIO;
} }
} }

View file

@ -82,6 +82,6 @@ extern int ov_write_regvals(struct i2c_client *c,
struct ovcamchip_regvals *rvals); struct ovcamchip_regvals *rvals);
extern int ov_write_mask(struct i2c_client *c, unsigned char reg, extern int ov_write_mask(struct i2c_client *c, unsigned char reg,
unsigned char value, unsigned char mask); unsigned char value, unsigned char mask);
#endif #endif

View file

@ -1,4 +1,4 @@
/* /*
planb - PlanB frame grabber driver planb - PlanB frame grabber driver
PlanB is used in the 7x00/8x00 series of PowerMacintosh PlanB is used in the 7x00/8x00 series of PowerMacintosh
@ -584,7 +584,7 @@ static void resume_overlay(struct planb *pb)
wake_up_interruptible(&pb->suspendq); wake_up_interruptible(&pb->suspendq);
} }
static void add_clip(struct planb *pb, struct video_clip *clip) static void add_clip(struct planb *pb, struct video_clip *clip)
{ {
volatile unsigned char *base; volatile unsigned char *base;
int xc = clip->x, yc = clip->y; int xc = clip->x, yc = clip->y;
@ -758,7 +758,7 @@ static void cmd_buff(struct planb *pb)
PLANB_SET(CH_SYNC)); PLANB_SET(CH_SYNC));
tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
PLANB_SET(DMA_ABORT)); PLANB_SET(DMA_ABORT));
/* odd field data: */ /* odd field data: */
jump = virt_to_bus(c1 + nlines / 2); jump = virt_to_bus(c1 + nlines / 2);
for (i=1; i < nlines; i += stepsize, c1++) for (i=1; i < nlines; i += stepsize, c1++)
@ -1247,7 +1247,7 @@ static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb)
tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++; tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
PLANB_SET(DMA_ABORT)); PLANB_SET(DMA_ABORT));
/* odd field data: */ /* odd field data: */
jump_addr = c1 + TAB_FACTOR * nlines / 2; jump_addr = c1 + TAB_FACTOR * nlines / 2;
jump = virt_to_bus(jump_addr); jump = virt_to_bus(jump_addr);
@ -1383,7 +1383,7 @@ static int planb_open(struct video_device *dev, int mode)
pb->user++; pb->user++;
DEBUG("PlanB: device opened\n"); DEBUG("PlanB: device opened\n");
return 0; return 0;
} }
static void planb_close(struct video_device *dev) static void planb_close(struct video_device *dev)
@ -1424,9 +1424,9 @@ static long planb_write(struct video_device *v, const char *buf,
static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{ {
struct planb *pb=(struct planb *)dev; struct planb *pb=(struct planb *)dev;
switch (cmd) switch (cmd)
{ {
case VIDIOCGCAP: case VIDIOCGCAP:
{ {
struct video_capability b; struct video_capability b;
@ -1440,26 +1440,26 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
b.channels = 2; /* composite & svhs */ b.channels = 2; /* composite & svhs */
b.audios = 0; b.audios = 0;
b.maxwidth = PLANB_MAXPIXELS; b.maxwidth = PLANB_MAXPIXELS;
b.maxheight = PLANB_MAXLINES; b.maxheight = PLANB_MAXLINES;
b.minwidth = 32; /* wild guess */ b.minwidth = 32; /* wild guess */
b.minheight = 32; b.minheight = 32;
if (copy_to_user(arg,&b,sizeof(b))) if (copy_to_user(arg,&b,sizeof(b)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case VIDIOCSFBUF: case VIDIOCSFBUF:
{ {
struct video_buffer v; struct video_buffer v;
unsigned short bpp; unsigned short bpp;
unsigned int fmt; unsigned int fmt;
DEBUG("PlanB: IOCTL VIDIOCSFBUF\n"); DEBUG("PlanB: IOCTL VIDIOCSFBUF\n");
if (!capable(CAP_SYS_ADMIN) if (!capable(CAP_SYS_ADMIN)
|| !capable(CAP_SYS_RAWIO)) || !capable(CAP_SYS_RAWIO))
return -EPERM; return -EPERM;
if (copy_from_user(&v, arg,sizeof(v))) if (copy_from_user(&v, arg,sizeof(v)))
return -EFAULT; return -EFAULT;
planb_lock(pb); planb_lock(pb);
switch(v.depth) { switch(v.depth) {
case 8: case 8:
@ -1478,7 +1478,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
break; break;
default: default:
planb_unlock(pb); planb_unlock(pb);
return -EINVAL; return -EINVAL;
} }
if (bpp * v.width > v.bytesperline) { if (bpp * v.width > v.bytesperline) {
planb_unlock(pb); planb_unlock(pb);
@ -1493,7 +1493,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
pb->win.bpl = pb->win.bpp * pb->win.swidth; pb->win.bpl = pb->win.bpp * pb->win.swidth;
pb->win.pad = v.bytesperline - pb->win.bpl; pb->win.pad = v.bytesperline - pb->win.bpl;
DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d," DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
" bpl %d (+ %d)\n", v.base, v.width,v.height, " bpl %d (+ %d)\n", v.base, v.width,v.height,
pb->win.bpp, pb->win.bpl, pb->win.pad); pb->win.bpp, pb->win.bpl, pb->win.pad);
@ -1504,11 +1504,11 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
resume_overlay(pb); resume_overlay(pb);
} }
planb_unlock(pb); planb_unlock(pb);
return 0; return 0;
} }
case VIDIOCGFBUF: case VIDIOCGFBUF:
{ {
struct video_buffer v; struct video_buffer v;
DEBUG("PlanB: IOCTL VIDIOCGFBUF\n"); DEBUG("PlanB: IOCTL VIDIOCGFBUF\n");
@ -1518,15 +1518,15 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.depth = pb->win.depth; v.depth = pb->win.depth;
v.bytesperline = pb->win.bpl + pb->win.pad; v.bytesperline = pb->win.bpl + pb->win.pad;
if (copy_to_user(arg, &v, sizeof(v))) if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case VIDIOCCAPTURE: case VIDIOCCAPTURE:
{ {
int i; int i;
if(copy_from_user(&i, arg, sizeof(i))) if(copy_from_user(&i, arg, sizeof(i)))
return -EFAULT; return -EFAULT;
if(i==0) { if(i==0) {
DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n"); DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
@ -1695,7 +1695,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
struct video_window vw; struct video_window vw;
struct video_clip clip; struct video_clip clip;
int i; int i;
DEBUG("PlanB: IOCTL VIDIOCSWIN\n"); DEBUG("PlanB: IOCTL VIDIOCSWIN\n");
if(copy_from_user(&vw,arg,sizeof(vw))) if(copy_from_user(&vw,arg,sizeof(vw)))
@ -1749,7 +1749,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case VIDIOCSYNC: { case VIDIOCSYNC: {
int i; int i;
IDEBUG("PlanB: IOCTL VIDIOCSYNC\n"); IDEBUG("PlanB: IOCTL VIDIOCSYNC\n");
@ -1759,42 +1759,42 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
IDEBUG("PlanB: sync to frame %d\n", i); IDEBUG("PlanB: sync to frame %d\n", i);
if(i > (MAX_GBUFFERS - 1) || i < 0) if(i > (MAX_GBUFFERS - 1) || i < 0)
return -EINVAL; return -EINVAL;
chk_grab: chk_grab:
switch (pb->frame_stat[i]) { switch (pb->frame_stat[i]) {
case GBUFFER_UNUSED: case GBUFFER_UNUSED:
return -EINVAL; return -EINVAL;
case GBUFFER_GRABBING: case GBUFFER_GRABBING:
IDEBUG("PlanB: waiting for grab" IDEBUG("PlanB: waiting for grab"
" done (%d)\n", i); " done (%d)\n", i);
interruptible_sleep_on(&pb->capq); interruptible_sleep_on(&pb->capq);
if(signal_pending(current)) if(signal_pending(current))
return -EINTR; return -EINTR;
goto chk_grab; goto chk_grab;
case GBUFFER_DONE: case GBUFFER_DONE:
pb->frame_stat[i] = GBUFFER_UNUSED; pb->frame_stat[i] = GBUFFER_UNUSED;
break; break;
} }
return 0; return 0;
} }
case VIDIOCMCAPTURE: case VIDIOCMCAPTURE:
{ {
struct video_mmap vm; struct video_mmap vm;
volatile unsigned int status; volatile unsigned int status;
IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n"); IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n");
if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm))) if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
return -EFAULT; return -EFAULT;
status = pb->frame_stat[vm.frame]; status = pb->frame_stat[vm.frame];
if (status != GBUFFER_UNUSED) if (status != GBUFFER_UNUSED)
return -EBUSY; return -EBUSY;
return vgrab(pb, &vm); return vgrab(pb, &vm);
} }
case VIDIOCGMBUF: case VIDIOCGMBUF:
{ {
int i; int i;
@ -1811,7 +1811,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case PLANBIOCGSAAREGS: case PLANBIOCGSAAREGS:
{ {
struct planb_saa_regs preg; struct planb_saa_regs preg;
@ -1828,7 +1828,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case PLANBIOCSSAAREGS: case PLANBIOCSSAAREGS:
{ {
struct planb_saa_regs preg; struct planb_saa_regs preg;
@ -1842,7 +1842,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
saa_set (preg.addr, preg.val, pb); saa_set (preg.addr, preg.val, pb);
return 0; return 0;
} }
case PLANBIOCGSTAT: case PLANBIOCGSTAT:
{ {
struct planb_stat_regs pstat; struct planb_stat_regs pstat;
@ -1859,7 +1859,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case PLANBIOCSMODE: { case PLANBIOCSMODE: {
int v; int v;
@ -1985,10 +1985,10 @@ static int planb_mmap(struct vm_area_struct *vma, struct video_device *dev, cons
{ {
int i; int i;
struct planb *pb = (struct planb *)dev; struct planb *pb = (struct planb *)dev;
unsigned long start = (unsigned long)adr; unsigned long start = (unsigned long)adr;
if (size > MAX_GBUFFERS * PLANB_MAX_FBUF) if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)
return -EINVAL; return -EINVAL;
if (!pb->rawbuf) { if (!pb->rawbuf) {
int err; int err;
if((err=grabbuf_alloc(pb))) if((err=grabbuf_alloc(pb)))
@ -2091,10 +2091,10 @@ static int init_planb(struct planb *pb)
/* clear interrupt mask */ /* clear interrupt mask */
pb->intr_mask = PLANB_CLR_IRQ; pb->intr_mask = PLANB_CLR_IRQ;
result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb); result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
if (result < 0) { if (result < 0) {
if (result==-EINVAL) if (result==-EINVAL)
printk(KERN_ERR "PlanB: Bad irq number (%d) " printk(KERN_ERR "PlanB: Bad irq number (%d) "
"or handler\n", (int)pb->irq); "or handler\n", (int)pb->irq);
else if (result==-EBUSY) else if (result==-EBUSY)
printk(KERN_ERR "PlanB: I don't know why, " printk(KERN_ERR "PlanB: I don't know why, "
@ -2102,7 +2102,7 @@ static int init_planb(struct planb *pb)
return result; return result;
} }
disable_irq(pb->irq); disable_irq(pb->irq);
/* Now add the template and register the device unit. */ /* Now add the template and register the device unit. */
memcpy(&pb->video_dev,&planb_template,sizeof(planb_template)); memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));
@ -2143,7 +2143,7 @@ static int init_planb(struct planb *pb)
} }
/* /*
* Scan for a PlanB controller, request the irq and map the io memory * Scan for a PlanB controller, request the irq and map the io memory
*/ */
static int find_planb(void) static int find_planb(void)
@ -2171,9 +2171,9 @@ static int find_planb(void)
pb = &planbs[0]; pb = &planbs[0];
planb_num = 1; planb_num = 1;
if (planb_devices->n_addrs != 1) { if (planb_devices->n_addrs != 1) {
printk (KERN_WARNING "PlanB: expecting 1 address for planb " printk (KERN_WARNING "PlanB: expecting 1 address for planb "
"(got %d)", planb_devices->n_addrs); "(got %d)", planb_devices->n_addrs);
return 0; return 0;
} }
@ -2236,7 +2236,7 @@ static int find_planb(void)
pb->planb_base = planb_regs; pb->planb_base = planb_regs;
pb->planb_base_phys = (struct planb_registers *)new_base; pb->planb_base_phys = (struct planb_registers *)new_base;
pb->irq = irq; pb->irq = irq;
return planb_num; return planb_num;
err_out_disable: err_out_disable:
@ -2251,7 +2251,7 @@ static void release_planb(void)
int i; int i;
struct planb *pb; struct planb *pb;
for (i=0;i<planb_num; i++) for (i=0;i<planb_num; i++)
{ {
pb=&planbs[i]; pb=&planbs[i];
@ -2278,7 +2278,7 @@ static void release_planb(void)
static int __init init_planbs(void) static int __init init_planbs(void)
{ {
int i; int i;
if (find_planb()<=0) if (find_planb()<=0)
return -EIO; return -EIO;
@ -2288,9 +2288,9 @@ static int __init init_planbs(void)
" with v4l\n", i); " with v4l\n", i);
release_planb(); release_planb();
return -EIO; return -EIO;
} }
printk(KERN_INFO "PlanB: registered device %d with v4l\n", i); printk(KERN_INFO "PlanB: registered device %d with v4l\n", i);
} }
return 0; return 0;
} }

View file

@ -1,4 +1,4 @@
/* /*
planb - PlanB frame grabber driver planb - PlanB frame grabber driver
PlanB is used in the 7x00/8x00 series of PowerMacintosh PlanB is used in the 7x00/8x00 series of PowerMacintosh
@ -167,7 +167,7 @@ struct planb {
struct video_device video_dev; struct video_device video_dev;
struct video_picture picture; /* Current picture params */ struct video_picture picture; /* Current picture params */
struct video_audio audio_dev; /* Current audio params */ struct video_audio audio_dev; /* Current audio params */
volatile struct planb_registers *planb_base; /* virt base of planb */ volatile struct planb_registers *planb_base; /* virt base of planb */
struct planb_registers *planb_base_phys; /* phys base of planb */ struct planb_registers *planb_base_phys; /* phys base of planb */
void *priv_space; /* Org. alloc. mem for kfree */ void *priv_space; /* Org. alloc. mem for kfree */
@ -209,7 +209,7 @@ struct planb {
int gwidth[MAX_GBUFFERS], gheight[MAX_GBUFFERS]; int gwidth[MAX_GBUFFERS], gheight[MAX_GBUFFERS];
unsigned int gfmt[MAX_GBUFFERS]; unsigned int gfmt[MAX_GBUFFERS];
int gnorm_switch[MAX_GBUFFERS]; int gnorm_switch[MAX_GBUFFERS];
volatile unsigned int *frame_stat; volatile unsigned int *frame_stat;
#define GBUFFER_UNUSED 0x00U #define GBUFFER_UNUSED 0x00U
#define GBUFFER_GRABBING 0x01U #define GBUFFER_GRABBING 0x01U
#define GBUFFER_DONE 0x02U #define GBUFFER_DONE 0x02U

View file

@ -12,10 +12,10 @@
* Most of this code is directly derived from his userspace driver. * Most of this code is directly derived from his userspace driver.
* His driver works so send any reports to alan@redhat.com unless the * His driver works so send any reports to alan@redhat.com unless the
* userspace driver also doesn't work for you... * userspace driver also doesn't work for you...
* *
* Changes: * Changes:
* 08/07/2003 Daniele Bellucci <bellucda@tiscali.it> * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
* - pms_capture: report back -EFAULT * - pms_capture: report back -EFAULT
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -66,14 +66,14 @@ static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
/* /*
* I/O ports and Shared Memory * I/O ports and Shared Memory
*/ */
static int io_port = 0x250; static int io_port = 0x250;
static int data_port = 0x251; static int data_port = 0x251;
static int mem_base = 0xC8000; static int mem_base = 0xC8000;
static void __iomem *mem; static void __iomem *mem;
static int video_nr = -1; static int video_nr = -1;
static inline void mvv_write(u8 index, u8 value) static inline void mvv_write(u8 index, u8 value)
{ {
@ -90,9 +90,9 @@ static int pms_i2c_stat(u8 slave)
{ {
int counter; int counter;
int i; int i;
outb(0x28, io_port); outb(0x28, io_port);
counter=0; counter=0;
while((inb(data_port)&0x01)==0) while((inb(data_port)&0x01)==0)
if(counter++==256) if(counter++==256)
@ -101,9 +101,9 @@ static int pms_i2c_stat(u8 slave)
while((inb(data_port)&0x01)!=0) while((inb(data_port)&0x01)!=0)
if(counter++==256) if(counter++==256)
break; break;
outb(slave, io_port); outb(slave, io_port);
counter=0; counter=0;
while((inb(data_port)&0x01)==0) while((inb(data_port)&0x01)==0)
if(counter++==256) if(counter++==256)
@ -112,7 +112,7 @@ static int pms_i2c_stat(u8 slave)
while((inb(data_port)&0x01)!=0) while((inb(data_port)&0x01)!=0)
if(counter++==256) if(counter++==256)
break; break;
for(i=0;i<12;i++) for(i=0;i<12;i++)
{ {
char st=inb(data_port); char st=inb(data_port);
@ -122,7 +122,7 @@ static int pms_i2c_stat(u8 slave)
break; break;
} }
outb(0x29, io_port); outb(0x29, io_port);
return inb(data_port); return inb(data_port);
} }
static int pms_i2c_write(u16 slave, u16 sub, u16 data) static int pms_i2c_write(u16 slave, u16 sub, u16 data)
@ -130,19 +130,19 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data)
int skip=0; int skip=0;
int count; int count;
int i; int i;
for(i=0;i<i2c_count;i++) for(i=0;i<i2c_count;i++)
{ {
if((i2cinfo[i].slave==slave) && if((i2cinfo[i].slave==slave) &&
(i2cinfo[i].sub == sub)) (i2cinfo[i].sub == sub))
{ {
if(i2cinfo[i].data==data) if(i2cinfo[i].data==data)
skip=1; skip=1;
i2cinfo[i].data=data; i2cinfo[i].data=data;
i=i2c_count+1; i=i2c_count+1;
} }
} }
if(i==i2c_count && i2c_count<64) if(i==i2c_count && i2c_count<64)
{ {
i2cinfo[i2c_count].slave=slave; i2cinfo[i2c_count].slave=slave;
@ -150,16 +150,16 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data)
i2cinfo[i2c_count].data=data; i2cinfo[i2c_count].data=data;
i2c_count++; i2c_count++;
} }
if(skip) if(skip)
return 0; return 0;
mvv_write(0x29, sub); mvv_write(0x29, sub);
mvv_write(0x2A, data); mvv_write(0x2A, data);
mvv_write(0x28, slave); mvv_write(0x28, slave);
outb(0x28, io_port); outb(0x28, io_port);
count=0; count=0;
while((inb(data_port)&1)==0) while((inb(data_port)&1)==0)
if(count>255) if(count>255)
@ -167,9 +167,9 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data)
while((inb(data_port)&1)!=0) while((inb(data_port)&1)!=0)
if(count>255) if(count>255)
break; break;
count=inb(data_port); count=inb(data_port);
if(count&2) if(count&2)
return -1; return -1;
return count; return count;
@ -189,8 +189,8 @@ static int pms_i2c_read(int slave, int sub)
static void pms_i2c_andor(int slave, int sub, int and, int or) static void pms_i2c_andor(int slave, int sub, int and, int or)
{ {
u8 tmp; u8 tmp;
tmp=pms_i2c_read(slave, sub); tmp=pms_i2c_read(slave, sub);
tmp = (tmp&and)|or; tmp = (tmp&and)|or;
pms_i2c_write(slave, sub, tmp); pms_i2c_write(slave, sub, tmp);
@ -199,7 +199,7 @@ static void pms_i2c_andor(int slave, int sub, int and, int or)
/* /*
* Control functions * Control functions
*/ */
static void pms_videosource(short source) static void pms_videosource(short source)
{ {
@ -234,8 +234,8 @@ static void pms_colour(short colour)
break; break;
} }
} }
static void pms_contrast(short contrast) static void pms_contrast(short contrast)
{ {
switch(decoder) switch(decoder)
@ -269,14 +269,14 @@ static void pms_format(short format)
{ {
int target; int target;
standard = format; standard = format;
if(decoder==PHILIPS1) if(decoder==PHILIPS1)
target=0x42; target=0x42;
else if(decoder==PHILIPS2) else if(decoder==PHILIPS2)
target=0x8A; target=0x8A;
else else
return; return;
switch(format) switch(format)
{ {
case 0: /* Auto */ case 0: /* Auto */
@ -302,7 +302,7 @@ static void pms_format(short format)
/* /*
* These features of the PMS card are not currently exposes. They * These features of the PMS card are not currently exposes. They
* could become a private v4l ioctl for PMSCONFIG or somesuch if * could become a private v4l ioctl for PMSCONFIG or somesuch if
* people need it. We also don't yet use the PMS interrupt. * people need it. We also don't yet use the PMS interrupt.
*/ */
@ -324,7 +324,7 @@ static void pms_hstart(short start)
/* /*
* Bandpass filters * Bandpass filters
*/ */
static void pms_bandpass(short pass) static void pms_bandpass(short pass)
{ {
if(decoder==PHILIPS2) if(decoder==PHILIPS2)
@ -493,7 +493,7 @@ static void pms_vert(u8 deciden, u8 decinum)
/* /*
* Turn 16bit ratios into best small ratio the chipset can grok * Turn 16bit ratios into best small ratio the chipset can grok
*/ */
static void pms_vertdeci(unsigned short decinum, unsigned short deciden) static void pms_vertdeci(unsigned short decinum, unsigned short deciden)
{ {
/* Knock it down by /5 once */ /* Knock it down by /5 once */
@ -546,7 +546,7 @@ static void pms_horzdeci(short decinum, short deciden)
decinum=512; decinum=512;
deciden=640; /* 768 would be ideal */ deciden=640; /* 768 would be ideal */
} }
while(((decinum|deciden)&1)==0) while(((decinum|deciden)&1)==0)
{ {
decinum>>=1; decinum>>=1;
@ -559,7 +559,7 @@ static void pms_horzdeci(short decinum, short deciden)
} }
if(deciden==32) if(deciden==32)
deciden--; deciden--;
mvv_write(0x24, 0x80|deciden); mvv_write(0x24, 0x80|deciden);
mvv_write(0x25, decinum); mvv_write(0x25, decinum);
} }
@ -567,14 +567,14 @@ static void pms_horzdeci(short decinum, short deciden)
static void pms_resolution(short width, short height) static void pms_resolution(short width, short height)
{ {
int fg_height; int fg_height;
fg_height=height; fg_height=height;
if(fg_height>280) if(fg_height>280)
fg_height=280; fg_height=280;
mvv_write(0x18, fg_height); mvv_write(0x18, fg_height);
mvv_write(0x19, fg_height>>8); mvv_write(0x19, fg_height>>8);
if(standard==1) if(standard==1)
{ {
mvv_write(0x1A, 0xFC); mvv_write(0x1A, 0xFC);
@ -598,7 +598,7 @@ static void pms_resolution(short width, short height)
mvv_write(0x42, 0x00); mvv_write(0x42, 0x00);
mvv_write(0x43, 0x00); mvv_write(0x43, 0x00);
mvv_write(0x44, MVVMEMORYWIDTH); mvv_write(0x44, MVVMEMORYWIDTH);
mvv_write(0x22, width+8); mvv_write(0x22, width+8);
mvv_write(0x23, (width+8)>> 8); mvv_write(0x23, (width+8)>> 8);
@ -618,7 +618,7 @@ static void pms_resolution(short width, short height)
/* /*
* Set Input * Set Input
*/ */
static void pms_vcrinput(short input) static void pms_vcrinput(short input)
{ {
if(decoder==PHILIPS2) if(decoder==PHILIPS2)
@ -643,20 +643,20 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */ mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */
/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
for (y = 0; y < dev->height; y++ ) for (y = 0; y < dev->height; y++ )
{ {
writeb(0, mem); /* synchronisiert neue Zeile */ writeb(0, mem); /* synchronisiert neue Zeile */
/* /*
* This is in truth a fifo, be very careful as if you * This is in truth a fifo, be very careful as if you
* forgot this odd things will occur 8) * forgot this odd things will occur 8)
*/ */
memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */ memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */
cnt -= dev->height; cnt -= dev->height;
while (cnt <= 0) while (cnt <= 0)
{ {
/* /*
* Don't copy too far * Don't copy too far
*/ */
@ -666,7 +666,7 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
cnt += dev->height; cnt += dev->height;
if (copy_to_user(buf, tmp+32, dt)) if (copy_to_user(buf, tmp+32, dt))
return len ? len : -EFAULT; return len ? len : -EFAULT;
buf += dt; buf += dt;
len += dt; len += dt;
} }
} }
@ -683,7 +683,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
{ {
struct video_device *dev = video_devdata(file); struct video_device *dev = video_devdata(file);
struct pms_device *pd=(struct pms_device *)dev; struct pms_device *pd=(struct pms_device *)dev;
switch(cmd) switch(cmd)
{ {
case VIDIOCGCAP: case VIDIOCGCAP:
@ -806,7 +806,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15))) ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15)))
return -EINVAL; return -EINVAL;
pd->picture= *p; pd->picture= *p;
/* /*
* Now load the card. * Now load the card.
*/ */
@ -815,7 +815,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
pms_brightness(p->brightness>>8); pms_brightness(p->brightness>>8);
pms_hue(p->hue>>8); pms_hue(p->hue>>8);
pms_colour(p->colour>>8); pms_colour(p->colour>>8);
pms_contrast(p->contrast>>8); pms_contrast(p->contrast>>8);
mutex_unlock(&pd->lock); mutex_unlock(&pd->lock);
return 0; return 0;
} }
@ -873,7 +873,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
struct video_device *v = video_devdata(file); struct video_device *v = video_devdata(file);
struct pms_device *pd=(struct pms_device *)v; struct pms_device *pd=(struct pms_device *)v;
int len; int len;
mutex_lock(&pd->lock); mutex_lock(&pd->lock);
len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count);
mutex_unlock(&pd->lock); mutex_unlock(&pd->lock);
@ -905,13 +905,13 @@ static struct pms_device pms_device;
/* /*
* Probe for and initialise the Mediavision PMS * Probe for and initialise the Mediavision PMS
*/ */
static int init_mediavision(void) static int init_mediavision(void)
{ {
int id; int id;
int idec, decst; int idec, decst;
int i; int i;
unsigned char i2c_defs[]={ unsigned char i2c_defs[]={
0x4C,0x30,0x00,0xE8, 0x4C,0x30,0x00,0xE8,
0xB6,0xE2,0x00,0x00, 0xB6,0xE2,0x00,0x00,
@ -925,7 +925,7 @@ static int init_mediavision(void)
mem = ioremap(mem_base, 0x800); mem = ioremap(mem_base, 0x800);
if (!mem) if (!mem)
return -ENOMEM; return -ENOMEM;
if (!request_region(0x9A01, 1, "Mediavision PMS config")) if (!request_region(0x9A01, 1, "Mediavision PMS config"))
{ {
printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n"); printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n");
@ -941,18 +941,18 @@ static int init_mediavision(void)
} }
outb(0xB8, 0x9A01); /* Unlock */ outb(0xB8, 0x9A01); /* Unlock */
outb(io_port>>4, 0x9A01); /* Set IO port */ outb(io_port>>4, 0x9A01); /* Set IO port */
id=mvv_read(3); id=mvv_read(3);
decst=pms_i2c_stat(0x43); decst=pms_i2c_stat(0x43);
if(decst!=-1) if(decst!=-1)
idec=2; idec=2;
else if(pms_i2c_stat(0xb9)!=-1) else if(pms_i2c_stat(0xb9)!=-1)
idec=3; idec=3;
else if(pms_i2c_stat(0x8b)!=-1) else if(pms_i2c_stat(0x8b)!=-1)
idec=1; idec=1;
else else
idec=0; idec=0;
printk(KERN_INFO "PMS type is %d\n", idec); printk(KERN_INFO "PMS type is %d\n", idec);
@ -966,11 +966,11 @@ static int init_mediavision(void)
/* /*
* Ok we have a PMS of some sort * Ok we have a PMS of some sort
*/ */
mvv_write(0x04, mem_base>>12); /* Set the memory area */ mvv_write(0x04, mem_base>>12); /* Set the memory area */
/* Ok now load the defaults */ /* Ok now load the defaults */
for(i=0;i<0x19;i++) for(i=0;i<0x19;i++)
{ {
if(i2c_defs[i]==0xFF) if(i2c_defs[i]==0xFF)
@ -978,7 +978,7 @@ static int init_mediavision(void)
else else
pms_i2c_write(0x8A, i, i2c_defs[i]); pms_i2c_write(0x8A, i, i2c_defs[i]);
} }
pms_i2c_write(0xB8,0x00,0x12); pms_i2c_write(0xB8,0x00,0x12);
pms_i2c_write(0xB8,0x04,0x00); pms_i2c_write(0xB8,0x04,0x00);
pms_i2c_write(0xB8,0x07,0x00); pms_i2c_write(0xB8,0x07,0x00);
@ -987,18 +987,18 @@ static int init_mediavision(void)
pms_i2c_write(0xB8,0x0A,0x00); pms_i2c_write(0xB8,0x0A,0x00);
pms_i2c_write(0xB8,0x0B,0x10); pms_i2c_write(0xB8,0x0B,0x10);
pms_i2c_write(0xB8,0x10,0x03); pms_i2c_write(0xB8,0x10,0x03);
mvv_write(0x01, 0x00); mvv_write(0x01, 0x00);
mvv_write(0x05, 0xA0); mvv_write(0x05, 0xA0);
mvv_write(0x08, 0x25); mvv_write(0x08, 0x25);
mvv_write(0x09, 0x00); mvv_write(0x09, 0x00);
mvv_write(0x0A, 0x20|MVVMEMORYWIDTH); mvv_write(0x0A, 0x20|MVVMEMORYWIDTH);
mvv_write(0x10, 0x02); mvv_write(0x10, 0x02);
mvv_write(0x1E, 0x0C); mvv_write(0x1E, 0x0C);
mvv_write(0x1F, 0x03); mvv_write(0x1F, 0x03);
mvv_write(0x26, 0x06); mvv_write(0x26, 0x06);
mvv_write(0x2B, 0x00); mvv_write(0x2B, 0x00);
mvv_write(0x2C, 0x20); mvv_write(0x2C, 0x20);
mvv_write(0x2D, 0x00); mvv_write(0x2D, 0x00);
@ -1018,13 +1018,13 @@ static int init_mediavision(void)
/* /*
* Initialization and module stuff * Initialization and module stuff
*/ */
static int __init init_pms_cards(void) static int __init init_pms_cards(void)
{ {
printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n"); printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
data_port = io_port +1; data_port = io_port +1;
if(init_mediavision()) if(init_mediavision())
{ {
printk(KERN_INFO "Board not found.\n"); printk(KERN_INFO "Board not found.\n");

View file

@ -15,6 +15,6 @@ default:
endif endif
clean: clean:
rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
rm -rf .tmp_versions rm -rf .tmp_versions

View file

@ -47,17 +47,17 @@ don't know how to set it properly in the driver. The options are:
size size
Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
'vga', for an image size of resp. 128x96, 160x120, 176x144, 'vga', for an image size of resp. 128x96, 160x120, 176x144,
320x240, 352x288 and 640x480 (of course, only for those cameras that 320x240, 352x288 and 640x480 (of course, only for those cameras that
support these resolutions). support these resolutions).
fps fps
Specifies the desired framerate. Is an integer in the range of 4-30. Specifies the desired framerate. Is an integer in the range of 4-30.
fbufs fbufs
This paramter specifies the number of internal buffers to use for storing This paramter specifies the number of internal buffers to use for storing
frames from the cam. This will help if the process that reads images from frames from the cam. This will help if the process that reads images from
the cam is a bit slow or momentarely busy. However, on slow machines it the cam is a bit slow or momentarely busy. However, on slow machines it
only introduces lag, so choose carefully. The default is 3, which is only introduces lag, so choose carefully. The default is 3, which is
reasonable. You can set it between 2 and 5. reasonable. You can set it between 2 and 5.
mbufs mbufs
@ -65,9 +65,9 @@ mbufs
buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends. buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
The default is 2, which is adequate for most applications (double The default is 2, which is adequate for most applications (double
buffering). buffering).
Should you experience a lot of 'Dumping frame...' messages during Should you experience a lot of 'Dumping frame...' messages during
grabbing with a tool that uses mmap(), you might want to increase if. grabbing with a tool that uses mmap(), you might want to increase if.
However, it doesn't really buffer images, it just gives you a bit more However, it doesn't really buffer images, it just gives you a bit more
slack when your program is behind. But you need a multi-threaded or slack when your program is behind. But you need a multi-threaded or
forked program to really take advantage of these buffers. forked program to really take advantage of these buffers.
@ -88,15 +88,15 @@ power_save
compression (only useful with the plugin) compression (only useful with the plugin)
With this option you can control the compression factor that the camera With this option you can control the compression factor that the camera
uses to squeeze the image through the USB bus. You can set the uses to squeeze the image through the USB bus. You can set the
parameter between 0 and 3: parameter between 0 and 3:
0 = prefer uncompressed images; if the requested mode is not available 0 = prefer uncompressed images; if the requested mode is not available
in an uncompressed format, the driver will silently switch to low in an uncompressed format, the driver will silently switch to low
compression. compression.
1 = low compression. 1 = low compression.
2 = medium compression. 2 = medium compression.
3 = high compression. 3 = high compression.
High compression takes less bandwidth of course, but it could also High compression takes less bandwidth of course, but it could also
introduce some unwanted artefacts. The default is 2, medium compression. introduce some unwanted artefacts. The default is 2, medium compression.
See the FAQ on the website for an overview of which modes require See the FAQ on the website for an overview of which modes require
@ -112,7 +112,7 @@ leds
this is let the LED blink while the camera is in use. This: this is let the LED blink while the camera is in use. This:
leds=500,500 leds=500,500
will blink the LED once every second. But with: will blink the LED once every second. But with:
leds=0,0 leds=0,0
@ -123,7 +123,7 @@ leds
when the camera is not used anymore. when the camera is not used anymore.
This parameter works only with the ToUCam range of cameras (720, 730, 740, This parameter works only with the ToUCam range of cameras (720, 730, 740,
750) and OEMs. For other cameras this command is silently ignored, and 750) and OEMs. For other cameras this command is silently ignored, and
the LED cannot be controlled. the LED cannot be controlled.
Finally: this parameters does not take effect UNTIL the first time you Finally: this parameters does not take effect UNTIL the first time you
@ -144,35 +144,35 @@ dev_hint
format: format:
[type[.serialnumber]:]node [type[.serialnumber]:]node
The square brackets mean that both the type and the serialnumber are The square brackets mean that both the type and the serialnumber are
optional, but a serialnumber cannot be specified without a type (which optional, but a serialnumber cannot be specified without a type (which
would be rather pointless). The serialnumber is separated from the type would be rather pointless). The serialnumber is separated from the type
by a '.'; the node number by a ':'. by a '.'; the node number by a ':'.
This somewhat cryptic syntax is best explained by a few examples: This somewhat cryptic syntax is best explained by a few examples:
dev_hint=3,5 The first detected cam gets assigned dev_hint=3,5 The first detected cam gets assigned
/dev/video3, the second /dev/video5. Any /dev/video3, the second /dev/video5. Any
other cameras will get the first free other cameras will get the first free
available slot (see below). available slot (see below).
dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1, dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1,
and a PCVC680 /dev/video2. and a PCVC680 /dev/video2.
dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
0123 goes to /dev/video3, the same
camera model with the 4567 serial
gets /dev/video0.
dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
next 3 Philips cams will use /dev/video4 0123 goes to /dev/video3, the same
through /dev/video6. camera model with the 4567 serial
gets /dev/video0.
dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
next 3 Philips cams will use /dev/video4
through /dev/video6.
Some points worth knowing: Some points worth knowing:
- Serialnumbers are case sensitive and must be written full, including - Serialnumbers are case sensitive and must be written full, including
leading zeroes (it's treated as a string). leading zeroes (it's treated as a string).
- If a device node is already occupied, registration will fail and - If a device node is already occupied, registration will fail and
the webcam is not available. the webcam is not available.
- You can have up to 64 video devices; be sure to make enough device - You can have up to 64 video devices; be sure to make enough device
nodes in /dev if you want to spread the numbers (this does not apply nodes in /dev if you want to spread the numbers (this does not apply
@ -186,13 +186,13 @@ trace
kernel log at debug level. kernel log at debug level.
The trace variable is a bitmask; each bit represents a certain feature. The trace variable is a bitmask; each bit represents a certain feature.
If you want to trace something, look up the bit value(s) in the table If you want to trace something, look up the bit value(s) in the table
below, add the values together and supply that to the trace variable. below, add the values together and supply that to the trace variable.
Value Value Description Default Value Value Description Default
(dec) (hex) (dec) (hex)
1 0x1 Module initialization; this will log messages On 1 0x1 Module initialization; this will log messages On
while loading and unloading the module while loading and unloading the module
2 0x2 probe() and disconnect() traces On 2 0x2 probe() and disconnect() traces On
@ -203,7 +203,7 @@ trace
16 0x10 Memory allocation of buffers, etc. Off 16 0x10 Memory allocation of buffers, etc. Off
32 0x20 Showing underflow, overflow and Dumping frame On 32 0x20 Showing underflow, overflow and Dumping frame On
messages messages
64 0x40 Show viewport and image sizes Off 64 0x40 Show viewport and image sizes Off
@ -217,7 +217,7 @@ trace
Example: Example:
# modprobe pwc size=cif fps=15 power_save=1 # modprobe pwc size=cif fps=15 power_save=1
The fbufs, mbufs and trace parameters are global and apply to all connected The fbufs, mbufs and trace parameters are global and apply to all connected

View file

@ -31,17 +31,17 @@
/* /*
Changes Changes
2001/08/03 Alvarado Added methods for changing white balance and 2001/08/03 Alvarado Added methods for changing white balance and
red/green gains red/green gains
*/ */
/* Control functions for the cam; brightness, contrast, video mode, etc. */ /* Control functions for the cam; brightness, contrast, video mode, etc. */
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/uaccess.h> #include <asm/uaccess.h>
#endif #endif
#include <asm/errno.h> #include <asm/errno.h>
#include "pwc.h" #include "pwc.h"
#include "pwc-ioctl.h" #include "pwc-ioctl.h"
#include "pwc-uncompress.h" #include "pwc-uncompress.h"
@ -116,13 +116,13 @@ static const char *size2name[PSZ_MAX] =
"SIF", "SIF",
"CIF", "CIF",
"VGA", "VGA",
}; };
/********/ /********/
/* Entries for the Nala (645/646) camera; the Nala doesn't have compression /* Entries for the Nala (645/646) camera; the Nala doesn't have compression
preferences, so you either get compressed or non-compressed streams. preferences, so you either get compressed or non-compressed streams.
An alternate value of 0 means this mode is not available at all. An alternate value of 0 means this mode is not available at all.
*/ */
@ -205,13 +205,13 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
{ /* closest match of framerate */ { /* closest match of framerate */
0, 0, 0, 0, 4, /* 0-4 */ 0, 0, 0, 0, 4, /* 0-4 */
5, 5, 7, 7, 10, /* 5-9 */ 5, 5, 7, 7, 10, /* 5-9 */
10, 10, 12, 12, 15, /* 10-14 */ 10, 10, 12, 12, 15, /* 10-14 */
15, 15, 15, 20, 20, /* 15-19 */ 15, 15, 15, 20, 20, /* 15-19 */
20, 20, 20, 24, 24, /* 20-24 */ 20, 20, 20, 24, 24, /* 20-24 */
24, 24, 24, 24, 24, /* 25-29 */ 24, 24, 24, 24, 24, /* 25-29 */
24 /* 30 */ 24 /* 30 */
}; };
int frames2table[31] = int frames2table[31] =
{ 0, 0, 0, 0, 0, /* 0-4 */ { 0, 0, 0, 0, 0, /* 0-4 */
1, 1, 1, 2, 2, /* 5-9 */ 1, 1, 1, 2, 2, /* 5-9 */
3, 3, 4, 4, 4, /* 10-14 */ 3, 3, 4, 4, 4, /* 10-14 */
@ -220,7 +220,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
7, 7, 7, 7, 7, /* 25-29 */ 7, 7, 7, 7, 7, /* 25-29 */
7 /* 30 */ 7 /* 30 */
}; };
if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25) if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
return -EINVAL; return -EINVAL;
frames = frames2frames[frames]; frames = frames2frames[frames];
@ -232,7 +232,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
if (pEntry->compressed) if (pEntry->compressed)
return -ENOENT; /* Not supported. */ return -ENOENT; /* Not supported. */
memcpy(buf, pEntry->mode, 3); memcpy(buf, pEntry->mode, 3);
ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
if (ret < 0) { if (ret < 0) {
Debug("Failed to send video command... %d\n", ret); Debug("Failed to send video command... %d\n", ret);
@ -257,7 +257,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
break; break;
} }
} }
pdev->cmd_len = 3; pdev->cmd_len = 3;
memcpy(pdev->cmd_buf, buf, 3); memcpy(pdev->cmd_buf, buf, 3);
@ -352,13 +352,13 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
/* special case: VGA @ 5 fps and snapshot is raw bayer mode */ /* special case: VGA @ 5 fps and snapshot is raw bayer mode */
if (size == PSZ_VGA && frames == 5 && snapshot) if (size == PSZ_VGA && frames == 5 && snapshot)
{ {
/* Only available in case the raw palette is selected or /* Only available in case the raw palette is selected or
we have the decompressor available. This mode is we have the decompressor available. This mode is
only available in compressed form only available in compressed form
*/ */
if (pdev->vpalette == VIDEO_PALETTE_RAW) if (pdev->vpalette == VIDEO_PALETTE_RAW)
{ {
Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette); Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
pChoose = &RawEntry; pChoose = &RawEntry;
} }
else else
@ -368,9 +368,9 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
} }
else else
{ {
/* Find a supported framerate with progressively higher compression ratios /* Find a supported framerate with progressively higher compression ratios
if the preferred ratio is not available. if the preferred ratio is not available.
Skip this step when using RAW modes. Skip this step when using RAW modes.
*/ */
while (compression <= 3) { while (compression <= 3) {
pChoose = &Kiara_table[size][fps][compression]; pChoose = &Kiara_table[size][fps][compression];
@ -383,7 +383,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
return -ENOENT; /* Not supported. */ return -ENOENT; /* Not supported. */
Debug("Using alternate setting %d.\n", pChoose->alternate); Debug("Using alternate setting %d.\n", pChoose->alternate);
/* usb_control_msg won't take staticly allocated arrays as argument?? */ /* usb_control_msg won't take staticly allocated arrays as argument?? */
memcpy(buf, pChoose->mode, 12); memcpy(buf, pChoose->mode, 12);
if (snapshot) if (snapshot)
@ -463,9 +463,9 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev)
*/ */
int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot) int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
{ {
int ret, size; int ret, size;
Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
size = pwc_decode_size(pdev, width, height); size = pwc_decode_size(pdev, width, height);
if (size < 0) { if (size < 0) {
Debug("Could not find suitable size.\n"); Debug("Could not find suitable size.\n");
@ -473,7 +473,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
} }
Debug("decode_size = %d.\n", size); Debug("decode_size = %d.\n", size);
ret = -EINVAL; ret = -EINVAL;
switch(pdev->type) { switch(pdev->type) {
case 645: case 645:
case 646: case 646:
@ -485,7 +485,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
case 690: case 690:
ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
break; break;
case 720: case 720:
case 730: case 730:
case 740: case 740:
@ -517,7 +517,7 @@ int pwc_get_brightness(struct pwc_device *pdev)
char buf; char buf;
int ret; int ret;
ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
return buf << 9; return buf << 9;
@ -566,7 +566,7 @@ int pwc_get_gamma(struct pwc_device *pdev)
{ {
char buf; char buf;
int ret; int ret;
ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -622,14 +622,14 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
{ {
char buf; char buf;
int ret; int ret;
if (mode) if (mode)
buf = 0x0; /* auto */ buf = 0x0; /* auto */
else else
buf = 0xff; /* fixed */ buf = 0xff; /* fixed */
ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1); ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1);
if (!mode && ret >= 0) { if (!mode && ret >= 0) {
if (value < 0) if (value < 0)
value = 0; value = 0;
@ -647,7 +647,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -658,7 +658,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
return ret; return ret;
if (buf > 0x3F) if (buf > 0x3F)
buf = 0x3F; buf = 0x3F;
*value = (buf << 10); *value = (buf << 10);
} }
else { /* auto */ else { /* auto */
ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1); ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1);
@ -683,7 +683,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
buf[0] = 0x0; /* auto */ buf[0] = 0x0; /* auto */
else else
buf[0] = 0xff; /* fixed */ buf[0] = 0xff; /* fixed */
ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1); ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1);
if (!mode && ret >= 0) { if (!mode && ret >= 0) {
@ -713,7 +713,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
} }
return ret; return ret;
} }
/* POWER */ /* POWER */
@ -765,22 +765,22 @@ static inline int pwc_restore_factory(struct pwc_device *pdev)
* 02: fluorescent lighting * 02: fluorescent lighting
* 03: manual * 03: manual
* 04: auto * 04: auto
*/ */
static inline int pwc_set_awb(struct pwc_device *pdev, int mode) static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
{ {
char buf; char buf;
int ret; int ret;
if (mode < 0) if (mode < 0)
mode = 0; mode = 0;
if (mode > 4) if (mode > 4)
mode = 4; mode = 4;
buf = mode & 0x07; /* just the lowest three bits */ buf = mode & 0x07; /* just the lowest three bits */
ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1); ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
return 0; return 0;
@ -790,17 +790,17 @@ static inline int pwc_get_awb(struct pwc_device *pdev)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1); ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
return buf; return buf;
} }
static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
{ {
unsigned char buf; unsigned char buf;
if (value < 0) if (value < 0)
value = 0; value = 0;
@ -815,7 +815,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -841,7 +841,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -851,14 +851,14 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
/* The following two functions are different, since they only read the /* The following two functions are different, since they only read the
internal red/blue gains, which may be different from the manual internal red/blue gains, which may be different from the manual
gains set or read above. gains set or read above.
*/ */
static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1); ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -870,7 +870,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1); ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -882,7 +882,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
{ {
unsigned char buf; unsigned char buf;
/* useful range is 0x01..0x20 */ /* useful range is 0x01..0x20 */
buf = speed / 0x7f0; buf = speed / 0x7f0;
return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
@ -892,7 +892,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -904,7 +904,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
{ {
unsigned char buf; unsigned char buf;
/* useful range is 0x01..0x3F */ /* useful range is 0x01..0x3F */
buf = (delay >> 10); buf = (delay >> 10);
return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
@ -914,7 +914,7 @@ static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -950,7 +950,7 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
{ {
unsigned char buf[2]; unsigned char buf[2];
int ret; int ret;
if (pdev->type < 730) { if (pdev->type < 730) {
*on_value = -1; *on_value = -1;
*off_value = -1; *off_value = -1;
@ -969,7 +969,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
if (contour < 0) if (contour < 0)
buf = 0xff; /* auto contour on */ buf = 0xff; /* auto contour on */
else else
@ -977,16 +977,16 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (contour < 0) if (contour < 0)
return 0; return 0;
if (contour > 0xffff) if (contour > 0xffff)
contour = 0xffff; contour = 0xffff;
buf = (contour >> 10); /* contour preset is [0..3f] */ buf = (contour >> 10); /* contour preset is [0..3f] */
ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
return 0; return 0;
} }
@ -994,7 +994,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
{ {
unsigned char buf; unsigned char buf;
int ret; int ret;
ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1002,7 +1002,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
if (buf == 0) { if (buf == 0) {
/* auto mode off, query current preset value */ /* auto mode off, query current preset value */
ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
*contour = buf << 10; *contour = buf << 10;
} }
@ -1015,7 +1015,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
{ {
unsigned char buf; unsigned char buf;
if (backlight) if (backlight)
buf = 0xff; buf = 0xff;
else else
@ -1027,7 +1027,7 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
{ {
int ret; int ret;
unsigned char buf; unsigned char buf;
ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1039,7 +1039,7 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
{ {
unsigned char buf; unsigned char buf;
if (flicker) if (flicker)
buf = 0xff; buf = 0xff;
else else
@ -1051,7 +1051,7 @@ static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
{ {
int ret; int ret;
unsigned char buf; unsigned char buf;
ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1076,7 +1076,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
{ {
int ret; int ret;
unsigned char buf; unsigned char buf;
ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1087,7 +1087,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
static int pwc_mpt_reset(struct pwc_device *pdev, int flags) static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
{ {
unsigned char buf; unsigned char buf;
buf = flags & 0x03; // only lower two bits are currently used buf = flags & 0x03; // only lower two bits are currently used
return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
} }
@ -1095,7 +1095,7 @@ static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
{ {
unsigned char buf[4]; unsigned char buf[4];
/* set new relative angle; angles are expressed in degrees * 100, /* set new relative angle; angles are expressed in degrees * 100,
but cam as .5 degree resolution, hence divide by 200. Also but cam as .5 degree resolution, hence divide by 200. Also
the angle must be multiplied by 64 before it's send to the angle must be multiplied by 64 before it's send to
@ -1114,7 +1114,7 @@ static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_sta
{ {
int ret; int ret;
unsigned char buf[5]; unsigned char buf[5];
ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5); ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1129,14 +1129,14 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
{ {
unsigned char buf; unsigned char buf;
int ret = -1, request; int ret = -1, request;
if (pdev->type < 675) if (pdev->type < 675)
request = SENSOR_TYPE_FORMATTER1; request = SENSOR_TYPE_FORMATTER1;
else if (pdev->type < 730) else if (pdev->type < 730)
return -1; /* The Vesta series doesn't have this call */ return -1; /* The Vesta series doesn't have this call */
else else
request = SENSOR_TYPE_FORMATTER2; request = SENSOR_TYPE_FORMATTER2;
ret = RecvControlMsg(GET_STATUS_CTL, request, 1); ret = RecvControlMsg(GET_STATUS_CTL, request, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1163,23 +1163,23 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCSUSER: case VIDIOCPWCSUSER:
{ {
if (pwc_save_user(pdev)) if (pwc_save_user(pdev))
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCFACTORY: case VIDIOCPWCFACTORY:
{ {
if (pwc_restore_factory(pdev)) if (pwc_restore_factory(pdev))
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCSCQUAL: case VIDIOCPWCSCQUAL:
{ {
int *qual = arg; int *qual = arg;
if (*qual < 0 || *qual > 3) if (*qual < 0 || *qual > 3)
@ -1190,14 +1190,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
pdev->vcompression = *qual; pdev->vcompression = *qual;
break; break;
} }
case VIDIOCPWCGCQUAL: case VIDIOCPWCGCQUAL:
{ {
int *qual = arg; int *qual = arg;
*qual = pdev->vcompression; *qual = pdev->vcompression;
break; break;
} }
case VIDIOCPWCPROBE: case VIDIOCPWCPROBE:
{ {
struct pwc_probe *probe = arg; struct pwc_probe *probe = arg;
@ -1220,27 +1220,27 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCGAGC: case VIDIOCPWCGAGC:
{ {
int *agc = arg; int *agc = arg;
if (pwc_get_agc(pdev, agc)) if (pwc_get_agc(pdev, agc))
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCSSHUTTER: case VIDIOCPWCSSHUTTER:
{ {
int *shutter_speed = arg; int *shutter_speed = arg;
ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
break; break;
} }
case VIDIOCPWCSAWB: case VIDIOCPWCSAWB:
{ {
struct pwc_whitebalance *wb = arg; struct pwc_whitebalance *wb = arg;
ret = pwc_set_awb(pdev, wb->mode); ret = pwc_set_awb(pdev, wb->mode);
if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
pwc_set_red_gain(pdev, wb->manual_red); pwc_set_red_gain(pdev, wb->manual_red);
@ -1270,18 +1270,18 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_read_red_gain(pdev, &wb->read_red); ret = pwc_read_red_gain(pdev, &wb->read_red);
if (ret < 0) if (ret < 0)
break; break;
ret = pwc_read_blue_gain(pdev, &wb->read_blue); ret = pwc_read_blue_gain(pdev, &wb->read_blue);
if (ret < 0) if (ret < 0)
break; break;
} }
} }
break; break;
} }
case VIDIOCPWCSAWBSPEED: case VIDIOCPWCSAWBSPEED:
{ {
struct pwc_wb_speed *wbs = arg; struct pwc_wb_speed *wbs = arg;
if (wbs->control_speed > 0) { if (wbs->control_speed > 0) {
ret = pwc_set_wb_speed(pdev, wbs->control_speed); ret = pwc_set_wb_speed(pdev, wbs->control_speed);
} }
@ -1290,11 +1290,11 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
} }
break; break;
} }
case VIDIOCPWCGAWBSPEED: case VIDIOCPWCGAWBSPEED:
{ {
struct pwc_wb_speed *wbs = arg; struct pwc_wb_speed *wbs = arg;
ret = pwc_get_wb_speed(pdev, &wbs->control_speed); ret = pwc_get_wb_speed(pdev, &wbs->control_speed);
if (ret < 0) if (ret < 0)
break; break;
@ -1304,7 +1304,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
break; break;
} }
case VIDIOCPWCSLED: case VIDIOCPWCSLED:
{ {
struct pwc_leds *leds = arg; struct pwc_leds *leds = arg;
ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
@ -1325,14 +1325,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_set_contour(pdev, *contour); ret = pwc_set_contour(pdev, *contour);
break; break;
} }
case VIDIOCPWCGCONTOUR: case VIDIOCPWCGCONTOUR:
{ {
int *contour = arg; int *contour = arg;
ret = pwc_get_contour(pdev, contour); ret = pwc_get_contour(pdev, contour);
break; break;
} }
case VIDIOCPWCSBACKLIGHT: case VIDIOCPWCSBACKLIGHT:
{ {
int *backlight = arg; int *backlight = arg;
@ -1346,7 +1346,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_get_backlight(pdev, backlight); ret = pwc_get_backlight(pdev, backlight);
break; break;
} }
case VIDIOCPWCSFLICKER: case VIDIOCPWCSFLICKER:
{ {
int *flicker = arg; int *flicker = arg;
@ -1360,14 +1360,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_get_flicker(pdev, flicker); ret = pwc_get_flicker(pdev, flicker);
break; break;
} }
case VIDIOCPWCSDYNNOISE: case VIDIOCPWCSDYNNOISE:
{ {
int *dynnoise = arg; int *dynnoise = arg;
ret = pwc_set_dynamic_noise(pdev, *dynnoise); ret = pwc_set_dynamic_noise(pdev, *dynnoise);
break; break;
} }
case VIDIOCPWCGDYNNOISE: case VIDIOCPWCGDYNNOISE:
{ {
int *dynnoise = arg; int *dynnoise = arg;
@ -1381,61 +1381,61 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
size->width = pdev->image.x; size->width = pdev->image.x;
size->height = pdev->image.y; size->height = pdev->image.y;
break; break;
} }
case VIDIOCPWCMPTRESET: case VIDIOCPWCMPTRESET:
{ {
if (pdev->features & FEATURE_MOTOR_PANTILT) if (pdev->features & FEATURE_MOTOR_PANTILT)
{ {
int *flags = arg; int *flags = arg;
ret = pwc_mpt_reset(pdev, *flags); ret = pwc_mpt_reset(pdev, *flags);
if (ret >= 0) if (ret >= 0)
{ {
pdev->pan_angle = 0; pdev->pan_angle = 0;
pdev->tilt_angle = 0; pdev->tilt_angle = 0;
} }
} }
else else
{ {
ret = -ENXIO; ret = -ENXIO;
} }
break; break;
} }
case VIDIOCPWCMPTGRANGE: case VIDIOCPWCMPTGRANGE:
{ {
if (pdev->features & FEATURE_MOTOR_PANTILT) if (pdev->features & FEATURE_MOTOR_PANTILT)
{ {
struct pwc_mpt_range *range = arg; struct pwc_mpt_range *range = arg;
*range = pdev->angle_range; *range = pdev->angle_range;
} }
else else
{ {
ret = -ENXIO; ret = -ENXIO;
} }
break; break;
} }
case VIDIOCPWCMPTSANGLE: case VIDIOCPWCMPTSANGLE:
{ {
int new_pan, new_tilt; int new_pan, new_tilt;
if (pdev->features & FEATURE_MOTOR_PANTILT) if (pdev->features & FEATURE_MOTOR_PANTILT)
{ {
struct pwc_mpt_angles *angles = arg; struct pwc_mpt_angles *angles = arg;
/* The camera can only set relative angles, so /* The camera can only set relative angles, so
do some calculations when getting an absolute angle . do some calculations when getting an absolute angle .
*/ */
if (angles->absolute) if (angles->absolute)
{ {
new_pan = angles->pan; new_pan = angles->pan;
new_tilt = angles->tilt; new_tilt = angles->tilt;
} }
else else
{ {
new_pan = pdev->pan_angle + angles->pan; new_pan = pdev->pan_angle + angles->pan;
new_tilt = pdev->tilt_angle + angles->tilt; new_tilt = pdev->tilt_angle + angles->tilt;
} }
/* check absolute ranges */ /* check absolute ranges */
if (new_pan < pdev->angle_range.pan_min || if (new_pan < pdev->angle_range.pan_min ||
@ -1463,53 +1463,53 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
pdev->tilt_angle += new_tilt; pdev->tilt_angle += new_tilt;
} }
if (ret == -EPIPE) /* stall -> out of range */ if (ret == -EPIPE) /* stall -> out of range */
ret = -ERANGE; ret = -ERANGE;
} }
} }
else else
{ {
ret = -ENXIO; ret = -ENXIO;
} }
break; break;
} }
case VIDIOCPWCMPTGANGLE: case VIDIOCPWCMPTGANGLE:
{ {
if (pdev->features & FEATURE_MOTOR_PANTILT)
{
struct pwc_mpt_angles *angles = arg;
angles->absolute = 1; if (pdev->features & FEATURE_MOTOR_PANTILT)
angles->pan = pdev->pan_angle; {
angles->tilt = pdev->tilt_angle; struct pwc_mpt_angles *angles = arg;
}
else angles->absolute = 1;
{ angles->pan = pdev->pan_angle;
ret = -ENXIO; angles->tilt = pdev->tilt_angle;
} }
break; else
} {
ret = -ENXIO;
case VIDIOCPWCMPTSTATUS: }
{ break;
if (pdev->features & FEATURE_MOTOR_PANTILT) }
{
struct pwc_mpt_status *status = arg; case VIDIOCPWCMPTSTATUS:
ret = pwc_mpt_get_status(pdev, status); {
} if (pdev->features & FEATURE_MOTOR_PANTILT)
else {
{ struct pwc_mpt_status *status = arg;
ret = -ENXIO; ret = pwc_mpt_get_status(pdev, status);
} }
break; else
{
ret = -ENXIO;
}
break;
} }
case VIDIOCPWCGVIDCMD: case VIDIOCPWCGVIDCMD:
{ {
struct pwc_video_command *cmd = arg; struct pwc_video_command *cmd = arg;
cmd->type = pdev->type; cmd->type = pdev->type;
cmd->release = pdev->release; cmd->release = pdev->release;
cmd->command_len = pdev->cmd_len; cmd->command_len = pdev->cmd_len;
memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len);
@ -1531,7 +1531,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
break; break;
} }
if (ret > 0) if (ret > 0)
return 0; return 0;
return ret; return ret;

View file

@ -25,18 +25,18 @@
*/ */
/* /*
This code forms the interface between the USB layers and the Philips This code forms the interface between the USB layers and the Philips
specific stuff. Some adanved stuff of the driver falls under an specific stuff. Some adanved stuff of the driver falls under an
NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
is thus not distributed in source form. The binary pwcx.o module is thus not distributed in source form. The binary pwcx.o module
contains the code that falls under the NDA. contains the code that falls under the NDA.
In case you're wondering: 'pwc' stands for "Philips WebCam", but In case you're wondering: 'pwc' stands for "Philips WebCam", but
I really didn't want to type 'philips_web_cam' every time (I'm lazy as I really didn't want to type 'philips_web_cam' every time (I'm lazy as
any Linux kernel hacker, but I don't like uncomprehensible abbreviations any Linux kernel hacker, but I don't like uncomprehensible abbreviations
without explanation). without explanation).
Oh yes, convention: to disctinguish between all the various pointers to Oh yes, convention: to disctinguish between all the various pointers to
device-structures, I use these names for the pointer variables: device-structures, I use these names for the pointer variables:
udev: struct usb_device * udev: struct usb_device *
@ -170,14 +170,14 @@ static struct video_device pwc_template = {
/* Okay, this is some magic that I worked out and the reasoning behind it... /* Okay, this is some magic that I worked out and the reasoning behind it...
The biggest problem with any USB device is of course: "what to do The biggest problem with any USB device is of course: "what to do
when the user unplugs the device while it is in use by an application?" when the user unplugs the device while it is in use by an application?"
We have several options: We have several options:
1) Curse them with the 7 plagues when they do (requires divine intervention) 1) Curse them with the 7 plagues when they do (requires divine intervention)
2) Tell them not to (won't work: they'll do it anyway) 2) Tell them not to (won't work: they'll do it anyway)
3) Oops the kernel (this will have a negative effect on a user's uptime) 3) Oops the kernel (this will have a negative effect on a user's uptime)
4) Do something sensible. 4) Do something sensible.
Of course, we go for option 4. Of course, we go for option 4.
It happens that this device will be linked to two times, once from It happens that this device will be linked to two times, once from
@ -185,15 +185,15 @@ static struct video_device pwc_template = {
pointers. This is done when the device is probed() and all initialization pointers. This is done when the device is probed() and all initialization
succeeded. The pwc_device struct links back to both structures. succeeded. The pwc_device struct links back to both structures.
When a device is unplugged while in use it will be removed from the When a device is unplugged while in use it will be removed from the
list of known USB devices; I also de-register it as a V4L device, but list of known USB devices; I also de-register it as a V4L device, but
unfortunately I can't free the memory since the struct is still in use unfortunately I can't free the memory since the struct is still in use
by the file descriptor. This free-ing is then deferend until the first by the file descriptor. This free-ing is then deferend until the first
opportunity. Crude, but it works. opportunity. Crude, but it works.
A small 'advantage' is that if a user unplugs the cam and plugs it back A small 'advantage' is that if a user unplugs the cam and plugs it back
in, it should get assigned the same video device minor, but unfortunately in, it should get assigned the same video device minor, but unfortunately
it's non-trivial to re-link the cam back to the video device... (that it's non-trivial to re-link the cam back to the video device... (that
would surely be magic! :)) would surely be magic! :))
*/ */
@ -203,14 +203,14 @@ static struct video_device pwc_template = {
/* Here we want the physical address of the memory. /* Here we want the physical address of the memory.
* This is used when initializing the contents of the area. * This is used when initializing the contents of the area.
*/ */
static inline unsigned long kvirt_to_pa(unsigned long adr) static inline unsigned long kvirt_to_pa(unsigned long adr)
{ {
unsigned long kva, ret; unsigned long kva, ret;
kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */ kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva); ret = __pa(kva);
return ret; return ret;
} }
static void * rvmalloc(unsigned long size) static void * rvmalloc(unsigned long size)
@ -219,13 +219,13 @@ static void * rvmalloc(unsigned long size)
unsigned long adr; unsigned long adr;
size=PAGE_ALIGN(size); size=PAGE_ALIGN(size);
mem=vmalloc_32(size); mem=vmalloc_32(size);
if (mem) if (mem)
{ {
memset(mem, 0, size); /* Clear the ram out, no junk to the user */ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr=(unsigned long) mem; adr=(unsigned long) mem;
while (size > 0) while (size > 0)
{ {
SetPageReserved(vmalloc_to_page((void *)adr)); SetPageReserved(vmalloc_to_page((void *)adr));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
@ -236,13 +236,13 @@ static void * rvmalloc(unsigned long size)
static void rvfree(void * mem, unsigned long size) static void rvfree(void * mem, unsigned long size)
{ {
unsigned long adr; unsigned long adr;
if (mem) if (mem)
{ {
adr=(unsigned long) mem; adr=(unsigned long) mem;
while ((long) size > 0) while ((long) size > 0)
{ {
ClearPageReserved(vmalloc_to_page((void *)adr)); ClearPageReserved(vmalloc_to_page((void *)adr));
adr+=PAGE_SIZE; adr+=PAGE_SIZE;
size-=PAGE_SIZE; size-=PAGE_SIZE;
@ -263,13 +263,13 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
if (pdev == NULL) if (pdev == NULL)
return -ENXIO; return -ENXIO;
#ifdef PWC_MAGIC #ifdef PWC_MAGIC
if (pdev->magic != PWC_MAGIC) { if (pdev->magic != PWC_MAGIC) {
Err("allocate_buffers(): magic failed.\n"); Err("allocate_buffers(): magic failed.\n");
return -ENXIO; return -ENXIO;
} }
#endif #endif
/* Allocate Isochronous pipe buffers */ /* Allocate Isochronous pipe buffers */
for (i = 0; i < MAX_ISO_BUFS; i++) { for (i = 0; i < MAX_ISO_BUFS; i++) {
if (pdev->sbuf[i].data == NULL) { if (pdev->sbuf[i].data == NULL) {
@ -308,7 +308,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
memset(kbuf, 128, PWC_FRAME_SIZE); memset(kbuf, 128, PWC_FRAME_SIZE);
} }
} }
/* Allocate decompressor table space */ /* Allocate decompressor table space */
kbuf = NULL; kbuf = NULL;
switch (pdev->type) switch (pdev->type)
@ -320,7 +320,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
case 730: case 730:
case 740: case 740:
case 750: case 750:
#if 0 #if 0
Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private)); Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private));
kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */
break; break;
@ -329,11 +329,11 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
/* TODO & FIXME */ /* TODO & FIXME */
kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
break; break;
#endif #endif
; ;
} }
pdev->decompress_data = kbuf; pdev->decompress_data = kbuf;
/* Allocate image buffer; double buffer for mmap() */ /* Allocate image buffer; double buffer for mmap() */
kbuf = rvmalloc(default_mbufs * pdev->len_per_image); kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
if (kbuf == NULL) { if (kbuf == NULL) {
@ -348,7 +348,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
pdev->image_ptr[i] = NULL; pdev->image_ptr[i] = NULL;
kbuf = NULL; kbuf = NULL;
Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
return 0; return 0;
} }
@ -366,7 +366,7 @@ static void pwc_free_buffers(struct pwc_device *pdev)
Err("free_buffers(): magic failed.\n"); Err("free_buffers(): magic failed.\n");
return; return;
} }
#endif #endif
/* Release Iso-pipe buffers */ /* Release Iso-pipe buffers */
for (i = 0; i < MAX_ISO_BUFS; i++) for (i = 0; i < MAX_ISO_BUFS; i++)
@ -403,17 +403,17 @@ static void pwc_free_buffers(struct pwc_device *pdev)
rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
} }
pdev->image_data = NULL; pdev->image_data = NULL;
Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
} }
/* The frame & image buffer mess. /* The frame & image buffer mess.
Yes, this is a mess. Well, it used to be simple, but alas... In this Yes, this is a mess. Well, it used to be simple, but alas... In this
module, 3 buffers schemes are used to get the data from the USB bus to module, 3 buffers schemes are used to get the data from the USB bus to
the user program. The first scheme involves the ISO buffers (called thus the user program. The first scheme involves the ISO buffers (called thus
since they transport ISO data from the USB controller), and not really since they transport ISO data from the USB controller), and not really
interesting. Suffices to say the data from this buffer is quickly interesting. Suffices to say the data from this buffer is quickly
gathered in an interrupt handler (pwc_isoc_handler) and placed into the gathered in an interrupt handler (pwc_isoc_handler) and placed into the
frame buffer. frame buffer.
@ -443,8 +443,8 @@ static void pwc_free_buffers(struct pwc_device *pdev)
and a 'full' frame list: and a 'full' frame list:
* Initially, all frame buffers but one are on the 'empty' list; the one * Initially, all frame buffers but one are on the 'empty' list; the one
remaining buffer is our initial fill frame. remaining buffer is our initial fill frame.
* If a frame is needed for filling, we try to take it from the 'empty' * If a frame is needed for filling, we try to take it from the 'empty'
list, unless that list is empty, in which case we take the buffer at list, unless that list is empty, in which case we take the buffer at
the head of the 'full' list. the head of the 'full' list.
* When our fill buffer has been filled, it is appended to the 'full' * When our fill buffer has been filled, it is appended to the 'full'
list. list.
@ -646,7 +646,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break;
} }
Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
/* Give up after a number of contiguous errors on the USB bus. /* Give up after a number of contiguous errors on the USB bus.
Appearantly something is wrong so we simulate an unplug event. Appearantly something is wrong so we simulate an unplug event.
*/ */
if (++pdev->visoc_errors > MAX_ISOC_ERRORS) if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
@ -673,8 +673,8 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
pdev->visoc_errors = 0; pdev->visoc_errors = 0;
/* vsync: 0 = don't copy data /* vsync: 0 = don't copy data
1 = sync-hunt 1 = sync-hunt
2 = synched 2 = synched
*/ */
/* Compact data */ /* Compact data */
for (i = 0; i < urb->number_of_packets; i++) { for (i = 0; i < urb->number_of_packets; i++) {
@ -701,18 +701,18 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
} /* ..flen > 0 */ } /* ..flen > 0 */
if (flen < pdev->vlast_packet_size) { if (flen < pdev->vlast_packet_size) {
/* Shorter packet... We probably have the end of an image-frame; /* Shorter packet... We probably have the end of an image-frame;
wake up read() process and let select()/poll() do something. wake up read() process and let select()/poll() do something.
Decompression is done in user time over there. Decompression is done in user time over there.
*/ */
if (pdev->vsync == 2) { if (pdev->vsync == 2) {
/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
frames on the USB wire after an exposure change. This conditition is frames on the USB wire after an exposure change. This conditition is
however detected in the cam and a bit is set in the header. however detected in the cam and a bit is set in the header.
*/ */
if (pdev->type == 730) { if (pdev->type == 730) {
unsigned char *ptr = (unsigned char *)fbuf->data; unsigned char *ptr = (unsigned char *)fbuf->data;
if (ptr[1] == 1 && ptr[0] & 0x10) { if (ptr[1] == 1 && ptr[0] & 0x10) {
#if PWC_DEBUG #if PWC_DEBUG
Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
@ -733,13 +733,13 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
Info("Image is normal.\n"); Info("Image is normal.\n");
} }
pdev->vmirror = ptr[0] & 0x03; pdev->vmirror = ptr[0] & 0x03;
/* Sometimes the trailer of the 730 is still sent as a 4 byte packet /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
after a short frame; this condition is filtered out specifically. A 4 byte after a short frame; this condition is filtered out specifically. A 4 byte
frame doesn't make sense anyway. frame doesn't make sense anyway.
So we get either this sequence: So we get either this sequence:
drop_bit set -> 4 byte frame -> short frame -> good frame drop_bit set -> 4 byte frame -> short frame -> good frame
Or this one: Or this one:
drop_bit set -> short frame -> good frame drop_bit set -> short frame -> good frame
So we drop either 3 or 2 frames in all! So we drop either 3 or 2 frames in all!
*/ */
if (fbuf->filled == 4) if (fbuf->filled == 4)
@ -830,7 +830,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
intf = usb_ifnum_to_if(udev, 0); intf = usb_ifnum_to_if(udev, 0);
if (intf) if (intf)
idesc = usb_altnum_to_altsetting(intf, pdev->valternate); idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
if (!idesc) if (!idesc)
return -EFAULT; return -EFAULT;
@ -841,7 +841,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
break; break;
} }
if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Err("Failed to find packet size for video endpoint in current alternate setting.\n"); Err("Failed to find packet size for video endpoint in current alternate setting.\n");
return -ENFILE; /* Odd error, that should be noticeable */ return -ENFILE; /* Odd error, that should be noticeable */
@ -875,18 +875,18 @@ static int pwc_isoc_init(struct pwc_device *pdev)
return ret; return ret;
} }
/* init URB structure */ /* init URB structure */
for (i = 0; i < MAX_ISO_BUFS; i++) { for (i = 0; i < MAX_ISO_BUFS; i++) {
urb = pdev->sbuf[i].urb; urb = pdev->sbuf[i].urb;
urb->interval = 1; // devik urb->interval = 1; // devik
urb->dev = udev; urb->dev = udev;
urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
urb->transfer_flags = URB_ISO_ASAP; urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = pdev->sbuf[i].data; urb->transfer_buffer = pdev->sbuf[i].data;
urb->transfer_buffer_length = ISO_BUFFER_SIZE; urb->transfer_buffer_length = ISO_BUFFER_SIZE;
urb->complete = pwc_isoc_handler; urb->complete = pwc_isoc_handler;
urb->context = pdev; urb->context = pdev;
urb->start_frame = 0; urb->start_frame = 0;
urb->number_of_packets = ISO_FRAMES_PER_DESC; urb->number_of_packets = ISO_FRAMES_PER_DESC;
for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
@ -935,7 +935,7 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
} }
/* Stop camera, but only if we are sure the camera is still there (unplug /* Stop camera, but only if we are sure the camera is still there (unplug
is signalled by EPIPE) is signalled by EPIPE)
*/ */
if (pdev->error_status && pdev->error_status != EPIPE) { if (pdev->error_status && pdev->error_status != EPIPE) {
Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
@ -956,12 +956,12 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
pwc_reset_buffers(pdev); pwc_reset_buffers(pdev);
/* Try to set video mode... */ /* Try to set video mode... */
start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
if (ret) { if (ret) {
Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
/* That failed... restore old mode (we know that worked) */ /* That failed... restore old mode (we know that worked) */
start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
if (start) { if (start) {
Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
} }
} }
if (start == 0) if (start == 0)
@ -987,18 +987,18 @@ static int pwc_video_open(struct inode *inode, struct file *file)
struct pwc_device *pdev; struct pwc_device *pdev;
Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
pdev = (struct pwc_device *)vdev->priv; pdev = (struct pwc_device *)vdev->priv;
if (pdev == NULL) if (pdev == NULL)
BUG(); BUG();
if (pdev->vopen) if (pdev->vopen)
return -EBUSY; return -EBUSY;
down(&pdev->modlock); down(&pdev->modlock);
if (!pdev->usb_init) { if (!pdev->usb_init) {
Trace(TRACE_OPEN, "Doing first time initialization.\n"); Trace(TRACE_OPEN, "Doing first time initialization.\n");
pdev->usb_init = 1; pdev->usb_init = 1;
if (pwc_trace & TRACE_OPEN) if (pwc_trace & TRACE_OPEN)
{ {
/* Query sensor type */ /* Query sensor type */
@ -1036,7 +1036,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
/* Set LED on/off time */ /* Set LED on/off time */
if (pwc_set_leds(pdev, led_on, led_off) < 0) if (pwc_set_leds(pdev, led_on, led_off) < 0)
Info("Failed to set LED on/off time.\n"); Info("Failed to set LED on/off time.\n");
pwc_construct(pdev); /* set min/max sizes correct */ pwc_construct(pdev); /* set min/max sizes correct */
/* So far, so good. Allocate memory. */ /* So far, so good. Allocate memory. */
@ -1046,7 +1046,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
up(&pdev->modlock); up(&pdev->modlock);
return i; return i;
} }
/* Reset buffers & parameters */ /* Reset buffers & parameters */
pwc_reset_buffers(pdev); pwc_reset_buffers(pdev);
for (i = 0; i < default_mbufs; i++) for (i = 0; i < default_mbufs; i++)
@ -1081,7 +1081,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
up(&pdev->modlock); up(&pdev->modlock);
return i; return i;
} }
i = pwc_isoc_init(pdev); i = pwc_isoc_init(pdev);
if (i) { if (i) {
Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
@ -1155,13 +1155,13 @@ static int pwc_video_close(struct inode *inode, struct file *file)
/* /*
* FIXME: what about two parallel reads ???? * FIXME: what about two parallel reads ????
* ANSWER: Not supported. You can't open the device more than once, * ANSWER: Not supported. You can't open the device more than once,
despite what the V4L1 interface says. First, I don't see despite what the V4L1 interface says. First, I don't see
the need, second there's no mechanism of alerting the the need, second there's no mechanism of alerting the
2nd/3rd/... process of events like changing image size. 2nd/3rd/... process of events like changing image size.
And I don't see the point of blocking that for the And I don't see the point of blocking that for the
2nd/3rd/... process. 2nd/3rd/... process.
In multi-threaded environments reading parallel from any In multi-threaded environments reading parallel from any
device is tricky anyhow. device is tricky anyhow.
*/ */
static ssize_t pwc_video_read(struct file *file, char __user * buf, static ssize_t pwc_video_read(struct file *file, char __user * buf,
@ -1171,7 +1171,7 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
struct pwc_device *pdev; struct pwc_device *pdev;
int noblock = file->f_flags & O_NONBLOCK; int noblock = file->f_flags & O_NONBLOCK;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int bytes_to_read; int bytes_to_read;
Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count); Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count);
if (vdev == NULL) if (vdev == NULL)
@ -1193,22 +1193,22 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
return -pdev->error_status ; return -pdev->error_status ;
} }
if (noblock) { if (noblock) {
remove_wait_queue(&pdev->frameq, &wait); remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
return -EWOULDBLOCK; return -EWOULDBLOCK;
} }
if (signal_pending(current)) { if (signal_pending(current)) {
remove_wait_queue(&pdev->frameq, &wait); remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
schedule(); schedule();
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
} }
remove_wait_queue(&pdev->frameq, &wait); remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
/* Decompress and release frame */ /* Decompress and release frame */
if (pwc_handle_frame(pdev)) if (pwc_handle_frame(pdev))
return -EFAULT; return -EFAULT;
@ -1218,7 +1218,7 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
if (pdev->vpalette == VIDEO_PALETTE_RAW) if (pdev->vpalette == VIDEO_PALETTE_RAW)
bytes_to_read = pdev->frame_size; bytes_to_read = pdev->frame_size;
else else
bytes_to_read = pdev->view.size; bytes_to_read = pdev->view.size;
/* copy bytes to user space; we allow for partial reads */ /* copy bytes to user space; we allow for partial reads */
if (count + pdev->image_read_pos > bytes_to_read) if (count + pdev->image_read_pos > bytes_to_read)
@ -1348,11 +1348,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
struct video_picture *p = arg; struct video_picture *p = arg;
/* /*
* FIXME: Suppose we are mid read * FIXME: Suppose we are mid read
ANSWER: No problem: the firmware of the camera ANSWER: No problem: the firmware of the camera
can handle brightness/contrast/etc can handle brightness/contrast/etc
changes at _any_ time, and the palette changes at _any_ time, and the palette
is used exactly once in the uncompress is used exactly once in the uncompress
routine. routine.
*/ */
pwc_set_brightness(pdev, p->brightness); pwc_set_brightness(pdev, p->brightness);
pwc_set_contrast(pdev, p->contrast); pwc_set_contrast(pdev, p->contrast);
@ -1373,21 +1373,21 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
break; break;
} }
/* Window/size parameters */ /* Window/size parameters */
case VIDIOCGWIN: case VIDIOCGWIN:
{ {
struct video_window *vw = arg; struct video_window *vw = arg;
vw->x = 0; vw->x = 0;
vw->y = 0; vw->y = 0;
vw->width = pdev->view.x; vw->width = pdev->view.x;
vw->height = pdev->view.y; vw->height = pdev->view.y;
vw->chromakey = 0; vw->chromakey = 0;
vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
(pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
break; break;
} }
case VIDIOCSWIN: case VIDIOCSWIN:
{ {
struct video_window *vw = arg; struct video_window *vw = arg;
@ -1402,9 +1402,9 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
if (ret) if (ret)
return ret; return ret;
break; break;
} }
/* We don't have overlay support (yet) */ /* We don't have overlay support (yet) */
case VIDIOCGFBUF: case VIDIOCGFBUF:
{ {
@ -1471,8 +1471,8 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return -EBUSY; /* buffer wasn't available. Bummer */ return -EBUSY; /* buffer wasn't available. Bummer */
pdev->image_used[vm->frame] = 1; pdev->image_used[vm->frame] = 1;
/* Okay, we're done here. In the SYNC call we wait until a /* Okay, we're done here. In the SYNC call we wait until a
frame comes available, then expand image into the given frame comes available, then expand image into the given
buffer. buffer.
In contrast to the CPiA cam the Philips cams deliver a In contrast to the CPiA cam the Philips cams deliver a
constant stream, almost like a grabber card. Also, constant stream, almost like a grabber card. Also,
@ -1487,16 +1487,16 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
{ {
/* The doc says: "Whenever a buffer is used it should /* The doc says: "Whenever a buffer is used it should
call VIDIOCSYNC to free this frame up and continue." call VIDIOCSYNC to free this frame up and continue."
The only odd thing about this whole procedure is The only odd thing about this whole procedure is
that MCAPTURE flags the buffer as "in use", and that MCAPTURE flags the buffer as "in use", and
SYNC immediately unmarks it, while it isn't SYNC immediately unmarks it, while it isn't
after SYNC that you know that the buffer actually after SYNC that you know that the buffer actually
got filled! So you better not start a CAPTURE in got filled! So you better not start a CAPTURE in
the same frame immediately (use double buffering). the same frame immediately (use double buffering).
This is not a problem for this cam, since it has This is not a problem for this cam, since it has
extra intermediate buffers, but a hardware extra intermediate buffers, but a hardware
grabber card will then overwrite the buffer grabber card will then overwrite the buffer
you're working on. you're working on.
*/ */
int *mbuf = arg; int *mbuf = arg;
@ -1512,10 +1512,10 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
/* Add ourselves to the frame wait-queue. /* Add ourselves to the frame wait-queue.
FIXME: needs auditing for safety. FIXME: needs auditing for safety.
QUESTION: In what respect? I think that using the QUESTION: In what respect? I think that using the
frameq is safe now. frameq is safe now.
*/ */
add_wait_queue(&pdev->frameq, &wait); add_wait_queue(&pdev->frameq, &wait);
while (pdev->full_frames == NULL) { while (pdev->full_frames == NULL) {
@ -1524,21 +1524,21 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
return -pdev->error_status; return -pdev->error_status;
} }
if (signal_pending(current)) { if (signal_pending(current)) {
remove_wait_queue(&pdev->frameq, &wait); remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
schedule(); schedule();
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
} }
remove_wait_queue(&pdev->frameq, &wait); remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
/* The frame is ready. Expand in the image buffer /* The frame is ready. Expand in the image buffer
requested by the user. I don't care if you requested by the user. I don't care if you
mmap() 5 buffers and request data in this order: mmap() 5 buffers and request data in this order:
buffer 4 2 3 0 1 2 3 0 4 3 1 . . . buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
Grabber hardware may not be so forgiving. Grabber hardware may not be so forgiving.
*/ */
@ -1551,11 +1551,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return -EFAULT; return -EFAULT;
break; break;
} }
case VIDIOCGAUDIO: case VIDIOCGAUDIO:
{ {
struct video_audio *v = arg; struct video_audio *v = arg;
strcpy(v->name, "Microphone"); strcpy(v->name, "Microphone");
v->audio = -1; /* unknown audio minor */ v->audio = -1; /* unknown audio minor */
v->flags = 0; v->flags = 0;
@ -1565,19 +1565,19 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
v->treble = 0; v->treble = 0;
v->balance = 0x8000; v->balance = 0x8000;
v->step = 1; v->step = 1;
break; break;
} }
case VIDIOCSAUDIO: case VIDIOCSAUDIO:
{ {
/* Dummy: nothing can be set */ /* Dummy: nothing can be set */
break; break;
} }
case VIDIOCGUNIT: case VIDIOCGUNIT:
{ {
struct video_unit *vu = arg; struct video_unit *vu = arg;
vu->video = pdev->vdev->minor & 0x3F; vu->video = pdev->vdev->minor & 0x3F;
vu->audio = -1; /* not known yet */ vu->audio = -1; /* not known yet */
vu->vbi = -1; vu->vbi = -1;
@ -1589,7 +1589,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return pwc_ioctl(pdev, cmd, arg); return pwc_ioctl(pdev, cmd, arg);
} /* ..switch */ } /* ..switch */
return 0; return 0;
} }
static int pwc_video_ioctl(struct inode *inode, struct file *file, static int pwc_video_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
@ -1605,10 +1605,10 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long start = vma->vm_start; unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end-vma->vm_start; unsigned long size = vma->vm_end-vma->vm_start;
unsigned long page, pos; unsigned long page, pos;
Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size); Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
pdev = vdev->priv; pdev = vdev->priv;
vma->vm_flags |= VM_IO; vma->vm_flags |= VM_IO;
pos = (unsigned long)pdev->image_data; pos = (unsigned long)pdev->image_data;
@ -1646,7 +1646,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
char serial_number[30], *name; char serial_number[30], *name;
/* Check if we can handle this device */ /* Check if we can handle this device */
Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct), le16_to_cpu(udev->descriptor.idProduct),
intf->altsetting->desc.bInterfaceNumber); intf->altsetting->desc.bInterfaceNumber);
@ -1770,11 +1770,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
name = "Logitech QuickCam (res.)"; name = "Logitech QuickCam (res.)";
type_id = 730; /* Assuming CMOS */ type_id = 730; /* Assuming CMOS */
break; break;
default: default:
return -ENODEV; return -ENODEV;
break; break;
} }
} }
else if (vendor_id == 0x055d) { else if (vendor_id == 0x055d) {
/* I don't know the difference between the C10 and the C30; /* I don't know the difference between the C10 and the C30;
I suppose the difference is the sensor, but both cameras I suppose the difference is the sensor, but both cameras
@ -1837,7 +1837,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return -ENODEV; return -ENODEV;
break; break;
} }
} }
else if (vendor_id == 0x0d81) { else if (vendor_id == 0x0d81) {
switch(product_id) { switch(product_id) {
@ -1856,7 +1856,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break; break;
} }
} }
else else
return -ENODEV; /* Not any of the know types; but the list keeps growing. */ return -ENODEV; /* Not any of the know types; but the list keeps growing. */
memset(serial_number, 0, 30); memset(serial_number, 0, 30);
@ -1880,9 +1880,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (vendor_id == 0x046D && product_id == 0x08B5) if (vendor_id == 0x046D && product_id == 0x08B5)
{ {
/* Logitech QuickCam Orbit /* Logitech QuickCam Orbit
The ranges have been determined experimentally; they may differ from cam to cam. The ranges have been determined experimentally; they may differ from cam to cam.
Also, the exact ranges left-right and up-down are different for my cam Also, the exact ranges left-right and up-down are different for my cam
*/ */
pdev->angle_range.pan_min = -7000; pdev->angle_range.pan_min = -7000;
pdev->angle_range.pan_max = 7000; pdev->angle_range.pan_max = 7000;
pdev->angle_range.tilt_min = -3000; pdev->angle_range.tilt_min = -3000;
@ -1939,7 +1939,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
} }
/* occupy slot */ /* occupy slot */
if (hint < MAX_DEV_HINTS) if (hint < MAX_DEV_HINTS)
device_hint[hint].pdev = pdev; device_hint[hint].pdev = pdev;
Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev); Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
@ -1968,13 +1968,13 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
goto disconnect_out; goto disconnect_out;
} }
#ifdef PWC_MAGIC #ifdef PWC_MAGIC
if (pdev->magic != PWC_MAGIC) { if (pdev->magic != PWC_MAGIC) {
Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
goto disconnect_out; goto disconnect_out;
} }
#endif #endif
/* We got unplugged; this is signalled by an EPIPE error code */ /* We got unplugged; this is signalled by an EPIPE error code */
if (pdev->vopen) { if (pdev->vopen) {
Info("Disconnected while webcam is in use!\n"); Info("Disconnected while webcam is in use!\n");
@ -2017,8 +2017,8 @@ static int pwc_atoi(const char *s)
} }
/* /*
* Initialization code & module stuff * Initialization code & module stuff
*/ */
static char size[10]; static char size[10];
@ -2168,7 +2168,7 @@ static int __init usb_pwc_init(void)
if (*dot != '\0') { if (*dot != '\0') {
/* There's a serial number as well */ /* There's a serial number as well */
int k; int k;
dot++; dot++;
k = 0; k = 0;
while (*dot != ':' && k < 29) { while (*dot != ':' && k < 29) {
@ -2178,18 +2178,18 @@ static int __init usb_pwc_init(void)
device_hint[i].serial_number[k] = '\0'; device_hint[i].serial_number[k] = '\0';
} }
} }
#if PWC_DEBUG #if PWC_DEBUG
Debug("device_hint[%d]:\n", i); Debug("device_hint[%d]:\n", i);
Debug(" type : %d\n", device_hint[i].type); Debug(" type : %d\n", device_hint[i].type);
Debug(" serial# : %s\n", device_hint[i].serial_number); Debug(" serial# : %s\n", device_hint[i].serial_number);
Debug(" node : %d\n", device_hint[i].device_node); Debug(" node : %d\n", device_hint[i].device_node);
#endif #endif
} }
else else
device_hint[i].type = 0; /* not filled */ device_hint[i].type = 0; /* not filled */
} /* ..for MAX_DEV_HINTS */ } /* ..for MAX_DEV_HINTS */
Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
return usb_register(&pwc_driver); return usb_register(&pwc_driver);
} }

View file

@ -33,10 +33,10 @@
/* /*
Changes Changes
2001/08/03 Alvarado Added ioctl constants to access methods for 2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains changing white balance and red/blue gains
2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
2003/12/13 Nemosft Unv. Some modifications to make interfacing to 2003/12/13 Nemosft Unv. Some modifications to make interfacing to
PWCX easier PWCX easier
*/ */
/* These are private ioctl() commands, specific for the Philips webcams. /* These are private ioctl() commands, specific for the Philips webcams.
@ -45,10 +45,10 @@
The #define names are built up like follows: The #define names are built up like follows:
VIDIOC VIDeo IOCtl prefix VIDIOC VIDeo IOCtl prefix
PWC Philps WebCam PWC Philps WebCam
G optional: Get G optional: Get
S optional: Set S optional: Set
... the function ... the function
*/ */
@ -94,7 +94,7 @@ struct pwc_serial
{ {
char serial[30]; /* String with serial number. Contains terminating 0 */ char serial[30]; /* String with serial number. Contains terminating 0 */
}; };
/* pwc_whitebalance.mode values */ /* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0 #define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1 #define PWC_WB_OUTDOOR 1
@ -102,14 +102,14 @@ struct pwc_serial
#define PWC_WB_MANUAL 3 #define PWC_WB_MANUAL 3
#define PWC_WB_AUTO 4 #define PWC_WB_AUTO 4
/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). /* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
Set mode to one of the PWC_WB_* values above. Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside *red and *blue are the respective gains of these colour components inside
the camera; range 0..65535 the camera; range 0..65535
When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
otherwise undefined. otherwise undefined.
'read_red' and 'read_blue' are read-only. 'read_red' and 'read_blue' are read-only.
*/ */
struct pwc_whitebalance struct pwc_whitebalance
{ {
int mode; int mode;
@ -117,9 +117,9 @@ struct pwc_whitebalance
int read_red, read_blue; /* R/O */ int read_red, read_blue; /* R/O */
}; };
/* /*
'control_speed' and 'control_delay' are used in automatic whitebalance mode, 'control_speed' and 'control_delay' are used in automatic whitebalance mode,
and tell the camera how fast it should react to changes in lighting, and and tell the camera how fast it should react to changes in lighting, and
with how much delay. Valid values are 0..65535. with how much delay. Valid values are 0..65535.
*/ */
struct pwc_wb_speed struct pwc_wb_speed
@ -148,11 +148,11 @@ struct pwc_imagesize
#define PWC_MPT_TILT 0x02 #define PWC_MPT_TILT 0x02
#define PWC_MPT_TIMEOUT 0x04 /* for status */ #define PWC_MPT_TIMEOUT 0x04 /* for status */
/* Set angles; when absolute != 0, the angle is absolute and the /* Set angles; when absolute != 0, the angle is absolute and the
driver calculates the relative offset for you. This can only driver calculates the relative offset for you. This can only
be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
absolute angles. absolute angles.
*/ */
struct pwc_mpt_angles struct pwc_mpt_angles
{ {
int absolute; /* write-only */ int absolute; /* write-only */
@ -179,14 +179,14 @@ struct pwc_mpt_status
/* This is used for out-of-kernel decompression. With it, you can get /* This is used for out-of-kernel decompression. With it, you can get
all the necessary information to initialize and use the decompressor all the necessary information to initialize and use the decompressor
routines in standalone applications. routines in standalone applications.
*/ */
struct pwc_video_command struct pwc_video_command
{ {
int type; /* camera type (645, 675, 730, etc.) */ int type; /* camera type (645, 675, 730, etc.) */
int release; /* release number */ int release; /* release number */
int size; /* one of PSZ_* */ int size; /* one of PSZ_* */
int alternate; int alternate;
int command_len; /* length of USB video command */ int command_len; /* length of USB video command */
unsigned char command_buf[13]; /* Actual USB video command */ unsigned char command_buf[13]; /* Actual USB video command */
int bandlength; /* >0 = compressed */ int bandlength; /* >0 = compressed */
@ -264,7 +264,7 @@ struct pwc_video_command
/* Flickerless mode; = 0 off, otherwise on */ /* Flickerless mode; = 0 off, otherwise on */
#define VIDIOCPWCSFLICKER _IOW('v', 208, int) #define VIDIOCPWCSFLICKER _IOW('v', 208, int)
#define VIDIOCPWCGFLICKER _IOR('v', 208, int) #define VIDIOCPWCGFLICKER _IOR('v', 208, int)
/* Dynamic noise reduction; 0 off, 3 = high noise reduction */ /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) #define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
@ -273,7 +273,7 @@ struct pwc_video_command
/* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) #define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize)
/* Motorized pan & tilt functions */ /* Motorized pan & tilt functions */
#define VIDIOCPWCMPTRESET _IOW('v', 211, int) #define VIDIOCPWCMPTRESET _IOW('v', 211, int)
#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range) #define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range)
#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles) #define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)

View file

@ -0,0 +1,318 @@
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This tables contains entries for the 730/740/750 (Kiara) camera, with
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
*/
#include "pwc-kiara.h"
#include "pwc-uncompress.h"
const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
{
/* SQCIF */
{
/* 5 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 10 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 15 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
/* QSIF */
{
/* 5 fps */
{
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
},
/* 10 fps */
{
{2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
{1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
{1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
{1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
},
/* 15 fps */
{
{3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
{2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
{2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
{1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
},
/* 20 fps */
{
{4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
{3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
{2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
{1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
},
/* 25 fps */
{
{5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
{3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
{2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
{1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
},
/* 30 fps */
{
{8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
{5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
{3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
{2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
},
},
/* QCIF */
{
/* 5 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 10 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 15 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
/* SIF */
{
/* 5 fps */
{
{4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
{3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
{2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
{1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
},
/* 10 fps */
{
{0, },
{6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
{3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
{2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
},
/* 15 fps */
{
{0, },
{9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
{4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
{3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
},
/* 20 fps */
{
{0, },
{9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
{5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
{3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
},
/* 25 fps */
{
{0, },
{9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
{6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
{4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
},
/* 30 fps */
{
{0, },
{9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
{6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
{4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
},
},
/* CIF */
{
/* 5 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 10 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 15 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
/* VGA */
{
/* 5 fps */
{
{0, },
{6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
{4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
{3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
},
/* 10 fps */
{
{0, },
{9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
{6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
{4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
},
/* 15 fps */
{
{0, },
{9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
{9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
{8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
};

View file

@ -1,4 +1,4 @@
/* Linux driver for Philips webcam /* Linux driver for Philips webcam
Various miscellaneous functions and tables. Various miscellaneous functions and tables.
(C) 1999-2003 Nemosoft Unv. (C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org) (C) 2004 Luc Saillard (luc@saillard.org)
@ -44,17 +44,17 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
int i, find; int i, find;
/* Make sure we don't go beyond our max size. /* Make sure we don't go beyond our max size.
NB: we have different limits for RAW and normal modes. In case NB: we have different limits for RAW and normal modes. In case
you don't have the decompressor loaded or use RAW mode, you don't have the decompressor loaded or use RAW mode,
the maximum viewable size is smaller. the maximum viewable size is smaller.
*/ */
if (pdev->vpalette == VIDEO_PALETTE_RAW) if (pdev->vpalette == VIDEO_PALETTE_RAW)
{ {
if (width > pdev->abs_max.x || height > pdev->abs_max.y) if (width > pdev->abs_max.x || height > pdev->abs_max.y)
{ {
Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
return -1; return -1;
} }
} }
else else
{ {
@ -88,8 +88,8 @@ void pwc_construct(struct pwc_device *pdev)
pdev->view_min.y = 96; pdev->view_min.y = 96;
pdev->view_max.x = 352; pdev->view_max.x = 352;
pdev->view_max.y = 288; pdev->view_max.y = 288;
pdev->abs_max.x = 352; pdev->abs_max.x = 352;
pdev->abs_max.y = 288; pdev->abs_max.y = 288;
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
pdev->vcinterface = 2; pdev->vcinterface = 2;
pdev->vendpoint = 4; pdev->vendpoint = 4;
@ -105,8 +105,8 @@ void pwc_construct(struct pwc_device *pdev)
pdev->view_max.x = 640; pdev->view_max.x = 640;
pdev->view_max.y = 480; pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
pdev->abs_max.x = 640; pdev->abs_max.x = 640;
pdev->abs_max.y = 480; pdev->abs_max.y = 480;
pdev->vcinterface = 3; pdev->vcinterface = 3;
pdev->vendpoint = 4; pdev->vendpoint = 4;
pdev->frame_header_size = 0; pdev->frame_header_size = 0;
@ -121,8 +121,8 @@ void pwc_construct(struct pwc_device *pdev)
pdev->view_max.x = 640; pdev->view_max.x = 640;
pdev->view_max.y = 480; pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
pdev->abs_max.x = 640; pdev->abs_max.x = 640;
pdev->abs_max.y = 480; pdev->abs_max.y = 480;
pdev->vcinterface = 3; pdev->vcinterface = 3;
pdev->vendpoint = 5; pdev->vendpoint = 5;
pdev->frame_header_size = TOUCAM_HEADER_SIZE; pdev->frame_header_size = TOUCAM_HEADER_SIZE;

View file

@ -54,7 +54,7 @@
{0}, {0},
}, },
/* VGA */ /* VGA */
{ {
{0}, {0},
{0}, {0},
{0}, {0},

View file

@ -0,0 +1,316 @@
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This tables contains entries for the 675/680/690 (Timon) camera, with
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
*/
#include "pwc-timon.h"
const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
{
/* SQCIF */
{
/* 5 fps */
{
{1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
{1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
{1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
{1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
},
/* 10 fps */
{
{2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
{2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
{2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
{2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
},
/* 15 fps */
{
{3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
{3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
{3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
{3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
},
/* 20 fps */
{
{4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
{4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
{4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
{4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
},
/* 25 fps */
{
{5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
{5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
{5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
{5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
},
/* 30 fps */
{
{7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
{7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
{7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
{7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
},
},
/* QSIF */
{
/* 5 fps */
{
{1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
{1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
{1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
{1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
},
/* 10 fps */
{
{2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
{1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
{1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
{1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
},
/* 15 fps */
{
{3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
{2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
{2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
{1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
},
/* 20 fps */
{
{4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
{3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
{2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
{1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
},
/* 25 fps */
{
{5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
{3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
{2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
{1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
},
/* 30 fps */
{
{8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
{5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
{3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
{2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
},
},
/* QCIF */
{
/* 5 fps */
{
{1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
{1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
{1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
{1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
},
/* 10 fps */
{
{3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
{2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
{2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
{1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
},
/* 15 fps */
{
{4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
{3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
{2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
{1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
},
/* 20 fps */
{
{6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
{4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
{3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
{2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
},
/* 25 fps */
{
{9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
{5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
{3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
{2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
},
/* 30 fps */
{
{0, },
{9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
{4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
{2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
},
},
/* SIF */
{
/* 5 fps */
{
{4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
{3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
{2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
{1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
},
/* 10 fps */
{
{0, },
{6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
{3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
{2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
},
/* 15 fps */
{
{0, },
{9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
{4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
{3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
},
/* 20 fps */
{
{0, },
{9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
{5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
{3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
},
/* 25 fps */
{
{0, },
{9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
{6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
{4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
},
/* 30 fps */
{
{0, },
{9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
{6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
{4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
},
},
/* CIF */
{
/* 5 fps */
{
{6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
{4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
{2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
{1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
},
/* 10 fps */
{
{0, },
{9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
{4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
{2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
},
/* 15 fps */
{
{0, },
{9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
{5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
{3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
},
/* 20 fps */
{
{0, },
{9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
{6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
{4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
},
/* 25 fps */
{
{0, },
{9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
{7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
{5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
},
/* 30 fps */
{
{0, },
{9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
{7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
{6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
},
},
/* VGA */
{
/* 5 fps */
{
{0, },
{6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
{4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
{3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
},
/* 10 fps */
{
{0, },
{9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
{6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
{4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
},
/* 15 fps */
{
{0, },
{9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
{9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
{8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
};

View file

@ -109,9 +109,9 @@ int pwc_decompress(struct pwc_device *pdev)
in planar format immediately. in planar format immediately.
*/ */
int flags; int flags;
flags = PWCX_FLAG_PLANAR; flags = PWCX_FLAG_PLANAR;
if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
{ {
printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n"); printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
flags |= PWCX_FLAG_BAYER; flags |= PWCX_FLAG_BAYER;

Some files were not shown because too many files have changed in this diff Show more