static LIST_HEAD(card_list);
static LIST_HEAD(dai_list);
static LIST_HEAD(platform_list);
+static LIST_HEAD(codec_list);
static int snd_soc_register_card(struct snd_soc_card *card);
static int snd_soc_unregister_card(struct snd_soc_card *card);
/**
* snd_soc_new_pcms - create new sound card and pcms
* @socdev: the SoC audio device
+ * @idx: ALSA card index
+ * @xid: card identification
*
* Create a new sound card based upon the codec and interface pcms.
*
* snd_soc_cnew - create new control
* @_template: control template
* @data: control private data
- * @lnng_name: control long name
+ * @long_name: control long name
*
* Create a new mixer control from a template control.
*
/**
* snd_soc_get_enum_double - enumerated double mixer get callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to get the value of a double enumerated mixer.
*
/**
* snd_soc_put_enum_double - enumerated double mixer put callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to set the value of a double enumerated mixer.
*
}
EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
+/**
+ * snd_soc_info_value_enum_double - semi enumerated double mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a double semi enumerated
+ * mixer control.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_value_enum_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct soc_value_enum *e = (struct soc_value_enum *)
+ kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
+ uinfo->value.enumerated.items = e->max;
+
+ if (uinfo->value.enumerated.item > e->max - 1)
+ uinfo->value.enumerated.item = e->max - 1;
+ strcpy(uinfo->value.enumerated.name,
+ e->texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_value_enum_double);
+
+/**
+ * snd_soc_get_value_enum_double - semi enumerated double mixer get callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to get the value of a double semi enumerated mixer.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_value_enum *e = (struct soc_value_enum *)
+ kcontrol->private_value;
+ unsigned short reg_val, val, mux;
+
+ reg_val = snd_soc_read(codec, e->reg);
+ val = (reg_val >> e->shift_l) & e->mask;
+ for (mux = 0; mux < e->max; mux++) {
+ if (val == e->values[mux])
+ break;
+ }
+ ucontrol->value.enumerated.item[0] = mux;
+ if (e->shift_l != e->shift_r) {
+ val = (reg_val >> e->shift_r) & e->mask;
+ for (mux = 0; mux < e->max; mux++) {
+ if (val == e->values[mux])
+ break;
+ }
+ ucontrol->value.enumerated.item[1] = mux;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double);
+
+/**
+ * snd_soc_put_value_enum_double - semi enumerated double mixer put callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to set the value of a double semi enumerated mixer.
+ *
+ * Semi enumerated mixer: the enumerated items are referred as values. Can be
+ * used for handling bitfield coded enumeration for example.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_value_enum *e = (struct soc_value_enum *)
+ kcontrol->private_value;
+ unsigned short val;
+ unsigned short mask;
+
+ if (ucontrol->value.enumerated.item[0] > e->max - 1)
+ return -EINVAL;
+ val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
+ mask = e->mask << e->shift_l;
+ if (e->shift_l != e->shift_r) {
+ if (ucontrol->value.enumerated.item[1] > e->max - 1)
+ return -EINVAL;
+ val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
+ mask |= e->mask << e->shift_r;
+ }
+
+ return snd_soc_update_bits(codec, e->reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
+
/**
* snd_soc_info_enum_ext - external enumerated single mixer info callback
* @kcontrol: mixer control
/**
* snd_soc_get_volsw - single mixer get callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to get the value of a single mixer control.
*
/**
* snd_soc_put_volsw - single mixer put callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to set the value of a single mixer control.
*
/**
* snd_soc_get_volsw_2r - double mixer get callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to get the value of a double mixer control that spans 2 registers.
*
/**
* snd_soc_put_volsw_2r - double mixer set callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to set the value of a double mixer control that spans 2 registers.
*
/**
* snd_soc_get_volsw_s8 - signed mixer get callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to get the value of a signed mixer control.
*
/**
* snd_soc_put_volsw_sgn - signed mixer put callback
* @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
*
* Callback to set the value of a signed mixer control.
*
/**
* snd_soc_dai_set_clkdiv - configure DAI clock dividers.
* @dai: DAI
- * @clk_id: DAI specific clock divider ID
+ * @div_id: DAI specific clock divider ID
* @div: new clock divisor.
*
* Configures the clock dividers. This is used to derive the best DAI bit and
/**
* snd_soc_register_card - Register a card with the ASoC core
*
- * @param card Card to register
+ * @card: Card to register
*
* Note that currently this is an internal only function: it will be
* exposed to machine drivers after further backporting of ASoC v2
/**
* snd_soc_unregister_card - Unregister a card with the ASoC core
*
- * @param card Card to unregister
+ * @card: Card to unregister
*
* Note that currently this is an internal only function: it will be
* exposed to machine drivers after further backporting of ASoC v2
/**
* snd_soc_register_dai - Register a DAI with the ASoC core
*
- * @param dai DAI to register
+ * @dai: DAI to register
*/
int snd_soc_register_dai(struct snd_soc_dai *dai)
{
/**
* snd_soc_unregister_dai - Unregister a DAI from the ASoC core
*
- * @param dai DAI to unregister
+ * @dai: DAI to unregister
*/
void snd_soc_unregister_dai(struct snd_soc_dai *dai)
{
/**
* snd_soc_register_dais - Register multiple DAIs with the ASoC core
*
- * @param dai Array of DAIs to register
- * @param count Number of DAIs
+ * @dai: Array of DAIs to register
+ * @count: Number of DAIs
*/
int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count)
{
/**
* snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
*
- * @param dai Array of DAIs to unregister
- * @param count Number of DAIs
+ * @dai: Array of DAIs to unregister
+ * @count: Number of DAIs
*/
void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count)
{
/**
* snd_soc_register_platform - Register a platform with the ASoC core
*
- * @param platform platform to register
+ * @platform: platform to register
*/
int snd_soc_register_platform(struct snd_soc_platform *platform)
{
/**
* snd_soc_unregister_platform - Unregister a platform from the ASoC core
*
- * @param platform platform to unregister
+ * @platform: platform to unregister
*/
void snd_soc_unregister_platform(struct snd_soc_platform *platform)
{
}
EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
-static int __devinit snd_soc_init(void)
+/**
+ * snd_soc_register_codec - Register a codec with the ASoC core
+ *
+ * @codec: codec to register
+ */
+int snd_soc_register_codec(struct snd_soc_codec *codec)
+{
+ if (!codec->name)
+ return -EINVAL;
+
+ /* The device should become mandatory over time */
+ if (!codec->dev)
+ printk(KERN_WARNING "No device for codec %s\n", codec->name);
+
+ INIT_LIST_HEAD(&codec->list);
+
+ mutex_lock(&client_mutex);
+ list_add(&codec->list, &codec_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Registered codec '%s'\n", codec->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_codec);
+
+/**
+ * snd_soc_unregister_codec - Unregister a codec from the ASoC core
+ *
+ * @codec: codec to unregister
+ */
+void snd_soc_unregister_codec(struct snd_soc_codec *codec)
+{
+ mutex_lock(&client_mutex);
+ list_del(&codec->list);
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Unregistered codec '%s'\n", codec->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
+
+static int __init snd_soc_init(void)
{
#ifdef CONFIG_DEBUG_FS
debugfs_root = debugfs_create_dir("asoc", NULL);