aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/firewire
diff options
context:
space:
mode:
authorHenrik Kurelid <henke@kurelid.se>2009-08-01 07:02:38 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-12 11:19:08 -0400
commit166987c6987a25a95cef6889d24088f0eb2daa36 (patch)
treea10a778f99f993fc348ba783d361037f09d5bdc6 /drivers/media/dvb/firewire
parent114323ede9e84a64327b74ff6f7da5576c9ae361 (diff)
V4L/DVB (12482): firedtv: add PID filtering for SW zigzag retune
The AVC protocol uses the same command for tuning and PID filtering and since dvb-core uses a software zigzagging to do automatic retuning this could cause all PID filters to be cleared. PID filter information is now included in all DSD commands to the card. Background: There is a problem in the firedtv driver that causes recordings to stop if the SW zigzag algorithm in dvb-core kicks in with a retune after the application has set up the PID filters. Since tuning and setting PID filters uses the same AVC command (DSD) and only the replace subfunction is supported by the card, it is not possible to do a retune without setting the PID filters. This means that the PID filtering has to be sent in each tune. This problem applies to C and T cards since S and S2 cards tune using a vendor specific command. The patch corrects the problem by sending the PID list in each tune. I have tested it on my T card with a good result. How to trigger problem: Zap to a channel and output AV to a file, e.g. "tzap -c channels.conf SVT1 -r -o SVT1.ts". After a short while, pull the antenna cable from the card. The lock on the channel will disappear and the TS file will stop increasing in size. Wait a couple of seconds. Replug the cable again. You will get a lock on the channel again, but the TS file will never increase in size agains sinze no PIDS are filtered. Tested with kaffeine with DVB-T and DVB-C: Fixes retuning after antenna was plugged out and back in with DVB-T. Does not fix this with DVB-C, but also doesn't regress on DVB-C. Signed-off-by: Henrik Kurelid <henrik@kurelid.se> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/firewire')
-rw-r--r--drivers/media/dvb/firewire/firedtv-avc.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
index 32526f103b59..1a94c6bb601c 100644
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -254,6 +254,26 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length)
254 return 0; 254 return 0;
255} 255}
256 256
257static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
258{
259 int i, n, pos = 1;
260
261 for (i = 0, n = 0; i < 16; i++) {
262 if (test_bit(i, &fdtv->channel_active)) {
263 operand[pos++] = 0x13; /* flowfunction relay */
264 operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
265 operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f;
266 operand[pos++] = fdtv->channel_pid[i] & 0xff;
267 operand[pos++] = 0x00; /* tableID */
268 operand[pos++] = 0x00; /* filter_length */
269 n++;
270 }
271 }
272 operand[0] = n;
273
274 return pos;
275}
276
257/* 277/*
258 * tuning command for setting the relative LNB frequency 278 * tuning command for setting the relative LNB frequency
259 * (not supported by the AVC standard) 279 * (not supported by the AVC standard)
@@ -316,7 +336,8 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
316 } 336 }
317} 337}
318 338
319static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, 339static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
340 struct dvb_frontend_parameters *params,
320 struct avc_command_frame *c) 341 struct avc_command_frame *c)
321{ 342{
322 c->opcode = AVC_OPCODE_DSD; 343 c->opcode = AVC_OPCODE_DSD;
@@ -378,13 +399,13 @@ static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
378 399
379 c->operand[20] = 0x00; 400 c->operand[20] = 0x00;
380 c->operand[21] = 0x00; 401 c->operand[21] = 0x00;
381 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
382 c->operand[22] = 0x00;
383 402
384 c->length = 28; 403 /* Add PIDs to filter */
404 c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
385} 405}
386 406
387static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, 407static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
408 struct dvb_frontend_parameters *params,
388 struct avc_command_frame *c) 409 struct avc_command_frame *c)
389{ 410{
390 struct dvb_ofdm_parameters *ofdm = &params->u.ofdm; 411 struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
@@ -481,10 +502,9 @@ static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
481 502
482 c->operand[15] = 0x00; /* network_ID[0] */ 503 c->operand[15] = 0x00; /* network_ID[0] */
483 c->operand[16] = 0x00; /* network_ID[1] */ 504 c->operand[16] = 0x00; /* network_ID[1] */
484 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
485 c->operand[17] = 0x00;
486 505
487 c->length = 24; 506 /* Add PIDs to filter */
507 c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
488} 508}
489 509
490int avc_tuner_dsd(struct firedtv *fdtv, 510int avc_tuner_dsd(struct firedtv *fdtv,
@@ -502,8 +522,8 @@ int avc_tuner_dsd(struct firedtv *fdtv,
502 switch (fdtv->type) { 522 switch (fdtv->type) {
503 case FIREDTV_DVB_S: 523 case FIREDTV_DVB_S:
504 case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; 524 case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
505 case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break; 525 case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break;
506 case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break; 526 case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break;
507 default: 527 default:
508 BUG(); 528 BUG();
509 } 529 }