/*
+ *
* device driver for philips saa7134 based TV cards
* video4linux video interface
*
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
-#define V4L2_I2C_CLIENTS 1
+/* Include V4L1 specific functions. Should be removed soon */
+#include <linux/videodev.h>
/* ------------------------------------------------------------------ */
static unsigned int noninterlaced = 0;
static unsigned int gbufsize = 720*576*4;
static unsigned int gbufsize_max = 720*576*4;
-MODULE_PARM(video_debug,"i");
+module_param(video_debug, int, 0644);
MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
-MODULE_PARM(gbuffers,"i");
+module_param(gbuffers, int, 0444);
MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");
-MODULE_PARM(noninterlaced,"i");
+module_param(noninterlaced, int, 0644);
MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced");
#define dprintk(fmt, arg...) if (video_debug) \
printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x191 */
+
+/* Bit 0: VIP code T bit polarity */
+
+#define VP_T_CODE_P_NON_INVERTED 0x00
+#define VP_T_CODE_P_INVERTED 0x01
+
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x195 */
+
+/* Bit 2: Video output clock delay control */
+
+#define VP_CLK_CTRL2_NOT_DELAYED 0x00
+#define VP_CLK_CTRL2_DELAYED 0x04
+
+/* Bit 1: Video output clock invert control */
+
+#define VP_CLK_CTRL1_NON_INVERTED 0x00
+#define VP_CLK_CTRL1_INVERTED 0x02
+
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x196 */
+
+/* Bits 2 to 0: VSYNC pin video vertical sync type */
+
+#define VP_VS_TYPE_MASK 0x07
+
+#define VP_VS_TYPE_OFF 0x00
+#define VP_VS_TYPE_V123 0x01
+#define VP_VS_TYPE_V_ITU 0x02
+#define VP_VS_TYPE_VGATE_L 0x03
+#define VP_VS_TYPE_RESERVED1 0x04
+#define VP_VS_TYPE_RESERVED2 0x05
+#define VP_VS_TYPE_F_ITU 0x06
+#define VP_VS_TYPE_SC_FID 0x07
+
/* ------------------------------------------------------------------ */
/* data structs for video */
static int video_out[][9] = {
[CCIR656] = { 0x00, 0xb1, 0x00, 0xa1, 0x00, 0x04, 0x06, 0x00, 0x00 },
};
-
+
static struct saa7134_format formats[] = {
{
.name = "8 bpp gray",
.h_stop = 719, \
.video_v_start = 24, \
.video_v_stop = 311, \
- .vbi_v_start = 7, \
- .vbi_v_stop = 22, \
+ .vbi_v_start_0 = 7, \
+ .vbi_v_stop_0 = 22, \
+ .vbi_v_start_1 = 319, \
.src_timing = 4
#define NORM_525_60 \
.h_start = 0, \
.h_stop = 703, \
- .video_v_start = 22, \
- .video_v_stop = 22+239, \
- .vbi_v_start = 10, /* FIXME */ \
- .vbi_v_stop = 21, /* FIXME */ \
- .src_timing = 1
+ .video_v_start = 23, \
+ .video_v_stop = 262, \
+ .vbi_v_start_0 = 10, \
+ .vbi_v_stop_0 = 21, \
+ .vbi_v_start_1 = 273, \
+ .src_timing = 7
static struct saa7134_tvnorm tvnorms[] = {
{
.chroma_ctrl2 = 0x06,
.vgate_misc = 0x1c,
+ },{
+ .name = "PAL-60",
+ .id = V4L2_STD_PAL_60,
+
+ .h_start = 0,
+ .h_stop = 719,
+ .video_v_start = 23,
+ .video_v_stop = 262,
+ .vbi_v_start_0 = 10,
+ .vbi_v_stop_0 = 21,
+ .vbi_v_start_1 = 273,
+ .src_timing = 7,
+
+ .sync_control = 0x18,
+ .luma_control = 0x40,
+ .chroma_ctrl1 = 0x81,
+ .chroma_gain = 0x2a,
+ .chroma_ctrl2 = 0x06,
+ .vgate_misc = 0x1c,
}
};
#define TVNORMS ARRAY_SIZE(tvnorms)
.default_value = 0,
.type = V4L2_CTRL_TYPE_INTEGER,
},{
- .id = V4L2_CID_VFLIP,
- .name = "vertical flip",
+ .id = V4L2_CID_HFLIP,
+ .name = "Mirror",
.minimum = 0,
.maximum = 1,
.type = V4L2_CTRL_TYPE_BOOLEAN,
static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
{
unsigned int i;
-
+
for (i = 0; i < CTRLS; i++)
if (video_ctrls[i].id == id)
return video_ctrls+i;
static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
{
- int luma_control,sync_control,mux,nosignal;
+ int luma_control,sync_control,mux;
dprintk("set tv norm = %s\n",norm->name);
dev->tvnorm = norm;
- nosignal = (0 == (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03));
mux = card_in(dev,dev->ctl_input).vmux;
luma_control = norm->luma_control;
if (mux > 5)
luma_control |= 0x80; /* svideo */
- if (noninterlaced || nosignal)
+ if (noninterlaced || dev->nosignal)
sync_control |= 0x20;
/* setup cropping */
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_bounds.top = (norm->vbi_v_stop_0+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;
saa_writeb(SAA7134_HSYNC_START, 0xeb);
saa_writeb(SAA7134_HSYNC_STOP, 0xe0);
saa_writeb(SAA7134_SOURCE_TIMING1, norm->src_timing);
-
+
saa_writeb(SAA7134_SYNC_CTRL, sync_control);
saa_writeb(SAA7134_LUMA_CTRL, luma_control);
saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
saa_writeb(SAA7134_DEC_LUMA_CONTRAST, dev->ctl_contrast);
-
+
saa_writeb(SAA7134_DEC_CHROMA_SATURATION, dev->ctl_saturation);
saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue);
saa_writeb(SAA7134_CHROMA_CTRL1, norm->chroma_ctrl1);
saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40);
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
-#ifdef V4L2_I2C_CLIENTS
saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id);
-#else
- {
- /* pass down info to the i2c chips (v4l1) */
- struct video_channel c;
- memset(&c,0,sizeof(c));
- c.channel = dev->ctl_input;
- c.norm = VIDEO_MODE_PAL;
- if (norm->id & V4L2_STD_NTSC)
- c.norm = VIDEO_MODE_NTSC;
- if (norm->id & V4L2_STD_SECAM)
- c.norm = VIDEO_MODE_SECAM;
- saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c);
- }
-#endif
}
static void video_mux(struct saa7134_dev *dev, int input)
static void set_v_scale(struct saa7134_dev *dev, int task, int yscale)
{
int val,mirror;
-
+
saa_writeb(SAA7134_V_SCALE_RATIO1(task), yscale & 0xff);
saa_writeb(SAA7134_V_SCALE_RATIO2(task), yscale >> 8);
prescale = 1;
xscale = 1024 * dev->crop_current.width / prescale / width;
yscale = 512 * div * dev->crop_current.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);
saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff);
saa_writeb(SAA7134_H_SCALE_INC2(task), xscale >> 8);
set_v_scale(dev,task,yscale);
-
+
saa_writeb(SAA7134_VIDEO_PIXELS1(task), width & 0xff);
saa_writeb(SAA7134_VIDEO_PIXELS2(task), width >> 8);
saa_writeb(SAA7134_VIDEO_LINES1(task), height/div & 0xff);
{
struct cliplist swap;
int i,j,n;
-
+
for (i = entries-2; i >= 0; i--) {
for (n = 0, j = 0; j <= i; j++) {
if (cl[j].position > cl[j+1].position) {
maxh = dev->crop_current.height;
if (V4L2_FIELD_ANY == field) {
- field = (win->w.height > maxh/2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_TOP;
- }
- switch (field) {
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- maxh = maxh / 2;
- break;
- case V4L2_FIELD_INTERLACED:
- break;
- default:
- return -EINVAL;
- }
+ field = (win->w.height > maxh/2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_TOP;
+ }
+ switch (field) {
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ maxh = maxh / 2;
+ break;
+ case V4L2_FIELD_INTERLACED:
+ break;
+ default:
+ return -EINVAL;
+ }
win->field = field;
if (win->w.width > maxw)
dprintk("buffer_activate buf=%p\n",buf);
buf->vb.state = STATE_ACTIVE;
buf->top_seen = 0;
-
+
set_size(dev,TASK_A,buf->vb.width,buf->vb.height,
V4L2_FIELD_HAS_BOTH(buf->vb.field));
if (buf->fmt->yuv)
return 0;
}
-static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,
+static int buffer_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb,
enum v4l2_field field)
{
- struct saa7134_fh *fh = file->private_data;
+ struct saa7134_fh *fh = q->priv_data;
struct saa7134_dev *dev = fh->dev;
- struct saa7134_buf *buf = (struct saa7134_buf *)vb;
+ struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
unsigned int size;
int err;
-
+
/* sanity checks */
if (NULL == fh->fmt)
return -EINVAL;
}
static int
-buffer_setup(struct file *file, unsigned int *count, unsigned int *size)
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
- struct saa7134_fh *fh = file->private_data;
+ struct saa7134_fh *fh = q->priv_data;
*size = fh->fmt->depth * fh->width * fh->height >> 3;
if (0 == *count)
return 0;
}
-static void buffer_queue(struct file *file, struct videobuf_buffer *vb)
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct saa7134_fh *fh = file->private_data;
- struct saa7134_buf *buf = (struct saa7134_buf *)vb;
-
+ struct saa7134_fh *fh = q->priv_data;
+ struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+
saa7134_buffer_queue(fh->dev,&fh->dev->video_q,buf);
}
-static void buffer_release(struct file *file, struct videobuf_buffer *vb)
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct saa7134_fh *fh = file->private_data;
- struct saa7134_buf *buf = (struct saa7134_buf *)vb;
-
+ struct saa7134_fh *fh = q->priv_data;
+ struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+
saa7134_dma_free(fh->dev,buf);
}
case V4L2_CID_PRIVATE_INVERT:
c->value = dev->ctl_invert;
break;
- case V4L2_CID_VFLIP:
+ case V4L2_CID_HFLIP:
c->value = dev->ctl_mirror;
break;
case V4L2_CID_PRIVATE_Y_EVEN:
saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
break;
- case V4L2_CID_VFLIP:
+ case V4L2_CID_HFLIP:
dev->ctl_mirror = c->value;
restart_overlay = 1;
break;
static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh)
{
struct videobuf_queue* q = NULL;
-
+
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
q = &fh->cap;
static int saa7134_resource(struct saa7134_fh *fh)
{
int res = 0;
-
+
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
res = RESOURCE_VIDEO;
struct list_head *list;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int radio = 0;
-
list_for_each(list,&saa7134_devlist) {
h = list_entry(list, struct saa7134_dev, devlist);
if (h->video_dev && (h->video_dev->minor == minor))
v4l2_type_names[type]);
/* allocate + initialize per filehandle data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
fh->width = 720;
fh->height = 576;
-#ifdef VIDIOC_G_PRIORITY
v4l2_prio_open(&dev->prio,&fh->prio);
-#endif
videobuf_queue_init(&fh->cap, &video_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
- sizeof(struct saa7134_buf));
- init_MUTEX(&fh->cap.lock);
- saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
-
+ sizeof(struct saa7134_buf),
+ fh);
videobuf_queue_init(&fh->vbi, &saa7134_vbi_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB,
- sizeof(struct saa7134_buf));
- init_MUTEX(&fh->vbi.lock);
+ sizeof(struct saa7134_buf),
+ fh);
+ saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);
if (fh->radio) {
/* switch to radio mode */
saa7134_tvaudio_setinput(dev,&card(dev).radio);
- saa7134_i2c_call_clients(dev,AUDC_SET_RADIO,NULL);
+ saa7134_i2c_call_clients(dev,AUDC_SET_RADIO, NULL);
} else {
/* switch to video/vbi mode */
video_mux(dev,dev->ctl_input);
}
- return 0;
+ return 0;
}
static ssize_t
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (res_locked(fh->dev,RESOURCE_VIDEO))
return -EBUSY;
- return videobuf_read_one(file, saa7134_queue(fh),
- data, count, ppos);
+ return videobuf_read_one(saa7134_queue(fh),
+ data, count, ppos,
+ file->f_flags & O_NONBLOCK);
case V4L2_BUF_TYPE_VBI_CAPTURE:
if (!res_get(fh->dev,fh,RESOURCE_VBI))
return -EBUSY;
- return videobuf_read_stream(file, saa7134_queue(fh),
- data, count, ppos, 1);
+ return videobuf_read_stream(saa7134_queue(fh),
+ data, count, ppos, 1,
+ file->f_flags & O_NONBLOCK);
break;
default:
BUG();
} else {
down(&fh->cap.lock);
if (UNSET == fh->cap.read_off) {
- /* need to capture a new frame */
+ /* need to capture a new frame */
if (res_locked(fh->dev,RESOURCE_VIDEO)) {
- up(&fh->cap.lock);
- return POLLERR;
- }
- if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,fh->cap.field)) {
- up(&fh->cap.lock);
- return POLLERR;
- }
- fh->cap.ops->buf_queue(file,fh->cap.read_buf);
- fh->cap.read_off = 0;
+ up(&fh->cap.lock);
+ return POLLERR;
+ }
+ if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) {
+ up(&fh->cap.lock);
+ return POLLERR;
+ }
+ fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
+ fh->cap.read_off = 0;
}
up(&fh->cap.lock);
buf = fh->cap.read_buf;
/* stop video capture */
if (res_check(fh, RESOURCE_VIDEO)) {
- videobuf_streamoff(file,&fh->cap);
+ videobuf_streamoff(&fh->cap);
res_free(dev,fh,RESOURCE_VIDEO);
}
if (fh->cap.read_buf) {
- buffer_release(file,fh->cap.read_buf);
+ buffer_release(&fh->cap,fh->cap.read_buf);
kfree(fh->cap.read_buf);
}
/* stop vbi capture */
if (res_check(fh, RESOURCE_VBI)) {
if (fh->vbi.streaming)
- videobuf_streamoff(file,&fh->vbi);
+ videobuf_streamoff(&fh->vbi);
if (fh->vbi.reading)
- videobuf_read_stop(file,&fh->vbi);
+ videobuf_read_stop(&fh->vbi);
res_free(dev,fh,RESOURCE_VBI);
}
+ /* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/
+ saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0);
+ saa_andorb(SAA7134_OFMT_VIDEO_B, 0x1f, 0);
+ saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);
+ saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
+
+ saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
+
+ /* free stuff */
+ videobuf_mmap_free(&fh->cap);
+ videobuf_mmap_free(&fh->vbi);
saa7134_pgtable_free(dev->pci,&fh->pt_cap);
saa7134_pgtable_free(dev->pci,&fh->pt_vbi);
-#ifdef VIDIOC_G_PRIORITY
v4l2_prio_close(&dev->prio,&fh->prio);
-#endif
file->private_data = NULL;
kfree(fh);
return 0;
video_mmap(struct file *file, struct vm_area_struct * vma)
{
struct saa7134_fh *fh = file->private_data;
-
- return videobuf_mmap_mapper(vma,saa7134_queue(fh));
+
+ return videobuf_mmap_mapper(saa7134_queue(fh), vma);
}
/* ------------------------------------------------------------------ */
-void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f)
+static void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f)
{
struct saa7134_tvnorm *norm = dev->tvnorm;
f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
f->fmt.vbi.offset = 64 * 4;
- f->fmt.vbi.start[0] = norm->vbi_v_start;
- f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1;
- f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start +1;
+ f->fmt.vbi.start[0] = norm->vbi_v_start_0;
+ f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
+ f->fmt.vbi.start[1] = norm->vbi_v_start_1;
f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */
-#if 0
- if (V4L2_STD_PAL == norm->id) {
- /* FIXME */
- f->fmt.vbi.start[0] += 3;
- f->fmt.vbi.start[1] += 3*2;
- }
-#endif
}
-int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
- struct v4l2_format *f)
+static int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
+ struct v4l2_format *f)
{
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
}
}
-int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
- struct v4l2_format *f)
+static int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
+ struct v4l2_format *f)
{
int err;
-
+
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
field = f->fmt.pix.field;
maxw = min(dev->crop_current.width*4, dev->crop_bounds.width);
maxh = min(dev->crop_current.height*4, dev->crop_bounds.height);
-
+
if (V4L2_FIELD_ANY == field) {
field = (f->fmt.pix.height > maxh/2)
? V4L2_FIELD_INTERLACED
f->fmt.pix.width = maxw;
if (f->fmt.pix.height > maxh)
f->fmt.pix.height = maxh;
+ f->fmt.pix.width &= ~0x03;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
-
+
return 0;
}
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
}
}
-int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
- struct v4l2_format *f)
+static int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
+ struct v4l2_format *f)
{
unsigned long flags;
int err;
-
+
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
err = saa7134_try_fmt(dev,fh,f);
if (0 != err)
return err;
-
+
fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
fh->width = f->fmt.pix.width;
fh->height = f->fmt.pix.height;
unsigned int cmd, void *arg)
{
int err;
-
+
switch (cmd) {
case VIDIOC_QUERYCTRL:
{
case VIDIOC_S_INPUT:
{
int *i = arg;
-
+
if (*i < 0 || *i >= SAA7134_INPUT_MAX)
return -EINVAL;
if (NULL == card_in(dev,*i).name)
}
return 0;
}
+EXPORT_SYMBOL(saa7134_common_ioctl);
/*
* This function is _not_ called directly, but from
int err;
if (video_debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
-#ifdef VIDIOC_G_PRIORITY
switch (cmd) {
case VIDIOC_S_CTRL:
case VIDIOC_S_STD:
if (0 != err)
return err;
}
-#endif
switch (cmd) {
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
-
+ unsigned int tuner_type = dev->tuner_type;
+
memset(cap,0,sizeof(*cap));
- strcpy(cap->driver, "saa7134");
+ strcpy(cap->driver, "saa7134");
strlcpy(cap->card, saa7134_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_TUNER |
- V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING;
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_TUNER;
+
+ if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET))
+ cap->capabilities &= ~V4L2_CAP_TUNER;
+
return 0;
}
set_tvnorm(dev,&tvnorms[i]);
start_preview(dev,fh);
spin_unlock_irqrestore(&dev->slock,flags);
- } else
+ } else
set_tvnorm(dev,&tvnorms[i]);
saa7134_tvaudio_do_scan(dev);
up(&dev->lock);
crop->c.height = b->top - crop->c.top + b->height;
if (crop->c.left < b->left)
- crop->c.top = b->left;
+ crop->c.left = b->left;
if (crop->c.left > b->left + b->width)
- crop->c.top = b->left + b->width;
+ crop->c.left = 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;
break;
if (NULL != card_in(dev,n).name) {
strcpy(t->name, "Television");
+ t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM |
V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 |
return -EINVAL;
down(&dev->lock);
dev->ctl_freq = f->frequency;
-#ifdef V4L2_I2C_CLIENTS
+
saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f);
-#else
- saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&dev->ctl_freq);
-#endif
+
saa7134_tvaudio_do_scan(dev);
up(&dev->lock);
return 0;
}
-
+
/* --- control ioctls ---------------------------------------- */
case VIDIOC_ENUMINPUT:
case VIDIOC_G_INPUT:
}
case VIDIOC_S_AUDIO:
return 0;
- case VIDIOC_G_PARM:
- {
- struct v4l2_captureparm *parm = arg;
- memset(parm,0,sizeof(*parm));
- return 0;
- }
-
-#ifdef VIDIOC_G_PRIORITY
- case VIDIOC_G_PRIORITY:
- {
- enum v4l2_priority *p = arg;
-
- *p = v4l2_prio_max(&dev->prio);
- return 0;
- }
- case VIDIOC_S_PRIORITY:
- {
- enum v4l2_priority *prio = arg;
-
- return v4l2_prio_change(&dev->prio, &fh->prio, *prio);
- }
-#endif
+ case VIDIOC_G_PARM:
+ {
+ struct v4l2_captureparm *parm = arg;
+ memset(parm,0,sizeof(*parm));
+ return 0;
+ }
+
+ case VIDIOC_G_PRIORITY:
+ {
+ enum v4l2_priority *p = arg;
+
+ *p = v4l2_prio_max(&dev->prio);
+ return 0;
+ }
+ case VIDIOC_S_PRIORITY:
+ {
+ enum v4l2_priority *prio = arg;
+
+ return v4l2_prio_change(&dev->prio, &fh->prio, *prio);
+ }
/* --- preview ioctls ---------------------------------------- */
case VIDIOC_ENUM_FMT:
strcpy(f->description,"vbi data");
break;
default:
- return -EINVAL;
+ return -EINVAL;
}
return 0;
}
{
struct v4l2_framebuffer *fb = arg;
struct saa7134_format *fmt;
-
+
if(!capable(CAP_SYS_ADMIN) &&
!capable(CAP_SYS_RAWIO))
return -EPERM;
struct v4l2_format *f = arg;
return saa7134_try_fmt(dev,fh,f);
}
-
+#ifdef HAVE_V4L1
case VIDIOCGMBUF:
{
struct video_mbuf *mbuf = arg;
req.type = q->type;
req.count = gbuffers;
req.memory = V4L2_MEMORY_MMAP;
- err = videobuf_reqbufs(file,q,&req);
+ err = videobuf_reqbufs(q,&req);
if (err < 0)
return err;
memset(mbuf,0,sizeof(*mbuf));
}
return 0;
}
+#endif
case VIDIOC_REQBUFS:
- return videobuf_reqbufs(file,saa7134_queue(fh),arg);
+ return videobuf_reqbufs(saa7134_queue(fh),arg);
case VIDIOC_QUERYBUF:
return videobuf_querybuf(saa7134_queue(fh),arg);
case VIDIOC_QBUF:
- return videobuf_qbuf(file,saa7134_queue(fh),arg);
+ return videobuf_qbuf(saa7134_queue(fh),arg);
case VIDIOC_DQBUF:
- return videobuf_dqbuf(file,saa7134_queue(fh),arg);
+ return videobuf_dqbuf(saa7134_queue(fh),arg,
+ file->f_flags & O_NONBLOCK);
case VIDIOC_STREAMON:
{
int res = saa7134_resource(fh);
- if (!res_get(dev,fh,res))
+ if (!res_get(dev,fh,res))
return -EBUSY;
- return videobuf_streamon(file,saa7134_queue(fh));
+ return videobuf_streamon(saa7134_queue(fh));
}
case VIDIOC_STREAMOFF:
{
int res = saa7134_resource(fh);
- err = videobuf_streamoff(file,saa7134_queue(fh));
+ err = videobuf_streamoff(saa7134_queue(fh));
if (err < 0)
return err;
res_free(dev,fh,res);
{
struct saa7134_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev;
-
+
if (video_debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
memset(cap,0,sizeof(*cap));
- strcpy(cap->driver, "saa7134");
+ strcpy(cap->driver, "saa7134");
strlcpy(cap->card, saa7134_boards[dev->board].name,
sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
memset(t,0,sizeof(*t));
strcpy(t->name, "Radio");
- t->rangelow = (int)(65*16);
- t->rangehigh = (int)(108*16);
-
-#ifdef V4L2_I2C_CLIENTS
- saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,t);
-#else
- {
- struct video_tuner vt;
- memset(&vt,0,sizeof(vt));
- saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt);
- t->signal = vt.signal;
- }
-#endif
+ t->type = V4L2_TUNER_RADIO;
+
+ saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
+
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
+
+ if (0 != t->index)
+ return -EINVAL;
+
+ saa7134_i2c_call_clients(dev,VIDIOC_S_TUNER,t);
+
return 0;
}
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *i = arg;
-
+
if (i->index != 0)
return -EINVAL;
strcpy(i->name,"Radio");
return 0;
}
case VIDIOC_S_AUDIO:
- case VIDIOC_S_TUNER:
case VIDIOC_S_INPUT:
case VIDIOC_S_STD:
return 0;
case VIDIOC_G_FREQUENCY:
case VIDIOC_S_FREQUENCY:
return video_do_ioctl(inode,file,cmd,arg);
-
+
default:
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
radio_do_ioctl);
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
.open = video_open,
.release = video_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
{
.name = "saa7134-video",
.type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY|
- VID_TYPE_CLIPPING|VID_TYPE_SCALES,
+ VID_TYPE_CLIPPING|VID_TYPE_SCALES,
.hardware = 0,
.fops = &video_fops,
.minor = -1,
dev->ctl_hue = ctrl_by_id(V4L2_CID_HUE)->default_value;
dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
dev->ctl_volume = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
- dev->ctl_mute = ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
+ dev->ctl_mute = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
dev->ctl_invert = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
dev->ctl_automute = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
dev->tda9887_conf |= TDA9887_AUTOMUTE;
dev->automute = 0;
- INIT_LIST_HEAD(&dev->video_q.queue);
+ INIT_LIST_HEAD(&dev->video_q.queue);
init_timer(&dev->video_q.timeout);
dev->video_q.timeout.function = saa7134_buffer_timeout;
dev->video_q.timeout.data = (unsigned long)(&dev->video_q);
if (saa7134_boards[dev->board].video_out) {
/* enable video output */
int vo = saa7134_boards[dev->board].video_out;
+ int video_reg;
+ unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts;
saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]);
- saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_out[vo][1]);
+ video_reg = video_out[vo][1];
+ if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED)
+ video_reg &= ~VP_T_CODE_P_INVERTED;
+ saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg);
saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]);
saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]);
- saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_out[vo][5]);
- saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_out[vo][6]);
+ video_reg = video_out[vo][5];
+ if (vid_port_opts & SET_CLOCK_NOT_DELAYED)
+ video_reg &= ~VP_CLK_CTRL2_DELAYED;
+ if (vid_port_opts & SET_CLOCK_INVERTED)
+ video_reg |= VP_CLK_CTRL1_INVERTED;
+ saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg);
+ video_reg = video_out[vo][6];
+ if (vid_port_opts & SET_VSYNC_OFF) {
+ video_reg &= ~VP_VS_TYPE_MASK;
+ video_reg |= VP_VS_TYPE_OFF;
+ }
+ saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg);
saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]);
saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]);
}
-
+
return 0;
}
void saa7134_irq_video_intl(struct saa7134_dev *dev)
{
static const char *st[] = {
- "no signal", "found NTSC", "found PAL", "found SECAM" };
- int norm;
-
- norm = saa_readb(SAA7134_STATUS_VIDEO1) & 0x03;
- dprintk("DCSDT: %s\n",st[norm]);
-
- if (0 != norm) {
- /* wake up tvaudio audio carrier scan thread */
- saa7134_tvaudio_do_scan(dev);
- if (!noninterlaced)
- saa_clearb(SAA7134_SYNC_CTRL, 0x20);
- } else {
+ "(no signal)", "NTSC", "PAL", "SECAM" };
+ u32 st1,st2;
+
+ st1 = saa_readb(SAA7134_STATUS_VIDEO1);
+ st2 = saa_readb(SAA7134_STATUS_VIDEO2);
+ dprintk("DCSDT: pll: %s, sync: %s, norm: %s\n",
+ (st1 & 0x40) ? "not locked" : "locked",
+ (st2 & 0x40) ? "no" : "yes",
+ st[st1 & 0x03]);
+ dev->nosignal = (st1 & 0x40) || (st2 & 0x40);
+
+ if (dev->nosignal) {
/* no video signal -> mute audio */
if (dev->ctl_automute)
dev->automute = 1;
saa7134_tvaudio_setmute(dev);
saa_setb(SAA7134_SYNC_CTRL, 0x20);
+ } else {
+ /* wake up tvaudio audio carrier scan thread */
+ saa7134_tvaudio_do_scan(dev);
+ if (!noninterlaced)
+ saa_clearb(SAA7134_SYNC_CTRL, 0x20);
}
+ if (dev->mops && dev->mops->signal_change)
+ dev->mops->signal_change(dev);
}
void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
{
enum v4l2_field field;
-
+
spin_lock(&dev->slock);
if (dev->video_q.curr) {
dev->video_fieldcount++;