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
@ -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;
@ -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?
@ -225,54 +225,54 @@ 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) {
@ -324,12 +324,12 @@ 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 {
@ -341,13 +341,13 @@ int main(int argc, char ** argv)
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;
} }
} }
} }
} }
@ -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);

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

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

View file

@ -14,7 +14,7 @@ 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)

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

@ -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

@ -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:
{ {

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

@ -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

@ -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. */

View file

@ -67,11 +67,11 @@ MODULE_SUPPORTED_DEVICE("video");
static unsigned short colorspace_conv = 0; static unsigned short colorspace_conv = 0;
module_param(colorspace_conv, ushort, 0444); module_param(colorspace_conv, ushort, 0444);
MODULE_PARM_DESC(colorspace_conv, MODULE_PARM_DESC(colorspace_conv,
"\n<n> Colorspace conversion:" "\n<n> Colorspace conversion:"
"\n0 = disable" "\n0 = disable"
"\n1 = enable" "\n1 = enable"
"\nDefault value is 0" "\nDefault value is 0"
"\n"); "\n");
#define ABOUT "V4L-Driver for Vision CPiA based cameras" #define ABOUT "V4L-Driver for Vision CPiA based cameras"
@ -208,7 +208,7 @@ static u8 flicker_jumps[2][2][4] =
static void reset_camera_struct(struct cam_data *cam); static void reset_camera_struct(struct cam_data *cam);
static int find_over_exposure(int brightness); static int find_over_exposure(int brightness);
static void set_flicker(struct cam_params *params, volatile u32 *command_flags, static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
int on); int on);
/********************************************************************** /**********************************************************************
@ -262,7 +262,7 @@ static void rvfree(void *mem, unsigned long size)
static struct proc_dir_entry *cpia_proc_root=NULL; static struct proc_dir_entry *cpia_proc_root=NULL;
static int cpia_read_proc(char *page, char **start, off_t off, static int cpia_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
char *out = page; char *out = page;
int len, tmp; int len, tmp;
@ -276,58 +276,58 @@ static int cpia_read_proc(char *page, char **start, off_t off,
out += sprintf(out, "V4L Driver version: %d.%d.%d\n", out += sprintf(out, "V4L Driver version: %d.%d.%d\n",
CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n", out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n",
cam->params.version.firmwareVersion, cam->params.version.firmwareVersion,
cam->params.version.firmwareRevision, cam->params.version.firmwareRevision,
cam->params.version.vcVersion, cam->params.version.vcVersion,
cam->params.version.vcRevision); cam->params.version.vcRevision);
out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n", out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n",
cam->params.pnpID.vendor, cam->params.pnpID.product, cam->params.pnpID.vendor, cam->params.pnpID.product,
cam->params.pnpID.deviceRevision); cam->params.pnpID.deviceRevision);
out += sprintf(out, "VP-Version: %d.%d %04x\n", out += sprintf(out, "VP-Version: %d.%d %04x\n",
cam->params.vpVersion.vpVersion, cam->params.vpVersion.vpVersion,
cam->params.vpVersion.vpRevision, cam->params.vpVersion.vpRevision,
cam->params.vpVersion.cameraHeadID); cam->params.vpVersion.cameraHeadID);
out += sprintf(out, "system_state: %#04x\n", out += sprintf(out, "system_state: %#04x\n",
cam->params.status.systemState); cam->params.status.systemState);
out += sprintf(out, "grab_state: %#04x\n", out += sprintf(out, "grab_state: %#04x\n",
cam->params.status.grabState); cam->params.status.grabState);
out += sprintf(out, "stream_state: %#04x\n", out += sprintf(out, "stream_state: %#04x\n",
cam->params.status.streamState); cam->params.status.streamState);
out += sprintf(out, "fatal_error: %#04x\n", out += sprintf(out, "fatal_error: %#04x\n",
cam->params.status.fatalError); cam->params.status.fatalError);
out += sprintf(out, "cmd_error: %#04x\n", out += sprintf(out, "cmd_error: %#04x\n",
cam->params.status.cmdError); cam->params.status.cmdError);
out += sprintf(out, "debug_flags: %#04x\n", out += sprintf(out, "debug_flags: %#04x\n",
cam->params.status.debugFlags); cam->params.status.debugFlags);
out += sprintf(out, "vp_status: %#04x\n", out += sprintf(out, "vp_status: %#04x\n",
cam->params.status.vpStatus); cam->params.status.vpStatus);
out += sprintf(out, "error_code: %#04x\n", out += sprintf(out, "error_code: %#04x\n",
cam->params.status.errorCode); cam->params.status.errorCode);
/* QX3 specific entries */ /* QX3 specific entries */
if (cam->params.qx3.qx3_detected) { if (cam->params.qx3.qx3_detected) {
out += sprintf(out, "button: %4d\n", out += sprintf(out, "button: %4d\n",
cam->params.qx3.button); cam->params.qx3.button);
out += sprintf(out, "cradled: %4d\n", out += sprintf(out, "cradled: %4d\n",
cam->params.qx3.cradled); cam->params.qx3.cradled);
} }
out += sprintf(out, "video_size: %s\n", out += sprintf(out, "video_size: %s\n",
cam->params.format.videoSize == VIDEOSIZE_CIF ? cam->params.format.videoSize == VIDEOSIZE_CIF ?
"CIF " : "QCIF"); "CIF " : "QCIF");
out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n", out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n",
cam->params.roi.colStart*8, cam->params.roi.colStart*8,
cam->params.roi.rowStart*4, cam->params.roi.rowStart*4,
cam->params.roi.colEnd*8, cam->params.roi.colEnd*8,
cam->params.roi.rowEnd*4); cam->params.roi.rowEnd*4);
out += sprintf(out, "actual_fps: %3d\n", cam->fps); out += sprintf(out, "actual_fps: %3d\n", cam->fps);
out += sprintf(out, "transfer_rate: %4dkB/s\n", out += sprintf(out, "transfer_rate: %4dkB/s\n",
cam->transfer_rate); cam->transfer_rate);
out += sprintf(out, "\nread-write\n"); out += sprintf(out, "\nread-write\n");
out += sprintf(out, "----------------------- current min" out += sprintf(out, "----------------------- current min"
" max default comment\n"); " max default comment\n");
out += sprintf(out, "brightness: %8d %8d %8d %8d\n", out += sprintf(out, "brightness: %8d %8d %8d %8d\n",
cam->params.colourParams.brightness, 0, 100, 50); cam->params.colourParams.brightness, 0, 100, 50);
if (cam->params.version.firmwareVersion == 1 && if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2) cam->params.version.firmwareRevision == 2)
/* 1-02 firmware limits contrast to 80 */ /* 1-02 firmware limits contrast to 80 */
@ -336,26 +336,26 @@ static int cpia_read_proc(char *page, char **start, off_t off,
tmp = 96; tmp = 96;
out += sprintf(out, "contrast: %8d %8d %8d %8d" out += sprintf(out, "contrast: %8d %8d %8d %8d"
" steps of 8\n", " steps of 8\n",
cam->params.colourParams.contrast, 0, tmp, 48); cam->params.colourParams.contrast, 0, tmp, 48);
out += sprintf(out, "saturation: %8d %8d %8d %8d\n", out += sprintf(out, "saturation: %8d %8d %8d %8d\n",
cam->params.colourParams.saturation, 0, 100, 50); cam->params.colourParams.saturation, 0, 100, 50);
tmp = (25000+5000*cam->params.sensorFps.baserate)/ tmp = (25000+5000*cam->params.sensorFps.baserate)/
(1<<cam->params.sensorFps.divisor); (1<<cam->params.sensorFps.divisor);
out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n", out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n",
tmp/1000, tmp%1000, 3, 30, 15); tmp/1000, tmp%1000, 3, 30, 15);
out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n", out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n",
2*cam->params.streamStartLine, 0, 2*cam->params.streamStartLine, 0,
cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144, cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120); cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
out += sprintf(out, "sub_sample: %8s %8s %8s %8s\n", out += sprintf(out, "sub_sample: %8s %8s %8s %8s\n",
cam->params.format.subSample == SUBSAMPLE_420 ? cam->params.format.subSample == SUBSAMPLE_420 ?
"420" : "422", "420", "422", "422"); "420" : "422", "420", "422", "422");
out += sprintf(out, "yuv_order: %8s %8s %8s %8s\n", out += sprintf(out, "yuv_order: %8s %8s %8s %8s\n",
cam->params.format.yuvOrder == YUVORDER_YUYV ? cam->params.format.yuvOrder == YUVORDER_YUYV ?
"YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV"); "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV");
out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n", out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n",
cam->params.ecpTiming ? "slow" : "normal", "slow", cam->params.ecpTiming ? "slow" : "normal", "slow",
"normal", "normal"); "normal", "normal");
if (cam->params.colourBalance.balanceMode == 2) { if (cam->params.colourBalance.balanceMode == 2) {
@ -366,11 +366,11 @@ static int cpia_read_proc(char *page, char **start, off_t off,
out += sprintf(out, "color_balance_mode: %8s %8s %8s" out += sprintf(out, "color_balance_mode: %8s %8s %8s"
" %8s\n", tmpstr, "manual", "auto", "auto"); " %8s\n", tmpstr, "manual", "auto", "auto");
out += sprintf(out, "red_gain: %8d %8d %8d %8d\n", out += sprintf(out, "red_gain: %8d %8d %8d %8d\n",
cam->params.colourBalance.redGain, 0, 212, 32); cam->params.colourBalance.redGain, 0, 212, 32);
out += sprintf(out, "green_gain: %8d %8d %8d %8d\n", out += sprintf(out, "green_gain: %8d %8d %8d %8d\n",
cam->params.colourBalance.greenGain, 0, 212, 6); cam->params.colourBalance.greenGain, 0, 212, 6);
out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n", out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n",
cam->params.colourBalance.blueGain, 0, 212, 92); cam->params.colourBalance.blueGain, 0, 212, 92);
if (cam->params.version.firmwareVersion == 1 && if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2) cam->params.version.firmwareRevision == 2)
@ -381,11 +381,11 @@ static int cpia_read_proc(char *page, char **start, off_t off,
if (cam->params.exposure.gainMode == 0) if (cam->params.exposure.gainMode == 0)
out += sprintf(out, "max_gain: unknown %28s" out += sprintf(out, "max_gain: unknown %28s"
" powers of 2\n", tmpstr); " powers of 2\n", tmpstr);
else else
out += sprintf(out, "max_gain: %8d %28s" out += sprintf(out, "max_gain: %8d %28s"
" 1,2,4 or 8 \n", " 1,2,4 or 8 \n",
1<<(cam->params.exposure.gainMode-1), tmpstr); 1<<(cam->params.exposure.gainMode-1), tmpstr);
switch(cam->params.exposure.expMode) { switch(cam->params.exposure.expMode) {
case 1: case 1:
@ -402,10 +402,10 @@ static int cpia_read_proc(char *page, char **start, off_t off,
out += sprintf(out, "exposure_mode: %8s %8s %8s" out += sprintf(out, "exposure_mode: %8s %8s %8s"
" %8s\n", tmpstr, "manual", "auto", "auto"); " %8s\n", tmpstr, "manual", "auto", "auto");
out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n", out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n",
(2-cam->params.exposure.centreWeight) ? "on" : "off", (2-cam->params.exposure.centreWeight) ? "on" : "off",
"off", "on", "on"); "off", "on", "on");
out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n",
1<<cam->params.exposure.gain, 1, 1); 1<<cam->params.exposure.gain, 1, 1);
if (cam->params.version.firmwareVersion == 1 && if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2) cam->params.version.firmwareRevision == 2)
/* 1-02 firmware limits fineExp/2 to 127 */ /* 1-02 firmware limits fineExp/2 to 127 */
@ -414,7 +414,7 @@ static int cpia_read_proc(char *page, char **start, off_t off,
tmp = 510; tmp = 510;
out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n", out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n",
cam->params.exposure.fineExp*2, 0, tmp, 0); cam->params.exposure.fineExp*2, 0, tmp, 0);
if (cam->params.version.firmwareVersion == 1 && if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2) cam->params.version.firmwareRevision == 2)
/* 1-02 firmware limits coarseExpHi to 0 */ /* 1-02 firmware limits coarseExpHi to 0 */
@ -426,46 +426,46 @@ static int cpia_read_proc(char *page, char **start, off_t off,
" %8d\n", cam->params.exposure.coarseExpLo+ " %8d\n", cam->params.exposure.coarseExpLo+
256*cam->params.exposure.coarseExpHi, 0, tmp, 185); 256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
out += sprintf(out, "red_comp: %8d %8d %8d %8d\n", out += sprintf(out, "red_comp: %8d %8d %8d %8d\n",
cam->params.exposure.redComp, COMP_RED, 255, COMP_RED); cam->params.exposure.redComp, COMP_RED, 255, COMP_RED);
out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n", out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n",
cam->params.exposure.green1Comp, COMP_GREEN1, 255, cam->params.exposure.green1Comp, COMP_GREEN1, 255,
COMP_GREEN1); COMP_GREEN1);
out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n", out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n",
cam->params.exposure.green2Comp, COMP_GREEN2, 255, cam->params.exposure.green2Comp, COMP_GREEN2, 255,
COMP_GREEN2); COMP_GREEN2);
out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n", out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n",
cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE); cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE);
out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n", out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain1, 0, 0xff, 0x1c); cam->params.apcor.gain1, 0, 0xff, 0x1c);
out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n", out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain2, 0, 0xff, 0x1a); cam->params.apcor.gain2, 0, 0xff, 0x1a);
out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n", out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain4, 0, 0xff, 0x2d); cam->params.apcor.gain4, 0, 0xff, 0x2d);
out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n", out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain8, 0, 0xff, 0x2a); cam->params.apcor.gain8, 0, 0xff, 0x2a);
out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n", out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain1, 0, 255, 24); cam->params.vlOffset.gain1, 0, 255, 24);
out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n", out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain2, 0, 255, 28); cam->params.vlOffset.gain2, 0, 255, 28);
out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n", out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain4, 0, 255, 30); cam->params.vlOffset.gain4, 0, 255, 30);
out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n", out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain8, 0, 255, 30); cam->params.vlOffset.gain8, 0, 255, 30);
out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n", out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n",
cam->params.flickerControl.flickerMode ? "on" : "off", cam->params.flickerControl.flickerMode ? "on" : "off",
"off", "on", "off"); "off", "on", "off");
out += sprintf(out, "mains_frequency: %8d %8d %8d %8d" out += sprintf(out, "mains_frequency: %8d %8d %8d %8d"
" only 50/60\n", " only 50/60\n",
cam->mainsFreq ? 60 : 50, 50, 60, 50); cam->mainsFreq ? 60 : 50, 50, 60, 50);
if(cam->params.flickerControl.allowableOverExposure < 0) if(cam->params.flickerControl.allowableOverExposure < 0)
out += sprintf(out, "allowable_overexposure: %4dauto auto %8d auto\n", out += sprintf(out, "allowable_overexposure: %4dauto auto %8d auto\n",
-cam->params.flickerControl.allowableOverExposure, -cam->params.flickerControl.allowableOverExposure,
255); 255);
else else
out += sprintf(out, "allowable_overexposure: %8d auto %8d auto\n", out += sprintf(out, "allowable_overexposure: %8d auto %8d auto\n",
cam->params.flickerControl.allowableOverExposure, cam->params.flickerControl.allowableOverExposure,
255); 255);
out += sprintf(out, "compression_mode: "); out += sprintf(out, "compression_mode: ");
switch(cam->params.compression.mode) { switch(cam->params.compression.mode) {
case CPIA_COMPRESSION_NONE: case CPIA_COMPRESSION_NONE:
@ -483,49 +483,49 @@ static int cpia_read_proc(char *page, char **start, off_t off,
} }
out += sprintf(out, " none,auto,manual auto\n"); out += sprintf(out, " none,auto,manual auto\n");
out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n", out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n",
cam->params.compression.decimation == cam->params.compression.decimation ==
DECIMATION_ENAB ? "on":"off", "off", "on", DECIMATION_ENAB ? "on":"off", "off", "on",
"off"); "off");
out += sprintf(out, "compression_target: %9s %9s %9s %9s\n", out += sprintf(out, "compression_target: %9s %9s %9s %9s\n",
cam->params.compressionTarget.frTargeting == cam->params.compressionTarget.frTargeting ==
CPIA_COMPRESSION_TARGET_FRAMERATE ? CPIA_COMPRESSION_TARGET_FRAMERATE ?
"framerate":"quality", "framerate":"quality",
"framerate", "quality", "quality"); "framerate", "quality", "quality");
out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n", out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n",
cam->params.compressionTarget.targetFR, 1, 30, 15); cam->params.compressionTarget.targetFR, 1, 30, 15);
out += sprintf(out, "target_quality: %8d %8d %8d %8d\n", out += sprintf(out, "target_quality: %8d %8d %8d %8d\n",
cam->params.compressionTarget.targetQ, 1, 64, 5); cam->params.compressionTarget.targetQ, 1, 64, 5);
out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n", out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n",
cam->params.yuvThreshold.yThreshold, 0, 31, 6); cam->params.yuvThreshold.yThreshold, 0, 31, 6);
out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n", out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n",
cam->params.yuvThreshold.uvThreshold, 0, 31, 6); cam->params.yuvThreshold.uvThreshold, 0, 31, 6);
out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n", out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n",
cam->params.compressionParams.hysteresis, 0, 255, 3); cam->params.compressionParams.hysteresis, 0, 255, 3);
out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n", out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n",
cam->params.compressionParams.threshMax, 0, 255, 11); cam->params.compressionParams.threshMax, 0, 255, 11);
out += sprintf(out, "small_step: %8d %8d %8d %8d\n", out += sprintf(out, "small_step: %8d %8d %8d %8d\n",
cam->params.compressionParams.smallStep, 0, 255, 1); cam->params.compressionParams.smallStep, 0, 255, 1);
out += sprintf(out, "large_step: %8d %8d %8d %8d\n", out += sprintf(out, "large_step: %8d %8d %8d %8d\n",
cam->params.compressionParams.largeStep, 0, 255, 3); cam->params.compressionParams.largeStep, 0, 255, 3);
out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n", out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n",
cam->params.compressionParams.decimationHysteresis, cam->params.compressionParams.decimationHysteresis,
0, 255, 2); 0, 255, 2);
out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n", out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
cam->params.compressionParams.frDiffStepThresh, cam->params.compressionParams.frDiffStepThresh,
0, 255, 5); 0, 255, 5);
out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n", out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n",
cam->params.compressionParams.qDiffStepThresh, cam->params.compressionParams.qDiffStepThresh,
0, 255, 3); 0, 255, 3);
out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n", out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n",
cam->params.compressionParams.decimationThreshMod, cam->params.compressionParams.decimationThreshMod,
0, 255, 2); 0, 255, 2);
/* QX3 specific entries */ /* QX3 specific entries */
if (cam->params.qx3.qx3_detected) { if (cam->params.qx3.qx3_detected) {
out += sprintf(out, "toplight: %8s %8s %8s %8s\n", out += sprintf(out, "toplight: %8s %8s %8s %8s\n",
cam->params.qx3.toplight ? "on" : "off", cam->params.qx3.toplight ? "on" : "off",
"off", "on", "off"); "off", "on", "off");
out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n", out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n",
cam->params.qx3.bottomlight ? "on" : "off", cam->params.qx3.bottomlight ? "on" : "off",
"off", "on", "off"); "off", "on", "off");
} }
@ -543,7 +543,7 @@ static int cpia_read_proc(char *page, char **start, off_t off,
static int match(char *checkstr, char **buffer, unsigned long *count, static int match(char *checkstr, char **buffer, unsigned long *count,
int *find_colon, int *err) int *find_colon, int *err)
{ {
int ret, colon_found = 1; int ret, colon_found = 1;
int len = strlen(checkstr); int len = strlen(checkstr);
@ -583,7 +583,7 @@ static unsigned long int value(char **buffer, unsigned long *count, int *err)
} }
static int cpia_write_proc(struct file *file, const char __user *buf, static int cpia_write_proc(struct file *file, const char __user *buf,
unsigned long count, void *data) unsigned long count, void *data)
{ {
struct cam_data *cam = data; struct cam_data *cam = data;
struct cam_params new_params; struct cam_params new_params;
@ -639,7 +639,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
#define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval)) #define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval))
#define VALUE (value(&buffer,&count, &retval)) #define VALUE (value(&buffer,&count, &retval))
#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \ #define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
new_params.version.firmwareRevision == (y)) new_params.version.firmwareRevision == (y))
retval = 0; retval = 0;
while (count && !retval) { while (count && !retval) {
@ -1288,7 +1288,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
} }
command_flags |= COMMAND_SETCOMPRESSIONPARAMS; command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
} else if (MATCH("toplight")) { } else if (MATCH("toplight")) {
if (!retval && MATCH("on")) if (!retval && MATCH("on"))
new_params.qx3.toplight = 1; new_params.qx3.toplight = 1;
else if (!retval && MATCH("off")) else if (!retval && MATCH("off"))
new_params.qx3.toplight = 0; new_params.qx3.toplight = 0;
@ -1296,7 +1296,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
retval = -EINVAL; retval = -EINVAL;
command_flags |= COMMAND_SETLIGHTS; command_flags |= COMMAND_SETLIGHTS;
} else if (MATCH("bottomlight")) { } else if (MATCH("bottomlight")) {
if (!retval && MATCH("on")) if (!retval && MATCH("on"))
new_params.qx3.bottomlight = 1; new_params.qx3.bottomlight = 1;
else if (!retval && MATCH("off")) else if (!retval && MATCH("off"))
new_params.qx3.bottomlight = 0; new_params.qx3.bottomlight = 0;
@ -1354,7 +1354,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
out: out:
free_page((unsigned long)page); free_page((unsigned long)page);
return retval; return retval;
} }
static void create_proc_cpia_cam(struct cam_data *cam) static void create_proc_cpia_cam(struct cam_data *cam)
@ -1376,7 +1376,7 @@ static void create_proc_cpia_cam(struct cam_data *cam)
ent->write_proc = cpia_write_proc; ent->write_proc = cpia_write_proc;
/* /*
size of the proc entry is 3736 bytes for the standard webcam; size of the proc entry is 3736 bytes for the standard webcam;
the extra features of the QX3 microscope add 189 bytes. the extra features of the QX3 microscope add 189 bytes.
(we have not yet probed the camera to see which type it is). (we have not yet probed the camera to see which type it is).
*/ */
ent->size = 3736 + 189; ent->size = 3736 + 189;
@ -1599,10 +1599,10 @@ static void set_vw_size(struct cam_data *cam)
cam->params.roi.colStart += cam->vc.x >> 3; cam->params.roi.colStart += cam->vc.x >> 3;
cam->params.roi.colEnd = cam->params.roi.colStart + cam->params.roi.colEnd = cam->params.roi.colStart +
(cam->vc.width >> 3); (cam->vc.width >> 3);
cam->params.roi.rowStart += cam->vc.y >> 2; cam->params.roi.rowStart += cam->vc.y >> 2;
cam->params.roi.rowEnd = cam->params.roi.rowStart + cam->params.roi.rowEnd = cam->params.roi.rowStart +
(cam->vc.height >> 2); (cam->vc.height >> 2);
return; return;
} }
@ -1770,9 +1770,9 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
/* send a command to the camera with an additional data transaction */ /* send a command to the camera with an additional data transaction */
static int do_command_extended(struct cam_data *cam, u16 command, static int do_command_extended(struct cam_data *cam, u16 command,
u8 a, u8 b, u8 c, u8 d, u8 a, u8 b, u8 c, u8 d,
u8 e, u8 f, u8 g, u8 h, u8 e, u8 f, u8 g, u8 h,
u8 i, u8 j, u8 k, u8 l) u8 i, u8 j, u8 k, u8 l)
{ {
int retval; int retval;
u8 cmd[8], data[8]; u8 cmd[8], data[8];
@ -1809,7 +1809,7 @@ static int do_command_extended(struct cam_data *cam, u16 command,
#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16) #define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt, static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt,
int linesize, int mmap_kludge) int linesize, int mmap_kludge)
{ {
int y, u, v, r, g, b, y1; int y, u, v, r, g, b, y1;
@ -1925,7 +1925,7 @@ static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt,
static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt, static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt,
int in_uyvy, int mmap_kludge) int in_uyvy, int mmap_kludge)
{ {
int y, u, v, r, g, b, y1; int y, u, v, r, g, b, y1;
@ -2150,14 +2150,14 @@ static int parse_picture(struct cam_data *cam, int size)
if (!compressed || (compressed && !(*ibuf & 1))) { if (!compressed || (compressed && !(*ibuf & 1))) {
if(subsample_422 || even_line) { if(subsample_422 || even_line) {
obuf += yuvconvert(ibuf, obuf, out_fmt, obuf += yuvconvert(ibuf, obuf, out_fmt,
in_uyvy, cam->mmap_kludge); in_uyvy, cam->mmap_kludge);
ibuf += 4; ibuf += 4;
ll -= 4; ll -= 4;
} else { } else {
/* SUBSAMPLE_420 on an odd line */ /* SUBSAMPLE_420 on an odd line */
obuf += convert420(ibuf, obuf, obuf += convert420(ibuf, obuf,
out_fmt, linesize, out_fmt, linesize,
cam->mmap_kludge); cam->mmap_kludge);
ibuf += 2; ibuf += 2;
ll -= 2; ll -= 2;
} }
@ -2183,7 +2183,7 @@ static int parse_picture(struct cam_data *cam, int size)
if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) && if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) &&
(ibuf[2] == EOI) && (ibuf[3] == EOI)) { (ibuf[2] == EOI) && (ibuf[3] == EOI)) {
size -= 4; size -= 4;
break; break;
} }
@ -2233,7 +2233,7 @@ static int parse_picture(struct cam_data *cam, int size)
static inline int init_stream_cap(struct cam_data *cam) static inline int init_stream_cap(struct cam_data *cam)
{ {
return do_command(cam, CPIA_COMMAND_InitStreamCap, return do_command(cam, CPIA_COMMAND_InitStreamCap,
0, cam->params.streamStartLine, 0, 0); 0, cam->params.streamStartLine, 0, 0);
} }
@ -2254,7 +2254,7 @@ static int find_over_exposure(int brightness)
int MaxAllowableOverExposure, OverExposure; int MaxAllowableOverExposure, OverExposure;
MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness - MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
FLICKER_BRIGHTNESS_CONSTANT; FLICKER_BRIGHTNESS_CONSTANT;
if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) { if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) {
OverExposure = MaxAllowableOverExposure; OverExposure = MaxAllowableOverExposure;
@ -2280,59 +2280,59 @@ static void dispatch_commands(struct cam_data *cam)
DEB_BYTE(cam->cmd_queue>>8); DEB_BYTE(cam->cmd_queue>>8);
if (cam->cmd_queue & COMMAND_SETFORMAT) { if (cam->cmd_queue & COMMAND_SETFORMAT) {
do_command(cam, CPIA_COMMAND_SetFormat, do_command(cam, CPIA_COMMAND_SetFormat,
cam->params.format.videoSize, cam->params.format.videoSize,
cam->params.format.subSample, cam->params.format.subSample,
cam->params.format.yuvOrder, 0); cam->params.format.yuvOrder, 0);
do_command(cam, CPIA_COMMAND_SetROI, do_command(cam, CPIA_COMMAND_SetROI,
cam->params.roi.colStart, cam->params.roi.colEnd, cam->params.roi.colStart, cam->params.roi.colEnd,
cam->params.roi.rowStart, cam->params.roi.rowEnd); cam->params.roi.rowStart, cam->params.roi.rowEnd);
cam->first_frame = 1; cam->first_frame = 1;
} }
if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS) if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS)
do_command(cam, CPIA_COMMAND_SetColourParams, do_command(cam, CPIA_COMMAND_SetColourParams,
cam->params.colourParams.brightness, cam->params.colourParams.brightness,
cam->params.colourParams.contrast, cam->params.colourParams.contrast,
cam->params.colourParams.saturation, 0); cam->params.colourParams.saturation, 0);
if (cam->cmd_queue & COMMAND_SETAPCOR) if (cam->cmd_queue & COMMAND_SETAPCOR)
do_command(cam, CPIA_COMMAND_SetApcor, do_command(cam, CPIA_COMMAND_SetApcor,
cam->params.apcor.gain1, cam->params.apcor.gain1,
cam->params.apcor.gain2, cam->params.apcor.gain2,
cam->params.apcor.gain4, cam->params.apcor.gain4,
cam->params.apcor.gain8); cam->params.apcor.gain8);
if (cam->cmd_queue & COMMAND_SETVLOFFSET) if (cam->cmd_queue & COMMAND_SETVLOFFSET)
do_command(cam, CPIA_COMMAND_SetVLOffset, do_command(cam, CPIA_COMMAND_SetVLOffset,
cam->params.vlOffset.gain1, cam->params.vlOffset.gain1,
cam->params.vlOffset.gain2, cam->params.vlOffset.gain2,
cam->params.vlOffset.gain4, cam->params.vlOffset.gain4,
cam->params.vlOffset.gain8); cam->params.vlOffset.gain8);
if (cam->cmd_queue & COMMAND_SETEXPOSURE) { if (cam->cmd_queue & COMMAND_SETEXPOSURE) {
do_command_extended(cam, CPIA_COMMAND_SetExposure, do_command_extended(cam, CPIA_COMMAND_SetExposure,
cam->params.exposure.gainMode, cam->params.exposure.gainMode,
1, 1,
cam->params.exposure.compMode, cam->params.exposure.compMode,
cam->params.exposure.centreWeight, cam->params.exposure.centreWeight,
cam->params.exposure.gain, cam->params.exposure.gain,
cam->params.exposure.fineExp, cam->params.exposure.fineExp,
cam->params.exposure.coarseExpLo, cam->params.exposure.coarseExpLo,
cam->params.exposure.coarseExpHi, cam->params.exposure.coarseExpHi,
cam->params.exposure.redComp, cam->params.exposure.redComp,
cam->params.exposure.green1Comp, cam->params.exposure.green1Comp,
cam->params.exposure.green2Comp, cam->params.exposure.green2Comp,
cam->params.exposure.blueComp); cam->params.exposure.blueComp);
if(cam->params.exposure.expMode != 1) { if(cam->params.exposure.expMode != 1) {
do_command_extended(cam, CPIA_COMMAND_SetExposure, do_command_extended(cam, CPIA_COMMAND_SetExposure,
0, 0,
cam->params.exposure.expMode, cam->params.exposure.expMode,
0, 0, 0, 0,
cam->params.exposure.gain, cam->params.exposure.gain,
cam->params.exposure.fineExp, cam->params.exposure.fineExp,
cam->params.exposure.coarseExpLo, cam->params.exposure.coarseExpLo,
cam->params.exposure.coarseExpHi, cam->params.exposure.coarseExpHi,
0, 0, 0, 0); 0, 0, 0, 0);
} }
} }
@ -2358,47 +2358,47 @@ static void dispatch_commands(struct cam_data *cam)
if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET) if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET)
do_command(cam, CPIA_COMMAND_SetCompressionTarget, do_command(cam, CPIA_COMMAND_SetCompressionTarget,
cam->params.compressionTarget.frTargeting, cam->params.compressionTarget.frTargeting,
cam->params.compressionTarget.targetFR, cam->params.compressionTarget.targetFR,
cam->params.compressionTarget.targetQ, 0); cam->params.compressionTarget.targetQ, 0);
if (cam->cmd_queue & COMMAND_SETYUVTHRESH) if (cam->cmd_queue & COMMAND_SETYUVTHRESH)
do_command(cam, CPIA_COMMAND_SetYUVThresh, do_command(cam, CPIA_COMMAND_SetYUVThresh,
cam->params.yuvThreshold.yThreshold, cam->params.yuvThreshold.yThreshold,
cam->params.yuvThreshold.uvThreshold, 0, 0); cam->params.yuvThreshold.uvThreshold, 0, 0);
if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS) if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS)
do_command_extended(cam, CPIA_COMMAND_SetCompressionParams, do_command_extended(cam, CPIA_COMMAND_SetCompressionParams,
0, 0, 0, 0, 0, 0, 0, 0,
cam->params.compressionParams.hysteresis, cam->params.compressionParams.hysteresis,
cam->params.compressionParams.threshMax, cam->params.compressionParams.threshMax,
cam->params.compressionParams.smallStep, cam->params.compressionParams.smallStep,
cam->params.compressionParams.largeStep, cam->params.compressionParams.largeStep,
cam->params.compressionParams.decimationHysteresis, cam->params.compressionParams.decimationHysteresis,
cam->params.compressionParams.frDiffStepThresh, cam->params.compressionParams.frDiffStepThresh,
cam->params.compressionParams.qDiffStepThresh, cam->params.compressionParams.qDiffStepThresh,
cam->params.compressionParams.decimationThreshMod); cam->params.compressionParams.decimationThreshMod);
if (cam->cmd_queue & COMMAND_SETCOMPRESSION) if (cam->cmd_queue & COMMAND_SETCOMPRESSION)
do_command(cam, CPIA_COMMAND_SetCompression, do_command(cam, CPIA_COMMAND_SetCompression,
cam->params.compression.mode, cam->params.compression.mode,
cam->params.compression.decimation, 0, 0); cam->params.compression.decimation, 0, 0);
if (cam->cmd_queue & COMMAND_SETSENSORFPS) if (cam->cmd_queue & COMMAND_SETSENSORFPS)
do_command(cam, CPIA_COMMAND_SetSensorFPS, do_command(cam, CPIA_COMMAND_SetSensorFPS,
cam->params.sensorFps.divisor, cam->params.sensorFps.divisor,
cam->params.sensorFps.baserate, 0, 0); cam->params.sensorFps.baserate, 0, 0);
if (cam->cmd_queue & COMMAND_SETFLICKERCTRL) if (cam->cmd_queue & COMMAND_SETFLICKERCTRL)
do_command(cam, CPIA_COMMAND_SetFlickerCtrl, do_command(cam, CPIA_COMMAND_SetFlickerCtrl,
cam->params.flickerControl.flickerMode, cam->params.flickerControl.flickerMode,
cam->params.flickerControl.coarseJump, cam->params.flickerControl.coarseJump,
abs(cam->params.flickerControl.allowableOverExposure), abs(cam->params.flickerControl.allowableOverExposure),
0); 0);
if (cam->cmd_queue & COMMAND_SETECPTIMING) if (cam->cmd_queue & COMMAND_SETECPTIMING)
do_command(cam, CPIA_COMMAND_SetECPTiming, do_command(cam, CPIA_COMMAND_SetECPTiming,
cam->params.ecpTiming, 0, 0, 0); cam->params.ecpTiming, 0, 0, 0);
if (cam->cmd_queue & COMMAND_PAUSE) if (cam->cmd_queue & COMMAND_PAUSE)
do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
@ -2409,9 +2409,9 @@ static void dispatch_commands(struct cam_data *cam)
if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected) if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected)
{ {
int p1 = (cam->params.qx3.bottomlight == 0) << 1; int p1 = (cam->params.qx3.bottomlight == 0) << 1;
int p2 = (cam->params.qx3.toplight == 0) << 3; int p2 = (cam->params.qx3.toplight == 0) << 3;
do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0); do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0);
do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0); do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0);
} }
cam->cmd_queue = COMMAND_NONE; cam->cmd_queue = COMMAND_NONE;
@ -2422,11 +2422,11 @@ static void dispatch_commands(struct cam_data *cam)
static void set_flicker(struct cam_params *params, volatile u32 *command_flags, static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
int on) int on)
{ {
/* Everything in here is from the Windows driver */ /* Everything in here is from the Windows driver */
#define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \ #define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \
params->version.firmwareRevision == (y)) params->version.firmwareRevision == (y))
/* define for compgain calculation */ /* define for compgain calculation */
#if 0 #if 0
#define COMPGAIN(base, curexp, newexp) \ #define COMPGAIN(base, curexp, newexp) \
@ -2533,7 +2533,7 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
} }
#define FIRMWARE_VERSION(x,y) (cam->params.version.firmwareVersion == (x) && \ #define FIRMWARE_VERSION(x,y) (cam->params.version.firmwareVersion == (x) && \
cam->params.version.firmwareRevision == (y)) cam->params.version.firmwareRevision == (y))
/* monitor the exposure and adjust the sensor frame rate if needed */ /* monitor the exposure and adjust the sensor frame rate if needed */
static void monitor_exposure(struct cam_data *cam) static void monitor_exposure(struct cam_data *cam)
{ {
@ -2564,17 +2564,17 @@ static void monitor_exposure(struct cam_data *cam)
mutex_lock(&cam->param_lock); mutex_lock(&cam->param_lock);
light_exp = cam->params.colourParams.brightness + light_exp = cam->params.colourParams.brightness +
TC - 50 + EXP_ACC_LIGHT; TC - 50 + EXP_ACC_LIGHT;
if(light_exp > 255) if(light_exp > 255)
light_exp = 255; light_exp = 255;
dark_exp = cam->params.colourParams.brightness + dark_exp = cam->params.colourParams.brightness +
TC - 50 - EXP_ACC_DARK; TC - 50 - EXP_ACC_DARK;
if(dark_exp < 0) if(dark_exp < 0)
dark_exp = 0; dark_exp = 0;
very_dark_exp = dark_exp/2; very_dark_exp = dark_exp/2;
old_exposure = cam->params.exposure.coarseExpHi * 256 + old_exposure = cam->params.exposure.coarseExpHi * 256 +
cam->params.exposure.coarseExpLo; cam->params.exposure.coarseExpLo;
if(!cam->params.flickerControl.disabled) { if(!cam->params.flickerControl.disabled) {
/* Flicker control on */ /* Flicker control on */
@ -2685,8 +2685,8 @@ static void monitor_exposure(struct cam_data *cam)
cam->params.flickerControl.coarseJump = cam->params.flickerControl.coarseJump =
flicker_jumps[cam->mainsFreq] flicker_jumps[cam->mainsFreq]
[cam->params.sensorFps.baserate] [cam->params.sensorFps.baserate]
[cam->params.sensorFps.divisor]; [cam->params.sensorFps.divisor];
cam->cmd_queue |= COMMAND_SETFLICKERCTRL; cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
new_exposure = cam->params.flickerControl.coarseJump-1; new_exposure = cam->params.flickerControl.coarseJump-1;
@ -2704,15 +2704,15 @@ static void monitor_exposure(struct cam_data *cam)
cam->params.sensorFps.divisor > 0) { cam->params.sensorFps.divisor > 0) {
/* light for too long */ /* light for too long */
int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ; int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ;
--cam->params.sensorFps.divisor; --cam->params.sensorFps.divisor;
cam->cmd_queue |= COMMAND_SETSENSORFPS; cam->cmd_queue |= COMMAND_SETSENSORFPS;
cam->params.flickerControl.coarseJump = cam->params.flickerControl.coarseJump =
flicker_jumps[cam->mainsFreq] flicker_jumps[cam->mainsFreq]
[cam->params.sensorFps.baserate] [cam->params.sensorFps.baserate]
[cam->params.sensorFps.divisor]; [cam->params.sensorFps.divisor];
cam->cmd_queue |= COMMAND_SETFLICKERCTRL; cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
new_exposure = cam->params.flickerControl.coarseJump-1; new_exposure = cam->params.flickerControl.coarseJump-1;
@ -2786,14 +2786,14 @@ static void restart_flicker(struct cam_data *cam)
} }
cam_exposure = cam->raw_image[39]*2; cam_exposure = cam->raw_image[39]*2;
old_exp = cam->params.exposure.coarseExpLo + old_exp = cam->params.exposure.coarseExpLo +
cam->params.exposure.coarseExpHi*256; cam->params.exposure.coarseExpHi*256;
/* /*
see how far away camera exposure is from a valid see how far away camera exposure is from a valid
flicker exposure value flicker exposure value
*/ */
cam_exposure %= cam->params.flickerControl.coarseJump; cam_exposure %= cam->params.flickerControl.coarseJump;
if(!cam->params.flickerControl.disabled && if(!cam->params.flickerControl.disabled &&
cam_exposure <= cam->params.flickerControl.coarseJump - 3) { cam_exposure <= cam->params.flickerControl.coarseJump - 3) {
/* Flicker control auto-disabled */ /* Flicker control auto-disabled */
cam->params.flickerControl.disabled = 1; cam->params.flickerControl.disabled = 1;
} }
@ -2801,7 +2801,7 @@ static void restart_flicker(struct cam_data *cam)
if(cam->params.flickerControl.disabled && if(cam->params.flickerControl.disabled &&
cam->params.flickerControl.flickerMode && cam->params.flickerControl.flickerMode &&
old_exp > cam->params.flickerControl.coarseJump + old_exp > cam->params.flickerControl.coarseJump +
ROUND_UP_EXP_FOR_FLICKER) { ROUND_UP_EXP_FOR_FLICKER) {
/* exposure is now high enough to switch /* exposure is now high enough to switch
flicker control back on */ flicker control back on */
set_flicker(&cam->params, &cam->cmd_queue, 1); set_flicker(&cam->params, &cam->cmd_queue, 1);
@ -2878,7 +2878,7 @@ static int fetch_frame(void *data)
return -EINTR; return -EINTR;
do_command(cam, CPIA_COMMAND_GetCameraStatus, do_command(cam, CPIA_COMMAND_GetCameraStatus,
0, 0, 0, 0); 0, 0, 0, 0);
} }
if(cam->params.status.streamState != STREAM_READY) { if(cam->params.status.streamState != STREAM_READY) {
continue; continue;
@ -2913,8 +2913,8 @@ static int fetch_frame(void *data)
dispatch_commands(cam); dispatch_commands(cam);
/* Update our knowledge of the camera state */ /* Update our knowledge of the camera state */
do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
/* decompress and convert image to by copying it from /* decompress and convert image to by copying it from
@ -2933,7 +2933,7 @@ static int fetch_frame(void *data)
uncompressed. */ uncompressed. */
cam->first_frame = 1; cam->first_frame = 1;
do_command(cam, CPIA_COMMAND_SetGrabMode, do_command(cam, CPIA_COMMAND_SetGrabMode,
CPIA_GRAB_SINGLE, 0, 0, 0); CPIA_GRAB_SINGLE, 0, 0, 0);
/* FIXME: Trial & error - need up to 70ms for /* FIXME: Trial & error - need up to 70ms for
the grab mode change to complete ? */ the grab mode change to complete ? */
msleep_interruptible(70); msleep_interruptible(70);
@ -2957,12 +2957,12 @@ static int fetch_frame(void *data)
if (cam->first_frame) { if (cam->first_frame) {
cam->first_frame = 0; cam->first_frame = 0;
do_command(cam, CPIA_COMMAND_SetCompression, do_command(cam, CPIA_COMMAND_SetCompression,
cam->params.compression.mode, cam->params.compression.mode,
cam->params.compression.decimation, 0, 0); cam->params.compression.decimation, 0, 0);
/* Switch from single-grab to continuous grab */ /* Switch from single-grab to continuous grab */
do_command(cam, CPIA_COMMAND_SetGrabMode, do_command(cam, CPIA_COMMAND_SetGrabMode,
CPIA_GRAB_CONTINUOUS, 0, 0, 0); CPIA_GRAB_CONTINUOUS, 0, 0, 0);
} }
return 0; return 0;
} }
@ -3039,18 +3039,18 @@ static void save_camera_state(struct cam_data *cam)
static int set_camera_state(struct cam_data *cam) static int set_camera_state(struct cam_data *cam)
{ {
cam->cmd_queue = COMMAND_SETCOMPRESSION | cam->cmd_queue = COMMAND_SETCOMPRESSION |
COMMAND_SETCOMPRESSIONTARGET | COMMAND_SETCOMPRESSIONTARGET |
COMMAND_SETCOLOURPARAMS | COMMAND_SETCOLOURPARAMS |
COMMAND_SETFORMAT | COMMAND_SETFORMAT |
COMMAND_SETYUVTHRESH | COMMAND_SETYUVTHRESH |
COMMAND_SETECPTIMING | COMMAND_SETECPTIMING |
COMMAND_SETCOMPRESSIONPARAMS | COMMAND_SETCOMPRESSIONPARAMS |
COMMAND_SETEXPOSURE | COMMAND_SETEXPOSURE |
COMMAND_SETCOLOURBALANCE | COMMAND_SETCOLOURBALANCE |
COMMAND_SETSENSORFPS | COMMAND_SETSENSORFPS |
COMMAND_SETAPCOR | COMMAND_SETAPCOR |
COMMAND_SETFLICKERCTRL | COMMAND_SETFLICKERCTRL |
COMMAND_SETVLOFFSET; COMMAND_SETVLOFFSET;
do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_SINGLE,0,0,0); do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_SINGLE,0,0,0);
dispatch_commands(cam); dispatch_commands(cam);
@ -3113,13 +3113,13 @@ static int reset_camera(struct cam_data *cam)
cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 && cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 &&
cam->params.pnpID.product == 0x0001); cam->params.pnpID.product == 0x0001);
/* The fatal error checking should be done after /* The fatal error checking should be done after
* the camera powers up (developer's guide p 3-38) */ * the camera powers up (developer's guide p 3-38) */
/* Set streamState before transition to high power to avoid bug /* Set streamState before transition to high power to avoid bug
* in firmware 1-02 */ * in firmware 1-02 */
do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0, do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0,
STREAM_NOT_READY, 0); STREAM_NOT_READY, 0);
/* GotoHiPower */ /* GotoHiPower */
err = goto_high_power(cam); err = goto_high_power(cam);
@ -3142,7 +3142,7 @@ static int reset_camera(struct cam_data *cam)
/* Firmware 1-02 may do this for parallel port cameras, /* Firmware 1-02 may do this for parallel port cameras,
* just clear the flags (developer's guide p 3-38) */ * just clear the flags (developer's guide p 3-38) */
do_command(cam, CPIA_COMMAND_ModifyCameraStatus, do_command(cam, CPIA_COMMAND_ModifyCameraStatus,
FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0); FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
} }
} }
@ -3250,7 +3250,7 @@ static int cpia_close(struct inode *inode, struct file *file)
struct cam_data *cam = dev->priv; struct cam_data *cam = dev->priv;
if (cam->ops) { if (cam->ops) {
/* Return ownership of /proc/cpia/videoX to root */ /* Return ownership of /proc/cpia/videoX to root */
if(cam->proc_entry) if(cam->proc_entry)
cam->proc_entry->uid = 0; cam->proc_entry->uid = 0;
@ -3342,7 +3342,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
return -EFAULT; return -EFAULT;
} }
if (copy_to_user(buf, cam->decompressed_frame.data, if (copy_to_user(buf, cam->decompressed_frame.data,
cam->decompressed_frame.count)) { cam->decompressed_frame.count)) {
DBG("copy_to_user failed\n"); DBG("copy_to_user failed\n");
mutex_unlock(&cam->busy_lock); mutex_unlock(&cam->busy_lock);
return -EFAULT; return -EFAULT;
@ -3853,8 +3853,8 @@ static void reset_camera_struct(struct cam_data *cam)
cam->params.flickerControl.coarseJump = cam->params.flickerControl.coarseJump =
flicker_jumps[cam->mainsFreq] flicker_jumps[cam->mainsFreq]
[cam->params.sensorFps.baserate] [cam->params.sensorFps.baserate]
[cam->params.sensorFps.divisor]; [cam->params.sensorFps.divisor];
cam->params.flickerControl.allowableOverExposure = cam->params.flickerControl.allowableOverExposure =
-find_over_exposure(cam->params.colourParams.brightness); -find_over_exposure(cam->params.colourParams.brightness);
cam->params.vlOffset.gain1 = 20; cam->params.vlOffset.gain1 = 20;
@ -3928,7 +3928,7 @@ static void reset_camera_struct(struct cam_data *cam)
/* initialize cam_data structure */ /* initialize cam_data structure */
static void init_camera_struct(struct cam_data *cam, static void init_camera_struct(struct cam_data *cam,
struct cpia_camera_ops *ops ) struct cpia_camera_ops *ops )
{ {
int i; int i;
@ -3961,7 +3961,7 @@ static void init_camera_struct(struct cam_data *cam,
struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel) struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel)
{ {
struct cam_data *camera; struct cam_data *camera;
if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL)
return NULL; return NULL;

View file

@ -52,7 +52,7 @@
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);
@ -63,7 +63,7 @@ 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
@ -84,10 +84,10 @@ struct cpia_camera_ops
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.
@ -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 */
@ -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 @@ skip_init:
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

@ -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);
@ -549,11 +549,11 @@ static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
} }
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) {
@ -645,8 +645,8 @@ 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;
@ -709,7 +709,7 @@ static int cpia_pp_register(struct parport *port)
} }
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");

View file

@ -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);

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

@ -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

@ -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
@ -200,7 +200,7 @@ static int dsbr100_setfreq(dsbr100_device *radio, int freq)
(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),

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 @@ start_of_frame:
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 @@ end_of_frame:
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 @@ end_of_frame:
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

@ -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))
@ -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);
@ -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))
@ -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) {
@ -5221,8 +5221,8 @@ 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 },
@ -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,8 +5381,8 @@ 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 },
@ -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;
} }
} }

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

@ -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);
@ -1508,7 +1508,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
} }
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");
@ -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,40 +1759,40 @@ 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:
@ -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, "
@ -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;
} }

View file

@ -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

@ -136,10 +136,10 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data)
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;
} }
} }

View file

@ -91,8 +91,8 @@ compression (only useful with the plugin)
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.
@ -153,21 +153,21 @@ dev_hint
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 dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
0123 goes to /dev/video3, the same 0123 goes to /dev/video3, the same
camera model with the 4567 serial camera model with the 4567 serial
gets /dev/video0. gets /dev/video0.
dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
next 3 Philips cams will use /dev/video4 next 3 Philips cams will use /dev/video4
through /dev/video6. 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
@ -192,7 +192,7 @@ trace
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

View file

@ -32,7 +32,7 @@
/* /*
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. */
@ -205,11 +205,11 @@ 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 */
@ -358,7 +358,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
*/ */
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];
@ -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:
@ -800,7 +800,7 @@ static inline int pwc_get_awb(struct pwc_device *pdev)
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;
@ -1237,7 +1237,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
break; break;
} }
case VIDIOCPWCSAWB: case VIDIOCPWCSAWB:
{ {
struct pwc_whitebalance *wb = arg; struct pwc_whitebalance *wb = arg;
@ -1270,9 +1270,9 @@ 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;
@ -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);
@ -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 ||
@ -1465,51 +1465,51 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
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) if (pdev->features & FEATURE_MOTOR_PANTILT)
{ {
struct pwc_mpt_angles *angles = arg; struct pwc_mpt_angles *angles = arg;
angles->absolute = 1; angles->absolute = 1;
angles->pan = pdev->pan_angle; angles->pan = pdev->pan_angle;
angles->tilt = pdev->tilt_angle; angles->tilt = pdev->tilt_angle;
} }
else else
{ {
ret = -ENXIO; ret = -ENXIO;
} }
break; break;
} }
case VIDIOCPWCMPTSTATUS: case VIDIOCPWCMPTSTATUS:
{ {
if (pdev->features & FEATURE_MOTOR_PANTILT) if (pdev->features & FEATURE_MOTOR_PANTILT)
{ {
struct pwc_mpt_status *status = arg; struct pwc_mpt_status *status = arg;
ret = pwc_mpt_get_status(pdev, status); ret = pwc_mpt_get_status(pdev, status);
} }
else else
{ {
ret = -ENXIO; ret = -ENXIO;
} }
break; 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);

View file

@ -205,12 +205,12 @@ static struct video_device pwc_template = {
*/ */
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;
@ -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++) {
@ -737,9 +737,9 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
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)
@ -881,12 +881,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
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++) {
@ -957,11 +957,11 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
/* 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)
@ -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,18 +1193,18 @@ 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);
@ -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);
@ -1384,7 +1384,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
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;
} }
@ -1515,7 +1515,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
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) {
@ -1525,13 +1525,13 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
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);
@ -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
@ -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;
@ -2189,7 +2189,7 @@ static int __init usb_pwc_init(void)
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
*/ */
@ -185,8 +185,8 @@ 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 */

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

@ -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

@ -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

@ -110,8 +110,8 @@ int pwc_decompress(struct pwc_device *pdev)
*/ */
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;

View file

@ -150,8 +150,8 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
client=kmalloc(sizeof(*client), GFP_KERNEL); client=kmalloc(sizeof(*client), GFP_KERNEL);
if(client==NULL) if(client==NULL)
return -ENOMEM; return -ENOMEM;
client_template.adapter = adap; client_template.adapter = adap;
client_template.addr = addr; client_template.addr = addr;
memcpy(client, &client_template, sizeof(*client)); memcpy(client, &client_template, sizeof(*client));
t = kzalloc(sizeof(*t), GFP_KERNEL); t = kzalloc(sizeof(*t), GFP_KERNEL);
if(t==NULL) if(t==NULL)

View file

@ -32,7 +32,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "rds.h" #include <media/rds.h>
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { static unsigned short normal_i2c[] = {

View file

@ -139,7 +139,7 @@ saa7110_read (struct i2c_client *client)
static int static int
saa7110_selmux (struct i2c_client *client, saa7110_selmux (struct i2c_client *client,
int chan) int chan)
{ {
static const unsigned char modes[9][8] = { static const unsigned char modes[9][8] = {
/* mode 0 */ /* mode 0 */

View file

@ -40,7 +40,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/audiochip.h>
#include <asm/div64.h> #include <asm/div64.h>
MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver");

View file

@ -507,7 +507,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
/* release the old buffer */ /* release the old buffer */
if (substream->runtime->dma_area) { if (substream->runtime->dma_area) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev); dsp_buffer_free(dev);
substream->runtime->dma_area = NULL; substream->runtime->dma_area = NULL;
} }
@ -523,12 +523,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
return err; return err;
} }
if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) { if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) {
dsp_buffer_free(dev); dsp_buffer_free(dev);
return err; return err;
} }
if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev); dsp_buffer_free(dev);
return err; return err;
} }
@ -537,7 +537,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
dev->dmasound.dma.sglen, dev->dmasound.dma.sglen,
0))) { 0))) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev); dsp_buffer_free(dev);
return err; return err;
} }
@ -571,7 +571,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
if (substream->runtime->dma_area) { if (substream->runtime->dma_area) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev); dsp_buffer_free(dev);
substream->runtime->dma_area = NULL; substream->runtime->dma_area = NULL;
} }

View file

@ -254,12 +254,12 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf) void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *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;
} }
@ -960,7 +960,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (saa7134_no_overlay <= 0) { if (saa7134_no_overlay <= 0) {
saa7134_video_template.type |= VID_TYPE_OVERLAY; saa7134_video_template.type |= VID_TYPE_OVERLAY;
} else { } else {
printk("bttv: Overlay support disabled.\n"); printk("%s: Overlay support disabled.\n",dev->name);
} }
dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,

View file

@ -124,7 +124,7 @@ static int dsp_rec_start(struct saa7134_dev *dev)
unsigned long flags; unsigned long flags;
/* prepare buffer */ /* prepare buffer */
if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) if (0 != (err = videobuf_pci_dma_map(dev->pci,&dev->dmasound.dma)))
return err; return err;
if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt)))
goto fail1; goto fail1;
@ -213,7 +213,7 @@ static int dsp_rec_start(struct saa7134_dev *dev)
fail2: fail2:
saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
fail1: fail1:
videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma);
return err; return err;
} }
@ -231,7 +231,7 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
/* unlock buffer */ /* unlock buffer */
saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma);
return 0; return 0;
} }

View file

@ -89,7 +89,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return -EINVAL; return -EINVAL;
if (buf->vb.size != size) { if (buf->vb.size != size) {
saa7134_dma_free(dev,buf); saa7134_dma_free(q,buf);
} }
if (STATE_NEEDS_INIT == buf->vb.state) { if (STATE_NEEDS_INIT == buf->vb.state) {
@ -98,7 +98,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
buf->vb.size = size; buf->vb.size = size;
buf->pt = &dev->ts.pt_ts; buf->pt = &dev->ts.pt_ts;
err = videobuf_iolock(dev->pci,&buf->vb,NULL); err = videobuf_iolock(q,&buf->vb,NULL);
if (err) if (err)
goto oops; goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt, err = saa7134_pgtable_build(dev->pci,buf->pt,
@ -126,7 +126,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return 0; return 0;
oops: oops:
saa7134_dma_free(dev,buf); saa7134_dma_free(q,buf);
return err; return err;
} }
@ -152,10 +152,9 @@ static void buffer_queue(struct videobuf_queue *q, 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 saa7134_dev *dev = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
saa7134_dma_free(dev,buf); saa7134_dma_free(q,buf);
} }
struct videobuf_queue_ops saa7134_ts_qops = { struct videobuf_queue_ops saa7134_ts_qops = {

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