#define CODEC_IRQ 0x7f
-/* Clean up source. : _param, svcodec_param_offset, paramindex */
struct codec_param {
uint32_t api_index;
uint32_t ctx_index;
+ uint32_t mem_index;
uint32_t mmap_offset;
uint32_t ret;
};
enum codec_io_cmd {
- CODEC_API_INDEX = 0,
- CODEC_QUERY_STATE,
- CODEC_CONTEXT_INDEX,
- CODEC_MMAP_OFFSET,
- CODEC_FILE_INDEX,
- CODEC_CLOSED,
+ CODEC_CMD_API_INDEX = 0,
+ CODEC_CMD_CONTEXT_INDEX,
+ CODEC_CMD_FILE_INDEX,
+ CODEC_CMD_DEVICE_MEM_OFFSET,
+ CODEC_CMD_GET_THREAD_STATE,
+ CODEC_CMD_GET_VERSION,
+ CODEC_CMD_GET_DEVICE_MEM,
+ CODEC_CMD_SET_DEVICE_MEM,
+ CODEC_CMD_GET_MMAP_OFFSET,
+ CODEC_CMD_SET_MMAP_OFFSET,
+ CODEC_CMD_RESET_CODEC_INFO,
};
enum codec_api_index {
EMUL_AV_REGISTER_ALL = 1,
- EMUL_AVCODEC_ALLOC_CONTEXT,
EMUL_AVCODEC_OPEN,
EMUL_AVCODEC_CLOSE,
- EMUL_AV_FREE,
EMUL_AVCODEC_FLUSH_BUFFERS,
EMUL_AVCODEC_DECODE_VIDEO,
EMUL_AVCODEC_ENCODE_VIDEO,
EMUL_AV_PARSER_INIT,
EMUL_AV_PARSER_PARSE,
EMUL_AV_PARSER_CLOSE,
- EMUL_GET_CODEC_VER = 50,
- EMUL_LOCK_MEM_REGION,
+ EMUL_LOCK_MEM_REGION = 50,
EMUL_UNLOCK_MEM_REGION,
};
resource_size_t mem_size;
/* irq handler */
- wait_queue_head_t codec_wq;
+ wait_queue_head_t codec_job_wq;
spinlock_t lock;
- int sleep_flag;
+ int codec_job_done;
int availableMem;
};
unsigned int cmd,
unsigned long arg)
{
+ long value;
+
mutex_lock(&codec_mutex);
if (cmd == EMUL_LOCK_MEM_REGION) {
- if (svcodec->availableMem == 0)
+ if (svcodec->availableMem == 0) {
svcodec->availableMem = 1;
- else
+ } else {
svcodec->availableMem = -1;
-
+ }
+ value = svcodec->availableMem;
} else if (cmd == EMUL_UNLOCK_MEM_REGION) {
- svcodec->availableMem = 0;
+ value = svcodec->availableMem = 0;
+ } else if (cmd == CODEC_CMD_GET_VERSION) {
+ value = readl(svcodec->ioaddr + cmd);
+ } else if (cmd == CODEC_CMD_GET_MMAP_OFFSET) {
+ value = readl(svcodec->ioaddr + cmd);
+ CODEC_LOG(KERN_DEBUG,
+ "ioctl: get mmap offset: %d.\n", value);
} else {
- CODEC_LOG(KERN_ERR, "there is no command.\n");
+ CODEC_LOG(KERN_INFO,
+ "ioctl: no command available.\n");
+ value = 0;
}
- if (copy_to_user((void *)arg,
- &svcodec->availableMem,
- sizeof(int)))
- CODEC_LOG(KERN_ERR, "failed to copy data to user\n");
+ if (copy_to_user((void *)arg, &value, sizeof(int))) {
+ CODEC_LOG(KERN_ERR, "ioctl: failed to copy data to user\n");
+ }
mutex_unlock(&codec_mutex);
if (!svcodec) {
CODEC_LOG(KERN_ERR, "failed to get codec device info\n");
+ mutex_unlock(&codec_mutex);
return -EINVAL;
}
- if (copy_from_user(¶mInfo, buf, sizeof(struct codec_param)))
+ if (copy_from_user(¶mInfo, buf, sizeof(struct codec_param))) {
CODEC_LOG(KERN_ERR,
"failed to get codec parameter info from user\n");
+ mutex_unlock(&codec_mutex);
+ return -EIO;
+ }
- if (paramInfo.api_index == EMUL_AVCODEC_ALLOC_CONTEXT)
- writel((uint32_t)file, svcodec->ioaddr + CODEC_FILE_INDEX);
+ if (paramInfo.api_index == EMUL_AVCODEC_OPEN) {
+ writel((uint32_t)file, svcodec->ioaddr + CODEC_CMD_FILE_INDEX);
+ writel((uint32_t)paramInfo.mem_index,
+ svcodec->ioaddr + CODEC_CMD_SET_MMAP_OFFSET);
+ }
writel((uint32_t)paramInfo.ctx_index,
- svcodec->ioaddr + CODEC_CONTEXT_INDEX);
+ svcodec->ioaddr + CODEC_CMD_CONTEXT_INDEX);
writel((uint32_t)paramInfo.mmap_offset,
- svcodec->ioaddr + CODEC_MMAP_OFFSET);
+ svcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
writel((uint32_t)paramInfo.api_index,
- svcodec->ioaddr + CODEC_API_INDEX);
+ svcodec->ioaddr + CODEC_CMD_API_INDEX);
/* wait decoding or encoding job */
if (paramInfo.api_index >= EMUL_AVCODEC_DECODE_VIDEO &&
paramInfo.api_index <= EMUL_AVCODEC_ENCODE_AUDIO) {
- wait_event_interruptible(svcodec->codec_wq,
- svcodec->sleep_flag != 0);
- svcodec->sleep_flag = 0;
+ wait_event_interruptible(svcodec->codec_job_wq,
+ svcodec->codec_job_done != 0);
+ svcodec->codec_job_done = 0;
}
mutex_unlock(&codec_mutex);
size, vm->vm_page_prot);
if (ret < 0) {
CODEC_LOG(KERN_ERR, "failed to remap page range\n");
- return -EAGAIN;
+ return ret;
}
vm->vm_flags |= VM_IO;
static irqreturn_t svcodec_irq_handler (int irq, void *dev_id)
{
struct svcodec_device *dev = (struct svcodec_device *)dev_id;
+ unsigned long flags = 0;
int val = 0;
- unsigned long flags;
-
-/* spin_lock_irqsave(&dev->lock, flags); */
- val = readl(dev->ioaddr + CODEC_QUERY_STATE);
+ val = readl(dev->ioaddr + CODEC_CMD_GET_THREAD_STATE);
if (!(val & CODEC_IRQ)) {
-/* spin_unlock_irqrestore(&dev->lock, flags); */
return IRQ_NONE;
}
spin_lock_irqsave(&dev->lock, flags);
- dev->sleep_flag = 1;
- wake_up_interruptible(&dev->codec_wq);
+ dev->codec_job_done = 1;
+ wake_up_interruptible(&dev->codec_job_wq);
spin_unlock_irqrestore(&dev->lock, flags);
mutex_lock(&codec_mutex);
CODEC_LOG(KERN_DEBUG, "open! struct file:%p\n", file);
- svcodec->sleep_flag = 0;
+ svcodec->codec_job_done = 0;
/* register interrupt handler */
if (request_irq(svcodec->dev->irq, svcodec_irq_handler,
svcodec->availableMem = 0;
/* notify closing codec device of qemu. */
- if (file)
- writel((uint32_t)file, svcodec->ioaddr + CODEC_CLOSED);
+ if (file) {
+ CODEC_LOG(KERN_DEBUG, "reset codec info.\n");
+ writel((uint32_t)file,
+ svcodec->ioaddr + CODEC_CMD_RESET_CODEC_INFO);
+ }
module_put(THIS_MODULE);
mutex_unlock(&codec_mutex);
int ret;
svcodec = kmalloc(sizeof(struct svcodec_device), GFP_KERNEL);
+ if (!svcodec) {
+ CODEC_LOG(KERN_ERR, "Failed to allocate memory for codec.\n");
+ return -EIO;
+ }
memset(svcodec, 0x00, sizeof(struct svcodec_device));
+ svcodec->dev = pci_dev;
- init_waitqueue_head(&svcodec->codec_wq);
+ init_waitqueue_head(&svcodec->codec_job_wq);
spin_lock_init(&svcodec->lock);
- svcodec->dev = pci_dev;
-
- if (pci_enable_device(pci_dev)) {
+ if ((ret = pci_enable_device(pci_dev))) {
CODEC_LOG(KERN_ERR, "pci_enable_device failed\n");
- goto err_rel;
+ return ret;
}
pci_set_master(pci_dev);
svcodec->mem_start = pci_resource_start(pci_dev, 0);
svcodec->mem_size = pci_resource_len(pci_dev, 0);
-
if (!svcodec->mem_start) {
CODEC_LOG(KERN_ERR, "pci_resource_start failed\n");
- goto err_out;
+ pci_disable_device(pci_dev);
+ return -ENODEV;
}
if (!request_mem_region(svcodec->mem_start,
svcodec->mem_size,
DEVICE_NAME)) {
CODEC_LOG(KERN_ERR, "request_mem_region failed\n");
- goto err_out;
+ pci_disable_device(pci_dev);
+ return -EINVAL;
}
svcodec->io_start = pci_resource_start(pci_dev, 1);
svcodec->io_size = pci_resource_len(pci_dev, 1);
-
if (!svcodec->io_start) {
CODEC_LOG(KERN_ERR, "pci_resource_start failed\n");
- goto err_mem_region;
+ release_mem_region(svcodec->mem_start, svcodec->mem_size);
+ pci_disable_device(pci_dev);
+ return -ENODEV;
}
if (!request_mem_region(svcodec->io_start,
svcodec->io_size,
DEVICE_NAME)) {
CODEC_LOG(KERN_ERR, "request_io_region failed\n");
- goto err_mem_region;
- }
-
-#if 0
- svcodec->memaddr = ioremap(svcodec->mem_start, svcodec->mem_size);
- if (!svcodec->memaddr) {
- CODEC_LOG(KERN_ERR, "[%s] : ioremap failed\n", __func__);
- goto err_io_region;
+ release_mem_region(svcodec->mem_start, svcodec->mem_size);
+ pci_disable_device(pci_dev);
+ return -EINVAL;
}
-#endif
svcodec->ioaddr = ioremap_nocache(svcodec->io_start, svcodec->io_size);
if (!svcodec->ioaddr) {
CODEC_LOG(KERN_ERR, "ioremap failed\n");
- goto err_io_region;
+ release_mem_region(svcodec->io_start, svcodec->io_size);
+ release_mem_region(svcodec->mem_start, svcodec->mem_size);
+ pci_disable_device(pci_dev);
+ return -EINVAL;
}
-#if 0
- /* register chrdev */
- if (register_chrdev(CODEC_MAJOR, DEVICE_NAME, &svcodec_fops)) {
- CODEC_LOG(KERN_ERR, "register_chrdev failed\n");
- goto err_io_unmap;
- }
-#endif
ret = misc_register(&codec_dev);
if (ret) {
CODEC_LOG(KERN_ERR, "cannot register codec as misc\n");
- goto err_io_unmap;
+ iounmap(svcodec->ioaddr);
+ release_mem_region(svcodec->io_start, svcodec->io_size);
+ release_mem_region(svcodec->mem_start, svcodec->mem_size);
+ pci_disable_device(pci_dev);
+ return ret;
}
return 0;
-
-err_io_unmap:
- iounmap(svcodec->ioaddr);
-#if 0
-err_mem_unmap:
- iounmap(svcodec->memaddr);
-#endif
-err_io_region:
- release_mem_region(svcodec->io_start, svcodec->io_size);
-err_mem_region:
- release_mem_region(svcodec->mem_start, svcodec->mem_size);
-err_out:
- pci_disable_device(pci_dev);
-err_rel:
- return -EIO;
}
static void __devinit svcodec_remove(struct pci_dev *pci_dev)
svcodec->ioaddr = 0;
}
-#if 0
- if (svcodec->memaddr) {
- iounmap(svcodec->memaddr);
- svcodec->memaddr = 0;
- }
-#endif
-
if (svcodec->io_start) {
release_mem_region(svcodec->io_start,
svcodec->io_size);