zr36067.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:119k
- #define DEBUGLEVEL 0
- #define MAX_KMALLOC_MEM (128*1024)
- /*
- Miro/Pinnacle Systems Inc. DC10/DC10plus and
- Linux Media Labs LML33 video capture boards driver
- now with IOMega BUZ support!
-
- Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
-
- Based on
-
- Miro DC10 driver
- Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
-
- Iomega Buz driver version 1.0
- Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
- buz.0.0.3
- Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- bttv - Bt848 frame grabber driver
- Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
- & Marcus Metzler (mocm@thp.uni-koeln.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.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <linux/config.h>
- #include <linux/version.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/delay.h>
- #include <linux/errno.h>
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/major.h>
- #include <linux/slab.h>
- #include <linux/mm.h>
- #include <linux/pci.h>
- #include <linux/signal.h>
- #include <asm/io.h>
- #include <asm/pgtable.h>
- #include <asm/page.h>
- #include <linux/sched.h>
- #include <asm/segment.h>
- #include <linux/types.h>
- #include <linux/wrapper.h>
- #include <linux/spinlock.h>
- #include <linux/vmalloc.h>
- #include <linux/i2c-old.h>
- #define MAP_NR(x) virt_to_page(x)
- #define ZORAN_HARDWARE VID_HARDWARE_ZR36067
- #include <linux/videodev.h>
- #include <asm/uaccess.h>
- #include <linux/proc_fs.h>
- #include "zoran.h"
- #include <linux/video_decoder.h>
- #include <linux/video_encoder.h>
- // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined
- #if !defined(CONFIG_BIGPHYS_AREA)
- //#undef CONFIG_BIGPHYS_AREA
- #define BUZ_USE_HIMEM
- #endif
- #if defined(CONFIG_BIGPHYS_AREA)
- # include <linux/bigphysarea.h>
- #endif
- #define IRQ_MASK ( ZR36057_ISR_GIRQ0 | ZR36057_ISR_GIRQ1 | /* ZR36057_ISR_CodRepIRQ | */ ZR36057_ISR_JPEGRepIRQ ) // SW
- //#define GPIO_MASK 0xcd
- //#define GPIO_MASK 0x8d
- /*
- DC10:
- GPIO0 = /RESET ZR 36060
- GPIO1 = VIDEO BUS DIRECTION (0: CAPTURE, 1: DISPLAY)
- GPIO2 = VIDEO BUS ENABLE (0: ON, 1: OFF)
- GPIO3 = /SLEEP ZR 36060
- GPIO4 = ADC7175 (video out) FREQUENCY (0: LCC/SAA7110, 1: 27 MHz (quarz))
- GPIO5 = ZORAN FREQUENCY (0: LCC and LCC2 from SAA7110,
- 1: 27 and 13.5 MHz (quarz))
- GPIO6 = /FRAME ZR 36060
- GPIO7 = /RESET ADV7175 (video out)
- (I think they lost the SAA7110 reset.....)
- GIRQ0 signals that ZR36060's DATERR# line is asserted.
- GIRQ1 signals a vertical sync of the video signal (VS SAA7110)
- SAA7110A:
- mode 0 - Composite
- mode 1 -
- mode 2 -
- mode 3 -
- mode 4 -
- mode 5 - internal Composite (from PCTV)
- mode 6 -
- mode 7 - S-Video
- BUZ:
- GPIO0 = 1, take board out of reset
- GPIO1 = 1, take JPEG codec out of sleep mode
- GPIO3 = 1, deassert FRAME# to 36060
- GIRQ0 signals a vertical sync of the video signal
- GIRQ1 signals that ZR36060's DATERR# line is asserted.
- SAA7111A
- In their infinite wisdom, the Iomega engineers decided to
- use the same input line for composite and S-Video Color,
- although there are two entries not connected at all!
- Through this ingenious strike, it is not possible to
- keep two running video sources connected at the same time
- to Composite and S-VHS input!
- mode 0 - N/C
- mode 1 - S-Video Y
- mode 2 - noise or something I don't know
- mode 3 - Composite and S-Video C
- mode 4 - N/C
- mode 5 - S-Video (gain C independently selectable of gain Y)
- mode 6 - N/C
- mode 7 - S-Video (gain C adapted to gain Y)
- */
- #define MAJOR_VERSION 0 /* driver major version */
- #define MINOR_VERSION 7 /* driver minor version */
- #define ZORAN_NAME "zr36067" /* name of the device */
- #define BUZ_ERR KERN_ERR ZORAN_NAME
- #define BUZ_DEBUG KERN_INFO ZORAN_NAME
- #define BUZ_INFO KERN_INFO ZORAN_NAME
- #define BUZ_WARNING KERN_WARNING ZORAN_NAME
- #if(DEBUGLEVEL>0)
- #define DEBUG1(x...) x
- #else
- #define DEBUG1(x...)
- #endif
- #if(DEBUGLEVEL>1)
- #define DEBUG2(x...) x
- #else
- #define DEBUG2(x...)
- #endif
- #if(DEBUGLEVEL>2)
- #define DEBUG3(x...) x
- #else
- #define DEBUG3(x...)
- #endif
- #if(DEBUGLEVEL>3)
- #define DEBUG4(x...) x
- #else
- #define DEBUG4(x...)
- #endif
- /* The parameters for this driver */
- /*
- The video mem address of the video card.
- The driver has a little database for some videocards
- to determine it from there. If your video card is not in there
- you have either to give it to the driver as a parameter
- or set in in a VIDIOCSFBUF ioctl
- */
- static unsigned long vidmem = 0; /* Video memory base address */
- /* Special purposes only: */
- static int triton = 0; /* 0=no, 1=yes */
- static int natoma = 0; /* 0=no, 1=yes */
- /*
- Number and size of grab buffers for Video 4 Linux
- The vast majority of applications should not need more than 2,
- the very popular BTTV driver actually does ONLY have 2.
- Time sensitive applications might need more, the maximum
- is VIDEO_MAX_FRAME (defined in <linux/videodev.h>).
- The size is set so that the maximum possible request
- can be satisfied. Decrease it, if bigphys_area alloc'd
- memory is low. If you don't have the bigphys_area patch,
- set it to 128 KB. Will you allow only to grab small
- images with V4L, but that's better than nothing.
- v4l_bufsize has to be given in KB !
- */
- static int v4l_nbufs = 2;
- static int v4l_bufsize = 128; /* Everybody should be able to work with this setting */
- /*
- Default input and video norm at startup of the driver.
- */
- static int default_input = 0; /* 0=Composite, 1=S-VHS */
- static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */
- static int lock_norm = 0; /* 1=Don't change TV standard (norm) */
- static int pass_through = 0; /* 1=Pass through TV signal when device is not used */
- /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
- static int lml33dpath = 0; /* 1 will use digital path in capture mode instead of analog.
- It can be used for picture adjustments using tool like xawtv
- while watching image on TV monitor connected to the output.
- However, due to absence of 75 Ohm load on Bt819 input, there
- will be some image imperfections */
- static int video_nr = -1;
- MODULE_PARM(vidmem, "i");
- MODULE_PARM(triton, "i");
- MODULE_PARM(natoma, "i");
- MODULE_PARM(v4l_nbufs, "i");
- MODULE_PARM(v4l_bufsize, "i");
- MODULE_PARM(default_input, "i");
- MODULE_PARM(default_norm, "i");
- MODULE_PARM(lock_norm, "i");
- MODULE_PARM(pass_through, "i");
- MODULE_PARM(lml33dpath, "i");
- MODULE_PARM(video_nr, "i");
- static struct pci_device_id zr36067_pci_tbl[] = {
- { PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0 }
- };
- MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
- /* Anybody who uses more than four? */
- #define BUZ_MAX 4
- static int zoran_num; /* number of Buzs in use */
- static struct zoran zoran[BUZ_MAX];
- /* forward references */
- static void v4l_fbuffer_free(struct zoran *zr);
- static void jpg_fbuffer_free(struct zoran *zr);
- static void zoran_feed_stat_com(struct zoran *zr);
- /*
- * Allocate the V4L grab buffers
- *
- * These have to be pysically contiguous.
- * If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc
- * else we try to allocate them with bigphysarea_alloc_pages
- * if the bigphysarea patch is present in the kernel,
- * else we try to use high memory (if the user has bootet
- * Linux with the necessary memory left over).
- */
- static int v4l_fbuffer_alloc(struct zoran *zr)
- {
- int i, off;
- unsigned char *mem;
- for (i = 0; i < v4l_nbufs; i++) {
- if (zr->v4l_gbuf[i].fbuffer)
- printk(KERN_WARNING
- "%s: v4l_fbuffer_alloc: buffer %d allready allocated ???n",
- zr->name, i);
- //udelay(20);
- if (v4l_bufsize <= MAX_KMALLOC_MEM) {
- /* Use kmalloc */
- mem =
- (unsigned char *) kmalloc(v4l_bufsize,
- GFP_KERNEL);
- if (mem == 0) {
- printk(KERN_ERR
- "%s: kmalloc for V4L bufs failedn",
- zr->name);
- v4l_fbuffer_free(zr);
- return -ENOBUFS;
- }
- zr->v4l_gbuf[i].fbuffer = mem;
- zr->v4l_gbuf[i].fbuffer_phys = virt_to_phys(mem);
- zr->v4l_gbuf[i].fbuffer_bus = virt_to_bus(mem);
- for (off = 0; off < v4l_bufsize; off += PAGE_SIZE)
- mem_map_reserve(MAP_NR(mem + off));
- DEBUG1(printk
- (KERN_INFO
- "%s: V4L frame %d mem 0x%lx (bus: 0x%lx)n",
- zr->name, i, (unsigned long) mem,
- virt_to_bus(mem)));
- } else {
- #if defined(CONFIG_BIGPHYS_AREA)
- /* Use bigphysarea_alloc_pages */
- int n = (v4l_bufsize + PAGE_SIZE - 1) / PAGE_SIZE;
- mem =
- (unsigned char *) bigphysarea_alloc_pages(n, 0,
- GFP_KERNEL);
- if (mem == 0) {
- printk(KERN_ERR
- "%s: bigphysarea_alloc_pages for V4L bufs failedn",
- zr->name);
- v4l_fbuffer_free(zr);
- return -ENOBUFS;
- }
- zr->v4l_gbuf[i].fbuffer = mem;
- zr->v4l_gbuf[i].fbuffer_phys = virt_to_phys(mem);
- zr->v4l_gbuf[i].fbuffer_bus = virt_to_bus(mem);
- DEBUG1(printk
- (KERN_INFO
- "%s: Bigphysarea frame %d mem 0x%x (bus: 0x%x)n",
- zr->name, i, (unsigned) mem,
- (unsigned) virt_to_bus(mem)));
- /* Zero out the allocated memory */
- memset(zr->v4l_gbuf[i].fbuffer, 0, v4l_bufsize);
- #else
- /* No bigphysarea present, usage of high memory disabled,
- but user wants buffers of more than MAX_KMALLOC_MEM */
- printk(KERN_ERR
- "%s: No bigphysarea_patch present, usage of high memory disabled,n",
- zr->name);
- printk(KERN_ERR
- "%s: sorry, could not allocate V4L buffers of size %d KB.n",
- zr->name, v4l_bufsize >> 10);
- return -ENOBUFS;
- #endif
- }
- }
- return 0;
- }
- /* free the V4L grab buffers */
- static void v4l_fbuffer_free(struct zoran *zr)
- {
- int i, off;
- unsigned char *mem;
- for (i = 0; i < v4l_nbufs; i++) {
- if (!zr->v4l_gbuf[i].fbuffer)
- continue;
- if (v4l_bufsize <= MAX_KMALLOC_MEM) {
- mem = zr->v4l_gbuf[i].fbuffer;
- for (off = 0; off < v4l_bufsize; off += PAGE_SIZE)
- mem_map_unreserve(MAP_NR(mem + off));
- kfree((void *) zr->v4l_gbuf[i].fbuffer);
- }
- #if defined(CONFIG_BIGPHYS_AREA)
- else
- bigphysarea_free_pages((void *) zr->v4l_gbuf[i].
- fbuffer);
- #endif
- zr->v4l_gbuf[i].fbuffer = NULL;
- }
- }
- /*
- * Allocate the MJPEG grab buffers.
- *
- * If the requested buffer size is smaller than MAX_KMALLOC_MEM,
- * kmalloc is used to request a physically contiguous area,
- * else we allocate the memory in framgents with get_free_page.
- *
- * If a Natoma chipset is present and this is a revision 1 zr36057,
- * each MJPEG buffer needs to be physically contiguous.
- * (RJ: This statement is from Dave Perks' original driver,
- * I could never check it because I have a zr36067)
- * The driver cares about this because it reduces the buffer
- * size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation).
- *
- * RJ: The contents grab buffers needs never be accessed in the driver.
- * Therefore there is no need to allocate them with vmalloc in order
- * to get a contiguous virtual memory space.
- * I don't understand why many other drivers first allocate them with
- * vmalloc (which uses internally also get_free_page, but delivers you
- * virtual addresses) and then again have to make a lot of efforts
- * to get the physical address.
- *
- */
- static int jpg_fbuffer_alloc(struct zoran *zr)
- {
- int i, j, off; //alloc_contig;
- unsigned long mem;
- /* Decide if we should alloc contiguous or fragmented memory */
- /* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */
- //alloc_contig = (zr->jpg_bufsize <= MAX_KMALLOC_MEM);
- for (i = 0; i < zr->jpg_nbufs; i++) {
- if (zr->jpg_gbuf[i].frag_tab)
- printk(KERN_WARNING
- "%s: jpg_fbuffer_alloc: buffer %d allready allocated ???n",
- zr->name, i);
- /* Allocate fragment table for this buffer */
- mem = get_free_page(GFP_KERNEL);
- if (mem == 0) {
- printk(KERN_ERR
- "%s: jpg_fbuffer_alloc: get_free_page (frag_tab) failed for buffer %dn",
- zr->name, i);
- jpg_fbuffer_free(zr);
- return -ENOBUFS;
- }
- memset((void *) mem, 0, PAGE_SIZE);
- zr->jpg_gbuf[i].frag_tab = (u32 *) mem;
- zr->jpg_gbuf[i].frag_tab_bus = virt_to_bus((void *) mem);
- //if (alloc_contig) {
- if (zr->need_contiguous) {
- mem = (unsigned long) kmalloc(zr->jpg_bufsize, GFP_KERNEL);
- if (mem == 0) {
- printk(KERN_ERR "%s: jpg_fbuffer_alloc: kmalloc failed for buffer %dn",
- zr->name, i);
- jpg_fbuffer_free(zr);
- return -ENOBUFS;
- }
- zr->jpg_gbuf[i].frag_tab[0] = virt_to_bus((void *) mem);
- zr->jpg_gbuf[i].frag_tab[1] =
- ((zr->jpg_bufsize / 4) << 1) | 1;
- for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE)
- mem_map_reserve(MAP_NR(mem + off));
- } else {
- /* jpg_bufsize is allreay page aligned */
- for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++)
- {
- mem = get_free_page(GFP_KERNEL);
- if (mem == 0) {
- printk(KERN_ERR
- "%s: jpg_fbuffer_alloc: get_free_page failed for buffer %dn",
- zr->name, i);
- jpg_fbuffer_free(zr);
- return -ENOBUFS;
- }
- zr->jpg_gbuf[i].frag_tab[2 * j] =
- virt_to_bus((void *) mem);
- zr->jpg_gbuf[i].frag_tab[2 * j + 1] =
- (PAGE_SIZE / 4) << 1;
- mem_map_reserve(MAP_NR(mem));
- }
- zr->jpg_gbuf[i].frag_tab[2 * j - 1] |= 1;
- }
- }
- DEBUG1(printk
- ("%s: jpg_fbuffer_alloc: %ld KB allocatedn", zr->name,
- (zr->jpg_nbufs * zr->jpg_bufsize) >> 10));
- zr->jpg_buffers_allocated = 1;
- return 0;
- }
- /* free the MJPEG grab buffers */
- static void jpg_fbuffer_free(struct zoran *zr)
- {
- int i, j, off; // alloc_contig;
- unsigned char *mem;
- /* Decide if we should alloc contiguous or fragmented memory */
- /* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */
- //alloc_contig = (zr->jpg_bufsize <= MAX_KMALLOC_MEM);
- for (i = 0; i < zr->jpg_nbufs; i++) {
- if (!zr->jpg_gbuf[i].frag_tab)
- continue;
- //if (alloc_contig) {
- if (zr->need_contiguous) {
- if (zr->jpg_gbuf[i].frag_tab[0]) {
- mem =
- (unsigned char *) bus_to_virt(zr->
- jpg_gbuf
- [i].
- frag_tab
- [0]);
- for (off = 0; off < zr->jpg_bufsize;
- off += PAGE_SIZE)
- mem_map_unreserve(MAP_NR
- (mem + off));
- kfree((void *) mem);
- zr->jpg_gbuf[i].frag_tab[0] = 0;
- zr->jpg_gbuf[i].frag_tab[1] = 0;
- }
- } else {
- for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) {
- if (!zr->jpg_gbuf[i].frag_tab[2 * j])
- break;
- mem_map_unreserve(MAP_NR
- (bus_to_virt
- (zr->jpg_gbuf[i].
- frag_tab[2 * j])));
- free_page((unsigned long)
- bus_to_virt(zr->jpg_gbuf[i].
- frag_tab[2 * j]));
- zr->jpg_gbuf[i].frag_tab[2 * j] = 0;
- zr->jpg_gbuf[i].frag_tab[2 * j + 1] = 0;
- }
- }
- free_page((unsigned long) zr->jpg_gbuf[i].frag_tab);
- zr->jpg_gbuf[i].frag_tab = NULL;
- }
- zr->jpg_buffers_allocated = 0;
- }
- /* ----------------------------------------------------------------------- */
- /* I2C functions */
- #define I2C_DELAY 10
- /* software I2C functions */
- static void i2c_setlines(struct i2c_bus *bus, int ctrl, int data)
- {
- struct zoran *zr = (struct zoran *) bus->data;
- btwrite((data << 1) | ctrl, ZR36057_I2CBR);
- udelay(I2C_DELAY);
- }
- static int i2c_getdataline(struct i2c_bus *bus)
- {
- struct zoran *zr = (struct zoran *) bus->data;
- return (btread(ZR36057_I2CBR) >> 1) & 1;
- }
- static void attach_inform(struct i2c_bus *bus, int id)
- {
- int i;
- struct zoran *zr = (struct zoran *) bus->data;
- DEBUG1(printk(KERN_DEBUG "%s: i2c attach %02xn", zr->name, id));
- for (i = 0; i < bus->devcount; i++) {
- if (strcmp(bus->devices[i]->name, "saa7110") == 0) {
- if (zr->revision < 2) {
- zr->card = DC10;
- sprintf(zr->name, "DC10[%u]", zr->id);
- } else {
- zr->card = DC10plus;
- sprintf(zr->name, "DC10plus[%u]", zr->id);
- }
- break;
- }
- if (strcmp(bus->devices[i]->name, "bt819") == 0) {
- zr->card = LML33;
- sprintf(zr->name, "LML33[%u]", zr->id);
- break;
- }
- if (strcmp(bus->devices[i]->name, "saa7111") == 0) {
- zr->card = BUZ;
- sprintf(zr->name, "Buz[%u]", zr->id);
- break;
- }
- }
- }
- static void detach_inform(struct i2c_bus *bus, int id)
- {
- DEBUG1(struct zoran *zr = (struct zoran *) bus->data);
- DEBUG1(printk(KERN_DEBUG "%s: i2c detach %02xn", zr->name, id));
- }
- static struct i2c_bus zoran_i2c_bus_template = {
- "zr36057",
- I2C_BUSID_BT848,
- NULL,
- SPIN_LOCK_UNLOCKED,
- attach_inform,
- detach_inform,
- i2c_setlines,
- i2c_getdataline,
- NULL,
- NULL,
- };
- /*
- * Set the registers for the size we have specified. Don't bother
- * trying to understand this without the ZR36057 manual in front of
- * you [AC].
- *
- * PS: The manual is free for download in .pdf format from
- * www.zoran.com - nicely done those folks.
- */
- static struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 };
- static struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 };
- static struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 };
- static struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 };
- static struct tvnorm *dc10norms[] = {
- &f50sqpixel, /* PAL-BDGHI */
- &f60sqpixel, /* NTSC */
- &f50sqpixel, /* SECAM */
- };
- static struct tvnorm *lml33norms[] = {
- &f50ccir601, /* PAL-BDGHI */
- &f60ccir601, /* NTSC */
- NULL, /* SECAM (not supported in LML33) */
- };
- static struct tvnorm *buznorms[] = {
- &f50ccir601, /* PAL-BDGHI */
- &f60ccir601, /* NTSC */
- NULL, /* SECAM */
- };
- static struct tvnorm *unsupported[] = {
- NULL, /* PAL-BDGHI */
- NULL, /* NTSC */
- NULL, /* SECAM */
- };
- static struct tvnorm **cardnorms[] = {
- unsupported, /* UNKNOWN */
- dc10norms, /* DC10 */
- dc10norms, /* DC10plus */
- lml33norms, /* LML33 */
- buznorms, /* Buz */
- };
- static u32 cardvsync[] = {
- 0, /* UNKNOWN */
- ZR36057_ISR_GIRQ1, /* DC10 */
- ZR36057_ISR_GIRQ1, /* DC10plus */
- ZR36057_ISR_GIRQ0, /* LML33 */
- ZR36057_ISR_GIRQ0, /* Buz */
- };
- static u32 cardjpegint[] = {
- 0, /* UNKNOWN */
- ZR36057_ISR_GIRQ0, /* DC10 */
- ZR36057_ISR_GIRQ0, /* DC10plus */
- ZR36057_ISR_GIRQ1, /* LML33 */
- ZR36057_ISR_GIRQ1, /* Buz */
- };
- static int format2bpp(int format)
- {
- int bpp;
- /* Determine the number of bytes per pixel for the video format requested */
- switch (format) {
- case VIDEO_PALETTE_YUV422:
- bpp = 2;
- break;
- case VIDEO_PALETTE_RGB555:
- bpp = 2;
- break;
- case VIDEO_PALETTE_RGB565:
- bpp = 2;
- break;
- case VIDEO_PALETTE_RGB24:
- bpp = 3;
- break;
- case VIDEO_PALETTE_RGB32:
- bpp = 4;
- break;
- default:
- bpp = 0;
- }
- return bpp;
- }
- static void zr36057_adjust_vfe(struct zoran *zr,
- enum zoran_codec_mode mode)
- {
- u32 reg;
- switch (mode) {
- case BUZ_MODE_MOTION_DECOMPRESS:
- btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
- reg = btread(ZR36057_VFEHCR);
- if (reg & (1 << 10)) {
- reg += ((1 << 10) | 1);
- }
- btwrite(reg, ZR36057_VFEHCR);
- break;
- case BUZ_MODE_MOTION_COMPRESS:
- case BUZ_MODE_IDLE:
- default:
- if (zr->params.norm == VIDEO_MODE_NTSC)
- btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
- else
- btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
- reg = btread(ZR36057_VFEHCR);
- if (!(reg & (1 << 10))) {
- reg -= ((1 << 10) | 1);
- }
- btwrite(reg, ZR36057_VFEHCR);
- break;
- }
- }
- /*
- * set geometry
- */
- static void zr36057_set_vfe(struct zoran *zr, int video_width,
- int video_height, unsigned int video_format)
- {
- struct tvnorm *tvn;
- unsigned HStart, HEnd, VStart, VEnd;
- unsigned DispMode;
- unsigned VidWinWid, VidWinHt;
- unsigned hcrop1, hcrop2, vcrop1, vcrop2;
- unsigned Wa, We, Ha, He;
- unsigned X, Y, HorDcm, VerDcm;
- u32 reg;
- unsigned mask_line_size;
- tvn = zr->timing;
- Wa = tvn->Wa;
- Ha = tvn->Ha;
- DEBUG1(printk (BUZ_INFO ": width = %d, height = %dn", video_width, video_height));
- if (zr->params.norm != VIDEO_MODE_PAL
- && zr->params.norm != VIDEO_MODE_NTSC
- && zr->params.norm != VIDEO_MODE_SECAM) {
- printk(KERN_ERR "%s: set_vfe: video_norm = %d not validn",
- zr->name, zr->params.norm);
- return;
- }
- if (video_width < BUZ_MIN_WIDTH || video_height < BUZ_MIN_HEIGHT
- || video_width > Wa || video_height > Ha) {
- printk(KERN_ERR "%s: set_vfe: w=%d h=%d not validn",
- zr->name, video_width, video_height);
- return;
- }
- /* if window has more than half of active height,
- switch on interlacing - we want the full information */
- zr->video_interlace = (video_height > Ha / 2);
- /**** zr36057 ****/
- /* horizontal */
- VidWinWid = video_width;
- X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa;
- We = (VidWinWid * 64) / X;
- HorDcm = 64 - X;
- hcrop1 = 2 * ((tvn->Wa - We) / 4);
- hcrop2 = tvn->Wa - We - hcrop1;
- HStart = tvn->HStart | 1;
- if (zr->card == LML33)
- HStart += 62;
- if (zr->card == BUZ) { //HStart += 67;
- HStart += 44;
- }
- HEnd = HStart + tvn->Wa - 1;
- HStart += hcrop1;
- HEnd -= hcrop2;
- reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart)
- | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd);
- if (zr->card != BUZ)
- reg |= ZR36057_VFEHCR_HSPol;
- btwrite(reg, ZR36057_VFEHCR);
- /* Vertical */
- DispMode = !zr->video_interlace;
- VidWinHt = DispMode ? video_height : video_height / 2;
- Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha;
- He = (VidWinHt * 64) / Y;
- VerDcm = 64 - Y;
- vcrop1 = (tvn->Ha / 2 - He) / 2;
- vcrop2 = tvn->Ha / 2 - He - vcrop1;
- VStart = tvn->VStart;
- VEnd = VStart + tvn->Ha / 2 - 1;
- VStart += vcrop1;
- VEnd -= vcrop2;
- reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart)
- | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd);
- reg |= ZR36057_VFEVCR_VSPol;
- btwrite(reg, ZR36057_VFEVCR);
- /* scaler and pixel format */
- reg = 0;
- reg |= (HorDcm << ZR36057_VFESPFR_HorDcm);
- reg |= (VerDcm << ZR36057_VFESPFR_VerDcm);
- reg |= (DispMode << ZR36057_VFESPFR_DispMode);
- reg |= ZR36057_VFESPFR_LittleEndian;
- /* RJ: I don't know, why the following has to be the opposite
- of the corresponding ZR36060 setting, but only this way
- we get the correct colors when uncompressing to the screen */
- //reg |= ZR36057_VFESPFR_VCLKPol; /**/
- /* RJ: Don't know if that is needed for NTSC also */
- if (zr->params.norm != VIDEO_MODE_NTSC)
- reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang
- reg |= ZR36057_VFESPFR_TopField;
- switch (video_format) {
- case VIDEO_PALETTE_YUV422:
- reg |= ZR36057_VFESPFR_YUV422;
- break;
- case VIDEO_PALETTE_RGB555:
- reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif;
- break;
- case VIDEO_PALETTE_RGB565:
- reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif;
- break;
- case VIDEO_PALETTE_RGB24:
- reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24;
- break;
- case VIDEO_PALETTE_RGB32:
- reg |= ZR36057_VFESPFR_RGB888;
- break;
- default:
- printk(KERN_INFO "%s: Unknown color_fmt=%xn", zr->name,
- video_format);
- return;
- }
- if (HorDcm >= 48) {
- reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */
- } else if (HorDcm >= 32) {
- reg |= 2 << ZR36057_VFESPFR_HFilter; /* 4 tap filter */
- } else if (HorDcm >= 16) {
- reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */
- }
- btwrite(reg, ZR36057_VFESPFR);
- /* display configuration */
- reg = (16 << ZR36057_VDCR_MinPix)
- | (VidWinHt << ZR36057_VDCR_VidWinHt)
- | (VidWinWid << ZR36057_VDCR_VidWinWid);
- if (triton || zr->revision <= 1)
- reg &= ~ZR36057_VDCR_Triton;
- else
- reg |= ZR36057_VDCR_Triton;
- btwrite(reg, ZR36057_VDCR);
- /* Write overlay clipping mask data, but don't enable overlay clipping */
- /* RJ: since this makes only sense on the screen, we use
- zr->window.width instead of video_width */
- mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
- reg = virt_to_bus(zr->overlay_mask);
- btwrite(reg, ZR36057_MMTR);
- reg = virt_to_bus(zr->overlay_mask + mask_line_size);
- btwrite(reg, ZR36057_MMBR);
- reg = mask_line_size - (zr->window.width + 31) / 32;
- if (DispMode == 0)
- reg += mask_line_size;
- reg <<= ZR36057_OCR_MaskStride;
- btwrite(reg, ZR36057_OCR);
- zr36057_adjust_vfe(zr, zr->codec_mode);
- }
- /*
- * Switch overlay on or off
- */
- static void zr36057_overlay(struct zoran *zr, int on)
- {
- int fmt, bpp;
- u32 reg;
- if (on) {
- /* do the necessary settings ... */
- btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); /* switch it off first */
- switch (zr->buffer.depth) {
- case 15:
- fmt = VIDEO_PALETTE_RGB555;
- bpp = 2;
- break;
- case 16:
- fmt = VIDEO_PALETTE_RGB565;
- bpp = 2;
- break;
- case 24:
- fmt = VIDEO_PALETTE_RGB24;
- bpp = 3;
- break;
- case 32:
- fmt = VIDEO_PALETTE_RGB32;
- bpp = 4;
- break;
- default:
- fmt = 0;
- bpp = 0;
- }
- zr36057_set_vfe(zr, zr->window.width, zr->window.height,
- fmt);
- /* Start and length of each line MUST be 4-byte aligned.
- This should be allready checked before the call to this routine.
- All error messages are internal driver checking only! */
- /* video display top and bottom registers */
- reg =
- (u32) zr->buffer.base + zr->window.x * bpp +
- zr->window.y * zr->buffer.bytesperline;
- btwrite(reg, ZR36057_VDTR);
- if (reg & 3)
- printk(KERN_ERR
- "%s: zr36057_overlay: video_address not alignedn",
- zr->name);
- if (zr->video_interlace)
- reg += zr->buffer.bytesperline;
- btwrite(reg, ZR36057_VDBR);
- /* video stride, status, and frame grab register */
- reg = zr->buffer.bytesperline - zr->window.width * bpp;
- if (zr->video_interlace)
- reg += zr->buffer.bytesperline;
- if (reg & 3)
- printk(KERN_ERR
- "%s: zr36057_overlay: video_stride not alignedn",
- zr->name);
- reg = (reg << ZR36057_VSSFGR_DispStride);
- reg |= ZR36057_VSSFGR_VidOvf; /* clear overflow status */
- btwrite(reg, ZR36057_VSSFGR);
- /* Set overlay clipping */
- if (zr->window.clipcount)
- btor(ZR36057_OCR_OvlEnable, ZR36057_OCR);
- /* ... and switch it on */
- btor(ZR36057_VDCR_VidEn, ZR36057_VDCR);
- } else {
- /* Switch it off */
- btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
- }
- }
- /*
- * The overlay mask has one bit for each pixel on a scan line,
- * and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels.
- */
- static void write_overlay_mask(struct zoran *zr, struct video_clip *vp,
- int count)
- {
- unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
- u32 *mask;
- int x, y, width, height;
- unsigned i, j, k;
- u32 reg;
- /* fill mask with one bits */
- memset(zr->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT);
- reg = 0;
- for (i = 0; i < count; ++i) {
- /* pick up local copy of clip */
- x = vp[i].x;
- y = vp[i].y;
- width = vp[i].width;
- height = vp[i].height;
- /* trim clips that extend beyond the window */
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (x + width > zr->window.width) {
- width = zr->window.width - x;
- }
- if (y + height > zr->window.height) {
- height = zr->window.height - y;
- }
- /* ignore degenerate clips */
- if (height <= 0) {
- continue;
- }
- if (width <= 0) {
- continue;
- }
- /* apply clip for each scan line */
- for (j = 0; j < height; ++j) {
- /* reset bit for each pixel */
- /* this can be optimized later if need be */
- mask = zr->overlay_mask + (y + j) * mask_line_size;
- for (k = 0; k < width; ++k) {
- mask[(x + k) / 32] &=
- ~((u32) 1 << (x + k) % 32);
- }
- }
- }
- }
- /* Enable/Disable uncompressed memory grabbing of the 36057 */
- static void zr36057_set_memgrab(struct zoran *zr, int mode)
- {
- if (mode) {
- if (btread(ZR36057_VSSFGR) &
- (ZR36057_VSSFGR_SnapShot | ZR36057_VSSFGR_FrameGrab))
- printk(KERN_WARNING
- "%s: zr36057_set_memgrab_on with SnapShot or FrameGrab on ???n",
- zr->name);
- /* switch on VSync interrupts */
- btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts
- btor(cardvsync[zr->card], ZR36057_ICR); // SW
- /* enable SnapShot */
- btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
- /* Set zr36057 video front end and enable video */
- zr36057_set_vfe(zr, zr->gwidth, zr->gheight, zr->gformat);
- zr->v4l_memgrab_active = 1;
- } else {
- zr->v4l_memgrab_active = 0;
- /* switch off VSync interrupts */
- //btand(~ZR36057_ICR_GIRQ1, ZR36057_ICR); // SW
- /* reenable grabbing to screen if it was running */
- if (zr->v4l_overlay_active) {
- zr36057_overlay(zr, 1);
- } else {
- btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
- btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
- }
- }
- }
- static int wait_grab_pending(struct zoran *zr)
- {
- unsigned long flags;
- /* wait until all pending grabs are finished */
- if (!zr->v4l_memgrab_active)
- return 0;
- while (zr->v4l_pend_tail != zr->v4l_pend_head) {
- interruptible_sleep_on(&zr->v4l_capq);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
- spin_lock_irqsave(&zr->lock, flags);
- zr36057_set_memgrab(zr, 0);
- spin_unlock_irqrestore(&zr->lock, flags);
- return 0;
- }
- /*
- * V4L Buffer grabbing
- */
- static int v4l_grab(struct zoran *zr, struct video_mmap *mp)
- {
- unsigned long flags;
- int res, bpp;
- /*
- * There is a long list of limitations to what is allowed to be grabbed
- * We don't output error messages here, since some programs (e.g. xawtv)
- * just try several settings to find out what is valid or not.
- */
- /* No grabbing outside the buffer range! */
- if (mp->frame >= v4l_nbufs || mp->frame < 0) {
- DEBUG2(printk
- (KERN_ERR "%s: Can not grab frame %dn", zr->name,
- mp->frame));
- return -EINVAL;
- }
- /* Check size and format of the grab wanted */
- if (mp->height < BUZ_MIN_HEIGHT || mp->width < BUZ_MIN_WIDTH
- || mp->height > BUZ_MAX_HEIGHT || mp->width > BUZ_MAX_WIDTH) {
- DEBUG2(printk
- (KERN_ERR "%s: Wrong frame size.n", zr->name));
- return -EINVAL;
- }
- bpp = format2bpp(mp->format);
- if (bpp == 0) {
- DEBUG2(printk
- (KERN_ERR "%s: Wrong bytes-per-pixel formatn",
- zr->name));
- return -EINVAL;
- }
- /* Check against available buffer size */
- if (mp->height * mp->width * bpp > v4l_bufsize) {
- DEBUG2(printk
- (KERN_ERR "%s: Video buffer size is too smalln",
- zr->name));
- return -EINVAL;
- }
- /* The video front end needs 4-byte alinged line sizes */
- if ((bpp == 2 && (mp->width & 1)) || (bpp == 3 && (mp->width & 3))) {
- DEBUG2(printk
- (KERN_ERR "%s: Wrong frame alingmentn", zr->name));
- return -EINVAL;
- }
- /*
- * To minimize the time spent in the IRQ routine, we avoid setting up
- * the video front end there.
- * If this grab has different parameters from a running streaming capture
- * we stop the streaming capture and start it over again.
- */
- if (zr->v4l_memgrab_active
- && (zr->gwidth != mp->width || zr->gheight != mp->height
- || zr->gformat != mp->format)) {
- res = wait_grab_pending(zr);
- if (res)
- return res;
- }
- zr->gwidth = mp->width;
- zr->gheight = mp->height;
- zr->gformat = mp->format;
- zr->gbpl = bpp * zr->gwidth;
- spin_lock_irqsave(&zr->lock, flags);
- /* make sure a grab isn't going on currently with this buffer */
- switch (zr->v4l_gbuf[mp->frame].state) {
- default:
- case BUZ_STATE_PEND:
- res = -EBUSY; /* what are you doing? */
- break;
- case BUZ_STATE_USER:
- case BUZ_STATE_DONE:
- /* since there is at least one unused buffer there's room for at least one more pend[] entry */
- zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] =
- mp->frame;
- zr->v4l_gbuf[mp->frame].state = BUZ_STATE_PEND;
- res = 0;
- break;
- }
- /* put the 36057 into frame grabbing mode */
- if (!res && !zr->v4l_memgrab_active)
- zr36057_set_memgrab(zr, 1);
- spin_unlock_irqrestore(&zr->lock, flags);
- //DEBUG2(printk(KERN_INFO "%s: Frame grab 3...n", zr->name));
- return res;
- }
- /*
- * Sync on a V4L buffer
- */
- static int v4l_sync(struct zoran *zr, int frame)
- {
- unsigned long flags;
- /* check passed-in frame number */
- if (frame >= v4l_nbufs || frame < 0) {
- DEBUG1(printk(KERN_ERR "%s: v4l_sync: frame %d is invalidn",
- zr->name, frame));
- return -EINVAL;
- }
- /* Check if is buffer was queued at all */
- if (zr->v4l_gbuf[frame].state == BUZ_STATE_USER) {
- DEBUG1(printk(KERN_ERR
- "%s: v4l_sync: Attempt to sync on a buffer which was not queued?n",
- zr->name));
- return -EPROTO;
- }
- /* wait on this buffer to get ready */
- while (zr->v4l_gbuf[frame].state == BUZ_STATE_PEND) {
- interruptible_sleep_on(&zr->v4l_capq);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
- /* buffer should now be in BUZ_STATE_DONE */
- if (zr->v4l_gbuf[frame].state != BUZ_STATE_DONE)
- printk(KERN_ERR "%s: v4l_sync - internal errorn",
- zr->name);
- /* Check if streaming capture has finished */
- spin_lock_irqsave(&zr->lock, flags);
- if (zr->v4l_pend_tail == zr->v4l_pend_head)
- zr36057_set_memgrab(zr, 0);
- spin_unlock_irqrestore(&zr->lock, flags);
- return 0;
- }
- /*****************************************************************************
- * *
- * Set up the Buz-specific MJPEG part *
- * *
- *****************************************************************************/
- /*
- Wait til post office is no longer busy */
- static int post_office_wait(struct zoran *zr)
- {
- u32 por;
- // while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) {
- while ((por = btread(ZR36057_POR)) & ZR36057_POR_POPen) {
- /* wait for something to happen */
- }
- if ((por & ZR36057_POR_POTime) && zr->card != LML33
- && zr->card != BUZ) {
- /* In LML33/BUZ GWS line is not connected, so it has always timeout set */
- printk(KERN_WARNING "%s: pop timeout %08xn", zr->name, por);
- return -1;
- }
- return 0;
- }
- static int post_office_write(struct zoran *zr, unsigned guest,
- unsigned reg, unsigned value)
- {
- u32 por;
- por =
- ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) |
- ((reg & 7) << 16) | (value & 0xFF);
- btwrite(por, ZR36057_POR);
- return post_office_wait(zr);
- }
- static int post_office_read(struct zoran *zr, unsigned guest, unsigned reg)
- {
- u32 por;
- por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16);
- btwrite(por, ZR36057_POR);
- if (post_office_wait(zr) < 0) {
- return -1;
- }
- return btread(ZR36057_POR) & 0xFF;
- }
- static int zr36060_write_8(struct zoran *zr, unsigned reg, unsigned val)
- {
- if (post_office_wait(zr)
- || post_office_write(zr, 0, 1, reg >> 8)
- || post_office_write(zr, 0, 2, reg)) {
- return -1;
- }
- return post_office_write(zr, 0, 3, val);
- }
- static int zr36060_write_16(struct zoran *zr, unsigned reg, unsigned val)
- {
- if (zr36060_write_8(zr, reg + 0, val >> 8)) {
- return -1;
- }
- return zr36060_write_8(zr, reg + 1, val >> 0);
- }
- static int zr36060_write_24(struct zoran *zr, unsigned reg, unsigned val)
- {
- if (zr36060_write_8(zr, reg + 0, val >> 16)) {
- return -1;
- }
- return zr36060_write_16(zr, reg + 1, val >> 0);
- }
- static int zr36060_write_32(struct zoran *zr, unsigned reg, unsigned val)
- {
- if (zr36060_write_16(zr, reg + 0, val >> 16)) {
- return -1;
- }
- return zr36060_write_16(zr, reg + 2, val >> 0);
- }
- static u32 zr36060_read_8(struct zoran *zr, unsigned reg)
- {
- if (post_office_wait(zr)
- || post_office_write(zr, 0, 1, reg >> 8)
- || post_office_write(zr, 0, 2, reg)) {
- return -1;
- }
- return post_office_read(zr, 0, 3) & 0xFF;
- }
- /* ----------------------------------------------------------------------- */
- static void GPIO(struct zoran *zr, unsigned bit, unsigned value)
- {
- u32 reg;
- u32 mask;
- mask = 1 << (24 + bit);
- reg = btread(ZR36057_GPPGCR1) & ~mask;
- if (value) {
- reg |= mask;
- }
- btwrite(reg, ZR36057_GPPGCR1);
- udelay(1);
- }
- static void zr36060_sleep(struct zoran *zr, int sleep)
- {
- switch (zr->card) {
- case DC10:
- case DC10plus:
- GPIO(zr, 3, !sleep);
- break;
- case BUZ:
- case LML33:
- GPIO(zr, 1, !sleep);
- break;
- default:
- break;
- }
- if (!sleep)
- udelay(500);
- else
- udelay(2);
- }
- static int zr36060_reset(struct zoran *zr)
- {
- switch (zr->card) {
- case DC10:
- case DC10plus:
- zr36060_sleep(zr, 0);
- GPIO(zr, 0, 0);
- udelay(2);
- GPIO(zr, 0, 1);
- udelay(2);
- break;
- case LML33:
- case BUZ:
- zr36060_sleep(zr, 0);
- post_office_write(zr, 3, 0, 0);
- udelay(2);
- default:
- }
- return 0;
- }
- static void set_frame(struct zoran *zr, int val)
- {
- switch (zr->card) {
- case DC10:
- case DC10plus:
- GPIO(zr, 6, val);
- break;
- case LML33:
- case BUZ:
- GPIO(zr, 3, val);
- break;
- default:
- break;
- }
- }
- static void set_videobus_dir(struct zoran *zr, int val)
- {
- switch (zr->card) {
- case DC10:
- case DC10plus:
- GPIO(zr, 1, val);
- break;
- case LML33:
- if (lml33dpath == 0)
- GPIO(zr, 5, val);
- else
- GPIO(zr, 5, 1);
- break;
- case BUZ:
- default:
- break;
- }
- }
- static void set_videobus_enable(struct zoran *zr, int val)
- {
- switch (zr->card) {
- case LML33:
- GPIO(zr, 7, val);
- break;
- case DC10:
- case DC10plus:
- case BUZ:
- default:
- break;
- }
- }
- static void zr36060_set_jpg(struct zoran *zr, enum zoran_codec_mode mode)
- {
- struct tvnorm *tvn;
- u32 reg;
- int size, blocks;
- reg = (1 << 0) /* CodeMstr */
- |(0 << 2) /* CFIS=0 */
- |(0 << 6) /* Endian=0 */
- |(0 << 7); /* Code16=0 */
- zr36060_write_8(zr, 0x002, reg);
- switch (mode) {
- case BUZ_MODE_MOTION_DECOMPRESS:
- case BUZ_MODE_STILL_DECOMPRESS:
- reg = 0x00; /* Codec mode = decompression */
- break;
- case BUZ_MODE_MOTION_COMPRESS:
- case BUZ_MODE_STILL_COMPRESS:
- default:
- reg = 0xa4; /* Codec mode = compression with variable scale factor */
- break;
- }
- zr36060_write_8(zr, 0x003, reg);
- reg = 0x00; /* reserved, mbz */
- zr36060_write_8(zr, 0x004, reg);
- /* code volume */
- /* Target field size in pixels: */
- tvn = zr->timing;
- size =
- (tvn->Ha / 2) * (tvn->Wa) / (zr->params.HorDcm) /
- (zr->params.VerDcm);
- blocks = size / 64;
- /* Target compressed field size in bits: */
- size = size * 16; /* uncompressed size in bits */
- size = size * zr->params.quality / 400; /* quality = 100 is a compression ratio 1:4 */
- /* Lower limit (arbitrary, 1 KB) */
- if (size < 8192)
- size = 8192;
- /* Upper limit: 6/8 of the code buffers */
- if (size * zr->params.field_per_buff > zr->jpg_bufsize * 6)
- size = zr->jpg_bufsize * 6 / zr->params.field_per_buff;
- reg = size * 4 / blocks;
- if (reg > 0xf0)
- reg = 0xf0; /* 480 bits/block, does 0xff represents unlimited? */
- zr36060_write_8(zr, 0x005, reg);
- /* JPEG markers */
- reg = (zr->params.jpeg_markers) & 0x38; /* DRI, DQT, DHT */
- if (zr->params.COM_len)
- reg |= JPEG_MARKER_COM;
- if (zr->params.APP_len)
- reg |= JPEG_MARKER_APP;
- zr36060_write_8(zr, 0x006, reg);
- if (zr->card != LML33 && zr->card != BUZ) {
- reg = (0 << 3) /* EOAV=0 */
- |(0 << 2) /* EOI=0 */
- |(0 << 1) /* END=0 */
- |(1 << 0); /* DATERR=1 */
- } else {
- reg = (0 << 3) /* EOAV=0 */
- |(0 << 2) /* EOI=0 */
- |(0 << 1) /* END=0 */
- |(0 << 0); /* DATERR=0 */
- }
- zr36060_write_8(zr, 0x007, reg);
- reg = size;
- zr36060_write_32(zr, 0x009, reg);
- reg = (size * 10) / 11;
- zr36060_write_32(zr, 0x00d, reg); // Not needed for compr. with variable scale factor, just in case ...
- /* how do we set initial SF as a function of quality parameter? */
- reg = 0x0100; /* SF=1.0 */
- zr36060_write_16(zr, 0x011, reg);
- reg = 0x00ffffff; /* AF=max */
- zr36060_write_24(zr, 0x013, reg);
- reg = 0x0000; /* test */
- zr36060_write_16(zr, 0x024, reg);
- //post_office_read(zr,1,0);
- }
- static void zr36060_set_video(struct zoran *zr, enum zoran_codec_mode mode)
- {
- struct tvnorm *tvn;
- u32 reg;
- unsigned HStart;
- tvn = zr->timing;
- reg = (0 << 7) /* Video8 */
- |(0 << 6) /* Range */
- |(0 << 3) /* FlDet */
- |(1 << 2) /* FlVedge */
- |(0 << 1) /* FlExt */
- |(0 << 0); /* SyncMstr */
- if (mode != BUZ_MODE_STILL_DECOMPRESS) {
- /* limit pixels to range 16..235 as per CCIR-601 */
- reg |= (1 << 6); /* Range=1 */
- }
- zr36060_write_8(zr, 0x030, reg);
- switch (zr->card) {
- case DC10:
- case DC10plus:
- reg = (0 << 7) /* VCLKPol */
- |(0 << 6) /* PValPol */
- |(0 << 5) /* PoePol */
- |(0 << 4) /* SImgPol */
- |(1 << 3) /* BLPol */
- |(1 << 2) /* FlPol */
- |(1 << 1) /* HSPol */
- |(1 << 0); /* VSPol */
- break;
- case LML33:
- reg = (0 << 7) /* VCLKPol=0 */
- |(0 << 6) /* PValPol=0 */
- |(1 << 5) /* PoePol=1 */
- |(0 << 4) /* SImgPol=0 */
- |(0 << 3) /* BLPol=0 */
- |(0 << 2) /* FlPol=0 */
- |(0 << 1) /* HSPol=0, sync on falling edge */
- |(1 << 0); /* VSPol=1 */
- break;
- case BUZ:
- default:
- reg = (0 << 7) /* VCLKPol=0 */
- |(0 << 6) /* PValPol=0 */
- |(1 << 5) /* PoePol=1 */
- |(0 << 4) /* SImgPol=0 */
- |(0 << 3) /* BLPol=0 */
- |(0 << 2) /* FlPol=0 */
- |(1 << 1) /* HSPol=0, sync on falling edge */
- |(1 << 0); /* VSPol=1 */
- break;
- }
- zr36060_write_8(zr, 0x031, reg);
- switch (zr->params.HorDcm) {
- default:
- case 1:
- reg = (0 << 0);
- break; /* HScale = 0 */
- case 2:
- reg = (1 << 0);
- break; /* HScale = 1 */
- case 4:
- reg = (2 << 0);
- break; /* HScale = 2 */
- }
- if (zr->params.VerDcm == 2)
- reg |= (1 << 2);
- zr36060_write_8(zr, 0x032, reg);
- reg = 0x00; /* BackY */
- zr36060_write_8(zr, 0x033, reg);
- reg = 0x80; /* BackU */
- zr36060_write_8(zr, 0x034, reg);
- reg = 0x80; /* BackV */
- zr36060_write_8(zr, 0x035, reg);
- /* sync generator */
- reg = tvn->Ht - 1; /* Vtotal */
- zr36060_write_16(zr, 0x036, reg);
- reg = tvn->Wt - 1; /* Htotal */
- zr36060_write_16(zr, 0x038, reg);
- reg = 6 - 1; /* VsyncSize */
- zr36060_write_8(zr, 0x03a, reg);
- //reg = 30 - 1; /* HsyncSize */
- reg = (zr->params.norm == 1 ? 57 : 68);
- zr36060_write_8(zr, 0x03b, reg);
- reg = tvn->VStart - 1; /* BVstart */
- zr36060_write_8(zr, 0x03c, reg);
- reg += tvn->Ha / 2; /* BVend */
- zr36060_write_16(zr, 0x03e, reg);
- reg = tvn->HStart + 64 - 1; /* BHstart */
- zr36060_write_8(zr, 0x03d, reg);
- reg += tvn->Wa; /* BHend */
- zr36060_write_16(zr, 0x040, reg);
- /* active area */
- reg = zr->params.img_y + tvn->VStart; /* Vstart */
- zr36060_write_16(zr, 0x042, reg);
- reg += zr->params.img_height; /* Vend */
- zr36060_write_16(zr, 0x044, reg);
- HStart = tvn->HStart;
- if (zr->card == BUZ) {
- HStart += 44;
- } else {
- HStart += 64;
- }
- reg = zr->params.img_x + HStart; /* Hstart */
- zr36060_write_16(zr, 0x046, reg);
- reg += zr->params.img_width; /* Hend */
- zr36060_write_16(zr, 0x048, reg);
- /* subimage area */
- reg = tvn->VStart - 4; /* SVstart */
- zr36060_write_16(zr, 0x04a, reg);
- reg += tvn->Ha / 2 + 8; /* SVend */
- zr36060_write_16(zr, 0x04c, reg);
- reg = tvn->HStart + 64 - 4; /* SHstart */
- zr36060_write_16(zr, 0x04e, reg);
- reg += tvn->Wa + 8; /* SHend */
- zr36060_write_16(zr, 0x050, reg);
- }
- static void zr36060_set_jpg_SOF(struct zoran *zr)
- {
- u32 reg;
- reg = 0xffc0; /* SOF marker */
- zr36060_write_16(zr, 0x060, reg);
- reg = 17; /* SOF length */
- zr36060_write_16(zr, 0x062, reg);
- reg = 8; /* precision 8 bits */
- zr36060_write_8(zr, 0x064, reg);
- reg = zr->params.img_height / zr->params.VerDcm; /* image height */
- zr36060_write_16(zr, 0x065, reg);
- reg = zr->params.img_width / zr->params.HorDcm; /* image width */
- zr36060_write_16(zr, 0x067, reg);
- reg = 3; /* 3 color components */
- zr36060_write_8(zr, 0x069, reg);
- reg = 0x002100; /* Y component */
- zr36060_write_24(zr, 0x06a, reg);
- reg = 0x011101; /* U component */
- zr36060_write_24(zr, 0x06d, reg);
- reg = 0x021101; /* V component */
- zr36060_write_24(zr, 0x070, reg);
- }
- static void zr36060_set_jpg_SOS(struct zoran *zr)
- {
- u32 reg;
- reg = 0xffda; /* SOS marker */
- zr36060_write_16(zr, 0x07a, reg);
- reg = 12; /* SOS length */
- zr36060_write_16(zr, 0x07c, reg);
- reg = 3; /* 3 color components */
- zr36060_write_8(zr, 0x07e, reg);
- reg = 0x0000; /* Y component */
- zr36060_write_16(zr, 0x07f, reg);
- reg = 0x0111; /* U component */
- zr36060_write_16(zr, 0x081, reg);
- reg = 0x0211; /* V component */
- zr36060_write_16(zr, 0x083, reg);
- reg = 0x003f00; /* Start, end spectral scans */
- zr36060_write_24(zr, 0x085, reg);
- }
- static void zr36060_set_jpg_DRI(struct zoran *zr)
- {
- u32 reg;
- reg = 0xffdd; /* DRI marker */
- zr36060_write_16(zr, 0x0c0, reg);
- reg = 4; /* DRI length */
- zr36060_write_16(zr, 0x0c2, reg);
- reg = 8; /* length in MCUs */
- zr36060_write_16(zr, 0x0c4, reg);
- }
- static void zr36060_set_jpg_DQT(struct zoran *zr)
- {
- unsigned i;
- unsigned adr;
- static const u8 dqt[] = {
- 0xff, 0xdb, /* DHT marker */
- 0x00, 0x84, /* DHT length */
- 0x00, /* table ID 0 */
- 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
- 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
- 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
- 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
- 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
- 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
- 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
- 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
- 0x01, /* table ID 1 */
- 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
- 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
- 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
- };
- /* write fixed quantitization tables */
- adr = 0x0cc;
- for (i = 0; i < sizeof(dqt); ++i) {
- zr36060_write_8(zr, adr++, dqt[i]);
- }
- }
- static void zr36060_set_jpg_DHT(struct zoran *zr)
- {
- unsigned i;
- unsigned adr;
- static const u8 dht[] = {
- 0xff, 0xc4, /* DHT marker */
- 0x01, 0xa2, /* DHT length */
- 0x00, /* table class 0, ID 0 */
- 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, /* # codes of length 1..8 */
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* # codes of length 8..16 */
- 0x00, /* values for codes of length 2 */
- 0x01, 0x02, 0x03, 0x04, 0x05, /* values for codes of length 3 */
- 0x06, /* values for codes of length 4 */
- 0x07, /* values for codes of length 5 */
- 0x08, /* values for codes of length 6 */
- 0x09, /* values for codes of length 7 */
- 0x0a, /* values for codes of length 8 */
- 0x0b, /* values for codes of length 9 */
- 0x01, /* table class 0, ID 1 */
- 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* # codes of length 1..8 */
- 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* # codes of length 9..16 */
- 0x00, 0x01, 0x02, /* values for codes of length 2 */
- 0x03, /* values for codes of length 3 */
- 0x04, /* values for codes of length 4 */
- 0x05, /* values for codes of length 5 */
- 0x06, /* values for codes of length 6 */
- 0x07, /* values for codes of length 7 */
- 0x08, /* values for codes of length 8 */
- 0x09, /* values for codes of length 9 */
- 0x0a, /* values for codes of length 10 */
- 0x0b, /* values for codes of length 11 */
- 0x10,
- 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
- 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
- 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,
- 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00,
- 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11,
- 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
- 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08,
- 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23,
- 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a,
- 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18,
- 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
- 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55,
- 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
- 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75,
- 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84,
- 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
- 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
- 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
- 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
- 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
- 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
- 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
- 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5,
- 0xf6, 0xf7, 0xf8, 0xf9, 0xfa
- };
- /* write fixed Huffman tables */
- adr = 0x1d4;
- for (i = 0; i < sizeof(dht); ++i) {
- zr36060_write_8(zr, adr++, dht[i]);
- }
- }
- static void zr36060_set_jpg_APP(struct zoran *zr)
- {
- unsigned adr;
- int len, i;
- u32 reg;
- len = zr->params.APP_len;
- if (len < 0)
- len = 0;
- if (len > 60)
- len = 60;
- i = zr->params.APPn;
- if (i < 0)
- i = 0;
- if (i > 15)
- i = 15;
- reg = 0xffe0 + i; /* APPn marker */
- zr36060_write_16(zr, 0x380, reg);
- reg = len + 2; /* APPn len */
- zr36060_write_16(zr, 0x382, reg);
- /* write APPn data */
- adr = 0x384;
- for (i = 0; i < 60; i++) {
- zr36060_write_8(zr, adr++,
- (i < len ? zr->params.APP_data[i] : 0));
- }
- }
- static void zr36060_set_jpg_COM(struct zoran *zr)
- {
- unsigned adr;
- int len, i;
- u32 reg;
- len = zr->params.COM_len;
- if (len < 0)
- len = 0;
- if (len > 60)
- len = 60;
- reg = 0xfffe; /* COM marker */
- zr36060_write_16(zr, 0x3c0, reg);
- reg = len + 2; /* COM len */
- zr36060_write_16(zr, 0x3c2, reg);
- /* write COM data */
- adr = 0x3c4;
- for (i = 0; i < 60; i++) {
- zr36060_write_8(zr, adr++,
- (i < len ? zr->params.COM_data[i] : 0));
- }
- }
- static void zr36060_set_cap(struct zoran *zr, enum zoran_codec_mode mode)
- {
- unsigned i;
- u32 reg;
- zr36060_reset(zr);
- mdelay(10);
- reg = (0 << 7) /* Load=0 */
- |(1 << 0); /* SynRst=1 */
- zr36060_write_8(zr, 0x000, reg);
- zr36060_set_jpg(zr, mode);
- zr36060_set_video(zr, mode);
- zr36060_set_jpg_SOF(zr);
- zr36060_set_jpg_SOS(zr);
- zr36060_set_jpg_DRI(zr);
- zr36060_set_jpg_DQT(zr);
- zr36060_set_jpg_DHT(zr);
- zr36060_set_jpg_APP(zr);
- zr36060_set_jpg_COM(zr);
- reg = (1 << 7) /* Load=1 */
- |(1 << 0); /* SynRst=0 */
- zr36060_write_8(zr, 0x000, reg);
- /* wait for codec to unbusy */
- for (i = 0; i < 100000; ++i) {
- reg = zr36060_read_8(zr, 0x001);
- if ((reg & (1 << 7)) == 0) {
- return;
- }
- //udelay(100);
- }
- printk(KERN_ERR "%sZR36060: stuck busy, statux=%02xn", zr->name,
- reg);
- }
- static void init_jpeg_queue(struct zoran *zr)
- {
- int i;
- /* re-initialize DMA ring stuff */
- zr->jpg_que_head = 0;
- zr->jpg_dma_head = 0;
- zr->jpg_dma_tail = 0;
- zr->jpg_que_tail = 0;
- zr->jpg_seq_num = 0;
- zr->JPEG_error = 0;
- zr->num_errors = 0;
- zr->jpg_err_seq = 0;
- zr->jpg_err_shift = 0;
- zr->jpg_queued_num = 0;
- for (i = 0; i < zr->jpg_nbufs; i++) {
- zr->jpg_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */
- }
- for (i = 0; i < BUZ_NUM_STAT_COM; i++) {
- zr->stat_com[i] = 1; /* mark as unavailable to zr36057 */
- }
- }
- static void zr36057_set_jpg(struct zoran *zr, enum zoran_codec_mode mode)
- {
- struct tvnorm *tvn;
- u32 reg;
- tvn = zr->timing;
- /* assert P_Reset */
- btwrite(0, ZR36057_JPC);
- /* MJPEG compression mode */
- switch (mode) {
- case BUZ_MODE_MOTION_COMPRESS:
- default:
- reg = ZR36057_JMC_MJPGCmpMode;
- break;
- case BUZ_MODE_MOTION_DECOMPRESS:
- reg = ZR36057_JMC_MJPGExpMode;
- reg |= ZR36057_JMC_SyncMstr;
- /* RJ: The following is experimental - improves the output to screen */
- //if(zr->params.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; // No, it doesn't. SM
- break;
- case BUZ_MODE_STILL_COMPRESS:
- reg = ZR36057_JMC_JPGCmpMode;
- break;
- case BUZ_MODE_STILL_DECOMPRESS:
- reg = ZR36057_JMC_JPGExpMode;
- break;
- }
- reg |= ZR36057_JMC_JPG;
- if (zr->params.field_per_buff == 1)
- reg |= ZR36057_JMC_Fld_per_buff;
- btwrite(reg, ZR36057_JMC);
- /* vertical */
- btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR);
- reg =
- (6 << ZR36057_VSP_VsyncSize) | (tvn->Ht << ZR36057_VSP_FrmTot);
- btwrite(reg, ZR36057_VSP);
- reg = ((zr->params.img_y + tvn->VStart) << ZR36057_FVAP_NAY)
- | (zr->params.img_height << ZR36057_FVAP_PAY);
- btwrite(reg, ZR36057_FVAP);
- /* horizontal */
- btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
- reg =
- ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) | (tvn->
- Wt <<
- ZR36057_HSP_LineTot);
- btwrite(reg, ZR36057_HSP);
- reg = ((zr->params.img_x + tvn->HStart + 4) << ZR36057_FHAP_NAX)
- | (zr->params.img_width << ZR36057_FHAP_PAX);
- btwrite(reg, ZR36057_FHAP);
- /* field process parameters */
- if (zr->params.odd_even)
- reg = ZR36057_FPP_Odd_Even;
- else
- reg = 0;
- if (mode == BUZ_MODE_MOTION_DECOMPRESS && zr->card != LML33
- && zr->card != BUZ)
- reg ^= ZR36057_FPP_Odd_Even;
- btwrite(reg, ZR36057_FPP);
- /* Set proper VCLK Polarity, else colors will be wrong during playback */
- //btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR);
- /* code base address */
- reg = virt_to_bus(zr->stat_com);
- btwrite(reg, ZR36057_JCBA);
- /* FIFO threshold (FIFO is 160. double words) */
- /* NOTE: decimal values here */
- switch (mode) {
- case BUZ_MODE_STILL_COMPRESS:
- case BUZ_MODE_MOTION_COMPRESS:
- reg = 140;
- break;
- case BUZ_MODE_STILL_DECOMPRESS:
- case BUZ_MODE_MOTION_DECOMPRESS:
- reg = 20;
- break;
- default:
- reg = 80;
- break;
- }
- btwrite(reg, ZR36057_JCFT);
- zr36057_adjust_vfe(zr, mode);
- }
- #if (DEBUGLEVEL > 2)
- static void dump_guests(struct zoran *zr)
- {
- int i, guest[8];
- for (i = 1; i < 8; i++) { // Don't read zr36060 here
- guest[i] = post_office_read(zr, i, 0);
- }
- printk(KERN_INFO "%s: Guests:", zr->name);
- for (i = 1; i < 8; i++) {
- printk(" 0x%02x", guest[i]);
- }
- printk("n");
- }
- static unsigned long get_time(void)
- {
- struct timeval tv;
- do_gettimeofday(&tv);
- return (1000000 * tv.tv_sec + tv.tv_usec);
- }
- static void detect_guest_activity(struct zoran *zr)
- {
- int timeout, i, j, res, guest[8], guest0[8], change[8][3];
- unsigned long t0, t1;
- dump_guests(zr);
- printk(KERN_INFO "%s: Detecting guests activity, please wait...n",
- zr->name);
- for (i = 1; i < 8; i++) { // Don't read zr36060 here
- guest0[i] = guest[i] = post_office_read(zr, i, 0);
- }
- timeout = 0;
- j = 0;
- t0 = get_time();
- while (timeout < 10000) {
- udelay(10);
- timeout++;
- for (i = 1; (i < 8) && (j < 8); i++) {
- res = post_office_read(zr, i, 0);
- if (res != guest[i]) {
- t1 = get_time();
- change[j][0] = (t1 - t0);
- t0 = t1;
- change[j][1] = i;
- change[j][2] = res;
- j++;
- guest[i] = res;
- }
- }
- if (j >= 8)
- break;
- }
- printk(KERN_INFO "%s: Guests:", zr->name);
- for (i = 1; i < 8; i++) {
- printk(" 0x%02x", guest0[i]);
- }
- printk("n");
- if (j == 0) {
- printk(KERN_INFO "%s: No activity detected.n", zr->name);
- return;
- }
- for (i = 0; i < j; i++) {
- printk(KERN_INFO "%s: %6d: %d => 0x%02xn", zr->name,
- change[i][0], change[i][1], change[i][2]);
- }
- }
- #endif
- static void print_interrupts(struct zoran *zr)
- {
- int res, noerr;
- noerr = 0;
- printk(KERN_INFO "%s: interrupts received:", zr->name);
- if ((res = zr->field_counter) < -1 || res > 1) {
- printk(" FD:%d", res);
- }
- if ((res = zr->intr_counter_GIRQ1) != 0) {
- printk(" GIRQ1:%d", res);
- noerr++;
- }
- if ((res = zr->intr_counter_GIRQ0) != 0) {
- printk(" GIRQ0:%d", res);
- noerr++;
- }
- if ((res = zr->intr_counter_CodRepIRQ) != 0) {
- printk(" CodRepIRQ:%d", res);
- noerr++;
- }
- if ((res = zr->intr_counter_JPEGRepIRQ) != 0) {
- printk(" JPEGRepIRQ:%d", res);
- noerr++;
- }
- if (zr->JPEG_max_missed) {
- printk(" JPEG delays: max=%d min=%d", zr->JPEG_max_missed,
- zr->JPEG_min_missed);
- }
- if (zr->END_event_missed) {
- printk(" ENDs missed: %d", zr->END_event_missed);
- }
- //if (zr->jpg_queued_num) {
- printk(" queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail,
- zr->jpg_dma_tail, zr->jpg_dma_head, zr->jpg_que_head);
- //}
- if (!noerr) {
- printk(": no interrupts detected.");
- }
- printk("n");
- }
- static void clear_interrupt_counters(struct zoran *zr)
- {
- zr->intr_counter_GIRQ1 = 0;
- zr->intr_counter_GIRQ0 = 0;
- zr->intr_counter_CodRepIRQ = 0;
- zr->intr_counter_JPEGRepIRQ = 0;
- zr->field_counter = 0;
- zr->IRQ1_in = 0;
- zr->IRQ1_out = 0;
- zr->JPEG_in = 0;
- zr->JPEG_out = 0;
- zr->JPEG_0 = 0;
- zr->JPEG_1 = 0;
- zr->END_event_missed = 0;
- zr->JPEG_missed = 0;
- zr->JPEG_max_missed = 0;
- zr->JPEG_min_missed = 0x7fffffff;
- }
- static u32 count_reset_interrupt(struct zoran *zr)
- {
- u32 isr;
- if ((isr = btread(ZR36057_ISR) & 0x78000000)) {
- if (isr & ZR36057_ISR_GIRQ1) {
- btwrite(ZR36057_ISR_GIRQ1, ZR36057_ISR);
- zr->intr_counter_GIRQ1++;
- }
- if (isr & ZR36057_ISR_GIRQ0) {
- btwrite(ZR36057_ISR_GIRQ0, ZR36057_ISR);
- zr->intr_counter_GIRQ0++;
- }
- if (isr & ZR36057_ISR_CodRepIRQ) {
- btwrite(ZR36057_ISR_CodRepIRQ, ZR36057_ISR);
- zr->intr_counter_CodRepIRQ++;
- }
- if (isr & ZR36057_ISR_JPEGRepIRQ) {
- btwrite(ZR36057_ISR_JPEGRepIRQ, ZR36057_ISR);
- zr->intr_counter_JPEGRepIRQ++;
- }
- }
- return isr;
- }
- static void jpeg_start(struct zoran *zr)
- {
- int reg;
- zr->frame_num = 0;
- btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC); // /P_Reset
- btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); // CFlush
- btor(ZR36057_JPC_CodTrnsEn, ZR36057_JPC); // /CodTrnsEn
- btwrite(IRQ_MASK, ZR36057_ISR); // Clear IRQs
- btwrite(IRQ_MASK | ZR36057_ICR_IntPinEn, ZR36057_ICR); // Enable IRQs
- set_frame(zr, 0); // FRAME
- /* JPEG codec guest ID */
- reg =
- (1 << ZR36057_JCGI_JPEGuestID) | (0 <<
- ZR36057_JCGI_JPEGuestReg);
- btwrite(reg, ZR36057_JCGI);
- btor(ZR36057_JPC_Active, ZR36057_JPC); // /Active
- btor(ZR36057_JMC_Go_en, ZR36057_JMC); // /Go_en
- udelay(30);
- set_frame(zr, 1); // /FRAME
- }
- static void zr36057_enable_jpg(struct zoran *zr,
- enum zoran_codec_mode mode)
- {
- static int zero = 0;
- static int one = 1;
- zr->codec_mode = mode;
- switch (mode) {
- case BUZ_MODE_MOTION_COMPRESS:
- set_videobus_enable(zr, 0);
- set_videobus_dir(zr, 0); // GPIO(zr, 1, 0);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER,
- DECODER_ENABLE_OUTPUT, &one);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER,
- ENCODER_SET_INPUT, &zero);
- set_videobus_enable(zr, 1);
- zr36060_sleep(zr, 0);
- zr36060_set_cap(zr, mode); // Load ZR36060
- init_jpeg_queue(zr);
- zr36057_set_jpg(zr, mode); // P_Reset, ... Video param, FIFO
- clear_interrupt_counters(zr);
- DEBUG1(printk
- (KERN_INFO "%s: enable_jpg MOTION_COMPRESSn",
- zr->name));
- break;
- case BUZ_MODE_MOTION_DECOMPRESS:
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER,
- DECODER_ENABLE_OUTPUT, &zero);
- set_videobus_dir(zr, 1); // GPIO(zr, 1, 1);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER,
- ENCODER_SET_INPUT, &one);
- set_videobus_enable(zr, 1);
- zr36060_sleep(zr, 0);
- zr36060_set_cap(zr, mode); // Load ZR36060
- init_jpeg_queue(zr);
- zr36057_set_jpg(zr, mode); // P_Reset, ... Video param, FIFO
- clear_interrupt_counters(zr);
- DEBUG1(printk
- (KERN_INFO "%s: enable_jpg MOTION_DECOMPRESSn",
- zr->name));
- break;
- case BUZ_MODE_IDLE:
- default:
- /* shut down processing */
- btand(~(cardjpegint[zr->card] | ZR36057_ICR_JPEGRepIRQ),
- ZR36057_ICR);
- btwrite(cardjpegint[zr->card] | ZR36057_ICR_JPEGRepIRQ,
- ZR36057_ISR);
- btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // Go_en
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/20);
- set_videobus_dir(zr, 0); // GPIO(zr, 1, 0);
- set_frame(zr, 1); //GPIO(zr, 6, 1); // /FRAME
- btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); // /CFlush
- btwrite(0, ZR36057_JPC); // P_Reset,CodTrnsEn,Active
- btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC);
- btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC);
- zr36060_reset(zr);
- zr36060_sleep(zr, 1);
- zr36057_adjust_vfe(zr, mode);
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER,
- DECODER_ENABLE_OUTPUT, &one);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER,
- ENCODER_SET_INPUT, &zero);
- set_videobus_enable(zr, 1);
- DEBUG1(printk
- (KERN_INFO "%s: enable_jpg IDLEn", zr->name));
- break;
- }
- }
- /*
- * Queue a MJPEG buffer for capture/playback
- */
- static int jpg_qbuf(struct zoran *zr, int frame,
- enum zoran_codec_mode mode)
- {
- unsigned long flags;
- int res;
- /* Check if buffers are allocated */
- if (!zr->jpg_buffers_allocated) {
- printk(KERN_ERR
- "%s: jpg_qbuf: buffers not yet allocatedn",
- zr->name);
- return -ENOMEM;
- }
- /* Does the user want to stop streaming? */
- if (frame < 0) {
- if (zr->codec_mode == mode) {
- zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
- return 0;
- } else {
- printk(KERN_ERR
- "%s: jpg_qbuf - stop streaming but not in streaming moden",
- zr->name);
- return -EINVAL;
- }
- }
- /* No grabbing outside the buffer range! */
- if (frame >= zr->jpg_nbufs) {
- printk(KERN_ERR "%s: jpg_qbuf: buffer %d out of rangen",
- zr->name, frame);
- return -EINVAL;
- }
- /* what is the codec mode right now? */
- if (zr->codec_mode == BUZ_MODE_IDLE) {
- /* Ok load up the zr36060 */
- zr36057_enable_jpg(zr, mode);
- } else if (zr->codec_mode != mode) {
- /* wrong codec mode active - invalid */
- printk(KERN_ERR "%s: jpg_qbuf - codec in wrong moden",
- zr->name);
- return -EINVAL;
- }
- spin_lock_irqsave(&zr->lock, flags);
- /* make sure a grab isn't going on currently with this buffer */
- switch (zr->jpg_gbuf[frame].state) {
- case BUZ_STATE_DONE:
- DEBUG1(printk
- (KERN_WARNING
- "%s: Warning: queing frame in BUZ_STATE_DONE staten",
- zr->name));
- case BUZ_STATE_USER:
- /* since there is at least one unused buffer there's room for at least one more pend[] entry */
- zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = frame;
- zr->jpg_gbuf[frame].state = BUZ_STATE_PEND;
- zoran_feed_stat_com(zr);
- res = 0;
- break;
- default:
- case BUZ_STATE_DMA:
- case BUZ_STATE_PEND:
- res = -EBUSY; /* what are you doing? */
- break;
- }
- spin_unlock_irqrestore(&zr->lock, flags);
- /* Start the zr36060 when the first frame is queued */
- if (zr->jpg_que_head == 1)
- jpeg_start(zr);
- return res;
- }
- /*
- * Sync on a MJPEG buffer
- */
- static int jpg_sync(struct zoran *zr, struct zoran_sync *bs)
- {
- unsigned long flags;
- int frame, timeout;
- if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS
- && zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
- DEBUG1(printk(KERN_ERR
- "%s: BUZIOCSYNC: - codec not in streaming moden",
- zr->name));
- return -EINVAL;
- }
- while (zr->jpg_que_tail == zr->jpg_dma_tail) {
- if (zr->jpg_dma_tail == zr->jpg_dma_head)
- break;
- timeout =
- interruptible_sleep_on_timeout(&zr->jpg_capq, 10 * HZ);
- if (!timeout) {
- btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
- udelay(1);
- printk(KERN_ERR
- "%s: timeout: codec isr=0x%02x, csr=0x%02xn",
- zr->name, zr36060_read_8(zr, 0x008),
- zr36060_read_8(zr, 0x001));
- return -ETIME;
- } else if (signal_pending(current))
- return -ERESTARTSYS;
- }
- spin_lock_irqsave(&zr->lock, flags);
- if (zr->jpg_dma_tail != zr->jpg_dma_head)
- frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME];
- else
- frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
- /* buffer should now be in BUZ_STATE_DONE */
- #if(DEBUGLEVEL > 0)
- if (zr->jpg_gbuf[frame].state != BUZ_STATE_DONE)
- printk(KERN_ERR "%s: jpg_sync - internal errorn",
- zr->name);
- #endif
- *bs = zr->jpg_gbuf[frame].bs;
- zr->jpg_gbuf[frame].state = BUZ_STATE_USER;
- spin_unlock_irqrestore(&zr->lock, flags);
- return 0;
- }
- /* when this is called the spinlock must be held */
- static void zoran_feed_stat_com(struct zoran *zr)
- {
- /* move frames from pending queue to DMA */
- int frame, i, max_stat_com;
- max_stat_com =
- (zr->params.TmpDcm ==
- 1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1);
- while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com
- && zr->jpg_dma_head < zr->jpg_que_head) {
- frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME];
- if (zr->params.TmpDcm == 1) {
- /* fill 1 stat_com entry */
- i = (zr->jpg_dma_head -
- zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
- if (!(zr->stat_com[i] & 1))
- break;
- zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus;
- } else {
- /* fill 2 stat_com entries */
- i = ((zr->jpg_dma_head -
- zr->jpg_err_shift) & 1) * 2;
- if (!(zr->stat_com[i] & 1))
- break;
- zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus;
- zr->stat_com[i + 1] =
- zr->jpg_gbuf[frame].frag_tab_bus;
- }
- zr->jpg_gbuf[frame].state = BUZ_STATE_DMA;
- zr->jpg_dma_head++;
- }
- if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
- zr->jpg_queued_num++;
- }
- /* when this is called the spinlock must be held */
- static void zoran_reap_stat_com(struct zoran *zr)
- {
- /* move frames from DMA queue to done queue */
- int i;
- u32 stat_com;
- unsigned int seq;
- unsigned int dif;
- int frame;
- struct zoran_gbuffer *gbuf;
- /* In motion decompress we don't have a hardware frame counter,
- we just count the interrupts here */
- if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
- zr->jpg_seq_num++;
- }
- while (zr->jpg_dma_tail < zr->jpg_dma_head) {
- if (zr->params.TmpDcm == 1)
- i = (zr->jpg_dma_tail -
- zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
- else
- i = ((zr->jpg_dma_tail -
- zr->jpg_err_shift) & 1) * 2 + 1;
- stat_com = zr->stat_com[i];
- if ((stat_com & 1) == 0) {
- return;
- }
- frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
- gbuf = &zr->jpg_gbuf[frame];
- do_gettimeofday(&gbuf->bs.timestamp);
- if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
- gbuf->bs.length = (stat_com & 0x7fffff) >> 1;
- /* update sequence number with the help of the counter in stat_com */
- seq = ((stat_com >> 24) + zr->jpg_err_seq) & 0xff;
- dif = (seq - zr->jpg_seq_num) & 0xff;
- zr->jpg_seq_num += dif;
- } else {
- gbuf->bs.length = 0;
- }
- gbuf->bs.seq =
- zr->params.TmpDcm ==
- 2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num;
- gbuf->state = BUZ_STATE_DONE;
- zr->jpg_dma_tail++;
- }
- }
- static void error_handler(struct zoran *zr, u32 astat, u32 stat)
- {
- /* This is JPEG error handling part */
- if ((zr->codec_mode != BUZ_MODE_MOTION_COMPRESS)
- && (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS)) {
- //printk(KERN_ERR "%s: Internal error: error handling request in mode %dn", zr->name, zr->codec_mode);
- return;
- }
- if ((stat & 1) == 0
- && zr->codec_mode == BUZ_MODE_MOTION_COMPRESS
- && zr->jpg_dma_tail - zr->jpg_que_tail >= zr->jpg_nbufs) {
- /* No free buffers... */
- zoran_reap_stat_com(zr);
- zoran_feed_stat_com(zr);
- wake_up_interruptible(&zr->jpg_capq);
- zr->JPEG_missed = 0;
- return;
- }
- if (zr->JPEG_error != 1) {
- /*
- * First entry: error just happened during normal operation
- *
- * In BUZ_MODE_MOTION_COMPRESS:
- *
- * Possible glitch in TV signal. In this case we should
- * stop the codec and wait for good quality signal before
- * restarting it to avoid further problems
- *
- * In BUZ_MODE_MOTION_DECOMPRESS:
- *
- * Bad JPEG frame: we have to mark it as processed (codec crashed
- * and was not able to do it itself), and to remove it from queue.
- */
- btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
- udelay(1);
- stat =
- stat | (post_office_read(zr, 7, 0) & 3) << 8 |
- zr36060_read_8(zr, 0x008);
- btwrite(0, ZR36057_JPC);
- btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
- zr36060_reset(zr);
- zr36060_sleep(zr, 1);
- zr->JPEG_error = 1;
- zr->num_errors++;
- /* Report error */
- #if(DEBUGLEVEL > 1)
- if (zr->num_errors <= 8) {
- long frame;
- frame =
- zr->jpg_pend[zr->
- jpg_dma_tail & BUZ_MASK_FRAME];
- printk(KERN_ERR
- "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ",
- zr->name, stat, zr->last_isr,
- zr->jpg_que_tail, zr->jpg_dma_tail,
- zr->jpg_dma_head, zr->jpg_que_head,
- zr->jpg_seq_num, frame);
- printk("stat_com frames:");
- {
- int i, j;
- for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
- for (i = 0; i < zr->jpg_nbufs; i++) {
- if (zr->stat_com[j] ==
- zr->jpg_gbuf[i].
- frag_tab_bus) {
- printk("% d->%d",
- j, i);
- }
- }
- }
- printk("n");
- }
- }
- #endif
- /* Find an entry in stat_com and rotate contents */
- {
- int i;
- if (zr->params.TmpDcm == 1)
- i = (zr->jpg_dma_tail -
- zr->
- jpg_err_shift) & BUZ_MASK_STAT_COM;
- else
- i = ((zr->jpg_dma_tail -
- zr->jpg_err_shift) & 1) * 2;
- if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
- /* Mimic zr36067 operation */
- zr->stat_com[i] |= 1;
- if (zr->params.TmpDcm != 1)
- zr->stat_com[i + 1] |= 1;
- /* Refill */
- zoran_reap_stat_com(zr);
- zoran_feed_stat_com(zr);
- wake_up_interruptible(&zr->jpg_capq);
- /* Find an entry in stat_com again after refill */
- if (zr->params.TmpDcm == 1)
- i = (zr->jpg_dma_tail -
- zr->
- jpg_err_shift) &
- BUZ_MASK_STAT_COM;
- else
- i = ((zr->jpg_dma_tail -
- zr->jpg_err_shift) & 1) * 2;
- }
- if (i) {
- /* Rotate stat_comm entries to make current entry first */
- int j;
- u32 bus_addr[BUZ_NUM_STAT_COM];
- memcpy(bus_addr, zr->stat_com,
- sizeof(bus_addr));
- for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
- zr->stat_com[j] =
- bus_addr[(i +
- j) &
- BUZ_MASK_STAT_COM];
- }
- zr->jpg_err_shift += i;
- zr->jpg_err_shift &= BUZ_MASK_STAT_COM;
- }
- if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
- zr->jpg_err_seq = zr->jpg_seq_num; /* + 1; */
- }
- }
- /* Now the stat_comm buffer is ready for restart */
- {
- int status;
- status = 0;
- if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_GET_STATUS, &status);
- if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS
- || (status & DECODER_STATUS_GOOD)) {
- /********** RESTART code *************/
- zr36060_reset(zr);
- zr36060_set_cap(zr, zr->codec_mode);
- zr36057_set_jpg(zr, zr->codec_mode);
- jpeg_start(zr);
- #if(DEBUGLEVEL > 1)
- if (zr->num_errors <= 8)
- printk(KERN_INFO "%s: Restartn",
- zr->name);
- #endif
- zr->JPEG_missed = 0;
- zr->JPEG_error = 2;
- /********** End RESTART code ***********/
- }
- }
- }
- static void zoran_irq(int irq, void *dev_id, struct pt_regs *regs)
- {
- u32 stat, astat;
- int count;
- struct zoran *zr;
- unsigned long flags;
- zr = (struct zoran *) dev_id;
- count = 0;
- if (zr->testing) {
- /* Testing interrupts */
- spin_lock_irqsave(&zr->lock, flags);
- while ((stat = count_reset_interrupt(zr))) {
- if (count++ > 100) {
- btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
- printk(KERN_ERR
- "%s: IRQ lockup while testing, isr=0x%08x, cleared int maskn",
- zr->name, stat);
- wake_up_interruptible(&zr->test_q);
- }
- }
- zr->last_isr = stat;
- spin_unlock_irqrestore(&zr->lock, flags);
- return;
- }
- spin_lock_irqsave(&zr->lock, flags);
- while (1) {
- /* get/clear interrupt status bits */
- stat = count_reset_interrupt(zr);
- astat = stat & IRQ_MASK;
- if (!astat) {
- break;
- }
- if (astat & cardvsync[zr->card]) { // SW
- if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS
- || zr->codec_mode ==
- BUZ_MODE_MOTION_COMPRESS) {
- /* count missed interrupts */
- zr->JPEG_missed++;
- }
- //post_office_read(zr,1,0);
- /* Interrupts may still happen when zr->v4l_memgrab_active is switched off.
- We simply ignore them */
- if (zr->v4l_memgrab_active) {
- /* A lot more checks should be here ... */
- if ((btread(ZR36057_VSSFGR) &
- ZR36057_VSSFGR_SnapShot) == 0)
- printk(KERN_WARNING
- "%s: BuzIRQ with SnapShot off ???n",
- zr->name);
- if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) {
- /* There is a grab on a frame going on, check if it has finished */
- if ((btread(ZR36057_VSSFGR) &
- ZR36057_VSSFGR_FrameGrab) ==
- 0) {
- /* it is finished, notify the user */
- zr->v4l_gbuf[zr->
- v4l_grab_frame].
- state = BUZ_STATE_DONE;
- zr->v4l_grab_frame =
- NO_GRAB_ACTIVE;
- zr->v4l_grab_seq++;
- zr->v4l_pend_tail++;
- }
- }
- if (zr->v4l_grab_frame == NO_GRAB_ACTIVE)
- wake_up_interruptible(&zr->
- v4l_capq);
- /* Check if there is another grab queued */
- if (zr->v4l_grab_frame == NO_GRAB_ACTIVE
- && zr->v4l_pend_tail !=
- zr->v4l_pend_head) {
- int frame =
- zr->v4l_pend[zr->
- v4l_pend_tail &
- V4L_MASK_FRAME];
- u32 reg;
- zr->v4l_grab_frame = frame;
- /* Set zr36057 video front end and enable video */
- /* Buffer address */
- reg =
- zr->v4l_gbuf[frame].
- fbuffer_bus;
- btwrite(reg, ZR36057_VDTR);
- if (zr->video_interlace)
- reg += zr->gbpl;
- btwrite(reg, ZR36057_VDBR);
- /* video stride, status, and frame grab register */
- reg = 0;
- if (zr->video_interlace)
- reg += zr->gbpl;
- reg =
- (reg <<
- ZR36057_VSSFGR_DispStride);
- reg |= ZR36057_VSSFGR_VidOvf;
- reg |= ZR36057_VSSFGR_SnapShot;
- reg |= ZR36057_VSSFGR_FrameGrab;
- btwrite(reg, ZR36057_VSSFGR);
- btor(ZR36057_VDCR_VidEn,
- ZR36057_VDCR);
- }
- }
- }
- #if (IRQ_MASK & ZR36057_ISR_CodRepIRQ)
- if (astat & ZR36057_ISR_CodRepIRQ) {
- zr->intr_counter_CodRepIRQ++;
- IDEBUG(printk
- (KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQn",
- zr->name));
- btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR);
- }
- #endif /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */
- #if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ)
- if (astat & ZR36057_ISR_JPEGRepIRQ) {
- if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS
- || zr->codec_mode ==
- BUZ_MODE_MOTION_COMPRESS) {
- #if(DEBUGLEVEL > 1)
- if (!zr->frame_num || zr->JPEG_error) {
- printk(KERN_INFO
- "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%dn",
- zr->name, stat,
- zr->params.odd_even,
- zr->params.field_per_buff,
- zr->JPEG_missed);
- {
- char sc[] = "0000";
- char sv[5];
- int i;
- strcpy(sv, sc);
- for (i = 0; i < 4; i++) {
- if (zr->
- stat_com[i] &
- 1)
- sv[i] =
- '1';
- }
- sv[4] = 0;
- printk(KERN_INFO
- "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ldn",
- zr->name, sv,
- zr->jpg_que_tail,
- zr->jpg_dma_tail,
- zr->jpg_dma_head,
- zr->jpg_que_head);
- }
- } else {
- if (zr->JPEG_missed > zr->JPEG_max_missed) // Get statistics
- zr->JPEG_max_missed =
- zr->JPEG_missed;
- if (zr->JPEG_missed <
- zr->JPEG_min_missed)
- zr->JPEG_min_missed =
- zr->JPEG_missed;
- }
- #endif
- #if(DEBUGLEVEL > 2)
- if (zr->frame_num < 6) {
- int i;
- printk("%s: seq=%ld stat_com:",
- zr->name, zr->jpg_seq_num);
- for (i = 0; i < 4; i++) {
- printk(" %08x",
- zr->stat_com[i]);
- }
- printk("n");
- }
- #endif
- zr->frame_num++;
- zr->JPEG_missed = 0;
- zr->JPEG_error = 0;
- zoran_reap_stat_com(zr);
- zoran_feed_stat_com(zr);
- wake_up_interruptible(&zr->jpg_capq);
- } //else {
- // printk(KERN_ERR "%s: JPEG interrupt while not in motion (de)compress mode!n", zr->name);
- //}
- }
- #endif /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */
- if ((astat & cardjpegint[zr->card]) /* DATERR interrupt received */
- ||zr->JPEG_missed > 25 /* Too many fields missed without processing */
- || zr->JPEG_error == 1 /* We are already in error processing */
- || ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
- && (zr->
- frame_num & (zr->JPEG_missed >
- zr->params.field_per_buff)))
- /* fields missed during decompression */
- ) {
- error_handler(zr, astat, stat);
- }
- count++;
- if (count > 10) {
- printk(KERN_WARNING "%s: irq loop %dn", zr->name,
- count);
- if (count > 20) {
- btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
- printk(KERN_ERR
- "%s: IRQ lockup, cleared int maskn",
- zr->name);
- break;
- }
- }
- zr->last_isr = stat;
- }
- spin_unlock_irqrestore(&zr->lock, flags);
- }
- /* Check a zoran_params struct for correctness, insert default params */
- static int zoran_check_params(struct zoran *zr,
- struct zoran_params *params)
- {
- int err = 0, err0 = 0;
- /* insert constant params */
- params->major_version = MAJOR_VERSION;
- params->minor_version = MINOR_VERSION;
- /* Check input and norm: must be set by calling VIDIOCSCHAN only! */
- params->norm = zr->params.norm;
- params->input = zr->params.input;
- /* Check decimation, set default values for decimation = 1, 2, 4 */
- switch (params->decimation) {
- case 1:
- params->HorDcm = 1;
- params->VerDcm = 1;
- params->TmpDcm = 1;
- params->field_per_buff = 2;
- params->img_x = 0;
- params->img_y = 0;
- params->img_width = zr->timing->Wa;
- params->img_height = zr->timing->Ha / 2;
- break;
- case 2:
- params->HorDcm = 2;
- params->VerDcm = 1;
- params->TmpDcm = 2;
- params->field_per_buff = 1;
- params->img_x = 8;
- params->img_y = 0;
- params->img_width = zr->timing->Wa;
- params->img_height = zr->timing->Ha / 2;
- break;
- case 4:
- params->HorDcm = 4;
- params->VerDcm = 2;
- params->TmpDcm = 2;
- params->field_per_buff = 1;
- params->img_x = 8;
- params->img_y = 0;
- params->img_width = zr->timing->Wa;
- params->img_height = zr->timing->Ha / 2;
- break;
- case 0:
- /* We have to check the data the user has set */
- if (params->HorDcm != 1 && params->HorDcm != 2
- && params->HorDcm != 4)
- err0++;
- if (params->VerDcm != 1 && params->VerDcm != 2)
- err0++;
- if (params->TmpDcm != 1 && params->TmpDcm != 2)
- err0++;
- if (params->field_per_buff != 1
- && params->field_per_buff != 2)
- err0++;
- if (params->img_x < 0)
- err0++;
- if (params->img_y < 0)
- err0++;
- if (params->img_width < 0)
- err0++;
- if (params->img_height < 0)
- err0++;
- if (params->img_x + params->img_width > zr->timing->Wa)
- err0++;
- if (params->img_y + params->img_height >
- zr->timing->Ha / 2)
- err0++;
- if (params->HorDcm) {
- if (params->img_width % (16 * params->HorDcm) != 0)
- err0++;
- if (params->img_height % (8 * params->VerDcm) != 0)
- err0++;
- }
- if (err0) {
- DEBUG1(printk(KERN_ERR
- "%s: SET PARAMS: error in params for decimation = 0n",
- zr->name));
- err++;
- }
- break;
- default:
- DEBUG1(printk(KERN_ERR
- "%s: SET PARAMS: decimation = %d, must be 0, 1, 2 or 4n",
- zr->name, params->decimation));
- err++;
- break;
- }
- if (params->quality > 100)
- params->quality = 100;
- if (params->quality < 5)
- params->quality = 5;
- if (params->APPn < 0)
- params->APPn = 0;
- if (params->APPn > 15)
- params->APPn = 15;
- if (params->APP_len < 0)
- params->APP_len = 0;
- if (params->APP_len > 60)
- params->APP_len = 60;
- if (params->COM_len < 0)
- params->COM_len = 0;
- if (params->COM_len > 60)
- params->COM_len = 60;
- if (err)
- return -EINVAL;
- return 0;
- }
- static void zoran_open_init_params(struct zoran *zr)
- {
- int i;
- /* Per default, map the V4L Buffers */
- zr->map_mjpeg_buffers = 0;
- /* User must explicitly set a window */
- zr->window_set = 0;
- zr->window.x = 0;
- zr->window.y = 0;
- zr->window.width = 0;
- zr->window.height = 0;
- zr->window.chromakey = 0;
- zr->window.flags = 0;
- zr->window.clips = NULL;
- zr->window.clipcount = 0;
- zr->video_interlace = 0;
- zr->v4l_memgrab_active = 0;
- zr->v4l_overlay_active = 0;
- zr->v4l_grab_frame = NO_GRAB_ACTIVE;
- zr->v4l_grab_seq = 0;
- zr->gwidth = 0;
- zr->gheight = 0;
- zr->gformat = 0;
- zr->gbpl = 0;
- /* DMA ring stuff for V4L */
- zr->v4l_pend_tail = 0;
- zr->v4l_pend_head = 0;
- for (i = 0; i < v4l_nbufs; i++) {
- zr->v4l_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */
- }
- /* Set necessary params and call zoran_check_params to set the defaults */
- zr->params.decimation = 1;
- zr->params.quality = 50; /* default compression factor 8 */
- if (zr->card != BUZ)
- zr->params.odd_even = 1;
- else
- zr->params.odd_even = 0;
- zr->params.APPn = 0;
- zr->params.APP_len = 0; /* No APPn marker */
- for (i = 0; i < 60; i++)
- zr->params.APP_data[i] = 0;
- zr->params.COM_len = 0; /* No COM marker */
- for (i = 0; i < 60; i++)
- zr->params.COM_data[i] = 0;
- zr->params.VFIFO_FB = 0;
- memset(zr->params.reserved, 0, sizeof(zr->params.reserved));
- zr->params.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT;
- i = zoran_check_params(zr, &zr->params);
- if (i)
- printk(KERN_ERR
- "%s: zoran_open_init_params internal errorn",
- zr->name);
- clear_interrupt_counters(zr);
- zr->testing = 0;
- }
- /*
- * Open a zoran card. Right now the flags stuff is just playing
- */
- static int zoran_open(struct video_device *dev, int flags)
- {
- struct zoran *zr = (struct zoran *) dev;
- //int one = 1;
- DEBUG1(printk
- (KERN_INFO "%s: zoran_open, %s pid=[%d]n", zr->name,
- current->comm, current->pid));
- switch (flags) {
- case 0:
- if (zr->user > 1) {
- DEBUG1(printk(KERN_WARNING
- "%s: zoran_open: Buz is allready in usen",
- zr->name));
- return -EBUSY;
- }
- zr->user++;
- if (zr->user == 1 && v4l_fbuffer_alloc(zr) < 0) {
- zr->user--;
- printk(KERN_ERR
- "%s: zoran_open: v4l_fbuffer_alloc failedn",
- zr->name);
- return -ENOMEM;
- }
- /* default setup */
- if (zr->user == 1) { /* First device open */
- zoran_open_init_params(zr);
- zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
- btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts
- btor(ZR36057_ICR_IntPinEn, ZR36057_ICR);
- dev->busy = 0; /* Allow second open */
- }
- break;
- default:
- DEBUG1(printk(KERN_WARNING
- "%s: zoran_open: flags = 0x%x not yet supportedn",
- zr->name, flags));
- return -EBUSY;
- break;
- }
- MOD_INC_USE_COUNT;
- return 0;
- }
- static void zoran_close(struct video_device *dev)
- {
- struct zoran *zr = (struct zoran *) dev;
- int zero = 0, two = 2;
- DEBUG1(printk
- (KERN_INFO "%s: zoran_close, %s pid=[%d]n", zr->name,
- current->comm, current->pid));
- /* Clean up JPEG process */
- wake_up_interruptible(&zr->jpg_capq);
- zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
- jpg_fbuffer_free(zr);
- zr->jpg_nbufs = 0;
- if (zr->user == 1) { /* Last process */
- /* disable interrupts */
- btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
- #if(DEBUGLEVEL > 1)
- print_interrupts(zr);
- #endif
- /* Overlay off */
- wake_up_interruptible(&zr->v4l_capq);
- zr36057_set_memgrab(zr, 0);
- if (zr->v4l_overlay_active)
- zr36057_overlay(zr, 0);
- v4l_fbuffer_free(zr);
- if (!pass_through) { /* Switch to color bar */
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_ENABLE_OUTPUT, &zero);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEOENCODER,
- ENCODER_SET_INPUT, &two);
- set_videobus_enable(zr, 1);
- }
- }
- zr->user--;
- MOD_DEC_USE_COUNT;
- DEBUG2(printk(KERN_INFO "%s: zoran_close donen", zr->name));
- }
- static long zoran_read(struct video_device *dev, char *buf,
- unsigned long count, int nonblock)
- {
- return -EINVAL;
- }
- static long zoran_write(struct video_device *dev, const char *buf,
- unsigned long count, int nonblock)
- {
- return -EINVAL;
- }
- /*
- * ioctl routine
- */
- static int do_zoran_ioctl(struct zoran *zr, unsigned int cmd,
- void *arg)
- {
- switch (cmd) {
- case VIDIOCGCAP:
- {
- struct video_capability b;
- DEBUG2(printk("%s: ioctl VIDIOCGCAPn", zr->name));
- strncpy(b.name, zr->video_dev.name,
- sizeof(b.name));
- b.type =
- VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
- VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
- VID_TYPE_SCALES;
- /* theoretically we could also flag VID_TYPE_SUBCAPTURE
- but this is not even implemented in the BTTV driver */
- if (zr->card == DC10 || zr->card == DC10plus) {
- b.channels = 3; /* composite, svhs, internal */
- } else {
- b.channels = 2; /* composite, svhs */
- }
- b.audios = 0;
- b.maxwidth = BUZ_MAX_WIDTH;
- b.maxheight = BUZ_MAX_HEIGHT;
- b.minwidth = BUZ_MIN_WIDTH;
- b.minheight = BUZ_MIN_HEIGHT;
- if (copy_to_user(arg, &b, sizeof(b))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case VIDIOCGCHAN:
- {
- struct video_channel v;
- if (copy_from_user(&v, arg, sizeof(v))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl VIDIOCGCHAN for channel %dn",
- zr->name, v.channel));
- switch (v.channel) {
- case 0:
- strcpy(v.name, "Composite");
- break;
- case 1:
- strcpy(v.name, "SVHS");
- break;
- case 2:
- if (zr->card == DC10
- || zr->card == DC10plus) {
- strcpy(v.name, "Internal/comp");
- break;
- }
- default:
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCGCHAN on not existing channel %dn",
- zr->name, v.channel));
- return -EINVAL;
- }
- v.tuners = 0;
- v.flags = 0;
- v.type = VIDEO_TYPE_CAMERA;
- v.norm = zr->params.norm;
- if (copy_to_user(arg, &v, sizeof(v))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says:
- * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input."
- * ^^^^^^^
- * The famos BTTV driver has it implemented with a struct video_channel argument
- * and we follow it for compatibility reasons
- *
- * BTW: this is the only way the user can set the norm!
- */
- case VIDIOCSCHAN:
- {
- struct video_channel v;
- int input;
- int on, res;
- int encoder_norm;
- if (copy_from_user(&v, arg, sizeof(v))) {
- return -EFAULT;
- }
- if (zr->codec_mode != BUZ_MODE_IDLE) {
- if (v.norm != zr->params.norm
- || v.channel != zr->params.input) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSCHAN called while the card in capture/playback moden",
- zr->name));
- return -EINVAL;
- } else {
- DEBUG1(printk(BUZ_WARNING
- "%s: Warning: VIDIOCSCHAN called while the card in capture/playback moden",
- zr->name));
- }
- }
- DEBUG2(printk
- ("%s: ioctl VIDIOCSCHAN: channel=%d, norm=%dn",
- zr->name, v.channel, v.norm));
- switch (v.channel) {
- case 0:
- if (zr->card == BUZ)
- input = 3;
- else
- input = 0;
- break;
- case 1:
- input = 7;
- break;
- case 2:
- if (zr->card == DC10
- || zr->card == DC10plus) {
- input = 5;
- break;
- }
- default:
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSCHAN on not existing channel %dn",
- zr->name, v.channel));
- return -EINVAL;
- break;
- }
- if (lock_norm && v.norm != zr->params.norm) {
- if (lock_norm > 1) {
- DEBUG1(printk(KERN_WARNING
- "%s: VIDIOCSCHAN: TV standard is locked, can not switch norm.n",
- zr->name));
- return -EINVAL;
- } else {
- DEBUG1(printk(KERN_WARNING
- "%s: VIDIOCSCHAN: TV standard is locked, norm was not changed.n",
- zr->name));
- v.norm = zr->params.norm;
- }
- }
-
- if(v.norm >= 2)
- return -EINVAL;
- if (!cardnorms[zr->card][v.norm]) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSCHAN with not supported norm %dn",
- zr->name, v.norm));
- return -EOPNOTSUPP;
- break;
- }
- encoder_norm = v.norm;
- zr->params.norm = v.norm;
- zr->params.input = v.channel;
- zr->timing = cardnorms[zr->card][zr->params.norm];
- /* We switch overlay off and on since a change in the norm
- needs different VFE settings */
- on = zr->v4l_overlay_active
- && !zr->v4l_memgrab_active;
- if (on)
- zr36057_overlay(zr, 0);
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_INPUT, &input);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_NORM,
- &zr->params.norm);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEOENCODER,
- ENCODER_SET_NORM,
- &encoder_norm);
- set_videobus_enable(zr, 1);
- if (on)
- zr36057_overlay(zr, 1);
- /* Make sure the changes come into effect */
- res = wait_grab_pending(zr);
- if (res)
- return res;
- return 0;
- }
- break;
- case VIDIOCGTUNER:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCGTUNER not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case VIDIOCSTUNER:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCSTUNER not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case VIDIOCGPICT:
- {
- struct video_picture p = zr->picture;
- DEBUG2(printk
- ("%s: ioctl VIDIOCGPICTn", zr->name));
- p.depth = zr->buffer.depth;
- switch (zr->buffer.depth) {
- case 15:
- p.palette = VIDEO_PALETTE_RGB555;
- break;
- case 16:
- p.palette = VIDEO_PALETTE_RGB565;
- break;
- case 24:
- p.palette = VIDEO_PALETTE_RGB24;
- break;
- case 32:
- p.palette = VIDEO_PALETTE_RGB32;
- break;
- }
- if (copy_to_user(arg, &p, sizeof(p))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case VIDIOCSPICT:
- {
- struct video_picture p;
- if (copy_from_user(&p, arg, sizeof(p))) {
- return -EFAULT;
- }
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_PICTURE, &p);
- DEBUG2(printk
- ("%s: ioctl VIDIOCSPICT bri=%d hue=%d col=%d con=%d dep=%d pal=%dn",
- zr->name, p.brightness, p.hue, p.colour,
- p.contrast, p.depth, p.palette));
- /* The depth and palette values have no meaning to us,
- should we return -EINVAL if they don't fit ? */
- zr->picture = p;
- return 0;
- }
- break;
- case VIDIOCCAPTURE:
- {
- int v, res;
- if (copy_from_user(&v, arg, sizeof(v))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl VIDIOCCAPTURE: %dn", zr->name,
- v));
- /* If there is nothing to do, return immediatly */
- if ((v && zr->v4l_overlay_active)
- || (!v && !zr->v4l_overlay_active))
- return 0;
- if (v == 0) {
- zr->v4l_overlay_active = 0;
- if (!zr->v4l_memgrab_active)
- zr36057_overlay(zr, 0);
- /* When a grab is running, the video simply won't be switched on any more */
- } else {
- if (!zr->buffer_set || !zr->window_set) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCCAPTURE: buffer or window not setn",
- zr->name));
- return -EINVAL;
- }
- zr->v4l_overlay_active = 1;
- if (!zr->v4l_memgrab_active)
- zr36057_overlay(zr, 1);
- /* When a grab is running, the video will be switched on when grab is finished */
- }
- /* Make sure the changes come into effect */
- res = wait_grab_pending(zr);
- if (res)
- return res;
- return 0;
- }
- break;
- case VIDIOCGWIN:
- {
- DEBUG2(printk("%s: ioctl VIDIOCGWINn", zr->name));
- if (copy_to_user
- (arg, &zr->window, sizeof(zr->window))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case VIDIOCSWIN:
- {
- struct video_clip *vcp;
- struct video_window vw;
- struct tvnorm *tvn;
- int on, end, res, Wa, Ha;
- tvn = zr->timing;
- Wa = tvn->Wa;
- Ha = tvn->Ha;
- if (copy_from_user(&vw, arg, sizeof(vw))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl VIDIOCSWIN: x=%d y=%d w=%d h=%d clipcount=%dn",
- zr->name, vw.x, vw.y, vw.width, vw.height,
- vw.clipcount));
- if (!zr->buffer_set) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSWIN: frame buffer has to be set firstn",
- zr->name));
- return -EINVAL;
- }
- /*
- * The video front end needs 4-byte alinged line sizes, we correct that
- * silently here if necessary
- */
- if (zr->buffer.depth == 15
- || zr->buffer.depth == 16) {
- end = (vw.x + vw.width) & ~1; /* round down */
- vw.x = (vw.x + 1) & ~1; /* round up */
- vw.width = end - vw.x;
- }
- if (zr->buffer.depth == 24) {
- end = (vw.x + vw.width) & ~3; /* round down */
- vw.x = (vw.x + 3) & ~3; /* round up */
- vw.width = end - vw.x;
- }
- if (vw.width > Wa)
- vw.width = Wa;
- if (vw.height > Ha)
- vw.height = Ha;
- /* Check for vaild parameters */
- if (vw.width < BUZ_MIN_WIDTH
- || vw.height < BUZ_MIN_HEIGHT
- || vw.width > BUZ_MAX_WIDTH
- || vw.height > BUZ_MAX_HEIGHT) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSWIN: width = %d or height = %d invalidn",
- zr->name, vw.width, vw.height));
- return -EINVAL;
- }
- zr->window.x = vw.x;
- zr->window.y = vw.y;
- zr->window.width = vw.width;
- zr->window.height = vw.height;
- zr->window.chromakey = 0;
- zr->window.flags = 0; // RJ: Is this intended for interlace on/off ?
- zr->window.clips = NULL;
- /*
- * If an overlay is running, we have to switch it off
- * and switch it on again in order to get the new settings in effect.
- *
- * We also want to avoid that the overlay mask is written
- * when an overlay is running.
- */
- on = zr->v4l_overlay_active
- && !zr->v4l_memgrab_active;
- if (on)
- zr36057_overlay(zr, 0);
- /*
- * Write the overlay mask if clips are wanted.
- */
-
- if (vw.clipcount > 2048)
- return -EINVAL;
- if (vw.clipcount) {
- vcp =
- vmalloc(sizeof(struct video_clip) *
- (vw.clipcount + 4));
- if (vcp == NULL) {
- printk(KERN_ERR
- "%s: zoran_ioctl: Alloc of clip mask failedn",
- zr->name);
- return -ENOMEM;
- }
- if (copy_from_user
- (vcp, vw.clips,
- sizeof(struct video_clip) *
- vw.clipcount)) {
- vfree(vcp);
- return -EFAULT;
- }
- write_overlay_mask(zr, vcp, vw.clipcount);
- vfree(vcp);
- }
- zr->window.clipcount = vw.clipcount;
-
- if (on)
- zr36057_overlay(zr, 1);
- zr->window_set = 1;
- /* Make sure the changes come into effect */
- res = wait_grab_pending(zr);
- if (res)
- return res;
- return 0;
- }
- break;
- case VIDIOCGFBUF:
- {
- DEBUG2(printk
- ("%s: ioctl VIDIOCGFBUFn", zr->name));
- if (copy_to_user
- (arg, &zr->buffer, sizeof(zr->buffer))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case VIDIOCSFBUF:
- {
- struct video_buffer v;
- /* RJ: Isn't this too restrictive? As long as the user doesn't set
- the base address it shouldn't be too dangerous */
- if (!capable(CAP_SYS_ADMIN)) {
- DEBUG1(printk(KERN_ERR
- "%s: Only the superuser may issue VIDIOCSFBUF ioctln",
- zr->name));
- return -EPERM;
- }
- if (copy_from_user(&v, arg, sizeof(v))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl VIDIOCSFBUF: base=0x%x w=%d h=%d depth=%d bpl=%dn",
- zr->name, (u32) v.base, v.width, v.height,
- v.depth, v.bytesperline));
- if (zr->v4l_overlay_active) {
- /* Has the user gotten crazy ... ? */
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSFBUF not allowed when overlay activen",
- zr->name));
- return -EINVAL;
- }
- if (v.depth != 15 && v.depth != 16 && v.depth != 24
- && v.depth != 32) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSFBUF: depth=%d not supportedn",
- zr->name, v.depth));
- return -EINVAL;
- }
- if (v.height <= 0 || v.width <= 0
- || v.bytesperline <= 0) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSFBUF: invalid height/width/bpl valuen",
- zr->name));
- return -EINVAL;
- }
- if (v.bytesperline & 3) {
- DEBUG1(printk(KERN_ERR
- "%s: VIDIOCSFBUF: bytesperline must be 4-byte alignedn",
- zr->name));
- return -EINVAL;
- }
- if (v.base) {
- zr->buffer.base =
- (void *) ((unsigned long) v.base & ~3);
- }
- zr->buffer.height = v.height;
- zr->buffer.width = v.width;
- zr->buffer.depth = v.depth;
- zr->buffer.bytesperline = v.bytesperline;
- if (zr->buffer.base)
- zr->buffer_set = 1;
- zr->window_set = 0; /* The user should set new window parameters */
- return 0;
- }
- break;
- /* RJ: what is VIDIOCKEY intended to do ??? */
- case VIDIOCKEY:
- {
- /* Will be handled higher up .. */
- DEBUG2(printk("%s: ioctl VIDIOCKEYn", zr->name));
- return 0;
- }
- break;
- case VIDIOCGFREQ:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCGFREQ not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case VIDIOCSFREQ:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCSFREQ not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case VIDIOCGAUDIO:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCGAUDIO not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case VIDIOCSAUDIO:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCSAUDIO not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case VIDIOCSYNC:
- {
- int v;
- if (copy_from_user(&v, arg, sizeof(v))) {
- return -EFAULT;
- }
- DEBUG3(printk
- ("%s: ioctl VIDIOCSYNC %dn", zr->name, v));
- return v4l_sync(zr, v);
- }
- break;
- case VIDIOCMCAPTURE:
- {
- struct video_mmap vm;
- if (copy_from_user
- ((void *) &vm, (void *) arg, sizeof(vm))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl VIDIOCMCAPTURE frame=%d geom=%dx%d fmt=%dn",
- zr->name, vm.frame, vm.width, vm.height,
- vm.format));
- return v4l_grab(zr, &vm);
- }
- break;
- case VIDIOCGMBUF:
- {
- struct video_mbuf vm;
- int i;
- DEBUG2(printk
- ("%s: ioctl VIDIOCGMBUFn", zr->name));
- vm.size = v4l_nbufs * v4l_bufsize;
- vm.frames = v4l_nbufs;
- for (i = 0; i < v4l_nbufs; i++) {
- vm.offsets[i] = i * v4l_bufsize;
- }
- /* The next mmap will map the V4L buffers */
- zr->map_mjpeg_buffers = 0;
- if (copy_to_user(arg, &vm, sizeof(vm))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case VIDIOCGUNIT:
- {
- struct video_unit vu;
- DEBUG2(printk
- ("%s: ioctl VIDIOCGUNITn", zr->name));
- vu.video = zr->video_dev.minor;
- vu.vbi = VIDEO_NO_UNIT;
- vu.radio = VIDEO_NO_UNIT;
- vu.audio = VIDEO_NO_UNIT;
- vu.teletext = VIDEO_NO_UNIT;
- if (copy_to_user(arg, &vu, sizeof(vu))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- /*
- * RJ: In principal we could support subcaptures for V4L grabbing.
- * Not even the famous BTTV driver has them, however.
- * If there should be a strong demand, one could consider
- * to implement them.
- */
- case VIDIOCGCAPTURE:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCGCAPTURE not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case VIDIOCSCAPTURE:
- {
- DEBUG1(printk(KERN_ERR
- "%s: ioctl VIDIOCSCAPTURE not supportedn",
- zr->name));
- return -EINVAL;
- }
- break;
- case BUZIOC_G_PARAMS:
- {
- DEBUG2(printk
- ("%s: ioctl BUZIOC_G_PARAMSn", zr->name));
- if (copy_to_user
- (arg, &(zr->params), sizeof(zr->params))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case BUZIOC_S_PARAMS:
- {
- struct zoran_params bp;
- /* int input, on; */
- if (zr->codec_mode != BUZ_MODE_IDLE) {
- DEBUG1(printk(KERN_ERR
- "%s: BUZIOC_S_PARAMS called but Buz in capture/playback moden",
- zr->name));
- return -EINVAL;
- }
- if (copy_from_user(&bp, arg, sizeof(bp))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl BUZIOC_S_PARAMSn", zr->name));
- /* Check the params first before overwriting our internal values */
- if (zoran_check_params(zr, &bp))
- return -EINVAL;
- zr->params = bp;
- /* Make changes of input and norm go into effect immediatly */
- /* We switch overlay off and on since a change in the norm
- needs different VFE settings */
- if (copy_to_user(arg, &bp, sizeof(bp))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case BUZIOC_REQBUFS:
- {
- struct zoran_requestbuffers br;
- if (zr->jpg_buffers_allocated) {
- DEBUG1(printk(KERN_ERR
- "%s: BUZIOC_REQBUFS: buffers allready allocatedn",
- zr->name));
- return -EINVAL;
- }
- if (copy_from_user(&br, arg, sizeof(br))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl BUZIOC_REQBUFS count = %lu size=%lun",
- zr->name, br.count, br.size));
- /* Enforce reasonable lower and upper limits */
- if (br.count < 4)
- br.count = 4; /* Could be choosen smaller */
- if (br.count > BUZ_MAX_FRAME)
- br.count = BUZ_MAX_FRAME;
- br.size = PAGE_ALIGN(br.size);
- if (br.size < 8192)
- br.size = 8192; /* Arbitrary */
- /* br.size is limited by 1 page for the stat_com tables to a Maximum of 2 MB */
- if (br.size > (512 * 1024))
- br.size = (512 * 1024); /* 512 K should be enough */
- if (zr->need_contiguous
- && br.size > MAX_KMALLOC_MEM)
- br.size = MAX_KMALLOC_MEM;
- zr->jpg_nbufs = br.count;
- zr->jpg_bufsize = br.size;
- if (jpg_fbuffer_alloc(zr))
- return -ENOMEM;
- /* The next mmap will map the MJPEG buffers */
- zr->map_mjpeg_buffers = 1;
- if (copy_to_user(arg, &br, sizeof(br))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- case BUZIOC_QBUF_CAPT:
- {
- int nb;
- if (copy_from_user
- ((void *) &nb, (void *) arg, sizeof(int))) {
- return -EFAULT;
- }
- DEBUG4(printk
- ("%s: ioctl BUZIOC_QBUF_CAPT %dn",
- zr->name, nb));
- return jpg_qbuf(zr, nb, BUZ_MODE_MOTION_COMPRESS);
- }
- break;
- case BUZIOC_QBUF_PLAY:
- {
- int nb;
- if (copy_from_user
- ((void *) &nb, (void *) arg, sizeof(int))) {
- return -EFAULT;
- }
- DEBUG4(printk
- ("%s: ioctl BUZIOC_QBUF_PLAY %dn",
- zr->name, nb));
- return jpg_qbuf(zr, nb,
- BUZ_MODE_MOTION_DECOMPRESS);
- }
- break;
- case BUZIOC_SYNC:
- {
- struct zoran_sync bs;
- int res;
- DEBUG4(printk
- ("%s: ioctl BUZIOC_SYNCn", zr->name));
- res = jpg_sync(zr, &bs);
- if (copy_to_user(arg, &bs, sizeof(bs))) {
- return -EFAULT;
- }
- return res;
- }
- break;
- case BUZIOC_G_STATUS:
- {
- struct zoran_status bs;
- int norm, input, status;
- unsigned long timeout;
- if (zr->codec_mode != BUZ_MODE_IDLE) {
- DEBUG1(printk(KERN_ERR
- "%s: BUZIOC_G_STATUS called but Buz in capture/playback moden",
- zr->name));
- return -EINVAL;
- }
- if (copy_from_user(&bs, arg, sizeof(bs))) {
- return -EFAULT;
- }
- DEBUG2(printk
- ("%s: ioctl BUZIOC_G_STATUSn", zr->name));
- switch (bs.input) {
- case 0:
- if (zr->card == BUZ)
- input = 3;
- else
- input = 0;
- break;
- case 1:
- input = 7;
- break;
- default:
- DEBUG1(printk(KERN_ERR
- "%s: BUZIOC_G_STATUS on not existing input %dn",
- zr->name, bs.input));
- return -EINVAL;
- }
- /* Set video norm to VIDEO_MODE_AUTO */
- norm = VIDEO_MODE_AUTO;
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_INPUT, &input);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_NORM, &norm);
- set_videobus_enable(zr, 1);
- /* sleep 1 second */
- timeout = jiffies + 1 * HZ;
- while (jiffies < timeout)
- schedule();
- /* Get status of video decoder */
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_GET_STATUS, &status);
- bs.signal = (status & DECODER_STATUS_GOOD) ? 1 : 0;
- if (status & DECODER_STATUS_NTSC)
- bs.norm = VIDEO_MODE_NTSC;
- else if (status & DECODER_STATUS_SECAM)
- bs.norm = VIDEO_MODE_SECAM;
- else
- bs.norm = VIDEO_MODE_PAL;
- bs.color = (status & DECODER_STATUS_COLOR) ? 1 : 0;
- /* restore previous input and norm */
- if (zr->card == BUZ)
- input = zr->params.input == 0 ? 3 : 7;
- else
- input = zr->params.input == 0 ? 0 : 7;
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_INPUT, &input);
- i2c_control_device(&zr->i2c,
- I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_NORM,
- &zr->params.norm);
- set_videobus_enable(zr, 1);
- if (copy_to_user(arg, &bs, sizeof(bs))) {
- return -EFAULT;
- }
- return 0;
- }
- break;
- default:
- DEBUG1(printk
- ("%s: UNKNOWN ioctl cmd: 0x%xn", zr->name, cmd));
- return -ENOIOCTLCMD;
- }
- return 0;
- }
- static int zoran_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
- {
- struct zoran *zr = (struct zoran *) dev;
- int err;
-
- down(&zr->sem);
- err = do_zoran_ioctl(zr, cmd, arg);
- up(&zr->sem);
-
- return err;
- }
- /*
- * This maps the buffers to user space.
- *
- * Depending on the state of zr->map_mjpeg_buffers
- * the V4L or the MJPEG buffers are mapped
- *
- */
- static int do_zoran_mmap(struct zoran *zr, const char *adr,
- unsigned long size)
- {
- unsigned long start = (unsigned long) adr;
- unsigned long page, pos, todo, fraglen;
- int i, j;
- DEBUG2(printk
- (KERN_INFO "%s: mmap at 0x%08lx, size %lun", zr->name,
- start, size));
- if (zr->map_mjpeg_buffers) {
- /* Map the MJPEG buffers */
- if (!zr->jpg_buffers_allocated) {
- DEBUG1(printk(KERN_ERR
- "%s: zoran_mmap(MJPEG): buffers not yet allocatedn",
- zr->name));
- return -ENOMEM;
- }
- if (size > zr->jpg_nbufs * zr->jpg_bufsize) {
- DEBUG1(printk(KERN_ERR
- "%s: zoran_mmap(MJPEG): Max size is %lu - you wanted %lun",
- zr->name, zr->jpg_nbufs * zr->jpg_bufsize,
- size));
- return -EINVAL;
- }
- if (size != zr->jpg_nbufs * zr->jpg_bufsize)
- DEBUG1(printk(KERN_WARNING
- "%s: zoran_mmap(MJPEG): Expected %lu - you wanted %lun",
- zr->name, zr->jpg_nbufs * zr->jpg_bufsize,
- size));
- for (i = 0; i < zr->jpg_nbufs; i++) {
- for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) {
- fraglen =
- (zr->jpg_gbuf[i].
- frag_tab[2 * j + 1] & ~1) << 1;
- todo = size;
- if (todo > fraglen)
- todo = fraglen;
- pos =
- (unsigned long) zr->jpg_gbuf[i].
- frag_tab[2 * j];
- page = virt_to_phys(bus_to_virt(pos)); /* should just be pos on i386 */
- if (remap_page_range
- (start, page, todo, PAGE_SHARED)) {
- printk(KERN_ERR
- "%s: zoran_mmap(V4L): remap_page_range failedn",
- zr->name);
- return -EAGAIN;
- }
- size -= todo;
- start += todo;
- if (size == 0)
- break;
- if (zr->jpg_gbuf[i].
- frag_tab[2 * j + 1] & 1)
- break; /* was last fragment */
- }
- if (size == 0)
- break;
- }
- } else {
- /* Map the V4L buffers */
- if (size > v4l_nbufs * v4l_bufsize) {
- DEBUG1(printk(KERN_ERR
- "%s: zoran_mmap(V4L): Max size is %d - you wanted %ldn",
- zr->name, v4l_nbufs * v4l_bufsize, size));
- return -EINVAL;
- }
- if (size != v4l_nbufs * v4l_bufsize)
- DEBUG1(printk(KERN_WARNING
- "%s: zoran_mmap(V4L): Expected %d - you wanted %ldn",
- zr->name, v4l_nbufs * v4l_bufsize, size));
- for (i = 0; i < v4l_nbufs; i++) {
- todo = size;
- if (todo > v4l_bufsize)
- todo = v4l_bufsize;
- page = zr->v4l_gbuf[i].fbuffer_phys;
- DEBUG2(printk
- ("V4L remap page range %d 0x%lx %ld to 0x%lxn",
- i, page, todo, start));
- if (remap_page_range
- (start, page, todo, PAGE_SHARED)) {
- printk(KERN_ERR
- "%s: zoran_mmap(V4L): remap_page_range failedn",
- zr->name);
- return -EAGAIN;
- }
- size -= todo;
- start += todo;
- if (size == 0)
- break;
- }
- }
- return 0;
- }
- static int zoran_mmap(struct video_device *dev, const char *adr,
- unsigned long size)
- {
- int err;
- struct zoran *zr = (struct zoran *) dev;
-
- down(&zr->sem);
- err = do_zoran_mmap(zr, adr, size);
- up(&zr->sem);
-
- return err;
- }
- static int zoran_init_done(struct video_device *dev)
- {
- return 0;
- }
- static struct video_device zoran_template = {
- THIS_MODULE,
- ZORAN_NAME,
- VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |
- VID_TYPE_FRAMERAM | VID_TYPE_SCALES | VID_TYPE_SUBCAPTURE,
- ZORAN_HARDWARE,
- zoran_open,
- zoran_close,
- zoran_read,
- zoran_write,
- NULL,
- zoran_ioctl,
- zoran_mmap,
- zoran_init_done,
- NULL,
- 0,
- 0
- };
- /*
- * initialize video front end
- */
- static void zr36057_init_vfe(struct zoran *zr)
- {
- u32 reg;
- reg = btread(ZR36057_VFESPFR);
- reg |= ZR36057_VFESPFR_LittleEndian;
- reg &= ~ZR36057_VFESPFR_VCLKPol;
- reg |= ZR36057_VFESPFR_ExtFl;
- reg |= ZR36057_VFESPFR_TopField;
- btwrite(reg, ZR36057_VFESPFR);
- reg = btread(ZR36057_VDCR);
- if (triton || zr->revision <= 1)
- reg &= ~ZR36057_VDCR_Triton;
- else
- reg |= ZR36057_VDCR_Triton;
- btwrite(reg, ZR36057_VDCR);
- }
- static void test_interrupts(struct zoran *zr)
- {
- int timeout, icr;
- clear_interrupt_counters(zr);
- zr->testing = 1;
- icr = btread(ZR36057_ICR);
- btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR);
- timeout = interruptible_sleep_on_timeout(&zr->test_q, 1 * HZ);
- btwrite(0, ZR36057_ICR);
- btwrite(0x78000000, ZR36057_ISR);
- zr->testing = 0;
- printk(KERN_INFO "%s: Testing interrupts...n", zr->name);
- if (timeout) {
- printk(": time spent: %dn", 1 * HZ - timeout);
- }
- print_interrupts(zr);
- btwrite(icr, ZR36057_ICR);
- }
- static int zr36057_init(int i)
- {
- struct zoran *zr = &zoran[i];
- unsigned long mem;
- unsigned mem_needed;
- int j;
- int two = 2;
- int zero = 0;
- printk(KERN_INFO "%s: Initializing card[%d], zr=%xn", zr->name, i, (int) zr);
- /* default setup of all parameters which will persist beetween opens */
- zr->user = 0;
- init_waitqueue_head(&zr->v4l_capq);
- init_waitqueue_head(&zr->jpg_capq);
- init_waitqueue_head(&zr->test_q);
- zr->map_mjpeg_buffers = 0; /* Map V4L buffers by default */
- zr->jpg_nbufs = 0;
- zr->jpg_bufsize = 0;
- zr->jpg_buffers_allocated = 0;
- zr->buffer_set = 0; /* Flag if frame buffer has been set */
- zr->buffer.base = (void *) vidmem;
- zr->buffer.width = 0;
- zr->buffer.height = 0;
- zr->buffer.depth = 0;
- zr->buffer.bytesperline = 0;
- zr->params.norm = default_norm = (default_norm < 3 ? default_norm : VIDEO_MODE_PAL); /* Avoid nonsense settings from user */
- if (!(zr->timing = cardnorms[zr->card][zr->params.norm])) {
- printk(KERN_WARNING
- "%s: default TV statdard not supported by hardware. PAL will be used.n",
- zr->name);
- zr->params.norm = VIDEO_MODE_PAL;
- zr->timing = cardnorms[zr->card][zr->params.norm];
- }
- zr->params.input = default_input = (default_input ? 1 : 0); /* Avoid nonsense settings from user */
- zr->video_interlace = 0;
- /* Should the following be reset at every open ? */
- zr->picture.colour = 32768;
- zr->picture.brightness = 32768;
- zr->picture.hue = 32768;
- zr->picture.contrast = 32768;
- zr->picture.whiteness = 0;
- zr->picture.depth = 0;
- zr->picture.palette = 0;
- for (j = 0; j < VIDEO_MAX_FRAME; j++) {
- zr->v4l_gbuf[i].fbuffer = 0;
- zr->v4l_gbuf[i].fbuffer_phys = 0;
- zr->v4l_gbuf[i].fbuffer_bus = 0;
- }
- zr->stat_com = 0;
- /* default setup (will be repeated at every open) */
- zoran_open_init_params(zr);
- /* allocate memory *before* doing anything to the hardware in case allocation fails */
- /* STAT_COM table and overlay mask */
- mem_needed = (BUZ_NUM_STAT_COM + ((BUZ_MAX_WIDTH + 31) / 32) * BUZ_MAX_HEIGHT) * 4;
- mem = (unsigned long) kmalloc(mem_needed, GFP_KERNEL);
- if (!mem) {
- printk(KERN_ERR "%s: zr36057_init: kmalloc (STAT_COM + ovl.mask) failedn", zr->name);
- return -ENOMEM;
- }
- memset((void *) mem, 0, mem_needed);
- zr->stat_com = (u32 *) mem;
- for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
- zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */
- }
- zr->overlay_mask = (u32 *) (mem + BUZ_NUM_STAT_COM * 4);
- /* Initialize zr->jpg_gbuf */
- for (j = 0; j < BUZ_MAX_FRAME; j++) {
- zr->jpg_gbuf[j].frag_tab = 0;
- zr->jpg_gbuf[j].frag_tab_bus = 0;
- zr->jpg_gbuf[j].state = BUZ_STATE_USER;
- zr->jpg_gbuf[j].bs.frame = j;
- }
- /*
- * Now add the template and register the device unit.
- */
- memcpy(&zr->video_dev, &zoran_template, sizeof(zoran_template));
- strcpy(zr->video_dev.name, zr->name);
- if (video_register_device(&zr->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) {
- i2c_unregister_bus(&zr->i2c);
- kfree((void *) zr->stat_com);
- return -1;
- }
- /* Enable bus-mastering */
- pci_set_master(zr->pci_dev);
- if (zr->card == BUZ)
- j = zr->params.input == 0 ? 3 : 7;
- else
- j = zr->params.input == 0 ? 0 : 7;
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_INPUT, &j);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER,
- DECODER_SET_NORM, &zr->params.norm);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER,
- ENCODER_SET_NORM, &zr->params.norm);
- set_videobus_enable(zr, 1);
- /* toggle JPEG codec sleep to sync PLL */
- zr36060_sleep(zr, 1);
- zr36060_sleep(zr, 0);
- /* set individual interrupt enables (without GIRQ1)
- but don't global enable until zoran_open() */
- //btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ1, ZR36057_ICR); // SW
- // It looks like using only JPEGRepIRQEn is not always reliable,
- // may be when JPEG codec crashes it won't generate IRQ? So,
- btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM
- zr36057_init_vfe(zr);
- zr->zoran_proc = NULL;
- zr->initialized = 1;
- zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
- #if (DEBUGLEVEL > 2)
- detect_guest_activity(zr);
- #endif
- test_interrupts(zr);
- btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM
- if (!pass_through) {
- set_videobus_enable(zr, 0);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER,
- DECODER_ENABLE_OUTPUT, &zero);
- i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER,
- ENCODER_SET_INPUT, &two);
- set_videobus_enable(zr, 1);
- }
- return 0;
- }
- #include "zoran_procfs.c"
- static void release_dc10(void)
- {
- u8 command;
- int i;
- struct zoran *zr;
- for (i = 0; i < zoran_num; i++) {
- zr = &zoran[i];
- if (!zr->initialized)
- continue;
- /* unregister i2c_bus */
- i2c_unregister_bus((&zr->i2c));
- /* disable PCI bus-mastering */
- pci_read_config_byte(zr->pci_dev, PCI_COMMAND, &command);
- command &= ~PCI_COMMAND_MASTER;
- pci_write_config_byte(zr->pci_dev, PCI_COMMAND, command);
- /* put chip into reset */
- btwrite(0, ZR36057_SPGPPCR);
- free_irq(zr->pci_dev->irq, zr);
- /* unmap and free memory */
- kfree((void *) zr->stat_com);
- zoran_proc_cleanup(i);
- iounmap(zr->zr36057_mem);
- video_unregister_device(&zr->video_dev);
- }
- }
- /*
- * Scan for a Buz card (actually for the PCI contoler ZR36057),
- * request the irq and map the io memory
- */
- static int find_zr36057(void)
- {
- unsigned char latency, need_latency;
- struct zoran *zr;
- struct pci_dev *dev = NULL;
- int result;
- zoran_num = 0;
- while (zoran_num < BUZ_MAX
- && (dev =
- pci_find_device(PCI_VENDOR_ID_ZORAN,
- PCI_DEVICE_ID_ZORAN_36057,
- dev)) != NULL) {
- zr = &zoran[zoran_num];
- zr->pci_dev = dev;
- zr->zr36057_mem = NULL;
- zr->id = zoran_num;
- sprintf(zr->name, "MJPEG[%u]", zr->id);
- spin_lock_init(&zr->lock);
- init_MUTEX(&zr->sem);
- if (pci_enable_device(dev))
- continue;
- zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0);
- pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION,
- &zr->revision);
- if (zr->revision < 2) {
- printk(KERN_INFO
- "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.n",
- zr->name, zr->revision, zr->pci_dev->irq,
- zr->zr36057_adr);
- } else {
- unsigned short ss_vendor_id, ss_id;
- ss_vendor_id = zr->pci_dev->subsystem_vendor;
- ss_id = zr->pci_dev->subsystem_device;
- printk(KERN_INFO
- "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08xn",
- zr->name, zr->revision, zr->pci_dev->irq,
- zr->zr36057_adr);
- printk(KERN_INFO
- "%s: subsystem vendor=0x%04x id=0x%04xn",
- zr->name, ss_vendor_id, ss_id);
- }
- zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000);
- if (!zr->zr36057_mem) {
- printk(KERN_ERR "%s: ioremap failedn", zr->name);
- /* XXX handle error */
- }
- result = request_irq(zr->pci_dev->irq, zoran_irq, SA_SHIRQ | SA_INTERRUPT, zr->name, (void *) zr);
- if (result < 0) {
- if (result == -EINVAL) {
- printk(KERN_ERR
- "%s: Bad irq number or handlern",
- zr->name);
- } else if (result == -EBUSY) {
- printk(KERN_ERR
- "%s: IRQ %d busy, change your PnP config in BIOSn",
- zr->name, zr->pci_dev->irq);
- } else {
- printk(KERN_ERR
- "%s: Can't assign irq, error code %dn",
- zr->name, result);
- }
- iounmap(zr->zr36057_mem);
- continue;
- }
- /* set PCI latency timer */
- pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, &latency);
- need_latency = zr->revision > 1 ? 32 : 48;
- if (latency != need_latency) {
- printk(KERN_INFO "%s: Changing PCI latency from %d to %d.n", zr->name, latency, need_latency);
- pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, need_latency);
- }
- btwrite(0, ZR36057_SPGPPCR);
- mdelay(1);
- btwrite(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR);
- mdelay(1);
- /* assert P_Reset */
- btwrite(0, ZR36057_JPC);
- /* set up GPIO direction - all output */
- btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR);
- btwrite((0x81 << 24) | 0x8888, ZR36057_GPPGCR1);
- /* i2c */
- memcpy(&zr->i2c, &zoran_i2c_bus_template,
- sizeof(struct i2c_bus));
- strcpy(zr->i2c.name, zr->name);
- zr->i2c.data = zr;
- printk(KERN_INFO "%s: Initializing i2c bus...n", zr->name);
- if (i2c_register_bus(&zr->i2c) < 0) {
- /* put chip into reset */
- btwrite(0, ZR36057_SPGPPCR);
- free_irq(zr->pci_dev->irq, zr);
- iounmap(zr->zr36057_mem);
- printk(KERN_ERR "%s: Can't initialize i2c busn", zr->name);
- continue;
- }
- if (zr->card != DC10 && zr->card != DC10plus
- && zr->card != LML33 && zr->card != BUZ) {
- /* unregister i2c_bus */
- i2c_unregister_bus((&zr->i2c));
- /* put chip into reset */
- btwrite(0, ZR36057_SPGPPCR);
- free_irq(zr->pci_dev->irq, zr);
- iounmap(zr->zr36057_mem);
- printk(KERN_ERR "%s: Card not supportedn",
- zr->name);
- continue;
- }
- printk(KERN_INFO "%s card detectedn", zr->name);
- if (zr->card == LML33) {
- GPIO(zr, 2, 1); // Set Composite input/output
- }
- /* reset JPEG codec */
- zr36060_sleep(zr, 1);
- zr36060_reset(zr);
- /* video bus enabled */
- /* display codec revision */
- if (zr36060_read_8(zr, 0x022) == 0x33) {
- printk(KERN_INFO "%s: Zoran ZR36060 (rev %d)n",
- zr->name, zr36060_read_8(zr, 0x023));
- } else {
- /* unregister i2c_bus */
- i2c_unregister_bus((&zr->i2c));
- /* put chip into reset */
- btwrite(0, ZR36057_SPGPPCR);
- free_irq(zr->pci_dev->irq, zr);
- iounmap(zr->zr36057_mem);
- printk(KERN_ERR "%s: Zoran ZR36060 not foundn",
- zr->name);
- continue;
- }
- zoran_num++;
- }
- if (zoran_num == 0) {
- printk(KERN_INFO "No known MJPEG cards found.n");
- }
- return zoran_num;
- }
- static void handle_chipset(void)
- {
- if(pci_pci_problems & PCIPCI_FAIL)
- printk(KERN_WARNING "Chipset may not support reliable PCI-PCI DMA.n");
- if(pci_pci_problems & PCIPCI_TRITON)
- {
- printk(KERN_WARNING "Enabling Triton support.n");
- triton = 1;
- }
-
- if(pci_pci_problems & PCIPCI_NATOMA)
- {
- printk(KERN_WARNING "Enabling Natoma workaround.n");
- natoma = 1;
- }
- }
- static int init_dc10_cards(void)
- {
- int i;
- memset(zoran, 0, sizeof(zoran));
- printk(KERN_INFO
- "Zoran ZR36060 + ZR36057/67 MJPEG board driver version %d.%dn",
- MAJOR_VERSION, MINOR_VERSION);
- /* Look for cards */
- if (find_zr36057() < 0) {
- return -EIO;
- }
- if (zoran_num == 0)
- return 0; //-ENXIO;
- printk(KERN_INFO "MJPEG: %d card(s) foundn", zoran_num);
- /* check the parameters we have been given, adjust if necessary */
- if (v4l_nbufs < 0)
- v4l_nbufs = 0;
- if (v4l_nbufs > VIDEO_MAX_FRAME)
- v4l_nbufs = VIDEO_MAX_FRAME;
- /* The user specfies the in KB, we want them in byte (and page aligned) */
- v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024);
- if (v4l_bufsize < 32768)
- v4l_bufsize = 32768;
- /* 2 MB is arbitrary but sufficient for the maximum possible images */
- if (v4l_bufsize > 2048 * 1024)
- v4l_bufsize = 2048 * 1024;
- printk(KERN_INFO "MJPEG: using %d V4L buffers of size %d KBn",
- v4l_nbufs, v4l_bufsize >> 10);
- /* Use parameter for vidmem or try to find a video card */
- if (vidmem) {
- printk(KERN_INFO
- "MJPEG: Using supplied video memory base address @ 0x%lxn",
- vidmem);
- }
- /* check if we have a Triton or Natome chipset */
- handle_chipset();
- /* take care of Natoma chipset and a revision 1 zr36057 */
- for (i = 0; i < zoran_num; i++) {
- if (natoma && zoran[i].revision <= 1) {
- zoran[i].need_contiguous = 1;
- printk(KERN_INFO
- "%s: ZR36057/Natoma bug, max. buffer size is 128Kn",
- zoran[i].name);
- } else {
- zoran[i].need_contiguous = 0;
- }
- }
- /* initialize the Buzs */
- /* We have to know which ones must be released if an error occurs */
- for (i = 0; i < zoran_num; i++)
- zoran[i].initialized = 0;
- for (i = 0; i < zoran_num; i++) {
- if (zr36057_init(i) < 0) {
- release_dc10();
- return -EIO;
- }
- zoran_proc_init(i);
- }
- return 0;
- }
- static void unload_dc10_cards(void)
- {
- release_dc10();
- }
- module_init(init_dc10_cards);
- module_exit(unload_dc10_cards);
- MODULE_LICENSE("GPL");