📄 av7110.c
字号:
txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); len = (av7110->debilen + 3) & ~3; print_time("gpio"); dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen); switch (av7110->debitype & 0xff) { case DATA_TS_PLAY: case DATA_PES_PLAY: break; case DATA_MPEG_VIDEO_EVENT: { u32 h_ar; struct video_event event; av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2); h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); av7110->video_size.h = h_ar & 0xfff; dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", av7110->video_size.w, av7110->video_size.h, av7110->video_size.aspect_ratio); event.type = VIDEO_EVENT_SIZE_CHANGED; event.u.size.w = av7110->video_size.w; event.u.size.h = av7110->video_size.h; switch ((h_ar >> 12) & 0xf) { case 3: av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9; event.u.size.aspect_ratio = VIDEO_FORMAT_16_9; av7110->videostate.video_format = VIDEO_FORMAT_16_9; break; case 4: av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1; event.u.size.aspect_ratio = VIDEO_FORMAT_221_1; av7110->videostate.video_format = VIDEO_FORMAT_221_1; break; default: av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3; event.u.size.aspect_ratio = VIDEO_FORMAT_4_3; av7110->videostate.video_format = VIDEO_FORMAT_4_3; } dvb_video_add_event(av7110, &event); break; } case DATA_CI_PUT: { int avail; struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer; avail = dvb_ringbuffer_avail(cibuf); 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 = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8; len |= DVB_RINGBUFFER_PEEK(cibuf, 1); 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; } DVB_RINGBUFFER_SKIP(cibuf, 2); dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); dprintk(8, "DMA: CI\n"); start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len); spin_unlock(&av7110->debilock); wake_up(&cibuf->queue); 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 = av7110_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 = av7110_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(8, "GPIO0 PES_PLAY len=%04x\n", len); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); dprintk(8, "DMA: MPEG_PLAY\n"); start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len); spin_unlock(&av7110->debilock); return; case DATA_BMP_LOAD: len = av7110->debilen; dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len); 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); dprintk(8, "gpio DATA_BMP_LOAD done\n"); 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; dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len); start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len); 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; } /* fall through */ case DATA_TS_RECORD: case DATA_PES_RECORD: dprintk(8, "DMA: TS_REC etc.\n"); start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len); spin_unlock(&av7110->debilock); return; case DATA_DEBUG_MESSAGE: if (!len || len > 0xff) { iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; } start_debi_dma(av7110, DEBI_READ, Reserved, len); spin_unlock(&av7110->debilock); return; case DATA_IRCOMMAND: if (av7110->ir_handler) av7110->ir_handler(av7110, swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4))); iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; default: printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n", av7110->debitype, av7110->debilen); break; } av7110->debitype = -1; ARM_ClearMailBox(av7110); spin_unlock(&av7110->debilock);}#ifdef CONFIG_DVB_AV7110_OSDstatic int dvb_osd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg){ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; dprintk(4, "%p\n", av7110); if (cmd == OSD_SEND_CMD) return av7110_osd_cmd(av7110, (osd_cmd_t *) parg); if (cmd == OSD_GET_CAPABILITY) return av7110_osd_capability(av7110, (osd_cap_t *) parg); return -EINVAL;}static struct file_operations dvb_osd_fops = { .owner = THIS_MODULE, .ioctl = dvb_generic_ioctl, .open = dvb_generic_open, .release = dvb_generic_release,};static struct dvb_device dvbdev_osd = { .priv = NULL, .users = 1, .writers = 1, .fops = &dvb_osd_fops, .kernel_ioctl = dvb_osd_ioctl,};#endif /* CONFIG_DVB_AV7110_OSD */static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid){ dprintk(4, "%p\n", av7110); if (vpid == 0x1fff || apid == 0x1fff || ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) { vpid = apid = ttpid = subpid = pcrpid = 0; av7110->pids[DMX_PES_VIDEO] = 0; av7110->pids[DMX_PES_AUDIO] = 0; av7110->pids[DMX_PES_TELETEXT] = 0; av7110->pids[DMX_PES_PCR] = 0; } return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 5, pcrpid, vpid, apid, ttpid, subpid);}int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid){ int ret = 0; dprintk(4, "%p\n", av7110); if (down_interruptible(&av7110->pid_mutex)) return -ERESTARTSYS; if (!(vpid & 0x8000)) av7110->pids[DMX_PES_VIDEO] = vpid; if (!(apid & 0x8000)) av7110->pids[DMX_PES_AUDIO] = apid; if (!(ttpid & 0x8000)) av7110->pids[DMX_PES_TELETEXT] = ttpid; if (!(pcrpid & 0x8000)) av7110->pids[DMX_PES_PCR] = pcrpid; av7110->pids[DMX_PES_SUBTITLE] = 0; if (av7110->fe_synced) { pcrpid = av7110->pids[DMX_PES_PCR]; ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid); } up(&av7110->pid_mutex); return ret;}/****************************************************************************** * hardware filter functions ******************************************************************************/static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter){ struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed; struct av7110 *av7110 = (struct av7110 *) dvbdmxfeed->demux->priv; u16 buf[20]; int ret, i; u16 handle;// u16 mode = 0x0320; u16 mode = 0xb96a; dprintk(4, "%p\n", av7110); if (dvbdmxfilter->type == DMX_TYPE_SEC) { if (hw_sections) { buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) | dvbdmxfilter->maskandmode[0]; for (i = 3; i < 18; i++) buf[i + 4 - 2] = (dvbdmxfilter->filter.filter_value[i] << 8) | dvbdmxfilter->maskandmode[i]; mode = 4; } } else if ((dvbdmxfeed->ts_type & TS_PACKET) && !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) { av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed); } buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter; buf[1] = 16; buf[2] = dvbdmxfeed->pid; buf[3] = mode; ret = av7110_fw_request(av7110, buf, 20, &handle, 1); if (ret != 0 || handle >= 32) { printk("dvb-ttpci: %s error buf %04x %04x %04x %04x " "ret %d handle %04x\n", __FUNCTION__, buf[0], buf[1], buf[2], buf[3], ret, handle); dvbdmxfilter->hw_handle = 0xffff; if (!ret) ret = -1; return ret; } av7110->handle2filter[handle] = dvbdmxfilter; dvbdmxfilter->hw_handle = handle; return ret;}static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter){ struct av7110 *av7110 = (struct av7110 *) dvbdmxfilter->feed->demux->priv; u16 buf[3]; u16 answ[2]; int ret; u16 handle; dprintk(4, "%p\n", av7110); handle = dvbdmxfilter->hw_handle; if (handle >= 32) { printk("%s tried to stop invalid filter %04x, filter type = %x\n", __FUNCTION__, handle, dvbdmxfilter->type); return -EINVAL; } av7110->handle2filter[handle] = NULL; buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter; buf[1] = 1; buf[2] = handle; ret = av7110_fw_request(av7110, buf, 3, answ, 2); if (ret != 0 || answ[1] != handle) { printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x " "resp %04x %04x pid %d\n", __FUNCTION__, buf[0], buf[1], buf[2], ret, answ[0], answ[1], dvbdmxfilter->feed->pid); if (!ret) ret = -1; } return ret;}static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed){ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv; u16 *pid = dvbdmx->pids, npids[5]; int i; int ret = 0; dprintk(4, "%p\n", av7110); npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff; i = dvbdmxfeed->pes_type; npids[i] = (pid[i]&0x8000) ? 0 : pid[i]; if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) { npids[i] = 0; ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]); if (!ret) ret = StartHWFilter(dvbdmxfeed->filter); return ret; } if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) { ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]); if (ret) return ret; } if (dvbdmxfeed->pes_type < 2 && npids[0]) if (av7110->fe_synced) { ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0); if (ret) return ret; } if ((dvbdmxfeed->ts_type & TS_PACKET)) { if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000)) ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed); if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000)) ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed); } return ret;}static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed){ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv; u16 *pid = dvbdmx->pids, npids[5]; int i; int ret = 0; dprintk(4, "%p\n", av7110); if (dvbdmxfeed->pes_type <= 1) { ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO); if (ret) return ret; if (!av7110->rec_mode) dvbdmx->recording = 0; if (!av7110->playing) dvbdmx->playing = 0; } npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff; i = dvbdmxfeed->pes_type; switch (i) { case 2: //teletext if (dvbdmxfeed->ts_type & TS_PACKET) ret = StopHWFilter(dvbdmxfeed->filter); npids[2] = 0; break; case 0: case 1: case 4: if (!pids_off) return 0; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -