aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/max98090.txt2
-rw-r--r--arch/x86/include/asm/platform_sst_audio.h78
-rw-r--r--include/sound/rt286.h19
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/max98090.c42
-rw-r--r--sound/soc/codecs/mc13783.c6
-rw-r--r--sound/soc/codecs/rt286.c1224
-rw-r--r--sound/soc/codecs/rt286.h198
-rw-r--r--sound/soc/intel/Kconfig12
-rw-r--r--sound/soc/intel/Makefile2
-rw-r--r--sound/soc/intel/broadwell.c251
-rw-r--r--sound/soc/intel/byt-max98090.c8
-rw-r--r--sound/soc/intel/byt-rt5640.c1
-rw-r--r--sound/soc/intel/sst-atom-controls.h30
-rw-r--r--sound/soc/intel/sst-baytrail-ipc.c30
-rw-r--r--sound/soc/intel/sst-dsp.c10
-rw-r--r--sound/soc/intel/sst-dsp.h39
-rw-r--r--sound/soc/intel/sst-haswell-dsp.c57
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c40
-rw-r--r--sound/soc/intel/sst-mfld-dsp.h429
-rw-r--r--sound/soc/intel/sst-mfld-platform-compress.c11
-rw-r--r--sound/soc/intel/sst-mfld-platform-pcm.c319
-rw-r--r--sound/soc/intel/sst-mfld-platform.h29
-rw-r--r--sound/soc/kirkwood/Kconfig19
-rw-r--r--sound/soc/kirkwood/Makefile4
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c11
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c33
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c109
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c116
-rw-r--r--sound/soc/kirkwood/kirkwood.h7
31 files changed, 2695 insertions, 447 deletions
diff --git a/Documentation/devicetree/bindings/sound/max98090.txt b/Documentation/devicetree/bindings/sound/max98090.txt
index a5e63fa47dc5..c454e67f54bb 100644
--- a/Documentation/devicetree/bindings/sound/max98090.txt
+++ b/Documentation/devicetree/bindings/sound/max98090.txt
@@ -4,7 +4,7 @@ This device supports I2C only.
4 4
5Required properties: 5Required properties:
6 6
7- compatible : "maxim,max98090". 7- compatible : "maxim,max98090" or "maxim,max98091".
8 8
9- reg : The I2C address of the device. 9- reg : The I2C address of the device.
10 10
diff --git a/arch/x86/include/asm/platform_sst_audio.h b/arch/x86/include/asm/platform_sst_audio.h
new file mode 100644
index 000000000000..0a4e140315b6
--- /dev/null
+++ b/arch/x86/include/asm/platform_sst_audio.h
@@ -0,0 +1,78 @@
1/*
2 * platform_sst_audio.h: sst audio platform data header file
3 *
4 * Copyright (C) 2012-14 Intel Corporation
5 * Author: Jeeja KP <jeeja.kp@intel.com>
6 * Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
7 * Vinod Koul ,vinod.koul@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; version 2
12 * of the License.
13 */
14#ifndef _PLATFORM_SST_AUDIO_H_
15#define _PLATFORM_SST_AUDIO_H_
16
17#include <linux/sfi.h>
18
19enum sst_audio_task_id_mrfld {
20 SST_TASK_ID_NONE = 0,
21 SST_TASK_ID_SBA = 1,
22 SST_TASK_ID_MEDIA = 3,
23 SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
24};
25
26/* Device IDs for Merrifield are Pipe IDs,
27 * ref: DSP spec v0.75 */
28enum sst_audio_device_id_mrfld {
29 /* Output pipeline IDs */
30 PIPE_ID_OUT_START = 0x0,
31 PIPE_CODEC_OUT0 = 0x2,
32 PIPE_CODEC_OUT1 = 0x3,
33 PIPE_SPROT_LOOP_OUT = 0x4,
34 PIPE_MEDIA_LOOP1_OUT = 0x5,
35 PIPE_MEDIA_LOOP2_OUT = 0x6,
36 PIPE_VOIP_OUT = 0xC,
37 PIPE_PCM0_OUT = 0xD,
38 PIPE_PCM1_OUT = 0xE,
39 PIPE_PCM2_OUT = 0xF,
40 PIPE_MEDIA0_OUT = 0x12,
41 PIPE_MEDIA1_OUT = 0x13,
42/* Input Pipeline IDs */
43 PIPE_ID_IN_START = 0x80,
44 PIPE_CODEC_IN0 = 0x82,
45 PIPE_CODEC_IN1 = 0x83,
46 PIPE_SPROT_LOOP_IN = 0x84,
47 PIPE_MEDIA_LOOP1_IN = 0x85,
48 PIPE_MEDIA_LOOP2_IN = 0x86,
49 PIPE_VOIP_IN = 0x8C,
50 PIPE_PCM0_IN = 0x8D,
51 PIPE_PCM1_IN = 0x8E,
52 PIPE_MEDIA0_IN = 0x8F,
53 PIPE_MEDIA1_IN = 0x90,
54 PIPE_MEDIA2_IN = 0x91,
55 PIPE_RSVD = 0xFF,
56};
57
58/* The stream map for each platform consists of an array of the below
59 * stream map structure.
60 */
61struct sst_dev_stream_map {
62 u8 dev_num; /* device id */
63 u8 subdev_num; /* substream */
64 u8 direction;
65 u8 device_id; /* fw id */
66 u8 task_id; /* fw task */
67 u8 status;
68};
69
70struct sst_platform_data {
71 /* Intel software platform id*/
72 struct sst_dev_stream_map *pdev_strm_map;
73 unsigned int strm_map_size;
74};
75
76int add_sst_platform_device(void);
77#endif
78
diff --git a/include/sound/rt286.h b/include/sound/rt286.h
new file mode 100644
index 000000000000..eb773d1485f2
--- /dev/null
+++ b/include/sound/rt286.h
@@ -0,0 +1,19 @@
1/*
2 * linux/sound/rt286.h -- Platform data for RT286
3 *
4 * Copyright 2013 Realtek Microelectronics
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef __LINUX_SND_RT286_H
12#define __LINUX_SND_RT286_H
13
14struct rt286_platform_data {
15 bool cbj_en; /*combo jack enable*/
16 bool gpio2_en; /*GPIO2 enable*/
17};
18
19#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index e4a1d2aece36..4c7542571484 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -75,6 +75,7 @@ config SND_SOC_ALL_CODECS
75 select SND_SOC_PCM3008 75 select SND_SOC_PCM3008
76 select SND_SOC_PCM512x_I2C if I2C 76 select SND_SOC_PCM512x_I2C if I2C
77 select SND_SOC_PCM512x_SPI if SPI_MASTER 77 select SND_SOC_PCM512x_SPI if SPI_MASTER
78 select SND_SOC_RT286 if I2C
78 select SND_SOC_RT5631 if I2C 79 select SND_SOC_RT5631 if I2C
79 select SND_SOC_RT5640 if I2C 80 select SND_SOC_RT5640 if I2C
80 select SND_SOC_RT5645 if I2C 81 select SND_SOC_RT5645 if I2C
@@ -455,6 +456,9 @@ config SND_SOC_RL6231
455 default m if SND_SOC_RT5645=m 456 default m if SND_SOC_RT5645=m
456 default m if SND_SOC_RT5651=m 457 default m if SND_SOC_RT5651=m
457 458
459config SND_SOC_RT286
460 tristate
461
458config SND_SOC_RT5631 462config SND_SOC_RT5631
459 tristate 463 tristate
460 464
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 97b80a1e03af..ade412e49bd0 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -69,6 +69,7 @@ snd-soc-pcm512x-objs := pcm512x.o
69snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o 69snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
70snd-soc-pcm512x-spi-objs := pcm512x-spi.o 70snd-soc-pcm512x-spi-objs := pcm512x-spi.o
71snd-soc-rl6231-objs := rl6231.o 71snd-soc-rl6231-objs := rl6231.o
72snd-soc-rt286-objs := rt286.o
72snd-soc-rt5631-objs := rt5631.o 73snd-soc-rt5631-objs := rt5631.o
73snd-soc-rt5640-objs := rt5640.o 74snd-soc-rt5640-objs := rt5640.o
74snd-soc-rt5645-objs := rt5645.o 75snd-soc-rt5645-objs := rt5645.o
@@ -237,6 +238,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
237obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o 238obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
238obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o 239obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
239obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o 240obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
241obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
240obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o 242obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
241obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o 243obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
242obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o 244obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index d97f1ce7ff7d..4a063fa88526 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -26,10 +26,6 @@
26#include <sound/max98090.h> 26#include <sound/max98090.h>
27#include "max98090.h" 27#include "max98090.h"
28 28
29#define DEBUG
30#define EXTMIC_METHOD
31#define EXTMIC_METHOD_TEST
32
33/* Allows for sparsely populated register maps */ 29/* Allows for sparsely populated register maps */
34static struct reg_default max98090_reg[] = { 30static struct reg_default max98090_reg[] = {
35 { 0x00, 0x00 }, /* 00 Software Reset */ 31 { 0x00, 0x00 }, /* 00 Software Reset */
@@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
820 else 816 else
821 val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT; 817 val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT;
822 818
823
824 if (val >= 1) { 819 if (val >= 1) {
825 if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) { 820 if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) {
826 max98090->pa1en = val - 1; /* Update for volatile */ 821 max98090->pa1en = val - 1; /* Update for volatile */
@@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux =
1140 SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); 1135 SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum);
1141 1136
1142static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { 1137static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
1143
1144 SND_SOC_DAPM_INPUT("MIC1"), 1138 SND_SOC_DAPM_INPUT("MIC1"),
1145 SND_SOC_DAPM_INPUT("MIC2"), 1139 SND_SOC_DAPM_INPUT("MIC2"),
1146 SND_SOC_DAPM_INPUT("DMICL"), 1140 SND_SOC_DAPM_INPUT("DMICL"),
@@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
1304}; 1298};
1305 1299
1306static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { 1300static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
1307
1308 SND_SOC_DAPM_INPUT("DMIC3"), 1301 SND_SOC_DAPM_INPUT("DMIC3"),
1309 SND_SOC_DAPM_INPUT("DMIC4"), 1302 SND_SOC_DAPM_INPUT("DMIC4"),
1310 1303
@@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
1315}; 1308};
1316 1309
1317static const struct snd_soc_dapm_route max98090_dapm_routes[] = { 1310static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
1318
1319 {"MIC1 Input", NULL, "MIC1"}, 1311 {"MIC1 Input", NULL, "MIC1"},
1320 {"MIC2 Input", NULL, "MIC2"}, 1312 {"MIC2 Input", NULL, "MIC2"},
1321 1313
@@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
1493 {"SPKR", NULL, "SPK Right Out"}, 1485 {"SPKR", NULL, "SPK Right Out"},
1494 {"RCVL", NULL, "RCV Left Out"}, 1486 {"RCVL", NULL, "RCV Left Out"},
1495 {"RCVR", NULL, "RCV Right Out"}, 1487 {"RCVR", NULL, "RCV Right Out"},
1496
1497}; 1488};
1498 1489
1499static const struct snd_soc_dapm_route max98091_dapm_routes[] = { 1490static const struct snd_soc_dapm_route max98091_dapm_routes[] = {
1500
1501 /* DMIC inputs */ 1491 /* DMIC inputs */
1502 {"DMIC3", NULL, "DMIC3_ENA"}, 1492 {"DMIC3", NULL, "DMIC3_ENA"},
1503 {"DMIC4", NULL, "DMIC4_ENA"}, 1493 {"DMIC4", NULL, "DMIC4_ENA"},
1504 {"DMIC3", NULL, "AHPF"}, 1494 {"DMIC3", NULL, "AHPF"},
1505 {"DMIC4", NULL, "AHPF"}, 1495 {"DMIC4", NULL, "AHPF"},
1506
1507}; 1496};
1508 1497
1509static int max98090_add_widgets(struct snd_soc_codec *codec) 1498static int max98090_add_widgets(struct snd_soc_codec *codec)
@@ -1531,7 +1520,6 @@ static int max98090_add_widgets(struct snd_soc_codec *codec)
1531 1520
1532 snd_soc_dapm_add_routes(dapm, max98091_dapm_routes, 1521 snd_soc_dapm_add_routes(dapm, max98091_dapm_routes,
1533 ARRAY_SIZE(max98091_dapm_routes)); 1522 ARRAY_SIZE(max98091_dapm_routes));
1534
1535 } 1523 }
1536 1524
1537 return 0; 1525 return 0;
@@ -2212,22 +2200,11 @@ static struct snd_soc_dai_driver max98090_dai[] = {
2212} 2200}
2213}; 2201};
2214 2202
2215static void max98090_handle_pdata(struct snd_soc_codec *codec)
2216{
2217 struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
2218 struct max98090_pdata *pdata = max98090->pdata;
2219
2220 if (!pdata) {
2221 dev_err(codec->dev, "No platform data\n");
2222 return;
2223 }
2224
2225}
2226
2227static int max98090_probe(struct snd_soc_codec *codec) 2203static int max98090_probe(struct snd_soc_codec *codec)
2228{ 2204{
2229 struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); 2205 struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
2230 struct max98090_cdata *cdata; 2206 struct max98090_cdata *cdata;
2207 enum max98090_type devtype;
2231 int ret = 0; 2208 int ret = 0;
2232 2209
2233 dev_dbg(codec->dev, "max98090_probe\n"); 2210 dev_dbg(codec->dev, "max98090_probe\n");
@@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec)
2263 } 2240 }
2264 2241
2265 if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) { 2242 if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) {
2266 max98090->devtype = MAX98090; 2243 devtype = MAX98090;
2267 dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret); 2244 dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret);
2268 } else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) { 2245 } else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) {
2269 max98090->devtype = MAX98091; 2246 devtype = MAX98091;
2270 dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret); 2247 dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret);
2271 } else { 2248 } else {
2272 max98090->devtype = MAX98090; 2249 devtype = MAX98090;
2273 dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret); 2250 dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret);
2274 } 2251 }
2275 2252
2253 if (max98090->devtype != devtype) {
2254 dev_warn(codec->dev, "Mismatch in DT specified CODEC type.\n");
2255 max98090->devtype = devtype;
2256 }
2257
2276 max98090->jack_state = M98090_JACK_STATE_NO_HEADSET; 2258 max98090->jack_state = M98090_JACK_STATE_NO_HEADSET;
2277 2259
2278 INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); 2260 INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work);
@@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
2317 snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, 2299 snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
2318 M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); 2300 M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
2319 2301
2320 max98090_handle_pdata(codec);
2321
2322 max98090_add_widgets(codec); 2302 max98090_add_widgets(codec);
2323 2303
2324err_access: 2304err_access:
@@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev)
2428} 2408}
2429#endif 2409#endif
2430 2410
2431#ifdef CONFIG_PM 2411#ifdef CONFIG_PM_SLEEP
2432static int max98090_resume(struct device *dev) 2412static int max98090_resume(struct device *dev)
2433{ 2413{
2434 struct max98090_priv *max98090 = dev_get_drvdata(dev); 2414 struct max98090_priv *max98090 = dev_get_drvdata(dev);
@@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = {
2460 2440
2461static const struct i2c_device_id max98090_i2c_id[] = { 2441static const struct i2c_device_id max98090_i2c_id[] = {
2462 { "max98090", MAX98090 }, 2442 { "max98090", MAX98090 },
2443 { "max98091", MAX98091 },
2463 { } 2444 { }
2464}; 2445};
2465MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); 2446MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
2466 2447
2467static const struct of_device_id max98090_of_match[] = { 2448static const struct of_device_id max98090_of_match[] = {
2468 { .compatible = "maxim,max98090", }, 2449 { .compatible = "maxim,max98090", },
2450 { .compatible = "maxim,max98091", },
2469 { } 2451 { }
2470}; 2452};
2471MODULE_DEVICE_TABLE(of, max98090_of_match); 2453MODULE_DEVICE_TABLE(of, max98090_of_match);
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 9965277b595a..388f90a597fa 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -766,11 +766,11 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
766 766
767 ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port); 767 ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port);
768 if (ret) 768 if (ret)
769 return ret; 769 goto out;
770 770
771 ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); 771 ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port);
772 if (ret) 772 if (ret)
773 return ret; 773 goto out;
774 } 774 }
775 775
776 dev_set_drvdata(&pdev->dev, priv); 776 dev_set_drvdata(&pdev->dev, priv);
@@ -783,6 +783,8 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
783 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783, 783 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
784 mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); 784 mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async));
785 785
786out:
787 of_node_put(np);
786 return ret; 788 return ret;
787} 789}
788 790
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
new file mode 100644
index 000000000000..218f86efd196
--- /dev/null
+++ b/sound/soc/codecs/rt286.c
@@ -0,0 +1,1224 @@
1/*
2 * rt286.c -- RT286 ALSA SoC audio codec driver
3 *
4 * Copyright 2013 Realtek Semiconductor Corp.
5 * Author: Bard Liao <bardliao@realtek.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/pm.h>
17#include <linux/i2c.h>
18#include <linux/platform_device.h>
19#include <linux/spi/spi.h>
20#include <linux/acpi.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28#include <sound/jack.h>
29#include <linux/workqueue.h>
30#include <sound/rt286.h>
31#include <sound/hda_verbs.h>
32
33#include "rt286.h"
34
35#define RT286_VENDOR_ID 0x10ec0286
36
37struct rt286_priv {
38 struct regmap *regmap;
39 struct snd_soc_codec *codec;
40 struct rt286_platform_data pdata;
41 struct i2c_client *i2c;
42 struct snd_soc_jack *jack;
43 struct delayed_work jack_detect_work;
44 int sys_clk;
45 struct reg_default *index_cache;
46};
47
48static struct reg_default rt286_index_def[] = {
49 { 0x01, 0xaaaa },
50 { 0x02, 0x8aaa },
51 { 0x03, 0x0002 },
52 { 0x04, 0xaf01 },
53 { 0x08, 0x000d },
54 { 0x09, 0xd810 },
55 { 0x0a, 0x0060 },
56 { 0x0b, 0x0000 },
57 { 0x0d, 0x2800 },
58 { 0x0f, 0x0000 },
59 { 0x19, 0x0a17 },
60 { 0x20, 0x0020 },
61 { 0x33, 0x0208 },
62 { 0x49, 0x0004 },
63 { 0x4f, 0x50e9 },
64 { 0x50, 0x2c00 },
65 { 0x63, 0x2902 },
66 { 0x67, 0x1111 },
67 { 0x68, 0x1016 },
68 { 0x69, 0x273f },
69};
70#define INDEX_CACHE_SIZE ARRAY_SIZE(rt286_index_def)
71
72static const struct reg_default rt286_reg[] = {
73 { 0x00170500, 0x00000400 },
74 { 0x00220000, 0x00000031 },
75 { 0x00239000, 0x0000007f },
76 { 0x0023a000, 0x0000007f },
77 { 0x00270500, 0x00000400 },
78 { 0x00370500, 0x00000400 },
79 { 0x00870500, 0x00000400 },
80 { 0x00920000, 0x00000031 },
81 { 0x00935000, 0x000000c3 },
82 { 0x00936000, 0x000000c3 },
83 { 0x00970500, 0x00000400 },
84 { 0x00b37000, 0x00000097 },
85 { 0x00b37200, 0x00000097 },
86 { 0x00b37300, 0x00000097 },
87 { 0x00c37000, 0x00000000 },
88 { 0x00c37100, 0x00000080 },
89 { 0x01270500, 0x00000400 },
90 { 0x01370500, 0x00000400 },
91 { 0x01371f00, 0x411111f0 },
92 { 0x01439000, 0x00000080 },
93 { 0x0143a000, 0x00000080 },
94 { 0x01470700, 0x00000000 },
95 { 0x01470500, 0x00000400 },
96 { 0x01470c00, 0x00000000 },
97 { 0x01470100, 0x00000000 },
98 { 0x01837000, 0x00000000 },
99 { 0x01870500, 0x00000400 },
100 { 0x02050000, 0x00000000 },
101 { 0x02139000, 0x00000080 },
102 { 0x0213a000, 0x00000080 },
103 { 0x02170100, 0x00000000 },
104 { 0x02170500, 0x00000400 },
105 { 0x02170700, 0x00000000 },
106 { 0x02270100, 0x00000000 },
107 { 0x02370100, 0x00000000 },
108 { 0x02040000, 0x00004002 },
109 { 0x01870700, 0x00000020 },
110 { 0x00830000, 0x000000c3 },
111 { 0x00930000, 0x000000c3 },
112 { 0x01270700, 0x00000000 },
113};
114
115static bool rt286_volatile_register(struct device *dev, unsigned int reg)
116{
117 switch (reg) {
118 case 0 ... 0xff:
119 case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
120 case RT286_GET_HP_SENSE:
121 case RT286_GET_MIC1_SENSE:
122 case RT286_PROC_COEF:
123 return true;
124 default:
125 return false;
126 }
127
128
129}
130
131static bool rt286_readable_register(struct device *dev, unsigned int reg)
132{
133 switch (reg) {
134 case 0 ... 0xff:
135 case RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID):
136 case RT286_GET_HP_SENSE:
137 case RT286_GET_MIC1_SENSE:
138 case RT286_SET_AUDIO_POWER:
139 case RT286_SET_HPO_POWER:
140 case RT286_SET_SPK_POWER:
141 case RT286_SET_DMIC1_POWER:
142 case RT286_SPK_MUX:
143 case RT286_HPO_MUX:
144 case RT286_ADC0_MUX:
145 case RT286_ADC1_MUX:
146 case RT286_SET_MIC1:
147 case RT286_SET_PIN_HPO:
148 case RT286_SET_PIN_SPK:
149 case RT286_SET_PIN_DMIC1:
150 case RT286_SPK_EAPD:
151 case RT286_SET_AMP_GAIN_HPO:
152 case RT286_SET_DMIC2_DEFAULT:
153 case RT286_DACL_GAIN:
154 case RT286_DACR_GAIN:
155 case RT286_ADCL_GAIN:
156 case RT286_ADCR_GAIN:
157 case RT286_MIC_GAIN:
158 case RT286_SPOL_GAIN:
159 case RT286_SPOR_GAIN:
160 case RT286_HPOL_GAIN:
161 case RT286_HPOR_GAIN:
162 case RT286_F_DAC_SWITCH:
163 case RT286_F_RECMIX_SWITCH:
164 case RT286_REC_MIC_SWITCH:
165 case RT286_REC_I2S_SWITCH:
166 case RT286_REC_LINE_SWITCH:
167 case RT286_REC_BEEP_SWITCH:
168 case RT286_DAC_FORMAT:
169 case RT286_ADC_FORMAT:
170 case RT286_COEF_INDEX:
171 case RT286_PROC_COEF:
172 case RT286_SET_AMP_GAIN_ADC_IN1:
173 case RT286_SET_AMP_GAIN_ADC_IN2:
174 case RT286_SET_POWER(RT286_DAC_OUT1):
175 case RT286_SET_POWER(RT286_DAC_OUT2):
176 case RT286_SET_POWER(RT286_ADC_IN1):
177 case RT286_SET_POWER(RT286_ADC_IN2):
178 case RT286_SET_POWER(RT286_DMIC2):
179 case RT286_SET_POWER(RT286_MIC1):
180 return true;
181 default:
182 return false;
183 }
184}
185
186static int rt286_hw_write(void *context, unsigned int reg, unsigned int value)
187{
188 struct i2c_client *client = context;
189 struct rt286_priv *rt286 = i2c_get_clientdata(client);
190 u8 data[4];
191 int ret, i;
192
193 /*handle index registers*/
194 if (reg <= 0xff) {
195 rt286_hw_write(client, RT286_COEF_INDEX, reg);
196 reg = RT286_PROC_COEF;
197 for (i = 0; i < INDEX_CACHE_SIZE; i++) {
198 if (reg == rt286->index_cache[i].reg) {
199 rt286->index_cache[i].def = value;
200 break;
201 }
202
203 }
204 }
205
206 data[0] = (reg >> 24) & 0xff;
207 data[1] = (reg >> 16) & 0xff;
208 /*
209 * 4 bit VID: reg should be 0
210 * 12 bit VID: value should be 0
211 * So we use an OR operator to handle it rather than use if condition.
212 */
213 data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
214 data[3] = value & 0xff;
215
216 ret = i2c_master_send(client, data, 4);
217
218 if (ret == 4)
219 return 0;
220 else
221 pr_err("ret=%d\n", ret);
222 if (ret < 0)
223 return ret;
224 else
225 return -EIO;
226}
227
228static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value)
229{
230 struct i2c_client *client = context;
231 struct i2c_msg xfer[2];
232 int ret;
233 __be32 be_reg;
234 unsigned int index, vid, buf = 0x0;
235
236 /*handle index registers*/
237 if (reg <= 0xff) {
238 rt286_hw_write(client, RT286_COEF_INDEX, reg);
239 reg = RT286_PROC_COEF;
240 }
241
242 reg = reg | 0x80000;
243 vid = (reg >> 8) & 0xfff;
244
245 if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
246 index = (reg >> 8) & 0xf;
247 reg = (reg & ~0xf0f) | index;
248 }
249 be_reg = cpu_to_be32(reg);
250
251 /* Write register */
252 xfer[0].addr = client->addr;
253 xfer[0].flags = 0;
254 xfer[0].len = 4;
255 xfer[0].buf = (u8 *)&be_reg;
256
257 /* Read data */
258 xfer[1].addr = client->addr;
259 xfer[1].flags = I2C_M_RD;
260 xfer[1].len = 4;
261 xfer[1].buf = (u8 *)&buf;
262
263 ret = i2c_transfer(client->adapter, xfer, 2);
264 if (ret < 0)
265 return ret;
266 else if (ret != 2)
267 return -EIO;
268
269 *value = be32_to_cpu(buf);
270
271 return 0;
272}
273
274static void rt286_index_sync(struct snd_soc_codec *codec)
275{
276 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
277 int i;
278
279 for (i = 0; i < INDEX_CACHE_SIZE; i++) {
280 snd_soc_write(codec, rt286->index_cache[i].reg,
281 rt286->index_cache[i].def);
282 }
283}
284
285static int rt286_support_power_controls[] = {
286 RT286_DAC_OUT1,
287 RT286_DAC_OUT2,
288 RT286_ADC_IN1,
289 RT286_ADC_IN2,
290 RT286_MIC1,
291 RT286_DMIC1,
292 RT286_DMIC2,
293 RT286_SPK_OUT,
294 RT286_HP_OUT,
295};
296#define RT286_POWER_REG_LEN ARRAY_SIZE(rt286_support_power_controls)
297
298static int rt286_jack_detect(struct snd_soc_codec *codec, bool *hp, bool *mic)
299{
300 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
301 unsigned int val, buf;
302 int i;
303
304 *hp = false;
305 *mic = false;
306
307 if (rt286->pdata.cbj_en) {
308 buf = snd_soc_read(codec, RT286_GET_HP_SENSE);
309 *hp = buf & 0x80000000;
310 if (*hp) {
311 /* power on HV,VERF */
312 snd_soc_update_bits(codec,
313 RT286_POWER_CTRL1, 0x1001, 0x0);
314 /* power LDO1 */
315 snd_soc_update_bits(codec,
316 RT286_POWER_CTRL2, 0x4, 0x4);
317 snd_soc_write(codec, RT286_SET_MIC1, 0x24);
318 val = snd_soc_read(codec, RT286_CBJ_CTRL2);
319
320 msleep(200);
321 i = 40;
322 while (((val & 0x0800) == 0) && (i > 0)) {
323 val = snd_soc_read(codec,
324 RT286_CBJ_CTRL2);
325 i--;
326 msleep(20);
327 }
328
329 if (0x0400 == (val & 0x0700)) {
330 *mic = false;
331
332 snd_soc_write(codec,
333 RT286_SET_MIC1, 0x20);
334 /* power off HV,VERF */
335 snd_soc_update_bits(codec,
336 RT286_POWER_CTRL1, 0x1001, 0x1001);
337 snd_soc_update_bits(codec,
338 RT286_A_BIAS_CTRL3, 0xc000, 0x0000);
339 snd_soc_update_bits(codec,
340 RT286_CBJ_CTRL1, 0x0030, 0x0000);
341 snd_soc_update_bits(codec,
342 RT286_A_BIAS_CTRL2, 0xc000, 0x0000);
343 } else if ((0x0200 == (val & 0x0700)) ||
344 (0x0100 == (val & 0x0700))) {
345 *mic = true;
346 snd_soc_update_bits(codec,
347 RT286_A_BIAS_CTRL3, 0xc000, 0x8000);
348 snd_soc_update_bits(codec,
349 RT286_CBJ_CTRL1, 0x0030, 0x0020);
350 snd_soc_update_bits(codec,
351 RT286_A_BIAS_CTRL2, 0xc000, 0x8000);
352 } else {
353 *mic = false;
354 }
355
356 snd_soc_update_bits(codec,
357 RT286_MISC_CTRL1,
358 0x0060, 0x0000);
359 } else {
360 snd_soc_update_bits(codec,
361 RT286_MISC_CTRL1,
362 0x0060, 0x0020);
363 snd_soc_update_bits(codec,
364 RT286_A_BIAS_CTRL3,
365 0xc000, 0x8000);
366 snd_soc_update_bits(codec,
367 RT286_CBJ_CTRL1,
368 0x0030, 0x0020);
369 snd_soc_update_bits(codec,
370 RT286_A_BIAS_CTRL2,
371 0xc000, 0x8000);
372
373 *mic = false;
374 }
375 } else {
376 buf = snd_soc_read(codec, RT286_GET_HP_SENSE);
377 *hp = buf & 0x80000000;
378 buf = snd_soc_read(codec, RT286_GET_MIC1_SENSE);
379 *mic = buf & 0x80000000;
380 }
381
382 return 0;
383}
384
385static void rt286_jack_detect_work(struct work_struct *work)
386{
387 struct rt286_priv *rt286 =
388 container_of(work, struct rt286_priv, jack_detect_work.work);
389 int status = 0;
390 bool hp = false;
391 bool mic = false;
392
393 rt286_jack_detect(rt286->codec, &hp, &mic);
394
395 if (hp == true)
396 status |= SND_JACK_HEADPHONE;
397
398 if (mic == true)
399 status |= SND_JACK_MICROPHONE;
400
401 snd_soc_jack_report(rt286->jack, status,
402 SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
403}
404
405int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
406{
407 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
408
409 rt286->jack = jack;
410
411 /* Send an initial empty report */
412 snd_soc_jack_report(rt286->jack, 0,
413 SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
414
415 return 0;
416}
417EXPORT_SYMBOL_GPL(rt286_mic_detect);
418
419static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0);
420static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
421
422static const struct snd_kcontrol_new rt286_snd_controls[] = {
423 SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN,
424 RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv),
425 SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN,
426 RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv),
427 SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN,
428 0, 0x3, 0, mic_vol_tlv),
429 SOC_DOUBLE_R("Speaker Playback Switch", RT286_SPOL_GAIN,
430 RT286_SPOR_GAIN, RT286_MUTE_SFT, 1, 1),
431};
432
433/* Digital Mixer */
434static const struct snd_kcontrol_new rt286_front_mix[] = {
435 SOC_DAPM_SINGLE("DAC Switch", RT286_F_DAC_SWITCH,
436 RT286_MUTE_SFT, 1, 1),
437 SOC_DAPM_SINGLE("RECMIX Switch", RT286_F_RECMIX_SWITCH,
438 RT286_MUTE_SFT, 1, 1),
439};
440
441/* Analog Input Mixer */
442static const struct snd_kcontrol_new rt286_rec_mix[] = {
443 SOC_DAPM_SINGLE("Mic1 Switch", RT286_REC_MIC_SWITCH,
444 RT286_MUTE_SFT, 1, 1),
445 SOC_DAPM_SINGLE("I2S Switch", RT286_REC_I2S_SWITCH,
446 RT286_MUTE_SFT, 1, 1),
447 SOC_DAPM_SINGLE("Line1 Switch", RT286_REC_LINE_SWITCH,
448 RT286_MUTE_SFT, 1, 1),
449 SOC_DAPM_SINGLE("Beep Switch", RT286_REC_BEEP_SWITCH,
450 RT286_MUTE_SFT, 1, 1),
451};
452
453static const struct snd_kcontrol_new spo_enable_control =
454 SOC_DAPM_SINGLE("Switch", RT286_SET_PIN_SPK,
455 RT286_SET_PIN_SFT, 1, 0);
456
457static const struct snd_kcontrol_new hpol_enable_control =
458 SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOL_GAIN,
459 RT286_MUTE_SFT, 1, 1);
460
461static const struct snd_kcontrol_new hpor_enable_control =
462 SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT286_HPOR_GAIN,
463 RT286_MUTE_SFT, 1, 1);
464
465/* ADC0 source */
466static const char * const rt286_adc_src[] = {
467 "Mic", "RECMIX", "Dmic"
468};
469
470static const int rt286_adc_values[] = {
471 0, 4, 5,
472};
473
474static SOC_VALUE_ENUM_SINGLE_DECL(
475 rt286_adc0_enum, RT286_ADC0_MUX, RT286_ADC_SEL_SFT,
476 RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values);
477
478static const struct snd_kcontrol_new rt286_adc0_mux =
479 SOC_DAPM_ENUM("ADC 0 source", rt286_adc0_enum);
480
481static SOC_VALUE_ENUM_SINGLE_DECL(
482 rt286_adc1_enum, RT286_ADC1_MUX, RT286_ADC_SEL_SFT,
483 RT286_ADC_SEL_MASK, rt286_adc_src, rt286_adc_values);
484
485static const struct snd_kcontrol_new rt286_adc1_mux =
486 SOC_DAPM_ENUM("ADC 1 source", rt286_adc1_enum);
487
488static const char * const rt286_dac_src[] = {
489 "Front", "Surround"
490};
491/* HP-OUT source */
492static SOC_ENUM_SINGLE_DECL(rt286_hpo_enum, RT286_HPO_MUX,
493 0, rt286_dac_src);
494
495static const struct snd_kcontrol_new rt286_hpo_mux =
496SOC_DAPM_ENUM("HPO source", rt286_hpo_enum);
497
498/* SPK-OUT source */
499static SOC_ENUM_SINGLE_DECL(rt286_spo_enum, RT286_SPK_MUX,
500 0, rt286_dac_src);
501
502static const struct snd_kcontrol_new rt286_spo_mux =
503SOC_DAPM_ENUM("SPO source", rt286_spo_enum);
504
505static int rt286_spk_event(struct snd_soc_dapm_widget *w,
506 struct snd_kcontrol *kcontrol, int event)
507{
508 struct snd_soc_codec *codec = w->codec;
509
510 switch (event) {
511 case SND_SOC_DAPM_POST_PMU:
512 snd_soc_write(codec,
513 RT286_SPK_EAPD, RT286_SET_EAPD_HIGH);
514 break;
515 case SND_SOC_DAPM_PRE_PMD:
516 snd_soc_write(codec,
517 RT286_SPK_EAPD, RT286_SET_EAPD_LOW);
518 break;
519
520 default:
521 return 0;
522 }
523
524 return 0;
525}
526
527static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w,
528 struct snd_kcontrol *kcontrol, int event)
529{
530 struct snd_soc_codec *codec = w->codec;
531
532 switch (event) {
533 case SND_SOC_DAPM_POST_PMU:
534 snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0x20);
535 break;
536 case SND_SOC_DAPM_PRE_PMD:
537 snd_soc_write(codec, RT286_SET_PIN_DMIC1, 0);
538 break;
539 default:
540 return 0;
541 }
542
543 return 0;
544}
545
546static int rt286_adc_event(struct snd_soc_dapm_widget *w,
547 struct snd_kcontrol *kcontrol, int event)
548{
549 struct snd_soc_codec *codec = w->codec;
550 unsigned int nid;
551
552 nid = (w->reg >> 20) & 0xff;
553
554 switch (event) {
555 case SND_SOC_DAPM_POST_PMU:
556 snd_soc_update_bits(codec,
557 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
558 0x7080, 0x7000);
559 break;
560 case SND_SOC_DAPM_PRE_PMD:
561 snd_soc_update_bits(codec,
562 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0),
563 0x7080, 0x7080);
564 break;
565 default:
566 return 0;
567 }
568
569 return 0;
570}
571
572static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = {
573 /* Input Lines */
574 SND_SOC_DAPM_INPUT("DMIC1 Pin"),
575 SND_SOC_DAPM_INPUT("DMIC2 Pin"),
576 SND_SOC_DAPM_INPUT("MIC1"),
577 SND_SOC_DAPM_INPUT("LINE1"),
578 SND_SOC_DAPM_INPUT("Beep"),
579
580 /* DMIC */
581 SND_SOC_DAPM_PGA_E("DMIC1", RT286_SET_POWER(RT286_DMIC1), 0, 1,
582 NULL, 0, rt286_set_dmic1_event,
583 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
584 SND_SOC_DAPM_PGA("DMIC2", RT286_SET_POWER(RT286_DMIC2), 0, 1,
585 NULL, 0),
586 SND_SOC_DAPM_SUPPLY("DMIC Receiver", SND_SOC_NOPM,
587 0, 0, NULL, 0),
588
589 /* REC Mixer */
590 SND_SOC_DAPM_MIXER("RECMIX", SND_SOC_NOPM, 0, 0,
591 rt286_rec_mix, ARRAY_SIZE(rt286_rec_mix)),
592
593 /* ADCs */
594 SND_SOC_DAPM_ADC("ADC 0", NULL, SND_SOC_NOPM, 0, 0),
595 SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0),
596
597 /* ADC Mux */
598 SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1,
599 &rt286_adc0_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD |
600 SND_SOC_DAPM_POST_PMU),
601 SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1,
602 &rt286_adc1_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD |
603 SND_SOC_DAPM_POST_PMU),
604
605 /* Audio Interface */
606 SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
607 SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
608 SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
609 SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
610
611 /* Output Side */
612 /* DACs */
613 SND_SOC_DAPM_DAC("DAC 0", NULL, SND_SOC_NOPM, 0, 0),
614 SND_SOC_DAPM_DAC("DAC 1", NULL, SND_SOC_NOPM, 0, 0),
615
616 /* Output Mux */
617 SND_SOC_DAPM_MUX("SPK Mux", SND_SOC_NOPM, 0, 0, &rt286_spo_mux),
618 SND_SOC_DAPM_MUX("HPO Mux", SND_SOC_NOPM, 0, 0, &rt286_hpo_mux),
619
620 SND_SOC_DAPM_SUPPLY("HP Power", RT286_SET_PIN_HPO,
621 RT286_SET_PIN_SFT, 0, NULL, 0),
622
623 /* Output Mixer */
624 SND_SOC_DAPM_MIXER("Front", RT286_SET_POWER(RT286_DAC_OUT1), 0, 1,
625 rt286_front_mix, ARRAY_SIZE(rt286_front_mix)),
626 SND_SOC_DAPM_PGA("Surround", RT286_SET_POWER(RT286_DAC_OUT2), 0, 1,
627 NULL, 0),
628
629 /* Output Pga */
630 SND_SOC_DAPM_SWITCH_E("SPO", SND_SOC_NOPM, 0, 0,
631 &spo_enable_control, rt286_spk_event,
632 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
633 SND_SOC_DAPM_SWITCH("HPO L", SND_SOC_NOPM, 0, 0,
634 &hpol_enable_control),
635 SND_SOC_DAPM_SWITCH("HPO R", SND_SOC_NOPM, 0, 0,
636 &hpor_enable_control),
637
638 /* Output Lines */
639 SND_SOC_DAPM_OUTPUT("SPOL"),
640 SND_SOC_DAPM_OUTPUT("SPOR"),
641 SND_SOC_DAPM_OUTPUT("HPO Pin"),
642 SND_SOC_DAPM_OUTPUT("SPDIF"),
643};
644
645static const struct snd_soc_dapm_route rt286_dapm_routes[] = {
646 {"DMIC1", NULL, "DMIC1 Pin"},
647 {"DMIC2", NULL, "DMIC2 Pin"},
648 {"DMIC1", NULL, "DMIC Receiver"},
649 {"DMIC2", NULL, "DMIC Receiver"},
650
651 {"RECMIX", "Beep Switch", "Beep"},
652 {"RECMIX", "Line1 Switch", "LINE1"},
653 {"RECMIX", "Mic1 Switch", "MIC1"},
654
655 {"ADC 0 Mux", "Dmic", "DMIC1"},
656 {"ADC 0 Mux", "RECMIX", "RECMIX"},
657 {"ADC 0 Mux", "Mic", "MIC1"},
658 {"ADC 1 Mux", "Dmic", "DMIC2"},
659 {"ADC 1 Mux", "RECMIX", "RECMIX"},
660 {"ADC 1 Mux", "Mic", "MIC1"},
661
662 {"ADC 0", NULL, "ADC 0 Mux"},
663 {"ADC 1", NULL, "ADC 1 Mux"},
664
665 {"AIF1TX", NULL, "ADC 0"},
666 {"AIF2TX", NULL, "ADC 1"},
667
668 {"DAC 0", NULL, "AIF1RX"},
669 {"DAC 1", NULL, "AIF2RX"},
670
671 {"Front", "DAC Switch", "DAC 0"},
672 {"Front", "RECMIX Switch", "RECMIX"},
673
674 {"Surround", NULL, "DAC 1"},
675
676 {"SPK Mux", "Front", "Front"},
677 {"SPK Mux", "Surround", "Surround"},
678
679 {"HPO Mux", "Front", "Front"},
680 {"HPO Mux", "Surround", "Surround"},
681
682 {"SPO", "Switch", "SPK Mux"},
683 {"HPO L", "Switch", "HPO Mux"},
684 {"HPO R", "Switch", "HPO Mux"},
685 {"HPO L", NULL, "HP Power"},
686 {"HPO R", NULL, "HP Power"},
687
688 {"SPOL", NULL, "SPO"},
689 {"SPOR", NULL, "SPO"},
690 {"HPO Pin", NULL, "HPO L"},
691 {"HPO Pin", NULL, "HPO R"},
692};
693
694static int rt286_hw_params(struct snd_pcm_substream *substream,
695 struct snd_pcm_hw_params *params,
696 struct snd_soc_dai *dai)
697{
698 struct snd_soc_codec *codec = dai->codec;
699 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
700 unsigned int val = 0;
701 int d_len_code;
702
703 switch (params_rate(params)) {
704 /* bit 14 0:48K 1:44.1K */
705 case 44100:
706 val |= 0x4000;
707 break;
708 case 48000:
709 break;
710 default:
711 dev_err(codec->dev, "Unsupported sample rate %d\n",
712 params_rate(params));
713 return -EINVAL;
714 }
715 switch (rt286->sys_clk) {
716 case 12288000:
717 case 24576000:
718 if (params_rate(params) != 48000) {
719 dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
720 params_rate(params), rt286->sys_clk);
721 return -EINVAL;
722 }
723 break;
724 case 11289600:
725 case 22579200:
726 if (params_rate(params) != 44100) {
727 dev_err(codec->dev, "Sys_clk is not matched (%d %d)\n",
728 params_rate(params), rt286->sys_clk);
729 return -EINVAL;
730 }
731 break;
732 }
733
734 if (params_channels(params) <= 16) {
735 /* bit 3:0 Number of Channel */
736 val |= (params_channels(params) - 1);
737 } else {
738 dev_err(codec->dev, "Unsupported channels %d\n",
739 params_channels(params));
740 return -EINVAL;
741 }
742
743 d_len_code = 0;
744 switch (params_width(params)) {
745 /* bit 6:4 Bits per Sample */
746 case 16:
747 d_len_code = 0;
748 val |= (0x1 << 4);
749 break;
750 case 32:
751 d_len_code = 2;
752 val |= (0x4 << 4);
753 break;
754 case 20:
755 d_len_code = 1;
756 val |= (0x2 << 4);
757 break;
758 case 24:
759 d_len_code = 2;
760 val |= (0x3 << 4);
761 break;
762 case 8:
763 d_len_code = 3;
764 break;
765 default:
766 return -EINVAL;
767 }
768
769 snd_soc_update_bits(codec,
770 RT286_I2S_CTRL1, 0x0018, d_len_code << 3);
771 dev_dbg(codec->dev, "format val = 0x%x\n", val);
772
773 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
774 snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x407f, val);
775 else
776 snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x407f, val);
777
778 return 0;
779}
780
781static int rt286_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
782{
783 struct snd_soc_codec *codec = dai->codec;
784
785 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
786 case SND_SOC_DAIFMT_CBM_CFM:
787 snd_soc_update_bits(codec,
788 RT286_I2S_CTRL1, 0x800, 0x800);
789 break;
790 case SND_SOC_DAIFMT_CBS_CFS:
791 snd_soc_update_bits(codec,
792 RT286_I2S_CTRL1, 0x800, 0x0);
793 break;
794 default:
795 return -EINVAL;
796 }
797
798 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
799 case SND_SOC_DAIFMT_I2S:
800 snd_soc_update_bits(codec,
801 RT286_I2S_CTRL1, 0x300, 0x0);
802 break;
803 case SND_SOC_DAIFMT_LEFT_J:
804 snd_soc_update_bits(codec,
805 RT286_I2S_CTRL1, 0x300, 0x1 << 8);
806 break;
807 case SND_SOC_DAIFMT_DSP_A:
808 snd_soc_update_bits(codec,
809 RT286_I2S_CTRL1, 0x300, 0x2 << 8);
810 break;
811 case SND_SOC_DAIFMT_DSP_B:
812 snd_soc_update_bits(codec,
813 RT286_I2S_CTRL1, 0x300, 0x3 << 8);
814 break;
815 default:
816 return -EINVAL;
817 }
818 /* bit 15 Stream Type 0:PCM 1:Non-PCM */
819 snd_soc_update_bits(codec, RT286_DAC_FORMAT, 0x8000, 0);
820 snd_soc_update_bits(codec, RT286_ADC_FORMAT, 0x8000, 0);
821
822 return 0;
823}
824
825static int rt286_set_dai_sysclk(struct snd_soc_dai *dai,
826 int clk_id, unsigned int freq, int dir)
827{
828 struct snd_soc_codec *codec = dai->codec;
829 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
830
831 dev_dbg(codec->dev, "%s freq=%d\n", __func__, freq);
832
833 if (RT286_SCLK_S_MCLK == clk_id) {
834 snd_soc_update_bits(codec,
835 RT286_I2S_CTRL2, 0x0100, 0x0);
836 snd_soc_update_bits(codec,
837 RT286_PLL_CTRL1, 0x20, 0x20);
838 } else {
839 snd_soc_update_bits(codec,
840 RT286_I2S_CTRL2, 0x0100, 0x0100);
841 snd_soc_update_bits(codec,
842 RT286_PLL_CTRL, 0x4, 0x4);
843 snd_soc_update_bits(codec,
844 RT286_PLL_CTRL1, 0x20, 0x0);
845 }
846
847 switch (freq) {
848 case 19200000:
849 if (RT286_SCLK_S_MCLK == clk_id) {
850 dev_err(codec->dev, "Should not use MCLK\n");
851 return -EINVAL;
852 }
853 snd_soc_update_bits(codec,
854 RT286_I2S_CTRL2, 0x40, 0x40);
855 break;
856 case 24000000:
857 if (RT286_SCLK_S_MCLK == clk_id) {
858 dev_err(codec->dev, "Should not use MCLK\n");
859 return -EINVAL;
860 }
861 snd_soc_update_bits(codec,
862 RT286_I2S_CTRL2, 0x40, 0x0);
863 break;
864 case 12288000:
865 case 11289600:
866 snd_soc_update_bits(codec,
867 RT286_I2S_CTRL2, 0x8, 0x0);
868 snd_soc_update_bits(codec,
869 RT286_CLK_DIV, 0xfc1e, 0x0004);
870 break;
871 case 24576000:
872 case 22579200:
873 snd_soc_update_bits(codec,
874 RT286_I2S_CTRL2, 0x8, 0x8);
875 snd_soc_update_bits(codec,
876 RT286_CLK_DIV, 0xfc1e, 0x5406);
877 break;
878 default:
879 dev_err(codec->dev, "Unsupported system clock\n");
880 return -EINVAL;
881 }
882
883 rt286->sys_clk = freq;
884
885 return 0;
886}
887
888static int rt286_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
889{
890 struct snd_soc_codec *codec = dai->codec;
891
892 dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio);
893 if (50 == ratio)
894 snd_soc_update_bits(codec,
895 RT286_I2S_CTRL1, 0x1000, 0x1000);
896 else
897 snd_soc_update_bits(codec,
898 RT286_I2S_CTRL1, 0x1000, 0x0);
899
900
901 return 0;
902}
903
904static int rt286_set_bias_level(struct snd_soc_codec *codec,
905 enum snd_soc_bias_level level)
906{
907 switch (level) {
908 case SND_SOC_BIAS_PREPARE:
909 if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
910 snd_soc_write(codec,
911 RT286_SET_AUDIO_POWER, AC_PWRST_D0);
912 snd_soc_update_bits(codec,
913 RT286_DC_GAIN, 0x200, 0x200);
914 }
915 break;
916
917 case SND_SOC_BIAS_ON:
918 mdelay(10);
919 break;
920
921 case SND_SOC_BIAS_STANDBY:
922 snd_soc_write(codec,
923 RT286_SET_AUDIO_POWER, AC_PWRST_D3);
924 snd_soc_update_bits(codec,
925 RT286_DC_GAIN, 0x200, 0x0);
926 break;
927
928 default:
929 break;
930 }
931 codec->dapm.bias_level = level;
932
933 return 0;
934}
935
936static irqreturn_t rt286_irq(int irq, void *data)
937{
938 struct rt286_priv *rt286 = data;
939 bool hp = false;
940 bool mic = false;
941 int status = 0;
942
943 rt286_jack_detect(rt286->codec, &hp, &mic);
944
945 /* Clear IRQ */
946 snd_soc_update_bits(rt286->codec,
947 RT286_IRQ_CTRL, 0x1, 0x1);
948
949 if (hp == true)
950 status |= SND_JACK_HEADPHONE;
951
952 if (mic == true)
953 status |= SND_JACK_MICROPHONE;
954
955 snd_soc_jack_report(rt286->jack, status,
956 SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
957
958 pm_wakeup_event(&rt286->i2c->dev, 300);
959
960 return IRQ_HANDLED;
961}
962
963static int rt286_probe(struct snd_soc_codec *codec)
964{
965 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
966
967 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
968 rt286->codec = codec;
969
970 return 0;
971}
972
973static int rt286_remove(struct snd_soc_codec *codec)
974{
975 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
976
977 cancel_delayed_work_sync(&rt286->jack_detect_work);
978
979 return 0;
980}
981
982#ifdef CONFIG_PM
983static int rt286_suspend(struct snd_soc_codec *codec)
984{
985 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
986
987 regcache_cache_only(rt286->regmap, true);
988 regcache_mark_dirty(rt286->regmap);
989
990 return 0;
991}
992
993static int rt286_resume(struct snd_soc_codec *codec)
994{
995 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
996
997 regcache_cache_only(rt286->regmap, false);
998 rt286_index_sync(codec);
999 regcache_sync(rt286->regmap);
1000
1001 return 0;
1002}
1003#else
1004#define rt286_suspend NULL
1005#define rt286_resume NULL
1006#endif
1007
1008#define RT286_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
1009#define RT286_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1010 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
1011
1012static const struct snd_soc_dai_ops rt286_aif_dai_ops = {
1013 .hw_params = rt286_hw_params,
1014 .set_fmt = rt286_set_dai_fmt,
1015 .set_sysclk = rt286_set_dai_sysclk,
1016 .set_bclk_ratio = rt286_set_bclk_ratio,
1017};
1018
1019static struct snd_soc_dai_driver rt286_dai[] = {
1020 {
1021 .name = "rt286-aif1",
1022 .id = RT286_AIF1,
1023 .playback = {
1024 .stream_name = "AIF1 Playback",
1025 .channels_min = 1,
1026 .channels_max = 2,
1027 .rates = RT286_STEREO_RATES,
1028 .formats = RT286_FORMATS,
1029 },
1030 .capture = {
1031 .stream_name = "AIF1 Capture",
1032 .channels_min = 1,
1033 .channels_max = 2,
1034 .rates = RT286_STEREO_RATES,
1035 .formats = RT286_FORMATS,
1036 },
1037 .ops = &rt286_aif_dai_ops,
1038 .symmetric_rates = 1,
1039 },
1040 {
1041 .name = "rt286-aif2",
1042 .id = RT286_AIF2,
1043 .playback = {
1044 .stream_name = "AIF2 Playback",
1045 .channels_min = 1,
1046 .channels_max = 2,
1047 .rates = RT286_STEREO_RATES,
1048 .formats = RT286_FORMATS,
1049 },
1050 .capture = {
1051 .stream_name = "AIF2 Capture",
1052 .channels_min = 1,
1053 .channels_max = 2,
1054 .rates = RT286_STEREO_RATES,
1055 .formats = RT286_FORMATS,
1056 },
1057 .ops = &rt286_aif_dai_ops,
1058 .symmetric_rates = 1,
1059 },
1060
1061};
1062
1063static struct snd_soc_codec_driver soc_codec_dev_rt286 = {
1064 .probe = rt286_probe,
1065 .remove = rt286_remove,
1066 .suspend = rt286_suspend,
1067 .resume = rt286_resume,
1068 .set_bias_level = rt286_set_bias_level,
1069 .idle_bias_off = true,
1070 .controls = rt286_snd_controls,
1071 .num_controls = ARRAY_SIZE(rt286_snd_controls),
1072 .dapm_widgets = rt286_dapm_widgets,
1073 .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets),
1074 .dapm_routes = rt286_dapm_routes,
1075 .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes),
1076};
1077
1078static const struct regmap_config rt286_regmap = {
1079 .reg_bits = 32,
1080 .val_bits = 32,
1081 .max_register = 0x02370100,
1082 .volatile_reg = rt286_volatile_register,
1083 .readable_reg = rt286_readable_register,
1084 .reg_write = rt286_hw_write,
1085 .reg_read = rt286_hw_read,
1086 .cache_type = REGCACHE_RBTREE,
1087 .reg_defaults = rt286_reg,
1088 .num_reg_defaults = ARRAY_SIZE(rt286_reg),
1089};
1090
1091static const struct i2c_device_id rt286_i2c_id[] = {
1092 {"rt286", 0},
1093 {}
1094};
1095MODULE_DEVICE_TABLE(i2c, rt286_i2c_id);
1096
1097static const struct acpi_device_id rt286_acpi_match[] = {
1098 { "INT343A", 0 },
1099 {},
1100};
1101MODULE_DEVICE_TABLE(acpi, rt286_acpi_match);
1102
1103static int rt286_i2c_probe(struct i2c_client *i2c,
1104 const struct i2c_device_id *id)
1105{
1106 struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev);
1107 struct rt286_priv *rt286;
1108 int i, ret;
1109
1110 rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286),
1111 GFP_KERNEL);
1112 if (NULL == rt286)
1113 return -ENOMEM;
1114
1115 rt286->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt286_regmap);
1116 if (IS_ERR(rt286->regmap)) {
1117 ret = PTR_ERR(rt286->regmap);
1118 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
1119 ret);
1120 return ret;
1121 }
1122
1123 regmap_read(rt286->regmap,
1124 RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret);
1125 if (ret != RT286_VENDOR_ID) {
1126 dev_err(&i2c->dev,
1127 "Device with ID register %x is not rt286\n", ret);
1128 return -ENODEV;
1129 }
1130
1131 rt286->index_cache = rt286_index_def;
1132 rt286->i2c = i2c;
1133 i2c_set_clientdata(i2c, rt286);
1134
1135 if (pdata)
1136 rt286->pdata = *pdata;
1137
1138 regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3);
1139
1140 for (i = 0; i < RT286_POWER_REG_LEN; i++)
1141 regmap_write(rt286->regmap,
1142 RT286_SET_POWER(rt286_support_power_controls[i]),
1143 AC_PWRST_D1);
1144
1145 if (!rt286->pdata.cbj_en) {
1146 regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000);
1147 regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816);
1148 regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000);
1149 regmap_update_bits(rt286->regmap,
1150 RT286_CBJ_CTRL1, 0xf000, 0xb000);
1151 } else {
1152 regmap_update_bits(rt286->regmap,
1153 RT286_CBJ_CTRL1, 0xf000, 0x5000);
1154 }
1155
1156 mdelay(10);
1157
1158 if (!rt286->pdata.gpio2_en)
1159 regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x4000);
1160 else
1161 regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0);
1162
1163 mdelay(10);
1164
1165 /*Power down LDO2*/
1166 regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0x8, 0x0);
1167
1168 /*Set depop parameter*/
1169 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a);
1170 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737);
1171 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
1172
1173 if (rt286->i2c->irq) {
1174 regmap_update_bits(rt286->regmap,
1175 RT286_IRQ_CTRL, 0x2, 0x2);
1176
1177 INIT_DELAYED_WORK(&rt286->jack_detect_work,
1178 rt286_jack_detect_work);
1179 schedule_delayed_work(&rt286->jack_detect_work,
1180 msecs_to_jiffies(1250));
1181
1182 ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq,
1183 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286);
1184 if (ret != 0) {
1185 dev_err(&i2c->dev,
1186 "Failed to reguest IRQ: %d\n", ret);
1187 return ret;
1188 }
1189 }
1190
1191 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt286,
1192 rt286_dai, ARRAY_SIZE(rt286_dai));
1193
1194 return ret;
1195}
1196
1197static int rt286_i2c_remove(struct i2c_client *i2c)
1198{
1199 struct rt286_priv *rt286 = i2c_get_clientdata(i2c);
1200
1201 if (i2c->irq)
1202 free_irq(i2c->irq, rt286);
1203 snd_soc_unregister_codec(&i2c->dev);
1204
1205 return 0;
1206}
1207
1208
1209static struct i2c_driver rt286_i2c_driver = {
1210 .driver = {
1211 .name = "rt286",
1212 .owner = THIS_MODULE,
1213 .acpi_match_table = ACPI_PTR(rt286_acpi_match),
1214 },
1215 .probe = rt286_i2c_probe,
1216 .remove = rt286_i2c_remove,
1217 .id_table = rt286_i2c_id,
1218};
1219
1220module_i2c_driver(rt286_i2c_driver);
1221
1222MODULE_DESCRIPTION("ASoC RT286 driver");
1223MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
1224MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt286.h b/sound/soc/codecs/rt286.h
new file mode 100644
index 000000000000..b539b7320a79
--- /dev/null
+++ b/sound/soc/codecs/rt286.h
@@ -0,0 +1,198 @@
1/*
2 * rt286.h -- RT286 ALSA SoC audio driver
3 *
4 * Copyright 2011 Realtek Microelectronics
5 * Author: Johnny Hsu <johnnyhsu@realtek.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __RT286_H__
13#define __RT286_H__
14
15#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)
16
17#define RT286_AUDIO_FUNCTION_GROUP 0x01
18#define RT286_DAC_OUT1 0x02
19#define RT286_DAC_OUT2 0x03
20#define RT286_ADC_IN1 0x09
21#define RT286_ADC_IN2 0x08
22#define RT286_MIXER_IN 0x0b
23#define RT286_MIXER_OUT1 0x0c
24#define RT286_MIXER_OUT2 0x0d
25#define RT286_DMIC1 0x12
26#define RT286_DMIC2 0x13
27#define RT286_SPK_OUT 0x14
28#define RT286_MIC1 0x18
29#define RT286_LINE1 0x1a
30#define RT286_BEEP 0x1d
31#define RT286_SPDIF 0x1e
32#define RT286_VENDOR_REGISTERS 0x20
33#define RT286_HP_OUT 0x21
34#define RT286_MIXER_IN1 0x22
35#define RT286_MIXER_IN2 0x23
36
37#define RT286_SET_PIN_SFT 6
38#define RT286_SET_PIN_ENABLE 0x40
39#define RT286_SET_PIN_DISABLE 0
40#define RT286_SET_EAPD_HIGH 0x2
41#define RT286_SET_EAPD_LOW 0
42
43#define RT286_MUTE_SFT 7
44
45/* Verb commands */
46#define RT286_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM)
47#define RT286_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0)
48#define RT286_SET_AUDIO_POWER RT286_SET_POWER(RT286_AUDIO_FUNCTION_GROUP)
49#define RT286_SET_HPO_POWER RT286_SET_POWER(RT286_HP_OUT)
50#define RT286_SET_SPK_POWER RT286_SET_POWER(RT286_SPK_OUT)
51#define RT286_SET_DMIC1_POWER RT286_SET_POWER(RT286_DMIC1)
52#define RT286_SPK_MUX\
53 VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_SPK_OUT, 0)
54#define RT286_HPO_MUX\
55 VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_HP_OUT, 0)
56#define RT286_ADC0_MUX\
57 VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN1, 0)
58#define RT286_ADC1_MUX\
59 VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN2, 0)
60#define RT286_SET_MIC1\
61 VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_MIC1, 0)
62#define RT286_SET_PIN_HPO\
63 VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_HP_OUT, 0)
64#define RT286_SET_PIN_SPK\
65 VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_SPK_OUT, 0)
66#define RT286_SET_PIN_DMIC1\
67 VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_DMIC1, 0)
68#define RT286_SPK_EAPD\
69 VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT286_SPK_OUT, 0)
70#define RT286_SET_AMP_GAIN_HPO\
71 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0)
72#define RT286_SET_AMP_GAIN_ADC_IN1\
73 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0)
74#define RT286_SET_AMP_GAIN_ADC_IN2\
75 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN2, 0)
76#define RT286_GET_HP_SENSE\
77 VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_HP_OUT, 0)
78#define RT286_GET_MIC1_SENSE\
79 VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_MIC1, 0)
80#define RT286_SET_DMIC2_DEFAULT\
81 VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT286_DMIC2, 0)
82#define RT286_DACL_GAIN\
83 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0xa000)
84#define RT286_DACR_GAIN\
85 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0x9000)
86#define RT286_ADCL_GAIN\
87 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x6000)
88#define RT286_ADCR_GAIN\
89 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x5000)
90#define RT286_MIC_GAIN\
91 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIC1, 0x7000)
92#define RT286_SPOL_GAIN\
93 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0xa000)
94#define RT286_SPOR_GAIN\
95 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0x9000)
96#define RT286_HPOL_GAIN\
97 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0xa000)
98#define RT286_HPOR_GAIN\
99 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0x9000)
100#define RT286_F_DAC_SWITCH\
101 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7000)
102#define RT286_F_RECMIX_SWITCH\
103 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7100)
104#define RT286_REC_MIC_SWITCH\
105 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7000)
106#define RT286_REC_I2S_SWITCH\
107 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7100)
108#define RT286_REC_LINE_SWITCH\
109 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7200)
110#define RT286_REC_BEEP_SWITCH\
111 VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7300)
112#define RT286_DAC_FORMAT\
113 VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_DAC_OUT1, 0)
114#define RT286_ADC_FORMAT\
115 VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_ADC_IN1, 0)
116#define RT286_COEF_INDEX\
117 VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0)
118#define RT286_PROC_COEF\
119 VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0)
120
121/* Index registers */
122#define RT286_A_BIAS_CTRL1 0x01
123#define RT286_A_BIAS_CTRL2 0x02
124#define RT286_POWER_CTRL1 0x03
125#define RT286_A_BIAS_CTRL3 0x04
126#define RT286_POWER_CTRL2 0x08
127#define RT286_I2S_CTRL1 0x09
128#define RT286_I2S_CTRL2 0x0a
129#define RT286_CLK_DIV 0x0b
130#define RT286_DC_GAIN 0x0d
131#define RT286_POWER_CTRL3 0x0f
132#define RT286_MIC1_DET_CTRL 0x19
133#define RT286_MISC_CTRL1 0x20
134#define RT286_IRQ_CTRL 0x33
135#define RT286_PLL_CTRL1 0x49
136#define RT286_CBJ_CTRL1 0x4f
137#define RT286_CBJ_CTRL2 0x50
138#define RT286_PLL_CTRL 0x63
139#define RT286_DEPOP_CTRL1 0x66
140#define RT286_DEPOP_CTRL2 0x67
141#define RT286_DEPOP_CTRL3 0x68
142#define RT286_DEPOP_CTRL4 0x69
143
144/* SPDIF (0x06) */
145#define RT286_SPDIF_SEL_SFT 0
146#define RT286_SPDIF_SEL_PCM0 0
147#define RT286_SPDIF_SEL_PCM1 1
148#define RT286_SPDIF_SEL_SPOUT 2
149#define RT286_SPDIF_SEL_PP 3
150
151/* RECMIX (0x0b) */
152#define RT286_M_REC_BEEP_SFT 0
153#define RT286_M_REC_LINE1_SFT 1
154#define RT286_M_REC_MIC1_SFT 2
155#define RT286_M_REC_I2S_SFT 3
156
157/* Front (0x0c) */
158#define RT286_M_FRONT_DAC_SFT 0
159#define RT286_M_FRONT_REC_SFT 1
160
161/* SPK-OUT (0x14) */
162#define RT286_M_SPK_MUX_SFT 14
163#define RT286_SPK_SEL_MASK 0x1
164#define RT286_SPK_SEL_SFT 0
165#define RT286_SPK_SEL_F 0
166#define RT286_SPK_SEL_S 1
167
168/* HP-OUT (0x21) */
169#define RT286_M_HP_MUX_SFT 14
170#define RT286_HP_SEL_MASK 0x1
171#define RT286_HP_SEL_SFT 0
172#define RT286_HP_SEL_F 0
173#define RT286_HP_SEL_S 1
174
175/* ADC (0x22) (0x23) */
176#define RT286_ADC_SEL_MASK 0x7
177#define RT286_ADC_SEL_SFT 0
178#define RT286_ADC_SEL_SURR 0
179#define RT286_ADC_SEL_FRONT 1
180#define RT286_ADC_SEL_DMIC 2
181#define RT286_ADC_SEL_BEEP 4
182#define RT286_ADC_SEL_LINE1 5
183#define RT286_ADC_SEL_I2S 6
184#define RT286_ADC_SEL_MIC1 7
185
186#define RT286_SCLK_S_MCLK 0
187#define RT286_SCLK_S_PLL 1
188
189enum {
190 RT286_AIF1,
191 RT286_AIF2,
192 RT286_AIFS,
193};
194
195int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
196
197#endif /* __RT286_H__ */
198
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index c30fedb3e149..f5b4a9c79cdf 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -58,3 +58,15 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH
58 help 58 help
59 This adds audio driver for Intel Baytrail platform based boards 59 This adds audio driver for Intel Baytrail platform based boards
60 with the MAX98090 audio codec. 60 with the MAX98090 audio codec.
61
62config SND_SOC_INTEL_BROADWELL_MACH
63 tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
64 depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC
65 select SND_SOC_INTEL_HASWELL
66 select SND_COMPRESS_OFFLOAD
67 select SND_SOC_RT286
68 help
69 This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell
70 Ultrabook platforms.
71 Say Y if you have such a device
72 If unsure select "N".
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index 4bfca79a42ba..7acbfc43a0c6 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -24,7 +24,9 @@ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o
24snd-soc-sst-haswell-objs := haswell.o 24snd-soc-sst-haswell-objs := haswell.o
25snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o 25snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
26snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o 26snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
27snd-soc-sst-broadwell-objs := broadwell.o
27 28
28obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o 29obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
29obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o 30obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
30obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o 31obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
32obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c
new file mode 100644
index 000000000000..0e550f14028f
--- /dev/null
+++ b/sound/soc/intel/broadwell.c
@@ -0,0 +1,251 @@
1/*
2 * Intel Broadwell Wildcatpoint SST Audio
3 *
4 * Copyright (C) 2013, Intel Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/soc.h>
22#include <sound/pcm_params.h>
23
24#include "sst-dsp.h"
25#include "sst-haswell-ipc.h"
26
27#include "../codecs/rt286.h"
28
29static const struct snd_soc_dapm_widget broadwell_widgets[] = {
30 SND_SOC_DAPM_HP("Headphones", NULL),
31 SND_SOC_DAPM_SPK("Speaker", NULL),
32 SND_SOC_DAPM_MIC("Mic Jack", NULL),
33 SND_SOC_DAPM_MIC("DMIC1", NULL),
34 SND_SOC_DAPM_MIC("DMIC2", NULL),
35 SND_SOC_DAPM_LINE("Line Jack", NULL),
36};
37
38static const struct snd_soc_dapm_route broadwell_rt286_map[] = {
39
40 /* speaker */
41 {"Speaker", NULL, "SPOR"},
42 {"Speaker", NULL, "SPOL"},
43
44 /* HP jack connectors - unknown if we have jack deteck */
45 {"Headphones", NULL, "HPO Pin"},
46
47 /* other jacks */
48 {"MIC1", NULL, "Mic Jack"},
49 {"LINE1", NULL, "Line Jack"},
50
51 /* digital mics */
52 {"DMIC1 Pin", NULL, "DMIC1"},
53 {"DMIC2 Pin", NULL, "DMIC2"},
54
55 /* CODEC BE connections */
56 {"SSP0 CODEC IN", NULL, "AIF1 Capture"},
57 {"AIF1 Playback", NULL, "SSP0 CODEC OUT"},
58};
59
60static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
61 struct snd_pcm_hw_params *params)
62{
63 struct snd_interval *rate = hw_param_interval(params,
64 SNDRV_PCM_HW_PARAM_RATE);
65 struct snd_interval *channels = hw_param_interval(params,
66 SNDRV_PCM_HW_PARAM_CHANNELS);
67
68 /* The ADSP will covert the FE rate to 48k, stereo */
69 rate->min = rate->max = 48000;
70 channels->min = channels->max = 2;
71
72 /* set SSP0 to 16 bit */
73 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
74 SNDRV_PCM_HW_PARAM_FIRST_MASK],
75 SNDRV_PCM_FORMAT_S16_LE);
76 return 0;
77}
78
79static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream,
80 struct snd_pcm_hw_params *params)
81{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_dai *codec_dai = rtd->codec_dai;
84 int ret;
85
86 ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000,
87 SND_SOC_CLOCK_IN);
88
89 if (ret < 0) {
90 dev_err(rtd->dev, "can't set codec sysclk configuration\n");
91 return ret;
92 }
93
94 return ret;
95}
96
97static struct snd_soc_ops broadwell_rt286_ops = {
98 .hw_params = broadwell_rt286_hw_params,
99};
100
101static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd)
102{
103 struct snd_soc_codec *codec = rtd->codec;
104 struct snd_soc_dapm_context *dapm = &codec->dapm;
105 struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev);
106 struct sst_hsw *broadwell = pdata->dsp;
107 int ret;
108
109 /* Set ADSP SSP port settings */
110 ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0,
111 SST_HSW_DEVICE_MCLK_FREQ_24_MHZ,
112 SST_HSW_DEVICE_CLOCK_MASTER, 9);
113 if (ret < 0) {
114 dev_err(rtd->dev, "error: failed to set device config\n");
115 return ret;
116 }
117
118 /* always connected - check HP for jack detect */
119 snd_soc_dapm_enable_pin(dapm, "Headphones");
120 snd_soc_dapm_enable_pin(dapm, "Speaker");
121 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
122 snd_soc_dapm_enable_pin(dapm, "Line Jack");
123 snd_soc_dapm_enable_pin(dapm, "DMIC1");
124 snd_soc_dapm_enable_pin(dapm, "DMIC2");
125
126 return 0;
127}
128
129/* broadwell digital audio interface glue - connects codec <--> CPU */
130static struct snd_soc_dai_link broadwell_rt286_dais[] = {
131 /* Front End DAI links */
132 {
133 .name = "System PCM",
134 .stream_name = "System Playback",
135 .cpu_dai_name = "System Pin",
136 .platform_name = "haswell-pcm-audio",
137 .dynamic = 1,
138 .codec_name = "snd-soc-dummy",
139 .codec_dai_name = "snd-soc-dummy-dai",
140 .init = broadwell_rtd_init,
141 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
142 .dpcm_playback = 1,
143 },
144 {
145 .name = "Offload0",
146 .stream_name = "Offload0 Playback",
147 .cpu_dai_name = "Offload0 Pin",
148 .platform_name = "haswell-pcm-audio",
149 .dynamic = 1,
150 .codec_name = "snd-soc-dummy",
151 .codec_dai_name = "snd-soc-dummy-dai",
152 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
153 .dpcm_playback = 1,
154 },
155 {
156 .name = "Offload1",
157 .stream_name = "Offload1 Playback",
158 .cpu_dai_name = "Offload1 Pin",
159 .platform_name = "haswell-pcm-audio",
160 .dynamic = 1,
161 .codec_name = "snd-soc-dummy",
162 .codec_dai_name = "snd-soc-dummy-dai",
163 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
164 .dpcm_playback = 1,
165 },
166 {
167 .name = "Loopback PCM",
168 .stream_name = "Loopback",
169 .cpu_dai_name = "Loopback Pin",
170 .platform_name = "haswell-pcm-audio",
171 .dynamic = 0,
172 .codec_name = "snd-soc-dummy",
173 .codec_dai_name = "snd-soc-dummy-dai",
174 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
175 .dpcm_capture = 1,
176 },
177 {
178 .name = "Capture PCM",
179 .stream_name = "Capture",
180 .cpu_dai_name = "Capture Pin",
181 .platform_name = "haswell-pcm-audio",
182 .dynamic = 1,
183 .codec_name = "snd-soc-dummy",
184 .codec_dai_name = "snd-soc-dummy-dai",
185 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
186 .dpcm_capture = 1,
187 },
188
189 /* Back End DAI links */
190 {
191 /* SSP0 - Codec */
192 .name = "Codec",
193 .be_id = 0,
194 .cpu_dai_name = "snd-soc-dummy-dai",
195 .platform_name = "snd-soc-dummy",
196 .no_pcm = 1,
197 .codec_name = "i2c-INT343A:00",
198 .codec_dai_name = "rt286-aif1",
199 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
200 SND_SOC_DAIFMT_CBS_CFS,
201 .ignore_suspend = 1,
202 .ignore_pmdown_time = 1,
203 .be_hw_params_fixup = broadwell_ssp0_fixup,
204 .ops = &broadwell_rt286_ops,
205 .dpcm_playback = 1,
206 .dpcm_capture = 1,
207 },
208};
209
210/* broadwell audio machine driver for WPT + RT286S */
211static struct snd_soc_card broadwell_rt286 = {
212 .name = "broadwell-rt286",
213 .owner = THIS_MODULE,
214 .dai_link = broadwell_rt286_dais,
215 .num_links = ARRAY_SIZE(broadwell_rt286_dais),
216 .dapm_widgets = broadwell_widgets,
217 .num_dapm_widgets = ARRAY_SIZE(broadwell_widgets),
218 .dapm_routes = broadwell_rt286_map,
219 .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map),
220 .fully_routed = true,
221};
222
223static int broadwell_audio_probe(struct platform_device *pdev)
224{
225 broadwell_rt286.dev = &pdev->dev;
226
227 return snd_soc_register_card(&broadwell_rt286);
228}
229
230static int broadwell_audio_remove(struct platform_device *pdev)
231{
232 snd_soc_unregister_card(&broadwell_rt286);
233 return 0;
234}
235
236static struct platform_driver broadwell_audio = {
237 .probe = broadwell_audio_probe,
238 .remove = broadwell_audio_remove,
239 .driver = {
240 .name = "broadwell-audio",
241 .owner = THIS_MODULE,
242 },
243};
244
245module_platform_driver(broadwell_audio)
246
247/* Module information */
248MODULE_AUTHOR("Liam Girdwood, Xingchao Wang");
249MODULE_DESCRIPTION("Intel SST Audio for WPT/Broadwell");
250MODULE_LICENSE("GPL v2");
251MODULE_ALIAS("platform:broadwell-audio");
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/byt-max98090.c
index 5cfb41ec3fab..b8b8af571ef1 100644
--- a/sound/soc/intel/byt-max98090.c
+++ b/sound/soc/intel/byt-max98090.c
@@ -63,14 +63,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
63 .pin = "Headset Mic", 63 .pin = "Headset Mic",
64 .mask = SND_JACK_MICROPHONE, 64 .mask = SND_JACK_MICROPHONE,
65 }, 65 },
66 {
67 .pin = "Ext Spk",
68 .mask = SND_JACK_LINEOUT,
69 },
70 {
71 .pin = "Int Mic",
72 .mask = SND_JACK_LINEIN,
73 },
74}; 66};
75 67
76static struct snd_soc_jack_gpio hs_jack_gpios[] = { 68static struct snd_soc_jack_gpio hs_jack_gpios[] = {
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c
index 53d160d39972..234a58de3c53 100644
--- a/sound/soc/intel/byt-rt5640.c
+++ b/sound/soc/intel/byt-rt5640.c
@@ -34,6 +34,7 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
34}; 34};
35 35
36static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { 36static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
37 {"Headset Mic", NULL, "MICBIAS1"},
37 {"IN2P", NULL, "Headset Mic"}, 38 {"IN2P", NULL, "Headset Mic"},
38 {"IN2N", NULL, "Headset Mic"}, 39 {"IN2N", NULL, "Headset Mic"},
39 {"DMIC1", NULL, "Internal Mic"}, 40 {"DMIC1", NULL, "Internal Mic"},
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h
new file mode 100644
index 000000000000..14063ab8c7c5
--- /dev/null
+++ b/sound/soc/intel/sst-atom-controls.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2013-14 Intel Corp
3 * Author: Ramesh Babu <ramesh.babu.koul@intel.com>
4 * Omair M Abdullah <omair.m.abdullah@intel.com>
5 * Samreen Nilofer <samreen.nilofer@intel.com>
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 *
19 */
20
21#ifndef __SST_CONTROLS_V2_H__
22#define __SST_CONTROLS_V2_H__
23
24enum {
25 MERR_DPCM_AUDIO = 0,
26 MERR_DPCM_COMPR,
27};
28
29
30#endif
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c
index d207b22ea330..67673a2c0f41 100644
--- a/sound/soc/intel/sst-baytrail-ipc.c
+++ b/sound/soc/intel/sst-baytrail-ipc.c
@@ -122,6 +122,26 @@ struct sst_byt_tstamp {
122 u32 channel_peak[8]; 122 u32 channel_peak[8];
123} __packed; 123} __packed;
124 124
125struct sst_byt_fw_version {
126 u8 build;
127 u8 minor;
128 u8 major;
129 u8 type;
130} __packed;
131
132struct sst_byt_fw_build_info {
133 u8 date[16];
134 u8 time[16];
135} __packed;
136
137struct sst_byt_fw_init {
138 struct sst_byt_fw_version fw_version;
139 struct sst_byt_fw_build_info build_info;
140 u16 result;
141 u8 module_id;
142 u8 debug_info;
143} __packed;
144
125/* driver internal IPC message structure */ 145/* driver internal IPC message structure */
126struct ipc_message { 146struct ipc_message {
127 struct list_head list; 147 struct list_head list;
@@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
868{ 888{
869 struct sst_byt *byt; 889 struct sst_byt *byt;
870 struct sst_fw *byt_sst_fw; 890 struct sst_fw *byt_sst_fw;
891 struct sst_byt_fw_init init;
871 int err; 892 int err;
872 893
873 dev_dbg(dev, "initialising Byt DSP IPC\n"); 894 dev_dbg(dev, "initialising Byt DSP IPC\n");
@@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
929 goto boot_err; 950 goto boot_err;
930 } 951 }
931 952
953 /* show firmware information */
954 sst_dsp_inbox_read(byt->dsp, &init, sizeof(init));
955 dev_info(byt->dev, "FW version: %02x.%02x.%02x.%02x\n",
956 init.fw_version.major, init.fw_version.minor,
957 init.fw_version.build, init.fw_version.type);
958 dev_info(byt->dev, "Build type: %x\n", init.fw_version.type);
959 dev_info(byt->dev, "Build date: %s %s\n",
960 init.build_info.date, init.build_info.time);
961
932 pdata->dsp = byt; 962 pdata->dsp = byt;
933 byt->fw = byt_sst_fw; 963 byt->fw = byt_sst_fw;
934 964
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c
index 0b715b20a2d7..cd23060a0d86 100644
--- a/sound/soc/intel/sst-dsp.c
+++ b/sound/soc/intel/sst-dsp.c
@@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64);
224 224
225void sst_dsp_dump(struct sst_dsp *sst) 225void sst_dsp_dump(struct sst_dsp *sst)
226{ 226{
227 sst->ops->dump(sst); 227 if (sst->ops->dump)
228 sst->ops->dump(sst);
228} 229}
229EXPORT_SYMBOL_GPL(sst_dsp_dump); 230EXPORT_SYMBOL_GPL(sst_dsp_dump);
230 231
231void sst_dsp_reset(struct sst_dsp *sst) 232void sst_dsp_reset(struct sst_dsp *sst)
232{ 233{
233 sst->ops->reset(sst); 234 if (sst->ops->reset)
235 sst->ops->reset(sst);
234} 236}
235EXPORT_SYMBOL_GPL(sst_dsp_reset); 237EXPORT_SYMBOL_GPL(sst_dsp_reset);
236 238
237int sst_dsp_boot(struct sst_dsp *sst) 239int sst_dsp_boot(struct sst_dsp *sst)
238{ 240{
239 sst->ops->boot(sst); 241 if (sst->ops->boot)
242 sst->ops->boot(sst);
243
240 return 0; 244 return 0;
241} 245}
242EXPORT_SYMBOL_GPL(sst_dsp_boot); 246EXPORT_SYMBOL_GPL(sst_dsp_boot);
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h
index e44423be66c4..3165dfa97408 100644
--- a/sound/soc/intel/sst-dsp.h
+++ b/sound/soc/intel/sst-dsp.h
@@ -52,7 +52,11 @@
52#define SST_CLKCTL 0x78 52#define SST_CLKCTL 0x78
53#define SST_CSR2 0x80 53#define SST_CSR2 0x80
54#define SST_LTRC 0xE0 54#define SST_LTRC 0xE0
55#define SST_HDMC 0xE8 55#define SST_HMDC 0xE8
56
57#define SST_SHIM_BEGIN SST_CSR
58#define SST_SHIM_END SST_HDMC
59
56#define SST_DBGO 0xF0 60#define SST_DBGO 0xF0
57 61
58#define SST_SHIM_SIZE 0x100 62#define SST_SHIM_SIZE 0x100
@@ -73,6 +77,8 @@
73#define SST_CSR_S0IOCS (0x1 << 21) 77#define SST_CSR_S0IOCS (0x1 << 21)
74#define SST_CSR_S1IOCS (0x1 << 23) 78#define SST_CSR_S1IOCS (0x1 << 23)
75#define SST_CSR_LPCS (0x1 << 31) 79#define SST_CSR_LPCS (0x1 << 31)
80#define SST_CSR_24MHZ_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1 | SST_CSR_LPCS)
81#define SST_CSR_24MHZ_NO_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1)
76#define SST_BYT_CSR_RST (0x1 << 0) 82#define SST_BYT_CSR_RST (0x1 << 0)
77#define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) 83#define SST_BYT_CSR_VECTOR_SEL (0x1 << 1)
78#define SST_BYT_CSR_STALL (0x1 << 2) 84#define SST_BYT_CSR_STALL (0x1 << 2)
@@ -92,6 +98,14 @@
92#define SST_IMRX_DONE (0x1 << 0) 98#define SST_IMRX_DONE (0x1 << 0)
93#define SST_BYT_IMRX_REQUEST (0x1 << 1) 99#define SST_BYT_IMRX_REQUEST (0x1 << 1)
94 100
101/* IMRD / IMD */
102#define SST_IMRD_DONE (0x1 << 0)
103#define SST_IMRD_BUSY (0x1 << 1)
104#define SST_IMRD_SSP0 (0x1 << 16)
105#define SST_IMRD_DMAC0 (0x1 << 21)
106#define SST_IMRD_DMAC1 (0x1 << 22)
107#define SST_IMRD_DMAC (SST_IMRD_DMAC0 | SST_IMRD_DMAC1)
108
95/* IPCX / IPCC */ 109/* IPCX / IPCC */
96#define SST_IPCX_DONE (0x1 << 30) 110#define SST_IPCX_DONE (0x1 << 30)
97#define SST_IPCX_BUSY (0x1 << 31) 111#define SST_IPCX_BUSY (0x1 << 31)
@@ -118,9 +132,21 @@
118/* LTRC */ 132/* LTRC */
119#define SST_LTRC_VAL(x) (x << 0) 133#define SST_LTRC_VAL(x) (x << 0)
120 134
121/* HDMC */ 135/* HMDC */
122#define SST_HDMC_HDDA0(x) (x << 0) 136#define SST_HMDC_HDDA0(x) (x << 0)
123#define SST_HDMC_HDDA1(x) (x << 7) 137#define SST_HMDC_HDDA1(x) (x << 7)
138#define SST_HMDC_HDDA_E0_CH0 1
139#define SST_HMDC_HDDA_E0_CH1 2
140#define SST_HMDC_HDDA_E0_CH2 4
141#define SST_HMDC_HDDA_E0_CH3 8
142#define SST_HMDC_HDDA_E1_CH0 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH0)
143#define SST_HMDC_HDDA_E1_CH1 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH1)
144#define SST_HMDC_HDDA_E1_CH2 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH2)
145#define SST_HMDC_HDDA_E1_CH3 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH3)
146#define SST_HMDC_HDDA_E0_ALLCH (SST_HMDC_HDDA_E0_CH0 | SST_HMDC_HDDA_E0_CH1 | \
147 SST_HMDC_HDDA_E0_CH2 | SST_HMDC_HDDA_E0_CH3)
148#define SST_HMDC_HDDA_E1_ALLCH (SST_HMDC_HDDA_E1_CH0 | SST_HMDC_HDDA_E1_CH1 | \
149 SST_HMDC_HDDA_E1_CH2 | SST_HMDC_HDDA_E1_CH3)
124 150
125 151
126/* SST Vendor Defined Registers and bits */ 152/* SST Vendor Defined Registers and bits */
@@ -130,11 +156,16 @@
130#define SST_VDRTCTL3 0xaC 156#define SST_VDRTCTL3 0xaC
131 157
132/* VDRTCTL0 */ 158/* VDRTCTL0 */
159#define SST_VDRTCL0_APLLSE_MASK 1
133#define SST_VDRTCL0_DSRAMPGE_SHIFT 16 160#define SST_VDRTCL0_DSRAMPGE_SHIFT 16
134#define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) 161#define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT)
135#define SST_VDRTCL0_ISRAMPGE_SHIFT 6 162#define SST_VDRTCL0_ISRAMPGE_SHIFT 6
136#define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) 163#define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT)
137 164
165/* PMCS */
166#define SST_PMCS 0x84
167#define SST_PMCS_PS_MASK 0x3
168
138struct sst_dsp; 169struct sst_dsp;
139 170
140/* 171/*
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c
index a33b931181dc..4b6c163c10ff 100644
--- a/sound/soc/intel/sst-haswell-dsp.c
+++ b/sound/soc/intel/sst-haswell-dsp.c
@@ -28,9 +28,6 @@
28#include <linux/firmware.h> 28#include <linux/firmware.h>
29#include <linux/pm_runtime.h> 29#include <linux/pm_runtime.h>
30 30
31#include <linux/acpi.h>
32#include <acpi/acpi_bus.h>
33
34#include "sst-dsp.h" 31#include "sst-dsp.h"
35#include "sst-dsp-priv.h" 32#include "sst-dsp-priv.h"
36#include "sst-haswell-ipc.h" 33#include "sst-haswell-ipc.h"
@@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst)
272 SST_CSR2_SDFD_SSP1); 269 SST_CSR2_SDFD_SSP1);
273 270
274 /* enable DMA engine 0,1 all channels to access host memory */ 271 /* enable DMA engine 0,1 all channels to access host memory */
275 sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, 272 sst_dsp_shim_update_bits_unlocked(sst, SST_HMDC,
276 SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), 273 SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff),
277 SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); 274 SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff));
278 275
279 /* disable all clock gating */ 276 /* disable all clock gating */
280 writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); 277 writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2);
@@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = {
313 310
314/* wild cat point ADSP mem regions */ 311/* wild cat point ADSP mem regions */
315static const struct sst_adsp_memregion wpt_region[] = { 312static const struct sst_adsp_memregion wpt_region[] = {
316 {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ 313 {0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */
317 {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */
318 {0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */
319 {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ 314 {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */
320}; 315};
321 316
@@ -339,21 +334,40 @@ static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata)
339 return 0; 334 return 0;
340} 335}
341 336
337struct sst_sram_shift {
338 u32 dev_id; /* SST Device IDs */
339 u32 iram_shift;
340 u32 dram_shift;
341};
342
343static const struct sst_sram_shift sram_shift[] = {
344 {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */
345 {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */
346};
342static u32 hsw_block_get_bit(struct sst_mem_block *block) 347static u32 hsw_block_get_bit(struct sst_mem_block *block)
343{ 348{
344 u32 bit = 0, shift = 0; 349 u32 bit = 0, shift = 0, index;
350 struct sst_dsp *sst = block->dsp;
345 351
346 switch (block->type) { 352 for (index = 0; index < ARRAY_SIZE(sram_shift); index++) {
347 case SST_MEM_DRAM: 353 if (sram_shift[index].dev_id == sst->id)
348 shift = 16; 354 break;
349 break;
350 case SST_MEM_IRAM:
351 shift = 6;
352 break;
353 default:
354 return 0;
355 } 355 }
356 356
357 if (index < ARRAY_SIZE(sram_shift)) {
358 switch (block->type) {
359 case SST_MEM_DRAM:
360 shift = sram_shift[index].dram_shift;
361 break;
362 case SST_MEM_IRAM:
363 shift = sram_shift[index].iram_shift;
364 break;
365 default:
366 shift = 0;
367 }
368 } else
369 shift = 0;
370
357 bit = 1 << (block->index + shift); 371 bit = 1 << (block->index + shift);
358 372
359 return bit; 373 return bit;
@@ -501,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata)
501 } 515 }
502 } 516 }
503 517
504 /* set default power gating mask */ 518 /* set default power gating control, enable power gating control for all blocks. that is,
505 writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); 519 can't be accessed, please enable each block before accessing. */
520 writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0);
506 521
507 return 0; 522 return 0;
508} 523}
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index 434236343ddf..b6291516dbbf 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready {
183 u32 inbox_size; 183 u32 inbox_size;
184 u32 outbox_size; 184 u32 outbox_size;
185 u32 fw_info_size; 185 u32 fw_info_size;
186 u8 fw_info[1]; 186 u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
187} __attribute__((packed)); 187} __attribute__((packed));
188 188
189struct ipc_message { 189struct ipc_message {
@@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work)
457 return; 457 return;
458 } 458 }
459 459
460 /* if the DSP is busy we will TX messages after IRQ */ 460 /* if the DSP is busy, we will TX messages after IRQ.
461 * also postpone if we are in the middle of procesing completion irq*/
461 ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); 462 ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX);
462 if (ipcx & SST_IPCX_BUSY) { 463 if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) {
463 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); 464 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
464 return; 465 return;
465 } 466 }
@@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg,
502 ipc_shim_dbg(hsw, "message timeout"); 503 ipc_shim_dbg(hsw, "message timeout");
503 504
504 trace_ipc_error("error message timeout for", msg->header); 505 trace_ipc_error("error message timeout for", msg->header);
506 list_del(&msg->list);
505 ret = -ETIMEDOUT; 507 ret = -ETIMEDOUT;
506 } else { 508 } else {
507 509
@@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
569{ 571{
570 struct sst_hsw_ipc_fw_ready fw_ready; 572 struct sst_hsw_ipc_fw_ready fw_ready;
571 u32 offset; 573 u32 offset;
574 u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
575 char *tmp[5], *pinfo;
576 int i = 0;
572 577
573 offset = (header & 0x1FFFFFFF) << 3; 578 offset = (header & 0x1FFFFFFF) << 3;
574 579
@@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
589 fw_ready.inbox_offset, fw_ready.inbox_size); 594 fw_ready.inbox_offset, fw_ready.inbox_size);
590 dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", 595 dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n",
591 fw_ready.outbox_offset, fw_ready.outbox_size); 596 fw_ready.outbox_offset, fw_ready.outbox_size);
597 if (fw_ready.fw_info_size < sizeof(fw_ready.fw_info)) {
598 fw_ready.fw_info[fw_ready.fw_info_size] = 0;
599 dev_dbg(hsw->dev, " Firmware info: %s \n", fw_ready.fw_info);
600
601 /* log the FW version info got from the mailbox here. */
602 memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size);
603 pinfo = &fw_info[0];
604 for (i = 0; i < sizeof(tmp) / sizeof(char *); i++)
605 tmp[i] = strsep(&pinfo, " ");
606 dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - "
607 "version: %s.%s, build %s, source commit id: %s\n",
608 tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]);
609 }
592} 610}
593 611
594static void hsw_notification_work(struct work_struct *work) 612static void hsw_notification_work(struct work_struct *work)
@@ -671,7 +689,9 @@ static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg)
671 switch (stream_msg) { 689 switch (stream_msg) {
672 case IPC_STR_STAGE_MESSAGE: 690 case IPC_STR_STAGE_MESSAGE:
673 case IPC_STR_NOTIFICATION: 691 case IPC_STR_NOTIFICATION:
692 break;
674 case IPC_STR_RESET: 693 case IPC_STR_RESET:
694 trace_ipc_notification("stream reset", stream->reply.stream_hw_id);
675 break; 695 break;
676 case IPC_STR_PAUSE: 696 case IPC_STR_PAUSE:
677 stream->running = false; 697 stream->running = false;
@@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
762 } 782 }
763 783
764 /* update any stream states */ 784 /* update any stream states */
765 hsw_stream_update(hsw, msg); 785 if (msg_get_global_type(header) == IPC_GLB_STREAM_MESSAGE)
786 hsw_stream_update(hsw, msg);
766 787
767 /* wake up and return the error if we have waiters on this message ? */ 788 /* wake up and return the error if we have waiters on this message ? */
768 list_del(&msg->list); 789 list_del(&msg->list);
@@ -1628,7 +1649,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
1628 enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) 1649 enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx)
1629{ 1650{
1630 u32 header, state_; 1651 u32 header, state_;
1631 int ret; 1652 int ret, item;
1632 1653
1633 header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); 1654 header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE);
1634 state_ = state; 1655 state_ = state;
@@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
1642 return ret; 1663 return ret;
1643 } 1664 }
1644 1665
1666 for (item = 0; item < dx->entries_no; item++) {
1667 dev_dbg(hsw->dev,
1668 "Item[%d] offset[%x] - size[%x] - source[%x]\n",
1669 item, dx->mem_info[item].offset,
1670 dx->mem_info[item].size,
1671 dx->mem_info[item].source);
1672 }
1645 dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", 1673 dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n",
1646 dx->entries_no, state); 1674 dx->entries_no, state);
1647 1675
@@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1775 1803
1776 /* get the FW version */ 1804 /* get the FW version */
1777 sst_hsw_fw_get_version(hsw, &version); 1805 sst_hsw_fw_get_version(hsw, &version);
1778 dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n",
1779 version.type, version.major, version.minor, version.build);
1780 1806
1781 /* get the globalmixer */ 1807 /* get the globalmixer */
1782 ret = sst_hsw_mixer_get_info(hsw); 1808 ret = sst_hsw_mixer_get_info(hsw);
diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/sst-mfld-dsp.h
index 8d482d76475a..4257263157cd 100644
--- a/sound/soc/intel/sst-mfld-dsp.h
+++ b/sound/soc/intel/sst-mfld-dsp.h
@@ -3,7 +3,7 @@
3/* 3/*
4 * sst_mfld_dsp.h - Intel SST Driver for audio engine 4 * sst_mfld_dsp.h - Intel SST Driver for audio engine
5 * 5 *
6 * Copyright (C) 2008-12 Intel Corporation 6 * Copyright (C) 2008-14 Intel Corporation
7 * Authors: Vinod Koul <vinod.koul@linux.intel.com> 7 * Authors: Vinod Koul <vinod.koul@linux.intel.com>
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 * 9 *
@@ -19,6 +19,142 @@
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 20 */
21 21
22#define SST_MAX_BIN_BYTES 1024
23
24#define MAX_DBG_RW_BYTES 80
25#define MAX_NUM_SCATTER_BUFFERS 8
26#define MAX_LOOP_BACK_DWORDS 8
27/* IPC base address and mailbox, timestamp offsets */
28#define SST_MAILBOX_SIZE 0x0400
29#define SST_MAILBOX_SEND 0x0000
30#define SST_TIME_STAMP 0x1800
31#define SST_TIME_STAMP_MRFLD 0x800
32#define SST_RESERVED_OFFSET 0x1A00
33#define SST_SCU_LPE_MAILBOX 0x1000
34#define SST_LPE_SCU_MAILBOX 0x1400
35#define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16)
36#define PROCESS_MSG 0x80
37
38/* Message ID's for IPC messages */
39/* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */
40
41/* I2L Firmware/Codec Download msgs */
42#define IPC_IA_PREP_LIB_DNLD 0x01
43#define IPC_IA_LIB_DNLD_CMPLT 0x02
44#define IPC_IA_GET_FW_VERSION 0x04
45#define IPC_IA_GET_FW_BUILD_INF 0x05
46#define IPC_IA_GET_FW_INFO 0x06
47#define IPC_IA_GET_FW_CTXT 0x07
48#define IPC_IA_SET_FW_CTXT 0x08
49#define IPC_IA_PREPARE_SHUTDOWN 0x31
50/* I2L Codec Config/control msgs */
51#define IPC_PREP_D3 0x10
52#define IPC_IA_SET_CODEC_PARAMS 0x10
53#define IPC_IA_GET_CODEC_PARAMS 0x11
54#define IPC_IA_SET_PPP_PARAMS 0x12
55#define IPC_IA_GET_PPP_PARAMS 0x13
56#define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA
57#define IPC_IA_ALG_PARAMS 0x1A
58#define IPC_IA_TUNING_PARAMS 0x1B
59#define IPC_IA_SET_RUNTIME_PARAMS 0x1C
60#define IPC_IA_SET_PARAMS 0x1
61#define IPC_IA_GET_PARAMS 0x2
62
63#define IPC_EFFECTS_CREATE 0xE
64#define IPC_EFFECTS_DESTROY 0xF
65
66/* I2L Stream config/control msgs */
67#define IPC_IA_ALLOC_STREAM_MRFLD 0x2
68#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
69#define IPC_IA_FREE_STREAM_MRFLD 0x03
70#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
71#define IPC_IA_SET_STREAM_PARAMS 0x22
72#define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12
73#define IPC_IA_GET_STREAM_PARAMS 0x23
74#define IPC_IA_PAUSE_STREAM 0x24
75#define IPC_IA_PAUSE_STREAM_MRFLD 0x4
76#define IPC_IA_RESUME_STREAM 0x25
77#define IPC_IA_RESUME_STREAM_MRFLD 0x5
78#define IPC_IA_DROP_STREAM 0x26
79#define IPC_IA_DROP_STREAM_MRFLD 0x07
80#define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */
81#define IPC_IA_DRAIN_STREAM_MRFLD 0x8
82#define IPC_IA_CONTROL_ROUTING 0x29
83#define IPC_IA_VTSV_UPDATE_MODULES 0x20
84#define IPC_IA_VTSV_DETECTED 0x21
85
86#define IPC_IA_START_STREAM_MRFLD 0X06
87#define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */
88
89#define IPC_IA_SET_GAIN_MRFLD 0x21
90/* Debug msgs */
91#define IPC_IA_DBG_MEM_READ 0x40
92#define IPC_IA_DBG_MEM_WRITE 0x41
93#define IPC_IA_DBG_LOOP_BACK 0x42
94#define IPC_IA_DBG_LOG_ENABLE 0x45
95#define IPC_IA_DBG_SET_PROBE_PARAMS 0x47
96
97/* L2I Firmware/Codec Download msgs */
98#define IPC_IA_FW_INIT_CMPLT 0x81
99#define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01
100#define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11
101
102/* L2I Codec Config/control msgs */
103#define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */
104
105#define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */
106#define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */
107#define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */
108#define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */
109#define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */
110#define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */
111
112#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */
113/* L2S messages */
114#define IPC_SC_DDR_LINK_UP 0xC0
115#define IPC_SC_DDR_LINK_DOWN 0xC1
116#define IPC_SC_SET_LPECLK_REQ 0xC2
117#define IPC_SC_SSP_BIT_BANG 0xC3
118
119/* L2I Error reporting msgs */
120#define IPC_IA_MEM_ALLOC_FAIL 0xE0
121#define IPC_IA_PROC_ERR 0xE1 /* error in processing a
122 stream can be used by playback and
123 capture modules */
124
125/* L2I Debug msgs */
126#define IPC_IA_PRINT_STRING 0xF0
127
128/* Buffer under-run */
129#define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B
130
131/* Mrfld specific defines:
132 * For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR)
133 * received from FW, the format is:
134 * - IPC High: pvt_id is set to zero. Always short message.
135 * - msg_id is in lower 16-bits of IPC low payload.
136 * - pipe_id is in higher 16-bits of IPC low payload for period_elapsed.
137 * - error id is in higher 16-bits of IPC low payload for async errors.
138 */
139#define SST_ASYNC_DRV_ID 0
140
141/* Command Response or Acknowledge message to any IPC message will have
142 * same message ID and stream ID information which is sent.
143 * There is no specific Ack message ID. The data field is used as response
144 * meaning.
145 */
146enum ackData {
147 IPC_ACK_SUCCESS = 0,
148 IPC_ACK_FAILURE,
149};
150
151enum ipc_ia_msg_id {
152 IPC_CMD = 1, /*!< Task Control message ID */
153 IPC_SET_PARAMS = 2,/*!< Task Set param message ID */
154 IPC_GET_PARAMS = 3, /*!< Task Get param message ID */
155 IPC_INVALID = 0xFF, /*!<Task Get param message ID */
156};
157
22enum sst_codec_types { 158enum sst_codec_types {
23 /* AUDIO/MUSIC CODEC Type Definitions */ 159 /* AUDIO/MUSIC CODEC Type Definitions */
24 SST_CODEC_TYPE_UNKNOWN = 0, 160 SST_CODEC_TYPE_UNKNOWN = 0,
@@ -35,14 +171,157 @@ enum stream_type {
35 SST_STREAM_TYPE_MUSIC = 1, 171 SST_STREAM_TYPE_MUSIC = 1,
36}; 172};
37 173
174enum sst_error_codes {
175 /* Error code,response to msgId: Description */
176 /* Common error codes */
177 SST_SUCCESS = 0, /* Success */
178 SST_ERR_INVALID_STREAM_ID = 1,
179 SST_ERR_INVALID_MSG_ID = 2,
180 SST_ERR_INVALID_STREAM_OP = 3,
181 SST_ERR_INVALID_PARAMS = 4,
182 SST_ERR_INVALID_CODEC = 5,
183 SST_ERR_INVALID_MEDIA_TYPE = 6,
184 SST_ERR_STREAM_ERR = 7,
185
186 SST_ERR_STREAM_IN_USE = 15,
187};
188
189struct ipc_dsp_hdr {
190 u16 mod_index_id:8; /*!< DSP Command ID specific to tasks */
191 u16 pipe_id:8; /*!< instance of the module in the pipeline */
192 u16 mod_id; /*!< Pipe_id */
193 u16 cmd_id; /*!< Module ID = lpe_algo_types_t */
194 u16 length; /*!< Length of the payload only */
195} __packed;
196
197union ipc_header_high {
198 struct {
199 u32 msg_id:8; /* Message ID - Max 256 Message Types */
200 u32 task_id:4; /* Task ID associated with this comand */
201 u32 drv_id:4; /* Identifier for the driver to track*/
202 u32 rsvd1:8; /* Reserved */
203 u32 result:4; /* Reserved */
204 u32 res_rqd:1; /* Response rqd */
205 u32 large:1; /* Large Message if large = 1 */
206 u32 done:1; /* bit 30 - Done bit */
207 u32 busy:1; /* bit 31 - busy bit*/
208 } part;
209 u32 full;
210} __packed;
211/* IPC header */
212union ipc_header_mrfld {
213 struct {
214 u32 header_low_payload;
215 union ipc_header_high header_high;
216 } p;
217 u64 full;
218} __packed;
219/* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/
220
221/* IPC Header */
222union ipc_header {
223 struct {
224 u32 msg_id:8; /* Message ID - Max 256 Message Types */
225 u32 str_id:5;
226 u32 large:1; /* Large Message if large = 1 */
227 u32 reserved:2; /* Reserved for future use */
228 u32 data:14; /* Ack/Info for msg, size of msg in Mailbox */
229 u32 done:1; /* bit 30 */
230 u32 busy:1; /* bit 31 */
231 } part;
232 u32 full;
233} __packed;
234
235/* Firmware build info */
236struct sst_fw_build_info {
237 unsigned char date[16]; /* Firmware build date */
238 unsigned char time[16]; /* Firmware build time */
239} __packed;
240
241/* Firmware Version info */
242struct snd_sst_fw_version {
243 u8 build; /* build number*/
244 u8 minor; /* minor number*/
245 u8 major; /* major number*/
246 u8 type; /* build type */
247};
248
249struct ipc_header_fw_init {
250 struct snd_sst_fw_version fw_version;/* Firmware version details */
251 struct sst_fw_build_info build_info;
252 u16 result; /* Fw init result */
253 u8 module_id; /* Module ID in case of error */
254 u8 debug_info; /* Debug info from Module ID in case of fail */
255} __packed;
256
257struct snd_sst_tstamp {
258 u64 ring_buffer_counter; /* PB/CP: Bytes copied from/to DDR. */
259 u64 hardware_counter; /* PB/CP: Bytes DMAed to/from SSP. */
260 u64 frames_decoded;
261 u64 bytes_decoded;
262 u64 bytes_copied;
263 u32 sampling_frequency;
264 u32 channel_peak[8];
265} __packed;
266
267/* Stream type params struture for Alloc stream */
268struct snd_sst_str_type {
269 u8 codec_type; /* Codec type */
270 u8 str_type; /* 1 = voice 2 = music */
271 u8 operation; /* Playback or Capture */
272 u8 protected_str; /* 0=Non DRM, 1=DRM */
273 u8 time_slots;
274 u8 reserved; /* Reserved */
275 u16 result; /* Result used for acknowledgment */
276} __packed;
277
278/* Library info structure */
279struct module_info {
280 u32 lib_version;
281 u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/
282 u32 media_type;
283 u8 lib_name[12];
284 u32 lib_caps;
285 unsigned char b_date[16]; /* Lib build date */
286 unsigned char b_time[16]; /* Lib build time */
287} __packed;
288
289/* Library slot info */
290struct lib_slot_info {
291 u8 slot_num; /* 1 or 2 */
292 u8 reserved1;
293 u16 reserved2;
294 u32 iram_size; /* slot size in IRAM */
295 u32 dram_size; /* slot size in DRAM */
296 u32 iram_offset; /* starting offset of slot in IRAM */
297 u32 dram_offset; /* starting offset of slot in DRAM */
298} __packed;
299
300struct snd_ppp_mixer_params {
301 __u32 type; /*Type of the parameter */
302 __u32 size;
303 __u32 input_stream_bitmap; /*Input stream Bit Map*/
304} __packed;
305
306struct snd_sst_lib_download {
307 struct module_info lib_info; /* library info type, capabilities etc */
308 struct lib_slot_info slot_info; /* slot info to be downloaded */
309 u32 mod_entry_pt;
310};
311
312struct snd_sst_lib_download_info {
313 struct snd_sst_lib_download dload_lib;
314 u16 result; /* Result used for acknowledgment */
315 u8 pvt_id; /* Private ID */
316 u8 reserved; /* for alignment */
317};
38struct snd_pcm_params { 318struct snd_pcm_params {
39 u8 num_chan; /* 1=Mono, 2=Stereo */ 319 u8 num_chan; /* 1=Mono, 2=Stereo */
40 u8 pcm_wd_sz; /* 16/24 - bit*/ 320 u8 pcm_wd_sz; /* 16/24 - bit*/
41 u32 reserved; /* Bitrate in bits per second */ 321 u8 use_offload_path; /* 0-PCM using period elpased & ALSA interfaces
42 u32 sfreq; /* Sampling rate in Hz */ 322 1-PCM stream via compressed interface */
43 u8 use_offload_path;
44 u8 reserved2; 323 u8 reserved2;
45 u16 reserved3; 324 u32 sfreq; /* Sampling rate in Hz */
46 u8 channel_map[8]; 325 u8 channel_map[8];
47} __packed; 326} __packed;
48 327
@@ -76,6 +355,7 @@ struct snd_aac_params {
76struct snd_wma_params { 355struct snd_wma_params {
77 u8 num_chan; /* 1=Mono, 2=Stereo */ 356 u8 num_chan; /* 1=Mono, 2=Stereo */
78 u8 pcm_wd_sz; /* 16/24 - bit*/ 357 u8 pcm_wd_sz; /* 16/24 - bit*/
358 u16 reserved1;
79 u32 brate; /* Use the hard coded value. */ 359 u32 brate; /* Use the hard coded value. */
80 u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ 360 u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
81 u32 channel_mask; /* Channel Mask */ 361 u32 channel_mask; /* Channel Mask */
@@ -101,26 +381,153 @@ struct sst_address_info {
101}; 381};
102 382
103struct snd_sst_alloc_params_ext { 383struct snd_sst_alloc_params_ext {
104 struct sst_address_info ring_buf_info[8]; 384 __u16 sg_count;
105 u8 sg_count; 385 __u16 reserved;
106 u8 reserved; 386 __u32 frag_size; /*Number of samples after which period elapsed
107 u16 reserved2;
108 u32 frag_size; /*Number of samples after which period elapsed
109 message is sent valid only if path = 0*/ 387 message is sent valid only if path = 0*/
110} __packed; 388 struct sst_address_info ring_buf_info[8];
389};
111 390
112struct snd_sst_stream_params { 391struct snd_sst_stream_params {
113 union snd_sst_codec_params uc; 392 union snd_sst_codec_params uc;
114} __packed; 393} __packed;
115 394
116struct snd_sst_params { 395struct snd_sst_params {
396 u32 result;
117 u32 stream_id; 397 u32 stream_id;
118 u8 codec; 398 u8 codec;
119 u8 ops; 399 u8 ops;
120 u8 stream_type; 400 u8 stream_type;
121 u8 device_type; 401 u8 device_type;
402 u8 task;
122 struct snd_sst_stream_params sparams; 403 struct snd_sst_stream_params sparams;
123 struct snd_sst_alloc_params_ext aparams; 404 struct snd_sst_alloc_params_ext aparams;
124}; 405};
125 406
407struct snd_sst_alloc_mrfld {
408 u16 codec_type;
409 u8 operation;
410 u8 sg_count;
411 struct sst_address_info ring_buf_info[8];
412 u32 frag_size;
413 u32 ts;
414 struct snd_sst_stream_params codec_params;
415} __packed;
416
417/* Alloc stream params structure */
418struct snd_sst_alloc_params {
419 struct snd_sst_str_type str_type;
420 struct snd_sst_stream_params stream_params;
421 struct snd_sst_alloc_params_ext alloc_params;
422} __packed;
423
424/* Alloc stream response message */
425struct snd_sst_alloc_response {
426 struct snd_sst_str_type str_type; /* Stream type for allocation */
427 struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */
428};
429
430/* Drop response */
431struct snd_sst_drop_response {
432 u32 result;
433 u32 bytes;
434};
435
436struct snd_sst_async_msg {
437 u32 msg_id; /* Async msg id */
438 u32 payload[0];
439};
440
441struct snd_sst_async_err_msg {
442 u32 fw_resp; /* Firmware Result */
443 u32 lib_resp; /*Library result */
444} __packed;
445
446struct snd_sst_vol {
447 u32 stream_id;
448 s32 volume;
449 u32 ramp_duration;
450 u32 ramp_type; /* Ramp type, default=0 */
451};
452
453/* Gain library parameters for mrfld
454 * based on DSP command spec v0.82
455 */
456struct snd_sst_gain_v2 {
457 u16 gain_cell_num; /* num of gain cells to modify*/
458 u8 cell_nbr_idx; /* instance index*/
459 u8 cell_path_idx; /* pipe-id */
460 u16 module_id; /*module id */
461 u16 left_cell_gain; /* left gain value in dB*/
462 u16 right_cell_gain; /* right gain value in dB*/
463 u16 gain_time_const; /* gain time constant*/
464} __packed;
465
466struct snd_sst_mute {
467 u32 stream_id;
468 u32 mute;
469};
470
471struct snd_sst_runtime_params {
472 u8 type;
473 u8 str_id;
474 u8 size;
475 u8 rsvd;
476 void *addr;
477} __packed;
478
479enum stream_param_type {
480 SST_SET_TIME_SLOT = 0,
481 SST_SET_CHANNEL_INFO = 1,
482 OTHERS = 2, /*reserved for future params*/
483};
484
485/* CSV Voice call routing structure */
486struct snd_sst_control_routing {
487 u8 control; /* 0=start, 1=Stop */
488 u8 reserved[3]; /* Reserved- for 32 bit alignment */
489};
490
491struct ipc_post {
492 struct list_head node;
493 union ipc_header header; /* driver specific */
494 bool is_large;
495 bool is_process_reply;
496 union ipc_header_mrfld mrfld_header;
497 char *mailbox_data;
498};
499
500struct snd_sst_ctxt_params {
501 u32 address; /* Physical Address in DDR where the context is stored */
502 u32 size; /* size of the context */
503};
504
505struct snd_sst_lpe_log_params {
506 u8 dbg_type;
507 u8 module_id;
508 u8 log_level;
509 u8 reserved;
510} __packed;
511
512enum snd_sst_bytes_type {
513 SND_SST_BYTES_SET = 0x1,
514 SND_SST_BYTES_GET = 0x2,
515};
516
517struct snd_sst_bytes_v2 {
518 u8 type;
519 u8 ipc_msg;
520 u8 block;
521 u8 task_id;
522 u8 pipe_id;
523 u8 rsvd;
524 u16 len;
525 char bytes[0];
526};
527
528#define MAX_VTSV_FILES 2
529struct snd_sst_vtsv_info {
530 struct sst_address_info vfiles[MAX_VTSV_FILES];
531} __packed;
532
126#endif /* __SST_MFLD_DSP_H__ */ 533#endif /* __SST_MFLD_DSP_H__ */
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/sst-mfld-platform-compress.c
index 02abd19fce1d..29c059ca19e8 100644
--- a/sound/soc/intel/sst-mfld-platform-compress.c
+++ b/sound/soc/intel/sst-mfld-platform-compress.c
@@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
100 int retval; 100 int retval;
101 struct snd_sst_params str_params; 101 struct snd_sst_params str_params;
102 struct sst_compress_cb cb; 102 struct sst_compress_cb cb;
103 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
104 struct snd_soc_platform *platform = rtd->platform;
105 struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
103 106
104 stream = cstream->runtime->private_data; 107 stream = cstream->runtime->private_data;
105 /* construct fw structure for this*/ 108 /* construct fw structure for this*/
106 memset(&str_params, 0, sizeof(str_params)); 109 memset(&str_params, 0, sizeof(str_params));
107 110
108 str_params.ops = STREAM_OPS_PLAYBACK; 111 /* fill the device type and stream id to pass to SST driver */
109 str_params.stream_type = SST_STREAM_TYPE_MUSIC; 112 retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
110 str_params.device_type = SND_SST_DEVICE_COMPRESS; 113 pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
114 if (retval < 0)
115 return retval;
111 116
112 switch (params->codec.id) { 117 switch (params->codec.id) {
113 case SND_AUDIOCODEC_MP3: { 118 case SND_AUDIOCODEC_MP3: {
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c
index 7c790f51d259..706212a6a68c 100644
--- a/sound/soc/intel/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/sst-mfld-platform-pcm.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * sst_mfld_platform.c - Intel MID Platform driver 2 * sst_mfld_platform.c - Intel MID Platform driver
3 * 3 *
4 * Copyright (C) 2010-2013 Intel Corp 4 * Copyright (C) 2010-2014 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com> 5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com> 6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -27,7 +27,9 @@
27#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
28#include <sound/soc.h> 28#include <sound/soc.h>
29#include <sound/compress_driver.h> 29#include <sound/compress_driver.h>
30#include <asm/platform_sst_audio.h>
30#include "sst-mfld-platform.h" 31#include "sst-mfld-platform.h"
32#include "sst-atom-controls.h"
31 33
32struct sst_device *sst; 34struct sst_device *sst;
33static DEFINE_MUTEX(sst_lock); 35static DEFINE_MUTEX(sst_lock);
@@ -92,6 +94,13 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
92 .fifo_size = SST_FIFO_SIZE, 94 .fifo_size = SST_FIFO_SIZE,
93}; 95};
94 96
97static struct sst_dev_stream_map dpcm_strm_map[] = {
98 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
99 {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
100 {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
101 {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
102};
103
95/* MFLD - MSIC */ 104/* MFLD - MSIC */
96static struct snd_soc_dai_driver sst_platform_dai[] = { 105static struct snd_soc_dai_driver sst_platform_dai[] = {
97{ 106{
@@ -143,58 +152,142 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
143 return state; 152 return state;
144} 153}
145 154
155static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
156 struct snd_sst_alloc_params_ext *alloc_param)
157{
158 unsigned int channels;
159 snd_pcm_uframes_t period_size;
160 ssize_t periodbytes;
161 ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
162 u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
163
164 channels = substream->runtime->channels;
165 period_size = substream->runtime->period_size;
166 periodbytes = samples_to_bytes(substream->runtime, period_size);
167 alloc_param->ring_buf_info[0].addr = buffer_addr;
168 alloc_param->ring_buf_info[0].size = buffer_bytes;
169 alloc_param->sg_count = 1;
170 alloc_param->reserved = 0;
171 alloc_param->frag_size = periodbytes * channels;
172
173}
146static void sst_fill_pcm_params(struct snd_pcm_substream *substream, 174static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
147 struct sst_pcm_params *param) 175 struct snd_sst_stream_params *param)
148{ 176{
177 param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
178 param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
179 param->uc.pcm_params.sfreq = substream->runtime->rate;
180
181 /* PCM stream via ALSA interface */
182 param->uc.pcm_params.use_offload_path = 0;
183 param->uc.pcm_params.reserved2 = 0;
184 memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
149 185
150 param->num_chan = (u8) substream->runtime->channels;
151 param->pcm_wd_sz = substream->runtime->sample_bits;
152 param->reserved = 0;
153 param->sfreq = substream->runtime->rate;
154 param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream);
155 param->period_count = substream->runtime->period_size;
156 param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area);
157 pr_debug("period_cnt = %d\n", param->period_count);
158 pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz);
159} 186}
160 187
161static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) 188static int sst_get_stream_mapping(int dev, int sdev, int dir,
189 struct sst_dev_stream_map *map, int size)
190{
191 int i;
192
193 if (map == NULL)
194 return -EINVAL;
195
196
197 /* index 0 is not used in stream map */
198 for (i = 1; i < size; i++) {
199 if ((map[i].dev_num == dev) && (map[i].direction == dir))
200 return i;
201 }
202 return 0;
203}
204
205int sst_fill_stream_params(void *substream,
206 const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
207{
208 int map_size;
209 int index;
210 struct sst_dev_stream_map *map;
211 struct snd_pcm_substream *pstream = NULL;
212 struct snd_compr_stream *cstream = NULL;
213
214 map = ctx->pdata->pdev_strm_map;
215 map_size = ctx->pdata->strm_map_size;
216
217 if (is_compress == true)
218 cstream = (struct snd_compr_stream *)substream;
219 else
220 pstream = (struct snd_pcm_substream *)substream;
221
222 str_params->stream_type = SST_STREAM_TYPE_MUSIC;
223
224 /* For pcm streams */
225 if (pstream) {
226 index = sst_get_stream_mapping(pstream->pcm->device,
227 pstream->number, pstream->stream,
228 map, map_size);
229 if (index <= 0)
230 return -EINVAL;
231
232 str_params->stream_id = index;
233 str_params->device_type = map[index].device_id;
234 str_params->task = map[index].task_id;
235
236 str_params->ops = (u8)pstream->stream;
237 }
238
239 if (cstream) {
240 index = sst_get_stream_mapping(cstream->device->device,
241 0, cstream->direction,
242 map, map_size);
243 if (index <= 0)
244 return -EINVAL;
245 str_params->stream_id = index;
246 str_params->device_type = map[index].device_id;
247 str_params->task = map[index].task_id;
248
249 str_params->ops = (u8)cstream->direction;
250 }
251 return 0;
252}
253
254static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
255 struct snd_soc_platform *platform)
162{ 256{
163 struct sst_runtime_stream *stream = 257 struct sst_runtime_stream *stream =
164 substream->runtime->private_data; 258 substream->runtime->private_data;
165 struct sst_pcm_params param = {0}; 259 struct snd_sst_stream_params param = {{{0,},},};
166 struct sst_stream_params str_params = {0}; 260 struct snd_sst_params str_params = {0};
167 int ret_val; 261 struct snd_sst_alloc_params_ext alloc_params = {0};
262 int ret_val = 0;
263 struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
168 264
169 /* set codec params and inform SST driver the same */ 265 /* set codec params and inform SST driver the same */
170 sst_fill_pcm_params(substream, &param); 266 sst_fill_pcm_params(substream, &param);
267 sst_fill_alloc_params(substream, &alloc_params);
171 substream->runtime->dma_area = substream->dma_buffer.area; 268 substream->runtime->dma_area = substream->dma_buffer.area;
172 str_params.sparams = param; 269 str_params.sparams = param;
173 str_params.codec = param.codec; 270 str_params.aparams = alloc_params;
174 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 271 str_params.codec = SST_CODEC_TYPE_PCM;
175 str_params.ops = STREAM_OPS_PLAYBACK; 272
176 str_params.device_type = substream->pcm->device + 1; 273 /* fill the device type and stream id to pass to SST driver */
177 pr_debug("Playbck stream,Device %d\n", 274 ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
178 substream->pcm->device);
179 } else {
180 str_params.ops = STREAM_OPS_CAPTURE;
181 str_params.device_type = SND_SST_DEVICE_CAPTURE;
182 pr_debug("Capture stream,Device %d\n",
183 substream->pcm->device);
184 }
185 ret_val = stream->ops->open(&str_params);
186 pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
187 if (ret_val < 0) 275 if (ret_val < 0)
188 return ret_val; 276 return ret_val;
189 277
190 stream->stream_info.str_id = ret_val; 278 stream->stream_info.str_id = str_params.stream_id;
191 pr_debug("str id : %d\n", stream->stream_info.str_id); 279
280 ret_val = stream->ops->open(&str_params);
281 if (ret_val <= 0)
282 return ret_val;
283
284
192 return ret_val; 285 return ret_val;
193} 286}
194 287
195static void sst_period_elapsed(void *mad_substream) 288static void sst_period_elapsed(void *arg)
196{ 289{
197 struct snd_pcm_substream *substream = mad_substream; 290 struct snd_pcm_substream *substream = arg;
198 struct sst_runtime_stream *stream; 291 struct sst_runtime_stream *stream;
199 int status; 292 int status;
200 293
@@ -218,7 +311,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
218 pr_debug("setting buffer ptr param\n"); 311 pr_debug("setting buffer ptr param\n");
219 sst_set_stream_status(stream, SST_PLATFORM_INIT); 312 sst_set_stream_status(stream, SST_PLATFORM_INIT);
220 stream->stream_info.period_elapsed = sst_period_elapsed; 313 stream->stream_info.period_elapsed = sst_period_elapsed;
221 stream->stream_info.mad_substream = substream; 314 stream->stream_info.arg = substream;
222 stream->stream_info.buffer_ptr = 0; 315 stream->stream_info.buffer_ptr = 0;
223 stream->stream_info.sfreq = substream->runtime->rate; 316 stream->stream_info.sfreq = substream->runtime->rate;
224 ret_val = stream->ops->device_control( 317 ret_val = stream->ops->device_control(
@@ -230,19 +323,12 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
230} 323}
231/* end -- helper functions */ 324/* end -- helper functions */
232 325
233static int sst_platform_open(struct snd_pcm_substream *substream) 326static int sst_media_open(struct snd_pcm_substream *substream,
327 struct snd_soc_dai *dai)
234{ 328{
329 int ret_val = 0;
235 struct snd_pcm_runtime *runtime = substream->runtime; 330 struct snd_pcm_runtime *runtime = substream->runtime;
236 struct sst_runtime_stream *stream; 331 struct sst_runtime_stream *stream;
237 int ret_val;
238
239 pr_debug("sst_platform_open called\n");
240
241 snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw);
242 ret_val = snd_pcm_hw_constraint_integer(runtime,
243 SNDRV_PCM_HW_PARAM_PERIODS);
244 if (ret_val < 0)
245 return ret_val;
246 332
247 stream = kzalloc(sizeof(*stream), GFP_KERNEL); 333 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
248 if (!stream) 334 if (!stream)
@@ -251,50 +337,69 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
251 337
252 /* get the sst ops */ 338 /* get the sst ops */
253 mutex_lock(&sst_lock); 339 mutex_lock(&sst_lock);
254 if (!sst) { 340 if (!sst ||
341 !try_module_get(sst->dev->driver->owner)) {
255 pr_err("no device available to run\n"); 342 pr_err("no device available to run\n");
256 mutex_unlock(&sst_lock); 343 ret_val = -ENODEV;
257 kfree(stream); 344 goto out_ops;
258 return -ENODEV;
259 }
260 if (!try_module_get(sst->dev->driver->owner)) {
261 mutex_unlock(&sst_lock);
262 kfree(stream);
263 return -ENODEV;
264 } 345 }
265 stream->ops = sst->ops; 346 stream->ops = sst->ops;
266 mutex_unlock(&sst_lock); 347 mutex_unlock(&sst_lock);
267 348
268 stream->stream_info.str_id = 0; 349 stream->stream_info.str_id = 0;
269 sst_set_stream_status(stream, SST_PLATFORM_INIT); 350
270 stream->stream_info.mad_substream = substream; 351 stream->stream_info.arg = substream;
271 /* allocate memory for SST API set */ 352 /* allocate memory for SST API set */
272 runtime->private_data = stream; 353 runtime->private_data = stream;
273 354
274 return 0; 355 /* Make sure, that the period size is always even */
356 snd_pcm_hw_constraint_step(substream->runtime, 0,
357 SNDRV_PCM_HW_PARAM_PERIODS, 2);
358
359 return snd_pcm_hw_constraint_integer(runtime,
360 SNDRV_PCM_HW_PARAM_PERIODS);
361out_ops:
362 kfree(stream);
363 mutex_unlock(&sst_lock);
364 return ret_val;
275} 365}
276 366
277static int sst_platform_close(struct snd_pcm_substream *substream) 367static void sst_media_close(struct snd_pcm_substream *substream,
368 struct snd_soc_dai *dai)
278{ 369{
279 struct sst_runtime_stream *stream; 370 struct sst_runtime_stream *stream;
280 int ret_val = 0, str_id; 371 int ret_val = 0, str_id;
281 372
282 pr_debug("sst_platform_close called\n");
283 stream = substream->runtime->private_data; 373 stream = substream->runtime->private_data;
284 str_id = stream->stream_info.str_id; 374 str_id = stream->stream_info.str_id;
285 if (str_id) 375 if (str_id)
286 ret_val = stream->ops->close(str_id); 376 ret_val = stream->ops->close(str_id);
287 module_put(sst->dev->driver->owner); 377 module_put(sst->dev->driver->owner);
288 kfree(stream); 378 kfree(stream);
289 return ret_val;
290} 379}
291 380
292static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) 381static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform,
382 struct snd_pcm_substream *substream)
383{
384 struct sst_data *sst = snd_soc_platform_get_drvdata(platform);
385 struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map;
386 struct sst_runtime_stream *stream =
387 substream->runtime->private_data;
388 u32 str_id = stream->stream_info.str_id;
389 unsigned int pipe_id;
390 pipe_id = map[str_id].device_id;
391
392 pr_debug("%s: got pipe_id = %#x for str_id = %d\n",
393 __func__, pipe_id, str_id);
394 return pipe_id;
395}
396
397static int sst_media_prepare(struct snd_pcm_substream *substream,
398 struct snd_soc_dai *dai)
293{ 399{
294 struct sst_runtime_stream *stream; 400 struct sst_runtime_stream *stream;
295 int ret_val = 0, str_id; 401 int ret_val = 0, str_id;
296 402
297 pr_debug("sst_platform_pcm_prepare called\n");
298 stream = substream->runtime->private_data; 403 stream = substream->runtime->private_data;
299 str_id = stream->stream_info.str_id; 404 str_id = stream->stream_info.str_id;
300 if (stream->stream_info.str_id) { 405 if (stream->stream_info.str_id) {
@@ -303,8 +408,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
303 return ret_val; 408 return ret_val;
304 } 409 }
305 410
306 ret_val = sst_platform_alloc_stream(substream); 411 ret_val = sst_platform_alloc_stream(substream, dai->platform);
307 if (ret_val < 0) 412 if (ret_val <= 0)
308 return ret_val; 413 return ret_val;
309 snprintf(substream->pcm->id, sizeof(substream->pcm->id), 414 snprintf(substream->pcm->id, sizeof(substream->pcm->id),
310 "%d", stream->stream_info.str_id); 415 "%d", stream->stream_info.str_id);
@@ -316,6 +421,41 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
316 return ret_val; 421 return ret_val;
317} 422}
318 423
424static int sst_media_hw_params(struct snd_pcm_substream *substream,
425 struct snd_pcm_hw_params *params,
426 struct snd_soc_dai *dai)
427{
428 snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
429 memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
430 return 0;
431}
432
433static int sst_media_hw_free(struct snd_pcm_substream *substream,
434 struct snd_soc_dai *dai)
435{
436 return snd_pcm_lib_free_pages(substream);
437}
438
439static struct snd_soc_dai_ops sst_media_dai_ops = {
440 .startup = sst_media_open,
441 .shutdown = sst_media_close,
442 .prepare = sst_media_prepare,
443 .hw_params = sst_media_hw_params,
444 .hw_free = sst_media_hw_free,
445};
446
447static int sst_platform_open(struct snd_pcm_substream *substream)
448{
449 struct snd_pcm_runtime *runtime;
450
451 if (substream->pcm->internal)
452 return 0;
453
454 runtime = substream->runtime;
455 runtime->hw = sst_platform_pcm_hw;
456 return 0;
457}
458
319static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, 459static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
320 int cmd) 460 int cmd)
321{ 461{
@@ -331,7 +471,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
331 pr_debug("sst: Trigger Start\n"); 471 pr_debug("sst: Trigger Start\n");
332 str_cmd = SST_SND_START; 472 str_cmd = SST_SND_START;
333 status = SST_PLATFORM_RUNNING; 473 status = SST_PLATFORM_RUNNING;
334 stream->stream_info.mad_substream = substream; 474 stream->stream_info.arg = substream;
335 break; 475 break;
336 case SNDRV_PCM_TRIGGER_STOP: 476 case SNDRV_PCM_TRIGGER_STOP:
337 pr_debug("sst: in stop\n"); 477 pr_debug("sst: in stop\n");
@@ -377,32 +517,15 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer
377 pr_err("sst: error code = %d\n", ret_val); 517 pr_err("sst: error code = %d\n", ret_val);
378 return ret_val; 518 return ret_val;
379 } 519 }
380 return stream->stream_info.buffer_ptr; 520 substream->runtime->delay = str_info->pcm_delay;
381} 521 return str_info->buffer_ptr;
382
383static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream,
384 struct snd_pcm_hw_params *params)
385{
386 snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
387 memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
388
389 return 0;
390}
391
392static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream)
393{
394 return snd_pcm_lib_free_pages(substream);
395} 522}
396 523
397static struct snd_pcm_ops sst_platform_ops = { 524static struct snd_pcm_ops sst_platform_ops = {
398 .open = sst_platform_open, 525 .open = sst_platform_open,
399 .close = sst_platform_close,
400 .ioctl = snd_pcm_lib_ioctl, 526 .ioctl = snd_pcm_lib_ioctl,
401 .prepare = sst_platform_pcm_prepare,
402 .trigger = sst_platform_pcm_trigger, 527 .trigger = sst_platform_pcm_trigger,
403 .pointer = sst_platform_pcm_pointer, 528 .pointer = sst_platform_pcm_pointer,
404 .hw_params = sst_platform_pcm_hw_params,
405 .hw_free = sst_platform_pcm_hw_free,
406}; 529};
407 530
408static void sst_pcm_free(struct snd_pcm *pcm) 531static void sst_pcm_free(struct snd_pcm *pcm)
@@ -413,15 +536,15 @@ static void sst_pcm_free(struct snd_pcm *pcm)
413 536
414static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) 537static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
415{ 538{
539 struct snd_soc_dai *dai = rtd->cpu_dai;
416 struct snd_pcm *pcm = rtd->pcm; 540 struct snd_pcm *pcm = rtd->pcm;
417 int retval = 0; 541 int retval = 0;
418 542
419 pr_debug("sst_pcm_new called\n"); 543 if (dai->driver->playback.channels_min ||
420 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || 544 dai->driver->capture.channels_min) {
421 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
422 retval = snd_pcm_lib_preallocate_pages_for_all(pcm, 545 retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
423 SNDRV_DMA_TYPE_CONTINUOUS, 546 SNDRV_DMA_TYPE_CONTINUOUS,
424 snd_dma_continuous_data(GFP_KERNEL), 547 snd_dma_continuous_data(GFP_DMA),
425 SST_MIN_BUFFER, SST_MAX_BUFFER); 548 SST_MIN_BUFFER, SST_MAX_BUFFER);
426 if (retval) { 549 if (retval) {
427 pr_err("dma buffer allocationf fail\n"); 550 pr_err("dma buffer allocationf fail\n");
@@ -445,10 +568,28 @@ static const struct snd_soc_component_driver sst_component = {
445 568
446static int sst_platform_probe(struct platform_device *pdev) 569static int sst_platform_probe(struct platform_device *pdev)
447{ 570{
571 struct sst_data *drv;
448 int ret; 572 int ret;
573 struct sst_platform_data *pdata;
574
575 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
576 if (drv == NULL) {
577 pr_err("kzalloc failed\n");
578 return -ENOMEM;
579 }
580
581 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
582 if (pdata == NULL) {
583 pr_err("kzalloc failed for pdata\n");
584 return -ENOMEM;
585 }
586
587 pdata->pdev_strm_map = dpcm_strm_map;
588 pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
589 drv->pdata = pdata;
590 mutex_init(&drv->lock);
591 dev_set_drvdata(&pdev->dev, drv);
449 592
450 pr_debug("sst_platform_probe called\n");
451 sst = NULL;
452 ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); 593 ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
453 if (ret) { 594 if (ret) {
454 pr_err("registering soc platform failed\n"); 595 pr_err("registering soc platform failed\n");
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h
index 6c5e7dc49e3c..6c6a42c08e24 100644
--- a/sound/soc/intel/sst-mfld-platform.h
+++ b/sound/soc/intel/sst-mfld-platform.h
@@ -39,9 +39,10 @@ extern struct sst_device *sst;
39 39
40struct pcm_stream_info { 40struct pcm_stream_info {
41 int str_id; 41 int str_id;
42 void *mad_substream; 42 void *arg;
43 void (*period_elapsed) (void *mad_substream); 43 void (*period_elapsed) (void *arg);
44 unsigned long long buffer_ptr; 44 unsigned long long buffer_ptr;
45 unsigned long long pcm_delay;
45 int sfreq; 46 int sfreq;
46}; 47};
47 48
@@ -62,7 +63,9 @@ enum sst_controls {
62 SST_SND_BUFFER_POINTER = 0x05, 63 SST_SND_BUFFER_POINTER = 0x05,
63 SST_SND_STREAM_INIT = 0x06, 64 SST_SND_STREAM_INIT = 0x06,
64 SST_SND_START = 0x07, 65 SST_SND_START = 0x07,
65 SST_MAX_CONTROLS = 0x07, 66 SST_SET_BYTE_STREAM = 0x100A,
67 SST_GET_BYTE_STREAM = 0x100B,
68 SST_MAX_CONTROLS = SST_GET_BYTE_STREAM,
66}; 69};
67 70
68enum sst_stream_ops { 71enum sst_stream_ops {
@@ -124,8 +127,9 @@ struct compress_sst_ops {
124}; 127};
125 128
126struct sst_ops { 129struct sst_ops {
127 int (*open) (struct sst_stream_params *str_param); 130 int (*open) (struct snd_sst_params *str_param);
128 int (*device_control) (int cmd, void *arg); 131 int (*device_control) (int cmd, void *arg);
132 int (*set_generic_params)(enum sst_controls cmd, void *arg);
129 int (*close) (unsigned int str_id); 133 int (*close) (unsigned int str_id);
130}; 134};
131 135
@@ -143,10 +147,27 @@ struct sst_device {
143 char *name; 147 char *name;
144 struct device *dev; 148 struct device *dev;
145 struct sst_ops *ops; 149 struct sst_ops *ops;
150 struct platform_device *pdev;
146 struct compress_sst_ops *compr_ops; 151 struct compress_sst_ops *compr_ops;
147}; 152};
148 153
154struct sst_data;
149void sst_set_stream_status(struct sst_runtime_stream *stream, int state); 155void sst_set_stream_status(struct sst_runtime_stream *stream, int state);
156int sst_fill_stream_params(void *substream, const struct sst_data *ctx,
157 struct snd_sst_params *str_params, bool is_compress);
158
159struct sst_algo_int_control_v2 {
160 struct soc_mixer_control mc;
161 u16 module_id; /* module identifieer */
162 u16 pipe_id; /* location info: pipe_id + instance_id */
163 u16 instance_id;
164 unsigned int value; /* Value received is stored here */
165};
166struct sst_data {
167 struct platform_device *pdev;
168 struct sst_platform_data *pdata;
169 struct mutex lock;
170};
150int sst_register_dsp(struct sst_device *sst); 171int sst_register_dsp(struct sst_device *sst);
151int sst_unregister_dsp(struct sst_device *sst); 172int sst_unregister_dsp(struct sst_device *sst);
152#endif 173#endif
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index 06f4e8aa93ae..132bb83f8e99 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -1,6 +1,6 @@
1config SND_KIRKWOOD_SOC 1config SND_KIRKWOOD_SOC
2 tristate "SoC Audio for the Marvell Kirkwood and Dove chips" 2 tristate "SoC Audio for the Marvell Kirkwood and Dove chips"
3 depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || MACH_KIRKWOOD || COMPILE_TEST 3 depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the Kirkwood I2S interface. You will also need to select the 6 the Kirkwood I2S interface. You will also need to select the
@@ -15,20 +15,3 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB
15 Say Y if you want to add support for SoC audio on 15 Say Y if you want to add support for SoC audio on
16 the Armada 370 Development Board. 16 the Armada 370 Development Board.
17 17
18config SND_KIRKWOOD_SOC_OPENRD
19 tristate "SoC Audio support for Kirkwood Openrd Client"
20 depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST)
21 depends on I2C
22 select SND_SOC_CS42L51
23 help
24 Say Y if you want to add support for SoC audio on
25 Openrd Client.
26
27config SND_KIRKWOOD_SOC_T5325
28 tristate "SoC Audio support for HP t5325"
29 depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C
30 select SND_SOC_ALC5623
31 help
32 Say Y if you want to add support for SoC audio on
33 the HP t5325 thin client.
34
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile
index 7c1d8fe09e6b..c36b03d8006c 100644
--- a/sound/soc/kirkwood/Makefile
+++ b/sound/soc/kirkwood/Makefile
@@ -2,10 +2,6 @@ snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o
2 2
3obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o 3obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o
4 4
5snd-soc-openrd-objs := kirkwood-openrd.o
6snd-soc-t5325-objs := kirkwood-t5325.o
7snd-soc-armada-370-db-objs := armada-370-db.o 5snd-soc-armada-370-db-objs := armada-370-db.o
8 6
9obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o 7obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o
10obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o
11obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index aac22fccdcdc..4cf2245950d7 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -28,11 +28,12 @@ static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
28} 28}
29 29
30static struct snd_pcm_hardware kirkwood_dma_snd_hw = { 30static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
31 .info = (SNDRV_PCM_INFO_INTERLEAVED | 31 .info = SNDRV_PCM_INFO_INTERLEAVED |
32 SNDRV_PCM_INFO_MMAP | 32 SNDRV_PCM_INFO_MMAP |
33 SNDRV_PCM_INFO_MMAP_VALID | 33 SNDRV_PCM_INFO_MMAP_VALID |
34 SNDRV_PCM_INFO_BLOCK_TRANSFER | 34 SNDRV_PCM_INFO_BLOCK_TRANSFER |
35 SNDRV_PCM_INFO_PAUSE), 35 SNDRV_PCM_INFO_PAUSE |
36 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
36 .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, 37 .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES,
37 .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, 38 .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
38 .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, 39 .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES,
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 9f842222e798..0704cd6d2314 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -212,7 +212,8 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
212 KIRKWOOD_PLAYCTL_SIZE_MASK); 212 KIRKWOOD_PLAYCTL_SIZE_MASK);
213 priv->ctl_play |= ctl_play; 213 priv->ctl_play |= ctl_play;
214 } else { 214 } else {
215 priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK; 215 priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
216 KIRKWOOD_RECCTL_SIZE_MASK);
216 priv->ctl_rec |= ctl_rec; 217 priv->ctl_rec |= ctl_rec;
217 } 218 }
218 219
@@ -221,14 +222,24 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
221 return 0; 222 return 0;
222} 223}
223 224
225static unsigned kirkwood_i2s_play_mute(unsigned ctl)
226{
227 if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
228 ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
229 if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
230 ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
231 return ctl;
232}
233
224static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, 234static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
225 int cmd, struct snd_soc_dai *dai) 235 int cmd, struct snd_soc_dai *dai)
226{ 236{
237 struct snd_pcm_runtime *runtime = substream->runtime;
227 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); 238 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
228 uint32_t ctl, value; 239 uint32_t ctl, value;
229 240
230 ctl = readl(priv->io + KIRKWOOD_PLAYCTL); 241 ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
231 if (ctl & KIRKWOOD_PLAYCTL_PAUSE) { 242 if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
232 unsigned timeout = 5000; 243 unsigned timeout = 5000;
233 /* 244 /*
234 * The Armada510 spec says that if we enter pause mode, the 245 * The Armada510 spec says that if we enter pause mode, the
@@ -256,14 +267,16 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
256 ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ 267 ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */
257 else 268 else
258 ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ 269 ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */
259 270 ctl = kirkwood_i2s_play_mute(ctl);
260 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; 271 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
261 writel(value, priv->io + KIRKWOOD_PLAYCTL); 272 writel(value, priv->io + KIRKWOOD_PLAYCTL);
262 273
263 /* enable interrupts */ 274 /* enable interrupts */
264 value = readl(priv->io + KIRKWOOD_INT_MASK); 275 if (!runtime->no_period_wakeup) {
265 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; 276 value = readl(priv->io + KIRKWOOD_INT_MASK);
266 writel(value, priv->io + KIRKWOOD_INT_MASK); 277 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
278 writel(value, priv->io + KIRKWOOD_INT_MASK);
279 }
267 280
268 /* enable playback */ 281 /* enable playback */
269 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 282 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
@@ -295,6 +308,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
295 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 308 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
296 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | 309 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
297 KIRKWOOD_PLAYCTL_SPDIF_MUTE); 310 KIRKWOOD_PLAYCTL_SPDIF_MUTE);
311 ctl = kirkwood_i2s_play_mute(ctl);
298 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 312 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
299 break; 313 break;
300 314
@@ -322,8 +336,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
322 else 336 else
323 ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ 337 ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */
324 338
325 value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN | 339 value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
326 KIRKWOOD_RECCTL_SPDIF_EN);
327 writel(value, priv->io + KIRKWOOD_RECCTL); 340 writel(value, priv->io + KIRKWOOD_RECCTL);
328 341
329 /* enable interrupts */ 342 /* enable interrupts */
@@ -347,7 +360,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
347 360
348 /* disable all records */ 361 /* disable all records */
349 value = readl(priv->io + KIRKWOOD_RECCTL); 362 value = readl(priv->io + KIRKWOOD_RECCTL);
350 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); 363 value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
351 writel(value, priv->io + KIRKWOOD_RECCTL); 364 writel(value, priv->io + KIRKWOOD_RECCTL);
352 break; 365 break;
353 366
@@ -411,7 +424,7 @@ static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
411 writel(value, priv->io + KIRKWOOD_PLAYCTL); 424 writel(value, priv->io + KIRKWOOD_PLAYCTL);
412 425
413 value = readl(priv->io + KIRKWOOD_RECCTL); 426 value = readl(priv->io + KIRKWOOD_RECCTL);
414 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); 427 value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
415 writel(value, priv->io + KIRKWOOD_RECCTL); 428 writel(value, priv->io + KIRKWOOD_RECCTL);
416 429
417 return 0; 430 return 0;
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
deleted file mode 100644
index 65f2a5b9ec3b..000000000000
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ /dev/null
@@ -1,109 +0,0 @@
1/*
2 * kirkwood-openrd.c
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/interrupt.h>
16#include <linux/platform_device.h>
17#include <linux/slab.h>
18#include <sound/soc.h>
19#include <linux/platform_data/asoc-kirkwood.h>
20#include "../codecs/cs42l51.h"
21
22static int openrd_client_hw_params(struct snd_pcm_substream *substream,
23 struct snd_pcm_hw_params *params)
24{
25 struct snd_soc_pcm_runtime *rtd = substream->private_data;
26 struct snd_soc_dai *codec_dai = rtd->codec_dai;
27 unsigned int freq;
28
29 switch (params_rate(params)) {
30 default:
31 case 44100:
32 freq = 11289600;
33 break;
34 case 48000:
35 freq = 12288000;
36 break;
37 case 96000:
38 freq = 24576000;
39 break;
40 }
41
42 return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
43
44}
45
46static struct snd_soc_ops openrd_client_ops = {
47 .hw_params = openrd_client_hw_params,
48};
49
50
51static struct snd_soc_dai_link openrd_client_dai[] = {
52{
53 .name = "CS42L51",
54 .stream_name = "CS42L51 HiFi",
55 .cpu_dai_name = "i2s",
56 .platform_name = "mvebu-audio",
57 .codec_dai_name = "cs42l51-hifi",
58 .codec_name = "cs42l51-codec.0-004a",
59 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
60 .ops = &openrd_client_ops,
61},
62};
63
64
65static struct snd_soc_card openrd_client = {
66 .name = "OpenRD Client",
67 .owner = THIS_MODULE,
68 .dai_link = openrd_client_dai,
69 .num_links = ARRAY_SIZE(openrd_client_dai),
70};
71
72static int openrd_probe(struct platform_device *pdev)
73{
74 struct snd_soc_card *card = &openrd_client;
75 int ret;
76
77 card->dev = &pdev->dev;
78
79 ret = snd_soc_register_card(card);
80 if (ret)
81 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
82 ret);
83 return ret;
84}
85
86static int openrd_remove(struct platform_device *pdev)
87{
88 struct snd_soc_card *card = platform_get_drvdata(pdev);
89
90 snd_soc_unregister_card(card);
91 return 0;
92}
93
94static struct platform_driver openrd_driver = {
95 .driver = {
96 .name = "openrd-client-audio",
97 .owner = THIS_MODULE,
98 },
99 .probe = openrd_probe,
100 .remove = openrd_remove,
101};
102
103module_platform_driver(openrd_driver);
104
105/* Module information */
106MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
107MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
108MODULE_LICENSE("GPL");
109MODULE_ALIAS("platform:openrd-client-audio");
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
deleted file mode 100644
index 844b8415a011..000000000000
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ /dev/null
@@ -1,116 +0,0 @@
1/*
2 * kirkwood-t5325.c
3 *
4 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/interrupt.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <sound/soc.h>
18#include <linux/platform_data/asoc-kirkwood.h>
19#include "../codecs/alc5623.h"
20
21static int t5325_hw_params(struct snd_pcm_substream *substream,
22 struct snd_pcm_hw_params *params)
23{
24 struct snd_soc_pcm_runtime *rtd = substream->private_data;
25 struct snd_soc_dai *codec_dai = rtd->codec_dai;
26 unsigned int freq;
27
28 freq = params_rate(params) * 256;
29
30 return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
31
32}
33
34static struct snd_soc_ops t5325_ops = {
35 .hw_params = t5325_hw_params,
36};
37
38static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = {
39 SND_SOC_DAPM_HP("Headphone Jack", NULL),
40 SND_SOC_DAPM_SPK("Speaker", NULL),
41 SND_SOC_DAPM_MIC("Mic Jack", NULL),
42};
43
44static const struct snd_soc_dapm_route t5325_route[] = {
45 { "Headphone Jack", NULL, "HPL" },
46 { "Headphone Jack", NULL, "HPR" },
47
48 {"Speaker", NULL, "SPKOUT"},
49 {"Speaker", NULL, "SPKOUTN"},
50
51 { "MIC1", NULL, "Mic Jack" },
52 { "MIC2", NULL, "Mic Jack" },
53};
54
55static struct snd_soc_dai_link t5325_dai[] = {
56{
57 .name = "ALC5621",
58 .stream_name = "ALC5621 HiFi",
59 .cpu_dai_name = "i2s",
60 .platform_name = "mvebu-audio",
61 .codec_dai_name = "alc5621-hifi",
62 .codec_name = "alc562x-codec.0-001a",
63 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
64 .ops = &t5325_ops,
65},
66};
67
68static struct snd_soc_card t5325 = {
69 .name = "t5325",
70 .owner = THIS_MODULE,
71 .dai_link = t5325_dai,
72 .num_links = ARRAY_SIZE(t5325_dai),
73
74 .dapm_widgets = t5325_dapm_widgets,
75 .num_dapm_widgets = ARRAY_SIZE(t5325_dapm_widgets),
76 .dapm_routes = t5325_route,
77 .num_dapm_routes = ARRAY_SIZE(t5325_route),
78};
79
80static int t5325_probe(struct platform_device *pdev)
81{
82 struct snd_soc_card *card = &t5325;
83 int ret;
84
85 card->dev = &pdev->dev;
86
87 ret = snd_soc_register_card(card);
88 if (ret)
89 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
90 ret);
91 return ret;
92}
93
94static int t5325_remove(struct platform_device *pdev)
95{
96 struct snd_soc_card *card = platform_get_drvdata(pdev);
97
98 snd_soc_unregister_card(card);
99 return 0;
100}
101
102static struct platform_driver t5325_driver = {
103 .driver = {
104 .name = "t5325-audio",
105 .owner = THIS_MODULE,
106 },
107 .probe = t5325_probe,
108 .remove = t5325_remove,
109};
110
111module_platform_driver(t5325_driver);
112
113MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
114MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
115MODULE_LICENSE("GPL");
116MODULE_ALIAS("platform:t5325-audio");
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
index bf23afbba1d7..90e32a781424 100644
--- a/sound/soc/kirkwood/kirkwood.h
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -38,6 +38,9 @@
38#define KIRKWOOD_RECCTL_SIZE_24 (1<<0) 38#define KIRKWOOD_RECCTL_SIZE_24 (1<<0)
39#define KIRKWOOD_RECCTL_SIZE_32 (0<<0) 39#define KIRKWOOD_RECCTL_SIZE_32 (0<<0)
40 40
41#define KIRKWOOD_RECCTL_ENABLE_MASK (KIRKWOOD_RECCTL_SPDIF_EN | \
42 KIRKWOOD_RECCTL_I2S_EN)
43
41#define KIRKWOOD_REC_BUF_ADDR 0x1004 44#define KIRKWOOD_REC_BUF_ADDR 0x1004
42#define KIRKWOOD_REC_BUF_SIZE 0x1008 45#define KIRKWOOD_REC_BUF_SIZE 0x1008
43#define KIRKWOOD_REC_BYTE_COUNT 0x100C 46#define KIRKWOOD_REC_BYTE_COUNT 0x100C
@@ -121,9 +124,9 @@
121 124
122/* Theses values come from the marvell alsa driver */ 125/* Theses values come from the marvell alsa driver */
123/* need to find where they come from */ 126/* need to find where they come from */
124#define KIRKWOOD_SND_MIN_PERIODS 8 127#define KIRKWOOD_SND_MIN_PERIODS 2
125#define KIRKWOOD_SND_MAX_PERIODS 16 128#define KIRKWOOD_SND_MAX_PERIODS 16
126#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x800 129#define KIRKWOOD_SND_MIN_PERIOD_BYTES 256
127#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000 130#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000
128#define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \ 131#define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \
129 * KIRKWOOD_SND_MAX_PERIODS) 132 * KIRKWOOD_SND_MAX_PERIODS)