diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-05 06:47:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-05 06:47:50 -0700 |
commit | 62d2def9a5143ba5c8cd009e7f07e5dfa79830d2 (patch) | |
tree | 722390bba0b1da0d98bdd686d1837d89c3b10d45 | |
parent | 1e1e5ce78ff0fb2b1b9296894883c82de29057d0 (diff) | |
parent | 405ddbfa68177b6169d09bc2308a39196a8eb64a (diff) | |
download | op-kernel-dev-62d2def9a5143ba5c8cd009e7f07e5dfa79830d2.zip op-kernel-dev-62d2def9a5143ba5c8cd009e7f07e5dfa79830d2.tar.gz |
Merge tag 'media/v4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media fixes from Mauro Carvalho Chehab:
"Some bug fixes on au0828 and snd-usb-audio:
- the au0828+snd-usb-audio MC patch broke several things and produced
some race conditions. Better to revert the patches, and re-work on
them for a next version
- fix a regression at tuner disable links logic
- properly handle dev_state as a bitmask"
* tag 'media/v4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
[media] Revert "[media] media: au0828 change to use Managed Media Controller API"
[media] Revert "[media] sound/usb: Use Media Controller API to share media resources"
[media] au0828: Fix dev_state handling
[media] au0828: fix au0828_v4l2_close() dev_state race condition
[media] media: au0828 fix to clear enable/disable/change source handlers
[media] v4l2-mc: cleanup a warning
[media] au0828: disable tuner links and cache tuner/decoder
-rw-r--r-- | drivers/media/usb/au0828/au0828-cards.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-core.c | 52 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-input.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-video.c | 63 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828.h | 9 | ||||
-rw-r--r-- | sound/usb/Kconfig | 4 | ||||
-rw-r--r-- | sound/usb/Makefile | 2 | ||||
-rw-r--r-- | sound/usb/card.c | 14 | ||||
-rw-r--r-- | sound/usb/card.h | 3 | ||||
-rw-r--r-- | sound/usb/media.c | 318 | ||||
-rw-r--r-- | sound/usb/media.h | 72 | ||||
-rw-r--r-- | sound/usb/mixer.h | 3 | ||||
-rw-r--r-- | sound/usb/pcm.c | 28 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 1 | ||||
-rw-r--r-- | sound/usb/stream.c | 2 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 6 |
16 files changed, 78 insertions, 507 deletions
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index ca861ae..6b469e8 100644 --- a/drivers/media/usb/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c @@ -228,10 +228,6 @@ void au0828_card_analog_fe_setup(struct au0828_dev *dev) "au8522", 0x8e >> 1, NULL); if (sd == NULL) pr_err("analog subdev registration failed\n"); -#ifdef CONFIG_MEDIA_CONTROLLER - if (sd) - dev->decoder = &sd->entity; -#endif } /* Setup tuners */ diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 5dc82e8..cc22b32 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -137,8 +137,14 @@ static void au0828_unregister_media_device(struct au0828_dev *dev) #ifdef CONFIG_MEDIA_CONTROLLER if (dev->media_dev && media_devnode_is_registered(&dev->media_dev->devnode)) { + /* clear enable_source, disable_source */ + dev->media_dev->source_priv = NULL; + dev->media_dev->enable_source = NULL; + dev->media_dev->disable_source = NULL; + media_device_unregister(dev->media_dev); media_device_cleanup(dev->media_dev); + kfree(dev->media_dev); dev->media_dev = NULL; } #endif @@ -166,7 +172,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) Set the status so poll routines can check and avoid access after disconnect. */ - dev->dev_state = DEV_DISCONNECTED; + set_bit(DEV_DISCONNECTED, &dev->dev_state); au0828_rc_unregister(dev); /* Digital TV */ @@ -192,7 +198,7 @@ static int au0828_media_device_init(struct au0828_dev *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - mdev = media_device_get_devres(&udev->dev); + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return -ENOMEM; @@ -456,7 +462,8 @@ static int au0828_media_device_register(struct au0828_dev *dev, { #ifdef CONFIG_MEDIA_CONTROLLER int ret; - struct media_entity *entity, *demod = NULL, *tuner = NULL; + struct media_entity *entity, *demod = NULL; + struct media_link *link; if (!dev->media_dev) return 0; @@ -482,26 +489,37 @@ static int au0828_media_device_register(struct au0828_dev *dev, } /* - * Find tuner and demod to disable the link between - * the two to avoid disable step when tuner is requested - * by video or audio. Note that this step can't be done - * until dvb graph is created during dvb register. + * Find tuner, decoder and demod. + * + * The tuner and decoder should be cached, as they'll be used by + * au0828_enable_source. + * + * It also needs to disable the link between tuner and + * decoder/demod, to avoid disable step when tuner is requested + * by video or audio. Note that this step can't be done until dvb + * graph is created during dvb register. */ media_device_for_each_entity(entity, dev->media_dev) { - if (entity->function == MEDIA_ENT_F_DTV_DEMOD) + switch (entity->function) { + case MEDIA_ENT_F_TUNER: + dev->tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + dev->decoder = entity; + break; + case MEDIA_ENT_F_DTV_DEMOD: demod = entity; - else if (entity->function == MEDIA_ENT_F_TUNER) - tuner = entity; + break; + } } - /* Disable link between tuner and demod */ - if (tuner && demod) { - struct media_link *link; - list_for_each_entry(link, &demod->links, list) { - if (link->sink->entity == demod && - link->source->entity == tuner) { + /* Disable link between tuner->demod and/or tuner->decoder */ + if (dev->tuner) { + list_for_each_entry(link, &dev->tuner->links, list) { + if (demod && link->sink->entity == demod) + media_entity_setup_link(link, 0); + if (dev->decoder && link->sink->entity == dev->decoder) media_entity_setup_link(link, 0); - } } } diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c index b0f0679..3d6687f 100644 --- a/drivers/media/usb/au0828/au0828-input.c +++ b/drivers/media/usb/au0828/au0828-input.c @@ -130,7 +130,7 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) bool first = true; /* do nothing if device is disconnected */ - if (ir->dev->dev_state == DEV_DISCONNECTED) + if (test_bit(DEV_DISCONNECTED, &ir->dev->dev_state)) return 0; /* Check IR int */ @@ -260,7 +260,7 @@ static void au0828_rc_stop(struct rc_dev *rc) cancel_delayed_work_sync(&ir->work); /* do nothing if device is disconnected */ - if (ir->dev->dev_state != DEV_DISCONNECTED) { + if (!test_bit(DEV_DISCONNECTED, &ir->dev->dev_state)) { /* Disable IR */ au8522_rc_clear(ir, 0xe0, 1 << 4); } diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 13f6dab..32d7db9 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -106,14 +106,13 @@ static inline void print_err_status(struct au0828_dev *dev, static int check_dev(struct au0828_dev *dev) { - if (dev->dev_state & DEV_DISCONNECTED) { + if (test_bit(DEV_DISCONNECTED, &dev->dev_state)) { pr_info("v4l2 ioctl: device not present\n"); return -ENODEV; } - if (dev->dev_state & DEV_MISCONFIGURED) { - pr_info("v4l2 ioctl: device is misconfigured; " - "close and open it again\n"); + if (test_bit(DEV_MISCONFIGURED, &dev->dev_state)) { + pr_info("v4l2 ioctl: device is misconfigured; close and open it again\n"); return -EIO; } return 0; @@ -521,8 +520,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) if (!dev) return 0; - if ((dev->dev_state & DEV_DISCONNECTED) || - (dev->dev_state & DEV_MISCONFIGURED)) + if (test_bit(DEV_DISCONNECTED, &dev->dev_state) || + test_bit(DEV_MISCONFIGURED, &dev->dev_state)) return 0; if (urb->status < 0) { @@ -824,10 +823,10 @@ static int au0828_stream_interrupt(struct au0828_dev *dev) int ret = 0; dev->stream_state = STREAM_INTERRUPT; - if (dev->dev_state == DEV_DISCONNECTED) + if (test_bit(DEV_DISCONNECTED, &dev->dev_state)) return -ENODEV; else if (ret) { - dev->dev_state = DEV_MISCONFIGURED; + set_bit(DEV_MISCONFIGURED, &dev->dev_state); dprintk(1, "%s device is misconfigured!\n", __func__); return ret; } @@ -1026,7 +1025,7 @@ static int au0828_v4l2_open(struct file *filp) int ret; dprintk(1, - "%s called std_set %d dev_state %d stream users %d users %d\n", + "%s called std_set %d dev_state %ld stream users %d users %d\n", __func__, dev->std_set_in_tuner_core, dev->dev_state, dev->streaming_users, dev->users); @@ -1045,7 +1044,7 @@ static int au0828_v4l2_open(struct file *filp) au0828_analog_stream_enable(dev); au0828_analog_stream_reset(dev); dev->stream_state = STREAM_OFF; - dev->dev_state |= DEV_INITIALIZED; + set_bit(DEV_INITIALIZED, &dev->dev_state); } dev->users++; mutex_unlock(&dev->lock); @@ -1059,7 +1058,7 @@ static int au0828_v4l2_close(struct file *filp) struct video_device *vdev = video_devdata(filp); dprintk(1, - "%s called std_set %d dev_state %d stream users %d users %d\n", + "%s called std_set %d dev_state %ld stream users %d users %d\n", __func__, dev->std_set_in_tuner_core, dev->dev_state, dev->streaming_users, dev->users); @@ -1075,7 +1074,7 @@ static int au0828_v4l2_close(struct file *filp) del_timer_sync(&dev->vbi_timeout); } - if (dev->dev_state == DEV_DISCONNECTED) + if (test_bit(DEV_DISCONNECTED, &dev->dev_state)) goto end; if (dev->users == 1) { @@ -1135,7 +1134,7 @@ static void au0828_init_tuner(struct au0828_dev *dev) .type = V4L2_TUNER_ANALOG_TV, }; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); if (dev->std_set_in_tuner_core) @@ -1207,7 +1206,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct video_device *vdev = video_devdata(file); struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); @@ -1250,7 +1249,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); f->fmt.pix.width = dev->width; @@ -1269,7 +1268,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); return au0828_set_format(dev, VIDIOC_TRY_FMT, f); @@ -1281,7 +1280,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct au0828_dev *dev = video_drvdata(file); int rc; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); rc = check_dev(dev); @@ -1303,7 +1302,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); if (norm == dev->std) @@ -1335,7 +1334,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); *norm = dev->std; @@ -1357,7 +1356,7 @@ static int vidioc_enum_input(struct file *file, void *priv, [AU0828_VMUX_DVB] = "DVB", }; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); tmp = input->index; @@ -1387,7 +1386,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); *i = dev->ctrl_input; @@ -1398,7 +1397,7 @@ static void au0828_s_input(struct au0828_dev *dev, int index) { int i; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); switch (AUVI_INPUT(index).type) { @@ -1496,7 +1495,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); a->index = dev->ctrl_ainput; @@ -1516,7 +1515,7 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio if (a->index != dev->ctrl_ainput) return -EINVAL; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); return 0; } @@ -1534,7 +1533,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (ret) return ret; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); strcpy(t->name, "Auvitek tuner"); @@ -1554,7 +1553,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, if (t->index != 0) return -EINVAL; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); au0828_init_tuner(dev); @@ -1576,7 +1575,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, if (freq->tuner != 0) return -EINVAL; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); freq->frequency = dev->ctrl_freq; return 0; @@ -1591,7 +1590,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (freq->tuner != 0) return -EINVAL; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); au0828_init_tuner(dev); @@ -1617,7 +1616,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); format->fmt.vbi.samples_per_line = dev->vbi_width; @@ -1643,7 +1642,7 @@ static int vidioc_cropcap(struct file *file, void *priv, if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); cc->bounds.left = 0; @@ -1665,7 +1664,7 @@ static int vidioc_g_register(struct file *file, void *priv, { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); reg->val = au0828_read(dev, reg->reg); @@ -1678,7 +1677,7 @@ static int vidioc_s_register(struct file *file, void *priv, { struct au0828_dev *dev = video_drvdata(file); - dprintk(1, "%s called std_set %d dev_state %d\n", __func__, + dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); return au0828_writereg(dev, reg->reg, reg->val); diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index ff7f851..87f3284 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -21,6 +21,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/bitops.h> #include <linux/usb.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -121,9 +122,9 @@ enum au0828_stream_state { /* device state */ enum au0828_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04 + DEV_INITIALIZED = 0, + DEV_DISCONNECTED = 1, + DEV_MISCONFIGURED = 2 }; struct au0828_dev; @@ -247,7 +248,7 @@ struct au0828_dev { int input_type; int std_set_in_tuner_core; unsigned int ctrl_input; - enum au0828_dev_state dev_state; + long unsigned int dev_state; /* defined at enum au0828_dev_state */; enum au0828_stream_state stream_state; wait_queue_head_t open; diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index d14bf41..a452ad7 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -15,7 +15,6 @@ config SND_USB_AUDIO select SND_RAWMIDI select SND_PCM select BITREVERSE - select SND_USB_AUDIO_USE_MEDIA_CONTROLLER if MEDIA_CONTROLLER && (MEDIA_SUPPORT=y || MEDIA_SUPPORT=SND_USB_AUDIO) help Say Y here to include support for USB audio and USB MIDI devices. @@ -23,9 +22,6 @@ config SND_USB_AUDIO To compile this driver as a module, choose M here: the module will be called snd-usb-audio. -config SND_USB_AUDIO_USE_MEDIA_CONTROLLER - bool - config SND_USB_UA101 tristate "Edirol UA-101/UA-1000 driver" select SND_PCM diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 8dca3c4..2d2d122 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -15,8 +15,6 @@ snd-usb-audio-objs := card.o \ quirks.o \ stream.o -snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o - snd-usbmidi-lib-objs := midi.o # Toplevel Module Dependency diff --git a/sound/usb/card.c b/sound/usb/card.c index 63244bb..3fc6358 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -66,7 +66,6 @@ #include "format.h" #include "power.h" #include "stream.h" -#include "media.h" MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); MODULE_DESCRIPTION("USB Audio"); @@ -612,11 +611,6 @@ static int usb_audio_probe(struct usb_interface *intf, if (err < 0) goto __error; - if (quirk->media_device) { - /* don't want to fail when media_snd_device_create() fails */ - media_snd_device_create(chip, intf); - } - usb_chip[chip->index] = chip; chip->num_interfaces++; usb_set_intfdata(intf, chip); @@ -673,14 +667,6 @@ static void usb_audio_disconnect(struct usb_interface *intf) list_for_each(p, &chip->midi_list) { snd_usbmidi_disconnect(p); } - /* - * Nice to check quirk && quirk->media_device - * need some special handlings. Doesn't look like - * we have access to quirk here - * Acceses mixer_list - */ - media_snd_device_delete(chip); - /* release mixer resources */ list_for_each_entry(mixer, &chip->mixer_list, list) { snd_usb_mixer_disconnect(mixer); diff --git a/sound/usb/card.h b/sound/usb/card.h index 34a0898..71778ca 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -105,8 +105,6 @@ struct snd_usb_endpoint { struct list_head list; }; -struct media_ctl; - struct snd_usb_substream { struct snd_usb_stream *stream; struct usb_device *dev; @@ -158,7 +156,6 @@ struct snd_usb_substream { } dsd_dop; bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */ - struct media_ctl *media_ctl; }; struct snd_usb_stream { diff --git a/sound/usb/media.c b/sound/usb/media.c deleted file mode 100644 index 93a50d01..0000000 --- a/sound/usb/media.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * media.c - Media Controller specific ALSA driver code - * - * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * This file is released under the GPLv2. - */ - -/* - * This file adds Media Controller support to ALSA driver - * to use the Media Controller API to share tuner with DVB - * and V4L2 drivers that control media device. Media device - * is created based on existing quirks framework. Using this - * approach, the media controller API usage can be added for - * a specific device. -*/ - -#include <linux/init.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include <sound/pcm.h> -#include <sound/core.h> - -#include "usbaudio.h" -#include "card.h" -#include "mixer.h" -#include "media.h" - -static int media_snd_enable_source(struct media_ctl *mctl) -{ - if (mctl && mctl->media_dev->enable_source) - return mctl->media_dev->enable_source(&mctl->media_entity, - &mctl->media_pipe); - return 0; -} - -static void media_snd_disable_source(struct media_ctl *mctl) -{ - if (mctl && mctl->media_dev->disable_source) - mctl->media_dev->disable_source(&mctl->media_entity); -} - -int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm, - int stream) -{ - struct media_device *mdev; - struct media_ctl *mctl; - struct device *pcm_dev = &pcm->streams[stream].dev; - u32 intf_type; - int ret = 0; - u16 mixer_pad; - struct media_entity *entity; - - mdev = subs->stream->chip->media_dev; - if (!mdev) - return -ENODEV; - - if (subs->media_ctl) - return 0; - - /* allocate media_ctl */ - mctl = kzalloc(sizeof(*mctl), GFP_KERNEL); - if (!mctl) - return -ENOMEM; - - mctl->media_dev = mdev; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK; - mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK; - mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE; - mixer_pad = 1; - } else { - intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE; - mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE; - mctl->media_pad.flags = MEDIA_PAD_FL_SINK; - mixer_pad = 2; - } - mctl->media_entity.name = pcm->name; - media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad); - ret = media_device_register_entity(mctl->media_dev, - &mctl->media_entity); - if (ret) - goto free_mctl; - - mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0, - MAJOR(pcm_dev->devt), - MINOR(pcm_dev->devt)); - if (!mctl->intf_devnode) { - ret = -ENOMEM; - goto unregister_entity; - } - mctl->intf_link = media_create_intf_link(&mctl->media_entity, - &mctl->intf_devnode->intf, - MEDIA_LNK_FL_ENABLED); - if (!mctl->intf_link) { - ret = -ENOMEM; - goto devnode_remove; - } - - /* create link between mixer and audio */ - media_device_for_each_entity(entity, mdev) { - switch (entity->function) { - case MEDIA_ENT_F_AUDIO_MIXER: - ret = media_create_pad_link(entity, mixer_pad, - &mctl->media_entity, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) - goto remove_intf_link; - break; - } - } - - subs->media_ctl = mctl; - return 0; - -remove_intf_link: - media_remove_intf_link(mctl->intf_link); -devnode_remove: - media_devnode_remove(mctl->intf_devnode); -unregister_entity: - media_device_unregister_entity(&mctl->media_entity); -free_mctl: - kfree(mctl); - return ret; -} - -void media_snd_stream_delete(struct snd_usb_substream *subs) -{ - struct media_ctl *mctl = subs->media_ctl; - - if (mctl && mctl->media_dev) { - struct media_device *mdev; - - mdev = subs->stream->chip->media_dev; - if (mdev && media_devnode_is_registered(&mdev->devnode)) { - media_devnode_remove(mctl->intf_devnode); - media_device_unregister_entity(&mctl->media_entity); - media_entity_cleanup(&mctl->media_entity); - } - kfree(mctl); - subs->media_ctl = NULL; - } -} - -int media_snd_start_pipeline(struct snd_usb_substream *subs) -{ - struct media_ctl *mctl = subs->media_ctl; - - if (mctl) - return media_snd_enable_source(mctl); - return 0; -} - -void media_snd_stop_pipeline(struct snd_usb_substream *subs) -{ - struct media_ctl *mctl = subs->media_ctl; - - if (mctl) - media_snd_disable_source(mctl); -} - -int media_snd_mixer_init(struct snd_usb_audio *chip) -{ - struct device *ctl_dev = &chip->card->ctl_dev; - struct media_intf_devnode *ctl_intf; - struct usb_mixer_interface *mixer; - struct media_device *mdev = chip->media_dev; - struct media_mixer_ctl *mctl; - u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL; - int ret; - - if (!mdev) - return -ENODEV; - - ctl_intf = chip->ctl_intf_media_devnode; - if (!ctl_intf) { - ctl_intf = media_devnode_create(mdev, intf_type, 0, - MAJOR(ctl_dev->devt), - MINOR(ctl_dev->devt)); - if (!ctl_intf) - return -ENOMEM; - chip->ctl_intf_media_devnode = ctl_intf; - } - - list_for_each_entry(mixer, &chip->mixer_list, list) { - - if (mixer->media_mixer_ctl) - continue; - - /* allocate media_mixer_ctl */ - mctl = kzalloc(sizeof(*mctl), GFP_KERNEL); - if (!mctl) - return -ENOMEM; - - mctl->media_dev = mdev; - mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER; - mctl->media_entity.name = chip->card->mixername; - mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK; - mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE; - mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE; - media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX, - mctl->media_pad); - ret = media_device_register_entity(mctl->media_dev, - &mctl->media_entity); - if (ret) { - kfree(mctl); - return ret; - } - - mctl->intf_link = media_create_intf_link(&mctl->media_entity, - &ctl_intf->intf, - MEDIA_LNK_FL_ENABLED); - if (!mctl->intf_link) { - media_device_unregister_entity(&mctl->media_entity); - media_entity_cleanup(&mctl->media_entity); - kfree(mctl); - return -ENOMEM; - } - mctl->intf_devnode = ctl_intf; - mixer->media_mixer_ctl = mctl; - } - return 0; -} - -static void media_snd_mixer_delete(struct snd_usb_audio *chip) -{ - struct usb_mixer_interface *mixer; - struct media_device *mdev = chip->media_dev; - - if (!mdev) - return; - - list_for_each_entry(mixer, &chip->mixer_list, list) { - struct media_mixer_ctl *mctl; - - mctl = mixer->media_mixer_ctl; - if (!mixer->media_mixer_ctl) - continue; - - if (media_devnode_is_registered(&mdev->devnode)) { - media_device_unregister_entity(&mctl->media_entity); - media_entity_cleanup(&mctl->media_entity); - } - kfree(mctl); - mixer->media_mixer_ctl = NULL; - } - if (media_devnode_is_registered(&mdev->devnode)) - media_devnode_remove(chip->ctl_intf_media_devnode); - chip->ctl_intf_media_devnode = NULL; -} - -int media_snd_device_create(struct snd_usb_audio *chip, - struct usb_interface *iface) -{ - struct media_device *mdev; - struct usb_device *usbdev = interface_to_usbdev(iface); - int ret; - - mdev = media_device_get_devres(&usbdev->dev); - if (!mdev) - return -ENOMEM; - if (!mdev->dev) { - /* register media device */ - mdev->dev = &usbdev->dev; - if (usbdev->product) - strlcpy(mdev->model, usbdev->product, - sizeof(mdev->model)); - if (usbdev->serial) - strlcpy(mdev->serial, usbdev->serial, - sizeof(mdev->serial)); - strcpy(mdev->bus_info, usbdev->devpath); - mdev->hw_revision = le16_to_cpu(usbdev->descriptor.bcdDevice); - media_device_init(mdev); - } - if (!media_devnode_is_registered(&mdev->devnode)) { - ret = media_device_register(mdev); - if (ret) { - dev_err(&usbdev->dev, - "Couldn't register media device. Error: %d\n", - ret); - return ret; - } - } - - /* save media device - avoid lookups */ - chip->media_dev = mdev; - - /* Create media entities for mixer and control dev */ - ret = media_snd_mixer_init(chip); - if (ret) { - dev_err(&usbdev->dev, - "Couldn't create media mixer entities. Error: %d\n", - ret); - - /* clear saved media_dev */ - chip->media_dev = NULL; - - return ret; - } - return 0; -} - -void media_snd_device_delete(struct snd_usb_audio *chip) -{ - struct media_device *mdev = chip->media_dev; - - media_snd_mixer_delete(chip); - - if (mdev) { - if (media_devnode_is_registered(&mdev->devnode)) - media_device_unregister(mdev); - chip->media_dev = NULL; - } -} diff --git a/sound/usb/media.h b/sound/usb/media.h deleted file mode 100644 index 1dcdcdc..0000000 --- a/sound/usb/media.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * media.h - Media Controller specific ALSA driver code - * - * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * This file is released under the GPLv2. - */ - -/* - * This file adds Media Controller support to ALSA driver - * to use the Media Controller API to share tuner with DVB - * and V4L2 drivers that control media device. Media device - * is created based on existing quirks framework. Using this - * approach, the media controller API usage can be added for - * a specific device. -*/ -#ifndef __MEDIA_H - -#ifdef CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER - -#include <media/media-device.h> -#include <media/media-entity.h> -#include <sound/asound.h> - -struct media_ctl { - struct media_device *media_dev; - struct media_entity media_entity; - struct media_intf_devnode *intf_devnode; - struct media_link *intf_link; - struct media_pad media_pad; - struct media_pipeline media_pipe; -}; - -/* - * One source pad each for SNDRV_PCM_STREAM_CAPTURE and - * SNDRV_PCM_STREAM_PLAYBACK. One for sink pad to link - * to AUDIO Source -*/ -#define MEDIA_MIXER_PAD_MAX (SNDRV_PCM_STREAM_LAST + 2) - -struct media_mixer_ctl { - struct media_device *media_dev; - struct media_entity media_entity; - struct media_intf_devnode *intf_devnode; - struct media_link *intf_link; - struct media_pad media_pad[MEDIA_MIXER_PAD_MAX]; - struct media_pipeline media_pipe; -}; - -int media_snd_device_create(struct snd_usb_audio *chip, - struct usb_interface *iface); -void media_snd_device_delete(struct snd_usb_audio *chip); -int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm, - int stream); -void media_snd_stream_delete(struct snd_usb_substream *subs); -int media_snd_start_pipeline(struct snd_usb_substream *subs); -void media_snd_stop_pipeline(struct snd_usb_substream *subs); -#else -static inline int media_snd_device_create(struct snd_usb_audio *chip, - struct usb_interface *iface) - { return 0; } -static inline void media_snd_device_delete(struct snd_usb_audio *chip) { } -static inline int media_snd_stream_init(struct snd_usb_substream *subs, - struct snd_pcm *pcm, int stream) - { return 0; } -static inline void media_snd_stream_delete(struct snd_usb_substream *subs) { } -static inline int media_snd_start_pipeline(struct snd_usb_substream *subs) - { return 0; } -static inline void media_snd_stop_pipeline(struct snd_usb_substream *subs) { } -#endif -#endif /* __MEDIA_H */ diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index f378944..3417ef3 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -3,8 +3,6 @@ #include <sound/info.h> -struct media_mixer_ctl; - struct usb_mixer_interface { struct snd_usb_audio *chip; struct usb_host_interface *hostif; @@ -24,7 +22,6 @@ struct usb_mixer_interface { struct urb *rc_urb; struct usb_ctrlrequest *rc_setup_packet; u8 rc_buffer[6]; - struct media_mixer_ctl *media_mixer_ctl; }; #define MAX_CHANNELS 16 /* max logical channels */ diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0e4e0640..44d178e 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -35,7 +35,6 @@ #include "pcm.h" #include "clock.h" #include "power.h" -#include "media.h" #define SUBSTREAM_FLAG_DATA_EP_STARTED 0 #define SUBSTREAM_FLAG_SYNC_EP_STARTED 1 @@ -718,14 +717,10 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, struct audioformat *fmt; int ret; - ret = media_snd_start_pipeline(subs); - if (ret) - return ret; - ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, params_buffer_bytes(hw_params)); if (ret < 0) - goto err_ret; + return ret; subs->pcm_format = params_format(hw_params); subs->period_bytes = params_period_bytes(hw_params); @@ -739,27 +734,22 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, dev_dbg(&subs->dev->dev, "cannot set format: format = %#x, rate = %d, channels = %d\n", subs->pcm_format, subs->cur_rate, subs->channels); - ret = -EINVAL; - goto err_ret; + return -EINVAL; } ret = snd_usb_lock_shutdown(subs->stream->chip); if (ret < 0) - goto err_ret; + return ret; ret = set_format(subs, fmt); snd_usb_unlock_shutdown(subs->stream->chip); if (ret < 0) - goto err_ret; + return ret; subs->interface = fmt->iface; subs->altset_idx = fmt->altset_idx; subs->need_setup_ep = true; return 0; - -err_ret: - media_snd_stop_pipeline(subs); - return ret; } /* @@ -771,7 +761,6 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) { struct snd_usb_substream *subs = substream->runtime->private_data; - media_snd_stop_pipeline(subs); subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; @@ -1232,7 +1221,6 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usb_substream *subs = &as->substream[direction]; - int ret; subs->interface = -1; subs->altset_idx = 0; @@ -1246,12 +1234,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) subs->dsd_dop.channel = 0; subs->dsd_dop.marker = 1; - ret = setup_hw_info(runtime, subs); - if (ret == 0) - ret = media_snd_stream_init(subs, as->pcm, direction); - if (ret) - snd_usb_autosuspend(subs->stream->chip); - return ret; + return setup_hw_info(runtime, subs); } static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) @@ -1260,7 +1243,6 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) struct snd_usb_substream *subs = &as->substream[direction]; stop_endpoints(subs, true); - media_snd_stop_pipeline(subs); if (subs->interface >= 0 && !snd_usb_lock_shutdown(subs->stream->chip)) { diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 9d087b1..c60a776 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2886,7 +2886,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), .product_name = pname, \ .ifnum = QUIRK_ANY_INTERFACE, \ .type = QUIRK_AUDIO_ALIGN_TRANSFER, \ - .media_device = 1, \ } \ } diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 6fe7f21..8e9548bc 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -36,7 +36,6 @@ #include "format.h" #include "clock.h" #include "stream.h" -#include "media.h" /* * free a substream @@ -53,7 +52,6 @@ static void free_substream(struct snd_usb_substream *subs) kfree(fp); } kfree(subs->rate_list.list); - media_snd_stream_delete(subs); } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index a161c7c..b665d85 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -30,9 +30,6 @@ * */ -struct media_device; -struct media_intf_devnode; - struct snd_usb_audio { int index; struct usb_device *dev; @@ -63,8 +60,6 @@ struct snd_usb_audio { bool autoclock; /* from the 'autoclock' module param */ struct usb_host_interface *ctrl_intf; /* the audio control interface */ - struct media_device *media_dev; - struct media_intf_devnode *ctl_intf_media_devnode; }; #define usb_audio_err(chip, fmt, args...) \ @@ -115,7 +110,6 @@ struct snd_usb_audio_quirk { const char *product_name; int16_t ifnum; uint16_t type; - bool media_device; const void *data; }; |