mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 16:54:20 +08:00
Staging: dt3155: remove the driver
There is now a proper V4L driver for this device in the tree, so remove this one. Cc: Scott Smedley <ss@aao.gov.au> Cc: H Hartley Sweeten <hartleys@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
084f70ee09
commit
8c310573fe
@ -131,8 +131,6 @@ source "drivers/staging/samsung-laptop/Kconfig"
|
||||
|
||||
source "drivers/staging/sm7xx/Kconfig"
|
||||
|
||||
source "drivers/staging/dt3155/Kconfig"
|
||||
|
||||
source "drivers/staging/dt3155v4l/Kconfig"
|
||||
|
||||
source "drivers/staging/crystalhd/Kconfig"
|
||||
|
@ -46,7 +46,6 @@ obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
|
||||
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
|
||||
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
|
||||
obj-$(CONFIG_FB_SM7XX) += sm7xx/
|
||||
obj-$(CONFIG_DT3155) += dt3155/
|
||||
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
|
||||
obj-$(CONFIG_CRYSTALHD) += crystalhd/
|
||||
obj-$(CONFIG_CXT1E1) += cxt1e1/
|
||||
|
@ -1,4 +0,0 @@
|
||||
config DT3155
|
||||
tristate "DT3155 Digitizer support"
|
||||
depends on PCI
|
||||
|
@ -1,6 +0,0 @@
|
||||
obj-$(CONFIG_DT3155) += dt3155.o
|
||||
dt3155-objs := \
|
||||
dt3155_drv.o \
|
||||
dt3155_isr.o \
|
||||
dt3155_io.o \
|
||||
allocator.o
|
@ -1,10 +0,0 @@
|
||||
TODO:
|
||||
- fix checkpatch.pl issues
|
||||
- remove old kernel support, it is not needed
|
||||
- convert to proper PCI device API
|
||||
- fix sparse warnings
|
||||
- audit for correct subsystem interaction
|
||||
- review review review!
|
||||
|
||||
Please send patches to Greg Kroah-Hartman <greg@kroah.com>
|
||||
and Scott Smedley <ss@aao.gov.au>
|
@ -1,98 +0,0 @@
|
||||
|
||||
The allocator shown here exploits high memory. This document explains
|
||||
how a user can deal with drivers uses this allocator and how a
|
||||
programmer can link in the module.
|
||||
|
||||
The module is being used by my pxc and pxdrv device drivers (as well as
|
||||
other ones), available from ftp.systemy.it/pub/develop and
|
||||
ftp.linux.it/pub/People/Rubini
|
||||
|
||||
User's manual
|
||||
=============
|
||||
|
||||
|
||||
One of the most compelling problems with any DMA-capable device is the
|
||||
allocation of a suitable memory buffer. The "allocator" module tries
|
||||
to deal with the problem in a clean way. The module is able to use
|
||||
high memory (above the one used in normal operation) for DMA
|
||||
allocation.
|
||||
|
||||
To prevent the kernel for using high memory, so that it remains
|
||||
available for DMA, you should pass a command line argument to the
|
||||
kernel. Command line arguments can be passed to Lilo, to Loadlin or
|
||||
to whichever loader you are using (unless it's very poor in design).
|
||||
For Lilo, either use "append=" in /etc/lilo.conf or add commandline
|
||||
arguments to the interactive prompt. For example, I have a 32MB box
|
||||
and reserve two megs for DMA:
|
||||
|
||||
In lilo.conf:
|
||||
image = /zImage
|
||||
label = linux
|
||||
append = "mem=30M"
|
||||
|
||||
Or, interactively:
|
||||
LILO: linux mem=30M
|
||||
|
||||
Once the kernel is booted with the right command-line argument, any
|
||||
driver linked with the allocator module will be able to get
|
||||
DMA-capable memory without much trouble (unless the various drivers
|
||||
need more memory than available).
|
||||
|
||||
The module implements an alloc/free mechanism, so that it can serve
|
||||
multiple drivers at the same time. Note however that the allocator
|
||||
uses all of high memory and assumes to be the only piece of software
|
||||
using such memory.
|
||||
|
||||
|
||||
Programmer's manual
|
||||
===================
|
||||
|
||||
The allocator, as released, is designed to be linked to a device
|
||||
driver. In this case, the driver must call allocator_init() before
|
||||
using the allocator and must call allocator_cleanup() before
|
||||
unloading. This is usually done from within init_module() and
|
||||
cleanup_module(). If the allocator is linked to a driver, it won't be
|
||||
possible for several drivers to allocate high DMA memory, as explained
|
||||
above.
|
||||
|
||||
It is possible, on the other hand, to compile the module as a standalone
|
||||
module, so that several modules can rely on the allocator for they DMA
|
||||
buffers. To compile the allocator as a standalone module, do the
|
||||
following in this directory (or provide a suitable Makefile, or edit
|
||||
the source code):
|
||||
|
||||
make allocator.o CC="gcc -Dallocator_init=init_module -Dallocator_cleanup=cleanup_module -include /usr/include/linux/module.h"
|
||||
|
||||
The previous commandline tells to include <linux/module.h> in the
|
||||
first place, and to rename the init and cleanup function to the ones
|
||||
needed for module loading and unloading. Drivers using a standalone
|
||||
allocator won't need to call allocator_init() nor allocator_cleanup().
|
||||
|
||||
The allocator exports the following functions (declared in allocator.h):
|
||||
|
||||
unsigned long allocator_allocate_dma (unsigned long kilobytes,
|
||||
int priority);
|
||||
|
||||
This function returns a physical address, over high_memory,
|
||||
which corresponds to an area of at least "kilobytes" kilobytes.
|
||||
The area will be owned by the module calling the function.
|
||||
The returned address can be passed to device boards, to instruct
|
||||
their DMA controllers, via phys_to_bus(). The address can be used
|
||||
by C code after vremap()/ioremap(). The "priority" argument should
|
||||
be GFP_KERNEL or GFP_ATOMIC, according to the context of the
|
||||
caller; it is used to call kmalloc(), as the allocator must keep
|
||||
track of any region it gives away. In case of error the function
|
||||
returns 0, and the caller is expected to issue a -ENOMEM error.
|
||||
|
||||
|
||||
void allocator_free_dma (unsigned long address);
|
||||
|
||||
This function is the reverse of the previous one. If a driver
|
||||
doesn't free the DMA memory it allocated, the allocator will
|
||||
consider such memory as busy. Note, however, that
|
||||
allocator_cleanup() calls kfree() on every region it reclaimed,
|
||||
so that a driver with the allocator linked in can avoid calling
|
||||
allocator_free_dma() at unload time.
|
||||
|
||||
|
||||
|
@ -1,294 +0,0 @@
|
||||
/*
|
||||
* allocator.c -- allocate after high_memory, if available
|
||||
*
|
||||
* NOTE: this is different from my previous allocator, the one that
|
||||
* assembles pages, which revealed itself both slow and unreliable.
|
||||
*
|
||||
* Copyright (C) 1998 rubini@linux.it (Alessandro Rubini)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
|
||||
-- Changes --
|
||||
|
||||
Date Programmer Description of changes made
|
||||
-------------------------------------------------------------------
|
||||
02-Aug-2002 NJC allocator now steps in 1MB increments, rather
|
||||
than doubling its size each time.
|
||||
Also, allocator_init(u32 *) now returns
|
||||
(in the first arg) the size of the free
|
||||
space. This is no longer consistent with
|
||||
using the allocator as a module, and some changes
|
||||
may be necessary for that purpose. This was
|
||||
designed to work with the DT3155 driver, in
|
||||
stand alone mode only!!!
|
||||
26-Oct-2009 SS Port to 2.6.30 kernel.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __KERNEL__
|
||||
# define __KERNEL__
|
||||
#endif
|
||||
#ifndef MODULE
|
||||
# define MODULE
|
||||
#endif
|
||||
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mm.h> /* PAGE_ALIGN() */
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#include "allocator.h"
|
||||
|
||||
/*#define ALL_DEBUG*/
|
||||
#define ALL_MSG "allocator: "
|
||||
|
||||
#undef PDEBUG /* undef it, just in case */
|
||||
#ifdef ALL_DEBUG
|
||||
# define __static
|
||||
# define DUMP_LIST() dump_list()
|
||||
# ifdef __KERNEL__
|
||||
/* This one if debugging is on, and kernel space */
|
||||
# define PDEBUG(fmt, args...) printk(KERN_DEBUG ALL_MSG fmt, ## args)
|
||||
# else
|
||||
/* This one for user space */
|
||||
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
|
||||
# endif
|
||||
#else
|
||||
# define PDEBUG(fmt, args...) /* not debugging: nothing */
|
||||
# define DUMP_LIST()
|
||||
# define __static static
|
||||
#endif
|
||||
|
||||
#undef PDEBUGG
|
||||
#define PDEBUGG(fmt, args...)
|
||||
/*#define PDEBUGG(fmt, args...) printk( KERN_DEBUG ALL_MSG fmt, ## args)*/
|
||||
|
||||
|
||||
static int allocator_himem = 1; /* 0 = probe, pos. = megs, neg. = disable */
|
||||
static int allocator_step = 1; /* This is the step size in MB */
|
||||
static int allocator_probe = 1; /* This is a flag -- 1=probe, 0=don't probe */
|
||||
|
||||
static unsigned long allocator_buffer; /* physical address */
|
||||
static unsigned long allocator_buffer_size; /* kilobytes */
|
||||
|
||||
/*
|
||||
* The allocator keeps a list of DMA areas, so multiple devices
|
||||
* can coexist. The list is kept sorted by address
|
||||
*/
|
||||
|
||||
struct allocator_struct {
|
||||
unsigned long address;
|
||||
unsigned long size;
|
||||
struct allocator_struct *next;
|
||||
};
|
||||
|
||||
static struct allocator_struct *allocator_list;
|
||||
|
||||
#ifdef ALL_DEBUG
|
||||
static int dump_list(void)
|
||||
{
|
||||
struct allocator_struct *ptr;
|
||||
|
||||
PDEBUG("Current list:\n");
|
||||
for (ptr = allocator_list; ptr; ptr = ptr->next)
|
||||
PDEBUG("0x%08lx (size %likB)\n", ptr->address, ptr->size>>10);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================================================================
|
||||
* This function is the actual allocator.
|
||||
*
|
||||
* If space is available in high memory (as detected at load time), that
|
||||
* one is returned. The return value is a physical address (i.e., it can
|
||||
* be used straight ahead for DMA, but needs remapping for program use).
|
||||
*/
|
||||
|
||||
unsigned long allocator_allocate_dma(unsigned long kilobytes, gfp_t flags)
|
||||
{
|
||||
struct allocator_struct *ptr = allocator_list, *newptr;
|
||||
unsigned long bytes = kilobytes << 10;
|
||||
|
||||
/* check if high memory is available */
|
||||
if (!allocator_buffer)
|
||||
return 0;
|
||||
|
||||
/* Round it to a multiple of the pagesize */
|
||||
bytes = PAGE_ALIGN(bytes);
|
||||
PDEBUG("request for %li bytes\n", bytes);
|
||||
|
||||
while (ptr && ptr->next) {
|
||||
if (ptr->next->address - (ptr->address + ptr->size) >= bytes)
|
||||
break; /* enough space */
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (!ptr->next) {
|
||||
DUMP_LIST();
|
||||
PDEBUG("alloc failed\n");
|
||||
return 0; /* end of list */
|
||||
}
|
||||
newptr = kmalloc(sizeof(struct allocator_struct), flags);
|
||||
if (!newptr)
|
||||
return 0;
|
||||
|
||||
/* ok, now stick it after ptr */
|
||||
newptr->address = ptr->address + ptr->size;
|
||||
newptr->size = bytes;
|
||||
newptr->next = ptr->next;
|
||||
ptr->next = newptr;
|
||||
|
||||
DUMP_LIST();
|
||||
PDEBUG("returning 0x%08lx\n", newptr->address);
|
||||
return newptr->address;
|
||||
}
|
||||
|
||||
int allocator_free_dma(unsigned long address)
|
||||
{
|
||||
struct allocator_struct *ptr = allocator_list, *prev;
|
||||
|
||||
while (ptr && ptr->next) {
|
||||
if (ptr->next->address == address)
|
||||
break;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
/* the one being freed is ptr->next */
|
||||
prev = ptr; ptr = ptr->next;
|
||||
|
||||
if (!ptr) {
|
||||
pr_err(ALL_MSG "free_dma but add. not allocated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,
|
||||
ptr->next->address);
|
||||
prev->next = ptr->next;
|
||||
kfree(ptr);
|
||||
|
||||
/* dump_list(); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ========================================================================
|
||||
* Init and cleanup
|
||||
*
|
||||
* On cleanup everything is released. If the list is not empty, that a
|
||||
* problem of our clients
|
||||
*/
|
||||
int allocator_init(u32 *allocator_max)
|
||||
{
|
||||
/* check how much free memory is there */
|
||||
void *remapped;
|
||||
unsigned long max;
|
||||
unsigned long trial_size = allocator_himem<<20;
|
||||
unsigned long last_trial = 0;
|
||||
unsigned long step = allocator_step<<20;
|
||||
unsigned long i = 0;
|
||||
struct allocator_struct *head, *tail;
|
||||
char test_string[] = "0123456789abcde"; /* 16 bytes */
|
||||
|
||||
PDEBUGG("himem = %i\n", allocator_himem);
|
||||
if (allocator_himem < 0) /* don't even try */
|
||||
return -EINVAL;
|
||||
|
||||
if (!trial_size)
|
||||
trial_size = 1<<20; /* not specified: try one meg */
|
||||
|
||||
while (1) {
|
||||
remapped = ioremap(__pa(high_memory), trial_size);
|
||||
if (!remapped) {
|
||||
PDEBUGG("%li megs failed!\n", trial_size>>20);
|
||||
break;
|
||||
}
|
||||
PDEBUGG("Trying %li megs (at %p, %p)\n", trial_size>>20,
|
||||
(void *)__pa(high_memory), remapped);
|
||||
for (i = last_trial; i < trial_size; i += 16) {
|
||||
strcpy((char *)(remapped)+i, test_string);
|
||||
if (strcmp((char *)(remapped)+i, test_string))
|
||||
break;
|
||||
}
|
||||
iounmap((void *)remapped);
|
||||
schedule();
|
||||
last_trial = trial_size;
|
||||
if (i == trial_size)
|
||||
trial_size += step; /* increment, if all went well */
|
||||
else {
|
||||
PDEBUGG("%li megs copy test failed!\n", trial_size>>20);
|
||||
break;
|
||||
}
|
||||
if (!allocator_probe)
|
||||
break;
|
||||
}
|
||||
PDEBUG("%li megs (%li k, %li b)\n", i>>20, i>>10, i);
|
||||
allocator_buffer_size = i>>10; /* kilobytes */
|
||||
allocator_buffer = __pa(high_memory);
|
||||
if (!allocator_buffer_size) {
|
||||
printk(KERN_WARNING ALL_MSG "no free high memory to use\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* to simplify things, always have two cells in the list:
|
||||
* the first and the last. This avoids some conditionals and
|
||||
* extra code when allocating and deallocating: we only play
|
||||
* in the middle of the list
|
||||
*/
|
||||
head = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
|
||||
if (!head)
|
||||
return -ENOMEM;
|
||||
tail = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
|
||||
if (!tail) {
|
||||
kfree(head);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
max = allocator_buffer_size<<10;
|
||||
|
||||
head->size = tail->size = 0;
|
||||
head->address = allocator_buffer;
|
||||
tail->address = allocator_buffer + max;
|
||||
head->next = tail;
|
||||
tail->next = NULL;
|
||||
allocator_list = head;
|
||||
|
||||
/* Back to the user code, in KB */
|
||||
*allocator_max = allocator_buffer_size;
|
||||
|
||||
return 0; /* ok, ready */
|
||||
}
|
||||
|
||||
void allocator_cleanup(void)
|
||||
{
|
||||
struct allocator_struct *ptr, *next;
|
||||
|
||||
for (ptr = allocator_list; ptr; ptr = next) {
|
||||
next = ptr->next;
|
||||
PDEBUG("freeing list: 0x%08lx\n", ptr->address);
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
allocator_buffer = 0;
|
||||
allocator_buffer_size = 0;
|
||||
allocator_list = NULL;
|
||||
}
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* allocator.h -- prototypes for allocating high memory
|
||||
*
|
||||
* NOTE: this is different from my previous allocator, the one that
|
||||
* assembles pages, which revealed itself both slow and unreliable.
|
||||
*
|
||||
* Copyright (C) 1998 rubini@linux.it (Alessandro Rubini)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
int allocator_free_dma(unsigned long address);
|
||||
unsigned long allocator_allocate_dma(unsigned long kilobytes, gfp_t flags);
|
||||
int allocator_init(u32 *);
|
||||
void allocator_cleanup(void);
|
@ -1,161 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
|
||||
Jason Lapenta, Scott Smedley
|
||||
|
||||
This file is part of the DT3155 Device Driver.
|
||||
|
||||
The DT3155 Device Driver 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.
|
||||
|
||||
The DT3155 Device Driver is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the DT3155 Device Driver; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
-- Changes --
|
||||
|
||||
Date Programmer Description of changes made
|
||||
-------------------------------------------------------------------
|
||||
03-Jul-2000 JML n/a
|
||||
10-Oct-2001 SS port to 2.4 kernel.
|
||||
24-Jul-2002 SS remove unused code & added GPL licence.
|
||||
05-Aug-2005 SS port to 2.6 kernel; make CCIR mode default.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DT3155_INC
|
||||
#define _DT3155_INC
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/time.h> /* struct timeval */
|
||||
|
||||
|
||||
/* Uncomment this for 50Hz CCIR */
|
||||
#define CCIR 1
|
||||
|
||||
/* Can be 1 or 2 */
|
||||
#define MAXBOARDS 1
|
||||
|
||||
#define BOARD_MAX_BUFFS 3
|
||||
#define MAXBUFFERS (BOARD_MAX_BUFFS*MAXBOARDS)
|
||||
|
||||
#define PCI_PAGE_SIZE (1 << 12)
|
||||
|
||||
#ifdef CCIR
|
||||
#define DT3155_MAX_ROWS 576
|
||||
#define DT3155_MAX_COLS 768
|
||||
#define FORMAT50HZ 1
|
||||
#else
|
||||
#define DT3155_MAX_ROWS 480
|
||||
#define DT3155_MAX_COLS 640
|
||||
#define FORMAT50HZ 0
|
||||
#endif
|
||||
|
||||
/* Configuration structure */
|
||||
struct dt3155_config {
|
||||
u32 acq_mode;
|
||||
u32 cols, rows;
|
||||
u32 continuous;
|
||||
};
|
||||
|
||||
|
||||
/* hold data for each frame */
|
||||
struct frame_info {
|
||||
u32 addr; /* address of the buffer with the frame */
|
||||
u32 tag; /* unique number for the frame */
|
||||
struct timeval time; /* time that capture took place */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for interrupt and buffer handling.
|
||||
* This is the setup for 1 card
|
||||
*/
|
||||
struct dt3155_fbuffer {
|
||||
int nbuffers;
|
||||
|
||||
struct frame_info frame_info[BOARD_MAX_BUFFS];
|
||||
|
||||
int empty_buffers[BOARD_MAX_BUFFS]; /* indexes empty frames */
|
||||
int empty_len; /* Number of empty buffers */
|
||||
/* Zero means empty */
|
||||
|
||||
int active_buf; /* Where data is currently dma'ing */
|
||||
int locked_buf; /* Buffers used by user */
|
||||
|
||||
int ready_que[BOARD_MAX_BUFFS];
|
||||
u32 ready_head; /* The most recent buffer located here */
|
||||
u32 ready_len; /* The number of ready buffers */
|
||||
|
||||
int even_happened;
|
||||
int even_stopped;
|
||||
|
||||
int stop_acquire; /* Flag to stop interrupts */
|
||||
u32 frame_count; /* Counter for frames acquired by this card */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define DT3155_MODE_FRAME 1
|
||||
#define DT3155_MODE_FIELD 2
|
||||
|
||||
#define DT3155_SNAP 1
|
||||
#define DT3155_ACQ 2
|
||||
|
||||
/* There is one status structure for each card. */
|
||||
struct dt3155_status {
|
||||
int fixed_mode; /* if 1, we are in fixed frame mode */
|
||||
u32 reg_addr; /* Register address for a single card */
|
||||
u32 mem_addr; /* Buffer start addr for this card */
|
||||
u32 mem_size; /* This is the amount of mem available */
|
||||
u32 irq; /* this card's irq */
|
||||
struct dt3155_config config; /* configuration struct */
|
||||
struct dt3155_fbuffer fbuffer; /* frame buffer state struct */
|
||||
u32 state; /* this card's state */
|
||||
u32 device_installed; /* Flag if installed. 1=installed */
|
||||
};
|
||||
|
||||
/* Reference to global status structure */
|
||||
extern struct dt3155_status dt3155_status[MAXBOARDS];
|
||||
|
||||
#define DT3155_STATE_IDLE 0x00
|
||||
#define DT3155_STATE_FRAME 0x01
|
||||
#define DT3155_STATE_FLD 0x02
|
||||
#define DT3155_STATE_STOP 0x100
|
||||
#define DT3155_STATE_ERROR 0x200
|
||||
#define DT3155_STATE_MODE 0x0ff
|
||||
|
||||
#define DT3155_IOC_MAGIC '!'
|
||||
|
||||
#define DT3155_SET_CONFIG _IOW(DT3155_IOC_MAGIC, 1, struct dt3155_config)
|
||||
#define DT3155_GET_CONFIG _IOR(DT3155_IOC_MAGIC, 2, struct dt3155_status)
|
||||
#define DT3155_STOP _IO(DT3155_IOC_MAGIC, 3)
|
||||
#define DT3155_START _IO(DT3155_IOC_MAGIC, 4)
|
||||
#define DT3155_FLUSH _IO(DT3155_IOC_MAGIC, 5)
|
||||
#define DT3155_IOC_MAXNR 5
|
||||
|
||||
/* Error codes */
|
||||
|
||||
#define DT_ERR_NO_BUFFERS 0x10000 /* not used but it might be one day */
|
||||
#define DT_ERR_CORRUPT 0x20000
|
||||
#define DT_ERR_OVERRUN 0x30000
|
||||
#define DT_ERR_I2C_TIMEOUT 0x40000
|
||||
#define DT_ERR_MASK 0xff0000/* not used but it might be one day */
|
||||
|
||||
/* User code will probably want to declare one of these for each card */
|
||||
struct dt3155_read {
|
||||
u32 offset;
|
||||
u32 frame_seq;
|
||||
u32 state;
|
||||
|
||||
struct frame_info frame_info;
|
||||
};
|
||||
|
||||
#endif /* _DT3155_inc */
|
@ -1,60 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Module load/unload script for use with SysV-style /etc/init.d/ systems.
|
||||
# On a Debian system, copy this to /etc/init.d/dt3155 and then run
|
||||
# /usr/sbin/update-rc.d dt3155 defaults 55
|
||||
# to create the appropriate /etc/rc?.d/[SK]55dt3155 start/stop links.
|
||||
# (The "55" is arbitrary but is what I use to load this rather late.)
|
||||
#
|
||||
# Andy Dougherty Feb 22 2000 doughera@lafayette.edu
|
||||
# Dept. of Physics
|
||||
# Lafayette College, Easton PA 18042
|
||||
#
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
# Edit to point to your local copy.
|
||||
FILE=/usr/local/lib/modules/dt3155/dt3155.o
|
||||
NAME="dt3155"
|
||||
DESC="dt3155 Frame Grabber module"
|
||||
DEV="dt3155"
|
||||
|
||||
if test ! -f $FILE; then
|
||||
echo "Unable to locate $FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Loading $DESC "
|
||||
if /sbin/insmod -v -f $FILE; then
|
||||
major=`grep $DEV /proc/devices | awk "{print \\$1}"`
|
||||
rm -f /dev/dt3155?
|
||||
mknod /dev/dt3155a c $major 0
|
||||
mknod /dev/dt3155b c $major 1
|
||||
chmod go+rw /dev/dt3155?
|
||||
echo
|
||||
else
|
||||
echo "$FILE not loaded."
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
echo -n "Unloading $DESC: "
|
||||
if /sbin/rmmod $NAME ; then
|
||||
echo
|
||||
else
|
||||
echo "$DEV not removed"
|
||||
exit 0
|
||||
fi
|
||||
rm -f /dev/dt3155?
|
||||
;;
|
||||
*)
|
||||
echo "Usage: /etc/init.d/$NAME {start|stop}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,39 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
|
||||
Scott Smedley
|
||||
|
||||
This file is part of the DT3155 Device Driver.
|
||||
|
||||
The DT3155 Device Driver 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.
|
||||
|
||||
The DT3155 Device Driver is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the DT3155 Device Driver; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DT3155_DRV_INC
|
||||
#define DT3155_DRV_INC
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/wait.h>
|
||||
|
||||
/* wait queue for reads */
|
||||
extern wait_queue_head_t dt3155_read_wait_queue[MAXBOARDS];
|
||||
#endif
|
||||
|
||||
/* number of devices */
|
||||
extern u32 ndevices;
|
||||
|
||||
extern int dt3155_errno;
|
||||
|
||||
#endif
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
|
||||
* Jason Lapenta, Scott Smedley
|
||||
*
|
||||
* This file is part of the DT3155 Device Driver.
|
||||
*
|
||||
* The DT3155 Device Driver 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.
|
||||
*
|
||||
* The DT3155 Device Driver is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file provides some basic register io routines. It is modified from
|
||||
* demo code provided by Data Translations.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "dt3155.h"
|
||||
#include "dt3155_io.h"
|
||||
#include "dt3155_drv.h"
|
||||
|
||||
|
||||
/*
|
||||
* wait_ibsyclr()
|
||||
*
|
||||
* This function handles read/write timing and r/w timeout error
|
||||
*/
|
||||
static int wait_ibsyclr(void __iomem *mmio)
|
||||
{
|
||||
IIC_CSR2_R iic_csr2_r;
|
||||
|
||||
/* wait 100 microseconds */
|
||||
udelay(100L);
|
||||
/* __delay(loops_per_sec/10000); */
|
||||
|
||||
iic_csr2_r.reg = readl(mmio + IIC_CSR2);
|
||||
if (iic_csr2_r.fld.NEW_CYCLE) {
|
||||
/* if NEW_CYCLE didn't clear */
|
||||
/* TIMEOUT ERROR */
|
||||
dt3155_errno = DT_ERR_I2C_TIMEOUT;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0; /* no error */
|
||||
}
|
||||
|
||||
/*
|
||||
* WriteI2C()
|
||||
*
|
||||
* This function handles writing to 8-bit DT3155 registers
|
||||
*
|
||||
* 1st parameter is pointer to 32-bit register base address
|
||||
* 2nd parameter is reg. index;
|
||||
* 3rd is value to be written
|
||||
*/
|
||||
int WriteI2C(void __iomem *mmio, u_short wIregIndex, u8 byVal)
|
||||
{
|
||||
IIC_CSR2_R iic_csr2_r;
|
||||
|
||||
/* read 32 bit IIC_CSR2 register data into union */
|
||||
iic_csr2_r.reg = readl(mmio + IIC_CSR2);
|
||||
|
||||
/* for write operation */
|
||||
iic_csr2_r.fld.DIR_RD = 0;
|
||||
/* I2C address of I2C register: */
|
||||
iic_csr2_r.fld.DIR_ADDR = wIregIndex;
|
||||
/* 8 bit data to be written to I2C reg */
|
||||
iic_csr2_r.fld.DIR_WR_DATA = byVal;
|
||||
/* will start a direct I2C cycle: */
|
||||
iic_csr2_r.fld.NEW_CYCLE = 1;
|
||||
|
||||
/* xfer union data into 32 bit IIC_CSR2 register */
|
||||
writel(iic_csr2_r.reg, mmio + IIC_CSR2);
|
||||
|
||||
/* wait for IIC cycle to finish */
|
||||
return wait_ibsyclr(mmio);
|
||||
}
|
||||
|
||||
/*
|
||||
* ReadI2C()
|
||||
*
|
||||
* This function handles reading from 8-bit DT3155 registers
|
||||
*
|
||||
* 1st parameter is pointer to 32-bit register base address
|
||||
* 2nd parameter is reg. index;
|
||||
* 3rd is adrs of value to be read
|
||||
*/
|
||||
int ReadI2C(void __iomem *mmio, u_short wIregIndex, u8 *byVal)
|
||||
{
|
||||
IIC_CSR1_R iic_csr1_r;
|
||||
IIC_CSR2_R iic_csr2_r;
|
||||
int writestat; /* status for return */
|
||||
|
||||
/* read 32 bit IIC_CSR2 register data into union */
|
||||
iic_csr2_r.reg = readl(mmio + IIC_CSR2);
|
||||
|
||||
/* for read operation */
|
||||
iic_csr2_r.fld.DIR_RD = 1;
|
||||
|
||||
/* I2C address of I2C register: */
|
||||
iic_csr2_r.fld.DIR_ADDR = wIregIndex;
|
||||
|
||||
/* will start a direct I2C cycle: */
|
||||
iic_csr2_r.fld.NEW_CYCLE = 1;
|
||||
|
||||
/* xfer union's data into 32 bit IIC_CSR2 register */
|
||||
writel(iic_csr2_r.reg, mmio + IIC_CSR2);
|
||||
|
||||
/* wait for IIC cycle to finish */
|
||||
writestat = wait_ibsyclr(mmio);
|
||||
|
||||
/* Next 2 commands read 32 bit IIC_CSR1 register's data into union */
|
||||
/* first read data is in IIC_CSR1 */
|
||||
iic_csr1_r.reg = readl(mmio + IIC_CSR1);
|
||||
|
||||
/* now get data u8 out of register */
|
||||
*byVal = (u8) iic_csr1_r.fld.RD_DATA;
|
||||
|
||||
return writestat;
|
||||
}
|
@ -1,304 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
|
||||
Jason Lapenta, Scott Smedley
|
||||
|
||||
This file is part of the DT3155 Device Driver.
|
||||
|
||||
The DT3155 Device Driver 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.
|
||||
|
||||
The DT3155 Device Driver is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the DT3155 Device Driver; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
|
||||
-- Changes --
|
||||
|
||||
Date Programmer Description of changes made
|
||||
-------------------------------------------------------------------
|
||||
24-Jul-2002 SS GPL licence.
|
||||
|
||||
*/
|
||||
|
||||
/* This code is a modified version of examples provided by Data Translations.*/
|
||||
|
||||
#ifndef DT3155_IO_INC
|
||||
#define DT3155_IO_INC
|
||||
|
||||
/***************** 32 bit register globals **************/
|
||||
|
||||
/* offsets for 32-bit memory mapped registers */
|
||||
|
||||
#define EVEN_DMA_START 0x000
|
||||
#define ODD_DMA_START 0x00C
|
||||
#define EVEN_DMA_STRIDE 0x018
|
||||
#define ODD_DMA_STRIDE 0x024
|
||||
#define EVEN_PIXEL_FMT 0x030
|
||||
#define ODD_PIXEL_FMT 0x034
|
||||
#define FIFO_TRIGGER 0x038
|
||||
#define XFER_MODE 0x03C
|
||||
#define CSR1 0x040
|
||||
#define RETRY_WAIT_CNT 0x044
|
||||
#define INT_CSR 0x048
|
||||
#define EVEN_FLD_MASK 0x04C
|
||||
#define ODD_FLD_MASK 0x050
|
||||
#define MASK_LENGTH 0x054
|
||||
#define FIFO_FLAG_CNT 0x058
|
||||
#define IIC_CLK_DUR 0x05C
|
||||
#define IIC_CSR1 0x060
|
||||
#define IIC_CSR2 0x064
|
||||
#define EVEN_DMA_UPPR_LMT 0x08C
|
||||
#define ODD_DMA_UPPR_LMT 0x090
|
||||
|
||||
#define CLK_DUR_VAL 0x01010101
|
||||
|
||||
|
||||
|
||||
/******** Assignments and Typedefs for 32 bit Memory Mapped Registers ********/
|
||||
|
||||
typedef union fifo_trigger_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 PACKED:6;
|
||||
u32 :9;
|
||||
u32 PLANER:7;
|
||||
u32 :9;
|
||||
} fld;
|
||||
} FIFO_TRIGGER_R;
|
||||
|
||||
typedef union xfer_mode_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 :2;
|
||||
u32 FIELD_TOGGLE:1;
|
||||
u32 :5;
|
||||
u32 :2;
|
||||
u32 :22;
|
||||
} fld;
|
||||
} XFER_MODE_R;
|
||||
|
||||
typedef union csr1_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 CAP_CONT_EVE:1;
|
||||
u32 CAP_CONT_ODD:1;
|
||||
u32 CAP_SNGL_EVE:1;
|
||||
u32 CAP_SNGL_ODD:1;
|
||||
u32 FLD_DN_EVE :1;
|
||||
u32 FLD_DN_ODD :1;
|
||||
u32 SRST :1;
|
||||
u32 FIFO_EN :1;
|
||||
u32 FLD_CRPT_EVE:1;
|
||||
u32 FLD_CRPT_ODD:1;
|
||||
u32 ADDR_ERR_EVE:1;
|
||||
u32 ADDR_ERR_ODD:1;
|
||||
u32 CRPT_DIS :1;
|
||||
u32 RANGE_EN :1;
|
||||
u32 :16;
|
||||
} fld;
|
||||
} CSR1_R;
|
||||
|
||||
typedef union retry_wait_cnt_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 RTRY_WAIT_CNT:8;
|
||||
u32 :24;
|
||||
} fld;
|
||||
} RETRY_WAIT_CNT_R;
|
||||
|
||||
typedef union int_csr_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 FLD_END_EVE :1;
|
||||
u32 FLD_END_ODD :1;
|
||||
u32 FLD_START :1;
|
||||
u32 :5;
|
||||
u32 FLD_END_EVE_EN:1;
|
||||
u32 FLD_END_ODD_EN:1;
|
||||
u32 FLD_START_EN :1;
|
||||
u32 :21;
|
||||
} fld;
|
||||
} INT_CSR_R;
|
||||
|
||||
typedef union mask_length_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 MASK_LEN_EVE:5;
|
||||
u32 :11;
|
||||
u32 MASK_LEN_ODD:5;
|
||||
u32 :11;
|
||||
} fld;
|
||||
} MASK_LENGTH_R;
|
||||
|
||||
typedef union fifo_flag_cnt_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 AF_COUNT:7;
|
||||
u32 :9;
|
||||
u32 AE_COUNT:7;
|
||||
u32 :9;
|
||||
} fld;
|
||||
} FIFO_FLAG_CNT_R;
|
||||
|
||||
typedef union iic_clk_dur {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 PHASE_1:8;
|
||||
u32 PHASE_2:8;
|
||||
u32 PHASE_3:8;
|
||||
u32 PHASE_4:8;
|
||||
} fld;
|
||||
} IIC_CLK_DUR_R;
|
||||
|
||||
typedef union iic_csr1_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 AUTO_EN :1;
|
||||
u32 BYPASS :1;
|
||||
u32 SDA_OUT :1;
|
||||
u32 SCL_OUT :1;
|
||||
u32 :4;
|
||||
u32 AUTO_ABORT :1;
|
||||
u32 DIRECT_ABORT:1;
|
||||
u32 SDA_IN :1;
|
||||
u32 SCL_IN :1;
|
||||
u32 :4;
|
||||
u32 AUTO_ADDR :8;
|
||||
u32 RD_DATA :8;
|
||||
} fld;
|
||||
} IIC_CSR1_R;
|
||||
|
||||
/**********************************
|
||||
* iic_csr2_tag
|
||||
*/
|
||||
typedef union iic_csr2_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 DIR_WR_DATA :8;
|
||||
u32 DIR_SUB_ADDR:8;
|
||||
u32 DIR_RD :1;
|
||||
u32 DIR_ADDR :7;
|
||||
u32 NEW_CYCLE :1;
|
||||
u32 :7;
|
||||
} fld;
|
||||
} IIC_CSR2_R;
|
||||
|
||||
/* use for both EVEN and ODD DMA UPPER LIMITS */
|
||||
|
||||
/*
|
||||
* dma_upper_lmt_tag
|
||||
*/
|
||||
typedef union dma_upper_lmt_tag {
|
||||
u32 reg;
|
||||
struct {
|
||||
u32 DMA_UPPER_LMT_VAL:24;
|
||||
u32 :8;
|
||||
} fld;
|
||||
} DMA_UPPER_LMT_R;
|
||||
|
||||
|
||||
/***************** 8 bit I2C register globals ***********/
|
||||
#define CSR2 0x010 /* indices of 8-bit I2C mapped reg's*/
|
||||
#define EVEN_CSR 0x011
|
||||
#define ODD_CSR 0x012
|
||||
#define CONFIG 0x013
|
||||
#define DT_ID 0x01F
|
||||
#define X_CLIP_START 0x020
|
||||
#define Y_CLIP_START 0x022
|
||||
#define X_CLIP_END 0x024
|
||||
#define Y_CLIP_END 0x026
|
||||
#define AD_ADDR 0x030
|
||||
#define AD_LUT 0x031
|
||||
#define AD_CMD 0x032
|
||||
#define DIG_OUT 0x040
|
||||
#define PM_LUT_ADDR 0x050
|
||||
#define PM_LUT_DATA 0x051
|
||||
|
||||
|
||||
/******** Assignments and Typedefs for 8 bit I2C Registers********************/
|
||||
|
||||
typedef union i2c_csr2_tag {
|
||||
u8 reg;
|
||||
struct {
|
||||
u8 CHROM_FIL:1;
|
||||
u8 SYNC_SNTL:1;
|
||||
u8 HZ50:1;
|
||||
u8 SYNC_PRESENT:1;
|
||||
u8 BUSY_EVE:1;
|
||||
u8 BUSY_ODD:1;
|
||||
u8 DISP_PASS:1;
|
||||
} fld;
|
||||
} I2C_CSR2;
|
||||
|
||||
typedef union i2c_even_csr_tag {
|
||||
u8 reg;
|
||||
struct {
|
||||
u8 DONE_EVE :1;
|
||||
u8 SNGL_EVE :1;
|
||||
u8 ERROR_EVE:1;
|
||||
u8 :5;
|
||||
} fld;
|
||||
} I2C_EVEN_CSR;
|
||||
|
||||
typedef union i2c_odd_csr_tag {
|
||||
u8 reg;
|
||||
struct {
|
||||
u8 DONE_ODD:1;
|
||||
u8 SNGL_ODD:1;
|
||||
u8 ERROR_ODD:1;
|
||||
u8 :5;
|
||||
} fld;
|
||||
} I2C_ODD_CSR;
|
||||
|
||||
typedef union i2c_config_tag {
|
||||
u8 reg;
|
||||
struct {
|
||||
u8 ACQ_MODE:2;
|
||||
u8 EXT_TRIG_EN:1;
|
||||
u8 EXT_TRIG_POL:1;
|
||||
u8 H_SCALE:1;
|
||||
u8 CLIP:1;
|
||||
u8 PM_LUT_SEL:1;
|
||||
u8 PM_LUT_PGM:1;
|
||||
} fld;
|
||||
} I2C_CONFIG;
|
||||
|
||||
|
||||
typedef union i2c_ad_cmd_tag {
|
||||
/* bits can have 3 different meanings depending on value of AD_ADDR */
|
||||
u8 reg;
|
||||
/* Bt252 Command Register if AD_ADDR = 00h */
|
||||
struct {
|
||||
u8 :2;
|
||||
u8 SYNC_LVL_SEL:2;
|
||||
u8 SYNC_CNL_SEL:2;
|
||||
u8 DIGITIZE_CNL_SEL1:2;
|
||||
} bt252_command;
|
||||
|
||||
/* Bt252 IOUT0 register if AD_ADDR = 01h */
|
||||
struct {
|
||||
u8 IOUT_DATA:8;
|
||||
} bt252_iout0;
|
||||
|
||||
/* BT252 IOUT1 register if AD_ADDR = 02h */
|
||||
struct {
|
||||
u8 IOUT_DATA:8;
|
||||
} bt252_iout1;
|
||||
} I2C_AD_CMD;
|
||||
|
||||
|
||||
/* access 8-bit IIC registers */
|
||||
|
||||
extern int ReadI2C(void __iomem *mmio, u_short wIregIndex, u8 *byVal);
|
||||
extern int WriteI2C(void __iomem *mmio, u_short wIregIndex, u8 byVal);
|
||||
|
||||
#endif
|
@ -1,461 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
|
||||
Jason Lapenta, Scott Smedley, Greg Sharp
|
||||
|
||||
This file is part of the DT3155 Device Driver.
|
||||
|
||||
The DT3155 Device Driver 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.
|
||||
|
||||
The DT3155 Device Driver is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the DT3155 Device Driver; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
File: dt3155_isr.c
|
||||
Purpose: Buffer management routines, and other routines for the ISR
|
||||
(the actual isr is in dt3155_drv.c)
|
||||
|
||||
-- Changes --
|
||||
|
||||
Date Programmer Description of changes made
|
||||
-------------------------------------------------------------------
|
||||
03-Jul-2000 JML n/a
|
||||
02-Apr-2002 SS Mods to make work with separate allocator
|
||||
module; Merged John Roll's mods to make work with
|
||||
multiple boards.
|
||||
10-Jul-2002 GCS Complete rewrite of setup_buffers to disallow
|
||||
buffers which span a 4MB boundary.
|
||||
24-Jul-2002 SS GPL licence.
|
||||
30-Jul-2002 NJC Added support for buffer loop.
|
||||
31-Jul-2002 NJC Complete rewrite of buffer management
|
||||
02-Aug-2002 NJC Including slab.h instead of malloc.h (no warning).
|
||||
Also, allocator_init() now returns allocator_max
|
||||
so cleaned up allocate_buffers() accordingly.
|
||||
08-Aug-2005 SS port to 2.6 kernel.
|
||||
|
||||
*/
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "dt3155.h"
|
||||
#include "dt3155_drv.h"
|
||||
#include "dt3155_io.h"
|
||||
#include "dt3155_isr.h"
|
||||
#include "allocator.h"
|
||||
|
||||
#define FOUR_MB (0x0400000) /* Can't DMA accross a 4MB boundary!*/
|
||||
#define UPPER_10_BITS (0x3FF<<22) /* Can't DMA accross a 4MB boundary!*/
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Simple array based que struct
|
||||
*
|
||||
* Some handy functions using the buffering structure.
|
||||
*****************************************************************************/
|
||||
|
||||
/***************************
|
||||
* are_empty_buffers
|
||||
***************************/
|
||||
bool are_empty_buffers(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
return fb->empty_len;
|
||||
}
|
||||
|
||||
/**************************
|
||||
* push_empty
|
||||
*
|
||||
* This is slightly confusing. The number empty_len is the literal #
|
||||
* of empty buffers. After calling, empty_len-1 is the index into the
|
||||
* empty buffer stack. So, if empty_len == 1, there is one empty buffer,
|
||||
* given by fb->empty_buffers[0].
|
||||
* empty_buffers should never fill up, though this is not checked.
|
||||
**************************/
|
||||
void push_empty(struct dt3155_fbuffer *fb, int index)
|
||||
{
|
||||
fb->empty_buffers[fb->empty_len] = index;
|
||||
fb->empty_len++;
|
||||
}
|
||||
|
||||
/**************************
|
||||
* pop_empty
|
||||
**************************/
|
||||
int pop_empty(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
fb->empty_len--;
|
||||
return fb->empty_buffers[fb->empty_len];
|
||||
}
|
||||
|
||||
/*************************
|
||||
* is_ready_buf_empty
|
||||
*************************/
|
||||
bool is_ready_buf_empty(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
return fb->ready_len == 0;
|
||||
}
|
||||
|
||||
/*************************
|
||||
* is_ready_buf_full
|
||||
*
|
||||
* this should *never* be true if there are any active, locked or empty
|
||||
* buffers, since it corresponds to nbuffers ready buffers!!
|
||||
* 7/31/02: total rewrite. --NJC
|
||||
*************************/
|
||||
bool is_ready_buf_full(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
return fb->ready_len == fb->nbuffers;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* push_ready
|
||||
*****************************************************/
|
||||
void push_ready(struct dt3155_fbuffer *fb, int index)
|
||||
{
|
||||
int head = fb->ready_head;
|
||||
|
||||
fb->ready_que[head] = index;
|
||||
fb->ready_head = (head + 1) % fb->nbuffers;
|
||||
fb->ready_len++;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* get_tail
|
||||
*
|
||||
* Simply comptutes the tail given the head and the length.
|
||||
*****************************************************/
|
||||
static int get_tail(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
return (fb->ready_head - fb->ready_len + fb->nbuffers) % fb->nbuffers;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* pop_ready
|
||||
*
|
||||
* This assumes that there is a ready buffer ready... should
|
||||
* be checked (e.g. with is_ready_buf_empty() prior to call.
|
||||
*****************************************************/
|
||||
int pop_ready(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
int tail = get_tail(fb);
|
||||
|
||||
fb->ready_len--;
|
||||
return fb->ready_que[tail];
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* printques
|
||||
*****************************************************/
|
||||
void printques(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_INFO "\n R:");
|
||||
for (i = get_tail(fb); i != fb->ready_head; i++, i %= fb->nbuffers)
|
||||
printk(" %d ", fb->ready_que[i]);
|
||||
|
||||
printk(KERN_INFO "\n E:");
|
||||
for (i = 0; i < fb->empty_len; i++)
|
||||
printk(" %d ", fb->empty_buffers[i]);
|
||||
|
||||
printk(KERN_INFO "\n A: %d", fb->active_buf);
|
||||
|
||||
printk(KERN_INFO "\n L: %d\n", fb->locked_buf);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* adjust_4MB
|
||||
*
|
||||
* If a buffer intersects the 4MB boundary, push
|
||||
* the start address up to the beginning of the
|
||||
* next 4MB chunk (assuming bufsize < 4MB).
|
||||
*****************************************************/
|
||||
static u32 adjust_4MB(u32 buf_addr, u32 bufsize)
|
||||
{
|
||||
if (((buf_addr+bufsize) & UPPER_10_BITS) != (buf_addr & UPPER_10_BITS))
|
||||
return (buf_addr+bufsize) & UPPER_10_BITS;
|
||||
else
|
||||
return buf_addr;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* allocate_buffers
|
||||
*
|
||||
* Try to allocate enough memory for all requested
|
||||
* buffers. If there is not enough free space
|
||||
* try for less memory.
|
||||
*****************************************************/
|
||||
static void allocate_buffers(u32 *buf_addr, u32* total_size_kbs,
|
||||
u32 bufsize)
|
||||
{
|
||||
/* Compute the minimum amount of memory guaranteed to hold all
|
||||
MAXBUFFERS such that no buffer crosses the 4MB boundary.
|
||||
Store this value in the variable "full_size" */
|
||||
|
||||
u32 allocator_max;
|
||||
u32 bufs_per_chunk = (FOUR_MB / bufsize);
|
||||
u32 filled_chunks = (MAXBUFFERS-1) / bufs_per_chunk;
|
||||
u32 leftover_bufs = MAXBUFFERS - filled_chunks * bufs_per_chunk;
|
||||
|
||||
u32 full_size = bufsize /* possibly unusable part of 1st chunk */
|
||||
+ filled_chunks * FOUR_MB /* max # of completely filled 4mb chunks */
|
||||
+ leftover_bufs * bufsize; /* these buffs will be in a partly filled
|
||||
chunk at beginning or end */
|
||||
|
||||
u32 full_size_kbs = 1 + (full_size-1) / 1024;
|
||||
u32 min_size_kbs = 2*ndevices*bufsize / 1024;
|
||||
u32 size_kbs;
|
||||
|
||||
/* Now, try to allocate full_size. If this fails, keep trying for
|
||||
less & less memory until it succeeds. */
|
||||
#ifndef STANDALONE_ALLOCATOR
|
||||
/* initialize the allocator */
|
||||
allocator_init(&allocator_max);
|
||||
#endif
|
||||
size_kbs = full_size_kbs;
|
||||
*buf_addr = 0;
|
||||
printk(KERN_INFO "DT3155: We would like to get: %d KB\n", full_size_kbs);
|
||||
printk(KERN_INFO "DT3155: ...but need at least: %d KB\n", min_size_kbs);
|
||||
printk(KERN_INFO "DT3155: ...the allocator has: %d KB\n", allocator_max);
|
||||
size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max);
|
||||
if (size_kbs > min_size_kbs) {
|
||||
*buf_addr = allocator_allocate_dma(size_kbs, GFP_KERNEL);
|
||||
if (*buf_addr != 0) {
|
||||
printk(KERN_INFO "DT3155: Managed to allocate: %d KB\n",
|
||||
size_kbs);
|
||||
*total_size_kbs = size_kbs;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* If we got here, the allocation failed */
|
||||
printk(KERN_INFO "DT3155: Allocator failed!\n");
|
||||
*buf_addr = 0;
|
||||
*total_size_kbs = 0;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
* dt3155_setup_buffers
|
||||
*
|
||||
* setup_buffers just puts the buffering system into
|
||||
* a consistent state before the start of interrupts
|
||||
*
|
||||
* JML : it looks like all the buffers need to be
|
||||
* continuous. So I'm going to try and allocate one
|
||||
* continuous buffer.
|
||||
*
|
||||
* GCS : Fix DMA problems when buffer spans
|
||||
* 4MB boundary. Also, add error checking. This
|
||||
* function will return -ENOMEM when not enough memory.
|
||||
*****************************************************/
|
||||
u32 dt3155_setup_buffers(u32 *allocatorAddr)
|
||||
|
||||
{
|
||||
struct dt3155_fbuffer *fb;
|
||||
u32 index;
|
||||
u32 rambuff_addr; /* start of allocation */
|
||||
u32 rambuff_size; /* total size allocated to driver */
|
||||
u32 rambuff_acm; /* accumlator, keep track of how much
|
||||
is left after being split up*/
|
||||
u32 rambuff_end; /* end of rambuff */
|
||||
u32 numbufs; /* number of useful buffers allocated (per device) */
|
||||
u32 bufsize = DT3155_MAX_ROWS * DT3155_MAX_COLS;
|
||||
int minor;
|
||||
|
||||
/* zero the fbuffer status and address structure */
|
||||
for (minor = 0; minor < ndevices; minor++) {
|
||||
fb = &dt3155_status[minor].fbuffer;
|
||||
memset(fb, 0, sizeof(*fb));
|
||||
}
|
||||
|
||||
/* allocate a large contiguous chunk of RAM */
|
||||
allocate_buffers(&rambuff_addr, &rambuff_size, bufsize);
|
||||
printk(KERN_INFO "DT3155: mem info\n");
|
||||
printk(KERN_INFO " - rambuf_addr = 0x%x\n", rambuff_addr);
|
||||
printk(KERN_INFO " - length (kb) = %u\n", rambuff_size);
|
||||
if (rambuff_addr == 0) {
|
||||
printk(KERN_INFO
|
||||
"DT3155: Error setup_buffers() allocator dma failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
*allocatorAddr = rambuff_addr;
|
||||
rambuff_end = rambuff_addr + 1024 * rambuff_size;
|
||||
|
||||
/* after allocation, we need to count how many useful buffers there
|
||||
are so we can give an equal number to each device */
|
||||
rambuff_acm = rambuff_addr;
|
||||
for (index = 0; index < MAXBUFFERS; index++) {
|
||||
/*avoid spanning 4MB bdry*/
|
||||
rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
|
||||
if (rambuff_acm + bufsize > rambuff_end)
|
||||
break;
|
||||
rambuff_acm += bufsize;
|
||||
}
|
||||
/* Following line is OK, will waste buffers if index
|
||||
* not evenly divisible by ndevices -NJC*/
|
||||
numbufs = index / ndevices;
|
||||
printk(KERN_INFO " - numbufs = %u\n", numbufs);
|
||||
if (numbufs < 2) {
|
||||
printk(KERN_INFO
|
||||
"DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* now that we have board memory we spit it up */
|
||||
/* between the boards and the buffers */
|
||||
rambuff_acm = rambuff_addr;
|
||||
for (minor = 0; minor < ndevices; minor++) {
|
||||
fb = &dt3155_status[minor].fbuffer;
|
||||
rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
|
||||
|
||||
/* Save the start of this boards buffer space (for mmap). */
|
||||
dt3155_status[minor].mem_addr = rambuff_acm;
|
||||
|
||||
for (index = 0; index < numbufs; index++) {
|
||||
rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
|
||||
if (rambuff_acm + bufsize > rambuff_end) {
|
||||
/* Should never happen */
|
||||
printk(KERN_INFO "DT3155 PROGRAM ERROR (GCS)\n"
|
||||
"Error distributing allocated buffers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
fb->frame_info[index].addr = rambuff_acm;
|
||||
push_empty(fb, index);
|
||||
/* printk(" - Buffer : %lx\n", fb->frame_info[index].addr); */
|
||||
fb->nbuffers += 1;
|
||||
rambuff_acm += bufsize;
|
||||
}
|
||||
|
||||
/* Make sure there is an active buffer there. */
|
||||
fb->active_buf = pop_empty(fb);
|
||||
fb->even_happened = 0;
|
||||
fb->even_stopped = 0;
|
||||
|
||||
/* make sure there is no locked_buf JML 2/28/00 */
|
||||
fb->locked_buf = -1;
|
||||
|
||||
dt3155_status[minor].mem_size = rambuff_acm -
|
||||
dt3155_status[minor].mem_addr;
|
||||
|
||||
/* setup the ready queue */
|
||||
fb->ready_head = 0;
|
||||
fb->ready_len = 0;
|
||||
printk(KERN_INFO "Available buffers for device %d: %d\n",
|
||||
minor, fb->nbuffers);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* internal_release_locked_buffer
|
||||
*
|
||||
* The internal function for releasing a locked buffer.
|
||||
* It assumes interrupts are turned off.
|
||||
*****************************************************/
|
||||
static void internal_release_locked_buffer(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
if (fb->locked_buf >= 0) {
|
||||
push_empty(fb, fb->locked_buf);
|
||||
fb->locked_buf = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* dt3155_release_locked_buffer
|
||||
*
|
||||
* The user function of the above.
|
||||
*****************************************************/
|
||||
void dt3155_release_locked_buffer(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
unsigned long int flags;
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
internal_release_locked_buffer(fb);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* dt3155_flush
|
||||
*****************************************************/
|
||||
int dt3155_flush(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
unsigned long int flags;
|
||||
int index;
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
|
||||
internal_release_locked_buffer(fb);
|
||||
fb->empty_len = 0;
|
||||
|
||||
for (index = 0; index < fb->nbuffers; index++)
|
||||
push_empty(fb, index);
|
||||
|
||||
/* Make sure there is an active buffer there. */
|
||||
fb->active_buf = pop_empty(fb);
|
||||
|
||||
fb->even_happened = 0;
|
||||
fb->even_stopped = 0;
|
||||
|
||||
/* setup the ready queue */
|
||||
fb->ready_head = 0;
|
||||
fb->ready_len = 0;
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* dt3155_get_ready_buffer
|
||||
*
|
||||
* get_ready_buffer will grab the next chunk of data
|
||||
* if it is already there, otherwise it returns 0.
|
||||
* If the user has a buffer locked it will unlock
|
||||
* that buffer before returning the new one.
|
||||
*****************************************************/
|
||||
int dt3155_get_ready_buffer(struct dt3155_fbuffer *fb)
|
||||
{
|
||||
unsigned long int flags;
|
||||
int frame_index;
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
|
||||
#ifdef DEBUG_QUES_A
|
||||
printques(fb);
|
||||
#endif
|
||||
|
||||
internal_release_locked_buffer(fb);
|
||||
|
||||
if (is_ready_buf_empty(fb)) {
|
||||
frame_index = -1;
|
||||
} else {
|
||||
frame_index = pop_ready(fb);
|
||||
fb->locked_buf = frame_index;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_QUES_B
|
||||
printques(fb);
|
||||
#endif
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return frame_index;
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
|
||||
Jason Lapenta, Scott Smedley
|
||||
|
||||
This file is part of the DT3155 Device Driver.
|
||||
|
||||
The DT3155 Device Driver 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.
|
||||
|
||||
The DT3155 Device Driver is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the DT3155 Device Driver; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
|
||||
-- Changes --
|
||||
|
||||
Date Programmer Description of changes made
|
||||
-------------------------------------------------------------------
|
||||
03-Jul-2000 JML n/a
|
||||
24-Jul-2002 SS GPL licence.
|
||||
26-Oct-2009 SS Porting to 2.6.30 kernel.
|
||||
|
||||
-- notes --
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DT3155_ISR_H
|
||||
#define DT3155_ISR_H
|
||||
|
||||
/**********************************
|
||||
* User functions for buffering
|
||||
**********************************/
|
||||
|
||||
/*
|
||||
* Initialize the buffering system.
|
||||
* This should be called prior to enabling interrupts
|
||||
*/
|
||||
u32 dt3155_setup_buffers(u32 *allocatorAddr);
|
||||
|
||||
/*
|
||||
* Get the next frame of data if it is ready.
|
||||
* Returns zero if no data is ready. If there is data but the user has a
|
||||
* locked buffer, it will unlock that buffer and return it to the free list.
|
||||
*/
|
||||
int dt3155_get_ready_buffer(struct dt3155_fbuffer *fb);
|
||||
|
||||
/*
|
||||
* Return a locked buffer to the free list.
|
||||
*/
|
||||
void dt3155_release_locked_buffer(struct dt3155_fbuffer *fb);
|
||||
|
||||
/*
|
||||
* Flush the buffer system.
|
||||
*/
|
||||
int dt3155_flush(struct dt3155_fbuffer *fb);
|
||||
|
||||
/**********************************
|
||||
* Simple array based que struct
|
||||
**********************************/
|
||||
|
||||
bool are_empty_buffers(struct dt3155_fbuffer *fb);
|
||||
void push_empty(struct dt3155_fbuffer *fb, int index);
|
||||
|
||||
int pop_empty(struct dt3155_fbuffer *fb);
|
||||
|
||||
bool is_ready_buf_empty(struct dt3155_fbuffer *fb);
|
||||
bool is_ready_buf_full(struct dt3155_fbuffer *fb);
|
||||
|
||||
void push_ready(struct dt3155_fbuffer *fb, int index);
|
||||
int pop_ready(struct dt3155_fbuffer *fb);
|
||||
|
||||
void printques(struct dt3155_fbuffer *fb);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user