#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
+#include <linux/semaphore.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <asm/uaccess.h>
#include "avformat.h"
-#define DRIVER_NAME "SVCODEC"
+#define DRIVER_NAME "svcodec"
#define CODEC_MAJOR 240
MODULE_LICENSE("GPL");
struct _param {
uint32_t apiIndex;
uint32_t in_args_num;
- uint32_t in_args[20];
+ uint32_t in_args[10];
uint32_t ret;
};
enum svodec_param_offset {
CODEC_API_INDEX = 0,
CODEC_IN_PARAM,
- CODEC_RETURN_VALUE
+ CODEC_RETURN_VALUE,
+ CODEC_READY_TO_GET_DATA,
+ CODEC_GET_RESULT_DATA,
};
-struct codec_buf {
- AVFormatContext *pFormatCtx;
- AVClass *pClass;
- struct AVInputFormat *pInputFmt;
- ByteIOContext *pByteIOCtx;
- AVStream *pStream;
-
- AVCodecContext *pCodecCtx;
- AVFrame *pFrame;
- AVCodec *pCodec;
-};
-
-struct svcodec_dev {
+typedef struct _svcodec_dev {
struct pci_dev *dev; /* pci device */
- volatile unsigned long *ioaddr; /* memory mapped registers */
- volatile unsigned long *memaddr; /* memory mapped registers */
+ volatile unsigned int *ioaddr;
+ volatile unsigned int *memaddr;
resource_size_t io_start;
resource_size_t io_size;
resource_size_t mem_start;
resource_size_t mem_size;
- /* image buffer */
-// uint8_t *img_buf;
-};
+ uint8_t *imgBuf;
+/* struct semaphore sem;
+ int wake_up; */
+} svcodec_dev;
static struct pci_device_id svcodec_pci_table[] __devinitdata = {
{
};
MODULE_DEVICE_TABLE(pci, svcodec_pci_table);
-static struct svcodec_dev *svcodec;
-
-// static void call_workqueue(void *data);
+static svcodec_dev *svcodec;
-// DECLARE_WAIT_QUEUE_HEAD(waitqueue_read);
-// DECLARE_WORK(work_queue, call_workqueue);
+#if 0
+static void call_workqueue(void *data);
+DECLARE_WAIT_QUEUE_HEAD(waitqueue_read);
+DECLARE_WORK(work_queue, call_workqueue);
+#endif
static int svcodec_open (struct inode *inode, struct file *file)
{
try_module_get(THIS_MODULE);
/* register interrupt handler */
-/* if (request_irq(svcodec->dev->irq, svcodec_interrupt, IRQF_SHARED,
+/* if (request_irq(svcodec->dev->irq, svcodec_irq_handler, IRQF_SHARED,
DRIVER_NAME, svcodec)) {
printk(KERN_ERR "[%s] : request_irq failed\n", __func__);
- } */
+ return -EBUSY;
+ }
+ init_MUTEX(&svcodec->sem); */
- SVCODEC_LOG("\n");
return 0;
}
-static long tempCnt = 0;
+static int get_picture_size (int pix_fmt, int width, int height)
+{
+ int size;
+
+ switch (pix_fmt) {
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV422P:
+ case PIX_FMT_YUV444P:
+ case PIX_FMT_YUV410P:
+ case PIX_FMT_YUV411P:
+ case PIX_FMT_YUVJ420P:
+ case PIX_FMT_YUVJ422P:
+ case PIX_FMT_YUVJ444P:
+ size = (width * height * 3) / 2;
+ break;
+ case PIX_FMT_RGB24:
+ case PIX_FMT_BGR24:
+ size = width * height * 3;
+ break;
+/* case PIX_FMT_RGB32:
+ size = width * height * 4;
+ break;
+ case PIX_FMT_RGB555:
+ case PIX_FMT_RGB565:
+ case PIX_FMT_YUYV422:
+ case PIX_FMT_UYVY422:
+ size = widht * height * 2;
+ break; */
+ default:
+ size = -1;
+ }
+ return size;
+}
+
static ssize_t svcodec_write (struct file *file, const char __user *buf,
size_t count, loff_t *fops)
{
struct _param paramInfo;
AVCodecContext tempCtx;
- uint8_t *ptr = NULL;
- int i;
if (!svcodec) {
- printk(KERN_ERR "[%s] : Fail to get codec device info\n", __func__);
+ printk(KERN_ERR "[%s]:Fail to get codec device info\n", __func__);
}
- if(copy_from_user(¶mInfo, buf, sizeof(struct _param)))
- {
- // error handling !!!
+ if (copy_from_user(¶mInfo, buf, sizeof(struct _param))) {
+ printk(KERN_ERR "[%s]:Fail to get codec parameter info from user\n", __func__);
}
- for (i = 0; i < paramInfo.in_args_num; i++) {
- writel(paramInfo.in_args[i], svcodec->ioaddr + CODEC_IN_PARAM);
- }
/* guest to host */
if (paramInfo.apiIndex == 2) {
AVCodecContext *ctx;
AVCodec *codec;
int size, size1;
-// int *id;
-// char *bEncode;
ctx = (AVCodecContext*)paramInfo.in_args[0];
codec = (AVCodec*)paramInfo.in_args[1];
-/* id = (int*)paramInfo.in_args[2];
- bEncode = (char*)paramInfo.in_args[3]; */
size = sizeof(AVCodecContext);
+ printk(KERN_DEBUG "[%s]:AVCodecContext size:%d\n", sizeof(AVCodecContext));
memcpy(&tempCtx, ctx, size);
memcpy_toio(svcodec->memaddr, ctx, size);
size1 = size + sizeof(AVCodec);
memcpy_toio((uint8_t*)svcodec->memaddr + size1, ctx->extradata, ctx->extradata_size);
-
-// memcpy_toio(svcodec->memaddr + size + 4, bEncode, sizeof(char));
-// writel((uint32_t)ctx->extradata, svcodec->ioaddr + CODEC_IN_PARAM);
} else if (paramInfo.apiIndex == 6) {
int value = -1;
value = *(int*)paramInfo.ret;
size = sizeof(AVCodecContext);
memcpy(&tempCtx, ctx, size);
- memcpy_toio(svcodec->memaddr, ctx, size);
+// memcpy_toio(svcodec->memaddr, ctx, size);
memcpy_toio((uint8_t*)svcodec->memaddr + size, &buf_size, sizeof(int));
if (buf_size > 0) {
size += sizeof(int);
memcpy_toio((uint8_t*)svcodec->memaddr + size, buf, buf_size);
}
-
-/* writel((uint32_t)&ctx->frame_number, svcodec->ioaddr + CODEC_IN_PARAM);
- writel((uint32_t)&ctx->pix_fmt, svcodec->ioaddr + CODEC_IN_PARAM);
- writel((uint32_t)&ctx->coded_frame, svcodec->ioaddr + CODEC_IN_PARAM);
- writel((uint32_t)&ctx->sample_aspect_ratio, svcodec->ioaddr + CODEC_IN_PARAM);
- writel((uint32_t)&ctx->reordered_opaque, svcodec->ioaddr + CODEC_IN_PARAM); */
} else if (paramInfo.apiIndex == 22) {
AVCodecContext *ctx = NULL;
AVFrame *pict = NULL;
pict = (AVFrame*)paramInfo.in_args[3];
pict_buf = (uint8_t*)paramInfo.in_args[4];
pict_buf_size = (ctx->height * ctx->width) * 3 / 2;
-
-// writel((uint32_t)ctx->coded_frame, svcodec->ioaddr + CODEC_IN_PARAM);
- ptr = kmalloc(buf_size, GFP_KERNEL);
-// writel((uint32_t)ptr, svcodec->ioaddr + CODEC_IN_PARAM);
+
+ svcodec->imgBuf = kmalloc(buf_size, GFP_KERNEL);
+ if (!svcodec->imgBuf) {
+ printk(KERN_ERR "[%s]Failed to allocate image buffer\n", __func__);
+ }
memcpy_toio(svcodec->memaddr, &buf_size, sizeof(int));
memcpy_toio((uint8_t*)svcodec->memaddr + 4, buf, buf_size);
size += sizeof(AVFrame);
SVCODEC_LOG("AVCODEC_ENCODE_VIDEO 1\n");
memcpy_toio((uint8_t*)svcodec->memaddr + size, pict_buf, pict_buf_size);
- SVCODEC_LOG("ENCODE Count :%ld\n", ++tempCnt);
} else {
int pict_temp = 0;
memcpy_toio((uint8_t*)svcodec->memaddr + size, &pict_temp, sizeof(int));
SVCODEC_LOG("AVCODEC_ENCODE_VIDEO 2\n");
}
} else if (paramInfo.apiIndex == 24) {
+ int pix_fmt;
int width, height;
- int size, size2;
+ int size;
+ pix_fmt = *(int*)paramInfo.in_args[1];
width = *(int*)paramInfo.in_args[2];
height = *(int*)paramInfo.in_args[3];
- size = width * height;
- size2 = size / 4;
- ptr = kmalloc(size + size2 * 2, GFP_KERNEL);
- writel((uint32_t)ptr, svcodec->ioaddr + CODEC_IN_PARAM);
+ size = get_picture_size(pix_fmt, width, height);
+ svcodec->imgBuf = kmalloc(size, GFP_KERNEL);
+ if (!svcodec->imgBuf) {
+ printk(KERN_ERR "[%s]Failed to allocate image buffer\n", __func__);
+ }
}
- // return value
- writel(paramInfo.ret, svcodec->ioaddr + CODEC_RETURN_VALUE);
-
// api index
writel((uint32_t)paramInfo.apiIndex, svcodec->ioaddr + CODEC_API_INDEX);
/* host to guest */
if (paramInfo.apiIndex == 2) {
AVCodecContext *avctx;
+ AVCodec *codec;
int *ret, size;
avctx = (AVCodecContext*)paramInfo.in_args[0];
+ codec = (AVCodec*)paramInfo.in_args[1];
+ ret = (int*)paramInfo.ret;
size = sizeof(AVCodecContext);
memcpy_fromio(avctx, svcodec->memaddr, size);
-#if 1
+ memcpy_fromio(ret, (uint8_t*)svcodec->memaddr + size, sizeof(int));
+
avctx->av_class = tempCtx.av_class;
- avctx->codec = (AVCodec*)paramInfo.in_args[1];
+ avctx->codec = codec;
// avctx->priv_data = tempCtx.priv_data;
avctx->extradata = tempCtx.extradata;
avctx->opaque = tempCtx.opaque;
avctx->execute = tempCtx.execute;
avctx->thread_opaque = tempCtx.thread_opaque;
avctx->execute2 = tempCtx.execute2;
-#endif
- ret = (int*)paramInfo.ret;
- memcpy_fromio(ret, (uint8_t*)svcodec->memaddr + size, sizeof(int));
-
+
+ if (copy_to_user((void*)(paramInfo.in_args[0]), avctx, sizeof(AVCodecContext))) {
+ printk(KERN_ERR "[%s]:Fail to copy AVCodecContext to user\n", __func__);
+ }
} else if (paramInfo.apiIndex == 3) {
int *ret;
ret = (int*)paramInfo.ret;
} else if (paramInfo.apiIndex == 20) {
AVCodecContext *avctx;
AVFrame *frame;
- int size, *got_picture_ptr, *ret, buf_size;
+ int size;
+ int *got_picture_ptr;
+ int *ret;
+ int buf_size;
+
avctx = (AVCodecContext*)paramInfo.in_args[0];
frame = (AVFrame*)paramInfo.in_args[1];
got_picture_ptr = (int*)paramInfo.in_args[2];
size = sizeof(AVCodecContext);
memcpy_fromio(avctx, svcodec->memaddr, size);
memcpy_fromio(frame, (uint8_t*)svcodec->memaddr + size, sizeof(AVFrame));
- size += sizeof(AVFrame);
+ size += sizeof(AVFrame);
memcpy_fromio(got_picture_ptr, (uint8_t*)svcodec->memaddr + size, sizeof(int));
size += sizeof(int);
memcpy_fromio(ret, (uint8_t*)svcodec->memaddr + size , sizeof(int));
*got_picture_ptr = 0;
memcpy_fromio(ret, svcodec->memaddr, sizeof(int));
}
-#if 1
avctx->coded_frame = frame;
avctx->av_class = tempCtx.av_class;
- avctx->codec = (AVCodec*)paramInfo.in_args[1];
+ avctx->codec = tempCtx.codec;
avctx->extradata = tempCtx.extradata;
avctx->opaque = tempCtx.opaque;
avctx->get_buffer = tempCtx.get_buffer;
avctx->execute = tempCtx.execute;
avctx->thread_opaque = tempCtx.thread_opaque;
avctx->execute2 = tempCtx.execute2;
-#endif
+ if (copy_to_user((void*)(paramInfo.in_args[0]), avctx, sizeof(AVCodecContext))) {
+ printk(KERN_ERR "[%s]:Fail to copy AVCodecContext to user\n", __func__);
+ }
} else if (paramInfo.apiIndex == 22) {
-// AVCodecContext *ctx;
uint32_t buf_size;
-
int *ret;
-// ctx = (AVCodecContext*)paramInfo.in_args[0];
buf_size = *(uint32_t*)paramInfo.in_args[2];
ret = (int*)paramInfo.ret;
if (buf_size > 0) {
- memcpy_fromio(ptr, svcodec->memaddr, buf_size);
- if(copy_to_user((void *)(paramInfo.in_args[1]), ptr, buf_size))
- {
- // error handling !!!
+ memcpy_fromio(svcodec->imgBuf, svcodec->memaddr, buf_size);
+ if (copy_to_user((void *)(paramInfo.in_args[1]), svcodec->imgBuf, buf_size)) {
+ printk(KERN_ERR "[%s]:Fail to copy image buffers to user\n", __func__);
}
memcpy_fromio(ret, (uint8_t*)svcodec->memaddr + buf_size , sizeof(int));
} else {
memcpy_fromio(ret, svcodec->memaddr , sizeof(int));
}
- kfree(ptr);
+ kfree(svcodec->imgBuf);
+ svcodec->imgBuf = NULL;
} else if (paramInfo.apiIndex == 24) {
+ int pix_fmt;
int width, height;
- int size, size2;
+ int size;
+ pix_fmt = *(int*)paramInfo.in_args[1];
width = *(int*)paramInfo.in_args[2];
height = *(int*)paramInfo.in_args[3];
- size = width * height;
- size2 = size / 4;
- memcpy_fromio(ptr, svcodec->memaddr, (size * 3 / 2));
- if(copy_to_user((void *)(paramInfo.in_args[4]), ptr, size + size2 * 2))
- {
- // error handling !!!
+ size = get_picture_size(pix_fmt, width, height);
+ memcpy_fromio(svcodec->imgBuf, svcodec->memaddr, size);
+ if (copy_to_user((void*)paramInfo.in_args[4], svcodec->imgBuf, size)) {
+ printk(KERN_ERR "[%s]:Fail to copy image buffers to user\n", __func__);
}
- kfree(ptr);
+ kfree(svcodec->imgBuf);
+ svcodec->imgBuf = NULL;
}
return 0;
}
-// FIX ME
-/* static int get_image_size (int pixelFormat)
-{
- int size;
- int width;
- int height;
-
- switch (pixelFormat) {
- case PIX_FMT_YUV420P:
- case PIX_FMT_YUV422P:
- case PIX_FMT_YUV444P:
- case PIX_FMT_YUV410P:
- case PIX_FMT_YUV411P:
- case PIX_FMT_YUVJ420P:
- case PIX_FMT_YUVJ422P:
- case PIX_FMT_YUVJ444P:
- size = (width * height * 3) / 2;
- break;
- case PIX_FMT_RGB24:
- case PIX_FMT_BGR24:
- size = width * height * 3;
- break;
- case PIX_FMT_RGB32:
- size = width * height * 4;
- break;
- case PIX_FMT_RGB555:
- case PIX_FMT_RGB565:
- case PIX_FMT_YUYV422:
- case PIX_FMT_UYVY422:
- size = widht * height * 2;
- break;
- default:
- size = -1;
- }
- return size;
-} */
-
static ssize_t svcodec_read (struct file *file, char __user *buf,
size_t count, loff_t *fops)
{
if (!svcodec) {
printk(KERN_ERR "[%s] : Fail to get codec device info\n", __func__);
}
-// readl(svcodec->ioaddr);
return 0;
}
free_irq(svcodec->dev->irq, svcodec);
} */
-/* if (svcodec->img_buf) {
- kfree(svcodec->img_buf);
- svcodec->img_buf = NULL;
- } */
- tempCnt = 0;
+ if (svcodec->imgBuf) {
+ kfree(svcodec->imgBuf);
+ svcodec->imgBuf = NULL;
+ }
module_put(THIS_MODULE);
SVCODEC_LOG("\n");
return 0;
}
-// static void call_workqueue(void *data)
-//{
-// SVCODEC_LOG("\n");
-//}
-
-/*
- * Interrupt handler
- */
#if 0
-static irqreturn_t svcodec_interrupt (int irq, void *dev_id);
+static void call_workqueue(void *data)
+{
+ SVCODEC_LOG("\n");
+}
-static irqreturn_t svcodec_interrupt (int irq, void *dev_id)
+static irqreturn_t svcodec_irq_handler (int irq, void *dev_id)
{
-// SVCODEC_LOG("\n");
- // schedule_work(&work_queue);
+ int ret = -1;
+ svcodec_dev *dev = (svcodec_dev*)dev_id;
+
+ ret = ioread32(dev->ioaddr + CODEC_READY_TO_GET_DATA);
+ if (ret == 0) {
+ return IRQ_NONE;
+ }
+ SVCODEC_LOG("\n");
+ dev->wake_up = ret;
+ wake_up_interruptible(&waitqueue);
+ schedule_work(&work_queue);
+ iowrite32(0, dev->ioaddr + CODEC_GET_RESULT_DATA);
/* need more implementation */
-// return IRQ_HANDLED;
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
#endif
.open = svcodec_open,
.mmap = svcodec_mmap,
.release = svcodec_release,
-// .ioctl = svcodec_ioctl,
};
static void __devinit svcodec_remove (struct pci_dev *pci_dev)
{
if (svcodec) {
-
if (svcodec->ioaddr) {
iounmap(svcodec->ioaddr);
svcodec->ioaddr = 0;
{
int ret;
- svcodec = (struct svcodec_dev*)kmalloc(sizeof(struct svcodec_dev), GFP_KERNEL);
- memset(svcodec, 0x00, sizeof(struct svcodec_dev));
+ svcodec = (svcodec_dev*)kmalloc(sizeof(svcodec_dev), GFP_KERNEL);
+ memset(svcodec, 0x00, sizeof(svcodec_dev));
svcodec->dev = pci_dev;
printk(KERN_ERR "[%s] : pci_resource_start failed\n", __func__);
goto err_out;
}
-
- SVCODEC_LOG("mem_start:0x%x, mem_size:0x%x\n", svcodec->mem_start, svcodec->mem_size);
if (!request_mem_region(svcodec->mem_start, svcodec->mem_size, DRIVER_NAME)) {
printk(KERN_ERR "[%s] : request_mem_region failed\n", __func__);
goto err_mem_region;
}
- SVCODEC_LOG("io_start:0x%x, io_size:0x%x\n", svcodec->io_start, svcodec->io_size);
-
if (!request_mem_region(svcodec->io_start, svcodec->io_size, DRIVER_NAME)) {
printk(KERN_ERR "[%s] : request_io_region failed\n", __func__);
goto err_mem_region;
printk(KERN_ERR "[%s] : ioremap failed\n", __func__);
goto err_mem_unmap;
}
- SVCODEC_LOG("MEM_ADDR:0x%lx, IO_ADDR:0x%lx\n", (unsigned long)svcodec->memaddr, (unsigned long)svcodec->ioaddr);
// pci_set_drvdata(pci_dev, svcodec);
if (register_chrdev(CODEC_MAJOR, DRIVER_NAME, &codec_fops)) {
static int __init svcodec_init (void)
{
- SVCODEC_LOG("Codec accelerator initialized\n");
+ SVCODEC_LOG("SVCODEC initialized\n");
return pci_register_driver(&driver);
}