📄 gfx_atom.c
字号:
ip->offset += valid_count; } return valid_count;}inline void iobuf_pos_skip(iobuf_pos_t *ip, UINT count){ ip->offset += count; while(ip->offset > PAGE_SIZE) { ip->pageno++; ip->offset -= PAGE_SIZE; }}void dmablt_kiobuf_init(){ dmablt_kiobuf.iobuf_locked = 0; sema_init(&dmablt_kiobuf.sem, 1);}inline void dmablt_kiobuf_addtransfer(BYTE** dest, iobuf_pos_t* bufpos, UINT bytecount, UINT repeat){ BYTE* vaddr; UINT first_entry; UINT last_entry; UINT i; first_entry = dmablt_kiobuf.list.cur_entry; while(bytecount > 0) { if(dmablt_kiobuf.list.cur_entry == dmablt_kiobuf.list.allocated_entries) { printk(KERN_ALERT "ran out of entries at %d\n", dmablt_kiobuf.list.cur_entry); return; } dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].bytecount = iobuf_pos_get(bufpos, bytecount, &vaddr); dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].source_phys_addr = virt_to_bus(vaddr); dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].dest_phys_addr = virt_to_bus(*dest); *dest += dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].bytecount; bytecount -= dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].bytecount; dmablt_kiobuf.list.cur_entry++; } while(repeat > 0) { last_entry = dmablt_kiobuf.list.cur_entry; for(i=first_entry; i < last_entry; i++) { if(dmablt_kiobuf.list.cur_entry == dmablt_kiobuf.list.allocated_entries) { printk(KERN_ALERT "ran out of entries at %d\n", dmablt_kiobuf.list.cur_entry); return; } dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].bytecount = dmablt_kiobuf.list.entry[i].bytecount; dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].source_phys_addr = dmablt_kiobuf.list.entry[i].source_phys_addr; dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].dest_phys_addr = virt_to_bus(*dest); *dest += dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].bytecount; dmablt_kiobuf.list.cur_entry++; } repeat--; }}void dmablt_kiobuf_transfer(GFX_DMABLT_PARM_T *pParm){ UINT i,j; UINT nent; iobuf_pos_t Ybufpos; iobuf_pos_t UVbufpos; if(pParm->synchMode == GFX_DMABLT_MODE_ASYNCH) { /* wait for prior DMA to finish */// waitfor_dma(); down_interruptible(&dmablt_kiobuf.sem); } dmablt_kiobuf.synchMode = pParm->synchMode; /* release any previously pinned memory pages */ if(dmablt_kiobuf.iobuf_locked) { iobuf_unlock(&dmablt_kiobuf.iobufYs); iobuf_unlock(&dmablt_kiobuf.iobufUVs); kfree(dmablt_kiobuf.list.entry); } /* allocate memory for the list of DMA transfers */ nent = pParm->imageHeight * 8; dmablt_kiobuf.list.entry = (dmalist_ent_t *)kmalloc(nent*sizeof(dmalist_ent_t), GFP_KERNEL); dmablt_kiobuf.list.allocated_entries = nent; /* page-in and pin buffers in memory for DMA transfer */ iobuf_lock(&dmablt_kiobuf.iobufYs, READ, pParm->srcY, pParm->srcStride*pParm->imageHeight); iobuf_lock(&dmablt_kiobuf.iobufUVs, READ, pParm->srcUV, pParm->srcStride*pParm->imageHeight); dmablt_kiobuf.iobuf_locked = 1; /* create list of DMA transfers */ dmablt_kiobuf.list.cur_entry = 0; iobuf_pos_init(&Ybufpos, dmablt_kiobuf.iobufYs); iobuf_pos_skip(&Ybufpos, pParm->srcLineOffset * pParm->srcStride); i=0; while(i < pParm->imageHeight) { for(j=0; j < pParm->draw1xLines; j++) { dmablt_kiobuf_addtransfer(&pParm->dstY, &Ybufpos, pParm->dstStride, 0); iobuf_pos_skip(&Ybufpos, pParm->srcStride-pParm->dstStride); i++; } for(j=0; j < pParm->drawMxLines; j++) { dmablt_kiobuf_addtransfer(&pParm->dstY, &Ybufpos, pParm->dstStride, pParm->drawMxCount-1); iobuf_pos_skip(&Ybufpos, pParm->srcStride-pParm->dstStride); i++; } } iobuf_pos_init(&UVbufpos, dmablt_kiobuf.iobufUVs); iobuf_pos_skip(&UVbufpos, (pParm->srcLineOffset<<1) * pParm->srcStride); i=0; while(i < pParm->imageHeight/2) { for(j=0; j < pParm->draw1xLines; j++) { dmablt_kiobuf_addtransfer(&pParm->dstUV, &UVbufpos, pParm->dstStride, 0); iobuf_pos_skip(&UVbufpos, pParm->srcStride-pParm->dstStride); i++; } for(j=0; j < pParm->drawMxLines; j++) { dmablt_kiobuf_addtransfer(&pParm->dstUV, &UVbufpos, pParm->dstStride, pParm->drawMxCount-1); iobuf_pos_skip(&UVbufpos, pParm->srcStride-pParm->dstStride); i++; } } /* initiate first DMA transfer */ dmablt_kiobuf.list.num_entries = dmablt_kiobuf.list.cur_entry; dmablt_kiobuf.list.cur_entry = 0; if(pParm->synchMode == GFX_DMABLT_MODE_ASYNCH) { auto_dma( dmablt_kiobuf.list.entry[0].dest_phys_addr, dmablt_kiobuf.list.entry[0].source_phys_addr, dmablt_kiobuf.list.entry[0].bytecount); /* when DMA finishes, ISR does "up(&dmablt_kiobuf.sem);" */ } else { /* wait until DMA finishes before returning */ sema_init(&dmablt_kiobuf.sem, 0); auto_dma( dmablt_kiobuf.list.entry[0].dest_phys_addr, dmablt_kiobuf.list.entry[0].source_phys_addr, dmablt_kiobuf.list.entry[0].bytecount); /* when DMA finishes, ISR does "up(&dmablt_kiobuf.sem);" */ down_interruptible(&dmablt_kiobuf.sem); }}void dmablt_contig_init(){ sema_init(&dmablt_contig.sem, 1);}void dmablt_contig_transfer(GFX_DMABLT_PARM_T *pParm){ if(pParm->synchMode == GFX_DMABLT_MODE_ASYNCH) { /* wait for prior DMA to finish */ down_interruptible(&dmablt_contig.sem); } memcpy(&dmablt_contig.p, pParm, sizeof(GFX_DMABLT_PARM_T)); dmablt_contig.p.srcY = (BYTE*)virt_to_bus(dmablt_contig.p.srcY+(dmablt_contig.p.srcLineOffset*dmablt_contig.p.srcStride)); dmablt_contig.p.dstY = (BYTE*)virt_to_bus(dmablt_contig.p.dstY); dmablt_contig.p.srcUV = (BYTE*)virt_to_bus(dmablt_contig.p.srcUV+((dmablt_contig.p.srcLineOffset>>1)*dmablt_contig.p.srcStride)); dmablt_contig.p.dstUV = (BYTE*)virt_to_bus(dmablt_contig.p.dstUV); dmablt_contig.draw1x_lines_left = dmablt_contig.p.draw1xLines; dmablt_contig.drawMx_lines_left = dmablt_contig.p.drawMxLines; dmablt_contig.drawMx_count_left = dmablt_contig.p.drawMxCount; dmablt_contig.component = 0; dmablt_contig.linecount = 0; if(dmablt_contig.p.draw1xLines != 0) { dmablt_contig.draw_state = DRAW1X; } else { dmablt_contig.draw_state = DRAWMX; } if(pParm->synchMode == GFX_DMABLT_MODE_ASYNCH) { auto_dma((UINT)dmablt_contig.p.dstY, (UINT)dmablt_contig.p.srcY, dmablt_contig.p.dstStride); /* when DMA finishes, ISR does "up(&dmablt_contig.sem);" */ } else { /* wait until DMA finishes before returning */ sema_init(&dmablt_contig.sem, 0); auto_dma((UINT)dmablt_contig.p.dstY, (UINT)dmablt_contig.p.srcY, dmablt_contig.p.dstStride); /* when DMA finishes, ISR does "up(&dmablt_contig.sem);" */ down_interruptible(&dmablt_contig.sem); }}int linedma_count = 0;int worddma_count = 0;int bytedma_count = 0;inline void auto_dma(UINT dst, UINT src, UINT bytecount){ if((src & 0xF) == 0 && (dst & 0xF) == 0 && (bytecount & 0xF) == 0) { /* 16-byte line DMA */ start_dma(dst, src, bytecount>>4, 3); linedma_count++; } else if((src & 0x3) == 0 && (dst & 0x3) == 0 && (bytecount & 0x3) == 0) { /* 4-byte word DMA */ start_dma(dst, src, bytecount>>2, 2); worddma_count++; } else { /* single byte width DMA */ start_dma(dst, src, bytecount, 1); bytedma_count++; }}//#define PRIORITY_MASK 0x00000000 /* low priority */#define PRIORITY_MASK 0x00800001 /* high priority */inline void start_dma(UINT dst, UINT src, UINT count, BYTE width){ MT_DCR(DMA0SA1, src); /* set source address */ MT_DCR(DMA0DA1, dst); /* set destination address */ MT_DCR(DMA0CT1, count); /* set transfer count */ MT_DCR(DMA0CR1, 0xC3400302 | PRIORITY_MASK | (width << 26));}void waitfor_dma(){ int i=0; while((MF_DCR(DMASR0) & 0x00000200)) i++; if(i != 0) { printk(KERN_ALERT "waited for DMA %d times\n", i); }}int i=0;int gfx_atom_dmablt_handle_request(GFX_DMABLT_PARM_T *pParm){ // tell interrupt handler which transfer method to use dmablt_type = pParm->srcMemType; // initiate transfer using the appropriate method if(pParm->srcMemType == GFX_DMABLT_SRCMEM_PHYS) { dmablt_contig_transfer(pParm); } else if(pParm->srcMemType == GFX_DMABLT_SRCMEM_USER) { dmablt_kiobuf_transfer(pParm); }#if 0 if(++i == 30) { i = 0; printk(KERN_ALERT "line %d, word %d, byte %d\n", linedma_count, worddma_count, bytedma_count); }#endif return 0;}int gfx_atom_dmablt_wait_handle_request(void){ if(dmablt_type == GFX_DMABLT_SRCMEM_PHYS) { if(dmablt_contig.p.synchMode == GFX_DMABLT_MODE_ASYNCH) { down_interruptible(&dmablt_contig.sem); up(&dmablt_contig.sem); } } else if(dmablt_type == GFX_DMABLT_SRCMEM_USER) { if(dmablt_kiobuf.synchMode == GFX_DMABLT_MODE_ASYNCH) { down_interruptible(&dmablt_kiobuf.sem); up(&dmablt_kiobuf.sem); } } return 0;}int gfx_atom_pmalloc_handle_request(GFX_PMALLOC_PARM_T *pParm){ struct kiobuf *iobuf; iobuf_pos_t iobuf_pos; BYTE *vaddr; switch(pParm->mode) { case GFX_PMALLOC_ALLOCATE: /* occupy an integral number of pages */ pParm->uAllocSize += PAGE_SIZE - (pParm->uAllocSize & (PAGE_SIZE-1)); //printk(KERN_ALERT "Allocate size = %d bytes\n", pParm->uAllocSize); pParm->hBuffer = os_alloc_physical_justify(pParm->uAllocSize, OSD_ADDRESS_ALIGNMENT); if(NULL == pParm->hBuffer) { printk(KERN_INFO "Failed to alloc %d buffer for new surface!\n", pParm->uAllocSize); pParm->hBuffer = NULL; return -1; } printk(KERN_INFO "Buffer allocated = %08x \n", (UINT)pParm->hBuffer); pParm->uPhysical = os_get_physical_address(pParm->hBuffer); pParm->pLogical = os_get_logical_address(pParm->hBuffer); pParm->uSize = os_get_actual_physical_size(pParm->hBuffer); break; case GFX_PMALLOC_FREE: os_free_physical(pParm->hBuffer); break; case GFX_PMALLOC_CHKALIGN: iobuf_lock(&iobuf, READ, pParm->pLogical, pParm->uSize); iobuf_pos_init(&iobuf_pos, iobuf); iobuf_pos_get(&iobuf_pos, 1, &vaddr); pParm->uPhysical = virt_to_bus(vaddr); iobuf_unlock(&iobuf); break; default: printk(KERN_ALERT "invalid mode\n"); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -