0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/init.h>
0010 #include <linux/slab.h>
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/device.h>
0014 #include <linux/spinlock.h>
0015
0016 #include <media/v4l2-device.h>
0017
0018 #include <sound/core.h>
0019 #include <sound/initval.h>
0020
0021 #include "cobalt-driver.h"
0022 #include "cobalt-alsa.h"
0023 #include "cobalt-alsa-pcm.h"
0024
0025 static void snd_cobalt_card_free(struct snd_cobalt_card *cobsc)
0026 {
0027 if (cobsc == NULL)
0028 return;
0029
0030 cobsc->s->alsa = NULL;
0031
0032 kfree(cobsc);
0033 }
0034
0035 static void snd_cobalt_card_private_free(struct snd_card *sc)
0036 {
0037 if (sc == NULL)
0038 return;
0039 snd_cobalt_card_free(sc->private_data);
0040 sc->private_data = NULL;
0041 sc->private_free = NULL;
0042 }
0043
0044 static int snd_cobalt_card_create(struct cobalt_stream *s,
0045 struct snd_card *sc,
0046 struct snd_cobalt_card **cobsc)
0047 {
0048 *cobsc = kzalloc(sizeof(struct snd_cobalt_card), GFP_KERNEL);
0049 if (*cobsc == NULL)
0050 return -ENOMEM;
0051
0052 (*cobsc)->s = s;
0053 (*cobsc)->sc = sc;
0054
0055 sc->private_data = *cobsc;
0056 sc->private_free = snd_cobalt_card_private_free;
0057
0058 return 0;
0059 }
0060
0061 static int snd_cobalt_card_set_names(struct snd_cobalt_card *cobsc)
0062 {
0063 struct cobalt_stream *s = cobsc->s;
0064 struct cobalt *cobalt = s->cobalt;
0065 struct snd_card *sc = cobsc->sc;
0066
0067
0068 strscpy(sc->driver, "cobalt", sizeof(sc->driver));
0069
0070
0071 snprintf(sc->shortname, sizeof(sc->shortname), "cobalt-%d-%d",
0072 cobalt->instance, s->video_channel);
0073
0074
0075 snprintf(sc->longname, sizeof(sc->longname),
0076 "Cobalt %d HDMI %d",
0077 cobalt->instance, s->video_channel);
0078
0079 return 0;
0080 }
0081
0082 int cobalt_alsa_init(struct cobalt_stream *s)
0083 {
0084 struct cobalt *cobalt = s->cobalt;
0085 struct snd_card *sc = NULL;
0086 struct snd_cobalt_card *cobsc;
0087 int ret;
0088
0089
0090
0091
0092
0093
0094
0095 ret = snd_card_new(&cobalt->pci_dev->dev, SNDRV_DEFAULT_IDX1,
0096 SNDRV_DEFAULT_STR1, THIS_MODULE, 0, &sc);
0097 if (ret) {
0098 cobalt_err("snd_card_new() failed with err %d\n", ret);
0099 goto err_exit;
0100 }
0101
0102
0103 ret = snd_cobalt_card_create(s, sc, &cobsc);
0104 if (ret) {
0105 cobalt_err("snd_cobalt_card_create() failed with err %d\n",
0106 ret);
0107 goto err_exit_free;
0108 }
0109
0110
0111 snd_cobalt_card_set_names(cobsc);
0112
0113 ret = snd_cobalt_pcm_create(cobsc);
0114 if (ret) {
0115 cobalt_err("snd_cobalt_pcm_create() failed with err %d\n",
0116 ret);
0117 goto err_exit_free;
0118 }
0119
0120
0121
0122
0123 s->alsa = cobsc;
0124
0125
0126 ret = snd_card_register(sc);
0127 if (ret) {
0128 s->alsa = NULL;
0129 cobalt_err("snd_card_register() failed with err %d\n", ret);
0130 goto err_exit_free;
0131 }
0132
0133 return 0;
0134
0135 err_exit_free:
0136 if (sc != NULL)
0137 snd_card_free(sc);
0138 kfree(cobsc);
0139 err_exit:
0140 return ret;
0141 }
0142
0143 void cobalt_alsa_exit(struct cobalt_stream *s)
0144 {
0145 struct snd_cobalt_card *cobsc = s->alsa;
0146
0147 if (cobsc)
0148 snd_card_free(cobsc->sc);
0149 s->alsa = NULL;
0150 }