📄 ncplus_mjpeg.c
字号:
/* * ncplus_mjpeg.c * * Copyright(C) 2005 Chipsbrain Co., Ltd. * * 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; with out 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * modified by Chipsbrain Engineer <support@chipsbrain.com> */static const char version[] = "ncplus_mjpeg.c:v3.0.1 (C) 2005 Chipsbrain Co., Ltd.\n";#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#define MJPEG_PROC#define __NO_VERSION__#include <linux/module.h>#include <linux/version.h>#include <linux/config.h>#include <linux/init.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/vmalloc.h> /* vmalloc() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/types.h> /* size_t */#include <linux/fcntl.h> /* O_ACCMODE */#include <linux/kdev_t.h>#include <linux/timer.h> #include <asm/system.h> /* cli(), *_flags */#include <linux/interrupt.h>#include <linux/sched.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>//#include <asm-arm/spinlock.h> #ifdef MJPEG_PROC#include <linux/proc_fs.h>#endif#include "ncplus_mjpeg.h" /* local definitions and sysdep.h */#include "ncplus_jpghdr.h" /* jpeg header *//*#define MJPEG_RESOL_160 0x00#define MJPEG_RESOL_320 0x01#define MJPEG_RESOL_640 0x02#define MJPEG_YUV_420 0x03#define MJPEG_YUV_422 0x04*/struct mjpeg_buffer { char valid; /* is valid */ int count; /* buffer count */ char *data; /* buffer data */};#if 0struct mjpeg_info { char res; /* resolution */ char yuv; /* YUV format */ int alpha; /* alpha coefficient */};#endifstruct mjpeg_device { spinlock_t lock; /* buffer lock */ struct mjpeg_buffer buf[2]; /* buffer */ struct mjpeg_buffer *wbuf; /* write buffer pointer */ struct mjpeg_buffer *rbuf; /* read buffer pointer */ int max_size; /* status: mjpeg data max size */ unsigned char jpg_hdr[JPEG_HDR_SIZE];// struct mjpeg_info *info; /* mjpeg infomation */ int jpg_rotate;};static struct mjpeg_device *mjpeg_dev = NULL;// mjpeg watchdog #define MJPEG_WATCHDOG_TIMEOUT 1 // 1 secstatic unsigned long mjpeg_watchdog_timeout;struct timer_list mjpeg_watchdog_timer;#define DEVICE_NAME "mjpeg"#define BUF1 0#define BUF2 1/* * I don't use static symbols here, because we export no symbols */static int mjpeg_major = MJPEG_MAJOR;static int gs_new_frame = 0;static int mjpeg_default = 2; // 0(q0), 1(q2), 2(c0), 3(c2), 4(v0), 5(v2)static int mjpeg_debug_ioctl = 0;static int mjpeg_perform = 9256; // 9256(c0, c2), 9216(q0, q2)static int mjpeg_alphacoeff = 64; /* 50%(64), 32(best), 128(worst) */static int mjpeg_bDeviceReadOpen = 0;static int mjpeg_bDeviceWriteOpen = 0;static int gs_thread_no=0;MODULE_PARM(mjpeg_default,"i");MODULE_PARM(mjpeg_alphacoeff,"i");MODULE_PARM(mjpeg_debug,"i");MODULE_PARM(mjpeg_debug_owner,"i");MODULE_PARM(mjpeg_debug_interrupt,"i");MODULE_PARM(mjpeg_debug_ioctl,"i");MODULE_PARM(mjpeg_debug_stop,"i");MODULE_PARM(mjpeg_perform,"i");MODULE_PARM(mjpeg_frmeasure,"i");//MODULE_AUTHOR("donald kim");//MODULE_LICENSE("GPL");/* * Functions Prototypes */int mjpeg_init_module(void);void mjpeg_cleanup_module(void);int mjpeg_open(struct inode *inode, struct file *filp);ssize_t mjpeg_read(struct file *filp, char *buffer, size_t length, loff_t *offset);int mjpeg_release(struct inode *inode, struct file *filp);int mjpeg_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg);static int mjpeg_raw_reset(void);static int mjpeg_reset(struct mjpeg_device *dev);static void setup_mjpeg(struct mjpeg_device *dev);void ncplus_mjpeg_interrupt(int, void *, struct pt_regs *);static void setting_by_ioctl(struct mjpeg_device *dev);static void mjpeg_watchdog_init(void);static void mjpeg_watchdog(unsigned long data);static int mjpeg_buff_alloc(struct mjpeg_device *dev);static void mjpeg_buff_free(struct mjpeg_device *dev);static inline void mjpeg_buff_change(struct mjpeg_device *dev);static inline void mjpeg_buff_init(struct mjpeg_device *dev);static int mjpeg_hdr_res(struct mjpeg_device *dev);static int mjpeg_hdr_qt(struct mjpeg_device *dev);#ifdef MJPEG_PROCstruct proc_dir_entry *proc_mjpeg;#endif/* * Device Operations */struct file_operations mjpeg_fops = { read : mjpeg_read, ioctl : mjpeg_ioctl, open : mjpeg_open, release : mjpeg_release,};/* * JPEG Header * Resolution * YUV */static int mjpeg_hdr_res(struct mjpeg_device *dev){ switch (mjpeg_default) { case 0: /* 160x120 YUV 420 */ dev->jpg_hdr[0x245] = 0x00; /* width */ dev->jpg_hdr[0x246] = 0xA0; dev->jpg_hdr[0x243] = 0x00; /* height */ dev->jpg_hdr[0x244] = 0x78; dev->jpg_hdr[0x249] = 0x22; /* YUV 420 */ dev->jpg_hdr[0x23C] = 0x07; /* q0 */ dev->jpg_hdr[0x23D] = 0xD0; break; case 1: /* 160x120 YUV 422 */ dev->jpg_hdr[0x245] = 0x00; /* width */ dev->jpg_hdr[0x246] = 0xA0; dev->jpg_hdr[0x243] = 0x00; /* height */ dev->jpg_hdr[0x244] = 0x78; dev->jpg_hdr[0x249] = 0x21; /* YUV 422 */ dev->jpg_hdr[0x23C] = 0x03; /* q2 */ dev->jpg_hdr[0x23D] = 0xE8; break; case 2: /* 320x240 YUV 420 */ dev->jpg_hdr[0x245] = 0x01; /* width */ dev->jpg_hdr[0x246] = 0x40; dev->jpg_hdr[0x243] = 0x00; /* height */ dev->jpg_hdr[0x244] = 0xF0; dev->jpg_hdr[0x249] = 0x22; /* YUV 420 */ dev->jpg_hdr[0x23C] = 0x03; /* c0 */ dev->jpg_hdr[0x23D] = 0xE8; break; case 3: /* 320x240 YUV 422 */ dev->jpg_hdr[0x245] = 0x01; /* width */ dev->jpg_hdr[0x246] = 0x40; dev->jpg_hdr[0x243] = 0x00; /* height */ dev->jpg_hdr[0x244] = 0xF0; dev->jpg_hdr[0x249] = 0x21; /* YUV 422 */ dev->jpg_hdr[0x23C] = 0x07; /* c2 */ dev->jpg_hdr[0x23D] = 0xD0; break; case 4: /* 640x480 YUV 420 */ dev->jpg_hdr[0x245] = 0x02; /* width */ dev->jpg_hdr[0x246] = 0x80; dev->jpg_hdr[0x243] = 0x01; /* height */ dev->jpg_hdr[0x244] = 0xE0; dev->jpg_hdr[0x249] = 0x22; /* YUV 420 */ dev->jpg_hdr[0x23C] = 0x07; /* v0 */ dev->jpg_hdr[0x23D] = 0xD0; break; case 5: /* 640x480 YUV 422 */ dev->jpg_hdr[0x245] = 0x02; /* width */ dev->jpg_hdr[0x246] = 0x80; dev->jpg_hdr[0x243] = 0x01; /* height */ dev->jpg_hdr[0x244] = 0xE0; dev->jpg_hdr[0x249] = 0x21; /* YUV 422 */ dev->jpg_hdr[0x23C] = 0x07; /* v2 */ dev->jpg_hdr[0x23D] = 0xD0; break; default: printk("mjpeg: header error\n"); return -1; } return 0;} /* * JPEG Header * Quantization table */static int mjpeg_hdr_qt(struct mjpeg_device *dev){ int r; int i; unsigned long tmp; switch (mjpeg_alphacoeff) { case 32: for (i = 0; i < 64; i++) { dev->jpg_hdr[0x07+i] = yquant[i] / 2; dev->jpg_hdr[0x48+i] = uvquant[i] / 2; } goto final; case 64: r = 1; break; case 128: r = 2; break; case 256: r = 4; break; case 512: r = 8; break; default: printk("mjpg: header error\n"); return -1; } for (i = 0; i < 64; i++) { tmp = (unsigned long)yquant[i]; tmp = tmp * r; if (tmp > 0xff) tmp = 0xff; dev->jpg_hdr[0x07+i] = (unsigned char)tmp; tmp = (unsigned long)uvquant[i]; tmp = tmp * r; if (tmp > 0xff) tmp = 0xff; dev->jpg_hdr[0x48+i] = (unsigned char)tmp; }final: return 0;}#ifdef MJPEG_PROCint mjpeg_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ struct mjpeg_device *dev = mjpeg_dev; struct mjpeg_buffer *r = dev->rbuf; int size = 0; size += sprintf(page+size, "%20s : %7d bytes\n", "mjpeg data", r->count); size += sprintf(page+size, "%20s : %7d bytes\n", "mjpeg max data", dev->max_size); return size;}#endifstatic inline void mjpeg_buff_init(struct mjpeg_device *dev) { struct mjpeg_buffer *buf = dev->wbuf; buf->valid = 0; buf->count = 0; /* * jpeg header copy */ memcpy(buf->data, dev->jpg_hdr, JPEG_HDR_SIZE); buf->count += JPEG_HDR_SIZE;}static inline void mjpeg_buff_change(struct mjpeg_device *dev){ struct mjpeg_buffer *tmp; tmp = dev->rbuf; dev->rbuf = dev->wbuf; dev->wbuf = tmp;}/* * mjpeg interrupt service routine */void ncplus_mjpeg_interrupt(int irq, void *dev_id, struct pt_regs *regs){ unsigned long dma_count, status; struct mjpeg_device *dev = dev_id; struct mjpeg_buffer *w = dev->wbuf; unsigned long *buffer = NULL; // mjpeg watchdog timeout renewal mjpeg_watchdog_timeout = jiffies + (HZ * MJPEG_WATCHDOG_TIMEOUT); mod_timer(&mjpeg_watchdog_timer, mjpeg_watchdog_timeout); if(gs_new_frame) { mjpeg_buff_init(dev); gs_new_frame = 0; gs_thread_no = 0; } buffer = (unsigned long *)(w->data + w->count); status = mjpeg_readl(MODULE_FUNC_STS); dma_count = (((unsigned long)mjpeg_readl(MCU_FIFO_STATUS)&0xffff0000)>>16); if (w->count + (dma_count * 4) > COMPRESSED_SIZE) { printk("mjpeg: buffer overflow\n"); mjpeg_reset(dev); mjpeg_buff_init(dev); return; } if ((status & FRAME_ENC_FINISHED)==0x60) { mjpeg_writel((mjpeg_readl(JPEG_STATUS))&0xfffffffe, JPEG_STATUS); } insl(MJPEG_BASE+DMA_START_ADD_VAL, buffer, dma_count); w->count += dma_count * 4; if ((status & FRAME_ENC_FINISHED)==0x60) { if (w->count > dev->max_size) dev->max_size = w->count; w->valid = 1; mjpeg_buff_change(dev); gs_new_frame = 1; } return;}/* * Device Operations */int mjpeg_open(struct inode *inode, struct file *filp){ if ((filp->f_flags & O_ACCMODE) & (O_WRONLY | O_RDWR)) { /* if (mjpeg_bDeviceWriteOpen) { printk(DEVICE_NAME " : Device already open for writing\n"); return -EBUSY; } else */ ++mjpeg_bDeviceWriteOpen; } else { /* if (mjpeg_bDeviceReadOpen) { printk(DEVICE_NAME " : Device already open for reading\n"); return -EBUSY; } else */ ++mjpeg_bDeviceReadOpen; } /* if (!filp->private_data) { //dev = mjpeg_dev; filp->private_data = dev; } else { dev = filp->private_data; } */ //filp->private_data = dev; //MOD_INC_USE_COUNT; return 0;}int mjpeg_release(struct inode *inode, struct file *filp){ if ((filp->f_flags & O_ACCMODE) & (O_WRONLY | O_RDWR)) --mjpeg_bDeviceWriteOpen; else --mjpeg_bDeviceReadOpen; //MOD_DEC_USE_COUNT; return 0;}/* * return value * 0 : end of file * positive : read bytes count * negative(-1) : buffer empty */ssize_t mjpeg_read(struct file *filp, char *buffer, size_t length, loff_t *offset){ struct mjpeg_device *dev = mjpeg_dev; struct mjpeg_buffer *r = dev->rbuf; int count = 0; unsigned long flags; // spin_lock flags spin_lock_irqsave(dev->lock, flags); if (r->valid) { count = r->count; if (copy_to_user(buffer, r->data, count) ) { printk(DEVICE_NAME " : copy_to_user fault!\n"); return -EFAULT; } } else count = 0; spin_unlock_irqrestore(mjpeg_device, flags); return count;}/* * The ioctl() implementation */int mjpeg_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ struct mjpeg_device *dev = mjpeg_dev; int err = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -