📄 osdfb.c
字号:
/******************************************************************** Copyright (c) 2002 Sigma Designs Inc. All rights reserved. ********************************************************************//* @file osdfb.c See licensing details in LICENSING file */// pch from HWL#include "pch.h"#include "common.h"#include "cquasar.h"#include "regs840x.h"#include "regs847x.h"#include "regs85xx.h"#include <linux/timex.h>#include <linux/autoconf.h>#define PALETTE_ENTRIES 256#define PALETTE_OFFSET 8#define PIXELDATA_OFFSET (8+PALETTE_ENTRIES*4)#define MAXDMAXFER (16*1024)#define OSD_IRQ 14void setpaletteentry (unsigned short R, unsigned short G, unsigned short B, unsigned short alpha, paletteentry *there){ unsigned short y, u, v; there->a = alpha >> 8; vgargbtotvyuv (R, G, B, &y, &u, &v); there->y = y >> 8; there->u = u >> 8; there->v = v >> 8;}void getpaletteentry (unsigned short *pR, unsigned short *pG, unsigned short *pB, unsigned short *palpha,paletteentry *there){ unsigned short y, u, v; *palpha = RANGE8TO16 ((unsigned short)(there->a)); y = RANGE8TO16 ((unsigned short)there->y); u = RANGE8TO16 ((unsigned short)there->u); v = RANGE8TO16 ((unsigned short)there->v); tvyuvtovgargb (y, u, v, pR, pG, pB);}#ifdef HAS_MIREvoid mire(struct quasarprivate *pQ){ // compute small palette { int i; memset(pQ->O.pal,0,PALETTE_ENTRIES*sizeof(paletteentry)); for (i=0;i<64;i++) { pQ->O.pal[i].a=0xff;pQ->O.pal[i].y=i*4; pQ->O.pal[i].u=64;pQ->O.pal[i].v=64; } for (i=0;i<64;i++) { pQ->O.pal[i+64].a=0xff;pQ->O.pal[i+64].y=i*4; pQ->O.pal[i+64].u=64;pQ->O.pal[i+64].v=192; } for (i=0;i<64;i++) { pQ->O.pal[i+128].a=0xff;pQ->O.pal[i+128].y=i*4; pQ->O.pal[i+128].u=192;pQ->O.pal[i+128].v=192; } for (i=0;i<64;i++) { pQ->O.pal[i+192].a=0xff;pQ->O.pal[i+192].y=i*4; pQ->O.pal[i+192].u=192;pQ->O.pal[i+192].v=64; } } // make beautiful image { int x,y; for (x=0;x<pQ->O.width;x++) for (y=0;y<pQ->O.height;y++) pQ->O.videomemory[x+y*pQ->O.width]=(unsigned char)( (x/16)+(y/16)*16 ); } // pQprintk("mire: ready\n");}#endif /* HAS_MIRE */int osdfb_init (struct quasarprivate *pQ, int width, int height){ int i, j; memset (&pQ->O, 0, sizeof (struct osdfbprivate)); pQ->O.width = width; pQ->O.height = height; pQ->O.size = PIXELDATA_OFFSET + pQ->O.width*pQ->O.height; // use hardcoded address pQ->O.buf=pQ->O.mmbuf = (char *)(OSDFB_ADDRESS); memset (pQ->O.buf+PIXELDATA_OFFSET, 0, width*height); if (pQ->O.buf==NULL) { pQprintk ("*osdfb_init: no room left to allocate fb\n"); goto bailout; } pQprintk ("osdfb_init: %dx%d (%d bytes) fb at 0x%08lx\n", pQ->O.width, pQ->O.height, pQ->O.size, (unsigned long)pQ->O.buf); pQ->O.pal = (paletteentry *)(pQ->O.buf + PALETTE_OFFSET); pQ->O.videomemory = pQ->O.buf + PIXELDATA_OFFSET; pQ->O.videomemorysize = pQ->O.size - PIXELDATA_OFFSET; // write osd header pQ->O.buf[0] = 0x3e; pQ->O.buf[1] = pQ->O.size >> 16; pQ->O.buf[2] = pQ->O.size >> 8; pQ->O.buf[3] = pQ->O.size & 0xff; pQ->O.buf[4] = pQ->O.width >> 8; pQ->O.buf[5] = pQ->O.width & 0xff; pQ->O.buf[6] = pQ->O.height >> 8; pQ->O.buf[7] = pQ->O.height & 0xff; // set default general alpha pQ->O.general_alpha = REALMAGICHWL_OSDFB_DEFAULT_GENERAL_ALPHA;#ifdef HAS_MIRE mire(pQ);#endif pQprintk ("osdfb_init: completed.\n"); // can't rmmod when the osdfb is active. MOD_INC_USE_COUNT; return 0; bailout: return -1;}static int osd_lines_per_block=0;static int osd_lines_left=0;static unsigned long osd_block=0;//XXX : Actually not used for now.#if 0static void osdfb_tophalf(int irq, void *dev_t, struct pt_regs * regs){ struct quasarprivate *pQ=(struct quasarprivate *)dev_t; int osd_int_mask, osd_int, osd_int_status; osd_int_mask=IDecoder_ReadReg(pQ->H.pIDecoder, OSD_host_int_mask); osd_int=IDecoder_ReadReg(pQ->H.pIDecoder, OSD_host_int); osd_int_status=IDecoder_ReadReg(pQ->H.pIDecoder, OSD_host_int_status); if(osd_int_status & 0x6) { // overflow or underflow pQprintk("OSD DMA INTERRUPT ERROR: %04x %04x %04x\n", osd_int_mask, osd_int, osd_int_status); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_int, osd_int); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_int_mask, 0); } osd_lines_left-=osd_lines_per_block; if(osd_lines_left>0) { if(osd_lines_left<osd_lines_per_block) osd_lines_per_block=osd_lines_left; // IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_mux_ena, 2); // flush/reset fifo IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_addr_lo, osd_block & 0xffff); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_addr_hi, osd_block >> 16); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_xfer_cnt, pQ->O.width*osd_lines_per_block); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_mux_ena, 1); osd_block+=pQ->O.width*osd_lines_per_block; } else { osd_lines_per_block=0; IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_int_mask, 0x0); } //clear IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_int, osd_int); }#endifvoid osdfb_softreset(struct quasarprivate *pQ){ CQuasar *this = (CQuasar*) pQ->H.pIDecoder; JSymbolTable *pJ = (JSymbolTable*)this->pQ; int i, tmp; /* when run from hwlprivate_hardreset(), the offset can be about anywhere. Resuming on a random offset crashes OSD engine. */ pQ->O.offset = 0; switch (pQ->O.control) { case 1: pQprintk(__FUNCTION__ ": going to uCode OSD control\n"); IDecoder_WriteDM(pQ->H.pIDecoder, pJ->Jasper_OSD_Control.addr, 0); while(osdfb_refresh(pQ)==0); // disable anti-flicker filter { unsigned long flicker; flicker = 0; // 0 <= flicker <= 15 IDecoderBoard_SetProperty(pQ->H.pIDecoderBoard, DECODER_SET, edecOsdFlicker, 0, &flicker, sizeof(DWORD), 0); } if (IDecoderBoard_OsdWriteCommand(pQ->H.pIDecoderBoard, OSD_FLUSH)==Q_OK) { pQprintk("osdfb_cleanup: OSD_FLUSH succeeded\n"); } else { pQprintk("osdfb_cleanup: OSD_FLUSH failed\n"); } IDecoderBoard_FlushPacketsFifo(pQ->H.pIDecoderBoard,OSD,&pQ->H.OsdEventPending); // returns void IDecoderBoard_InitPacketsFifo(pQ->H.pIDecoderBoard,OSD); // returns void pQ->H.OsdByteCounter=0; pQ->H.OsdEventPending=0; if (IDecoderBoard_OsdWriteCommand(pQ->H.pIDecoderBoard, OSD_ON)==Q_OK) { pQprintk("osdfb_softreset: OSD_ON succeeded\n"); } else { pQprintk("osdfb_softreset: OSD_ON failed\n"); } break; case 2: pQprintk(__FUNCTION__ ": going to ARM OSD control\n"); IDecoder_WriteDM(pQ->H.pIDecoder, pJ->Jasper_OSD_Control.addr, 1);//XX : We could do this here... #if 0 request_irq(OSD_IRQ, osdfb_tophalf, SA_SHIRQ, "osd_dma_host", pQ); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_WIDTH, pQ->O.width); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_HEIGHT, pQ->O.height); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_TOP, 40); //(480-pQ->O.height)/2); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_BOT, 240); // (480+pQ->O.height)/2); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_LEFT, 200); // (720-pQ->O.width)/2); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_RIGHT, 750); // (720+pQ->O.width)/2); tmp = IDecoder_ReadReg(pQ->H.pIDecoder, LBC_config); tmp |= (1<<8); IDecoder_WriteReg(pQ->H.pIDecoder, LBC_config, tmp); IDecoder_WriteReg(pQ->H.pIDecoder, OSD_CTRL, 0x1f5a); //enable all osd dma interrupts IDecoder_WriteReg(pQ->H.pIDecoder, OSD_host_int_mask, 0x7); break;#endif default: pQprintk(__FUNCTION__ ": disable OSD (%d)\n", pQ->O.control); pQ->O.active=0; return; } // activate refresh pQ->O.active=1; }static int wait_vsync = 0;// deactivate osdint osdfb_cleanup(struct quasarprivate *pQ){ int i; unsigned short tmp1, tmp2; // stop refresh pQ->O.active=0; switch(pQ->O.control) { case 1: if (IDecoderBoard_OsdWriteCommand(pQ->H.pIDecoderBoard, OSD_OFF)==Q_OK) { pQprintk("osdfb_cleanup: OSD_OFF succeeded\n"); } else { pQprintk("osdfb_cleanup: OSD_OFF failed\n"); } if (IDecoderBoard_OsdWriteCommand(pQ->H.pIDecoderBoard, OSD_FLUSH)==Q_OK) { pQprintk("osdfb_cleanup: OSD_FLUSH succeeded\n"); } else { pQprintk("osdfb_cleanup: OSD_FLUSH failed\n"); } IDecoderBoard_FlushPacketsFifo(pQ->H.pIDecoderBoard,OSD,&pQ->H.OsdEventPending); // returns void IDecoderBoard_InitPacketsFifo(pQ->H.pIDecoderBoard,OSD); // returns void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -