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:
- interrupts: Interrupt number for McPDM
- interrupt-parent: The parent interrupt controller
- ti,hwmods: Name of the hwmod associated to the McPDM
- clocks: phandle for the pdmclk provider, likely <&twl6040>
- clock-names: Must be "pdmclk"
Example:
......@@ -19,3 +21,11 @@ mcpdm: mcpdm@40132000 {
interrupt-parent = <&gic>;
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:
- #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
- 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:
- interrupts : Should contain SSI interrupt for PIO transfer
......
......@@ -23,6 +23,11 @@ Required properties:
- rockchip,playback-channels: max playback channels, if not set, 8 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:
i2s@ff890000 {
......
......@@ -13,16 +13,7 @@
#define __SIMPLE_CARD_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;
};
#include <sound/simple_card_utils.h>
struct asoc_simple_card_info {
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
tristate "ASoC Simple sound card support"
select SND_SIMPLE_CARD_UTILS
help
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
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 @@
#include <sound/soc-dai.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 snd_soc_card snd_card;
struct simple_dai_props {
......@@ -29,10 +35,8 @@ struct simple_card_data {
unsigned int mclk_fs;
} *dai_props;
unsigned int mclk_fs;
int gpio_hp_det;
int gpio_hp_det_invert;
int gpio_mic_det;
int gpio_mic_det_invert;
struct asoc_simple_jack hp_jack;
struct asoc_simple_jack mic_jack;
struct snd_soc_dai_link dai_link[]; /* dynamically allocated */
};
......@@ -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_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)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
......@@ -110,32 +177,6 @@ static struct snd_soc_ops asoc_simple_card_ops = {
.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,
struct asoc_simple_dai *set)
{
......@@ -184,30 +225,14 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
if (gpio_is_valid(priv->gpio_hp_det)) {
snd_soc_card_jack_new(rtd->card, "Headphones",
SND_JACK_HEADPHONE,
&simple_card_hp_jack,
simple_card_hp_jack_pins,
ARRAY_SIZE(simple_card_hp_jack_pins));
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);
}
ret = asoc_simple_card_init_hp(rtd->card, &priv->hp_jack, PREFIX);
if (ret < 0)
return ret;
ret = asoc_simple_card_init_mic(rtd->card, &priv->hp_jack, PREFIX);
if (ret < 0)
return ret;
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;
}
......@@ -223,6 +248,9 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
u32 val;
int ret;
if (!np)
return 0;
/*
* Get node via "sound-dai = <&phandle port>"
* 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,
*args_count = args.args_count;
/* Get dai->name */
ret = snd_soc_of_get_dai_name(np, name);
if (ret < 0)
return ret;
if (name) {
ret = snd_soc_of_get_dai_name(np, name);
if (ret < 0)
return ret;
}
if (!dai)
return 0;
/* Parse TDM slot */
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,
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,
struct simple_card_data *priv,
int idx,
......@@ -328,7 +319,6 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
struct device_node *cpu = NULL;
struct device_node *plat = NULL;
struct device_node *codec = NULL;
char *name;
char prop[128];
char *prefix = "";
int ret, cpu_args;
......@@ -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 */
if (is_top_level_node)
prefix = "simple-audio-card,";
prefix = PREFIX;
snprintf(prop, sizeof(prop), "%scpu", prefix);
cpu = of_get_child_by_name(node, prop);
......@@ -353,8 +343,8 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
goto dai_link_of_err;
}
ret = asoc_simple_card_parse_daifmt(node, priv,
codec, prefix, idx);
ret = asoc_simple_card_parse_daifmt(dev, node, codec,
prefix, &dai_link->dai_fmt);
if (ret < 0)
goto dai_link_of_err;
......@@ -374,35 +364,28 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
if (ret < 0)
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) {
ret = -EINVAL;
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 name is created from CPU/CODEC dai name */
name = devm_kzalloc(dev,
strlen(dai_link->cpu_dai_name) +
strlen(dai_link->codec_dai_name) + 2,
GFP_KERNEL);
if (!name) {
ret = -ENOMEM;
ret = asoc_simple_card_set_dailink_name(dev, dai_link,
"%s-%s",
dai_link->cpu_dai_name,
dai_link->codec_dai_name);
if (ret < 0)
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->init = asoc_simple_card_dai_init;
......@@ -438,42 +421,35 @@ static int asoc_simple_card_parse_of(struct device_node *node,
struct simple_card_data *priv)
{
struct device *dev = simple_priv_to_dev(priv);
enum of_gpio_flags flags;
u32 val;
int ret;
if (!node)
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 */
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,
"simple-audio-card,widgets");
PREFIX "widgets");
if (ret)
return ret;
}
/* 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,
"simple-audio-card,routing");
PREFIX "routing");
if (ret)
return ret;
}
/* 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)
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 */
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;
int i = 0;
......@@ -494,20 +470,9 @@ static int asoc_simple_card_parse_of(struct device_node *node,
return ret;
}
priv->gpio_hp_det = of_get_named_gpio_flags(node,
"simple-audio-card,hp-det-gpio", 0, &flags);
priv->gpio_hp_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW);
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;
ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
if (ret)
return ret;
return 0;
}
......@@ -536,7 +501,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
int num_links, ret;
/* 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);
else
num_links = 1;
......@@ -555,9 +520,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
priv->snd_card.dai_link = dai_link;
priv->snd_card.num_links = num_links;
priv->gpio_hp_det = -ENOENT;
priv->gpio_mic_det = -ENOENT;
/* Get room for the other properties */
priv->dai_props = devm_kzalloc(dev,
sizeof(*priv->dai_props) * num_links,
......@@ -624,12 +586,8 @@ static int asoc_simple_card_remove(struct platform_device *pdev)
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
if (gpio_is_valid(priv->gpio_hp_det))
snd_soc_jack_free_gpios(&simple_card_hp_jack, 1,
&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);
asoc_simple_card_remove_jack(&priv->hp_jack);
asoc_simple_card_remove_jack(&priv->mic_jack);
return asoc_simple_card_unref(card);
}
......
......@@ -107,6 +107,7 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
select SND_SOC_TWL6040
select SND_SOC_DMIC
select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS)
select CLK_TWL6040
help
Say Y if you want to add support for SoC audio on OMAP boards using
ABE and twl6040 codec. This driver currently supports:
......
......@@ -31,6 +31,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/of_device.h>
......@@ -54,6 +55,7 @@ struct omap_mcpdm {
unsigned long phys_base;
void __iomem *io_base;
int irq;
struct clk *pdmclk;
struct mutex mutex;
......@@ -66,6 +68,9 @@ struct omap_mcpdm {
/* McPDM needs to be restarted due to runtime reconfiguration */
bool restart;
/* pm state for suspend/resume handling */
int pm_active_count;
struct snd_dmaengine_dai_dma_data dma_data[2];
};
......@@ -173,6 +178,10 @@ static inline int omap_mcpdm_active(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,
MCPDM_DN_IRQ_EMPTY | MCPDM_DN_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,
mutex_lock(&mcpdm->mutex);
if (!dai->active) {
u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
if (!dai->active)
omap_mcpdm_open_streams(mcpdm);
}
mutex_unlock(&mcpdm->mutex);
return 0;
......@@ -384,6 +390,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
int ret;
clk_prepare_enable(mcpdm->pdmclk);
pm_runtime_enable(mcpdm->dev);
/* Disable lines while request is ongoing */
......@@ -418,8 +425,54 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
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;
}
#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_FORMATS SNDRV_PCM_FMTBIT_S32_LE
......@@ -427,6 +480,8 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
static struct snd_soc_dai_driver omap_mcpdm_dai = {
.probe = omap_mcpdm_probe,
.remove = omap_mcpdm_remove,
.suspend = omap_mcpdm_suspend,
.resume = omap_mcpdm_resume,
.probe_order = SND_SOC_COMP_ORDER_LATE,
.remove_order = SND_SOC_COMP_ORDER_EARLY,
.playback = {
......@@ -494,6 +549,15 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
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,
&omap_mcpdm_component,
&omap_mcpdm_dai, 1);
......
......@@ -11,8 +11,10 @@
*/
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
......@@ -23,6 +25,11 @@
#define DRV_NAME "rockchip-i2s"
struct rk_i2s_pins {
u32 reg_offset;
u32 shift;
};
struct rk_i2s_dev {
struct device *dev;
......@@ -33,6 +40,7 @@ struct rk_i2s_dev {
struct snd_dmaengine_dai_dma_data playback_dma_data;
struct regmap *regmap;
struct regmap *grf;
/*
* Used to indicate the tx/rx status.
......@@ -42,6 +50,7 @@ struct rk_i2s_dev {
bool tx_start;
bool rx_start;
bool is_master_mode;
const struct rk_i2s_pins *pins;
};
static int i2s_runtime_suspend(struct device *dev)
......@@ -300,14 +309,38 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK,
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,
I2S_DMACR_TDL(16));
regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
I2S_DMACR_RDL(16));
val = I2S_CKR_TRCM_TXRX;
if (dai->driver->symmetric_rates || rtd->dai_link->symmetric_rates)
val = I2S_CKR_TRCM_TXSHARE;
if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates)
val = I2S_CKR_TRCM_TXONLY;
regmap_update_bits(i2s->regmap, I2S_CKR,
I2S_CKR_TRCM_MASK,
......@@ -485,9 +518,23 @@ static const struct regmap_config rockchip_i2s_regmap_config = {
.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)
{
struct device_node *node = pdev->dev.of_node;
const struct of_device_id *of_id;
struct rk_i2s_dev *i2s;
struct snd_soc_dai_driver *soc_dai;
struct resource *res;
......@@ -501,6 +548,17 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
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 */
i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
......@@ -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.maxburst = 4;
i2s->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, i2s);
pm_runtime_enable(&pdev->dev);
......@@ -606,14 +663,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev)
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 = {
SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
NULL)
......
......@@ -81,8 +81,8 @@
#define I2S_CKR_TRCM_SHIFT 28
#define I2S_CKR_TRCM(x) (x << 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_RXSHARE (2 << I2S_CKR_TRCM_SHIFT)
#define I2S_CKR_TRCM_TXONLY (1 << 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_MSS_SHIFT 27
#define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT)
......@@ -236,4 +236,11 @@ enum {
#define I2S_TXDR (0x0024)
#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 */
......@@ -34,13 +34,18 @@
#define DRV_NAME "rockchip-snd-max98090"
static struct snd_soc_jack headset_jack;
/* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin headset_jack_pins[] = {
{
.pin = "Headset Jack",
.mask = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
.pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
},
{
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
},
};
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[] = {
{"IN34", NULL, "Headset Mic"},
{"IN34", NULL, "MICBIAS"},
{"MICBIAS", NULL, "Headset Mic"},
{"Headset Mic", NULL, "MICBIAS"},
{"DMICL", NULL, "Int Mic"},
{"Headphone", NULL, "HPL"},
{"Headphone", NULL, "HPR"},
......@@ -114,43 +119,27 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
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 = {
.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 = {
.name = "max98090",
.stream_name = "Audio",
.codec_dai_name = "HiFi",
.init = rk_init,
.ops = &rk_aif1_ops,
/* set max98090 as slave */
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
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 = {
.name = "ROCKCHIP-I2S",
.owner = THIS_MODULE,
......@@ -166,6 +155,26 @@ static struct snd_soc_card snd_soc_card_rk = {
.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)
{
int ret = 0;
......
......@@ -101,21 +101,7 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
int ret;
srate = params_rate(params);
switch (srate) {
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;
}
mclk = srate * 128;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
......@@ -139,7 +125,6 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
return ret;
}
val |= SPDIF_CFGR_CLK_DIV(mclk/(srate * 256));
ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR,
SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE |
SDPIF_CFGR_VDW_MASK,
......
......@@ -44,6 +44,7 @@ config SND_SOC_RCAR
config SND_SOC_RSRC_CARD
tristate "Renesas Sampling Rate Convert Sound Card"
select SND_SIMPLE_CARD_UTILS
help
This option enables simple sound if you need sampling rate convert
......
......@@ -33,11 +33,15 @@ struct rsnd_adg {
struct clk *clkout[CLKOUTMAX];
struct clk_onecell_data onecell;
struct rsnd_mod mod;
u32 flags;
int rbga_rate_for_441khz; /* RBGA */
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) \
for (i = 0; \
(i < CLKMAX) && \
......@@ -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);
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",
rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod),
data, rate);
......@@ -532,6 +546,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
{
struct rsnd_adg *adg;
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
if (!adg) {
......@@ -545,6 +560,9 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg);
if (of_get_property(np, "clkout-lr-asynchronous", NULL))
adg->flags = LRCLK_ASYNC;
priv->adg = adg;
return 0;
......
......@@ -206,7 +206,7 @@ static int _rsnd_gen_regmap_init(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_MODE1, 0x804),
RSND_GEN_S_REG(SSI_MODE2, 0x808),
......@@ -221,7 +221,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
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_O_BUSIF_MODE,0x4, 0x20),
RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
......@@ -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_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(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08),
......@@ -328,7 +328,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
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(SSISR, 0x04, 0x40),
RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
......@@ -359,14 +359,14 @@ static int rsnd_gen2_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(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08),
RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
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(SSISR, 0x04, 0x40),
RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
......
......@@ -20,6 +20,7 @@
#include <sound/jack.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <sound/simple_card_utils.h>
struct rsrc_card_of_data {
const char *prefix;
......@@ -46,25 +47,13 @@ static const struct of_device_id 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_CODEC 1
struct rsrc_card_priv {
struct snd_soc_card snd_card;
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;
int dai_num;
u32 convert_rate;
u32 convert_channels;
};
......@@ -77,7 +66,7 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
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);
return clk_prepare_enable(dai_props->clk);
......@@ -87,7 +76,7 @@ static void rsrc_card_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
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);
clk_disable_unprepare(dai_props->clk);
......@@ -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 snd_soc_dai *dai;
struct snd_soc_dai_link *dai_link;
struct rsrc_card_dai *dai_props;
struct asoc_simple_dai *dai_props;
int num = rtd->num;
int ret;
......@@ -159,44 +148,13 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
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,
struct rsrc_card_priv *priv,
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 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;
int ret;
......@@ -232,9 +190,11 @@ static int rsrc_card_parse_links(struct device_node *np,
if (ret < 0)
return ret;
/* set dai_name */
snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s",
dai_link->cpu_dai_name);
ret = asoc_simple_card_set_dailink_name(dev, dai_link,
"fe.%s",
dai_link->cpu_dai_name);
if (ret < 0)
return ret;
/*
* In soc_bind_dai_link() will check cpu name after
......@@ -248,7 +208,6 @@ static int rsrc_card_parse_links(struct device_node *np,
if (!args.args_count)
dai_link->cpu_dai_name = NULL;
} else {
struct device *dev = rsrc_priv_to_dev(priv);
const struct rsrc_card_of_data *of_data;
of_data = of_device_get_match_data(dev);
......@@ -266,6 +225,12 @@ static int rsrc_card_parse_links(struct device_node *np,
if (ret < 0)
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 */
if (of_data) {
priv->codec_conf.of_node = dai_link->codec_of_node;
......@@ -276,18 +241,12 @@ static int rsrc_card_parse_links(struct device_node *np,
dai_link->codec_of_node,
"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 */
dai_link->platform_of_node = dai_link->cpu_of_node;
dai_link->dpcm_playback = 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->init = rsrc_card_dai_init;
......@@ -299,7 +258,7 @@ static int rsrc_card_parse_clk(struct device_node *np,
int idx, bool is_fe)
{
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 device_node *of_np = is_fe ? dai_link->cpu_of_node :
dai_link->codec_of_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 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;
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,
return ret;
dev_dbg(dev, "\t%s / %04x / %d\n",
dai_props->dai_name,
dai_link->name,
dai_link->dai_fmt,
dai_props->sysclk);
......@@ -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,
struct rsrc_card_priv *priv)
{
struct device *dev = rsrc_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link;
struct device_node *np;
unsigned int daifmt = 0;
......@@ -370,8 +330,8 @@ static int rsrc_card_dai_link_of(struct device_node *node,
dai_link = rsrc_priv_to_link(priv, i);
if (strcmp(np->name, "codec") == 0) {
ret = rsrc_card_parse_daifmt(node, np, priv,
dai_link, &daifmt);
ret = asoc_simple_card_parse_daifmt(dev, node, np,
NULL, &daifmt);
if (ret < 0)
return ret;
break;
......@@ -402,7 +362,7 @@ static int rsrc_card_parse_of(struct device_node *node,
struct device *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;
int ret;
int num;
......@@ -418,7 +378,6 @@ static int rsrc_card_parse_of(struct device_node *node,
priv->dai_props = props;
priv->dai_link = links;
priv->dai_num = num;
/* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE;
......@@ -436,9 +395,6 @@ static int rsrc_card_parse_of(struct device_node *node,
"audio-routing");
}
/* Parse the card name from DT */
snd_soc_of_parse_card_name(&priv->snd_card, "card-name");
/* sampling rate convert */
of_property_read_u32(node, "convert-rate", &priv->convert_rate);
......@@ -454,8 +410,9 @@ static int rsrc_card_parse_of(struct device_node *node,
if (ret < 0)
return ret;
if (!priv->snd_card.name)
priv->snd_card.name = priv->snd_card.dai_link->name;
ret = asoc_simple_card_parse_card_name(&priv->snd_card, "card-");
if (ret < 0)
return ret;
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