Ejemplo n.º 1
0
/* add firmware name into devres list */
static int fw_add_devm_name(struct device *dev, const char *name)
{
	struct fw_name_devm *fwn;

	fwn = fw_find_devm_name(dev, name);
	if (fwn)
		return 1;

	fwn = devres_alloc(fw_name_devm_release, sizeof(struct fw_name_devm) +
			   strlen(name) + 1, GFP_KERNEL);
	if (!fwn)
		return -ENOMEM;

	fwn->magic = (unsigned long)&fw_cache;
	strcpy(fwn->name, name);
	devres_add(dev, fwn);

	return 0;
}
Ejemplo n.º 2
0
/**
 * devm_snd_soc_register_card - resource managed card registration
 * @dev: Device used to manage card
 * @card: Card to register
 *
 * Register a card with automatic unregistration when the device is
 * unregistered.
 */
int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
{
	struct snd_soc_card **ptr;
	int ret;

	ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return -ENOMEM;

	ret = snd_soc_register_card(card);
	if (ret == 0) {
		*ptr = card;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return ret;
}
Ejemplo n.º 3
0
int devm_register_reboot_notifier(struct device *dev, struct notifier_block *nb)
{
	struct notifier_block **rcnb;
	int ret;

	rcnb = devres_alloc(devm_unregister_reboot_notifier,
			    sizeof(*rcnb), GFP_KERNEL);
	if (!rcnb)
		return -ENOMEM;

	ret = register_reboot_notifier(nb);
	if (!ret) {
		*rcnb = nb;
		devres_add(dev, rcnb);
	} else {
		devres_free(rcnb);
	}

	return ret;
}
Ejemplo n.º 4
0
/**
 * devm_snd_soc_register_platform - resource managed platform registration
 * @dev: Device used to manage platform
 * @platform_drv: platform to register
 *
 * Register a platform driver with automatic unregistration when the device is
 * unregistered.
 */
int devm_snd_soc_register_platform(struct device *dev,
			const struct snd_soc_platform_driver *platform_drv)
{
	struct device **ptr;
	int ret;

	ptr = devres_alloc(devm_platform_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return -ENOMEM;

	ret = snd_soc_register_platform(dev, platform_drv);
	if (ret == 0) {
		*ptr = dev;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return ret;
}
Ejemplo n.º 5
0
/**
 * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration
 * @dev: The parent device for the PCM device
 * @config: Platform specific PCM configuration
 * @flags: Platform specific quirks
 *
 * Register a dmaengine based PCM device with automatic unregistration when the
 * device is unregistered.
 */
int devm_snd_dmaengine_pcm_register(struct device *dev,
	const struct snd_dmaengine_pcm_config *config, unsigned int flags)
{
	struct device **ptr;
	int ret;

	ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return -ENOMEM;

	ret = snd_dmaengine_pcm_register(dev, config, flags);
	if (ret == 0) {
		*ptr = dev;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return ret;
}
Ejemplo n.º 6
0
static int bcm2835_devm_add_vchi_ctx(struct device *dev)
{
	struct bcm2835_vchi_ctx *vchi_ctx;
	int ret;

	vchi_ctx = devres_alloc(bcm2835_devm_free_vchi_ctx, sizeof(*vchi_ctx),
				GFP_KERNEL);
	if (!vchi_ctx)
		return -ENOMEM;

	ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
	if (ret) {
		devres_free(vchi_ctx);
		return ret;
	}

	devres_add(dev, vchi_ctx);

	return 0;
}
Ejemplo n.º 7
0
int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
{
	unsigned *dr;
	int rc;

	dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
	if (!dr)
		return -ENOMEM;

	rc = gpio_request(gpio, label);
	if (rc) {
		devres_free(dr);
		return rc;
	}

	*dr = gpio;
	devres_add(dev, dr);

	return 0;
}
Ejemplo n.º 8
0
/**
 * devm_ioremap_exec_nocache - Managed ioremap_exec_nocache()
 * @dev: Generic device to remap IO address for
 * @offset: BUS offset to map
 * @size: Size of map
 *
 * Managed ioremap_exec_nocache().  Map is automatically unmapped on driver
 * detach.
 */
void __iomem *devm_ioremap_exec_nocache(struct device *dev,
					resource_size_t offset,
					unsigned long size)
{
	void __iomem **ptr, *addr;

	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return NULL;

	addr = ioremap_exec_nocache(offset, size);
	if (addr) {
		*ptr = addr;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return addr;
}
Ejemplo n.º 9
0
static int snd_devm_add_child(struct device *dev, struct device *child)
{
	struct device **dr;
	int ret;

	dr = devres_alloc(snd_devm_unregister_child, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return -ENOMEM;

	ret = device_add(child);
	if (ret) {
		devres_free(dr);
		return ret;
	}

	*dr = child;
	devres_add(dev, dr);

	return 0;
}
Ejemplo n.º 10
0
/**
 * devm_snd_soc_register_component - resource managed component registration
 * @dev: Device used to manage component
 * @cmpnt_drv: Component driver
 * @dai_drv: DAI driver
 * @num_dai: Number of DAIs to register
 *
 * Register a component with automatic unregistration when the device is
 * unregistered.
 */
int devm_snd_soc_register_component(struct device *dev,
			 const struct snd_soc_component_driver *cmpnt_drv,
			 struct snd_soc_dai_driver *dai_drv, int num_dai)
{
	struct device **ptr;
	int ret;

	ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return -ENOMEM;

	ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
	if (ret == 0) {
		*ptr = dev;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return ret;
}
Ejemplo n.º 11
0
static struct snd_card *snd_devm_card_new(struct device *dev)
{
	struct snd_card **dr;
	struct snd_card *card;
	int ret;

	dr = devres_alloc(snd_devm_card_free, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return ERR_PTR(-ENOMEM);

	ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
	if (ret) {
		devres_free(dr);
		return ERR_PTR(ret);
	}

	*dr = card;
	devres_add(dev, dr);

	return card;
}
Ejemplo n.º 12
0
struct stm_device_state *devm_stm_device_init(struct device *dev,
	struct stm_device_config *config)
{
	struct stm_device_state *state = devres_alloc(stm_device_devres_exit,
			sizeof(*state) + sizeof(*state->sysconf_fields) *
			config->sysconfs_num, GFP_KERNEL);

	BUG_ON(!dev);
	BUG_ON(!config);

	if (state) {
		if (__stm_device_init(state, config, dev) == 0) {
			devres_add(dev, state);
		} else {
			devres_free(state);
			state = NULL;
		}
	}

	return state;
}
Ejemplo n.º 13
0
/**
 * irq_sim_init - Initialize the interrupt simulator for a managed device.
 *
 * @dev:        Device to initialize the simulator object for.
 * @sim:        The interrupt simulator object to initialize.
 * @num_irqs:   Number of interrupts to allocate
 *
 * Returns 0 on success and a negative error number on failure.
 */
int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
		      unsigned int num_irqs)
{
	struct irq_sim_devres *dr;
	int rv;

	dr = devres_alloc(devm_irq_sim_release, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return -ENOMEM;

	rv = irq_sim_init(sim, num_irqs);
	if (rv) {
		devres_free(dr);
		return rv;
	}

	dr->sim = sim;
	devres_add(dev, dr);

	return 0;
}
Ejemplo n.º 14
0
Archivo: eth.c Proyecto: krzk/linux
struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv,
					   unsigned int txqs, unsigned int rxqs)
{
	struct net_device **dr;
	struct net_device *netdev;

	dr = devres_alloc(devm_free_netdev, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return NULL;

	netdev = alloc_etherdev_mqs(sizeof_priv, txqs, rxqs);
	if (!netdev) {
		devres_free(dr);
		return NULL;
	}

	*dr = netdev;
	devres_add(dev, dr);

	return netdev;
}
Ejemplo n.º 15
0
/**
 * devm_led_classdev_register - resource managed led_classdev_register()
 * @parent: The device to register.
 * @led_cdev: the led_classdev structure for this device.
 */
int devm_led_classdev_register(struct device *parent,
			       struct led_classdev *led_cdev)
{
	struct led_classdev **dr;
	int rc;

	dr = devres_alloc(devm_led_classdev_release, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return -ENOMEM;

	rc = led_classdev_register(parent, led_cdev);
	if (rc) {
		devres_free(dr);
		return rc;
	}

	*dr = led_cdev;
	devres_add(parent, dr);

	return 0;
}
/**
 * devm_regulator_register - Resource managed regulator_register()
 * @regulator_desc: regulator to register
 * @config: runtime configuration for regulator
 *
 * Called by regulator drivers to register a regulator.  Returns a
 * valid pointer to struct regulator_dev on success or an ERR_PTR() on
 * error.  The regulator will automatically be released when the device
 * is unbound.
 */
struct regulator_dev *devm_regulator_register(struct device *dev,
				  const struct regulator_desc *regulator_desc,
				  const struct regulator_config *config)
{
	struct regulator_dev **ptr, *rdev;

	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
			   GFP_KERNEL);
	if (!ptr)
		return ERR_PTR(-ENOMEM);

	rdev = regulator_register(regulator_desc, config);
	if (!IS_ERR(rdev)) {
		*ptr = rdev;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return rdev;
}
Ejemplo n.º 17
0
struct dentry* devm_hello_create_u32(struct device *dev, const char *name, umode_t mode, struct dentry *parent, u32 *pvalue)
{
	struct dentry *pu32 = NULL;\
	void *ptr = NULL;

	if(!pvalue || !name || name[0] == '\0')
		return NULL;

	ptr = devres_alloc(devm_hello_release, 0, GFP_KERNEL);
	if (!ptr)
		return NULL;

	pu32 = debugfs_create_u32(name, mode, parent, pvalue);
	if (pu32) {
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return pu32;
}
Ejemplo n.º 18
0
int devm_rave_sp_register_event_notifier(struct device *dev,
					 struct notifier_block *nb)
{
	struct rave_sp *sp = dev_get_drvdata(dev->parent);
	struct notifier_block **rcnb;
	int ret;

	rcnb = devres_alloc(rave_sp_unregister_event_notifier,
			    sizeof(*rcnb), GFP_KERNEL);
	if (!rcnb)
		return -ENOMEM;

	ret = blocking_notifier_chain_register(&sp->event_notifier_list, nb);
	if (!ret) {
		*rcnb = nb;
		devres_add(dev, rcnb);
	} else {
		devres_free(rcnb);
	}

	return ret;
}
Ejemplo n.º 19
0
/**
 * devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
 *					    device's child node
 * @dev:	GPIO consumer
 * @con_id:	function within the GPIO consumer
 * @index:	index of the GPIO to obtain in the consumer
 * @child:	firmware node (child of @dev)
 * @flags:	GPIO initialization flags
 *
 * GPIO descriptors returned from this function are automatically disposed on
 * driver detach.
 *
 * On successfull request the GPIO pin is configured in accordance with
 * provided @flags.
 */
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
						const char *con_id, int index,
						struct fwnode_handle *child,
						enum gpiod_flags flags,
						const char *label)
{
	char prop_name[32]; /* 32 is max size of property name */
	struct gpio_desc **dr;
	struct gpio_desc *desc;
	unsigned int i;

	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
			  GFP_KERNEL);
	if (!dr)
		return ERR_PTR(-ENOMEM);

	for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
		if (con_id)
			snprintf(prop_name, sizeof(prop_name), "%s-%s",
					    con_id, gpio_suffixes[i]);
		else
			snprintf(prop_name, sizeof(prop_name), "%s",
					    gpio_suffixes[i]);

		desc = fwnode_get_named_gpiod(child, prop_name, index, flags,
					      label);
		if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
			break;
	}
	if (IS_ERR(desc)) {
		devres_free(dr);
		return desc;
	}

	*dr = desc;
	devres_add(dev, dr);

	return desc;
}
Ejemplo n.º 20
0
int __must_check devm_clk_bulk_get_all(struct device *dev,
				       struct clk_bulk_data **clks)
{
	struct clk_bulk_devres *devres;
	int ret;

	devres = devres_alloc(devm_clk_bulk_release,
			      sizeof(*devres), GFP_KERNEL);
	if (!devres)
		return -ENOMEM;

	ret = clk_bulk_get_all(dev, &devres->clks);
	if (ret > 0) {
		*clks = devres->clks;
		devres->num_clks = ret;
		devres_add(dev, devres);
	} else {
		devres_free(devres);
	}

	return ret;
}
Ejemplo n.º 21
0
/**
 * devm_thermal_zone_of_sensor_register - Resource managed version of
 *				thermal_zone_of_sensor_register()
 * @dev: a valid struct device pointer of a sensor device. Must contain
 *       a valid .of_node, for the sensor node.
 * @sensor_id: a sensor identifier, in case the sensor IP has more
 *	       than one sensors
 * @data: a private pointer (owned by the caller) that will be passed
 *	  back, when a temperature reading is needed.
 * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
 *
 * Refer thermal_zone_of_sensor_register() for more details.
 *
 * Return: On success returns a valid struct thermal_zone_device,
 * otherwise, it returns a corresponding ERR_PTR(). Caller must
 * check the return value with help of IS_ERR() helper.
 * Registered thermal_zone_device device will automatically be
 * released when device is unbounded.
 */
struct thermal_zone_device *devm_thermal_zone_of_sensor_register(
	struct device *dev, int sensor_id,
	void *data, const struct thermal_zone_of_device_ops *ops)
{
	struct thermal_zone_device **ptr, *tzd;

	ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr),
			   GFP_KERNEL);
	if (!ptr)
		return ERR_PTR(-ENOMEM);

	tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops);
	if (IS_ERR(tzd)) {
		devres_free(ptr);
		return tzd;
	}

	*ptr = tzd;
	devres_add(dev, ptr);

	return tzd;
}
Ejemplo n.º 22
0
struct dentry* devm_hello_create_dir(struct device *dev, const char *name, struct dentry *parent)
{

	struct dentry *dir = NULL;
	void *ptr = NULL;

	if(!name || name[0] == '\0')
		return NULL;

	ptr = devres_alloc(devm_hello_release, 0, GFP_KERNEL);
	if (!ptr)
		return NULL;

	dir = debugfs_create_dir(name, parent);
	if (dir) {
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return dir;
}
Ejemplo n.º 23
0
static int ux500_pd_bus_notify(struct notifier_block *nb,
				unsigned long action,
				void *data,
				bool enable)
{
	struct device *dev = data;
	struct pm_runtime_data *prd;

	dev_dbg(dev, "%s() %ld !\n", __func__, action);

	if (action == BUS_NOTIFY_BIND_DRIVER) {
		prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL);
		if (prd) {
			devres_add(dev, prd);
			platform_pm_runtime_init(dev, prd);
			if (enable)
				ux500_pd_enable(prd);
		} else
			dev_err(dev, "unable to alloc memory for runtime pm\n");
	}

	return 0;
}
Ejemplo n.º 24
0
Archivo: led.c Proyecto: 03199618/linux
/* Register CAN LED triggers for a CAN device
 *
 * This is normally called from a driver's probe function
 */
void devm_can_led_init(struct net_device *netdev)
{
	struct can_priv *priv = netdev_priv(netdev);
	void *res;

	res = devres_alloc(can_led_release, 0, GFP_KERNEL);
	if (!res) {
		netdev_err(netdev, "cannot register LED triggers\n");
		return;
	}

	snprintf(priv->tx_led_trig_name, sizeof(priv->tx_led_trig_name),
		 "%s-tx", netdev->name);
	snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name),
		 "%s-rx", netdev->name);

	led_trigger_register_simple(priv->tx_led_trig_name,
				    &priv->tx_led_trig);
	led_trigger_register_simple(priv->rx_led_trig_name,
				    &priv->rx_led_trig);

	devres_add(&netdev->dev, res);
}
Ejemplo n.º 25
0
/**
 * devm_gpiod_get_array - Resource-managed gpiod_get_array()
 * @dev:	GPIO consumer
 * @con_id:	function within the GPIO consumer
 * @flags:	optional GPIO initialization flags
 *
 * Managed gpiod_get_array(). GPIO descriptors returned from this function are
 * automatically disposed on driver detach. See gpiod_get_array() for detailed
 * information about behavior and return values.
 */
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
						     const char *con_id,
						     enum gpiod_flags flags)
{
	struct gpio_descs **dr;
	struct gpio_descs *descs;

	dr = devres_alloc(devm_gpiod_release_array,
			  sizeof(struct gpio_descs *), GFP_KERNEL);
	if (!dr)
		return ERR_PTR(-ENOMEM);

	descs = gpiod_get_array(dev, con_id, flags);
	if (IS_ERR(descs)) {
		devres_free(dr);
		return descs;
	}

	*dr = descs;
	devres_add(dev, dr);

	return descs;
}
Ejemplo n.º 26
0
/**
 * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
 * @dev:	GPIO consumer
 * @con_id:	function within the GPIO consumer
 * @child:	firmware node (child of @dev)
 *
 * GPIO descriptors returned from this function are automatically disposed on
 * driver detach.
 */
struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
        const char *con_id,
        struct fwnode_handle *child)
{
    static const char * const suffixes[] = { "gpios", "gpio" };
    char prop_name[32]; /* 32 is max size of property name */
    struct gpio_desc **dr;
    struct gpio_desc *desc;
    unsigned int i;

    dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
                      GFP_KERNEL);
    if (!dr)
        return ERR_PTR(-ENOMEM);

    for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
        if (con_id)
            snprintf(prop_name, sizeof(prop_name), "%s-%s",
                     con_id, suffixes[i]);
        else
            snprintf(prop_name, sizeof(prop_name), "%s",
                     suffixes[i]);

        desc = fwnode_get_named_gpiod(child, prop_name);
        if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
            break;
    }
    if (IS_ERR(desc)) {
        devres_free(dr);
        return desc;
    }

    *dr = desc;
    devres_add(dev, dr);

    return desc;
}
Ejemplo n.º 27
0
/**
 * devm_input_allocate_polled_device - allocate managed polled device
 * @dev: device owning the polled device being created
 *
 * Returns prepared &struct input_polled_dev or %NULL.
 *
 * Managed polled input devices do not need to be explicitly unregistered
 * or freed as it will be done automatically when owner device unbinds
 * from * its driver (or binding fails). Once such managed polled device
 * is allocated, it is ready to be set up and registered in the same
 * fashion as regular polled input devices (using
 * input_register_polled_device() function).
 *
 * If you want to manually unregister and free such managed polled devices,
 * it can be still done by calling input_unregister_polled_device() and
 * input_free_polled_device(), although it is rarely needed.
 *
 * NOTE: the owner device is set up as parent of input device and users
 * should not override it.
 */
struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev)
{
	struct input_polled_dev *polldev;
	struct input_polled_devres *devres;

	devres = devres_alloc(devm_input_polldev_release, sizeof(*devres),
			      GFP_KERNEL);
	if (!devres)
		return NULL;

	polldev = input_allocate_polled_device();
	if (!polldev) {
		devres_free(devres);
		return NULL;
	}

	polldev->input->dev.parent = dev;
	polldev->devres_managed = true;

	devres->polldev = polldev;
	devres_add(dev, devres);

	return polldev;
}
Ejemplo n.º 28
0
void *devm_memremap_pages(struct device *dev, struct resource *res)
{
	int is_ram = region_intersects(res->start, resource_size(res),
			"System RAM");
	struct page_map *page_map;
	int error, nid;

	if (is_ram == REGION_MIXED) {
		WARN_ONCE(1, "%s attempted on mixed region %pr\n",
				__func__, res);
		return ERR_PTR(-ENXIO);
	}

	if (is_ram == REGION_INTERSECTS)
		return __va(res->start);

	page_map = devres_alloc(devm_memremap_pages_release,
			sizeof(*page_map), GFP_KERNEL);
	if (!page_map)
		return ERR_PTR(-ENOMEM);

	memcpy(&page_map->res, res, sizeof(*res));

	nid = dev_to_node(dev);
	if (nid < 0)
		nid = 0;

	error = arch_add_memory(nid, res->start, resource_size(res), true);
	if (error) {
		devres_free(page_map);
		return ERR_PTR(error);
	}

	devres_add(dev, page_map);
	return __va(res->start);
}
Ejemplo n.º 29
0
/**
 * devm_gpiod_get_index - Resource-managed gpiod_get_index()
 * @dev:	GPIO consumer
 * @con_id:	function within the GPIO consumer
 * @idx:	index of the GPIO to obtain in the consumer
 * @flags:	optional GPIO initialization flags
 *
 * Managed gpiod_get_index(). GPIO descriptors returned from this function are
 * automatically disposed on driver detach. See gpiod_get_index() for detailed
 * information about behavior and return values.
 */
struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
						    const char *con_id,
						    unsigned int idx,
						    enum gpiod_flags flags)
{
	struct gpio_desc **dr;
	struct gpio_desc *desc;

	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
			  GFP_KERNEL);
	if (!dr)
		return ERR_PTR(-ENOMEM);

	desc = gpiod_get_index(dev, con_id, idx, flags);
	if (IS_ERR(desc)) {
		devres_free(dr);
		return desc;
	}

	*dr = desc;
	devres_add(dev, dr);

	return desc;
}
Ejemplo n.º 30
0
/**
 * snd_hdac_acomp_init - Initialize audio component
 * @bus: HDA core bus
 * @match_master: match function for finding components
 * @extra_size: Extra bytes to allocate
 *
 * This function is supposed to be used only by a HD-audio controller
 * driver that needs the interaction with graphics driver.
 *
 * This function initializes and sets up the audio component to communicate
 * with graphics driver.
 *
 * Unlike snd_hdac_i915_init(), this function doesn't synchronize with the
 * binding with the DRM component.  Each caller needs to sync via master_bind
 * audio_ops.
 *
 * Returns zero for success or a negative error code.
 */
int snd_hdac_acomp_init(struct hdac_bus *bus,
			const struct drm_audio_component_audio_ops *aops,
			int (*match_master)(struct device *, void *),
			size_t extra_size)
{
	struct component_match *match = NULL;
	struct device *dev = bus->dev;
	struct drm_audio_component *acomp;
	int ret;

	if (WARN_ON(hdac_get_acomp(dev)))
		return -EBUSY;

	acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size,
			     GFP_KERNEL);
	if (!acomp)
		return -ENOMEM;
	acomp->audio_ops = aops;
	bus->audio_component = acomp;
	devres_add(dev, acomp);

	component_match_add(dev, &match, match_master, bus);
	ret = component_master_add_with_match(dev, &hdac_component_master_ops,
					      match);
	if (ret < 0)
		goto out_err;

	return 0;

out_err:
	bus->audio_component = NULL;
	devres_destroy(dev, hdac_acomp_release, NULL, NULL);
	dev_info(dev, "failed to add audio component master (%d)\n", ret);

	return ret;
}