Commit f3413783 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/omap', 'asoc/topic/rcar' and...

Merge remote-tracking branches 'asoc/topic/omap', 'asoc/topic/rcar' and 'asoc/topic/rockchip' into asoc-next
...@@ -8,6 +8,8 @@ Required properties: ...@@ -8,6 +8,8 @@ Required properties:
- interrupts: Interrupt number for McPDM - interrupts: Interrupt number for McPDM
- interrupt-parent: The parent interrupt controller - interrupt-parent: The parent interrupt controller
- ti,hwmods: Name of the hwmod associated to the McPDM - ti,hwmods: Name of the hwmod associated to the McPDM
- clocks: phandle for the pdmclk provider, likely <&twl6040>
- clock-names: Must be "pdmclk"
Example: Example:
...@@ -19,3 +21,11 @@ mcpdm: mcpdm@40132000 { ...@@ -19,3 +21,11 @@ mcpdm: mcpdm@40132000 {
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
ti,hwmods = "mcpdm"; ti,hwmods = "mcpdm";
}; };
In board DTS file the pdmclk needs to be added:
&mcpdm {
clocks = <&twl6040>;
clock-names = "pdmclk";
status = "okay";
};
...@@ -373,6 +373,8 @@ Optional properties: ...@@ -373,6 +373,8 @@ Optional properties:
- #clock-cells : it must be 0 if your system has audio_clkout - #clock-cells : it must be 0 if your system has audio_clkout
it must be 1 if your system has audio_clkout0/1/2/3 it must be 1 if your system has audio_clkout0/1/2/3
- clock-frequency : for all audio_clkout0/1/2/3 - clock-frequency : for all audio_clkout0/1/2/3
- clkout-lr-asynchronous : boolean property. it indicates that audio_clkoutn
is asynchronizes with lr-clock.
SSI subnode properties: SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer - interrupts : Should contain SSI interrupt for PIO transfer
......
...@@ -23,6 +23,11 @@ Required properties: ...@@ -23,6 +23,11 @@ Required properties:
- rockchip,playback-channels: max playback channels, if not set, 8 channels default. - rockchip,playback-channels: max playback channels, if not set, 8 channels default.
- rockchip,capture-channels: max capture channels, if not set, 2 channels default. - rockchip,capture-channels: max capture channels, if not set, 2 channels default.
Required properties for controller which support multi channels
playback/capture:
- rockchip,grf: the phandle of the syscon node for GRF register.
Example for rk3288 I2S controller: Example for rk3288 I2S controller:
i2s@ff890000 { i2s@ff890000 {
......
...@@ -13,16 +13,7 @@ ...@@ -13,16 +13,7 @@
#define __SIMPLE_CARD_H #define __SIMPLE_CARD_H
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/simple_card_utils.h>
struct asoc_simple_dai {
const char *name;
unsigned int sysclk;
int slots;
int slot_width;
unsigned int tx_slot_mask;
unsigned int rx_slot_mask;
struct clk *clk;
};
struct asoc_simple_card_info { struct asoc_simple_card_info {
const char *name; const char *name;
......
/*
* simple_card_core.h
*
* Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __SIMPLE_CARD_CORE_H
#define __SIMPLE_CARD_CORE_H
#include <sound/soc.h>
struct asoc_simple_dai {
const char *name;
unsigned int sysclk;
int slots;
int slot_width;
unsigned int tx_slot_mask;
unsigned int rx_slot_mask;
struct clk *clk;
};
int asoc_simple_card_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
char *prefix,
unsigned int *retfmt);
int asoc_simple_card_set_dailink_name(struct device *dev,
struct snd_soc_dai_link *dai_link,
const char *fmt, ...);
int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
char *prefix);
#endif /* __SIMPLE_CARD_CORE_H */
config SND_SIMPLE_CARD_UTILS
tristate
config SND_SIMPLE_CARD config SND_SIMPLE_CARD
tristate "ASoC Simple sound card support" tristate "ASoC Simple sound card support"
select SND_SIMPLE_CARD_UTILS
help help
This option enables generic simple sound card support This option enables generic simple sound card support
obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) := simple-card-utils.o
snd-soc-simple-card-objs := simple-card.o snd-soc-simple-card-objs := simple-card.o
obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
/*
* simple-card-core.c
*
* Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/of.h>
#include <sound/simple_card_utils.h>
int asoc_simple_card_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
char *prefix,
unsigned int *retfmt)
{
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
int prefix_len = prefix ? strlen(prefix) : 0;
unsigned int daifmt;
daifmt = snd_soc_of_parse_daifmt(node, prefix,
&bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
if (prefix_len && !bitclkmaster && !framemaster) {
/*
* No dai-link level and master setting was not found from
* sound node level, revert back to legacy DT parsing and
* take the settings from codec node.
*/
dev_dbg(dev, "Revert to legacy daifmt parsing\n");
daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
} else {
if (codec == bitclkmaster)
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
else
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
}
of_node_put(bitclkmaster);
of_node_put(framemaster);
*retfmt = daifmt;
return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt);
int asoc_simple_card_set_dailink_name(struct device *dev,
struct snd_soc_dai_link *dai_link,
const char *fmt, ...)
{
va_list ap;
char *name = NULL;
int ret = -ENOMEM;
va_start(ap, fmt);
name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap);
va_end(ap);
if (name) {
ret = 0;
dai_link->name = name;
dai_link->stream_name = name;
}
return ret;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name);
int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
char *prefix)
{
char prop[128];
int ret;
snprintf(prop, sizeof(prop), "%sname", prefix);
/* Parse the card name from DT */
ret = snd_soc_of_parse_card_name(card, prop);
if (ret < 0)
return ret;
if (!card->name && card->dai_link)
card->name = card->dai_link->name;
return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);
...@@ -21,6 +21,12 @@ ...@@ -21,6 +21,12 @@
#include <sound/soc-dai.h> #include <sound/soc-dai.h>
#include <sound/soc.h> #include <sound/soc.h>
struct asoc_simple_jack {
struct snd_soc_jack jack;
struct snd_soc_jack_pin pin;
struct snd_soc_jack_gpio gpio;
};
struct simple_card_data { struct simple_card_data {
struct snd_soc_card snd_card; struct snd_soc_card snd_card;
struct simple_dai_props { struct simple_dai_props {
...@@ -29,10 +35,8 @@ struct simple_card_data { ...@@ -29,10 +35,8 @@ struct simple_card_data {
unsigned int mclk_fs; unsigned int mclk_fs;
} *dai_props; } *dai_props;
unsigned int mclk_fs; unsigned int mclk_fs;
int gpio_hp_det; struct asoc_simple_jack hp_jack;
int gpio_hp_det_invert; struct asoc_simple_jack mic_jack;
int gpio_mic_det;
int gpio_mic_det_invert;
struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ struct snd_soc_dai_link dai_link[]; /* dynamically allocated */
}; };
...@@ -40,6 +44,69 @@ struct simple_card_data { ...@@ -40,6 +44,69 @@ struct simple_card_data {
#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i)
#define simple_priv_to_props(priv, i) ((priv)->dai_props + i) #define simple_priv_to_props(priv, i) ((priv)->dai_props + i)
#define PREFIX "simple-audio-card,"
#define asoc_simple_card_init_hp(card, sjack, prefix)\
asoc_simple_card_init_jack(card, sjack, 1, prefix)
#define asoc_simple_card_init_mic(card, sjack, prefix)\
asoc_simple_card_init_jack(card, sjack, 0, prefix)
static int asoc_simple_card_init_jack(struct snd_soc_card *card,
struct asoc_simple_jack *sjack,
int is_hp, char *prefix)
{
struct device *dev = card->dev;
enum of_gpio_flags flags;
char prop[128];
char *pin_name;
char *gpio_name;
int mask;
int det;
sjack->gpio.gpio = -ENOENT;
if (is_hp) {
snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
pin_name = "Headphones";
gpio_name = "Headphone detection";
mask = SND_JACK_HEADPHONE;
} else {
snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
pin_name = "Mic Jack";
gpio_name = "Mic detection";
mask = SND_JACK_MICROPHONE;
}
det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
if (det == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (gpio_is_valid(det)) {
sjack->pin.pin = pin_name;
sjack->pin.mask = mask;
sjack->gpio.name = gpio_name;
sjack->gpio.report = mask;
sjack->gpio.gpio = det;
sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
sjack->gpio.debounce_time = 150;
snd_soc_card_jack_new(card, pin_name, mask,
&sjack->jack,
&sjack->pin, 1);
snd_soc_jack_add_gpios(&sjack->jack, 1,
&sjack->gpio);
}
return 0;
}
static void asoc_simple_card_remove_jack(struct asoc_simple_jack *sjack)
{
if (gpio_is_valid(sjack->gpio.gpio))
snd_soc_jack_free_gpios(&sjack->jack, 1, &sjack->gpio);
}
static int asoc_simple_card_startup(struct snd_pcm_substream *substream) static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
...@@ -110,32 +177,6 @@ static struct snd_soc_ops asoc_simple_card_ops = { ...@@ -110,32 +177,6 @@ static struct snd_soc_ops asoc_simple_card_ops = {
.hw_params = asoc_simple_card_hw_params, .hw_params = asoc_simple_card_hw_params,
}; };
static struct snd_soc_jack simple_card_hp_jack;
static struct snd_soc_jack_pin simple_card_hp_jack_pins[] = {
{
.pin = "Headphones",
.mask = SND_JACK_HEADPHONE,
},
};
static struct snd_soc_jack_gpio simple_card_hp_jack_gpio = {
.name = "Headphone detection",
.report = SND_JACK_HEADPHONE,
.debounce_time = 150,
};
static struct snd_soc_jack simple_card_mic_jack;
static struct snd_soc_jack_pin simple_card_mic_jack_pins[] = {
{
.pin = "Mic Jack",
.mask = SND_JACK_MICROPHONE,
},
};
static struct snd_soc_jack_gpio simple_card_mic_jack_gpio = {
.name = "Mic detection",
.report = SND_JACK_MICROPHONE,
.debounce_time = 150,
};
static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
struct asoc_simple_dai *set) struct asoc_simple_dai *set)
{ {
...@@ -184,30 +225,14 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -184,30 +225,14 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (gpio_is_valid(priv->gpio_hp_det)) { ret = asoc_simple_card_init_hp(rtd->card, &priv->hp_jack, PREFIX);
snd_soc_card_jack_new(rtd->card, "Headphones", if (ret < 0)
SND_JACK_HEADPHONE, return ret;
&simple_card_hp_jack,
simple_card_hp_jack_pins, ret = asoc_simple_card_init_mic(rtd->card, &priv->hp_jack, PREFIX);
ARRAY_SIZE(simple_card_hp_jack_pins)); if (ret < 0)
return ret;
simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det;
simple_card_hp_jack_gpio.invert = priv->gpio_hp_det_invert;
snd_soc_jack_add_gpios(&simple_card_hp_jack, 1,
&simple_card_hp_jack_gpio);
}
if (gpio_is_valid(priv->gpio_mic_det)) {
snd_soc_card_jack_new(rtd->card, "Mic Jack",
SND_JACK_MICROPHONE,
&simple_card_mic_jack,
simple_card_mic_jack_pins,
ARRAY_SIZE(simple_card_mic_jack_pins));
simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det;
simple_card_mic_jack_gpio.invert = priv->gpio_mic_det_invert;
snd_soc_jack_add_gpios(&simple_card_mic_jack, 1,
&simple_card_mic_jack_gpio);
}
return 0; return 0;
} }
...@@ -223,6 +248,9 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ...@@ -223,6 +248,9 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
u32 val; u32 val;
int ret; int ret;
if (!np)
return 0;
/* /*
* Get node via "sound-dai = <&phandle port>" * Get node via "sound-dai = <&phandle port>"
* it will be used as xxx_of_node on soc_bind_dai_link() * it will be used as xxx_of_node on soc_bind_dai_link()
...@@ -238,9 +266,14 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ...@@ -238,9 +266,14 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
*args_count = args.args_count; *args_count = args.args_count;
/* Get dai->name */ /* Get dai->name */
if (name) {
ret = snd_soc_of_get_dai_name(np, name); ret = snd_soc_of_get_dai_name(np, name);
if (ret < 0) if (ret < 0)
return ret; return ret;
}
if (!dai)
return 0;
/* Parse TDM slot */ /* Parse TDM slot */
ret = snd_soc_of_parse_tdm_slot(np, &dai->tx_slot_mask, ret = snd_soc_of_parse_tdm_slot(np, &dai->tx_slot_mask,
...@@ -275,48 +308,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ...@@ -275,48 +308,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
return 0; return 0;
} }
static int asoc_simple_card_parse_daifmt(struct device_node *node,
struct simple_card_data *priv,
struct device_node *codec,
char *prefix, int idx)
{
struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
struct device *dev = simple_priv_to_dev(priv);
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
unsigned int daifmt;
daifmt = snd_soc_of_parse_daifmt(node, prefix,
&bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
if (strlen(prefix) && !bitclkmaster && !framemaster) {
/*
* No dai-link level and master setting was not found from
* sound node level, revert back to legacy DT parsing and
* take the settings from codec node.
*/
dev_dbg(dev, "Revert to legacy daifmt parsing\n");
daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
} else {
if (codec == bitclkmaster)
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
else
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
}
dai_link->dai_fmt = daifmt;
of_node_put(bitclkmaster);
of_node_put(framemaster);
return 0;
}
static int asoc_simple_card_dai_link_of(struct device_node *node, static int asoc_simple_card_dai_link_of(struct device_node *node,
struct simple_card_data *priv, struct simple_card_data *priv,
int idx, int idx,
...@@ -328,7 +319,6 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ...@@ -328,7 +319,6 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
struct device_node *cpu = NULL; struct device_node *cpu = NULL;
struct device_node *plat = NULL; struct device_node *plat = NULL;
struct device_node *codec = NULL; struct device_node *codec = NULL;
char *name;
char prop[128]; char prop[128];
char *prefix = ""; char *prefix = "";
int ret, cpu_args; int ret, cpu_args;
...@@ -336,7 +326,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ...@@ -336,7 +326,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
/* For single DAI link & old style of DT node */ /* For single DAI link & old style of DT node */
if (is_top_level_node) if (is_top_level_node)
prefix = "simple-audio-card,"; prefix = PREFIX;
snprintf(prop, sizeof(prop), "%scpu", prefix); snprintf(prop, sizeof(prop), "%scpu", prefix);
cpu = of_get_child_by_name(node, prop); cpu = of_get_child_by_name(node, prop);
...@@ -353,8 +343,8 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ...@@ -353,8 +343,8 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
goto dai_link_of_err; goto dai_link_of_err;
} }
ret = asoc_simple_card_parse_daifmt(node, priv, ret = asoc_simple_card_parse_daifmt(dev, node, codec,
codec, prefix, idx); prefix, &dai_link->dai_fmt);
if (ret < 0) if (ret < 0)
goto dai_link_of_err; goto dai_link_of_err;
...@@ -374,35 +364,28 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ...@@ -374,35 +364,28 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
if (ret < 0) if (ret < 0)
goto dai_link_of_err; goto dai_link_of_err;
ret = asoc_simple_card_sub_parse_of(plat, NULL,
&dai_link->platform_of_node,
NULL, NULL);
if (ret < 0)
goto dai_link_of_err;
if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
ret = -EINVAL; ret = -EINVAL;
goto dai_link_of_err; goto dai_link_of_err;
} }
if (plat) {
struct of_phandle_args args;
ret = of_parse_phandle_with_args(plat, "sound-dai",
"#sound-dai-cells", 0, &args);
dai_link->platform_of_node = args.np;
} else {
/* Assumes platform == cpu */ /* Assumes platform == cpu */
if (!dai_link->platform_of_node)
dai_link->platform_of_node = dai_link->cpu_of_node; dai_link->platform_of_node = dai_link->cpu_of_node;
}
/* DAI link name is created from CPU/CODEC dai name */ ret = asoc_simple_card_set_dailink_name(dev, dai_link,
name = devm_kzalloc(dev, "%s-%s",
strlen(dai_link->cpu_dai_name) + dai_link->cpu_dai_name,
strlen(dai_link->codec_dai_name) + 2, dai_link->codec_dai_name);
GFP_KERNEL); if (ret < 0)
if (!name) {
ret = -ENOMEM;
goto dai_link_of_err; goto dai_link_of_err;
}
sprintf(name, "%s-%s", dai_link->cpu_dai_name,
dai_link->codec_dai_name);
dai_link->name = dai_link->stream_name = name;
dai_link->ops = &asoc_simple_card_ops; dai_link->ops = &asoc_simple_card_ops;
dai_link->init = asoc_simple_card_dai_init; dai_link->init = asoc_simple_card_dai_init;
...@@ -438,42 +421,35 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -438,42 +421,35 @@ static int asoc_simple_card_parse_of(struct device_node *node,
struct simple_card_data *priv) struct simple_card_data *priv)
{ {
struct device *dev = simple_priv_to_dev(priv); struct device *dev = simple_priv_to_dev(priv);
enum of_gpio_flags flags;
u32 val; u32 val;
int ret; int ret;
if (!node) if (!node)
return -EINVAL; return -EINVAL;
/* Parse the card name from DT */
snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name");
/* The off-codec widgets */ /* The off-codec widgets */
if (of_property_read_bool(node, "simple-audio-card,widgets")) { if (of_property_read_bool(node, PREFIX "widgets")) {
ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card,
"simple-audio-card,widgets"); PREFIX "widgets");
if (ret) if (ret)
return ret; return ret;
} }
/* DAPM routes */ /* DAPM routes */
if (of_property_read_bool(node, "simple-audio-card,routing")) { if (of_property_read_bool(node, PREFIX "routing")) {
ret = snd_soc_of_parse_audio_routing(&priv->snd_card, ret = snd_soc_of_parse_audio_routing(&priv->snd_card,
"simple-audio-card,routing"); PREFIX "routing");
if (ret) if (ret)
return ret; return ret;
} }
/* Factor to mclk, used in hw_params() */ /* Factor to mclk, used in hw_params() */
ret = of_property_read_u32(node, "simple-audio-card,mclk-fs", &val); ret = of_property_read_u32(node, PREFIX "mclk-fs", &val);
if (ret == 0) if (ret == 0)
priv->mclk_fs = val; priv->mclk_fs = val;
dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ?
priv->snd_card.name : "");
/* Single/Muti DAI link(s) & New style of DT node */ /* Single/Muti DAI link(s) & New style of DT node */
if (of_get_child_by_name(node, "simple-audio-card,dai-link")) { if (of_get_child_by_name(node, PREFIX "dai-link")) {
struct device_node *np = NULL; struct device_node *np = NULL;
int i = 0; int i = 0;
...@@ -494,20 +470,9 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -494,20 +470,9 @@ static int asoc_simple_card_parse_of(struct device_node *node,
return ret; return ret;
} }
priv->gpio_hp_det = of_get_named_gpio_flags(node, ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
"simple-audio-card,hp-det-gpio", 0, &flags); if (ret)
priv->gpio_hp_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW); return ret;
if (priv->gpio_hp_det == -EPROBE_DEFER)
return -EPROBE_DEFER;
priv->gpio_mic_det = of_get_named_gpio_flags(node,
"simple-audio-card,mic-det-gpio", 0, &flags);
priv->gpio_mic_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW);
if (priv->gpio_mic_det == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!priv->snd_card.name)
priv->snd_card.name = priv->snd_card.dai_link->name;
return 0; return 0;
} }
...@@ -536,7 +501,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -536,7 +501,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
int num_links, ret; int num_links, ret;
/* Get the number of DAI links */ /* Get the number of DAI links */
if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) if (np && of_get_child_by_name(np, PREFIX "dai-link"))
num_links = of_get_child_count(np); num_links = of_get_child_count(np);
else else
num_links = 1; num_links = 1;
...@@ -555,9 +520,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -555,9 +520,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
priv->snd_card.dai_link = dai_link; priv->snd_card.dai_link = dai_link;
priv->snd_card.num_links = num_links; priv->snd_card.num_links = num_links;
priv->gpio_hp_det = -ENOENT;
priv->gpio_mic_det = -ENOENT;
/* Get room for the other properties */ /* Get room for the other properties */
priv->dai_props = devm_kzalloc(dev, priv->dai_props = devm_kzalloc(dev,
sizeof(*priv->dai_props) * num_links, sizeof(*priv->dai_props) * num_links,
...@@ -624,12 +586,8 @@ static int asoc_simple_card_remove(struct platform_device *pdev) ...@@ -624,12 +586,8 @@ static int asoc_simple_card_remove(struct platform_device *pdev)
struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_card *card = platform_get_drvdata(pdev);
struct simple_card_data *priv = snd_soc_card_get_drvdata(card); struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
if (gpio_is_valid(priv->gpio_hp_det)) asoc_simple_card_remove_jack(&priv->hp_jack);
snd_soc_jack_free_gpios(&simple_card_hp_jack, 1, asoc_simple_card_remove_jack(&priv->mic_jack);
&simple_card_hp_jack_gpio);
if (gpio_is_valid(priv->gpio_mic_det))
snd_soc_jack_free_gpios(&simple_card_mic_jack, 1,
&simple_card_mic_jack_gpio);
return asoc_simple_card_unref(card); return asoc_simple_card_unref(card);
} }
......
...@@ -107,6 +107,7 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040 ...@@ -107,6 +107,7 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
select SND_SOC_TWL6040 select SND_SOC_TWL6040
select SND_SOC_DMIC select SND_SOC_DMIC
select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS) select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS)
select CLK_TWL6040
help help
Say Y if you want to add support for SoC audio on OMAP boards using Say Y if you want to add support for SoC audio on OMAP boards using
ABE and twl6040 codec. This driver currently supports: ABE and twl6040 codec. This driver currently supports:
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/clk.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -54,6 +55,7 @@ struct omap_mcpdm { ...@@ -54,6 +55,7 @@ struct omap_mcpdm {
unsigned long phys_base; unsigned long phys_base;
void __iomem *io_base; void __iomem *io_base;
int irq; int irq;
struct clk *pdmclk;
struct mutex mutex; struct mutex mutex;
...@@ -66,6 +68,9 @@ struct omap_mcpdm { ...@@ -66,6 +68,9 @@ struct omap_mcpdm {
/* McPDM needs to be restarted due to runtime reconfiguration */ /* McPDM needs to be restarted due to runtime reconfiguration */
bool restart; bool restart;
/* pm state for suspend/resume handling */
int pm_active_count;
struct snd_dmaengine_dai_dma_data dma_data[2]; struct snd_dmaengine_dai_dma_data dma_data[2];
}; };
...@@ -173,6 +178,10 @@ static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm) ...@@ -173,6 +178,10 @@ static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
*/ */
static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm) static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
{ {
u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET, omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL | MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL); MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
...@@ -258,12 +267,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, ...@@ -258,12 +267,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
mutex_lock(&mcpdm->mutex); mutex_lock(&mcpdm->mutex);
if (!dai->active) { if (!dai->active)
u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
omap_mcpdm_open_streams(mcpdm); omap_mcpdm_open_streams(mcpdm);
}
mutex_unlock(&mcpdm->mutex); mutex_unlock(&mcpdm->mutex);
return 0; return 0;
...@@ -384,6 +390,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai) ...@@ -384,6 +390,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
int ret; int ret;
clk_prepare_enable(mcpdm->pdmclk);
pm_runtime_enable(mcpdm->dev); pm_runtime_enable(mcpdm->dev);
/* Disable lines while request is ongoing */ /* Disable lines while request is ongoing */
...@@ -418,8 +425,54 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai) ...@@ -418,8 +425,54 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
pm_runtime_disable(mcpdm->dev); pm_runtime_disable(mcpdm->dev);
clk_disable_unprepare(mcpdm->pdmclk);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int omap_mcpdm_suspend(struct snd_soc_dai *dai)
{
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
if (dai->active) {
omap_mcpdm_stop(mcpdm);
omap_mcpdm_close_streams(mcpdm);
}
mcpdm->pm_active_count = 0;
while (pm_runtime_active(mcpdm->dev)) {
pm_runtime_put_sync(mcpdm->dev);
mcpdm->pm_active_count++;
}
clk_disable_unprepare(mcpdm->pdmclk);
return 0;
}
static int omap_mcpdm_resume(struct snd_soc_dai *dai)
{
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
clk_prepare_enable(mcpdm->pdmclk);
if (mcpdm->pm_active_count) {
while (mcpdm->pm_active_count--)
pm_runtime_get_sync(mcpdm->dev);
if (dai->active) {
omap_mcpdm_open_streams(mcpdm);
omap_mcpdm_start(mcpdm);
}
}
return 0; return 0;
} }
#else
#define omap_mcpdm_suspend NULL
#define omap_mcpdm_resume NULL
#endif
#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) #define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define OMAP_MCPDM_FORMATS SNDRV_PCM_FMTBIT_S32_LE #define OMAP_MCPDM_FORMATS SNDRV_PCM_FMTBIT_S32_LE
...@@ -427,6 +480,8 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai) ...@@ -427,6 +480,8 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
static struct snd_soc_dai_driver omap_mcpdm_dai = { static struct snd_soc_dai_driver omap_mcpdm_dai = {
.probe = omap_mcpdm_probe, .probe = omap_mcpdm_probe,
.remove = omap_mcpdm_remove, .remove = omap_mcpdm_remove,
.suspend = omap_mcpdm_suspend,
.resume = omap_mcpdm_resume,
.probe_order = SND_SOC_COMP_ORDER_LATE, .probe_order = SND_SOC_COMP_ORDER_LATE,
.remove_order = SND_SOC_COMP_ORDER_EARLY, .remove_order = SND_SOC_COMP_ORDER_EARLY,
.playback = { .playback = {
...@@ -494,6 +549,15 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) ...@@ -494,6 +549,15 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
mcpdm->dev = &pdev->dev; mcpdm->dev = &pdev->dev;
mcpdm->pdmclk = devm_clk_get(&pdev->dev, "pdmclk");
if (IS_ERR(mcpdm->pdmclk)) {
if (PTR_ERR(mcpdm->pdmclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_warn(&pdev->dev, "Error getting pdmclk (%ld)!\n",
PTR_ERR(mcpdm->pdmclk));
mcpdm->pdmclk = NULL;
}
ret = devm_snd_soc_register_component(&pdev->dev, ret = devm_snd_soc_register_component(&pdev->dev,
&omap_mcpdm_component, &omap_mcpdm_component,
&omap_mcpdm_dai, 1); &omap_mcpdm_dai, 1);
......
...@@ -11,8 +11,10 @@ ...@@ -11,8 +11,10 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -23,6 +25,11 @@ ...@@ -23,6 +25,11 @@
#define DRV_NAME "rockchip-i2s" #define DRV_NAME "rockchip-i2s"
struct rk_i2s_pins {
u32 reg_offset;
u32 shift;
};
struct rk_i2s_dev { struct rk_i2s_dev {
struct device *dev; struct device *dev;
...@@ -33,6 +40,7 @@ struct rk_i2s_dev { ...@@ -33,6 +40,7 @@ struct rk_i2s_dev {
struct snd_dmaengine_dai_dma_data playback_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data;
struct regmap *regmap; struct regmap *regmap;
struct regmap *grf;
/* /*
* Used to indicate the tx/rx status. * Used to indicate the tx/rx status.
...@@ -42,6 +50,7 @@ struct rk_i2s_dev { ...@@ -42,6 +50,7 @@ struct rk_i2s_dev {
bool tx_start; bool tx_start;
bool rx_start; bool rx_start;
bool is_master_mode; bool is_master_mode;
const struct rk_i2s_pins *pins;
}; };
static int i2s_runtime_suspend(struct device *dev) static int i2s_runtime_suspend(struct device *dev)
...@@ -300,14 +309,38 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -300,14 +309,38 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK, I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
val); val);
if (!IS_ERR(i2s->grf) && i2s->pins) {
regmap_read(i2s->regmap, I2S_TXCR, &val);
val &= I2S_TXCR_CSR_MASK;
switch (val) {
case I2S_CHN_4:
val = I2S_IO_4CH_OUT_6CH_IN;
break;
case I2S_CHN_6:
val = I2S_IO_6CH_OUT_4CH_IN;
break;
case I2S_CHN_8:
val = I2S_IO_8CH_OUT_2CH_IN;
break;
default:
val = I2S_IO_2CH_OUT_8CH_IN;
break;
}
val <<= i2s->pins->shift;
val |= (I2S_IO_DIRECTION_MASK << i2s->pins->shift) << 16;
regmap_write(i2s->grf, i2s->pins->reg_offset, val);
}
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
I2S_DMACR_TDL(16)); I2S_DMACR_TDL(16));
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
I2S_DMACR_RDL(16)); I2S_DMACR_RDL(16));
val = I2S_CKR_TRCM_TXRX; val = I2S_CKR_TRCM_TXRX;
if (dai->driver->symmetric_rates || rtd->dai_link->symmetric_rates) if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates)
val = I2S_CKR_TRCM_TXSHARE; val = I2S_CKR_TRCM_TXONLY;
regmap_update_bits(i2s->regmap, I2S_CKR, regmap_update_bits(i2s->regmap, I2S_CKR,
I2S_CKR_TRCM_MASK, I2S_CKR_TRCM_MASK,
...@@ -485,9 +518,23 @@ static const struct regmap_config rockchip_i2s_regmap_config = { ...@@ -485,9 +518,23 @@ static const struct regmap_config rockchip_i2s_regmap_config = {
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
static const struct rk_i2s_pins rk3399_i2s_pins = {
.reg_offset = 0xe220,
.shift = 11,
};
static const struct of_device_id rockchip_i2s_match[] = {
{ .compatible = "rockchip,rk3066-i2s", },
{ .compatible = "rockchip,rk3188-i2s", },
{ .compatible = "rockchip,rk3288-i2s", },
{ .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins },
{},
};
static int rockchip_i2s_probe(struct platform_device *pdev) static int rockchip_i2s_probe(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
const struct of_device_id *of_id;
struct rk_i2s_dev *i2s; struct rk_i2s_dev *i2s;
struct snd_soc_dai_driver *soc_dai; struct snd_soc_dai_driver *soc_dai;
struct resource *res; struct resource *res;
...@@ -501,6 +548,17 @@ static int rockchip_i2s_probe(struct platform_device *pdev) ...@@ -501,6 +548,17 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
i2s->dev = &pdev->dev;
i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
if (!IS_ERR(i2s->grf)) {
of_id = of_match_device(rockchip_i2s_match, &pdev->dev);
if (!of_id || !of_id->data)
return -EINVAL;
i2s->pins = of_id->data;
}
/* try to prepare related clocks */ /* try to prepare related clocks */
i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) { if (IS_ERR(i2s->hclk)) {
...@@ -540,7 +598,6 @@ static int rockchip_i2s_probe(struct platform_device *pdev) ...@@ -540,7 +598,6 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.maxburst = 4; i2s->capture_dma_data.maxburst = 4;
i2s->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, i2s); dev_set_drvdata(&pdev->dev, i2s);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
...@@ -606,14 +663,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev) ...@@ -606,14 +663,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id rockchip_i2s_match[] = {
{ .compatible = "rockchip,rk3066-i2s", },
{ .compatible = "rockchip,rk3188-i2s", },
{ .compatible = "rockchip,rk3288-i2s", },
{ .compatible = "rockchip,rk3399-i2s", },
{},
};
static const struct dev_pm_ops rockchip_i2s_pm_ops = { static const struct dev_pm_ops rockchip_i2s_pm_ops = {
SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
NULL) NULL)
......
...@@ -81,8 +81,8 @@ ...@@ -81,8 +81,8 @@
#define I2S_CKR_TRCM_SHIFT 28 #define I2S_CKR_TRCM_SHIFT 28
#define I2S_CKR_TRCM(x) (x << I2S_CKR_TRCM_SHIFT) #define I2S_CKR_TRCM(x) (x << I2S_CKR_TRCM_SHIFT)
#define I2S_CKR_TRCM_TXRX (0 << I2S_CKR_TRCM_SHIFT) #define I2S_CKR_TRCM_TXRX (0 << I2S_CKR_TRCM_SHIFT)
#define I2S_CKR_TRCM_TXSHARE (1 << I2S_CKR_TRCM_SHIFT) #define I2S_CKR_TRCM_TXONLY (1 << I2S_CKR_TRCM_SHIFT)
#define I2S_CKR_TRCM_RXSHARE (2 << I2S_CKR_TRCM_SHIFT) #define I2S_CKR_TRCM_RXONLY (2 << I2S_CKR_TRCM_SHIFT)
#define I2S_CKR_TRCM_MASK (3 << I2S_CKR_TRCM_SHIFT) #define I2S_CKR_TRCM_MASK (3 << I2S_CKR_TRCM_SHIFT)
#define I2S_CKR_MSS_SHIFT 27 #define I2S_CKR_MSS_SHIFT 27
#define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT) #define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT)
...@@ -236,4 +236,11 @@ enum { ...@@ -236,4 +236,11 @@ enum {
#define I2S_TXDR (0x0024) #define I2S_TXDR (0x0024)
#define I2S_RXDR (0x0028) #define I2S_RXDR (0x0028)
/* io direction cfg register */
#define I2S_IO_DIRECTION_MASK (7)
#define I2S_IO_8CH_OUT_2CH_IN (0)
#define I2S_IO_6CH_OUT_4CH_IN (4)
#define I2S_IO_4CH_OUT_6CH_IN (6)
#define I2S_IO_2CH_OUT_8CH_IN (7)
#endif /* _ROCKCHIP_IIS_H */ #endif /* _ROCKCHIP_IIS_H */
...@@ -34,13 +34,18 @@ ...@@ -34,13 +34,18 @@
#define DRV_NAME "rockchip-snd-max98090" #define DRV_NAME "rockchip-snd-max98090"
static struct snd_soc_jack headset_jack; static struct snd_soc_jack headset_jack;
/* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin headset_jack_pins[] = { static struct snd_soc_jack_pin headset_jack_pins[] = {
{ {
.pin = "Headset Jack", .pin = "Headphone",
.mask = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | .mask = SND_JACK_HEADPHONE,
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
}, },
{
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
},
}; };
static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
...@@ -53,7 +58,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { ...@@ -53,7 +58,7 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = {
static const struct snd_soc_dapm_route rk_audio_map[] = { static const struct snd_soc_dapm_route rk_audio_map[] = {
{"IN34", NULL, "Headset Mic"}, {"IN34", NULL, "Headset Mic"},
{"IN34", NULL, "MICBIAS"}, {"IN34", NULL, "MICBIAS"},
{"MICBIAS", NULL, "Headset Mic"}, {"Headset Mic", NULL, "MICBIAS"},
{"DMICL", NULL, "Int Mic"}, {"DMICL", NULL, "Int Mic"},
{"Headphone", NULL, "HPL"}, {"Headphone", NULL, "HPL"},
{"Headphone", NULL, "HPR"}, {"Headphone", NULL, "HPR"},
...@@ -114,43 +119,27 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream, ...@@ -114,43 +119,27 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static int rk_init(struct snd_soc_pcm_runtime *runtime)
{
/* Enable Headset and 4 Buttons Jack detection */
return snd_soc_card_jack_new(runtime->card, "Headset Jack",
SND_JACK_HEADSET |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&headset_jack,
headset_jack_pins,
ARRAY_SIZE(headset_jack_pins));
}
static int rk_98090_headset_init(struct snd_soc_component *component)
{
return ts3a227e_enable_jack_detect(component, &headset_jack);
}
static struct snd_soc_ops rk_aif1_ops = { static struct snd_soc_ops rk_aif1_ops = {
.hw_params = rk_aif1_hw_params, .hw_params = rk_aif1_hw_params,
}; };
static struct snd_soc_aux_dev rk_98090_headset_dev = {
.name = "Headset Chip",
.init = rk_98090_headset_init,
};
static struct snd_soc_dai_link rk_dailink = { static struct snd_soc_dai_link rk_dailink = {
.name = "max98090", .name = "max98090",
.stream_name = "Audio", .stream_name = "Audio",
.codec_dai_name = "HiFi", .codec_dai_name = "HiFi",
.init = rk_init,
.ops = &rk_aif1_ops, .ops = &rk_aif1_ops,
/* set max98090 as slave */ /* set max98090 as slave */
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAIFMT_CBS_CFS,
}; };
static int rk_98090_headset_init(struct snd_soc_component *component);
static struct snd_soc_aux_dev rk_98090_headset_dev = {
.name = "Headset Chip",
.init = rk_98090_headset_init,
};
static struct snd_soc_card snd_soc_card_rk = { static struct snd_soc_card snd_soc_card_rk = {
.name = "ROCKCHIP-I2S", .name = "ROCKCHIP-I2S",
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -166,6 +155,26 @@ static struct snd_soc_card snd_soc_card_rk = { ...@@ -166,6 +155,26 @@ static struct snd_soc_card snd_soc_card_rk = {
.num_controls = ARRAY_SIZE(rk_mc_controls), .num_controls = ARRAY_SIZE(rk_mc_controls),
}; };
static int rk_98090_headset_init(struct snd_soc_component *component)
{
int ret;
/* Enable Headset and 4 Buttons Jack detection */
ret = snd_soc_card_jack_new(&snd_soc_card_rk, "Headset Jack",
SND_JACK_HEADSET |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&headset_jack,
headset_jack_pins,
ARRAY_SIZE(headset_jack_pins));
if (ret)
return ret;
ret = ts3a227e_enable_jack_detect(component, &headset_jack);
return ret;
}
static int snd_rk_mc_probe(struct platform_device *pdev) static int snd_rk_mc_probe(struct platform_device *pdev)
{ {
int ret = 0; int ret = 0;
......
...@@ -101,21 +101,7 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, ...@@ -101,21 +101,7 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
int ret; int ret;
srate = params_rate(params); srate = params_rate(params);
switch (srate) { mclk = srate * 128;
case 32000:
case 48000:
case 96000:
mclk = 96000 * 128; /* 12288000 hz */
break;
case 44100:
mclk = 44100 * 256; /* 11289600 hz */
break;
case 192000:
mclk = 192000 * 128; /* 24576000 hz */
break;
default:
return -EINVAL;
}
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE: case SNDRV_PCM_FORMAT_S16_LE:
...@@ -139,7 +125,6 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, ...@@ -139,7 +125,6 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
val |= SPDIF_CFGR_CLK_DIV(mclk/(srate * 256));
ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR,
SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE | SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE |
SDPIF_CFGR_VDW_MASK, SDPIF_CFGR_VDW_MASK,
......
...@@ -44,6 +44,7 @@ config SND_SOC_RCAR ...@@ -44,6 +44,7 @@ config SND_SOC_RCAR
config SND_SOC_RSRC_CARD config SND_SOC_RSRC_CARD
tristate "Renesas Sampling Rate Convert Sound Card" tristate "Renesas Sampling Rate Convert Sound Card"
select SND_SIMPLE_CARD_UTILS
help help
This option enables simple sound if you need sampling rate convert This option enables simple sound if you need sampling rate convert
......
...@@ -33,11 +33,15 @@ struct rsnd_adg { ...@@ -33,11 +33,15 @@ struct rsnd_adg {
struct clk *clkout[CLKOUTMAX]; struct clk *clkout[CLKOUTMAX];
struct clk_onecell_data onecell; struct clk_onecell_data onecell;
struct rsnd_mod mod; struct rsnd_mod mod;
u32 flags;
int rbga_rate_for_441khz; /* RBGA */ int rbga_rate_for_441khz; /* RBGA */
int rbgb_rate_for_48khz; /* RBGB */ int rbgb_rate_for_48khz; /* RBGB */
}; };
#define LRCLK_ASYNC (1 << 0)
#define adg_mode_flags(adg) (adg->flags)
#define for_each_rsnd_clk(pos, adg, i) \ #define for_each_rsnd_clk(pos, adg, i) \
for (i = 0; \ for (i = 0; \
(i < CLKMAX) && \ (i < CLKMAX) && \
...@@ -355,6 +359,16 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ...@@ -355,6 +359,16 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
rsnd_adg_set_ssi_clk(ssi_mod, data); rsnd_adg_set_ssi_clk(ssi_mod, data);
if (!(adg_mode_flags(adg) & LRCLK_ASYNC)) {
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
u32 ckr = 0;
if (0 == (rate % 8000))
ckr = 0x80000000;
rsnd_mod_bset(adg_mod, SSICKR, 0x80000000, ckr);
}
dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n", dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n",
rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod), rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod),
data, rate); data, rate);
...@@ -532,6 +546,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv) ...@@ -532,6 +546,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
{ {
struct rsnd_adg *adg; struct rsnd_adg *adg;
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
if (!adg) { if (!adg) {
...@@ -545,6 +560,9 @@ int rsnd_adg_probe(struct rsnd_priv *priv) ...@@ -545,6 +560,9 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
rsnd_adg_get_clkin(priv, adg); rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg); rsnd_adg_get_clkout(priv, adg);
if (of_get_property(np, "clkout-lr-asynchronous", NULL))
adg->flags = LRCLK_ASYNC;
priv->adg = adg; priv->adg = adg;
return 0; return 0;
......
...@@ -206,7 +206,7 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, ...@@ -206,7 +206,7 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
*/ */
static int rsnd_gen2_probe(struct rsnd_priv *priv) static int rsnd_gen2_probe(struct rsnd_priv *priv)
{ {
const static struct rsnd_regmap_field_conf conf_ssiu[] = { static const struct rsnd_regmap_field_conf conf_ssiu[] = {
RSND_GEN_S_REG(SSI_MODE0, 0x800), RSND_GEN_S_REG(SSI_MODE0, 0x800),
RSND_GEN_S_REG(SSI_MODE1, 0x804), RSND_GEN_S_REG(SSI_MODE1, 0x804),
RSND_GEN_S_REG(SSI_MODE2, 0x808), RSND_GEN_S_REG(SSI_MODE2, 0x808),
...@@ -221,7 +221,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) ...@@ -221,7 +221,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
}; };
const static struct rsnd_regmap_field_conf conf_scu[] = { static const struct rsnd_regmap_field_conf conf_scu[] = {
RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0, 0x20), RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0, 0x20),
RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4, 0x20), RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4, 0x20),
RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20), RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
...@@ -308,7 +308,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) ...@@ -308,7 +308,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100), RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100),
RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100),
}; };
const static struct rsnd_regmap_field_conf conf_adg[] = { static const struct rsnd_regmap_field_conf conf_adg[] = {
RSND_GEN_S_REG(BRRA, 0x00), RSND_GEN_S_REG(BRRA, 0x00),
RSND_GEN_S_REG(BRRB, 0x04), RSND_GEN_S_REG(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08), RSND_GEN_S_REG(SSICKR, 0x08),
...@@ -328,7 +328,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) ...@@ -328,7 +328,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c),
}; };
const static struct rsnd_regmap_field_conf conf_ssi[] = { static const struct rsnd_regmap_field_conf conf_ssi[] = {
RSND_GEN_M_REG(SSICR, 0x00, 0x40), RSND_GEN_M_REG(SSICR, 0x00, 0x40),
RSND_GEN_M_REG(SSISR, 0x04, 0x40), RSND_GEN_M_REG(SSISR, 0x04, 0x40),
RSND_GEN_M_REG(SSITDR, 0x08, 0x40), RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
...@@ -359,14 +359,14 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) ...@@ -359,14 +359,14 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
static int rsnd_gen1_probe(struct rsnd_priv *priv) static int rsnd_gen1_probe(struct rsnd_priv *priv)
{ {
const static struct rsnd_regmap_field_conf conf_adg[] = { static const struct rsnd_regmap_field_conf conf_adg[] = {
RSND_GEN_S_REG(BRRA, 0x00), RSND_GEN_S_REG(BRRA, 0x00),
RSND_GEN_S_REG(BRRB, 0x04), RSND_GEN_S_REG(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08), RSND_GEN_S_REG(SSICKR, 0x08),
RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
}; };
const static struct rsnd_regmap_field_conf conf_ssi[] = { static const struct rsnd_regmap_field_conf conf_ssi[] = {
RSND_GEN_M_REG(SSICR, 0x00, 0x40), RSND_GEN_M_REG(SSICR, 0x00, 0x40),
RSND_GEN_M_REG(SSISR, 0x04, 0x40), RSND_GEN_M_REG(SSISR, 0x04, 0x40),
RSND_GEN_M_REG(SSITDR, 0x08, 0x40), RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <sound/jack.h> #include <sound/jack.h>
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/soc-dai.h> #include <sound/soc-dai.h>
#include <sound/simple_card_utils.h>
struct rsrc_card_of_data { struct rsrc_card_of_data {
const char *prefix; const char *prefix;
...@@ -46,25 +47,13 @@ static const struct of_device_id rsrc_card_of_match[] = { ...@@ -46,25 +47,13 @@ static const struct of_device_id rsrc_card_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, rsrc_card_of_match); MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
#define DAI_NAME_NUM 32
struct rsrc_card_dai {
unsigned int sysclk;
unsigned int tx_slot_mask;
unsigned int rx_slot_mask;
int slots;
int slot_width;
struct clk *clk;
char dai_name[DAI_NAME_NUM];
};
#define IDX_CPU 0 #define IDX_CPU 0
#define IDX_CODEC 1 #define IDX_CODEC 1
struct rsrc_card_priv { struct rsrc_card_priv {
struct snd_soc_card snd_card; struct snd_soc_card snd_card;
struct snd_soc_codec_conf codec_conf; struct snd_soc_codec_conf codec_conf;
struct rsrc_card_dai *dai_props; struct asoc_simple_dai *dai_props;
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
int dai_num;
u32 convert_rate; u32 convert_rate;
u32 convert_channels; u32 convert_channels;
}; };
...@@ -77,7 +66,7 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream) ...@@ -77,7 +66,7 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct rsrc_card_dai *dai_props = struct asoc_simple_dai *dai_props =
rsrc_priv_to_props(priv, rtd->num); rsrc_priv_to_props(priv, rtd->num);
return clk_prepare_enable(dai_props->clk); return clk_prepare_enable(dai_props->clk);
...@@ -87,7 +76,7 @@ static void rsrc_card_shutdown(struct snd_pcm_substream *substream) ...@@ -87,7 +76,7 @@ static void rsrc_card_shutdown(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct rsrc_card_dai *dai_props = struct asoc_simple_dai *dai_props =
rsrc_priv_to_props(priv, rtd->num); rsrc_priv_to_props(priv, rtd->num);
clk_disable_unprepare(dai_props->clk); clk_disable_unprepare(dai_props->clk);
...@@ -103,7 +92,7 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -103,7 +92,7 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai; struct snd_soc_dai *dai;
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
struct rsrc_card_dai *dai_props; struct asoc_simple_dai *dai_props;
int num = rtd->num; int num = rtd->num;
int ret; int ret;
...@@ -159,44 +148,13 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -159,44 +148,13 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0; return 0;
} }
static int rsrc_card_parse_daifmt(struct device_node *node,
struct device_node *codec,
struct rsrc_card_priv *priv,
struct snd_soc_dai_link *dai_link,
unsigned int *retfmt)
{
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
unsigned int daifmt;
daifmt = snd_soc_of_parse_daifmt(node, NULL,
&bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
if (!bitclkmaster && !framemaster)
return -EINVAL;
if (codec == bitclkmaster)
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
else
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
of_node_put(bitclkmaster);
of_node_put(framemaster);
*retfmt = daifmt;
return 0;
}
static int rsrc_card_parse_links(struct device_node *np, static int rsrc_card_parse_links(struct device_node *np,
struct rsrc_card_priv *priv, struct rsrc_card_priv *priv,
int idx, bool is_fe) int idx, bool is_fe)
{ {
struct device *dev = rsrc_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx);
struct of_phandle_args args; struct of_phandle_args args;
int ret; int ret;
...@@ -232,9 +190,11 @@ static int rsrc_card_parse_links(struct device_node *np, ...@@ -232,9 +190,11 @@ static int rsrc_card_parse_links(struct device_node *np,
if (ret < 0) if (ret < 0)
return ret; return ret;
/* set dai_name */ ret = asoc_simple_card_set_dailink_name(dev, dai_link,
snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s", "fe.%s",
dai_link->cpu_dai_name); dai_link->cpu_dai_name);
if (ret < 0)
return ret;
/* /*
* In soc_bind_dai_link() will check cpu name after * In soc_bind_dai_link() will check cpu name after
...@@ -248,7 +208,6 @@ static int rsrc_card_parse_links(struct device_node *np, ...@@ -248,7 +208,6 @@ static int rsrc_card_parse_links(struct device_node *np,
if (!args.args_count) if (!args.args_count)
dai_link->cpu_dai_name = NULL; dai_link->cpu_dai_name = NULL;
} else { } else {
struct device *dev = rsrc_priv_to_dev(priv);
const struct rsrc_card_of_data *of_data; const struct rsrc_card_of_data *of_data;
of_data = of_device_get_match_data(dev); of_data = of_device_get_match_data(dev);
...@@ -266,6 +225,12 @@ static int rsrc_card_parse_links(struct device_node *np, ...@@ -266,6 +225,12 @@ static int rsrc_card_parse_links(struct device_node *np,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = asoc_simple_card_set_dailink_name(dev, dai_link,
"be.%s",
dai_link->codec_dai_name);
if (ret < 0)
return ret;
/* additional name prefix */ /* additional name prefix */
if (of_data) { if (of_data) {
priv->codec_conf.of_node = dai_link->codec_of_node; priv->codec_conf.of_node = dai_link->codec_of_node;
...@@ -276,18 +241,12 @@ static int rsrc_card_parse_links(struct device_node *np, ...@@ -276,18 +241,12 @@ static int rsrc_card_parse_links(struct device_node *np,
dai_link->codec_of_node, dai_link->codec_of_node,
"audio-prefix"); "audio-prefix");
} }
/* set dai_name */
snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s",
dai_link->codec_dai_name);
} }
/* Simple Card assumes platform == cpu */ /* Simple Card assumes platform == cpu */
dai_link->platform_of_node = dai_link->cpu_of_node; dai_link->platform_of_node = dai_link->cpu_of_node;
dai_link->dpcm_playback = 1; dai_link->dpcm_playback = 1;
dai_link->dpcm_capture = 1; dai_link->dpcm_capture = 1;
dai_link->name = dai_props->dai_name;
dai_link->stream_name = dai_props->dai_name;
dai_link->ops = &rsrc_card_ops; dai_link->ops = &rsrc_card_ops;
dai_link->init = rsrc_card_dai_init; dai_link->init = rsrc_card_dai_init;
...@@ -299,7 +258,7 @@ static int rsrc_card_parse_clk(struct device_node *np, ...@@ -299,7 +258,7 @@ static int rsrc_card_parse_clk(struct device_node *np,
int idx, bool is_fe) int idx, bool is_fe)
{ {
struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx);
struct clk *clk; struct clk *clk;
struct device_node *of_np = is_fe ? dai_link->cpu_of_node : struct device_node *of_np = is_fe ? dai_link->cpu_of_node :
dai_link->codec_of_node; dai_link->codec_of_node;
...@@ -336,7 +295,7 @@ static int rsrc_card_dai_sub_link_of(struct device_node *node, ...@@ -336,7 +295,7 @@ static int rsrc_card_dai_sub_link_of(struct device_node *node,
{ {
struct device *dev = rsrc_priv_to_dev(priv); struct device *dev = rsrc_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx);
int ret; int ret;
ret = rsrc_card_parse_links(np, priv, idx, is_fe); ret = rsrc_card_parse_links(np, priv, idx, is_fe);
...@@ -348,7 +307,7 @@ static int rsrc_card_dai_sub_link_of(struct device_node *node, ...@@ -348,7 +307,7 @@ static int rsrc_card_dai_sub_link_of(struct device_node *node,
return ret; return ret;
dev_dbg(dev, "\t%s / %04x / %d\n", dev_dbg(dev, "\t%s / %04x / %d\n",
dai_props->dai_name, dai_link->name,
dai_link->dai_fmt, dai_link->dai_fmt,
dai_props->sysclk); dai_props->sysclk);
...@@ -358,6 +317,7 @@ static int rsrc_card_dai_sub_link_of(struct device_node *node, ...@@ -358,6 +317,7 @@ static int rsrc_card_dai_sub_link_of(struct device_node *node,
static int rsrc_card_dai_link_of(struct device_node *node, static int rsrc_card_dai_link_of(struct device_node *node,
struct rsrc_card_priv *priv) struct rsrc_card_priv *priv)
{ {
struct device *dev = rsrc_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
struct device_node *np; struct device_node *np;
unsigned int daifmt = 0; unsigned int daifmt = 0;
...@@ -370,8 +330,8 @@ static int rsrc_card_dai_link_of(struct device_node *node, ...@@ -370,8 +330,8 @@ static int rsrc_card_dai_link_of(struct device_node *node,
dai_link = rsrc_priv_to_link(priv, i); dai_link = rsrc_priv_to_link(priv, i);
if (strcmp(np->name, "codec") == 0) { if (strcmp(np->name, "codec") == 0) {
ret = rsrc_card_parse_daifmt(node, np, priv, ret = asoc_simple_card_parse_daifmt(dev, node, np,
dai_link, &daifmt); NULL, &daifmt);
if (ret < 0) if (ret < 0)
return ret; return ret;
break; break;
...@@ -402,7 +362,7 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -402,7 +362,7 @@ static int rsrc_card_parse_of(struct device_node *node,
struct device *dev) struct device *dev)
{ {
const struct rsrc_card_of_data *of_data = of_device_get_match_data(dev); const struct rsrc_card_of_data *of_data = of_device_get_match_data(dev);
struct rsrc_card_dai *props; struct asoc_simple_dai *props;
struct snd_soc_dai_link *links; struct snd_soc_dai_link *links;
int ret; int ret;
int num; int num;
...@@ -418,7 +378,6 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -418,7 +378,6 @@ static int rsrc_card_parse_of(struct device_node *node,
priv->dai_props = props; priv->dai_props = props;
priv->dai_link = links; priv->dai_link = links;
priv->dai_num = num;
/* Init snd_soc_card */ /* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE; priv->snd_card.owner = THIS_MODULE;
...@@ -436,9 +395,6 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -436,9 +395,6 @@ static int rsrc_card_parse_of(struct device_node *node,
"audio-routing"); "audio-routing");
} }
/* Parse the card name from DT */
snd_soc_of_parse_card_name(&priv->snd_card, "card-name");
/* sampling rate convert */ /* sampling rate convert */
of_property_read_u32(node, "convert-rate", &priv->convert_rate); of_property_read_u32(node, "convert-rate", &priv->convert_rate);
...@@ -454,8 +410,9 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -454,8 +410,9 @@ static int rsrc_card_parse_of(struct device_node *node,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!priv->snd_card.name) ret = asoc_simple_card_parse_card_name(&priv->snd_card, "card-");
priv->snd_card.name = priv->snd_card.dai_link->name; if (ret < 0)
return ret;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment