转载:http://zhiqiang0071.cublog.cn
——————————————–
撰写了符合v4L2的s3c2440的camera驱动,采用videobuf模块管理视频内存,需要申请四个物理上连续的内存,但是linux内核中现有的
videobuf-dma-contig
在我的系统中只能申请三个(其实是因为默认定义可以申请的buffer大小只有
2M,
如果修改大点也可以直接使用
videobuf-dma-contig的,修改的地方是arch/arm/include/asm/memory.h
, #define CONSISTENT_DMA_SIZE SZ_2M),故以videobuf-
dma-contig
为蓝本,撰写了videobuf-contig.c,
videobuf-contig采用获取物理上连续的页并设置为保留的方式来获得物理上连续的内存,在
s3c2440平台
中这些物理内存的
物理地址等于总线地址,
可以进行DMA传输。
把videobuf-contig.c加入到内核的drivers/media/video文件夹下 ,把
videobuf-contig.h加入到内核的include/media文件夹下
,
修改
drivers/media/video/kconfig,加入
config VIDEOBUF_CONTIG
select VIDEOBUF_GEN
tristate
修改
drivers/media/video/Makefile,加入
obj-$(CONFIG_VIDEOBUF_CONTIG) += videobuf-contig.o
代码如下:
videobuf-contig.c:
|
/* #include <linux/init.h> #include <linux/pci.h> #include <media/videobuf–contig.h> #define MAGIC_PC_MEM 0x #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ static int debug; MODULE_DESCRIPTION(“helper module to manage video4linux physic continue buffers”); #define dprintk(level, fmt, arg...) if (debug >= level) \ struct videobuf_contig_memory /* Allocate physic continue memory for buffers */ mem = (void *)__get_dma_pages(GFP_KERNEL, return mem; /* Free memory for buffers */ if (!addr) /*/ static void dprintk(2,“vm_open %p [count=%u,vma=%08lx-%08lx]\n”,map, map–>count++; static void videobuf_vm_close(struct vm_area_struct *vma) dprintk(2,“vm_close %p [count=%u,vma=%08lx-%08lx]\n”, map, dprintk(1, “munmap %p q=%p\n”, map, q); /* We need first to cancel streams, before unmapping */ for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (q–>bufs[i]–>map != map) mem = q–>bufs[i]–>priv; MAGIC_CHECK(mem–>magic, MAGIC_PC_MEM); dprintk(1, “%s: buf[%d] freeing (%d)\n”, free_contig(mem–>vaddr, mem–>size); q–>bufs[i]–>map = NULL; kfree(map); mutex_unlock(&q–>vb_lock); return; static struct vm_operations_struct videobuf_vm_ops = /* ——————————————————————— /* Allocated area consists on 3 parts: static void *__videobuf_alloc(size_t size) vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); mem = vb–>priv = ((char *)vb)+size; dprintk(1,“%s: allocated at %p(%ld+%ld) & %p(%ld)\n”, return vb; static int __videobuf_iolock (struct videobuf_queue* q, BUG_ON(!mem); MAGIC_CHECK(mem–>magic, MAGIC_PC_MEM); switch (vb–>memory) { /* All handling should be done by __videobuf_mmap_mapper() */ dprintk(1, “%s memory method USERPTR\n”, __func__); if (vb–>baddr) { /* The only USERPTR currently supported is the one needed for break; /* Currently, doesn’t support V4L2_MEMORY_OVERLAY */ return 0; static int __videobuf_sync(struct videobuf_queue *q, static int __videobuf_mmap_free(struct videobuf_queue *q) dprintk(1, “%s\n”, __func__); return 0; static int __videobuf_mmap_mapper(struct videobuf_queue *q, dprintk(1, “%s\n”, __func__); /* look for first buffer to map */ if (V4L2_MEMORY_MMAP != q–>bufs[first]–>memory) /* create mapping + update buffer list */ q–>bufs[first]–>map = map; q–>bufs[first]–>baddr = vma–>vm_start; mem = q–>bufs[first]–>priv; mem–>size = PAGE_ALIGN(q–>bufs[first]–>bsize); size = vma–>vm_end – vma–>vm_start; /* Try to remap memory */ vma–>vm_ops = &videobuf_vm_ops; dprintk(1,“mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n”, videobuf_vm_open(vma); return 0; error: static int __videobuf_copy_to_user ( struct videobuf_queue *q, BUG_ON(!mem); /* copy to userspace */ vaddr = mem–>vaddr; if (copy_to_user(data, vaddr + q–>read_off, count)) return count; static int __videobuf_copy_stream ( struct videobuf_queue *q, if (vbihack) { /* copy stuff using the common method */ if ( (count==–EFAULT) && (0 == pos) ) return count; static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf) BUG_ON(!mem); return mem–>vaddr; static struct videobuf_qtype_ops qops = { .alloc = __videobuf_alloc, void videobuf_queue_contig_init(struct videobuf_queue* q, EXPORT_SYMBOL_GPL(videobuf_queue_contig_init); u32 videobuf_to_contig (struct videobuf_buffer *buf) return mem–>paddr; void videobuf_contig_free (struct videobuf_buffer *buf) /* mmapped memory can’t be freed here, otherwise mmapped region MAGIC_CHECK(mem–>magic, MAGIC_PC_MEM); free_contig(mem–>vaddr, mem–>size); return; |
videobuf-contig.h:
/*
* helper functions for physically contiguous capture buffers
*
* The functions expect the hardware being able to scatter gather
* (i.e. the buffers are not linear in physical memory, but fragmented
* into PAGE_SIZE chunks). They also assume the driver does not need
* to touch the video data.
*
* (c) 2009 modified from videobuf-dma-contig by Seen Yang,
*
* 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
*/
#ifndef _VIDEOBUF_CONTIG_H
#define _VIDEOBUF_CONTIG_H
#include <media/videobuf–core.h>
/* ——————————————————————— */
void videobuf_queue_contig_init(struct videobuf_queue* q,
struct videobuf_queue_ops *ops,
void *dev,
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
unsigned int msize,
void *priv);
u32 videobuf_to_contig (struct videobuf_buffer *buf);
void videobuf_contig_free (struct videobuf_buffer *buf);
#endif
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211398.html原文链接:https://javaforall.net
