diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/renesas,rsnd.txt | 10 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/rt5631.txt | 48 | ||||
-rw-r--r-- | include/sound/rcar_snd.h | 8 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 3 | ||||
-rw-r--r-- | sound/soc/codecs/rt286.c | 231 | ||||
-rw-r--r-- | sound/soc/codecs/rt5631.c | 38 | ||||
-rw-r--r-- | sound/soc/rockchip/Kconfig | 9 | ||||
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/core.c | 236 | ||||
-rw-r--r-- | sound/soc/sh/rcar/dvc.c | 215 | ||||
-rw-r--r-- | sound/soc/sh/rcar/gen.c | 30 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 92 | ||||
-rw-r--r-- | sound/soc/sh/rcar/src.c | 101 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 233 |
14 files changed, 915 insertions, 341 deletions
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index aa697abf337e..2dd690bc19cc 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt | |||
@@ -1,8 +1,12 @@ | |||
1 | Renesas R-Car sound | 1 | Renesas R-Car sound |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible : "renesas,rcar_sound-gen1" if generation1 | 4 | - compatible : "renesas,rcar_sound-<soctype>", fallbacks |
5 | "renesas,rcar_sound-gen1" if generation1, and | ||
5 | "renesas,rcar_sound-gen2" if generation2 | 6 | "renesas,rcar_sound-gen2" if generation2 |
7 | Examples with soctypes are: | ||
8 | - "renesas,rcar_sound-r8a7790" (R-Car H2) | ||
9 | - "renesas,rcar_sound-r8a7791" (R-Car M2-W) | ||
6 | - reg : Should contain the register physical address. | 10 | - reg : Should contain the register physical address. |
7 | required register is | 11 | required register is |
8 | SRU/ADG/SSI if generation1 | 12 | SRU/ADG/SSI if generation1 |
@@ -35,9 +39,9 @@ DAI subnode properties: | |||
35 | 39 | ||
36 | Example: | 40 | Example: |
37 | 41 | ||
38 | rcar_sound: rcar_sound@0xffd90000 { | 42 | rcar_sound: rcar_sound@ec500000 { |
39 | #sound-dai-cells = <1>; | 43 | #sound-dai-cells = <1>; |
40 | compatible = "renesas,rcar_sound-gen2"; | 44 | compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2"; |
41 | reg = <0 0xec500000 0 0x1000>, /* SCU */ | 45 | reg = <0 0xec500000 0 0x1000>, /* SCU */ |
42 | <0 0xec5a0000 0 0x100>, /* ADG */ | 46 | <0 0xec5a0000 0 0x100>, /* ADG */ |
43 | <0 0xec540000 0 0x1000>, /* SSIU */ | 47 | <0 0xec540000 0 0x1000>, /* SSIU */ |
diff --git a/Documentation/devicetree/bindings/sound/rt5631.txt b/Documentation/devicetree/bindings/sound/rt5631.txt new file mode 100644 index 000000000000..92b986ca337b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5631.txt | |||
@@ -0,0 +1,48 @@ | |||
1 | ALC5631/RT5631 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "realtek,alc5631" or "realtek,rt5631" | ||
8 | |||
9 | - reg : the I2C address of the device. | ||
10 | |||
11 | Pins on the device (for linking into audio routes): | ||
12 | |||
13 | * SPK_OUT_R_P | ||
14 | * SPK_OUT_R_N | ||
15 | * SPK_OUT_L_P | ||
16 | * SPK_OUT_L_N | ||
17 | * HP_OUT_L | ||
18 | * HP_OUT_R | ||
19 | * AUX_OUT2_LP | ||
20 | * AUX_OUT2_RN | ||
21 | * AUX_OUT1_LP | ||
22 | * AUX_OUT1_RN | ||
23 | * AUX_IN_L_JD | ||
24 | * AUX_IN_R_JD | ||
25 | * MONO_IN_P | ||
26 | * MONO_IN_N | ||
27 | * MIC1_P | ||
28 | * MIC1_N | ||
29 | * MIC2_P | ||
30 | * MIC2_N | ||
31 | * MONO_OUT_P | ||
32 | * MONO_OUT_N | ||
33 | * MICBIAS1 | ||
34 | * MICBIAS2 | ||
35 | |||
36 | Example: | ||
37 | |||
38 | alc5631: alc5631@1a { | ||
39 | compatible = "realtek,alc5631"; | ||
40 | reg = <0x1a>; | ||
41 | }; | ||
42 | |||
43 | or | ||
44 | |||
45 | rt5631: rt5631@1a { | ||
46 | compatible = "realtek,rt5631"; | ||
47 | reg = <0x1a>; | ||
48 | }; | ||
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index d76412b84b48..83284cae464c 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h | |||
@@ -36,14 +36,14 @@ | |||
36 | #define RSND_SSI_CLK_PIN_SHARE (1 << 31) | 36 | #define RSND_SSI_CLK_PIN_SHARE (1 << 31) |
37 | #define RSND_SSI_NO_BUSIF (1 << 30) /* SSI+DMA without BUSIF */ | 37 | #define RSND_SSI_NO_BUSIF (1 << 30) /* SSI+DMA without BUSIF */ |
38 | 38 | ||
39 | #define RSND_SSI(_dma_id, _pio_irq, _flags) \ | 39 | #define RSND_SSI(_dma_id, _irq, _flags) \ |
40 | { .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } | 40 | { .dma_id = _dma_id, .irq = _irq, .flags = _flags } |
41 | #define RSND_SSI_UNUSED \ | 41 | #define RSND_SSI_UNUSED \ |
42 | { .dma_id = -1, .pio_irq = -1, .flags = 0 } | 42 | { .dma_id = -1, .irq = -1, .flags = 0 } |
43 | 43 | ||
44 | struct rsnd_ssi_platform_info { | 44 | struct rsnd_ssi_platform_info { |
45 | int dma_id; | 45 | int dma_id; |
46 | int pio_irq; | 46 | int irq; |
47 | u32 flags; | 47 | u32 flags; |
48 | }; | 48 | }; |
49 | 49 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1362edd380e5..3fbf59484a42 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -501,7 +501,8 @@ config SND_SOC_RT286 | |||
501 | depends on I2C | 501 | depends on I2C |
502 | 502 | ||
503 | config SND_SOC_RT5631 | 503 | config SND_SOC_RT5631 |
504 | tristate | 504 | tristate "Realtek ALC5631/RT5631 CODEC" |
505 | depends on I2C | ||
505 | 506 | ||
506 | config SND_SOC_RT5640 | 507 | config SND_SOC_RT5640 |
507 | tristate | 508 | tristate |
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 4aa555cbcca8..2cd4fe463102 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | #include <linux/dmi.h> | ||
20 | #include <linux/acpi.h> | 21 | #include <linux/acpi.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -36,11 +37,13 @@ | |||
36 | 37 | ||
37 | struct rt286_priv { | 38 | struct rt286_priv { |
38 | struct regmap *regmap; | 39 | struct regmap *regmap; |
40 | struct snd_soc_codec *codec; | ||
39 | struct rt286_platform_data pdata; | 41 | struct rt286_platform_data pdata; |
40 | struct i2c_client *i2c; | 42 | struct i2c_client *i2c; |
41 | struct snd_soc_jack *jack; | 43 | struct snd_soc_jack *jack; |
42 | struct delayed_work jack_detect_work; | 44 | struct delayed_work jack_detect_work; |
43 | int sys_clk; | 45 | int sys_clk; |
46 | int clk_id; | ||
44 | struct reg_default *index_cache; | 47 | struct reg_default *index_cache; |
45 | }; | 48 | }; |
46 | 49 | ||
@@ -188,7 +191,7 @@ static int rt286_hw_write(void *context, unsigned int reg, unsigned int value) | |||
188 | u8 data[4]; | 191 | u8 data[4]; |
189 | int ret, i; | 192 | int ret, i; |
190 | 193 | ||
191 | /*handle index registers*/ | 194 | /* handle index registers */ |
192 | if (reg <= 0xff) { | 195 | if (reg <= 0xff) { |
193 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | 196 | rt286_hw_write(client, RT286_COEF_INDEX, reg); |
194 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { | 197 | for (i = 0; i < INDEX_CACHE_SIZE; i++) { |
@@ -231,7 +234,7 @@ static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value) | |||
231 | __be32 be_reg; | 234 | __be32 be_reg; |
232 | unsigned int index, vid, buf = 0x0; | 235 | unsigned int index, vid, buf = 0x0; |
233 | 236 | ||
234 | /*handle index registers*/ | 237 | /* handle index registers */ |
235 | if (reg <= 0xff) { | 238 | if (reg <= 0xff) { |
236 | rt286_hw_write(client, RT286_COEF_INDEX, reg); | 239 | rt286_hw_write(client, RT286_COEF_INDEX, reg); |
237 | reg = RT286_PROC_COEF; | 240 | reg = RT286_PROC_COEF; |
@@ -298,7 +301,6 @@ static int rt286_support_power_controls[] = { | |||
298 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | 301 | static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) |
299 | { | 302 | { |
300 | unsigned int val, buf; | 303 | unsigned int val, buf; |
301 | int i; | ||
302 | 304 | ||
303 | *hp = false; | 305 | *hp = false; |
304 | *mic = false; | 306 | *mic = false; |
@@ -309,67 +311,44 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
309 | if (*hp) { | 311 | if (*hp) { |
310 | /* power on HV,VERF */ | 312 | /* power on HV,VERF */ |
311 | regmap_update_bits(rt286->regmap, | 313 | regmap_update_bits(rt286->regmap, |
312 | RT286_POWER_CTRL1, 0x1001, 0x0); | 314 | RT286_DC_GAIN, 0x200, 0x200); |
315 | |||
316 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | ||
317 | "HV"); | ||
318 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, | ||
319 | "VREF"); | ||
313 | /* power LDO1 */ | 320 | /* power LDO1 */ |
314 | regmap_update_bits(rt286->regmap, | 321 | snd_soc_dapm_force_enable_pin(&rt286->codec->dapm, |
315 | RT286_POWER_CTRL2, 0x4, 0x4); | 322 | "LDO1"); |
316 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); | 323 | snd_soc_dapm_sync(&rt286->codec->dapm); |
317 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
318 | 324 | ||
319 | msleep(200); | 325 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24); |
320 | i = 40; | 326 | msleep(50); |
321 | while (((val & 0x0800) == 0) && (i > 0)) { | ||
322 | regmap_read(rt286->regmap, | ||
323 | RT286_CBJ_CTRL2, &val); | ||
324 | i--; | ||
325 | msleep(20); | ||
326 | } | ||
327 | 327 | ||
328 | if (0x0400 == (val & 0x0700)) { | 328 | regmap_update_bits(rt286->regmap, |
329 | *mic = false; | 329 | RT286_CBJ_CTRL1, 0xfcc0, 0xd400); |
330 | msleep(300); | ||
331 | regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); | ||
330 | 332 | ||
331 | regmap_write(rt286->regmap, | 333 | if (0x0070 == (val & 0x0070)) { |
332 | RT286_SET_MIC1, 0x20); | ||
333 | /* power off HV,VERF */ | ||
334 | regmap_update_bits(rt286->regmap, | ||
335 | RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
336 | regmap_update_bits(rt286->regmap, | ||
337 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
338 | regmap_update_bits(rt286->regmap, | ||
339 | RT286_CBJ_CTRL1, 0x0030, 0x0000); | ||
340 | regmap_update_bits(rt286->regmap, | ||
341 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
342 | } else if ((0x0200 == (val & 0x0700)) || | ||
343 | (0x0100 == (val & 0x0700))) { | ||
344 | *mic = true; | 334 | *mic = true; |
345 | regmap_update_bits(rt286->regmap, | ||
346 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
347 | regmap_update_bits(rt286->regmap, | ||
348 | RT286_CBJ_CTRL1, 0x0030, 0x0020); | ||
349 | regmap_update_bits(rt286->regmap, | ||
350 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
351 | } else { | 335 | } else { |
352 | *mic = false; | 336 | regmap_update_bits(rt286->regmap, |
337 | RT286_CBJ_CTRL1, 0xfcc0, 0xe400); | ||
338 | msleep(300); | ||
339 | regmap_read(rt286->regmap, | ||
340 | RT286_CBJ_CTRL2, &val); | ||
341 | if (0x0070 == (val & 0x0070)) | ||
342 | *mic = true; | ||
343 | else | ||
344 | *mic = false; | ||
353 | } | 345 | } |
354 | |||
355 | regmap_update_bits(rt286->regmap, | ||
356 | RT286_MISC_CTRL1, | ||
357 | 0x0060, 0x0000); | ||
358 | } else { | ||
359 | regmap_update_bits(rt286->regmap, | ||
360 | RT286_MISC_CTRL1, | ||
361 | 0x0060, 0x0020); | ||
362 | regmap_update_bits(rt286->regmap, | 346 | regmap_update_bits(rt286->regmap, |
363 | RT286_A_BIAS_CTRL3, | 347 | RT286_DC_GAIN, 0x200, 0x0); |
364 | 0xc000, 0x8000); | ||
365 | regmap_update_bits(rt286->regmap, | ||
366 | RT286_CBJ_CTRL1, | ||
367 | 0x0030, 0x0020); | ||
368 | regmap_update_bits(rt286->regmap, | ||
369 | RT286_A_BIAS_CTRL2, | ||
370 | 0xc000, 0x8000); | ||
371 | 348 | ||
349 | } else { | ||
372 | *mic = false; | 350 | *mic = false; |
351 | regmap_write(rt286->regmap, RT286_SET_MIC1, 0x20); | ||
373 | } | 352 | } |
374 | } else { | 353 | } else { |
375 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | 354 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); |
@@ -378,6 +357,12 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
378 | *mic = buf & 0x80000000; | 357 | *mic = buf & 0x80000000; |
379 | } | 358 | } |
380 | 359 | ||
360 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "HV"); | ||
361 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "VREF"); | ||
362 | if (!*hp) | ||
363 | snd_soc_dapm_disable_pin(&rt286->codec->dapm, "LDO1"); | ||
364 | snd_soc_dapm_sync(&rt286->codec->dapm); | ||
365 | |||
381 | return 0; | 366 | return 0; |
382 | } | 367 | } |
383 | 368 | ||
@@ -415,6 +400,17 @@ int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
415 | } | 400 | } |
416 | EXPORT_SYMBOL_GPL(rt286_mic_detect); | 401 | EXPORT_SYMBOL_GPL(rt286_mic_detect); |
417 | 402 | ||
403 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, | ||
404 | struct snd_soc_dapm_widget *sink) | ||
405 | { | ||
406 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(source->codec); | ||
407 | |||
408 | if (rt286->clk_id == RT286_SCLK_S_MCLK) | ||
409 | return 1; | ||
410 | else | ||
411 | return 0; | ||
412 | } | ||
413 | |||
418 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); | 414 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6350, 50, 0); |
419 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | 415 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); |
420 | 416 | ||
@@ -568,7 +564,84 @@ static int rt286_adc_event(struct snd_soc_dapm_widget *w, | |||
568 | return 0; | 564 | return 0; |
569 | } | 565 | } |
570 | 566 | ||
567 | static int rt286_vref_event(struct snd_soc_dapm_widget *w, | ||
568 | struct snd_kcontrol *kcontrol, int event) | ||
569 | { | ||
570 | struct snd_soc_codec *codec = w->codec; | ||
571 | |||
572 | switch (event) { | ||
573 | case SND_SOC_DAPM_PRE_PMU: | ||
574 | snd_soc_update_bits(codec, | ||
575 | RT286_CBJ_CTRL1, 0x0400, 0x0000); | ||
576 | mdelay(50); | ||
577 | break; | ||
578 | default: | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, | ||
586 | struct snd_kcontrol *kcontrol, int event) | ||
587 | { | ||
588 | struct snd_soc_codec *codec = w->codec; | ||
589 | |||
590 | switch (event) { | ||
591 | case SND_SOC_DAPM_POST_PMU: | ||
592 | snd_soc_update_bits(codec, RT286_POWER_CTRL2, 0x38, 0x08); | ||
593 | break; | ||
594 | case SND_SOC_DAPM_PRE_PMD: | ||
595 | snd_soc_update_bits(codec, RT286_POWER_CTRL2, 0x38, 0x30); | ||
596 | break; | ||
597 | default: | ||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static int rt286_mic1_event(struct snd_soc_dapm_widget *w, | ||
605 | struct snd_kcontrol *kcontrol, int event) | ||
606 | { | ||
607 | struct snd_soc_codec *codec = w->codec; | ||
608 | |||
609 | switch (event) { | ||
610 | case SND_SOC_DAPM_PRE_PMU: | ||
611 | snd_soc_update_bits(codec, | ||
612 | RT286_A_BIAS_CTRL3, 0xc000, 0x8000); | ||
613 | snd_soc_update_bits(codec, | ||
614 | RT286_A_BIAS_CTRL2, 0xc000, 0x8000); | ||
615 | break; | ||
616 | case SND_SOC_DAPM_POST_PMD: | ||
617 | snd_soc_update_bits(codec, | ||
618 | RT286_A_BIAS_CTRL3, 0xc000, 0x0000); | ||
619 | snd_soc_update_bits(codec, | ||
620 | RT286_A_BIAS_CTRL2, 0xc000, 0x0000); | ||
621 | break; | ||
622 | default: | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
571 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | 629 | static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { |
630 | SND_SOC_DAPM_SUPPLY_S("HV", 1, RT286_POWER_CTRL1, | ||
631 | 12, 1, NULL, 0), | ||
632 | SND_SOC_DAPM_SUPPLY("VREF", RT286_POWER_CTRL1, | ||
633 | 0, 1, rt286_vref_event, SND_SOC_DAPM_PRE_PMU), | ||
634 | SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT286_POWER_CTRL2, | ||
635 | 2, 0, NULL, 0), | ||
636 | SND_SOC_DAPM_SUPPLY_S("LDO2", 2, RT286_POWER_CTRL1, | ||
637 | 13, 1, rt286_ldo2_event, SND_SOC_DAPM_PRE_PMD | | ||
638 | SND_SOC_DAPM_POST_PMU), | ||
639 | SND_SOC_DAPM_SUPPLY("MCLK MODE", RT286_PLL_CTRL1, | ||
640 | 5, 0, NULL, 0), | ||
641 | SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM, | ||
642 | 0, 0, rt286_mic1_event, SND_SOC_DAPM_PRE_PMU | | ||
643 | SND_SOC_DAPM_POST_PMD), | ||
644 | |||
572 | /* Input Lines */ | 645 | /* Input Lines */ |
573 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), | 646 | SND_SOC_DAPM_INPUT("DMIC1 Pin"), |
574 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), | 647 | SND_SOC_DAPM_INPUT("DMIC2 Pin"), |
@@ -642,6 +715,25 @@ static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | |||
642 | }; | 715 | }; |
643 | 716 | ||
644 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { | 717 | static const struct snd_soc_dapm_route rt286_dapm_routes[] = { |
718 | {"ADC 0", NULL, "MCLK MODE", is_mclk_mode}, | ||
719 | {"ADC 1", NULL, "MCLK MODE", is_mclk_mode}, | ||
720 | {"Front", NULL, "MCLK MODE", is_mclk_mode}, | ||
721 | {"Surround", NULL, "MCLK MODE", is_mclk_mode}, | ||
722 | |||
723 | {"HP Power", NULL, "LDO1"}, | ||
724 | {"HP Power", NULL, "LDO2"}, | ||
725 | |||
726 | {"MIC1", NULL, "LDO1"}, | ||
727 | {"MIC1", NULL, "LDO2"}, | ||
728 | {"MIC1", NULL, "HV"}, | ||
729 | {"MIC1", NULL, "VREF"}, | ||
730 | {"MIC1", NULL, "MIC1 Input Buffer"}, | ||
731 | |||
732 | {"SPO", NULL, "LDO1"}, | ||
733 | {"SPO", NULL, "LDO2"}, | ||
734 | {"SPO", NULL, "HV"}, | ||
735 | {"SPO", NULL, "VREF"}, | ||
736 | |||
645 | {"DMIC1", NULL, "DMIC1 Pin"}, | 737 | {"DMIC1", NULL, "DMIC1 Pin"}, |
646 | {"DMIC2", NULL, "DMIC2 Pin"}, | 738 | {"DMIC2", NULL, "DMIC2 Pin"}, |
647 | {"DMIC1", NULL, "DMIC Receiver"}, | 739 | {"DMIC1", NULL, "DMIC Receiver"}, |
@@ -880,6 +972,7 @@ static int rt286_set_dai_sysclk(struct snd_soc_dai *dai, | |||
880 | } | 972 | } |
881 | 973 | ||
882 | rt286->sys_clk = freq; | 974 | rt286->sys_clk = freq; |
975 | rt286->clk_id = clk_id; | ||
883 | 976 | ||
884 | return 0; | 977 | return 0; |
885 | } | 978 | } |
@@ -915,13 +1008,18 @@ static int rt286_set_bias_level(struct snd_soc_codec *codec, | |||
915 | 1008 | ||
916 | case SND_SOC_BIAS_ON: | 1009 | case SND_SOC_BIAS_ON: |
917 | mdelay(10); | 1010 | mdelay(10); |
1011 | snd_soc_update_bits(codec, | ||
1012 | RT286_CBJ_CTRL1, 0x0400, 0x0400); | ||
1013 | snd_soc_update_bits(codec, | ||
1014 | RT286_DC_GAIN, 0x200, 0x0); | ||
1015 | |||
918 | break; | 1016 | break; |
919 | 1017 | ||
920 | case SND_SOC_BIAS_STANDBY: | 1018 | case SND_SOC_BIAS_STANDBY: |
921 | snd_soc_write(codec, | 1019 | snd_soc_write(codec, |
922 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); | 1020 | RT286_SET_AUDIO_POWER, AC_PWRST_D3); |
923 | snd_soc_update_bits(codec, | 1021 | snd_soc_update_bits(codec, |
924 | RT286_DC_GAIN, 0x200, 0x0); | 1022 | RT286_CBJ_CTRL1, 0x0400, 0x0000); |
925 | break; | 1023 | break; |
926 | 1024 | ||
927 | default: | 1025 | default: |
@@ -962,6 +1060,7 @@ static int rt286_probe(struct snd_soc_codec *codec) | |||
962 | { | 1060 | { |
963 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | 1061 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); |
964 | 1062 | ||
1063 | rt286->codec = codec; | ||
965 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 1064 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
966 | 1065 | ||
967 | if (rt286->i2c->irq) { | 1066 | if (rt286->i2c->irq) { |
@@ -1107,6 +1206,16 @@ static const struct acpi_device_id rt286_acpi_match[] = { | |||
1107 | }; | 1206 | }; |
1108 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); | 1207 | MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); |
1109 | 1208 | ||
1209 | static struct dmi_system_id force_combo_jack_table[] = { | ||
1210 | { | ||
1211 | .ident = "Intel Wilson Beach", | ||
1212 | .matches = { | ||
1213 | DMI_MATCH(DMI_BOARD_NAME, "Wilson Beach SDS") | ||
1214 | } | ||
1215 | }, | ||
1216 | { } | ||
1217 | }; | ||
1218 | |||
1110 | static int rt286_i2c_probe(struct i2c_client *i2c, | 1219 | static int rt286_i2c_probe(struct i2c_client *i2c, |
1111 | const struct i2c_device_id *id) | 1220 | const struct i2c_device_id *id) |
1112 | { | 1221 | { |
@@ -1142,6 +1251,9 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1142 | if (pdata) | 1251 | if (pdata) |
1143 | rt286->pdata = *pdata; | 1252 | rt286->pdata = *pdata; |
1144 | 1253 | ||
1254 | if (dmi_check_system(force_combo_jack_table)) | ||
1255 | rt286->pdata.cbj_en = true; | ||
1256 | |||
1145 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); | 1257 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); |
1146 | 1258 | ||
1147 | for (i = 0; i < RT286_POWER_REG_LEN; i++) | 1259 | for (i = 0; i < RT286_POWER_REG_LEN; i++) |
@@ -1152,7 +1264,6 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1152 | if (!rt286->pdata.cbj_en) { | 1264 | if (!rt286->pdata.cbj_en) { |
1153 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); | 1265 | regmap_write(rt286->regmap, RT286_CBJ_CTRL2, 0x0000); |
1154 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); | 1266 | regmap_write(rt286->regmap, RT286_MIC1_DET_CTRL, 0x0816); |
1155 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); | ||
1156 | regmap_update_bits(rt286->regmap, | 1267 | regmap_update_bits(rt286->regmap, |
1157 | RT286_CBJ_CTRL1, 0xf000, 0xb000); | 1268 | RT286_CBJ_CTRL1, 0xf000, 0xb000); |
1158 | } else { | 1269 | } else { |
@@ -1169,10 +1280,12 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1169 | 1280 | ||
1170 | mdelay(10); | 1281 | mdelay(10); |
1171 | 1282 | ||
1172 | /*Power down LDO2*/ | 1283 | regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000); |
1173 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0x8, 0x0); | 1284 | /* Power down LDO, VREF */ |
1285 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0xc, 0x0); | ||
1286 | regmap_update_bits(rt286->regmap, RT286_POWER_CTRL1, 0x1001, 0x1001); | ||
1174 | 1287 | ||
1175 | /*Set depop parameter*/ | 1288 | /* Set depop parameter */ |
1176 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); | 1289 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL2, 0x403a, 0x401a); |
1177 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); | 1290 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); |
1178 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); | 1291 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); |
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 1ba27db660a6..6d7b7ca7d530 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -1612,29 +1612,6 @@ static int rt5631_probe(struct snd_soc_codec *codec) | |||
1612 | return 0; | 1612 | return 0; |
1613 | } | 1613 | } |
1614 | 1614 | ||
1615 | static int rt5631_remove(struct snd_soc_codec *codec) | ||
1616 | { | ||
1617 | rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1618 | return 0; | ||
1619 | } | ||
1620 | |||
1621 | #ifdef CONFIG_PM | ||
1622 | static int rt5631_suspend(struct snd_soc_codec *codec) | ||
1623 | { | ||
1624 | rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1625 | return 0; | ||
1626 | } | ||
1627 | |||
1628 | static int rt5631_resume(struct snd_soc_codec *codec) | ||
1629 | { | ||
1630 | rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1631 | return 0; | ||
1632 | } | ||
1633 | #else | ||
1634 | #define rt5631_suspend NULL | ||
1635 | #define rt5631_resume NULL | ||
1636 | #endif | ||
1637 | |||
1638 | #define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000 | 1615 | #define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000 |
1639 | #define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ | 1616 | #define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ |
1640 | SNDRV_PCM_FMTBIT_S20_3LE | \ | 1617 | SNDRV_PCM_FMTBIT_S20_3LE | \ |
@@ -1672,10 +1649,8 @@ static struct snd_soc_dai_driver rt5631_dai[] = { | |||
1672 | 1649 | ||
1673 | static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { | 1650 | static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { |
1674 | .probe = rt5631_probe, | 1651 | .probe = rt5631_probe, |
1675 | .remove = rt5631_remove, | ||
1676 | .suspend = rt5631_suspend, | ||
1677 | .resume = rt5631_resume, | ||
1678 | .set_bias_level = rt5631_set_bias_level, | 1652 | .set_bias_level = rt5631_set_bias_level, |
1653 | .suspend_bias_off = true, | ||
1679 | .controls = rt5631_snd_controls, | 1654 | .controls = rt5631_snd_controls, |
1680 | .num_controls = ARRAY_SIZE(rt5631_snd_controls), | 1655 | .num_controls = ARRAY_SIZE(rt5631_snd_controls), |
1681 | .dapm_widgets = rt5631_dapm_widgets, | 1656 | .dapm_widgets = rt5631_dapm_widgets, |
@@ -1686,10 +1661,20 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { | |||
1686 | 1661 | ||
1687 | static const struct i2c_device_id rt5631_i2c_id[] = { | 1662 | static const struct i2c_device_id rt5631_i2c_id[] = { |
1688 | { "rt5631", 0 }, | 1663 | { "rt5631", 0 }, |
1664 | { "alc5631", 0 }, | ||
1689 | { } | 1665 | { } |
1690 | }; | 1666 | }; |
1691 | MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); | 1667 | MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); |
1692 | 1668 | ||
1669 | #ifdef CONFIG_OF | ||
1670 | static struct of_device_id rt5631_i2c_dt_ids[] = { | ||
1671 | { .compatible = "realtek,rt5631"}, | ||
1672 | { .compatible = "realtek,alc5631"}, | ||
1673 | { } | ||
1674 | }; | ||
1675 | MODULE_DEVICE_TABLE(of, rt5631_i2c_dt_ids); | ||
1676 | #endif | ||
1677 | |||
1693 | static const struct regmap_config rt5631_regmap_config = { | 1678 | static const struct regmap_config rt5631_regmap_config = { |
1694 | .reg_bits = 8, | 1679 | .reg_bits = 8, |
1695 | .val_bits = 16, | 1680 | .val_bits = 16, |
@@ -1734,6 +1719,7 @@ static struct i2c_driver rt5631_i2c_driver = { | |||
1734 | .driver = { | 1719 | .driver = { |
1735 | .name = "rt5631", | 1720 | .name = "rt5631", |
1736 | .owner = THIS_MODULE, | 1721 | .owner = THIS_MODULE, |
1722 | .of_match_table = of_match_ptr(rt5631_i2c_dt_ids), | ||
1737 | }, | 1723 | }, |
1738 | .probe = rt5631_i2c_probe, | 1724 | .probe = rt5631_i2c_probe, |
1739 | .remove = rt5631_i2c_remove, | 1725 | .remove = rt5631_i2c_remove, |
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index 78fc159559b0..e18182699d83 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig | |||
@@ -1,11 +1,16 @@ | |||
1 | config SND_SOC_ROCKCHIP | 1 | config SND_SOC_ROCKCHIP |
2 | tristate "ASoC support for Rockchip" | 2 | tristate "ASoC support for Rockchip" |
3 | depends on COMPILE_TEST || ARCH_ROCKCHIP | 3 | depends on COMPILE_TEST || ARCH_ROCKCHIP |
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
5 | help | 4 | help |
6 | 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 |
7 | the Rockchip SoCs' Audio interfaces. You will also need to | 6 | the Rockchip SoCs' Audio interfaces. You will also need to |
8 | select the audio interfaces to support below. | 7 | select the audio interfaces to support below. |
9 | 8 | ||
10 | config SND_SOC_ROCKCHIP_I2S | 9 | config SND_SOC_ROCKCHIP_I2S |
11 | tristate | 10 | tristate "Rockchip I2S Device Driver" |
11 | depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP | ||
12 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
13 | help | ||
14 | Say Y or M if you want to add support for I2S driver for | ||
15 | Rockchip I2S device. The device supports upto maximum of | ||
16 | 8 channels each for play and record. | ||
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index fc41a0e8b09f..14d1a7193469 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -430,7 +430,7 @@ int rsnd_adg_probe(struct platform_device *pdev, | |||
430 | adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); | 430 | adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); |
431 | 431 | ||
432 | for_each_rsnd_clk(clk, adg, i) | 432 | for_each_rsnd_clk(clk, adg, i) |
433 | dev_dbg(dev, "clk %d : %p\n", i, clk); | 433 | dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk)); |
434 | 434 | ||
435 | rsnd_adg_ssi_clk_init(priv, adg); | 435 | rsnd_adg_ssi_clk_init(priv, adg); |
436 | 436 | ||
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 70042197f9e2..75308bbc2ce8 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -349,7 +349,7 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
349 | dma_name); | 349 | dma_name); |
350 | if (!dma->chan) { | 350 | if (!dma->chan) { |
351 | dev_err(dev, "can't get dma channel\n"); | 351 | dev_err(dev, "can't get dma channel\n"); |
352 | return -EIO; | 352 | goto rsnd_dma_channel_err; |
353 | } | 353 | } |
354 | 354 | ||
355 | ret = dmaengine_slave_config(dma->chan, &cfg); | 355 | ret = dmaengine_slave_config(dma->chan, &cfg); |
@@ -363,8 +363,15 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
363 | 363 | ||
364 | rsnd_dma_init_err: | 364 | rsnd_dma_init_err: |
365 | rsnd_dma_quit(priv, dma); | 365 | rsnd_dma_quit(priv, dma); |
366 | rsnd_dma_channel_err: | ||
366 | 367 | ||
367 | return ret; | 368 | /* |
369 | * DMA failed. try to PIO mode | ||
370 | * see | ||
371 | * rsnd_ssi_fallback() | ||
372 | * rsnd_rdai_continuance_probe() | ||
373 | */ | ||
374 | return -EAGAIN; | ||
368 | } | 375 | } |
369 | 376 | ||
370 | void rsnd_dma_quit(struct rsnd_priv *priv, | 377 | void rsnd_dma_quit(struct rsnd_priv *priv, |
@@ -409,9 +416,16 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) | |||
409 | ({ \ | 416 | ({ \ |
410 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ | 417 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ |
411 | struct device *dev = rsnd_priv_to_dev(priv); \ | 418 | struct device *dev = rsnd_priv_to_dev(priv); \ |
412 | dev_dbg(dev, "%s [%d] %s\n", \ | 419 | u32 mask = 1 << __rsnd_mod_shift_##func; \ |
413 | rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ | 420 | u32 call = __rsnd_mod_call_##func << __rsnd_mod_shift_##func; \ |
414 | (mod)->ops->func(mod, rdai); \ | 421 | int ret = 0; \ |
422 | if ((mod->status & mask) == call) { \ | ||
423 | dev_dbg(dev, "%s[%d] %s\n", \ | ||
424 | rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ | ||
425 | ret = (mod)->ops->func(mod, rdai); \ | ||
426 | mod->status = (mod->status & ~mask) | (~call & mask); \ | ||
427 | } \ | ||
428 | ret; \ | ||
415 | }) | 429 | }) |
416 | 430 | ||
417 | #define rsnd_mod_call(mod, func, rdai...) \ | 431 | #define rsnd_mod_call(mod, func, rdai...) \ |
@@ -456,6 +470,13 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, | |||
456 | return 0; | 470 | return 0; |
457 | } | 471 | } |
458 | 472 | ||
473 | static void rsnd_dai_disconnect(struct rsnd_mod *mod, | ||
474 | struct rsnd_dai_stream *io) | ||
475 | { | ||
476 | mod->io = NULL; | ||
477 | io->mod[mod->type] = NULL; | ||
478 | } | ||
479 | |||
459 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) | 480 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) |
460 | { | 481 | { |
461 | int id = rdai - priv->rdai; | 482 | int id = rdai - priv->rdai; |
@@ -686,6 +707,20 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { | |||
686 | ret; \ | 707 | ret; \ |
687 | }) | 708 | }) |
688 | 709 | ||
710 | #define rsnd_path_break(priv, io, type) \ | ||
711 | { \ | ||
712 | struct rsnd_mod *mod; \ | ||
713 | int id = -1; \ | ||
714 | \ | ||
715 | if (rsnd_is_enable_path(io, type)) { \ | ||
716 | id = rsnd_info_id(priv, io, type); \ | ||
717 | if (id >= 0) { \ | ||
718 | mod = rsnd_##type##_mod_get(priv, id); \ | ||
719 | rsnd_dai_disconnect(mod, io); \ | ||
720 | } \ | ||
721 | } \ | ||
722 | } | ||
723 | |||
689 | static int rsnd_path_init(struct rsnd_priv *priv, | 724 | static int rsnd_path_init(struct rsnd_priv *priv, |
690 | struct rsnd_dai *rdai, | 725 | struct rsnd_dai *rdai, |
691 | struct rsnd_dai_stream *io) | 726 | struct rsnd_dai_stream *io) |
@@ -934,6 +969,150 @@ static struct snd_pcm_ops rsnd_pcm_ops = { | |||
934 | }; | 969 | }; |
935 | 970 | ||
936 | /* | 971 | /* |
972 | * snd_kcontrol | ||
973 | */ | ||
974 | #define kcontrol_to_cfg(kctrl) ((struct rsnd_kctrl_cfg *)kctrl->private_value) | ||
975 | static int rsnd_kctrl_info(struct snd_kcontrol *kctrl, | ||
976 | struct snd_ctl_elem_info *uinfo) | ||
977 | { | ||
978 | struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl); | ||
979 | |||
980 | if (cfg->texts) { | ||
981 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
982 | uinfo->count = cfg->size; | ||
983 | uinfo->value.enumerated.items = cfg->max; | ||
984 | if (uinfo->value.enumerated.item >= cfg->max) | ||
985 | uinfo->value.enumerated.item = cfg->max - 1; | ||
986 | strlcpy(uinfo->value.enumerated.name, | ||
987 | cfg->texts[uinfo->value.enumerated.item], | ||
988 | sizeof(uinfo->value.enumerated.name)); | ||
989 | } else { | ||
990 | uinfo->count = cfg->size; | ||
991 | uinfo->value.integer.min = 0; | ||
992 | uinfo->value.integer.max = cfg->max; | ||
993 | uinfo->type = (cfg->max == 1) ? | ||
994 | SNDRV_CTL_ELEM_TYPE_BOOLEAN : | ||
995 | SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
996 | } | ||
997 | |||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | static int rsnd_kctrl_get(struct snd_kcontrol *kctrl, | ||
1002 | struct snd_ctl_elem_value *uc) | ||
1003 | { | ||
1004 | struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl); | ||
1005 | int i; | ||
1006 | |||
1007 | for (i = 0; i < cfg->size; i++) | ||
1008 | if (cfg->texts) | ||
1009 | uc->value.enumerated.item[i] = cfg->val[i]; | ||
1010 | else | ||
1011 | uc->value.integer.value[i] = cfg->val[i]; | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, | ||
1017 | struct snd_ctl_elem_value *uc) | ||
1018 | { | ||
1019 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | ||
1020 | struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl); | ||
1021 | int i, change = 0; | ||
1022 | |||
1023 | for (i = 0; i < cfg->size; i++) { | ||
1024 | if (cfg->texts) { | ||
1025 | change |= (uc->value.enumerated.item[i] != cfg->val[i]); | ||
1026 | cfg->val[i] = uc->value.enumerated.item[i]; | ||
1027 | } else { | ||
1028 | change |= (uc->value.integer.value[i] != cfg->val[i]); | ||
1029 | cfg->val[i] = uc->value.integer.value[i]; | ||
1030 | } | ||
1031 | } | ||
1032 | |||
1033 | if (change) | ||
1034 | cfg->update(mod); | ||
1035 | |||
1036 | return change; | ||
1037 | } | ||
1038 | |||
1039 | static int __rsnd_kctrl_new(struct rsnd_mod *mod, | ||
1040 | struct rsnd_dai *rdai, | ||
1041 | struct snd_soc_pcm_runtime *rtd, | ||
1042 | const unsigned char *name, | ||
1043 | struct rsnd_kctrl_cfg *cfg, | ||
1044 | void (*update)(struct rsnd_mod *mod)) | ||
1045 | { | ||
1046 | struct snd_card *card = rtd->card->snd_card; | ||
1047 | struct snd_kcontrol *kctrl; | ||
1048 | struct snd_kcontrol_new knew = { | ||
1049 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1050 | .name = name, | ||
1051 | .info = rsnd_kctrl_info, | ||
1052 | .get = rsnd_kctrl_get, | ||
1053 | .put = rsnd_kctrl_put, | ||
1054 | .private_value = (unsigned long)cfg, | ||
1055 | }; | ||
1056 | int ret; | ||
1057 | |||
1058 | kctrl = snd_ctl_new1(&knew, mod); | ||
1059 | if (!kctrl) | ||
1060 | return -ENOMEM; | ||
1061 | |||
1062 | ret = snd_ctl_add(card, kctrl); | ||
1063 | if (ret < 0) | ||
1064 | return ret; | ||
1065 | |||
1066 | cfg->update = update; | ||
1067 | |||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, | ||
1072 | struct rsnd_dai *rdai, | ||
1073 | struct snd_soc_pcm_runtime *rtd, | ||
1074 | const unsigned char *name, | ||
1075 | void (*update)(struct rsnd_mod *mod), | ||
1076 | struct rsnd_kctrl_cfg_m *_cfg, | ||
1077 | u32 max) | ||
1078 | { | ||
1079 | _cfg->cfg.max = max; | ||
1080 | _cfg->cfg.size = RSND_DVC_CHANNELS; | ||
1081 | _cfg->cfg.val = _cfg->val; | ||
1082 | return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update); | ||
1083 | } | ||
1084 | |||
1085 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, | ||
1086 | struct rsnd_dai *rdai, | ||
1087 | struct snd_soc_pcm_runtime *rtd, | ||
1088 | const unsigned char *name, | ||
1089 | void (*update)(struct rsnd_mod *mod), | ||
1090 | struct rsnd_kctrl_cfg_s *_cfg, | ||
1091 | u32 max) | ||
1092 | { | ||
1093 | _cfg->cfg.max = max; | ||
1094 | _cfg->cfg.size = 1; | ||
1095 | _cfg->cfg.val = &_cfg->val; | ||
1096 | return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update); | ||
1097 | } | ||
1098 | |||
1099 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, | ||
1100 | struct rsnd_dai *rdai, | ||
1101 | struct snd_soc_pcm_runtime *rtd, | ||
1102 | const unsigned char *name, | ||
1103 | struct rsnd_kctrl_cfg_s *_cfg, | ||
1104 | void (*update)(struct rsnd_mod *mod), | ||
1105 | const char * const *texts, | ||
1106 | u32 max) | ||
1107 | { | ||
1108 | _cfg->cfg.max = max; | ||
1109 | _cfg->cfg.size = 1; | ||
1110 | _cfg->cfg.val = &_cfg->val; | ||
1111 | _cfg->cfg.texts = texts; | ||
1112 | return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update); | ||
1113 | } | ||
1114 | |||
1115 | /* | ||
937 | * snd_soc_platform | 1116 | * snd_soc_platform |
938 | */ | 1117 | */ |
939 | 1118 | ||
@@ -976,6 +1155,49 @@ static const struct snd_soc_component_driver rsnd_soc_component = { | |||
976 | .name = "rsnd", | 1155 | .name = "rsnd", |
977 | }; | 1156 | }; |
978 | 1157 | ||
1158 | static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, | ||
1159 | struct rsnd_dai *rdai, | ||
1160 | int is_play) | ||
1161 | { | ||
1162 | struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture; | ||
1163 | int ret; | ||
1164 | |||
1165 | ret = rsnd_dai_call(probe, io, rdai); | ||
1166 | if (ret == -EAGAIN) { | ||
1167 | /* | ||
1168 | * Fallback to PIO mode | ||
1169 | */ | ||
1170 | |||
1171 | /* | ||
1172 | * call "remove" for SSI/SRC/DVC | ||
1173 | * SSI will be switch to PIO mode if it was DMA mode | ||
1174 | * see | ||
1175 | * rsnd_dma_init() | ||
1176 | * rsnd_ssi_fallback() | ||
1177 | */ | ||
1178 | rsnd_dai_call(remove, io, rdai); | ||
1179 | |||
1180 | /* | ||
1181 | * remove SRC/DVC from DAI, | ||
1182 | */ | ||
1183 | rsnd_path_break(priv, io, src); | ||
1184 | rsnd_path_break(priv, io, dvc); | ||
1185 | |||
1186 | /* | ||
1187 | * fallback | ||
1188 | */ | ||
1189 | rsnd_dai_call(fallback, io, rdai); | ||
1190 | |||
1191 | /* | ||
1192 | * retry to "probe". | ||
1193 | * DAI has SSI which is PIO mode only now. | ||
1194 | */ | ||
1195 | ret = rsnd_dai_call(probe, io, rdai); | ||
1196 | } | ||
1197 | |||
1198 | return ret; | ||
1199 | } | ||
1200 | |||
979 | /* | 1201 | /* |
980 | * rsnd probe | 1202 | * rsnd probe |
981 | */ | 1203 | */ |
@@ -1037,11 +1259,11 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1037 | } | 1259 | } |
1038 | 1260 | ||
1039 | for_each_rsnd_dai(rdai, priv, i) { | 1261 | for_each_rsnd_dai(rdai, priv, i) { |
1040 | ret = rsnd_dai_call(probe, &rdai->playback, rdai); | 1262 | ret = rsnd_rdai_continuance_probe(priv, rdai, 1); |
1041 | if (ret) | 1263 | if (ret) |
1042 | goto exit_snd_probe; | 1264 | goto exit_snd_probe; |
1043 | 1265 | ||
1044 | ret = rsnd_dai_call(probe, &rdai->capture, rdai); | 1266 | ret = rsnd_rdai_continuance_probe(priv, rdai, 0); |
1045 | if (ret) | 1267 | if (ret) |
1046 | goto exit_snd_probe; | 1268 | goto exit_snd_probe; |
1047 | } | 1269 | } |
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 3f443930c2b1..5380a4827ba7 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -11,8 +11,6 @@ | |||
11 | #include "rsnd.h" | 11 | #include "rsnd.h" |
12 | 12 | ||
13 | #define RSND_DVC_NAME_SIZE 16 | 13 | #define RSND_DVC_NAME_SIZE 16 |
14 | #define RSND_DVC_VOLUME_MAX 100 | ||
15 | #define RSND_DVC_VOLUME_NUM 2 | ||
16 | 14 | ||
17 | #define DVC_NAME "dvc" | 15 | #define DVC_NAME "dvc" |
18 | 16 | ||
@@ -20,8 +18,11 @@ struct rsnd_dvc { | |||
20 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ | 18 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ |
21 | struct rsnd_mod mod; | 19 | struct rsnd_mod mod; |
22 | struct clk *clk; | 20 | struct clk *clk; |
23 | u8 volume[RSND_DVC_VOLUME_NUM]; | 21 | struct rsnd_kctrl_cfg_m volume; |
24 | u8 mute[RSND_DVC_VOLUME_NUM]; | 22 | struct rsnd_kctrl_cfg_m mute; |
23 | struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */ | ||
24 | struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */ | ||
25 | struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */ | ||
25 | }; | 26 | }; |
26 | 27 | ||
27 | #define rsnd_mod_to_dvc(_mod) \ | 28 | #define rsnd_mod_to_dvc(_mod) \ |
@@ -33,23 +34,87 @@ struct rsnd_dvc { | |||
33 | ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ | 34 | ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ |
34 | i++) | 35 | i++) |
35 | 36 | ||
37 | static const char const *dvc_ramp_rate[] = { | ||
38 | "128 dB/1 step", /* 00000 */ | ||
39 | "64 dB/1 step", /* 00001 */ | ||
40 | "32 dB/1 step", /* 00010 */ | ||
41 | "16 dB/1 step", /* 00011 */ | ||
42 | "8 dB/1 step", /* 00100 */ | ||
43 | "4 dB/1 step", /* 00101 */ | ||
44 | "2 dB/1 step", /* 00110 */ | ||
45 | "1 dB/1 step", /* 00111 */ | ||
46 | "0.5 dB/1 step", /* 01000 */ | ||
47 | "0.25 dB/1 step", /* 01001 */ | ||
48 | "0.125 dB/1 step", /* 01010 */ | ||
49 | "0.125 dB/2 steps", /* 01011 */ | ||
50 | "0.125 dB/4 steps", /* 01100 */ | ||
51 | "0.125 dB/8 steps", /* 01101 */ | ||
52 | "0.125 dB/16 steps", /* 01110 */ | ||
53 | "0.125 dB/32 steps", /* 01111 */ | ||
54 | "0.125 dB/64 steps", /* 10000 */ | ||
55 | "0.125 dB/128 steps", /* 10001 */ | ||
56 | "0.125 dB/256 steps", /* 10010 */ | ||
57 | "0.125 dB/512 steps", /* 10011 */ | ||
58 | "0.125 dB/1024 steps", /* 10100 */ | ||
59 | "0.125 dB/2048 steps", /* 10101 */ | ||
60 | "0.125 dB/4096 steps", /* 10110 */ | ||
61 | "0.125 dB/8192 steps", /* 10111 */ | ||
62 | }; | ||
63 | |||
36 | static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | 64 | static void rsnd_dvc_volume_update(struct rsnd_mod *mod) |
37 | { | 65 | { |
38 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 66 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
39 | u32 max = (0x00800000 - 1); | 67 | u32 val[RSND_DVC_CHANNELS]; |
40 | u32 vol[RSND_DVC_VOLUME_NUM]; | 68 | u32 dvucr = 0; |
41 | u32 mute = 0; | 69 | u32 mute = 0; |
42 | int i; | 70 | int i; |
43 | 71 | ||
44 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { | 72 | for (i = 0; i < dvc->mute.cfg.size; i++) |
45 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; | 73 | mute |= (!!dvc->mute.cfg.val[i]) << i; |
46 | mute |= (!!dvc->mute[i]) << i; | 74 | |
75 | /* Disable DVC Register access */ | ||
76 | rsnd_mod_write(mod, DVC_DVUER, 0); | ||
77 | |||
78 | /* Enable Ramp */ | ||
79 | if (dvc->ren.val) { | ||
80 | dvucr |= 0x10; | ||
81 | |||
82 | /* Digital Volume Max */ | ||
83 | for (i = 0; i < RSND_DVC_CHANNELS; i++) | ||
84 | val[i] = dvc->volume.cfg.max; | ||
85 | |||
86 | rsnd_mod_write(mod, DVC_VRCTR, 0xff); | ||
87 | rsnd_mod_write(mod, DVC_VRPDR, dvc->rup.val << 8 | | ||
88 | dvc->rdown.val); | ||
89 | /* | ||
90 | * FIXME !! | ||
91 | * use scale-downed Digital Volume | ||
92 | * as Volume Ramp | ||
93 | * 7F FFFF -> 3FF | ||
94 | */ | ||
95 | rsnd_mod_write(mod, DVC_VRDBR, | ||
96 | 0x3ff - (dvc->volume.val[0] >> 13)); | ||
97 | |||
98 | } else { | ||
99 | for (i = 0; i < RSND_DVC_CHANNELS; i++) | ||
100 | val[i] = dvc->volume.val[i]; | ||
101 | } | ||
102 | |||
103 | /* Enable Digital Volume */ | ||
104 | dvucr |= 0x100; | ||
105 | rsnd_mod_write(mod, DVC_VOL0R, val[0]); | ||
106 | rsnd_mod_write(mod, DVC_VOL1R, val[1]); | ||
107 | |||
108 | /* Enable Mute */ | ||
109 | if (mute) { | ||
110 | dvucr |= 0x1; | ||
111 | rsnd_mod_write(mod, DVC_ZCMCR, mute); | ||
47 | } | 112 | } |
48 | 113 | ||
49 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); | 114 | rsnd_mod_write(mod, DVC_DVUCR, dvucr); |
50 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); | ||
51 | 115 | ||
52 | rsnd_mod_write(mod, DVC_ZCMCR, mute); | 116 | /* Enable DVC Register access */ |
117 | rsnd_mod_write(mod, DVC_DVUER, 1); | ||
53 | } | 118 | } |
54 | 119 | ||
55 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | 120 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, |
@@ -58,7 +123,8 @@ static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | |||
58 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 123 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
59 | struct device *dev = rsnd_priv_to_dev(priv); | 124 | struct device *dev = rsnd_priv_to_dev(priv); |
60 | 125 | ||
61 | dev_dbg(dev, "%s (Gen2) is probed\n", rsnd_mod_name(mod)); | 126 | dev_dbg(dev, "%s[%d] (Gen2) is probed\n", |
127 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
62 | 128 | ||
63 | return 0; | 129 | return 0; |
64 | } | 130 | } |
@@ -102,16 +168,11 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
102 | 168 | ||
103 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); | 169 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); |
104 | 170 | ||
105 | /* enable Volume / Mute */ | ||
106 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x101); | ||
107 | |||
108 | /* ch0/ch1 Volume */ | 171 | /* ch0/ch1 Volume */ |
109 | rsnd_dvc_volume_update(dvc_mod); | 172 | rsnd_dvc_volume_update(dvc_mod); |
110 | 173 | ||
111 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); | 174 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); |
112 | 175 | ||
113 | rsnd_mod_write(dvc_mod, DVC_DVUER, 1); | ||
114 | |||
115 | rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io); | 176 | rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io); |
116 | 177 | ||
117 | return 0; | 178 | return 0; |
@@ -143,86 +204,6 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod, | |||
143 | return 0; | 204 | return 0; |
144 | } | 205 | } |
145 | 206 | ||
146 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | ||
147 | struct snd_ctl_elem_info *uinfo) | ||
148 | { | ||
149 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | ||
150 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
151 | u8 *val = (u8 *)kctrl->private_value; | ||
152 | |||
153 | uinfo->count = RSND_DVC_VOLUME_NUM; | ||
154 | uinfo->value.integer.min = 0; | ||
155 | |||
156 | if (val == dvc->volume) { | ||
157 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
158 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | ||
159 | } else { | ||
160 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
161 | uinfo->value.integer.max = 1; | ||
162 | } | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, | ||
168 | struct snd_ctl_elem_value *ucontrol) | ||
169 | { | ||
170 | u8 *val = (u8 *)kctrl->private_value; | ||
171 | int i; | ||
172 | |||
173 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | ||
174 | ucontrol->value.integer.value[i] = val[i]; | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl, | ||
180 | struct snd_ctl_elem_value *ucontrol) | ||
181 | { | ||
182 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | ||
183 | u8 *val = (u8 *)kctrl->private_value; | ||
184 | int i, change = 0; | ||
185 | |||
186 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { | ||
187 | change |= (ucontrol->value.integer.value[i] != val[i]); | ||
188 | val[i] = ucontrol->value.integer.value[i]; | ||
189 | } | ||
190 | |||
191 | if (change) | ||
192 | rsnd_dvc_volume_update(mod); | ||
193 | |||
194 | return change; | ||
195 | } | ||
196 | |||
197 | static int __rsnd_dvc_pcm_new(struct rsnd_mod *mod, | ||
198 | struct rsnd_dai *rdai, | ||
199 | struct snd_soc_pcm_runtime *rtd, | ||
200 | const unsigned char *name, | ||
201 | u8 *private) | ||
202 | { | ||
203 | struct snd_card *card = rtd->card->snd_card; | ||
204 | struct snd_kcontrol *kctrl; | ||
205 | struct snd_kcontrol_new knew = { | ||
206 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
207 | .name = name, | ||
208 | .info = rsnd_dvc_volume_info, | ||
209 | .get = rsnd_dvc_volume_get, | ||
210 | .put = rsnd_dvc_volume_put, | ||
211 | .private_value = (unsigned long)private, | ||
212 | }; | ||
213 | int ret; | ||
214 | |||
215 | kctrl = snd_ctl_new1(&knew, mod); | ||
216 | if (!kctrl) | ||
217 | return -ENOMEM; | ||
218 | |||
219 | ret = snd_ctl_add(card, kctrl); | ||
220 | if (ret < 0) | ||
221 | return ret; | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | 207 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, |
227 | struct rsnd_dai *rdai, | 208 | struct rsnd_dai *rdai, |
228 | struct snd_soc_pcm_runtime *rtd) | 209 | struct snd_soc_pcm_runtime *rtd) |
@@ -232,18 +213,48 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
232 | int ret; | 213 | int ret; |
233 | 214 | ||
234 | /* Volume */ | 215 | /* Volume */ |
235 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | 216 | ret = rsnd_kctrl_new_m(mod, rdai, rtd, |
236 | rsnd_dai_is_play(rdai, io) ? | 217 | rsnd_dai_is_play(rdai, io) ? |
237 | "DVC Out Playback Volume" : "DVC In Capture Volume", | 218 | "DVC Out Playback Volume" : "DVC In Capture Volume", |
238 | dvc->volume); | 219 | rsnd_dvc_volume_update, |
220 | &dvc->volume, 0x00800000 - 1); | ||
239 | if (ret < 0) | 221 | if (ret < 0) |
240 | return ret; | 222 | return ret; |
241 | 223 | ||
242 | /* Mute */ | 224 | /* Mute */ |
243 | ret = __rsnd_dvc_pcm_new(mod, rdai, rtd, | 225 | ret = rsnd_kctrl_new_m(mod, rdai, rtd, |
244 | rsnd_dai_is_play(rdai, io) ? | 226 | rsnd_dai_is_play(rdai, io) ? |
245 | "DVC Out Mute Switch" : "DVC In Mute Switch", | 227 | "DVC Out Mute Switch" : "DVC In Mute Switch", |
246 | dvc->mute); | 228 | rsnd_dvc_volume_update, |
229 | &dvc->mute, 1); | ||
230 | if (ret < 0) | ||
231 | return ret; | ||
232 | |||
233 | /* Ramp */ | ||
234 | ret = rsnd_kctrl_new_s(mod, rdai, rtd, | ||
235 | rsnd_dai_is_play(rdai, io) ? | ||
236 | "DVC Out Ramp Switch" : "DVC In Ramp Switch", | ||
237 | rsnd_dvc_volume_update, | ||
238 | &dvc->ren, 1); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | ret = rsnd_kctrl_new_e(mod, rdai, rtd, | ||
243 | rsnd_dai_is_play(rdai, io) ? | ||
244 | "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", | ||
245 | &dvc->rup, | ||
246 | rsnd_dvc_volume_update, | ||
247 | dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate)); | ||
248 | if (ret < 0) | ||
249 | return ret; | ||
250 | |||
251 | ret = rsnd_kctrl_new_e(mod, rdai, rtd, | ||
252 | rsnd_dai_is_play(rdai, io) ? | ||
253 | "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", | ||
254 | &dvc->rdown, | ||
255 | rsnd_dvc_volume_update, | ||
256 | dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate)); | ||
257 | |||
247 | if (ret < 0) | 258 | if (ret < 0) |
248 | return ret; | 259 | return ret; |
249 | 260 | ||
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index f95e7ab135e8..87a6f2d62775 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -8,6 +8,17 @@ | |||
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | |||
12 | /* | ||
13 | * #define DEBUG | ||
14 | * | ||
15 | * you can also add below in | ||
16 | * ${LINUX}/drivers/base/regmap/regmap.c | ||
17 | * for regmap debug | ||
18 | * | ||
19 | * #define LOG_DEVICE "xxxx.rcar_sound" | ||
20 | */ | ||
21 | |||
11 | #include "rsnd.h" | 22 | #include "rsnd.h" |
12 | 23 | ||
13 | struct rsnd_gen { | 24 | struct rsnd_gen { |
@@ -67,9 +78,10 @@ u32 rsnd_read(struct rsnd_priv *priv, | |||
67 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 78 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
68 | return 0; | 79 | return 0; |
69 | 80 | ||
70 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); | 81 | dev_dbg(dev, "r %s[%d] - %4d : %08x\n", |
82 | rsnd_mod_name(mod), rsnd_mod_id(mod), reg, val); | ||
71 | 83 | ||
72 | dev_dbg(dev, "r %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, val); | 84 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); |
73 | 85 | ||
74 | return val; | 86 | return val; |
75 | } | 87 | } |
@@ -84,9 +96,10 @@ void rsnd_write(struct rsnd_priv *priv, | |||
84 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 96 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
85 | return; | 97 | return; |
86 | 98 | ||
87 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); | 99 | dev_dbg(dev, "w %s[%d] - %4d : %08x\n", |
100 | rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data); | ||
88 | 101 | ||
89 | dev_dbg(dev, "w %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, data); | 102 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); |
90 | } | 103 | } |
91 | 104 | ||
92 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | 105 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, |
@@ -98,11 +111,11 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | |||
98 | if (!rsnd_is_accessible_reg(priv, gen, reg)) | 111 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
99 | return; | 112 | return; |
100 | 113 | ||
114 | dev_dbg(dev, "b %s[%d] - %4d : %08x/%08x\n", | ||
115 | rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data, mask); | ||
116 | |||
101 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), | 117 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), |
102 | mask, data); | 118 | mask, data); |
103 | |||
104 | dev_dbg(dev, "b %s - 0x%04d : %08x/%08x\n", | ||
105 | rsnd_mod_name(mod), reg, data, mask); | ||
106 | } | 119 | } |
107 | 120 | ||
108 | #define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \ | 121 | #define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \ |
@@ -311,6 +324,9 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
311 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), | 324 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), |
312 | RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), | 325 | RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), |
313 | RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), | 326 | RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), |
327 | RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100), | ||
328 | RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100), | ||
329 | RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100), | ||
314 | RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), | 330 | RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), |
315 | RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), | 331 | RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), |
316 | RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), | 332 | RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d119adf97c9c..5826c8abf794 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -91,6 +91,9 @@ enum rsnd_reg { | |||
91 | RSND_REG_SHARE20, | 91 | RSND_REG_SHARE20, |
92 | RSND_REG_SHARE21, | 92 | RSND_REG_SHARE21, |
93 | RSND_REG_SHARE22, | 93 | RSND_REG_SHARE22, |
94 | RSND_REG_SHARE23, | ||
95 | RSND_REG_SHARE24, | ||
96 | RSND_REG_SHARE25, | ||
94 | 97 | ||
95 | RSND_REG_MAX, | 98 | RSND_REG_MAX, |
96 | }; | 99 | }; |
@@ -129,6 +132,9 @@ enum rsnd_reg { | |||
129 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 | 132 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 |
130 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 | 133 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 |
131 | #define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22 | 134 | #define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22 |
135 | #define RSND_REG_DVC_VRCTR RSND_REG_SHARE23 | ||
136 | #define RSND_REG_DVC_VRPDR RSND_REG_SHARE24 | ||
137 | #define RSND_REG_DVC_VRDBR RSND_REG_SHARE25 | ||
132 | 138 | ||
133 | struct rsnd_of_data; | 139 | struct rsnd_of_data; |
134 | struct rsnd_priv; | 140 | struct rsnd_priv; |
@@ -200,6 +206,8 @@ struct rsnd_mod_ops { | |||
200 | int (*pcm_new)(struct rsnd_mod *mod, | 206 | int (*pcm_new)(struct rsnd_mod *mod, |
201 | struct rsnd_dai *rdai, | 207 | struct rsnd_dai *rdai, |
202 | struct snd_soc_pcm_runtime *rtd); | 208 | struct snd_soc_pcm_runtime *rtd); |
209 | int (*fallback)(struct rsnd_mod *mod, | ||
210 | struct rsnd_dai *rdai); | ||
203 | }; | 211 | }; |
204 | 212 | ||
205 | struct rsnd_dai_stream; | 213 | struct rsnd_dai_stream; |
@@ -210,7 +218,35 @@ struct rsnd_mod { | |||
210 | struct rsnd_mod_ops *ops; | 218 | struct rsnd_mod_ops *ops; |
211 | struct rsnd_dma dma; | 219 | struct rsnd_dma dma; |
212 | struct rsnd_dai_stream *io; | 220 | struct rsnd_dai_stream *io; |
221 | u32 status; | ||
213 | }; | 222 | }; |
223 | /* | ||
224 | * status | ||
225 | * | ||
226 | * bit | ||
227 | * 0 0: probe 1: remove | ||
228 | * 1 0: init 1: quit | ||
229 | * 2 0: start 1: stop | ||
230 | * 3 0: pcm_new | ||
231 | * 4 0: fallback | ||
232 | */ | ||
233 | #define __rsnd_mod_shift_probe 0 | ||
234 | #define __rsnd_mod_shift_remove 0 | ||
235 | #define __rsnd_mod_shift_init 1 | ||
236 | #define __rsnd_mod_shift_quit 1 | ||
237 | #define __rsnd_mod_shift_start 2 | ||
238 | #define __rsnd_mod_shift_stop 2 | ||
239 | #define __rsnd_mod_shift_pcm_new 3 | ||
240 | #define __rsnd_mod_shift_fallback 4 | ||
241 | |||
242 | #define __rsnd_mod_call_probe 0 | ||
243 | #define __rsnd_mod_call_remove 1 | ||
244 | #define __rsnd_mod_call_init 0 | ||
245 | #define __rsnd_mod_call_quit 1 | ||
246 | #define __rsnd_mod_call_start 0 | ||
247 | #define __rsnd_mod_call_stop 1 | ||
248 | #define __rsnd_mod_call_pcm_new 0 | ||
249 | #define __rsnd_mod_call_fallback 0 | ||
214 | 250 | ||
215 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | 251 | #define rsnd_mod_to_priv(mod) ((mod)->priv) |
216 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) | 252 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) |
@@ -267,7 +303,8 @@ struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); | |||
267 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); | 303 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); |
268 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); | 304 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); |
269 | #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) | 305 | #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) |
270 | #define rsnd_io_to_runtime(io) ((io)->substream->runtime) | 306 | #define rsnd_io_to_runtime(io) ((io)->substream ? \ |
307 | (io)->substream->runtime : NULL) | ||
271 | 308 | ||
272 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); | 309 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); |
273 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); | 310 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); |
@@ -382,6 +419,51 @@ struct rsnd_priv { | |||
382 | }) | 419 | }) |
383 | 420 | ||
384 | /* | 421 | /* |
422 | * rsnd_kctrl | ||
423 | */ | ||
424 | struct rsnd_kctrl_cfg { | ||
425 | unsigned int max; | ||
426 | unsigned int size; | ||
427 | u32 *val; | ||
428 | const char * const *texts; | ||
429 | void (*update)(struct rsnd_mod *mod); | ||
430 | }; | ||
431 | |||
432 | #define RSND_DVC_CHANNELS 2 | ||
433 | struct rsnd_kctrl_cfg_m { | ||
434 | struct rsnd_kctrl_cfg cfg; | ||
435 | u32 val[RSND_DVC_CHANNELS]; | ||
436 | }; | ||
437 | |||
438 | struct rsnd_kctrl_cfg_s { | ||
439 | struct rsnd_kctrl_cfg cfg; | ||
440 | u32 val; | ||
441 | }; | ||
442 | |||
443 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, | ||
444 | struct rsnd_dai *rdai, | ||
445 | struct snd_soc_pcm_runtime *rtd, | ||
446 | const unsigned char *name, | ||
447 | void (*update)(struct rsnd_mod *mod), | ||
448 | struct rsnd_kctrl_cfg_m *_cfg, | ||
449 | u32 max); | ||
450 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, | ||
451 | struct rsnd_dai *rdai, | ||
452 | struct snd_soc_pcm_runtime *rtd, | ||
453 | const unsigned char *name, | ||
454 | void (*update)(struct rsnd_mod *mod), | ||
455 | struct rsnd_kctrl_cfg_s *_cfg, | ||
456 | u32 max); | ||
457 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, | ||
458 | struct rsnd_dai *rdai, | ||
459 | struct snd_soc_pcm_runtime *rtd, | ||
460 | const unsigned char *name, | ||
461 | struct rsnd_kctrl_cfg_s *_cfg, | ||
462 | void (*update)(struct rsnd_mod *mod), | ||
463 | const char * const *texts, | ||
464 | u32 max); | ||
465 | |||
466 | /* | ||
385 | * R-Car SRC | 467 | * R-Car SRC |
386 | */ | 468 | */ |
387 | int rsnd_src_probe(struct platform_device *pdev, | 469 | int rsnd_src_probe(struct platform_device *pdev, |
@@ -395,10 +477,11 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
395 | struct rsnd_dai *rdai, | 477 | struct rsnd_dai *rdai, |
396 | int use_busif); | 478 | int use_busif); |
397 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | 479 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, |
398 | struct rsnd_dai *rdai, | 480 | struct rsnd_dai *rdai); |
399 | int use_busif); | 481 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod, |
400 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, | ||
401 | struct rsnd_dai *rdai); | 482 | struct rsnd_dai *rdai); |
483 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod, | ||
484 | struct rsnd_dai *rdai); | ||
402 | 485 | ||
403 | #define rsnd_src_nr(priv) ((priv)->src_nr) | 486 | #define rsnd_src_nr(priv) ((priv)->src_nr) |
404 | 487 | ||
@@ -410,6 +493,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
410 | struct rsnd_priv *priv); | 493 | struct rsnd_priv *priv); |
411 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | 494 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); |
412 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | 495 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); |
496 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); | ||
413 | 497 | ||
414 | /* | 498 | /* |
415 | * R-Car DVC | 499 | * R-Car DVC |
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 9183e0145503..eede3ac6eed2 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -175,30 +175,47 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
175 | } | 175 | } |
176 | 176 | ||
177 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | 177 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, |
178 | struct rsnd_dai *rdai, | 178 | struct rsnd_dai *rdai) |
179 | int use_busif) | ||
180 | { | 179 | { |
181 | /* | 180 | /* |
182 | * DMA settings for SSIU | 181 | * DMA settings for SSIU |
183 | */ | 182 | */ |
184 | if (use_busif) | 183 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0); |
185 | rsnd_mod_write(ssi_mod, SSI_CTRL, 0); | ||
186 | 184 | ||
187 | return 0; | 185 | return 0; |
188 | } | 186 | } |
189 | 187 | ||
190 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, | 188 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod, |
191 | struct rsnd_dai *rdai) | 189 | struct rsnd_dai *rdai) |
192 | { | 190 | { |
193 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | 191 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); |
194 | 192 | ||
195 | /* enable PIO interrupt if Gen2 */ | 193 | if (rsnd_is_gen1(priv)) |
196 | if (rsnd_is_gen2(priv)) | 194 | return 0; |
195 | |||
196 | /* enable SSI interrupt if Gen2 */ | ||
197 | if (rsnd_ssi_is_dma_mode(ssi_mod)) | ||
198 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0e000000); | ||
199 | else | ||
197 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); | 200 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); |
198 | 201 | ||
199 | return 0; | 202 | return 0; |
200 | } | 203 | } |
201 | 204 | ||
205 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod, | ||
206 | struct rsnd_dai *rdai) | ||
207 | { | ||
208 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | ||
209 | |||
210 | if (rsnd_is_gen1(priv)) | ||
211 | return 0; | ||
212 | |||
213 | /* disable SSI interrupt if Gen2 */ | ||
214 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x00000000); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
202 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | 219 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, |
203 | struct rsnd_dai_stream *io, | 220 | struct rsnd_dai_stream *io, |
204 | struct snd_pcm_runtime *runtime) | 221 | struct snd_pcm_runtime *runtime) |
@@ -239,12 +256,6 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, | |||
239 | rsnd_mod_write(mod, SRC_SWRSR, 0); | 256 | rsnd_mod_write(mod, SRC_SWRSR, 0); |
240 | rsnd_mod_write(mod, SRC_SWRSR, 1); | 257 | rsnd_mod_write(mod, SRC_SWRSR, 1); |
241 | 258 | ||
242 | /* | ||
243 | * Initialize the operation of the SRC internal circuits | ||
244 | * see rsnd_src_start() | ||
245 | */ | ||
246 | rsnd_mod_write(mod, SRC_SRCIR, 1); | ||
247 | |||
248 | /* Set channel number and output bit length */ | 259 | /* Set channel number and output bit length */ |
249 | rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod)); | 260 | rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod)); |
250 | 261 | ||
@@ -269,6 +280,12 @@ static int rsnd_src_init(struct rsnd_mod *mod, | |||
269 | 280 | ||
270 | clk_prepare_enable(src->clk); | 281 | clk_prepare_enable(src->clk); |
271 | 282 | ||
283 | /* | ||
284 | * Initialize the operation of the SRC internal circuits | ||
285 | * see rsnd_src_start() | ||
286 | */ | ||
287 | rsnd_mod_write(mod, SRC_SRCIR, 1); | ||
288 | |||
272 | return 0; | 289 | return 0; |
273 | } | 290 | } |
274 | 291 | ||
@@ -282,32 +299,20 @@ static int rsnd_src_quit(struct rsnd_mod *mod, | |||
282 | return 0; | 299 | return 0; |
283 | } | 300 | } |
284 | 301 | ||
285 | static int rsnd_src_start(struct rsnd_mod *mod, | 302 | static int rsnd_src_start(struct rsnd_mod *mod) |
286 | struct rsnd_dai *rdai) | ||
287 | { | 303 | { |
288 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
289 | |||
290 | /* | 304 | /* |
291 | * Cancel the initialization and operate the SRC function | 305 | * Cancel the initialization and operate the SRC function |
292 | * see rsnd_src_set_convert_rate() | 306 | * see rsnd_src_init() |
293 | */ | 307 | */ |
294 | rsnd_mod_write(mod, SRC_SRCIR, 0); | 308 | rsnd_mod_write(mod, SRC_SRCIR, 0); |
295 | 309 | ||
296 | if (rsnd_src_convert_rate(src)) | ||
297 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); | ||
298 | |||
299 | return 0; | 310 | return 0; |
300 | } | 311 | } |
301 | 312 | ||
302 | 313 | static int rsnd_src_stop(struct rsnd_mod *mod) | |
303 | static int rsnd_src_stop(struct rsnd_mod *mod, | ||
304 | struct rsnd_dai *rdai) | ||
305 | { | 314 | { |
306 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 315 | /* nothing to do */ |
307 | |||
308 | if (rsnd_src_convert_rate(src)) | ||
309 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); | ||
310 | |||
311 | return 0; | 316 | return 0; |
312 | } | 317 | } |
313 | 318 | ||
@@ -414,6 +419,7 @@ static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, | |||
414 | static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, | 419 | static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, |
415 | struct rsnd_dai *rdai) | 420 | struct rsnd_dai *rdai) |
416 | { | 421 | { |
422 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
417 | int ret; | 423 | int ret; |
418 | 424 | ||
419 | ret = rsnd_src_set_convert_rate(mod, rdai); | 425 | ret = rsnd_src_set_convert_rate(mod, rdai); |
@@ -427,6 +433,10 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, | |||
427 | rsnd_mod_write(mod, SRC_MNFSR, | 433 | rsnd_mod_write(mod, SRC_MNFSR, |
428 | rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); | 434 | rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); |
429 | 435 | ||
436 | /* Gen1/Gen2 are not compatible */ | ||
437 | if (rsnd_src_convert_rate(src)) | ||
438 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); | ||
439 | |||
430 | /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ | 440 | /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ |
431 | 441 | ||
432 | return 0; | 442 | return 0; |
@@ -438,7 +448,8 @@ static int rsnd_src_probe_gen1(struct rsnd_mod *mod, | |||
438 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 448 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
439 | struct device *dev = rsnd_priv_to_dev(priv); | 449 | struct device *dev = rsnd_priv_to_dev(priv); |
440 | 450 | ||
441 | dev_dbg(dev, "%s (Gen1) is probed\n", rsnd_mod_name(mod)); | 451 | dev_dbg(dev, "%s[%d] (Gen1) is probed\n", |
452 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
442 | 453 | ||
443 | return 0; | 454 | return 0; |
444 | } | 455 | } |
@@ -474,7 +485,7 @@ static int rsnd_src_start_gen1(struct rsnd_mod *mod, | |||
474 | 485 | ||
475 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); | 486 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); |
476 | 487 | ||
477 | return rsnd_src_start(mod, rdai); | 488 | return rsnd_src_start(mod); |
478 | } | 489 | } |
479 | 490 | ||
480 | static int rsnd_src_stop_gen1(struct rsnd_mod *mod, | 491 | static int rsnd_src_stop_gen1(struct rsnd_mod *mod, |
@@ -484,7 +495,7 @@ static int rsnd_src_stop_gen1(struct rsnd_mod *mod, | |||
484 | 495 | ||
485 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); | 496 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); |
486 | 497 | ||
487 | return rsnd_src_stop(mod, rdai); | 498 | return rsnd_src_stop(mod); |
488 | } | 499 | } |
489 | 500 | ||
490 | static struct rsnd_mod_ops rsnd_src_gen1_ops = { | 501 | static struct rsnd_mod_ops rsnd_src_gen1_ops = { |
@@ -507,16 +518,17 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | |||
507 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 518 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
508 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 519 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
509 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 520 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
521 | u32 convert_rate = rsnd_src_convert_rate(src); | ||
510 | uint ratio; | 522 | uint ratio; |
511 | int ret; | 523 | int ret; |
512 | 524 | ||
513 | /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ | 525 | /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ |
514 | if (!rsnd_src_convert_rate(src)) | 526 | if (!convert_rate) |
515 | ratio = 0; | 527 | ratio = 0; |
516 | else if (rsnd_src_convert_rate(src) > runtime->rate) | 528 | else if (convert_rate > runtime->rate) |
517 | ratio = 100 * rsnd_src_convert_rate(src) / runtime->rate; | 529 | ratio = 100 * convert_rate / runtime->rate; |
518 | else | 530 | else |
519 | ratio = 100 * runtime->rate / rsnd_src_convert_rate(src); | 531 | ratio = 100 * runtime->rate / convert_rate; |
520 | 532 | ||
521 | if (ratio > 600) { | 533 | if (ratio > 600) { |
522 | dev_err(dev, "FSO/FSI ratio error\n"); | 534 | dev_err(dev, "FSO/FSI ratio error\n"); |
@@ -529,6 +541,11 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | |||
529 | 541 | ||
530 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); | 542 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); |
531 | 543 | ||
544 | if (convert_rate) { | ||
545 | /* Gen1/Gen2 are not compatible */ | ||
546 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); | ||
547 | } | ||
548 | |||
532 | switch (rsnd_mod_id(mod)) { | 549 | switch (rsnd_mod_id(mod)) { |
533 | case 5: | 550 | case 5: |
534 | case 6: | 551 | case 6: |
@@ -578,9 +595,11 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod, | |||
578 | rsnd_info_is_playback(priv, src), | 595 | rsnd_info_is_playback(priv, src), |
579 | src->info->dma_id); | 596 | src->info->dma_id); |
580 | if (ret < 0) | 597 | if (ret < 0) |
581 | dev_err(dev, "SRC DMA failed\n"); | 598 | dev_err(dev, "%s[%d] (Gen2) failed\n", |
582 | 599 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | |
583 | dev_dbg(dev, "%s (Gen2) is probed\n", rsnd_mod_name(mod)); | 600 | else |
601 | dev_dbg(dev, "%s[%d] (Gen2) is probed\n", | ||
602 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
584 | 603 | ||
585 | return ret; | 604 | return ret; |
586 | } | 605 | } |
@@ -624,7 +643,7 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, | |||
624 | 643 | ||
625 | rsnd_mod_write(mod, SRC_CTRL, val); | 644 | rsnd_mod_write(mod, SRC_CTRL, val); |
626 | 645 | ||
627 | return rsnd_src_start(mod, rdai); | 646 | return rsnd_src_start(mod); |
628 | } | 647 | } |
629 | 648 | ||
630 | static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | 649 | static int rsnd_src_stop_gen2(struct rsnd_mod *mod, |
@@ -636,7 +655,7 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | |||
636 | 655 | ||
637 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); | 656 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); |
638 | 657 | ||
639 | return rsnd_src_stop(mod, rdai); | 658 | return rsnd_src_stop(mod); |
640 | } | 659 | } |
641 | 660 | ||
642 | static struct rsnd_mod_ops rsnd_src_gen2_ops = { | 661 | static struct rsnd_mod_ops rsnd_src_gen2_ops = { |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 34e84009162b..3844fbef4664 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -68,7 +68,6 @@ struct rsnd_ssi { | |||
68 | struct rsnd_dai *rdai; | 68 | struct rsnd_dai *rdai; |
69 | u32 cr_own; | 69 | u32 cr_own; |
70 | u32 cr_clk; | 70 | u32 cr_clk; |
71 | u32 cr_etc; | ||
72 | int err; | 71 | int err; |
73 | unsigned int usrcnt; | 72 | unsigned int usrcnt; |
74 | unsigned int rate; | 73 | unsigned int rate; |
@@ -83,7 +82,7 @@ struct rsnd_ssi { | |||
83 | #define rsnd_ssi_nr(priv) ((priv)->ssi_nr) | 82 | #define rsnd_ssi_nr(priv) ((priv)->ssi_nr) |
84 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) | 83 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) |
85 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) | 84 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) |
86 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) | 85 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0) |
87 | #define rsnd_ssi_dma_available(ssi) \ | 86 | #define rsnd_ssi_dma_available(ssi) \ |
88 | rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) | 87 | rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) |
89 | #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) | 88 | #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) |
@@ -96,6 +95,9 @@ static int rsnd_ssi_use_busif(struct rsnd_mod *mod) | |||
96 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 95 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
97 | int use_busif = 0; | 96 | int use_busif = 0; |
98 | 97 | ||
98 | if (!rsnd_ssi_is_dma_mode(mod)) | ||
99 | return 0; | ||
100 | |||
99 | if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF)) | 101 | if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF)) |
100 | use_busif = 1; | 102 | use_busif = 1; |
101 | if (rsnd_io_to_mod_src(io)) | 103 | if (rsnd_io_to_mod_src(io)) |
@@ -159,7 +161,8 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | |||
159 | ssi->cr_clk = FORCE | SWL_32 | | 161 | ssi->cr_clk = FORCE | SWL_32 | |
160 | SCKD | SWSD | CKDV(j); | 162 | SCKD | SWSD | CKDV(j); |
161 | 163 | ||
162 | dev_dbg(dev, "ssi%d outputs %u Hz\n", | 164 | dev_dbg(dev, "%s[%d] outputs %u Hz\n", |
165 | rsnd_mod_name(&ssi->mod), | ||
163 | rsnd_mod_id(&ssi->mod), rate); | 166 | rsnd_mod_id(&ssi->mod), rate); |
164 | 167 | ||
165 | return 0; | 168 | return 0; |
@@ -184,6 +187,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
184 | { | 187 | { |
185 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | 188 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); |
186 | struct device *dev = rsnd_priv_to_dev(priv); | 189 | struct device *dev = rsnd_priv_to_dev(priv); |
190 | u32 cr_mode; | ||
187 | u32 cr; | 191 | u32 cr; |
188 | 192 | ||
189 | if (0 == ssi->usrcnt) { | 193 | if (0 == ssi->usrcnt) { |
@@ -197,16 +201,29 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
197 | } | 201 | } |
198 | } | 202 | } |
199 | 203 | ||
204 | cr_mode = rsnd_ssi_is_dma_mode(&ssi->mod) ? | ||
205 | DMEN : /* DMA : enable DMA */ | ||
206 | DIEN; /* PIO : enable Data interrupt */ | ||
207 | |||
208 | |||
200 | cr = ssi->cr_own | | 209 | cr = ssi->cr_own | |
201 | ssi->cr_clk | | 210 | ssi->cr_clk | |
202 | ssi->cr_etc | | 211 | cr_mode | |
203 | EN; | 212 | UIEN | OIEN | EN; |
204 | 213 | ||
205 | rsnd_mod_write(&ssi->mod, SSICR, cr); | 214 | rsnd_mod_write(&ssi->mod, SSICR, cr); |
206 | 215 | ||
216 | /* enable WS continue */ | ||
217 | if (rsnd_dai_is_clk_master(rdai)) | ||
218 | rsnd_mod_write(&ssi->mod, SSIWSR, CONT); | ||
219 | |||
220 | /* clear error status */ | ||
221 | rsnd_mod_write(&ssi->mod, SSISR, 0); | ||
222 | |||
207 | ssi->usrcnt++; | 223 | ssi->usrcnt++; |
208 | 224 | ||
209 | dev_dbg(dev, "ssi%d hw started\n", rsnd_mod_id(&ssi->mod)); | 225 | dev_dbg(dev, "%s[%d] hw started\n", |
226 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); | ||
210 | } | 227 | } |
211 | 228 | ||
212 | static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, | 229 | static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, |
@@ -249,7 +266,8 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, | |||
249 | clk_disable_unprepare(ssi->clk); | 266 | clk_disable_unprepare(ssi->clk); |
250 | } | 267 | } |
251 | 268 | ||
252 | dev_dbg(dev, "ssi%d hw stopped\n", rsnd_mod_id(&ssi->mod)); | 269 | dev_dbg(dev, "%s[%d] hw stopped\n", |
270 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); | ||
253 | } | 271 | } |
254 | 272 | ||
255 | /* | 273 | /* |
@@ -334,25 +352,54 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | |||
334 | } | 352 | } |
335 | } | 353 | } |
336 | 354 | ||
337 | /* | 355 | static int rsnd_ssi_start(struct rsnd_mod *mod, |
338 | * SSI PIO | 356 | struct rsnd_dai *rdai) |
339 | */ | 357 | { |
340 | static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) | 358 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
359 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
360 | |||
361 | rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod)); | ||
362 | |||
363 | rsnd_ssi_hw_start(ssi, rdai, io); | ||
364 | |||
365 | rsnd_src_ssi_irq_enable(mod, rdai); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int rsnd_ssi_stop(struct rsnd_mod *mod, | ||
371 | struct rsnd_dai *rdai) | ||
372 | { | ||
373 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
374 | |||
375 | rsnd_src_ssi_irq_disable(mod, rdai); | ||
376 | |||
377 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); | ||
378 | |||
379 | rsnd_ssi_hw_stop(ssi, rdai); | ||
380 | |||
381 | rsnd_src_ssiu_stop(mod, rdai); | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | ||
341 | { | 387 | { |
342 | struct rsnd_ssi *ssi = data; | 388 | struct rsnd_ssi *ssi = data; |
389 | struct rsnd_dai *rdai = ssi->rdai; | ||
343 | struct rsnd_mod *mod = &ssi->mod; | 390 | struct rsnd_mod *mod = &ssi->mod; |
344 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 391 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
345 | u32 status = rsnd_mod_read(mod, SSISR); | 392 | u32 status = rsnd_mod_read(mod, SSISR); |
346 | irqreturn_t ret = IRQ_NONE; | ||
347 | 393 | ||
348 | if (io && (status & DIRQ)) { | 394 | if (!io) |
349 | struct rsnd_dai *rdai = ssi->rdai; | 395 | return IRQ_NONE; |
396 | |||
397 | /* PIO only */ | ||
398 | if (status & DIRQ) { | ||
350 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 399 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
351 | u32 *buf = (u32 *)(runtime->dma_area + | 400 | u32 *buf = (u32 *)(runtime->dma_area + |
352 | rsnd_dai_pointer_offset(io, 0)); | 401 | rsnd_dai_pointer_offset(io, 0)); |
353 | 402 | ||
354 | rsnd_ssi_record_error(ssi, status); | ||
355 | |||
356 | /* | 403 | /* |
357 | * 8/16/32 data can be assesse to TDR/RDR register | 404 | * 8/16/32 data can be assesse to TDR/RDR register |
358 | * directly as 32bit data | 405 | * directly as 32bit data |
@@ -364,73 +411,60 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) | |||
364 | *buf = rsnd_mod_read(mod, SSIRDR); | 411 | *buf = rsnd_mod_read(mod, SSIRDR); |
365 | 412 | ||
366 | rsnd_dai_pointer_update(io, sizeof(*buf)); | 413 | rsnd_dai_pointer_update(io, sizeof(*buf)); |
414 | } | ||
415 | |||
416 | /* PIO / DMA */ | ||
417 | if (status & (UIRQ | OIRQ)) { | ||
418 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
419 | struct device *dev = rsnd_priv_to_dev(priv); | ||
420 | |||
421 | /* | ||
422 | * restart SSI | ||
423 | */ | ||
424 | rsnd_ssi_stop(mod, rdai); | ||
425 | rsnd_ssi_start(mod, rdai); | ||
367 | 426 | ||
368 | ret = IRQ_HANDLED; | 427 | dev_dbg(dev, "%s[%d] restart\n", |
428 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
369 | } | 429 | } |
370 | 430 | ||
371 | return ret; | 431 | rsnd_ssi_record_error(ssi, status); |
432 | |||
433 | return IRQ_HANDLED; | ||
372 | } | 434 | } |
373 | 435 | ||
436 | /* | ||
437 | * SSI PIO | ||
438 | */ | ||
374 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, | 439 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, |
375 | struct rsnd_dai *rdai) | 440 | struct rsnd_dai *rdai) |
376 | { | 441 | { |
377 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 442 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
378 | struct device *dev = rsnd_priv_to_dev(priv); | 443 | struct device *dev = rsnd_priv_to_dev(priv); |
379 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 444 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
380 | int irq = ssi->info->pio_irq; | ||
381 | int ret; | 445 | int ret; |
382 | 446 | ||
383 | ret = devm_request_irq(dev, irq, | 447 | ret = devm_request_irq(dev, ssi->info->irq, |
384 | rsnd_ssi_pio_interrupt, | 448 | rsnd_ssi_interrupt, |
385 | IRQF_SHARED, | 449 | IRQF_SHARED, |
386 | dev_name(dev), ssi); | 450 | dev_name(dev), ssi); |
387 | if (ret) | 451 | if (ret) |
388 | dev_err(dev, "SSI request interrupt failed\n"); | 452 | dev_err(dev, "%s[%d] (PIO) request interrupt failed\n", |
389 | 453 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | |
390 | dev_dbg(dev, "%s (PIO) is probed\n", rsnd_mod_name(mod)); | 454 | else |
455 | dev_dbg(dev, "%s[%d] (PIO) is probed\n", | ||
456 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
391 | 457 | ||
392 | return ret; | 458 | return ret; |
393 | } | 459 | } |
394 | 460 | ||
395 | static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | ||
396 | struct rsnd_dai *rdai) | ||
397 | { | ||
398 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
399 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
400 | |||
401 | /* enable PIO IRQ */ | ||
402 | ssi->cr_etc = UIEN | OIEN | DIEN; | ||
403 | |||
404 | rsnd_src_ssiu_start(mod, rdai, 0); | ||
405 | |||
406 | rsnd_src_enable_ssi_irq(mod, rdai); | ||
407 | |||
408 | rsnd_ssi_hw_start(ssi, rdai, io); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, | ||
414 | struct rsnd_dai *rdai) | ||
415 | { | ||
416 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
417 | |||
418 | ssi->cr_etc = 0; | ||
419 | |||
420 | rsnd_ssi_hw_stop(ssi, rdai); | ||
421 | |||
422 | rsnd_src_ssiu_stop(mod, rdai, 0); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | 461 | static struct rsnd_mod_ops rsnd_ssi_pio_ops = { |
428 | .name = SSI_NAME, | 462 | .name = SSI_NAME, |
429 | .probe = rsnd_ssi_pio_probe, | 463 | .probe = rsnd_ssi_pio_probe, |
430 | .init = rsnd_ssi_init, | 464 | .init = rsnd_ssi_init, |
431 | .quit = rsnd_ssi_quit, | 465 | .quit = rsnd_ssi_quit, |
432 | .start = rsnd_ssi_pio_start, | 466 | .start = rsnd_ssi_start, |
433 | .stop = rsnd_ssi_pio_stop, | 467 | .stop = rsnd_ssi_stop, |
434 | }; | 468 | }; |
435 | 469 | ||
436 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | 470 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, |
@@ -442,15 +476,28 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | |||
442 | int dma_id = ssi->info->dma_id; | 476 | int dma_id = ssi->info->dma_id; |
443 | int ret; | 477 | int ret; |
444 | 478 | ||
479 | ret = devm_request_irq(dev, ssi->info->irq, | ||
480 | rsnd_ssi_interrupt, | ||
481 | IRQF_SHARED, | ||
482 | dev_name(dev), ssi); | ||
483 | if (ret) | ||
484 | goto rsnd_ssi_dma_probe_fail; | ||
485 | |||
445 | ret = rsnd_dma_init( | 486 | ret = rsnd_dma_init( |
446 | priv, rsnd_mod_to_dma(mod), | 487 | priv, rsnd_mod_to_dma(mod), |
447 | rsnd_info_is_playback(priv, ssi), | 488 | rsnd_info_is_playback(priv, ssi), |
448 | dma_id); | 489 | dma_id); |
490 | if (ret) | ||
491 | goto rsnd_ssi_dma_probe_fail; | ||
449 | 492 | ||
450 | if (ret < 0) | 493 | dev_dbg(dev, "%s[%d] (DMA) is probed\n", |
451 | dev_err(dev, "SSI DMA failed\n"); | 494 | rsnd_mod_name(mod), rsnd_mod_id(mod)); |
495 | |||
496 | return ret; | ||
452 | 497 | ||
453 | dev_dbg(dev, "%s (DMA) is probed\n", rsnd_mod_name(mod)); | 498 | rsnd_ssi_dma_probe_fail: |
499 | dev_err(dev, "%s[%d] (DMA) is failed\n", | ||
500 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
454 | 501 | ||
455 | return ret; | 502 | return ret; |
456 | } | 503 | } |
@@ -458,30 +505,48 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | |||
458 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, | 505 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, |
459 | struct rsnd_dai *rdai) | 506 | struct rsnd_dai *rdai) |
460 | { | 507 | { |
508 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
509 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
510 | struct device *dev = rsnd_priv_to_dev(priv); | ||
511 | int irq = ssi->info->irq; | ||
512 | |||
461 | rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); | 513 | rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); |
462 | 514 | ||
515 | /* PIO will request IRQ again */ | ||
516 | devm_free_irq(dev, irq, ssi); | ||
517 | |||
463 | return 0; | 518 | return 0; |
464 | } | 519 | } |
465 | 520 | ||
466 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | 521 | static int rsnd_ssi_fallback(struct rsnd_mod *mod, |
467 | struct rsnd_dai *rdai) | 522 | struct rsnd_dai *rdai) |
468 | { | 523 | { |
469 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 524 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
470 | struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod); | 525 | struct device *dev = rsnd_priv_to_dev(priv); |
471 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
472 | 526 | ||
473 | /* enable DMA transfer */ | 527 | /* |
474 | ssi->cr_etc = DMEN; | 528 | * fallback to PIO |
529 | * | ||
530 | * SSI .probe might be called again. | ||
531 | * see | ||
532 | * rsnd_rdai_continuance_probe() | ||
533 | */ | ||
534 | mod->ops = &rsnd_ssi_pio_ops; | ||
475 | 535 | ||
476 | rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod)); | 536 | dev_info(dev, "%s[%d] fallback to PIO mode\n", |
537 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
477 | 538 | ||
478 | rsnd_dma_start(dma); | 539 | return 0; |
540 | } | ||
479 | 541 | ||
480 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); | 542 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, |
543 | struct rsnd_dai *rdai) | ||
544 | { | ||
545 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | ||
481 | 546 | ||
482 | /* enable WS continue */ | 547 | rsnd_ssi_start(mod, rdai); |
483 | if (rsnd_dai_is_clk_master(rdai)) | 548 | |
484 | rsnd_mod_write(&ssi->mod, SSIWSR, CONT); | 549 | rsnd_dma_start(dma); |
485 | 550 | ||
486 | return 0; | 551 | return 0; |
487 | } | 552 | } |
@@ -489,18 +554,11 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | |||
489 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | 554 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, |
490 | struct rsnd_dai *rdai) | 555 | struct rsnd_dai *rdai) |
491 | { | 556 | { |
492 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 557 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
493 | struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod); | ||
494 | |||
495 | ssi->cr_etc = 0; | ||
496 | |||
497 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); | ||
498 | |||
499 | rsnd_ssi_hw_stop(ssi, rdai); | ||
500 | 558 | ||
501 | rsnd_dma_stop(dma); | 559 | rsnd_dma_stop(dma); |
502 | 560 | ||
503 | rsnd_src_ssiu_stop(mod, rdai, 1); | 561 | rsnd_ssi_stop(mod, rdai); |
504 | 562 | ||
505 | return 0; | 563 | return 0; |
506 | } | 564 | } |
@@ -519,8 +577,15 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | |||
519 | .quit = rsnd_ssi_quit, | 577 | .quit = rsnd_ssi_quit, |
520 | .start = rsnd_ssi_dma_start, | 578 | .start = rsnd_ssi_dma_start, |
521 | .stop = rsnd_ssi_dma_stop, | 579 | .stop = rsnd_ssi_dma_stop, |
580 | .fallback = rsnd_ssi_fallback, | ||
522 | }; | 581 | }; |
523 | 582 | ||
583 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) | ||
584 | { | ||
585 | return mod->ops == &rsnd_ssi_dma_ops; | ||
586 | } | ||
587 | |||
588 | |||
524 | /* | 589 | /* |
525 | * Non SSI | 590 | * Non SSI |
526 | */ | 591 | */ |
@@ -614,7 +679,7 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev, | |||
614 | /* | 679 | /* |
615 | * irq | 680 | * irq |
616 | */ | 681 | */ |
617 | ssi_info->pio_irq = irq_of_parse_and_map(np, 0); | 682 | ssi_info->irq = irq_of_parse_and_map(np, 0); |
618 | 683 | ||
619 | /* | 684 | /* |
620 | * DMA | 685 | * DMA |