forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/media/usb/au0828/au0828-core.c
....@@ -1,18 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Driver for the Auvitek USB bridge
34 *
45 * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- *
15
- * GNU General Public License for more details.
166 */
177
188 #include "au0828.h"
....@@ -155,9 +145,7 @@
155145 dev->media_dev->disable_source = NULL;
156146 mutex_unlock(&mdev->graph_mutex);
157147
158
- media_device_unregister(dev->media_dev);
159
- media_device_cleanup(dev->media_dev);
160
- kfree(dev->media_dev);
148
+ media_device_delete(dev->media_dev, KBUILD_MODNAME, THIS_MODULE);
161149 dev->media_dev = NULL;
162150 #endif
163151 }
....@@ -210,13 +198,9 @@
210198 #ifdef CONFIG_MEDIA_CONTROLLER
211199 struct media_device *mdev;
212200
213
- mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
214
- if (!mdev)
215
- return -ENOMEM;
216
-
217
- /* check if media device is already initialized */
218
- if (!mdev->dev)
219
- media_device_usb_init(mdev, udev, udev->product);
201
+ mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE);
202
+ if (IS_ERR(mdev))
203
+ return PTR_ERR(mdev);
220204
221205 dev->media_dev = mdev;
222206 #endif
....@@ -234,7 +218,7 @@
234218 if (!new) {
235219 /*
236220 * Called during au0828 probe time to connect
237
- * entites that were created prior to registering
221
+ * entities that were created prior to registering
238222 * the notify handler. Find mixer and decoder.
239223 */
240224 media_device_for_each_entity(entity, dev->media_dev) {
....@@ -266,14 +250,38 @@
266250
267251 create_link:
268252 if (decoder && mixer) {
269
- ret = media_create_pad_link(decoder,
270
- DEMOD_PAD_AUDIO_OUT,
271
- mixer, 0,
272
- MEDIA_LNK_FL_ENABLED);
273
- if (ret)
253
+ ret = media_get_pad_index(decoder, false,
254
+ PAD_SIGNAL_AUDIO);
255
+ if (ret >= 0)
256
+ ret = media_create_pad_link(decoder, ret,
257
+ mixer, 0,
258
+ MEDIA_LNK_FL_ENABLED);
259
+ if (ret < 0)
274260 dev_err(&dev->usbdev->dev,
275261 "Mixer Pad Link Create Error: %d\n", ret);
276262 }
263
+}
264
+
265
+static bool au0828_is_link_shareable(struct media_entity *owner,
266
+ struct media_entity *entity)
267
+{
268
+ bool shareable = false;
269
+
270
+ /* Tuner link can be shared by audio, video, and VBI */
271
+ switch (owner->function) {
272
+ case MEDIA_ENT_F_IO_V4L:
273
+ case MEDIA_ENT_F_AUDIO_CAPTURE:
274
+ case MEDIA_ENT_F_IO_VBI:
275
+ if (entity->function == MEDIA_ENT_F_IO_V4L ||
276
+ entity->function == MEDIA_ENT_F_AUDIO_CAPTURE ||
277
+ entity->function == MEDIA_ENT_F_IO_VBI)
278
+ shareable = true;
279
+ break;
280
+ case MEDIA_ENT_F_DTV_DEMOD:
281
+ default:
282
+ break;
283
+ }
284
+ return shareable;
277285 }
278286
279287 /* Callers should hold graph_mutex */
....@@ -318,18 +326,20 @@
318326 /*
319327 * Default input is tuner and default input_type
320328 * is AU0828_VMUX_TELEVISION.
321
- * FIXME:
329
+ *
322330 * There is a problem when s_input is called to
323331 * change the default input. s_input will try to
324332 * enable_source before attempting to change the
325333 * input on the device, and will end up enabling
326334 * default source which is tuner.
327335 *
328
- * Additional logic is necessary in au0828
329
- * to detect that the input has changed and
330
- * enable the right source.
336
+ * Additional logic is necessary in au0828 to detect
337
+ * that the input has changed and enable the right
338
+ * source. au0828 handles this case in its s_input.
339
+ * It will disable the old source and enable the new
340
+ * source.
341
+ *
331342 */
332
-
333343 if (dev->input_type == AU0828_VMUX_TELEVISION)
334344 find_source = dev->tuner;
335345 else if (dev->input_type == AU0828_VMUX_SVIDEO ||
....@@ -342,27 +352,33 @@
342352 }
343353 }
344354
345
- /* Is an active link between sink and source */
355
+ /* Is there an active link between sink and source */
346356 if (dev->active_link) {
347
- /*
348
- * If DVB is using the tuner and calling entity is
349
- * audio/video, the following check will be false,
350
- * since sink is different. Result is Busy.
351
- */
352
- if (dev->active_link->sink->entity == sink &&
353
- dev->active_link->source->entity == find_source) {
354
- /*
355
- * Either ALSA or Video own tuner. sink is
356
- * the same for both. Prevent Video stepping
357
- * on ALSA when ALSA owns the source.
357
+ if (dev->active_link_owner == entity) {
358
+ /* This check is necessary to handle multiple
359
+ * enable_source calls from v4l_ioctls during
360
+ * the course of video/vbi application run-time.
358361 */
359
- if (dev->active_link_owner != entity &&
360
- dev->active_link_owner->function ==
361
- MEDIA_ENT_F_AUDIO_CAPTURE) {
362
- pr_debug("ALSA has the tuner\n");
363
- ret = -EBUSY;
364
- goto end;
365
- }
362
+ pr_debug("%s already owns the tuner\n", entity->name);
363
+ ret = 0;
364
+ goto end;
365
+ } else if (au0828_is_link_shareable(dev->active_link_owner,
366
+ entity)) {
367
+ /* Either ALSA or Video own tuner. Sink is the same
368
+ * for both. Allow sharing the active link between
369
+ * their common source (tuner) and sink (decoder).
370
+ * Starting pipeline between sharing entity and sink
371
+ * will fail with pipe mismatch, while owner has an
372
+ * active pipeline. Switch pipeline ownership from
373
+ * user to owner when owner disables the source.
374
+ */
375
+ dev->active_link_shared = true;
376
+ /* save the user info to use from disable */
377
+ dev->active_link_user = entity;
378
+ dev->active_link_user_pipe = pipe;
379
+ pr_debug("%s owns the tuner %s can share!\n",
380
+ dev->active_link_owner->name,
381
+ entity->name);
366382 ret = 0;
367383 goto end;
368384 } else {
....@@ -389,7 +405,7 @@
389405 source = found_link->source->entity;
390406 ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
391407 if (ret) {
392
- pr_err("Activate tuner link %s->%s. Error %d\n",
408
+ pr_err("Activate link from %s->%s. Error %d\n",
393409 source->name, sink->name, ret);
394410 goto end;
395411 }
....@@ -399,25 +415,26 @@
399415 pr_err("Start Pipeline: %s->%s Error %d\n",
400416 source->name, entity->name, ret);
401417 ret = __media_entity_setup_link(found_link, 0);
402
- pr_err("Deactivate link Error %d\n", ret);
418
+ if (ret)
419
+ pr_err("Deactivate link Error %d\n", ret);
403420 goto end;
404421 }
405
- /*
406
- * save active link and active link owner to avoid audio
407
- * deactivating video owned link from disable_source and
408
- * vice versa
422
+
423
+ /* save link state to allow audio and video share the link
424
+ * and not disable the link while the other is using it.
425
+ * active_link_owner is used to deactivate the link.
409426 */
410427 dev->active_link = found_link;
411428 dev->active_link_owner = entity;
412429 dev->active_source = source;
413430 dev->active_sink = sink;
414431
415
- pr_debug("Enabled Source: %s->%s->%s Ret %d\n",
432
+ pr_info("Enabled Source: %s->%s->%s Ret %d\n",
416433 dev->active_source->name, dev->active_sink->name,
417434 dev->active_link_owner->name, ret);
418435 end:
419
- pr_debug("au0828_enable_source() end %s %d %d\n",
420
- entity->name, entity->function, ret);
436
+ pr_debug("%s end: ent:%s fnc:%d ret %d\n",
437
+ __func__, entity->name, entity->function, ret);
421438 return ret;
422439 }
423440
....@@ -436,21 +453,95 @@
436453 if (!dev->active_link)
437454 return;
438455
439
- /* link is active - stop pipeline from source (tuner) */
456
+ /* link is active - stop pipeline from source
457
+ * (tuner/s-video/Composite) to the entity
458
+ * When DVB/s-video/Composite owns tuner, it won't be in
459
+ * shared state.
460
+ */
440461 if (dev->active_link->sink->entity == dev->active_sink &&
441462 dev->active_link->source->entity == dev->active_source) {
442463 /*
443
- * prevent video from deactivating link when audio
444
- * has active pipeline
464
+ * Prevent video from deactivating link when audio
465
+ * has active pipeline and vice versa. In addition
466
+ * handle the case when more than one video/vbi
467
+ * application is sharing the link.
445468 */
469
+ bool owner_is_audio = false;
470
+
471
+ if (dev->active_link_owner->function ==
472
+ MEDIA_ENT_F_AUDIO_CAPTURE)
473
+ owner_is_audio = true;
474
+
475
+ if (dev->active_link_shared) {
476
+ pr_debug("Shared link owner %s user %s %d\n",
477
+ dev->active_link_owner->name,
478
+ entity->name, dev->users);
479
+
480
+ /* Handle video device users > 1
481
+ * When audio owns the shared link with
482
+ * more than one video users, avoid
483
+ * disabling the source and/or switching
484
+ * the owner until the last disable_source
485
+ * call from video _close(). Use dev->users to
486
+ * determine when to switch/disable.
487
+ */
488
+ if (dev->active_link_owner != entity) {
489
+ /* video device has users > 1 */
490
+ if (owner_is_audio && dev->users > 1)
491
+ return;
492
+
493
+ dev->active_link_user = NULL;
494
+ dev->active_link_user_pipe = NULL;
495
+ dev->active_link_shared = false;
496
+ return;
497
+ }
498
+
499
+ /* video owns the link and has users > 1 */
500
+ if (!owner_is_audio && dev->users > 1)
501
+ return;
502
+
503
+ /* stop pipeline */
504
+ __media_pipeline_stop(dev->active_link_owner);
505
+ pr_debug("Pipeline stop for %s\n",
506
+ dev->active_link_owner->name);
507
+
508
+ ret = __media_pipeline_start(
509
+ dev->active_link_user,
510
+ dev->active_link_user_pipe);
511
+ if (ret) {
512
+ pr_err("Start Pipeline: %s->%s %d\n",
513
+ dev->active_source->name,
514
+ dev->active_link_user->name,
515
+ ret);
516
+ goto deactivate_link;
517
+ }
518
+ /* link user is now the owner */
519
+ dev->active_link_owner = dev->active_link_user;
520
+ dev->active_link_user = NULL;
521
+ dev->active_link_user_pipe = NULL;
522
+ dev->active_link_shared = false;
523
+
524
+ pr_debug("Pipeline started for %s\n",
525
+ dev->active_link_owner->name);
526
+ return;
527
+ } else if (!owner_is_audio && dev->users > 1)
528
+ /* video/vbi owns the link and has users > 1 */
529
+ return;
530
+
446531 if (dev->active_link_owner != entity)
447532 return;
448
- __media_pipeline_stop(entity);
533
+
534
+ /* stop pipeline */
535
+ __media_pipeline_stop(dev->active_link_owner);
536
+ pr_debug("Pipeline stop for %s\n",
537
+ dev->active_link_owner->name);
538
+
539
+deactivate_link:
449540 ret = __media_entity_setup_link(dev->active_link, 0);
450541 if (ret)
451542 pr_err("Deactivate link Error %d\n", ret);
452543
453
- pr_debug("Disabled Source: %s->%s->%s Ret %d\n",
544
+ pr_info("Disabled Source: %s->%s->%s Ret %d\n",
454545 dev->active_source->name, dev->active_sink->name,
455546 dev->active_link_owner->name, ret);
456547
....@@ -458,6 +549,8 @@
458549 dev->active_link_owner = NULL;
459550 dev->active_source = NULL;
460551 dev->active_sink = NULL;
552
+ dev->active_link_shared = false;
553
+ dev->active_link_user = NULL;
461554 }
462555 }
463556 #endif
....@@ -478,6 +571,9 @@
478571 /* register media device */
479572 ret = media_device_register(dev->media_dev);
480573 if (ret) {
574
+ media_device_delete(dev->media_dev, KBUILD_MODNAME,
575
+ THIS_MODULE);
576
+ dev->media_dev = NULL;
481577 dev_err(&udev->dev,
482578 "Media Device Register Error: %d\n", ret);
483579 return ret;