diff options
171 files changed, 2641 insertions, 1460 deletions
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 87a7c07a..320384c 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -492,9 +492,9 @@ } /* (2) */ - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; /* (3) */ err = snd_mychip_create(card, pci, &chip); @@ -590,8 +590,9 @@ <programlisting> <![CDATA[ struct snd_card *card; + int err; .... - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); ]]> </programlisting> </informalexample> @@ -809,26 +810,28 @@ <para> As mentioned above, to create a card instance, call - <function>snd_card_new()</function>. + <function>snd_card_create()</function>. <informalexample> <programlisting> <![CDATA[ struct snd_card *card; - card = snd_card_new(index, id, module, extra_size); + int err; + err = snd_card_create(index, id, module, extra_size, &card); ]]> </programlisting> </informalexample> </para> <para> - The function takes four arguments, the card-index number, the + The function takes five arguments, the card-index number, the id string, the module pointer (usually <constant>THIS_MODULE</constant>), - and the size of extra-data space. The last argument is used to + the size of extra-data space, and the pointer to return the + card instance. The extra_size argument is used to allocate card->private_data for the chip-specific data. Note that these data - are allocated by <function>snd_card_new()</function>. + are allocated by <function>snd_card_create()</function>. </para> </section> @@ -915,15 +918,16 @@ </para> <section id="card-management-chip-specific-snd-card-new"> - <title>1. Allocating via <function>snd_card_new()</function>.</title> + <title>1. Allocating via <function>snd_card_create()</function>.</title> <para> As mentioned above, you can pass the extra-data-length - to the 4th argument of <function>snd_card_new()</function>, i.e. + to the 4th argument of <function>snd_card_create()</function>, i.e. <informalexample> <programlisting> <![CDATA[ - card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct mychip)); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct mychip), &card); ]]> </programlisting> </informalexample> @@ -952,8 +956,8 @@ <para> After allocating a card instance via - <function>snd_card_new()</function> (with - <constant>NULL</constant> on the 4th arg), call + <function>snd_card_create()</function> (with + <constant>0</constant> on the 4th arg), call <function>kzalloc()</function>. <informalexample> @@ -961,7 +965,7 @@ <![CDATA[ struct snd_card *card; struct mychip *chip; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); ..... chip = kzalloc(sizeof(*chip), GFP_KERNEL); ]]> @@ -5750,8 +5754,9 @@ struct _snd_pcm_runtime { .... struct snd_card *card; struct mychip *chip; + int err; .... - card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); .... chip = kzalloc(sizeof(*chip), GFP_KERNEL); .... @@ -5763,7 +5768,7 @@ struct _snd_pcm_runtime { </informalexample> When you created the chip data with - <function>snd_card_new()</function>, it's anyway accessible + <function>snd_card_create()</function>, it's anyway accessible via <structfield>private_data</structfield> field. <informalexample> @@ -5775,9 +5780,10 @@ struct _snd_pcm_runtime { .... struct snd_card *card; struct mychip *chip; + int err; .... - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct mychip)); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct mychip), &card); .... chip = card->private_data; .... diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt index 46f9684..9e67632 100644 --- a/Documentation/sound/alsa/soc/dapm.txt +++ b/Documentation/sound/alsa/soc/dapm.txt @@ -116,6 +116,9 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0), SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls, ARRAY_SIZE(wm8731_output_mixer_controls)), +If you dont want the mixer elements prefixed with the name of the mixer widget, +you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same +as for SND_SOC_DAPM_MIXER. 2.3 Platform/Machine domain Widgets ----------------------------------- diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c index 6d48e00..a6fff78 100644 --- a/arch/arm/mach-pxa/e740.c +++ b/arch/arm/mach-pxa/e740.c @@ -135,6 +135,11 @@ static unsigned long e740_pin_config[] __initdata = { /* IrDA */ GPIO38_GPIO | MFP_LPM_DRIVE_HIGH, + /* Audio power control */ + GPIO16_GPIO, /* AC97 codec AVDD2 supply (analogue power) */ + GPIO40_GPIO, /* Mic amp power */ + GPIO41_GPIO, /* Headphone amp power */ + /* PC Card */ GPIO8_GPIO, /* CD0 */ GPIO44_GPIO, /* CD1 */ diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c index be1ab8e..665066f 100644 --- a/arch/arm/mach-pxa/e750.c +++ b/arch/arm/mach-pxa/e750.c @@ -133,6 +133,11 @@ static unsigned long e750_pin_config[] __initdata = { /* IrDA */ GPIO38_GPIO | MFP_LPM_DRIVE_HIGH, + /* Audio power control */ + GPIO4_GPIO, /* Headphone amp power */ + GPIO7_GPIO, /* Speaker amp power */ + GPIO37_GPIO, /* Headphone detect */ + /* PC Card */ GPIO8_GPIO, /* CD0 */ GPIO44_GPIO, /* CD1 */ diff --git a/arch/arm/mach-pxa/include/mach/eseries-gpio.h b/arch/arm/mach-pxa/include/mach/eseries-gpio.h index efbd2aa..f3e5509 100644 --- a/arch/arm/mach-pxa/include/mach/eseries-gpio.h +++ b/arch/arm/mach-pxa/include/mach/eseries-gpio.h @@ -45,6 +45,21 @@ /* e7xx IrDA power control */ #define GPIO_E7XX_IR_OFF 38 +/* e740 audio control GPIOs */ +#define GPIO_E740_WM9705_nAVDD2 16 +#define GPIO_E740_MIC_ON 40 +#define GPIO_E740_AMP_ON 41 + +/* e750 audio control GPIOs */ +#define GPIO_E750_HP_AMP_OFF 4 +#define GPIO_E750_SPK_AMP_OFF 7 +#define GPIO_E750_HP_DETECT 37 + +/* e800 audio control GPIOs */ +#define GPIO_E800_HP_DETECT 81 +#define GPIO_E800_HP_AMP_OFF 82 +#define GPIO_E800_SPK_AMP_ON 83 + /* ASIC related GPIOs */ #define GPIO_ESERIES_TMIO_IRQ 5 #define GPIO_ESERIES_TMIO_PCLR 19 diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 66c755c..ce98d95 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -803,9 +803,10 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, return (-ENOENT); } - card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); - if (!card) - return (-ENOMEM); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx88_card_t), &card); + if (err < 0) + return err; card->private_free = snd_cx88_dev_free; diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 94378cc..6657950 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -438,9 +438,10 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); - card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, + &card); + if (err < 0) + return err; spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 26194a0..482be14 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -990,10 +990,10 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if (!enable[devnum]) return -ENODEV; - card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); - - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(snd_card_saa7134_t), &card); + if (err < 0) + return err; strcpy(card->driver, "SAA7134"); diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c index a7de401..cd19be6 100644 --- a/drivers/staging/go7007/snd-go7007.c +++ b/drivers/staging/go7007/snd-go7007.c @@ -248,10 +248,11 @@ int go7007_snd_init(struct go7007 *go) spin_lock_init(&gosnd->lock); gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; gosnd->capturing = 0; - gosnd->card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (gosnd->card == NULL) { + ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, + &gosnd->card); + if (ret < 0) { kfree(gosnd); - return -ENOMEM; + return ret; } ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, &go7007_snd_device_ops); diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 60d3f9e..14e09ab 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -1099,10 +1099,9 @@ static int gmidi_register_card(struct gmidi_device *dev) .dev_free = gmidi_snd_free, }; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) { - ERROR(dev, "snd_card_new failed\n"); - err = -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) { + ERROR(dev, "snd_card_create failed\n"); goto fail; } dev->card = card; diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h index af95a1d..d899dc0 100644 --- a/include/linux/mfd/wm8350/audio.h +++ b/include/linux/mfd/wm8350/audio.h @@ -490,6 +490,7 @@ /* * R231 (0xE7) - Jack Status */ +#define WM8350_JACK_L_LVL 0x0800 #define WM8350_JACK_R_LVL 0x0400 /* diff --git a/include/sound/core.h b/include/sound/core.h index f632484..25420c3 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -296,8 +296,20 @@ int snd_card_locked(int card); extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd); #endif +int snd_card_create(int idx, const char *id, + struct module *module, int extra_size, + struct snd_card **card_ret); + +static inline __deprecated struct snd_card *snd_card_new(int idx, const char *id, - struct module *module, int extra_size); + struct module *module, int extra_size) +{ + struct snd_card *card; + if (snd_card_create(idx, id, module, extra_size, &card) < 0) + return NULL; + return card; +} + int snd_card_disconnect(struct snd_card *card); int snd_card_free(struct snd_card *card); int snd_card_free_when_closed(struct snd_card *card); diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index dfa8049..bb3a863 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -76,6 +76,11 @@ wcontrols, wncontrols)\ { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols} +#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ + wcontrols, wncontrols)\ +{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ + .shift = wshift, .invert = winvert, .kcontrols = wcontrols, \ + .num_kcontrols = wncontrols} #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ { .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0} @@ -101,6 +106,11 @@ { .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \ .event = wevent, .event_flags = wflags} +#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ + wcontrols, wncontrols, wevent, wflags) \ +{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ + .invert = winvert, .kcontrols = wcontrols, \ + .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \ { .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \ @@ -250,10 +260,10 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, int snd_soc_dapm_sys_add(struct device *dev); /* dapm audio pin control and status */ -int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin); -int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin); -int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin); -int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin); +int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin); +int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin); +int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin); +int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin); int snd_soc_dapm_sync(struct snd_soc_codec *codec); /* dapm widget types */ @@ -263,6 +273,7 @@ enum snd_soc_dapm_type { snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_mixer, /* mixes several analog signals together */ + snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ snd_soc_dapm_adc, /* analog to digital converter */ snd_soc_dapm_dac, /* digital to analog converter */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 24593ac..0e77352 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -154,6 +154,8 @@ enum snd_soc_bias_level { SND_SOC_BIAS_OFF, }; +struct snd_jack; +struct snd_soc_card; struct snd_soc_device; struct snd_soc_pcm_stream; struct snd_soc_ops; @@ -164,6 +166,8 @@ struct snd_soc_platform; struct snd_soc_codec; struct soc_enum; struct snd_soc_ac97_ops; +struct snd_soc_jack; +struct snd_soc_jack_pin; typedef int (*hw_write_t)(void *,const char* ,int); typedef int (*hw_read_t)(void *,char* ,int); @@ -184,6 +188,13 @@ int snd_soc_init_card(struct snd_soc_device *socdev); int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw); +/* Jack reporting */ +int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack); +void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); +int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_pin *pins); + /* codec IO */ #define snd_soc_read(codec, reg) codec->read(codec, reg) #define snd_soc_write(codec, reg, value) codec->write(codec, reg, value) @@ -203,6 +214,8 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); */ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, void *data, char *long_name); +int snd_soc_add_controls(struct snd_soc_codec *codec, + const struct snd_kcontrol_new *controls, int num_controls); int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, @@ -237,6 +250,27 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +/** + * struct snd_soc_jack_pin - Describes a pin to update based on jack detection + * + * @pin: name of the pin to update + * @mask: bits to check for in reported jack status + * @invert: if non-zero then pin is enabled when status is not reported + */ +struct snd_soc_jack_pin { + struct list_head list; + const char *pin; + int mask; + bool invert; +}; + +struct snd_soc_jack { + struct snd_jack *jack; + struct snd_soc_card *card; + struct list_head pins; + int status; +}; + /* SoC PCM stream information */ struct snd_soc_pcm_stream { char *stream_name; @@ -384,6 +418,8 @@ struct snd_soc_card { struct snd_soc_device *socdev; + struct snd_soc_codec *codec; + struct snd_soc_platform *platform; struct delayed_work delayed_work; struct work_struct deferred_resume_work; @@ -393,7 +429,6 @@ struct snd_soc_card { struct snd_soc_device { struct device *dev; struct snd_soc_card *card; - struct snd_soc_codec *codec; struct snd_soc_codec_device *codec_dev; void *codec_data; }; diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/alsa.c index 6178504..0fa3855 100644 --- a/sound/aoa/core/alsa.c +++ b/sound/aoa/core/alsa.c @@ -23,9 +23,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev) /* cannot be EEXIST due to usage in aoa_fabric_register */ return -EBUSY; - alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card)); - if (!alsa_card) - return -ENOMEM; + err = snd_card_create(index, name, mod, sizeof(struct aoa_card), + &alsa_card); + if (err < 0) + return err; aoa_card = alsa_card->private_data; aoa_card->alsa_card = alsa_card; alsa_card->dev = dev; diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 89096e8..7d39aac 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -995,10 +995,11 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) { struct aaci *aaci; struct snd_card *card; + int err; - card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct aaci)); - if (card == NULL) + err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, sizeof(struct aaci), &card); + if (err < 0) return NULL; card->private_free = aaci_free_card; diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 85cf591..7ed100c 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -173,10 +173,9 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) struct snd_ac97_template ac97_template; int ret; - ret = -ENOMEM; - card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, 0); - if (!card) + ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); + if (ret < 0) goto err; card->dev = &dev->dev; diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index 1dcd51d..51d708c 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c @@ -887,9 +887,10 @@ static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr) struct sa11xx_uda1341 *chip; /* register the soundcard */ - card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct sa11xx_uda1341)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(-1, id, THIS_MODULE, + sizeof(struct sa11xx_uda1341), &card); + if (err < 0) + return err; chip = card->private_data; spin_lock_init(&chip->s[0].dma_lock); diff --git a/sound/core/init.c b/sound/core/init.c index 0d5520c..dc4b80c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -121,31 +121,44 @@ static inline int init_info_for_card(struct snd_card *card) #endif /** - * snd_card_new - create and initialize a soundcard structure + * snd_card_create - create and initialize a soundcard structure * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] * @xid: card identification (ASCII string) * @module: top level module for locking * @extra_size: allocate this extra size after the main soundcard structure + * @card_ret: the pointer to store the created card instance * * Creates and initializes a soundcard structure. * - * Returns kmallocated snd_card structure. Creates the ALSA control interface - * (which is blocked until snd_card_register function is called). + * The function allocates snd_card instance via kzalloc with the given + * space for the driver to use freely. The allocated struct is stored + * in the given card_ret pointer. + * + * Returns zero if successful or a negative error code. */ -struct snd_card *snd_card_new(int idx, const char *xid, - struct module *module, int extra_size) +int snd_card_create(int idx, const char *xid, + struct module *module, int extra_size, + struct snd_card **card_ret) { struct snd_card *card; int err, idx2; + if (snd_BUG_ON(!card_ret)) + return -EINVAL; + *card_ret = NULL; + if (extra_size < 0) extra_size = 0; card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); - if (card == NULL) - return NULL; + if (!card) + return -ENOMEM; if (xid) { - if (!snd_info_check_reserved_words(xid)) + if (!snd_info_check_reserved_words(xid)) { + snd_printk(KERN_ERR + "given id string '%s' is reserved.\n", xid); + err = -EBUSY; goto __error; + } strlcpy(card->id, xid, sizeof(card->id)); } err = 0; @@ -202,26 +215,28 @@ struct snd_card *snd_card_new(int idx, const char *xid, #endif /* the control interface cannot be accessed from the user space until */ /* snd_cards_bitmask and snd_cards are set with snd_card_register */ - if ((err = snd_ctl_create(card)) < 0) { - snd_printd("unable to register control minors\n"); + err = snd_ctl_create(card); + if (err < 0) { + snd_printk(KERN_ERR "unable to register control minors\n"); goto __error; } - if ((err = snd_info_card_create(card)) < 0) { - snd_printd("unable to create card info\n"); + err = snd_info_card_create(card); + if (err < 0) { + snd_printk(KERN_ERR "unable to create card info\n"); goto __error_ctl; } if (extra_size > 0) card->private_data = (char *)card + sizeof(struct snd_card); - return card; + *card_ret = card; + return 0; __error_ctl: snd_device_free_all(card, SNDRV_DEV_CMD_PRE); __error: kfree(card); - return NULL; + return err; } - -EXPORT_SYMBOL(snd_card_new); +EXPORT_SYMBOL(snd_card_create); /* return non-zero if a card is already locked */ int snd_card_locked(int card) diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 73be7e1..54239d2 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -588,10 +588,10 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) int idx, err; int dev = devptr->id; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dummy)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_dummy), &card); + if (err < 0) + return err; dummy = card->private_data; dummy->card = card; for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 7783843..1950ffc 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c @@ -1279,9 +1279,9 @@ static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev) if (!enable[dev]) return -ENOENT; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr); if (err < 0) { PDEBUG(INIT_FAILURE, "probe(): create failed!\n"); diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 5b996f3..149d05a 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -73,9 +73,9 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); *rcard = NULL; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "MPU-401 UART"); strcpy(card->shortname, card->driver); sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 5b89c088..c3e9833 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -696,9 +696,9 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev) int err; struct mtpav *mtp_card; - card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card)); - if (! card) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card); + if (err < 0) + return err; mtp_card = card->private_data; spin_lock_init(&mtp_card->spinlock); diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 87ba1dd..33d9db7 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -957,10 +957,10 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev) if ((err = snd_mts64_probe_port(p)) < 0) return err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) { snd_printd("Cannot create card\n"); - return -ENOMEM; + return err; } strcpy(card->driver, DRIVER_NAME); strcpy(card->shortname, "ESI " CARD_NAME); diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index a4049eb..aa2ae07 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -98,9 +98,9 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pcsp_chip.timer.function = pcsp_do_timer; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_pcsp_create(card); if (err < 0) { diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index b1c047e..60158e2 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -746,10 +746,10 @@ static int __devinit snd_portman_probe(struct platform_device *pdev) if ((err = snd_portman_probe_port(p)) < 0) return err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) { snd_printd("Cannot create card\n"); - return -ENOMEM; + return err; } strcpy(card->driver, DRIVER_NAME); strcpy(card->shortname, CARD_NAME); diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index d8aab9d..891d081 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -936,9 +936,9 @@ static int __devinit snd_serial_probe(struct platform_device *devptr) return -ENODEV; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "Serial"); strcpy(card->shortname, "Serial MIDI (UART16550A)"); diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index f79e361..6f48711 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -90,10 +90,10 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr) int idx, err; int dev = devptr->id; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_virmidi)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_virmidi), &card); + if (err < 0) + return err; vmidi = (struct snd_card_virmidi *)card->private_data; vmidi->card = card; diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 7752424..9660e59 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -157,9 +157,10 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard struct snd_ad1816a *chip; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_ad1816a))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_ad1816a), &card); + if (error < 0) + return error; acard = (struct snd_card_ad1816a *)card->private_data; if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 223a6c0..4beeb6f 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c @@ -91,9 +91,9 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c index 374b717..7465ae0 100644 --- a/sound/isa/adlib.c +++ b/sound/isa/adlib.c @@ -53,10 +53,10 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) struct snd_opl3 *opl3; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) { + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) { dev_err(dev, "could not create card\n"); - return -EINVAL; + return error; } card->private_data = request_region(port[n], 4, CRD_NAME); diff --git a/sound/isa/als100.c b/sound/isa/als100.c index f1ce30f..5fd52e4 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -163,9 +163,10 @@ static int __devinit snd_card_als100_probe(int dev, struct snd_card_als100 *acard; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_als100))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_als100), &card); + if (error < 0) + return error; acard = card->private_data; if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) { diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 3e74d1a..f7aa637 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -184,9 +184,10 @@ static int __devinit snd_card_azt2320_probe(int dev, struct snd_wss *chip; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_azt2320))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_azt2320), &card); + if (error < 0) + return error; acard = (struct snd_card_azt2320 *)card->private_data; if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index e49aec7..24e6090 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -467,20 +467,22 @@ static int snd_cmi8330_resume(struct snd_card *card) #define PFX "cmi8330: " -static struct snd_card *snd_cmi8330_card_new(int dev) +static int snd_cmi8330_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; struct snd_cmi8330 *acard; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cmi8330)); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cmi8330), &card); + if (err < 0) { snd_printk(KERN_ERR PFX "could not get a new card\n"); - return NULL; + return err; } acard = card->private_data; acard->card = card; - return card; + *cardp = card; + return 0; } static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) @@ -564,9 +566,9 @@ static int __devinit snd_cmi8330_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_cmi8330_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_cmi8330_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_cmi8330_probe(card, dev)) < 0) { snd_card_free(card); @@ -628,9 +630,9 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_cmi8330_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_cmi8330_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { snd_printk(KERN_ERR PFX "PnP detection failed\n"); snd_card_free(card); diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index f019d44..cb9153e 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -95,9 +95,9 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n], WSS_HW_DETECT, 0, &chip); diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 019c940..f784598 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -382,16 +382,18 @@ static void snd_card_cs4236_free(struct snd_card *card) release_and_free_resource(acard->res_sb_port); } -static struct snd_card *snd_cs423x_card_new(int dev) +static int snd_cs423x_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_cs4236)); - if (card == NULL) - return NULL; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_cs4236), &card); + if (err < 0) + return err; card->private_free = snd_card_cs4236_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) @@ -512,9 +514,9 @@ static int __devinit snd_cs423x_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_cs423x_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_cs423x_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_cs423x_probe(card, dev)) < 0) { snd_card_free(card); @@ -594,9 +596,9 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_cs423x_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_cs423x_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_card_cs4232_pnp(dev, card->private_data, pdev)) < 0) { printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n"); snd_card_free(card); @@ -656,9 +658,9 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_cs423x_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_cs423x_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n"); diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c index a0242c3..80f5b1a 100644 --- a/sound/isa/dt019x.c +++ b/sound/isa/dt019x.c @@ -150,9 +150,10 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard, struct snd_card_dt019x *acard; struct snd_opl3 *opl3; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_dt019x))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_dt019x), &card); + if (error < 0) + return error; acard = card->private_data; snd_card_set_dev(card, &pcard->card->dev); diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index b463771..d746750 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -122,9 +122,9 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n) struct snd_pcm *pcm; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; error = snd_es1688_legacy_create(card, dev, n, &chip); if (error < 0) diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 90498e4..8cfbff7 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -2125,10 +2125,10 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, #define is_isapnp_selected(dev) 0 #endif -static struct snd_card *snd_es18xx_card_new(int dev) +static int snd_es18xx_card_new(int dev, struct snd_card **cardp) { - return snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_audiodrive)); + return snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_audiodrive), cardp); } static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) @@ -2197,9 +2197,9 @@ static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr) struct snd_card *card; int err; - card = snd_es18xx_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_es18xx_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, devptr); if ((err = snd_audiodrive_probe(card, dev)) < 0) { snd_card_free(card); @@ -2303,9 +2303,9 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_es18xx_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_es18xx_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; @@ -2362,9 +2362,9 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_es18xx_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_es18xx_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { snd_card_free(card); diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 426532a..086b8f0 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -148,9 +148,9 @@ static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) struct snd_gus_card *gus; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; if (pcm_channels[n] < 2) pcm_channels[n] = 2; diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 7ad4c3b..180a8de 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -241,9 +241,9 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) struct snd_opl3 *opl3; int error; - card = snd_card_new(index[n], id[n], THIS_MODULE, 0); - if (!card) - return -EINVAL; + error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); + if (error < 0) + return error; if (mpu_port[n] == SNDRV_AUTO_PORT) mpu_port[n] = 0; diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index f94c197..f26eac8 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -214,10 +214,10 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) struct snd_wss *wss; struct snd_gusmax *maxcard; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_gusmax)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_gusmax), &card); + if (err < 0) + return err; card->private_free = snd_gusmax_free; maxcard = (struct snd_gusmax *)card->private_data; maxcard->card = card; diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 5faecfb..50e429a 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -626,20 +626,22 @@ static void snd_interwave_free(struct snd_card *card) free_irq(iwcard->irq, (void *)iwcard); } -static struct snd_card *snd_interwave_card_new(int dev) +static int snd_interwave_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; struct snd_interwave *iwcard; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_interwave)); - if (card == NULL) - return NULL; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_interwave), &card); + if (err < 0) + return err; iwcard = card->private_data; iwcard->card = card; iwcard->irq = -1; card->private_free = snd_interwave_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_interwave_probe(struct snd_card *card, int dev) @@ -778,9 +780,9 @@ static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr) struct snd_card *card; int err; - card = snd_interwave_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_interwave_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, devptr); if ((err = snd_interwave_probe(card, dev)) < 0) { @@ -876,9 +878,9 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_interwave_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_interwave_card_new(dev, &card); + if (res < 0) + return res; if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { snd_card_free(card); diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 58c972b..645491a 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -617,21 +617,24 @@ static void snd_opl3sa2_free(struct snd_card *card) release_and_free_resource(chip->res_port); } -static struct snd_card *snd_opl3sa2_card_new(int dev) +static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; struct snd_opl3sa2 *chip; + int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_opl3sa2)); - if (card == NULL) - return NULL; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_opl3sa2), &card); + if (err < 0) + return err; strcpy(card->driver, "OPL3SA2"); strcpy(card->shortname, "Yamaha OPL3-SA2"); chip = card->private_data; spin_lock_init(&chip->reg_lock); chip->irq = -1; card->private_free = snd_opl3sa2_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) @@ -723,9 +726,9 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_opl3sa2_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_opl3sa2_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; @@ -789,9 +792,9 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_opl3sa2_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_opl3sa2_card_new(dev, &card); + if (err < 0) + return err; if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { snd_card_free(card); return err; @@ -870,9 +873,9 @@ static int __devinit snd_opl3sa2_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_opl3sa2_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_opl3sa2_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_opl3sa2_probe(card, dev)) < 0) { snd_card_free(card); diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 440755c..02e30d7 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1228,9 +1228,10 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) struct snd_pcm *pcm; struct snd_rawmidi *rmidi; - if (!(card = snd_card_new(index, id, THIS_MODULE, - sizeof(struct snd_miro)))) - return -ENOMEM; + error = snd_card_create(index, id, THIS_MODULE, + sizeof(struct snd_miro), &card); + if (error < 0) + return error; card->private_free = snd_card_miro_free; miro = card->private_data; diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 19706b0..cd6e60a 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -830,15 +830,18 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) return snd_card_register(card); } -static struct snd_card *snd_opti9xx_card_new(void) +static int snd_opti9xx_card_new(struct snd_card **cardp) { struct snd_card *card; + int err; - card = snd_card_new(index, id, THIS_MODULE, sizeof(struct snd_opti9xx)); - if (! card) - return NULL; + err = snd_card_create(index, id, THIS_MODULE, + sizeof(struct snd_opti9xx), &card); + if (err < 0) + return err; card->private_free = snd_card_opti9xx_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_opti9xx_isa_match(struct device *devptr, @@ -903,9 +906,9 @@ static int __devinit snd_opti9xx_isa_probe(struct device *devptr, } #endif - card = snd_opti9xx_card_new(); - if (! card) - return -ENOMEM; + error = snd_opti9xx_card_new(&card); + if (error < 0) + return error; if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) { snd_card_free(card); @@ -950,9 +953,9 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, return -EBUSY; if (! isapnp) return -ENODEV; - card = snd_opti9xx_card_new(); - if (! card) - return -ENOMEM; + error = snd_opti9xx_card_new(&card); + if (error < 0) + return error; chip = card->private_data; hw = snd_card_opti9xx_pnp(chip, pcard, pid); diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c index c8c8e21..cafc3a7 100644 --- a/sound/isa/sb/es968.c +++ b/sound/isa/sb/es968.c @@ -108,9 +108,10 @@ static int __devinit snd_card_es968_probe(int dev, struct snd_card *card; struct snd_card_es968 *acard; - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_es968))) == NULL) - return -ENOMEM; + error = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_es968), &card); + if (error < 0) + return error; acard = card->private_data; if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) { snd_card_free(card); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 2c201f7..519c363 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -324,14 +324,18 @@ static void snd_sb16_free(struct snd_card *card) #define is_isapnp_selected(dev) 0 #endif -static struct snd_card *snd_sb16_card_new(int dev) +static int snd_sb16_card_new(int dev, struct snd_card **cardp) { - struct snd_card *card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_sb16)); - if (card == NULL) - return NULL; + struct snd_card *card; + int err; + + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_sb16), &card); + if (err < 0) + return err; card->private_free = snd_sb16_free; - return card; + *cardp = card; + return 0; } static int __devinit snd_sb16_probe(struct snd_card *card, int dev) @@ -489,9 +493,9 @@ static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev) struct snd_card *card; int err; - card = snd_sb16_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_sb16_card_new(dev, &card); + if (err < 0) + return err; acard = card->private_data; /* non-PnP FM port address is hardwired with base port address */ @@ -610,9 +614,9 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, for ( ; dev < SNDRV_CARDS; dev++) { if (!enable[dev] || !isapnp[dev]) continue; - card = snd_sb16_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_sb16_card_new(dev, &card); + if (res < 0) + return res; snd_card_set_dev(card, &pcard->card->dev); if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || (res = snd_sb16_probe(card, dev)) < 0) { diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index ea06877..3cd57ee 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -103,10 +103,10 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) struct snd_opl3 *opl3; int err; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_sb8)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_sb8), &card); + if (err < 0) + return err; acard = card->private_data; card->private_free = snd_sb8_free; diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index ca35924..7a14703 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -489,9 +489,9 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) char __iomem *vmss_port; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if (xirq == SNDRV_AUTO_IRQ) { xirq = snd_legacy_find_free_irq(possible_irqs); diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index 2c7503b..6fe27b9 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c @@ -243,9 +243,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) struct snd_card *card; struct snd_wss *chip; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; xirq = irq[dev]; if (xirq == SNDRV_AUTO_IRQ) { diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 48a16d8..4025fb5 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -1357,10 +1357,10 @@ static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) struct soundscape *sscape; int ret; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct soundscape)); - if (!card) - return -ENOMEM; + ret = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct soundscape), &card); + if (ret < 0) + return ret; sscape = get_card_soundscape(card); sscape->type = SSCAPE; @@ -1462,10 +1462,10 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, * Create a new ALSA sound card entry, in anticipation * of detecting our hardware ... */ - card = snd_card_new(index[idx], id[idx], THIS_MODULE, - sizeof(struct soundscape)); - if (!card) - return -ENOMEM; + ret = snd_card_create(index[idx], id[idx], THIS_MODULE, + sizeof(struct soundscape), &card); + if (ret < 0) + return ret; sscape = get_card_soundscape(card); diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 4c095bc..95898b2 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -338,15 +338,16 @@ snd_wavefront_free(struct snd_card *card) } } -static struct snd_card *snd_wavefront_card_new(int dev) +static int snd_wavefront_card_new(int dev, struct snd_card **cardp) { struct snd_card *card; snd_wavefront_card_t *acard; + int err; - card = snd_card_new (index[dev], id[dev], THIS_MODULE, - sizeof(snd_wavefront_card_t)); - if (card == NULL) - return NULL; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(snd_wavefront_card_t), &card); + if (err < 0) + return err; acard = card->private_data; acard->wavefront.irq = -1; @@ -357,7 +358,8 @@ static struct snd_card *snd_wavefront_card_new(int dev) acard->wavefront.card = card; card->private_free = snd_wavefront_free; - return card; + *cardp = card; + return 0; } static int __devinit @@ -567,9 +569,9 @@ static int __devinit snd_wavefront_isa_probe(struct device *pdev, struct snd_card *card; int err; - card = snd_wavefront_card_new(dev); - if (! card) - return -ENOMEM; + err = snd_wavefront_card_new(dev, &card); + if (err < 0) + return err; snd_card_set_dev(card, pdev); if ((err = snd_wavefront_probe(card, dev)) < 0) { snd_card_free(card); @@ -616,9 +618,9 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, if (dev >= SNDRV_CARDS) return -ENODEV; - card = snd_wavefront_card_new(dev); - if (! card) - return -ENOMEM; + res = snd_wavefront_card_new(dev, &card); + if (res < 0) + return res; if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) { if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 1881cec..99e1391b 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -636,9 +636,10 @@ au1000_init(void) struct snd_card *card; struct snd_au1000 *au1000; - card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(struct snd_au1000)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(-1, "AC97", THIS_MODULE, + sizeof(struct snd_au1000), &card); + if (err < 0) + return err; card->private_free = snd_au1000_free; au1000 = card->private_data; diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index db495be..c52691c 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -878,9 +878,9 @@ static int __devinit hal2_probe(struct platform_device *pdev) struct snd_hal2 *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = hal2_create(card, &chip); if (err < 0) { diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 4c63504..66f3b48 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -936,9 +936,9 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev) struct snd_sgio2audio *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_sgio2audio_create(card, &chip); if (err < 0) { diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 41f870f..6055fd6 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -975,9 +975,9 @@ snd_harmony_probe(struct parisc_device *padev) struct snd_card *card; struct snd_harmony *h; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_harmony_create(card, padev, &h); if (err < 0) diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index a7f38e6..d1f242b 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -995,10 +995,10 @@ snd_ad1889_probe(struct pci_dev *pci, } /* (2) */ - card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, 0, &card); /* XXX REVISIT: we can probably allocate chip in this call */ - if (card == NULL) - return -ENOMEM; + if (err < 0) + return err; strcpy(card->driver, "AD1889"); strcpy(card->shortname, "Analog Devices AD1889"); diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 1a0fd65..b36c551 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -2307,9 +2307,9 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, snd_ali_printk("probe ...\n"); - card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_ali_create(card, pci, pcm_channels, spdif, &codec); if (err < 0) diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 8df6824..f557c15 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -812,10 +812,10 @@ static int __devinit snd_als300_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (card == NULL) - return -ENOMEM; + if (err < 0) + return err; chip_type = pci_id->driver_data; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index ba57005..542a0c6 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -889,12 +889,13 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); pci_set_master(pci); - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(*acard) /* private_data: acard */); - if (card == NULL) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(*acard) /* private_data: acard */, + &card); + if (err < 0) { pci_release_regions(pci); pci_disable_device(pci); - return -ENOMEM; + return err; } acard = card->private_data; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 226fe82..9ce8548 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1645,9 +1645,9 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, struct atiixp *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA"); strcpy(card->shortname, "ATI IXP"); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 0e6e5cc..c3136cc 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1288,9 +1288,9 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, struct atiixp_modem *chip; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ATIIXP-MODEM"); strcpy(card->shortname, "ATI IXP Modem"); diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index a36d4d1..9ec1223 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -250,9 +250,9 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } // (2) - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; // (3) if ((err = snd_vortex_create(card, pci, &chip)) < 0) { diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 3f00ddf..eefcbf6 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -368,9 +368,9 @@ static int __devinit snd_aw2_probe(struct pci_dev *pci, } /* (2) Create card instance */ - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; /* (3) Create main component */ err = snd_aw2_create(card, pci, &chip); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 333007c..1df96e7 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2216,9 +2216,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "AZF3328"); strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 1aa1c04..a299340 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -888,9 +888,9 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_bt87x_create(card, pci, &chip); if (err < 0) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 0e62205..b116456 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1707,9 +1707,9 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; err = snd_ca0106_create(dev, card, pci, &chip); if (err < 0) diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1a74ca6..c7899c3 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -3272,9 +3272,9 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci->device) { case PCI_DEVICE_ID_CMEDIA_CM8738: diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 192e784..b9b07f4 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1925,9 +1925,9 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) { snd_card_free(card); diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index e876b32..c9b3e3d 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -88,9 +88,9 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_cs46xx_create(card, pci, external_amp[dev], thinkpad[dev], &chip)) < 0) { diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index 6dea5b5..dc46432 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c @@ -258,10 +258,10 @@ static int __devinit snd_cs5530_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (card == NULL) - return -ENOMEM; + if (err < 0) + return err; err = snd_cs5530_create(card, pci, &chip); if (err < 0) { diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 826e6de..ac1d72e 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -353,9 +353,9 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) goto probefail_out; diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 8dbc5c4..9d015a7 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -1997,9 +1997,9 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, DE_INIT(("Echoaudio driver starting...\n")); i = 0; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; snd_card_set_dev(card, &pci->dev); diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 8354c1a..c7f3b99 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -114,9 +114,9 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if (max_buffer_size[dev] < 32) max_buffer_size[dev] = 32; else if (max_buffer_size[dev] > 1024) diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 5ff4dbb..31542ad 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -1544,9 +1544,9 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) { snd_card_free(card); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 9bf9536..e00614c 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -2409,9 +2409,9 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_ensoniq_create(card, pci, &ensoniq)) < 0) { snd_card_free(card); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 4cd9a1fa..34a78af 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1799,9 +1799,9 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; for (idx = 0; idx < 5; idx++) { if (pci_resource_start(pci, idx) == 0 || !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index e9c3794..dc97e81 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2645,9 +2645,9 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if (total_bufsize[dev] < 128) total_bufsize[dev] = 128; diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index c129f9e..60cdb9e 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1468,9 +1468,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 11e791b..f960344 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2335,10 +2335,10 @@ static int __devinit azx_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (!card) { + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR SFX "Error creating card!\n"); - return -ENOMEM; + return err; } err = azx_create(card, pci, dev, pci_id->driver_data, &chip); diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 58d7cda..bab1c70 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2648,9 +2648,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ICE1712"); strcpy(card->shortname, "ICEnsemble ICE1712"); diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index bb8d8c7..7ff36d3 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2456,9 +2456,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ICE1724"); strcpy(card->shortname, "ICEnsemble ICE1724"); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 19d3391..671ff65 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -3058,9 +3058,9 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, int err; struct shortname_table *name; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; if (spdif_aclink < 0) spdif_aclink = check_default_spdif_aclink(pci); diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 93449e4..33a843c 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -1269,9 +1269,9 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, int err; struct shortname_table *name; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; strcpy(card->driver, "ICH-MODEM"); strcpy(card->shortname, "Intel ICH"); diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5f8006b..8b79969 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -2443,9 +2443,9 @@ snd_korg1212_probe(struct pci_dev *pci, dev++; return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) { snd_card_free(card); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 59bbaf8..7014154 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2691,9 +2691,9 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci->device) { case PCI_DEVICE_ID_ESS_ALLEGRO: diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index f23a735..bfc19e3 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1365,12 +1365,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, else idx = index[dev] + i; snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); - card = snd_card_new(idx, tmpid, THIS_MODULE, 0); + err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); - if (! card) { + if (err < 0) { snd_printk(KERN_ERR "cannot allocate the card %d\n", i); snd_mixart_free(mgr); - return -ENOMEM; + return err; } strcpy(card->driver, CARD_NAME); diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 50c9f8a..522a040 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1668,9 +1668,9 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, } } - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci->device) { case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO: diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 84f481d..9c81e0b 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -459,10 +459,10 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, struct oxygen *chip; int err; - card = snd_card_new(index, id, model->owner, - sizeof *chip + model->model_data_size); - if (!card) - return -ENOMEM; + err = snd_card_create(index, id, model->owner, + sizeof(*chip) + model->model_data_size, &card); + if (err < 0) + return err; chip = card->private_data; chip->card = card; diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 27cf2c2..7f95459 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1510,12 +1510,12 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i); - card = snd_card_new(idx, tmpid, THIS_MODULE, 0); + err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); - if (! card) { + if (err < 0) { snd_printk(KERN_ERR "cannot allocate the card %d\n", i); pcxhr_free(mgr); - return -ENOMEM; + return err; } strcpy(card->driver, DRIVER_NAME); diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 3caacfb..6f10344 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -2102,9 +2102,9 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_riptide_create(card, pci, &chip)) < 0) { snd_card_free(card); return err; diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index e7ef3a1..d7b966e 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1941,9 +1941,10 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme32))) == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct rme32), &card); + if (err < 0) + return err; card->private_free = snd_rme32_card_free; rme32 = (struct rme32 *) card->private_data; rme32->card = card; diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 3fdd488..55fb1c1 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -2348,9 +2348,10 @@ snd_rme96_probe(struct pci_dev *pci, dev++; return -ENOENT; } - if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme96))) == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct rme96), &card); + if (err < 0) + return err; card->private_free = snd_rme96_card_free; rme96 = (struct rme96 *)card->private_data; rme96->card = card; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 44d0c15..05b3f79 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -5158,8 +5158,10 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, return -ENOENT; } - if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp)))) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct hdsp), &card); + if (err < 0) + return err; hdsp = (struct hdsp *) card->private_data; card->private_free = snd_hdsp_card_free; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 71231cf..d4b4e0d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -4503,10 +4503,10 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], - THIS_MODULE, sizeof(struct hdspm)); - if (!card) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], + THIS_MODULE, sizeof(struct hdspm), &card); + if (err < 0) + return err; hdspm = card->private_data; card->private_free = snd_hdspm_card_free; diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 2570907..bc539ab 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -2594,11 +2594,11 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_rme9652)); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_rme9652), &card); - if (!card) - return -ENOMEM; + if (err < 0) + return err; rme9652 = (struct snd_rme9652 *) card->private_data; card->private_free = snd_rme9652_card_free; diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index df2007e..baf6d8e 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -1387,9 +1387,8 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, if (!enable) goto error_out; - rc = -ENOMEM; - card = snd_card_new(index, id, THIS_MODULE, sizeof(*sis)); - if (!card) + rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); + if (rc < 0) goto error_out; strcpy(card->driver, "SiS7019"); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index cd408b8..c5601b0 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1423,9 +1423,9 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; for (idx = 0; idx < 5; idx++) { if (pci_resource_start(pci, idx) == 0 || !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index d94b16f..21cef97 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -89,9 +89,9 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_trident_create(card, pci, pcm_channels[dev], diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 1aafe95..d870554 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2433,9 +2433,9 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; card_type = pci_id->driver_data; switch (card_type) { diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 5bd79d2..c086b76 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -1167,9 +1167,9 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; card_type = pci_id->driver_data; switch (card_type) { diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index acc352f..fc9136c 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -204,9 +204,9 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch ((int)pci_id->driver_data) { case VX_PCI_VX222_OLD: diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 2631a55..4af6666 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -187,9 +187,9 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci_id->device) { case 0x0004: str = "YMF724"; model = "DS-1"; break; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 819aaaa..7dea74b 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -91,7 +91,7 @@ static int snd_pdacf_dev_free(struct snd_device *device) */ static int snd_pdacf_probe(struct pcmcia_device *link) { - int i; + int i, err; struct snd_pdacf *pdacf; struct snd_card *card; static struct snd_device_ops ops = { @@ -112,20 +112,23 @@ static int snd_pdacf_probe(struct pcmcia_device *link) return -ENODEV; /* disabled explicitly */ /* ok, create a card instance */ - card = snd_card_new(index[i], id[i], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); - return -ENOMEM; + return err; } pdacf = snd_pdacf_create(card); - if (! pdacf) - return -EIO; + if (!pdacf) { + snd_card_free(card); + return -ENOMEM; + } - if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops); + if (err < 0) { kfree(pdacf); snd_card_free(card); - return -ENODEV; + return err; } snd_card_set_dev(card, &handle_to_dev(link)); diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 706602a..7445cc8 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -130,23 +130,26 @@ static struct snd_vx_hardware vxp440_hw = { /* * create vxpocket instance */ -static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl, - struct pcmcia_device *link) +static int snd_vxpocket_new(struct snd_card *card, int ibl, + struct pcmcia_device *link, + struct snd_vxpocket **chip_ret) { struct vx_core *chip; struct snd_vxpocket *vxp; static struct snd_device_ops ops = { .dev_free = snd_vxpocket_dev_free, }; + int err; chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, sizeof(struct snd_vxpocket) - sizeof(struct vx_core)); - if (! chip) - return NULL; + if (!chip) + return -ENOMEM; - if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { kfree(chip); - return NULL; + return err; } chip->ibl.size = ibl; @@ -169,7 +172,8 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl, link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; - return vxp; + *chip_ret = vxp; + return 0; } @@ -292,7 +296,7 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) { struct snd_card *card; struct snd_vxpocket *vxp; - int i; + int i, err; /* find an empty slot from the card list */ for (i = 0; i < SNDRV_CARDS; i++) { @@ -307,16 +311,16 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) return -ENODEV; /* disabled explicitly */ /* ok, create a card instance */ - card = snd_card_new(index[i], id[i], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); - return -ENOMEM; + return err; } - vxp = snd_vxpocket_new(card, ibl[i], p_dev); - if (! vxp) { + err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp); + if (err < 0) { snd_card_free(card); - return -ENODEV; + return err; } card->private_data = vxp; diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index c936225..2e18ed0 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -58,9 +58,9 @@ static int __init snd_pmac_probe(struct platform_device *devptr) char *name_ext; int err; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; if ((err = snd_pmac_new(card, &chip)) < 0) goto __error; diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 8f9e385..ef2c3f4 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -969,11 +969,9 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) } /* create card instance */ - the_card.card = snd_card_new(index, id, THIS_MODULE, 0); - if (!the_card.card) { - ret = -ENXIO; + ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); + if (ret < 0) goto clean_irq; - } strcpy(the_card.card->driver, "PS3"); strcpy(the_card.card->shortname, "PS3"); diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 7c920f3..f551233 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -609,11 +609,11 @@ static int __devinit snd_aica_probe(struct platform_device *devptr) dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL); if (unlikely(!dreamcastcard)) return -ENOMEM; - dreamcastcard->card = - snd_card_new(index, SND_AICA_DRIVER, THIS_MODULE, 0); - if (unlikely(!dreamcastcard->card)) { + err = snd_card_create(index, SND_AICA_DRIVER, THIS_MODULE, 0, + &dreamcastcard->card); + if (unlikely(err < 0)) { kfree(dreamcastcard); - return -ENODEV; + return err; } strcpy(dreamcastcard->card->driver, "snd_aica"); strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index ef025c6..3d2bb6f 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -6,6 +6,7 @@ menuconfig SND_SOC tristate "ALSA for SoC audio support" select SND_PCM select AC97_BUS if SND_SOC_AC97_BUS + select SND_JACK if INPUT=y || INPUT=SND ---help--- If you want ASoC support, you should say Y here and also to the diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 86a9b1f..0237879 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,4 +1,4 @@ -snd-soc-core-objs := soc-core.o soc-dapm.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index 3dcdc4e..9ef6b96 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c @@ -347,7 +347,7 @@ static int atmel_pcm_mmap(struct snd_pcm_substream *substream, vma->vm_end - vma->vm_start, vma->vm_page_prot); } -struct snd_pcm_ops atmel_pcm_ops = { +static struct snd_pcm_ops atmel_pcm_ops = { .open = atmel_pcm_open, .close = atmel_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index bc8d654..30490a2 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -305,7 +305,7 @@ static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) return 0; } -struct snd_pcm_ops au1xpsc_pcm_ops = { +static struct snd_pcm_ops au1xpsc_pcm_ops = { .open = au1xpsc_pcm_open, .close = au1xpsc_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 8067cfa..8cfed1a 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c @@ -297,7 +297,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, } #endif -struct snd_pcm_ops bf5xx_pcm_ac97_ops = { +static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { .open = bf5xx_pcm_open, .ioctl = snd_pcm_lib_ioctl, .hw_params = bf5xx_pcm_hw_params, diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 53d290b..1318c4f 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -184,7 +184,7 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, return 0 ; } -struct snd_pcm_ops bf5xx_pcm_i2s_ops = { +static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { .open = bf5xx_pcm_open, .ioctl = snd_pcm_lib_ioctl, .hw_params = bf5xx_pcm_hw_params, diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d0e0d69..a195303 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" + select SND_SOC_L3 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 if I2C @@ -34,6 +35,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8903 if I2C select SND_SOC_WM8971 if I2C select SND_SOC_WM8990 if I2C + select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS select SND_SOC_WM9713 if SND_SOC_AC97_BUS help @@ -90,7 +92,6 @@ config SND_SOC_SSM2602 config SND_SOC_TLV320AIC23 tristate - depends on I2C config SND_SOC_TLV320AIC26 tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE @@ -98,15 +99,12 @@ config SND_SOC_TLV320AIC26 config SND_SOC_TLV320AIC3X tristate - depends on I2C config SND_SOC_TWL4030 tristate - depends on TWL4030_CORE config SND_SOC_UDA134X tristate - select SND_SOC_L3 config SND_SOC_UDA1380 tristate @@ -144,6 +142,9 @@ config SND_SOC_WM8971 config SND_SOC_WM8990 tristate +config SND_SOC_WM9705 + tristate + config SND_SOC_WM9712 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index c4ddc9a..3664cdc 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -23,6 +23,7 @@ snd-soc-wm8900-objs := wm8900.o snd-soc-wm8903-objs := wm8903.o snd-soc-wm8971-objs := wm8971.o snd-soc-wm8990-objs := wm8990.o +snd-soc-wm9705-objs := wm9705.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o @@ -51,5 +52,7 @@ obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o +obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o +obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index fb53e65..11f84b6 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -30,7 +30,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; @@ -84,10 +84,10 @@ static int ac97_soc_probe(struct platform_device *pdev) printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (!socdev->codec) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (!socdev->card->codec) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->name = "AC97"; @@ -123,23 +123,21 @@ bus_err: snd_soc_free_pcms(socdev); err: - kfree(socdev->codec->reg_cache); - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int ac97_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (!codec) return 0; snd_soc_free_pcms(socdev); - kfree(socdev->codec->reg_cache); - kfree(socdev->codec); + kfree(socdev->card->codec); return 0; } @@ -149,7 +147,7 @@ static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - snd_ac97_suspend(socdev->codec->ac97); + snd_ac97_suspend(socdev->card->codec->ac97); return 0; } @@ -158,7 +156,7 @@ static int ac97_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - snd_ac97_resume(socdev->codec->ac97); + snd_ac97_resume(socdev->card->codec->ac97); return 0; } diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 73fdbb4..ddb3b08 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -93,20 +93,6 @@ SOC_ENUM("Capture Source", ad1980_cap_src), SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), }; -/* add non dapm controls */ -static int ad1980_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(ad1980_snd_ac97_controls); i++) { - err = snd_ctl_add(codec->card, snd_soc_cnew( - &ad1980_snd_ac97_controls[i], codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) { @@ -123,7 +109,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, default: reg = reg >> 1; - if (reg >= (ARRAY_SIZE(ad1980_reg))) + if (reg >= ARRAY_SIZE(ad1980_reg)) return -EINVAL; return cache[reg]; @@ -137,7 +123,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; - if (reg < (ARRAY_SIZE(ad1980_reg))) + if (reg < ARRAY_SIZE(ad1980_reg)) cache[reg] = val; return 0; @@ -200,10 +186,10 @@ static int ad1980_soc_probe(struct platform_device *pdev) printk(KERN_INFO "AD1980 SoC Audio Codec\n"); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (socdev->card->codec == NULL) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->reg_cache = @@ -269,7 +255,8 @@ static int ad1980_soc_probe(struct platform_device *pdev) ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); - ad1980_add_controls(codec); + snd_soc_add_controls(codec, ad1980_snd_ac97_controls, + ARRAY_SIZE(ad1980_snd_ac97_controls)); ret = snd_soc_init_card(socdev); if (ret < 0) { printk(KERN_ERR "ad1980: failed to register card\n"); @@ -288,15 +275,15 @@ codec_err: kfree(codec->reg_cache); cache_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int ad1980_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index b09289a..e61dac5 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -53,7 +53,7 @@ static int ad73311_soc_probe(struct platform_device *pdev) codec->owner = THIS_MODULE; codec->dai = &ad73311_dai; codec->num_dai = 1; - socdev->codec = codec; + socdev->card->codec = codec; INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -75,15 +75,15 @@ static int ad73311_soc_probe(struct platform_device *pdev) register_err: snd_soc_free_pcms(socdev); pcm_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int ad73311_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 81300d8d..d56e6bb 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -155,21 +155,6 @@ static const struct snd_kcontrol_new ak4535_snd_controls[] = { SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0), }; -/* add non dapm controls */ -static int ak4535_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&ak4535_snd_controls[i], codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Mono 1 Mixer */ static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = { SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0), @@ -344,7 +329,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ak4535_priv *ak4535 = codec->private_data; u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); int rate = params_rate(params), fs = 256; @@ -462,7 +447,7 @@ EXPORT_SYMBOL_GPL(ak4535_dai); static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -471,7 +456,7 @@ static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) static int ak4535_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; ak4535_sync(codec); ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ak4535_set_bias_level(codec, codec->suspend_bias_level); @@ -484,7 +469,7 @@ static int ak4535_resume(struct platform_device *pdev) */ static int ak4535_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "AK4535"; @@ -510,7 +495,8 @@ static int ak4535_init(struct snd_soc_device *socdev) /* power on device */ ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - ak4535_add_controls(codec); + snd_soc_add_controls(codec, ak4535_snd_controls, + ARRAY_SIZE(ak4535_snd_controls)); ak4535_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -537,7 +523,7 @@ static int ak4535_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = ak4535_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -636,7 +622,7 @@ static int ak4535_probe(struct platform_device *pdev) } codec->private_data = ak4535; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -663,7 +649,7 @@ static int ak4535_probe(struct platform_device *pdev) static int ak4535_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index f1aa0c3..21253b4 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -12,11 +12,7 @@ * * Current features/limitations: * - * 1) Software mode is supported. Stand-alone mode is automatically - * selected if I2C is disabled or if a CS4270 is not found on the I2C - * bus. However, stand-alone mode is only partially implemented because - * there is no mechanism yet for this driver and the machine driver to - * communicate the values of the M0, M1, MCLK1, and MCLK2 pins. + * 1) Software mode is supported. Stand-alone mode is not supported. * 2) Only I2C is supported, not SPI * 3) Only Master mode is supported, not Slave. * 4) The machine driver's 'startup' function must call @@ -35,18 +31,6 @@ #include "cs4270.h" -/* If I2C is defined, then we support software mode. However, if we're - not compiled as module but I2C is, then we can't use I2C calls. */ -#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) -#define USE_I2C -#endif - -/* Private data for the CS4270 */ -struct cs4270_private { - unsigned int mclk; /* Input frequency of the MCLK pin */ - unsigned int mode; /* The mode (I2S or left-justified) */ -}; - /* * The codec isn't really big-endian or little-endian, since the I2S * interface requires data to be sent serially with the MSbit first. @@ -60,8 +44,6 @@ struct cs4270_private { SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) -#ifdef USE_I2C - /* CS4270 registers addresses */ #define CS4270_CHIPID 0x01 /* Chip ID */ #define CS4270_PWRCTL 0x02 /* Power Control */ @@ -121,6 +103,14 @@ struct cs4270_private { #define CS4270_MUTE_DAC_A 0x01 #define CS4270_MUTE_DAC_B 0x02 +/* Private data for the CS4270 */ +struct cs4270_private { + struct snd_soc_codec codec; + u8 reg_cache[CS4270_NUMREGS]; + unsigned int mclk; /* Input frequency of the MCLK pin */ + unsigned int mode; /* The mode (I2S or left-justified) */ +}; + /* * Clock Ratio Selection for Master Mode with I2C enabled * @@ -272,17 +262,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, } /* - * A list of addresses on which this CS4270 could use. I2C addresses are - * 7 bits. For the CS4270, the upper four bits are always 1001, and the - * lower three bits are determined via the AD2, AD1, and AD0 pins - * (respectively). - */ -static const unsigned short normal_i2c[] = { - 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END -}; -I2C_CLIENT_INSMOD; - -/* * Pre-fill the CS4270 register cache. * * We use the auto-increment feature of the CS4270 to read all registers in @@ -371,7 +350,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct cs4270_private *cs4270 = codec->private_data; int ret; unsigned int i; @@ -476,7 +455,6 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, } #ifdef CONFIG_SND_SOC_CS4270_HWMUTE - /* * Set the CS4270 external mute * @@ -501,32 +479,16 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute) return snd_soc_write(codec, CS4270_MUTE, reg6); } - +#else +#define cs4270_mute NULL #endif -static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *); - /* A list of non-DAPM controls that the CS4270 supports */ static const struct snd_kcontrol_new cs4270_snd_controls[] = { SOC_DOUBLE_R("Master Playback Volume", CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) }; -static const struct i2c_device_id cs4270_id[] = { - {"cs4270", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs4270_id); - -static struct i2c_driver cs4270_i2c_driver = { - .driver = { - .name = "CS4270 I2C", - .owner = THIS_MODULE, - }, - .id_table = cs4270_id, - .probe = cs4270_i2c_probe, -}; - /* * Global variable to store socdev for i2c probe function. * @@ -544,6 +506,31 @@ static struct i2c_driver cs4270_i2c_driver = { */ static struct snd_soc_device *cs4270_socdev; +struct snd_soc_dai cs4270_dai = { + .name = "cs4270", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = 0, + .formats = CS4270_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = 0, + .formats = CS4270_FORMATS, + }, + .ops = { + .hw_params = cs4270_hw_params, + .set_sysclk = cs4270_set_dai_sysclk, + .set_fmt = cs4270_set_dai_fmt, + .digital_mute = cs4270_mute, + }, +}; +EXPORT_SYMBOL_GPL(cs4270_dai); + /* * Initialize the I2C interface of the CS4270 * @@ -557,125 +544,38 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct snd_soc_device *socdev = cs4270_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec; + struct cs4270_private *cs4270; int i; int ret = 0; - /* Probing all possible addresses has one drawback: if there are - multiple CS4270s on the bus, then you cannot specify which - socdev is matched with which CS4270. For now, we just reject - this I2C device if the socdev already has one attached. */ - if (codec->control_data) - return -ENODEV; - - /* Note: codec_dai->codec is NULL here */ - - codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); - if (!codec->reg_cache) { - printk(KERN_ERR "cs4270: could not allocate register cache\n"); - ret = -ENOMEM; - goto error; - } - /* Verify that we have a CS4270 */ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); if (ret < 0) { printk(KERN_ERR "cs4270: failed to read I2C\n"); - goto error; + return ret; } /* The top four bits of the chip ID should be 1100. */ if ((ret & 0xF0) != 0xC0) { - /* The device at this address is not a CS4270 codec */ - ret = -ENODEV; - goto error; + printk(KERN_ERR "cs4270: device at addr %X is not a CS4270\n", + i2c_client->addr); + return -ENODEV; } printk(KERN_INFO "cs4270: found device at I2C address %X\n", i2c_client->addr); printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); - codec->control_data = i2c_client; - codec->read = cs4270_read_reg_cache; - codec->write = cs4270_i2c_write; - codec->reg_cache_size = CS4270_NUMREGS; - - /* The I2C interface is set up, so pre-fill our register cache */ - - ret = cs4270_fill_cache(codec); - if (ret < 0) { - printk(KERN_ERR "cs4270: failed to fill register cache\n"); - goto error; - } - - /* Add the non-DAPM controls */ - - for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { - struct snd_kcontrol *kctrl = - snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); - - ret = snd_ctl_add(codec->card, kctrl); - if (ret < 0) - goto error; - } - - i2c_set_clientdata(i2c_client, codec); - - return 0; - -error: - codec->control_data = NULL; - - kfree(codec->reg_cache); - codec->reg_cache = NULL; - codec->reg_cache_size = 0; - - return ret; -} - -#endif /* USE_I2C*/ - -struct snd_soc_dai cs4270_dai = { - .name = "CS4270", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = 0, - .formats = CS4270_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = 0, - .formats = CS4270_FORMATS, - }, -}; -EXPORT_SYMBOL_GPL(cs4270_dai); - -/* - * ASoC probe function - * - * This function is called when the machine driver calls - * platform_device_add(). - */ -static int cs4270_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - printk(KERN_INFO "CS4270 ALSA SoC Codec\n"); - /* Allocate enough space for the snd_soc_codec structure and our private data together. */ - codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) + - sizeof(struct cs4270_private), GFP_KERNEL); - if (!codec) { + cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); + if (!cs4270) { printk(KERN_ERR "cs4270: Could not allocate codec structure\n"); return -ENOMEM; } + codec = &cs4270->codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); @@ -685,10 +585,20 @@ static int cs4270_probe(struct platform_device *pdev) codec->owner = THIS_MODULE; codec->dai = &cs4270_dai; codec->num_dai = 1; - codec->private_data = (void *) codec + - ALIGN(sizeof(struct snd_soc_codec), 4); + codec->private_data = cs4270; + codec->control_data = i2c_client; + codec->read = cs4270_read_reg_cache; + codec->write = cs4270_i2c_write; + codec->reg_cache = cs4270->reg_cache; + codec->reg_cache_size = CS4270_NUMREGS; - socdev->codec = codec; + /* The I2C interface is set up, so pre-fill our register cache */ + + ret = cs4270_fill_cache(codec); + if (ret < 0) { + printk(KERN_ERR "cs4270: failed to fill register cache\n"); + goto error_free_codec; + } /* Register PCMs */ @@ -698,66 +608,92 @@ static int cs4270_probe(struct platform_device *pdev) goto error_free_codec; } -#ifdef USE_I2C - cs4270_socdev = socdev; + /* Add the non-DAPM controls */ + + for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { + struct snd_kcontrol *kctrl; + + kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); + if (!kctrl) { + printk(KERN_ERR "cs4270: error creating control '%s'\n", + cs4270_snd_controls[i].name); + ret = -ENOMEM; + goto error_free_pcms; + } - ret = i2c_add_driver(&cs4270_i2c_driver); - if (ret) { - printk(KERN_ERR "cs4270: failed to attach driver"); - goto error_free_pcms; + ret = snd_ctl_add(codec->card, kctrl); + if (ret < 0) { + printk(KERN_ERR "cs4270: error adding control '%s'\n", + cs4270_snd_controls[i].name); + goto error_free_pcms; + } } - /* Did we find a CS4270 on the I2C bus? */ - if (codec->control_data) { - /* Initialize codec ops */ - cs4270_dai.ops.hw_params = cs4270_hw_params; - cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk; - cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt; -#ifdef CONFIG_SND_SOC_CS4270_HWMUTE - cs4270_dai.ops.digital_mute = cs4270_mute; -#endif - } else - printk(KERN_INFO "cs4270: no I2C device found, " - "using stand-alone mode\n"); -#else - printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); -#endif + /* Initialize the SOC device */ ret = snd_soc_init_card(socdev); if (ret < 0) { printk(KERN_ERR "cs4270: failed to register card\n"); - goto error_del_driver; + goto error_free_pcms;; } - return 0; + i2c_set_clientdata(i2c_client, socdev); -error_del_driver: -#ifdef USE_I2C - i2c_del_driver(&cs4270_i2c_driver); + return 0; error_free_pcms: -#endif snd_soc_free_pcms(socdev); error_free_codec: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(cs4270); return ret; } -static int cs4270_remove(struct platform_device *pdev) +static int cs4270_i2c_remove(struct i2c_client *i2c_client) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_device *socdev = i2c_get_clientdata(i2c_client); + struct snd_soc_codec *codec = socdev->card->codec; + struct cs4270_private *cs4270 = codec->private_data; snd_soc_free_pcms(socdev); + kfree(cs4270); -#ifdef USE_I2C - i2c_del_driver(&cs4270_i2c_driver); -#endif + return 0; +} - kfree(socdev->codec); - socdev->codec = NULL; +static struct i2c_device_id cs4270_id[] = { + {"cs4270", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs4270_id); + +static struct i2c_driver cs4270_i2c_driver = { + .driver = { + .name = "cs4270", + .owner = THIS_MODULE, + }, + .id_table = cs4270_id, + .probe = cs4270_i2c_probe, + .remove = cs4270_i2c_remove, +}; + +/* + * ASoC probe function + * + * This function is called when the machine driver calls + * platform_device_add(). + */ +static int cs4270_probe(struct platform_device *pdev) +{ + cs4270_socdev = platform_get_drvdata(pdev);; + + return i2c_add_driver(&cs4270_i2c_driver); +} + +static int cs4270_remove(struct platform_device *pdev) +{ + i2c_del_driver(&cs4270_i2c_driver); return 0; } @@ -776,6 +712,8 @@ EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); static int __init cs4270_init(void) { + printk(KERN_INFO "Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); + return snd_soc_register_dai(&cs4270_dai); } module_init(cs4270_init); diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 9a3e67e..5cda9e6 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -67,11 +67,11 @@ static int pcm3008_soc_probe(struct platform_device *pdev) printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (!socdev->codec) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (!socdev->card->codec) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->name = "PCM3008"; @@ -139,7 +139,7 @@ gpio_err: card_err: snd_soc_free_pcms(socdev); pcm_err: - kfree(socdev->codec); + kfree(socdev->card->codec); return ret; } @@ -147,7 +147,7 @@ pcm_err: static int pcm3008_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct pcm3008_setup_data *setup = socdev->codec_data; if (!codec) @@ -155,7 +155,7 @@ static int pcm3008_soc_remove(struct platform_device *pdev) pcm3008_gpio_free(setup); snd_soc_free_pcms(socdev); - kfree(socdev->codec); + kfree(socdev->card->codec); return 0; } diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index cac3736..58e225d 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -151,21 +151,6 @@ SOC_ENUM("Capture Source", ssm2602_enum[0]), SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), }; -/* add non dapm controls */ -static int ssm2602_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(ssm2602_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&ssm2602_snd_controls[i], codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Output Mixer */ static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), @@ -291,7 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, u16 srate; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ssm2602_priv *ssm2602 = codec->private_data; struct i2c_client *i2c = codec->control_data; u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; @@ -336,7 +321,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ssm2602_priv *ssm2602 = codec->private_data; struct i2c_client *i2c = codec->control_data; struct snd_pcm_runtime *master_runtime; @@ -373,7 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* set active */ ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); @@ -385,7 +370,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct ssm2602_priv *ssm2602 = codec->private_data; /* deactivate */ if (!codec->active) @@ -550,7 +535,7 @@ EXPORT_SYMBOL_GPL(ssm2602_dai); static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -559,7 +544,7 @@ static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) static int ssm2602_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -581,7 +566,7 @@ static int ssm2602_resume(struct platform_device *pdev) */ static int ssm2602_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "SSM2602"; @@ -622,7 +607,8 @@ static int ssm2602_init(struct snd_soc_device *socdev) APANA_ENABLE_MIC_BOOST); ssm2602_write(codec, SSM2602_PWR, 0); - ssm2602_add_controls(codec); + snd_soc_add_controls(codec, ssm2602_snd_controls, + ARRAY_SIZE(ssm2602_snd_controls)); ssm2602_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -653,7 +639,7 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = ssm2602_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -747,7 +733,7 @@ static int ssm2602_probe(struct platform_device *pdev) } codec->private_data = ssm2602; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -768,7 +754,7 @@ static int ssm2602_probe(struct platform_device *pdev) static int ssm2602_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index cfdea00..8b20c36 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -183,24 +183,6 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), }; -/* add non dapm controls */ -static int tlv320aic23_add_controls(struct snd_soc_codec *codec) -{ - - int err, i; - - for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&tlv320aic23_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; - -} - /* PGA Mixer controls for Line and Mic switch */ static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0), @@ -423,7 +405,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 iface_reg; int ret; struct aic23 *aic23 = container_of(codec, struct aic23, codec); @@ -471,7 +453,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* set active */ tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); @@ -484,7 +466,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic23 *aic23 = container_of(codec, struct aic23, codec); /* deactivate */ @@ -627,7 +609,7 @@ static int tlv320aic23_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -638,7 +620,7 @@ static int tlv320aic23_suspend(struct platform_device *pdev, static int tlv320aic23_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u16 reg; @@ -660,7 +642,7 @@ static int tlv320aic23_resume(struct platform_device *pdev) */ static int tlv320aic23_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; u16 reg; @@ -718,7 +700,8 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); - tlv320aic23_add_controls(codec); + snd_soc_add_controls(codec, tlv320aic23_snd_controls, + ARRAY_SIZE(tlv320aic23_snd_controls)); tlv320aic23_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -746,7 +729,7 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) { struct snd_soc_device *socdev = tlv320aic23_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -804,7 +787,7 @@ static int tlv320aic23_probe(struct platform_device *pdev) if (aic23 == NULL) return -ENOMEM; codec = &aic23->codec; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -823,7 +806,7 @@ static int tlv320aic23_probe(struct platform_device *pdev) static int tlv320aic23_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic23 *aic23 = container_of(codec, struct aic23, codec); if (codec->control_data) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 29f2f1a..229e464 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -130,7 +130,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic26 *aic26 = codec->private_data; int fsref, divisor, wlen, pval, jval, dval, qval; u16 reg; @@ -338,7 +338,7 @@ static int aic26_probe(struct platform_device *pdev) return -ENODEV; } codec = &aic26->codec; - socdev->codec = codec; + socdev->card->codec = codec; dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", &pdev->dev, socdev->dev); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index b47a749..ba64b0c 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -311,22 +311,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), }; -/* add non dapm controls */ -static int aic3x_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(aic3x_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&aic3x_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Left DAC Mux */ static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); @@ -743,7 +727,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic3x_priv *aic3x = codec->private_data; int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; @@ -1095,7 +1079,7 @@ EXPORT_SYMBOL_GPL(aic3x_dai); static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -1105,7 +1089,7 @@ static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) static int aic3x_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u8 *cache = codec->reg_cache; @@ -1128,7 +1112,7 @@ static int aic3x_resume(struct platform_device *pdev) */ static int aic3x_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct aic3x_setup_data *setup = socdev->codec_data; int reg, ret = 0; @@ -1224,7 +1208,8 @@ static int aic3x_init(struct snd_soc_device *socdev) aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); - aic3x_add_controls(codec); + snd_soc_add_controls(codec, aic3x_snd_controls, + ARRAY_SIZE(aic3x_snd_controls)); aic3x_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -1258,7 +1243,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = aic3x_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -1363,7 +1348,7 @@ static int aic3x_probe(struct platform_device *pdev) } codec->private_data = aic3x; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1389,7 +1374,7 @@ static int aic3x_probe(struct platform_device *pdev) static int aic3x_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* power down chip */ if (codec->control_data) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index ea370a4..f985bef 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -42,7 +42,7 @@ */ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { 0x00, /* this register not used */ - 0x93, /* REG_CODEC_MODE (0x1) */ + 0x91, /* REG_CODEC_MODE (0x1) */ 0xc3, /* REG_OPTION (0x2) */ 0x00, /* REG_UNKNOWN (0x3) */ 0x00, /* REG_MICBIAS_CTL (0x4) */ @@ -125,6 +125,9 @@ static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, { u8 *cache = codec->reg_cache; + if (reg >= TWL4030_CACHEREGNUM) + return -EIO; + return cache[reg]; } @@ -151,26 +154,17 @@ static int twl4030_write(struct snd_soc_codec *codec, return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); } -static void twl4030_clear_codecpdz(struct snd_soc_codec *codec) +static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) { u8 mode; mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); - twl4030_write(codec, TWL4030_REG_CODEC_MODE, - mode & ~TWL4030_CODECPDZ); + if (enable) + mode |= TWL4030_CODECPDZ; + else + mode &= ~TWL4030_CODECPDZ; - /* REVISIT: this delay is present in TI sample drivers */ - /* but there seems to be no TRM requirement for it */ - udelay(10); -} - -static void twl4030_set_codecpdz(struct snd_soc_codec *codec) -{ - u8 mode; - - mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); - twl4030_write(codec, TWL4030_REG_CODEC_MODE, - mode | TWL4030_CODECPDZ); + twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); /* REVISIT: this delay is present in TI sample drivers */ /* but there seems to be no TRM requirement for it */ @@ -182,7 +176,7 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) int i; /* clear CODECPDZ prior to setting register defaults */ - twl4030_clear_codecpdz(codec); + twl4030_codec_enable(codec, 0); /* set all audio section registers to reasonable defaults */ for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) @@ -190,6 +184,48 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) } +static void twl4030_power_up(struct snd_soc_codec *codec) +{ + u8 anamicl, regmisc1, byte; + int i = 0; + + /* set CODECPDZ to turn on codec */ + twl4030_codec_enable(codec, 1); + + /* initiate offset cancellation */ + anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); + twl4030_write(codec, TWL4030_REG_ANAMICL, + anamicl | TWL4030_CNCL_OFFSET_START); + + /* wait for offset cancellation to complete */ + do { + /* this takes a little while, so don't slam i2c */ + udelay(2000); + twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, + TWL4030_REG_ANAMICL); + } while ((i++ < 100) && + ((byte & TWL4030_CNCL_OFFSET_START) == + TWL4030_CNCL_OFFSET_START)); + + /* Make sure that the reg_cache has the same value as the HW */ + twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); + + /* anti-pop when changing analog gain */ + regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); + twl4030_write(codec, TWL4030_REG_MISC_SET_1, + regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); + + /* toggle CODECPDZ as per TRM */ + twl4030_codec_enable(codec, 0); + twl4030_codec_enable(codec, 1); +} + +static void twl4030_power_down(struct snd_soc_codec *codec) +{ + /* power down */ + twl4030_codec_enable(codec, 0); +} + /* Earpiece */ static const char *twl4030_earpiece_texts[] = {"Off", "DACL1", "DACL2", "DACR1"}; @@ -420,6 +456,47 @@ static int handsfree_event(struct snd_soc_dapm_widget *w, return 0; } +static int headsetl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + unsigned char hs_gain, hs_pop; + + /* Save the current volume */ + hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* Do the anti-pop/bias ramp enable according to the TRM */ + hs_pop = TWL4030_RAMP_DELAY_645MS; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + hs_pop |= TWL4030_VMID_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + /* Is this needed? Can we just use whatever gain here? */ + twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, + (hs_gain & (~0x0f)) | 0x0a); + hs_pop |= TWL4030_RAMP_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + + /* Restore the original volume */ + twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, hs_gain); + break; + case SND_SOC_DAPM_POST_PMD: + /* Do the anti-pop/bias ramp disable according to the TRM */ + hs_pop = twl4030_read_reg_cache(w->codec, + TWL4030_REG_HS_POPN_SET); + hs_pop &= ~TWL4030_RAMP_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + /* Bypass the reg_cache to mute the headset */ + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + hs_gain & (~0x0f), + TWL4030_REG_HS_GAIN_SET); + hs_pop &= ~TWL4030_VMID_EN; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + break; + } + return 0; +} + /* * Some of the gain controls in TWL (mostly those which are associated with * the outputs) are implemented in an interesting way: @@ -670,22 +747,6 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { 0, 3, 5, 0, input_gain_tlv), }; -/* add non dapm controls */ -static int twl4030_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&twl4030_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { /* Left channel inputs */ SND_SOC_DAPM_INPUT("MAINMIC"), @@ -742,8 +803,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0, &twl4030_dapm_predriver_control), /* HeadsetL/R */ - SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_hsol_control), + SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0, + &twl4030_dapm_hsol_control, headsetl_event, + SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, &twl4030_dapm_hsor_control), /* CarkitL/R */ @@ -782,16 +844,16 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| SND_SOC_DAPM_POST_REG), - /* Analog input muxes with power switch for the physical ADCL/R */ + /* Analog input muxes with switch for the capture amplifiers */ SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route", - TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control), + TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control), SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route", - TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control), + TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control), - SND_SOC_DAPM_PGA("Analog Left Amplifier", - TWL4030_REG_ANAMICL, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Analog Right Amplifier", - TWL4030_REG_ANAMICR, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC Physical Left", + TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC Physical Right", + TWL4030_REG_AVADC_CTL, 1, 0, NULL, 0), SND_SOC_DAPM_PGA("Digimic0 Enable", TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0), @@ -865,23 +927,23 @@ static const struct snd_soc_dapm_route intercon[] = { {"Analog Right Capture Route", "Sub mic", "SUBMIC"}, {"Analog Right Capture Route", "AUXR", "AUXR"}, - {"Analog Left Amplifier", NULL, "Analog Left Capture Route"}, - {"Analog Right Amplifier", NULL, "Analog Right Capture Route"}, + {"ADC Physical Left", NULL, "Analog Left Capture Route"}, + {"ADC Physical Right", NULL, "Analog Right Capture Route"}, {"Digimic0 Enable", NULL, "DIGIMIC0"}, {"Digimic1 Enable", NULL, "DIGIMIC1"}, /* TX1 Left capture path */ - {"TX1 Capture Route", "Analog", "Analog Left Amplifier"}, + {"TX1 Capture Route", "Analog", "ADC Physical Left"}, {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, /* TX1 Right capture path */ - {"TX1 Capture Route", "Analog", "Analog Right Amplifier"}, + {"TX1 Capture Route", "Analog", "ADC Physical Right"}, {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, /* TX2 Left capture path */ - {"TX2 Capture Route", "Analog", "Analog Left Amplifier"}, + {"TX2 Capture Route", "Analog", "ADC Physical Left"}, {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, /* TX2 Right capture path */ - {"TX2 Capture Route", "Analog", "Analog Right Amplifier"}, + {"TX2 Capture Route", "Analog", "ADC Physical Right"}, {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, {"ADC Virtual Left1", NULL, "TX1 Capture Route"}, @@ -902,69 +964,6 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec) return 0; } -static void twl4030_power_up(struct snd_soc_codec *codec) -{ - u8 anamicl, regmisc1, byte, popn; - int i = 0; - - /* set CODECPDZ to turn on codec */ - twl4030_set_codecpdz(codec); - - /* initiate offset cancellation */ - anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); - twl4030_write(codec, TWL4030_REG_ANAMICL, - anamicl | TWL4030_CNCL_OFFSET_START); - - - /* wait for offset cancellation to complete */ - do { - /* this takes a little while, so don't slam i2c */ - udelay(2000); - twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, - TWL4030_REG_ANAMICL); - } while ((i++ < 100) && - ((byte & TWL4030_CNCL_OFFSET_START) == - TWL4030_CNCL_OFFSET_START)); - - /* anti-pop when changing analog gain */ - regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); - twl4030_write(codec, TWL4030_REG_MISC_SET_1, - regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); - - /* toggle CODECPDZ as per TRM */ - twl4030_clear_codecpdz(codec); - twl4030_set_codecpdz(codec); - - /* program anti-pop with bias ramp delay */ - popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - popn &= TWL4030_RAMP_DELAY; - popn |= TWL4030_RAMP_DELAY_645MS; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - popn |= TWL4030_VMID_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - - /* enable anti-pop ramp */ - popn |= TWL4030_RAMP_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); -} - -static void twl4030_power_down(struct snd_soc_codec *codec) -{ - u8 popn; - - /* disable anti-pop ramp */ - popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - popn &= ~TWL4030_RAMP_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - - /* disable bias out */ - popn &= ~TWL4030_VMID_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); - - /* power down */ - twl4030_clear_codecpdz(codec); -} - static int twl4030_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -994,7 +993,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u8 mode, old_mode, format, old_format; @@ -1040,7 +1039,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, if (mode != old_mode) { /* change rate and set CODECPDZ */ twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 1); } /* sample size */ @@ -1063,13 +1062,13 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, if (format != old_format) { /* clear CODECPDZ before changing format (codec requirement) */ - twl4030_clear_codecpdz(codec); + twl4030_codec_enable(codec, 0); /* change format */ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); /* set CODECPDZ afterwards */ - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 1); } return 0; } @@ -1139,13 +1138,13 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, if (format != old_format) { /* clear CODECPDZ before changing format (codec requirement) */ - twl4030_clear_codecpdz(codec); + twl4030_codec_enable(codec, 0); /* change format */ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); /* set CODECPDZ afterwards */ - twl4030_set_codecpdz(codec); + twl4030_codec_enable(codec, 1); } return 0; @@ -1179,7 +1178,7 @@ EXPORT_SYMBOL_GPL(twl4030_dai); static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -1189,7 +1188,7 @@ static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) static int twl4030_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); twl4030_set_bias_level(codec, codec->suspend_bias_level); @@ -1203,7 +1202,7 @@ static int twl4030_resume(struct platform_device *pdev) static int twl4030_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; printk(KERN_INFO "TWL4030 Audio Codec init \n"); @@ -1233,7 +1232,8 @@ static int twl4030_init(struct snd_soc_device *socdev) /* power on device */ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - twl4030_add_controls(codec); + snd_soc_add_controls(codec, twl4030_snd_controls, + ARRAY_SIZE(twl4030_snd_controls)); twl4030_add_widgets(codec); ret = snd_soc_init_card(socdev); @@ -1263,7 +1263,7 @@ static int twl4030_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1277,7 +1277,7 @@ static int twl4030_probe(struct platform_device *pdev) static int twl4030_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; printk(KERN_INFO "TWL4030 Audio Codec remove\n"); snd_soc_free_pcms(socdev); diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index a2c5064..6615992 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -173,7 +173,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct uda134x_priv *uda134x = codec->private_data; struct snd_pcm_runtime *master_runtime; @@ -206,7 +206,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct uda134x_priv *uda134x = codec->private_data; if (uda134x->master_substream == substream) @@ -221,7 +221,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct uda134x_priv *uda134x = codec->private_data; u8 hw_params; @@ -431,39 +431,6 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), }; -static int uda134x_add_controls(struct snd_soc_codec *codec) -{ - int err, i, n; - const struct snd_kcontrol_new *ctrls; - struct uda134x_platform_data *pd = codec->control_data; - - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1344: - n = ARRAY_SIZE(uda1340_snd_controls); - ctrls = uda1340_snd_controls; - break; - case UDA134X_UDA1341: - n = ARRAY_SIZE(uda1341_snd_controls); - ctrls = uda1341_snd_controls; - break; - default: - printk(KERN_ERR "%s unkown codec type: %d", - __func__, pd->model); - return -EINVAL; - } - - for (i = 0; i < n; i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&ctrls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - struct snd_soc_dai uda134x_dai = { .name = "UDA134X", /* playback capabilities */ @@ -525,11 +492,11 @@ static int uda134x_soc_probe(struct platform_device *pdev) return -EINVAL; } - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (socdev->card->codec == NULL) return ret; - codec = socdev->codec; + codec = socdev->card->codec; uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); if (uda134x == NULL) @@ -572,7 +539,22 @@ static int uda134x_soc_probe(struct platform_device *pdev) goto pcm_err; } - ret = uda134x_add_controls(codec); + switch (pd->model) { + case UDA134X_UDA1340: + case UDA134X_UDA1344: + ret = snd_soc_add_controls(codec, uda1340_snd_controls, + ARRAY_SIZE(uda1340_snd_controls)); + break; + case UDA134X_UDA1341: + ret = snd_soc_add_controls(codec, uda1341_snd_controls, + ARRAY_SIZE(uda1341_snd_controls)); + break; + default: + printk(KERN_ERR "%s unkown codec type: %d", + __func__, pd->model); + return -EINVAL; + } + if (ret < 0) { printk(KERN_ERR "UDA134X: failed to register controls\n"); goto pcm_err; @@ -602,7 +584,7 @@ priv_err: static int uda134x_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -622,7 +604,7 @@ static int uda134x_soc_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -632,7 +614,7 @@ static int uda134x_soc_suspend(struct platform_device *pdev, static int uda134x_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index e6bf084..98e4a65 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -271,21 +271,6 @@ static const struct snd_kcontrol_new uda1380_snd_controls[] = { SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), }; -/* add non dapm controls */ -static int uda1380_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&uda1380_snd_controls[i], codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Input mux */ static const struct snd_kcontrol_new uda1380_input_mux_control = SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); @@ -412,7 +397,7 @@ static int uda1380_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, reg_start, reg_end, clk; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -445,7 +430,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* set WSPLL power and divider if running from this clock */ @@ -484,7 +469,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* shut down WSPLL power if running from this clock */ @@ -606,7 +591,7 @@ EXPORT_SYMBOL_GPL(uda1380_dai); static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -615,7 +600,7 @@ static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) static int uda1380_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -637,7 +622,7 @@ static int uda1380_resume(struct platform_device *pdev) */ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "UDA1380"; @@ -675,7 +660,8 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) } /* uda1380 init */ - uda1380_add_controls(codec); + snd_soc_add_controls(codec, uda1380_snd_controls, + ARRAY_SIZE(uda1380_snd_controls)); uda1380_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -702,7 +688,7 @@ static int uda1380_i2c_probe(struct i2c_client *i2c, { struct snd_soc_device *socdev = uda1380_socdev; struct uda1380_setup_data *setup = socdev->codec_data; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -793,7 +779,7 @@ static int uda1380_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -817,7 +803,7 @@ static int uda1380_probe(struct platform_device *pdev) static int uda1380_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index e3989d4..75d3438 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -51,10 +51,17 @@ struct wm8350_output { u16 mute; }; +struct wm8350_jack_data { + struct snd_soc_jack *jack; + int report; +}; + struct wm8350_data { struct snd_soc_codec codec; struct wm8350_output out1; struct wm8350_output out2; + struct wm8350_jack_data hpl; + struct wm8350_jack_data hpr; struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; }; @@ -775,21 +782,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Beep", NULL, "IN3R PGA"}, }; -static int wm8350_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8350_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static int wm8350_add_widgets(struct snd_soc_codec *codec) { int ret; @@ -1309,7 +1301,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -1318,7 +1310,7 @@ static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) static int wm8350_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1328,6 +1320,95 @@ static int wm8350_resume(struct platform_device *pdev) return 0; } +static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) +{ + struct wm8350_data *priv = data; + u16 reg; + int report; + int mask; + struct wm8350_jack_data *jack = NULL; + + switch (irq) { + case WM8350_IRQ_CODEC_JCK_DET_L: + jack = &priv->hpl; + mask = WM8350_JACK_L_LVL; + break; + + case WM8350_IRQ_CODEC_JCK_DET_R: + jack = &priv->hpr; + mask = WM8350_JACK_R_LVL; + break; + + default: + BUG(); + } + + if (!jack->jack) { + dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); + return; + } + + /* Debounce */ + msleep(200); + + reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); + if (reg & mask) + report = jack->report; + else + report = 0; + + snd_soc_jack_report(jack->jack, report, jack->report); +} + +/** + * wm8350_hp_jack_detect - Enable headphone jack detection. + * + * @codec: WM8350 codec + * @which: left or right jack detect signal + * @jack: jack to report detection events on + * @report: value to report + * + * Enables the headphone jack detection of the WM8350. + */ +int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, + struct snd_soc_jack *jack, int report) +{ + struct wm8350_data *priv = codec->private_data; + struct wm8350 *wm8350 = codec->control_data; + int irq; + int ena; + + switch (which) { + case WM8350_JDL: + priv->hpl.jack = jack; + priv->hpl.report = report; + irq = WM8350_IRQ_CODEC_JCK_DET_L; + ena = WM8350_JDL_ENA; + break; + + case WM8350_JDR: + priv->hpr.jack = jack; + priv->hpr.report = report; + irq = WM8350_IRQ_CODEC_JCK_DET_R; + ena = WM8350_JDR_ENA; + break; + + default: + return -EINVAL; + } + + wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); + wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); + + /* Sync status */ + wm8350_hp_jack_handler(wm8350, irq, priv); + + wm8350_unmask_irq(wm8350, irq); + + return 0; +} +EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); + static struct snd_soc_codec *wm8350_codec; static int wm8350_probe(struct platform_device *pdev) @@ -1342,8 +1423,8 @@ static int wm8350_probe(struct platform_device *pdev) BUG_ON(!wm8350_codec); - socdev->codec = wm8350_codec; - codec = socdev->codec; + socdev->card->codec = wm8350_codec; + codec = socdev->card->codec; wm8350 = codec->control_data; priv = codec->private_data; @@ -1381,13 +1462,21 @@ static int wm8350_probe(struct platform_device *pdev) wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, WM8350_OUT2_VU | WM8350_OUT2R_MUTE); + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, + wm8350_hp_jack_handler, priv); + wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, + wm8350_hp_jack_handler, priv); + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { dev_err(&pdev->dev, "failed to create pcms\n"); return ret; } - wm8350_add_controls(codec); + snd_soc_add_controls(codec, wm8350_snd_controls, + ARRAY_SIZE(wm8350_snd_controls)); wm8350_add_widgets(codec); wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1409,10 +1498,23 @@ card_err: static int wm8350_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8350 *wm8350 = codec->control_data; + struct wm8350_data *priv = codec->private_data; int ret; + wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, + WM8350_JDL_ENA | WM8350_JDR_ENA); + wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); + + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); + wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + + priv->hpl.jack = NULL; + priv->hpr.jack = NULL; + /* cancel any work waiting to be queued. */ ret = cancel_delayed_work(&codec->delayed_work); diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index cc2887a..d11bd92 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h @@ -17,4 +17,12 @@ extern struct snd_soc_dai wm8350_dai; extern struct snd_soc_codec_device soc_codec_dev_wm8350; +enum wm8350_jack { + WM8350_JDL = 1, + WM8350_JDR = 2, +}; + +int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, + struct snd_soc_jack *jack, int report); + #endif diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 40f8238..f01078c 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -171,22 +171,6 @@ SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST, 8, 1, 0), SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), }; -/* add non dapm controls */ -static int wm8510_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8510_snd_controls[i], codec, - NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Speaker Output Mixer */ static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0), @@ -468,7 +452,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; @@ -597,7 +581,7 @@ EXPORT_SYMBOL_GPL(wm8510_dai); static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -606,7 +590,7 @@ static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) static int wm8510_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -628,7 +612,7 @@ static int wm8510_resume(struct platform_device *pdev) */ static int wm8510_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8510"; @@ -656,7 +640,8 @@ static int wm8510_init(struct snd_soc_device *socdev) /* power on device */ codec->bias_level = SND_SOC_BIAS_OFF; wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8510_add_controls(codec); + snd_soc_add_controls(codec, wm8510_snd_controls, + ARRAY_SIZE(wm8510_snd_controls)); wm8510_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -685,7 +670,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8510_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -766,7 +751,7 @@ err_driver: static int __devinit wm8510_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8510_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -832,7 +817,7 @@ static int wm8510_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -862,7 +847,7 @@ static int wm8510_probe(struct platform_device *pdev) static int wm8510_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index d004e58..d3c51ba 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -200,7 +200,7 @@ static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); + BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); return cache[reg]; } @@ -223,7 +223,7 @@ static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg, { u8 data[2]; - BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); + BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); /* Registers are 9 bits wide */ value &= 0x1ff; @@ -330,20 +330,6 @@ SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), }; -/* Add non-DAPM controls */ -static int wm8580_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8580_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8580_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), @@ -553,7 +539,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); paifb &= ~WM8580_AIF_LENGTH_MASK; @@ -830,7 +816,7 @@ EXPORT_SYMBOL_GPL(wm8580_dai); */ static int wm8580_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8580"; @@ -866,7 +852,8 @@ static int wm8580_init(struct snd_soc_device *socdev) goto pcm_err; } - wm8580_add_controls(codec); + snd_soc_add_controls(codec, wm8580_snd_controls, + ARRAY_SIZE(wm8580_snd_controls)); wm8580_add_widgets(codec); ret = snd_soc_init_card(socdev); @@ -901,7 +888,7 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8580_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -999,7 +986,7 @@ static int wm8580_probe(struct platform_device *pdev) } codec->private_data = wm8580; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1020,7 +1007,7 @@ static int wm8580_probe(struct platform_device *pdev) static int wm8580_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 80b1198..f8363b3 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -47,7 +47,7 @@ static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); + BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); return cache[reg]; } @@ -55,7 +55,7 @@ static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec, u16 reg, unsigned int value) { u16 *cache = codec->reg_cache; - BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); + BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); cache[reg] = value; } @@ -92,21 +92,6 @@ SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL, SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), }; -static int wm8728_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8728_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* * DAPM controls. */ @@ -152,7 +137,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); dac &= ~0x18; @@ -279,7 +264,7 @@ EXPORT_SYMBOL_GPL(wm8728_dai); static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -289,7 +274,7 @@ static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) static int wm8728_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8728_set_bias_level(codec, codec->suspend_bias_level); @@ -302,7 +287,7 @@ static int wm8728_resume(struct platform_device *pdev) */ static int wm8728_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8728"; @@ -330,7 +315,8 @@ static int wm8728_init(struct snd_soc_device *socdev) /* power on device */ wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8728_add_controls(codec); + snd_soc_add_controls(codec, wm8728_snd_controls, + ARRAY_SIZE(wm8728_snd_controls)); wm8728_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -363,7 +349,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -444,7 +430,7 @@ err_driver: static int __devinit wm8728_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -508,7 +494,7 @@ static int wm8728_probe(struct platform_device *pdev) if (codec == NULL) return -ENOMEM; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -541,7 +527,7 @@ static int wm8728_probe(struct platform_device *pdev) static int wm8728_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index c444b9f..0150fe5 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -129,22 +129,6 @@ SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), }; -/* add non dapm controls */ -static int wm8731_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8731_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - /* Output Mixer */ static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), @@ -269,7 +253,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8731_priv *wm8731 = codec->private_data; u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; int i = get_coeff(wm8731->sysclk, params_rate(params)); @@ -299,7 +283,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* set active */ wm8731_write(codec, WM8731_ACTIVE, 0x0001); @@ -312,7 +296,7 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* deactivate */ if (!codec->active) { @@ -474,7 +458,7 @@ EXPORT_SYMBOL_GPL(wm8731_dai); static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8731_write(codec, WM8731_ACTIVE, 0x0); wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -484,7 +468,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) static int wm8731_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -506,7 +490,7 @@ static int wm8731_resume(struct platform_device *pdev) */ static int wm8731_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8731"; @@ -543,7 +527,8 @@ static int wm8731_init(struct snd_soc_device *socdev) reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); - wm8731_add_controls(codec); + snd_soc_add_controls(codec, wm8731_snd_controls, + ARRAY_SIZE(wm8731_snd_controls)); wm8731_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -576,7 +561,7 @@ static int wm8731_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8731_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -657,7 +642,7 @@ err_driver: static int __devinit wm8731_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8731_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -731,7 +716,7 @@ static int wm8731_probe(struct platform_device *pdev) } codec->private_data = wm8731; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -765,7 +750,7 @@ static int wm8731_probe(struct platform_device *pdev) static int wm8731_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 5997fa6..96afb86 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -231,21 +231,6 @@ SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0), }; -/* add non dapm controls */ -static int wm8750_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8750_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * DAPM Controls */ @@ -619,7 +604,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8750_priv *wm8750 = codec->private_data; u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; @@ -727,7 +712,7 @@ static void wm8750_work(struct work_struct *work) static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -736,7 +721,7 @@ static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) static int wm8750_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -769,7 +754,7 @@ static int wm8750_resume(struct platform_device *pdev) */ static int wm8750_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8750"; @@ -816,7 +801,8 @@ static int wm8750_init(struct snd_soc_device *socdev) reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); - wm8750_add_controls(codec); + snd_soc_add_controls(codec, wm8750_snd_controls, + ARRAY_SIZE(wm8750_snd_controls)); wm8750_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -850,7 +836,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8750_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -931,7 +917,7 @@ err_driver: static int __devinit wm8750_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8750_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -1003,7 +989,7 @@ static int wm8750_probe(struct platform_device *pdev) } codec->private_data = wm8750; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1057,7 +1043,7 @@ static int run_delayed_work(struct delayed_work *dwork) static int wm8750_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 77620ab..6f9e6be 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -97,7 +97,7 @@ static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1)) + if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) return -1; return cache[reg - 1]; } @@ -109,7 +109,7 @@ static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { u16 *cache = codec->reg_cache; - if (reg < 1 || reg > 0x3f) + if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) return; cache[reg - 1] = value; } @@ -339,21 +339,6 @@ SOC_ENUM("ADC Data Select", wm8753_enum[27]), SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), }; -/* add non dapm controls */ -static int wm8753_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8753_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * _DAPM_ Controls */ @@ -927,7 +912,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8753_priv *wm8753 = codec->private_data; u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; @@ -1161,7 +1146,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8753_priv *wm8753 = codec->private_data; u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; @@ -1505,7 +1490,7 @@ static void wm8753_work(struct work_struct *work) static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* we only need to suspend if we are a valid card */ if (!codec->card) @@ -1518,7 +1503,7 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) static int wm8753_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -1555,7 +1540,7 @@ static int wm8753_resume(struct platform_device *pdev) */ static int wm8753_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8753"; @@ -1610,7 +1595,8 @@ static int wm8753_init(struct snd_soc_device *socdev) reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); - wm8753_add_controls(codec); + snd_soc_add_controls(codec, wm8753_snd_controls, + ARRAY_SIZE(wm8753_snd_controls)); wm8753_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -1645,7 +1631,7 @@ static int wm8753_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8753_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -1726,7 +1712,7 @@ err_driver: static int __devinit wm8753_spi_probe(struct spi_device *spi) { struct snd_soc_device *socdev = wm8753_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; codec->control_data = spi; @@ -1801,7 +1787,7 @@ static int wm8753_probe(struct platform_device *pdev) } codec->private_data = wm8753; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1853,7 +1839,7 @@ static int run_delayed_work(struct delayed_work *dwork) static int wm8753_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 6767de1..85c0f1b 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -517,22 +517,6 @@ SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1, }; -/* add non dapm controls */ -static int wm8900_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8900_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8900_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); @@ -736,7 +720,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 reg; reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; @@ -1226,7 +1210,7 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8900_priv *wm8900 = codec->private_data; int fll_out = wm8900->fll_out; int fll_in = wm8900->fll_in; @@ -1250,7 +1234,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) static int wm8900_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8900_priv *wm8900 = codec->private_data; u16 *cache; int i, ret; @@ -1430,7 +1414,7 @@ static int wm8900_probe(struct platform_device *pdev) } codec = wm8900_codec; - socdev->codec = codec; + socdev->card->codec = codec; /* Register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); @@ -1439,7 +1423,8 @@ static int wm8900_probe(struct platform_device *pdev) goto pcm_err; } - wm8900_add_controls(codec); + snd_soc_add_controls(codec, wm8900_snd_controls, + ARRAY_SIZE(wm8900_snd_controls)); wm8900_add_widgets(codec); ret = snd_soc_init_card(socdev); diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index bde7454..d36b2b1 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -744,21 +744,6 @@ SOC_DOUBLE_R_TLV("Speaker Volume", 0, 63, 0, out_tlv), }; -static int wm8903_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8903_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8903_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static const struct snd_kcontrol_new linput_mode_mux = SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum); @@ -1276,7 +1261,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8903_priv *wm8903 = codec->private_data; struct i2c_client *i2c = codec->control_data; struct snd_pcm_runtime *master_runtime; @@ -1318,7 +1303,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8903_priv *wm8903 = codec->private_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -1338,7 +1323,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8903_priv *wm8903 = codec->private_data; struct i2c_client *i2c = codec->control_data; int fs = params_rate(params); @@ -1542,7 +1527,7 @@ EXPORT_SYMBOL_GPL(wm8903_dai); static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -1552,7 +1537,7 @@ static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) static int wm8903_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct i2c_client *i2c = codec->control_data; int i; u16 *reg_cache = codec->reg_cache; @@ -1728,7 +1713,7 @@ static int wm8903_probe(struct platform_device *pdev) goto err; } - socdev->codec = wm8903_codec; + socdev->card->codec = wm8903_codec; /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); @@ -1737,8 +1722,9 @@ static int wm8903_probe(struct platform_device *pdev) goto err; } - wm8903_add_controls(socdev->codec); - wm8903_add_widgets(socdev->codec); + snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls, + ARRAY_SIZE(wm8903_snd_controls)); + wm8903_add_widgets(socdev->card->codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -1759,7 +1745,7 @@ err: static int wm8903_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 88ead7f..24d4c90 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -195,21 +195,6 @@ static const struct snd_kcontrol_new wm8971_snd_controls[] = { SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0), }; -/* add non-DAPM controls */ -static int wm8971_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8971_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * DAPM Controls */ @@ -546,7 +531,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm8971_priv *wm8971 = codec->private_data; u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; @@ -652,7 +637,7 @@ static void wm8971_work(struct work_struct *work) static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -661,7 +646,7 @@ static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) static int wm8971_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -692,7 +677,7 @@ static int wm8971_resume(struct platform_device *pdev) static int wm8971_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8971"; @@ -745,7 +730,8 @@ static int wm8971_init(struct snd_soc_device *socdev) reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); - wm8971_add_controls(codec); + snd_soc_add_controls(codec, wm8971_snd_controls, + ARRAY_SIZE(wm8971_snd_controls)); wm8971_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -772,7 +758,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8971_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -873,7 +859,7 @@ static int wm8971_probe(struct platform_device *pdev) } codec->private_data = wm8971; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -908,7 +894,7 @@ static int wm8971_probe(struct platform_device *pdev) static int wm8971_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 5b5afc1..6af1d39 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -116,7 +116,7 @@ static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec, unsigned int reg) { u16 *cache = codec->reg_cache; - BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1); + BUG_ON(reg >= ARRAY_SIZE(wm8990_reg)); return cache[reg]; } @@ -129,7 +129,7 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec, u16 *cache = codec->reg_cache; /* Reset register and reserved registers are uncached */ - if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1) + if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg)) return; cache[reg] = value; @@ -417,21 +417,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, }; -/* add non dapm controls */ -static int wm8990_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8990_snd_controls[i], codec, - NULL)); - if (err < 0) - return err; - } - return 0; -} - /* * _DAPM_ Controls */ @@ -1177,7 +1162,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); audio1 &= ~WM8990_AIF_WL_MASK; @@ -1376,7 +1361,7 @@ EXPORT_SYMBOL_GPL(wm8990_dai); static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; /* we only need to suspend if we are a valid card */ if (!codec->card) @@ -1389,7 +1374,7 @@ static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) static int wm8990_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i; u8 data[2]; u16 *cache = codec->reg_cache; @@ -1417,7 +1402,7 @@ static int wm8990_resume(struct platform_device *pdev) */ static int wm8990_init(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 reg; int ret = 0; @@ -1460,7 +1445,8 @@ static int wm8990_init(struct snd_soc_device *socdev) wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); - wm8990_add_controls(codec); + snd_soc_add_controls(codec, wm8990_snd_controls, + ARRAY_SIZE(wm8990_snd_controls)); wm8990_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -1494,7 +1480,7 @@ static int wm8990_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = wm8990_socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int ret; i2c_set_clientdata(i2c, codec); @@ -1593,7 +1579,7 @@ static int wm8990_probe(struct platform_device *pdev) } codec->private_data = wm8990; - socdev->codec = codec; + socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); @@ -1619,7 +1605,7 @@ static int wm8990_probe(struct platform_device *pdev) static int wm8990_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec->control_data) wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c new file mode 100644 index 0000000..2e9e06b --- /dev/null +++ b/sound/soc/codecs/wm9705.c @@ -0,0 +1,413 @@ +/* + * wm9705.c -- ALSA Soc WM9705 codec support + * + * Copyright 2008 Ian Molton <spyro@f2s.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; Version 2 of the License only. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/ac97_codec.h> +#include <sound/initval.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include "wm9705.h" + +/* + * WM9705 register cache + */ +static const u16 wm9705_reg[] = { + 0x6150, 0x8000, 0x8000, 0x8000, /* 0x0 */ + 0x0000, 0x8000, 0x8008, 0x8008, /* 0x8 */ + 0x8808, 0x8808, 0x8808, 0x8808, /* 0x10 */ + 0x8808, 0x0000, 0x8000, 0x0000, /* 0x18 */ + 0x0000, 0x0000, 0x0000, 0x000f, /* 0x20 */ + 0x0605, 0x0000, 0xbb80, 0x0000, /* 0x28 */ + 0x0000, 0xbb80, 0x0000, 0x0000, /* 0x30 */ + 0x0000, 0x2000, 0x0000, 0x0000, /* 0x38 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x40 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x48 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x50 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x58 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x60 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 0x68 */ + 0x0000, 0x0808, 0x0000, 0x0006, /* 0x70 */ + 0x0000, 0x0000, 0x574d, 0x4c05, /* 0x78 */ +}; + +static const struct snd_kcontrol_new wm9705_snd_ac97_controls[] = { + SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), + SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1), + SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), + SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1), + SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1), + SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1), + SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1), + SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), + SOC_SINGLE("PCBeep Playback Volume", AC97_PC_BEEP, 1, 15, 1), + SOC_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 31, 1), + SOC_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1), + SOC_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1), + SOC_SINGLE("Mic Playback Volume", AC97_MIC, 0, 31, 1), + SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 6, 1, 0), + SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0), + SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), +}; + +static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; +static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", + "Line", "Stereo Mix", "Mono Mix", "Phone"}; + +static const struct soc_enum wm9705_enum_mic = + SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); +static const struct soc_enum wm9705_enum_rec_l = + SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); +static const struct soc_enum wm9705_enum_rec_r = + SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); + +/* Headphone Mixer */ +static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { + SOC_DAPM_SINGLE("PCBeep Playback Switch", AC97_PC_BEEP, 15, 1, 1), + SOC_DAPM_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1), + SOC_DAPM_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1), + SOC_DAPM_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1), + SOC_DAPM_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1), +}; + +/* Mic source */ +static const struct snd_kcontrol_new wm9705_mic_src_controls = + SOC_DAPM_ENUM("Route", wm9705_enum_mic); + +/* Capture source */ +static const struct snd_kcontrol_new wm9705_capture_selectl_controls = + SOC_DAPM_ENUM("Route", wm9705_enum_rec_l); +static const struct snd_kcontrol_new wm9705_capture_selectr_controls = + SOC_DAPM_ENUM("Route", wm9705_enum_rec_r); + +/* DAPM widgets */ +static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = { + SND_SOC_DAPM_MUX("Mic Source", SND_SOC_NOPM, 0, 0, + &wm9705_mic_src_controls), + SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0, + &wm9705_capture_selectl_controls), + SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0, + &wm9705_capture_selectr_controls), + SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_MIXER_NAMED_CTL("HP Mixer", SND_SOC_NOPM, 0, 0, + &wm9705_hp_mixer_controls[0], + ARRAY_SIZE(wm9705_hp_mixer_controls)), + SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Speaker PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Line PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Line out PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Mono PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Phone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Mic PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("PCBEEP PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("CD PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), + SND_SOC_DAPM_OUTPUT("LOUT"), + SND_SOC_DAPM_OUTPUT("ROUT"), + SND_SOC_DAPM_OUTPUT("MONOOUT"), + SND_SOC_DAPM_INPUT("PHONE"), + SND_SOC_DAPM_INPUT("LINEINL"), + SND_SOC_DAPM_INPUT("LINEINR"), + SND_SOC_DAPM_INPUT("CDINL"), + SND_SOC_DAPM_INPUT("CDINR"), + SND_SOC_DAPM_INPUT("PCBEEP"), + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("MIC2"), +}; + +/* Audio map + * WM9705 has no switches to disable the route from the inputs to the HP mixer + * so in order to prevent active inputs from forcing the audio outputs to be + * constantly enabled, we use the mutes on those inputs to simulate such + * controls. + */ +static const struct snd_soc_dapm_route audio_map[] = { + /* HP mixer */ + {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"}, + {"HP Mixer", "CD Playback Switch", "CD PGA"}, + {"HP Mixer", "Mic Playback Switch", "Mic PGA"}, + {"HP Mixer", "Phone Playback Switch", "Phone PGA"}, + {"HP Mixer", "Line Playback Switch", "Line PGA"}, + {"HP Mixer", NULL, "Left DAC"}, + {"HP Mixer", NULL, "Right DAC"}, + + /* mono mixer */ + {"Mono Mixer", NULL, "HP Mixer"}, + + /* outputs */ + {"Headphone PGA", NULL, "HP Mixer"}, + {"HPOUTL", NULL, "Headphone PGA"}, + {"HPOUTR", NULL, "Headphone PGA"}, + {"Line out PGA", NULL, "HP Mixer"}, + {"LOUT", NULL, "Line out PGA"}, + {"ROUT", NULL, "Line out PGA"}, + {"Mono PGA", NULL, "Mono Mixer"}, + {"MONOOUT", NULL, "Mono PGA"}, + + /* inputs */ + {"CD PGA", NULL, "CDINL"}, + {"CD PGA", NULL, "CDINR"}, + {"Line PGA", NULL, "LINEINL"}, + {"Line PGA", NULL, "LINEINR"}, + {"Phone PGA", NULL, "PHONE"}, + {"Mic Source", "Mic 1", "MIC1"}, + {"Mic Source", "Mic 2", "MIC2"}, + {"Mic PGA", NULL, "Mic Source"}, + {"PCBEEP PGA", NULL, "PCBEEP"}, + + /* Left capture selector */ + {"Left Capture Source", "Mic", "Mic Source"}, + {"Left Capture Source", "CD", "CDINL"}, + {"Left Capture Source", "Line", "LINEINL"}, + {"Left Capture Source", "Stereo Mix", "HP Mixer"}, + {"Left Capture Source", "Mono Mix", "HP Mixer"}, + {"Left Capture Source", "Phone", "PHONE"}, + + /* Right capture source */ + {"Right Capture Source", "Mic", "Mic Source"}, + {"Right Capture Source", "CD", "CDINR"}, + {"Right Capture Source", "Line", "LINEINR"}, + {"Right Capture Source", "Stereo Mix", "HP Mixer"}, + {"Right Capture Source", "Mono Mix", "HP Mixer"}, + {"Right Capture Source", "Phone", "PHONE"}, + + {"ADC PGA", NULL, "Left Capture Source"}, + {"ADC PGA", NULL, "Right Capture Source"}, + + /* ADC's */ + {"Left ADC", NULL, "ADC PGA"}, + {"Right ADC", NULL, "ADC PGA"}, +}; + +static int wm9705_add_widgets(struct snd_soc_codec *codec) +{ + snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, + ARRAY_SIZE(wm9705_dapm_widgets)); + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_new_widgets(codec); + + return 0; +} + +/* We use a register cache to enhance read performance. */ +static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + switch (reg) { + case AC97_RESET: + case AC97_VENDOR_ID1: + case AC97_VENDOR_ID2: + return soc_ac97_ops.read(codec->ac97, reg); + default: + reg = reg >> 1; + + if (reg >= (ARRAY_SIZE(wm9705_reg))) + return -EIO; + + return cache[reg]; + } +} + +static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int val) +{ + u16 *cache = codec->reg_cache; + + soc_ac97_ops.write(codec->ac97, reg, val); + reg = reg >> 1; + if (reg < (ARRAY_SIZE(wm9705_reg))) + cache[reg] = val; + + return 0; +} + +static int ac97_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->card->codec; + int reg; + u16 vra; + + vra = ac97_read(codec, AC97_EXTENDED_STATUS); + ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = AC97_PCM_FRONT_DAC_RATE; + else + reg = AC97_PCM_LR_ADC_RATE; + + return ac97_write(codec, reg, runtime->rate); +} + +#define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +struct snd_soc_dai wm9705_dai[] = { + { + .name = "AC97 HiFi", + .ac97_control = 1, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = WM9705_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = WM9705_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = { + .prepare = ac97_prepare, + }, + }, + { + .name = "AC97 Aux", + .playback = { + .stream_name = "Aux Playback", + .channels_min = 1, + .channels_max = 1, + .rates = WM9705_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + } +}; +EXPORT_SYMBOL_GPL(wm9705_dai); + +static int wm9705_reset(struct snd_soc_codec *codec) +{ + if (soc_ac97_ops.reset) { + soc_ac97_ops.reset(codec->ac97); + if (ac97_read(codec, 0) == wm9705_reg[0]) + return 0; /* Success */ + } + + return -EIO; +} + +static int wm9705_soc_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret = 0; + + printk(KERN_INFO "WM9705 SoC Audio Codec\n"); + + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), + GFP_KERNEL); + if (socdev->card->codec == NULL) + return -ENOMEM; + codec = socdev->card->codec; + mutex_init(&codec->mutex); + + codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); + if (codec->reg_cache == NULL) { + ret = -ENOMEM; + goto cache_err; + } + codec->reg_cache_size = sizeof(wm9705_reg); + codec->reg_cache_step = 2; + + codec->name = "WM9705"; + codec->owner = THIS_MODULE; + codec->dai = wm9705_dai; + codec->num_dai = ARRAY_SIZE(wm9705_dai); + codec->write = ac97_write; + codec->read = ac97_read; + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); + if (ret < 0) { + printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); + goto codec_err; + } + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) + goto pcm_err; + + ret = wm9705_reset(codec); + if (ret) + goto reset_err; + + snd_soc_add_controls(codec, wm9705_snd_ac97_controls, + ARRAY_SIZE(wm9705_snd_ac97_controls)); + wm9705_add_widgets(codec); + + ret = snd_soc_init_card(socdev); + if (ret < 0) { + printk(KERN_ERR "wm9705: failed to register card\n"); + goto pcm_err; + } + + return 0; + +reset_err: + snd_soc_free_pcms(socdev); +pcm_err: + snd_soc_free_ac97_codec(codec); +codec_err: + kfree(codec->reg_cache); +cache_err: + kfree(socdev->card->codec); + socdev->card->codec = NULL; + return ret; +} + +static int wm9705_soc_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + + if (codec == NULL) + return 0; + + snd_soc_dapm_free(socdev); + snd_soc_free_pcms(socdev); + snd_soc_free_ac97_codec(codec); + kfree(codec->reg_cache); + kfree(codec); + return 0; +} + +struct snd_soc_codec_device soc_codec_dev_wm9705 = { + .probe = wm9705_soc_probe, + .remove = wm9705_soc_remove, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); + +MODULE_DESCRIPTION("ASoC WM9705 driver"); +MODULE_AUTHOR("Ian Molton"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h new file mode 100644 index 0000000..d380f11 --- /dev/null +++ b/sound/soc/codecs/wm9705.h @@ -0,0 +1,14 @@ +/* + * wm9705.h -- WM9705 Soc Audio driver + */ + +#ifndef _WM9705_H +#define _WM9705_H + +#define WM9705_DAI_AC97_HIFI 0 +#define WM9705_DAI_AC97_AUX 1 + +extern struct snd_soc_dai wm9705_dai[2]; +extern struct snd_soc_codec_device soc_codec_dev_wm9705; + +#endif diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index af83d62..b3a8be7 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -154,21 +154,6 @@ SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), }; -/* add non dapm controls */ -static int wm9712_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm9712_snd_ac97_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* We have to create a fake left and right HP mixers because * the codec only has a single control that is shared by both channels. * This makes it impossible to determine the audio path. @@ -467,7 +452,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, else { reg = reg >> 1; - if (reg > (ARRAY_SIZE(wm9712_reg))) + if (reg >= (ARRAY_SIZE(wm9712_reg))) return -EIO; return cache[reg]; @@ -481,7 +466,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; - if (reg <= (ARRAY_SIZE(wm9712_reg))) + if (reg < (ARRAY_SIZE(wm9712_reg))) cache[reg] = val; return 0; @@ -493,7 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int reg; u16 vra; @@ -514,7 +499,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 vra, xsle; vra = ac97_read(codec, AC97_EXTENDED_STATUS); @@ -607,7 +592,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -616,7 +601,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev, static int wm9712_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; int i, ret; u16 *cache = codec->reg_cache; @@ -652,10 +637,11 @@ static int wm9712_soc_probe(struct platform_device *pdev) printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), + GFP_KERNEL); + if (socdev->card->codec == NULL) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); @@ -698,7 +684,8 @@ static int wm9712_soc_probe(struct platform_device *pdev) ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm9712_add_controls(codec); + snd_soc_add_controls(codec, wm9712_snd_ac97_controls, + ARRAY_SIZE(wm9712_snd_ac97_controls)); wm9712_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { @@ -718,15 +705,15 @@ codec_err: kfree(codec->reg_cache); cache_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int wm9712_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index f3ca8aa..54db9c5 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -32,7 +32,6 @@ struct wm9713_priv { u32 pll_in; /* PLL input frequency */ - u32 pll_out; /* PLL output frequency */ }; static unsigned int ac97_read(struct snd_soc_codec *codec, @@ -190,21 +189,6 @@ SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0), SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), }; -/* add non dapm controls */ -static int wm9713_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm9713_snd_ac97_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - return 0; -} - /* We have to create a fake left and right HP mixers because * the codec only has a single control that is shared by both channels. * This makes it impossible to determine the audio path using the current @@ -636,7 +620,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, else { reg = reg >> 1; - if (reg > (ARRAY_SIZE(wm9713_reg))) + if (reg >= (ARRAY_SIZE(wm9713_reg))) return -EIO; return cache[reg]; @@ -650,7 +634,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, if (reg < 0x7c) soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; - if (reg <= (ARRAY_SIZE(wm9713_reg))) + if (reg < (ARRAY_SIZE(wm9713_reg))) cache[reg] = val; return 0; @@ -738,13 +722,13 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, struct _pll_div pll_div; /* turn PLL off ? */ - if (freq_in == 0 || freq_out == 0) { + if (freq_in == 0) { /* disable PLL power and select ext source */ reg = ac97_read(codec, AC97_HANDSET_RATE); ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080); reg = ac97_read(codec, AC97_EXTENDED_MID); ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200); - wm9713->pll_out = 0; + wm9713->pll_in = 0; return 0; } @@ -788,7 +772,6 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff); reg = ac97_read(codec, AC97_HANDSET_RATE); ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f); - wm9713->pll_out = freq_out; wm9713->pll_in = freq_in; /* wait 10ms AC97 link frames for the link to stabilise */ @@ -1132,7 +1115,7 @@ static int wm9713_soc_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; u16 reg; /* Disable everything except touchpanel - that will be handled @@ -1150,7 +1133,7 @@ static int wm9713_soc_suspend(struct platform_device *pdev, static int wm9713_soc_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; struct wm9713_priv *wm9713 = codec->private_data; int i, ret; u16 *cache = codec->reg_cache; @@ -1164,8 +1147,8 @@ static int wm9713_soc_resume(struct platform_device *pdev) wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* do we need to re-start the PLL ? */ - if (wm9713->pll_out) - wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out); + if (wm9713->pll_in) + wm9713_set_pll(codec, 0, wm9713->pll_in, 0); /* only synchronise the codec if warm reset failed */ if (ret == 0) { @@ -1191,10 +1174,11 @@ static int wm9713_soc_probe(struct platform_device *pdev) printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION); - socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (socdev->codec == NULL) + socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), + GFP_KERNEL); + if (socdev->card->codec == NULL) return -ENOMEM; - codec = socdev->codec; + codec = socdev->card->codec; mutex_init(&codec->mutex); codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); @@ -1245,7 +1229,8 @@ static int wm9713_soc_probe(struct platform_device *pdev) reg = ac97_read(codec, AC97_CD) & 0x7fff; ac97_write(codec, AC97_CD, reg); - wm9713_add_controls(codec); + snd_soc_add_controls(codec, wm9713_snd_ac97_controls, + ARRAY_SIZE(wm9713_snd_ac97_controls)); wm9713_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) @@ -1265,15 +1250,15 @@ priv_err: kfree(codec->reg_cache); cache_err: - kfree(socdev->codec); - socdev->codec = NULL; + kfree(socdev->card->codec); + socdev->card->codec = NULL; return ret; } static int wm9713_soc_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; if (codec == NULL) return 0; diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 366049d..7af3b5b 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -286,7 +286,7 @@ static int davinci_pcm_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); } -struct snd_pcm_ops davinci_pcm_ops = { +static struct snd_pcm_ops davinci_pcm_ops = { .open = davinci_pcm_open, .close = davinci_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 4935d1b..50baef1 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -25,7 +25,9 @@ #include <asm/dma.h> #include <asm/mach-types.h> +#ifdef CONFIG_SFFSDR_FPGA #include <asm/plat-sffsdr/sffsdr-fpga.h> +#endif #include <mach/mcbsp.h> #include <mach/edma.h> @@ -43,6 +45,17 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, int fs; int ret = 0; + /* Fsref can be 32000, 44100 or 48000. */ + fs = params_rate(params); + +#ifndef CONFIG_SFFSDR_FPGA + /* Without the FPGA module, the Fs is fixed at 44100 Hz */ + if (fs != 44100) { + pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n"); + return -EINVAL; + } +#endif + /* Set cpu DAI configuration: * CLKX and CLKR are the inputs for the Sample Rate Generator. * FSX and FSR are outputs, driven by the sample Rate Generator. */ @@ -53,12 +66,13 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* Fsref can be 32000, 44100 or 48000. */ - fs = params_rate(params); - pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); +#ifndef CONFIG_SFFSDR_FPGA + return 0; +#else return sffsdr_fpga_set_codec_fs(fs); +#endif } static struct snd_soc_ops sffsdr_ops = { diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 95c12b2..9fc9082 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,17 +1,18 @@ config SND_SOC_OF_SIMPLE tristate +# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers +# for the SSI and the Elo DMA controller. You will still need to select +# a platform driver and a codec driver. config SND_SOC_MPC8610 - bool "ALSA SoC support for the MPC8610 SOC" - depends on MPC8610_HPCD - default y if MPC8610 - help - Say Y if you want to add support for codecs attached to the SSI - device on an MPC8610. + tristate + depends on MPC8610 config SND_SOC_MPC8610_HPCD - bool "ALSA SoC support for the Freescale MPC8610 HPCD board" - depends on SND_SOC_MPC8610 + tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" + # I2C is necessary for the CS4270 driver + depends on MPC8610_HPCD && I2C + select SND_SOC_MPC8610 select SND_SOC_CS4270 select SND_SOC_CS4270_VD33_ERRATA default y if MPC8610_HPCD diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 035da4a..f85134c 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -2,10 +2,13 @@ obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o # MPC8610 HPCD Machine Support -obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o +snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o +obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o # MPC8610 Platform Support -obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o +snd-soc-fsl-ssi-objs := fsl_ssi.o +snd-soc-fsl-dma-objs := fsl_dma.o +obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 4f7f040..675732e 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -8,7 +8,7 @@ config SND_OMAP_SOC_MCBSP config SND_OMAP_SOC_N810 tristate "SoC Audio support for Nokia N810" - depends on SND_OMAP_SOC && MACH_NOKIA_N810 + depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C select SND_OMAP_SOC_MCBSP select OMAP_MUX select SND_SOC_TLV320AIC3X @@ -17,7 +17,7 @@ config SND_OMAP_SOC_N810 config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" - depends on SND_OMAP_SOC && MACH_OMAP_OSK + depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C select SND_OMAP_SOC_MCBSP select SND_SOC_TLV320AIC23 help @@ -55,3 +55,13 @@ config SND_OMAP_SOC_OMAP3_PANDORA select SND_SOC_TWL4030 help Say Y if you want to add support for SoC audio on the OMAP3 Pandora. + +config SND_OMAP_SOC_OMAP3_BEAGLE + tristate "SoC Audio support for OMAP3 Beagle" + depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE + select SND_OMAP_SOC_MCBSP + select SND_SOC_TWL4030 + help + Say Y if you want to add support for SoC audio on the Beagleboard. + + diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 76fedd9..0c9e4ac 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -12,6 +12,7 @@ snd-soc-overo-objs := overo.o snd-soc-omap2evm-objs := omap2evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap3pandora-objs := omap3pandora.o +snd-soc-omap3beagle-objs := omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o @@ -19,3 +20,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index b0362df..607a38c 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -264,7 +264,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); } -struct snd_pcm_ops omap_pcm_ops = { +static struct snd_pcm_ops omap_pcm_ops = { .open = omap_pcm_open, .close = omap_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index f82e106..958ac3f 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -61,6 +61,24 @@ config SND_PXA2XX_SOC_TOSA Say Y if you want to add support for SoC audio on Sharp Zaurus SL-C6000x models (Tosa). +config SND_PXA2XX_SOC_E740 + tristate "SoC AC97 Audio support for e740" + depends on SND_PXA2XX_SOC && MACH_E740 + select SND_SOC_WM9705 + select SND_PXA2XX_SOC_AC97 + help + Say Y if you want to add support for SoC audio on the + toshiba e740 PDA + +config SND_PXA2XX_SOC_E750 + tristate "SoC AC97 Audio support for e750" + depends on SND_PXA2XX_SOC && MACH_E750 + select SND_SOC_WM9705 + select SND_PXA2XX_SOC_AC97 + help + Say Y if you want to add support for SoC audio on the + toshiba e750 PDA + config SND_PXA2XX_SOC_E800 tristate "SoC AC97 Audio support for e800" depends on SND_PXA2XX_SOC && MACH_E800 diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 08a9f27..97a51a8 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -13,6 +13,8 @@ obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o snd-soc-corgi-objs := corgi.o snd-soc-poodle-objs := poodle.o snd-soc-tosa-objs := tosa.o +snd-soc-e740-objs := e740_wm9705.o +snd-soc-e750-objs := e750_wm9705.o snd-soc-e800-objs := e800_wm9712.o snd-soc-spitz-objs := spitz.o snd-soc-em-x270-objs := em-x270.o @@ -22,6 +24,8 @@ snd-soc-zylonite-objs := zylonite.o obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o +obj-$(CONFIG_SND_PXA2XX_SOC_E740) += snd-soc-e740.o +obj-$(CONFIG_SND_PXA2XX_SOC_E750) += snd-soc-e750.o obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c new file mode 100644 index 0000000..7cd2f89 --- /dev/null +++ b/sound/soc/pxa/e740_wm9705.c @@ -0,0 +1,211 @@ +/* + * e740-wm9705.c -- SoC audio for e740 + * + * Copyright 2007 (c) Ian Molton <spyro@f2s.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 ONLY. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/gpio.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <mach/audio.h> +#include <mach/eseries-gpio.h> + +#include <asm/mach-types.h> + +#include "../codecs/wm9705.h" +#include "pxa2xx-pcm.h" +#include "pxa2xx-ac97.h" + + +#define E740_AUDIO_OUT 1 +#define E740_AUDIO_IN 2 + +static int e740_audio_power; + +static void e740_sync_audio_power(int status) +{ + gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status); + gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0); + gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0); +} + +static int e740_mic_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + e740_audio_power |= E740_AUDIO_IN; + else if (event & SND_SOC_DAPM_POST_PMD) + e740_audio_power &= ~E740_AUDIO_IN; + + e740_sync_audio_power(e740_audio_power); + + return 0; +} + +static int e740_output_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + e740_audio_power |= E740_AUDIO_OUT; + else if (event & SND_SOC_DAPM_POST_PMD) + e740_audio_power &= ~E740_AUDIO_OUT; + + e740_sync_audio_power(e740_audio_power); + + return 0; +} + +static const struct snd_soc_dapm_widget e740_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_MIC("Mic (Internal)", NULL), + SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e740_output_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Output Amp", NULL, "LOUT"}, + {"Output Amp", NULL, "ROUT"}, + {"Output Amp", NULL, "MONOOUT"}, + + {"Speaker", NULL, "Output Amp"}, + {"Headphone Jack", NULL, "Output Amp"}, + + {"MIC1", NULL, "Mic Amp"}, + {"Mic Amp", NULL, "Mic (Internal)"}, +}; + +static int e740_ac97_init(struct snd_soc_codec *codec) +{ + snd_soc_dapm_nc_pin(codec, "HPOUTL"); + snd_soc_dapm_nc_pin(codec, "HPOUTR"); + snd_soc_dapm_nc_pin(codec, "PHONE"); + snd_soc_dapm_nc_pin(codec, "LINEINL"); + snd_soc_dapm_nc_pin(codec, "LINEINR"); + snd_soc_dapm_nc_pin(codec, "CDINL"); + snd_soc_dapm_nc_pin(codec, "CDINR"); + snd_soc_dapm_nc_pin(codec, "PCBEEP"); + snd_soc_dapm_nc_pin(codec, "MIC2"); + + snd_soc_dapm_new_controls(codec, e740_dapm_widgets, + ARRAY_SIZE(e740_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_sync(codec); + + return 0; +} + +static struct snd_soc_dai_link e740_dai[] = { + { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], + .init = e740_ac97_init, + }, + { + .name = "AC97 Aux", + .stream_name = "AC97 Aux", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], + }, +}; + +static struct snd_soc_card e740 = { + .name = "Toshiba e740", + .platform = &pxa2xx_soc_platform, + .dai_link = e740_dai, + .num_links = ARRAY_SIZE(e740_dai), +}; + +static struct snd_soc_device e740_snd_devdata = { + .card = &e740, + .codec_dev = &soc_codec_dev_wm9705, +}; + +static struct platform_device *e740_snd_device; + +static int __init e740_init(void) +{ + int ret; + + if (!machine_is_e740()) + return -ENODEV; + + ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp"); + if (ret) + return ret; + + ret = gpio_request(GPIO_E740_AMP_ON, "Output amp"); + if (ret) + goto free_mic_amp_gpio; + + ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power"); + if (ret) + goto free_op_amp_gpio; + + /* Disable audio */ + ret = gpio_direction_output(GPIO_E740_MIC_ON, 0); + if (ret) + goto free_apwr_gpio; + ret = gpio_direction_output(GPIO_E740_AMP_ON, 0); + if (ret) + goto free_apwr_gpio; + ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1); + if (ret) + goto free_apwr_gpio; + + e740_snd_device = platform_device_alloc("soc-audio", -1); + if (!e740_snd_device) { + ret = -ENOMEM; + goto free_apwr_gpio; + } + + platform_set_drvdata(e740_snd_device, &e740_snd_devdata); + e740_snd_devdata.dev = &e740_snd_device->dev; + ret = platform_device_add(e740_snd_device); + + if (!ret) + return 0; + +/* Fail gracefully */ + platform_device_put(e740_snd_device); +free_apwr_gpio: + gpio_free(GPIO_E740_WM9705_nAVDD2); +free_op_amp_gpio: + gpio_free(GPIO_E740_AMP_ON); +free_mic_amp_gpio: + gpio_free(GPIO_E740_MIC_ON); + + return ret; +} + +static void __exit e740_exit(void) +{ + platform_device_unregister(e740_snd_device); +} + +module_init(e740_init); +module_exit(e740_exit); + +/* Module information */ +MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); +MODULE_DESCRIPTION("ALSA SoC driver for e740"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c new file mode 100644 index 0000000..8dceccc --- /dev/null +++ b/sound/soc/pxa/e750_wm9705.c @@ -0,0 +1,187 @@ +/* + * e750-wm9705.c -- SoC audio for e750 + * + * Copyright 2007 (c) Ian Molton <spyro@f2s.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 ONLY. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/gpio.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <mach/audio.h> +#include <mach/eseries-gpio.h> + +#include <asm/mach-types.h> + +#include "../codecs/wm9705.h" +#include "pxa2xx-pcm.h" +#include "pxa2xx-ac97.h" + +static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1); + + return 0; +} + +static int e750_hp_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E750_HP_AMP_OFF, 0); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E750_HP_AMP_OFF, 1); + + return 0; +} + +static const struct snd_soc_dapm_widget e750_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_MIC("Mic (Internal)", NULL), + SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Headphone Amp", NULL, "HPOUTL"}, + {"Headphone Amp", NULL, "HPOUTR"}, + {"Headphone Jack", NULL, "Headphone Amp"}, + + {"Speaker Amp", NULL, "MONOOUT"}, + {"Speaker", NULL, "Speaker Amp"}, + + {"MIC1", NULL, "Mic (Internal)"}, +}; + +static int e750_ac97_init(struct snd_soc_codec *codec) +{ + snd_soc_dapm_nc_pin(codec, "LOUT"); + snd_soc_dapm_nc_pin(codec, "ROUT"); + snd_soc_dapm_nc_pin(codec, "PHONE"); + snd_soc_dapm_nc_pin(codec, "LINEINL"); + snd_soc_dapm_nc_pin(codec, "LINEINR"); + snd_soc_dapm_nc_pin(codec, "CDINL"); + snd_soc_dapm_nc_pin(codec, "CDINR"); + snd_soc_dapm_nc_pin(codec, "PCBEEP"); + snd_soc_dapm_nc_pin(codec, "MIC2"); + + snd_soc_dapm_new_controls(codec, e750_dapm_widgets, + ARRAY_SIZE(e750_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_sync(codec); + + return 0; +} + +static struct snd_soc_dai_link e750_dai[] = { + { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], + .init = e750_ac97_init, + /* use ops to check startup state */ + }, + { + .name = "AC97 Aux", + .stream_name = "AC97 Aux", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], + .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], + }, +}; + +static struct snd_soc_card e750 = { + .name = "Toshiba e750", + .platform = &pxa2xx_soc_platform, + .dai_link = e750_dai, + .num_links = ARRAY_SIZE(e750_dai), +}; + +static struct snd_soc_device e750_snd_devdata = { + .card = &e750, + .codec_dev = &soc_codec_dev_wm9705, +}; + +static struct platform_device *e750_snd_device; + +static int __init e750_init(void) +{ + int ret; + + if (!machine_is_e750()) + return -ENODEV; + + ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp"); + if (ret) + return ret; + + ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp"); + if (ret) + goto free_hp_amp_gpio; + + ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1); + if (ret) + goto free_spk_amp_gpio; + + ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1); + if (ret) + goto free_spk_amp_gpio; + + e750_snd_device = platform_device_alloc("soc-audio", -1); + if (!e750_snd_device) { + ret = -ENOMEM; + goto free_spk_amp_gpio; + } + + platform_set_drvdata(e750_snd_device, &e750_snd_devdata); + e750_snd_devdata.dev = &e750_snd_device->dev; + ret = platform_device_add(e750_snd_device); + + if (!ret) + return 0; + +/* Fail gracefully */ + platform_device_put(e750_snd_device); +free_spk_amp_gpio: + gpio_free(GPIO_E750_SPK_AMP_OFF); +free_hp_amp_gpio: + gpio_free(GPIO_E750_HP_AMP_OFF); + + return ret; +} + +static void __exit e750_exit(void) +{ + platform_device_unregister(e750_snd_device); + gpio_free(GPIO_E750_SPK_AMP_OFF); + gpio_free(GPIO_E750_HP_AMP_OFF); +} + +module_init(e750_init); +module_exit(e750_exit); + +/* Module information */ +MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); +MODULE_DESCRIPTION("ALSA SoC driver for e750"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 2e3386d..bc019cd 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -1,8 +1,6 @@ /* * e800-wm9712.c -- SoC audio for e800 * - * Based on tosa.c - * * Copyright 2007 (c) Ian Molton <spyro@f2s.com> * * This program is free software; you can redistribute it and/or modify it @@ -13,7 +11,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/device.h> +#include <linux/gpio.h> #include <sound/core.h> #include <sound/pcm.h> @@ -21,23 +19,85 @@ #include <sound/soc-dapm.h> #include <asm/mach-types.h> -#include <mach/pxa-regs.h> -#include <mach/hardware.h> #include <mach/audio.h> +#include <mach/eseries-gpio.h> #include "../codecs/wm9712.h" #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" -static struct snd_soc_card e800; +static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E800_SPK_AMP_ON, 1); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E800_SPK_AMP_ON, 0); -static struct snd_soc_dai_link e800_dai[] = { + return 0; +} + +static int e800_hp_amp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event & SND_SOC_DAPM_PRE_PMU) + gpio_set_value(GPIO_E800_HP_AMP_OFF, 0); + else if (event & SND_SOC_DAPM_POST_PMD) + gpio_set_value(GPIO_E800_HP_AMP_OFF, 1); + + return 0; +} + +static const struct snd_soc_dapm_widget e800_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic (Internal1)", NULL), + SND_SOC_DAPM_MIC("Mic (Internal2)", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"Headphone Jack", NULL, "HPOUTL"}, + {"Headphone Jack", NULL, "HPOUTR"}, + {"Headphone Jack", NULL, "Headphone Amp"}, + + {"Speaker Amp", NULL, "MONOOUT"}, + {"Speaker", NULL, "Speaker Amp"}, + + {"MIC1", NULL, "Mic (Internal1)"}, + {"MIC2", NULL, "Mic (Internal2)"}, +}; + +static int e800_ac97_init(struct snd_soc_codec *codec) { - .name = "AC97 Aux", - .stream_name = "AC97 Aux", - .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], - .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], -}, + snd_soc_dapm_new_controls(codec, e800_dapm_widgets, + ARRAY_SIZE(e800_dapm_widgets)); + + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_sync(codec); + + return 0; +} + +static struct snd_soc_dai_link e800_dai[] = { + { + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], + .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], + .init = e800_ac97_init, + }, + { + .name = "AC97 Aux", + .stream_name = "AC97 Aux", + .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], + .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + }, }; static struct snd_soc_card e800 = { @@ -61,6 +121,22 @@ static int __init e800_init(void) if (!machine_is_e800()) return -ENODEV; + ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp"); + if (ret) + return ret; + + ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp"); + if (ret) + goto free_hp_amp_gpio; + + ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1); + if (ret) + goto free_spk_amp_gpio; + + ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1); + if (ret) + goto free_spk_amp_gpio; + e800_snd_device = platform_device_alloc("soc-audio", -1); if (!e800_snd_device) return -ENOMEM; @@ -69,8 +145,15 @@ static int __init e800_init(void) e800_snd_devdata.dev = &e800_snd_device->dev; ret = platform_device_add(e800_snd_device); - if (ret) - platform_device_put(e800_snd_device); + if (!ret) + return 0; + +/* Fail gracefully */ + platform_device_put(e800_snd_device); +free_spk_amp_gpio: + gpio_free(GPIO_E800_SPK_AMP_ON); +free_hp_amp_gpio: + gpio_free(GPIO_E800_HP_AMP_OFF); return ret; } @@ -78,6 +161,8 @@ static int __init e800_init(void) static void __exit e800_exit(void) { platform_device_unregister(e800_snd_device); + gpio_free(GPIO_E800_SPK_AMP_ON); + gpio_free(GPIO_E800_HP_AMP_OFF); } module_init(e800_init); @@ -86,4 +171,4 @@ module_exit(e800_exit); /* Module information */ MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); MODULE_DESCRIPTION("ALSA SoC driver for e800"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index f8e9ecd..ec2fb76 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/device.h> +#include <linux/clk.h> #include <linux/i2c.h> #include <sound/core.h> #include <sound/pcm.h> @@ -26,6 +27,17 @@ #include "pxa2xx-ac97.h" #include "pxa-ssp.h" +/* + * There is a physical switch SW15 on the board which changes the MCLK + * for the WM9713 between the standard AC97 master clock and the + * output of the CLK_POUT signal from the PXA. + */ +static int clk_pout; +module_param(clk_pout, int, 0); +MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board)."); + +static struct clk *pout; + static struct snd_soc_card zylonite; static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { @@ -61,10 +73,8 @@ static const struct snd_soc_dapm_route audio_map[] = { static int zylonite_wm9713_init(struct snd_soc_codec *codec) { - /* Currently we only support use of the AC97 clock here. If - * CLK_POUT is selected by SW15 then the clock API will need - * to be used to request and enable it here. - */ + if (clk_pout) + snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, ARRAY_SIZE(zylonite_dapm_widgets)); @@ -135,11 +145,12 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs - * to be set instead. - */ - ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, - WM9713_PCMDIV(wm9713_div)); + if (clk_pout) + ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, + WM9713_PCMDIV(wm9713_div)); + else + ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, + WM9713_PCMDIV(wm9713_div)); if (ret < 0) return ret; @@ -173,8 +184,72 @@ static struct snd_soc_dai_link zylonite_dai[] = { }, }; +static int zylonite_probe(struct platform_device *pdev) +{ + int ret; + + if (clk_pout) { + pout = clk_get(NULL, "CLK_POUT"); + if (IS_ERR(pout)) { + dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n", + PTR_ERR(pout)); + return PTR_ERR(pout); + } + + ret = clk_enable(pout); + if (ret != 0) { + dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", + ret); + clk_put(pout); + return ret; + } + + dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n", + clk_get_rate(pout)); + } + + return 0; +} + +static int zylonite_remove(struct platform_device *pdev) +{ + if (clk_pout) { + clk_disable(pout); + clk_put(pout); + } + + return 0; +} + +static int zylonite_suspend_post(struct platform_device *pdev, + pm_message_t state) +{ + if (clk_pout) + clk_disable(pout); + + return 0; +} + +static int zylonite_resume_pre(struct platform_device *pdev) +{ + int ret = 0; + + if (clk_pout) { + ret = clk_enable(pout); + if (ret != 0) + dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n", + ret); + } + + return ret; +} + static struct snd_soc_card zylonite = { .name = "Zylonite", + .probe = &zylonite_probe, + .remove = &zylonite_remove, + .suspend_post = &zylonite_suspend_post, + .resume_pre = &zylonite_resume_pre, .platform = &pxa2xx_soc_platform, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index fcd03ac..e05a710 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -48,4 +48,5 @@ config SND_S3C24XX_SOC_S3C24XX_UDA134X tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" depends on SND_S3C24XX_SOC select SND_S3C24XX_SOC_I2S + select SND_SOC_L3 select SND_SOC_UDA134X diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 55fdb4a..580a1a5 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -234,7 +234,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) cpu_dai->capture.active = codec_dai->capture.active = 1; cpu_dai->active = codec_dai->active = 1; cpu_dai->runtime = runtime; - socdev->codec->active++; + card->codec->active++; mutex_unlock(&pcm_mutex); return 0; @@ -264,7 +264,7 @@ static void close_delayed_work(struct work_struct *work) struct snd_soc_card *card = container_of(work, struct snd_soc_card, delayed_work.work); struct snd_soc_device *socdev = card->socdev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; struct snd_soc_dai *codec_dai; int i; @@ -319,7 +319,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; mutex_lock(&pcm_mutex); @@ -387,7 +387,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; int ret = 0; mutex_lock(&pcm_mutex); @@ -553,7 +553,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; mutex_lock(&pcm_mutex); @@ -629,7 +629,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) struct snd_soc_card *card = socdev->card; struct snd_soc_platform *platform = card->platform; struct snd_soc_codec_device *codec_dev = socdev->codec_dev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; int i; /* Due to the resume being scheduled into a workqueue we could @@ -705,7 +705,7 @@ static void soc_resume_deferred(struct work_struct *work) struct snd_soc_device *socdev = card->socdev; struct snd_soc_platform *platform = card->platform; struct snd_soc_codec_device *codec_dev = socdev->codec_dev; - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = card->codec; struct platform_device *pdev = to_platform_device(socdev->dev); int i; @@ -982,8 +982,8 @@ static struct platform_driver soc_driver = { static int soc_new_pcm(struct snd_soc_device *socdev, struct snd_soc_dai_link *dai_link, int num) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; + struct snd_soc_codec *codec = card->codec; struct snd_soc_platform *platform = card->platform; struct snd_soc_dai *codec_dai = dai_link->codec_dai; struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; @@ -998,7 +998,7 @@ static int soc_new_pcm(struct snd_soc_device *socdev, rtd->dai = dai_link; rtd->socdev = socdev; - codec_dai->codec = socdev->codec; + codec_dai->codec = card->codec; /* check client and interface hw capabilities */ sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name, @@ -1048,9 +1048,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, } /* codec register dump */ -static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf) +static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) { - struct snd_soc_codec *codec = devdata->codec; int i, step = 1, count = 0; if (!codec->reg_cache_size) @@ -1090,7 +1089,7 @@ static ssize_t codec_reg_show(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_soc_device *devdata = dev_get_drvdata(dev); - return soc_codec_reg_show(devdata, buf); + return soc_codec_reg_show(devdata->card->codec, buf); } static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); @@ -1107,12 +1106,10 @@ static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, { ssize_t ret; struct snd_soc_codec *codec = file->private_data; - struct device *card_dev = codec->card->dev; - struct snd_soc_device *devdata = card_dev->driver_data; char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = soc_codec_reg_show(devdata, buf); + ret = soc_codec_reg_show(codec, buf); if (ret >= 0) ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); kfree(buf); @@ -1309,19 +1306,19 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits); */ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; - int ret = 0, i; + struct snd_soc_codec *codec = card->codec; + int ret, i; mutex_lock(&codec->mutex); /* register a sound card */ - codec->card = snd_card_new(idx, xid, codec->owner, 0); - if (!codec->card) { + ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card); + if (ret < 0) { printk(KERN_ERR "asoc: can't create sound card for codec %s\n", codec->name); mutex_unlock(&codec->mutex); - return -ENODEV; + return ret; } codec->card->dev = socdev->dev; @@ -1355,8 +1352,8 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms); */ int snd_soc_init_card(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; + struct snd_soc_codec *codec = card->codec; int ret = 0, i, ac97 = 0, err = 0; for (i = 0; i < card->num_links; i++) { @@ -1404,7 +1401,7 @@ int snd_soc_init_card(struct snd_soc_device *socdev) if (err < 0) printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); - soc_init_codec_debugfs(socdev->codec); + soc_init_codec_debugfs(codec); mutex_unlock(&codec->mutex); out: @@ -1421,14 +1418,14 @@ EXPORT_SYMBOL_GPL(snd_soc_init_card); */ void snd_soc_free_pcms(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; #ifdef CONFIG_SND_SOC_AC97_BUS struct snd_soc_dai *codec_dai; int i; #endif mutex_lock(&codec->mutex); - soc_cleanup_codec_debugfs(socdev->codec); + soc_cleanup_codec_debugfs(codec); #ifdef CONFIG_SND_SOC_AC97_BUS for (i = 0; i < codec->num_dai; i++) { codec_dai = &codec->dai[i]; @@ -1495,6 +1492,37 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, EXPORT_SYMBOL_GPL(snd_soc_cnew); /** + * snd_soc_add_controls - add an array of controls to a codec. + * Convienience function to add a list of controls. Many codecs were + * duplicating this code. + * + * @codec: codec to add controls to + * @controls: array of controls to add + * @num_controls: number of elements in the array + * + * Return 0 for success, else error. + */ +int snd_soc_add_controls(struct snd_soc_codec *codec, + const struct snd_kcontrol_new *controls, int num_controls) +{ + struct snd_card *card = codec->card; + int err, i; + + for (i = 0; i < num_controls; i++) { + const struct snd_kcontrol_new *control = &controls[i]; + err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); + if (err < 0) { + dev_err(codec->dev, "%s: Failed to add %s\n", + codec->name, control->name); + return err; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_add_controls); + +/** * snd_soc_info_enum_double - enumerated double mixer info callback * @kcontrol: mixer control * @uinfo: control element information diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a2f1da8..f4a8753 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -54,14 +54,15 @@ static int dapm_up_seq[] = { snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, - snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, - snd_soc_dapm_spk, snd_soc_dapm_post + snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, + snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post }; + static int dapm_down_seq[] = { snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, - snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic, - snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux, - snd_soc_dapm_post + snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, + snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, + snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post }; static int dapm_status = 1; @@ -101,7 +102,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, { switch (w->id) { case snd_soc_dapm_switch: - case snd_soc_dapm_mixer: { + case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: { int val; struct soc_mixer_control *mc = (struct soc_mixer_control *) w->kcontrols[i].private_value; @@ -323,15 +325,33 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, if (path->name != (char*)w->kcontrols[i].name) continue; - /* add dapm control with long name */ - name_len = 2 + strlen(w->name) - + strlen(w->kcontrols[i].name); + /* add dapm control with long name. + * for dapm_mixer this is the concatenation of the + * mixer and kcontrol name. + * for dapm_mixer_named_ctl this is simply the + * kcontrol name. + */ + name_len = strlen(w->kcontrols[i].name) + 1; + if (w->id == snd_soc_dapm_mixer) + name_len += 1 + strlen(w->name); + path->long_name = kmalloc(name_len, GFP_KERNEL); + if (path->long_name == NULL) return -ENOMEM; - snprintf(path->long_name, name_len, "%s %s", - w->name, w->kcontrols[i].name); + switch (w->id) { + case snd_soc_dapm_mixer: + default: + snprintf(path->long_name, name_len, "%s %s", + w->name, w->kcontrols[i].name); + break; + case snd_soc_dapm_mixer_named_ctl: + snprintf(path->long_name, name_len, "%s", + w->kcontrols[i].name); + break; + } + path->long_name[name_len - 1] = '\0'; path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, @@ -687,6 +707,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) case snd_soc_dapm_adc: case snd_soc_dapm_pga: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: if (w->name) { in = is_connected_input_ep(w); dapm_clear_walk(w->codec); @@ -760,6 +781,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, int found = 0; if (widget->id != snd_soc_dapm_mixer && + widget->id != snd_soc_dapm_mixer_named_ctl && widget->id != snd_soc_dapm_switch) return -ENODEV; @@ -795,7 +817,7 @@ static ssize_t dapm_widget_show(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_soc_device *devdata = dev_get_drvdata(dev); - struct snd_soc_codec *codec = devdata->codec; + struct snd_soc_codec *codec = devdata->card->codec; struct snd_soc_dapm_widget *w; int count = 0; char *state = "not set"; @@ -813,6 +835,7 @@ static ssize_t dapm_widget_show(struct device *dev, case snd_soc_dapm_adc: case snd_soc_dapm_pga: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: if (w->name) count += sprintf(buf + count, "%s: %s\n", w->name, w->power ? "On":"Off"); @@ -876,7 +899,7 @@ static void dapm_free_widgets(struct snd_soc_codec *codec) } static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, - char *pin, int status) + const char *pin, int status) { struct snd_soc_dapm_widget *w; @@ -991,6 +1014,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, break; case snd_soc_dapm_switch: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: ret = dapm_connect_mixer(codec, wsource, wsink, path, control); if (ret != 0) goto err; @@ -1068,6 +1092,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) switch(w->id) { case snd_soc_dapm_switch: case snd_soc_dapm_mixer: + case snd_soc_dapm_mixer_named_ctl: dapm_new_mixer(codec, w); break; case snd_soc_dapm_mux: @@ -1527,8 +1552,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, enum snd_soc_bias_level level) { - struct snd_soc_codec *codec = socdev->codec; struct snd_soc_card *card = socdev->card; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; if (card->set_bias_level) @@ -1549,7 +1574,7 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ -int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin) { return snd_soc_dapm_set_pin(codec, pin, 1); } @@ -1564,7 +1589,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ -int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin) { return snd_soc_dapm_set_pin(codec, pin, 0); } @@ -1584,7 +1609,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to * do any widget power switching. */ -int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin) { return snd_soc_dapm_set_pin(codec, pin, 0); } @@ -1599,7 +1624,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); * * Returns 1 for connected otherwise 0. */ -int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin) +int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin) { struct snd_soc_dapm_widget *w; @@ -1620,7 +1645,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); */ void snd_soc_dapm_free(struct snd_soc_device *socdev) { - struct snd_soc_codec *codec = socdev->codec; + struct snd_soc_codec *codec = socdev->card->codec; snd_soc_dapm_sys_remove(socdev->dev); dapm_free_widgets(codec); diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c new file mode 100644 index 0000000..ab64a30 --- /dev/null +++ b/sound/soc/soc-jack.c @@ -0,0 +1,138 @@ +/* + * soc-jack.c -- ALSA SoC jack handling + * + * Copyright 2008 Wolfson Microelectronics PLC. + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <sound/jack.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +/** + * snd_soc_jack_new - Create a new jack + * @card: ASoC card + * @id: an identifying string for this jack + * @type: a bitmask of enum snd_jack_type values that can be detected by + * this jack + * @jack: structure to use for the jack + * + * Creates a new jack object. + * + * Returns zero if successful, or a negative error code on failure. + * On success jack will be initialised. + */ +int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack) +{ + jack->card = card; + INIT_LIST_HEAD(&jack->pins); + + return snd_jack_new(card->codec->card, id, type, &jack->jack); +} +EXPORT_SYMBOL_GPL(snd_soc_jack_new); + +/** + * snd_soc_jack_report - Report the current status for a jack + * + * @jack: the jack + * @status: a bitmask of enum snd_jack_type values that are currently detected. + * @mask: a bitmask of enum snd_jack_type values that being reported. + * + * If configured using snd_soc_jack_add_pins() then the associated + * DAPM pins will be enabled or disabled as appropriate and DAPM + * synchronised. + * + * Note: This function uses mutexes and should be called from a + * context which can sleep (such as a workqueue). + */ +void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) +{ + struct snd_soc_codec *codec = jack->card->codec; + struct snd_soc_jack_pin *pin; + int enable; + int oldstatus; + + if (!jack) { + WARN_ON_ONCE(!jack); + return; + } + + mutex_lock(&codec->mutex); + + oldstatus = jack->status; + + jack->status &= ~mask; + jack->status |= status; + + /* The DAPM sync is expensive enough to be worth skipping */ + if (jack->status == oldstatus) + goto out; + + list_for_each_entry(pin, &jack->pins, list) { + enable = pin->mask & status; + + if (pin->invert) + enable = !enable; + + if (enable) + snd_soc_dapm_enable_pin(codec, pin->pin); + else + snd_soc_dapm_disable_pin(codec, pin->pin); + } + + snd_soc_dapm_sync(codec); + + snd_jack_report(jack->jack, status); + +out: + mutex_unlock(&codec->mutex); +} +EXPORT_SYMBOL_GPL(snd_soc_jack_report); + +/** + * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack + * + * @jack: ASoC jack + * @count: Number of pins + * @pins: Array of pins + * + * After this function has been called the DAPM pins specified in the + * pins array will have their status updated to reflect the current + * state of the jack whenever the jack status is updated. + */ +int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_pin *pins) +{ + int i; + + for (i = 0; i < count; i++) { + if (!pins[i].pin) { + printk(KERN_ERR "No name for pin %d\n", i); + return -EINVAL; + } + if (!pins[i].mask) { + printk(KERN_ERR "No mask for pin %d (%s)\n", i, + pins[i].pin); + return -EINVAL; + } + + INIT_LIST_HEAD(&pins[i].list); + list_add(&(pins[i].list), &jack->pins); + } + + /* Update to reflect the last reported status; canned jack + * implementations are likely to set their state before the + * card has an opportunity to associate pins. + */ + snd_soc_jack_report(jack, 0, 0); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index f87933e..ba38912 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -1018,9 +1018,10 @@ static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_de return -ENOENT; } - card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev_num], id[dev_num], THIS_MODULE, 0, + &card); + if (err < 0) + return err; strcpy(card->driver, "AMD7930"); strcpy(card->shortname, "Sun AMD7930"); diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 41c3875..7d93fa7 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1563,6 +1563,7 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) { struct snd_card *card; struct snd_cs4231 *chip; + int err; *rcard = NULL; @@ -1574,10 +1575,10 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cs4231)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cs4231), &card); + if (err < 0) + return err; strcpy(card->driver, "CS4231"); strcpy(card->shortname, "Sun CS4231"); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 23ed6f0..af95ff1 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2612,10 +2612,10 @@ static int __devinit dbri_probe(struct of_device *op, const struct of_device_id return -ENODEV; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dbri)); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_dbri), &card); + if (err < 0) + return err; strcpy(card->driver, "DBRI"); strcpy(card->shortname, "Sun DBRI"); diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 09802e8..4c7b051 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -965,12 +965,11 @@ static int __devinit snd_at73c213_probe(struct spi_device *spi) return PTR_ERR(board->dac_clk); } - retval = -ENOMEM; - /* Allocate "card" using some unused identifiers. */ snprintf(id, sizeof id, "at73c213_%d", board->ssc_id); - card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct snd_at73c213)); - if (!card) + retval = snd_card_create(-1, id, THIS_MODULE, + sizeof(struct snd_at73c213), &card); + if (retval < 0) goto out; chip = card->private_data; diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 41c36b0..09aed23 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -336,9 +336,10 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) log("Unable to set up control system (ret=%d)\n", ret); } -static struct snd_card* create_card(struct usb_device* usb_dev) +static int create_card(struct usb_device* usb_dev, struct snd_card **cardp) { int devnum; + int err; struct snd_card *card; struct snd_usb_caiaqdev *dev; @@ -347,12 +348,12 @@ static struct snd_card* create_card(struct usb_device* usb_dev) break; if (devnum >= SNDRV_CARDS) - return NULL; + return -ENODEV; - card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, - sizeof(struct snd_usb_caiaqdev)); - if (!card) - return NULL; + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(struct snd_usb_caiaqdev), &card); + if (err < 0) + return err; dev = caiaqdev(card); dev->chip.dev = usb_dev; @@ -362,7 +363,8 @@ static struct snd_card* create_card(struct usb_device* usb_dev) spin_lock_init(&dev->spinlock); snd_card_set_dev(card, &usb_dev->dev); - return card; + *cardp = card; + return 0; } static int __devinit init_card(struct snd_usb_caiaqdev *dev) @@ -441,10 +443,10 @@ static int __devinit snd_probe(struct usb_interface *intf, struct snd_card *card; struct usb_device *device = interface_to_usbdev(intf); - card = create_card(device); + ret = create_card(device, &card); - if (!card) - return -ENOMEM; + if (ret < 0) + return ret; usb_set_intfdata(intf, card); ret = init_card(caiaqdev(card)); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c709b95..eec32e1 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -3463,10 +3463,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, return -ENXIO; } - card = snd_card_new(index[idx], id[idx], THIS_MODULE, 0); - if (card == NULL) { + err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); + if (err < 0) { snd_printk(KERN_ERR "cannot create card instance %d\n", idx); - return -ENOMEM; + return err; } chip = kzalloc(sizeof(*chip), GFP_KERNEL); diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 73e59f4..98276aa 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -478,19 +478,21 @@ static bool us122l_create_card(struct snd_card *card) return true; } -static struct snd_card *usx2y_create_card(struct usb_device *device) +static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) { int dev; struct snd_card *card; + int err; + for (dev = 0; dev < SNDRV_CARDS; ++dev) if (enable[dev] && !snd_us122l_card_used[dev]) break; if (dev >= SNDRV_CARDS) - return NULL; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct us122l)); - if (!card) - return NULL; + return -ENODEV; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct us122l), &card); + if (err < 0) + return err; snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; US122L(card)->chip.dev = device; @@ -509,46 +511,57 @@ static struct snd_card *usx2y_create_card(struct usb_device *device) US122L(card)->chip.dev->devnum ); snd_card_set_dev(card, &device->dev); - return card; + *cardp = card; + return 0; } -static void *us122l_usb_probe(struct usb_interface *intf, - const struct usb_device_id *device_id) +static int us122l_usb_probe(struct usb_interface *intf, + const struct usb_device_id *device_id, + struct snd_card **cardp) { struct usb_device *device = interface_to_usbdev(intf); - struct snd_card *card = usx2y_create_card(device); + struct snd_card *card; + int err; - if (!card) - return NULL; + err = usx2y_create_card(device, &card); + if (err < 0) + return err; - if (!us122l_create_card(card) || - snd_card_register(card) < 0) { + if (!us122l_create_card(card)) { snd_card_free(card); - return NULL; + return -EINVAL; + } + + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return err; } usb_get_dev(device); - return card; + *cardp = card; + return 0; } static int snd_us122l_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct snd_card *card; + int err; + snd_printdd(KERN_DEBUG"%p:%i\n", intf, intf->cur_altsetting->desc.bInterfaceNumber); if (intf->cur_altsetting->desc.bInterfaceNumber != 1) return 0; - card = us122l_usb_probe(usb_get_intf(intf), id); - - if (card) { - usb_set_intfdata(intf, card); - return 0; + err = us122l_usb_probe(usb_get_intf(intf), id, &card); + if (err < 0) { + usb_put_intf(intf); + return err; } - usb_put_intf(intf); - return -EIO; + usb_set_intfdata(intf, card); + return 0; } static void snd_us122l_disconnect(struct usb_interface *intf) diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 11639bd..af8b849 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -333,18 +333,21 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = { { /* terminator */ } }; -static struct snd_card *usX2Y_create_card(struct usb_device *device) +static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) { int dev; struct snd_card * card; + int err; + for (dev = 0; dev < SNDRV_CARDS; ++dev) if (enable[dev] && !snd_usX2Y_card_used[dev]) break; if (dev >= SNDRV_CARDS) - return NULL; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev)); - if (!card) - return NULL; + return -ENODEV; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct usX2Ydev), &card); + if (err < 0) + return err; snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1; card->private_free = snd_usX2Y_card_private_free; usX2Y(card)->chip.dev = device; @@ -362,26 +365,36 @@ static struct snd_card *usX2Y_create_card(struct usb_device *device) usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum ); snd_card_set_dev(card, &device->dev); - return card; + *cardp = card; + return 0; } -static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id) +static int usX2Y_usb_probe(struct usb_device *device, + struct usb_interface *intf, + const struct usb_device_id *device_id, + struct snd_card **cardp) { int err; struct snd_card * card; + + *cardp = NULL; if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && - le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428) || - !(card = usX2Y_create_card(device))) - return NULL; + le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) + return -EINVAL; + + err = usX2Y_create_card(device, &card); + if (err < 0) + return err; if ((err = usX2Y_hwdep_new(card, device)) < 0 || (err = snd_card_register(card)) < 0) { snd_card_free(card); - return NULL; + return err; } - return card; + *cardp = card; + return 0; } /* @@ -389,13 +402,14 @@ static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *in */ static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) { - void *chip; - chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id); - if (chip) { - usb_set_intfdata(intf, chip); - return 0; - } else - return -EIO; + struct snd_card *card; + int err; + + err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card); + if (err < 0) + return err; + dev_set_drvdata(&intf->dev, card); + return 0; } static void snd_usX2Y_disconnect(struct usb_interface *intf) |