Commit ae17a14f authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/samsung', 'asoc/topic/sgtl5000',...

Merge remote-tracking branches 'asoc/topic/samsung', 'asoc/topic/sgtl5000', 'asoc/topic/simple', 'asoc/topic/sirf' and 'asoc/topic/ssm4567' into asoc-next
Samsung Exynos Odroid XU3/XU4 audio complex with MAX98090 codec
Required properties:
- compatible - "samsung,odroidxu3-audio" - for Odroid XU3 board,
"samsung,odroidxu4-audio" - for Odroid XU4 board
- model - the user-visible name of this sound complex
- 'cpu' subnode with a 'sound-dai' property containing the phandle of the I2S
controller
- 'codec' subnode with a 'sound-dai' property containing list of phandles
to the CODEC nodes, first entry must be corresponding to the MAX98090
CODEC and the second entry must be the phandle of the HDMI IP block node
- clocks - should contain entries matching clock names in the clock-names
property
- clock-names - should contain following entries:
- "epll" - indicating the EPLL output clock
- "i2s_rclk" - indicating the RCLK (root) clock of the I2S0 controller
- samsung,audio-widgets - this property specifies off-codec audio elements
like headphones or speakers, for details see widgets.txt
- samsung,audio-routing - a list of the connections between audio
components; each entry is a pair of strings, the first being the
connection's sink, the second being the connection's source;
valid names for sources and sinks are the MAX98090's pins (as
documented in its binding), and the jacks on the board
For Odroid X2:
"Headphone Jack", "Mic Jack", "DMIC"
For Odroid U3, XU3:
"Headphone Jack", "Speakers"
For Odroid XU4:
no entries
Example:
sound {
compatible = "samsung,odroidxu3-audio";
samsung,cpu-dai = <&i2s0>;
samsung,codec-dai = <&max98090>;
model = "Odroid-XU3";
samsung,audio-routing =
"Headphone Jack", "HPL",
"Headphone Jack", "HPR",
"IN1", "Mic Jack",
"Mic Jack", "MICBIAS";
clocks = <&clock CLK_FOUT_EPLL>, <&i2s0 CLK_I2S_RCLK_SRC>;
clock-names = "epll", "sclk_i2s";
cpu {
sound-dai = <&i2s0 0>;
};
codec {
sound-dai = <&hdmi>, <&max98090>;
};
};
...@@ -26,6 +26,15 @@ Optional properties: ...@@ -26,6 +26,15 @@ Optional properties:
If this node is not mentioned or the value is unknown, then If this node is not mentioned or the value is unknown, then
the value is set to 1.25V. the value is set to 1.25V.
- lrclk-strength: the LRCLK pad strength. Possible values are:
0, 1, 2 and 3 as per the table below:
VDDIO 1.8V 2.5V 3.3V
0 = Disable
1 = 1.66 mA 2.87 mA 4.02 mA
2 = 3.33 mA 5.74 mA 8.03 mA
3 = 4.99 mA 8.61 mA 12.05 mA
Example: Example:
codec: sgtl5000@0a { codec: sgtl5000@0a {
......
...@@ -99,6 +99,13 @@ enum sgtl5000_micbias_resistor { ...@@ -99,6 +99,13 @@ enum sgtl5000_micbias_resistor {
SGTL5000_MICBIAS_8K = 8, SGTL5000_MICBIAS_8K = 8,
}; };
enum {
I2S_LRCLK_STRENGTH_DISABLE,
I2S_LRCLK_STRENGTH_LOW,
I2S_LRCLK_STRENGTH_MEDIUM,
I2S_LRCLK_STRENGTH_HIGH,
};
/* sgtl5000 private structure in codec */ /* sgtl5000 private structure in codec */
struct sgtl5000_priv { struct sgtl5000_priv {
int sysclk; /* sysclk rate */ int sysclk; /* sysclk rate */
...@@ -111,6 +118,7 @@ struct sgtl5000_priv { ...@@ -111,6 +118,7 @@ struct sgtl5000_priv {
int revision; int revision;
u8 micbias_resistor; u8 micbias_resistor;
u8 micbias_voltage; u8 micbias_voltage;
u8 lrclk_strength;
}; };
/* /*
...@@ -1089,6 +1097,7 @@ static int sgtl5000_enable_regulators(struct i2c_client *client) ...@@ -1089,6 +1097,7 @@ static int sgtl5000_enable_regulators(struct i2c_client *client)
static int sgtl5000_probe(struct snd_soc_codec *codec) static int sgtl5000_probe(struct snd_soc_codec *codec)
{ {
int ret; int ret;
u16 reg;
struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
/* power up sgtl5000 */ /* power up sgtl5000 */
...@@ -1118,7 +1127,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) ...@@ -1118,7 +1127,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
SGTL5000_DAC_MUTE_RIGHT | SGTL5000_DAC_MUTE_RIGHT |
SGTL5000_DAC_MUTE_LEFT); SGTL5000_DAC_MUTE_LEFT);
snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f); reg = ((sgtl5000->lrclk_strength) << SGTL5000_PAD_I2S_LRCLK_SHIFT | 0x5f);
snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, reg);
snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL, snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL,
SGTL5000_HP_ZCD_EN | SGTL5000_HP_ZCD_EN |
...@@ -1347,6 +1357,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, ...@@ -1347,6 +1357,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
} }
} }
sgtl5000->lrclk_strength = I2S_LRCLK_STRENGTH_LOW;
if (!of_property_read_u32(np, "lrclk-strength", &value)) {
if (value > I2S_LRCLK_STRENGTH_HIGH)
value = I2S_LRCLK_STRENGTH_LOW;
sgtl5000->lrclk_strength = value;
}
/* Ensure sgtl5000 will start with sane register values */ /* Ensure sgtl5000 will start with sane register values */
sgtl5000_fill_defaults(client); sgtl5000_fill_defaults(client);
......
...@@ -485,6 +485,14 @@ static const struct i2c_device_id ssm4567_i2c_ids[] = { ...@@ -485,6 +485,14 @@ static const struct i2c_device_id ssm4567_i2c_ids[] = {
}; };
MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids);
#ifdef CONFIG_OF
static const struct of_device_id ssm4567_of_match[] = {
{ .compatible = "adi,ssm4567", },
{ }
};
MODULE_DEVICE_TABLE(of, ssm4567_of_match);
#endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id ssm4567_acpi_match[] = { static const struct acpi_device_id ssm4567_acpi_match[] = {
...@@ -498,6 +506,7 @@ MODULE_DEVICE_TABLE(acpi, ssm4567_acpi_match); ...@@ -498,6 +506,7 @@ MODULE_DEVICE_TABLE(acpi, ssm4567_acpi_match);
static struct i2c_driver ssm4567_driver = { static struct i2c_driver ssm4567_driver = {
.driver = { .driver = {
.name = "ssm4567", .name = "ssm4567",
.of_match_table = of_match_ptr(ssm4567_of_match),
.acpi_match_table = ACPI_PTR(ssm4567_acpi_match), .acpi_match_table = ACPI_PTR(ssm4567_acpi_match),
}, },
.probe = ssm4567_i2c_probe, .probe = ssm4567_i2c_probe,
......
...@@ -40,9 +40,10 @@ struct simple_card_data { ...@@ -40,9 +40,10 @@ struct simple_card_data {
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
}; };
#define simple_priv_to_dev(priv) ((priv)->snd_card.dev) #define simple_priv_to_card(priv) (&(priv)->snd_card)
#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 simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
#define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
#define DAI "sound-dai" #define DAI "sound-dai"
#define CELL "#sound-dai-cells" #define CELL "#sound-dai-cells"
...@@ -323,6 +324,7 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node, ...@@ -323,6 +324,7 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node,
{ {
struct device *dev = simple_priv_to_dev(priv); struct device *dev = simple_priv_to_dev(priv);
struct device_node *aux_node; struct device_node *aux_node;
struct snd_soc_card *card = simple_priv_to_card(priv);
int i, n, len; int i, n, len;
if (!of_find_property(node, PREFIX "aux-devs", &len)) if (!of_find_property(node, PREFIX "aux-devs", &len))
...@@ -332,19 +334,19 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node, ...@@ -332,19 +334,19 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node,
if (n <= 0) if (n <= 0)
return -EINVAL; return -EINVAL;
priv->snd_card.aux_dev = devm_kzalloc(dev, card->aux_dev = devm_kzalloc(dev,
n * sizeof(*priv->snd_card.aux_dev), GFP_KERNEL); n * sizeof(*card->aux_dev), GFP_KERNEL);
if (!priv->snd_card.aux_dev) if (!card->aux_dev)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
if (!aux_node) if (!aux_node)
return -EINVAL; return -EINVAL;
priv->snd_card.aux_dev[i].codec_of_node = aux_node; card->aux_dev[i].codec_of_node = aux_node;
} }
priv->snd_card.num_aux_devs = n; card->num_aux_devs = n;
return 0; return 0;
} }
...@@ -352,6 +354,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -352,6 +354,7 @@ 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);
struct snd_soc_card *card = simple_priv_to_card(priv);
struct device_node *dai_link; struct device_node *dai_link;
int ret; int ret;
...@@ -362,7 +365,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -362,7 +365,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
/* The off-codec widgets */ /* The off-codec widgets */
if (of_property_read_bool(node, PREFIX "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(card,
PREFIX "widgets"); PREFIX "widgets");
if (ret) if (ret)
goto card_parse_end; goto card_parse_end;
...@@ -370,7 +373,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -370,7 +373,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
/* DAPM routes */ /* DAPM routes */
if (of_property_read_bool(node, PREFIX "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(card,
PREFIX "routing"); PREFIX "routing");
if (ret) if (ret)
goto card_parse_end; goto card_parse_end;
...@@ -401,7 +404,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -401,7 +404,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
goto card_parse_end; goto card_parse_end;
} }
ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); ret = asoc_simple_card_parse_card_name(card, PREFIX);
if (ret < 0) if (ret < 0)
goto card_parse_end; goto card_parse_end;
...@@ -418,8 +421,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -418,8 +421,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
struct simple_card_data *priv; struct simple_card_data *priv;
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
struct simple_dai_props *dai_props; struct simple_dai_props *dai_props;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct snd_soc_card *card;
int num, ret; int num, ret;
/* Get the number of DAI links */ /* Get the number of DAI links */
...@@ -442,10 +446,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -442,10 +446,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
priv->dai_link = dai_link; priv->dai_link = dai_link;
/* Init snd_soc_card */ /* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE; card = simple_priv_to_card(priv);
priv->snd_card.dev = dev; card->owner = THIS_MODULE;
priv->snd_card.dai_link = priv->dai_link; card->dev = dev;
priv->snd_card.num_links = num; card->dai_link = priv->dai_link;
card->num_links = num;
if (np && of_device_is_available(np)) { if (np && of_device_is_available(np)) {
...@@ -474,7 +479,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -474,7 +479,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name; card->name = (cinfo->card) ? cinfo->card : cinfo->name;
dai_link->name = cinfo->name; dai_link->name = cinfo->name;
dai_link->stream_name = cinfo->name; dai_link->stream_name = cinfo->name;
dai_link->platform_name = cinfo->platform; dai_link->platform_name = cinfo->platform;
...@@ -489,13 +494,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -489,13 +494,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
sizeof(priv->dai_props->codec_dai)); sizeof(priv->dai_props->codec_dai));
} }
snd_soc_card_set_drvdata(&priv->snd_card, priv); snd_soc_card_set_drvdata(card, priv);
ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); ret = devm_snd_soc_register_card(dev, card);
if (ret >= 0) if (ret >= 0)
return ret; return ret;
err: err:
asoc_simple_card_clean_reference(&priv->snd_card); asoc_simple_card_clean_reference(card);
return ret; return ret;
} }
......
...@@ -31,9 +31,10 @@ struct simple_card_data { ...@@ -31,9 +31,10 @@ struct simple_card_data {
u32 convert_channels; u32 convert_channels;
}; };
#define simple_priv_to_dev(priv) ((priv)->snd_card.dev) #define simple_priv_to_card(priv) (&(priv)->snd_card)
#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 simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
#define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
#define DAI "sound-dai" #define DAI "sound-dai"
#define CELL "#sound-dai-cells" #define CELL "#sound-dai-cells"
...@@ -109,6 +110,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, ...@@ -109,6 +110,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np,
struct device *dev = simple_priv_to_dev(priv); struct device *dev = simple_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx); struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx);
struct snd_soc_card *card = simple_priv_to_card(priv);
int ret; int ret;
if (is_fe) { if (is_fe) {
...@@ -163,7 +165,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, ...@@ -163,7 +165,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np,
if (ret < 0) if (ret < 0)
return ret; return ret;
snd_soc_of_parse_audio_prefix(&priv->snd_card, snd_soc_of_parse_audio_prefix(card,
&priv->codec_conf, &priv->codec_conf,
dai_link->codec_of_node, dai_link->codec_of_node,
PREFIX "prefix"); PREFIX "prefix");
...@@ -201,6 +203,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -201,6 +203,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
{ {
struct device *dev = simple_priv_to_dev(priv); struct device *dev = simple_priv_to_dev(priv);
struct device_node *np; struct device_node *np;
struct snd_soc_card *card = simple_priv_to_card(priv);
unsigned int daifmt = 0; unsigned int daifmt = 0;
bool is_fe; bool is_fe;
int ret, i; int ret, i;
...@@ -208,7 +211,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -208,7 +211,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
if (!node) if (!node)
return -EINVAL; return -EINVAL;
ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); ret = snd_soc_of_parse_audio_routing(card, PREFIX "routing");
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -239,12 +242,12 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -239,12 +242,12 @@ static int asoc_simple_card_parse_of(struct device_node *node,
i++; i++;
} }
ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); ret = asoc_simple_card_parse_card_name(card, PREFIX);
if (ret < 0) if (ret < 0)
return ret; return ret;
dev_dbg(dev, "New card: %s\n", dev_dbg(dev, "New card: %s\n",
priv->snd_card.name ? priv->snd_card.name : ""); card->name ? card->name : "");
dev_dbg(dev, "convert_rate %d\n", priv->convert_rate); dev_dbg(dev, "convert_rate %d\n", priv->convert_rate);
dev_dbg(dev, "convert_channels %d\n", priv->convert_channels); dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
...@@ -256,8 +259,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -256,8 +259,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
struct simple_card_data *priv; struct simple_card_data *priv;
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
struct asoc_simple_dai *dai_props; struct asoc_simple_dai *dai_props;
struct snd_soc_card *card;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node; struct device_node *np = dev->of_node;
int num, ret; int num, ret;
/* Allocate the private data */ /* Allocate the private data */
...@@ -276,12 +280,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -276,12 +280,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
priv->dai_link = dai_link; priv->dai_link = dai_link;
/* Init snd_soc_card */ /* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE; card = simple_priv_to_card(priv);
priv->snd_card.dev = dev; card->owner = THIS_MODULE;
priv->snd_card.dai_link = priv->dai_link; card->dev = dev;
priv->snd_card.num_links = num; card->dai_link = priv->dai_link;
priv->snd_card.codec_conf = &priv->codec_conf; card->num_links = num;
priv->snd_card.num_configs = 1; card->codec_conf = &priv->codec_conf;
card->num_configs = 1;
ret = asoc_simple_card_parse_of(np, priv); ret = asoc_simple_card_parse_of(np, priv);
if (ret < 0) { if (ret < 0) {
...@@ -290,13 +295,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -290,13 +295,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
goto err; goto err;
} }
snd_soc_card_set_drvdata(&priv->snd_card, priv); snd_soc_card_set_drvdata(card, priv);
ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); ret = devm_snd_soc_register_card(dev, card);
if (ret >= 0) if (ret >= 0)
return ret; return ret;
err: err:
asoc_simple_card_clean_reference(&priv->snd_card); asoc_simple_card_clean_reference(card);
return ret; return ret;
} }
......
...@@ -185,6 +185,14 @@ config SND_SOC_SNOW ...@@ -185,6 +185,14 @@ config SND_SOC_SNOW
Say Y if you want to add audio support for various Snow Say Y if you want to add audio support for various Snow
boards based on Exynos5 series of SoCs. boards based on Exynos5 series of SoCs.
config SND_SOC_ODROID
tristate "Audio support for Odroid XU3/XU4"
depends on SND_SOC_SAMSUNG && I2C
select SND_SOC_MAX98090
select SND_SAMSUNG_I2S
help
Say Y here to enable audio support for the Odroid XU3/XU4.
config SND_SOC_ARNDALE_RT5631_ALC5631 config SND_SOC_ARNDALE_RT5631_ALC5631
tristate "Audio support for RT5631(ALC5631) on Arndale Board" tristate "Audio support for RT5631(ALC5631) on Arndale Board"
depends on I2C depends on I2C
......
...@@ -40,6 +40,7 @@ snd-soc-tobermory-objs := tobermory.o ...@@ -40,6 +40,7 @@ snd-soc-tobermory-objs := tobermory.o
snd-soc-lowland-objs := lowland.o snd-soc-lowland-objs := lowland.o
snd-soc-littlemill-objs := littlemill.o snd-soc-littlemill-objs := littlemill.o
snd-soc-bells-objs := bells.o snd-soc-bells-objs := bells.o
snd-soc-odroid-objs := odroid.o
snd-soc-arndale-rt5631-objs := arndale_rt5631.o snd-soc-arndale-rt5631-objs := arndale_rt5631.o
snd-soc-tm2-wm5110-objs := tm2_wm5110.o snd-soc-tm2-wm5110-objs := tm2_wm5110.o
...@@ -62,5 +63,6 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o ...@@ -62,5 +63,6 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o
obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o
obj-$(CONFIG_SND_SOC_ODROID) += snd-soc-odroid.o
obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o
obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o
...@@ -446,7 +446,6 @@ static struct snd_soc_card bells_cards[] = { ...@@ -446,7 +446,6 @@ static struct snd_soc_card bells_cards[] = {
}, },
}; };
static int bells_probe(struct platform_device *pdev) static int bells_probe(struct platform_device *pdev)
{ {
int ret; int ret;
......
...@@ -160,5 +160,3 @@ ...@@ -160,5 +160,3 @@
#define I2SSIZE_SHIFT (16) #define I2SSIZE_SHIFT (16)
#endif /* __SND_SOC_SAMSUNG_I2S_REGS_H */ #endif /* __SND_SOC_SAMSUNG_I2S_REGS_H */
...@@ -1242,7 +1242,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) ...@@ -1242,7 +1242,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
i2s_dai_data = (struct samsung_i2s_dai_data *) i2s_dai_data = (struct samsung_i2s_dai_data *)
platform_get_device_id(pdev)->driver_data; platform_get_device_id(pdev)->driver_data;
pri_dai = i2s_alloc_dai(pdev, false); pri_dai = i2s_alloc_dai(pdev, false);
if (!pri_dai) { if (!pri_dai) {
dev_err(&pdev->dev, "Unable to alloc I2S_pri\n"); dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
......
/*
* Copyright (C) 2017 Samsung Electronics Co., Ltd.
*
* 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/clk.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include "i2s.h"
#include "i2s-regs.h"
struct odroid_priv {
struct snd_soc_card card;
struct snd_soc_dai_link dai_link;
struct clk *pll;
struct clk *rclk;
};
static int odroid_card_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
return 0;
}
static int odroid_card_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
unsigned int pll_freq, rclk_freq;
int ret;
switch (params_rate(params)) {
case 32000:
case 64000:
pll_freq = 131072000U;
break;
case 44100:
case 88200:
case 176400:
pll_freq = 180633600U;
break;
case 48000:
case 96000:
case 192000:
pll_freq = 196608000U;
break;
default:
return -EINVAL;
}
ret = clk_set_rate(priv->pll, pll_freq + 1);
if (ret < 0)
return ret;
rclk_freq = params_rate(params) * 256 * 4;
ret = clk_set_rate(priv->rclk, rclk_freq);
if (ret < 0)
return ret;
if (rtd->num_codecs > 1) {
struct snd_soc_dai *codec_dai = rtd->codec_dais[1];
ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk_freq,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
}
return 0;
}
static const struct snd_soc_ops odroid_card_ops = {
.startup = odroid_card_startup,
.hw_params = odroid_card_hw_params,
};
static void odroid_put_codec_of_nodes(struct snd_soc_dai_link *link)
{
struct snd_soc_dai_link_component *component = link->codecs;
int i;
for (i = 0; i < link->num_codecs; i++, component++) {
if (!component->of_node)
break;
of_node_put(component->of_node);
}
}
static int odroid_audio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *cpu, *codec;
struct odroid_priv *priv;
struct snd_soc_dai_link *link;
struct snd_soc_card *card;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
card = &priv->card;
card->dev = dev;
card->owner = THIS_MODULE;
card->fully_routed = true;
snd_soc_card_set_drvdata(card, priv);
priv->pll = devm_clk_get(dev, "epll");
if (IS_ERR(priv->pll))
return PTR_ERR(priv->pll);
priv->rclk = devm_clk_get(dev, "i2s_rclk");
if (IS_ERR(priv->rclk))
return PTR_ERR(priv->rclk);
ret = snd_soc_of_parse_card_name(card, "model");
if (ret < 0)
return ret;
if (of_property_read_bool(dev->of_node, "samsung,audio-widgets")) {
ret = snd_soc_of_parse_audio_simple_widgets(card,
"samsung,audio-widgets");
if (ret < 0)
return ret;
}
if (of_property_read_bool(dev->of_node, "samsung,audio-routing")) {
ret = snd_soc_of_parse_audio_routing(card,
"samsung,audio-routing");
if (ret < 0)
return ret;
}
link = &priv->dai_link;
link->ops = &odroid_card_ops;
link->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS;
card->dai_link = &priv->dai_link;
card->num_links = 1;
cpu = of_get_child_by_name(dev->of_node, "cpu");
codec = of_get_child_by_name(dev->of_node, "codec");
link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
if (!link->cpu_of_node) {
dev_err(dev, "Failed parsing cpu/sound-dai property\n");
return -EINVAL;
}
ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
if (ret < 0)
goto err_put_codec_n;
link->platform_of_node = link->cpu_of_node;
link->name = "Primary";
link->stream_name = link->name;
ret = devm_snd_soc_register_card(dev, card);
if (ret < 0) {
dev_err(dev, "snd_soc_register_card() failed: %d\n", ret);
goto err_put_i2s_n;
}
return 0;
err_put_i2s_n:
of_node_put(link->cpu_of_node);
err_put_codec_n:
odroid_put_codec_of_nodes(link);
return ret;
}
static int odroid_audio_remove(struct platform_device *pdev)
{
struct odroid_priv *priv = platform_get_drvdata(pdev);
of_node_put(priv->dai_link.cpu_of_node);
odroid_put_codec_of_nodes(&priv->dai_link);
return 0;
}
static const struct of_device_id odroid_audio_of_match[] = {
{ .compatible = "samsung,odroid-xu3-audio" },
{ .compatible = "samsung,odroid-xu4-audio"},
{ },
};
MODULE_DEVICE_TABLE(of, odroid_audio_of_match);
static struct platform_driver odroid_audio_driver = {
.driver = {
.name = "odroid-audio",
.of_match_table = odroid_audio_of_match,
.pm = &snd_soc_pm_ops,
},
.probe = odroid_audio_probe,
.remove = odroid_audio_remove,
};
module_platform_driver(odroid_audio_driver);
MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
MODULE_DESCRIPTION("Odroid XU3/XU4 audio support");
MODULE_LICENSE("GPL v2");
...@@ -72,7 +72,6 @@ static inline void dbg_showcon(const char *fn, u32 con) ...@@ -72,7 +72,6 @@ static inline void dbg_showcon(const char *fn, u32 con)
} }
#endif #endif
/* Turn on or off the transmission path. */ /* Turn on or off the transmission path. */
static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on) static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
{ {
......
...@@ -19,6 +19,7 @@ struct sirf_audio_port { ...@@ -19,6 +19,7 @@ struct sirf_audio_port {
static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai)
{ {
struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, snd_soc_dai_init_dma_data(dai, &port->playback_dma_data,
&port->capture_dma_data); &port->capture_dma_data);
return 0; return 0;
......
...@@ -27,6 +27,7 @@ static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w, ...@@ -27,6 +27,7 @@ static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w,
struct snd_soc_card *card = dapm->card; struct snd_soc_card *card = dapm->card;
struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card);
int on = !SND_SOC_DAPM_EVENT_OFF(event); int on = !SND_SOC_DAPM_EVENT_OFF(event);
if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) if (gpio_is_valid(sirf_audio_card->gpio_hp_pa))
gpio_set_value(sirf_audio_card->gpio_hp_pa, on); gpio_set_value(sirf_audio_card->gpio_hp_pa, on);
return 0; return 0;
......
...@@ -71,6 +71,7 @@ static void sirf_usp_rx_disable(struct sirf_usp *usp) ...@@ -71,6 +71,7 @@ static void sirf_usp_rx_disable(struct sirf_usp *usp)
static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai) static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai)
{ {
struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data, snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data,
&usp->capture_dma_data); &usp->capture_dma_data);
return 0; return 0;
...@@ -294,6 +295,7 @@ static struct snd_soc_dai_driver sirf_usp_pcm_dai = { ...@@ -294,6 +295,7 @@ static struct snd_soc_dai_driver sirf_usp_pcm_dai = {
static int sirf_usp_pcm_runtime_suspend(struct device *dev) static int sirf_usp_pcm_runtime_suspend(struct device *dev)
{ {
struct sirf_usp *usp = dev_get_drvdata(dev); struct sirf_usp *usp = dev_get_drvdata(dev);
clk_disable_unprepare(usp->clk); clk_disable_unprepare(usp->clk);
return 0; return 0;
} }
...@@ -302,6 +304,7 @@ static int sirf_usp_pcm_runtime_resume(struct device *dev) ...@@ -302,6 +304,7 @@ static int sirf_usp_pcm_runtime_resume(struct device *dev)
{ {
struct sirf_usp *usp = dev_get_drvdata(dev); struct sirf_usp *usp = dev_get_drvdata(dev);
int ret; int ret;
ret = clk_prepare_enable(usp->clk); ret = clk_prepare_enable(usp->clk);
if (ret) { if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
......
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