aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2013-03-09 14:10:55 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-23 09:02:04 -0400
commit96d7ca5ec9baac231ab3dfd62abcb75141d80626 (patch)
treeee45b36c9c4de19fb9b8d83467fc651696bc8b85
parent61356eea6742ad38ad9ecfd5c65e2662e4c9d8ab (diff)
[media] dvb_usb_v2: rework USB streaming logic
Control flow order changed a little bit. HW PID filter is now disabled also when streaming is stopped - earlier it was just set only when streaming was started. Control flow is now: * set streaming status bit * submit USB streaming packets * enable HW PID filter * ask device to start streaming * N x add PID to device HW PID filter ... streaming video ... * N x remove PID from device HW PID filter * ask device to stop streaming * disable HW PID filter * kill USB streaming packets * clear streaming status bit Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c215
1 files changed, 116 insertions, 99 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 9b24a0e9675a..19f6737d9817 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -260,135 +260,152 @@ static int wait_schedule(void *ptr)
260 return 0; 260 return 0;
261} 261}
262 262
263static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, 263static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
264 int count)
265{ 264{
266 struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; 265 struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
267 struct dvb_usb_device *d = adap_to_d(adap); 266 struct dvb_usb_device *d = adap_to_d(adap);
268 int ret; 267 int ret = 0;
269 dev_dbg(&d->udev->dev, "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d '%s'\n", 268 struct usb_data_stream_properties stream_props;
269 dev_dbg(&d->udev->dev,
270 "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n",
270 __func__, adap->id, adap->active_fe, dvbdmxfeed->type, 271 __func__, adap->id, adap->active_fe, dvbdmxfeed->type,
271 adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, 272 adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid,
272 dvbdmxfeed->pid, dvbdmxfeed->index, 273 dvbdmxfeed->pid, dvbdmxfeed->index);
273 (count == 1) ? "on" : "off");
274 274
275 /* wait init is done */
275 wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule, 276 wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule,
276 TASK_UNINTERRUPTIBLE); 277 TASK_UNINTERRUPTIBLE);
277 278
278 if (adap->active_fe == -1) 279 if (adap->active_fe == -1)
279 return -EINVAL; 280 return -EINVAL;
280 281
281 adap->feed_count += count; 282 /* skip feed setup if we are already feeding */
282 283 if (adap->feed_count++ > 0)
283 /* stop feeding if it is last pid */ 284 goto skip_feed_start;
284 if (adap->feed_count == 0) {
285 dev_dbg(&d->udev->dev, "%s: stop feeding\n", __func__);
286
287 if (d->props->streaming_ctrl) {
288 ret = d->props->streaming_ctrl(
289 adap->fe[adap->active_fe], 0);
290 if (ret < 0) {
291 dev_err(&d->udev->dev,
292 "%s: streaming_ctrl() failed=%d\n",
293 KBUILD_MODNAME, ret);
294 usb_urb_killv2(&adap->stream);
295 goto err_clear_wait;
296 }
297 }
298 usb_urb_killv2(&adap->stream);
299 285
300 clear_bit(ADAP_STREAMING, &adap->state_bits); 286 /* set 'streaming' status bit */
301 smp_mb__after_clear_bit(); 287 set_bit(ADAP_STREAMING, &adap->state_bits);
302 wake_up_bit(&adap->state_bits, ADAP_STREAMING); 288
289 /* resolve input and output streaming parameters */
290 if (d->props->get_stream_config) {
291 memcpy(&stream_props, &adap->props->stream,
292 sizeof(struct usb_data_stream_properties));
293 ret = d->props->get_stream_config(adap->fe[adap->active_fe],
294 &adap->ts_type, &stream_props);
295 if (ret)
296 dev_err(&d->udev->dev,
297 "%s: get_stream_config() failed=%d\n",
298 KBUILD_MODNAME, ret);
299 } else {
300 stream_props = adap->props->stream;
301 }
302
303 switch (adap->ts_type) {
304 case DVB_USB_FE_TS_TYPE_204:
305 adap->stream.complete = dvb_usb_data_complete_204;
306 break;
307 case DVB_USB_FE_TS_TYPE_RAW:
308 adap->stream.complete = dvb_usb_data_complete_raw;
309 break;
310 case DVB_USB_FE_TS_TYPE_188:
311 default:
312 adap->stream.complete = dvb_usb_data_complete;
313 break;
314 }
315
316 /* submit USB streaming packets */
317 usb_urb_submitv2(&adap->stream, &stream_props);
318
319 /* enable HW PID filter */
320 if (adap->pid_filtering && adap->props->pid_filter_ctrl) {
321 ret = adap->props->pid_filter_ctrl(adap, 1);
322 if (ret)
323 dev_err(&d->udev->dev,
324 "%s: pid_filter_ctrl() failed=%d\n",
325 KBUILD_MODNAME, ret);
303 } 326 }
304 327
305 /* activate the pid on the device pid filter */ 328 /* ask device to start streaming */
306 if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && 329 if (d->props->streaming_ctrl) {
307 adap->pid_filtering && adap->props->pid_filter) { 330 ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 1);
331 if (ret)
332 dev_err(&d->udev->dev,
333 "%s: streaming_ctrl() failed=%d\n",
334 KBUILD_MODNAME, ret);
335 }
336skip_feed_start:
337
338 /* add PID to device HW PID filter */
339 if (adap->pid_filtering && adap->props->pid_filter) {
308 ret = adap->props->pid_filter(adap, dvbdmxfeed->index, 340 ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
309 dvbdmxfeed->pid, (count == 1) ? 1 : 0); 341 dvbdmxfeed->pid, 1);
310 if (ret < 0) 342 if (ret)
311 dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", 343 dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
312 KBUILD_MODNAME, ret); 344 KBUILD_MODNAME, ret);
313 } 345 }
314 346
315 /* start feeding if it is first pid */ 347 if (ret)
316 if (adap->feed_count == 1 && count == 1) { 348 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
317 struct usb_data_stream_properties stream_props; 349 return ret;
318 set_bit(ADAP_STREAMING, &adap->state_bits); 350}
319 dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__);
320 351
321 /* resolve input and output streaming paramters */ 352static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
322 if (d->props->get_stream_config) { 353{
323 memcpy(&stream_props, &adap->props->stream, 354 struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
324 sizeof(struct usb_data_stream_properties)); 355 struct dvb_usb_device *d = adap_to_d(adap);
325 ret = d->props->get_stream_config( 356 int ret = 0;
326 adap->fe[adap->active_fe], 357 dev_dbg(&d->udev->dev,
327 &adap->ts_type, &stream_props); 358 "%s: adap=%d active_fe=%d feed_type=%d setting pid [%s]: %04x (%04d) at index %d\n",
328 if (ret < 0) 359 __func__, adap->id, adap->active_fe, dvbdmxfeed->type,
329 goto err_clear_wait; 360 adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid,
330 } else { 361 dvbdmxfeed->pid, dvbdmxfeed->index);
331 stream_props = adap->props->stream;
332 }
333 362
334 switch (adap->ts_type) { 363 if (adap->active_fe == -1)
335 case DVB_USB_FE_TS_TYPE_204: 364 return -EINVAL;
336 adap->stream.complete = dvb_usb_data_complete_204;
337 break;
338 case DVB_USB_FE_TS_TYPE_RAW:
339 adap->stream.complete = dvb_usb_data_complete_raw;
340 break;
341 case DVB_USB_FE_TS_TYPE_188:
342 default:
343 adap->stream.complete = dvb_usb_data_complete;
344 break;
345 }
346 365
347 usb_urb_submitv2(&adap->stream, &stream_props); 366 /* remove PID from device HW PID filter */
348 367 if (adap->pid_filtering && adap->props->pid_filter) {
349 if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && 368 ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
350 adap->props->caps & 369 dvbdmxfeed->pid, 0);
351 DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && 370 if (ret)
352 adap->props->pid_filter_ctrl) { 371 dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
353 ret = adap->props->pid_filter_ctrl(adap, 372 KBUILD_MODNAME, ret);
354 adap->pid_filtering); 373 }
355 if (ret < 0) {
356 dev_err(&d->udev->dev,
357 "%s: pid_filter_ctrl() failed=%d\n",
358 KBUILD_MODNAME, ret);
359 goto err_clear_wait;
360 }
361 }
362 374
363 if (d->props->streaming_ctrl) { 375 /* we cannot stop streaming until last PID is removed */
364 ret = d->props->streaming_ctrl( 376 if (--adap->feed_count > 0)
365 adap->fe[adap->active_fe], 1); 377 goto skip_feed_stop;
366 if (ret < 0) { 378
367 dev_err(&d->udev->dev, 379 /* ask device to stop streaming */
368 "%s: streaming_ctrl() failed=%d\n", 380 if (d->props->streaming_ctrl) {
369 KBUILD_MODNAME, ret); 381 ret = d->props->streaming_ctrl(adap->fe[adap->active_fe], 0);
370 goto err_clear_wait; 382 if (ret)
371 } 383 dev_err(&d->udev->dev,
372 } 384 "%s: streaming_ctrl() failed=%d\n",
385 KBUILD_MODNAME, ret);
373 } 386 }
374 387
375 return 0; 388 /* disable HW PID filter */
376err_clear_wait: 389 if (adap->pid_filtering && adap->props->pid_filter_ctrl) {
390 ret = adap->props->pid_filter_ctrl(adap, 0);
391 if (ret)
392 dev_err(&d->udev->dev,
393 "%s: pid_filter_ctrl() failed=%d\n",
394 KBUILD_MODNAME, ret);
395 }
396
397 /* kill USB streaming packets */
398 usb_urb_killv2(&adap->stream);
399
400 /* clear 'streaming' status bit */
377 clear_bit(ADAP_STREAMING, &adap->state_bits); 401 clear_bit(ADAP_STREAMING, &adap->state_bits);
378 smp_mb__after_clear_bit(); 402 smp_mb__after_clear_bit();
379 wake_up_bit(&adap->state_bits, ADAP_STREAMING); 403 wake_up_bit(&adap->state_bits, ADAP_STREAMING);
380 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); 404skip_feed_stop:
381 return ret;
382}
383
384static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
385{
386 return dvb_usb_ctrl_feed(dvbdmxfeed, 1);
387}
388 405
389static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 406 if (ret)
390{ 407 dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
391 return dvb_usb_ctrl_feed(dvbdmxfeed, -1); 408 return ret;
392} 409}
393 410
394static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) 411static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)