为了在video设备中分配大块连续物理内存,移植android Pmem
驱动部分:
1、 pmem driver 文件从android linux中copy,并配置好makefile和config
2、在devs.c中添加
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#include <linux/memblock.h>
#endif
#ifdef CONFIG_ANDROID_PMEM
static struct android_pmem_platform_data pmem_pdata = {
.name = "pmem",
.no_allocator = 1,
.cached = 1,
.start = 0,
.size = 0,
};
struct platform_device pmem_device = {
.name = "android_pmem",
.id = 0,
.dev = { .platform_data = &pmem_pdata },
};
void __init s5p_pmem_reserve_mem(phys_addr_t base, unsigned int size)
{
if (memblock_remove(base, size)) {
printk(KERN_ERR "Failed to reserve memory for PMEM device (%ld bytes at 0x%08lx)\n",
size, (unsigned long)base);
base = 0;
return;
}
printk(KERN_INFO "reserve memory for PMEM device (%ld bytes at 0x%08lx)\n",
size, (unsigned long)base);
pmem_pdata.start = base;
pmem_pdata.size = size;
}
#endif
在devs.h中添加
#ifdef CONFIG_ANDROID_PMEM
extern struct platform_device pmem_device;
extern void __init s5p_pmem_reserve_mem(phys_addr_t base, unsigned int size);
#endif
在mach-smdkv210.c中添加
static void __init smdkv210_reserve(void)
{
s5p_mfc_reserve_mem(0x3b800000, 36 << 20, 0x3dc00000, 36 << 20);
#ifdef CONFIG_ANDROID_PMEM
s5p_pmem_reserve_mem(0x3b000000, 8 << 20);
#endif
}
static struct platform_device *smdkv210_devices[] 中加入变量
#ifdef CONFIG_ANDROID_PMEM
&pmem_device,
#endif
测试程序:
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/mman.h>
#include <assert.h>
#include <linux/videodev2.h>
#include <linux/fb.h>
#include <pthread.h>
#include <poll.h>
#include <semaphore.h>
#include "android_pmem.h"
int main()
{
int pmem_fd;
void *pmem_base;
unsigned int size;
struct pmem_region region;
pmem_fd = open("/dev/pmem", O_RDWR, 0);//打开设备,为了操作硬件引擎,要noncache的
printf("pmem_fd:%d\n", pmem_fd);
if (pmem_fd >= 0)
{
if (ioctl(pmem_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) //获取全部空间
perror("PMEM_GET_TOTAL_SIZE failed\n");
size = region.len;
printf("region.len:0x%08x offset:0x%08x\n",region.len, region.offset);
pmem_base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);//mmap操作
if (pmem_base == MAP_FAILED)
{ pmem_base = 0;
close(pmem_fd);
pmem_fd = -1;
perror("mmap pmem error!\n");
}
printf("pmem_base:0x%08x\n", pmem_base);
}
if ( ioctl(pmem_fd, PMEM_GET_PHYS, ®ion) < 0)
{//获取物理地址
perror("PMEM_GET_PHYS failed\n");
}
printf("region:0x%08x\n",region.offset);
if(munmap(pmem_base, size) < 0)
{
perror("munmap error\n");
}
close(pmem_fd);
return 0;
}