diff options
author | Mark Brown <broonie@linaro.org> | 2013-06-17 12:20:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-06-17 12:20:30 -0400 |
commit | 458bcee95d9ff742dcb379f6605a4023848ed8cb (patch) | |
tree | 1ac46e360f79c77b4dda692ad1110076d909e3bd | |
parent | 93d4c1e04f9a316decc2d0fca3ce3a8e9722a155 (diff) | |
parent | eef6473ff3ce2383febebd2e799beceaece9adda (diff) |
Merge remote-tracking branch 'asoc/topic/ux500' into asoc-next
-rw-r--r-- | sound/soc/codecs/ab8500-codec.c | 79 | ||||
-rw-r--r-- | sound/soc/codecs/ab8500-codec.h | 42 | ||||
-rw-r--r-- | sound/soc/ux500/mop500_ab8500.c | 36 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_msp_dai.c | 11 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_msp_dai.h | 4 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_msp_i2s.c | 88 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_msp_i2s.h | 74 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_pcm.c | 30 |
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 | ||
2383 | static 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 | |||
2365 | static struct snd_soc_dai_driver ab8500_codec_dai[] = { | 2388 | static 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 @@ | |||
43 | static unsigned int tx_slots = DEF_TX_SLOTS; | 45 | static unsigned int tx_slots = DEF_TX_SLOTS; |
44 | static unsigned int rx_slots = DEF_RX_SLOTS; | 46 | static unsigned int rx_slots = DEF_RX_SLOTS; |
45 | 47 | ||
48 | /* Configuration consistency parameters */ | ||
49 | static DEFINE_MUTEX(mop500_ab8500_params_lock); | ||
50 | static unsigned long mop500_ab8500_usage; | ||
51 | static int mop500_ab8500_rate; | ||
52 | static int mop500_ab8500_channels; | ||
53 | |||
46 | /* Clocks */ | 54 | /* Clocks */ |
47 | static const char * const enum_mclk[] = { | 55 | static 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 | ||
354 | static 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 | |||
331 | struct snd_soc_ops mop500_ab8500_ops[] = { | 366 | struct 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 { | |||
51 | struct ux500_msp_i2s_drvdata { | 51 | struct 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 */ | ||
30 | static DEFINE_SPINLOCK(msp_rxtx_lock); | ||
31 | |||
32 | /* Protocol desciptors */ | 28 | /* Protocol desciptors */ |
33 | static const struct msp_protdesc prot_descs[] = { | 29 | static const struct msp_protdesc prot_descs[] = { |
34 | { /* I2S */ | 30 | { /* I2S */ |
@@ -356,24 +352,8 @@ static int configure_multichannel(struct ux500_msp *msp, | |||
356 | 352 | ||
357 | static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) | 353 | static 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 | ||
631 | int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) | 613 | int 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 | ||
776 | MODULE_LICENSE("GPL v2"); | 710 | MODULE_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 | ||
344 | enum msp_spi_burst_mode { | ||
345 | MSP_SPI_BURST_MODE_DISABLE = 0, | ||
346 | MSP_SPI_BURST_MODE_ENABLE = 1 | ||
347 | }; | ||
348 | |||
349 | enum msp_expand_mode { | 345 | enum 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 | ||
373 | enum 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 | |||
380 | enum i2s_direction_t { | 369 | enum 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 | ||
457 | struct 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 | |||
472 | struct 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 | |||
483 | struct ux500_msp_config { | 446 | struct 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; | 471 | struct 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 | ||
514 | struct ux500_msp { | 477 | struct 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 | |||
539 | struct ux500_msp_dma_params { | ||
540 | unsigned int data_size; | ||
541 | struct stedma40_chan_cfg *dma_cfg; | ||
542 | }; | 488 | }; |
543 | 489 | ||
544 | struct msp_i2s_platform_data; | 490 | struct 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 | ||
106 | static 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 | |||
106 | static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { | 135 | static 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 | ||
112 | int ux500_pcm_register_platform(struct platform_device *pdev) | 142 | int ux500_pcm_register_platform(struct platform_device *pdev) |