📄 av7110.c
字号:
npids[i] = (pid[i]&0x8000) ? 0 : pid[i]; break; } if (!ret) ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]); return ret;}static int av7110_start_feed(struct dvb_demux_feed *feed){ struct dvb_demux *demux = feed->demux; struct av7110 *av7110 = demux->priv; int ret = 0; dprintk(4, "%p\n", av7110); if (!demux->dmx.frontend) return -EINVAL; if (feed->pid > 0x1fff) return -EINVAL; if (feed->type == DMX_TYPE_TS) { if ((feed->ts_type & TS_DECODER) && (feed->pes_type < DMX_TS_PES_OTHER)) { switch (demux->dmx.frontend->source) { case DMX_MEMORY_FE: if (feed->ts_type & TS_DECODER) if (feed->pes_type < 2 && !(demux->pids[0] & 0x8000) && !(demux->pids[1] & 0x8000)) { dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout); ret = av7110_av_start_play(av7110,RP_AV); if (!ret) demux->playing = 1; } break; default: ret = dvb_feed_start_pid(feed); break; } } else if ((feed->ts_type & TS_PACKET) && (demux->dmx.frontend->source != DMX_MEMORY_FE)) { ret = StartHWFilter(feed->filter); } } else if (feed->type == DMX_TYPE_SEC) { int i; for (i = 0; i < demux->filternum; i++) { if (demux->filter[i].state != DMX_STATE_READY) continue; if (demux->filter[i].type != DMX_TYPE_SEC) continue; if (demux->filter[i].filter.parent != &feed->feed.sec) continue; demux->filter[i].state = DMX_STATE_GO; if (demux->dmx.frontend->source != DMX_MEMORY_FE) { ret = StartHWFilter(&demux->filter[i]); if (ret) break; } } } return ret;}static int av7110_stop_feed(struct dvb_demux_feed *feed){ struct dvb_demux *demux = feed->demux; struct av7110 *av7110 = demux->priv; int i, rc, ret = 0; dprintk(4, "%p\n", av7110); if (feed->type == DMX_TYPE_TS) { if (feed->ts_type & TS_DECODER) { if (feed->pes_type >= DMX_TS_PES_OTHER || !demux->pesfilter[feed->pes_type]) return -EINVAL; demux->pids[feed->pes_type] |= 0x8000; demux->pesfilter[feed->pes_type] = NULL; } if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) { ret = dvb_feed_stop_pid(feed); } else if ((feed->ts_type & TS_PACKET) && (demux->dmx.frontend->source != DMX_MEMORY_FE)) ret = StopHWFilter(feed->filter); } if (!ret && feed->type == DMX_TYPE_SEC) { for (i = 0; i<demux->filternum; i++) { if (demux->filter[i].state == DMX_STATE_GO && demux->filter[i].filter.parent == &feed->feed.sec) { demux->filter[i].state = DMX_STATE_READY; if (demux->dmx.frontend->source != DMX_MEMORY_FE) { rc = StopHWFilter(&demux->filter[i]); if (!ret) ret = rc; /* keep going, stop as many filters as possible */ } } } } return ret;}static void restart_feeds(struct av7110 *av7110){ struct dvb_demux *dvbdmx = &av7110->demux; struct dvb_demux_feed *feed; int mode; int i, j; dprintk(4, "%p\n", av7110); mode = av7110->playing; av7110->playing = 0; av7110->rec_mode = 0; for (i = 0; i < dvbdmx->feednum; i++) { feed = &dvbdmx->feed[i]; if (feed->state == DMX_STATE_GO) { if (feed->type == DMX_TYPE_SEC) { for (j = 0; j < dvbdmx->filternum; j++) { if (dvbdmx->filter[j].type != DMX_TYPE_SEC) continue; if (dvbdmx->filter[j].filter.parent != &feed->feed.sec) continue; if (dvbdmx->filter[j].state == DMX_STATE_GO) dvbdmx->filter[j].state = DMX_STATE_READY; } } av7110_start_feed(feed); } } if (mode) av7110_av_start_play(av7110, mode);}static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, uint64_t *stc, unsigned int *base){ int ret; u16 fwstc[4]; u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC); struct dvb_demux *dvbdemux; struct av7110 *av7110; /* pointer casting paranoia... */ BUG_ON(!demux); dvbdemux = demux->priv; BUG_ON(!dvbdemux); av7110 = dvbdemux->priv; dprintk(4, "%p\n", av7110); if (num != 0) return -EINVAL; ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4); if (ret) { printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__); return ret; } dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n", fwstc[0], fwstc[1], fwstc[2], fwstc[3]); *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) | (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]); *base = 1; dprintk(4, "stc = %lu\n", (unsigned long)*stc); return 0;}/****************************************************************************** * SEC device file operations ******************************************************************************/static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone){ struct av7110* av7110 = fe->dvb->priv; switch (tone) { case SEC_TONE_ON: return Set22K(av7110, 1); case SEC_TONE_OFF: return Set22K(av7110, 0); default: return -EINVAL; }}static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd){ struct av7110* av7110 = fe->dvb->priv; return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);}static int av7110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd){ struct av7110* av7110 = fe->dvb->priv; return av7110_diseqc_send(av7110, 0, NULL, minicmd);}/* simplified code from budget-core.c */static int stop_ts_capture(struct av7110 *budget){ dprintk(2, "budget: %p\n", budget); if (--budget->feeding1) return budget->feeding1; saa7146_write(budget->dev, MC1, MASK_20); /* DMA3 off */ SAA7146_IER_DISABLE(budget->dev, MASK_10); SAA7146_ISR_CLEAR(budget->dev, MASK_10); return 0;}static int start_ts_capture(struct av7110 *budget){ dprintk(2, "budget: %p\n", budget); if (budget->feeding1) return ++budget->feeding1; memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH); budget->tsf = 0xff; budget->ttbp = 0; SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ return ++budget->feeding1;}static int budget_start_feed(struct dvb_demux_feed *feed){ struct dvb_demux *demux = feed->demux; struct av7110 *budget = demux->priv; int status; dprintk(2, "av7110: %p\n", budget); spin_lock(&budget->feedlock1); feed->pusi_seen = 0; /* have a clean section start */ status = start_ts_capture(budget); spin_unlock(&budget->feedlock1); return status;}static int budget_stop_feed(struct dvb_demux_feed *feed){ struct dvb_demux *demux = feed->demux; struct av7110 *budget = demux->priv; int status; dprintk(2, "budget: %p\n", budget); spin_lock(&budget->feedlock1); status = stop_ts_capture(budget); spin_unlock(&budget->feedlock1); return status;}static void vpeirq(unsigned long data){ struct av7110 *budget = (struct av7110 *) data; u8 *mem = (u8 *) (budget->grabbing); u32 olddma = budget->ttbp; u32 newdma = saa7146_read(budget->dev, PCI_VDP3); if (!budgetpatch) { printk("av7110.c: vpeirq() called while budgetpatch disabled!" " check saa7146 IER register\n"); BUG(); } /* nearest lower position divisible by 188 */ newdma -= newdma % 188; if (newdma >= TS_BUFLEN) return; budget->ttbp = newdma; if (!budget->feeding1 || (newdma == olddma)) return; /* Ensure streamed PCI data is synced to CPU */ pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);#if 0 /* track rps1 activity */ printk("vpeirq: %02x Event Counter 1 0x%04x\n", mem[olddma], saa7146_read(budget->dev, EC1R) & 0x3fff);#endif if (newdma > olddma) /* no wraparound, dump olddma..newdma */ dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188); else { /* wraparound, dump olddma..buflen and 0..newdma */ dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188); dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188); }}static int av7110_register(struct av7110 *av7110){ int ret, i; struct dvb_demux *dvbdemux = &av7110->demux; struct dvb_demux *dvbdemux1 = &av7110->demux1; dprintk(4, "%p\n", av7110); if (av7110->registered) return -1; av7110->registered = 1; dvbdemux->priv = (void *) av7110; for (i = 0; i < 32; i++) av7110->handle2filter[i] = NULL; dvbdemux->filternum = 32; dvbdemux->feednum = 32; dvbdemux->start_feed = av7110_start_feed; dvbdemux->stop_feed = av7110_stop_feed; dvbdemux->write_to_decoder = av7110_write_to_decoder; dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); dvb_dmx_init(&av7110->demux); av7110->demux.dmx.get_stc = dvb_get_stc; av7110->dmxdev.filternum = 32; av7110->dmxdev.demux = &dvbdemux->dmx; av7110->dmxdev.capabilities = 0; dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter); av7110->hw_frontend.source = DMX_FRONTEND_0; ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend); if (ret < 0) return ret; av7110->mem_frontend.source = DMX_MEMORY_FE; ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend); if (ret < 0) return ret; ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &av7110->hw_frontend); if (ret < 0) return ret; av7110_av_register(av7110); av7110_ca_register(av7110);#ifdef CONFIG_DVB_AV7110_OSD dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev, &dvbdev_osd, av7110, DVB_DEVICE_OSD);#endif dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); if (budgetpatch) { /* initialize software demux1 without its own frontend * demux1 hardware is connected to frontend0 of demux0 */ dvbdemux1->priv = (void *) av7110; dvbdemux1->filternum = 256; dvbdemux1->feednum = 256; dvbdemux1->start_feed = budget_start_feed; dvbdemux1->stop_feed = budget_stop_feed; dvbdemux1->write_to_decoder = NULL; dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); dvb_dmx_init(&av7110->demux1); av7110->dmxdev1.filternum = 256; av7110->dmxdev1.demux = &dvbdemux1->dmx; av7110->dmxdev1.capabilities = 0; dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter); dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx); printk("dvb-ttpci: additional demux1 for budget-patch registered\n"); } return 0;}static void dvb_unregister(struct av7110 *av7110){ struct dvb_demux *dvbdemux = &av7110->demux; struct dvb_demux *dvbdemux1 = &av7110->demux1; dprintk(4, "%p\n", av7110); if (!av7110->registered) return; if (budgetpatch) { dvb_net_release(&av7110->dvb_net1); dvbdemux->dmx.close(&dvbdemux1->dmx); dvb_dmxdev_release(&av7110->dmxdev1); dvb_dmx_release(&av7110->demux1); } dvb_net_release(&av7110->dvb_net); dvbdemux->dmx.close(&dvbdemux->dmx); dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend); dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend); dvb_dmxdev_release(&av7110->dmxdev); dvb_dmx_release(&av7110->demux); if (av7110->fe != NULL) { dvb_unregister_frontend(av7110->fe); dvb_frontend_detach(av7110->fe); } dvb_unregister_device(av7110->osd_dev); av7110_av_unregister(av7110); av7110_ca_unregister(av7110);}/**************************************************************************** * I2C client commands ****************************************************************************/int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val){ u8 msg[2] = { reg, val }; struct i2c_msg msgs; msgs.flags = 0; msgs.addr = id / 2; msgs.len = 2; msgs.buf = msg; return i2c_transfer(&av7110->i2c_adap, &msgs, 1);}#if 0u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg){ u8 mm1[] = {0x00}; u8 mm2[] = {0x00}; struct i2c_msg msgs[2]; msgs[0].flags = 0; msgs[1].flags = I2C_M_RD;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -