📄 gfx_atom.c
字号:
//vulcan/drv/gfx/gfx_atom.c/*----------------------------------------------------------------------------+|| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 2002| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*/////Comment:// Linux device driver interrupt and DMA handling functions for graphics//Revision Log:// Oct/21/2002 Created by BJC#include <os/os-types.h>#include <os/os-io.h>#include <os/os-interrupt.h>#include <os/os-sync.h>#include <os/drv_debug.h>#include <gfx/gfx_inf_struct.h>#include <asm/semaphore.h>#include <asm/io.h>#include <linux/iobuf.h>#include <linux/mm.h>#include <linux/slab.h>#include "osd_atom.h"#include "osd_osi.h"#include "gfx_atom.h"#include "../vid/vid_atom_hw.h"static GFX_SWAP_SURFACE_T osdanim_swap; // gfx_inf_h_swap_surface() <--> gfx_atom_osdanim_irq_handler()extern unsigned int stb_vid_int_status; // exported from the av_core driver (vid_atom_int.c)static GFX_DMABLT_SRCMEM_T dmablt_type; // tell interrupt handler which transfer method to usestatic dmablt_contig_t dmablt_contig;static dmablt_kiobuf_t dmablt_kiobuf;// local data structuretypedef struct __GFX_HANDLE_T_STRUCTURE__{ GFX_SURFACE_T surface; UINT uLocks; GFX_SURFACE_PHYSICAL_PARM_T phy;} GFX_HANDLE_T;extern GFX_HANDLE_T *gpHandles; // declared in gfx_inf_helper.cvoid gfx_atom_osdanim_irq_handler(int irq, void* dev_id, struct pt_regs *regs){ unsigned long reg; //PDEBUG("\n[IRQ = %d\n", uIrq); //get irq status // The av_core driver reads the video decoder interrupt status register first, // so it has already been reset. Use the exported value from av_core instead.// reg = MF_DCR(VID_HOST_INT); reg = stb_vid_int_status; /*------------------------------------------------------------------------+ | OSD animation interrupt +------------------------------------------------------------------------*/ // when this interrupt goes active, there is 1.2ms to swap surfaces if (reg & 0x1) { if(osdanim_swap.bReadyForSwap) { osdanim_swap.bReadyForSwap = 0; if(osdanim_swap.hOldSurface != 0) { osd_osi_detach_comp_gfx_surface(osdanim_swap.hGraphDev, &gpHandles[osdanim_swap.hOldSurface].surface); } osd_osi_attach_comp_gfx_surface(osdanim_swap.hGraphDev, &gpHandles[osdanim_swap.hNewSurface].surface); } osdanim_swap.missedInts++; up(&osdanim_swap.sem); } return;}void gfx_atom_dmablt_irq_handler(UINT uIrq, void *pData){ if(dmablt_type == GFX_DMABLT_SRCMEM_USER) { // use kiobuf to DMA directly from user-space memory if(MF_DCR(0xe0) & 0x40000000) { MT_DCR(0xe0, 0x40000000); /* start next DMA */ if(++dmablt_kiobuf.list.cur_entry < dmablt_kiobuf.list.num_entries) { auto_dma( dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].dest_phys_addr, dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].source_phys_addr, dmablt_kiobuf.list.entry[dmablt_kiobuf.list.cur_entry].bytecount); } else { up(&dmablt_kiobuf.sem); } } } else if(dmablt_type == GFX_DMABLT_SRCMEM_PHYS) { // source memory is contiguous BYTE repeat_prev_line=0; if(MF_DCR(0xe0) & 0x40000000) { MT_DCR(0xe0, 0x40000000); switch(dmablt_contig.draw_state) { case DRAW1X: if(--dmablt_contig.draw1x_lines_left == 0) { dmablt_contig.draw1x_lines_left = dmablt_contig.p.draw1xLines; if(dmablt_contig.p.drawMxLines != 0) { dmablt_contig.draw_state = DRAWMX; } } repeat_prev_line = 0; break; case DRAWMX: if(--dmablt_contig.drawMx_count_left == 0) { dmablt_contig.drawMx_count_left = dmablt_contig.p.drawMxCount; if(--dmablt_contig.drawMx_lines_left == 0) { dmablt_contig.drawMx_lines_left = dmablt_contig.p.drawMxLines; if(dmablt_contig.p.draw1xLines != 0) { dmablt_contig.draw_state = DRAW1X; } else { dmablt_contig.draw_state = DRAWMX; } } repeat_prev_line = 0; } else { repeat_prev_line = 1; } break; } switch(dmablt_contig.component) { case 0: dmablt_contig.p.dstY += dmablt_contig.p.dstStride; if(repeat_prev_line) { auto_dma((UINT)dmablt_contig.p.dstY, (UINT)dmablt_contig.p.srcY, dmablt_contig.p.dstStride); } else if(++dmablt_contig.linecount == dmablt_contig.p.imageHeight) { /* done with Y */ dmablt_contig.linecount = 0; dmablt_contig.component = 1; 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; if(dmablt_contig.p.draw1xLines != 0) { dmablt_contig.draw_state = DRAW1X; } else { dmablt_contig.draw_state = DRAWMX; } auto_dma((UINT)dmablt_contig.p.dstUV, (UINT)dmablt_contig.p.srcUV, dmablt_contig.p.dstStride); } else { dmablt_contig.p.srcY += dmablt_contig.p.srcStride; auto_dma((UINT)dmablt_contig.p.dstY, (UINT)dmablt_contig.p.srcY, dmablt_contig.p.dstStride); } break; case 1: dmablt_contig.p.dstUV += dmablt_contig.p.dstStride; if(repeat_prev_line) { auto_dma((UINT)dmablt_contig.p.dstUV, (UINT)dmablt_contig.p.srcUV, dmablt_contig.p.dstStride); } else if(++dmablt_contig.linecount == dmablt_contig.p.imageHeight/2) { /* done with UV */ up(&dmablt_contig.sem); dmablt_contig.component = 2; } else { dmablt_contig.p.srcUV += dmablt_contig.p.srcStride; auto_dma((UINT)dmablt_contig.p.dstUV, (UINT)dmablt_contig.p.srcUV, dmablt_contig.p.dstStride); } break; } } } else { PDEBUG("invalid dmablt_type (%d)\n", dmablt_type); } return;}int gfx_atom_init(void){// UINT32 flags; sema_init(&osdanim_swap.sem, 0); osdanim_swap.bReadyForSwap = 0; //install interrupt handler#if 0 if(os_install_irq(IRQ_VID, IRQ_LEVEL_TRIG | IRQ_POSITIVE_TRIG, gfx_atom_osdanim_irq_handler, (void*)0) != 0) {printk(KERN_ALERT "IRQ_VID install failed\n"); PDEBUG("install interrupt handler error\n"); return -1; }#else if(request_irq(IRQ_VID, gfx_atom_osdanim_irq_handler, SA_SHIRQ, "OSDanim", &gfx_atom_init) != 0) { PDEBUG("install interrupt handler error\n"); return -1; }#endif /* moved setting the mask to osd_atom_set_display_cntl when the amination interrupt bit is set os_disable_irq(IRQ_VID); // enable OSD animation interrupt from video decoder flags = os_enter_critical_section(); MT_DCR(VID_MASK, MF_DCR(VID_MASK) | DECOD_HOST_INT_OSD_DATA); os_leave_critical_section(flags); os_enable_irq(IRQ_VID);*/ PDEBUG("install irq handler and task OK\n"); //install DMA1 interrupt handler // initialize both transfer mechanisms so either can be used dmablt_contig_init(); dmablt_kiobuf_init(); if(os_install_irq(IRQ_DMA1, IRQ_LEVEL_TRIG | IRQ_POSITIVE_TRIG, gfx_atom_dmablt_irq_handler, (void*)0) != 0) { PDEBUG("dma blt install interrupt handler error\n"); return -1; } // this interrupt should already be enabled// os_enable_irq(IRQ_DMA1); return 0;}void gfx_atom_deinit(void){/* moved setting the mask to osd_atom_set_display_cntl when the amination interrupt bit is reset UINT32 flags; os_disable_irq(IRQ_VID); // disable OSD animation interrupt from video decoder flags = os_enter_critical_section(); MT_DCR(VID_MASK, MF_DCR(VID_MASK) & ~DECOD_HOST_INT_OSD_DATA); os_leave_critical_section(flags);*/ #if 0 os_uninstall_irq(IRQ_VID); //remove irq handler#else free_irq(IRQ_VID, &gfx_atom_init);#endif // leave interrupt enabled// os_disable_irq(IRQ_DMA1); os_uninstall_irq(IRQ_DMA1); //remove irq handler}int iobuf_lock(struct kiobuf **iobuf, int access, void *userbuf, int size){ int result; result = alloc_kiovec(1, iobuf); if(result) { printk(KERN_WARNING "failed to allocate kiobuf\n"); return result; } result = map_user_kiobuf(access, *iobuf, (unsigned int)userbuf, size); if(result) { free_kiovec(1, iobuf); printk(KERN_WARNING "failed to map kiobuf\n"); } return 0;}void iobuf_unlock(struct kiobuf **iobuf){ unmap_kiobuf(*iobuf); free_kiovec(1, iobuf); }inline void iobuf_pos_init(iobuf_pos_t *ip, struct kiobuf *iobuf){ ip->iobuf = iobuf; ip->offset = iobuf->offset; ip->pageno = 0;}inline UINT iobuf_pos_get(iobuf_pos_t *ip, UINT count, BYTE* *vaddr){ UINT valid_count; *vaddr = (BYTE*)page_address(ip->iobuf->maplist[ip->pageno])+ip->offset; valid_count = count; if(ip->offset + valid_count > PAGE_SIZE) { valid_count = PAGE_SIZE - ip->offset; ip->pageno++; ip->offset=0; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -