-/*
+/*
planb - PlanB frame grabber driver
PlanB is used in the 7x00/8x00 series of PowerMacintosh
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/videodev.h>
+#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/irq.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include "planb.h"
#include "saa7196.h"
static int def_norm = PLANB_DEF_NORM; /* default norm */
static int video_nr = -1;
-MODULE_PARM(def_norm, "i");
+module_param(def_norm, int, 0);
MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
-MODULE_PARM(video_nr,"i");
+module_param(video_nr, int, 0);
MODULE_LICENSE("GPL");
saa_write_reg (SAA7196_STDC, saa_regs[pb->win.norm][SAA7196_STDC]);
/* Let's wait 30msec for this one */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(30 * HZ / 1000);
+ msleep_interruptible(30);
return (unsigned char)in_8 (&planb_regs->saa_status);
}
static inline void planb_lock(struct planb *pb)
{
- down(&pb->lock);
+ mutex_lock(&pb->lock);
}
static inline void planb_unlock(struct planb *pb)
{
- up(&pb->lock);
+ mutex_unlock(&pb->lock);
}
/***************/
/* overlay support functions */
/*****************************/
+static inline int overlay_is_active(struct planb *pb)
+{
+ unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
+ unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr);
+
+ return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys)
+ && (caddr < (pb->ch1_cmd_phys + size))
+ && (caddr >= (unsigned)pb->ch1_cmd_phys);
+}
+
static void overlay_start(struct planb *pb)
{
wake_up_interruptible(&pb->suspendq);
}
-static void add_clip(struct planb *pb, struct video_clip *clip)
+static void add_clip(struct planb *pb, struct video_clip *clip)
{
volatile unsigned char *base;
int xc = clip->x, yc = clip->y;
PLANB_SET(CH_SYNC));
tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
PLANB_SET(DMA_ABORT));
-
+
/* odd field data: */
jump = virt_to_bus(c1 + nlines / 2);
for (i=1; i < nlines; i += stepsize, c1++)
#define PLANB_PALETTE_MAX 15
-static inline int overlay_is_active(struct planb *pb)
-{
- unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
- unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr);
-
- return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys)
- && (caddr < (pb->ch1_cmd_phys + size))
- && (caddr >= (unsigned)pb->ch1_cmd_phys);
-}
-
static int vgrab(struct planb *pb, struct video_mmap *mp)
{
unsigned int fr = mp->frame;
tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
PLANB_SET(DMA_ABORT));
-
+
/* odd field data: */
jump_addr = c1 + TAB_FACTOR * nlines / 2;
jump = virt_to_bus(jump_addr);
pb->user++;
DEBUG("PlanB: device opened\n");
-
- MOD_INC_USE_COUNT;
- return 0;
+ return 0;
}
static void planb_close(struct video_device *dev)
planb_unlock(pb);
DEBUG("PlanB: device closed\n");
-
- MOD_DEC_USE_COUNT;
}
static long planb_read(struct video_device *v, char *buf, unsigned long count,
static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
struct planb *pb=(struct planb *)dev;
-
+
switch (cmd)
- {
+ {
case VIDIOCGCAP:
{
struct video_capability b;
b.channels = 2; /* composite & svhs */
b.audios = 0;
b.maxwidth = PLANB_MAXPIXELS;
- b.maxheight = PLANB_MAXLINES;
- b.minwidth = 32; /* wild guess */
- b.minheight = 32;
- if (copy_to_user(arg,&b,sizeof(b)))
- return -EFAULT;
+ b.maxheight = PLANB_MAXLINES;
+ b.minwidth = 32; /* wild guess */
+ b.minheight = 32;
+ if (copy_to_user(arg,&b,sizeof(b)))
+ return -EFAULT;
return 0;
}
case VIDIOCSFBUF:
{
- struct video_buffer v;
+ struct video_buffer v;
unsigned short bpp;
unsigned int fmt;
DEBUG("PlanB: IOCTL VIDIOCSFBUF\n");
- if (!capable(CAP_SYS_ADMIN)
+ if (!capable(CAP_SYS_ADMIN)
|| !capable(CAP_SYS_RAWIO))
- return -EPERM;
- if (copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
+ return -EPERM;
+ if (copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
planb_lock(pb);
switch(v.depth) {
case 8:
break;
default:
planb_unlock(pb);
- return -EINVAL;
+ return -EINVAL;
}
if (bpp * v.width > v.bytesperline) {
planb_unlock(pb);
pb->win.bpl = pb->win.bpp * pb->win.swidth;
pb->win.pad = v.bytesperline - pb->win.bpl;
- DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
+ DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
" bpl %d (+ %d)\n", v.base, v.width,v.height,
pb->win.bpp, pb->win.bpl, pb->win.pad);
resume_overlay(pb);
}
planb_unlock(pb);
- return 0;
+ return 0;
}
case VIDIOCGFBUF:
{
- struct video_buffer v;
+ struct video_buffer v;
DEBUG("PlanB: IOCTL VIDIOCGFBUF\n");
v.depth = pb->win.depth;
v.bytesperline = pb->win.bpl + pb->win.pad;
if (copy_to_user(arg, &v, sizeof(v)))
- return -EFAULT;
+ return -EFAULT;
return 0;
}
case VIDIOCCAPTURE:
{
int i;
- if(copy_from_user(&i, arg, sizeof(i)))
- return -EFAULT;
+ if(copy_from_user(&i, arg, sizeof(i)))
+ return -EFAULT;
if(i==0) {
DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
}
planb_lock(pb);
/* empty the grabbing queue */
- while(pb->grabbing)
- interruptible_sleep_on(&pb->capq);
+ wait_event(pb->capq, !pb->grabbing);
pb->maxlines = maxlines;
pb->win.norm = v.norm;
/* Stop overlay if running */
struct video_window vw;
struct video_clip clip;
int i;
-
+
DEBUG("PlanB: IOCTL VIDIOCSWIN\n");
if(copy_from_user(&vw,arg,sizeof(vw)))
return -EFAULT;
return 0;
}
- case VIDIOCSYNC: {
+ case VIDIOCSYNC: {
int i;
IDEBUG("PlanB: IOCTL VIDIOCSYNC\n");
IDEBUG("PlanB: sync to frame %d\n", i);
- if(i > (MAX_GBUFFERS - 1) || i < 0)
- return -EINVAL;
+ if(i > (MAX_GBUFFERS - 1) || i < 0)
+ return -EINVAL;
chk_grab:
- switch (pb->frame_stat[i]) {
- case GBUFFER_UNUSED:
- return -EINVAL;
+ switch (pb->frame_stat[i]) {
+ case GBUFFER_UNUSED:
+ return -EINVAL;
case GBUFFER_GRABBING:
IDEBUG("PlanB: waiting for grab"
" done (%d)\n", i);
- interruptible_sleep_on(&pb->capq);
+ interruptible_sleep_on(&pb->capq);
if(signal_pending(current))
return -EINTR;
goto chk_grab;
- case GBUFFER_DONE:
- pb->frame_stat[i] = GBUFFER_UNUSED;
- break;
- }
- return 0;
+ case GBUFFER_DONE:
+ pb->frame_stat[i] = GBUFFER_UNUSED;
+ break;
+ }
+ return 0;
}
- case VIDIOCMCAPTURE:
+ case VIDIOCMCAPTURE:
{
- struct video_mmap vm;
+ struct video_mmap vm;
volatile unsigned int status;
IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n");
if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
return -EFAULT;
- status = pb->frame_stat[vm.frame];
- if (status != GBUFFER_UNUSED)
- return -EBUSY;
+ status = pb->frame_stat[vm.frame];
+ if (status != GBUFFER_UNUSED)
+ return -EBUSY;
- return vgrab(pb, &vm);
+ return vgrab(pb, &vm);
}
-
+
case VIDIOCGMBUF:
{
int i;
return -EFAULT;
return 0;
}
-
+
case PLANBIOCGSAAREGS:
{
struct planb_saa_regs preg;
return -EFAULT;
return 0;
}
-
+
case PLANBIOCSSAAREGS:
{
struct planb_saa_regs preg;
saa_set (preg.addr, preg.val, pb);
return 0;
}
-
+
case PLANBIOCGSTAT:
{
struct planb_stat_regs pstat;
return -EFAULT;
return 0;
}
-
+
case PLANBIOCSMODE: {
int v;
{
int i;
struct planb *pb = (struct planb *)dev;
- unsigned long start = (unsigned long)adr;
+ unsigned long start = (unsigned long)adr;
if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)
- return -EINVAL;
+ return -EINVAL;
if (!pb->rawbuf) {
int err;
if((err=grabbuf_alloc(pb)))
return err;
}
for (i = 0; i < pb->rawbuf_size; i++) {
- if (remap_page_range(vma, start, virt_to_phys((void *)pb->rawbuf[i]),
- PAGE_SIZE, PAGE_SHARED))
+ unsigned long pfn;
+
+ pfn = virt_to_phys((void *)pb->rawbuf[i]) >> PAGE_SHIFT;
+ if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
return -EAGAIN;
start += PAGE_SIZE;
if (size <= PAGE_SIZE)
#endif
pb->tab_size = PLANB_MAXLINES + 40;
pb->suspend = 0;
- init_MUTEX(&pb->lock);
+ mutex_init(&pb->lock);
pb->ch1_cmd = 0;
pb->ch2_cmd = 0;
pb->mask = 0;
/* clear interrupt mask */
pb->intr_mask = PLANB_CLR_IRQ;
- result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
- if (result < 0) {
- if (result==-EINVAL)
- printk(KERN_ERR "PlanB: Bad irq number (%d) "
+ result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
+ if (result < 0) {
+ if (result==-EINVAL)
+ printk(KERN_ERR "PlanB: Bad irq number (%d) "
"or handler\n", (int)pb->irq);
else if (result==-EBUSY)
printk(KERN_ERR "PlanB: I don't know why, "
return result;
}
disable_irq(pb->irq);
-
+
/* Now add the template and register the device unit. */
memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));
}
/*
- * Scan for a PlanB controller, request the irq and map the io memory
+ * Scan for a PlanB controller, request the irq and map the io memory
*/
static int find_planb(void)
struct pci_dev *pdev;
int rc;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return 0;
planb_devices = find_devices("planb");
pb = &planbs[0];
planb_num = 1;
- if (planb_devices->n_addrs != 1) {
- printk (KERN_WARNING "PlanB: expecting 1 address for planb "
- "(got %d)", planb_devices->n_addrs);
+ if (planb_devices->n_addrs != 1) {
+ printk (KERN_WARNING "PlanB: expecting 1 address for planb "
+ "(got %d)", planb_devices->n_addrs);
return 0;
}
pb->planb_base = planb_regs;
pb->planb_base_phys = (struct planb_registers *)new_base;
pb->irq = irq;
-
+
return planb_num;
err_out_disable:
int i;
struct planb *pb;
- for (i=0;i<planb_num; i++)
+ for (i=0;i<planb_num; i++)
{
pb=&planbs[i];
static int __init init_planbs(void)
{
int i;
-
+
if (find_planb()<=0)
return -EIO;
" with v4l\n", i);
release_planb();
return -EIO;
- }
+ }
printk(KERN_INFO "PlanB: registered device %d with v4l\n", i);
- }
+ }
return 0;
}