Commit 5478e1ce authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] v4l: saa7134 driver update

From: Gerd Knorr <kraxel@bytesex.org>

This is a update for the saa7134 driver.  Changes:

  * add cropping support.
  * fix Makefile to build the saa6752hs module.
  * fix locking bug in oss dsp driver.
  * infrared remote keytable update.
  * some card-specific fixes.
parent df5f63d9
...@@ -3,6 +3,6 @@ saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ ...@@ -3,6 +3,6 @@ saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \
saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \ saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \
saa7134-vbi.o saa7134-video.o saa7134-input.o saa7134-vbi.o saa7134-video.o saa7134-input.o
obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa6752hs.o
EXTRA_CFLAGS = -I$(src)/.. EXTRA_CFLAGS = -I$(src)/..
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* device driver for philips saa7134 based TV cards * device driver for philips saa7134 based TV cards
* card-specific stuff. * card-specific stuff.
* *
* (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] * (c) 2001-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -732,7 +732,9 @@ struct saa7134_board saa7134_boards[] = { ...@@ -732,7 +732,9 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_ASUSTEK_TVFM7133] = { [SAA7134_BOARD_ASUSTEK_TVFM7133] = {
.name = "ASUS TV-FM 7133", .name = "ASUS TV-FM 7133",
.audio_clock = 0x00187de7, .audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1236_MK3, // probably wrong, the 7133 one is the NTSC version ...
// .tuner_type = TUNER_PHILIPS_FM1236_MK3
.tuner_type = TUNER_LG_NTSC_NEW_TAPC,
.need_tda9887 = 1, .need_tda9887 = 1,
.inputs = {{ .inputs = {{
.name = name_tv, .name = name_tv,
......
...@@ -101,7 +101,7 @@ unsigned int saa7134_devcount; ...@@ -101,7 +101,7 @@ unsigned int saa7134_devcount;
/* debug help functions */ /* debug help functions */
static const char *v4l1_ioctls[] = { static const char *v4l1_ioctls[] = {
"0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", "0", "GCAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
"CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
"SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
"GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
...@@ -466,7 +466,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ...@@ -466,7 +466,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
} }
/* audio capture -- dma 3 */ /* audio capture -- dma 3 */
if (dev->oss.recording) { if (dev->oss.dma_running) {
ctrl |= SAA7134_MAIN_CTRL_TE6; ctrl |= SAA7134_MAIN_CTRL_TE6;
irq |= SAA7134_IRQ1_INTE_RA3_1 | irq |= SAA7134_IRQ1_INTE_RA3_1 |
SAA7134_IRQ1_INTE_RA3_0; SAA7134_IRQ1_INTE_RA3_0;
......
...@@ -100,42 +100,42 @@ static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = { ...@@ -100,42 +100,42 @@ static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
[ 0x23 ] = KEY_STOP, [ 0x23 ] = KEY_STOP,
}; };
/* Alfons Geser <a.geser@cox.net> */ /* Alfons Geser <a.geser@cox.net>
* updates from Job D. R. Borges <jobdrb@ig.com.br> */
static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = {
[ 18 ] = KEY_POWER, [ 18 ] = KEY_POWER,
[ 1 ] = KEY_TV, // DVR [ 1 ] = KEY_TV, // DVR
[ 21 ] = KEY_VIDEO, // DVD [ 21 ] = KEY_DVD, // DVD
[ 23 ] = KEY_AUDIO, // music [ 23 ] = KEY_AUDIO, // music
// DVR mode / DVD mode / music mode // DVR mode / DVD mode / music mode
[ 27 ] = KEY_MUTE, // mute [ 27 ] = KEY_MUTE, // mute
[ 2 ] = KEY_RESERVED, // MTS/SAP / audio /autoseek [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek
[ 30 ] = KEY_RESERVED, // closed captioning / subtitle / seek [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek
[ 22 ] = KEY_ZOOM, // full screen [ 22 ] = KEY_ZOOM, // full screen
[ 28 ] = KEY_RESERVED, // video source / eject /delall [ 28 ] = KEY_VIDEO, // video source / eject / delall
[ 29 ] = KEY_RESERVED, // playback / angle /del [ 29 ] = KEY_RESTART, // playback / angle / del
[ 47 ] = KEY_SEARCH, // scan / menu / playlist [ 47 ] = KEY_SEARCH, // scan / menu / playlist
[ 48 ] = KEY_RESERVED, // CH surfing / bookmark / memo [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo
[ 49 ] = KEY_HELP, // help [ 49 ] = KEY_HELP, // help
[ 50 ] = KEY_RESERVED, // num/memo [ 50 ] = KEY_MODE, // num/memo
[ 51 ] = KEY_ESC, // cancel [ 51 ] = KEY_ESC, // cancel
[ 12 ] = KEY_UP, // up [ 12 ] = KEY_UP, // up
[ 16 ] = KEY_DOWN, // down [ 16 ] = KEY_DOWN, // down
[ 8 ] = KEY_LEFT, // left [ 8 ] = KEY_LEFT, // left
[ 4 ] = KEY_RIGHT, // right [ 4 ] = KEY_RIGHT, // right
[ 3 ] = KEY_ENTER, // select [ 3 ] = KEY_SELECT, // select
[ 31 ] = KEY_REWIND, // rewind [ 31 ] = KEY_REWIND, // rewind
[ 32 ] = KEY_PLAYPAUSE, // play/pause [ 32 ] = KEY_PLAYPAUSE, // play/pause
[ 41 ] = KEY_FORWARD, // forward [ 41 ] = KEY_FORWARD, // forward
[ 20 ] = KEY_RESERVED, // repeat [ 20 ] = KEY_AGAIN, // repeat
[ 43 ] = KEY_RECORD, // recording [ 43 ] = KEY_RECORD, // recording
[ 44 ] = KEY_STOP, // stop [ 44 ] = KEY_STOP, // stop
[ 45 ] = KEY_PLAY, // play [ 45 ] = KEY_PLAY, // play
[ 46 ] = KEY_RESERVED, // snapshot [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle
[ 0 ] = KEY_KP0, [ 0 ] = KEY_KP0,
[ 5 ] = KEY_KP1, [ 5 ] = KEY_KP1,
......
...@@ -64,7 +64,7 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) ...@@ -64,7 +64,7 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
dev->oss.bufsize = blksize * blocks; dev->oss.bufsize = blksize * blocks;
dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", dprintk("buffer config: %d blocks / %d bytes, %d kB total\n",
blocks,blksize,blksize * blocks / 1024); blocks,blksize,blksize * blocks / 1024);
return 0; return 0;
} }
...@@ -74,6 +74,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) ...@@ -74,6 +74,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
if (!dev->oss.bufsize) if (!dev->oss.bufsize)
BUG(); BUG();
videobuf_dma_init(&dev->oss.dma);
err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE,
dev->oss.bufsize >> PAGE_SHIFT); dev->oss.bufsize >> PAGE_SHIFT);
if (0 != err) if (0 != err)
...@@ -92,6 +93,20 @@ static int dsp_buffer_free(struct saa7134_dev *dev) ...@@ -92,6 +93,20 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
return 0; return 0;
} }
static void dsp_dma_start(struct saa7134_dev *dev)
{
dev->oss.dma_blk = 0;
dev->oss.dma_running = 1;
saa7134_set_dmabits(dev);
}
static void dsp_dma_stop(struct saa7134_dev *dev)
{
dev->oss.dma_blk = -1;
dev->oss.dma_running = 0;
saa7134_set_dmabits(dev);
}
static int dsp_rec_start(struct saa7134_dev *dev) static int dsp_rec_start(struct saa7134_dev *dev)
{ {
int err, bswap, sign; int err, bswap, sign;
...@@ -178,10 +193,9 @@ static int dsp_rec_start(struct saa7134_dev *dev) ...@@ -178,10 +193,9 @@ static int dsp_rec_start(struct saa7134_dev *dev)
saa_writel(SAA7134_RS_CONTROL(6),control); saa_writel(SAA7134_RS_CONTROL(6),control);
/* start dma */ /* start dma */
dev->oss.recording_on = 1;
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
dev->oss.recording = 1; dsp_dma_start(dev);
dev->oss.dma_blk = 0;
saa7134_set_dmabits(dev);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
return 0; return 0;
...@@ -199,10 +213,9 @@ static int dsp_rec_stop(struct saa7134_dev *dev) ...@@ -199,10 +213,9 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
dprintk("rec_stop dma_blk=%d\n",dev->oss.dma_blk); dprintk("rec_stop dma_blk=%d\n",dev->oss.dma_blk);
/* stop dma */ /* stop dma */
dev->oss.recording_on = 0;
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
dev->oss.dma_blk = -1; dsp_dma_stop(dev);
dev->oss.recording = 0;
saa7134_set_dmabits(dev);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
/* unlock buffer */ /* unlock buffer */
...@@ -259,7 +272,7 @@ static int dsp_release(struct inode *inode, struct file *file) ...@@ -259,7 +272,7 @@ static int dsp_release(struct inode *inode, struct file *file)
struct saa7134_dev *dev = file->private_data; struct saa7134_dev *dev = file->private_data;
down(&dev->oss.lock); down(&dev->oss.lock);
if (dev->oss.recording) if (dev->oss.recording_on)
dsp_rec_stop(dev); dsp_rec_stop(dev);
dsp_buffer_free(dev); dsp_buffer_free(dev);
dev->oss.users_dsp--; dev->oss.users_dsp--;
...@@ -274,6 +287,7 @@ static ssize_t dsp_read(struct file *file, char *buffer, ...@@ -274,6 +287,7 @@ static ssize_t dsp_read(struct file *file, char *buffer,
struct saa7134_dev *dev = file->private_data; struct saa7134_dev *dev = file->private_data;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
unsigned int bytes; unsigned int bytes;
unsigned long flags;
int err,ret = 0; int err,ret = 0;
add_wait_queue(&dev->oss.wq, &wait); add_wait_queue(&dev->oss.wq, &wait);
...@@ -281,7 +295,7 @@ static ssize_t dsp_read(struct file *file, char *buffer, ...@@ -281,7 +295,7 @@ static ssize_t dsp_read(struct file *file, char *buffer,
while (count > 0) { while (count > 0) {
/* wait for data if needed */ /* wait for data if needed */
if (0 == dev->oss.read_count) { if (0 == dev->oss.read_count) {
if (!dev->oss.recording) { if (!dev->oss.recording_on) {
err = dsp_rec_start(dev); err = dsp_rec_start(dev);
if (err < 0) { if (err < 0) {
if (0 == ret) if (0 == ret)
...@@ -289,6 +303,13 @@ static ssize_t dsp_read(struct file *file, char *buffer, ...@@ -289,6 +303,13 @@ static ssize_t dsp_read(struct file *file, char *buffer,
break; break;
} }
} }
if (dev->oss.recording_on &&
!dev->oss.dma_running) {
/* recover from overruns */
spin_lock_irqsave(&dev->slock,flags);
dsp_dma_start(dev);
spin_unlock_irqrestore(&dev->slock,flags);
}
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
if (0 == ret) if (0 == ret)
ret = -EAGAIN; ret = -EAGAIN;
...@@ -365,7 +386,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, ...@@ -365,7 +386,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
return -EFAULT; return -EFAULT;
down(&dev->oss.lock); down(&dev->oss.lock);
dev->oss.channels = val ? 2 : 1; dev->oss.channels = val ? 2 : 1;
if (dev->oss.recording) { if (dev->oss.recording_on) {
dsp_rec_stop(dev); dsp_rec_stop(dev);
dsp_rec_start(dev); dsp_rec_start(dev);
} }
...@@ -379,7 +400,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, ...@@ -379,7 +400,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
down(&dev->oss.lock); down(&dev->oss.lock);
dev->oss.channels = val; dev->oss.channels = val;
if (dev->oss.recording) { if (dev->oss.recording_on) {
dsp_rec_stop(dev); dsp_rec_stop(dev);
dsp_rec_start(dev); dsp_rec_start(dev);
} }
...@@ -408,7 +429,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, ...@@ -408,7 +429,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case AFMT_S16_BE: case AFMT_S16_BE:
down(&dev->oss.lock); down(&dev->oss.lock);
dev->oss.afmt = val; dev->oss.afmt = val;
if (dev->oss.recording) { if (dev->oss.recording_on) {
dsp_rec_stop(dev); dsp_rec_stop(dev);
dsp_rec_start(dev); dsp_rec_start(dev);
} }
...@@ -438,7 +459,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, ...@@ -438,7 +459,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_RESET: case SNDCTL_DSP_RESET:
down(&dev->oss.lock); down(&dev->oss.lock);
if (dev->oss.recording) if (dev->oss.recording_on)
dsp_rec_stop(dev); dsp_rec_stop(dev);
up(&dev->oss.lock); up(&dev->oss.lock);
return 0; return 0;
...@@ -448,7 +469,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, ...@@ -448,7 +469,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_SETFRAGMENT: case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, (int*)arg)) if (get_user(val, (int*)arg))
return -EFAULT; return -EFAULT;
if (dev->oss.recording) if (dev->oss.recording_on)
return -EBUSY; return -EBUSY;
dsp_buffer_free(dev); dsp_buffer_free(dev);
dsp_buffer_conf(dev,1 << (val & 0xffff), (arg >> 16) & 0xffff); dsp_buffer_conf(dev,1 << (val & 0xffff), (arg >> 16) & 0xffff);
...@@ -484,7 +505,7 @@ static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait) ...@@ -484,7 +505,7 @@ static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait)
if (0 == dev->oss.read_count) { if (0 == dev->oss.read_count) {
down(&dev->oss.lock); down(&dev->oss.lock);
if (!dev->oss.recording) if (!dev->oss.recording_on)
dsp_rec_start(dev); dsp_rec_start(dev);
up(&dev->oss.lock); up(&dev->oss.lock);
} else } else
...@@ -800,7 +821,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) ...@@ -800,7 +821,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) { if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) {
dprintk("irq: overrun [full=%d/%d]\n",dev->oss.read_count, dprintk("irq: overrun [full=%d/%d]\n",dev->oss.read_count,
dev->oss.bufsize); dev->oss.bufsize);
dsp_rec_stop(dev); dsp_dma_stop(dev);
goto done; goto done;
} }
......
...@@ -60,8 +60,9 @@ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with ...@@ -60,8 +60,9 @@ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with
#define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \ #define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \
dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg))) dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg)))
#define SCAN_INITIAL_DELAY (HZ) #define SCAN_INITIAL_DELAY (HZ)
#define SCAN_SAMPLE_DELAY (HZ/5) #define SCAN_SAMPLE_DELAY (HZ/5)
#define SCAN_SUBCARRIER_DELAY (HZ*2)
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/* saa7134 code */ /* saa7134 code */
...@@ -557,7 +558,7 @@ static int tvaudio_thread(void *data) ...@@ -557,7 +558,7 @@ static int tvaudio_thread(void *data)
if (UNSET == audio) if (UNSET == audio)
audio = i; audio = i;
tvaudio_setmode(dev,&tvaudio[i],"trying"); tvaudio_setmode(dev,&tvaudio[i],"trying");
if (tvaudio_sleep(dev,HZ*2)) if (tvaudio_sleep(dev,SCAN_SUBCARRIER_DELAY))
goto restart; goto restart;
if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) { if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) {
audio = i; audio = i;
......
...@@ -30,14 +30,17 @@ ...@@ -30,14 +30,17 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static unsigned int video_debug = 0; static unsigned int video_debug = 0;
static unsigned int gbuffers = 8; static unsigned int gbuffers = 8;
static unsigned int gbufsize = 768*576*4; static unsigned int noninterlaced = 0;
static unsigned int gbufsize_max = 768*576*4; static unsigned int gbufsize = 768*576*4;
static unsigned int gbufsize_max = 768*576*4;
MODULE_PARM(video_debug,"i"); MODULE_PARM(video_debug,"i");
MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
MODULE_PARM(gbuffers,"i"); MODULE_PARM(gbuffers,"i");
MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32"); MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");
MODULE_PARM(noninterlaced,"i");
MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced");
#define dprintk(fmt, arg...) if (video_debug) \ #define dprintk(fmt, arg...) if (video_debug) \
printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg) printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
...@@ -149,8 +152,6 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -149,8 +152,6 @@ static struct saa7134_tvnorm tvnorms[] = {
{ {
.name = "PAL", .name = "PAL",
.id = V4L2_STD_PAL, .id = V4L2_STD_PAL,
.width = 720,
.height = 576,
.sync_control = 0x18, .sync_control = 0x18,
.luma_control = 0x40, .luma_control = 0x40,
...@@ -169,8 +170,6 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -169,8 +170,6 @@ static struct saa7134_tvnorm tvnorms[] = {
},{ },{
.name = "NTSC", .name = "NTSC",
.id = V4L2_STD_NTSC, .id = V4L2_STD_NTSC,
.width = 720,
.height = 480,
.sync_control = 0x59, .sync_control = 0x59,
.luma_control = 0x40, .luma_control = 0x40,
...@@ -189,8 +188,6 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -189,8 +188,6 @@ static struct saa7134_tvnorm tvnorms[] = {
},{ },{
.name = "SECAM", .name = "SECAM",
.id = V4L2_STD_SECAM, .id = V4L2_STD_SECAM,
.width = 720,
.height = 576,
.sync_control = 0x18, /* old: 0x58, */ .sync_control = 0x18, /* old: 0x58, */
.luma_control = 0x1b, .luma_control = 0x1b,
...@@ -209,8 +206,6 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -209,8 +206,6 @@ static struct saa7134_tvnorm tvnorms[] = {
},{ },{
.name = "PAL-M", .name = "PAL-M",
.id = V4L2_STD_PAL_M, .id = V4L2_STD_PAL_M,
.width = 720,
.height = 480,
.sync_control = 0x59, .sync_control = 0x59,
.luma_control = 0x40, .luma_control = 0x40,
...@@ -229,8 +224,6 @@ static struct saa7134_tvnorm tvnorms[] = { ...@@ -229,8 +224,6 @@ static struct saa7134_tvnorm tvnorms[] = {
},{ },{
.name = "PAL-Nc", .name = "PAL-Nc",
.id = V4L2_STD_PAL_Nc, .id = V4L2_STD_PAL_Nc,
.width = 720,
.height = 576,
.sync_control = 0x18, .sync_control = 0x18,
.luma_control = 0x40, .luma_control = 0x40,
...@@ -437,15 +430,33 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) ...@@ -437,15 +430,33 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
{ {
struct video_channel c; struct video_channel c;
int luma_control,mux; int luma_control,sync_control,mux;
dprintk("set tv norm = %s\n",norm->name); dprintk("set tv norm = %s\n",norm->name);
dev->tvnorm = norm; dev->tvnorm = norm;
mux = card_in(dev,dev->ctl_input).vmux; mux = card_in(dev,dev->ctl_input).vmux;
luma_control = norm->luma_control; luma_control = norm->luma_control;
sync_control = norm->sync_control;
if (mux > 5) if (mux > 5)
luma_control |= 0x80; /* svideo */ luma_control |= 0x80; /* svideo */
if (noninterlaced)
sync_control |= 0x20;
/* setup cropping */
dev->crop_bounds.left = norm->h_start;
dev->crop_defrect.left = norm->h_start;
dev->crop_bounds.width = norm->h_stop - norm->h_start +1;
dev->crop_defrect.width = norm->h_stop - norm->h_start +1;
dev->crop_bounds.top = (norm->vbi_v_stop+1)*2;
dev->crop_defrect.top = norm->video_v_start*2;
dev->crop_bounds.height = ((norm->id & V4L2_STD_525_60) ? 524 : 624)
- dev->crop_bounds.top;
dev->crop_defrect.height = (norm->video_v_stop - norm->video_v_start +1)*2;
dev->crop_current = dev->crop_defrect;
/* setup video decoder */ /* setup video decoder */
saa_writeb(SAA7134_INCR_DELAY, 0x08); saa_writeb(SAA7134_INCR_DELAY, 0x08);
...@@ -458,7 +469,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) ...@@ -458,7 +469,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
saa_writeb(SAA7134_HSYNC_STOP, 0xe0); saa_writeb(SAA7134_HSYNC_STOP, 0xe0);
saa_writeb(SAA7134_SOURCE_TIMING1, norm->src_timing); saa_writeb(SAA7134_SOURCE_TIMING1, norm->src_timing);
saa_writeb(SAA7134_SYNC_CTRL, norm->sync_control); saa_writeb(SAA7134_SYNC_CTRL, sync_control);
saa_writeb(SAA7134_LUMA_CTRL, luma_control); saa_writeb(SAA7134_LUMA_CTRL, luma_control);
saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright); saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
saa_writeb(SAA7134_DEC_LUMA_CONTRAST, dev->ctl_contrast); saa_writeb(SAA7134_DEC_LUMA_CONTRAST, dev->ctl_contrast);
...@@ -563,25 +574,30 @@ static void set_v_scale(struct saa7134_dev *dev, int task, int yscale) ...@@ -563,25 +574,30 @@ static void set_v_scale(struct saa7134_dev *dev, int task, int yscale)
static void set_size(struct saa7134_dev *dev, int task, static void set_size(struct saa7134_dev *dev, int task,
int width, int height, int interlace) int width, int height, int interlace)
{ {
struct saa7134_tvnorm *norm = dev->tvnorm;
int prescale,xscale,yscale,y_even,y_odd; int prescale,xscale,yscale,y_even,y_odd;
int h_start, h_stop, v_start, v_stop;
int div = interlace ? 2 : 1; int div = interlace ? 2 : 1;
/* setup video scaler */ /* setup video scaler */
saa_writeb(SAA7134_VIDEO_H_START1(task), norm->h_start & 0xff); h_start = dev->crop_current.left;
saa_writeb(SAA7134_VIDEO_H_START2(task), norm->h_start >> 8); v_start = dev->crop_current.top/2;
saa_writeb(SAA7134_VIDEO_H_STOP1(task), norm->h_stop & 0xff); h_stop = (dev->crop_current.left + dev->crop_current.width -1);
saa_writeb(SAA7134_VIDEO_H_STOP2(task), norm->h_stop >> 8); v_stop = (dev->crop_current.top + dev->crop_current.height -1)/2;
saa_writeb(SAA7134_VIDEO_V_START1(task), norm->video_v_start & 0xff);
saa_writeb(SAA7134_VIDEO_V_START2(task), norm->video_v_start >> 8); saa_writeb(SAA7134_VIDEO_H_START1(task), h_start & 0xff);
saa_writeb(SAA7134_VIDEO_V_STOP1(task), norm->video_v_stop & 0xff); saa_writeb(SAA7134_VIDEO_H_START2(task), h_start >> 8);
saa_writeb(SAA7134_VIDEO_V_STOP2(task), norm->video_v_stop >> 8); saa_writeb(SAA7134_VIDEO_H_STOP1(task), h_stop & 0xff);
saa_writeb(SAA7134_VIDEO_H_STOP2(task), h_stop >> 8);
prescale = norm->width / width; saa_writeb(SAA7134_VIDEO_V_START1(task), v_start & 0xff);
saa_writeb(SAA7134_VIDEO_V_START2(task), v_start >> 8);
saa_writeb(SAA7134_VIDEO_V_STOP1(task), v_stop & 0xff);
saa_writeb(SAA7134_VIDEO_V_STOP2(task), v_stop >> 8);
prescale = dev->crop_defrect.width / width;
if (0 == prescale) if (0 == prescale)
prescale = 1; prescale = 1;
xscale = 1024 * norm->width / prescale / width; xscale = 1024 * dev->crop_defrect.width / prescale / width;
yscale = 512 * div * norm->height / height; yscale = 512 * div * dev->crop_defrect.height / height;
dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);
set_h_prescale(dev,task,prescale); set_h_prescale(dev,task,prescale);
saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff); saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff);
...@@ -708,8 +724,8 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) ...@@ -708,8 +724,8 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win)
return -EINVAL; return -EINVAL;
field = win->field; field = win->field;
maxw = dev->tvnorm->width; maxw = dev->crop_current.width;
maxh = dev->tvnorm->height; maxh = dev->crop_current.height;
if (V4L2_FIELD_ANY == field) { if (V4L2_FIELD_ANY == field) {
field = (win->w.height > maxh/2) field = (win->w.height > maxh/2)
...@@ -895,8 +911,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, ...@@ -895,8 +911,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
return -EINVAL; return -EINVAL;
if (fh->width < 48 || if (fh->width < 48 ||
fh->height < 32 || fh->height < 32 ||
fh->width > dev->tvnorm->width || fh->width > dev->crop_current.width ||
fh->height > dev->tvnorm->height) fh->height > dev->crop_current.height)
return -EINVAL; return -EINVAL;
size = (fh->width * fh->height * fh->fmt->depth) >> 3; size = (fh->width * fh->height * fh->fmt->depth) >> 3;
if (0 != buf->vb.baddr && buf->vb.bsize < size) if (0 != buf->vb.baddr && buf->vb.bsize < size)
...@@ -1393,8 +1409,8 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1393,8 +1409,8 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
return -EINVAL; return -EINVAL;
field = f->fmt.pix.field; field = f->fmt.pix.field;
maxw = dev->tvnorm->width; maxw = dev->crop_current.width;
maxh = dev->tvnorm->height; maxh = dev->crop_current.height;
if (V4L2_FIELD_ANY == field) { if (V4L2_FIELD_ANY == field) {
field = (f->fmt.pix.height > maxh/2) field = (f->fmt.pix.height > maxh/2)
...@@ -1482,7 +1498,6 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, ...@@ -1482,7 +1498,6 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
} }
up(&dev->lock); up(&dev->lock);
return 0; return 0;
break;
case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_CAPTURE:
saa7134_vbi_fmt(dev,f); saa7134_vbi_fmt(dev,f);
return 0; return 0;
...@@ -1674,6 +1689,74 @@ static int video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1674,6 +1689,74 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return 0; return 0;
} }
case VIDIOC_CROPCAP:
{
struct v4l2_cropcap *cap = arg;
if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
return -EINVAL;
cap->bounds = dev->crop_bounds;
cap->defrect = dev->crop_defrect;
cap->pixelaspect.numerator = 1;
cap->pixelaspect.denominator = 1;
if (dev->tvnorm->id & V4L2_STD_525_60) {
cap->pixelaspect.numerator = 11;
cap->pixelaspect.denominator = 10;
}
if (dev->tvnorm->id & V4L2_STD_625_50) {
cap->pixelaspect.numerator = 54;
cap->pixelaspect.denominator = 59;
}
return 0;
}
case VIDIOC_G_CROP:
{
struct v4l2_crop * crop = arg;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
return -EINVAL;
crop->c = dev->crop_current;
return 0;
}
case VIDIOC_S_CROP:
{
struct v4l2_crop *crop = arg;
struct v4l2_rect *b = &dev->crop_bounds;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
return -EINVAL;
if (crop->c.height < 0)
return -EINVAL;
if (crop->c.width < 0)
return -EINVAL;
if (res_locked(fh->dev,RESOURCE_OVERLAY))
return -EBUSY;
if (res_locked(fh->dev,RESOURCE_VIDEO))
return -EBUSY;
if (crop->c.top < b->top)
crop->c.top = b->top;
if (crop->c.top > b->top + b->height)
crop->c.top = b->top + b->height;
if (crop->c.height > b->top - crop->c.top + b->height)
crop->c.height = b->top - crop->c.top + b->height;
if (crop->c.left < b->left)
crop->c.top = b->left;
if (crop->c.left > b->left + b->width)
crop->c.top = b->left + b->width;
if (crop->c.width > b->left - crop->c.left + b->width)
crop->c.width = b->left - crop->c.left + b->width;
dev->crop_current = crop->c;
return 0;
}
/* --- tuner ioctls ------------------------------------------ */ /* --- tuner ioctls ------------------------------------------ */
case VIDIOC_G_TUNER: case VIDIOC_G_TUNER:
{ {
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
*/ */
#include <linux/version.h> #include <linux/version.h>
#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,9) #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,11)
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -73,8 +73,6 @@ enum saa7134_video_out { ...@@ -73,8 +73,6 @@ enum saa7134_video_out {
struct saa7134_tvnorm { struct saa7134_tvnorm {
char *name; char *name;
v4l2_std_id id; v4l2_std_id id;
unsigned int width;
unsigned int height;
/* video decoder */ /* video decoder */
unsigned int sync_control; unsigned int sync_control;
...@@ -301,7 +299,8 @@ struct saa7134_oss { ...@@ -301,7 +299,8 @@ struct saa7134_oss {
unsigned int afmt; unsigned int afmt;
unsigned int rate; unsigned int rate;
unsigned int channels; unsigned int channels;
unsigned int recording; unsigned int recording_on;
unsigned int dma_running;
unsigned int blocks; unsigned int blocks;
unsigned int blksize; unsigned int blksize;
unsigned int bufsize; unsigned int bufsize;
...@@ -395,6 +394,11 @@ struct saa7134_dev { ...@@ -395,6 +394,11 @@ struct saa7134_dev {
int ctl_y_odd; int ctl_y_odd;
int ctl_y_even; int ctl_y_even;
/* crop */
struct v4l2_rect crop_bounds;
struct v4l2_rect crop_defrect;
struct v4l2_rect crop_current;
/* other global state info */ /* other global state info */
unsigned int automute; unsigned int automute;
struct saa7134_thread thread; struct saa7134_thread thread;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment