Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7448a8d authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

V4L/DVB (6952): Add code for autoloading em28xx-alsa, if needed



Older em28xx devices does implement standard Audio Class.

However, on newer devices, this were replaced by a Vendor Class. This
patch autodetects that an em28xx lacks Audio Class and auto-loads
em28xx-alsa, for the devices that implements only a Vendor Class.

For devices with Audio Class, snd-usb-audio module will provide an ALSA
interface.

This patch uses the request_module_async function as defined on cx88-mpeg.c, 
originally wrote by Markus Rechberger.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 6d79468d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -472,7 +472,6 @@ static struct em28xx_ops audio_ops = {

static int __init em28xx_alsa_register(void)
{
	request_module("em28xx");
	return em28xx_register_extension(&audio_ops);
}

+38 −0
Original line number Diff line number Diff line
@@ -1668,6 +1668,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
	dev->em28xx_read_reg_req = em28xx_read_reg_req;
	dev->is_em2800 = em28xx_boards[dev->model].is_em2800;

	errCode = em28xx_read_reg(dev, CHIPID_REG);
	if (errCode >= 0)
		em28xx_info("em28xx chip ID = %d\n", errCode);

	em28xx_pre_card_setup(dev);

	errCode = em28xx_config(dev);
@@ -1794,6 +1798,25 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
	return 0;
}

#if defined(CONFIG_MODULES) && defined(MODULE)
static void request_module_async(struct work_struct *work)
{
	struct em28xx *dev = container_of(work,
			     struct em28xx, request_module_wk);

	if (!dev->has_audio_class)
		request_module("em28xx-alsa");
}

static void request_modules(struct em28xx *dev)
{
	INIT_WORK(&dev->request_module_wk, request_module_async);
	schedule_work(&dev->request_module_wk);
}
#else
#define request_modules(dev)
#endif /* CONFIG_MODULES */

/*
 * em28xx_usb_probe()
 * checks for supported devices
@@ -1864,6 +1887,18 @@ static int em28xx_usb_probe(struct usb_interface *interface,
	dev->devno = nr;
	dev->model = id->driver_info;

	/* Checks if audio is provided by some interface */
	for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
		uif = udev->config->interface[i];
		if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
			dev->has_audio_class = 1;
			break;
		}
	}

	printk(KERN_INFO DRIVER_NAME " %s usb audio class\n",
		   dev->has_audio_class ? "Has" : "Doesn't have");

	/* compute alternate max packet sizes */
	uif = udev->actconfig->interface[0];

@@ -1900,6 +1935,9 @@ static int em28xx_usb_probe(struct usb_interface *interface,

	/* save our data pointer in this interface device */
	usb_set_intfdata(interface, dev);

	request_modules(dev);

	return 0;
}

+3 −0
Original line number Diff line number Diff line
@@ -246,6 +246,7 @@ struct em28xx {
	unsigned int has_msp34xx:1;
	unsigned int has_tda9887:1;
	unsigned int stream_on:1;	/* Locks streams */
	unsigned int has_audio_class:1;

	int video_inputs;	/* number of video inputs */
	struct list_head	devlist;
@@ -295,6 +296,8 @@ struct em28xx {
	enum em28xx_stream_state stream;
	enum em28xx_io_method io;

	struct work_struct         request_module_wk;

	/* locks */
	struct mutex lock;
	spinlock_t queue_lock;