mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 23:24:11 +08:00
Merge remote-tracking branch 'asoc/topic/component' into asoc-next
This commit is contained in:
commit
a1cb98ac8b
@ -257,7 +257,6 @@ struct snd_soc_dai {
|
||||
|
||||
struct snd_soc_dapm_widget *playback_widget;
|
||||
struct snd_soc_dapm_widget *capture_widget;
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
/* DAI DMA data */
|
||||
void *playback_dma_data;
|
||||
@ -273,6 +272,10 @@ struct snd_soc_dai {
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_component *component;
|
||||
|
||||
/* CODEC TDM slot masks and params (for fixup) */
|
||||
unsigned int tx_mask;
|
||||
unsigned int rx_mask;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
|
||||
struct list_head list;
|
||||
|
@ -431,7 +431,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
|
||||
const char *pin);
|
||||
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
|
||||
void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
|
||||
|
||||
/* Mostly internal - should not normally be used */
|
||||
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
|
||||
@ -441,6 +441,8 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
|
||||
struct snd_soc_dapm_widget_list **list);
|
||||
|
||||
struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
|
||||
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
|
||||
struct snd_kcontrol *kcontrol);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
@ -524,7 +526,6 @@ struct snd_soc_dapm_widget {
|
||||
const char *name; /* widget name */
|
||||
const char *sname; /* stream name */
|
||||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_platform *platform;
|
||||
struct list_head list;
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
|
||||
@ -593,7 +594,6 @@ struct snd_soc_dapm_context {
|
||||
struct device *dev; /* from parent - for debug */
|
||||
struct snd_soc_component *component; /* parent component */
|
||||
struct snd_soc_codec *codec; /* parent codec */
|
||||
struct snd_soc_platform *platform; /* parent platform */
|
||||
struct snd_soc_card *card; /* parent card */
|
||||
|
||||
/* used during DAPM updates */
|
||||
@ -601,6 +601,8 @@ struct snd_soc_dapm_context {
|
||||
struct list_head list;
|
||||
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dapm;
|
||||
|
@ -436,6 +436,10 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
|
||||
int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd, struct snd_soc_platform *platform);
|
||||
|
||||
int soc_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai);
|
||||
|
||||
/* Jack reporting */
|
||||
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
|
||||
struct snd_soc_jack *jack);
|
||||
@ -503,10 +507,12 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
|
||||
const char *prefix);
|
||||
struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
|
||||
const char *name);
|
||||
int snd_soc_add_component_controls(struct snd_soc_component *component,
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
const struct snd_kcontrol_new *controls, unsigned int num_controls);
|
||||
int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
|
||||
const struct snd_kcontrol_new *controls, int num_controls);
|
||||
int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
|
||||
@ -677,12 +683,17 @@ struct snd_soc_component_driver {
|
||||
int (*of_xlate_dai_name)(struct snd_soc_component *component,
|
||||
struct of_phandle_args *args,
|
||||
const char **dai_name);
|
||||
void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
|
||||
int subseq);
|
||||
int (*stream_event)(struct snd_soc_component *, int event);
|
||||
};
|
||||
|
||||
struct snd_soc_component {
|
||||
const char *name;
|
||||
int id;
|
||||
const char *name_prefix;
|
||||
struct device *dev;
|
||||
struct snd_soc_card *card;
|
||||
|
||||
unsigned int active;
|
||||
|
||||
@ -705,18 +716,18 @@ struct snd_soc_component {
|
||||
int val_bytes;
|
||||
|
||||
struct mutex io_mutex;
|
||||
|
||||
/* Don't use these, use snd_soc_component_get_dapm() */
|
||||
struct snd_soc_dapm_context dapm;
|
||||
struct snd_soc_dapm_context *dapm_ptr;
|
||||
};
|
||||
|
||||
/* SoC Audio Codec device */
|
||||
struct snd_soc_codec {
|
||||
const char *name;
|
||||
const char *name_prefix;
|
||||
int id;
|
||||
struct device *dev;
|
||||
const struct snd_soc_codec_driver *driver;
|
||||
|
||||
struct mutex mutex;
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
|
||||
@ -790,9 +801,6 @@ struct snd_soc_codec_driver {
|
||||
void (*seq_notifier)(struct snd_soc_dapm_context *,
|
||||
enum snd_soc_dapm_type, int);
|
||||
|
||||
/* codec stream completion event */
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
|
||||
bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
@ -834,9 +842,6 @@ struct snd_soc_platform_driver {
|
||||
/* platform stream compress ops */
|
||||
const struct snd_compr_ops *compr_ops;
|
||||
|
||||
/* platform stream completion event */
|
||||
int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
|
||||
|
||||
/* probe ordering - for components with runtime dependencies */
|
||||
int probe_order;
|
||||
int remove_order;
|
||||
@ -847,23 +852,23 @@ struct snd_soc_platform_driver {
|
||||
int (*bespoke_trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
struct snd_soc_platform {
|
||||
struct snd_soc_dai_link_component {
|
||||
const char *name;
|
||||
int id;
|
||||
const struct device_node *of_node;
|
||||
const char *dai_name;
|
||||
};
|
||||
|
||||
struct snd_soc_platform {
|
||||
struct device *dev;
|
||||
const struct snd_soc_platform_driver *driver;
|
||||
|
||||
unsigned int suspended:1; /* platform is suspended */
|
||||
unsigned int probed:1;
|
||||
|
||||
struct snd_soc_card *card;
|
||||
struct list_head list;
|
||||
struct list_head card_list;
|
||||
|
||||
struct snd_soc_component component;
|
||||
|
||||
struct snd_soc_dapm_context dapm;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_platform_root;
|
||||
#endif
|
||||
@ -896,6 +901,10 @@ struct snd_soc_dai_link {
|
||||
const struct device_node *codec_of_node;
|
||||
/* You MUST specify the DAI name within the codec */
|
||||
const char *codec_dai_name;
|
||||
|
||||
struct snd_soc_dai_link_component *codecs;
|
||||
unsigned int num_codecs;
|
||||
|
||||
/*
|
||||
* You MAY specify the link's platform/PCM/DMA driver, either by
|
||||
* device name, or by DT/OF node, but not both. Some forms of link
|
||||
@ -1047,7 +1056,6 @@ struct snd_soc_card {
|
||||
|
||||
/* lists of probed devices belonging to this card */
|
||||
struct list_head codec_dev_list;
|
||||
struct list_head platform_dev_list;
|
||||
|
||||
struct list_head widgets;
|
||||
struct list_head paths;
|
||||
@ -1094,6 +1102,9 @@ struct snd_soc_pcm_runtime {
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
struct snd_soc_dai **codec_dais;
|
||||
unsigned int num_codecs;
|
||||
|
||||
struct delayed_work delayed_work;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_dpcm_root;
|
||||
@ -1164,6 +1175,21 @@ static inline struct snd_soc_platform *snd_soc_component_to_platform(
|
||||
return container_of(component, struct snd_soc_platform, component);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
|
||||
* embedded in
|
||||
* @dapm: The DAPM context to cast to the component
|
||||
*
|
||||
* This function must only be used on DAPM contexts that are known to be part of
|
||||
* a component (e.g. in a component driver). Otherwise the behavior is
|
||||
* undefined.
|
||||
*/
|
||||
static inline struct snd_soc_component *snd_soc_dapm_to_component(
|
||||
struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
return container_of(dapm, struct snd_soc_component, dapm);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
|
||||
* @dapm: The DAPM context to cast to the CODEC
|
||||
@ -1188,7 +1214,18 @@ static inline struct snd_soc_codec *snd_soc_dapm_to_codec(
|
||||
static inline struct snd_soc_platform *snd_soc_dapm_to_platform(
|
||||
struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
return container_of(dapm, struct snd_soc_platform, dapm);
|
||||
return snd_soc_component_to_platform(snd_soc_dapm_to_component(dapm));
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_component_get_dapm() - Returns the DAPM context associated with a
|
||||
* component
|
||||
* @component: The component for which to get the DAPM context
|
||||
*/
|
||||
static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
|
||||
struct snd_soc_component *component)
|
||||
{
|
||||
return component->dapm_ptr;
|
||||
}
|
||||
|
||||
/* codec IO */
|
||||
@ -1261,7 +1298,6 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
|
||||
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
|
||||
{
|
||||
INIT_LIST_HEAD(&card->codec_dev_list);
|
||||
INIT_LIST_HEAD(&card->platform_dev_list);
|
||||
INIT_LIST_HEAD(&card->widgets);
|
||||
INIT_LIST_HEAD(&card->paths);
|
||||
INIT_LIST_HEAD(&card->dapm_list);
|
||||
|
@ -296,17 +296,17 @@ TRACE_EVENT(snd_soc_cache_sync,
|
||||
TP_ARGS(codec, type, status),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, codec->name )
|
||||
__string( name, codec->component.name)
|
||||
__string( status, status )
|
||||
__string( type, type )
|
||||
__field( int, id )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, codec->name);
|
||||
__assign_str(name, codec->component.name);
|
||||
__assign_str(status, status);
|
||||
__assign_str(type, type);
|
||||
__entry->id = codec->id;
|
||||
__entry->id = codec->component.id;
|
||||
),
|
||||
|
||||
TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),
|
||||
|
@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
|
||||
/* add codec as bus device for standard ac97 */
|
||||
ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL,
|
||||
&ac97_bus);
|
||||
ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops,
|
||||
NULL, &ac97_bus);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -253,7 +253,7 @@ static void v253_close(struct tty_struct *tty)
|
||||
/* Prevent the codec driver from further accessing the modem */
|
||||
codec->hw_write = NULL;
|
||||
cx20442->control_data = NULL;
|
||||
codec->card->pop_time = 0;
|
||||
codec->component.card->pop_time = 0;
|
||||
}
|
||||
|
||||
/* Line discipline .hangup() */
|
||||
@ -281,7 +281,7 @@ static void v253_receive(struct tty_struct *tty,
|
||||
/* Set up codec driver access to modem controls */
|
||||
cx20442->control_data = tty;
|
||||
codec->hw_write = (hw_write_t)tty->ops->write;
|
||||
codec->card->pop_time = 1;
|
||||
codec->component.card->pop_time = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,7 +372,7 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec)
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, cx20442);
|
||||
codec->hw_write = NULL;
|
||||
codec->card->pop_time = 0;
|
||||
codec->component.card->pop_time = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1404,7 +1404,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
|
||||
if (dac33->irq >= 0) {
|
||||
ret = request_irq(dac33->irq, dac33_interrupt_handler,
|
||||
IRQF_TRIGGER_RISING,
|
||||
codec->name, codec);
|
||||
codec->component.name, codec);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
|
||||
dac33->irq, ret);
|
||||
|
@ -479,7 +479,7 @@ static struct snd_soc_dai_driver uda134x_dai = {
|
||||
static int uda134x_soc_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct uda134x_priv *uda134x;
|
||||
struct uda134x_platform_data *pd = codec->card->dev->platform_data;
|
||||
struct uda134x_platform_data *pd = codec->component.card->dev->platform_data;
|
||||
const struct snd_soc_dapm_widget *widgets;
|
||||
unsigned num_widgets;
|
||||
|
||||
|
@ -472,7 +472,7 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
|
||||
* list each time to find the desired power state do so now
|
||||
* and save the result.
|
||||
*/
|
||||
list_for_each_entry(w, &codec->card->widgets, list) {
|
||||
list_for_each_entry(w, &codec->component.card->widgets, list) {
|
||||
if (w->dapm != &codec->dapm)
|
||||
continue;
|
||||
if (strcmp(w->name, "LOUT1 PGA") == 0)
|
||||
|
@ -1382,7 +1382,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
|
||||
int ret;
|
||||
int val;
|
||||
|
||||
dsp->card = codec->card;
|
||||
dsp->card = codec->component.card;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
@ -1617,7 +1617,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
|
||||
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
|
||||
struct wm_adsp *dsp = &dsps[w->shift];
|
||||
|
||||
dsp->card = codec->card;
|
||||
dsp->card = codec->component.card;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
|
@ -301,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty)
|
||||
static void cx81801_close(struct tty_struct *tty)
|
||||
{
|
||||
struct snd_soc_codec *codec = tty->disc_data;
|
||||
struct snd_soc_dapm_context *dapm = &codec->card->dapm;
|
||||
struct snd_soc_dapm_context *dapm = &codec->component.card->dapm;
|
||||
|
||||
del_timer_sync(&cx81801_timer);
|
||||
|
||||
|
@ -78,7 +78,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
|
||||
mutex_init(&codec->cache_rw_mutex);
|
||||
|
||||
dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n",
|
||||
codec->name);
|
||||
codec->component.name);
|
||||
|
||||
if (codec_drv->reg_cache_default)
|
||||
codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
|
||||
@ -98,8 +98,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
|
||||
int snd_soc_cache_exit(struct snd_soc_codec *codec)
|
||||
{
|
||||
dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n",
|
||||
codec->name);
|
||||
|
||||
codec->component.name);
|
||||
kfree(codec->reg_cache);
|
||||
codec->reg_cache = NULL;
|
||||
return 0;
|
||||
@ -192,7 +191,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec)
|
||||
return 0;
|
||||
|
||||
dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n",
|
||||
codec->name);
|
||||
codec->component.name);
|
||||
trace_snd_soc_cache_sync(codec, name, "start");
|
||||
ret = snd_soc_flat_cache_sync(codec);
|
||||
if (!ret)
|
||||
|
@ -37,7 +37,8 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
|
||||
if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
|
||||
ret = platform->driver->compr_ops->open(cstream);
|
||||
if (ret < 0) {
|
||||
pr_err("compress asoc: can't open platform %s\n", platform->name);
|
||||
pr_err("compress asoc: can't open platform %s\n",
|
||||
platform->component.name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -84,7 +85,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
|
||||
if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
|
||||
ret = platform->driver->compr_ops->open(cstream);
|
||||
if (ret < 0) {
|
||||
pr_err("compress asoc: can't open platform %s\n", platform->name);
|
||||
pr_err("compress asoc: can't open platform %s\n",
|
||||
platform->component.name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -627,6 +629,11 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
char new_name[64];
|
||||
int ret = 0, direction = 0;
|
||||
|
||||
if (rtd->num_codecs > 1) {
|
||||
dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check client and interface hw capabilities */
|
||||
snprintf(new_name, sizeof(new_name), "%s %s-%d",
|
||||
rtd->dai_link->stream_name, codec_dai->name, num);
|
||||
@ -680,7 +687,7 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
|
||||
if (ret < 0) {
|
||||
pr_err("compress asoc: can't create compress for codec %s\n",
|
||||
codec->name);
|
||||
codec->component.name);
|
||||
goto compr_err;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -349,13 +349,28 @@ static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a
|
||||
* kcontrol
|
||||
* @kcontrol: The kcontrol
|
||||
*
|
||||
* Note: This function must only be used on kcontrols that are known to have
|
||||
* been registered for a CODEC. Otherwise the behaviour is undefined.
|
||||
*/
|
||||
struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
|
||||
struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm);
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
|
||||
* @kcontrol: The kcontrol
|
||||
*/
|
||||
struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec;
|
||||
return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec);
|
||||
|
||||
@ -375,23 +390,38 @@ static void dapm_reset(struct snd_soc_card *card)
|
||||
}
|
||||
}
|
||||
|
||||
static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
|
||||
unsigned int *value)
|
||||
static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
if (!w->dapm->component)
|
||||
return -EIO;
|
||||
return snd_soc_component_read(w->dapm->component, reg, value);
|
||||
if (!dapm->component)
|
||||
return NULL;
|
||||
return dapm->component->name_prefix;
|
||||
}
|
||||
|
||||
static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
|
||||
static int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg,
|
||||
unsigned int *value)
|
||||
{
|
||||
if (!dapm->component)
|
||||
return -EIO;
|
||||
return snd_soc_component_read(dapm->component, reg, value);
|
||||
}
|
||||
|
||||
static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm,
|
||||
int reg, unsigned int mask, unsigned int value)
|
||||
{
|
||||
if (!w->dapm->component)
|
||||
if (!dapm->component)
|
||||
return -EIO;
|
||||
return snd_soc_component_update_bits_async(w->dapm->component, reg,
|
||||
return snd_soc_component_update_bits_async(dapm->component, reg,
|
||||
mask, value);
|
||||
}
|
||||
|
||||
static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm,
|
||||
int reg, unsigned int mask, unsigned int value)
|
||||
{
|
||||
if (!dapm->component)
|
||||
return -EIO;
|
||||
return snd_soc_component_test_bits(dapm->component, reg, mask, value);
|
||||
}
|
||||
|
||||
static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
if (dapm->component)
|
||||
@ -420,15 +450,10 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
if (dapm->codec) {
|
||||
if (dapm->codec->driver->set_bias_level)
|
||||
ret = dapm->codec->driver->set_bias_level(dapm->codec,
|
||||
level);
|
||||
else
|
||||
dapm->bias_level = level;
|
||||
} else if (!card || dapm != &card->dapm) {
|
||||
if (dapm->set_bias_level)
|
||||
ret = dapm->set_bias_level(dapm, level);
|
||||
else if (!card || dapm != &card->dapm)
|
||||
dapm->bias_level = level;
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
@ -452,7 +477,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
|
||||
int i;
|
||||
|
||||
if (e->reg != SND_SOC_NOPM) {
|
||||
soc_widget_read(dest, e->reg, &val);
|
||||
soc_dapm_read(dapm, e->reg, &val);
|
||||
val = (val >> e->shift_l) & e->mask;
|
||||
item = snd_soc_enum_val_to_item(e, val);
|
||||
} else {
|
||||
@ -496,7 +521,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w,
|
||||
unsigned int val;
|
||||
|
||||
if (reg != SND_SOC_NOPM) {
|
||||
soc_widget_read(w, reg, &val);
|
||||
soc_dapm_read(w->dapm, reg, &val);
|
||||
val = (val >> shift) & mask;
|
||||
if (invert)
|
||||
val = max - val;
|
||||
@ -570,11 +595,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
if (dapm->codec)
|
||||
prefix = dapm->codec->name_prefix;
|
||||
else
|
||||
prefix = NULL;
|
||||
|
||||
prefix = soc_dapm_prefix(dapm);
|
||||
if (prefix)
|
||||
prefix_len = strlen(prefix) + 1;
|
||||
else
|
||||
@ -1308,16 +1329,18 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
|
||||
static void dapm_seq_run_coalesced(struct snd_soc_card *card,
|
||||
struct list_head *pending)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm;
|
||||
struct snd_soc_dapm_widget *w;
|
||||
int reg;
|
||||
unsigned int value = 0;
|
||||
unsigned int mask = 0;
|
||||
|
||||
reg = list_first_entry(pending, struct snd_soc_dapm_widget,
|
||||
power_list)->reg;
|
||||
w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list);
|
||||
reg = w->reg;
|
||||
dapm = w->dapm;
|
||||
|
||||
list_for_each_entry(w, pending, power_list) {
|
||||
WARN_ON(reg != w->reg);
|
||||
WARN_ON(reg != w->reg || dapm != w->dapm);
|
||||
w->power = w->new_power;
|
||||
|
||||
mask |= w->mask << w->shift;
|
||||
@ -1326,7 +1349,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
|
||||
else
|
||||
value |= w->off_val << w->shift;
|
||||
|
||||
pop_dbg(w->dapm->dev, card->pop_time,
|
||||
pop_dbg(dapm->dev, card->pop_time,
|
||||
"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
|
||||
w->name, reg, value, mask);
|
||||
|
||||
@ -1339,14 +1362,12 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
|
||||
/* Any widget will do, they should all be updating the
|
||||
* same register.
|
||||
*/
|
||||
w = list_first_entry(pending, struct snd_soc_dapm_widget,
|
||||
power_list);
|
||||
|
||||
pop_dbg(w->dapm->dev, card->pop_time,
|
||||
pop_dbg(dapm->dev, card->pop_time,
|
||||
"pop test : Applying 0x%x/0x%x to %x in %dms\n",
|
||||
value, mask, reg, card->pop_time);
|
||||
pop_wait(card->pop_time);
|
||||
soc_widget_update_bits(w, reg, mask, value);
|
||||
soc_dapm_update_bits(dapm, reg, mask, value);
|
||||
}
|
||||
|
||||
list_for_each_entry(w, pending, power_list) {
|
||||
@ -1492,7 +1513,8 @@ static void dapm_widget_update(struct snd_soc_card *card)
|
||||
if (!w)
|
||||
return;
|
||||
|
||||
ret = soc_widget_update_bits(w, update->reg, update->mask, update->val);
|
||||
ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask,
|
||||
update->val);
|
||||
if (ret < 0)
|
||||
dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
|
||||
w->name, ret);
|
||||
@ -2062,17 +2084,13 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
|
||||
|
||||
/* show dapm widget status in sys fs */
|
||||
static ssize_t dapm_widget_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t dapm_widget_show_codec(struct snd_soc_codec *codec, char *buf)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
|
||||
struct snd_soc_codec *codec =rtd->codec;
|
||||
struct snd_soc_dapm_widget *w;
|
||||
int count = 0;
|
||||
char *state = "not set";
|
||||
|
||||
list_for_each_entry(w, &codec->card->widgets, list) {
|
||||
list_for_each_entry(w, &codec->component.card->widgets, list) {
|
||||
if (w->dapm != &codec->dapm)
|
||||
continue;
|
||||
|
||||
@ -2120,6 +2138,21 @@ static ssize_t dapm_widget_show(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
/* show dapm widget status in sys fs */
|
||||
static ssize_t dapm_widget_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
|
||||
int i, count = 0;
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
struct snd_soc_codec *codec = rtd->codec_dais[i]->codec;
|
||||
count += dapm_widget_show_codec(codec, buf + count);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
|
||||
|
||||
int snd_soc_dapm_sys_add(struct device *dev)
|
||||
@ -2371,14 +2404,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
|
||||
const char *source;
|
||||
char prefixed_sink[80];
|
||||
char prefixed_source[80];
|
||||
const char *prefix;
|
||||
int ret;
|
||||
|
||||
if (dapm->codec && dapm->codec->name_prefix) {
|
||||
prefix = soc_dapm_prefix(dapm);
|
||||
if (prefix) {
|
||||
snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
|
||||
dapm->codec->name_prefix, route->sink);
|
||||
prefix, route->sink);
|
||||
sink = prefixed_sink;
|
||||
snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
|
||||
dapm->codec->name_prefix, route->source);
|
||||
prefix, route->source);
|
||||
source = prefixed_source;
|
||||
} else {
|
||||
sink = route->sink;
|
||||
@ -2439,6 +2474,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
|
||||
const char *source;
|
||||
char prefixed_sink[80];
|
||||
char prefixed_source[80];
|
||||
const char *prefix;
|
||||
|
||||
if (route->control) {
|
||||
dev_err(dapm->dev,
|
||||
@ -2446,12 +2482,13 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dapm->codec && dapm->codec->name_prefix) {
|
||||
prefix = soc_dapm_prefix(dapm);
|
||||
if (prefix) {
|
||||
snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
|
||||
dapm->codec->name_prefix, route->sink);
|
||||
prefix, route->sink);
|
||||
sink = prefixed_sink;
|
||||
snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
|
||||
dapm->codec->name_prefix, route->source);
|
||||
prefix, route->source);
|
||||
source = prefixed_source;
|
||||
} else {
|
||||
sink = route->sink;
|
||||
@ -2670,7 +2707,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
|
||||
|
||||
/* Read the initial power state from the device */
|
||||
if (w->reg >= 0) {
|
||||
soc_widget_read(w, w->reg, &val);
|
||||
soc_dapm_read(w->dapm, w->reg, &val);
|
||||
val = val >> w->shift;
|
||||
val &= w->mask;
|
||||
if (val == w->on_val)
|
||||
@ -2701,8 +2738,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
|
||||
int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
|
||||
struct snd_soc_card *card = dapm->card;
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
int reg = mc->reg;
|
||||
@ -2711,17 +2748,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
unsigned int mask = (1 << fls(max)) - 1;
|
||||
unsigned int invert = mc->invert;
|
||||
unsigned int val;
|
||||
int ret = 0;
|
||||
|
||||
if (snd_soc_volsw_is_stereo(mc))
|
||||
dev_warn(codec->dapm.dev,
|
||||
dev_warn(dapm->dev,
|
||||
"ASoC: Control '%s' is stereo, which is not supported\n",
|
||||
kcontrol->id.name);
|
||||
|
||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||
if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
|
||||
val = (snd_soc_read(codec, reg) >> shift) & mask;
|
||||
else
|
||||
if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
|
||||
ret = soc_dapm_read(dapm, reg, &val);
|
||||
val = (val >> shift) & mask;
|
||||
} else {
|
||||
val = dapm_kcontrol_get_value(kcontrol);
|
||||
}
|
||||
mutex_unlock(&card->dapm_mutex);
|
||||
|
||||
if (invert)
|
||||
@ -2729,7 +2769,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
||||
else
|
||||
ucontrol->value.integer.value[0] = val;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
|
||||
|
||||
@ -2745,8 +2785,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
|
||||
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
|
||||
struct snd_soc_card *card = dapm->card;
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
int reg = mc->reg;
|
||||
@ -2760,7 +2800,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
int ret = 0;
|
||||
|
||||
if (snd_soc_volsw_is_stereo(mc))
|
||||
dev_warn(codec->dapm.dev,
|
||||
dev_warn(dapm->dev,
|
||||
"ASoC: Control '%s' is stereo, which is not supported\n",
|
||||
kcontrol->id.name);
|
||||
|
||||
@ -2778,7 +2818,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
mask = mask << shift;
|
||||
val = val << shift;
|
||||
|
||||
reg_change = snd_soc_test_bits(codec, reg, mask, val);
|
||||
reg_change = soc_dapm_test_bits(dapm, reg, mask, val);
|
||||
}
|
||||
|
||||
if (change || reg_change) {
|
||||
@ -2817,12 +2857,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
|
||||
int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned int reg_val, val;
|
||||
int ret = 0;
|
||||
|
||||
if (e->reg != SND_SOC_NOPM)
|
||||
reg_val = snd_soc_read(codec, e->reg);
|
||||
ret = soc_dapm_read(dapm, e->reg, ®_val);
|
||||
else
|
||||
reg_val = dapm_kcontrol_get_value(kcontrol);
|
||||
|
||||
@ -2834,7 +2875,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
|
||||
ucontrol->value.enumerated.item[1] = val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
|
||||
|
||||
@ -2850,8 +2891,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
|
||||
int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
|
||||
struct snd_soc_card *card = dapm->card;
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
unsigned int *item = ucontrol->value.enumerated.item;
|
||||
unsigned int val, change;
|
||||
@ -2874,7 +2915,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
|
||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||
|
||||
if (e->reg != SND_SOC_NOPM)
|
||||
change = snd_soc_test_bits(codec, e->reg, mask, val);
|
||||
change = soc_dapm_test_bits(dapm, e->reg, mask, val);
|
||||
else
|
||||
change = dapm_kcontrol_set_value(kcontrol, val);
|
||||
|
||||
@ -2971,6 +3012,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
|
||||
const struct snd_soc_dapm_widget *widget)
|
||||
{
|
||||
struct snd_soc_dapm_widget *w;
|
||||
const char *prefix;
|
||||
int ret;
|
||||
|
||||
if ((w = dapm_cnew_widget(widget)) == NULL)
|
||||
@ -3011,9 +3053,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
|
||||
break;
|
||||
}
|
||||
|
||||
if (dapm->codec && dapm->codec->name_prefix)
|
||||
w->name = kasprintf(GFP_KERNEL, "%s %s",
|
||||
dapm->codec->name_prefix, widget->name);
|
||||
prefix = soc_dapm_prefix(dapm);
|
||||
if (prefix)
|
||||
w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name);
|
||||
else
|
||||
w->name = kasprintf(GFP_KERNEL, "%s", widget->name);
|
||||
|
||||
@ -3066,7 +3108,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
|
||||
|
||||
w->dapm = dapm;
|
||||
w->codec = dapm->codec;
|
||||
w->platform = dapm->platform;
|
||||
INIT_LIST_HEAD(&w->sources);
|
||||
INIT_LIST_HEAD(&w->sinks);
|
||||
INIT_LIST_HEAD(&w->list);
|
||||
@ -3173,27 +3214,15 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
if (source->driver->ops && source->driver->ops->hw_params) {
|
||||
substream.stream = SNDRV_PCM_STREAM_CAPTURE;
|
||||
ret = source->driver->ops->hw_params(&substream,
|
||||
params, source);
|
||||
if (ret != 0) {
|
||||
dev_err(source->dev,
|
||||
"ASoC: hw_params() failed: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
substream.stream = SNDRV_PCM_STREAM_CAPTURE;
|
||||
ret = soc_dai_hw_params(&substream, params, source);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (sink->driver->ops && sink->driver->ops->hw_params) {
|
||||
substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
ret = sink->driver->ops->hw_params(&substream, params,
|
||||
sink);
|
||||
if (ret != 0) {
|
||||
dev_err(sink->dev,
|
||||
"ASoC: hw_params() failed: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
|
||||
ret = soc_dai_hw_params(&substream, params, sink);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case SND_SOC_DAPM_POST_PMU:
|
||||
@ -3365,25 +3394,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
|
||||
static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = card->rtd;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dapm_widget *sink, *source;
|
||||
struct snd_soc_dai *cpu_dai, *codec_dai;
|
||||
int i;
|
||||
|
||||
/* for each BE DAI link... */
|
||||
for (i = 0; i < card->num_rtd; i++) {
|
||||
rtd = &card->rtd[i];
|
||||
cpu_dai = rtd->cpu_dai;
|
||||
codec_dai = rtd->codec_dai;
|
||||
|
||||
/*
|
||||
* dynamic FE links have no fixed DAI mapping.
|
||||
* CODEC<->CODEC links have no direct connection.
|
||||
*/
|
||||
if (rtd->dai_link->dynamic || rtd->dai_link->params)
|
||||
continue;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
|
||||
|
||||
/* there is no point in connecting BE DAI links with dummies */
|
||||
if (snd_soc_dai_is_dummy(codec_dai) ||
|
||||
@ -3395,8 +3414,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
|
||||
source = cpu_dai->playback_widget;
|
||||
sink = codec_dai->playback_widget;
|
||||
dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
|
||||
cpu_dai->codec->name, source->name,
|
||||
codec_dai->platform->name, sink->name);
|
||||
cpu_dai->component->name, source->name,
|
||||
codec_dai->component->name, sink->name);
|
||||
|
||||
snd_soc_dapm_add_path(&card->dapm, source, sink,
|
||||
NULL, NULL);
|
||||
@ -3407,8 +3426,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
|
||||
source = codec_dai->capture_widget;
|
||||
sink = cpu_dai->capture_widget;
|
||||
dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
|
||||
codec_dai->codec->name, source->name,
|
||||
cpu_dai->platform->name, sink->name);
|
||||
codec_dai->component->name, source->name,
|
||||
cpu_dai->component->name, sink->name);
|
||||
|
||||
snd_soc_dapm_add_path(&card->dapm, source, sink,
|
||||
NULL, NULL);
|
||||
@ -3445,11 +3464,34 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
|
||||
}
|
||||
}
|
||||
|
||||
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = card->rtd;
|
||||
int i;
|
||||
|
||||
/* for each BE DAI link... */
|
||||
for (i = 0; i < card->num_rtd; i++) {
|
||||
rtd = &card->rtd[i];
|
||||
|
||||
/*
|
||||
* dynamic FE links have no fixed DAI mapping.
|
||||
* CODEC<->CODEC links have no direct connection.
|
||||
*/
|
||||
if (rtd->dai_link->dynamic || rtd->dai_link->params)
|
||||
continue;
|
||||
|
||||
dapm_connect_dai_link_widgets(card, rtd);
|
||||
}
|
||||
}
|
||||
|
||||
static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
|
||||
int event)
|
||||
{
|
||||
int i;
|
||||
|
||||
soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event);
|
||||
soc_dapm_dai_stream_event(rtd->codec_dai, stream, event);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event);
|
||||
|
||||
dapm_power_widgets(rtd->card, event);
|
||||
}
|
||||
@ -3758,36 +3800,31 @@ static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins
|
||||
* @codec: The codec whose pins should be processed
|
||||
* snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins
|
||||
* @card: The card whose pins should be processed
|
||||
*
|
||||
* Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec
|
||||
* which are unused. Pins are used if they are connected externally to the
|
||||
* codec, whether that be to some other device, or a loop-back connection to
|
||||
* the codec itself.
|
||||
* Automatically call snd_soc_dapm_nc_pin() for any external pins in the card
|
||||
* which are unused. Pins are used if they are connected externally to a
|
||||
* component, whether that be to some other device, or a loop-back connection to
|
||||
* the component itself.
|
||||
*/
|
||||
void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
|
||||
void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_dapm_widget *w;
|
||||
|
||||
dev_dbg(codec->dev, "ASoC: Auto NC: DAPMs: card:%p codec:%p\n",
|
||||
&card->dapm, &codec->dapm);
|
||||
dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm);
|
||||
|
||||
list_for_each_entry(w, &card->widgets, list) {
|
||||
if (w->dapm != dapm)
|
||||
continue;
|
||||
switch (w->id) {
|
||||
case snd_soc_dapm_input:
|
||||
case snd_soc_dapm_output:
|
||||
case snd_soc_dapm_micbias:
|
||||
dev_dbg(codec->dev, "ASoC: Auto NC: Checking widget %s\n",
|
||||
dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n",
|
||||
w->name);
|
||||
if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
|
||||
dev_dbg(codec->dev,
|
||||
dev_dbg(card->dev,
|
||||
"... Not in map; disabling\n");
|
||||
snd_soc_dapm_nc_pin(dapm, w->name);
|
||||
snd_soc_dapm_nc_pin(w->dapm, w->name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -43,7 +43,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
|
||||
INIT_LIST_HEAD(&jack->jack_zones);
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
|
||||
|
||||
return snd_jack_new(codec->card->snd_card, id, type, &jack->jack);
|
||||
return snd_jack_new(codec->component.card->snd_card, id, type, &jack->jack);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_jack_new);
|
||||
|
||||
@ -260,7 +260,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
|
||||
static irqreturn_t gpio_handler(int irq, void *data)
|
||||
{
|
||||
struct snd_soc_jack_gpio *gpio = data;
|
||||
struct device *dev = gpio->jack->codec->card->dev;
|
||||
struct device *dev = gpio->jack->codec->component.card->dev;
|
||||
|
||||
trace_snd_soc_jack_irq(gpio->name);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (C) 2010 Texas Instruments Inc.
|
||||
*
|
||||
* Authors: Liam Girdwood <lrg@ti.com>
|
||||
* Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
* 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
|
||||
@ -47,22 +47,26 @@
|
||||
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
|
||||
{
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&rtd->pcm_mutex);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
cpu_dai->playback_active++;
|
||||
codec_dai->playback_active++;
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
rtd->codec_dais[i]->playback_active++;
|
||||
} else {
|
||||
cpu_dai->capture_active++;
|
||||
codec_dai->capture_active++;
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
rtd->codec_dais[i]->capture_active++;
|
||||
}
|
||||
|
||||
cpu_dai->active++;
|
||||
codec_dai->active++;
|
||||
cpu_dai->component->active++;
|
||||
codec_dai->component->active++;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
rtd->codec_dais[i]->active++;
|
||||
rtd->codec_dais[i]->component->active++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,22 +82,26 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
|
||||
void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
|
||||
{
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&rtd->pcm_mutex);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
cpu_dai->playback_active--;
|
||||
codec_dai->playback_active--;
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
rtd->codec_dais[i]->playback_active--;
|
||||
} else {
|
||||
cpu_dai->capture_active--;
|
||||
codec_dai->capture_active--;
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
rtd->codec_dais[i]->capture_active--;
|
||||
}
|
||||
|
||||
cpu_dai->active--;
|
||||
codec_dai->active--;
|
||||
cpu_dai->component->active--;
|
||||
codec_dai->component->active--;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
rtd->codec_dais[i]->component->active--;
|
||||
rtd->codec_dais[i]->active--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,11 +115,16 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
|
||||
*/
|
||||
bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
int i;
|
||||
bool ignore = true;
|
||||
|
||||
if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
|
||||
return true;
|
||||
|
||||
return rtd->cpu_dai->component->ignore_pmdown_time &&
|
||||
rtd->codec_dai->component->ignore_pmdown_time;
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
ignore &= rtd->codec_dais[i]->component->ignore_pmdown_time;
|
||||
|
||||
return rtd->cpu_dai->component->ignore_pmdown_time && ignore;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -222,8 +235,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
unsigned int rate, channels, sample_bits, symmetry;
|
||||
unsigned int rate, channels, sample_bits, symmetry, i;
|
||||
|
||||
rate = params_rate(params);
|
||||
channels = params_channels(params);
|
||||
@ -231,8 +243,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
|
||||
|
||||
/* reject unmatched parameters when applying symmetry */
|
||||
symmetry = cpu_dai->driver->symmetric_rates ||
|
||||
codec_dai->driver->symmetric_rates ||
|
||||
rtd->dai_link->symmetric_rates;
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
symmetry |= rtd->codec_dais[i]->driver->symmetric_rates;
|
||||
|
||||
if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) {
|
||||
dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
|
||||
cpu_dai->rate, rate);
|
||||
@ -240,8 +255,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
symmetry = cpu_dai->driver->symmetric_channels ||
|
||||
codec_dai->driver->symmetric_channels ||
|
||||
rtd->dai_link->symmetric_channels;
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
symmetry |= rtd->codec_dais[i]->driver->symmetric_channels;
|
||||
|
||||
if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) {
|
||||
dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
|
||||
cpu_dai->channels, channels);
|
||||
@ -249,8 +267,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
symmetry = cpu_dai->driver->symmetric_samplebits ||
|
||||
codec_dai->driver->symmetric_samplebits ||
|
||||
rtd->dai_link->symmetric_samplebits;
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
symmetry |= rtd->codec_dais[i]->driver->symmetric_samplebits;
|
||||
|
||||
if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) {
|
||||
dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
|
||||
cpu_dai->sample_bits, sample_bits);
|
||||
@ -264,15 +285,20 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver;
|
||||
struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver;
|
||||
struct snd_soc_dai_link *link = rtd->dai_link;
|
||||
unsigned int symmetry, i;
|
||||
|
||||
return cpu_driver->symmetric_rates || codec_driver->symmetric_rates ||
|
||||
link->symmetric_rates || cpu_driver->symmetric_channels ||
|
||||
codec_driver->symmetric_channels || link->symmetric_channels ||
|
||||
cpu_driver->symmetric_samplebits ||
|
||||
codec_driver->symmetric_samplebits ||
|
||||
link->symmetric_samplebits;
|
||||
symmetry = cpu_driver->symmetric_rates || link->symmetric_rates ||
|
||||
cpu_driver->symmetric_channels || link->symmetric_channels ||
|
||||
cpu_driver->symmetric_samplebits || link->symmetric_samplebits;
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
symmetry = symmetry ||
|
||||
rtd->codec_dais[i]->driver->symmetric_rates ||
|
||||
rtd->codec_dais[i]->driver->symmetric_channels ||
|
||||
rtd->codec_dais[i]->driver->symmetric_samplebits;
|
||||
|
||||
return symmetry;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -284,15 +310,10 @@ static int sample_sizes[] = {
|
||||
24, 32,
|
||||
};
|
||||
|
||||
static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits)
|
||||
{
|
||||
int ret, i, bits;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
bits = dai->driver->playback.sig_bits;
|
||||
else
|
||||
bits = dai->driver->capture.sig_bits;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
int ret, i;
|
||||
|
||||
if (!bits)
|
||||
return;
|
||||
@ -304,38 +325,105 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
|
||||
ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
|
||||
sample_sizes[i], bits);
|
||||
if (ret != 0)
|
||||
dev_warn(dai->dev,
|
||||
dev_warn(rtd->dev,
|
||||
"ASoC: Failed to set MSB %d/%d: %d\n",
|
||||
bits, sample_sizes[i], ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
|
||||
struct snd_soc_pcm_stream *codec_stream,
|
||||
struct snd_soc_pcm_stream *cpu_stream)
|
||||
static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i;
|
||||
unsigned int bits = 0, cpu_bits;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->playback.sig_bits == 0) {
|
||||
bits = 0;
|
||||
break;
|
||||
}
|
||||
bits = max(codec_dai->driver->playback.sig_bits, bits);
|
||||
}
|
||||
cpu_bits = cpu_dai->driver->playback.sig_bits;
|
||||
} else {
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->playback.sig_bits == 0) {
|
||||
bits = 0;
|
||||
break;
|
||||
}
|
||||
bits = max(codec_dai->driver->capture.sig_bits, bits);
|
||||
}
|
||||
cpu_bits = cpu_dai->driver->capture.sig_bits;
|
||||
}
|
||||
|
||||
soc_pcm_set_msb(substream, bits);
|
||||
soc_pcm_set_msb(substream, cpu_bits);
|
||||
}
|
||||
|
||||
static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_pcm_hardware *hw = &runtime->hw;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver;
|
||||
struct snd_soc_dai_driver *codec_dai_drv;
|
||||
struct snd_soc_pcm_stream *codec_stream;
|
||||
struct snd_soc_pcm_stream *cpu_stream;
|
||||
unsigned int chan_min = 0, chan_max = UINT_MAX;
|
||||
unsigned int rate_min = 0, rate_max = UINT_MAX;
|
||||
unsigned int rates = UINT_MAX;
|
||||
u64 formats = ULLONG_MAX;
|
||||
int i;
|
||||
|
||||
hw->channels_min = max(codec_stream->channels_min,
|
||||
cpu_stream->channels_min);
|
||||
hw->channels_max = min(codec_stream->channels_max,
|
||||
cpu_stream->channels_max);
|
||||
if (hw->formats)
|
||||
hw->formats &= codec_stream->formats & cpu_stream->formats;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
cpu_stream = &cpu_dai_drv->playback;
|
||||
else
|
||||
hw->formats = codec_stream->formats & cpu_stream->formats;
|
||||
hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates,
|
||||
cpu_stream->rates);
|
||||
cpu_stream = &cpu_dai_drv->capture;
|
||||
|
||||
hw->rate_min = 0;
|
||||
hw->rate_max = UINT_MAX;
|
||||
/* first calculate min/max only for CODECs in the DAI link */
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai_drv = rtd->codec_dais[i]->driver;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
codec_stream = &codec_dai_drv->playback;
|
||||
else
|
||||
codec_stream = &codec_dai_drv->capture;
|
||||
chan_min = max(chan_min, codec_stream->channels_min);
|
||||
chan_max = min(chan_max, codec_stream->channels_max);
|
||||
rate_min = max(rate_min, codec_stream->rate_min);
|
||||
rate_max = min_not_zero(rate_max, codec_stream->rate_max);
|
||||
formats &= codec_stream->formats;
|
||||
rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
|
||||
}
|
||||
|
||||
/*
|
||||
* chan min/max cannot be enforced if there are multiple CODEC DAIs
|
||||
* connected to a single CPU DAI, use CPU DAI's directly and let
|
||||
* channel allocation be fixed up later
|
||||
*/
|
||||
if (rtd->num_codecs > 1) {
|
||||
chan_min = cpu_stream->channels_min;
|
||||
chan_max = cpu_stream->channels_max;
|
||||
}
|
||||
|
||||
hw->channels_min = max(chan_min, cpu_stream->channels_min);
|
||||
hw->channels_max = min(chan_max, cpu_stream->channels_max);
|
||||
if (hw->formats)
|
||||
hw->formats &= formats & cpu_stream->formats;
|
||||
else
|
||||
hw->formats = formats & cpu_stream->formats;
|
||||
hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates);
|
||||
|
||||
snd_pcm_limit_hw_rates(runtime);
|
||||
|
||||
hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
|
||||
hw->rate_min = max(hw->rate_min, codec_stream->rate_min);
|
||||
hw->rate_min = max(hw->rate_min, rate_min);
|
||||
hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
|
||||
hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max);
|
||||
hw->rate_max = min_not_zero(hw->rate_max, rate_max);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -349,15 +437,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
|
||||
struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
|
||||
int ret = 0;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
const char *codec_dai_name = "multicodec";
|
||||
int i, ret = 0;
|
||||
|
||||
pinctrl_pm_select_default_state(cpu_dai->dev);
|
||||
pinctrl_pm_select_default_state(codec_dai->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
pinctrl_pm_select_default_state(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_get_sync(cpu_dai->dev);
|
||||
pm_runtime_get_sync(codec_dai->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
pm_runtime_get_sync(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_get_sync(platform->dev);
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
@ -376,18 +465,28 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
|
||||
ret = platform->driver->ops->open(substream);
|
||||
if (ret < 0) {
|
||||
dev_err(platform->dev, "ASoC: can't open platform"
|
||||
" %s: %d\n", platform->name, ret);
|
||||
" %s: %d\n", platform->component.name, ret);
|
||||
goto platform_err;
|
||||
}
|
||||
}
|
||||
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
|
||||
ret = codec_dai->driver->ops->startup(substream, codec_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(codec_dai->dev, "ASoC: can't open codec"
|
||||
" %s: %d\n", codec_dai->name, ret);
|
||||
goto codec_dai_err;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
|
||||
ret = codec_dai->driver->ops->startup(substream,
|
||||
codec_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(codec_dai->dev,
|
||||
"ASoC: can't open codec %s: %d\n",
|
||||
codec_dai->name, ret);
|
||||
goto codec_dai_err;
|
||||
}
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
codec_dai->tx_mask = 0;
|
||||
else
|
||||
codec_dai->rx_mask = 0;
|
||||
}
|
||||
|
||||
if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
|
||||
@ -404,13 +503,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
|
||||
goto dynamic;
|
||||
|
||||
/* Check that the codec and cpu DAIs are compatible */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback,
|
||||
&cpu_dai_drv->playback);
|
||||
} else {
|
||||
soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture,
|
||||
&cpu_dai_drv->capture);
|
||||
}
|
||||
soc_pcm_init_runtime_hw(substream);
|
||||
|
||||
if (rtd->num_codecs == 1)
|
||||
codec_dai_name = rtd->codec_dai->name;
|
||||
|
||||
if (soc_pcm_has_symmetry(substream))
|
||||
runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
|
||||
@ -418,23 +514,22 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
|
||||
ret = -EINVAL;
|
||||
if (!runtime->hw.rates) {
|
||||
printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
|
||||
codec_dai->name, cpu_dai->name);
|
||||
codec_dai_name, cpu_dai->name);
|
||||
goto config_err;
|
||||
}
|
||||
if (!runtime->hw.formats) {
|
||||
printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n",
|
||||
codec_dai->name, cpu_dai->name);
|
||||
codec_dai_name, cpu_dai->name);
|
||||
goto config_err;
|
||||
}
|
||||
if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
|
||||
runtime->hw.channels_min > runtime->hw.channels_max) {
|
||||
printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n",
|
||||
codec_dai->name, cpu_dai->name);
|
||||
codec_dai_name, cpu_dai->name);
|
||||
goto config_err;
|
||||
}
|
||||
|
||||
soc_pcm_apply_msb(substream, codec_dai);
|
||||
soc_pcm_apply_msb(substream, cpu_dai);
|
||||
soc_pcm_apply_msb(substream);
|
||||
|
||||
/* Symmetry only applies if we've already got an active stream. */
|
||||
if (cpu_dai->active) {
|
||||
@ -443,14 +538,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
|
||||
goto config_err;
|
||||
}
|
||||
|
||||
if (codec_dai->active) {
|
||||
ret = soc_pcm_apply_symmetry(substream, codec_dai);
|
||||
if (ret != 0)
|
||||
goto config_err;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
if (rtd->codec_dais[i]->active) {
|
||||
ret = soc_pcm_apply_symmetry(substream,
|
||||
rtd->codec_dais[i]);
|
||||
if (ret != 0)
|
||||
goto config_err;
|
||||
}
|
||||
}
|
||||
|
||||
pr_debug("ASoC: %s <-> %s info:\n",
|
||||
codec_dai->name, cpu_dai->name);
|
||||
codec_dai_name, cpu_dai->name);
|
||||
pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates);
|
||||
pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min,
|
||||
runtime->hw.channels_max);
|
||||
@ -469,10 +567,15 @@ config_err:
|
||||
rtd->dai_link->ops->shutdown(substream);
|
||||
|
||||
machine_err:
|
||||
if (codec_dai->driver->ops->shutdown)
|
||||
codec_dai->driver->ops->shutdown(substream, codec_dai);
|
||||
i = rtd->num_codecs;
|
||||
|
||||
codec_dai_err:
|
||||
while (--i >= 0) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops->shutdown)
|
||||
codec_dai->driver->ops->shutdown(substream, codec_dai);
|
||||
}
|
||||
|
||||
if (platform->driver->ops && platform->driver->ops->close)
|
||||
platform->driver->ops->close(substream);
|
||||
|
||||
@ -483,10 +586,13 @@ out:
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
|
||||
pm_runtime_put(platform->dev);
|
||||
pm_runtime_put(codec_dai->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
pm_runtime_put(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_put(cpu_dai->dev);
|
||||
if (!codec_dai->active)
|
||||
pinctrl_pm_select_sleep_state(codec_dai->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
if (!rtd->codec_dais[i]->active)
|
||||
pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
|
||||
}
|
||||
if (!cpu_dai->active)
|
||||
pinctrl_pm_select_sleep_state(cpu_dai->dev);
|
||||
|
||||
@ -502,7 +608,7 @@ static void close_delayed_work(struct work_struct *work)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd =
|
||||
container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
||||
@ -531,7 +637,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i;
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
||||
@ -541,14 +648,20 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
|
||||
if (!cpu_dai->active)
|
||||
cpu_dai->rate = 0;
|
||||
|
||||
if (!codec_dai->active)
|
||||
codec_dai->rate = 0;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (!codec_dai->active)
|
||||
codec_dai->rate = 0;
|
||||
}
|
||||
|
||||
if (cpu_dai->driver->ops->shutdown)
|
||||
cpu_dai->driver->ops->shutdown(substream, cpu_dai);
|
||||
|
||||
if (codec_dai->driver->ops->shutdown)
|
||||
codec_dai->driver->ops->shutdown(substream, codec_dai);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops->shutdown)
|
||||
codec_dai->driver->ops->shutdown(substream, codec_dai);
|
||||
}
|
||||
|
||||
if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
|
||||
rtd->dai_link->ops->shutdown(substream);
|
||||
@ -578,10 +691,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
|
||||
pm_runtime_put(platform->dev);
|
||||
pm_runtime_put(codec_dai->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
pm_runtime_put(rtd->codec_dais[i]->dev);
|
||||
pm_runtime_put(cpu_dai->dev);
|
||||
if (!codec_dai->active)
|
||||
pinctrl_pm_select_sleep_state(codec_dai->dev);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
if (!rtd->codec_dais[i]->active)
|
||||
pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
|
||||
}
|
||||
if (!cpu_dai->active)
|
||||
pinctrl_pm_select_sleep_state(cpu_dai->dev);
|
||||
|
||||
@ -598,8 +714,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret = 0;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i, ret = 0;
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
||||
@ -621,12 +737,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
}
|
||||
}
|
||||
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
|
||||
ret = codec_dai->driver->ops->prepare(substream, codec_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
|
||||
ret = codec_dai->driver->ops->prepare(substream,
|
||||
codec_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(codec_dai->dev,
|
||||
"ASoC: DAI prepare error: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -649,13 +769,44 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
snd_soc_dapm_stream_event(rtd, substream->stream,
|
||||
SND_SOC_DAPM_STREAM_START);
|
||||
|
||||
snd_soc_dai_digital_mute(codec_dai, 0, substream->stream);
|
||||
for (i = 0; i < rtd->num_codecs; i++)
|
||||
snd_soc_dai_digital_mute(rtd->codec_dais[i], 0,
|
||||
substream->stream);
|
||||
|
||||
out:
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params,
|
||||
unsigned int mask)
|
||||
{
|
||||
struct snd_interval *interval;
|
||||
int channels = hweight_long(mask);
|
||||
|
||||
interval = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
interval->min = channels;
|
||||
interval->max = channels;
|
||||
}
|
||||
|
||||
int soc_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dai->driver->ops && dai->driver->ops->hw_params) {
|
||||
ret = dai->driver->ops->hw_params(substream, params, dai);
|
||||
if (ret < 0) {
|
||||
dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n",
|
||||
dai->name, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by ALSA when the hardware params are set by application. This
|
||||
* function can also be called multiple times and can allocate buffers
|
||||
@ -667,8 +818,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret = 0;
|
||||
int i, ret = 0;
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
||||
@ -685,29 +835,40 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
}
|
||||
}
|
||||
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) {
|
||||
ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(codec_dai->dev, "ASoC: can't set %s hw params:"
|
||||
" %d\n", codec_dai->name, ret);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
|
||||
struct snd_pcm_hw_params codec_params;
|
||||
|
||||
/* copy params for each codec */
|
||||
codec_params = *params;
|
||||
|
||||
/* fixup params based on TDM slot masks */
|
||||
if (codec_dai->tx_mask)
|
||||
soc_pcm_codec_params_fixup(&codec_params,
|
||||
codec_dai->tx_mask);
|
||||
if (codec_dai->rx_mask)
|
||||
soc_pcm_codec_params_fixup(&codec_params,
|
||||
codec_dai->rx_mask);
|
||||
|
||||
ret = soc_dai_hw_params(substream, &codec_params, codec_dai);
|
||||
if(ret < 0)
|
||||
goto codec_err;
|
||||
}
|
||||
|
||||
codec_dai->rate = params_rate(&codec_params);
|
||||
codec_dai->channels = params_channels(&codec_params);
|
||||
codec_dai->sample_bits = snd_pcm_format_physical_width(
|
||||
params_format(&codec_params));
|
||||
}
|
||||
|
||||
if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) {
|
||||
ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
|
||||
if (ret < 0) {
|
||||
dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n",
|
||||
cpu_dai->name, ret);
|
||||
goto interface_err;
|
||||
}
|
||||
}
|
||||
ret = soc_dai_hw_params(substream, params, cpu_dai);
|
||||
if (ret < 0)
|
||||
goto interface_err;
|
||||
|
||||
if (platform->driver->ops && platform->driver->ops->hw_params) {
|
||||
ret = platform->driver->ops->hw_params(substream, params);
|
||||
if (ret < 0) {
|
||||
dev_err(platform->dev, "ASoC: %s hw params failed: %d\n",
|
||||
platform->name, ret);
|
||||
platform->component.name, ret);
|
||||
goto platform_err;
|
||||
}
|
||||
}
|
||||
@ -718,11 +879,6 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
cpu_dai->sample_bits =
|
||||
snd_pcm_format_physical_width(params_format(params));
|
||||
|
||||
codec_dai->rate = params_rate(params);
|
||||
codec_dai->channels = params_channels(params);
|
||||
codec_dai->sample_bits =
|
||||
snd_pcm_format_physical_width(params_format(params));
|
||||
|
||||
out:
|
||||
mutex_unlock(&rtd->pcm_mutex);
|
||||
return ret;
|
||||
@ -732,10 +888,16 @@ platform_err:
|
||||
cpu_dai->driver->ops->hw_free(substream, cpu_dai);
|
||||
|
||||
interface_err:
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
|
||||
codec_dai->driver->ops->hw_free(substream, codec_dai);
|
||||
i = rtd->num_codecs;
|
||||
|
||||
codec_err:
|
||||
while (--i >= 0) {
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
|
||||
codec_dai->driver->ops->hw_free(substream, codec_dai);
|
||||
codec_dai->rate = 0;
|
||||
}
|
||||
|
||||
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
|
||||
rtd->dai_link->ops->hw_free(substream);
|
||||
|
||||
@ -751,8 +913,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
int i;
|
||||
|
||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||
|
||||
@ -763,16 +926,22 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
cpu_dai->sample_bits = 0;
|
||||
}
|
||||
|
||||
if (codec_dai->active == 1) {
|
||||
codec_dai->rate = 0;
|
||||
codec_dai->channels = 0;
|
||||
codec_dai->sample_bits = 0;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->active == 1) {
|
||||
codec_dai->rate = 0;
|
||||
codec_dai->channels = 0;
|
||||
codec_dai->sample_bits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply codec digital mute */
|
||||
if ((playback && codec_dai->playback_active == 1) ||
|
||||
(!playback && codec_dai->capture_active == 1))
|
||||
snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
if ((playback && rtd->codec_dais[i]->playback_active == 1) ||
|
||||
(!playback && rtd->codec_dais[i]->capture_active == 1))
|
||||
snd_soc_dai_digital_mute(rtd->codec_dais[i], 1,
|
||||
substream->stream);
|
||||
}
|
||||
|
||||
/* free any machine hw params */
|
||||
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
|
||||
@ -783,8 +952,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
platform->driver->ops->hw_free(substream);
|
||||
|
||||
/* now free hw params for the DAIs */
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
|
||||
codec_dai->driver->ops->hw_free(substream, codec_dai);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
|
||||
codec_dai->driver->ops->hw_free(substream, codec_dai);
|
||||
}
|
||||
|
||||
if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
|
||||
cpu_dai->driver->ops->hw_free(substream, cpu_dai);
|
||||
@ -798,13 +970,17 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i, ret;
|
||||
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) {
|
||||
ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) {
|
||||
ret = codec_dai->driver->ops->trigger(substream,
|
||||
cmd, codec_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (platform->driver->ops && platform->driver->ops->trigger) {
|
||||
@ -834,14 +1010,18 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
int ret;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i, ret;
|
||||
|
||||
if (codec_dai->driver->ops &&
|
||||
codec_dai->driver->ops->bespoke_trigger) {
|
||||
ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops &&
|
||||
codec_dai->driver->ops->bespoke_trigger) {
|
||||
ret = codec_dai->driver->ops->bespoke_trigger(substream,
|
||||
cmd, codec_dai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (platform->driver->bespoke_trigger) {
|
||||
@ -867,10 +1047,12 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_uframes_t offset = 0;
|
||||
snd_pcm_sframes_t delay = 0;
|
||||
snd_pcm_sframes_t codec_delay = 0;
|
||||
int i;
|
||||
|
||||
if (platform->driver->ops && platform->driver->ops->pointer)
|
||||
offset = platform->driver->ops->pointer(substream);
|
||||
@ -878,11 +1060,21 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
|
||||
delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
|
||||
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->delay)
|
||||
delay += codec_dai->driver->ops->delay(substream, codec_dai);
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->ops && codec_dai->driver->ops->delay)
|
||||
codec_delay = max(codec_delay,
|
||||
codec_dai->driver->ops->delay(substream,
|
||||
codec_dai));
|
||||
}
|
||||
delay += codec_delay;
|
||||
|
||||
/*
|
||||
* None of the existing platform drivers implement delay(), so
|
||||
* for now the codec_dai of first multicodec entry is used
|
||||
*/
|
||||
if (platform->driver->delay)
|
||||
delay += platform->driver->delay(substream, codec_dai);
|
||||
delay += platform->driver->delay(substream, rtd->codec_dais[0]);
|
||||
|
||||
runtime->delay = delay;
|
||||
|
||||
@ -985,7 +1177,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
|
||||
struct snd_soc_dapm_widget *widget, int stream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *be;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
for (i = 0; i < card->num_links; i++) {
|
||||
@ -994,9 +1186,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
|
||||
if (!be->dai_link->no_pcm)
|
||||
continue;
|
||||
|
||||
if (be->cpu_dai->playback_widget == widget ||
|
||||
be->codec_dai->playback_widget == widget)
|
||||
if (be->cpu_dai->playback_widget == widget)
|
||||
return be;
|
||||
|
||||
for (j = 0; j < be->num_codecs; j++) {
|
||||
struct snd_soc_dai *dai = be->codec_dais[j];
|
||||
if (dai->playback_widget == widget)
|
||||
return be;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -1006,9 +1203,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
|
||||
if (!be->dai_link->no_pcm)
|
||||
continue;
|
||||
|
||||
if (be->cpu_dai->capture_widget == widget ||
|
||||
be->codec_dai->capture_widget == widget)
|
||||
if (be->cpu_dai->capture_widget == widget)
|
||||
return be;
|
||||
|
||||
for (j = 0; j < be->num_codecs; j++) {
|
||||
struct snd_soc_dai *dai = be->codec_dais[j];
|
||||
if (dai->capture_widget == widget)
|
||||
return be;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1071,6 +1273,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
|
||||
|
||||
/* Destroy any old FE <--> BE connections */
|
||||
list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
|
||||
unsigned int i;
|
||||
|
||||
/* is there a valid CPU DAI widget for this BE */
|
||||
widget = dai_get_widget(dpcm->be->cpu_dai, stream);
|
||||
@ -1080,11 +1283,14 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
|
||||
continue;
|
||||
|
||||
/* is there a valid CODEC DAI widget for this BE */
|
||||
widget = dai_get_widget(dpcm->be->codec_dai, stream);
|
||||
for (i = 0; i < dpcm->be->num_codecs; i++) {
|
||||
struct snd_soc_dai *dai = dpcm->be->codec_dais[i];
|
||||
widget = dai_get_widget(dai, stream);
|
||||
|
||||
/* prune the BE if it's no longer in our active list */
|
||||
if (widget && widget_in_list(list, widget))
|
||||
continue;
|
||||
/* prune the BE if it's no longer in our active list */
|
||||
if (widget && widget_in_list(list, widget))
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n",
|
||||
stream ? "capture" : "playback",
|
||||
@ -2114,16 +2320,22 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
|
||||
list_for_each_entry(dpcm, clients, list_be) {
|
||||
|
||||
struct snd_soc_pcm_runtime *be = dpcm->be;
|
||||
struct snd_soc_dai *dai = be->codec_dai;
|
||||
struct snd_soc_dai_driver *drv = dai->driver;
|
||||
int i;
|
||||
|
||||
if (be->dai_link->ignore_suspend)
|
||||
continue;
|
||||
|
||||
dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name);
|
||||
for (i = 0; i < be->num_codecs; i++) {
|
||||
struct snd_soc_dai *dai = be->codec_dais[i];
|
||||
struct snd_soc_dai_driver *drv = dai->driver;
|
||||
|
||||
if (drv->ops && drv->ops->digital_mute && dai->playback_active)
|
||||
drv->ops->digital_mute(dai, mute);
|
||||
dev_dbg(be->dev, "ASoC: BE digital mute %s\n",
|
||||
be->dai_link->name);
|
||||
|
||||
if (drv->ops && drv->ops->digital_mute &&
|
||||
dai->playback_active)
|
||||
drv->ops->digital_mute(dai, mute);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2188,22 +2400,27 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
|
||||
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
{
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
struct snd_pcm *pcm;
|
||||
char new_name[64];
|
||||
int ret = 0, playback = 0, capture = 0;
|
||||
int i;
|
||||
|
||||
if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
|
||||
playback = rtd->dai_link->dpcm_playback;
|
||||
capture = rtd->dai_link->dpcm_capture;
|
||||
} else {
|
||||
if (codec_dai->driver->playback.channels_min &&
|
||||
cpu_dai->driver->playback.channels_min)
|
||||
playback = 1;
|
||||
if (codec_dai->driver->capture.channels_min &&
|
||||
cpu_dai->driver->capture.channels_min)
|
||||
capture = 1;
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
if (codec_dai->driver->playback.channels_min)
|
||||
playback = 1;
|
||||
if (codec_dai->driver->capture.channels_min)
|
||||
capture = 1;
|
||||
}
|
||||
|
||||
capture = capture && cpu_dai->driver->capture.channels_min;
|
||||
playback = playback && cpu_dai->driver->playback.channels_min;
|
||||
}
|
||||
|
||||
if (rtd->dai_link->playback_only) {
|
||||
@ -2229,7 +2446,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
rtd->dai_link->stream_name);
|
||||
else
|
||||
snprintf(new_name, sizeof(new_name), "%s %s-%d",
|
||||
rtd->dai_link->stream_name, codec_dai->name, num);
|
||||
rtd->dai_link->stream_name,
|
||||
(rtd->num_codecs > 1) ?
|
||||
"multicodec" : rtd->codec_dai->name, num);
|
||||
|
||||
ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
|
||||
capture, &pcm);
|
||||
@ -2302,8 +2521,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
|
||||
|
||||
pcm->private_free = platform->driver->pcm_free;
|
||||
out:
|
||||
dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", codec_dai->name,
|
||||
cpu_dai->name);
|
||||
dev_info(rtd->card->dev, "%s <-> %s mapping ok\n",
|
||||
(rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,
|
||||
cpu_dai->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
|
||||
int srate, mclk;
|
||||
int err;
|
||||
@ -105,7 +104,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
|
||||
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card);
|
||||
|
||||
snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
|
||||
&tegra_alc5632_hs_jack);
|
||||
|
@ -49,8 +49,7 @@ static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card);
|
||||
int srate, mclk;
|
||||
int err;
|
||||
@ -127,7 +126,7 @@ static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct tegra_max98090 *machine = snd_soc_card_get_drvdata(codec->card);
|
||||
struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card);
|
||||
|
||||
if (gpio_is_valid(machine->gpio_hp_det)) {
|
||||
snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
|
||||
|
@ -51,8 +51,7 @@ static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
|
||||
int srate, mclk;
|
||||
int err;
|
||||
@ -110,7 +109,7 @@ static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(codec->card);
|
||||
struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card);
|
||||
|
||||
snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
|
||||
&tegra_rt5640_hp_jack);
|
||||
|
@ -55,8 +55,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
|
||||
int srate, mclk;
|
||||
int err;
|
||||
|
@ -60,8 +60,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
|
||||
int srate, mclk;
|
||||
int err;
|
||||
@ -173,7 +172,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
|
||||
|
||||
if (gpio_is_valid(machine->gpio_hp_det)) {
|
||||
|
@ -50,8 +50,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
struct snd_soc_codec *codec = codec_dai->codec;
|
||||
struct snd_soc_card *card = codec->card;
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
|
||||
int srate, mclk;
|
||||
int err;
|
||||
|
Loading…
Reference in New Issue
Block a user