add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
config VIDEO_SAA7134
tristate "Philips SAA7134 support"
depends on VIDEO_DEV && PCI && I2C && INPUT
select VIDEOBUF_DMA_SG
select VIDEO_IR
select VIDEO_TUNER
select VIDEO_TVEEPROM
select CRC32
select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
---help---
This is a video4linux driver for Philips SAA713x based
TV cards.
To compile this driver as a module, choose M here: the
module will be called saa7134.
config VIDEO_SAA7134_ALSA
tristate "Philips SAA7134 DMA audio support"
depends on VIDEO_SAA7134 && SND
select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio in
Philips SAA713x based TV cards using ALSA
To compile this driver as a module, choose M here: the
module will be called saa7134-alsa.
config VIDEO_SAA7134_DVB
tristate "DVB/ATSC Support for saa7134 based TV cards"
depends on VIDEO_SAA7134 && DVB_CORE
select VIDEOBUF_DVB
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_NXT200X if !DVB_FE_CUSTOMISE
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
select DVB_ISL6405 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
select DVB_ZL10036 if !DVB_FE_CUSTOMISE
select DVB_MT312 if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
select DVB_TDA10048 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
select DVB_ZL10039 if !DVB_FE_CUSTOMISE
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
To compile this driver as a module, choose M here: the
module will be called saa7134-dvb.

View File

@@ -0,0 +1,15 @@
saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \
saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \
saa7134-video.o saa7134-input.o
obj-$(CONFIG_VIDEO_SAA7134) += saa6752hs.o saa7134.o saa7134-empress.o
obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
EXTRA_CFLAGS += -Idrivers/media/video
EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,594 @@
/*
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include "saa7134-reg.h"
#include "saa7134.h"
#include <media/saa6752hs.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
/* ------------------------------------------------------------------ */
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
module_param_array(empress_nr, int, NULL, 0444);
MODULE_PARM_DESC(empress_nr,"ts device number");
static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug,"enable debug messages");
#define dprintk(fmt, arg...) if (debug) \
printk(KERN_DEBUG "%s/empress: " fmt, dev->name , ## arg)
/* ------------------------------------------------------------------ */
static void ts_reset_encoder(struct saa7134_dev* dev)
{
if (!dev->empress_started)
return;
saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
msleep(10);
saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
msleep(100);
dev->empress_started = 0;
}
static int ts_init_encoder(struct saa7134_dev* dev)
{
u32 leading_null_bytes = 0;
/* If more cards start to need this, then this
should probably be added to the card definitions. */
switch (dev->board) {
case SAA7134_BOARD_BEHOLD_M6:
case SAA7134_BOARD_BEHOLD_M63:
case SAA7134_BOARD_BEHOLD_M6_EXTRA:
leading_null_bytes = 1;
break;
}
ts_reset_encoder(dev);
saa_call_all(dev, core, init, leading_null_bytes);
dev->empress_started = 1;
return 0;
}
/* ------------------------------------------------------------------ */
static int ts_open(struct file *file)
{
int minor = video_devdata(file)->minor;
struct saa7134_dev *dev;
int err;
lock_kernel();
list_for_each_entry(dev, &saa7134_devlist, devlist)
if (dev->empress_dev && dev->empress_dev->minor == minor)
goto found;
unlock_kernel();
return -ENODEV;
found:
dprintk("open minor=%d\n",minor);
err = -EBUSY;
if (!mutex_trylock(&dev->empress_tsq.vb_lock))
goto done;
if (atomic_read(&dev->empress_users))
goto done_up;
/* Unmute audio */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
atomic_inc(&dev->empress_users);
file->private_data = dev;
err = 0;
done_up:
mutex_unlock(&dev->empress_tsq.vb_lock);
done:
unlock_kernel();
return err;
}
static int ts_release(struct file *file)
{
struct saa7134_dev *dev = file->private_data;
videobuf_stop(&dev->empress_tsq);
videobuf_mmap_free(&dev->empress_tsq);
/* stop the encoder */
ts_reset_encoder(dev);
/* Mute audio */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
atomic_dec(&dev->empress_users);
return 0;
}
static ssize_t
ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
{
struct saa7134_dev *dev = file->private_data;
if (!dev->empress_started)
ts_init_encoder(dev);
return videobuf_read_stream(&dev->empress_tsq,
data, count, ppos, 0,
file->f_flags & O_NONBLOCK);
}
static unsigned int
ts_poll(struct file *file, struct poll_table_struct *wait)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_poll_stream(file, &dev->empress_tsq, wait);
}
static int
ts_mmap(struct file *file, struct vm_area_struct * vma)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_mmap_mapper(&dev->empress_tsq, vma);
}
/*
* This function is _not_ called directly, but from
* video_generic_ioctl (and maybe others). userspace
* copying is done already, arg is a kernel pointer.
*/
static int empress_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
struct saa7134_dev *dev = file->private_data;
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));
cap->version = SAA7134_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
return 0;
}
static int empress_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
if (i->index != 0)
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA;
strcpy(i->name, "CCIR656");
return 0;
}
static int empress_g_input(struct file *file, void *priv, unsigned int *i)
{
*i = 0;
return 0;
}
static int empress_s_input(struct file *file, void *priv, unsigned int i)
{
if (i != 0)
return -EINVAL;
return 0;
}
static int empress_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index != 0)
return -EINVAL;
strlcpy(f->description, "MPEG TS", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_MPEG;
return 0;
}
static int empress_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_dev *dev = file->private_data;
saa_call_all(dev, video, g_fmt, f);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
return 0;
}
static int empress_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_dev *dev = file->private_data;
saa_call_all(dev, video, s_fmt, f);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
return 0;
}
static int empress_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_dev *dev = file->private_data;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
return 0;
}
static int empress_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_reqbufs(&dev->empress_tsq, p);
}
static int empress_querybuf(struct file *file, void *priv,
struct v4l2_buffer *b)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_querybuf(&dev->empress_tsq, b);
}
static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_qbuf(&dev->empress_tsq, b);
}
static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_dqbuf(&dev->empress_tsq, b,
file->f_flags & O_NONBLOCK);
}
static int empress_streamon(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_streamon(&dev->empress_tsq);
}
static int empress_streamoff(struct file *file, void *priv,
enum v4l2_buf_type type)
{
struct saa7134_dev *dev = file->private_data;
return videobuf_streamoff(&dev->empress_tsq);
}
static int empress_s_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *ctrls)
{
struct saa7134_dev *dev = file->private_data;
int err;
/* count == 0 is abused in saa6752hs.c, so that special
case is handled here explicitly. */
if (ctrls->count == 0)
return 0;
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
ts_init_encoder(dev);
return err;
}
static int empress_g_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *ctrls)
{
struct saa7134_dev *dev = file->private_data;
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
}
static int empress_g_ctrl(struct file *file, void *priv,
struct v4l2_control *c)
{
struct saa7134_dev *dev = file->private_data;
return saa7134_g_ctrl_internal(dev, NULL, c);
}
static int empress_s_ctrl(struct file *file, void *priv,
struct v4l2_control *c)
{
struct saa7134_dev *dev = file->private_data;
return saa7134_s_ctrl_internal(dev, NULL, c);
}
static int empress_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *c)
{
/* Must be sorted from low to high control ID! */
static const u32 user_ctrls[] = {
V4L2_CID_USER_CLASS,
V4L2_CID_BRIGHTNESS,
V4L2_CID_CONTRAST,
V4L2_CID_SATURATION,
V4L2_CID_HUE,
V4L2_CID_AUDIO_VOLUME,
V4L2_CID_AUDIO_MUTE,
V4L2_CID_HFLIP,
0
};
/* Must be sorted from low to high control ID! */
static const u32 mpeg_ctrls[] = {
V4L2_CID_MPEG_CLASS,
V4L2_CID_MPEG_STREAM_TYPE,
V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
V4L2_CID_MPEG_AUDIO_ENCODING,
V4L2_CID_MPEG_AUDIO_L2_BITRATE,
V4L2_CID_MPEG_VIDEO_ENCODING,
V4L2_CID_MPEG_VIDEO_ASPECT,
V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
V4L2_CID_MPEG_VIDEO_BITRATE,
V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
0
};
static const u32 *ctrl_classes[] = {
user_ctrls,
mpeg_ctrls,
NULL
};
struct saa7134_dev *dev = file->private_data;
c->id = v4l2_ctrl_next(ctrl_classes, c->id);
if (c->id == 0)
return -EINVAL;
if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
return saa7134_queryctrl(file, priv, c);
return saa_call_empress(dev, core, queryctrl, c);
}
static int empress_querymenu(struct file *file, void *priv,
struct v4l2_querymenu *c)
{
struct saa7134_dev *dev = file->private_data;
if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
return saa_call_empress(dev, core, querymenu, c);
}
static int empress_g_chip_ident(struct file *file, void *fh,
struct v4l2_dbg_chip_ident *chip)
{
struct saa7134_dev *dev = file->private_data;
chip->ident = V4L2_IDENT_NONE;
chip->revision = 0;
if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
!strcmp(chip->match.name, "saa6752hs"))
return saa_call_empress(dev, core, g_chip_ident, chip);
if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR)
return saa_call_empress(dev, core, g_chip_ident, chip);
return -EINVAL;
}
static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
{
struct saa7134_dev *dev = file->private_data;
return saa7134_s_std_internal(dev, NULL, id);
}
static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
{
struct saa7134_dev *dev = file->private_data;
*id = dev->tvnorm->id;
return 0;
}
static const struct v4l2_file_operations ts_fops =
{
.owner = THIS_MODULE,
.open = ts_open,
.release = ts_release,
.read = ts_read,
.poll = ts_poll,
.mmap = ts_mmap,
.ioctl = video_ioctl2,
};
static const struct v4l2_ioctl_ops ts_ioctl_ops = {
.vidioc_querycap = empress_querycap,
.vidioc_enum_fmt_vid_cap = empress_enum_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = empress_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap,
.vidioc_reqbufs = empress_reqbufs,
.vidioc_querybuf = empress_querybuf,
.vidioc_qbuf = empress_qbuf,
.vidioc_dqbuf = empress_dqbuf,
.vidioc_streamon = empress_streamon,
.vidioc_streamoff = empress_streamoff,
.vidioc_s_ext_ctrls = empress_s_ext_ctrls,
.vidioc_g_ext_ctrls = empress_g_ext_ctrls,
.vidioc_enum_input = empress_enum_input,
.vidioc_g_input = empress_g_input,
.vidioc_s_input = empress_s_input,
.vidioc_queryctrl = empress_queryctrl,
.vidioc_querymenu = empress_querymenu,
.vidioc_g_ctrl = empress_g_ctrl,
.vidioc_s_ctrl = empress_s_ctrl,
.vidioc_g_chip_ident = empress_g_chip_ident,
.vidioc_s_std = empress_s_std,
.vidioc_g_std = empress_g_std,
};
/* ----------------------------------------------------------- */
static struct video_device saa7134_empress_template = {
.name = "saa7134-empress",
.fops = &ts_fops,
.minor = -1,
.ioctl_ops = &ts_ioctl_ops,
.tvnorms = SAA7134_NORMS,
.current_norm = V4L2_STD_PAL,
};
static void empress_signal_update(struct work_struct *work)
{
struct saa7134_dev* dev =
container_of(work, struct saa7134_dev, empress_workqueue);
if (dev->nosignal) {
dprintk("no video signal\n");
} else {
dprintk("video signal acquired\n");
}
}
static void empress_signal_change(struct saa7134_dev *dev)
{
schedule_work(&dev->empress_workqueue);
}
static int empress_init(struct saa7134_dev *dev)
{
int err;
dprintk("%s: %s\n",dev->name,__func__);
dev->empress_dev = video_device_alloc();
if (NULL == dev->empress_dev)
return -ENOMEM;
*(dev->empress_dev) = saa7134_empress_template;
dev->empress_dev->parent = &dev->pci->dev;
dev->empress_dev->release = video_device_release;
snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
"%s empress (%s)", dev->name,
saa7134_boards[dev->board].name);
INIT_WORK(&dev->empress_workqueue, empress_signal_update);
err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
empress_nr[dev->nr]);
if (err < 0) {
printk(KERN_INFO "%s: can't register video device\n",
dev->name);
video_device_release(dev->empress_dev);
dev->empress_dev = NULL;
return err;
}
printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
dev->name, dev->empress_dev->num);
videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
&dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
sizeof(struct saa7134_buf),
dev);
empress_signal_update(&dev->empress_workqueue);
return 0;
}
static int empress_fini(struct saa7134_dev *dev)
{
dprintk("%s: %s\n",dev->name,__func__);
if (NULL == dev->empress_dev)
return 0;
flush_scheduled_work();
video_unregister_device(dev->empress_dev);
dev->empress_dev = NULL;
return 0;
}
static struct saa7134_mpeg_ops empress_ops = {
.type = SAA7134_MPEG_EMPRESS,
.init = empress_init,
.fini = empress_fini,
.signal_change = empress_signal_change,
};
static int __init empress_register(void)
{
return saa7134_ts_register(&empress_ops);
}
static void __exit empress_unregister(void)
{
saa7134_ts_unregister(&empress_ops);
}
module_init(empress_register);
module_exit(empress_unregister);
/* ----------------------------------------------------------- */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@@ -0,0 +1,425 @@
/*
*
* device driver for philips saa7134 based TV cards
* i2c interface support
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include "saa7134-reg.h"
#include "saa7134.h"
#include <media/v4l2-common.h>
/* ----------------------------------------------------------- */
static unsigned int i2c_debug;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
static unsigned int i2c_scan;
module_param(i2c_scan, int, 0444);
MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
#define d1printk if (1 == i2c_debug) printk
#define d2printk if (2 == i2c_debug) printk
#define I2C_WAIT_DELAY 32
#define I2C_WAIT_RETRY 16
/* ----------------------------------------------------------- */
static char *str_i2c_status[] = {
"IDLE", "DONE_STOP", "BUSY", "TO_SCL", "TO_ARB", "DONE_WRITE",
"DONE_READ", "DONE_WRITE_TO", "DONE_READ_TO", "NO_DEVICE",
"NO_ACKN", "BUS_ERR", "ARB_LOST", "SEQ_ERR", "ST_ERR", "SW_ERR"
};
enum i2c_status {
IDLE = 0, // no I2C command pending
DONE_STOP = 1, // I2C command done and STOP executed
BUSY = 2, // executing I2C command
TO_SCL = 3, // executing I2C command, time out on clock stretching
TO_ARB = 4, // time out on arbitration trial, still trying
DONE_WRITE = 5, // I2C command done and awaiting next write command
DONE_READ = 6, // I2C command done and awaiting next read command
DONE_WRITE_TO = 7, // see 5, and time out on status echo
DONE_READ_TO = 8, // see 6, and time out on status echo
NO_DEVICE = 9, // no acknowledge on device slave address
NO_ACKN = 10, // no acknowledge after data byte transfer
BUS_ERR = 11, // bus error
ARB_LOST = 12, // arbitration lost during transfer
SEQ_ERR = 13, // erroneous programming sequence
ST_ERR = 14, // wrong status echoing
SW_ERR = 15 // software error
};
static char *str_i2c_attr[] = {
"NOP", "STOP", "CONTINUE", "START"
};
enum i2c_attr {
NOP = 0, // no operation on I2C bus
STOP = 1, // stop condition, no associated byte transfer
CONTINUE = 2, // continue with byte transfer
START = 3 // start condition with byte transfer
};
static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
{
enum i2c_status status;
status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name,
str_i2c_status[status]);
return status;
}
static inline void i2c_set_status(struct saa7134_dev *dev,
enum i2c_status status)
{
d2printk(KERN_DEBUG "%s: i2c stat => %s\n",dev->name,
str_i2c_status[status]);
saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
}
static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
{
d2printk(KERN_DEBUG "%s: i2c attr => %s\n",dev->name,
str_i2c_attr[attr]);
saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
}
static inline int i2c_is_error(enum i2c_status status)
{
switch (status) {
case NO_DEVICE:
case NO_ACKN:
case BUS_ERR:
case ARB_LOST:
case SEQ_ERR:
case ST_ERR:
return true;
default:
return false;
}
}
static inline int i2c_is_idle(enum i2c_status status)
{
switch (status) {
case IDLE:
case DONE_STOP:
return true;
default:
return false;
}
}
static inline int i2c_is_busy(enum i2c_status status)
{
switch (status) {
case BUSY:
case TO_SCL:
case TO_ARB:
return true;
default:
return false;
}
}
static int i2c_is_busy_wait(struct saa7134_dev *dev)
{
enum i2c_status status;
int count;
for (count = 0; count < I2C_WAIT_RETRY; count++) {
status = i2c_get_status(dev);
if (!i2c_is_busy(status))
break;
saa_wait(I2C_WAIT_DELAY);
}
if (I2C_WAIT_RETRY == count)
return false;
return true;
}
static int i2c_reset(struct saa7134_dev *dev)
{
enum i2c_status status;
int count;
d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
status = i2c_get_status(dev);
if (!i2c_is_error(status))
return true;
i2c_set_status(dev,status);
for (count = 0; count < I2C_WAIT_RETRY; count++) {
status = i2c_get_status(dev);
if (!i2c_is_error(status))
break;
udelay(I2C_WAIT_DELAY);
}
if (I2C_WAIT_RETRY == count)
return false;
if (!i2c_is_idle(status))
return false;
i2c_set_attr(dev,NOP);
return true;
}
static inline int i2c_send_byte(struct saa7134_dev *dev,
enum i2c_attr attr,
unsigned char data)
{
enum i2c_status status;
__u32 dword;
/* have to write both attr + data in one 32bit word */
dword = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2);
dword &= 0x0f;
dword |= (attr << 6);
dword |= ((__u32)data << 8);
dword |= 0x00 << 16; /* 100 kHz */
// dword |= 0x40 << 16; /* 400 kHz */
dword |= 0xf0 << 24;
saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data);
if (!i2c_is_busy_wait(dev))
return -EIO;
status = i2c_get_status(dev);
if (i2c_is_error(status))
return -EIO;
return 0;
}
static inline int i2c_recv_byte(struct saa7134_dev *dev)
{
enum i2c_status status;
unsigned char data;
i2c_set_attr(dev,CONTINUE);
if (!i2c_is_busy_wait(dev))
return -EIO;
status = i2c_get_status(dev);
if (i2c_is_error(status))
return -EIO;
data = saa_readb(SAA7134_I2C_DATA);
d2printk(KERN_DEBUG "%s: i2c data <= 0x%x\n",dev->name,data);
return data;
}
static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs, int num)
{
struct saa7134_dev *dev = i2c_adap->algo_data;
enum i2c_status status;
unsigned char data;
int addr,rc,i,byte;
status = i2c_get_status(dev);
if (!i2c_is_idle(status))
if (!i2c_reset(dev))
return -EIO;
d2printk("start xfer\n");
d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
for (i = 0; i < num; i++) {
if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
/* send address */
d2printk("send address\n");
addr = msgs[i].addr << 1;
if (msgs[i].flags & I2C_M_RD)
addr |= 1;
if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) {
/* workaround for a saa7134 i2c bug
* needed to talk to the mt352 demux
* thanks to pinnacle for the hint */
int quirk = 0xfe;
d1printk(" [%02x quirk]",quirk);
i2c_send_byte(dev,START,quirk);
i2c_recv_byte(dev);
}
d1printk(" < %02x", addr);
rc = i2c_send_byte(dev,START,addr);
if (rc < 0)
goto err;
}
if (msgs[i].flags & I2C_M_RD) {
/* read bytes */
d2printk("read bytes\n");
for (byte = 0; byte < msgs[i].len; byte++) {
d1printk(" =");
rc = i2c_recv_byte(dev);
if (rc < 0)
goto err;
d1printk("%02x", rc);
msgs[i].buf[byte] = rc;
}
} else {
/* write bytes */
d2printk("write bytes\n");
for (byte = 0; byte < msgs[i].len; byte++) {
data = msgs[i].buf[byte];
d1printk(" %02x", data);
rc = i2c_send_byte(dev,CONTINUE,data);
if (rc < 0)
goto err;
}
}
}
d2printk("xfer done\n");
d1printk(" >");
i2c_set_attr(dev,STOP);
rc = -EIO;
if (!i2c_is_busy_wait(dev))
goto err;
status = i2c_get_status(dev);
if (i2c_is_error(status))
goto err;
/* ensure that the bus is idle for at least one bit slot */
msleep(1);
d1printk("\n");
return num;
err:
if (1 == i2c_debug) {
status = i2c_get_status(dev);
printk(" ERROR: %s\n",str_i2c_status[status]);
}
return rc;
}
/* ----------------------------------------------------------- */
static u32 functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm saa7134_algo = {
.master_xfer = saa7134_i2c_xfer,
.functionality = functionality,
};
static struct i2c_adapter saa7134_adap_template = {
.owner = THIS_MODULE,
.name = "saa7134",
.id = I2C_HW_SAA7134,
.algo = &saa7134_algo,
};
static struct i2c_client saa7134_client_template = {
.name = "saa7134 internal",
};
/* ----------------------------------------------------------- */
static int
saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
{
unsigned char buf;
int i,err;
dev->i2c_client.addr = 0xa0 >> 1;
buf = 0;
if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
dev->name,err);
return -1;
}
if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n",
dev->name,err);
return -1;
}
for (i = 0; i < len; i++) {
if (0 == (i % 16))
printk(KERN_INFO "%s: i2c eeprom %02x:",dev->name,i);
printk(" %02x",eedata[i]);
if (15 == (i % 16))
printk("\n");
}
return 0;
}
static char *i2c_devs[128] = {
[ 0x20 ] = "mpeg encoder (saa6752hs)",
[ 0xa0 >> 1 ] = "eeprom",
[ 0xc0 >> 1 ] = "tuner (analog)",
[ 0x86 >> 1 ] = "tda9887",
[ 0x5a >> 1 ] = "remote control",
};
static void do_i2c_scan(char *name, struct i2c_client *c)
{
unsigned char buf;
int i,rc;
for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
c->addr = i;
rc = i2c_master_recv(c,&buf,0);
if (rc < 0)
continue;
printk("%s: i2c scan: found device @ 0x%x [%s]\n",
name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
}
}
int saa7134_i2c_register(struct saa7134_dev *dev)
{
dev->i2c_adap = saa7134_adap_template;
dev->i2c_adap.dev.parent = &dev->pci->dev;
strcpy(dev->i2c_adap.name,dev->name);
dev->i2c_adap.algo_data = dev;
i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
i2c_add_adapter(&dev->i2c_adap);
dev->i2c_client = saa7134_client_template;
dev->i2c_client.adapter = &dev->i2c_adap;
saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
if (i2c_scan)
do_i2c_scan(dev->name,&dev->i2c_client);
/* Instantiate the IR receiver device, if present */
saa7134_probe_i2c_ir(dev);
return 0;
}
int saa7134_i2c_unregister(struct saa7134_dev *dev)
{
i2c_del_adapter(&dev->i2c_adap);
return 0;
}
/* ----------------------------------------------------------- */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@@ -0,0 +1,957 @@
/*
*
* handle saa7134 IR remotes via linux kernel input layer.
*
* 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
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include "saa7134-reg.h"
#include "saa7134.h"
static unsigned int disable_ir;
module_param(disable_ir, int, 0444);
MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
static unsigned int ir_debug;
module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
static int pinnacle_remote;
module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */
MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
static int ir_rc5_remote_gap = 885;
module_param(ir_rc5_remote_gap, int, 0644);
static int ir_rc5_key_timeout = 115;
module_param(ir_rc5_key_timeout, int, 0644);
static int repeat_delay = 500;
module_param(repeat_delay, int, 0644);
MODULE_PARM_DESC(repeat_delay, "delay before key repeat started");
static int repeat_period = 33;
module_param(repeat_period, int, 0644);
MODULE_PARM_DESC(repeat_period, "repeat period between "
"keypresses when key is down");
static unsigned int disable_other_ir;
module_param(disable_other_ir, int, 0644);
MODULE_PARM_DESC(disable_other_ir, "disable full codes of "
"alternative remotes from other manufacturers");
#define dprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
#define i2cdprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg)
/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
static int saa7134_rc5_irq(struct saa7134_dev *dev);
static int saa7134_nec_irq(struct saa7134_dev *dev);
static void nec_task(unsigned long data);
static void saa7134_nec_timer(unsigned long data);
/* -------------------- GPIO generic keycode builder -------------------- */
static int build_key(struct saa7134_dev *dev)
{
struct card_ir *ir = dev->remote;
u32 gpio, data;
/* here comes the additional handshake steps for some cards */
switch (dev->board) {
case SAA7134_BOARD_GOTVIEW_7135:
saa_setb(SAA7134_GPIO_GPSTATUS1, 0x80);
saa_clearb(SAA7134_GPIO_GPSTATUS1, 0x80);
break;
}
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
if (ir->polling) {
if (ir->last_gpio == gpio)
return 0;
ir->last_gpio = gpio;
}
data = ir_extract_bits(gpio, ir->mask_keycode);
dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
gpio, ir->mask_keycode, data);
switch (dev->board) {
case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
if (data == ir->mask_keycode)
ir_input_nokey(ir->dev, &ir->ir);
else
ir_input_keydown(ir->dev, &ir->ir, data, data);
return 0;
}
if (ir->polling) {
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
ir_input_keydown(ir->dev, &ir->ir, data, data);
} else {
ir_input_nokey(ir->dev, &ir->ir);
}
}
else { /* IRQ driven mode - handle key press and release in one go */
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
ir_input_keydown(ir->dev, &ir->ir, data, data);
ir_input_nokey(ir->dev, &ir->ir);
}
}
return 0;
}
/* --------------------- Chip specific I2C key builders ----------------- */
static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
u32 *ir_raw)
{
unsigned char b;
int gpio;
/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
struct saa7134_dev *dev = ir->c->adapter->algo_data;
if (dev == NULL) {
dprintk("get_key_msi_tvanywhere_plus: "
"gir->c->adapter->algo_data is NULL!\n");
return -EIO;
}
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
/* GPIO&0x40 is pulsed low when a button is pressed. Don't do
I2C receive if gpio&0x40 is not low. */
if (gpio & 0x40)
return 0; /* No button press */
/* GPIO says there is a button press. Get it. */
if (1 != i2c_master_recv(ir->c, &b, 1)) {
i2cdprintk("read error\n");
return -EIO;
}
/* No button press */
if (b == 0xff)
return 0;
/* Button pressed */
dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
*ir_key = b;
*ir_raw = b;
return 1;
}
static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char b;
/* poll IR chip */
if (1 != i2c_master_recv(ir->c, &b, 1)) {
i2cdprintk("read error\n");
return -EIO;
}
/* no button press */
if (b==0)
return 0;
/* repeating */
if (b & 0x80)
return 1;
*ir_key = b;
*ir_raw = b;
return 1;
}
static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char buf[5], cod4, code3, code4;
/* poll IR chip */
if (5 != i2c_master_recv(ir->c, buf, 5))
return -EIO;
cod4 = buf[4];
code4 = (cod4 >> 2);
code3 = buf[3];
if (code3 == 0)
/* no key pressed */
return 0;
/* return key */
*ir_key = code4;
*ir_raw = code4;
return 1;
}
static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char data[12];
u32 gpio;
struct saa7134_dev *dev = ir->c->adapter->algo_data;
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
if (0x400000 & ~gpio)
return 0; /* No button press */
ir->c->addr = 0x5a >> 1;
if (12 != i2c_master_recv(ir->c, data, 12)) {
i2cdprintk("read error\n");
return -EIO;
}
/* IR of this card normally decode signals NEC-standard from
* - Sven IHOO MT 5.1R remote. xxyye718
* - Sven DVD HD-10xx remote. xxyyf708
* - BBK ...
* - mayby others
* So, skip not our, if disable full codes mode.
*/
if (data[10] != 0x6b && data[11] != 0x86 && disable_other_ir)
return 0;
/* Wrong data decode fix */
if (data[9] != (unsigned char)(~data[8]))
return 0;
*ir_key = data[9];
*ir_raw = data[9];
return 1;
}
/* Common (grey or coloured) pinnacle PCTV remote handling
*
*/
static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
int parity_offset, int marker, int code_modulo)
{
unsigned char b[4];
unsigned int start = 0,parity = 0,code = 0;
/* poll IR chip */
if (4 != i2c_master_recv(ir->c, b, 4)) {
i2cdprintk("read error\n");
return -EIO;
}
for (start = 0; start < ARRAY_SIZE(b); start++) {
if (b[start] == marker) {
code=b[(start+parity_offset + 1) % 4];
parity=b[(start+parity_offset) % 4];
}
}
/* Empty Request */
if (parity == 0)
return 0;
/* Repeating... */
if (ir->old == parity)
return 0;
ir->old = parity;
/* drop special codes when a key is held down a long time for the grey controller
In this case, the second bit of the code is asserted */
if (marker == 0xfe && (code & 0x40))
return 0;
code %= code_modulo;
*ir_raw = code;
*ir_key = code;
i2cdprintk("Pinnacle PCTV key %02x\n", code);
return 1;
}
/* The grey pinnacle PCTV remote
*
* There are one issue with this remote:
* - I2c packet does not change when the same key is pressed quickly. The workaround
* is to hold down each key for about half a second, so that another code is generated
* in the i2c packet, and the function can distinguish key presses.
*
* Sylvain Pasche <sylvain.pasche@gmail.com>
*/
static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
}
/* The new pinnacle PCTV remote (with the colored buttons)
*
* Ricardo Cerqueira <v4l@cerqueira.org>
*/
static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
*
* this is the only value that results in 42 unique
* codes < 128
*/
return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
}
void saa7134_input_irq(struct saa7134_dev *dev)
{
struct card_ir *ir = dev->remote;
if (ir->nec_gpio) {
saa7134_nec_irq(dev);
} else if (!ir->polling && !ir->rc5_gpio) {
build_key(dev);
} else if (ir->rc5_gpio) {
saa7134_rc5_irq(dev);
}
}
static void saa7134_input_timer(unsigned long data)
{
struct saa7134_dev *dev = (struct saa7134_dev *)data;
struct card_ir *ir = dev->remote;
build_key(dev);
mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
}
void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
{
if (ir->polling) {
setup_timer(&ir->timer, saa7134_input_timer,
(unsigned long)dev);
ir->timer.expires = jiffies + HZ;
add_timer(&ir->timer);
} else if (ir->rc5_gpio) {
/* set timer_end for code completion */
init_timer(&ir->timer_end);
ir->timer_end.function = ir_rc5_timer_end;
ir->timer_end.data = (unsigned long)ir;
init_timer(&ir->timer_keyup);
ir->timer_keyup.function = ir_rc5_timer_keyup;
ir->timer_keyup.data = (unsigned long)ir;
ir->shift_by = 2;
ir->start = 0x2;
ir->addr = 0x17;
ir->rc5_key_timeout = ir_rc5_key_timeout;
ir->rc5_remote_gap = ir_rc5_remote_gap;
} else if (ir->nec_gpio) {
setup_timer(&ir->timer_keyup, saa7134_nec_timer,
(unsigned long)dev);
tasklet_init(&ir->tlet, nec_task, (unsigned long)dev);
}
}
void saa7134_ir_stop(struct saa7134_dev *dev)
{
if (dev->remote->polling)
del_timer_sync(&dev->remote->timer);
}
int saa7134_input_init1(struct saa7134_dev *dev)
{
struct card_ir *ir;
struct input_dev *input_dev;
struct ir_scancode_table *ir_codes = NULL;
u32 mask_keycode = 0;
u32 mask_keydown = 0;
u32 mask_keyup = 0;
int polling = 0;
int rc5_gpio = 0;
int nec_gpio = 0;
int ir_type = IR_TYPE_OTHER;
int err;
if (dev->has_remote != SAA7134_REMOTE_GPIO)
return -ENODEV;
if (disable_ir)
return -ENODEV;
/* detect & configure */
switch (dev->board) {
case SAA7134_BOARD_FLYVIDEO2000:
case SAA7134_BOARD_FLYVIDEO3000:
case SAA7134_BOARD_FLYTVPLATINUM_FM:
case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
ir_codes = &ir_codes_flyvideo_table;
mask_keycode = 0xEC00000;
mask_keydown = 0x0040000;
break;
case SAA7134_BOARD_CINERGY400:
case SAA7134_BOARD_CINERGY600:
case SAA7134_BOARD_CINERGY600_MK3:
ir_codes = &ir_codes_cinergy_table;
mask_keycode = 0x00003f;
mask_keyup = 0x040000;
break;
case SAA7134_BOARD_ECS_TVP3XP:
case SAA7134_BOARD_ECS_TVP3XP_4CB5:
ir_codes = &ir_codes_eztv_table;
mask_keycode = 0x00017c;
mask_keyup = 0x000002;
polling = 50; // ms
break;
case SAA7134_BOARD_KWORLD_XPERT:
case SAA7134_BOARD_AVACSSMARTTV:
ir_codes = &ir_codes_pixelview_table;
mask_keycode = 0x00001F;
mask_keyup = 0x000020;
polling = 50; // ms
break;
case SAA7134_BOARD_MD2819:
case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
case SAA7134_BOARD_AVERMEDIA_305:
case SAA7134_BOARD_AVERMEDIA_307:
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
case SAA7134_BOARD_AVERMEDIA_M102:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
ir_codes = &ir_codes_avermedia_table;
mask_keycode = 0x0007C8;
mask_keydown = 0x000010;
polling = 50; // ms
/* Set GPIO pin2 to high to enable the IR controller */
saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
break;
case SAA7134_BOARD_AVERMEDIA_M135A:
ir_codes = &ir_codes_avermedia_m135a_table;
mask_keydown = 0x0040000;
mask_keycode = 0x00013f;
nec_gpio = 1;
break;
case SAA7134_BOARD_AVERMEDIA_777:
case SAA7134_BOARD_AVERMEDIA_A16AR:
ir_codes = &ir_codes_avermedia_table;
mask_keycode = 0x02F200;
mask_keydown = 0x000400;
polling = 50; // ms
/* Without this we won't receive key up events */
saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
break;
case SAA7134_BOARD_AVERMEDIA_A16D:
ir_codes = &ir_codes_avermedia_a16d_table;
mask_keycode = 0x02F200;
mask_keydown = 0x000400;
polling = 50; /* ms */
/* Without this we won't receive key up events */
saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
break;
case SAA7134_BOARD_KWORLD_TERMINATOR:
ir_codes = &ir_codes_pixelview_table;
mask_keycode = 0x00001f;
mask_keyup = 0x000060;
polling = 50; // ms
break;
case SAA7134_BOARD_MANLI_MTV001:
case SAA7134_BOARD_MANLI_MTV002:
ir_codes = &ir_codes_manli_table;
mask_keycode = 0x001f00;
mask_keyup = 0x004000;
polling = 50; /* ms */
break;
case SAA7134_BOARD_BEHOLD_409FM:
case SAA7134_BOARD_BEHOLD_401:
case SAA7134_BOARD_BEHOLD_403:
case SAA7134_BOARD_BEHOLD_403FM:
case SAA7134_BOARD_BEHOLD_405:
case SAA7134_BOARD_BEHOLD_405FM:
case SAA7134_BOARD_BEHOLD_407:
case SAA7134_BOARD_BEHOLD_407FM:
case SAA7134_BOARD_BEHOLD_409:
case SAA7134_BOARD_BEHOLD_505FM:
case SAA7134_BOARD_BEHOLD_505RDS:
case SAA7134_BOARD_BEHOLD_507_9FM:
case SAA7134_BOARD_BEHOLD_507RDS_MK3:
case SAA7134_BOARD_BEHOLD_507RDS_MK5:
ir_codes = &ir_codes_manli_table;
mask_keycode = 0x003f00;
mask_keyup = 0x004000;
polling = 50; /* ms */
break;
case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
ir_codes = &ir_codes_behold_columbus_table;
mask_keycode = 0x003f00;
mask_keyup = 0x004000;
polling = 50; // ms
break;
case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
ir_codes = &ir_codes_pctv_sedna_table;
mask_keycode = 0x001f00;
mask_keyup = 0x004000;
polling = 50; // ms
break;
case SAA7134_BOARD_GOTVIEW_7135:
ir_codes = &ir_codes_gotview7135_table;
mask_keycode = 0x0003CC;
mask_keydown = 0x000010;
polling = 5; /* ms */
saa_setb(SAA7134_GPIO_GPMODE1, 0x80);
break;
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
ir_codes = &ir_codes_videomate_tv_pvr_table;
mask_keycode = 0x00003F;
mask_keyup = 0x400000;
polling = 50; // ms
break;
case SAA7134_BOARD_PROTEUS_2309:
ir_codes = &ir_codes_proteus_2309_table;
mask_keycode = 0x00007F;
mask_keyup = 0x000080;
polling = 50; // ms
break;
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
ir_codes = &ir_codes_videomate_tv_pvr_table;
mask_keycode = 0x003F00;
mask_keyup = 0x040000;
break;
case SAA7134_BOARD_FLYDVBS_LR300:
case SAA7134_BOARD_FLYDVBT_LR301:
case SAA7134_BOARD_FLYDVBTDUO:
ir_codes = &ir_codes_flydvb_table;
mask_keycode = 0x0001F00;
mask_keydown = 0x0040000;
break;
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
ir_codes = &ir_codes_asus_pc39_table;
mask_keydown = 0x0040000;
rc5_gpio = 1;
break;
case SAA7134_BOARD_ENCORE_ENLTV:
case SAA7134_BOARD_ENCORE_ENLTV_FM:
ir_codes = &ir_codes_encore_enltv_table;
mask_keycode = 0x00007f;
mask_keyup = 0x040000;
polling = 50; // ms
break;
case SAA7134_BOARD_ENCORE_ENLTV_FM53:
ir_codes = &ir_codes_encore_enltv_fm53_table;
mask_keydown = 0x0040000;
mask_keycode = 0x00007f;
nec_gpio = 1;
break;
case SAA7134_BOARD_10MOONSTVMASTER3:
ir_codes = &ir_codes_encore_enltv_table;
mask_keycode = 0x5f80000;
mask_keyup = 0x8000000;
polling = 50; //ms
break;
case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
ir_codes = &ir_codes_genius_tvgo_a11mce_table;
mask_keycode = 0xff;
mask_keydown = 0xf00000;
polling = 50; /* ms */
break;
case SAA7134_BOARD_REAL_ANGEL_220:
ir_codes = &ir_codes_real_audio_220_32_keys_table;
mask_keycode = 0x3f00;
mask_keyup = 0x4000;
polling = 50; /* ms */
break;
case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
ir_codes = &ir_codes_kworld_plus_tv_analog_table;
mask_keycode = 0x7f;
polling = 40; /* ms */
break;
case SAA7134_BOARD_VIDEOMATE_S350:
ir_codes = &ir_codes_videomate_s350_table;
mask_keycode = 0x003f00;
mask_keydown = 0x040000;
break;
}
if (NULL == ir_codes) {
printk("%s: Oops: IR config error [card=%d]\n",
dev->name, dev->board);
return -ENODEV;
}
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ir || !input_dev) {
err = -ENOMEM;
goto err_out_free;
}
ir->dev = input_dev;
/* init hardware-specific stuff */
ir->mask_keycode = mask_keycode;
ir->mask_keydown = mask_keydown;
ir->mask_keyup = mask_keyup;
ir->polling = polling;
ir->rc5_gpio = rc5_gpio;
ir->nec_gpio = nec_gpio;
/* init input device */
snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
saa7134_boards[dev->board].name);
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(dev->pci));
ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
input_dev->name = ir->name;
input_dev->phys = ir->phys;
input_dev->id.bustype = BUS_PCI;
input_dev->id.version = 1;
if (dev->pci->subsystem_vendor) {
input_dev->id.vendor = dev->pci->subsystem_vendor;
input_dev->id.product = dev->pci->subsystem_device;
} else {
input_dev->id.vendor = dev->pci->vendor;
input_dev->id.product = dev->pci->device;
}
input_dev->dev.parent = &dev->pci->dev;
dev->remote = ir;
saa7134_ir_start(dev, ir);
err = input_register_device(ir->dev);
if (err)
goto err_out_stop;
/* the remote isn't as bouncy as a keyboard */
ir->dev->rep[REP_DELAY] = repeat_delay;
ir->dev->rep[REP_PERIOD] = repeat_period;
return 0;
err_out_stop:
saa7134_ir_stop(dev);
dev->remote = NULL;
err_out_free:
input_free_device(input_dev);
kfree(ir);
return err;
}
void saa7134_input_fini(struct saa7134_dev *dev)
{
if (NULL == dev->remote)
return;
saa7134_ir_stop(dev);
input_unregister_device(dev->remote->dev);
kfree(dev->remote);
dev->remote = NULL;
}
void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
{
const unsigned short addr_list[] = {
0x7a, 0x47, 0x71, 0x2d,
I2C_CLIENT_END
};
struct i2c_msg msg_msi = {
.addr = 0x50,
.flags = I2C_M_RD,
.len = 0,
.buf = NULL,
};
int rc;
if (disable_ir) {
dprintk("IR has been disabled, not probing for i2c remote\n");
return;
}
memset(&dev->info, 0, sizeof(dev->info));
memset(&dev->init_data, 0, sizeof(dev->init_data));
strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE);
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_PCTV_110i:
case SAA7134_BOARD_PINNACLE_PCTV_310i:
dev->init_data.name = "Pinnacle PCTV";
if (pinnacle_remote == 0) {
dev->init_data.get_key = get_key_pinnacle_color;
dev->init_data.ir_codes = &ir_codes_pinnacle_color_table;
dev->info.addr = 0x47;
} else {
dev->init_data.get_key = get_key_pinnacle_grey;
dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table;
dev->info.addr = 0x47;
}
break;
case SAA7134_BOARD_UPMOST_PURPLE_TV:
dev->init_data.name = "Purple TV";
dev->init_data.get_key = get_key_purpletv;
dev->init_data.ir_codes = &ir_codes_purpletv_table;
break;
case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
dev->init_data.name = "MSI TV@nywhere Plus";
dev->init_data.get_key = get_key_msi_tvanywhere_plus;
dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table;
dev->info.addr = 0x30;
/* MSI TV@nywhere Plus controller doesn't seem to
respond to probes unless we read something from
an existing device. Weird...
REVISIT: might no longer be needed */
rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n",
msg_msi.addr, dev->i2c_adap.name,
(1 == rc) ? "yes" : "no");
break;
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
dev->init_data.name = "HVR 1110";
dev->init_data.get_key = get_key_hvr1110;
dev->init_data.ir_codes = &ir_codes_hauppauge_new_table;
break;
case SAA7134_BOARD_BEHOLD_607FM_MK3:
case SAA7134_BOARD_BEHOLD_607FM_MK5:
case SAA7134_BOARD_BEHOLD_609FM_MK3:
case SAA7134_BOARD_BEHOLD_609FM_MK5:
case SAA7134_BOARD_BEHOLD_607RDS_MK3:
case SAA7134_BOARD_BEHOLD_607RDS_MK5:
case SAA7134_BOARD_BEHOLD_609RDS_MK3:
case SAA7134_BOARD_BEHOLD_609RDS_MK5:
case SAA7134_BOARD_BEHOLD_M6:
case SAA7134_BOARD_BEHOLD_M63:
case SAA7134_BOARD_BEHOLD_M6_EXTRA:
case SAA7134_BOARD_BEHOLD_H6:
case SAA7134_BOARD_BEHOLD_X7:
dev->init_data.name = "BeholdTV";
dev->init_data.get_key = get_key_beholdm6xx;
dev->init_data.ir_codes = &ir_codes_behold_table;
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
dev->info.addr = 0x40;
break;
}
if (dev->init_data.name)
dev->info.platform_data = &dev->init_data;
/* No need to probe if address is known */
if (dev->info.addr) {
i2c_new_device(&dev->i2c_adap, &dev->info);
return;
}
/* Address not known, fallback to probing */
i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list);
}
static int saa7134_rc5_irq(struct saa7134_dev *dev)
{
struct card_ir *ir = dev->remote;
struct timeval tv;
u32 gap;
unsigned long current_jiffies, timeout;
/* get time of bit */
current_jiffies = jiffies;
do_gettimeofday(&tv);
/* avoid overflow with gap >1s */
if (tv.tv_sec - ir->base_time.tv_sec > 1) {
gap = 200000;
} else {
gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
tv.tv_usec - ir->base_time.tv_usec;
}
/* active code => add bit */
if (ir->active) {
/* only if in the code (otherwise spurious IRQ or timer
late) */
if (ir->last_bit < 28) {
ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
ir_rc5_remote_gap;
ir->code |= 1 << ir->last_bit;
}
/* starting new code */
} else {
ir->active = 1;
ir->code = 0;
ir->base_time = tv;
ir->last_bit = 0;
timeout = current_jiffies + (500 + 30 * HZ) / 1000;
mod_timer(&ir->timer_end, timeout);
}
return 1;
}
/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms
The first pulse (start) has 9 + 4.5 ms
*/
static void saa7134_nec_timer(unsigned long data)
{
struct saa7134_dev *dev = (struct saa7134_dev *) data;
struct card_ir *ir = dev->remote;
dprintk("Cancel key repeat\n");
ir_input_nokey(ir->dev, &ir->ir);
}
static void nec_task(unsigned long data)
{
struct saa7134_dev *dev = (struct saa7134_dev *) data;
struct card_ir *ir;
struct timeval tv;
int count, pulse, oldpulse, gap;
u32 ircode = 0, not_code = 0;
int ngap = 0;
if (!data) {
printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n");
/* GPIO will be kept disabled */
return;
}
ir = dev->remote;
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
pulse = oldpulse;
do_gettimeofday(&tv);
ir->base_time = tv;
/* Decode NEC pulsecode. This code can take up to 76.5 ms to run.
Unfortunately, using IRQ to decode pulse didn't work, since it uses
a pulse train of 38KHz. This means one pulse on each 52 us
*/
do {
/* Wait until the end of pulse/space or 5 ms */
for (count = 0; count < 500; count++) {
udelay(10);
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)
& ir->mask_keydown;
if (pulse != oldpulse)
break;
}
do_gettimeofday(&tv);
gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
tv.tv_usec - ir->base_time.tv_usec;
if (!pulse) {
/* Bit 0 has 560 us, while bit 1 has 1120 us.
Do something only if bit == 1
*/
if (ngap && (gap > 560 + 280)) {
unsigned int shift = ngap - 1;
/* Address first, then command */
if (shift < 8) {
shift += 8;
ircode |= 1 << shift;
} else if (shift < 16) {
not_code |= 1 << shift;
} else if (shift < 24) {
shift -= 16;
ircode |= 1 << shift;
} else {
shift -= 24;
not_code |= 1 << shift;
}
}
ngap++;
}
ir->base_time = tv;
/* TIMEOUT - Long pulse */
if (gap >= 5000)
break;
oldpulse = pulse;
} while (ngap < 32);
if (ngap == 32) {
/* FIXME: should check if not_code == ~ircode */
ir->code = ir_extract_bits(ircode, ir->mask_keycode);
dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n",
ir->code, ircode, not_code);
ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code);
} else
dprintk("Repeat last key\n");
/* Keep repeating the last key */
mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150));
saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
}
static int saa7134_nec_irq(struct saa7134_dev *dev)
{
struct card_ir *ir = dev->remote;
saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
tasklet_schedule(&ir->tlet);
return 1;
}

View File

@@ -0,0 +1,378 @@
/*
*
* philips saa7134 registers
*/
/* ------------------------------------------------------------------ */
/*
* PCI ID's
*/
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7130
# define PCI_DEVICE_ID_PHILIPS_SAA7130 0x7130
#endif
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7133
# define PCI_DEVICE_ID_PHILIPS_SAA7133 0x7133
#endif
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7134
# define PCI_DEVICE_ID_PHILIPS_SAA7134 0x7134
#endif
#ifndef PCI_DEVICE_ID_PHILIPS_SAA7135
# define PCI_DEVICE_ID_PHILIPS_SAA7135 0x7135
#endif
/* ------------------------------------------------------------------ */
/*
* registers -- 32 bit
*/
/* DMA channels, n = 0 ... 6 */
#define SAA7134_RS_BA1(n) ((0x200 >> 2) + 4*n)
#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n)
#define SAA7134_RS_PITCH(n) ((0x208 >> 2) + 4*n)
#define SAA7134_RS_CONTROL(n) ((0x20c >> 2) + 4*n)
#define SAA7134_RS_CONTROL_WSWAP (0x01 << 25)
#define SAA7134_RS_CONTROL_BSWAP (0x01 << 24)
#define SAA7134_RS_CONTROL_BURST_2 (0x01 << 21)
#define SAA7134_RS_CONTROL_BURST_4 (0x02 << 21)
#define SAA7134_RS_CONTROL_BURST_8 (0x03 << 21)
#define SAA7134_RS_CONTROL_BURST_16 (0x04 << 21)
#define SAA7134_RS_CONTROL_BURST_32 (0x05 << 21)
#define SAA7134_RS_CONTROL_BURST_64 (0x06 << 21)
#define SAA7134_RS_CONTROL_BURST_MAX (0x07 << 21)
#define SAA7134_RS_CONTROL_ME (0x01 << 20)
#define SAA7134_FIFO_SIZE (0x2a0 >> 2)
#define SAA7134_THRESHOULD (0x2a4 >> 2)
#define SAA7133_NUM_SAMPLES (0x588 >> 2)
#define SAA7133_AUDIO_CHANNEL (0x58c >> 2)
#define SAA7133_AUDIO_FORMAT (0x58f >> 2)
#define SAA7133_DIGITAL_OUTPUT_SEL1 (0x46c >> 2)
#define SAA7133_DIGITAL_OUTPUT_SEL2 (0x470 >> 2)
#define SAA7133_DIGITAL_INPUT_XBAR1 (0x464 >> 2)
#define SAA7133_ANALOG_IO_SELECT (0x594 >> 2)
/* main control */
#define SAA7134_MAIN_CTRL (0x2a8 >> 2)
#define SAA7134_MAIN_CTRL_VPLLE (1 << 15)
#define SAA7134_MAIN_CTRL_APLLE (1 << 14)
#define SAA7134_MAIN_CTRL_EXOSC (1 << 13)
#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12)
#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11)
#define SAA7134_MAIN_CTRL_ESFE (1 << 10)
#define SAA7134_MAIN_CTRL_EBADC (1 << 9)
#define SAA7134_MAIN_CTRL_EBDAC (1 << 8)
#define SAA7134_MAIN_CTRL_TE6 (1 << 6)
#define SAA7134_MAIN_CTRL_TE5 (1 << 5)
#define SAA7134_MAIN_CTRL_TE4 (1 << 4)
#define SAA7134_MAIN_CTRL_TE3 (1 << 3)
#define SAA7134_MAIN_CTRL_TE2 (1 << 2)
#define SAA7134_MAIN_CTRL_TE1 (1 << 1)
#define SAA7134_MAIN_CTRL_TE0 (1 << 0)
/* DMA status */
#define SAA7134_DMA_STATUS (0x2ac >> 2)
/* audio / video status */
#define SAA7134_AV_STATUS (0x2c0 >> 2)
#define SAA7134_AV_STATUS_STEREO (1 << 17)
#define SAA7134_AV_STATUS_DUAL (1 << 16)
#define SAA7134_AV_STATUS_PILOT (1 << 15)
#define SAA7134_AV_STATUS_SMB (1 << 14)
#define SAA7134_AV_STATUS_DMB (1 << 13)
#define SAA7134_AV_STATUS_VDSP (1 << 12)
#define SAA7134_AV_STATUS_IIC_STATUS (3 << 10)
#define SAA7134_AV_STATUS_MVM (7 << 7)
#define SAA7134_AV_STATUS_FIDT (1 << 6)
#define SAA7134_AV_STATUS_INTL (1 << 5)
#define SAA7134_AV_STATUS_RDCAP (1 << 4)
#define SAA7134_AV_STATUS_PWR_ON (1 << 3)
#define SAA7134_AV_STATUS_LOAD_ERR (1 << 2)
#define SAA7134_AV_STATUS_TRIG_ERR (1 << 1)
#define SAA7134_AV_STATUS_CONF_ERR (1 << 0)
/* interrupt */
#define SAA7134_IRQ1 (0x2c4 >> 2)
#define SAA7134_IRQ1_INTE_RA3_1 (1 << 25)
#define SAA7134_IRQ1_INTE_RA3_0 (1 << 24)
#define SAA7134_IRQ1_INTE_RA2_3 (1 << 19)
#define SAA7134_IRQ1_INTE_RA2_2 (1 << 18)
#define SAA7134_IRQ1_INTE_RA2_1 (1 << 17)
#define SAA7134_IRQ1_INTE_RA2_0 (1 << 16)
#define SAA7134_IRQ1_INTE_RA1_3 (1 << 11)
#define SAA7134_IRQ1_INTE_RA1_2 (1 << 10)
#define SAA7134_IRQ1_INTE_RA1_1 (1 << 9)
#define SAA7134_IRQ1_INTE_RA1_0 (1 << 8)
#define SAA7134_IRQ1_INTE_RA0_7 (1 << 7)
#define SAA7134_IRQ1_INTE_RA0_6 (1 << 6)
#define SAA7134_IRQ1_INTE_RA0_5 (1 << 5)
#define SAA7134_IRQ1_INTE_RA0_4 (1 << 4)
#define SAA7134_IRQ1_INTE_RA0_3 (1 << 3)
#define SAA7134_IRQ1_INTE_RA0_2 (1 << 2)
#define SAA7134_IRQ1_INTE_RA0_1 (1 << 1)
#define SAA7134_IRQ1_INTE_RA0_0 (1 << 0)
#define SAA7134_IRQ2 (0x2c8 >> 2)
#define SAA7134_IRQ2_INTE_GPIO23A (1 << 17)
#define SAA7134_IRQ2_INTE_GPIO23 (1 << 16)
#define SAA7134_IRQ2_INTE_GPIO22A (1 << 15)
#define SAA7134_IRQ2_INTE_GPIO22 (1 << 14)
#define SAA7134_IRQ2_INTE_GPIO18A (1 << 13)
#define SAA7134_IRQ2_INTE_GPIO18 (1 << 12)
#define SAA7134_IRQ2_INTE_GPIO16 (1 << 11) /* not certain */
#define SAA7134_IRQ2_INTE_SC2 (1 << 10)
#define SAA7134_IRQ2_INTE_SC1 (1 << 9)
#define SAA7134_IRQ2_INTE_SC0 (1 << 8)
#define SAA7134_IRQ2_INTE_DEC5 (1 << 7)
#define SAA7134_IRQ2_INTE_DEC4 (1 << 6)
#define SAA7134_IRQ2_INTE_DEC3 (1 << 5)
#define SAA7134_IRQ2_INTE_DEC2 (1 << 4)
#define SAA7134_IRQ2_INTE_DEC1 (1 << 3)
#define SAA7134_IRQ2_INTE_DEC0 (1 << 2)
#define SAA7134_IRQ2_INTE_PE (1 << 1)
#define SAA7134_IRQ2_INTE_AR (1 << 0)
#define SAA7134_IRQ_REPORT (0x2cc >> 2)
#define SAA7134_IRQ_REPORT_GPIO23 (1 << 17)
#define SAA7134_IRQ_REPORT_GPIO22 (1 << 16)
#define SAA7134_IRQ_REPORT_GPIO18 (1 << 15)
#define SAA7134_IRQ_REPORT_GPIO16 (1 << 14) /* not certain */
#define SAA7134_IRQ_REPORT_LOAD_ERR (1 << 13)
#define SAA7134_IRQ_REPORT_CONF_ERR (1 << 12)
#define SAA7134_IRQ_REPORT_TRIG_ERR (1 << 11)
#define SAA7134_IRQ_REPORT_MMC (1 << 10)
#define SAA7134_IRQ_REPORT_FIDT (1 << 9)
#define SAA7134_IRQ_REPORT_INTL (1 << 8)
#define SAA7134_IRQ_REPORT_RDCAP (1 << 7)
#define SAA7134_IRQ_REPORT_PWR_ON (1 << 6)
#define SAA7134_IRQ_REPORT_PE (1 << 5)
#define SAA7134_IRQ_REPORT_AR (1 << 4)
#define SAA7134_IRQ_REPORT_DONE_RA3 (1 << 3)
#define SAA7134_IRQ_REPORT_DONE_RA2 (1 << 2)
#define SAA7134_IRQ_REPORT_DONE_RA1 (1 << 1)
#define SAA7134_IRQ_REPORT_DONE_RA0 (1 << 0)
#define SAA7134_IRQ_STATUS (0x2d0 >> 2)
/* ------------------------------------------------------------------ */
/*
* registers -- 8 bit
*/
/* video decoder */
#define SAA7134_INCR_DELAY 0x101
#define SAA7134_ANALOG_IN_CTRL1 0x102
#define SAA7134_ANALOG_IN_CTRL2 0x103
#define SAA7134_ANALOG_IN_CTRL3 0x104
#define SAA7134_ANALOG_IN_CTRL4 0x105
#define SAA7134_HSYNC_START 0x106
#define SAA7134_HSYNC_STOP 0x107
#define SAA7134_SYNC_CTRL 0x108
#define SAA7134_LUMA_CTRL 0x109
#define SAA7134_DEC_LUMA_BRIGHT 0x10a
#define SAA7134_DEC_LUMA_CONTRAST 0x10b
#define SAA7134_DEC_CHROMA_SATURATION 0x10c
#define SAA7134_DEC_CHROMA_HUE 0x10d
#define SAA7134_CHROMA_CTRL1 0x10e
#define SAA7134_CHROMA_GAIN 0x10f
#define SAA7134_CHROMA_CTRL2 0x110
#define SAA7134_MODE_DELAY_CTRL 0x111
#define SAA7134_ANALOG_ADC 0x114
#define SAA7134_VGATE_START 0x115
#define SAA7134_VGATE_STOP 0x116
#define SAA7134_MISC_VGATE_MSB 0x117
#define SAA7134_RAW_DATA_GAIN 0x118
#define SAA7134_RAW_DATA_OFFSET 0x119
#define SAA7134_STATUS_VIDEO1 0x11e
#define SAA7134_STATUS_VIDEO2 0x11f
/* video scaler */
#define SAA7134_SOURCE_TIMING1 0x000
#define SAA7134_SOURCE_TIMING2 0x001
#define SAA7134_REGION_ENABLE 0x004
#define SAA7134_SCALER_STATUS0 0x006
#define SAA7134_SCALER_STATUS1 0x007
#define SAA7134_START_GREEN 0x00c
#define SAA7134_START_BLUE 0x00d
#define SAA7134_START_RED 0x00e
#define SAA7134_GREEN_PATH(x) (0x010 +x)
#define SAA7134_BLUE_PATH(x) (0x020 +x)
#define SAA7134_RED_PATH(x) (0x030 +x)
#define TASK_A 0x040
#define TASK_B 0x080
#define SAA7134_TASK_CONDITIONS(t) (0x000 +t)
#define SAA7134_FIELD_HANDLING(t) (0x001 +t)
#define SAA7134_DATA_PATH(t) (0x002 +t)
#define SAA7134_VBI_H_START1(t) (0x004 +t)
#define SAA7134_VBI_H_START2(t) (0x005 +t)
#define SAA7134_VBI_H_STOP1(t) (0x006 +t)
#define SAA7134_VBI_H_STOP2(t) (0x007 +t)
#define SAA7134_VBI_V_START1(t) (0x008 +t)
#define SAA7134_VBI_V_START2(t) (0x009 +t)
#define SAA7134_VBI_V_STOP1(t) (0x00a +t)
#define SAA7134_VBI_V_STOP2(t) (0x00b +t)
#define SAA7134_VBI_H_LEN1(t) (0x00c +t)
#define SAA7134_VBI_H_LEN2(t) (0x00d +t)
#define SAA7134_VBI_V_LEN1(t) (0x00e +t)
#define SAA7134_VBI_V_LEN2(t) (0x00f +t)
#define SAA7134_VIDEO_H_START1(t) (0x014 +t)
#define SAA7134_VIDEO_H_START2(t) (0x015 +t)
#define SAA7134_VIDEO_H_STOP1(t) (0x016 +t)
#define SAA7134_VIDEO_H_STOP2(t) (0x017 +t)
#define SAA7134_VIDEO_V_START1(t) (0x018 +t)
#define SAA7134_VIDEO_V_START2(t) (0x019 +t)
#define SAA7134_VIDEO_V_STOP1(t) (0x01a +t)
#define SAA7134_VIDEO_V_STOP2(t) (0x01b +t)
#define SAA7134_VIDEO_PIXELS1(t) (0x01c +t)
#define SAA7134_VIDEO_PIXELS2(t) (0x01d +t)
#define SAA7134_VIDEO_LINES1(t) (0x01e +t)
#define SAA7134_VIDEO_LINES2(t) (0x01f +t)
#define SAA7134_H_PRESCALE(t) (0x020 +t)
#define SAA7134_ACC_LENGTH(t) (0x021 +t)
#define SAA7134_LEVEL_CTRL(t) (0x022 +t)
#define SAA7134_FIR_PREFILTER_CTRL(t) (0x023 +t)
#define SAA7134_LUMA_BRIGHT(t) (0x024 +t)
#define SAA7134_LUMA_CONTRAST(t) (0x025 +t)
#define SAA7134_CHROMA_SATURATION(t) (0x026 +t)
#define SAA7134_VBI_H_SCALE_INC1(t) (0x028 +t)
#define SAA7134_VBI_H_SCALE_INC2(t) (0x029 +t)
#define SAA7134_VBI_PHASE_OFFSET_LUMA(t) (0x02a +t)
#define SAA7134_VBI_PHASE_OFFSET_CHROMA(t) (0x02b +t)
#define SAA7134_H_SCALE_INC1(t) (0x02c +t)
#define SAA7134_H_SCALE_INC2(t) (0x02d +t)
#define SAA7134_H_PHASE_OFF_LUMA(t) (0x02e +t)
#define SAA7134_H_PHASE_OFF_CHROMA(t) (0x02f +t)
#define SAA7134_V_SCALE_RATIO1(t) (0x030 +t)
#define SAA7134_V_SCALE_RATIO2(t) (0x031 +t)
#define SAA7134_V_FILTER(t) (0x032 +t)
#define SAA7134_V_PHASE_OFFSET0(t) (0x034 +t)
#define SAA7134_V_PHASE_OFFSET1(t) (0x035 +t)
#define SAA7134_V_PHASE_OFFSET2(t) (0x036 +t)
#define SAA7134_V_PHASE_OFFSET3(t) (0x037 +t)
/* clipping & dma */
#define SAA7134_OFMT_VIDEO_A 0x300
#define SAA7134_OFMT_DATA_A 0x301
#define SAA7134_OFMT_VIDEO_B 0x302
#define SAA7134_OFMT_DATA_B 0x303
#define SAA7134_ALPHA_NOCLIP 0x304
#define SAA7134_ALPHA_CLIP 0x305
#define SAA7134_UV_PIXEL 0x308
#define SAA7134_CLIP_RED 0x309
#define SAA7134_CLIP_GREEN 0x30a
#define SAA7134_CLIP_BLUE 0x30b
/* i2c bus */
#define SAA7134_I2C_ATTR_STATUS 0x180
#define SAA7134_I2C_DATA 0x181
#define SAA7134_I2C_CLOCK_SELECT 0x182
#define SAA7134_I2C_TIMER 0x183
/* audio */
#define SAA7134_NICAM_ADD_DATA1 0x140
#define SAA7134_NICAM_ADD_DATA2 0x141
#define SAA7134_NICAM_STATUS 0x142
#define SAA7134_AUDIO_STATUS 0x143
#define SAA7134_NICAM_ERROR_COUNT 0x144
#define SAA7134_IDENT_SIF 0x145
#define SAA7134_LEVEL_READOUT1 0x146
#define SAA7134_LEVEL_READOUT2 0x147
#define SAA7134_NICAM_ERROR_LOW 0x148
#define SAA7134_NICAM_ERROR_HIGH 0x149
#define SAA7134_DCXO_IDENT_CTRL 0x14a
#define SAA7134_DEMODULATOR 0x14b
#define SAA7134_AGC_GAIN_SELECT 0x14c
#define SAA7134_CARRIER1_FREQ0 0x150
#define SAA7134_CARRIER1_FREQ1 0x151
#define SAA7134_CARRIER1_FREQ2 0x152
#define SAA7134_CARRIER2_FREQ0 0x154
#define SAA7134_CARRIER2_FREQ1 0x155
#define SAA7134_CARRIER2_FREQ2 0x156
#define SAA7134_NUM_SAMPLES0 0x158
#define SAA7134_NUM_SAMPLES1 0x159
#define SAA7134_NUM_SAMPLES2 0x15a
#define SAA7134_AUDIO_FORMAT_CTRL 0x15b
#define SAA7134_MONITOR_SELECT 0x160
#define SAA7134_FM_DEEMPHASIS 0x161
#define SAA7134_FM_DEMATRIX 0x162
#define SAA7134_CHANNEL1_LEVEL 0x163
#define SAA7134_CHANNEL2_LEVEL 0x164
#define SAA7134_NICAM_CONFIG 0x165
#define SAA7134_NICAM_LEVEL_ADJUST 0x166
#define SAA7134_STEREO_DAC_OUTPUT_SELECT 0x167
#define SAA7134_I2S_OUTPUT_FORMAT 0x168
#define SAA7134_I2S_OUTPUT_SELECT 0x169
#define SAA7134_I2S_OUTPUT_LEVEL 0x16a
#define SAA7134_DSP_OUTPUT_SELECT 0x16b
#define SAA7134_AUDIO_MUTE_CTRL 0x16c
#define SAA7134_SIF_SAMPLE_FREQ 0x16d
#define SAA7134_ANALOG_IO_SELECT 0x16e
#define SAA7134_AUDIO_CLOCK0 0x170
#define SAA7134_AUDIO_CLOCK1 0x171
#define SAA7134_AUDIO_CLOCK2 0x172
#define SAA7134_AUDIO_PLL_CTRL 0x173
#define SAA7134_AUDIO_CLOCKS_PER_FIELD0 0x174
#define SAA7134_AUDIO_CLOCKS_PER_FIELD1 0x175
#define SAA7134_AUDIO_CLOCKS_PER_FIELD2 0x176
/* video port output */
#define SAA7134_VIDEO_PORT_CTRL0 0x190
#define SAA7134_VIDEO_PORT_CTRL1 0x191
#define SAA7134_VIDEO_PORT_CTRL2 0x192
#define SAA7134_VIDEO_PORT_CTRL3 0x193
#define SAA7134_VIDEO_PORT_CTRL4 0x194
#define SAA7134_VIDEO_PORT_CTRL5 0x195
#define SAA7134_VIDEO_PORT_CTRL6 0x196
#define SAA7134_VIDEO_PORT_CTRL7 0x197
#define SAA7134_VIDEO_PORT_CTRL8 0x198
/* transport stream interface */
#define SAA7134_TS_PARALLEL 0x1a0
#define SAA7134_TS_PARALLEL_SERIAL 0x1a1
#define SAA7134_TS_SERIAL0 0x1a2
#define SAA7134_TS_SERIAL1 0x1a3
#define SAA7134_TS_DMA0 0x1a4
#define SAA7134_TS_DMA1 0x1a5
#define SAA7134_TS_DMA2 0x1a6
/* GPIO Controls */
#define SAA7134_GPIO_GPRESCAN 0x80
#define SAA7134_GPIO_27_25 0x0E
#define SAA7134_GPIO_GPMODE0 0x1B0
#define SAA7134_GPIO_GPMODE1 0x1B1
#define SAA7134_GPIO_GPMODE2 0x1B2
#define SAA7134_GPIO_GPMODE3 0x1B3
#define SAA7134_GPIO_GPSTATUS0 0x1B4
#define SAA7134_GPIO_GPSTATUS1 0x1B5
#define SAA7134_GPIO_GPSTATUS2 0x1B6
#define SAA7134_GPIO_GPSTATUS3 0x1B7
/* I2S output */
#define SAA7134_I2S_AUDIO_OUTPUT 0x1c0
/* test modes */
#define SAA7134_SPECIAL_MODE 0x1d0
#define SAA7134_PRODUCTION_TEST_MODE 0x1d1
/* audio -- saa7133 + saa7135 only */
#define SAA7135_DSP_RWSTATE 0x580
#define SAA7135_DSP_RWSTATE_ERR (1 << 3)
#define SAA7135_DSP_RWSTATE_IDA (1 << 2)
#define SAA7135_DSP_RWSTATE_RDB (1 << 1)
#define SAA7135_DSP_RWSTATE_WRR (1 << 0)
#define SAA7135_DSP_RWCLEAR 0x586
#define SAA7135_DSP_RWCLEAR_RERR 1
#define SAA7133_I2S_AUDIO_CONTROL 0x591
/* ------------------------------------------------------------------ */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@@ -0,0 +1,328 @@
/*
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include "saa7134-reg.h"
#include "saa7134.h"
/* ------------------------------------------------------------------ */
static unsigned int ts_debug;
module_param(ts_debug, int, 0644);
MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
#define dprintk(fmt, arg...) if (ts_debug) \
printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
/* ------------------------------------------------------------------ */
static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
dprintk("buffer_activate [%p]",buf);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->top_seen = 0;
if (NULL == next)
next = buf;
if (V4L2_FIELD_TOP == buf->vb.field) {
dprintk("- [top] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
} else {
dprintk("- [bottom] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
}
/* start DMA */
saa7134_set_dmabits(dev);
mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT);
if (!dev->ts_started)
saa7134_ts_start(dev);
return 0;
}
static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field)
{
struct saa7134_dev *dev = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
unsigned int lines, llength, size;
int err;
dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
llength = TS_PACKET_SIZE;
lines = dev->ts.nr_packets;
size = lines * llength;
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
if (buf->vb.size != size) {
saa7134_dma_free(q,buf);
}
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
dprintk("buffer_prepare: needs_init\n");
buf->vb.width = llength;
buf->vb.height = lines;
buf->vb.size = size;
buf->pt = &dev->ts.pt_ts;
err = videobuf_iolock(q,&buf->vb,NULL);
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
dma->sglist,
dma->sglen,
saa7134_buffer_startpage(buf));
if (err)
goto oops;
}
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
buf->vb.field = field;
return 0;
oops:
saa7134_dma_free(q,buf);
return err;
}
static int
buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
struct saa7134_dev *dev = q->priv_data;
*size = TS_PACKET_SIZE * dev->ts.nr_packets;
if (0 == *count)
*count = dev->ts.nr_bufs;
*count = saa7134_buffer_count(*size,*count);
return 0;
}
static void buffer_queue(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);
saa7134_buffer_queue(dev,&dev->ts_q,buf);
}
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
struct saa7134_dev *dev = q->priv_data;
if (dev->ts_started)
saa7134_ts_stop(dev);
saa7134_dma_free(q,buf);
}
struct videobuf_queue_ops saa7134_ts_qops = {
.buf_setup = buffer_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
.buf_release = buffer_release,
};
EXPORT_SYMBOL_GPL(saa7134_ts_qops);
/* ----------------------------------------------------------- */
/* exported stuff */
static unsigned int tsbufs = 8;
module_param(tsbufs, int, 0444);
MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32");
static unsigned int ts_nr_packets = 64;
module_param(ts_nr_packets, int, 0444);
MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
int saa7134_ts_init_hw(struct saa7134_dev *dev)
{
/* deactivate TS softreset */
saa_writeb(SAA7134_TS_SERIAL1, 0x00);
/* TSSOP high active, TSVAL high active, TSLOCK ignored */
saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
/* TSNOPIT=0, TSCOLAP=0 */
saa_writeb(SAA7134_TS_DMA2,
((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00));
return 0;
}
int saa7134_ts_init1(struct saa7134_dev *dev)
{
/* sanitycheck insmod options */
if (tsbufs < 2)
tsbufs = 2;
if (tsbufs > VIDEO_MAX_FRAME)
tsbufs = VIDEO_MAX_FRAME;
if (ts_nr_packets < 4)
ts_nr_packets = 4;
if (ts_nr_packets > 312)
ts_nr_packets = 312;
dev->ts.nr_bufs = tsbufs;
dev->ts.nr_packets = ts_nr_packets;
INIT_LIST_HEAD(&dev->ts_q.queue);
init_timer(&dev->ts_q.timeout);
dev->ts_q.timeout.function = saa7134_buffer_timeout;
dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q);
dev->ts_q.dev = dev;
dev->ts_q.need_two = 1;
dev->ts_started = 0;
saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
/* init TS hw */
saa7134_ts_init_hw(dev);
return 0;
}
/* Function for stop TS */
int saa7134_ts_stop(struct saa7134_dev *dev)
{
dprintk("TS stop\n");
BUG_ON(!dev->ts_started);
/* Stop TS stream */
switch (saa7134_boards[dev->board].ts_type) {
case SAA7134_MPEG_TS_PARALLEL:
saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
dev->ts_started = 0;
break;
case SAA7134_MPEG_TS_SERIAL:
saa_writeb(SAA7134_TS_SERIAL0, 0x40);
dev->ts_started = 0;
break;
}
return 0;
}
/* Function for start TS */
int saa7134_ts_start(struct saa7134_dev *dev)
{
dprintk("TS start\n");
BUG_ON(dev->ts_started);
/* dma: setup channel 5 (= TS) */
saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
saa_writeb(SAA7134_TS_DMA1,
((dev->ts.nr_packets - 1) >> 8) & 0xff);
/* TSNOPIT=0, TSCOLAP=0 */
saa_writeb(SAA7134_TS_DMA2,
(((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
(dev->ts.pt_ts.dma >> 12));
/* reset hardware TS buffers */
saa_writeb(SAA7134_TS_SERIAL1, 0x00);
saa_writeb(SAA7134_TS_SERIAL1, 0x03);
saa_writeb(SAA7134_TS_SERIAL1, 0x00);
saa_writeb(SAA7134_TS_SERIAL1, 0x01);
/* TS clock non-inverted */
saa_writeb(SAA7134_TS_SERIAL1, 0x00);
/* Start TS stream */
switch (saa7134_boards[dev->board].ts_type) {
case SAA7134_MPEG_TS_PARALLEL:
saa_writeb(SAA7134_TS_SERIAL0, 0x40);
saa_writeb(SAA7134_TS_PARALLEL, 0xec |
(saa7134_boards[dev->board].ts_force_val << 4));
break;
case SAA7134_MPEG_TS_SERIAL:
saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
saa_writeb(SAA7134_TS_PARALLEL, 0x6c |
(saa7134_boards[dev->board].ts_force_val << 4));
saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
saa_writeb(SAA7134_TS_SERIAL1, 0x02);
break;
}
dev->ts_started = 1;
return 0;
}
int saa7134_ts_fini(struct saa7134_dev *dev)
{
saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts);
return 0;
}
void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
{
enum v4l2_field field;
spin_lock(&dev->slock);
if (dev->ts_q.curr) {
field = dev->ts_q.curr->vb.field;
if (field == V4L2_FIELD_TOP) {
if ((status & 0x100000) != 0x000000)
goto done;
} else {
if ((status & 0x100000) != 0x100000)
goto done;
}
saa7134_buffer_finish(dev,&dev->ts_q,VIDEOBUF_DONE);
}
saa7134_buffer_next(dev,&dev->ts_q);
done:
spin_unlock(&dev->slock);
}
/* ----------------------------------------------------------- */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,256 @@
/*
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "saa7134-reg.h"
#include "saa7134.h"
/* ------------------------------------------------------------------ */
static unsigned int vbi_debug;
module_param(vbi_debug, int, 0644);
MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
static unsigned int vbibufs = 4;
module_param(vbibufs, int, 0444);
MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
#define dprintk(fmt, arg...) if (vbi_debug) \
printk(KERN_DEBUG "%s/vbi: " fmt, dev->name , ## arg)
/* ------------------------------------------------------------------ */
#define VBI_LINE_COUNT 16
#define VBI_LINE_LENGTH 2048
#define VBI_SCALE 0x200
static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf,
int task)
{
struct saa7134_tvnorm *norm = dev->tvnorm;
/* setup video scaler */
saa_writeb(SAA7134_VBI_H_START1(task), norm->h_start & 0xff);
saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8);
saa_writeb(SAA7134_VBI_H_STOP1(task), norm->h_stop & 0xff);
saa_writeb(SAA7134_VBI_H_STOP2(task), norm->h_stop >> 8);
saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 & 0xff);
saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8);
saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop_0 & 0xff);
saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop_0 >> 8);
saa_writeb(SAA7134_VBI_H_SCALE_INC1(task), VBI_SCALE & 0xff);
saa_writeb(SAA7134_VBI_H_SCALE_INC2(task), VBI_SCALE >> 8);
saa_writeb(SAA7134_VBI_PHASE_OFFSET_LUMA(task), 0x00);
saa_writeb(SAA7134_VBI_PHASE_OFFSET_CHROMA(task), 0x00);
saa_writeb(SAA7134_VBI_H_LEN1(task), buf->vb.width & 0xff);
saa_writeb(SAA7134_VBI_H_LEN2(task), buf->vb.width >> 8);
saa_writeb(SAA7134_VBI_V_LEN1(task), buf->vb.height & 0xff);
saa_writeb(SAA7134_VBI_V_LEN2(task), buf->vb.height >> 8);
saa_andorb(SAA7134_DATA_PATH(task), 0xc0, 0x00);
}
/* ------------------------------------------------------------------ */
static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
unsigned long control,base;
dprintk("buffer_activate [%p]\n",buf);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->top_seen = 0;
task_init(dev,buf,TASK_A);
task_init(dev,buf,TASK_B);
saa_writeb(SAA7134_OFMT_DATA_A, 0x06);
saa_writeb(SAA7134_OFMT_DATA_B, 0x06);
/* DMA: setup channel 2+3 (= VBI Task A+B) */
base = saa7134_buffer_base(buf);
control = SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
(buf->pt->dma >> 12);
saa_writel(SAA7134_RS_BA1(2),base);
saa_writel(SAA7134_RS_BA2(2),base + buf->vb.size/2);
saa_writel(SAA7134_RS_PITCH(2),buf->vb.width);
saa_writel(SAA7134_RS_CONTROL(2),control);
saa_writel(SAA7134_RS_BA1(3),base);
saa_writel(SAA7134_RS_BA2(3),base + buf->vb.size/2);
saa_writel(SAA7134_RS_PITCH(3),buf->vb.width);
saa_writel(SAA7134_RS_CONTROL(3),control);
/* start DMA */
saa7134_set_dmabits(dev);
mod_timer(&dev->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
static int buffer_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb,
enum v4l2_field field)
{
struct saa7134_fh *fh = q->priv_data;
struct saa7134_dev *dev = fh->dev;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
struct saa7134_tvnorm *norm = dev->tvnorm;
unsigned int lines, llength, size;
int err;
lines = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
if (lines > VBI_LINE_COUNT)
lines = VBI_LINE_COUNT;
llength = VBI_LINE_LENGTH;
size = lines * llength * 2;
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
if (buf->vb.size != size)
saa7134_dma_free(q,buf);
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
buf->vb.width = llength;
buf->vb.height = lines;
buf->vb.size = size;
buf->pt = &fh->pt_vbi;
err = videobuf_iolock(q,&buf->vb,NULL);
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
dma->sglist,
dma->sglen,
saa7134_buffer_startpage(buf));
if (err)
goto oops;
}
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
buf->vb.field = field;
return 0;
oops:
saa7134_dma_free(q,buf);
return err;
}
static int
buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
struct saa7134_fh *fh = q->priv_data;
struct saa7134_dev *dev = fh->dev;
int llength,lines;
lines = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
llength = VBI_LINE_LENGTH;
*size = lines * llength * 2;
if (0 == *count)
*count = vbibufs;
*count = saa7134_buffer_count(*size,*count);
return 0;
}
static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct saa7134_fh *fh = q->priv_data;
struct saa7134_dev *dev = fh->dev;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
saa7134_buffer_queue(dev,&dev->vbi_q,buf);
}
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
saa7134_dma_free(q,buf);
}
struct videobuf_queue_ops saa7134_vbi_qops = {
.buf_setup = buffer_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
.buf_release = buffer_release,
};
/* ------------------------------------------------------------------ */
int saa7134_vbi_init1(struct saa7134_dev *dev)
{
INIT_LIST_HEAD(&dev->vbi_q.queue);
init_timer(&dev->vbi_q.timeout);
dev->vbi_q.timeout.function = saa7134_buffer_timeout;
dev->vbi_q.timeout.data = (unsigned long)(&dev->vbi_q);
dev->vbi_q.dev = dev;
if (vbibufs < 2)
vbibufs = 2;
if (vbibufs > VIDEO_MAX_FRAME)
vbibufs = VIDEO_MAX_FRAME;
return 0;
}
int saa7134_vbi_fini(struct saa7134_dev *dev)
{
/* nothing */
return 0;
}
void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
{
spin_lock(&dev->slock);
if (dev->vbi_q.curr) {
dev->vbi_fieldcount++;
/* make sure we have seen both fields */
if ((status & 0x10) == 0x00) {
dev->vbi_q.curr->top_seen = 1;
goto done;
}
if (!dev->vbi_q.curr->top_seen)
goto done;
dev->vbi_q.curr->vb.field_count = dev->vbi_fieldcount;
saa7134_buffer_finish(dev,&dev->vbi_q,VIDEOBUF_DONE);
}
saa7134_buffer_next(dev,&dev->vbi_q);
done:
spin_unlock(&dev->slock);
}
/* ----------------------------------------------------------- */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,819 @@
/*
*
* v4l2 device driver for philips saa7134 based TV cards
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/version.h>
#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,15)
#include <linux/pci.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <linux/kdev_t.h>
#include <linux/input.h>
#include <linux/notifier.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <asm/io.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <media/tuner.h>
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
#include <media/videobuf-dma-sg.h>
#include <sound/core.h>
#include <sound/pcm.h>
#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
#include <media/videobuf-dvb.h>
#endif
#define UNSET (-1U)
/* ----------------------------------------------------------- */
/* enums */
enum saa7134_tvaudio_mode {
TVAUDIO_FM_MONO = 1,
TVAUDIO_FM_BG_STEREO = 2,
TVAUDIO_FM_SAT_STEREO = 3,
TVAUDIO_FM_K_STEREO = 4,
TVAUDIO_NICAM_AM = 5,
TVAUDIO_NICAM_FM = 6,
};
enum saa7134_audio_in {
TV = 1,
LINE1 = 2,
LINE2 = 3,
LINE2_LEFT,
};
enum saa7134_video_out {
CCIR656 = 1,
};
/* ----------------------------------------------------------- */
/* static data */
struct saa7134_tvnorm {
char *name;
v4l2_std_id id;
/* video decoder */
unsigned int sync_control;
unsigned int luma_control;
unsigned int chroma_ctrl1;
unsigned int chroma_gain;
unsigned int chroma_ctrl2;
unsigned int vgate_misc;
/* video scaler */
unsigned int h_start;
unsigned int h_stop;
unsigned int video_v_start;
unsigned int video_v_stop;
unsigned int vbi_v_start_0;
unsigned int vbi_v_stop_0;
unsigned int src_timing;
unsigned int vbi_v_start_1;
};
struct saa7134_tvaudio {
char *name;
v4l2_std_id std;
enum saa7134_tvaudio_mode mode;
int carr1;
int carr2;
};
struct saa7134_format {
char *name;
unsigned int fourcc;
unsigned int depth;
unsigned int pm;
unsigned int vshift; /* vertical downsampling (for planar yuv) */
unsigned int hshift; /* horizontal downsampling (for planar yuv) */
unsigned int bswap:1;
unsigned int wswap:1;
unsigned int yuv:1;
unsigned int planar:1;
unsigned int uvswap:1;
};
/* ----------------------------------------------------------- */
/* card configuration */
#define SAA7134_BOARD_NOAUTO UNSET
#define SAA7134_BOARD_UNKNOWN 0
#define SAA7134_BOARD_PROTEUS_PRO 1
#define SAA7134_BOARD_FLYVIDEO3000 2
#define SAA7134_BOARD_FLYVIDEO2000 3
#define SAA7134_BOARD_EMPRESS 4
#define SAA7134_BOARD_MONSTERTV 5
#define SAA7134_BOARD_MD9717 6
#define SAA7134_BOARD_TVSTATION_RDS 7
#define SAA7134_BOARD_CINERGY400 8
#define SAA7134_BOARD_MD5044 9
#define SAA7134_BOARD_KWORLD 10
#define SAA7134_BOARD_CINERGY600 11
#define SAA7134_BOARD_MD7134 12
#define SAA7134_BOARD_TYPHOON_90031 13
#define SAA7134_BOARD_ELSA 14
#define SAA7134_BOARD_ELSA_500TV 15
#define SAA7134_BOARD_ASUSTeK_TVFM7134 16
#define SAA7134_BOARD_VA1000POWER 17
#define SAA7134_BOARD_BMK_MPEX_NOTUNER 18
#define SAA7134_BOARD_VIDEOMATE_TV 19
#define SAA7134_BOARD_CRONOS_PLUS 20
#define SAA7134_BOARD_10MOONSTVMASTER 21
#define SAA7134_BOARD_MD2819 22
#define SAA7134_BOARD_BMK_MPEX_TUNER 23
#define SAA7134_BOARD_TVSTATION_DVR 24
#define SAA7134_BOARD_ASUSTEK_TVFM7133 25
#define SAA7134_BOARD_PINNACLE_PCTV_STEREO 26
#define SAA7134_BOARD_MANLI_MTV002 27
#define SAA7134_BOARD_MANLI_MTV001 28
#define SAA7134_BOARD_TG3000TV 29
#define SAA7134_BOARD_ECS_TVP3XP 30
#define SAA7134_BOARD_ECS_TVP3XP_4CB5 31
#define SAA7134_BOARD_AVACSSMARTTV 32
#define SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER 33
#define SAA7134_BOARD_NOVAC_PRIMETV7133 34
#define SAA7134_BOARD_AVERMEDIA_STUDIO_305 35
#define SAA7134_BOARD_UPMOST_PURPLE_TV 36
#define SAA7134_BOARD_ITEMS_MTV005 37
#define SAA7134_BOARD_CINERGY200 38
#define SAA7134_BOARD_FLYTVPLATINUM_MINI 39
#define SAA7134_BOARD_VIDEOMATE_TV_PVR 40
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS 41
#define SAA7134_BOARD_SABRENT_SBTTVFM 42
#define SAA7134_BOARD_ZOLID_XPERT_TV7134 43
#define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44
#define SAA7134_BOARD_AVERMEDIA_STUDIO_307 45
#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46
#define SAA7134_BOARD_CINERGY400_CARDBUS 47
#define SAA7134_BOARD_CINERGY600_MK3 48
#define SAA7134_BOARD_VIDEOMATE_GOLD_PLUS 49
#define SAA7134_BOARD_PINNACLE_300I_DVBT_PAL 50
#define SAA7134_BOARD_PROVIDEO_PV952 51
#define SAA7134_BOARD_AVERMEDIA_305 52
#define SAA7134_BOARD_ASUSTeK_TVFM7135 53
#define SAA7134_BOARD_FLYTVPLATINUM_FM 54
#define SAA7134_BOARD_FLYDVBTDUO 55
#define SAA7134_BOARD_AVERMEDIA_307 56
#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
#define SAA7134_BOARD_ADS_INSTANT_TV 58
#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60
#define SAA7134_BOARD_PHILIPS_TOUGH 61
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
#define SAA7134_BOARD_KWORLD_XPERT 63
#define SAA7134_BOARD_FLYTV_DIGIMATRIX 64
#define SAA7134_BOARD_KWORLD_TERMINATOR 65
#define SAA7134_BOARD_YUAN_TUN900 66
#define SAA7134_BOARD_BEHOLD_409FM 67
#define SAA7134_BOARD_GOTVIEW_7135 68
#define SAA7134_BOARD_PHILIPS_EUROPA 69
#define SAA7134_BOARD_VIDEOMATE_DVBT_300 70
#define SAA7134_BOARD_VIDEOMATE_DVBT_200 71
#define SAA7134_BOARD_RTD_VFG7350 72
#define SAA7134_BOARD_RTD_VFG7330 73
#define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74
#define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75
#define SAA7134_BOARD_MONSTERTV_MOBILE 76
#define SAA7134_BOARD_PINNACLE_PCTV_110i 77
#define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78
#define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79
#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80
#define SAA7134_BOARD_PHILIPS_TIGER 81
#define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82
#define SAA7134_BOARD_CINERGY250PCI 83
#define SAA7134_BOARD_FLYDVB_TRIO 84
#define SAA7134_BOARD_AVERMEDIA_777 85
#define SAA7134_BOARD_FLYDVBT_LR301 86
#define SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331 87
#define SAA7134_BOARD_TEVION_DVBT_220RF 88
#define SAA7134_BOARD_ELSA_700TV 89
#define SAA7134_BOARD_KWORLD_ATSC110 90
#define SAA7134_BOARD_AVERMEDIA_A169_B 91
#define SAA7134_BOARD_AVERMEDIA_A169_B1 92
#define SAA7134_BOARD_MD7134_BRIDGE_2 93
#define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
#define SAA7134_BOARD_FLYVIDEO3000_NTSC 95
#define SAA7134_BOARD_MEDION_MD8800_QUADRO 96
#define SAA7134_BOARD_FLYDVBS_LR300 97
#define SAA7134_BOARD_PROTEUS_2309 98
#define SAA7134_BOARD_AVERMEDIA_A16AR 99
#define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100
#define SAA7134_BOARD_PINNACLE_PCTV_310i 101
#define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102
#define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103
#define SAA7134_BOARD_HAUPPAUGE_HVR1110 104
#define SAA7134_BOARD_CINERGY_HT_PCMCIA 105
#define SAA7134_BOARD_ENCORE_ENLTV 106
#define SAA7134_BOARD_ENCORE_ENLTV_FM 107
#define SAA7134_BOARD_CINERGY_HT_PCI 108
#define SAA7134_BOARD_PHILIPS_TIGER_S 109
#define SAA7134_BOARD_AVERMEDIA_M102 110
#define SAA7134_BOARD_ASUS_P7131_4871 111
#define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112
#define SAA7134_BOARD_ECS_TVP3XP_4CB6 113
#define SAA7134_BOARD_KWORLD_DVBT_210 114
#define SAA7134_BOARD_SABRENT_TV_PCB05 115
#define SAA7134_BOARD_10MOONSTVMASTER3 116
#define SAA7134_BOARD_AVERMEDIA_SUPER_007 117
#define SAA7134_BOARD_BEHOLD_401 118
#define SAA7134_BOARD_BEHOLD_403 119
#define SAA7134_BOARD_BEHOLD_403FM 120
#define SAA7134_BOARD_BEHOLD_405 121
#define SAA7134_BOARD_BEHOLD_405FM 122
#define SAA7134_BOARD_BEHOLD_407 123
#define SAA7134_BOARD_BEHOLD_407FM 124
#define SAA7134_BOARD_BEHOLD_409 125
#define SAA7134_BOARD_BEHOLD_505FM 126
#define SAA7134_BOARD_BEHOLD_507_9FM 127
#define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128
#define SAA7134_BOARD_BEHOLD_607FM_MK3 129
#define SAA7134_BOARD_BEHOLD_M6 130
#define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
#define SAA7134_BOARD_PHILIPS_SNAKE 133
#define SAA7134_BOARD_CREATIX_CTX953 134
#define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135
#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136
#define SAA7134_BOARD_AVERMEDIA_A16D 137
#define SAA7134_BOARD_AVERMEDIA_M115 138
#define SAA7134_BOARD_VIDEOMATE_T750 139
#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140
#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
#define SAA7134_BOARD_BEHOLD_H6 142
#define SAA7134_BOARD_BEHOLD_M63 143
#define SAA7134_BOARD_BEHOLD_M6_EXTRA 144
#define SAA7134_BOARD_AVERMEDIA_M103 145
#define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146
#define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147
#define SAA7134_BOARD_ENCORE_ENLTV_FM53 148
#define SAA7134_BOARD_AVERMEDIA_M135A 149
#define SAA7134_BOARD_REAL_ANGEL_220 150
#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151
#define SAA7134_BOARD_ASUSTeK_TIGER 152
#define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
#define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
#define SAA7134_BOARD_HAUPPAUGE_HVR1150 155
#define SAA7134_BOARD_HAUPPAUGE_HVR1120 156
#define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157
#define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158
#define SAA7134_BOARD_BEHOLD_505RDS 159
#define SAA7134_BOARD_BEHOLD_507RDS_MK3 160
#define SAA7134_BOARD_BEHOLD_507RDS_MK5 161
#define SAA7134_BOARD_BEHOLD_607FM_MK5 162
#define SAA7134_BOARD_BEHOLD_609FM_MK3 163
#define SAA7134_BOARD_BEHOLD_609FM_MK5 164
#define SAA7134_BOARD_BEHOLD_607RDS_MK3 165
#define SAA7134_BOARD_BEHOLD_607RDS_MK5 166
#define SAA7134_BOARD_BEHOLD_609RDS_MK3 167
#define SAA7134_BOARD_BEHOLD_609RDS_MK5 168
#define SAA7134_BOARD_VIDEOMATE_S350 169
#define SAA7134_BOARD_AVERMEDIA_STUDIO_505 170
#define SAA7134_BOARD_BEHOLD_X7 171
#define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172
#define SAA7134_BOARD_ZOLID_HYBRID_PCI 173
#define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
/* ----------------------------------------------------------- */
/* Since we support 2 remote types, lets tell them apart */
#define SAA7134_REMOTE_GPIO 1
#define SAA7134_REMOTE_I2C 2
/* ----------------------------------------------------------- */
/* Video Output Port Register Initialization Options */
#define SET_T_CODE_POLARITY_NON_INVERTED (1 << 0)
#define SET_CLOCK_NOT_DELAYED (1 << 1)
#define SET_CLOCK_INVERTED (1 << 2)
#define SET_VSYNC_OFF (1 << 3)
struct saa7134_input {
char *name;
unsigned int vmux;
enum saa7134_audio_in amux;
unsigned int gpio;
unsigned int tv:1;
};
enum saa7134_mpeg_type {
SAA7134_MPEG_UNUSED,
SAA7134_MPEG_EMPRESS,
SAA7134_MPEG_DVB,
};
enum saa7134_mpeg_ts_type {
SAA7134_MPEG_TS_PARALLEL = 0,
SAA7134_MPEG_TS_SERIAL,
};
struct saa7134_board {
char *name;
unsigned int audio_clock;
/* input switching */
unsigned int gpiomask;
struct saa7134_input inputs[SAA7134_INPUT_MAX];
struct saa7134_input radio;
struct saa7134_input mute;
/* i2c chip info */
unsigned int tuner_type;
unsigned int radio_type;
unsigned char tuner_addr;
unsigned char radio_addr;
unsigned char empress_addr;
unsigned char rds_addr;
unsigned int tda9887_conf;
unsigned int tuner_config;
/* peripheral I/O */
enum saa7134_video_out video_out;
enum saa7134_mpeg_type mpeg;
enum saa7134_mpeg_ts_type ts_type;
unsigned int vid_port_opts;
unsigned int ts_force_val:1;
};
#define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name)
#define card_is_empress(dev) (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg)
#define card_is_dvb(dev) (SAA7134_MPEG_DVB == saa7134_boards[dev->board].mpeg)
#define card_has_mpeg(dev) (SAA7134_MPEG_UNUSED != saa7134_boards[dev->board].mpeg)
#define card(dev) (saa7134_boards[dev->board])
#define card_in(dev,n) (saa7134_boards[dev->board].inputs[n])
/* ----------------------------------------------------------- */
/* device / file handle status */
#define RESOURCE_OVERLAY 1
#define RESOURCE_VIDEO 2
#define RESOURCE_VBI 4
#define INTERLACE_AUTO 0
#define INTERLACE_ON 1
#define INTERLACE_OFF 2
#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
#define TS_BUFFER_TIMEOUT msecs_to_jiffies(1000) /* 1 second */
struct saa7134_dev;
struct saa7134_dma;
/* saa7134 page table */
struct saa7134_pgtable {
unsigned int size;
__le32 *cpu;
dma_addr_t dma;
};
/* tvaudio thread status */
struct saa7134_thread {
struct task_struct *thread;
unsigned int scan1;
unsigned int scan2;
unsigned int mode;
unsigned int stopped;
};
/* buffer for one video/vbi/ts frame */
struct saa7134_buf {
/* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb;
/* saa7134 specific */
struct saa7134_format *fmt;
unsigned int top_seen;
int (*activate)(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next);
/* page tables */
struct saa7134_pgtable *pt;
};
struct saa7134_dmaqueue {
struct saa7134_dev *dev;
struct saa7134_buf *curr;
struct list_head queue;
struct timer_list timeout;
unsigned int need_two;
};
/* video filehandle status */
struct saa7134_fh {
struct saa7134_dev *dev;
unsigned int radio;
enum v4l2_buf_type type;
unsigned int resources;
enum v4l2_priority prio;
/* video overlay */
struct v4l2_window win;
struct v4l2_clip clips[8];
unsigned int nclips;
/* video capture */
struct saa7134_format *fmt;
unsigned int width,height;
struct videobuf_queue cap;
struct saa7134_pgtable pt_cap;
/* vbi capture */
struct videobuf_queue vbi;
struct saa7134_pgtable pt_vbi;
};
/* dmasound dsp status */
struct saa7134_dmasound {
struct mutex lock;
int minor_mixer;
int minor_dsp;
unsigned int users_dsp;
/* mixer */
enum saa7134_audio_in input;
unsigned int count;
unsigned int line1;
unsigned int line2;
/* dsp */
unsigned int afmt;
unsigned int rate;
unsigned int channels;
unsigned int recording_on;
unsigned int dma_running;
unsigned int blocks;
unsigned int blksize;
unsigned int bufsize;
struct saa7134_pgtable pt;
struct videobuf_dmabuf dma;
unsigned int dma_blk;
unsigned int read_offset;
unsigned int read_count;
void * priv_data;
struct snd_pcm_substream *substream;
};
/* ts/mpeg status */
struct saa7134_ts {
/* TS capture */
struct saa7134_pgtable pt_ts;
int nr_packets;
int nr_bufs;
};
/* ts/mpeg ops */
struct saa7134_mpeg_ops {
enum saa7134_mpeg_type type;
struct list_head next;
int (*init)(struct saa7134_dev *dev);
int (*fini)(struct saa7134_dev *dev);
void (*signal_change)(struct saa7134_dev *dev);
};
/* global device status */
struct saa7134_dev {
struct list_head devlist;
struct mutex lock;
spinlock_t slock;
struct v4l2_prio_state prio;
struct v4l2_device v4l2_dev;
/* workstruct for loading modules */
struct work_struct request_module_wk;
/* insmod option/autodetected */
int autodetected;
/* various device info */
unsigned int resources;
struct video_device *video_dev;
struct video_device *radio_dev;
struct video_device *vbi_dev;
struct saa7134_dmasound dmasound;
/* infrared remote */
int has_remote;
struct card_ir *remote;
/* pci i/o */
char name[32];
int nr;
struct pci_dev *pci;
unsigned char pci_rev,pci_lat;
__u32 __iomem *lmmio;
__u8 __iomem *bmmio;
/* config info */
unsigned int board;
unsigned int tuner_type;
unsigned int radio_type;
unsigned char tuner_addr;
unsigned char radio_addr;
unsigned int tda9887_conf;
unsigned int gpio_value;
/* i2c i/o */
struct i2c_adapter i2c_adap;
struct i2c_client i2c_client;
unsigned char eedata[256];
int has_rds;
/* video overlay */
struct v4l2_framebuffer ovbuf;
struct saa7134_format *ovfmt;
unsigned int ovenable;
enum v4l2_field ovfield;
/* video+ts+vbi capture */
struct saa7134_dmaqueue video_q;
struct saa7134_dmaqueue vbi_q;
unsigned int video_fieldcount;
unsigned int vbi_fieldcount;
/* various v4l controls */
struct saa7134_tvnorm *tvnorm; /* video */
struct saa7134_tvaudio *tvaudio;
unsigned int ctl_input;
int ctl_bright;
int ctl_contrast;
int ctl_hue;
int ctl_saturation;
int ctl_freq;
int ctl_mute; /* audio */
int ctl_volume;
int ctl_invert; /* private */
int ctl_mirror;
int ctl_y_odd;
int ctl_y_even;
int ctl_automute;
/* crop */
struct v4l2_rect crop_bounds;
struct v4l2_rect crop_defrect;
struct v4l2_rect crop_current;
/* other global state info */
unsigned int automute;
struct saa7134_thread thread;
struct saa7134_input *input;
struct saa7134_input *hw_input;
unsigned int hw_mute;
int last_carrier;
int nosignal;
unsigned int insuspend;
/* I2C keyboard data */
struct i2c_board_info info;
struct IR_i2c_init_data init_data;
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
int ts_started;
struct saa7134_mpeg_ops *mops;
/* SAA7134_MPEG_EMPRESS only */
struct video_device *empress_dev;
struct videobuf_queue empress_tsq;
atomic_t empress_users;
struct work_struct empress_workqueue;
int empress_started;
#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
/* SAA7134_MPEG_DVB only */
struct videobuf_dvb_frontends frontends;
int (*original_demod_sleep)(struct dvb_frontend *fe);
int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
#endif
void (*gate_ctrl)(struct saa7134_dev *dev, int open);
};
/* ----------------------------------------------------------- */
#define saa_readl(reg) readl(dev->lmmio + (reg))
#define saa_writel(reg,value) writel((value), dev->lmmio + (reg));
#define saa_andorl(reg,mask,value) \
writel((readl(dev->lmmio+(reg)) & ~(mask)) |\
((value) & (mask)), dev->lmmio+(reg))
#define saa_setl(reg,bit) saa_andorl((reg),(bit),(bit))
#define saa_clearl(reg,bit) saa_andorl((reg),(bit),0)
#define saa_readb(reg) readb(dev->bmmio + (reg))
#define saa_writeb(reg,value) writeb((value), dev->bmmio + (reg));
#define saa_andorb(reg,mask,value) \
writeb((readb(dev->bmmio+(reg)) & ~(mask)) |\
((value) & (mask)), dev->bmmio+(reg))
#define saa_setb(reg,bit) saa_andorb((reg),(bit),(bit))
#define saa_clearb(reg,bit) saa_andorb((reg),(bit),0)
#define saa_wait(us) { udelay(us); }
#define SAA7134_NORMS (\
V4L2_STD_PAL | V4L2_STD_PAL_N | \
V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
V4L2_STD_NTSC | V4L2_STD_PAL_M | \
V4L2_STD_PAL_60)
#define GRP_EMPRESS (1)
#define saa_call_all(dev, o, f, args...) do { \
if (dev->gate_ctrl) \
dev->gate_ctrl(dev, 1); \
v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args); \
if (dev->gate_ctrl) \
dev->gate_ctrl(dev, 0); \
} while (0)
#define saa_call_empress(dev, o, f, args...) ({ \
long _rc; \
if (dev->gate_ctrl) \
dev->gate_ctrl(dev, 1); \
_rc = v4l2_device_call_until_err(&(dev)->v4l2_dev, \
GRP_EMPRESS, o, f , ##args); \
if (dev->gate_ctrl) \
dev->gate_ctrl(dev, 0); \
_rc; \
})
/* ----------------------------------------------------------- */
/* saa7134-core.c */
extern struct list_head saa7134_devlist;
extern struct mutex saa7134_devlist_lock;
extern int saa7134_no_overlay;
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
#define SAA7134_PGTABLE_SIZE 4096
int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt);
int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
struct scatterlist *list, unsigned int length,
unsigned int startpage);
void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt);
int saa7134_buffer_count(unsigned int size, unsigned int count);
int saa7134_buffer_startpage(struct saa7134_buf *buf);
unsigned long saa7134_buffer_base(struct saa7134_buf *buf);
int saa7134_buffer_queue(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
struct saa7134_buf *buf);
void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
unsigned int state);
void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
void saa7134_buffer_timeout(unsigned long data);
void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
int saa7134_set_dmabits(struct saa7134_dev *dev);
extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
/* saa7134-cards.c */
extern struct saa7134_board saa7134_boards[];
extern const unsigned int saa7134_bcount;
extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
extern int saa7134_board_init1(struct saa7134_dev *dev);
extern int saa7134_board_init2(struct saa7134_dev *dev);
int saa7134_tuner_callback(void *priv, int component, int command, int arg);
/* ----------------------------------------------------------- */
/* saa7134-i2c.c */
int saa7134_i2c_register(struct saa7134_dev *dev);
int saa7134_i2c_unregister(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
/* saa7134-video.c */
extern unsigned int video_debug;
extern struct video_device saa7134_video_template;
extern struct video_device saa7134_radio_template;
int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c);
int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c);
int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id);
int saa7134_videoport_init(struct saa7134_dev *dev);
void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
int saa7134_video_init1(struct saa7134_dev *dev);
int saa7134_video_init2(struct saa7134_dev *dev);
void saa7134_irq_video_signalchange(struct saa7134_dev *dev);
void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status);
/* ----------------------------------------------------------- */
/* saa7134-ts.c */
#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
extern struct videobuf_queue_ops saa7134_ts_qops;
int saa7134_ts_init1(struct saa7134_dev *dev);
int saa7134_ts_fini(struct saa7134_dev *dev);
void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status);
int saa7134_ts_register(struct saa7134_mpeg_ops *ops);
void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops);
int saa7134_ts_init_hw(struct saa7134_dev *dev);
int saa7134_ts_start(struct saa7134_dev *dev);
int saa7134_ts_stop(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
/* saa7134-vbi.c */
extern struct videobuf_queue_ops saa7134_vbi_qops;
extern struct video_device saa7134_vbi_template;
int saa7134_vbi_init1(struct saa7134_dev *dev);
int saa7134_vbi_fini(struct saa7134_dev *dev);
void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status);
/* ----------------------------------------------------------- */
/* saa7134-tvaudio.c */
int saa7134_tvaudio_rx2mode(u32 rx);
void saa7134_tvaudio_setmute(struct saa7134_dev *dev);
void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
struct saa7134_input *in);
void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level);
int saa7134_tvaudio_getstereo(struct saa7134_dev *dev);
void saa7134_tvaudio_init(struct saa7134_dev *dev);
int saa7134_tvaudio_init2(struct saa7134_dev *dev);
int saa7134_tvaudio_fini(struct saa7134_dev *dev);
int saa7134_tvaudio_do_scan(struct saa7134_dev *dev);
int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value);
void saa7134_enable_i2s(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
/* saa7134-oss.c */
extern const struct file_operations saa7134_dsp_fops;
extern const struct file_operations saa7134_mixer_fops;
int saa7134_oss_init1(struct saa7134_dev *dev);
int saa7134_oss_fini(struct saa7134_dev *dev);
void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status);
/* ----------------------------------------------------------- */
/* saa7134-input.c */
int saa7134_input_init1(struct saa7134_dev *dev);
void saa7134_input_fini(struct saa7134_dev *dev);
void saa7134_input_irq(struct saa7134_dev *dev);
void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir);
void saa7134_ir_stop(struct saa7134_dev *dev);
/*
* Local variables:
* c-basic-offset: 8
* End:
*/