aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/samsung,odroid.txt57
-rw-r--r--Documentation/devicetree/bindings/sound/sgtl5000.txt9
-rw-r--r--sound/soc/codecs/sgtl5000.c19
-rw-r--r--sound/soc/codecs/ssm4567.c9
-rw-r--r--sound/soc/generic/simple-card.c43
-rw-r--r--sound/soc/generic/simple-scu-card.c37
-rw-r--r--sound/soc/samsung/Kconfig8
-rw-r--r--sound/soc/samsung/Makefile2
-rw-r--r--sound/soc/samsung/bells.c1
-rw-r--r--sound/soc/samsung/i2s-regs.h2
-rw-r--r--sound/soc/samsung/i2s.c1
-rw-r--r--sound/soc/samsung/odroid.c219
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c1
-rw-r--r--sound/soc/sirf/sirf-audio-port.c1
-rw-r--r--sound/soc/sirf/sirf-audio.c1
-rw-r--r--sound/soc/sirf/sirf-usp.c3
16 files changed, 372 insertions, 41 deletions
diff --git a/Documentation/devicetree/bindings/sound/samsung,odroid.txt b/Documentation/devicetree/bindings/sound/samsung,odroid.txt
new file mode 100644
index 000000000000..c1ac70cb0afb
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/samsung,odroid.txt
@@ -0,0 +1,57 @@
1Samsung Exynos Odroid XU3/XU4 audio complex with MAX98090 codec
2
3Required properties:
4
5 - compatible - "samsung,odroidxu3-audio" - for Odroid XU3 board,
6 "samsung,odroidxu4-audio" - for Odroid XU4 board
7 - model - the user-visible name of this sound complex
8 - 'cpu' subnode with a 'sound-dai' property containing the phandle of the I2S
9 controller
10 - 'codec' subnode with a 'sound-dai' property containing list of phandles
11 to the CODEC nodes, first entry must be corresponding to the MAX98090
12 CODEC and the second entry must be the phandle of the HDMI IP block node
13 - clocks - should contain entries matching clock names in the clock-names
14 property
15 - clock-names - should contain following entries:
16 - "epll" - indicating the EPLL output clock
17 - "i2s_rclk" - indicating the RCLK (root) clock of the I2S0 controller
18 - samsung,audio-widgets - this property specifies off-codec audio elements
19 like headphones or speakers, for details see widgets.txt
20 - samsung,audio-routing - a list of the connections between audio
21 components; each entry is a pair of strings, the first being the
22 connection's sink, the second being the connection's source;
23 valid names for sources and sinks are the MAX98090's pins (as
24 documented in its binding), and the jacks on the board
25
26 For Odroid X2:
27 "Headphone Jack", "Mic Jack", "DMIC"
28
29 For Odroid U3, XU3:
30 "Headphone Jack", "Speakers"
31
32 For Odroid XU4:
33 no entries
34
35Example:
36
37sound {
38 compatible = "samsung,odroidxu3-audio";
39 samsung,cpu-dai = <&i2s0>;
40 samsung,codec-dai = <&max98090>;
41 model = "Odroid-XU3";
42 samsung,audio-routing =
43 "Headphone Jack", "HPL",
44 "Headphone Jack", "HPR",
45 "IN1", "Mic Jack",
46 "Mic Jack", "MICBIAS";
47
48 clocks = <&clock CLK_FOUT_EPLL>, <&i2s0 CLK_I2S_RCLK_SRC>;
49 clock-names = "epll", "sclk_i2s";
50
51 cpu {
52 sound-dai = <&i2s0 0>;
53 };
54 codec {
55 sound-dai = <&hdmi>, <&max98090>;
56 };
57};
diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt
index 5666da7b8605..7a73a9d62015 100644
--- a/Documentation/devicetree/bindings/sound/sgtl5000.txt
+++ b/Documentation/devicetree/bindings/sound/sgtl5000.txt
@@ -26,6 +26,15 @@ Optional properties:
26 If this node is not mentioned or the value is unknown, then 26 If this node is not mentioned or the value is unknown, then
27 the value is set to 1.25V. 27 the value is set to 1.25V.
28 28
29- lrclk-strength: the LRCLK pad strength. Possible values are:
300, 1, 2 and 3 as per the table below:
31
32VDDIO 1.8V 2.5V 3.3V
330 = Disable
341 = 1.66 mA 2.87 mA 4.02 mA
352 = 3.33 mA 5.74 mA 8.03 mA
363 = 4.99 mA 8.61 mA 12.05 mA
37
29Example: 38Example:
30 39
31codec: sgtl5000@0a { 40codec: sgtl5000@0a {
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 1589325855bc..5a2702edeb77 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -99,6 +99,13 @@ enum sgtl5000_micbias_resistor {
99 SGTL5000_MICBIAS_8K = 8, 99 SGTL5000_MICBIAS_8K = 8,
100}; 100};
101 101
102enum {
103 I2S_LRCLK_STRENGTH_DISABLE,
104 I2S_LRCLK_STRENGTH_LOW,
105 I2S_LRCLK_STRENGTH_MEDIUM,
106 I2S_LRCLK_STRENGTH_HIGH,
107};
108
102/* sgtl5000 private structure in codec */ 109/* sgtl5000 private structure in codec */
103struct sgtl5000_priv { 110struct sgtl5000_priv {
104 int sysclk; /* sysclk rate */ 111 int sysclk; /* sysclk rate */
@@ -111,6 +118,7 @@ struct sgtl5000_priv {
111 int revision; 118 int revision;
112 u8 micbias_resistor; 119 u8 micbias_resistor;
113 u8 micbias_voltage; 120 u8 micbias_voltage;
121 u8 lrclk_strength;
114}; 122};
115 123
116/* 124/*
@@ -1089,6 +1097,7 @@ static int sgtl5000_enable_regulators(struct i2c_client *client)
1089static int sgtl5000_probe(struct snd_soc_codec *codec) 1097static int sgtl5000_probe(struct snd_soc_codec *codec)
1090{ 1098{
1091 int ret; 1099 int ret;
1100 u16 reg;
1092 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); 1101 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
1093 1102
1094 /* power up sgtl5000 */ 1103 /* power up sgtl5000 */
@@ -1118,7 +1127,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
1118 SGTL5000_DAC_MUTE_RIGHT | 1127 SGTL5000_DAC_MUTE_RIGHT |
1119 SGTL5000_DAC_MUTE_LEFT); 1128 SGTL5000_DAC_MUTE_LEFT);
1120 1129
1121 snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f); 1130 reg = ((sgtl5000->lrclk_strength) << SGTL5000_PAD_I2S_LRCLK_SHIFT | 0x5f);
1131 snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, reg);
1122 1132
1123 snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL, 1133 snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL,
1124 SGTL5000_HP_ZCD_EN | 1134 SGTL5000_HP_ZCD_EN |
@@ -1347,6 +1357,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
1347 } 1357 }
1348 } 1358 }
1349 1359
1360 sgtl5000->lrclk_strength = I2S_LRCLK_STRENGTH_LOW;
1361 if (!of_property_read_u32(np, "lrclk-strength", &value)) {
1362 if (value > I2S_LRCLK_STRENGTH_HIGH)
1363 value = I2S_LRCLK_STRENGTH_LOW;
1364 sgtl5000->lrclk_strength = value;
1365 }
1366
1350 /* Ensure sgtl5000 will start with sane register values */ 1367 /* Ensure sgtl5000 will start with sane register values */
1351 sgtl5000_fill_defaults(client); 1368 sgtl5000_fill_defaults(client);
1352 1369
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c
index 2bb5a11c9ba1..a622623e8558 100644
--- a/sound/soc/codecs/ssm4567.c
+++ b/sound/soc/codecs/ssm4567.c
@@ -485,6 +485,14 @@ static const struct i2c_device_id ssm4567_i2c_ids[] = {
485}; 485};
486MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); 486MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids);
487 487
488#ifdef CONFIG_OF
489static const struct of_device_id ssm4567_of_match[] = {
490 { .compatible = "adi,ssm4567", },
491 { }
492};
493MODULE_DEVICE_TABLE(of, ssm4567_of_match);
494#endif
495
488#ifdef CONFIG_ACPI 496#ifdef CONFIG_ACPI
489 497
490static const struct acpi_device_id ssm4567_acpi_match[] = { 498static const struct acpi_device_id ssm4567_acpi_match[] = {
@@ -498,6 +506,7 @@ MODULE_DEVICE_TABLE(acpi, ssm4567_acpi_match);
498static struct i2c_driver ssm4567_driver = { 506static struct i2c_driver ssm4567_driver = {
499 .driver = { 507 .driver = {
500 .name = "ssm4567", 508 .name = "ssm4567",
509 .of_match_table = of_match_ptr(ssm4567_of_match),
501 .acpi_match_table = ACPI_PTR(ssm4567_acpi_match), 510 .acpi_match_table = ACPI_PTR(ssm4567_acpi_match),
502 }, 511 },
503 .probe = ssm4567_i2c_probe, 512 .probe = ssm4567_i2c_probe,
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 85b4f1806514..2c9dedab5184 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -40,9 +40,10 @@ struct simple_card_data {
40 struct snd_soc_dai_link *dai_link; 40 struct snd_soc_dai_link *dai_link;
41}; 41};
42 42
43#define simple_priv_to_dev(priv) ((priv)->snd_card.dev) 43#define simple_priv_to_card(priv) (&(priv)->snd_card)
44#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
45#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) 44#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
45#define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
46#define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
46 47
47#define DAI "sound-dai" 48#define DAI "sound-dai"
48#define CELL "#sound-dai-cells" 49#define CELL "#sound-dai-cells"
@@ -323,6 +324,7 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node,
323{ 324{
324 struct device *dev = simple_priv_to_dev(priv); 325 struct device *dev = simple_priv_to_dev(priv);
325 struct device_node *aux_node; 326 struct device_node *aux_node;
327 struct snd_soc_card *card = simple_priv_to_card(priv);
326 int i, n, len; 328 int i, n, len;
327 329
328 if (!of_find_property(node, PREFIX "aux-devs", &len)) 330 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 if (n <= 0) 334 if (n <= 0)
333 return -EINVAL; 335 return -EINVAL;
334 336
335 priv->snd_card.aux_dev = devm_kzalloc(dev, 337 card->aux_dev = devm_kzalloc(dev,
336 n * sizeof(*priv->snd_card.aux_dev), GFP_KERNEL); 338 n * sizeof(*card->aux_dev), GFP_KERNEL);
337 if (!priv->snd_card.aux_dev) 339 if (!card->aux_dev)
338 return -ENOMEM; 340 return -ENOMEM;
339 341
340 for (i = 0; i < n; i++) { 342 for (i = 0; i < n; i++) {
341 aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); 343 aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
342 if (!aux_node) 344 if (!aux_node)
343 return -EINVAL; 345 return -EINVAL;
344 priv->snd_card.aux_dev[i].codec_of_node = aux_node; 346 card->aux_dev[i].codec_of_node = aux_node;
345 } 347 }
346 348
347 priv->snd_card.num_aux_devs = n; 349 card->num_aux_devs = n;
348 return 0; 350 return 0;
349} 351}
350 352
@@ -352,6 +354,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
352 struct simple_card_data *priv) 354 struct simple_card_data *priv)
353{ 355{
354 struct device *dev = simple_priv_to_dev(priv); 356 struct device *dev = simple_priv_to_dev(priv);
357 struct snd_soc_card *card = simple_priv_to_card(priv);
355 struct device_node *dai_link; 358 struct device_node *dai_link;
356 int ret; 359 int ret;
357 360
@@ -362,7 +365,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
362 365
363 /* The off-codec widgets */ 366 /* The off-codec widgets */
364 if (of_property_read_bool(node, PREFIX "widgets")) { 367 if (of_property_read_bool(node, PREFIX "widgets")) {
365 ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, 368 ret = snd_soc_of_parse_audio_simple_widgets(card,
366 PREFIX "widgets"); 369 PREFIX "widgets");
367 if (ret) 370 if (ret)
368 goto card_parse_end; 371 goto card_parse_end;
@@ -370,7 +373,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
370 373
371 /* DAPM routes */ 374 /* DAPM routes */
372 if (of_property_read_bool(node, PREFIX "routing")) { 375 if (of_property_read_bool(node, PREFIX "routing")) {
373 ret = snd_soc_of_parse_audio_routing(&priv->snd_card, 376 ret = snd_soc_of_parse_audio_routing(card,
374 PREFIX "routing"); 377 PREFIX "routing");
375 if (ret) 378 if (ret)
376 goto card_parse_end; 379 goto card_parse_end;
@@ -401,7 +404,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
401 goto card_parse_end; 404 goto card_parse_end;
402 } 405 }
403 406
404 ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); 407 ret = asoc_simple_card_parse_card_name(card, PREFIX);
405 if (ret < 0) 408 if (ret < 0)
406 goto card_parse_end; 409 goto card_parse_end;
407 410
@@ -418,8 +421,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
418 struct simple_card_data *priv; 421 struct simple_card_data *priv;
419 struct snd_soc_dai_link *dai_link; 422 struct snd_soc_dai_link *dai_link;
420 struct simple_dai_props *dai_props; 423 struct simple_dai_props *dai_props;
421 struct device_node *np = pdev->dev.of_node;
422 struct device *dev = &pdev->dev; 424 struct device *dev = &pdev->dev;
425 struct device_node *np = dev->of_node;
426 struct snd_soc_card *card;
423 int num, ret; 427 int num, ret;
424 428
425 /* Get the number of DAI links */ 429 /* Get the number of DAI links */
@@ -442,10 +446,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
442 priv->dai_link = dai_link; 446 priv->dai_link = dai_link;
443 447
444 /* Init snd_soc_card */ 448 /* Init snd_soc_card */
445 priv->snd_card.owner = THIS_MODULE; 449 card = simple_priv_to_card(priv);
446 priv->snd_card.dev = dev; 450 card->owner = THIS_MODULE;
447 priv->snd_card.dai_link = priv->dai_link; 451 card->dev = dev;
448 priv->snd_card.num_links = num; 452 card->dai_link = priv->dai_link;
453 card->num_links = num;
449 454
450 if (np && of_device_is_available(np)) { 455 if (np && of_device_is_available(np)) {
451 456
@@ -474,7 +479,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
474 return -EINVAL; 479 return -EINVAL;
475 } 480 }
476 481
477 priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name; 482 card->name = (cinfo->card) ? cinfo->card : cinfo->name;
478 dai_link->name = cinfo->name; 483 dai_link->name = cinfo->name;
479 dai_link->stream_name = cinfo->name; 484 dai_link->stream_name = cinfo->name;
480 dai_link->platform_name = cinfo->platform; 485 dai_link->platform_name = cinfo->platform;
@@ -489,13 +494,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
489 sizeof(priv->dai_props->codec_dai)); 494 sizeof(priv->dai_props->codec_dai));
490 } 495 }
491 496
492 snd_soc_card_set_drvdata(&priv->snd_card, priv); 497 snd_soc_card_set_drvdata(card, priv);
493 498
494 ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); 499 ret = devm_snd_soc_register_card(dev, card);
495 if (ret >= 0) 500 if (ret >= 0)
496 return ret; 501 return ret;
497err: 502err:
498 asoc_simple_card_clean_reference(&priv->snd_card); 503 asoc_simple_card_clean_reference(card);
499 504
500 return ret; 505 return ret;
501} 506}
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index 308ff4c11a8d..dcbcab230d1b 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -31,9 +31,10 @@ struct simple_card_data {
31 u32 convert_channels; 31 u32 convert_channels;
32}; 32};
33 33
34#define simple_priv_to_dev(priv) ((priv)->snd_card.dev) 34#define simple_priv_to_card(priv) (&(priv)->snd_card)
35#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
36#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) 35#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
36#define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
37#define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
37 38
38#define DAI "sound-dai" 39#define DAI "sound-dai"
39#define CELL "#sound-dai-cells" 40#define CELL "#sound-dai-cells"
@@ -109,6 +110,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np,
109 struct device *dev = simple_priv_to_dev(priv); 110 struct device *dev = simple_priv_to_dev(priv);
110 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); 111 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
111 struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx); 112 struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx);
113 struct snd_soc_card *card = simple_priv_to_card(priv);
112 int ret; 114 int ret;
113 115
114 if (is_fe) { 116 if (is_fe) {
@@ -163,7 +165,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np,
163 if (ret < 0) 165 if (ret < 0)
164 return ret; 166 return ret;
165 167
166 snd_soc_of_parse_audio_prefix(&priv->snd_card, 168 snd_soc_of_parse_audio_prefix(card,
167 &priv->codec_conf, 169 &priv->codec_conf,
168 dai_link->codec_of_node, 170 dai_link->codec_of_node,
169 PREFIX "prefix"); 171 PREFIX "prefix");
@@ -201,6 +203,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
201{ 203{
202 struct device *dev = simple_priv_to_dev(priv); 204 struct device *dev = simple_priv_to_dev(priv);
203 struct device_node *np; 205 struct device_node *np;
206 struct snd_soc_card *card = simple_priv_to_card(priv);
204 unsigned int daifmt = 0; 207 unsigned int daifmt = 0;
205 bool is_fe; 208 bool is_fe;
206 int ret, i; 209 int ret, i;
@@ -208,7 +211,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
208 if (!node) 211 if (!node)
209 return -EINVAL; 212 return -EINVAL;
210 213
211 ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); 214 ret = snd_soc_of_parse_audio_routing(card, PREFIX "routing");
212 if (ret < 0) 215 if (ret < 0)
213 return ret; 216 return ret;
214 217
@@ -239,12 +242,12 @@ static int asoc_simple_card_parse_of(struct device_node *node,
239 i++; 242 i++;
240 } 243 }
241 244
242 ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); 245 ret = asoc_simple_card_parse_card_name(card, PREFIX);
243 if (ret < 0) 246 if (ret < 0)
244 return ret; 247 return ret;
245 248
246 dev_dbg(dev, "New card: %s\n", 249 dev_dbg(dev, "New card: %s\n",
247 priv->snd_card.name ? priv->snd_card.name : ""); 250 card->name ? card->name : "");
248 dev_dbg(dev, "convert_rate %d\n", priv->convert_rate); 251 dev_dbg(dev, "convert_rate %d\n", priv->convert_rate);
249 dev_dbg(dev, "convert_channels %d\n", priv->convert_channels); 252 dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
250 253
@@ -256,8 +259,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
256 struct simple_card_data *priv; 259 struct simple_card_data *priv;
257 struct snd_soc_dai_link *dai_link; 260 struct snd_soc_dai_link *dai_link;
258 struct asoc_simple_dai *dai_props; 261 struct asoc_simple_dai *dai_props;
262 struct snd_soc_card *card;
259 struct device *dev = &pdev->dev; 263 struct device *dev = &pdev->dev;
260 struct device_node *np = pdev->dev.of_node; 264 struct device_node *np = dev->of_node;
261 int num, ret; 265 int num, ret;
262 266
263 /* Allocate the private data */ 267 /* Allocate the private data */
@@ -276,12 +280,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
276 priv->dai_link = dai_link; 280 priv->dai_link = dai_link;
277 281
278 /* Init snd_soc_card */ 282 /* Init snd_soc_card */
279 priv->snd_card.owner = THIS_MODULE; 283 card = simple_priv_to_card(priv);
280 priv->snd_card.dev = dev; 284 card->owner = THIS_MODULE;
281 priv->snd_card.dai_link = priv->dai_link; 285 card->dev = dev;
282 priv->snd_card.num_links = num; 286 card->dai_link = priv->dai_link;
283 priv->snd_card.codec_conf = &priv->codec_conf; 287 card->num_links = num;
284 priv->snd_card.num_configs = 1; 288 card->codec_conf = &priv->codec_conf;
289 card->num_configs = 1;
285 290
286 ret = asoc_simple_card_parse_of(np, priv); 291 ret = asoc_simple_card_parse_of(np, priv);
287 if (ret < 0) { 292 if (ret < 0) {
@@ -290,13 +295,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
290 goto err; 295 goto err;
291 } 296 }
292 297
293 snd_soc_card_set_drvdata(&priv->snd_card, priv); 298 snd_soc_card_set_drvdata(card, priv);
294 299
295 ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); 300 ret = devm_snd_soc_register_card(dev, card);
296 if (ret >= 0) 301 if (ret >= 0)
297 return ret; 302 return ret;
298err: 303err:
299 asoc_simple_card_clean_reference(&priv->snd_card); 304 asoc_simple_card_clean_reference(card);
300 305
301 return ret; 306 return ret;
302} 307}
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index f1f1d7959a1b..0520f5afd7cc 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -185,6 +185,14 @@ config SND_SOC_SNOW
185 Say Y if you want to add audio support for various Snow 185 Say Y if you want to add audio support for various Snow
186 boards based on Exynos5 series of SoCs. 186 boards based on Exynos5 series of SoCs.
187 187
188config SND_SOC_ODROID
189 tristate "Audio support for Odroid XU3/XU4"
190 depends on SND_SOC_SAMSUNG && I2C
191 select SND_SOC_MAX98090
192 select SND_SAMSUNG_I2S
193 help
194 Say Y here to enable audio support for the Odroid XU3/XU4.
195
188config SND_SOC_ARNDALE_RT5631_ALC5631 196config SND_SOC_ARNDALE_RT5631_ALC5631
189 tristate "Audio support for RT5631(ALC5631) on Arndale Board" 197 tristate "Audio support for RT5631(ALC5631) on Arndale Board"
190 depends on I2C 198 depends on I2C
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index b5df5e2e3d94..b6c2ee358333 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -40,6 +40,7 @@ snd-soc-tobermory-objs := tobermory.o
40snd-soc-lowland-objs := lowland.o 40snd-soc-lowland-objs := lowland.o
41snd-soc-littlemill-objs := littlemill.o 41snd-soc-littlemill-objs := littlemill.o
42snd-soc-bells-objs := bells.o 42snd-soc-bells-objs := bells.o
43snd-soc-odroid-objs := odroid.o
43snd-soc-arndale-rt5631-objs := arndale_rt5631.o 44snd-soc-arndale-rt5631-objs := arndale_rt5631.o
44snd-soc-tm2-wm5110-objs := tm2_wm5110.o 45snd-soc-tm2-wm5110-objs := tm2_wm5110.o
45 46
@@ -62,5 +63,6 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o
62obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o 63obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
63obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o 64obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
64obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o 65obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o
66obj-$(CONFIG_SND_SOC_ODROID) += snd-soc-odroid.o
65obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o 67obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o
66obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o 68obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index 3dd246fa0059..34deba461ae1 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -446,7 +446,6 @@ static struct snd_soc_card bells_cards[] = {
446 }, 446 },
447}; 447};
448 448
449
450static int bells_probe(struct platform_device *pdev) 449static int bells_probe(struct platform_device *pdev)
451{ 450{
452 int ret; 451 int ret;
diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h
index 9170c311d66e..fe6914005494 100644
--- a/sound/soc/samsung/i2s-regs.h
+++ b/sound/soc/samsung/i2s-regs.h
@@ -160,5 +160,3 @@
160#define I2SSIZE_SHIFT (16) 160#define I2SSIZE_SHIFT (16)
161 161
162#endif /* __SND_SOC_SAMSUNG_I2S_REGS_H */ 162#endif /* __SND_SOC_SAMSUNG_I2S_REGS_H */
163
164
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 52a47ed292a4..af3ba4d4ccc5 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1242,7 +1242,6 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1242 i2s_dai_data = (struct samsung_i2s_dai_data *) 1242 i2s_dai_data = (struct samsung_i2s_dai_data *)
1243 platform_get_device_id(pdev)->driver_data; 1243 platform_get_device_id(pdev)->driver_data;
1244 1244
1245
1246 pri_dai = i2s_alloc_dai(pdev, false); 1245 pri_dai = i2s_alloc_dai(pdev, false);
1247 if (!pri_dai) { 1246 if (!pri_dai) {
1248 dev_err(&pdev->dev, "Unable to alloc I2S_pri\n"); 1247 dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c
new file mode 100644
index 000000000000..0c0b00e40646
--- /dev/null
+++ b/sound/soc/samsung/odroid.c
@@ -0,0 +1,219 @@
1/*
2 * Copyright (C) 2017 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/of.h>
11#include <linux/of_device.h>
12#include <linux/module.h>
13#include <sound/soc.h>
14#include <sound/pcm_params.h>
15#include "i2s.h"
16#include "i2s-regs.h"
17
18struct odroid_priv {
19 struct snd_soc_card card;
20 struct snd_soc_dai_link dai_link;
21
22 struct clk *pll;
23 struct clk *rclk;
24};
25
26static int odroid_card_startup(struct snd_pcm_substream *substream)
27{
28 struct snd_pcm_runtime *runtime = substream->runtime;
29
30 snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
31 return 0;
32}
33
34static int odroid_card_hw_params(struct snd_pcm_substream *substream,
35 struct snd_pcm_hw_params *params)
36{
37 struct snd_soc_pcm_runtime *rtd = substream->private_data;
38 struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
39 unsigned int pll_freq, rclk_freq;
40 int ret;
41
42 switch (params_rate(params)) {
43 case 32000:
44 case 64000:
45 pll_freq = 131072000U;
46 break;
47 case 44100:
48 case 88200:
49 case 176400:
50 pll_freq = 180633600U;
51 break;
52 case 48000:
53 case 96000:
54 case 192000:
55 pll_freq = 196608000U;
56 break;
57 default:
58 return -EINVAL;
59 }
60
61 ret = clk_set_rate(priv->pll, pll_freq + 1);
62 if (ret < 0)
63 return ret;
64
65 rclk_freq = params_rate(params) * 256 * 4;
66
67 ret = clk_set_rate(priv->rclk, rclk_freq);
68 if (ret < 0)
69 return ret;
70
71 if (rtd->num_codecs > 1) {
72 struct snd_soc_dai *codec_dai = rtd->codec_dais[1];
73
74 ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk_freq,
75 SND_SOC_CLOCK_IN);
76 if (ret < 0)
77 return ret;
78 }
79
80 return 0;
81}
82
83static const struct snd_soc_ops odroid_card_ops = {
84 .startup = odroid_card_startup,
85 .hw_params = odroid_card_hw_params,
86};
87
88static void odroid_put_codec_of_nodes(struct snd_soc_dai_link *link)
89{
90 struct snd_soc_dai_link_component *component = link->codecs;
91 int i;
92
93 for (i = 0; i < link->num_codecs; i++, component++) {
94 if (!component->of_node)
95 break;
96 of_node_put(component->of_node);
97 }
98}
99
100static int odroid_audio_probe(struct platform_device *pdev)
101{
102 struct device *dev = &pdev->dev;
103 struct device_node *cpu, *codec;
104 struct odroid_priv *priv;
105 struct snd_soc_dai_link *link;
106 struct snd_soc_card *card;
107 int ret;
108
109 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
110 if (!priv)
111 return -ENOMEM;
112
113 card = &priv->card;
114 card->dev = dev;
115
116 card->owner = THIS_MODULE;
117 card->fully_routed = true;
118
119 snd_soc_card_set_drvdata(card, priv);
120
121 priv->pll = devm_clk_get(dev, "epll");
122 if (IS_ERR(priv->pll))
123 return PTR_ERR(priv->pll);
124
125 priv->rclk = devm_clk_get(dev, "i2s_rclk");
126 if (IS_ERR(priv->rclk))
127 return PTR_ERR(priv->rclk);
128
129 ret = snd_soc_of_parse_card_name(card, "model");
130 if (ret < 0)
131 return ret;
132
133 if (of_property_read_bool(dev->of_node, "samsung,audio-widgets")) {
134 ret = snd_soc_of_parse_audio_simple_widgets(card,
135 "samsung,audio-widgets");
136 if (ret < 0)
137 return ret;
138 }
139
140 if (of_property_read_bool(dev->of_node, "samsung,audio-routing")) {
141 ret = snd_soc_of_parse_audio_routing(card,
142 "samsung,audio-routing");
143 if (ret < 0)
144 return ret;
145 }
146
147 link = &priv->dai_link;
148
149 link->ops = &odroid_card_ops;
150 link->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
151 SND_SOC_DAIFMT_CBS_CFS;
152
153 card->dai_link = &priv->dai_link;
154 card->num_links = 1;
155
156 cpu = of_get_child_by_name(dev->of_node, "cpu");
157 codec = of_get_child_by_name(dev->of_node, "codec");
158
159 link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
160 if (!link->cpu_of_node) {
161 dev_err(dev, "Failed parsing cpu/sound-dai property\n");
162 return -EINVAL;
163 }
164
165 ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
166 if (ret < 0)
167 goto err_put_codec_n;
168
169 link->platform_of_node = link->cpu_of_node;
170
171 link->name = "Primary";
172 link->stream_name = link->name;
173
174 ret = devm_snd_soc_register_card(dev, card);
175 if (ret < 0) {
176 dev_err(dev, "snd_soc_register_card() failed: %d\n", ret);
177 goto err_put_i2s_n;
178 }
179
180 return 0;
181
182err_put_i2s_n:
183 of_node_put(link->cpu_of_node);
184err_put_codec_n:
185 odroid_put_codec_of_nodes(link);
186 return ret;
187}
188
189static int odroid_audio_remove(struct platform_device *pdev)
190{
191 struct odroid_priv *priv = platform_get_drvdata(pdev);
192
193 of_node_put(priv->dai_link.cpu_of_node);
194 odroid_put_codec_of_nodes(&priv->dai_link);
195
196 return 0;
197}
198
199static const struct of_device_id odroid_audio_of_match[] = {
200 { .compatible = "samsung,odroid-xu3-audio" },
201 { .compatible = "samsung,odroid-xu4-audio"},
202 { },
203};
204MODULE_DEVICE_TABLE(of, odroid_audio_of_match);
205
206static struct platform_driver odroid_audio_driver = {
207 .driver = {
208 .name = "odroid-audio",
209 .of_match_table = odroid_audio_of_match,
210 .pm = &snd_soc_pm_ops,
211 },
212 .probe = odroid_audio_probe,
213 .remove = odroid_audio_remove,
214};
215module_platform_driver(odroid_audio_driver);
216
217MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
218MODULE_DESCRIPTION("Odroid XU3/XU4 audio support");
219MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 644f186fd35c..8f42deaa184b 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -72,7 +72,6 @@ static inline void dbg_showcon(const char *fn, u32 con)
72} 72}
73#endif 73#endif
74 74
75
76/* Turn on or off the transmission path. */ 75/* Turn on or off the transmission path. */
77static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on) 76static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
78{ 77{
diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c
index 3f2cce03275c..be066de74aaa 100644
--- a/sound/soc/sirf/sirf-audio-port.c
+++ b/sound/soc/sirf/sirf-audio-port.c
@@ -19,6 +19,7 @@ struct sirf_audio_port {
19static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) 19static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai)
20{ 20{
21 struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); 21 struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai);
22
22 snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, 23 snd_soc_dai_init_dma_data(dai, &port->playback_dma_data,
23 &port->capture_dma_data); 24 &port->capture_dma_data);
24 return 0; 25 return 0;
diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c
index 94ea152e0362..f2bc50790f76 100644
--- a/sound/soc/sirf/sirf-audio.c
+++ b/sound/soc/sirf/sirf-audio.c
@@ -27,6 +27,7 @@ static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w,
27 struct snd_soc_card *card = dapm->card; 27 struct snd_soc_card *card = dapm->card;
28 struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); 28 struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card);
29 int on = !SND_SOC_DAPM_EVENT_OFF(event); 29 int on = !SND_SOC_DAPM_EVENT_OFF(event);
30
30 if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) 31 if (gpio_is_valid(sirf_audio_card->gpio_hp_pa))
31 gpio_set_value(sirf_audio_card->gpio_hp_pa, on); 32 gpio_set_value(sirf_audio_card->gpio_hp_pa, on);
32 return 0; 33 return 0;
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c
index 45fc06c0e0e5..77e7dcf969d0 100644
--- a/sound/soc/sirf/sirf-usp.c
+++ b/sound/soc/sirf/sirf-usp.c
@@ -71,6 +71,7 @@ static void sirf_usp_rx_disable(struct sirf_usp *usp)
71static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai) 71static int sirf_usp_pcm_dai_probe(struct snd_soc_dai *dai)
72{ 72{
73 struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai); 73 struct sirf_usp *usp = snd_soc_dai_get_drvdata(dai);
74
74 snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data, 75 snd_soc_dai_init_dma_data(dai, &usp->playback_dma_data,
75 &usp->capture_dma_data); 76 &usp->capture_dma_data);
76 return 0; 77 return 0;
@@ -294,6 +295,7 @@ static struct snd_soc_dai_driver sirf_usp_pcm_dai = {
294static int sirf_usp_pcm_runtime_suspend(struct device *dev) 295static int sirf_usp_pcm_runtime_suspend(struct device *dev)
295{ 296{
296 struct sirf_usp *usp = dev_get_drvdata(dev); 297 struct sirf_usp *usp = dev_get_drvdata(dev);
298
297 clk_disable_unprepare(usp->clk); 299 clk_disable_unprepare(usp->clk);
298 return 0; 300 return 0;
299} 301}
@@ -302,6 +304,7 @@ static int sirf_usp_pcm_runtime_resume(struct device *dev)
302{ 304{
303 struct sirf_usp *usp = dev_get_drvdata(dev); 305 struct sirf_usp *usp = dev_get_drvdata(dev);
304 int ret; 306 int ret;
307
305 ret = clk_prepare_enable(usp->clk); 308 ret = clk_prepare_enable(usp->clk);
306 if (ret) { 309 if (ret) {
307 dev_err(dev, "clk_enable failed: %d\n", ret); 310 dev_err(dev, "clk_enable failed: %d\n", ret);