📄 hwlprivate.c
字号:
/******************************************************************** Copyright (c) 2002 Sigma Designs Inc. All rights reserved. ********************************************************************//* @file hwlprivate.c See licensing details in LICENSING file */// pch from HWL#include "pch.h"#include "registry.h"#include "regs840x.h"#include "common.h"#include "cqsrbrd.h"// debugunsigned long hw_video_byte_counter;unsigned long hw_audio_byte_counter;//// ac3 frame sizeDWORD frmsizecod_table[4][38] = { // 48 {64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192, 224, 224, 256, 256, 320, 320, 384, 384, 448, 448, 512, 512, 640, 640, 768, 768, 896, 896, 1024, 1024, 1152, 1152, 1280, 1280}, // 44.1 {69, 70, 87, 88, 104, 105, 121, 122, 139, 140, 174, 175, 208, 209, 243, 244, 278, 279, 348, 349, 417, 418, 487, 488, 557, 558, 696, 697, 835, 836, 975, 976, 1114, 1115, 1253, 1254, 1393, 1394}, // 32 {96, 96, 120, 120, 144, 144, 168, 168, 192, 192, 240, 240, 288, 288, 336, 336, 384, 384, 480, 480, 576, 576, 672, 672, 768, 768, 960, 960, 1152, 1152, 1344, 1344, 1536, 1536, 1728, 1728, 1920, 1920}, //reserved - default to 48 {64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192, 224, 224, 256, 256, 320, 320, 384, 384, 448, 448, 512, 512, 640, 640, 768, 768, 896, 896, 1024, 1024, 1152, 1152, 1280, 1280},};//#define VERBOSE 1//#define VERBOSE_2 1//XXX#define MPEG_IRQMASK (CC_INTERRUPT | VSYNC_INTERRUPT | AUDIO_FIFO_THRESHOLD | VIDEO_FIFO_THRESHOLD | VIDEO_END_OF_SEQUENCE | OSD_INTERRUPT)////// FIXME#define INTENA_REG (*(volatile int *)0x00500224)#define INTPOL_REG (*(volatile int *)0x00500220)static inline void disable_quasar_irq(){ int reg; reg = INTENA_REG; reg &= ~(1<<QUASAR_IRQ(&Q)); INTENA_REG = reg; }static inline void enable_quasar_irq(){ int reg; reg = INTENA_REG; reg |= (1<<QUASAR_IRQ(&Q)); INTENA_REG = reg; }// Lock and Unlock Quasar Interrupts#define QLOCK() disable_quasar_irq();#define QUNLOCK() enable_quasar_irq();/////// static feedpacket *getFeedPacket(FeedPacketQ *pQ){#ifdef VERBOSE// if(pQ->pFirstPacket)// pQprintk("getFeedPacket: Q=%p packet = %p\n",pQ, pQ->pFirstPacket);#endif return pQ->pFirstPacket;}static void nextFeedPacket(FeedPacketQ *pQ){ feedpacket *pP=pQ->pFirstPacket;#ifdef VERBOSE if(pP) pQprintk("nextFeedPacket: Q=%p, packet = %p\n",pQ,pP);#endif // Used Q is empty do nothing if(pP==NULL) {#ifdef VERBOSE pQprintk("Q %p is empty\n",pQ);#endif return; } // advance Used Q to next pQ->pFirstPacket=pP->pNext;#ifdef QUEUES_STAT pQ->nb--; pQ->nb_out++; pFreeQ->nb++; pFreeQ->nb_in++;#endif // Used Q is empty now ? if(pP->pNext==NULL) {#ifdef VERBOSE pQprintk("Last packet in Q %p\n",pQ);#endif pQ->pLastPacket=NULL; } // Free Q is empty ? if((pFreeQ->pLastPacket)==NULL) pFreeQ->pFirstPacket=pP; else pFreeQ->pLastPacket->pNext=pP; pFreeQ->pLastPacket=pP; pP->pNext=NULL;}//int apts_counter = 0;//int vpts_counter = 0;static void hwlprivate_tophalf(int irq, void *dev_t, struct pt_regs * regs){ /* THIS FUNCTION IS TIME CRITICAL AND FREEZES THE PC UNTIL IT RETURNS. Don't access user space (we are not called from a process) Don't call schedule() Don't sleep Don't kmalloc anything else than GFP_ATOMIC Don't use semaphores. We should: "Do the fewest things possible. Implement everything else in hwlprivate_tasklet." But we don't! It shouldnt be a problem for Jasper DVD player. Sorry Manu :) - Fabrice */ struct quasarprivate *pQ=(struct quasarprivate *)dev_t; int osd_image_completed; DWORD IrqStatus; feedpacket *pP;#if 0//XXX REMOVE if(pQ->H.pIDecoderBoard->lpVtbl == NULL ) { pQprintk("Error : IDecoderBaord->lpVtbl is NULL\n"); asm(".long 0x66727473\n"); return; }//XXX REMOVE if(irq!=21) pQprintk("ERORR the IRQ is not 21!!\n");#endif // shared irq case: we return - shouldnt happen with JASPER. if (IDecoderBoard_IsIntActive(pQ->H.pIDecoderBoard,&IrqStatus)==FALSE) { printk ("hwl_tophalf: Spurious IRQ - is it shared??\n" "pIDecoderBoard = %p\n&IsIntActive = %p)\n", pQ->H.pIDecoderBoard, pQ->H.pIDecoderBoard->lpVtbl->IsIntActive); return; }#ifdef VERBOSE// pQprintk("Received Quasar interrupt: status = %08x\n",IrqStatus);#endif if (IrqStatus & CC_INTERRUPT) IDecoderBoard_CloseCaptionInterrupt (pQ->H.pIDecoderBoard, 0); if (IrqStatus & VIDEO_END_OF_SEQUENCE) { //printk ("!!!!! VIDEO_END_OF_SEQUENCE: %d\n", pQ->out_display_option); if (pQ->out_display_option == evOutDisplayOption_16x9to4x3_PanScan) { CQuasar *this = (CQuasar*)pQ->H.pIDecoder; Q4SymbolTable *pQ4 = (Q4SymbolTable*)this->pQ; if (pQ4) { //printk ("!!!!! set to 540\n"); IDecoder_WriteDM (pQ->H.pIDecoder, pQ4->DisplayHorSize.addr, 540); } } }/* if (IrqStatus & VIDEO_EVENT_PAUSE) { printk ("VIDEO_EVENT_PAUSE\n"); IDecoderBoard_VideoHwPause (pQ->H.pIDecoderBoard); }*//* if (IrqStatus & VIDEO_FIFO_THRESHOLD) { if (pQ->callingProcessPid!=0) kill_proc(pQ->callingProcessPid,SIGUSR2,0); } if (IrqStatus & AUDIO_FIFO_THRESHOLD) { if (pQ->callingProcessPid!=0) kill_proc(pQ->callingProcessPid,SIGUSR2,0); }*/#if 0 if (IrqStatus & (VIDEO_FIFO_THRESHOLD | AUDIO_FIFO_THRESHOLD /*| VSYNC_INTERRUPT*/)) { feedpacket *pP; DATA_FIFO vfifo, afifo;/* if ((IrqStatus & AUDIO_FIFO_THRESHOLD) && (pQ->H.AudioByteCounter > 1000000)) { IDecoderBoard_GetDataFifoInfo (pQ->H.pIDecoderBoard, AUDIO, &afifo); if (getFeedPacket(pAudioQ) == NULL) printk ("***** (PRE) audioQ is empty!\n"); } if ((IrqStatus & VIDEO_FIFO_THRESHOLD) && (pQ->H.VideoByteCounter > 3000000)) { IDecoderBoard_GetDataFifoInfo (pQ->H.pIDecoderBoard, VIDEO, &vfifo); if (getFeedPacket(pVideoQ) == NULL) printk ("***** (PRE) videoQ is empty!\n"); }*/ IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, VIDEO, &pQ->H.VideoEventPending); IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, AUDIO, &pQ->H.AudioEventPending); IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, SPU, &pQ->H.SpuEventPending); // Try to send all Q'ed packets while(((pP=getFeedPacket(pVideoQ))!=NULL) && (hwlprivate_feedme(pQ,pP)==0)) nextFeedPacket(pVideoQ); while(((pP=getFeedPacket(pAudioQ))!=NULL) && (hwlprivate_feedme(pQ,pP)==0)) nextFeedPacket(pAudioQ); while(((pP=getFeedPacket(pSpuQ))!=NULL) && (hwlprivate_feedme(pQ,pP)==0)) nextFeedPacket(pSpuQ); if (1) { IDecoderBoard_GetDataFifoInfo (pQ->H.pIDecoderBoard, VIDEO, &vfifo); IDecoderBoard_GetDataFifoInfo (pQ->H.pIDecoderBoard, AUDIO, &afifo); if ((vfifo.Fullness == 0) || (afifo.Fullness == 0)) { if (pQ->H.AudioByteCounter && (getFeedPacket(pAudioQ) == NULL)) { printk ("***** (POST) audioQ is empty! (%d)\n", (int)afifo.Fullness); } if (pQ->H.VideoByteCounter && (getFeedPacket(pVideoQ) == NULL)) { printk ("***** (POST) videoQ is empty! (%d)\n", (int)vfifo.Fullness); } } } }#endif pQ->interrupt_counter++; // update read/write pointers if (IrqStatus & VSYNC_INTERRUPT) { IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, VIDEO, &pQ->H.VideoEventPending); IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, AUDIO, &pQ->H.AudioEventPending); IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, SUBPICTURE, &pQ->H.SpuEventPending); IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, OSD, &pQ->H.OsdEventPending); while(((pP=getFeedPacket(pSpuQ))!=NULL) && (hwlprivate_feedme(pQ,pP)==0)) nextFeedPacket(pSpuQ); } if (IrqStatus & VIDEO_FIFO_THRESHOLD) { while(((pP=getFeedPacket(pVideoQ))!=NULL) && (hwlprivate_feedme(pQ,pP)==0)) nextFeedPacket(pVideoQ); } if (IrqStatus & AUDIO_FIFO_THRESHOLD) { while(((pP=getFeedPacket(pAudioQ))!=NULL) && (hwlprivate_feedme(pQ,pP)==0)) nextFeedPacket(pAudioQ); } // XXX vincent - must call refresh all the time // when we are paused, the threshold interrupts will not come osd_image_completed = 0; if (IrqStatus & VSYNC_INTERRUPT) { // automatic refresh if (pQ->O.active) { osd_image_completed = osdfb_refresh (pQ); } else { osd_image_completed = 1; } // manual refresh if (pQ->H.osd_wait && pQ->H.osdleft) { int xfer; MPEG_WRITE_DATA MWD; BOOL rc; while (1) { MWD.pOverlapped = 0; MWD.pPacketList = 0; MWD.uiPacketCount = 0; MWD.uiPacketIndex = 0; MWD.pData = pQ->H.posd; xfer = min ((int)pQ->H.osdleft, (int)0xf000); rc = IDecoderBoard_SendOSDPayload (pQ->H.pIDecoderBoard, &MWD, (unsigned long)xfer, 0, 0, &pQ->H.OsdByteCounter, &pQ->H.OsdEventPending); if (rc == TRUE) { pQ->H.posd += xfer; pQ->H.osdleft -= xfer; } else break; } } } if (IrqStatus & OSD_INTERRUPT) { if (pQ->H.osd_wait) { ASSERT (pQ->H.osdleft == 0); complete (pQ->H.osd_wait); pQ->H.osd_wait = 0; } } if (osd_image_completed) { // this means that one osd picture has been sent // complete any pending SetProperty commands if (pQ->destination_pending) {// printk ("(%d %d %d %d)\n",// pQ->destination_wnd.x,// pQ->destination_wnd.y,// pQ->destination_wnd.w,// pQ->destination_wnd.h); IDecoderBoard_SetProperty ( pQ->H.pIDecoderBoard, VIDEO_SET, evDestinationWindow, 0, &pQ->destination_wnd, sizeof(pQ->destination_wnd), 0); pQ->destination_pending = 0; } if (pQ->aspect_pending) { IDecoderBoard_SetProperty ( pQ->H.pIDecoderBoard, VIDEO_SET, evInAspectRatio, 0, &pQ->in_aspect_ratio, sizeof(pQ->in_aspect_ratio), 0); pQ->aspect_pending = 0; } if (pQ->display_pending) { IDecoderBoard_SetProperty ( pQ->H.pIDecoderBoard, VIDEO_SET, evOutDisplayOption, 0, &pQ->out_display_option, sizeof(pQ->out_display_option), 0); pQ->display_pending = 0; } if (pQ->osd_destination_pending) { IDecoderBoard_SetProperty ( pQ->H.pIDecoderBoard, OSD_SET, eOsdDestinationWindow, 0, &pQ->osd_destination_wnd, sizeof(pQ->osd_destination_wnd), 0); pQ->osd_destination_pending = 0; } if (pQ->forced_progressive_pending) { IDecoderBoard_SetProperty ( pQ->H.pIDecoderBoard, VIDEO_SET, evForcedProgressiveAlways, 0, &pQ->forced_progressive, sizeof(pQ->forced_progressive), 0); pQ->forced_progressive_pending = 0; } if (pQ->play_pending) { DWORD vr, vl, v; if ((PLAY_OPTIONS)pQ->play_mode != VideoHwPlayToEvent) { IDecoderBoard_AudioHwPlay(pQ->H.pIDecoderBoard); } IDecoderBoard_VideoHwPlay(pQ->H.pIDecoderBoard, (PLAY_OPTIONS)(pQ->play_mode), 1); pQ->play_pending = 0; // XXX vincent: patch to unmute the audio // sometimes the audio gain register is muted after a PLAY? v = IDecoder_ReadReg (pQ->H.pIDecoder, 0x1FD7); vr = IDecoder_GetVolumeRight (pQ->H.pIDecoder); vl = IDecoder_GetVolumeLeft (pQ->H.pIDecoder); if ((v == 0) && (vr || vl)) {#ifdef VERBOSE //XXX pQprintk("[%d]Warning: audio muted... unmuting!!!\n", (int)pQ->interrupt_counter);#endif IDecoder_SetVolumeRight (pQ->H.pIDecoder, vr); IDecoder_SetVolumeLeft (pQ->H.pIDecoder, vl); } else {#ifdef VERBOSE pQprintk("[%d]Warning: audio not muted... OK!!!\n", pQ->interrupt_counter);#endif } } } //XXX audio auto mute counter measures // sometime the audio gain register goes mute { DWORD vr, vl, v; v = IDecoder_ReadReg (pQ->H.pIDecoder, 0x1FD7); vr = IDecoder_GetVolumeRight (pQ->H.pIDecoder);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -