brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · c57f87a Raw
151 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  ALSA interface to cobalt PCM capture streams4 *5 *  Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.6 *  All rights reserved.7 */8 9#include <linux/init.h>10#include <linux/slab.h>11#include <linux/module.h>12#include <linux/kernel.h>13#include <linux/device.h>14#include <linux/spinlock.h>15 16#include <media/v4l2-device.h>17 18#include <sound/core.h>19#include <sound/initval.h>20 21#include "cobalt-driver.h"22#include "cobalt-alsa.h"23#include "cobalt-alsa-pcm.h"24 25static void snd_cobalt_card_free(struct snd_cobalt_card *cobsc)26{27	if (cobsc == NULL)28		return;29 30	cobsc->s->alsa = NULL;31 32	kfree(cobsc);33}34 35static void snd_cobalt_card_private_free(struct snd_card *sc)36{37	if (sc == NULL)38		return;39	snd_cobalt_card_free(sc->private_data);40	sc->private_data = NULL;41	sc->private_free = NULL;42}43 44static int snd_cobalt_card_create(struct cobalt_stream *s,45				       struct snd_card *sc,46				       struct snd_cobalt_card **cobsc)47{48	*cobsc = kzalloc(sizeof(struct snd_cobalt_card), GFP_KERNEL);49	if (*cobsc == NULL)50		return -ENOMEM;51 52	(*cobsc)->s = s;53	(*cobsc)->sc = sc;54 55	sc->private_data = *cobsc;56	sc->private_free = snd_cobalt_card_private_free;57 58	return 0;59}60 61static int snd_cobalt_card_set_names(struct snd_cobalt_card *cobsc)62{63	struct cobalt_stream *s = cobsc->s;64	struct cobalt *cobalt = s->cobalt;65	struct snd_card *sc = cobsc->sc;66 67	/* sc->driver is used by alsa-lib's configurator: simple, unique */68	strscpy(sc->driver, "cobalt", sizeof(sc->driver));69 70	/* sc->shortname is a symlink in /proc/asound: COBALT-M -> cardN */71	snprintf(sc->shortname,  sizeof(sc->shortname), "cobalt-%d-%d",72		 cobalt->instance, s->video_channel);73 74	/* sc->longname is read from /proc/asound/cards */75	snprintf(sc->longname, sizeof(sc->longname),76		 "Cobalt %d HDMI %d",77		 cobalt->instance, s->video_channel);78 79	return 0;80}81 82int cobalt_alsa_init(struct cobalt_stream *s)83{84	struct cobalt *cobalt = s->cobalt;85	struct snd_card *sc = NULL;86	struct snd_cobalt_card *cobsc;87	int ret;88 89	/* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */90 91	/* (1) Check and increment the device index */92	/* This is a no-op for us.  We'll use the cobalt->instance */93 94	/* (2) Create a card instance */95	ret = snd_card_new(&cobalt->pci_dev->dev, SNDRV_DEFAULT_IDX1,96			   SNDRV_DEFAULT_STR1, THIS_MODULE, 0, &sc);97	if (ret) {98		cobalt_err("snd_card_new() failed with err %d\n", ret);99		goto err_exit;100	}101 102	/* (3) Create a main component */103	ret = snd_cobalt_card_create(s, sc, &cobsc);104	if (ret) {105		cobalt_err("snd_cobalt_card_create() failed with err %d\n",106			   ret);107		goto err_exit_free;108	}109 110	/* (4) Set the driver ID and name strings */111	snd_cobalt_card_set_names(cobsc);112 113	ret = snd_cobalt_pcm_create(cobsc);114	if (ret) {115		cobalt_err("snd_cobalt_pcm_create() failed with err %d\n",116			   ret);117		goto err_exit_free;118	}119	/* FIXME - proc files */120 121	/* (7) Set the driver data and return 0 */122	/* We do this out of normal order for PCI drivers to avoid races */123	s->alsa = cobsc;124 125	/* (6) Register the card instance */126	ret = snd_card_register(sc);127	if (ret) {128		s->alsa = NULL;129		cobalt_err("snd_card_register() failed with err %d\n", ret);130		goto err_exit_free;131	}132 133	return 0;134 135err_exit_free:136	if (sc != NULL)137		snd_card_free(sc);138	kfree(cobsc);139err_exit:140	return ret;141}142 143void cobalt_alsa_exit(struct cobalt_stream *s)144{145	struct snd_cobalt_card *cobsc = s->alsa;146 147	if (cobsc)148		snd_card_free(cobsc->sc);149	s->alsa = NULL;150}151