lkml.org 
[lkml]   [2017]   [Aug]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 06/11] ALSA: vsnd: Introduce ALSA virtual sound driver
    Date
    From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>

    Implement essential initialization of the sound driver:
    - introduce required data structures
    - handle driver registration
    - handle sound card registration
    - register sound driver on backend connection
    - remove sound driver on backend disconnect

    Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
    ---
    sound/drivers/xen-front.c | 161 +++++++++++++++++++++++++++++++++++++++++++++-
    1 file changed, 159 insertions(+), 2 deletions(-)

    diff --git a/sound/drivers/xen-front.c b/sound/drivers/xen-front.c
    index 04ebc15757f4..f3e3f64f0aa6 100644
    --- a/sound/drivers/xen-front.c
    +++ b/sound/drivers/xen-front.c
    @@ -19,13 +19,14 @@
    */

    #include <linux/module.h>
    +#include <linux/platform_device.h>

    #include <sound/core.h>
    #include <sound/pcm.h>

    -#include <xen/platform_pci.h>
    #include <xen/events.h>
    #include <xen/grant_table.h>
    +#include <xen/platform_pci.h>
    #include <xen/xen.h>
    #include <xen/xenbus.h>

    @@ -66,6 +67,33 @@ struct sh_buf_info {
    size_t vbuffer_sz;
    };

    +struct sdev_pcm_stream_info {
    + int unique_id;
    + struct snd_pcm_hardware pcm_hw;
    + struct xdrv_evtchnl_info *evt_chnl;
    + bool is_open;
    + uint8_t req_next_id;
    + struct sh_buf_info sh_buf;
    +};
    +
    +struct sdev_pcm_instance_info {
    + struct sdev_card_info *card_info;
    + struct snd_pcm *pcm;
    + struct snd_pcm_hardware pcm_hw;
    + int num_pcm_streams_pb;
    + struct sdev_pcm_stream_info *streams_pb;
    + int num_pcm_streams_cap;
    + struct sdev_pcm_stream_info *streams_cap;
    +};
    +
    +struct sdev_card_info {
    + struct xdrv_info *xdrv_info;
    + struct snd_card *card;
    + struct snd_pcm_hardware pcm_hw;
    + int num_pcm_instances;
    + struct sdev_pcm_instance_info *pcm_instances;
    +};
    +
    struct cfg_stream {
    int unique_id;
    char *xenstore_path;
    @@ -99,6 +127,8 @@ struct xdrv_info {
    struct xenbus_device *xb_dev;
    spinlock_t io_lock;
    struct mutex mutex;
    + bool sdrv_registered;
    + struct platform_device *sdrv_pdev;
    int num_evt_channels;
    struct xdrv_evtchnl_info *evt_chnls;
    struct sdev_card_plat_data cfg_plat_data;
    @@ -138,6 +168,132 @@ static struct snd_pcm_hardware sdrv_pcm_hw_default = {
    .fifo_size = 0,
    };

    +static int sdrv_new_pcm(struct sdev_card_info *card_info,
    + struct cfg_pcm_instance *instance_config,
    + struct sdev_pcm_instance_info *pcm_instance_info)
    +{
    + return 0;
    +}
    +
    +static int sdrv_probe(struct platform_device *pdev)
    +{
    + struct sdev_card_info *card_info;
    + struct sdev_card_plat_data *platdata;
    + struct snd_card *card;
    + int ret, i;
    +
    + platdata = dev_get_platdata(&pdev->dev);
    +
    + dev_dbg(&pdev->dev, "Creating virtual sound card\n");
    +
    + ret = snd_card_new(&pdev->dev, 0, XENSND_DRIVER_NAME, THIS_MODULE,
    + sizeof(struct sdev_card_info), &card);
    + if (ret < 0)
    + return ret;
    +
    + card_info = card->private_data;
    + card_info->xdrv_info = platdata->xdrv_info;
    + card_info->card = card;
    + card_info->pcm_instances = devm_kcalloc(&pdev->dev,
    + platdata->cfg_card.num_pcm_instances,
    + sizeof(struct sdev_pcm_instance_info), GFP_KERNEL);
    + if (!card_info->pcm_instances) {
    + ret = -ENOMEM;
    + goto fail;
    + }
    +
    + card_info->num_pcm_instances = platdata->cfg_card.num_pcm_instances;
    + card_info->pcm_hw = platdata->cfg_card.pcm_hw;
    +
    + for (i = 0; i < platdata->cfg_card.num_pcm_instances; i++) {
    + ret = sdrv_new_pcm(card_info,
    + &platdata->cfg_card.pcm_instances[i],
    + &card_info->pcm_instances[i]);
    + if (ret < 0)
    + goto fail;
    + }
    +
    + strncpy(card->driver, XENSND_DRIVER_NAME, sizeof(card->driver));
    + strncpy(card->shortname, platdata->cfg_card.name_short,
    + sizeof(card->shortname));
    + strncpy(card->longname, platdata->cfg_card.name_long,
    + sizeof(card->longname));
    +
    + ret = snd_card_register(card);
    + if (ret < 0)
    + goto fail;
    +
    + platform_set_drvdata(pdev, card);
    + return 0;
    +
    +fail:
    + snd_card_free(card);
    + return ret;
    +}
    +
    +static int sdrv_remove(struct platform_device *pdev)
    +{
    + struct sdev_card_info *info;
    + struct snd_card *card = platform_get_drvdata(pdev);
    +
    + info = card->private_data;
    + dev_dbg(&pdev->dev, "Removing virtual sound card %d\n",
    + info->card->number);
    + snd_card_free(card);
    + return 0;
    +}
    +
    +static struct platform_driver sdrv_info = {
    + .probe = sdrv_probe,
    + .remove = sdrv_remove,
    + .driver = {
    + .name = XENSND_DRIVER_NAME,
    + },
    +};
    +
    +static void sdrv_cleanup(struct xdrv_info *drv_info)
    +{
    + if (!drv_info->sdrv_registered)
    + return;
    +
    + if (drv_info->sdrv_pdev) {
    + struct platform_device *sdrv_pdev;
    +
    + sdrv_pdev = drv_info->sdrv_pdev;
    + if (sdrv_pdev)
    + platform_device_unregister(sdrv_pdev);
    + }
    + platform_driver_unregister(&sdrv_info);
    + drv_info->sdrv_registered = false;
    +}
    +
    +static int sdrv_init(struct xdrv_info *drv_info)
    +{
    + struct platform_device *sdrv_pdev;
    + int ret;
    +
    + ret = platform_driver_register(&sdrv_info);
    + if (ret < 0)
    + return ret;
    +
    + drv_info->sdrv_registered = true;
    + /* pass card configuration via platform data */
    + sdrv_pdev = platform_device_register_data(NULL,
    + XENSND_DRIVER_NAME, 0, &drv_info->cfg_plat_data,
    + sizeof(drv_info->cfg_plat_data));
    + if (IS_ERR(sdrv_pdev))
    + goto fail;
    +
    + drv_info->sdrv_pdev = sdrv_pdev;
    + return 0;
    +
    +fail:
    + dev_err(&drv_info->xb_dev->dev,
    + "failed to register virtual sound driver\n");
    + sdrv_cleanup(drv_info);
    + return -ENODEV;
    +}
    +
    static irqreturn_t xdrv_evtchnl_interrupt(int irq, void *dev_id)
    {
    struct xdrv_evtchnl_info *channel = dev_id;
    @@ -830,6 +986,7 @@ static int cfg_card(struct xdrv_info *drv_info,

    static void xdrv_remove_internal(struct xdrv_info *drv_info)
    {
    + sdrv_cleanup(drv_info);
    xdrv_evtchnl_free_all(drv_info);
    }

    @@ -1018,7 +1175,7 @@ static int xdrv_be_on_initwait(struct xdrv_info *drv_info)

    static inline int xdrv_be_on_connected(struct xdrv_info *drv_info)
    {
    - return 0;
    + return sdrv_init(drv_info);
    }

    static inline void xdrv_be_on_disconnected(struct xdrv_info *drv_info)
    --
    2.7.4
    \
     
     \ /
      Last update: 2017-08-07 09:44    [W:3.385 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site