summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/Kconfig5
-rw-r--r--linux/drivers/media/common/ir-functions.c25
-rw-r--r--linux/drivers/media/common/tuners/tuner-xc2028.c2
-rw-r--r--linux/drivers/media/common/tuners/xc5000.c2
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvbdev.c9
-rw-r--r--linux/drivers/media/dvb/dvb-usb/cxusb.c21
-rw-r--r--linux/drivers/media/dvb/dvb-usb/gp8psk.c3
-rw-r--r--linux/drivers/media/dvb/frontends/bcm3510.c5
-rw-r--r--linux/drivers/media/dvb/frontends/nxt200x.c3
-rw-r--r--linux/drivers/media/dvb/frontends/or51211.c4
-rw-r--r--linux/drivers/media/dvb/frontends/sp8870.c2
-rw-r--r--linux/drivers/media/dvb/frontends/sp887x.c2
-rw-r--r--linux/drivers/media/dvb/frontends/tda10048.c2
-rw-r--r--linux/drivers/media/dvb/frontends/tda1004x.c2
-rw-r--r--linux/drivers/media/dvb/siano/smscoreapi.h1
-rw-r--r--linux/drivers/media/dvb/siano/smsusb.c2
-rw-r--r--linux/drivers/media/radio/miropcm20-rds.c8
-rw-r--r--linux/drivers/media/video/Kconfig88
-rw-r--r--linux/drivers/media/video/Makefile3
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-cards.c3
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-core.c148
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-core.h3
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-vbi.c147
-rw-r--r--linux/drivers/media/video/cx18/cx18-irq.c4
-rw-r--r--linux/drivers/media/video/cx18/cx18-irq.h4
-rw-r--r--linux/drivers/media/video/cx18/cx18-streams.c4
-rw-r--r--linux/drivers/media/video/cx2341x.c151
-rw-r--r--linux/drivers/media/video/cx23885/Kconfig1
-rw-r--r--linux/drivers/media/video/cx25840/cx25840-core.c157
-rw-r--r--linux/drivers/media/video/cx25840/cx25840-core.h3
-rw-r--r--linux/drivers/media/video/cx25840/cx25840-vbi.c152
-rw-r--r--linux/drivers/media/video/dabusb.c4
-rw-r--r--linux/drivers/media/video/gspca/gspca.c4
-rw-r--r--linux/drivers/media/video/ir-kbd-i2c.c82
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-i2c.c2
-rw-r--r--linux/drivers/media/video/ivtv/ivtvfb.c4
-rw-r--r--linux/drivers/media/video/mt9m001.c4
-rw-r--r--linux/drivers/media/video/ov7670.c16
-rw-r--r--linux/drivers/media/video/pxa_camera.c27
-rw-r--r--linux/drivers/media/video/saa7115.c2
-rw-r--r--linux/drivers/media/video/saa7127.c46
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-cards.c5
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-input.c78
-rw-r--r--linux/drivers/media/video/sh_mobile_ceu_camera.c657
-rw-r--r--linux/drivers/media/video/soc_camera.c46
-rw-r--r--linux/drivers/media/video/soc_camera_platform.c198
-rw-r--r--linux/drivers/media/video/tvmixer.c6
-rw-r--r--linux/drivers/media/video/videobuf-dma-contig.c419
-rw-r--r--linux/drivers/media/video/videobuf-dma-sg.c2
-rw-r--r--linux/drivers/media/video/videobuf-vmalloc.c2
-rw-r--r--linux/drivers/media/video/videodev.c173
51 files changed, 2069 insertions, 674 deletions
diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig
index 7a7803b5d..93ea201f4 100644
--- a/linux/drivers/media/Kconfig
+++ b/linux/drivers/media/Kconfig
@@ -38,7 +38,6 @@ config VIDEO_ALLOW_V4L1
bool "Enable Video For Linux API 1 (DEPRECATED)"
depends on VIDEO_DEV && VIDEO_V4L2_COMMON
default VIDEO_DEV && VIDEO_V4L2_COMMON
- select VIDEO_V4L1_COMPAT
---help---
Enables drivers based on the legacy V4L1 API.
@@ -49,9 +48,9 @@ config VIDEO_ALLOW_V4L1
If you are unsure as to whether this is required, answer Y.
config VIDEO_V4L1_COMPAT
- bool "Enable Video For Linux API 1 compatible Layer"
+ bool "Enable Video For Linux API 1 compatible Layer" if !VIDEO_ALLOW_V4L1
depends on VIDEO_DEV
- default VIDEO_DEV
+ default y
---help---
Enables a compatibility API used by most V4L2 devices to allow
its usage with legacy applications that supports only V4L1 api.
diff --git a/linux/drivers/media/common/ir-functions.c b/linux/drivers/media/common/ir-functions.c
index 3653b6d37..ddbd4be99 100644
--- a/linux/drivers/media/common/ir-functions.c
+++ b/linux/drivers/media/common/ir-functions.c
@@ -78,6 +78,7 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
if (repeat)
set_bit(EV_REP, dev->evbit);
}
+EXPORT_SYMBOL_GPL(ir_input_init);
void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
{
@@ -86,6 +87,7 @@ void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
ir_input_key_event(dev,ir);
}
}
+EXPORT_SYMBOL_GPL(ir_input_nokey);
void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
u32 ir_key, u32 ir_raw)
@@ -108,6 +110,7 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
input_event(a, EV_IR, ir->ir_type, ir->ir_raw);
#endif
}
+EXPORT_SYMBOL_GPL(ir_input_keydown);
/* -------------------------------------------------------------------------- */
/* extract mask bits out of data and pack them into the result */
@@ -126,6 +129,7 @@ u32 ir_extract_bits(u32 data, u32 mask)
return value;
}
+EXPORT_SYMBOL_GPL(ir_extract_bits);
static int inline getbit(u32 *samples, int bit)
{
@@ -150,6 +154,7 @@ int ir_dump_samples(u32 *samples, int count)
printk("\n");
return 0;
}
+EXPORT_SYMBOL_GPL(ir_dump_samples);
/* decode raw samples, pulse distance coding used by NEC remotes */
int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
@@ -216,6 +221,7 @@ int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
return value;
}
+EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
/* decode raw samples, biphase coding, used by rc5 for example */
int ir_decode_biphase(u32 *samples, int count, int low, int high)
@@ -257,6 +263,7 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high)
}
return value;
}
+EXPORT_SYMBOL_GPL(ir_decode_biphase);
/* RC5 decoding stuff, moved from bttv-input.c to share it with
* saa7134 */
@@ -357,6 +364,7 @@ void ir_rc5_timer_end(unsigned long data)
}
}
}
+EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
void ir_rc5_timer_keyup(unsigned long data)
{
@@ -365,21 +373,4 @@ void ir_rc5_timer_keyup(unsigned long data)
dprintk(1, "ir-common: key released\n");
ir_input_nokey(ir->dev, &ir->ir);
}
-
-EXPORT_SYMBOL_GPL(ir_input_init);
-EXPORT_SYMBOL_GPL(ir_input_nokey);
-EXPORT_SYMBOL_GPL(ir_input_keydown);
-
-EXPORT_SYMBOL_GPL(ir_extract_bits);
-EXPORT_SYMBOL_GPL(ir_dump_samples);
-EXPORT_SYMBOL_GPL(ir_decode_biphase);
-EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
-
-EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c
index 88fd2c91c..a3272e81e 100644
--- a/linux/drivers/media/common/tuners/tuner-xc2028.c
+++ b/linux/drivers/media/common/tuners/tuner-xc2028.c
@@ -259,7 +259,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
{
struct xc2028_data *priv = fe->tuner_priv;
const struct firmware *fw = NULL;
- unsigned char *p, *endp;
+ const unsigned char *p, *endp;
int rc = 0;
int n, n_array;
char name[33];
diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c
index 63b4dba44..e0f045e1b 100644
--- a/linux/drivers/media/common/tuners/xc5000.c
+++ b/linux/drivers/media/common/tuners/xc5000.c
@@ -282,7 +282,7 @@ static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
return result;
}
-static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
+static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
{
struct xc5000_priv *priv = fe->tuner_priv;
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c
index 0ae0e5852..e6d20310a 100644
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c
@@ -33,6 +33,7 @@
#include <linux/cdev.h>
#include "compat.h"
#include <linux/mutex.h>
+#include <linux/smp_lock.h>
#include "dvbdev.h"
static int dvbdev_debug;
@@ -75,6 +76,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
+ lock_kernel();
dvbdev = dvbdev_find_device (iminor(inode));
if (dvbdev && dvbdev->fops) {
@@ -95,8 +97,10 @@ static int dvb_device_open(struct inode *inode, struct file *file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
+ unlock_kernel();
return err;
}
+ unlock_kernel();
return -ENODEV;
}
@@ -425,7 +429,12 @@ static int __init init_dvbdev(void)
return retval;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
cdev_init(&dvb_device_cdev, &dvb_device_fops);
+#else
+ cdev_init(&dvb_device_cdev,
+ (struct file_operations *)&dvb_device_fops);
+#endif
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
printk(KERN_ERR "dvb-core: unable register character device\n");
goto error;
diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c
index 9a3e97247..578afce68 100644
--- a/linux/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c
@@ -24,6 +24,7 @@
* see Documentation/dvb/README.dvb-usb for more information
*/
#include <media/tuner.h>
+#include <linux/vmalloc.h>
#include "cxusb.h"
@@ -791,12 +792,26 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
- fw->data[idoff + 2] =
+ struct firmware new_fw;
+ u8 *new_fw_data = vmalloc(fw->size);
+ int ret;
+
+ if (!new_fw_data)
+ return -ENOMEM;
+
+ memcpy(new_fw_data, fw->data, fw->size);
+ new_fw.size = fw->size;
+ new_fw.data = new_fw_data;
+
+ new_fw_data[idoff + 2] =
le16_to_cpu(udev->descriptor.idProduct) + 1;
- fw->data[idoff + 3] =
+ new_fw_data[idoff + 3] =
le16_to_cpu(udev->descriptor.idProduct) >> 8;
- return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
+ ret = usb_cypress_load_firmware(udev, &new_fw,
+ CYPRESS_FX2);
+ vfree(new_fw_data);
+ return ret;
}
}
diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.c b/linux/drivers/media/dvb/dvb-usb/gp8psk.c
index 6eb8cc37f..1b002909b 100644
--- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -86,7 +86,8 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
{
int ret;
const struct firmware *fw = NULL;
- u8 *ptr, *buf;
+ const u8 *ptr;
+ u8 *buf;
if ((ret = request_firmware(&fw, bcm4500_firmware,
&d->udev->dev)) != 0) {
err("did not find the bcm4500 firmware file. (%s) "
diff --git a/linux/drivers/media/dvb/frontends/bcm3510.c b/linux/drivers/media/dvb/frontends/bcm3510.c
index 1cd63a4df..ba85a5618 100644
--- a/linux/drivers/media/dvb/frontends/bcm3510.c
+++ b/linux/drivers/media/dvb/frontends/bcm3510.c
@@ -591,7 +591,8 @@ static void bcm3510_release(struct dvb_frontend* fe)
*/
#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
-static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, u8 *b, u16 len)
+static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, const u8 *b,
+ u16 len)
{
int ret = 0,i;
bcm3510_register_value vH, vL,vD;
@@ -615,7 +616,7 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe)
struct bcm3510_state* st = fe->demodulator_priv;
const struct firmware *fw;
u16 addr,len;
- u8 *b;
+ const u8 *b;
int ret,i;
deb_info("requesting firmware\n");
diff --git a/linux/drivers/media/dvb/frontends/nxt200x.c b/linux/drivers/media/dvb/frontends/nxt200x.c
index 9172843dd..a079fa824 100644
--- a/linux/drivers/media/dvb/frontends/nxt200x.c
+++ b/linux/drivers/media/dvb/frontends/nxt200x.c
@@ -94,7 +94,8 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
return 0;
}
-static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8 len)
+static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
+ const u8 *buf, u8 len)
{
u8 buf2 [len+1];
int err;
diff --git a/linux/drivers/media/dvb/frontends/or51211.c b/linux/drivers/media/dvb/frontends/or51211.c
index 7eaa47655..6afe12aac 100644
--- a/linux/drivers/media/dvb/frontends/or51211.c
+++ b/linux/drivers/media/dvb/frontends/or51211.c
@@ -69,7 +69,7 @@ struct or51211_state {
u32 current_frequency;
};
-static int i2c_writebytes (struct or51211_state* state, u8 reg, u8 *buf,
+static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
int len)
{
int err;
@@ -77,7 +77,7 @@ static int i2c_writebytes (struct or51211_state* state, u8 reg, u8 *buf,
msg.addr = reg;
msg.flags = 0;
msg.len = len;
- msg.buf = buf;
+ msg.buf = (u8 *)buf;
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk(KERN_WARNING "or51211: i2c_writebytes error "
diff --git a/linux/drivers/media/dvb/frontends/sp8870.c b/linux/drivers/media/dvb/frontends/sp8870.c
index aa78aa14a..1c9a9b405 100644
--- a/linux/drivers/media/dvb/frontends/sp8870.c
+++ b/linux/drivers/media/dvb/frontends/sp8870.c
@@ -98,7 +98,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
{
struct i2c_msg msg;
- char *fw_buf = fw->data;
+ const char *fw_buf = fw->data;
int fw_pos;
u8 tx_buf[255];
int tx_len;
diff --git a/linux/drivers/media/dvb/frontends/sp887x.c b/linux/drivers/media/dvb/frontends/sp887x.c
index 49f55877f..4543609e1 100644
--- a/linux/drivers/media/dvb/frontends/sp887x.c
+++ b/linux/drivers/media/dvb/frontends/sp887x.c
@@ -140,7 +140,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
u8 buf [BLOCKSIZE+2];
int i;
int fw_size = fw->size;
- unsigned char *mem = fw->data;
+ const unsigned char *mem = fw->data;
dprintk("%s\n", __func__);
diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c
index f2d66234a..7c718e247 100644
--- a/linux/drivers/media/dvb/frontends/tda10048.c
+++ b/linux/drivers/media/dvb/frontends/tda10048.c
@@ -233,7 +233,7 @@ static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
}
static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
- u8 *data, u16 len)
+ const u8 *data, u16 len)
{
int ret = -EREMOTEIO;
struct i2c_msg msg;
diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c
index a0d638653..1465ff77b 100644
--- a/linux/drivers/media/dvb/frontends/tda1004x.c
+++ b/linux/drivers/media/dvb/frontends/tda1004x.c
@@ -317,7 +317,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
}
static int tda1004x_do_upload(struct tda1004x_state *state,
- unsigned char *mem, unsigned int len,
+ const unsigned char *mem, unsigned int len,
u8 dspCodeCounterReg, u8 dspCodeInReg)
{
u8 buf[65];
diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h
index 482ef0676..dbedc315f 100644
--- a/linux/drivers/media/dvb/siano/smscoreapi.h
+++ b/linux/drivers/media/dvb/siano/smscoreapi.h
@@ -29,6 +29,7 @@
#include <linux/scatterlist.h>
#include <linux/types.h>
#include <asm/page.h>
+
#include "compat.h"
#include "dmxdev.h"
#include "dvbdev.h"
diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c
index 079deb2a1..40582bf70 100644
--- a/linux/drivers/media/dvb/siano/smsusb.c
+++ b/linux/drivers/media/dvb/siano/smsusb.c
@@ -55,7 +55,7 @@ struct smsusb_device_t {
static int smsusb_submit_urb(struct smsusb_device_t *dev,
struct smsusb_urb_t *surb);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
static void smsusb_onresponse(struct urb *urb)
#else
static void smsusb_onresponse(struct urb *urb, struct pt_regs *regs)
diff --git a/linux/drivers/media/radio/miropcm20-rds.c b/linux/drivers/media/radio/miropcm20-rds.c
index 06dfed9ef..af90cdcf2 100644
--- a/linux/drivers/media/radio/miropcm20-rds.c
+++ b/linux/drivers/media/radio/miropcm20-rds.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/smp_lock.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
@@ -27,13 +28,16 @@ static int rds_f_open(struct inode *in, struct file *fi)
if (rds_users)
return -EBUSY;
+ lock_kernel();
rds_users++;
if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) {
rds_users--;
printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n");
+ unlock_kernel();
return -ENOMEM;
}
+ unlock_kernel();
return 0;
}
@@ -104,7 +108,11 @@ static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length,
}
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
static const struct file_operations rds_fops = {
+#else
+static struct file_operations rds_fops = {
+#endif
.owner = THIS_MODULE,
.read = rds_f_read,
.open = rds_f_open,
diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig
index 45c90b8bc..70a96a361 100644
--- a/linux/drivers/media/video/Kconfig
+++ b/linux/drivers/media/video/Kconfig
@@ -24,21 +24,21 @@ config VIDEOBUF_VMALLOC
select VIDEOBUF_GEN
tristate
+config VIDEOBUF_DMA_CONTIG
+ depends on HAS_DMA
+ select VIDEOBUF_GEN
+ tristate
+
config VIDEOBUF_DVB
tristate
select VIDEOBUF_GEN
- select VIDEOBUF_DMA_SG
config VIDEO_BTCX
tristate
-config VIDEO_IR_I2C
- tristate
-
config VIDEO_IR
tristate
depends on INPUT
- select VIDEO_IR_I2C if I2C
config VIDEO_TVEEPROM
tristate
@@ -84,6 +84,19 @@ config VIDEO_HELPER_CHIPS_AUTO
In doubt, say Y.
+config VIDEO_IR_I2C
+ tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO
+ depends on I2C && VIDEO_IR
+ default y
+ ---help---
+ Most boards have an IR chip directly connected via GPIO. However,
+ some video boards have the IR connected via I2C bus.
+
+ If your board doesn't have an I2C IR chip, you may disable this
+ option.
+
+ In doubt, say Y.
+
#
# Encoder / Decoder module configuration
#
@@ -600,9 +613,6 @@ config VIDEO_STRADIS
driver for PCI. There is a product page at
<http://www.stradis.com/>.
-config VIDEO_ZORAN_ZR36060
- tristate
-
config VIDEO_ZORAN
tristate "Zoran ZR36057/36067 Video For Linux"
depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
@@ -616,61 +626,64 @@ config VIDEO_ZORAN
To compile this driver as a module, choose M here: the
module will be called zr36067.
+config VIDEO_ZORAN_DC30
+ tristate "Pinnacle/Miro DC30(+) support"
+ depends on VIDEO_ZORAN
+ select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
+ help
+ Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
+ card. This also supports really old DC10 cards based on the
+ zr36050 MJPEG codec and zr36016 VFE.
+
+config VIDEO_ZORAN_ZR36060
+ tristate "Zoran ZR36060"
+ depends on VIDEO_ZORAN
+ help
+ Say Y to support Zoran boards based on 36060 chips.
+ This includes Iomega Bus, Pinnacle DC10, Linux media Labs 33
+ and 33 R10 and AverMedia 6 boards.
+
config VIDEO_ZORAN_BUZ
tristate "Iomega Buz support"
- depends on VIDEO_ZORAN
+ depends on VIDEO_ZORAN_ZR36060
select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_ZORAN_ZR36060
help
Support for the Iomega Buz MJPEG capture/playback card.
config VIDEO_ZORAN_DC10
tristate "Pinnacle/Miro DC10(+) support"
- depends on VIDEO_ZORAN
- select VIDEO_SAA7110
+ depends on VIDEO_ZORAN_ZR36060
+ select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_ZORAN_ZR36060
help
Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
card.
-config VIDEO_ZORAN_DC30
- tristate "Pinnacle/Miro DC30(+) support"
- depends on VIDEO_ZORAN
- select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
- help
- Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
- card. This also supports really old DC10 cards based on the
- zr36050 MJPEG codec and zr36016 VFE.
-
config VIDEO_ZORAN_LML33
tristate "Linux Media Labs LML33 support"
- depends on VIDEO_ZORAN
+ depends on VIDEO_ZORAN_ZR36060
select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_ZORAN_ZR36060
help
Support for the Linux Media Labs LML33 MJPEG capture/playback
card.
config VIDEO_ZORAN_LML33R10
tristate "Linux Media Labs LML33R10 support"
- depends on VIDEO_ZORAN
+ depends on VIDEO_ZORAN_ZR36060
select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_ZORAN_ZR36060
help
support for the Linux Media Labs LML33R10 MJPEG capture/playback
card.
config VIDEO_ZORAN_AVS6EYES
tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
- depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1
+ depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
- select VIDEO_ZORAN_ZR36060
help
Support for the AverMedia 6 Eyes video surveillance card.
@@ -915,7 +928,7 @@ endif # V4L_USB_DRIVERS
config SOC_CAMERA
tristate "SoC camera support"
depends on VIDEO_V4L2 && HAS_DMA
- select VIDEOBUF_DMA_SG
+ select VIDEOBUF_GEN
help
SoC Camera is a common API to several cameras, not connecting
over a bus like PCI or USB. For example some i2c camera connected
@@ -950,11 +963,26 @@ config MT9V022_PCA9536_SWITCH
Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
extender to switch between 8 and 10 bit datawidth modes
+config SOC_CAMERA_PLATFORM
+ tristate "platform camera support"
+ depends on SOC_CAMERA
+ help
+ This is a generic SoC camera platform driver, useful for testing
+
config VIDEO_PXA27x
tristate "PXA27x Quick Capture Interface driver"
depends on VIDEO_DEV && PXA27x
select SOC_CAMERA
+ select VIDEOBUF_DMA_SG
---help---
This is a v4l2 driver for the PXA27x Quick Capture Interface
+config VIDEO_SH_MOBILE_CEU
+ tristate "SuperH Mobile CEU Interface driver"
+ depends on VIDEO_DEV
+ select SOC_CAMERA
+ select VIDEOBUF_DMA_CONTIG
+ ---help---
+ This is a v4l2 driver for the SuperH Mobile CEU Interface
+
endif # VIDEO_CAPTURE_DRIVERS
diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile
index 0a1837c99..00e2df8a4 100644
--- a/linux/drivers/media/video/Makefile
+++ b/linux/drivers/media/video/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
+obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
@@ -133,9 +134,11 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
+obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
obj-$(CONFIG_VIDEO_AU0828) += au0828/
diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c
index df2dfd2ba..ff9d09f09 100644
--- a/linux/drivers/media/video/bt8xx/bttv-cards.c
+++ b/linux/drivers/media/video/bt8xx/bttv-cards.c
@@ -3809,7 +3809,8 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
#define BTTV_ALT_DCLK 0x100000
#define BTTV_ALT_NCONFIG 0x800000
-static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
+static int __devinit pvr_altera_load(struct bttv *btv, const u8 *micro,
+ u32 microlen)
{
u32 n;
u8 bits;
diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c
index 3ccdf613b..3b0a2c450 100644
--- a/linux/drivers/media/video/cx18/cx18-av-core.c
+++ b/linux/drivers/media/video/cx18/cx18-av-core.c
@@ -80,6 +80,7 @@ static void log_video_status(struct cx18 *cx);
static void cx18_av_initialize(struct cx18 *cx)
{
+ struct cx18_av_state *state = &cx->av_state;
u32 v;
cx18_av_loadfw(cx);
@@ -159,6 +160,149 @@ static void cx18_av_initialize(struct cx18 *cx)
/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
/* } */
cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
+ state->default_volume = 228 - cx18_av_read(cx, 0x8d4);
+ state->default_volume = ((state->default_volume / 2) + 23) << 9;
+}
+
+/* ----------------------------------------------------------------------- */
+
+void cx18_av_std_setup(struct cx18 *cx)
+{
+ struct cx18_av_state *state = &cx->av_state;
+ v4l2_std_id std = state->std;
+ int hblank, hactive, burst, vblank, vactive, sc;
+ int vblank656, src_decimation;
+ int luma_lpf, uv_lpf, comb;
+ u32 pll_int, pll_frac, pll_post;
+
+ /* datasheet startup, step 8d */
+ if (std & ~V4L2_STD_NTSC)
+ cx18_av_write(cx, 0x49f, 0x11);
+ else
+ cx18_av_write(cx, 0x49f, 0x14);
+
+ if (std & V4L2_STD_625_50) {
+ hblank = 132;
+ hactive = 720;
+ burst = 93;
+ vblank = 36;
+ vactive = 580;
+ vblank656 = 40;
+ src_decimation = 0x21f;
+
+ luma_lpf = 2;
+ if (std & V4L2_STD_PAL) {
+ uv_lpf = 1;
+ comb = 0x20;
+ sc = 688739;
+ } else if (std == V4L2_STD_PAL_Nc) {
+ uv_lpf = 1;
+ comb = 0x20;
+ sc = 556453;
+ } else { /* SECAM */
+ uv_lpf = 0;
+ comb = 0;
+ sc = 672351;
+ }
+ } else {
+ hactive = 720;
+ hblank = 122;
+ vactive = 487;
+ luma_lpf = 1;
+ uv_lpf = 1;
+ vblank = 26;
+ vblank656 = 26;
+
+ src_decimation = 0x21f;
+ if (std == V4L2_STD_PAL_60) {
+ burst = 0x5b;
+ luma_lpf = 2;
+ comb = 0x20;
+ sc = 688739;
+ } else if (std == V4L2_STD_PAL_M) {
+ burst = 0x61;
+ comb = 0x20;
+ sc = 555452;
+ } else {
+ burst = 0x5b;
+ comb = 0x66;
+ sc = 556063;
+ }
+ }
+
+ /* DEBUG: Displays configured PLL frequency */
+ pll_int = cx18_av_read(cx, 0x108);
+ pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
+ pll_post = cx18_av_read(cx, 0x109);
+ CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
+ pll_int, pll_frac, pll_post);
+
+ if (pll_post) {
+ int fin, fsc;
+ int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
+
+ pll >>= 25;
+ pll /= pll_post;
+ CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
+ pll / 1000000, pll % 1000000);
+ CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
+ pll / 8000000, (pll / 8) % 1000000);
+
+ fin = ((u64)src_decimation * pll) >> 12;
+ CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
+ fin / 1000000, fin % 1000000);
+
+ fsc = (((u64)sc) * pll) >> 24L;
+ CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
+ fsc / 1000000, fsc % 1000000);
+
+ CX18_DEBUG_INFO("hblank %i, hactive %i, "
+ "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
+ "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
+ " sc 0x%06x\n",
+ hblank, hactive, vblank, vactive, vblank656,
+ src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+ }
+
+ /* Sets horizontal blanking delay and active lines */
+ cx18_av_write(cx, 0x470, hblank);
+ cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
+ (hactive << 4)));
+ cx18_av_write(cx, 0x472, hactive >> 4);
+
+ /* Sets burst gate delay */
+ cx18_av_write(cx, 0x473, burst);
+
+ /* Sets vertical blanking delay and active duration */
+ cx18_av_write(cx, 0x474, vblank);
+ cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
+ (vactive << 4)));
+ cx18_av_write(cx, 0x476, vactive >> 4);
+ cx18_av_write(cx, 0x477, vblank656);
+
+ /* Sets src decimation rate */
+ cx18_av_write(cx, 0x478, 0xff & src_decimation);
+ cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
+
+ /* Sets Luma and UV Low pass filters */
+ cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
+
+ /* Enables comb filters */
+ cx18_av_write(cx, 0x47b, comb);
+
+ /* Sets SC Step*/
+ cx18_av_write(cx, 0x47c, sc);
+ cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
+ cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
+
+ /* Sets VBI parameters */
+ if (std & V4L2_STD_625_50) {
+ cx18_av_write(cx, 0x47f, 0x01);
+ state->vbi_line_offset = 5;
+ } else {
+ cx18_av_write(cx, 0x47f, 0x00);
+ state->vbi_line_offset = 8;
+ }
}
/* ----------------------------------------------------------------------- */
@@ -320,7 +464,7 @@ static int set_v4lstd(struct cx18 *cx)
}
cx18_av_and_or(cx, 0x400, ~0x2f, fmt | 0x20);
cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
- cx18_av_vbi_setup(cx);
+ cx18_av_std_setup(cx);
input_change(cx);
return 0;
}
@@ -559,6 +703,8 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
switch (qc->id) {
case V4L2_CID_AUDIO_VOLUME:
+ return v4l2_ctrl_query_fill(qc, 0, 65535,
+ 65535 / 100, state->default_volume);
case V4L2_CID_AUDIO_MUTE:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h
index b54239959..eb61fa1e0 100644
--- a/linux/drivers/media/video/cx18/cx18-av-core.h
+++ b/linux/drivers/media/video/cx18/cx18-av-core.h
@@ -79,6 +79,7 @@ struct cx18_av_state {
u32 audclk_freq;
int audmode;
int vbi_line_offset;
+ int default_volume;
u32 id;
u32 rev;
int is_initialized;
@@ -305,6 +306,7 @@ u32 cx18_av_read4(struct cx18 *cx, u16 addr);
int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
+void cx18_av_std_setup(struct cx18 *cx);
/* ----------------------------------------------------------------------- */
/* cx18_av-firmware.c */
@@ -317,7 +319,6 @@ void cx18_av_audio_set_path(struct cx18 *cx);
/* ----------------------------------------------------------------------- */
/* cx18_av-vbi.c */
-void cx18_av_vbi_setup(struct cx18 *cx);
int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg);
#endif
diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c
index 0c92f1236..02fdf57bb 100644
--- a/linux/drivers/media/video/cx18/cx18-av-vbi.c
+++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c
@@ -83,145 +83,6 @@ static int decode_vps(u8 *dst, u8 *p)
return err & 0xf0;
}
-void cx18_av_vbi_setup(struct cx18 *cx)
-{
- struct cx18_av_state *state = &cx->av_state;
- v4l2_std_id std = state->std;
- int hblank, hactive, burst, vblank, vactive, sc;
- int vblank656, src_decimation;
- int luma_lpf, uv_lpf, comb;
- u32 pll_int, pll_frac, pll_post;
-
- /* datasheet startup, step 8d */
- if (std & ~V4L2_STD_NTSC)
- cx18_av_write(cx, 0x49f, 0x11);
- else
- cx18_av_write(cx, 0x49f, 0x14);
-
- if (std & V4L2_STD_625_50) {
- hblank = 0x084;
- hactive = 0x2d0;
- burst = 0x5d;
- vblank = 0x024;
- vactive = 0x244;
- vblank656 = 0x28;
- src_decimation = 0x21f;
-
- luma_lpf = 2;
- if (std & V4L2_STD_PAL) {
- uv_lpf = 1;
- comb = 0x20;
- sc = 0x0a8263;
- } else if (std == V4L2_STD_PAL_Nc) {
- uv_lpf = 1;
- comb = 0x20;
- sc = 0x087da5;
- } else { /* SECAM */
- uv_lpf = 0;
- comb = 0;
- sc = 0x0a425f;
- }
- } else {
- hactive = 720;
- hblank = 122;
- vactive = 487;
- luma_lpf = 1;
- uv_lpf = 1;
- vblank = 26;
- vblank656 = 26;
-
- src_decimation = 0x21f;
- if (std == V4L2_STD_PAL_60) {
- burst = 0x5b;
- luma_lpf = 2;
- comb = 0x20;
- sc = 0x0a8263;
- } else if (std == V4L2_STD_PAL_M) {
- burst = 0x61;
- comb = 0x20;
- sc = 555452;
- } else {
- burst = 0x5b;
- comb = 0x66;
- sc = 556063;
- }
- }
-
- /* DEBUG: Displays configured PLL frequency */
- pll_int = cx18_av_read(cx, 0x108);
- pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
- pll_post = cx18_av_read(cx, 0x109);
- CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
- pll_int, pll_frac, pll_post);
-
- if (pll_post) {
- int fin, fsc;
- int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
-
- pll >>= 25;
- pll /= pll_post;
- CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
- pll / 1000000, pll % 1000000);
- CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
- pll / 8000000, (pll / 8) % 1000000);
-
- fin = ((u64)src_decimation * pll) >> 12;
- CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
- fin / 1000000, fin % 1000000);
-
- fsc = (((u64)sc) * pll) >> 24L;
- CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
- fsc / 1000000, fsc % 1000000);
-
- CX18_DEBUG_INFO("hblank %i, hactive %i, "
- "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
- "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
- " sc 0x%06x\n",
- hblank, hactive, vblank, vactive, vblank656,
- src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
- }
-
- /* Sets horizontal blanking delay and active lines */
- cx18_av_write(cx, 0x470, hblank);
- cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
- (hactive << 4)));
- cx18_av_write(cx, 0x472, hactive >> 4);
-
- /* Sets burst gate delay */
- cx18_av_write(cx, 0x473, burst);
-
- /* Sets vertical blanking delay and active duration */
- cx18_av_write(cx, 0x474, vblank);
- cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
- (vactive << 4)));
- cx18_av_write(cx, 0x476, vactive >> 4);
- cx18_av_write(cx, 0x477, vblank656);
-
- /* Sets src decimation rate */
- cx18_av_write(cx, 0x478, 0xff & src_decimation);
- cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
-
- /* Sets Luma and UV Low pass filters */
- cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
-
- /* Enables comb filters */
- cx18_av_write(cx, 0x47b, comb);
-
- /* Sets SC Step*/
- cx18_av_write(cx, 0x47c, sc);
- cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
- cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
-
- /* Sets VBI parameters */
- if (std & V4L2_STD_625_50) {
- cx18_av_write(cx, 0x47f, 0x01);
- state->vbi_line_offset = 5;
- } else {
- cx18_av_write(cx, 0x47f, 0x00);
- state->vbi_line_offset = 8;
- }
-}
-
int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
{
struct cx18_av_state *state = &cx->av_state;
@@ -287,8 +148,8 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
/* raw VBI */
memset(svbi, 0, sizeof(*svbi));
- /* Setup VBI */
- cx18_av_vbi_setup(cx);
+ /* Setup standard */
+ cx18_av_std_setup(cx);
/* VBI Offset */
cx18_av_write(cx, 0x47f, vbi_offset);
@@ -299,8 +160,8 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
for (x = 0; x <= 23; x++)
lcr[x] = 0x00;
- /* Setup VBI */
- cx18_av_vbi_setup(cx);
+ /* Setup standard */
+ cx18_av_std_setup(cx);
/* Sliced VBI */
cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
diff --git a/linux/drivers/media/video/cx18/cx18-irq.c b/linux/drivers/media/video/cx18/cx18-irq.c
index 25114a5cb..654664783 100644
--- a/linux/drivers/media/video/cx18/cx18-irq.c
+++ b/linux/drivers/media/video/cx18/cx18-irq.c
@@ -132,7 +132,11 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1)
CX18_WARN("Unexpected interrupt %08x\n", sw1);
}
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
+irqreturn_t cx18_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+#else
irqreturn_t cx18_irq_handler(int irq, void *dev_id)
+#endif
{
struct cx18 *cx = (struct cx18 *)dev_id;
u32 sw1, sw1_mask;
diff --git a/linux/drivers/media/video/cx18/cx18-irq.h b/linux/drivers/media/video/cx18/cx18-irq.h
index 379f704f5..cbcd2022f 100644
--- a/linux/drivers/media/video/cx18/cx18-irq.h
+++ b/linux/drivers/media/video/cx18/cx18-irq.h
@@ -30,7 +30,11 @@
#define SW2_INT_STATUS 0xc73144
#define SW2_INT_ENABLE_PCI 0xc7315c
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
+irqreturn_t cx18_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+#else
irqreturn_t cx18_irq_handler(int irq, void *dev_id);
+#endif
void cx18_irq_work_handler(struct work_struct *work);
void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock);
diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c
index df99070e6..a4886bc6c 100644
--- a/linux/drivers/media/video/cx18/cx18-streams.c
+++ b/linux/drivers/media/video/cx18/cx18-streams.c
@@ -311,8 +311,10 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
/* Teardown all streams */
for (type = 0; type < CX18_MAX_STREAMS; type++) {
- if (cx->streams[type].dvb.enabled)
+ if (cx->streams[type].dvb.enabled) {
cx18_dvb_unregister(&cx->streams[type]);
+ cx->streams[type].dvb.enabled = false;
+ }
vdev = cx->streams[type].v4l2dev;
diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c
index 3f2191162..835062f5b 100644
--- a/linux/drivers/media/video/cx2341x.c
+++ b/linux/drivers/media/video/cx2341x.c
@@ -78,6 +78,61 @@ const u32 cx2341x_mpeg_ctrls[] = {
};
EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
+static const struct cx2341x_mpeg_params default_params = {
+ /* misc */
+ .capabilities = 0,
+ .port = CX2341X_PORT_MEMORY,
+ .width = 720,
+ .height = 480,
+ .is_50hz = 0,
+
+ /* stream */
+ .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+ .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
+ .stream_insert_nav_packets = 0,
+
+ /* audio */
+ .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+ .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
+ .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
+ .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
+ .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
+ .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
+ .audio_mute = 0,
+
+ /* video */
+ .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+ .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
+ .video_b_frames = 2,
+ .video_gop_size = 12,
+ .video_gop_closure = 1,
+ .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .video_bitrate = 6000000,
+ .video_bitrate_peak = 8000000,
+ .video_temporal_decimation = 0,
+ .video_mute = 0,
+ .video_mute_yuv = 0x008080, /* YCbCr value for black */
+
+ /* encoding filters */
+ .video_spatial_filter_mode =
+ V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+ .video_spatial_filter = 0,
+ .video_luma_spatial_filter_type =
+ V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
+ .video_chroma_spatial_filter_type =
+ V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+ .video_temporal_filter_mode =
+ V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+ .video_temporal_filter = 8,
+ .video_median_filter_type =
+ V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+ .video_luma_median_filter_top = 255,
+ .video_luma_median_filter_bottom = 0,
+ .video_chroma_median_filter_top = 255,
+ .video_chroma_median_filter_bottom = 0,
+};
+
/* Map the control ID to the correct field in the cx2341x_mpeg_params
struct. Return -EINVAL if the ID is unknown, else return 0. */
@@ -431,13 +486,13 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+ default_params.audio_encoding);
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_L2_BITRATE_192K,
V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
- V4L2_MPEG_AUDIO_L2_BITRATE_224K);
+ default_params.audio_l2_bitrate);
case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
@@ -480,17 +535,22 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return cx2341x_ctrl_query_fill(qctrl,
V4L2_MPEG_STREAM_VBI_FMT_NONE,
V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
- V4L2_MPEG_STREAM_VBI_FMT_NONE);
+ default_params.stream_vbi_fmt);
+
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
+ params->is_50hz ? 12 : 15);
/* CX23415/6 specific */
case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
return cx2341x_ctrl_query_fill(qctrl,
V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
+ default_params.video_spatial_filter_mode);
case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
- cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
+ cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
+ default_params.video_spatial_filter);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
if (params->video_spatial_filter_mode ==
V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
@@ -502,7 +562,7 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
1,
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
+ default_params.video_luma_spatial_filter_type);
if (params->video_spatial_filter_mode ==
V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
@@ -513,7 +573,7 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
1,
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
+ default_params.video_chroma_spatial_filter_type);
if (params->video_spatial_filter_mode ==
V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
@@ -523,10 +583,11 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return cx2341x_ctrl_query_fill(qctrl,
V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
+ default_params.video_temporal_filter_mode);
case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
- cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
+ cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
+ default_params.video_temporal_filter);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
if (params->video_temporal_filter_mode ==
V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
@@ -537,10 +598,11 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return cx2341x_ctrl_query_fill(qctrl,
V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
+ default_params.video_median_filter_type);
case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+ cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+ default_params.video_luma_median_filter_top);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
if (params->video_median_filter_type ==
V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -548,7 +610,8 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+ cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+ default_params.video_luma_median_filter_bottom);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
if (params->video_median_filter_type ==
V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -556,7 +619,8 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+ cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+ default_params.video_chroma_median_filter_top);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
if (params->video_median_filter_type ==
V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -564,7 +628,8 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return 0;
case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
- cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+ cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+ default_params.video_chroma_median_filter_bottom);
qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
if (params->video_median_filter_type ==
V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -572,7 +637,8 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
return 0;
case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
- return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+ return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
+ default_params.stream_insert_nav_packets);
default:
return v4l2_ctrl_query_fill_std(qctrl);
@@ -726,61 +792,6 @@ EXPORT_SYMBOL(cx2341x_ext_ctrls);
void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
{
- static struct cx2341x_mpeg_params default_params = {
- /* misc */
- .capabilities = 0,
- .port = CX2341X_PORT_MEMORY,
- .width = 720,
- .height = 480,
- .is_50hz = 0,
-
- /* stream */
- .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
- .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
- .stream_insert_nav_packets = 0,
-
- /* audio */
- .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
- .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
- .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
- .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
- .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
- .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
- .audio_mute = 0,
-
- /* video */
- .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
- .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
- .video_b_frames = 2,
- .video_gop_size = 12,
- .video_gop_closure = 1,
- .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
- .video_bitrate = 6000000,
- .video_bitrate_peak = 8000000,
- .video_temporal_decimation = 0,
- .video_mute = 0,
- .video_mute_yuv = 0x008080, /* YCbCr value for black */
-
- /* encoding filters */
- .video_spatial_filter_mode =
- V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
- .video_spatial_filter = 0,
- .video_luma_spatial_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
- .video_chroma_spatial_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
- .video_temporal_filter_mode =
- V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
- .video_temporal_filter = 8,
- .video_median_filter_type =
- V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
- .video_luma_median_filter_top = 255,
- .video_luma_median_filter_bottom = 0,
- .video_chroma_median_filter_top = 255,
- .video_chroma_median_filter_bottom = 0,
- };
-
*p = default_params;
cx2341x_calc_audio_properties(p);
}
diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig
index 04e9640c2..5cfb46bbd 100644
--- a/linux/drivers/media/video/cx23885/Kconfig
+++ b/linux/drivers/media/video/cx23885/Kconfig
@@ -9,6 +9,7 @@ config VIDEO_CX23885
select VIDEO_TVEEPROM
select VIDEO_IR
select VIDEOBUF_DVB
+ select VIDEOBUF_DMA_SG
select VIDEO_CX25840
select VIDEO_CX2341X
select DVB_DIB7000P if !DVB_FE_CUSTOMISE
diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c
index a43ed390a..ecd498c70 100644
--- a/linux/drivers/media/video/cx25840/cx25840-core.c
+++ b/linux/drivers/media/video/cx25840/cx25840-core.c
@@ -248,7 +248,7 @@ static void cx25840_initialize(struct i2c_client *client)
cx25840_write(client, 0x8d3, 0x1f);
cx25840_write(client, 0x8e3, 0x03);
- cx25840_vbi_setup(client);
+ cx25840_std_setup(client);
/* trial and error says these are needed to get audio */
cx25840_write(client, 0x914, 0xa0);
@@ -356,7 +356,7 @@ static void cx23885_initialize(struct i2c_client *client)
finish_wait(&state->fw_wait, &wait);
destroy_workqueue(q);
- cx25840_vbi_setup(client);
+ cx25840_std_setup(client);
/* (re)set input */
set_input(client, state->vid_input, state->aud_input);
@@ -367,6 +367,153 @@ static void cx23885_initialize(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
+void cx25840_std_setup(struct i2c_client *client)
+{
+ struct cx25840_state *state = i2c_get_clientdata(client);
+ v4l2_std_id std = state->std;
+ int hblank, hactive, burst, vblank, vactive, sc;
+ int vblank656, src_decimation;
+ int luma_lpf, uv_lpf, comb;
+ u32 pll_int, pll_frac, pll_post;
+
+ /* datasheet startup, step 8d */
+ if (std & ~V4L2_STD_NTSC)
+ cx25840_write(client, 0x49f, 0x11);
+ else
+ cx25840_write(client, 0x49f, 0x14);
+
+ if (std & V4L2_STD_625_50) {
+ hblank = 132;
+ hactive = 720;
+ burst = 93;
+ vblank = 36;
+ vactive = 580;
+ vblank656 = 40;
+ src_decimation = 0x21f;
+ luma_lpf = 2;
+
+ if (std & V4L2_STD_SECAM) {
+ uv_lpf = 0;
+ comb = 0;
+ sc = 0x0a425f;
+ } else if (std == V4L2_STD_PAL_Nc) {
+ uv_lpf = 1;
+ comb = 0x20;
+ sc = 556453;
+ } else {
+ uv_lpf = 1;
+ comb = 0x20;
+ sc = 688739;
+ }
+ } else {
+ hactive = 720;
+ hblank = 122;
+ vactive = 487;
+ luma_lpf = 1;
+ uv_lpf = 1;
+
+ src_decimation = 0x21f;
+ if (std == V4L2_STD_PAL_60) {
+ vblank = 26;
+ vblank656 = 26;
+ burst = 0x5b;
+ luma_lpf = 2;
+ comb = 0x20;
+ sc = 688739;
+ } else if (std == V4L2_STD_PAL_M) {
+ vblank = 20;
+ vblank656 = 24;
+ burst = 0x61;
+ comb = 0x20;
+ sc = 555452;
+ } else {
+ vblank = 26;
+ vblank656 = 26;
+ burst = 0x5b;
+ comb = 0x66;
+ sc = 556063;
+ }
+ }
+
+ /* DEBUG: Displays configured PLL frequency */
+ pll_int = cx25840_read(client, 0x108);
+ pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff;
+ pll_post = cx25840_read(client, 0x109);
+ v4l_dbg(1, cx25840_debug, client,
+ "PLL regs = int: %u, frac: %u, post: %u\n",
+ pll_int, pll_frac, pll_post);
+
+ if (pll_post) {
+ int fin, fsc;
+ int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L;
+
+ pll /= pll_post;
+ v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
+ pll / 1000000, pll % 1000000);
+ v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
+ pll / 8000000, (pll / 8) % 1000000);
+
+ fin = ((u64)src_decimation * pll) >> 12;
+ v4l_dbg(1, cx25840_debug, client,
+ "ADC Sampling freq = %d.%06d MHz\n",
+ fin / 1000000, fin % 1000000);
+
+ fsc = (((u64)sc) * pll) >> 24L;
+ v4l_dbg(1, cx25840_debug, client,
+ "Chroma sub-carrier freq = %d.%06d MHz\n",
+ fsc / 1000000, fsc % 1000000);
+
+ v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
+ "vblank %i, vactive %i, vblank656 %i, src_dec %i, "
+ "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, "
+ "sc 0x%06x\n",
+ hblank, hactive, vblank, vactive, vblank656,
+ src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+ }
+
+ /* Sets horizontal blanking delay and active lines */
+ cx25840_write(client, 0x470, hblank);
+ cx25840_write(client, 0x471,
+ 0xff & (((hblank >> 8) & 0x3) | (hactive << 4)));
+ cx25840_write(client, 0x472, hactive >> 4);
+
+ /* Sets burst gate delay */
+ cx25840_write(client, 0x473, burst);
+
+ /* Sets vertical blanking delay and active duration */
+ cx25840_write(client, 0x474, vblank);
+ cx25840_write(client, 0x475,
+ 0xff & (((vblank >> 8) & 0x3) | (vactive << 4)));
+ cx25840_write(client, 0x476, vactive >> 4);
+ cx25840_write(client, 0x477, vblank656);
+
+ /* Sets src decimation rate */
+ cx25840_write(client, 0x478, 0xff & src_decimation);
+ cx25840_write(client, 0x479, 0xff & (src_decimation >> 8));
+
+ /* Sets Luma and UV Low pass filters */
+ cx25840_write(client, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
+
+ /* Enables comb filters */
+ cx25840_write(client, 0x47b, comb);
+
+ /* Sets SC Step*/
+ cx25840_write(client, 0x47c, sc);
+ cx25840_write(client, 0x47d, 0xff & sc >> 8);
+ cx25840_write(client, 0x47e, 0xff & sc >> 16);
+
+ /* Sets VBI parameters */
+ if (std & V4L2_STD_625_50) {
+ cx25840_write(client, 0x47f, 0x01);
+ state->vbi_line_offset = 5;
+ } else {
+ cx25840_write(client, 0x47f, 0x00);
+ state->vbi_line_offset = 8;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
static void input_change(struct i2c_client *client)
{
struct cx25840_state *state = i2c_get_clientdata(client);
@@ -584,7 +731,7 @@ static int set_v4lstd(struct i2c_client *client)
}
cx25840_and_or(client, 0x400, ~0xf, fmt);
cx25840_and_or(client, 0x403, ~0x3, pal_m);
- cx25840_vbi_setup(client);
+ cx25840_std_setup(client);
if (!state->is_cx25836)
input_change(client);
return 0;
@@ -1076,6 +1223,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
switch (qc->id) {
case V4L2_CID_AUDIO_VOLUME:
+ return v4l2_ctrl_query_fill(qc, 0, 65535,
+ 65535 / 100, state->default_volume);
case V4L2_CID_AUDIO_MUTE:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_BASS:
@@ -1283,6 +1432,8 @@ static int cx25840_probe(struct i2c_client *client,
state->pvr150_workaround = 0;
state->audmode = V4L2_TUNER_MODE_LANG1;
state->unmute_volume = -1;
+ state->default_volume = 228 - cx25840_read(client, 0x8d4);
+ state->default_volume = ((state->default_volume / 2) + 23) << 9;
state->vbi_line_offset = 8;
state->id = id;
state->rev = device_id;
diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h
index df6d8bcc1..f81a9a959 100644
--- a/linux/drivers/media/video/cx25840/cx25840-core.h
+++ b/linux/drivers/media/video/cx25840/cx25840-core.h
@@ -45,6 +45,7 @@ struct cx25840_state {
u32 audclk_freq;
int audmode;
int unmute_volume; /* -1 if not muted */
+ int default_volume;
int vbi_line_offset;
u32 id;
u32 rev;
@@ -62,6 +63,7 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
u8 cx25840_read(struct i2c_client *client, u16 addr);
u32 cx25840_read4(struct i2c_client *client, u16 addr);
int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
+void cx25840_std_setup(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
/* cx25850-firmware.c */
@@ -74,7 +76,6 @@ void cx25840_audio_set_path(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
/* cx25850-vbi.c */
-void cx25840_vbi_setup(struct i2c_client *client);
int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg);
#endif
diff --git a/linux/drivers/media/video/cx25840/cx25840-vbi.c b/linux/drivers/media/video/cx25840/cx25840-vbi.c
index 2d8364e65..08e293ee3 100644
--- a/linux/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/linux/drivers/media/video/cx25840/cx25840-vbi.c
@@ -83,150 +83,6 @@ static int decode_vps(u8 * dst, u8 * p)
return err & 0xf0;
}
-void cx25840_vbi_setup(struct i2c_client *client)
-{
- struct cx25840_state *state = i2c_get_clientdata(client);
- v4l2_std_id std = state->std;
- int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
- int luma_lpf,uv_lpf, comb;
- u32 pll_int,pll_frac,pll_post;
-
- /* datasheet startup, step 8d */
- if (std & ~V4L2_STD_NTSC) {
- cx25840_write(client, 0x49f, 0x11);
- } else {
- cx25840_write(client, 0x49f, 0x14);
- }
-
- if (std & V4L2_STD_625_50) {
- hblank=0x084;
- hactive=0x2d0;
- burst=0x5d;
- vblank=0x024;
- vactive=0x244;
- vblank656=0x28;
- src_decimation=0x21f;
-
- luma_lpf=2;
- if (std & V4L2_STD_SECAM) {
- uv_lpf=0;
- comb=0;
- sc=0x0a425f;
- } else if (std == V4L2_STD_PAL_Nc) {
- uv_lpf=1;
- comb=0x20;
- sc=556453;
- } else {
- uv_lpf=1;
- comb=0x20;
- sc=0x0a8263;
- }
- } else {
- hactive=720;
- hblank=122;
- vactive=487;
- luma_lpf=1;
- uv_lpf=1;
-
- src_decimation=0x21f;
- if (std == V4L2_STD_PAL_60) {
- vblank=26;
- vblank656=26;
- burst=0x5b;
- luma_lpf=2;
- comb=0x20;
- sc=0x0a8263;
- } else if (std == V4L2_STD_PAL_M) {
- vblank=20;
- vblank656=24;
- burst=0x61;
- comb=0x20;
-
- sc=555452;
- } else {
- vblank=26;
- vblank656=26;
- burst=0x5b;
- comb=0x66;
- sc=556063;
- }
- }
-
- /* DEBUG: Displays configured PLL frequency */
- pll_int=cx25840_read(client, 0x108);
- pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff;
- pll_post=cx25840_read(client, 0x109);
- v4l_dbg(1, cx25840_debug, client,
- "PLL regs = int: %u, frac: %u, post: %u\n",
- pll_int,pll_frac,pll_post);
-
- if (pll_post) {
- int fin, fsc;
- int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L;
-
- pll/=pll_post;
- v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
- pll/1000000, pll%1000000);
- v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
- pll/8000000, (pll/8)%1000000);
-
- fin=((u64)src_decimation*pll)>>12;
- v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = "
- "%d.%06d MHz\n",
- fin/1000000,fin%1000000);
-
- fsc= (((u64)sc)*pll) >> 24L;
- v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = "
- "%d.%06d MHz\n",
- fsc/1000000,fsc%1000000);
-
- v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
- "vblank %i, vactive %i, vblank656 %i, src_dec %i, "
- "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
- " sc 0x%06x\n",
- hblank, hactive, vblank, vactive, vblank656,
- src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
- }
-
- /* Sets horizontal blanking delay and active lines */
- cx25840_write(client, 0x470, hblank);
- cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4)));
- cx25840_write(client, 0x472, hactive>>4);
-
- /* Sets burst gate delay */
- cx25840_write(client, 0x473, burst);
-
- /* Sets vertical blanking delay and active duration */
- cx25840_write(client, 0x474, vblank);
- cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4)));
- cx25840_write(client, 0x476, vactive>>4);
- cx25840_write(client, 0x477, vblank656);
-
- /* Sets src decimation rate */
- cx25840_write(client, 0x478, 0xff&src_decimation);
- cx25840_write(client, 0x479, 0xff&(src_decimation>>8));
-
- /* Sets Luma and UV Low pass filters */
- cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30));
-
- /* Enables comb filters */
- cx25840_write(client, 0x47b, comb);
-
- /* Sets SC Step*/
- cx25840_write(client, 0x47c, sc);
- cx25840_write(client, 0x47d, 0xff&sc>>8);
- cx25840_write(client, 0x47e, 0xff&sc>>16);
-
- /* Sets VBI parameters */
- if (std & V4L2_STD_625_50) {
- cx25840_write(client, 0x47f, 0x01);
- state->vbi_line_offset = 5;
- } else {
- cx25840_write(client, 0x47f, 0x00);
- state->vbi_line_offset = 8;
- }
-}
-
int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct cx25840_state *state = i2c_get_clientdata(client);
@@ -293,8 +149,8 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
/* raw VBI */
memset(svbi, 0, sizeof(*svbi));
- /* Setup VBI */
- cx25840_vbi_setup(client);
+ /* Setup standard */
+ cx25840_std_setup(client);
/* VBI Offset */
cx25840_write(client, 0x47f, vbi_offset);
@@ -305,8 +161,8 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
for (x = 0; x <= 23; x++)
lcr[x] = 0x00;
- /* Setup VBI */
- cx25840_vbi_setup(client);
+ /* Setup standard */
+ cx25840_std_setup(client);
/* Sliced VBI */
cx25840_write(client, 0x404, 0x32); /* Ancillary data */
diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c
index 4efe3f839..72bf5868c 100644
--- a/linux/drivers/media/video/dabusb.c
+++ b/linux/drivers/media/video/dabusb.c
@@ -700,7 +700,11 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm
return ret;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
static const struct file_operations dabusb_fops =
+#else
+static struct file_operations dabusb_fops =
+#endif
{
.owner = THIS_MODULE,
.llseek = no_llseek,
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index 4d65b1be4..697202d47 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -30,7 +30,11 @@
#include <linux/pagemap.h>
#include <linux/io.h>
#include <asm/page.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+#include <asm/uaccess.h>
+#else
#include <linux/uaccess.h>
+#endif
#include <linux/jiffies.h>
#include "gspca.h"
diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c
index fc668f5b5..73fcfddce 100644
--- a/linux/drivers/media/video/ir-kbd-i2c.c
+++ b/linux/drivers/media/video/ir-kbd-i2c.c
@@ -195,88 +195,6 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
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)) {
- dprintk(2,"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;
-
- dprintk(1,"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>
- */
-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);
-}
-
-EXPORT_SYMBOL_GPL(get_key_pinnacle_grey);
-
-
-/* The new pinnacle PCTV remote (with the colored buttons)
- *
- * Ricardo Cerqueira <v4l@cerqueira.org>
- */
-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);
-}
-
-EXPORT_SYMBOL_GPL(get_key_pinnacle_color);
-
/* ----------------------------------------------------------------------- */
static void ir_key_poll(struct IR_i2c *ir)
diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c
index 3446ab458..1488bc7ce 100644
--- a/linux/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c
@@ -135,7 +135,7 @@ static const u8 hw_addrs[] = {
static const char * const hw_devicenames[] = {
"cx25840",
"saa7115",
- "saa7127",
+ "saa7127_auto", /* saa7127 or saa7129 */
"msp3400",
"tuner",
"wm8775",
diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c
index bdfda48e5..bdedff281 100644
--- a/linux/drivers/media/video/ivtv/ivtvfb.c
+++ b/linux/drivers/media/video/ivtv/ivtvfb.c
@@ -367,6 +367,7 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -448,6 +449,7 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
return (err) ? err : count;
}
+#endif
static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
@@ -909,7 +911,9 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
static struct fb_ops ivtvfb_ops = {
.owner = THIS_MODULE,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
.fb_write = ivtvfb_write,
+#endif
.fb_check_var = ivtvfb_check_var,
.fb_set_par = ivtvfb_set_par,
.fb_setcolreg = ivtvfb_setcolreg,
diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c
index 089ce311f..94709f05c 100644
--- a/linux/drivers/media/video/mt9m001.c
+++ b/linux/drivers/media/video/mt9m001.c
@@ -617,8 +617,12 @@ static void mt9m001_video_remove(struct soc_camera_device *icd)
soc_camera_video_stop(&mt9m001->icd);
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
static int mt9m001_probe(struct i2c_client *client,
const struct i2c_device_id *did)
+#else
+static int mt9m001_probe(struct i2c_client *client)
+#endif
{
struct mt9m001 *mt9m001;
struct soc_camera_device *icd;
diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c
index dcf7678a8..9cf1aa2bc 100644
--- a/linux/drivers/media/video/ov7670.c
+++ b/linux/drivers/media/video/ov7670.c
@@ -877,7 +877,7 @@ static int ov7670_store_cmatrix(struct i2c_client *client,
int matrix[CMATRIX_LEN])
{
int i, ret;
- unsigned char signbits;
+ unsigned char signbits = 0;
/*
* Weird crap seems to exist in the upper part of
@@ -1053,7 +1053,7 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
static int ov7670_t_brightness(struct i2c_client *client, int value)
{
- unsigned char com8, v;
+ unsigned char com8 = 0, v;
int ret;
ov7670_read(client, REG_COM8, &com8);
@@ -1066,7 +1066,7 @@ static int ov7670_t_brightness(struct i2c_client *client, int value)
static int ov7670_q_brightness(struct i2c_client *client, __s32 *value)
{
- unsigned char v;
+ unsigned char v = 0;
int ret = ov7670_read(client, REG_BRIGHT, &v);
*value = ov7670_sm_to_abs(v);
@@ -1080,7 +1080,7 @@ static int ov7670_t_contrast(struct i2c_client *client, int value)
static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
{
- unsigned char v;
+ unsigned char v = 0;
int ret = ov7670_read(client, REG_CONTRAS, &v);
*value = v;
@@ -1090,7 +1090,7 @@ static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
{
int ret;
- unsigned char v;
+ unsigned char v = 0;
ret = ov7670_read(client, REG_MVFP, &v);
*value = (v & MVFP_MIRROR) == MVFP_MIRROR;
@@ -1100,7 +1100,7 @@ static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
static int ov7670_t_hflip(struct i2c_client *client, int value)
{
- unsigned char v;
+ unsigned char v = 0;
int ret;
ret = ov7670_read(client, REG_MVFP, &v);
@@ -1118,7 +1118,7 @@ static int ov7670_t_hflip(struct i2c_client *client, int value)
static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
{
int ret;
- unsigned char v;
+ unsigned char v = 0;
ret = ov7670_read(client, REG_MVFP, &v);
*value = (v & MVFP_FLIP) == MVFP_FLIP;
@@ -1128,7 +1128,7 @@ static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
static int ov7670_t_vflip(struct i2c_client *client, int value)
{
- unsigned char v;
+ unsigned char v = 0;
int ret;
ret = ov7670_read(client, REG_MVFP, &v);
diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c
index 5ec5bb9a9..b15f82c49 100644
--- a/linux/drivers/media/video/pxa_camera.c
+++ b/linux/drivers/media/video/pxa_camera.c
@@ -30,6 +30,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
+#include <media/videobuf-dma-sg.h>
#include <media/soc_camera.h>
#include <linux/videodev2.h>
@@ -582,6 +583,19 @@ static struct videobuf_queue_ops pxa_videobuf_ops = {
.buf_release = pxa_videobuf_release,
};
+static void pxa_camera_init_videobuf(struct videobuf_queue *q,
+ struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct pxa_camera_dev *pcdev = ici->priv;
+
+ /* We must pass NULL as dev pointer, then all pci_* dma operations
+ * transform to normal dma_* ones. */
+ videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
+ sizeof(struct pxa_buffer), icd);
+}
+
static int mclk_get_divisor(struct pxa_camera_dev *pcdev)
{
unsigned int mclk_10khz = pcdev->platform_mclk_10khz;
@@ -983,34 +997,23 @@ static int pxa_camera_querycap(struct soc_camera_host *ici,
return 0;
}
-static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
-{
- struct soc_camera_host *ici =
- to_soc_camera_host(icf->icd->dev.parent);
- struct pxa_camera_dev *pcdev = ici->priv;
-
- return &pcdev->lock;
-}
-
static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
.owner = THIS_MODULE,
.add = pxa_camera_add_device,
.remove = pxa_camera_remove_device,
.set_fmt_cap = pxa_camera_set_fmt_cap,
.try_fmt_cap = pxa_camera_try_fmt_cap,
+ .init_videobuf = pxa_camera_init_videobuf,
.reqbufs = pxa_camera_reqbufs,
.poll = pxa_camera_poll,
.querycap = pxa_camera_querycap,
.try_bus_param = pxa_camera_try_bus_param,
.set_bus_param = pxa_camera_set_bus_param,
- .spinlock_alloc = pxa_camera_spinlock_alloc,
};
/* Should be allocated dynamically too, but we have only one. */
static struct soc_camera_host pxa_soc_camera_host = {
.drv_name = PXA_CAM_DRV_NAME,
- .vbq_ops = &pxa_videobuf_ops,
- .msize = sizeof(struct pxa_buffer),
.ops = &pxa_soc_camera_host_ops,
};
diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c
index 5d99f8455..5488679ed 100644
--- a/linux/drivers/media/video/saa7115.c
+++ b/linux/drivers/media/video/saa7115.c
@@ -1567,7 +1567,7 @@ static int saa7115_remove(struct i2c_client *client)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
static const struct i2c_device_id saa7115_id[] = {
- { "saa711x", 1 }, /* autodetect */
+ { "saa7115_auto", 1 }, /* autodetect */
{ "saa7111", 0 },
{ "saa7113", 0 },
{ "saa7114", 0 },
diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c
index 28905adfb..0b126a849 100644
--- a/linux/drivers/media/video/saa7127.c
+++ b/linux/drivers/media/video/saa7127.c
@@ -672,7 +672,6 @@ static int saa7127_probe(struct i2c_client *client,
{
struct saa7127_state *state;
struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */
- int read_result = 0;
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -720,20 +719,33 @@ static int saa7127_probe(struct i2c_client *client,
saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL);
saa7127_set_video_enable(client, 1);
- /* Detect if it's an saa7129 */
- read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2);
- saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa);
- if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
- v4l_info(client, "saa7129 found @ 0x%x (%s)\n",
- client->addr << 1, client->adapter->name);
- saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result);
- saa7127_write_inittab(client, saa7129_init_config_extra);
- state->ident = V4L2_IDENT_SAA7129;
- } else {
- v4l_info(client, "saa7127 found @ 0x%x (%s)\n",
- client->addr << 1, client->adapter->name);
- state->ident = V4L2_IDENT_SAA7127;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ if (id->driver_data) { /* Chip type is already known */
+ state->ident = id->driver_data;
+ } else { /* Needs detection */
+#else
+ {
+#endif
+ int read_result;
+
+ /* Detect if it's an saa7129 */
+ read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2);
+ saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa);
+ if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
+ saa7127_write(client, SAA7129_REG_FADE_KEY_COL2,
+ read_result);
+ state->ident = V4L2_IDENT_SAA7129;
+ strlcpy(client->name, "saa7129", I2C_NAME_SIZE);
+ } else {
+ state->ident = V4L2_IDENT_SAA7127;
+ strlcpy(client->name, "saa7127", I2C_NAME_SIZE);
+ }
}
+
+ v4l_info(client, "%s found @ 0x%x (%s)\n", client->name,
+ client->addr << 1, client->adapter->name);
+ if (state->ident == V4L2_IDENT_SAA7129)
+ saa7127_write_inittab(client, saa7129_init_config_extra);
return 0;
}
@@ -751,7 +763,11 @@ static int saa7127_remove(struct i2c_client *client)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
static struct i2c_device_id saa7127_id[] = {
- { "saa7127", 0 },
+ { "saa7127_auto", 0 }, /* auto-detection */
+ { "saa7126", V4L2_IDENT_SAA7127 },
+ { "saa7127", V4L2_IDENT_SAA7127 },
+ { "saa7128", V4L2_IDENT_SAA7129 },
+ { "saa7129", V4L2_IDENT_SAA7129 },
{ }
};
MODULE_DEVICE_TABLE(i2c, saa7127_id);
diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
index 08597a558..8ec09c97e 100644
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c
@@ -6078,9 +6078,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
i2c_transfer(&dev->i2c_adap, &msg, 1);
break;
}
-#if 0
- /* FIXME: This entry doesn't exist yet */
- case SAA7134_BOARD_ASUSTeK_TVFM35:
+ case SAA7134_BOARD_ASUSTeK_TVFM7135:
/* The card below is detected as card=53, but is different */
if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
@@ -6089,7 +6087,6 @@ int saa7134_board_init2(struct saa7134_dev *dev)
dev->name, saa7134_boards[dev->board].name);
}
break;
-#endif
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
hauppauge_eeprom(dev, dev->eedata+0x80);
/* break intentionally omitted */
diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c
index 89fc7dfc2..f26fd7061 100644
--- a/linux/drivers/media/video/saa7134/saa7134-input.c
+++ b/linux/drivers/media/video/saa7134/saa7134-input.c
@@ -198,6 +198,84 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
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;
diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c
new file mode 100644
index 000000000..012005e1a
--- /dev/null
+++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c
@@ -0,0 +1,657 @@
+/*
+ * V4L2 Driver for SuperH Mobile CEU interface
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * Based on V4L2 Driver for PXA camera host - "pxa_camera.c",
+ *
+ * Copyright (C) 2006, Sascha Hauer, Pengutronix
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/soc_camera.h>
+#include <media/sh_mobile_ceu.h>
+#include <media/videobuf-dma-contig.h>
+
+/* register offsets for sh7722 / sh7723 */
+
+#define CAPSR 0x00
+#define CAPCR 0x04
+#define CAMCR 0x08
+#define CMCYR 0x0c
+#define CAMOR 0x10
+#define CAPWR 0x14
+#define CAIFR 0x18
+#define CSTCR 0x20 /* not on sh7723 */
+#define CSECR 0x24 /* not on sh7723 */
+#define CRCNTR 0x28
+#define CRCMPR 0x2c
+#define CFLCR 0x30
+#define CFSZR 0x34
+#define CDWDR 0x38
+#define CDAYR 0x3c
+#define CDACR 0x40
+#define CDBYR 0x44
+#define CDBCR 0x48
+#define CBDSR 0x4c
+#define CFWCR 0x5c
+#define CLFCR 0x60
+#define CDOCR 0x64
+#define CDDCR 0x68
+#define CDDAR 0x6c
+#define CEIER 0x70
+#define CETCR 0x74
+#define CSTSR 0x7c
+#define CSRTR 0x80
+#define CDSSR 0x84
+#define CDAYR2 0x90
+#define CDACR2 0x94
+#define CDBYR2 0x98
+#define CDBCR2 0x9c
+
+static DEFINE_MUTEX(camera_lock);
+
+/* per video frame buffer */
+struct sh_mobile_ceu_buffer {
+ struct videobuf_buffer vb; /* v4l buffer must be first */
+ const struct soc_camera_data_format *fmt;
+};
+
+struct sh_mobile_ceu_dev {
+ struct device *dev;
+ struct soc_camera_host ici;
+ struct soc_camera_device *icd;
+
+ unsigned int irq;
+ void __iomem *base;
+ unsigned long video_limit;
+
+ spinlock_t lock;
+ struct list_head capture;
+ struct videobuf_buffer *active;
+
+ struct sh_mobile_ceu_info *pdata;
+};
+
+static void ceu_write(struct sh_mobile_ceu_dev *priv,
+ unsigned long reg_offs, unsigned long data)
+{
+ iowrite32(data, priv->base + reg_offs);
+}
+
+static unsigned long ceu_read(struct sh_mobile_ceu_dev *priv,
+ unsigned long reg_offs)
+{
+ return ioread32(priv->base + reg_offs);
+}
+
+/*
+ * Videobuf operations
+ */
+static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq,
+ unsigned int *count,
+ unsigned int *size)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3;
+
+ *size = PAGE_ALIGN(icd->width * icd->height * bytes_per_pixel);
+
+ if (0 == *count)
+ *count = 2;
+
+ if (pcdev->video_limit) {
+ while (*size * *count > pcdev->video_limit)
+ (*count)--;
+ }
+
+ dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
+
+ return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq,
+ struct sh_mobile_ceu_buffer *buf)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
+ &buf->vb, buf->vb.baddr, buf->vb.bsize);
+
+ if (in_interrupt())
+ BUG();
+
+ videobuf_dma_contig_free(vq, &buf->vb);
+ dev_dbg(&icd->dev, "%s freed\n", __func__);
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
+{
+ ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~1);
+ ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & 0x0317f313);
+ ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | 1);
+
+ ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~0x10000);
+
+ ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10);
+
+ if (pcdev->active) {
+ ceu_write(pcdev, CDAYR, videobuf_to_dma_contig(pcdev->active));
+ ceu_write(pcdev, CAPSR, 0x1); /* start capture */
+ }
+}
+
+static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ struct sh_mobile_ceu_buffer *buf;
+ int ret;
+
+ buf = container_of(vb, struct sh_mobile_ceu_buffer, vb);
+
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ /* Added list head initialization on alloc */
+ WARN_ON(!list_empty(&vb->queue));
+
+#ifdef DEBUG
+ /* This can be useful if you want to see if we actually fill
+ * the buffer with something */
+ memset((void *)vb->baddr, 0xaa, vb->bsize);
+#endif
+
+ BUG_ON(NULL == icd->current_fmt);
+
+ if (buf->fmt != icd->current_fmt ||
+ vb->width != icd->width ||
+ vb->height != icd->height ||
+ vb->field != field) {
+ buf->fmt = icd->current_fmt;
+ vb->width = icd->width;
+ vb->height = icd->height;
+ vb->field = field;
+ vb->state = VIDEOBUF_NEEDS_INIT;
+ }
+
+ vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
+ if (0 != vb->baddr && vb->bsize < vb->size) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
+ ret = videobuf_iolock(vq, vb, NULL);
+ if (ret)
+ goto fail;
+ vb->state = VIDEOBUF_PREPARED;
+ }
+
+ return 0;
+fail:
+ free_buffer(vq, buf);
+out:
+ return ret;
+}
+
+static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ unsigned long flags;
+
+ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
+ vb, vb->baddr, vb->bsize);
+
+ vb->state = VIDEOBUF_ACTIVE;
+ spin_lock_irqsave(&pcdev->lock, flags);
+ list_add_tail(&vb->queue, &pcdev->capture);
+
+ if (!pcdev->active) {
+ pcdev->active = vb;
+ sh_mobile_ceu_capture(pcdev);
+ }
+
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+}
+
+static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb));
+}
+
+static struct videobuf_queue_ops sh_mobile_ceu_videobuf_ops = {
+ .buf_setup = sh_mobile_ceu_videobuf_setup,
+ .buf_prepare = sh_mobile_ceu_videobuf_prepare,
+ .buf_queue = sh_mobile_ceu_videobuf_queue,
+ .buf_release = sh_mobile_ceu_videobuf_release,
+};
+
+static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
+{
+ struct sh_mobile_ceu_dev *pcdev = data;
+ struct videobuf_buffer *vb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcdev->lock, flags);
+
+ vb = pcdev->active;
+ list_del_init(&vb->queue);
+
+ if (!list_empty(&pcdev->capture))
+ pcdev->active = list_entry(pcdev->capture.next,
+ struct videobuf_buffer, queue);
+ else
+ pcdev->active = NULL;
+
+ sh_mobile_ceu_capture(pcdev);
+
+ vb->state = VIDEOBUF_DONE;
+ do_gettimeofday(&vb->ts);
+ vb->field_count++;
+ wake_up(&vb->done);
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ int ret = -EBUSY;
+
+ mutex_lock(&camera_lock);
+
+ if (pcdev->icd)
+ goto err;
+
+ dev_info(&icd->dev,
+ "SuperH Mobile CEU driver attached to camera %d\n",
+ icd->devnum);
+
+ if (pcdev->pdata->enable_camera)
+ pcdev->pdata->enable_camera();
+
+ ret = icd->ops->init(icd);
+ if (ret)
+ goto err;
+
+ ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
+ while (ceu_read(pcdev, CSTSR) & 1)
+ msleep(1);
+
+ pcdev->icd = icd;
+err:
+ mutex_unlock(&camera_lock);
+
+ return ret;
+}
+
+static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+
+ BUG_ON(icd != pcdev->icd);
+
+ /* disable capture, disable interrupts */
+ ceu_write(pcdev, CEIER, 0);
+ ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
+ icd->ops->release(icd);
+ if (pcdev->pdata->disable_camera)
+ pcdev->pdata->disable_camera();
+
+ dev_info(&icd->dev,
+ "SuperH Mobile CEU driver detached from camera %d\n",
+ icd->devnum);
+
+ pcdev->icd = NULL;
+}
+
+static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
+ __u32 pixfmt)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ int ret, buswidth, width, cfszr_width, cdwdr_width;
+ unsigned long camera_flags, common_flags, value;
+
+ camera_flags = icd->ops->query_bus_param(icd);
+ common_flags = soc_camera_bus_param_compatible(camera_flags,
+ pcdev->pdata->flags);
+ if (!common_flags)
+ return -EINVAL;
+
+ ret = icd->ops->set_bus_param(icd, common_flags);
+ if (ret < 0)
+ return ret;
+
+ switch (common_flags & SOCAM_DATAWIDTH_MASK) {
+ case SOCAM_DATAWIDTH_8:
+ buswidth = 8;
+ break;
+ case SOCAM_DATAWIDTH_16:
+ buswidth = 16;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ceu_write(pcdev, CRCNTR, 0);
+ ceu_write(pcdev, CRCMPR, 0);
+
+ value = 0x00000010;
+ value |= (common_flags & SOCAM_VSYNC_ACTIVE_LOW) ? (1 << 1) : 0;
+ value |= (common_flags & SOCAM_HSYNC_ACTIVE_LOW) ? (1 << 0) : 0;
+ value |= (buswidth == 16) ? (1 << 12) : 0;
+ ceu_write(pcdev, CAMCR, value);
+
+ ceu_write(pcdev, CAPCR, 0x00300000);
+ ceu_write(pcdev, CAIFR, 0);
+
+ mdelay(1);
+
+ width = icd->width * (icd->current_fmt->depth / 8);
+ width = (buswidth == 16) ? width / 2 : width;
+ cfszr_width = (buswidth == 8) ? width / 2 : width;
+ cdwdr_width = (buswidth == 16) ? width * 2 : width;
+
+ ceu_write(pcdev, CAMOR, 0);
+ ceu_write(pcdev, CAPWR, (icd->height << 16) | width);
+ ceu_write(pcdev, CFLCR, 0); /* data fetch mode - no scaling */
+ ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width);
+ ceu_write(pcdev, CLFCR, 0); /* data fetch mode - no lowpass filter */
+ ceu_write(pcdev, CDOCR, 0x00000016);
+
+ ceu_write(pcdev, CDWDR, cdwdr_width);
+ ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
+
+ /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */
+ /* in data fetch mode: no need for CDACR, CDBYR, CDBCR */
+
+ return 0;
+}
+
+static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd,
+ __u32 pixfmt)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ unsigned long camera_flags, common_flags;
+
+ camera_flags = icd->ops->query_bus_param(icd);
+ common_flags = soc_camera_bus_param_compatible(camera_flags,
+ pcdev->pdata->flags);
+ if (!common_flags)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd,
+ __u32 pixfmt, struct v4l2_rect *rect)
+{
+ return icd->ops->set_fmt_cap(icd, pixfmt, rect);
+}
+
+static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ /* FIXME: calculate using depth and bus width */
+
+ if (f->fmt.pix.height < 4)
+ f->fmt.pix.height = 4;
+ if (f->fmt.pix.height > 1920)
+ f->fmt.pix.height = 1920;
+ if (f->fmt.pix.width < 2)
+ f->fmt.pix.width = 2;
+ if (f->fmt.pix.width > 2560)
+ f->fmt.pix.width = 2560;
+ f->fmt.pix.width &= ~0x01;
+ f->fmt.pix.height &= ~0x03;
+
+ /* limit to sensor capabilities */
+ return icd->ops->try_fmt_cap(icd, f);
+}
+
+static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf,
+ struct v4l2_requestbuffers *p)
+{
+ int i;
+
+ /* This is for locking debugging only. I removed spinlocks and now I
+ * check whether .prepare is ever called on a linked buffer, or whether
+ * a dma IRQ can occur for an in-work or unlinked buffer. Until now
+ * it hadn't triggered */
+ for (i = 0; i < p->count; i++) {
+ struct sh_mobile_ceu_buffer *buf;
+
+ buf = container_of(icf->vb_vidq.bufs[i],
+ struct sh_mobile_ceu_buffer, vb);
+ INIT_LIST_HEAD(&buf->vb.queue);
+ }
+
+ return 0;
+}
+
+static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt)
+{
+ struct soc_camera_file *icf = file->private_data;
+ struct sh_mobile_ceu_buffer *buf;
+
+ buf = list_entry(icf->vb_vidq.stream.next,
+ struct sh_mobile_ceu_buffer, vb.stream);
+
+ poll_wait(file, &buf->vb.done, pt);
+
+ if (buf->vb.state == VIDEOBUF_DONE ||
+ buf->vb.state == VIDEOBUF_ERROR)
+ return POLLIN|POLLRDNORM;
+
+ return 0;
+}
+
+static int sh_mobile_ceu_querycap(struct soc_camera_host *ici,
+ struct v4l2_capability *cap)
+{
+ strlcpy(cap->card, "SuperH_Mobile_CEU", sizeof(cap->card));
+ cap->version = KERNEL_VERSION(0, 0, 5);
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ return 0;
+}
+
+static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
+ struct soc_camera_device *icd)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+
+ videobuf_queue_dma_contig_init(q,
+ &sh_mobile_ceu_videobuf_ops,
+ &ici->dev, &pcdev->lock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_NONE,
+ sizeof(struct sh_mobile_ceu_buffer),
+ icd);
+}
+
+static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
+ .owner = THIS_MODULE,
+ .add = sh_mobile_ceu_add_device,
+ .remove = sh_mobile_ceu_remove_device,
+ .set_fmt_cap = sh_mobile_ceu_set_fmt_cap,
+ .try_fmt_cap = sh_mobile_ceu_try_fmt_cap,
+ .reqbufs = sh_mobile_ceu_reqbufs,
+ .poll = sh_mobile_ceu_poll,
+ .querycap = sh_mobile_ceu_querycap,
+ .try_bus_param = sh_mobile_ceu_try_bus_param,
+ .set_bus_param = sh_mobile_ceu_set_bus_param,
+ .init_videobuf = sh_mobile_ceu_init_videobuf,
+};
+
+static int sh_mobile_ceu_probe(struct platform_device *pdev)
+{
+ struct sh_mobile_ceu_dev *pcdev;
+ struct resource *res;
+ void __iomem *base;
+ unsigned int irq;
+ int err = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (!res || !irq) {
+ dev_err(&pdev->dev, "Not enough CEU platform resources.\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+ pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
+ if (!pcdev) {
+ dev_err(&pdev->dev, "Could not allocate pcdev\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ platform_set_drvdata(pdev, pcdev);
+ INIT_LIST_HEAD(&pcdev->capture);
+ spin_lock_init(&pcdev->lock);
+
+ pcdev->pdata = pdev->dev.platform_data;
+ if (!pcdev->pdata) {
+ err = -EINVAL;
+ dev_err(&pdev->dev, "CEU platform data not set.\n");
+ goto exit_kfree;
+ }
+
+ base = ioremap_nocache(res->start, res->end - res->start + 1);
+ if (!base) {
+ err = -ENXIO;
+ dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n");
+ goto exit_kfree;
+ }
+
+ pcdev->irq = irq;
+ pcdev->base = base;
+ pcdev->video_limit = 0; /* only enabled if second resource exists */
+ pcdev->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+ err = dma_declare_coherent_memory(&pdev->dev, res->start,
+ res->start,
+ (res->end - res->start) + 1,
+ DMA_MEMORY_MAP |
+ DMA_MEMORY_EXCLUSIVE);
+ if (!err) {
+ dev_err(&pdev->dev, "Unable to declare CEU memory.\n");
+ err = -ENXIO;
+ goto exit_iounmap;
+ }
+
+ pcdev->video_limit = (res->end - res->start) + 1;
+ }
+
+ /* request irq */
+ err = request_irq(pcdev->irq, sh_mobile_ceu_irq, IRQF_DISABLED,
+ pdev->dev.bus_id, pcdev);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to register CEU interrupt.\n");
+ goto exit_release_mem;
+ }
+
+ pcdev->ici.priv = pcdev;
+ pcdev->ici.dev.parent = &pdev->dev;
+ pcdev->ici.nr = pdev->id;
+ pcdev->ici.drv_name = pdev->dev.bus_id,
+ pcdev->ici.ops = &sh_mobile_ceu_host_ops,
+
+ err = soc_camera_host_register(&pcdev->ici);
+ if (err)
+ goto exit_free_irq;
+
+ return 0;
+
+exit_free_irq:
+ free_irq(pcdev->irq, pcdev);
+exit_release_mem:
+ if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
+ dma_release_declared_memory(&pdev->dev);
+exit_iounmap:
+ iounmap(base);
+exit_kfree:
+ kfree(pcdev);
+exit:
+ return err;
+}
+
+static int sh_mobile_ceu_remove(struct platform_device *pdev)
+{
+ struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev);
+
+ soc_camera_host_unregister(&pcdev->ici);
+ free_irq(pcdev->irq, pcdev);
+ if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
+ dma_release_declared_memory(&pdev->dev);
+ iounmap(pcdev->base);
+ kfree(pcdev);
+ return 0;
+}
+
+static struct platform_driver sh_mobile_ceu_driver = {
+ .driver = {
+ .name = "sh_mobile_ceu",
+ },
+ .probe = sh_mobile_ceu_probe,
+ .remove = sh_mobile_ceu_remove,
+};
+
+static int __init sh_mobile_ceu_init(void)
+{
+ return platform_driver_register(&sh_mobile_ceu_driver);
+}
+
+static void __exit sh_mobile_ceu_exit(void)
+{
+ return platform_driver_unregister(&sh_mobile_ceu_driver);
+}
+
+module_init(sh_mobile_ceu_init);
+module_exit(sh_mobile_ceu_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile CEU driver");
+MODULE_AUTHOR("Magnus Damm");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c
index 8ae2d9916..e39b98f1e 100644
--- a/linux/drivers/media/video/soc_camera.c
+++ b/linux/drivers/media/video/soc_camera.c
@@ -26,6 +26,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
+#include <media/videobuf-core.h>
#include <media/soc_camera.h>
static LIST_HEAD(hosts);
@@ -182,7 +183,6 @@ static int soc_camera_open(struct inode *inode, struct file *file)
struct soc_camera_device *icd;
struct soc_camera_host *ici;
struct soc_camera_file *icf;
- spinlock_t *lock;
int ret;
icf = vmalloc(sizeof(*icf));
@@ -209,13 +209,6 @@ static int soc_camera_open(struct inode *inode, struct file *file)
}
icf->icd = icd;
-
- icf->lock = ici->ops->spinlock_alloc(icf);
- if (!icf->lock) {
- ret = -ENOMEM;
- goto esla;
- }
-
icd->use_count++;
/* Now we really have to activate the camera */
@@ -233,21 +226,12 @@ static int soc_camera_open(struct inode *inode, struct file *file)
file->private_data = icf;
dev_dbg(&icd->dev, "camera device open\n");
- /* We must pass NULL as dev pointer, then all pci_* dma operations
- * transform to normal dma_* ones. */
- videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
- ici->msize, icd);
+ ici->ops->init_videobuf(&icf->vb_vidq, icd);
return 0;
/* All errors are entered with the video_lock held */
eiciadd:
- lock = icf->lock;
- icf->lock = NULL;
- if (ici->ops->spinlock_free)
- ici->ops->spinlock_free(lock);
-esla:
module_put(ici->ops->owner);
emgi:
module_put(icd->ops->owner);
@@ -263,15 +247,11 @@ static int soc_camera_close(struct inode *inode, struct file *file)
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct video_device *vdev = icd->vdev;
- spinlock_t *lock = icf->lock;
mutex_lock(&video_lock);
icd->use_count--;
if (!icd->use_count)
ici->ops->remove(icd);
- icf->lock = NULL;
- if (ici->ops->spinlock_free)
- ici->ops->spinlock_free(lock);
module_put(icd->ops->owner);
module_put(ici->ops->owner);
mutex_unlock(&video_lock);
@@ -767,27 +747,12 @@ static void dummy_release(struct device *dev)
{
}
-static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
-{
- spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
-
- if (lock)
- spin_lock_init(lock);
-
- return lock;
-}
-
-static void spinlock_free(spinlock_t *lock)
-{
- kfree(lock);
-}
-
int soc_camera_host_register(struct soc_camera_host *ici)
{
int ret;
struct soc_camera_host *ix;
- if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove)
+ if (!ici->ops->init_videobuf || !ici->ops->add || !ici->ops->remove)
return -EINVAL;
/* Number might be equal to the platform device ID */
@@ -811,11 +776,6 @@ int soc_camera_host_register(struct soc_camera_host *ici)
if (ret)
goto edevr;
- if (!ici->ops->spinlock_alloc) {
- ici->ops->spinlock_alloc = spinlock_alloc;
- ici->ops->spinlock_free = spinlock_free;
- }
-
scan_add_host(ici);
return 0;
diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c
new file mode 100644
index 000000000..eefb0327e
--- /dev/null
+++ b/linux/drivers/media/video/soc_camera_platform.c
@@ -0,0 +1,198 @@
+/*
+ * Generic Platform Camera Driver
+ *
+ * Copyright (C) 2008 Magnus Damm
+ * Based on mt9m001 driver,
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/soc_camera.h>
+
+struct soc_camera_platform_info {
+ int iface;
+ char *format_name;
+ unsigned long format_depth;
+ struct v4l2_pix_format format;
+ unsigned long bus_param;
+ int (*set_capture)(struct soc_camera_platform_info *info, int enable);
+};
+
+struct soc_camera_platform_priv {
+ struct soc_camera_platform_info *info;
+ struct soc_camera_device icd;
+ struct soc_camera_data_format format;
+};
+
+static struct soc_camera_platform_info *
+soc_camera_platform_get_info(struct soc_camera_device *icd)
+{
+ struct soc_camera_platform_priv *priv;
+ priv = container_of(icd, struct soc_camera_platform_priv, icd);
+ return priv->info;
+}
+
+static int soc_camera_platform_init(struct soc_camera_device *icd)
+{
+ return 0;
+}
+
+static int soc_camera_platform_release(struct soc_camera_device *icd)
+{
+ return 0;
+}
+
+static int soc_camera_platform_start_capture(struct soc_camera_device *icd)
+{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ return p->set_capture(p, 1);
+}
+
+static int soc_camera_platform_stop_capture(struct soc_camera_device *icd)
+{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ return p->set_capture(p, 0);
+}
+
+static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+ return 0;
+}
+
+static unsigned long
+soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
+{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ return p->bus_param;
+}
+
+static int soc_camera_platform_set_fmt_cap(struct soc_camera_device *icd,
+ __u32 pixfmt, struct v4l2_rect *rect)
+{
+ return 0;
+}
+
+static int soc_camera_platform_try_fmt_cap(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+
+ f->fmt.pix.width = p->format.width;
+ f->fmt.pix.height = p->format.height;
+ return 0;
+}
+
+static int soc_camera_platform_video_probe(struct soc_camera_device *icd)
+{
+ struct soc_camera_platform_priv *priv;
+ priv = container_of(icd, struct soc_camera_platform_priv, icd);
+
+ priv->format.name = priv->info->format_name;
+ priv->format.depth = priv->info->format_depth;
+ priv->format.fourcc = priv->info->format.pixelformat;
+ priv->format.colorspace = priv->info->format.colorspace;
+
+ icd->formats = &priv->format;
+ icd->num_formats = 1;
+
+ return soc_camera_video_start(icd);
+}
+
+static void soc_camera_platform_video_remove(struct soc_camera_device *icd)
+{
+ soc_camera_video_stop(icd);
+}
+
+static struct soc_camera_ops soc_camera_platform_ops = {
+ .owner = THIS_MODULE,
+ .probe = soc_camera_platform_video_probe,
+ .remove = soc_camera_platform_video_remove,
+ .init = soc_camera_platform_init,
+ .release = soc_camera_platform_release,
+ .start_capture = soc_camera_platform_start_capture,
+ .stop_capture = soc_camera_platform_stop_capture,
+ .set_fmt_cap = soc_camera_platform_set_fmt_cap,
+ .try_fmt_cap = soc_camera_platform_try_fmt_cap,
+ .set_bus_param = soc_camera_platform_set_bus_param,
+ .query_bus_param = soc_camera_platform_query_bus_param,
+};
+
+static int soc_camera_platform_probe(struct platform_device *pdev)
+{
+ struct soc_camera_platform_priv *priv;
+ struct soc_camera_platform_info *p;
+ struct soc_camera_device *icd;
+ int ret;
+
+ p = pdev->dev.platform_data;
+ if (!p)
+ return -EINVAL;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->info = p;
+ platform_set_drvdata(pdev, priv);
+
+ icd = &priv->icd;
+ icd->ops = &soc_camera_platform_ops;
+ icd->control = &pdev->dev;
+ icd->width_min = 0;
+ icd->width_max = priv->info->format.width;
+ icd->height_min = 0;
+ icd->height_max = priv->info->format.height;
+ icd->y_skip_top = 0;
+ icd->iface = priv->info->iface;
+
+ ret = soc_camera_device_register(icd);
+ if (ret)
+ kfree(priv);
+
+ return ret;
+}
+
+static int soc_camera_platform_remove(struct platform_device *pdev)
+{
+ struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
+
+ soc_camera_device_unregister(&priv->icd);
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver soc_camera_platform_driver = {
+ .driver = {
+ .name = "soc_camera_platform",
+ },
+ .probe = soc_camera_platform_probe,
+ .remove = soc_camera_platform_remove,
+};
+
+static int __init soc_camera_platform_module_init(void)
+{
+ return platform_driver_register(&soc_camera_platform_driver);
+}
+
+static void __exit soc_camera_platform_module_exit(void)
+{
+ return platform_driver_unregister(&soc_camera_platform_driver);
+}
+
+module_init(soc_camera_platform_module_init);
+module_exit(soc_camera_platform_module_exit);
+
+MODULE_DESCRIPTION("SoC Camera Platform driver");
+MODULE_AUTHOR("Magnus Damm");
+MODULE_LICENSE("GPL v2");
diff --git a/linux/drivers/media/video/tvmixer.c b/linux/drivers/media/video/tvmixer.c
index b50e0942e..d7b931fd3 100644
--- a/linux/drivers/media/video/tvmixer.c
+++ b/linux/drivers/media/video/tvmixer.c
@@ -286,7 +286,11 @@ static int tvmixer_clients(struct i2c_client *client)
return -1;
/* everything is fine, register */
- if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
+ if ((minor = register_sound_mixer(&tvmixer_fops, devnr)) < 0) {
+#else
+ if ((minor = register_sound_mixer((struct file_operations *)&tvmixer_fops, devnr)) < 0) {
+#endif
printk(KERN_ERR "tvmixer: cannot allocate mixer device\n");
return -1;
}
diff --git a/linux/drivers/media/video/videobuf-dma-contig.c b/linux/drivers/media/video/videobuf-dma-contig.c
new file mode 100644
index 000000000..c71001da3
--- /dev/null
+++ b/linux/drivers/media/video/videobuf-dma-contig.c
@@ -0,0 +1,419 @@
+/*
+ * helper functions for physically contiguous capture buffers
+ *
+ * The functions support hardware lacking scatter gather support
+ * (i.e. the buffers must be linear in physical memory)
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * Based on videobuf-vmalloc.c,
+ * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.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
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <media/videobuf-dma-contig.h>
+#include "compat.h"
+
+struct videobuf_dma_contig_memory {
+ u32 magic;
+ void *vaddr;
+ dma_addr_t dma_handle;
+ unsigned long size;
+};
+
+#define MAGIC_DC_MEM 0x0733ac61
+#define MAGIC_CHECK(is, should) \
+ if (unlikely((is) != (should))) { \
+ pr_err("magic mismatch: %x expected %x\n", is, should); \
+ BUG(); \
+ }
+
+static void
+videobuf_vm_open(struct vm_area_struct *vma)
+{
+ struct videobuf_mapping *map = vma->vm_private_data;
+
+ dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
+ map, map->count, vma->vm_start, vma->vm_end);
+
+ map->count++;
+}
+
+static void videobuf_vm_close(struct vm_area_struct *vma)
+{
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+ int i;
+
+ dev_dbg(map->q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
+ map, map->count, vma->vm_start, vma->vm_end);
+
+ map->count--;
+ if (0 == map->count) {
+ struct videobuf_dma_contig_memory *mem;
+
+ dev_dbg(map->q->dev, "munmap %p q=%p\n", map, q);
+ mutex_lock(&q->vb_lock);
+
+ /* We need first to cancel streams, before unmapping */
+ if (q->streaming)
+ videobuf_queue_cancel(q);
+
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (NULL == q->bufs[i])
+ continue;
+
+ if (q->bufs[i]->map != map)
+ continue;
+
+ mem = q->bufs[i]->priv;
+ if (mem) {
+ /* This callback is called only if kernel has
+ allocated memory and this memory is mmapped.
+ In this case, memory should be freed,
+ in order to do memory unmap.
+ */
+
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ /* vfree is not atomic - can't be
+ called with IRQ's disabled
+ */
+ dev_dbg(map->q->dev, "buf[%d] freeing %p\n",
+ i, mem->vaddr);
+
+ dma_free_coherent(q->dev, mem->size,
+ mem->vaddr, mem->dma_handle);
+ mem->vaddr = NULL;
+ }
+
+ q->bufs[i]->map = NULL;
+ q->bufs[i]->baddr = 0;
+ }
+
+ kfree(map);
+
+ mutex_unlock(&q->vb_lock);
+ }
+}
+
+static struct vm_operations_struct videobuf_vm_ops = {
+ .open = videobuf_vm_open,
+ .close = videobuf_vm_close,
+};
+
+static void *__videobuf_alloc(size_t size)
+{
+ struct videobuf_dma_contig_memory *mem;
+ struct videobuf_buffer *vb;
+
+ vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
+ if (vb) {
+ mem = vb->priv = ((char *)vb) + size;
+ mem->magic = MAGIC_DC_MEM;
+ }
+
+ return vb;
+}
+
+static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf)
+{
+ struct videobuf_dma_contig_memory *mem = buf->priv;
+
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ return mem->vaddr;
+}
+
+static int __videobuf_iolock(struct videobuf_queue *q,
+ struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf)
+{
+ struct videobuf_dma_contig_memory *mem = vb->priv;
+
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ switch (vb->memory) {
+ case V4L2_MEMORY_MMAP:
+ dev_dbg(q->dev, "%s memory method MMAP\n", __func__);
+
+ /* All handling should be done by __videobuf_mmap_mapper() */
+ if (!mem->vaddr) {
+ dev_err(q->dev, "memory is not alloced/mmapped.\n");
+ return -EINVAL;
+ }
+ break;
+ case V4L2_MEMORY_USERPTR:
+ dev_dbg(q->dev, "%s memory method USERPTR\n", __func__);
+
+ /* The only USERPTR currently supported is the one needed for
+ read() method.
+ */
+ if (vb->baddr)
+ return -EINVAL;
+
+ mem->size = PAGE_ALIGN(vb->size);
+ mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
+ &mem->dma_handle, GFP_KERNEL);
+ if (!mem->vaddr) {
+ dev_err(q->dev, "dma_alloc_coherent %ld failed\n",
+ mem->size);
+ return -ENOMEM;
+ }
+
+ dev_dbg(q->dev, "dma_alloc_coherent data is at %p (%ld)\n",
+ mem->vaddr, mem->size);
+ break;
+ case V4L2_MEMORY_OVERLAY:
+ default:
+ dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __videobuf_sync(struct videobuf_queue *q,
+ struct videobuf_buffer *buf)
+{
+ struct videobuf_dma_contig_memory *mem = buf->priv;
+
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ dma_sync_single_for_cpu(q->dev, mem->dma_handle, mem->size,
+ DMA_FROM_DEVICE);
+ return 0;
+}
+
+static int __videobuf_mmap_free(struct videobuf_queue *q)
+{
+ unsigned int i;
+
+ dev_dbg(q->dev, "%s\n", __func__);
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (q->bufs[i] && q->bufs[i]->map)
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ struct vm_area_struct *vma)
+{
+ struct videobuf_dma_contig_memory *mem;
+ struct videobuf_mapping *map;
+ unsigned int first;
+ int retval;
+ unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ dev_dbg(q->dev, "%s\n", __func__);
+ if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ /* look for first buffer to map */
+ for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ if (!q->bufs[first])
+ continue;
+
+ if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
+ continue;
+ if (q->bufs[first]->boff == offset)
+ break;
+ }
+ if (VIDEO_MAX_FRAME == first) {
+ dev_dbg(q->dev, "invalid user space offset [offset=0x%lx]\n",
+ offset);
+ return -EINVAL;
+ }
+
+ /* create mapping + update buffer list */
+ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ q->bufs[first]->map = map;
+ map->start = vma->vm_start;
+ map->end = vma->vm_end;
+ map->q = q;
+
+ q->bufs[first]->baddr = vma->vm_start;
+
+ mem = q->bufs[first]->priv;
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ mem->size = PAGE_ALIGN(q->bufs[first]->bsize);
+ mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
+ &mem->dma_handle, GFP_KERNEL);
+ if (!mem->vaddr) {
+ dev_err(q->dev, "dma_alloc_coherent size %ld failed\n",
+ mem->size);
+ goto error;
+ }
+ dev_dbg(q->dev, "dma_alloc_coherent data is at addr %p (size %ld)\n",
+ mem->vaddr, mem->size);
+
+ /* Try to remap memory */
+
+ size = vma->vm_end - vma->vm_start;
+ size = (size < mem->size) ? size : mem->size;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ retval = remap_pfn_range(vma, vma->vm_start,
+ mem->dma_handle >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+ if (retval) {
+ dev_err(q->dev, "mmap: remap failed with error %d. ", retval);
+ dma_free_coherent(q->dev, mem->size,
+ mem->vaddr, mem->dma_handle);
+ goto error;
+ }
+
+ vma->vm_ops = &videobuf_vm_ops;
+ vma->vm_flags |= VM_DONTEXPAND;
+ vma->vm_private_data = map;
+
+ dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
+ map, q, vma->vm_start, vma->vm_end,
+ (long int) q->bufs[first]->bsize,
+ vma->vm_pgoff, first);
+
+ videobuf_vm_open(vma);
+
+ return 0;
+
+error:
+ kfree(map);
+ return -ENOMEM;
+}
+
+static int __videobuf_copy_to_user(struct videobuf_queue *q,
+ char __user *data, size_t count,
+ int nonblocking)
+{
+ struct videobuf_dma_contig_memory *mem = q->read_buf->priv;
+ void *vaddr;
+
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+ BUG_ON(!mem->vaddr);
+
+ /* copy to userspace */
+ if (count > q->read_buf->size - q->read_off)
+ count = q->read_buf->size - q->read_off;
+
+ vaddr = mem->vaddr;
+
+ if (copy_to_user(data, vaddr + q->read_off, count))
+ return -EFAULT;
+
+ return count;
+}
+
+static int __videobuf_copy_stream(struct videobuf_queue *q,
+ char __user *data, size_t count, size_t pos,
+ int vbihack, int nonblocking)
+{
+ unsigned int *fc;
+ struct videobuf_dma_contig_memory *mem = q->read_buf->priv;
+
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ if (vbihack) {
+ /* dirty, undocumented hack -- pass the frame counter
+ * within the last four bytes of each vbi data block.
+ * We need that one to maintain backward compatibility
+ * to all vbi decoding software out there ... */
+ fc = (unsigned int *)mem->vaddr;
+ fc += (q->read_buf->size >> 2) - 1;
+ *fc = q->read_buf->field_count >> 1;
+ dev_dbg(q->dev, "vbihack: %d\n", *fc);
+ }
+
+ /* copy stuff using the common method */
+ count = __videobuf_copy_to_user(q, data, count, nonblocking);
+
+ if ((count == -EFAULT) && (pos == 0))
+ return -EFAULT;
+
+ return count;
+}
+
+static struct videobuf_qtype_ops qops = {
+ .magic = MAGIC_QTYPE_OPS,
+
+ .alloc = __videobuf_alloc,
+ .iolock = __videobuf_iolock,
+ .sync = __videobuf_sync,
+ .mmap_free = __videobuf_mmap_free,
+ .mmap_mapper = __videobuf_mmap_mapper,
+ .video_copy_to_user = __videobuf_copy_to_user,
+ .copy_stream = __videobuf_copy_stream,
+ .vmalloc = __videobuf_to_vmalloc,
+};
+
+void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
+ struct videobuf_queue_ops *ops,
+ struct device *dev,
+ spinlock_t *irqlock,
+ enum v4l2_buf_type type,
+ enum v4l2_field field,
+ unsigned int msize,
+ void *priv)
+{
+ videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
+ priv, &qops);
+}
+EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init);
+
+dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf)
+{
+ struct videobuf_dma_contig_memory *mem = buf->priv;
+
+ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ return mem->dma_handle;
+}
+EXPORT_SYMBOL_GPL(videobuf_to_dma_contig);
+
+void videobuf_dma_contig_free(struct videobuf_queue *q,
+ struct videobuf_buffer *buf)
+{
+ struct videobuf_dma_contig_memory *mem = buf->priv;
+
+ /* mmapped memory can't be freed here, otherwise mmapped region
+ would be released, while still needed. In this case, the memory
+ release should happen inside videobuf_vm_close().
+ So, it should free memory only if the memory were allocated for
+ read() operation.
+ */
+ if ((buf->memory != V4L2_MEMORY_USERPTR) || !buf->baddr)
+ return;
+
+ if (!mem)
+ return;
+
+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+
+ dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
+ mem->vaddr = NULL;
+}
+EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
+
+MODULE_DESCRIPTION("helper module to manage video4linux dma contig buffers");
+MODULE_AUTHOR("Magnus Damm");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/videobuf-dma-sg.c b/linux/drivers/media/video/videobuf-dma-sg.c
index 21194d6fe..e64350e1f 100644
--- a/linux/drivers/media/video/videobuf-dma-sg.c
+++ b/linux/drivers/media/video/videobuf-dma-sg.c
@@ -1,7 +1,7 @@
/*
* helper functions for SG DMA video4linux capture buffers
*
- * The functions expect the hardware being able to scatter gatter
+ * The functions expect the hardware being able to scatter gather
* (i.e. the buffers are not linear in physical memory, but fragmented
* into PAGE_SIZE chunks). They also assume the driver does not need
* to touch the video data.
diff --git a/linux/drivers/media/video/videobuf-vmalloc.c b/linux/drivers/media/video/videobuf-vmalloc.c
index 6f487b348..eb25cc257 100644
--- a/linux/drivers/media/video/videobuf-vmalloc.c
+++ b/linux/drivers/media/video/videobuf-vmalloc.c
@@ -1,7 +1,7 @@
/*
* helper functions for vmalloc video4linux capture buffers
*
- * The functions expect the hardware being able to scatter gatter
+ * The functions expect the hardware being able to scatter gather
* (i.e. the buffers are not linear in physical memory, but fragmented
* into PAGE_SIZE chunks). They also assume the driver does not need
* to touch the video data.
diff --git a/linux/drivers/media/video/videodev.c b/linux/drivers/media/video/videodev.c
index 7ac11d5fb..b32b59afd 100644
--- a/linux/drivers/media/video/videodev.c
+++ b/linux/drivers/media/video/videodev.c
@@ -376,6 +376,7 @@ EXPORT_SYMBOL(v4l_printk_ioctl);
* sysfs stuff
*/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
static ssize_t show_index(struct device *cd,
struct device_attribute *attr, char *buf)
{
@@ -392,6 +393,30 @@ static ssize_t show_name(struct device *cd,
return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
}
+static struct device_attribute video_device_attrs[] = {
+ __ATTR(name, S_IRUGO, show_name, NULL),
+ __ATTR(index, S_IRUGO, show_index, NULL),
+ __ATTR_NULL
+};
+#else
+static ssize_t show_index(struct class_device *cd, char *buf)
+{
+ struct video_device *vfd = container_of(cd, struct video_device,
+ class_dev);
+ return sprintf(buf, "%i\n", vfd->index);
+}
+
+static ssize_t show_name(struct class_device *cd, char *buf)
+{
+ struct video_device *vfd = container_of(cd, struct video_device,
+ class_dev);
+ return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
+}
+
+static CLASS_DEVICE_ATTR(index, S_IRUGO, show_index, NULL);
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+#endif
+
struct video_device *video_device_alloc(void)
{
struct video_device *vfd;
@@ -407,7 +432,11 @@ void video_device_release(struct video_device *vfd)
}
EXPORT_SYMBOL(video_device_release);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void video_release(struct class_device *cd)
+#else
static void video_release(struct device *cd)
+#endif
{
struct video_device *vfd = container_of(cd, struct video_device,
class_dev);
@@ -420,16 +449,14 @@ static void video_release(struct device *cd)
vfd->release(vfd);
}
-static struct device_attribute video_device_attrs[] = {
- __ATTR(name, S_IRUGO, show_name, NULL),
- __ATTR(index, S_IRUGO, show_index, NULL),
- __ATTR_NULL
-};
-
static struct class video_class = {
.name = VIDEO_NAME,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+ .release = video_release,
+#else
.dev_attrs = video_device_attrs,
.dev_release = video_release,
+#endif
};
/*
@@ -457,7 +484,7 @@ static int video_open(struct inode *inode, struct file *file)
unsigned int minor = iminor(inode);
int err = 0;
struct video_device *vfl;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
const struct file_operations *old_fops;
#else
struct file_operations *old_fops;
@@ -478,7 +505,11 @@ static int video_open(struct inode *inode, struct file *file)
}
}
old_fops = file->f_op;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
file->f_op = fops_get(vfl->fops);
+#else
+ file->f_op = (struct file_operations *)fops_get(vfl->fops);
+#endif
if(file->f_op->open)
err = file->f_op->open(inode,file);
if (err) {
@@ -2016,26 +2047,8 @@ out:
}
EXPORT_SYMBOL(video_ioctl2);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
-struct index_info {
- struct device *dev;
- unsigned int used[VIDEO_NUM_DEVICES];
-};
-
-static int __fill_index_info(struct device *cd, void *data)
-{
- struct index_info *info = data;
- struct video_device *vfd = container_of(cd, struct video_device,
- class_dev);
-
- if (info->dev == vfd->dev)
- info->used[vfd->index] = 1;
-
- return 0;
-}
-
/**
- * assign_index - assign stream number based on parent device
+ * get_index - assign stream number based on parent device
* @vdev: video_device to assign index number to, vdev->dev should be assigned
* @num: -1 if auto assign, requested number otherwise
*
@@ -2045,46 +2058,35 @@ static int __fill_index_info(struct device *cd, void *data)
*/
static int get_index(struct video_device *vdev, int num)
{
- struct index_info *info;
+ u32 used = 0;
+ const int max_index = sizeof(used) * 8 - 1;
int i;
- int ret = 0;
- if (num >= VIDEO_NUM_DEVICES)
+ /* Currently a single v4l driver instance cannot create more than
+ 32 devices.
+ Increase to u64 or an array of u32 if more are needed. */
+ if (num > max_index) {
+ printk(KERN_ERR "videodev: %s num is too large\n", __func__);
return -EINVAL;
-
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- info->dev = vdev->dev;
-
- ret = class_for_each_device(&video_class, info,
- __fill_index_info);
-
- if (ret < 0)
- goto out;
-
- if (num >= 0) {
- if (!info->used[num])
- ret = num;
- else
- ret = -ENFILE;
-
- goto out;
}
for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
- if (info->used[i])
- continue;
- ret = i;
- goto out;
+ if (video_device[i] != NULL &&
+ video_device[i] != vdev &&
+ video_device[i]->dev == vdev->dev) {
+ used |= 1 << video_device[i]->index;
+ }
}
-out:
- kfree(info);
- return ret;
+ if (num >= 0) {
+ if (used & (1 << num))
+ return -ENFILE;
+ return num;
+ }
+
+ i = ffz(used);
+ return i > max_index ? -ENFILE : i;
}
-#endif
static const struct file_operations video_fops;
@@ -2178,35 +2180,57 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
video_device[i]=vfd;
vfd->minor=i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
ret = get_index(vfd, index);
-#else
- ret = 0;
-#endif
+ vfd->index = ret;
+
+ mutex_unlock(&videodev_lock);
+
if (ret < 0) {
- printk(KERN_ERR "%s: get_index failed\n",
- __func__);
+ printk(KERN_ERR "%s: get_index failed\n", __func__);
goto fail_minor;
}
- vfd->index = ret;
-
- mutex_unlock(&videodev_lock);
mutex_init(&vfd->lock);
/* sysfs class */
memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev));
- if (vfd->dev)
- vfd->class_dev.parent = vfd->dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
vfd->class_dev.class = &video_class;
vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+ if (vfd->dev)
+ vfd->class_dev.dev = vfd->dev;
+ sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base);
+ ret = class_device_register(&vfd->class_dev);
+#else
+ if (vfd->dev)
+ vfd->class_dev.parent = vfd->dev;
sprintf(vfd->class_dev.bus_id, "%s%d", name_base, i - base);
ret = device_register(&vfd->class_dev);
+#endif
if (ret < 0) {
- printk(KERN_ERR "%s: device_register failed\n",
- __func__);
+ printk(KERN_ERR "%s: device_register failed\n", __func__);
goto fail_minor;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+ ret = class_device_create_file(&vfd->class_dev,
+ &class_device_attr_name);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: class_device_create_file 'name' failed\n",
+ __func__);
+ class_device_unregister(&vfd->class_dev);
+ goto fail_minor;
+ }
+ ret = class_device_create_file(&vfd->class_dev,
+ &class_device_attr_index);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: class_device_create_file 'index' failed\n",
+ __func__);
+ class_device_unregister(&vfd->class_dev);
+ goto fail_minor;
+ }
+#endif
#if 1 /* keep */
/* needed until all drivers are fixed */
@@ -2241,7 +2265,11 @@ void video_unregister_device(struct video_device *vfd)
panic("videodev: bad unregister");
video_device[vfd->minor]=NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+ class_device_unregister(&vfd->class_dev);
+#else
device_unregister(&vfd->class_dev);
+#endif
mutex_unlock(&videodev_lock);
}
EXPORT_SYMBOL(video_unregister_device);
@@ -2265,7 +2293,12 @@ static int __init videodev_init(void)
int ret;
printk(KERN_INFO "Linux video capture interface: v2.00\n");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
+#else
+ if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME,
+ (struct file_operations *)&video_fops)) {
+#endif
printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
return -EIO;
}