Commit 034f2e11 authored by Stelian Pop's avatar Stelian Pop Committed by Linus Torvalds

[PATCH] meye driver update

The most important changes are:
	- allocate buffers on open(), not module load;
	- correct some failed allocation paths;
	- use wait_event;
	- C99 structs inits;
parent eaac83e4
Vaio Picturebook Motion Eye Camera Driver Readme Vaio Picturebook Motion Eye Camera Driver Readme
------------------------------------------------ ------------------------------------------------
Copyright (C) 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve Copyright (C) 2001-2002 Stelian Pop <stelian@popies.net>
Copyright (C) 2001-2002 Alcôve <www.alcove.com>
Copyright (C) 2000 Andrew Tridgell <tridge@samba.org> Copyright (C) 2000 Andrew Tridgell <tridge@samba.org>
This driver enable the use of video4linux compatible applications with the This driver enable the use of video4linux compatible applications with the
...@@ -52,7 +53,7 @@ Usage: ...@@ -52,7 +53,7 @@ Usage:
or or
xawtv -c /dev/video0 -geometry 320x240 xawtv -c /dev/video0 -geometry 320x240
motioneye (<http://www.alcove-labs.org/en/software/meye/>) motioneye (<http://popies.net/meye/>)
for getting ppm or jpg snapshots, mjpeg video for getting ppm or jpg snapshots, mjpeg video
Private API: Private API:
......
/* /*
* Motion Eye video4linux driver for Sony Vaio PictureBook * Motion Eye video4linux driver for Sony Vaio PictureBook
* *
* Copyright (C) 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcve * Copyright (C) 2001-2002 Stelian Pop <stelian@popies.net>
*
* Copyright (C) 2001-2002 Alcve <www.alcove.com>
* *
* Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com> * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
* *
...@@ -169,16 +171,28 @@ static int ptable_alloc(void) { ...@@ -169,16 +171,28 @@ static int ptable_alloc(void) {
meye.mchip_ptable[MCHIP_NB_PAGES] = pci_alloc_consistent(meye.mchip_dev, meye.mchip_ptable[MCHIP_NB_PAGES] = pci_alloc_consistent(meye.mchip_dev,
PAGE_SIZE, PAGE_SIZE,
&meye.mchip_dmahandle); &meye.mchip_dmahandle);
if (!meye.mchip_ptable[MCHIP_NB_PAGES]) if (!meye.mchip_ptable[MCHIP_NB_PAGES]) {
meye.mchip_dmahandle = 0;
return -1; return -1;
}
pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES]; pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
for (i = 0; i < MCHIP_NB_PAGES; i++) { for (i = 0; i < MCHIP_NB_PAGES; i++) {
meye.mchip_ptable[i] = pci_alloc_consistent(meye.mchip_dev, meye.mchip_ptable[i] = pci_alloc_consistent(meye.mchip_dev,
PAGE_SIZE, PAGE_SIZE,
pt); pt);
if (!meye.mchip_ptable[i]) if (!meye.mchip_ptable[i]) {
int j;
pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
for (j = 0; j < i; ++j) {
pci_free_consistent(meye.mchip_dev,
PAGE_SIZE,
meye.mchip_ptable[j], *pt);
pt++;
}
meye.mchip_dmahandle = 0;
return -1; return -1;
}
pt++; pt++;
} }
return 0; return 0;
...@@ -189,11 +203,13 @@ static void ptable_free(void) { ...@@ -189,11 +203,13 @@ static void ptable_free(void) {
int i; int i;
pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES]; pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
for (i = 0; i < MCHIP_NB_PAGES; i++) for (i = 0; i < MCHIP_NB_PAGES; i++) {
if (meye.mchip_ptable[i]) if (meye.mchip_ptable[i])
pci_free_consistent(meye.mchip_dev, pci_free_consistent(meye.mchip_dev,
PAGE_SIZE, PAGE_SIZE,
meye.mchip_ptable[i], *pt); meye.mchip_ptable[i], *pt);
pt++;
}
if (meye.mchip_ptable[MCHIP_NB_PAGES]) if (meye.mchip_ptable[MCHIP_NB_PAGES])
pci_free_consistent(meye.mchip_dev, pci_free_consistent(meye.mchip_dev,
...@@ -569,6 +585,16 @@ static void mchip_vrj_setup(u8 mode) { ...@@ -569,6 +585,16 @@ static void mchip_vrj_setup(u8 mode) {
mchip_load_tables(); mchip_load_tables();
} }
/* sets the DMA parameters into the chip */
static void mchip_dma_setup(u32 dma_addr) {
int i;
mchip_set(MCHIP_MM_PT_ADDR, dma_addr);
for (i = 0; i < 4; i++)
mchip_set(MCHIP_MM_FIR(i), 0);
meye.mchip_fnum = 0;
}
/* setup for DMA transfers - also zeros the framebuffer */ /* setup for DMA transfers - also zeros the framebuffer */
static int mchip_dma_alloc(void) { static int mchip_dma_alloc(void) {
if (!meye.mchip_dmahandle) if (!meye.mchip_dmahandle)
...@@ -579,18 +605,10 @@ static int mchip_dma_alloc(void) { ...@@ -579,18 +605,10 @@ static int mchip_dma_alloc(void) {
/* frees the DMA buffer */ /* frees the DMA buffer */
static void mchip_dma_free(void) { static void mchip_dma_free(void) {
if (meye.mchip_dmahandle) if (meye.mchip_dmahandle) {
mchip_dma_setup(0);
ptable_free(); ptable_free();
} }
/* sets the DMA parameters into the chip */
static void mchip_dma_setup(void) {
int i;
mchip_set(MCHIP_MM_PT_ADDR, meye.mchip_dmahandle);
for (i = 0; i < 4; i++)
mchip_set(MCHIP_MM_FIR(i), 0);
meye.mchip_fnum = 0;
} }
/* stop any existing HIC action and wait for any dma to complete then /* stop any existing HIC action and wait for any dma to complete then
...@@ -698,7 +716,7 @@ static void mchip_take_picture(void) { ...@@ -698,7 +716,7 @@ static void mchip_take_picture(void) {
mchip_hic_stop(); mchip_hic_stop();
mchip_subsample(); mchip_subsample();
mchip_dma_setup(); mchip_dma_setup(meye.mchip_dmahandle);
mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP); mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP);
mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
...@@ -741,7 +759,7 @@ static void mchip_continuous_start(void) { ...@@ -741,7 +759,7 @@ static void mchip_continuous_start(void) {
mchip_hic_stop(); mchip_hic_stop();
mchip_subsample(); mchip_subsample();
mchip_set_framerate(); mchip_set_framerate();
mchip_dma_setup(); mchip_dma_setup(meye.mchip_dmahandle);
meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT; meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
...@@ -801,7 +819,7 @@ static void mchip_cont_compression_start(void) { ...@@ -801,7 +819,7 @@ static void mchip_cont_compression_start(void) {
mchip_vrj_setup(0x3f); mchip_vrj_setup(0x3f);
mchip_subsample(); mchip_subsample();
mchip_set_framerate(); mchip_set_framerate();
mchip_dma_setup(); mchip_dma_setup(meye.mchip_dmahandle);
meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
...@@ -823,7 +841,7 @@ static void meye_irq(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -823,7 +841,7 @@ static void meye_irq(int irq, void *dev_id, struct pt_regs *regs) {
while (1) { while (1) {
v = mchip_get_frame(); v = mchip_get_frame();
if (!(v & MCHIP_MM_FIR_RDY)) if (!(v & MCHIP_MM_FIR_RDY))
goto out; return;
switch (meye.mchip_mode) { switch (meye.mchip_mode) {
case MCHIP_HIC_MODE_CONT_OUT: case MCHIP_HIC_MODE_CONT_OUT:
...@@ -856,12 +874,11 @@ static void meye_irq(int irq, void *dev_id, struct pt_regs *regs) { ...@@ -856,12 +874,11 @@ static void meye_irq(int irq, void *dev_id, struct pt_regs *regs) {
default: default:
/* do not free frame, since it can be a snap */ /* do not free frame, since it can be a snap */
goto out; return;
} /* switch */ } /* switch */
mchip_free_frame(); mchip_free_frame();
} }
out:
} }
/****************************************************************************/ /****************************************************************************/
...@@ -889,6 +906,7 @@ static int meye_open(struct inode *inode, struct file *file) { ...@@ -889,6 +906,7 @@ static int meye_open(struct inode *inode, struct file *file) {
static int meye_release(struct inode *inode, struct file *file) { static int meye_release(struct inode *inode, struct file *file) {
mchip_hic_stop(); mchip_hic_stop();
mchip_dma_free();
video_exclusive_release(inode,file); video_exclusive_release(inode,file);
return 0; return 0;
} }
...@@ -957,7 +975,6 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -957,7 +975,6 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCSYNC: { case VIDIOCSYNC: {
int *i = arg; int *i = arg;
DECLARE_WAITQUEUE(wait, current);
if (*i < 0 || *i >= gbuffers) if (*i < 0 || *i >= gbuffers)
return -EINVAL; return -EINVAL;
...@@ -967,18 +984,9 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -967,18 +984,9 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
case MEYE_BUF_UNUSED: case MEYE_BUF_UNUSED:
return -EINVAL; return -EINVAL;
case MEYE_BUF_USING: case MEYE_BUF_USING:
add_wait_queue(&meye.grabq.proc_list, &wait); if (wait_event_interruptible(meye.grabq.proc_list,
current->state = TASK_INTERRUPTIBLE; (meye.grab_buffer[*i].state != MEYE_BUF_USING)))
while (meye.grab_buffer[*i].state == MEYE_BUF_USING) {
schedule();
if(signal_pending(current)) {
remove_wait_queue(&meye.grabq.proc_list, &wait);
current->state = TASK_RUNNING;
return -EINTR; return -EINTR;
}
}
remove_wait_queue(&meye.grabq.proc_list, &wait);
current->state = TASK_RUNNING;
/* fall through */ /* fall through */
case MEYE_BUF_DONE: case MEYE_BUF_DONE:
meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
...@@ -1095,7 +1103,6 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -1095,7 +1103,6 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
case MEYEIOC_SYNC: { case MEYEIOC_SYNC: {
int *i = arg; int *i = arg;
DECLARE_WAITQUEUE(wait, current);
if (*i < 0 || *i >= gbuffers) if (*i < 0 || *i >= gbuffers)
return -EINVAL; return -EINVAL;
...@@ -1105,18 +1112,9 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, ...@@ -1105,18 +1112,9 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
case MEYE_BUF_UNUSED: case MEYE_BUF_UNUSED:
return -EINVAL; return -EINVAL;
case MEYE_BUF_USING: case MEYE_BUF_USING:
add_wait_queue(&meye.grabq.proc_list, &wait); if (wait_event_interruptible(meye.grabq.proc_list,
current->state = TASK_INTERRUPTIBLE; (meye.grab_buffer[*i].state != MEYE_BUF_USING)))
while (meye.grab_buffer[*i].state == MEYE_BUF_USING) {
schedule();
if(signal_pending(current)) {
remove_wait_queue(&meye.grabq.proc_list, &wait);
current->state = TASK_RUNNING;
return -EINTR; return -EINTR;
}
}
remove_wait_queue(&meye.grabq.proc_list, &wait);
current->state = TASK_RUNNING;
/* fall through */ /* fall through */
case MEYE_BUF_DONE: case MEYE_BUF_DONE:
meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
...@@ -1211,20 +1209,20 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) { ...@@ -1211,20 +1209,20 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) {
} }
static struct file_operations meye_fops = { static struct file_operations meye_fops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
open: meye_open, .open = meye_open,
release: meye_release, .release = meye_release,
mmap: meye_mmap, .mmap = meye_mmap,
ioctl: meye_ioctl, .ioctl = meye_ioctl,
llseek: no_llseek, .llseek = no_llseek,
}; };
static struct video_device meye_template = { static struct video_device meye_template = {
owner: THIS_MODULE, .owner = THIS_MODULE,
name: "meye", .name = "meye",
type: VID_TYPE_CAPTURE, .type = VID_TYPE_CAPTURE,
hardware: VID_HARDWARE_MEYE, .hardware = VID_HARDWARE_MEYE,
fops: &meye_fops, .fops = &meye_fops,
}; };
static int __devinit meye_probe(struct pci_dev *pcidev, static int __devinit meye_probe(struct pci_dev *pcidev,
...@@ -1244,15 +1242,9 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1244,15 +1242,9 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
meye.mchip_dev = pcidev; meye.mchip_dev = pcidev;
memcpy(&meye.video_dev, &meye_template, sizeof(meye_template)); memcpy(&meye.video_dev, &meye_template, sizeof(meye_template));
if (mchip_dma_alloc()) {
printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
ret = -ENOMEM;
goto out2;
}
if ((ret = pci_enable_device(meye.mchip_dev))) { if ((ret = pci_enable_device(meye.mchip_dev))) {
printk(KERN_ERR "meye: pci_enable_device failed\n"); printk(KERN_ERR "meye: pci_enable_device failed\n");
goto out3; goto out2;
} }
meye.mchip_irq = pcidev->irq; meye.mchip_irq = pcidev->irq;
...@@ -1260,14 +1252,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1260,14 +1252,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
if (!mchip_adr) { if (!mchip_adr) {
printk(KERN_ERR "meye: mchip has no device base address\n"); printk(KERN_ERR "meye: mchip has no device base address\n");
ret = -EIO; ret = -EIO;
goto out4; goto out3;
} }
if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0), if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0),
pci_resource_len(meye.mchip_dev, 0), pci_resource_len(meye.mchip_dev, 0),
"meye")) { "meye")) {
ret = -EIO; ret = -EIO;
printk(KERN_ERR "meye: request_mem_region failed\n"); printk(KERN_ERR "meye: request_mem_region failed\n");
goto out4; goto out3;
} }
pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision); pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision);
...@@ -1280,14 +1272,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1280,14 +1272,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
if ((ret = request_irq(meye.mchip_irq, meye_irq, if ((ret = request_irq(meye.mchip_irq, meye_irq,
SA_INTERRUPT | SA_SHIRQ, "meye", meye_irq))) { SA_INTERRUPT | SA_SHIRQ, "meye", meye_irq))) {
printk(KERN_ERR "meye: request_irq failed (ret=%d)\n", ret); printk(KERN_ERR "meye: request_irq failed (ret=%d)\n", ret);
goto out5; goto out4;
} }
meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS); meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS);
if (!meye.mchip_mmregs) { if (!meye.mchip_mmregs) {
printk(KERN_ERR "meye: ioremap failed\n"); printk(KERN_ERR "meye: ioremap failed\n");
ret = -EIO; ret = -EIO;
goto out6; goto out5;
} }
/* Ask the camera to perform a soft reset. */ /* Ask the camera to perform a soft reset. */
...@@ -1309,7 +1301,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1309,7 +1301,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
printk(KERN_ERR "meye: video_register_device failed\n"); printk(KERN_ERR "meye: video_register_device failed\n");
ret = -EIO; ret = -EIO;
goto out7; goto out6;
} }
printk(KERN_INFO "meye: Motion Eye Camera Driver v%d.%d.\n", printk(KERN_INFO "meye: Motion Eye Camera Driver v%d.%d.\n",
...@@ -1343,17 +1335,15 @@ static int __devinit meye_probe(struct pci_dev *pcidev, ...@@ -1343,17 +1335,15 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48); sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48);
return 0; return 0;
out7:
iounmap(meye.mchip_mmregs);
out6: out6:
free_irq(meye.mchip_irq, meye_irq); iounmap(meye.mchip_mmregs);
out5: out5:
free_irq(meye.mchip_irq, meye_irq);
out4:
release_mem_region(pci_resource_start(meye.mchip_dev, 0), release_mem_region(pci_resource_start(meye.mchip_dev, 0),
pci_resource_len(meye.mchip_dev, 0)); pci_resource_len(meye.mchip_dev, 0));
out4:
pci_disable_device(meye.mchip_dev);
out3: out3:
mchip_dma_free(); pci_disable_device(meye.mchip_dev);
out2: out2:
sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0);
out1: out1:
...@@ -1371,7 +1361,6 @@ static void __devexit meye_remove(struct pci_dev *pcidev) { ...@@ -1371,7 +1361,6 @@ static void __devexit meye_remove(struct pci_dev *pcidev) {
free_irq(meye.mchip_irq, meye_irq); free_irq(meye.mchip_irq, meye_irq);
iounmap(meye.mchip_mmregs); iounmap(meye.mchip_mmregs);
release_mem_region(pci_resource_start(meye.mchip_dev, 0), release_mem_region(pci_resource_start(meye.mchip_dev, 0),
...@@ -1398,10 +1387,10 @@ static struct pci_device_id meye_pci_tbl[] __devinitdata = { ...@@ -1398,10 +1387,10 @@ static struct pci_device_id meye_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, meye_pci_tbl); MODULE_DEVICE_TABLE(pci, meye_pci_tbl);
static struct pci_driver meye_driver = { static struct pci_driver meye_driver = {
name: "meye", .name = "meye",
id_table: meye_pci_tbl, .id_table = meye_pci_tbl,
probe: meye_probe, .probe = meye_probe,
remove: __devexit_p(meye_remove), .remove = __devexit_p(meye_remove),
}; };
static int __init meye_init_module(void) { static int __init meye_init_module(void) {
...@@ -1441,7 +1430,7 @@ static int __init meye_setup(char *str) { ...@@ -1441,7 +1430,7 @@ static int __init meye_setup(char *str) {
__setup("meye=", meye_setup); __setup("meye=", meye_setup);
#endif #endif
MODULE_AUTHOR("Stelian Pop <stelian.pop@fr.alcove.com>"); MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
MODULE_DESCRIPTION("video4linux driver for the MotionEye camera"); MODULE_DESCRIPTION("video4linux driver for the MotionEye camera");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
/* /*
* Motion Eye video4linux driver for Sony Vaio PictureBook * Motion Eye video4linux driver for Sony Vaio PictureBook
* *
* Copyright (C) 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcve * Copyright (C) 2001-2002 Stelian Pop <stelian@popies.net>
*
* Copyright (C) 2001-2002 Alcve <www.alcove.com>
* *
* Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com> * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
* *
...@@ -29,7 +31,7 @@ ...@@ -29,7 +31,7 @@
#define _MEYE_PRIV_H_ #define _MEYE_PRIV_H_
#define MEYE_DRIVER_MAJORVERSION 1 #define MEYE_DRIVER_MAJORVERSION 1
#define MEYE_DRIVER_MINORVERSION 4 #define MEYE_DRIVER_MINORVERSION 5
/****************************************************************************/ /****************************************************************************/
/* Motion JPEG chip registers */ /* Motion JPEG chip registers */
......
/* /*
* Motion Eye video4linux driver for Sony Vaio PictureBook * Motion Eye video4linux driver for Sony Vaio PictureBook
* *
* Copyright (C) 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcve * Copyright (C) 2001-2002 Stelian Pop <stelian@popies.net>
*
* Copyright (C) 2001-2002 Alcve <www.alcove.com>
* *
* Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com> * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment