📄 av7110.c
字号:
pwrite=cibuf->pwrite; avail=pwrite-cibuf->pread; if (avail<0) avail+=cibuf->size; if (avail<=2) { iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); break; } len=(cibuf->data[cibuf->pread]<<8); len|=cibuf->data[(cibuf->pread+1)%cibuf->size]; if (avail<len+2) { iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); break; } cibuf->pread=(cibuf->pread+2)%cibuf->size; if (pwrite<cibuf->pread) split=cibuf->size-cibuf->pread; if (split && split<len) { int todo=len-split; memcpy(av7110->debi_virt, cibuf->data+cibuf->pread, split); memcpy(av7110->debi_virt+split, cibuf->data, todo); } else memcpy(av7110->debi_virt, cibuf->data+cibuf->pread, len); cibuf->pread=(cibuf->pread+len)%cibuf->size; wake_up(&cibuf->queue); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); wait_for_debi_done(av7110); saa7146_write(av7110->saa_mem, IER, saa7146_read(av7110->saa_mem, IER) | MASK_19 ); if (len<5) len=5; /* we want a real DEBI DMA */ iwdebi(av7110, DEBISWAB, DPRAM_BASE+txbuf, 0, (len+3)&~3); spin_unlock(&av7110->debilock); return; } case DATA_MPEG_PLAY: if (!av7110->playing) { iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); break; } len=0; if (av7110->debitype&0x100) { spin_lock(&av7110->aout.lock); len=pes_play(av7110->debi_virt, &av7110->aout, 2048); spin_unlock(&av7110->aout.lock); } if (len<=0 && (av7110->debitype&0x200) &&av7110->videostate.play_state!=VIDEO_FREEZED) { spin_lock(&av7110->avout.lock); len=pes_play(av7110->debi_virt, &av7110->avout, 2048); spin_unlock(&av7110->avout.lock); } if (len<=0) { iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); break; } dprintk("GPIO0 PES_PLAY len=%04x\n", len); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); wait_for_debi_done(av7110); saa7146_write(av7110->saa_mem, IER, saa7146_read(av7110->saa_mem, IER) | MASK_19 ); iwdebi(av7110, DEBISWAB, DPRAM_BASE+txbuf, 0, (len+3)&~3); spin_unlock(&av7110->debilock); return; case DATA_BMP_LOAD: len=av7110->debilen; if (!len) { av7110->bmp_state=BMP_LOADED; iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2); iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); wake_up(&av7110->bmpq); break; } if (len>av7110->bmplen) len=av7110->bmplen; if (len>2*1024) len=2*1024; iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len); av7110->bmpp+=len; av7110->bmplen-=len; wait_for_debi_done(av7110); saa7146_write(av7110->saa_mem, IER, saa7146_read(av7110->saa_mem, IER) | MASK_19 ); if (len<5) len=5; /* we want a real DEBI DMA */ iwdebi(av7110, DEBISWAB, DPRAM_BASE+txbuf, 0, (len+3)&~3); spin_unlock(&av7110->debilock); return; case DATA_CI_GET: case DATA_COMMON_INTERFACE: case DATA_FSECTION: case DATA_IPMPE: case DATA_PIPING: if (!len || len>4*1024) { iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; } /* yes, fall through */ case DATA_TS_RECORD: case DATA_PES_RECORD: saa7146_write(av7110->saa_mem, IER, saa7146_read(av7110->saa_mem, IER) | MASK_19); irdebi(av7110, DEBISWAB, DPRAM_BASE+rxbuf, 0, len); spin_unlock(&av7110->debilock); return; case DATA_DEBUG_MESSAGE: if (!len || len>0xff) { iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; } saa7146_write(av7110->saa_mem, IER, saa7146_read(av7110->saa_mem, IER) | MASK_19); irdebi(av7110, DEBISWAB, Reserved, 0, len); spin_unlock(&av7110->debilock); return; case DATA_IRCOMMAND: IR_handle(av7110, swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4))); iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; default: printk("gpioirq unknown type=%d len=%d\n", av7110->debitype, av7110->debilen); break; } ARM_ClearMailBox(av7110); av7110->debitype=-1; spin_unlock(&av7110->debilock); dprintk("GPIO0 irq exit 0\n"); }/**************************************************************************** * DEBI command polling ****************************************************************************/static int OutCommand(av7110_t *av7110, u16* buf, int length){ int i; u32 start;#ifdef COM_DEBUG u32 stat;#endif if (!av7110->arm_ready) return -1; start = jiffies; while ( rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 ) ) { ddelay(1); if ((jiffies - start) > ARM_WAIT_FREE) { printk(KERN_ERR "%s: timeout waiting for COMMAND idle\n", __FUNCTION__); return -1; } }#ifndef _NOHANDSHAKE start = jiffies; while ( rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 ) ) { ddelay(1); if ((jiffies - start) > ARM_WAIT_SHAKE) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); return -1; } }#endif start = jiffies; while ( rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull ) { ddelay(1); if ((jiffies - start) > ARM_WAIT_OSD) { printk(KERN_ERR "%s: timeout waiting for !OSDQFull\n", __FUNCTION__); return -1; } } for (i=2; i<length; i++) wdebi(av7110, DEBINOSWAP, COMMAND + 2*i, (u32) buf[i], 2); if (length) wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2); else wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2); wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);#ifdef COM_DEBUG start = jiffies; while ( rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 ) ) { ddelay(1); if ((jiffies - start) > ARM_WAIT_FREE) { printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); return -1; } } stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & GPMQOver) { printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__); return -1; } else if (stat & OSDQOver) { printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__); return -1; }#endif return 0;}inline static int SOutCommand(av7110_t *av7110, u16* buf, int length){ int ret; if (!av7110->arm_ready) return -1; if (down_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; ret=OutCommand(av7110, buf, length); up(&av7110->dcomlock); if (ret) printk("SOutCommand error\n"); return ret;}static int outcom(av7110_t *av7110, int type, int com, int num, ...){ va_list args; u16 buf[num+2]; int i, ret; buf[0]=(( type << 8 ) | com); buf[1]=num; if (num) { va_start(args, num); for (i=0; i<num; i++) buf[i+2]=va_arg(args, u32); va_end(args); } ret = SOutCommand(av7110, buf, num+2); if (ret) printk("outcom error\n"); return ret;}int SendCICommand(av7110_t *av7110, u8 subcom, u8 *Params, u8 ParamLen){ int i, ret; u16 CommandBuffer[18] = { ((COMTYPE_COMMON_IF << 8) + subcom), 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; for(i=0; (i<ParamLen)&&(i<32); i++) { if(i%2 == 0) CommandBuffer[(i/2)+2] = (u16)(Params[i]) << 8; else CommandBuffer[(i/2)+2] |= Params[i]; } ret = SOutCommand(av7110, CommandBuffer, 18); if (ret) printk("SendCICommand error\n"); return ret;}static int CommandRequest(av7110_t *av7110, u16 *Buff, int length, u16 *buf, int n){ int err; s16 i; u32 start;#ifdef COM_DEBUG u32 stat;#endif if (!av7110->arm_ready) return -1; if (down_interruptible(&av7110->dcomlock)) return -ERESTARTSYS; if ((err = OutCommand(av7110, Buff, length)) < 0) { up(&av7110->dcomlock); printk("CommandRequest error\n"); return err; } start = jiffies; while ( rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) ) {#ifdef _NOHANDSHAKE ddelay(1);#endif if ((jiffies - start) > ARM_WAIT_FREE) { printk("%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); up(&av7110->dcomlock); return -1; } }#ifndef _NOHANDSHAKE start = jiffies; while ( rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 ) ) { ddelay(1); if ((jiffies - start) > ARM_WAIT_SHAKE) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); up(&av7110->dcomlock); return -1; } }#endif#ifdef COM_DEBUG stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & GPMQOver) { printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__); up(&av7110->dcomlock); return -1; } else if (stat & OSDQOver) { printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__); up(&av7110->dcomlock); return -1; }#endif for (i=0; i<n; i++) buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2*i, 0, 2); up(&av7110->dcomlock); return 0;}static inline int RequestParameter(av7110_t *av7110, u16 tag, u16* Buff, s16 length){ int ret; ret = CommandRequest(av7110, &tag, 0, Buff, length); if (ret) printk("RequestParameter error\n"); return ret;}/**************************************************************************** * Firmware commands ****************************************************************************/inline static int SendDAC(av7110_t *av7110, u8 addr, u8 data){ return outcom(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data);}static intSetVolume(av7110_t *av7110, int volleft, int volright){ int err=0; int chleft, chright, vol, val, balance = 0; switch (av7110->adac_type) { case DVB_ADAC_TI: chleft = (volleft * 256) / 1036; chright = (volright * 256) / 1036; if (chleft > 0x3f) chleft = 0x3f; if (chright > 0x3f) chright=0x3f; if ((err = SendDAC(av7110, 3, 0x80 + chleft))) return err; err=SendDAC(av7110, 4, chright); break; case DVB_ADAC_CRYSTAL: chleft=127-volleft/2; chright=127-volright/2; i2c_writereg(av7110, 0x20, 0x03, chleft); i2c_writereg(av7110, 0x20, 0x04, chright); break; case DVB_ADAC_MSP: vol = (volleft > volright) ? volleft : volright; val = (vol * 0x73 / 255) << 8; if (vol > 0) { balance = ((volright-volleft) * 127) / vol; } msp_writereg(av7110, 0x12, 0x0001, balance << 8); msp_writereg(av7110, 0x12, 0x0000, val); /* loudspeaker */ msp_writereg(av7110, 0x12, 0x0006, val); /* headphonesr */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -