📄 dvb-ttusb-budget.c
字号:
numstuff++;}static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len){ int maxwork = 1024; while (len) { if (!(maxwork--)) { printk("%s: too much work\n", __FUNCTION__); break; } switch (ttusb->mux_state) { case 0: case 1: case 2: len--; if (*data++ == 0xAA) ++ttusb->mux_state; else { ttusb->mux_state = 0;#if DEBUG > 3 if (ttusb->insync) printk("%02x ", data[-1]);#else if (ttusb->insync) { printk("%s: lost sync.\n", __FUNCTION__); ttusb->insync = 0; }#endif } break; case 3: ttusb->insync = 1; len--; ttusb->mux_npacks = *data++; ++ttusb->mux_state; ttusb->muxpack_ptr = 0; /* maximum bytes, until we know the length */ ttusb->muxpack_len = 2; break; case 4: { int avail; avail = len; if (avail > (ttusb->muxpack_len - ttusb->muxpack_ptr)) avail = ttusb->muxpack_len - ttusb->muxpack_ptr; memcpy(ttusb->muxpack + ttusb->muxpack_ptr, data, avail); ttusb->muxpack_ptr += avail; BUG_ON(ttusb->muxpack_ptr > 264); data += avail; len -= avail; /* determine length */ if (ttusb->muxpack_ptr == 2) { if (ttusb->muxpack[0] & 0x80) { ttusb->muxpack_len = ttusb->muxpack[1] + 2; if (ttusb-> muxpack[0] & 0x20) ttusb-> muxpack_len++; if ((!! (ttusb-> muxpack[0] & 0x20)) ^ !!(ttusb-> muxpack[1] & 1)) ttusb-> muxpack_len++; ttusb->muxpack_len += 4; } else if (ttusb->muxpack[0] == 0x47) ttusb->muxpack_len = 188 + 4; else if (ttusb->muxpack[0] == 0x00) ttusb->muxpack_len = ttusb->muxpack[1] + 2 + 4; else { dprintk ("%s: invalid state: first byte is %x\n", __FUNCTION__, ttusb->muxpack[0]); ttusb->mux_state = 0; } } /** * if length is valid and we reached the end: * goto next muxpack */ if ((ttusb->muxpack_ptr >= 2) && (ttusb->muxpack_ptr == ttusb->muxpack_len)) { ttusb_process_muxpack(ttusb, ttusb-> muxpack, ttusb-> muxpack_ptr); ttusb->muxpack_ptr = 0; /* maximum bytes, until we know the length */ ttusb->muxpack_len = 2; /** * no muxpacks left? * return to search-sync state */ if (!ttusb->mux_npacks--) { ttusb->mux_state = 0; break; } } break; } default: BUG(); break; } }}static void ttusb_iso_irq(struct urb *urb){ struct ttusb *ttusb = urb->context; if (!ttusb->iso_streaming) return;#if 0 printk("%s: status %d, errcount == %d, length == %i\n", __FUNCTION__, urb->status, urb->error_count, urb->actual_length);#endif if (!urb->status) { int i; for (i = 0; i < urb->number_of_packets; ++i) { struct usb_iso_packet_descriptor *d; u8 *data; int len; numpkt++; if (time_after_eq(jiffies, lastj + HZ)) {#if DEBUG > 2 printk ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n", numpkt * HZ / (jiffies - lastj), numts, numstuff, numsec, numinvalid, numts + numstuff + numsec + numinvalid);#endif numts = numstuff = numsec = numinvalid = 0; lastj = jiffies; numpkt = 0; } d = &urb->iso_frame_desc[i]; data = urb->transfer_buffer + d->offset; len = d->actual_length; d->actual_length = 0; d->status = 0; ttusb_process_frame(ttusb, data, len); } } usb_submit_urb(urb, GFP_ATOMIC);}static void ttusb_free_iso_urbs(struct ttusb *ttusb){ int i; for (i = 0; i < ISO_BUF_COUNT; i++) if (ttusb->iso_urb[i]) usb_free_urb(ttusb->iso_urb[i]); pci_free_consistent(NULL, ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT, ttusb->iso_buffer, ttusb->iso_dma_handle);}static int ttusb_alloc_iso_urbs(struct ttusb *ttusb){ int i; ttusb->iso_buffer = pci_alloc_consistent(NULL, ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT, &ttusb->iso_dma_handle); memset(ttusb->iso_buffer, 0, ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT); for (i = 0; i < ISO_BUF_COUNT; i++) { struct urb *urb; if (! (urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) { ttusb_free_iso_urbs(ttusb); return -ENOMEM; } ttusb->iso_urb[i] = urb; } return 0;}static void ttusb_stop_iso_xfer(struct ttusb *ttusb){ int i; for (i = 0; i < ISO_BUF_COUNT; i++) usb_kill_urb(ttusb->iso_urb[i]); ttusb->iso_streaming = 0;}static int ttusb_start_iso_xfer(struct ttusb *ttusb){ int i, j, err, buffer_offset = 0; if (ttusb->iso_streaming) { printk("%s: iso xfer already running!\n", __FUNCTION__); return 0; } ttusb->cc = -1; ttusb->insync = 0; ttusb->mux_state = 0; for (i = 0; i < ISO_BUF_COUNT; i++) { int frame_offset = 0; struct urb *urb = ttusb->iso_urb[i]; urb->dev = ttusb->dev; urb->context = ttusb; urb->complete = ttusb_iso_irq; urb->pipe = ttusb->isoc_in_pipe; urb->transfer_flags = URB_ISO_ASAP; urb->interval = 1; urb->number_of_packets = FRAMES_PER_ISO_BUF; urb->transfer_buffer_length = ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF; urb->transfer_buffer = ttusb->iso_buffer + buffer_offset; buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF; for (j = 0; j < FRAMES_PER_ISO_BUF; j++) { urb->iso_frame_desc[j].offset = frame_offset; urb->iso_frame_desc[j].length = ISO_FRAME_SIZE; frame_offset += ISO_FRAME_SIZE; } } for (i = 0; i < ISO_BUF_COUNT; i++) { if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_ATOMIC))) { ttusb_stop_iso_xfer(ttusb); printk ("%s: failed urb submission (%i: err = %i)!\n", __FUNCTION__, i, err); return err; } } ttusb->iso_streaming = 1; return 0;}#ifdef TTUSB_HWSECTIONSstatic void ttusb_handle_ts_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data, int len){ dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);}static void ttusb_handle_sec_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data, int len){// struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;#error TODO: handle ugly stuff// dvbdmxfeed->cb.sec(data, len, 0, 0, &dvbdmxfeed->feed.sec, 0);}#endifstatic int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed){ struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux; int feed_type = 1; dprintk("ttusb_start_feed\n"); switch (dvbdmxfeed->type) { case DMX_TYPE_TS: break; case DMX_TYPE_SEC: break; default: return -EINVAL; } if (dvbdmxfeed->type == DMX_TYPE_TS) { switch (dvbdmxfeed->pes_type) { case DMX_TS_PES_VIDEO: case DMX_TS_PES_AUDIO: case DMX_TS_PES_TELETEXT: case DMX_TS_PES_PCR: case DMX_TS_PES_OTHER: break; default: return -EINVAL; } }#ifdef TTUSB_HWSECTIONS#error TODO: allocate filters if (dvbdmxfeed->type == DMX_TYPE_TS) { feed_type = 1; } else if (dvbdmxfeed->type == DMX_TYPE_SEC) { feed_type = 2; }#endif ttusb_set_channel(ttusb, dvbdmxfeed->index, feed_type, dvbdmxfeed->pid); if (0 == ttusb->running_feed_count++) ttusb_start_iso_xfer(ttusb); return 0;}static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed){ struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux; ttusb_del_channel(ttusb, dvbdmxfeed->index); if (--ttusb->running_feed_count == 0) ttusb_stop_iso_xfer(ttusb); return 0;}static int ttusb_setup_interfaces(struct ttusb *ttusb){ usb_set_interface(ttusb->dev, 1, 1); ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1); ttusb->bulk_in_pipe = usb_rcvbulkpipe(ttusb->dev, 1); ttusb->isoc_in_pipe = usb_rcvisocpipe(ttusb->dev, 2); return 0;}#if 0static u8 stc_firmware[8192];static int stc_open(struct inode *inode, struct file *file){ struct ttusb *ttusb = file->private_data; int addr; for (addr = 0; addr < 8192; addr += 16) { u8 snd_buf[2] = { addr >> 8, addr & 0xFF }; ttusb_i2c_msg(ttusb, 0x50, snd_buf, 2, stc_firmware + addr, 16); } return 0;}static ssize_t stc_read(struct file *file, char *buf, size_t count, loff_t * offset){ int tc = count; if ((tc + *offset) > 8192) tc = 8192 - *offset; if (tc < 0) return 0; if (copy_to_user(buf, stc_firmware + *offset, tc)) return -EFAULT; *offset += tc; return tc;}static int stc_release(struct inode *inode, struct file *file){ return 0;}static struct file_operations stc_fops = { .owner = THIS_MODULE, .read = stc_read, .open = stc_open, .release = stc_release,};#endifstatic u32 functionality(struct i2c_adapter *adapter){ return I2C_FUNC_I2C;}static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params){ struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 data[4]; struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) }; u32 div; div = (params->frequency + 36166667) / 166667; data[0] = (div >> 8) & 0x7f; data[1] = div & 0xff; data[2] = ((div >> 10) & 0x60) | 0x85; data[3] = params->frequency < 592000000 ? 0x40 : 0x80; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO; return 0;}static struct cx22700_config alps_tdmb7_config = { .demod_address = 0x43,};static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe){ struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) }; // setup PLL configuration if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); // disable the mc44BC374c (do not check for errors) tuner_msg.addr = 0x65; tuner_msg.buf = disable_mc44BC374c; tuner_msg.len = sizeof(disable_mc44BC374c); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) { i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1); } return 0;}static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params){ struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 tuner_buf[4]; struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; int tuner_frequency = 0; u8 band, cp, filter; // determine charge pump tuner_frequency = params->frequency + 36130000; if (tuner_frequency < 87000000) return -EINVAL; else if (tuner_frequency < 130000000) cp = 3; else if (tuner_frequency < 160000000) cp = 5; else if (tuner_frequency < 200000000) cp = 6; else if (tuner_frequency < 290000000) cp = 3; else if (tuner_frequency < 420000000) cp = 5; else if (tuner_frequency < 480000000) cp = 6; else if (tuner_frequency < 620000000) cp = 3; else if (tuner_frequency < 830000000) cp = 5; else if (tuner_frequency < 895000000) cp = 7; else return -EINVAL; // determine band if (params->frequency < 49000000) return -EINVAL; else if (params->frequency < 159000000) band = 1; else if (params->frequency < 444000000) band = 2; else if (params->frequency < 861000000) band = 4; else return -EINVAL; // setup PLL filter switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: tda1004x_writereg(fe, 0x0C, 0); filter = 0; break; case BANDWIDTH_7_MHZ: tda1004x_writereg(fe, 0x0C, 0); filter = 0; break; case BANDWIDTH_8_MHZ: tda1004x_writereg(fe, 0x0C, 0xFF); filter = 1; break; default: return -EINVAL; } // calculate divisor // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000; // setup tuner buffer tuner_buf[0] = tuner_frequency >> 8; tuner_buf[1] = tuner_frequency & 0xff; tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); return 0;}static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name){ struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; return request_firmware(fw, name, &ttusb->dev->dev);}static struct tda1004x_config philips_tdm1316l_config = { .demod_address = 0x8, .invert = 1, .invert_oclk = 0, .request_firmware = philips_tdm1316l_request_firmware,};static u8 alps_bsbe1_inittab[] = { 0x01, 0x15, 0x02, 0x30, 0x03, 0x00, 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ 0x06, 0x40, /* DAC not used, set to high impendance mode */ 0x07, 0x00, /* DAC LSB */ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ 0x09, 0x00, /* FIFO */ 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1f, 0x50, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 0x29, 0x1e, // 1/2 threshold 0x2a, 0x14, // 2/3 threshold 0x2b, 0x0f, // 3/4 threshold 0x2c, 0x09, // 5/6 threshold 0x2d, 0x05, // 7/8 threshold 0x2e, 0x01, 0x31, 0x1f, // test all FECs 0x32, 0x19, // viterbi and synchro search 0x33, 0xfc, // rs control 0x34, 0x93, // error control 0x0f, 0x92, 0xff, 0xff};static u8 alps_bsru6_inittab[] = { 0x01, 0x15, 0x02, 0x30, 0x03, 0x00, 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ 0x06, 0x40, /* DAC not used, set to high impendance mode */ 0x07, 0x00, /* DAC LSB */ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ 0x09, 0x00, /* FIFO */ 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -