aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/ttpci/av7110.c
diff options
context:
space:
mode:
authorOliver Endriss <o.endriss@gmx.de>2008-09-03 18:15:27 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:36:56 -0400
commit9e615eac827094147401c44c9ff955b468d4fa79 (patch)
tree017049f6db122cffc170499fe40221dd418ed1a6 /drivers/media/dvb/ttpci/av7110.c
parent81ae953b687e7cdfa094b07a6544523f3bb81aa3 (diff)
V4L/DVB (8889): dvb-ttpci: Support full-ts hardware modification
Add support for the 'full-ts' hardware modification. On full-featured cards the data throughput is limited by the hardware design. The full-ts mod removes this bottleneck, i.e. the card is able to deliver the complete transport stream of a transponder. For details see http://www.escape-edv.de/endriss/dvb-full-ts-mod Signed-off-by: Oliver Endriss <o.endriss@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/ttpci/av7110.c')
-rw-r--r--drivers/media/dvb/ttpci/av7110.c113
1 files changed, 88 insertions, 25 deletions
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 3b641804f6cb..404108f09d77 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -88,6 +88,7 @@ static int budgetpatch;
88static int wss_cfg_4_3 = 0x4008; 88static int wss_cfg_4_3 = 0x4008;
89static int wss_cfg_16_9 = 0x0007; 89static int wss_cfg_16_9 = 0x0007;
90static int tv_standard; 90static int tv_standard;
91static int full_ts;
91 92
92module_param_named(debug, av7110_debug, int, 0644); 93module_param_named(debug, av7110_debug, int, 0644);
93MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); 94MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -106,6 +107,8 @@ module_param(volume, int, 0444);
106MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); 107MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
107module_param(budgetpatch, int, 0444); 108module_param(budgetpatch, int, 0444);
108MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)"); 109MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
110module_param(full_ts, int, 0444);
111MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
109module_param(wss_cfg_4_3, int, 0444); 112module_param(wss_cfg_4_3, int, 0444);
110MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data"); 113MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
111module_param(wss_cfg_16_9, int, 0444); 114module_param(wss_cfg_16_9, int, 0444);
@@ -116,6 +119,8 @@ MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
116DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 119DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
117 120
118static void restart_feeds(struct av7110 *av7110); 121static void restart_feeds(struct av7110 *av7110);
122static int budget_start_feed(struct dvb_demux_feed *feed);
123static int budget_stop_feed(struct dvb_demux_feed *feed);
119 124
120static int av7110_num; 125static int av7110_num;
121 126
@@ -806,6 +811,9 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
806 811
807 dprintk(4, "%p\n", av7110); 812 dprintk(4, "%p\n", av7110);
808 813
814 if (av7110->full_ts)
815 return 0;
816
809 if (dvbdmxfilter->type == DMX_TYPE_SEC) { 817 if (dvbdmxfilter->type == DMX_TYPE_SEC) {
810 if (hw_sections) { 818 if (hw_sections) {
811 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) | 819 buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
@@ -854,6 +862,9 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
854 862
855 dprintk(4, "%p\n", av7110); 863 dprintk(4, "%p\n", av7110);
856 864
865 if (av7110->full_ts)
866 return 0;
867
857 handle = dvbdmxfilter->hw_handle; 868 handle = dvbdmxfilter->hw_handle;
858 if (handle >= 32) { 869 if (handle >= 32) {
859 printk("%s tried to stop invalid filter %04x, filter type = %x\n", 870 printk("%s tried to stop invalid filter %04x, filter type = %x\n",
@@ -913,7 +924,7 @@ static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
913 return ret; 924 return ret;
914 } 925 }
915 926
916 if ((dvbdmxfeed->ts_type & TS_PACKET)) { 927 if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
917 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000)) 928 if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
918 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed); 929 ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
919 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000)) 930 if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
@@ -974,7 +985,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
974 if (!demux->dmx.frontend) 985 if (!demux->dmx.frontend)
975 return -EINVAL; 986 return -EINVAL;
976 987
977 if (feed->pid > 0x1fff) 988 if (!av7110->full_ts && feed->pid > 0x1fff)
978 return -EINVAL; 989 return -EINVAL;
979 990
980 if (feed->type == DMX_TYPE_TS) { 991 if (feed->type == DMX_TYPE_TS) {
@@ -1003,7 +1014,12 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
1003 } 1014 }
1004 } 1015 }
1005 1016
1006 else if (feed->type == DMX_TYPE_SEC) { 1017 if (av7110->full_ts) {
1018 budget_start_feed(feed);
1019 return ret;
1020 }
1021
1022 if (feed->type == DMX_TYPE_SEC) {
1007 int i; 1023 int i;
1008 1024
1009 for (i = 0; i < demux->filternum; i++) { 1025 for (i = 0; i < demux->filternum; i++) {
@@ -1050,7 +1066,12 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed)
1050 ret = StopHWFilter(feed->filter); 1066 ret = StopHWFilter(feed->filter);
1051 } 1067 }
1052 1068
1053 if (!ret && feed->type == DMX_TYPE_SEC) { 1069 if (av7110->full_ts) {
1070 budget_stop_feed(feed);
1071 return ret;
1072 }
1073
1074 if (feed->type == DMX_TYPE_SEC) {
1054 for (i = 0; i<demux->filternum; i++) { 1075 for (i = 0; i<demux->filternum; i++) {
1055 if (demux->filter[i].state == DMX_STATE_GO && 1076 if (demux->filter[i].state == DMX_STATE_GO &&
1056 demux->filter[i].filter.parent == &feed->feed.sec) { 1077 demux->filter[i].filter.parent == &feed->feed.sec) {
@@ -1074,6 +1095,7 @@ static void restart_feeds(struct av7110 *av7110)
1074 struct dvb_demux *dvbdmx = &av7110->demux; 1095 struct dvb_demux *dvbdmx = &av7110->demux;
1075 struct dvb_demux_feed *feed; 1096 struct dvb_demux_feed *feed;
1076 int mode; 1097 int mode;
1098 int feeding;
1077 int i, j; 1099 int i, j;
1078 1100
1079 dprintk(4, "%p\n", av7110); 1101 dprintk(4, "%p\n", av7110);
@@ -1082,6 +1104,8 @@ static void restart_feeds(struct av7110 *av7110)
1082 av7110->playing = 0; 1104 av7110->playing = 0;
1083 av7110->rec_mode = 0; 1105 av7110->rec_mode = 0;
1084 1106
1107 feeding = av7110->feeding1; /* full_ts mod */
1108
1085 for (i = 0; i < dvbdmx->feednum; i++) { 1109 for (i = 0; i < dvbdmx->feednum; i++) {
1086 feed = &dvbdmx->feed[i]; 1110 feed = &dvbdmx->feed[i];
1087 if (feed->state == DMX_STATE_GO) { 1111 if (feed->state == DMX_STATE_GO) {
@@ -1099,6 +1123,8 @@ static void restart_feeds(struct av7110 *av7110)
1099 } 1123 }
1100 } 1124 }
1101 1125
1126 av7110->feeding1 = feeding; /* full_ts mod */
1127
1102 if (mode) 1128 if (mode)
1103 av7110_av_start_play(av7110, mode); 1129 av7110_av_start_play(av7110, mode);
1104} 1130}
@@ -1197,8 +1223,9 @@ static int start_ts_capture(struct av7110 *budget)
1197 1223
1198 if (budget->feeding1) 1224 if (budget->feeding1)
1199 return ++budget->feeding1; 1225 return ++budget->feeding1;
1200 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH); 1226 memset(budget->grabbing, 0x00, TS_BUFLEN);
1201 budget->ttbp = 0; 1227 budget->ttbp = 0;
1228 SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
1202 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ 1229 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1203 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ 1230 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
1204 return ++budget->feeding1; 1231 return ++budget->feeding1;
@@ -1239,12 +1266,8 @@ static void vpeirq(unsigned long data)
1239 u8 *mem = (u8 *) (budget->grabbing); 1266 u8 *mem = (u8 *) (budget->grabbing);
1240 u32 olddma = budget->ttbp; 1267 u32 olddma = budget->ttbp;
1241 u32 newdma = saa7146_read(budget->dev, PCI_VDP3); 1268 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
1269 struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
1242 1270
1243 if (!budgetpatch) {
1244 printk("av7110.c: vpeirq() called while budgetpatch disabled!"
1245 " check saa7146 IER register\n");
1246 BUG();
1247 }
1248 /* nearest lower position divisible by 188 */ 1271 /* nearest lower position divisible by 188 */
1249 newdma -= newdma % 188; 1272 newdma -= newdma % 188;
1250 1273
@@ -1268,11 +1291,11 @@ static void vpeirq(unsigned long data)
1268 1291
1269 if (newdma > olddma) 1292 if (newdma > olddma)
1270 /* no wraparound, dump olddma..newdma */ 1293 /* no wraparound, dump olddma..newdma */
1271 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188); 1294 dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
1272 else { 1295 else {
1273 /* wraparound, dump olddma..buflen and 0..newdma */ 1296 /* wraparound, dump olddma..buflen and 0..newdma */
1274 dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188); 1297 dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
1275 dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188); 1298 dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
1276 } 1299 }
1277} 1300}
1278 1301
@@ -1294,8 +1317,8 @@ static int av7110_register(struct av7110 *av7110)
1294 for (i = 0; i < 32; i++) 1317 for (i = 0; i < 32; i++)
1295 av7110->handle2filter[i] = NULL; 1318 av7110->handle2filter[i] = NULL;
1296 1319
1297 dvbdemux->filternum = 32; 1320 dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
1298 dvbdemux->feednum = 32; 1321 dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
1299 dvbdemux->start_feed = av7110_start_feed; 1322 dvbdemux->start_feed = av7110_start_feed;
1300 dvbdemux->stop_feed = av7110_stop_feed; 1323 dvbdemux->stop_feed = av7110_stop_feed;
1301 dvbdemux->write_to_decoder = av7110_write_to_decoder; 1324 dvbdemux->write_to_decoder = av7110_write_to_decoder;
@@ -1305,7 +1328,7 @@ static int av7110_register(struct av7110 *av7110)
1305 dvb_dmx_init(&av7110->demux); 1328 dvb_dmx_init(&av7110->demux);
1306 av7110->demux.dmx.get_stc = dvb_get_stc; 1329 av7110->demux.dmx.get_stc = dvb_get_stc;
1307 1330
1308 av7110->dmxdev.filternum = 32; 1331 av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
1309 av7110->dmxdev.demux = &dvbdemux->dmx; 1332 av7110->dmxdev.demux = &dvbdemux->dmx;
1310 av7110->dmxdev.capabilities = 0; 1333 av7110->dmxdev.capabilities = 0;
1311 1334
@@ -1422,7 +1445,6 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
1422 return i2c_transfer(&av7110->i2c_adap, &msgs, 1); 1445 return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
1423} 1446}
1424 1447
1425#if 0
1426u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) 1448u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1427{ 1449{
1428 u8 mm1[] = {0x00}; 1450 u8 mm1[] = {0x00};
@@ -1439,7 +1461,6 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
1439 1461
1440 return mm2[0]; 1462 return mm2[0];
1441} 1463}
1442#endif
1443 1464
1444/**************************************************************************** 1465/****************************************************************************
1445 * INITIALIZATION 1466 * INITIALIZATION
@@ -2484,7 +2505,47 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
2484 av7110->dvb_adapter.proposed_mac); 2505 av7110->dvb_adapter.proposed_mac);
2485 ret = -ENOMEM; 2506 ret = -ENOMEM;
2486 2507
2487 if (budgetpatch) { 2508 /* full-ts mod? */
2509 if (full_ts)
2510 av7110->full_ts = true;
2511
2512 /* check for full-ts flag in eeprom */
2513 if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
2514 u8 flags = i2c_readreg(av7110, 0xaa, 2);
2515 if (flags != 0xff && (flags & 0x01))
2516 av7110->full_ts = true;
2517 }
2518
2519 if (av7110->full_ts) {
2520 printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
2521 spin_lock_init(&av7110->feedlock1);
2522 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2523 &av7110->pt);
2524 if (!av7110->grabbing)
2525 goto err_i2c_del_3;
2526
2527 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
2528 saa7146_write(dev, MC2, (MASK_10 | MASK_26));
2529
2530 saa7146_write(dev, DD1_INIT, 0x00000600);
2531 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
2532
2533 saa7146_write(dev, BRS_CTRL, 0x60000000);
2534 saa7146_write(dev, MC2, MASK_08 | MASK_24);
2535
2536 /* dma3 */
2537 saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
2538 saa7146_write(dev, BASE_ODD3, 0);
2539 saa7146_write(dev, BASE_EVEN3, 0);
2540 saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
2541 saa7146_write(dev, PITCH3, TS_WIDTH);
2542 saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
2543 saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
2544 saa7146_write(dev, MC2, MASK_04 | MASK_20);
2545
2546 tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
2547
2548 } else if (budgetpatch) {
2488 spin_lock_init(&av7110->feedlock1); 2549 spin_lock_init(&av7110->feedlock1);
2489 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length, 2550 av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
2490 &av7110->pt); 2551 &av7110->pt);
@@ -2710,11 +2771,13 @@ static int __devexit av7110_detach(struct saa7146_dev* saa)
2710#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) 2771#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
2711 av7110_ir_exit(av7110); 2772 av7110_ir_exit(av7110);
2712#endif 2773#endif
2713 if (budgetpatch) { 2774 if (budgetpatch || av7110->full_ts) {
2714 /* Disable RPS1 */ 2775 if (budgetpatch) {
2715 saa7146_write(saa, MC1, MASK_29); 2776 /* Disable RPS1 */
2716 /* VSYNC LOW (inactive) */ 2777 saa7146_write(saa, MC1, MASK_29);
2717 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); 2778 /* VSYNC LOW (inactive) */
2779 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
2780 }
2718 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */ 2781 saa7146_write(saa, MC1, MASK_20); /* DMA3 off */
2719 SAA7146_IER_DISABLE(saa, MASK_10); 2782 SAA7146_IER_DISABLE(saa, MASK_10);
2720 SAA7146_ISR_CLEAR(saa, MASK_10); 2783 SAA7146_ISR_CLEAR(saa, MASK_10);
@@ -2794,7 +2857,7 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
2794 tasklet_schedule(&av7110->gpio_tasklet); 2857 tasklet_schedule(&av7110->gpio_tasklet);
2795 } 2858 }
2796 2859
2797 if ((*isr & MASK_10) && budgetpatch) 2860 if (*isr & MASK_10)
2798 tasklet_schedule(&av7110->vpe_tasklet); 2861 tasklet_schedule(&av7110->vpe_tasklet);
2799} 2862}
2800 2863