aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-06-17 12:20:30 -0400
committerMark Brown <broonie@linaro.org>2013-06-17 12:20:30 -0400
commit458bcee95d9ff742dcb379f6605a4023848ed8cb (patch)
tree1ac46e360f79c77b4dda692ad1110076d909e3bd
parent93d4c1e04f9a316decc2d0fca3ce3a8e9722a155 (diff)
parenteef6473ff3ce2383febebd2e799beceaece9adda (diff)
Merge remote-tracking branch 'asoc/topic/ux500' into asoc-next
-rw-r--r--sound/soc/codecs/ab8500-codec.c79
-rw-r--r--sound/soc/codecs/ab8500-codec.h42
-rw-r--r--sound/soc/ux500/mop500_ab8500.c36
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c11
-rw-r--r--sound/soc/ux500/ux500_msp_dai.h4
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.c88
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.h74
-rw-r--r--sound/soc/ux500/ux500_pcm.c30
8 files changed, 159 insertions, 205 deletions
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 3126cac7b7c8..b8ba0adacfce 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2236,7 +2236,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2236 int slots, int slot_width) 2236 int slots, int slot_width)
2237{ 2237{
2238 struct snd_soc_codec *codec = dai->codec; 2238 struct snd_soc_codec *codec = dai->codec;
2239 unsigned int val, mask, slots_active; 2239 unsigned int val, mask, slot, slots_active;
2240 2240
2241 mask = BIT(AB8500_DIGIFCONF2_IF0WL0) | 2241 mask = BIT(AB8500_DIGIFCONF2_IF0WL0) |
2242 BIT(AB8500_DIGIFCONF2_IF0WL1); 2242 BIT(AB8500_DIGIFCONF2_IF0WL1);
@@ -2292,27 +2292,34 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2292 snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); 2292 snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
2293 2293
2294 /* Setup TDM DA according to active tx slots */ 2294 /* Setup TDM DA according to active tx slots */
2295
2296 if (tx_mask & ~0xff)
2297 return -EINVAL;
2298
2295 mask = AB8500_DASLOTCONFX_SLTODAX_MASK; 2299 mask = AB8500_DASLOTCONFX_SLTODAX_MASK;
2300 tx_mask = tx_mask << AB8500_DA_DATA0_OFFSET;
2296 slots_active = hweight32(tx_mask); 2301 slots_active = hweight32(tx_mask);
2302
2297 dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__, 2303 dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__,
2298 slots_active); 2304 slots_active);
2305
2299 switch (slots_active) { 2306 switch (slots_active) {
2300 case 0: 2307 case 0:
2301 break; 2308 break;
2302 case 1: 2309 case 1:
2303 /* Slot 9 -> DA_IN1 & DA_IN3 */ 2310 slot = find_first_bit((unsigned long *)&tx_mask, 32);
2304 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11); 2311 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
2305 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11); 2312 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
2306 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); 2313 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
2307 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); 2314 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
2308 break; 2315 break;
2309 case 2: 2316 case 2:
2310 /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */ 2317 slot = find_first_bit((unsigned long *)&tx_mask, 32);
2311 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9); 2318 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
2312 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9); 2319 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
2313 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); 2320 slot = find_next_bit((unsigned long *)&tx_mask, 32, slot + 1);
2314 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); 2321 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
2315 2322 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
2316 break; 2323 break;
2317 case 8: 2324 case 8:
2318 dev_dbg(dai->codec->dev, 2325 dev_dbg(dai->codec->dev,
@@ -2327,25 +2334,36 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2327 } 2334 }
2328 2335
2329 /* Setup TDM AD according to active RX-slots */ 2336 /* Setup TDM AD according to active RX-slots */
2337
2338 if (rx_mask & ~0xff)
2339 return -EINVAL;
2340
2341 rx_mask = rx_mask << AB8500_AD_DATA0_OFFSET;
2330 slots_active = hweight32(rx_mask); 2342 slots_active = hweight32(rx_mask);
2343
2331 dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__, 2344 dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__,
2332 slots_active); 2345 slots_active);
2346
2333 switch (slots_active) { 2347 switch (slots_active) {
2334 case 0: 2348 case 0:
2335 break; 2349 break;
2336 case 1: 2350 case 1:
2337 /* AD_OUT3 -> slot 0 & 1 */ 2351 slot = find_first_bit((unsigned long *)&rx_mask, 32);
2338 snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL, 2352 snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot),
2339 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | 2353 AB8500_MASK_SLOT(slot),
2340 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD); 2354 AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
2341 break; 2355 break;
2342 case 2: 2356 case 2:
2343 /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */ 2357 slot = find_first_bit((unsigned long *)&rx_mask, 32);
2358 snd_soc_update_bits(codec,
2359 AB8500_ADSLOTSEL(slot),
2360 AB8500_MASK_SLOT(slot),
2361 AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
2362 slot = find_next_bit((unsigned long *)&rx_mask, 32, slot + 1);
2344 snd_soc_update_bits(codec, 2363 snd_soc_update_bits(codec,
2345 AB8500_ADSLOTSEL1, 2364 AB8500_ADSLOTSEL(slot),
2346 AB8500_MASK_ALL, 2365 AB8500_MASK_SLOT(slot),
2347 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | 2366 AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT2, slot));
2348 AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD);
2349 break; 2367 break;
2350 case 8: 2368 case 8:
2351 dev_dbg(dai->codec->dev, 2369 dev_dbg(dai->codec->dev,
@@ -2362,6 +2380,11 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2362 return 0; 2380 return 0;
2363} 2381}
2364 2382
2383static const struct snd_soc_dai_ops ab8500_codec_ops = {
2384 .set_fmt = ab8500_codec_set_dai_fmt,
2385 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2386};
2387
2365static struct snd_soc_dai_driver ab8500_codec_dai[] = { 2388static struct snd_soc_dai_driver ab8500_codec_dai[] = {
2366 { 2389 {
2367 .name = "ab8500-codec-dai.0", 2390 .name = "ab8500-codec-dai.0",
@@ -2373,12 +2396,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
2373 .rates = AB8500_SUPPORTED_RATE, 2396 .rates = AB8500_SUPPORTED_RATE,
2374 .formats = AB8500_SUPPORTED_FMT, 2397 .formats = AB8500_SUPPORTED_FMT,
2375 }, 2398 },
2376 .ops = (struct snd_soc_dai_ops[]) { 2399 .ops = &ab8500_codec_ops,
2377 {
2378 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2379 .set_fmt = ab8500_codec_set_dai_fmt,
2380 }
2381 },
2382 .symmetric_rates = 1 2400 .symmetric_rates = 1
2383 }, 2401 },
2384 { 2402 {
@@ -2391,12 +2409,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
2391 .rates = AB8500_SUPPORTED_RATE, 2409 .rates = AB8500_SUPPORTED_RATE,
2392 .formats = AB8500_SUPPORTED_FMT, 2410 .formats = AB8500_SUPPORTED_FMT,
2393 }, 2411 },
2394 .ops = (struct snd_soc_dai_ops[]) { 2412 .ops = &ab8500_codec_ops,
2395 {
2396 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2397 .set_fmt = ab8500_codec_set_dai_fmt,
2398 }
2399 },
2400 .symmetric_rates = 1 2413 .symmetric_rates = 1
2401 } 2414 }
2402}; 2415};
diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h
index 306d0bc8455f..e2e54425d25e 100644
--- a/sound/soc/codecs/ab8500-codec.h
+++ b/sound/soc/codecs/ab8500-codec.h
@@ -24,6 +24,13 @@
24#define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000) 24#define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000)
25#define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE) 25#define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE)
26 26
27/* AB8500 interface slot offset definitions */
28
29#define AB8500_AD_DATA0_OFFSET 0
30#define AB8500_DA_DATA0_OFFSET 8
31#define AB8500_AD_DATA1_OFFSET 16
32#define AB8500_DA_DATA1_OFFSET 24
33
27/* AB8500 audio bank (0x0d) register definitions */ 34/* AB8500 audio bank (0x0d) register definitions */
28 35
29#define AB8500_POWERUP 0x00 36#define AB8500_POWERUP 0x00
@@ -73,6 +80,7 @@
73#define AB8500_ADSLOTSEL14 0x2C 80#define AB8500_ADSLOTSEL14 0x2C
74#define AB8500_ADSLOTSEL15 0x2D 81#define AB8500_ADSLOTSEL15 0x2D
75#define AB8500_ADSLOTSEL16 0x2E 82#define AB8500_ADSLOTSEL16 0x2E
83#define AB8500_ADSLOTSEL(slot) (AB8500_ADSLOTSEL1 + (slot >> 1))
76#define AB8500_ADSLOTHIZCTRL1 0x2F 84#define AB8500_ADSLOTHIZCTRL1 0x2F
77#define AB8500_ADSLOTHIZCTRL2 0x30 85#define AB8500_ADSLOTHIZCTRL2 0x30
78#define AB8500_ADSLOTHIZCTRL3 0x31 86#define AB8500_ADSLOTHIZCTRL3 0x31
@@ -144,6 +152,7 @@
144#define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1) 152#define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1)
145 153
146#define AB8500_MASK_ALL 0xFF 154#define AB8500_MASK_ALL 0xFF
155#define AB8500_MASK_SLOT(slot) ((slot & 1) ? 0xF0 : 0x0F)
147#define AB8500_MASK_NONE 0x00 156#define AB8500_MASK_NONE 0x00
148 157
149/* AB8500_POWERUP */ 158/* AB8500_POWERUP */
@@ -347,28 +356,21 @@
347#define AB8500_DIGIFCONF4_IF1WL0 0 356#define AB8500_DIGIFCONF4_IF1WL0 0
348 357
349/* AB8500_ADSLOTSELX */ 358/* AB8500_ADSLOTSELX */
350#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD 0x00 359#define AB8500_AD_OUT1 0x0
351#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD 0x10 360#define AB8500_AD_OUT2 0x1
352#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD 0x20 361#define AB8500_AD_OUT3 0x2
353#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD 0x30 362#define AB8500_AD_OUT4 0x3
354#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD 0x40 363#define AB8500_AD_OUT5 0x4
355#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD 0x50 364#define AB8500_AD_OUT6 0x5
356#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD 0x60 365#define AB8500_AD_OUT7 0x6
357#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD 0x70 366#define AB8500_AD_OUT8 0x7
358#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD 0x80 367#define AB8500_ZEROES 0x8
359#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0xF0 368#define AB8500_TRISTATE 0xF
360#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00
361#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x01
362#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x02
363#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x03
364#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x04
365#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x05
366#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x06
367#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x07
368#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN 0x08
369#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN 0x0F
370#define AB8500_ADSLOTSELX_EVEN_SHIFT 0 369#define AB8500_ADSLOTSELX_EVEN_SHIFT 0
371#define AB8500_ADSLOTSELX_ODD_SHIFT 4 370#define AB8500_ADSLOTSELX_ODD_SHIFT 4
371#define AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(out, slot) \
372 ((out) << (((slot) & 1) ? \
373 AB8500_ADSLOTSELX_ODD_SHIFT : AB8500_ADSLOTSELX_EVEN_SHIFT))
372 374
373/* AB8500_ADSLOTHIZCTRL1 */ 375/* AB8500_ADSLOTHIZCTRL1 */
374/* AB8500_ADSLOTHIZCTRL2 */ 376/* AB8500_ADSLOTHIZCTRL2 */
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c
index 884a36224fb1..7e923ecf8901 100644
--- a/sound/soc/ux500/mop500_ab8500.c
+++ b/sound/soc/ux500/mop500_ab8500.c
@@ -16,6 +16,7 @@
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/mutex.h>
19 20
20#include <sound/soc.h> 21#include <sound/soc.h>
21#include <sound/soc-dapm.h> 22#include <sound/soc-dapm.h>
@@ -24,6 +25,7 @@
24 25
25#include "ux500_pcm.h" 26#include "ux500_pcm.h"
26#include "ux500_msp_dai.h" 27#include "ux500_msp_dai.h"
28#include "mop500_ab8500.h"
27#include "../codecs/ab8500-codec.h" 29#include "../codecs/ab8500-codec.h"
28 30
29#define TX_SLOT_MONO 0x0008 31#define TX_SLOT_MONO 0x0008
@@ -43,6 +45,12 @@
43static unsigned int tx_slots = DEF_TX_SLOTS; 45static unsigned int tx_slots = DEF_TX_SLOTS;
44static unsigned int rx_slots = DEF_RX_SLOTS; 46static unsigned int rx_slots = DEF_RX_SLOTS;
45 47
48/* Configuration consistency parameters */
49static DEFINE_MUTEX(mop500_ab8500_params_lock);
50static unsigned long mop500_ab8500_usage;
51static int mop500_ab8500_rate;
52static int mop500_ab8500_channels;
53
46/* Clocks */ 54/* Clocks */
47static const char * const enum_mclk[] = { 55static const char * const enum_mclk[] = {
48 "SYSCLK", 56 "SYSCLK",
@@ -230,6 +238,21 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
230 substream->name, 238 substream->name,
231 substream->number); 239 substream->number);
232 240
241 /* Ensure configuration consistency between DAIs */
242 mutex_lock(&mop500_ab8500_params_lock);
243 if (mop500_ab8500_usage) {
244 if (mop500_ab8500_rate != params_rate(params) ||
245 mop500_ab8500_channels != params_channels(params)) {
246 mutex_unlock(&mop500_ab8500_params_lock);
247 return -EBUSY;
248 }
249 } else {
250 mop500_ab8500_rate = params_rate(params);
251 mop500_ab8500_channels = params_channels(params);
252 }
253 __set_bit(cpu_dai->id, &mop500_ab8500_usage);
254 mutex_unlock(&mop500_ab8500_params_lock);
255
233 channels = params_channels(params); 256 channels = params_channels(params);
234 257
235 switch (params_format(params)) { 258 switch (params_format(params)) {
@@ -328,9 +351,22 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
328 return 0; 351 return 0;
329} 352}
330 353
354static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream)
355{
356 struct snd_soc_pcm_runtime *rtd = substream->private_data;
357 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
358
359 mutex_lock(&mop500_ab8500_params_lock);
360 __clear_bit(cpu_dai->id, &mop500_ab8500_usage);
361 mutex_unlock(&mop500_ab8500_params_lock);
362
363 return 0;
364}
365
331struct snd_soc_ops mop500_ab8500_ops[] = { 366struct snd_soc_ops mop500_ab8500_ops[] = {
332 { 367 {
333 .hw_params = mop500_ab8500_hw_params, 368 .hw_params = mop500_ab8500_hw_params,
369 .hw_free = mop500_ab8500_hw_free,
334 .startup = mop500_ab8500_startup, 370 .startup = mop500_ab8500_startup,
335 .shutdown = mop500_ab8500_shutdown, 371 .shutdown = mop500_ab8500_shutdown,
336 } 372 }
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 7d5fc1328523..c6fb5cce980e 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -658,14 +658,11 @@ static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
658{ 658{
659 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev); 659 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
660 660
661 drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx; 661 dai->playback_dma_data = &drvdata->msp->playback_dma_data;
662 drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx; 662 dai->capture_dma_data = &drvdata->msp->capture_dma_data;
663 663
664 dai->playback_dma_data = &drvdata->playback_dma_data; 664 drvdata->msp->playback_dma_data.data_size = drvdata->slot_width;
665 dai->capture_dma_data = &drvdata->capture_dma_data; 665 drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
666
667 drvdata->playback_dma_data.data_size = drvdata->slot_width;
668 drvdata->capture_dma_data.data_size = drvdata->slot_width;
669 666
670 return 0; 667 return 0;
671} 668}
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h
index f53104359f15..312ae535e351 100644
--- a/sound/soc/ux500/ux500_msp_dai.h
+++ b/sound/soc/ux500/ux500_msp_dai.h
@@ -51,15 +51,11 @@ enum ux500_msp_clock_id {
51struct ux500_msp_i2s_drvdata { 51struct ux500_msp_i2s_drvdata {
52 struct ux500_msp *msp; 52 struct ux500_msp *msp;
53 struct regulator *reg_vape; 53 struct regulator *reg_vape;
54 struct ux500_msp_dma_params playback_dma_data;
55 struct ux500_msp_dma_params capture_dma_data;
56 unsigned int fmt; 54 unsigned int fmt;
57 unsigned int tx_mask; 55 unsigned int tx_mask;
58 unsigned int rx_mask; 56 unsigned int rx_mask;
59 int slots; 57 int slots;
60 int slot_width; 58 int slot_width;
61 u8 configured;
62 int data_delay;
63 59
64 /* Clocks */ 60 /* Clocks */
65 unsigned int master_clk; 61 unsigned int master_clk;
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c
index f2db6c90a9e2..1ca8b08ae993 100644
--- a/sound/soc/ux500/ux500_msp_i2s.c
+++ b/sound/soc/ux500/ux500_msp_i2s.c
@@ -15,7 +15,6 @@
15 15
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/pinctrl/consumer.h>
19#include <linux/delay.h> 18#include <linux/delay.h>
20#include <linux/slab.h> 19#include <linux/slab.h>
21#include <linux/io.h> 20#include <linux/io.h>
@@ -26,9 +25,6 @@
26 25
27#include "ux500_msp_i2s.h" 26#include "ux500_msp_i2s.h"
28 27
29/* MSP1/3 Tx/Rx usage protection */
30static DEFINE_SPINLOCK(msp_rxtx_lock);
31
32 /* Protocol desciptors */ 28 /* Protocol desciptors */
33static const struct msp_protdesc prot_descs[] = { 29static const struct msp_protdesc prot_descs[] = {
34 { /* I2S */ 30 { /* I2S */
@@ -356,24 +352,8 @@ static int configure_multichannel(struct ux500_msp *msp,
356 352
357static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) 353static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
358{ 354{
359 int status = 0, retval = 0; 355 int status = 0;
360 u32 reg_val_DMACR, reg_val_GCR; 356 u32 reg_val_DMACR, reg_val_GCR;
361 unsigned long flags;
362
363 /* Check msp state whether in RUN or CONFIGURED Mode */
364 if (msp->msp_state == MSP_STATE_IDLE) {
365 spin_lock_irqsave(&msp_rxtx_lock, flags);
366 if (msp->pinctrl_rxtx_ref == 0 &&
367 !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_def))) {
368 retval = pinctrl_select_state(msp->pinctrl_p,
369 msp->pinctrl_def);
370 if (retval)
371 pr_err("could not set MSP defstate\n");
372 }
373 if (!retval)
374 msp->pinctrl_rxtx_ref++;
375 spin_unlock_irqrestore(&msp_rxtx_lock, flags);
376 }
377 357
378 /* Configure msp with protocol dependent settings */ 358 /* Configure msp with protocol dependent settings */
379 configure_protocol(msp, config); 359 configure_protocol(msp, config);
@@ -387,12 +367,14 @@ static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
387 } 367 }
388 368
389 /* Make sure the correct DMA-directions are configured */ 369 /* Make sure the correct DMA-directions are configured */
390 if ((config->direction & MSP_DIR_RX) && (!msp->dma_cfg_rx)) { 370 if ((config->direction & MSP_DIR_RX) &&
371 !msp->capture_dma_data.dma_cfg) {
391 dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!", 372 dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!",
392 __func__); 373 __func__);
393 return -EINVAL; 374 return -EINVAL;
394 } 375 }
395 if ((config->direction == MSP_DIR_TX) && (!msp->dma_cfg_tx)) { 376 if ((config->direction == MSP_DIR_TX) &&
377 !msp->playback_dma_data.dma_cfg) {
396 dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!", 378 dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!",
397 __func__); 379 __func__);
398 return -EINVAL; 380 return -EINVAL;
@@ -630,8 +612,7 @@ int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)
630 612
631int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) 613int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
632{ 614{
633 int status = 0, retval = 0; 615 int status = 0;
634 unsigned long flags;
635 616
636 dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir); 617 dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir);
637 618
@@ -643,18 +624,6 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
643 (~(FRAME_GEN_ENABLE | SRG_ENABLE))), 624 (~(FRAME_GEN_ENABLE | SRG_ENABLE))),
644 msp->registers + MSP_GCR); 625 msp->registers + MSP_GCR);
645 626
646 spin_lock_irqsave(&msp_rxtx_lock, flags);
647 WARN_ON(!msp->pinctrl_rxtx_ref);
648 msp->pinctrl_rxtx_ref--;
649 if (msp->pinctrl_rxtx_ref == 0 &&
650 !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_sleep))) {
651 retval = pinctrl_select_state(msp->pinctrl_p,
652 msp->pinctrl_sleep);
653 if (retval)
654 pr_err("could not set MSP sleepstate\n");
655 }
656 spin_unlock_irqrestore(&msp_rxtx_lock, flags);
657
658 writel(0, msp->registers + MSP_GCR); 627 writel(0, msp->registers + MSP_GCR);
659 writel(0, msp->registers + MSP_TCF); 628 writel(0, msp->registers + MSP_TCF);
660 writel(0, msp->registers + MSP_RCF); 629 writel(0, msp->registers + MSP_RCF);
@@ -682,7 +651,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
682 struct msp_i2s_platform_data *platform_data) 651 struct msp_i2s_platform_data *platform_data)
683{ 652{
684 struct resource *res = NULL; 653 struct resource *res = NULL;
685 struct i2s_controller *i2s_cont;
686 struct device_node *np = pdev->dev.of_node; 654 struct device_node *np = pdev->dev.of_node;
687 struct ux500_msp *msp; 655 struct ux500_msp *msp;
688 656
@@ -707,8 +675,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
707 675
708 msp->id = platform_data->id; 676 msp->id = platform_data->id;
709 msp->dev = &pdev->dev; 677 msp->dev = &pdev->dev;
710 msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; 678 msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx;
711 msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; 679 msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx;
712 680
713 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 681 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
714 if (res == NULL) { 682 if (res == NULL) {
@@ -717,6 +685,9 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
717 return -ENOMEM; 685 return -ENOMEM;
718 } 686 }
719 687
688 msp->playback_dma_data.tx_rx_addr = res->start + MSP_DR;
689 msp->capture_dma_data.tx_rx_addr = res->start + MSP_DR;
690
720 msp->registers = devm_ioremap(&pdev->dev, res->start, 691 msp->registers = devm_ioremap(&pdev->dev, res->start,
721 resource_size(res)); 692 resource_size(res));
722 if (msp->registers == NULL) { 693 if (msp->registers == NULL) {
@@ -727,41 +698,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
727 msp->msp_state = MSP_STATE_IDLE; 698 msp->msp_state = MSP_STATE_IDLE;
728 msp->loopback_enable = 0; 699 msp->loopback_enable = 0;
729 700
730 /* I2S-controller is allocated and added in I2S controller class. */
731 i2s_cont = devm_kzalloc(&pdev->dev, sizeof(*i2s_cont), GFP_KERNEL);
732 if (!i2s_cont) {
733 dev_err(&pdev->dev,
734 "%s: ERROR: Failed to allocate I2S-controller!\n",
735 __func__);
736 return -ENOMEM;
737 }
738 i2s_cont->dev.parent = &pdev->dev;
739 i2s_cont->data = (void *)msp;
740 i2s_cont->id = (s16)msp->id;
741 snprintf(i2s_cont->name, sizeof(i2s_cont->name), "ux500-msp-i2s.%04x",
742 msp->id);
743 dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name);
744 msp->i2s_cont = i2s_cont;
745
746 msp->pinctrl_p = pinctrl_get(msp->dev);
747 if (IS_ERR(msp->pinctrl_p))
748 dev_err(&pdev->dev, "could not get MSP pinctrl\n");
749 else {
750 msp->pinctrl_def = pinctrl_lookup_state(msp->pinctrl_p,
751 PINCTRL_STATE_DEFAULT);
752 if (IS_ERR(msp->pinctrl_def)) {
753 dev_err(&pdev->dev,
754 "could not get MSP defstate (%li)\n",
755 PTR_ERR(msp->pinctrl_def));
756 }
757 msp->pinctrl_sleep = pinctrl_lookup_state(msp->pinctrl_p,
758 PINCTRL_STATE_SLEEP);
759 if (IS_ERR(msp->pinctrl_sleep))
760 dev_err(&pdev->dev,
761 "could not get MSP idlestate (%li)\n",
762 PTR_ERR(msp->pinctrl_def));
763 }
764
765 return 0; 701 return 0;
766} 702}
767 703
@@ -769,8 +705,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
769 struct ux500_msp *msp) 705 struct ux500_msp *msp)
770{ 706{
771 dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id); 707 dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);
772
773 device_unregister(&msp->i2s_cont->dev);
774} 708}
775 709
776MODULE_LICENSE("GPL v2"); 710MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h
index e5cd105c90f9..258d0bcee0bd 100644
--- a/sound/soc/ux500/ux500_msp_i2s.h
+++ b/sound/soc/ux500/ux500_msp_i2s.h
@@ -16,6 +16,7 @@
16#define UX500_MSP_I2S_H 16#define UX500_MSP_I2S_H
17 17
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/platform_data/asoc-ux500-msp.h>
19 20
20#define MSP_INPUT_FREQ_APB 48000000 21#define MSP_INPUT_FREQ_APB 48000000
21 22
@@ -341,11 +342,6 @@ enum msp_compress_mode {
341 MSP_COMPRESS_MODE_A_LAW = 3 342 MSP_COMPRESS_MODE_A_LAW = 3
342}; 343};
343 344
344enum msp_spi_burst_mode {
345 MSP_SPI_BURST_MODE_DISABLE = 0,
346 MSP_SPI_BURST_MODE_ENABLE = 1
347};
348
349enum msp_expand_mode { 345enum msp_expand_mode {
350 MSP_EXPAND_MODE_LINEAR = 0, 346 MSP_EXPAND_MODE_LINEAR = 0,
351 MSP_EXPAND_MODE_LINEAR_SIGNED = 1, 347 MSP_EXPAND_MODE_LINEAR_SIGNED = 1,
@@ -370,13 +366,6 @@ enum msp_protocol {
370 */ 366 */
371#define MAX_MSP_BACKUP_REGS 36 367#define MAX_MSP_BACKUP_REGS 36
372 368
373enum enum_i2s_controller {
374 MSP_0_I2S_CONTROLLER = 0,
375 MSP_1_I2S_CONTROLLER,
376 MSP_2_I2S_CONTROLLER,
377 MSP_3_I2S_CONTROLLER,
378};
379
380enum i2s_direction_t { 369enum i2s_direction_t {
381 MSP_DIR_TX = 0x01, 370 MSP_DIR_TX = 0x01,
382 MSP_DIR_RX = 0x02, 371 MSP_DIR_RX = 0x02,
@@ -454,32 +443,6 @@ struct msp_protdesc {
454 u32 clocks_per_frame; 443 u32 clocks_per_frame;
455}; 444};
456 445
457struct i2s_message {
458 enum i2s_direction_t i2s_direction;
459 void *txdata;
460 void *rxdata;
461 size_t txbytes;
462 size_t rxbytes;
463 int dma_flag;
464 int tx_offset;
465 int rx_offset;
466 bool cyclic_dma;
467 dma_addr_t buf_addr;
468 size_t buf_len;
469 size_t period_len;
470};
471
472struct i2s_controller {
473 struct module *owner;
474 unsigned int id;
475 unsigned int class;
476 const struct i2s_algorithm *algo; /* the algorithm to access the bus */
477 void *data;
478 struct mutex bus_lock;
479 struct device dev; /* the controller device */
480 char name[48];
481};
482
483struct ux500_msp_config { 446struct ux500_msp_config {
484 unsigned int f_inputclk; 447 unsigned int f_inputclk;
485 unsigned int rx_clk_sel; 448 unsigned int rx_clk_sel;
@@ -491,8 +454,6 @@ struct ux500_msp_config {
491 unsigned int tx_fsync_sel; 454 unsigned int tx_fsync_sel;
492 unsigned int rx_fifo_config; 455 unsigned int rx_fifo_config;
493 unsigned int tx_fifo_config; 456 unsigned int tx_fifo_config;
494 unsigned int spi_clk_mode;
495 unsigned int spi_burst_mode;
496 unsigned int loopback_enable; 457 unsigned int loopback_enable;
497 unsigned int tx_data_enable; 458 unsigned int tx_data_enable;
498 unsigned int default_protdesc; 459 unsigned int default_protdesc;
@@ -502,43 +463,28 @@ struct ux500_msp_config {
502 unsigned int direction; 463 unsigned int direction;
503 unsigned int protocol; 464 unsigned int protocol;
504 unsigned int frame_freq; 465 unsigned int frame_freq;
505 unsigned int frame_size;
506 enum msp_data_size data_size; 466 enum msp_data_size data_size;
507 unsigned int def_elem_len; 467 unsigned int def_elem_len;
508 unsigned int iodelay; 468 unsigned int iodelay;
509 void (*handler) (void *data); 469};
510 void *tx_callback_data; 470
511 void *rx_callback_data; 471struct ux500_msp_dma_params {
472 unsigned int data_size;
473 dma_addr_t tx_rx_addr;
474 struct stedma40_chan_cfg *dma_cfg;
512}; 475};
513 476
514struct ux500_msp { 477struct ux500_msp {
515 enum enum_i2s_controller id; 478 enum msp_i2s_id id;
516 void __iomem *registers; 479 void __iomem *registers;
517 struct device *dev; 480 struct device *dev;
518 struct i2s_controller *i2s_cont; 481 struct ux500_msp_dma_params playback_dma_data;
519 struct stedma40_chan_cfg *dma_cfg_rx; 482 struct ux500_msp_dma_params capture_dma_data;
520 struct stedma40_chan_cfg *dma_cfg_tx;
521 struct dma_chan *tx_pipeid;
522 struct dma_chan *rx_pipeid;
523 enum msp_state msp_state; 483 enum msp_state msp_state;
524 int (*transfer) (struct ux500_msp *msp, struct i2s_message *message);
525 struct timer_list notify_timer;
526 int def_elem_len; 484 int def_elem_len;
527 unsigned int dir_busy; 485 unsigned int dir_busy;
528 int loopback_enable; 486 int loopback_enable;
529 u32 backup_regs[MAX_MSP_BACKUP_REGS];
530 unsigned int f_bitclk; 487 unsigned int f_bitclk;
531 /* Pin modes */
532 struct pinctrl *pinctrl_p;
533 struct pinctrl_state *pinctrl_def;
534 struct pinctrl_state *pinctrl_sleep;
535 /* Reference Count */
536 int pinctrl_rxtx_ref;
537};
538
539struct ux500_msp_dma_params {
540 unsigned int data_size;
541 struct stedma40_chan_cfg *dma_cfg;
542}; 488};
543 489
544struct msp_i2s_platform_data; 490struct msp_i2s_platform_data;
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index b6e5ae277299..5f01c19776bf 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -103,10 +103,40 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
103 return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg); 103 return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg);
104} 104}
105 105
106static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
107 struct snd_pcm_hw_params *params,
108 struct dma_slave_config *slave_config)
109{
110 struct snd_soc_pcm_runtime *rtd = substream->private_data;
111 struct ux500_msp_dma_params *dma_params;
112 struct stedma40_chan_cfg *dma_cfg;
113 int ret;
114
115 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
116 dma_cfg = dma_params->dma_cfg;
117
118 ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
119 if (ret)
120 return ret;
121
122 slave_config->dst_maxburst = 4;
123 slave_config->dst_addr_width = dma_cfg->dst_info.data_width;
124 slave_config->src_maxburst = 4;
125 slave_config->src_addr_width = dma_cfg->src_info.data_width;
126
127 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
128 slave_config->dst_addr = dma_params->tx_rx_addr;
129 else
130 slave_config->src_addr = dma_params->tx_rx_addr;
131
132 return 0;
133}
134
106static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { 135static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = {
107 .pcm_hardware = &ux500_pcm_hw, 136 .pcm_hardware = &ux500_pcm_hw,
108 .compat_request_channel = ux500_pcm_request_chan, 137 .compat_request_channel = ux500_pcm_request_chan,
109 .prealloc_buffer_size = 128 * 1024, 138 .prealloc_buffer_size = 128 * 1024,
139 .prepare_slave_config = ux500_pcm_prepare_slave_config,
110}; 140};
111 141
112int ux500_pcm_register_platform(struct platform_device *pdev) 142int ux500_pcm_register_platform(struct platform_device *pdev)