⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hmp4d.c

📁 Hantro Driver MP4 Hardware Encoder/Decoder
💻 C
📖 第 1 页 / 共 2 页
字号:
	_reg_AIPI2_PAR &= ~(0x1 << 6);	_reg_CRM_PCCR0 |= 0x08008000;#endif	    hmp4d_data.iobaseaddr = base_port;    hmp4d_data.iosize = DEC_IO_SIZE;    hmp4d_data.irq = irq;	/* changed to devfs */	/* register hmp4e device */ 	result = devfs_register_chrdev(0, "hmp4d", &hmp4d_fops); 	if ( result < 0 ) 	{		printk("hmp4d error: unable to register chr driver\n");		return -ENODEV;	}#ifndef NODEVFS	devfs_handle = devfs_register(NULL, "hmp4d", DEVFS_FL_DEFAULT,				      result, 0,				      S_IFCHR | S_IRUSR | S_IWUSR,				      &hmp4d_fops, NULL);	if(devfs_handle == NULL)	{		printk("hmp4d error: unable to register driver\n");		return -ENODEV;	}#endif	hmp4d_major = result;	/* power management */#ifdef APM_HMP4D	if ((pmdev = pm_register(PM_EMMA_DEV, PM_SYS_UNKNOWN, hmp4d_pm_handler)) == NULL)	{		printk("Failed to register PM... continuing with driver init\n");	}	g_hmp4d_apmc = apmc_register(APMC_LEVEL_HIGHEST);#endif	/* register for ipc */	/* in case other emma device want to get the status of each other */	g_hmp4d_busy = 0;	inter_module_register("string_hmp4d_busy", THIS_MODULE, &g_hmp4d_busy);    result = ReserveIO();    if(result < 0)    {        goto err;    }    ResetAsic(&hmp4d_data);    result = AllocMemory();    if(result < 0)    {        ReleaseIO();        goto err;    }    printk(KERN_INFO "hmp4d: module inserted. Major = %d\n", hmp4d_major);    EXPORT_NO_SYMBOLS;    return 0;  err:    printk(KERN_INFO "hmp4d: module not inserted. Major = %d\n", hmp4d_major);    unregister_chrdev(hmp4d_major, "hmp4d");    return result;}void __exit hmp4d_cleanup(void){	/* change to devfs */   	if(hmp4d_major > 0)   	{		if(devfs_unregister_chrdev(hmp4d_major, "hmp4d") < 0)		{			printk("hmp4d error: failed to unregister from devfs\n");			return;		}	}#ifndef NODEVFS	if(devfs_handle != NULL)		devfs_unregister(devfs_handle);	else	{		printk("hmp4d error: failed to unregister from devfs, devfs_handle = 0x%08X\n", (int)devfs_handle);		return;	}#endif	/* power management */#ifdef APM_HMP4D	apmc_unregister(g_hmp4d_apmc);	pm_unregister(pmdev);#endif	/* unregister ipc */	inter_module_unregister("string_hmp4d_busy");    FreeMemory();    ReleaseIO();    printk(KERN_INFO "Decoder driver is unloaded sucessfully\n");    return;}module_init(hmp4d_init);module_exit(hmp4d_cleanup);static int AllocMemory(void){#if !CONS_ALLOC    struct page *pg;    char *start_addr, *end_addr;    u32 order, size;    hmp4d_data.buffer = NULL;#endif    hmp4d_data.buffsize = HMP4D_BUF_SIZE;#if !CONS_ALLOC    for(order = 0, size = PAGE_SIZE; size < hmp4d_data.buffsize;        order++, size <<= 1) ;    hmp4d_data.buffsize = size;    /* alloc memory */    start_addr = (char *) __get_free_pages(GFP_KERNEL, order);    if(!start_addr)    {        printk(KERN_INFO "hmp4d: failed to alloc memory\n");        return -ENOMEM;    }    else    {        memset(start_addr, 0, hmp4d_data.buffsize); /* clear the mem */        strcpy(start_addr, "Mapping test, data written from kernel!");        hmp4d_data.buffer = start_addr;    }    end_addr = start_addr + hmp4d_data.buffsize - 1;    PDEBUG("Alloc buffer 0x%08lx -- 0x%08lx\n", (long) start_addr,           (long) end_addr);    /* now we've got the kernel memory, but it can still be     * swapped out. We need to stop the VM system from removing our     * pages from main memory. To do this we just need to set the PG_reserved      * bit on each page, via mem_map_reserve() macro.     */    /* If we don't set the reserved bit, the user-space application sees      * all-zeroes pages. This is because remap_page_range() won't allow you to     * map non-reserved pages (check remap_pte_range()).     * The pte's will be cleared, resulting in a page faulting in a new zeroed      * page instead of the pages we are trying to mmap().      */    for(pg = virt_to_page(start_addr); pg <= virt_to_page(end_addr); pg++)    {        mem_map_reserve(pg);    }#else	hmp4d_data.buffsize = (HMP4D_BUF_SIZE + PAGE_SIZE - 1) & 		~(PAGE_SIZE - 1);        hmp4d_data.buffer = consistent_alloc(GFP_DMA | GFP_KERNEL, 		hmp4d_data.buffsize, (dma_addr_t *)&hmp4d_phys);	if (!hmp4d_data.buffer)	{printk("alloc %d failed\n", hmp4d_data.buffsize);		return -ENOMEM;	}	else	{		memset(hmp4d_data.buffer, 0, hmp4d_data.buffsize);		strcpy(hmp4d_data.buffer, 			"Mapping test, data written from kernel!");	}#endif    return 0;}static void FreeMemory(void){#if !CONS_ALLOC    struct page *pg;    u32 size, order;    /* first unreserve */    for(pg = virt_to_page(hmp4d_data.buffer);        pg < virt_to_page(hmp4d_data.buffer + hmp4d_data.buffsize); pg++)    {        mem_map_unreserve(pg);    }    for(order = 0, size = PAGE_SIZE; size < hmp4d_data.buffsize;        order++, size <<= 1) ;    /* and now free */    free_pages((long) hmp4d_data.buffer, order);    PDEBUG("Free buffer 0x%08lx -- 0x%08lx\n", (long) hmp4d_data.buffer,           (long) (hmp4d_data.buffer + hmp4d_data.buffsize - 1));#else	consistent_free(hmp4d_data.buffer, hmp4d_data.buffsize, hmp4d_phys);#endif}static int ReserveIO(void){    if(!request_mem_region(hmp4d_data.iobaseaddr, hmp4d_data.iosize, "hmp4d"))    {        printk(KERN_INFO "hmp4d: failed to reserve IO memory\n");        return -EBUSY;    }    hmp4d_data.hwregs =        (u32 *) ioremap_nocache(hmp4d_data.iobaseaddr, hmp4d_data.iosize);    if(hmp4d_data.hwregs == NULL)    {        printk(KERN_INFO "hmp4d: failed to ioremap IO memory\n");        ReleaseIO();        return -EBUSY;    }#if 1    if((readl(hmp4d_data.hwregs + 7) & 0x0000ffff) != DEC_HW_ID)    {        printk(KERN_INFO "hmp4d: HW not found at 0x%08lx\n",               hmp4d_data.iobaseaddr);        ReleaseIO();        return -EBUSY;    }#endif    return 0;}static void ReleaseIO(void){    if(hmp4d_data.hwregs)        iounmap(hmp4d_data.hwregs);    release_mem_region(hmp4d_data.iobaseaddr, hmp4d_data.iosize);}static int MapBuffers(struct file *filp, struct vm_area_struct *vma){    unsigned long phys;    unsigned long start = (unsigned long) vma->vm_start;    unsigned long size = (unsigned long) (vma->vm_end - vma->vm_start);    /* if userspace tries to mmap beyond end of our buffer, fail */    if(size > hmp4d_data.buffsize)        return -EINVAL;    vma->vm_flags |= VM_RESERVED;    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);    /* Remember this won't work for vmalloc()d memory ! */#if !CONS_ALLOC    phys = virt_to_phys(hmp4d_data.buffer);#else	phys = hmp4d_phys;#endif    if(remap_page_range(start, phys, size, vma->vm_page_prot))    {        return -EAGAIN;    }    return 0;}static int MapHwRegs(struct file *filp, struct vm_area_struct *vma){    unsigned long phys;    unsigned long start = (unsigned long) vma->vm_start;    unsigned long size = (unsigned long) (vma->vm_end - vma->vm_start);#if NON_PAGE_ALIGNED	int	ofs;	ofs  = hmp4d_data.iobaseaddr & (PAGE_SIZE - 1);#endif    /* if userspace tries to mmap beyond end of our buffer, fail */    if(size > PAGE_SIZE)        return -EINVAL;    vma->vm_flags |= VM_RESERVED | VM_IO;    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);    /* Remember this won't work for vmalloc()d memory ! */    phys = hmp4d_data.iobaseaddr;#if NON_PAGE_ALIGNED	if(remap_page_range(start, phys - ofs, hmp4d_data.iosize + ofs, 		vma->vm_page_prot))#else    if(remap_page_range(start, phys, hmp4d_data.iosize, vma->vm_page_prot))#endif    {        return -EAGAIN;    }    return 0;}void hmp4d_isr(int irq, void *dev_id, struct pt_regs *regs){    hmp4d_t *dev = (hmp4d_t *) dev_id;    /* Clear the HW Interrupt Register immediately! */    u32 irq_status = readl(dev->hwregs);    writel(irq_status & (~0x08), dev->hwregs);    PDEBUG("DecIRQ");    if(dev->async_queue)        kill_fasync(&dev->async_queue, SIGIO, POLL_IN);}void ResetAsic(hmp4d_t * dev){    u32 tmp;    tmp = readl(dev->hwregs);    tmp = tmp | 0x20;    writel(tmp, dev->hwregs);   /* enable dec CLK */    writel(tmp & (~0x01), dev->hwregs); /* disable dec */    writel(0x20, dev->hwregs);  /* clear reg 1 */    writel(0, dev->hwregs); /* disable dec CLK */}#ifdef APM_HMP4Dstatic int hmp4d_pm_handler(struct pm_dev *pmdev, pm_request_t rqst, void *data){	switch(rqst)	{		case PM_SUSPEND:		{			if(g_hmp4d_busy)			{				return 1;			}			else			{								printk("hmp4d suspend\n");				break;			}		}		case PM_RESUME:		{			printk("hmp4d resume\n");			break;		}	}		return 0;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -