aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-05-21 20:58:55 -0400
committerTakashi Iwai <tiwai@suse.de>2012-05-21 20:58:55 -0400
commit85e184e4c3cd3e2285ceab91ff8f0cac094e8a85 (patch)
tree1c1cf2d82a62bf0bef4ee390f578dcec35f4b427
parent382e6a859e6622de0aa62c01976ae8ebd90e986d (diff)
parent766812e6d5e2e23be1e212cf84902d5e834dd865 (diff)
Merge tag 'asoc-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Last minute updates These are all new code, they've been in -next already so should be OK for merge this time round. I'd been planning to send a pull request today after they'd had a bit of exposure there to make sure breakage didn't propagate into your tree.
-rw-r--r--Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt54
-rw-r--r--include/sound/sh_fsi.h6
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/omap-hdmi.c69
-rw-r--r--sound/soc/omap/Kconfig1
-rw-r--r--sound/soc/sh/fsi.c224
-rw-r--r--sound/soc/tegra/Kconfig10
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra_wm8753.c224
10 files changed, 529 insertions, 67 deletions
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt b/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt
new file mode 100644
index 000000000000..c4dd39ce6165
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt
@@ -0,0 +1,54 @@
1NVIDIA Tegra audio complex
2
3Required properties:
4- compatible : "nvidia,tegra-audio-wm8753"
5- nvidia,model : The user-visible name of this sound complex.
6- nvidia,audio-routing : A list of the connections between audio components.
7 Each entry is a pair of strings, the first being the connection's sink,
8 the second being the connection's source. Valid names for sources and
9 sinks are the WM8753's pins, and the jacks on the board:
10
11 WM8753 pins:
12
13 * LOUT1
14 * LOUT2
15 * ROUT1
16 * ROUT2
17 * MONO1
18 * MONO2
19 * OUT3
20 * OUT4
21 * LINE1
22 * LINE2
23 * RXP
24 * RXN
25 * ACIN
26 * ACOP
27 * MIC1N
28 * MIC1
29 * MIC2N
30 * MIC2
31 * Mic Bias
32
33 Board connectors:
34
35 * Headphone Jack
36 * Mic Jack
37
38- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
39- nvidia,audio-codec : The phandle of the WM8753 audio codec
40Example:
41
42sound {
43 compatible = "nvidia,tegra-audio-wm8753-whistler",
44 "nvidia,tegra-audio-wm8753"
45 nvidia,model = "tegra-wm8753-harmony";
46
47 nvidia,audio-routing =
48 "Headphone Jack", "LOUT1",
49 "Headphone Jack", "ROUT1";
50
51 nvidia,i2s-controller = <&i2s1>;
52 nvidia,audio-codec = <&wm8753>;
53};
54
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 956e30e89ea8..906010344dd7 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -21,10 +21,11 @@
21/* 21/*
22 * flags format 22 * flags format
23 * 23 *
24 * 0x000000BA 24 * 0x00000CBA
25 * 25 *
26 * A: inversion 26 * A: inversion
27 * B: format mode 27 * B: format mode
28 * C: chip specific
28 */ 29 */
29 30
30/* A: clock inversion */ 31/* A: clock inversion */
@@ -39,6 +40,9 @@
39#define SH_FSI_FMT_DAI (0 << 4) 40#define SH_FSI_FMT_DAI (0 << 4)
40#define SH_FSI_FMT_SPDIF (1 << 4) 41#define SH_FSI_FMT_SPDIF (1 << 4)
41 42
43/* C: chip specific */
44#define SH_FSI_OPTION_MASK 0x00000F00
45#define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */
42 46
43/* 47/*
44 * set_rate return value 48 * set_rate return value
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 22c686444633..1e1613a438dd 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -46,6 +46,7 @@ config SND_SOC_ALL_CODECS
46 select SND_SOC_MAX9877 if I2C 46 select SND_SOC_MAX9877 if I2C
47 select SND_SOC_MC13783 if MFD_MC13XXX 47 select SND_SOC_MC13783 if MFD_MC13XXX
48 select SND_SOC_ML26124 if I2C 48 select SND_SOC_ML26124 if I2C
49 select SND_SOC_OMAP_HDMI_CODEC if OMAP4_DSS_HDMI
49 select SND_SOC_PCM3008 50 select SND_SOC_PCM3008
50 select SND_SOC_RT5631 if I2C 51 select SND_SOC_RT5631 if I2C
51 select SND_SOC_SGTL5000 if I2C 52 select SND_SOC_SGTL5000 if I2C
@@ -236,6 +237,9 @@ config SND_SOC_MAX98095
236config SND_SOC_MAX9850 237config SND_SOC_MAX9850
237 tristate 238 tristate
238 239
240config SND_SOC_OMAP_HDMI_CODEC
241 tristate
242
239config SND_SOC_PCM3008 243config SND_SOC_PCM3008
240 tristate 244 tristate
241 245
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a9663e9c375b..fc27fec39487 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -33,6 +33,7 @@ snd-soc-max98095-objs := max98095.o
33snd-soc-max9850-objs := max9850.o 33snd-soc-max9850-objs := max9850.o
34snd-soc-mc13783-objs := mc13783.o 34snd-soc-mc13783-objs := mc13783.o
35snd-soc-ml26124-objs := ml26124.o 35snd-soc-ml26124-objs := ml26124.o
36snd-soc-omap-hdmi-codec-objs := omap-hdmi.o
36snd-soc-pcm3008-objs := pcm3008.o 37snd-soc-pcm3008-objs := pcm3008.o
37snd-soc-rt5631-objs := rt5631.o 38snd-soc-rt5631-objs := rt5631.o
38snd-soc-sgtl5000-objs := sgtl5000.o 39snd-soc-sgtl5000-objs := sgtl5000.o
@@ -143,6 +144,7 @@ obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
143obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o 144obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
144obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 145obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
145obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 146obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
147obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o
146obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 148obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
147obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o 149obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
148obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o 150obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
diff --git a/sound/soc/codecs/omap-hdmi.c b/sound/soc/codecs/omap-hdmi.c
new file mode 100644
index 000000000000..1bf5c74f5f96
--- /dev/null
+++ b/sound/soc/codecs/omap-hdmi.c
@@ -0,0 +1,69 @@
1/*
2 * ALSA SoC codec driver for HDMI audio on OMAP processors.
3 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
4 * Author: Ricardo Neri <ricardo.neri@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21#include <linux/module.h>
22#include <sound/soc.h>
23
24#define DRV_NAME "hdmi-audio-codec"
25
26static struct snd_soc_codec_driver omap_hdmi_codec;
27
28static struct snd_soc_dai_driver omap_hdmi_codec_dai = {
29 .name = "omap-hdmi-hifi",
30 .playback = {
31 .channels_min = 2,
32 .channels_max = 8,
33 .rates = SNDRV_PCM_RATE_32000 |
34 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
35 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
36 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
37 .formats = SNDRV_PCM_FMTBIT_S16_LE |
38 SNDRV_PCM_FMTBIT_S24_LE,
39 },
40};
41
42static __devinit int omap_hdmi_codec_probe(struct platform_device *pdev)
43{
44 return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec,
45 &omap_hdmi_codec_dai, 1);
46}
47
48static __devexit int omap_hdmi_codec_remove(struct platform_device *pdev)
49{
50 snd_soc_unregister_codec(&pdev->dev);
51 return 0;
52}
53
54static struct platform_driver omap_hdmi_codec_driver = {
55 .driver = {
56 .name = DRV_NAME,
57 .owner = THIS_MODULE,
58 },
59
60 .probe = omap_hdmi_codec_probe,
61 .remove = __devexit_p(omap_hdmi_codec_remove),
62};
63
64module_platform_driver(omap_hdmi_codec_driver);
65
66MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
67MODULE_DESCRIPTION("ASoC OMAP HDMI codec driver");
68MODULE_LICENSE("GPL");
69MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index deafbfaacdbf..9ccfa5e1c11b 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -113,6 +113,7 @@ config SND_OMAP_SOC_OMAP4_HDMI
113 tristate "SoC Audio support for Texas Instruments OMAP4 HDMI" 113 tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
114 depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4 114 depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4
115 select SND_OMAP_SOC_HDMI 115 select SND_OMAP_SOC_HDMI
116 select SND_SOC_OMAP_HDMI_CODEC
116 help 117 help
117 Say Y if you want to add support for SoC HDMI audio on Texas Instruments 118 Say Y if you want to add support for SoC HDMI audio on Texas Instruments
118 OMAP4 chips 119 OMAP4 chips
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 74ed2dffbffd..7cee22515d9d 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -132,6 +132,25 @@
132typedef int (*set_rate_func)(struct device *dev, int rate, int enable); 132typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
133 133
134/* 134/*
135 * bus options
136 *
137 * 0x000000BA
138 *
139 * A : sample widtht 16bit setting
140 * B : sample widtht 24bit setting
141 */
142
143#define SHIFT_16DATA 0
144#define SHIFT_24DATA 4
145
146#define PACKAGE_24BITBUS_BACK 0
147#define PACKAGE_24BITBUS_FRONT 1
148#define PACKAGE_16BITBUS_STREAM 2
149
150#define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA)
151#define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF)
152
153/*
135 * FSI driver use below type name for variable 154 * FSI driver use below type name for variable
136 * 155 *
137 * xxx_num : number of data 156 * xxx_num : number of data
@@ -189,6 +208,11 @@ struct fsi_stream {
189 int oerr_num; 208 int oerr_num;
190 209
191 /* 210 /*
211 * bus options
212 */
213 u32 bus_option;
214
215 /*
192 * thse are initialized by fsi_handler_init() 216 * thse are initialized by fsi_handler_init()
193 */ 217 */
194 struct fsi_stream_handler *handler; 218 struct fsi_stream_handler *handler;
@@ -211,8 +235,7 @@ struct fsi_priv {
211 struct fsi_stream playback; 235 struct fsi_stream playback;
212 struct fsi_stream capture; 236 struct fsi_stream capture;
213 237
214 u32 do_fmt; 238 u32 fmt;
215 u32 di_fmt;
216 239
217 int chan_num:16; 240 int chan_num:16;
218 int clk_master:1; 241 int clk_master:1;
@@ -321,6 +344,10 @@ static void _fsi_master_mask_set(struct fsi_master *master,
321/* 344/*
322 * basic function 345 * basic function
323 */ 346 */
347static int fsi_version(struct fsi_master *master)
348{
349 return master->core->ver;
350}
324 351
325static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) 352static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
326{ 353{
@@ -495,6 +522,7 @@ static void fsi_stream_init(struct fsi_priv *fsi,
495 io->period_samples = fsi_frame2sample(fsi, runtime->period_size); 522 io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
496 io->period_pos = 0; 523 io->period_pos = 0;
497 io->sample_width = samples_to_bytes(runtime, 1); 524 io->sample_width = samples_to_bytes(runtime, 1);
525 io->bus_option = 0;
498 io->oerr_num = -1; /* ignore 1st err */ 526 io->oerr_num = -1; /* ignore 1st err */
499 io->uerr_num = -1; /* ignore 1st err */ 527 io->uerr_num = -1; /* ignore 1st err */
500 fsi_stream_handler_call(io, init, fsi, io); 528 fsi_stream_handler_call(io, init, fsi, io);
@@ -522,6 +550,7 @@ static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
522 io->period_samples = 0; 550 io->period_samples = 0;
523 io->period_pos = 0; 551 io->period_pos = 0;
524 io->sample_width = 0; 552 io->sample_width = 0;
553 io->bus_option = 0;
525 io->oerr_num = 0; 554 io->oerr_num = 0;
526 io->uerr_num = 0; 555 io->uerr_num = 0;
527 spin_unlock_irqrestore(&master->lock, flags); 556 spin_unlock_irqrestore(&master->lock, flags);
@@ -581,6 +610,53 @@ static int fsi_stream_remove(struct fsi_priv *fsi)
581} 610}
582 611
583/* 612/*
613 * format/bus/dma setting
614 */
615static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io,
616 u32 bus, struct device *dev)
617{
618 struct fsi_master *master = fsi_get_master(fsi);
619 int is_play = fsi_stream_is_play(fsi, io);
620 u32 fmt = fsi->fmt;
621
622 if (fsi_version(master) >= 2) {
623 u32 dma = 0;
624
625 /*
626 * FSI2 needs DMA/Bus setting
627 */
628 switch (bus) {
629 case PACKAGE_24BITBUS_FRONT:
630 fmt |= CR_BWS_24;
631 dma |= VDMD_FRONT;
632 dev_dbg(dev, "24bit bus / package in front\n");
633 break;
634 case PACKAGE_16BITBUS_STREAM:
635 fmt |= CR_BWS_16;
636 dma |= VDMD_STREAM;
637 dev_dbg(dev, "16bit bus / stream mode\n");
638 break;
639 case PACKAGE_24BITBUS_BACK:
640 default:
641 fmt |= CR_BWS_24;
642 dma |= VDMD_BACK;
643 dev_dbg(dev, "24bit bus / package in back\n");
644 break;
645 }
646
647 if (is_play)
648 fsi_reg_write(fsi, OUT_DMAC, dma);
649 else
650 fsi_reg_write(fsi, IN_DMAC, dma);
651 }
652
653 if (is_play)
654 fsi_reg_write(fsi, DO_FMT, fmt);
655 else
656 fsi_reg_write(fsi, DI_FMT, fmt);
657}
658
659/*
584 * irq function 660 * irq function
585 */ 661 */
586 662
@@ -629,11 +705,6 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
629 struct fsi_master *master = fsi_get_master(fsi); 705 struct fsi_master *master = fsi_get_master(fsi);
630 u32 mask, val; 706 u32 mask, val;
631 707
632 if (master->core->ver < 2) {
633 pr_err("fsi: register access err (%s)\n", __func__);
634 return;
635 }
636
637 mask = BP | SE; 708 mask = BP | SE;
638 val = enable ? mask : 0; 709 val = enable ? mask : 0;
639 710
@@ -648,9 +719,7 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
648static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, 719static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
649 long rate, int enable) 720 long rate, int enable)
650{ 721{
651 struct fsi_master *master = fsi_get_master(fsi);
652 set_rate_func set_rate = fsi_get_info_set_rate(fsi); 722 set_rate_func set_rate = fsi_get_info_set_rate(fsi);
653 int fsi_ver = master->core->ver;
654 int ret; 723 int ret;
655 724
656 if (!set_rate) 725 if (!set_rate)
@@ -682,10 +751,7 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
682 data |= (0x3 << 12); 751 data |= (0x3 << 12);
683 break; 752 break;
684 case SH_FSI_ACKMD_32: 753 case SH_FSI_ACKMD_32:
685 if (fsi_ver < 2) 754 data |= (0x4 << 12);
686 dev_err(dev, "unsupported ACKMD\n");
687 else
688 data |= (0x4 << 12);
689 break; 755 break;
690 } 756 }
691 757
@@ -708,10 +774,7 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
708 data |= (0x4 << 8); 774 data |= (0x4 << 8);
709 break; 775 break;
710 case SH_FSI_BPFMD_16: 776 case SH_FSI_BPFMD_16:
711 if (fsi_ver < 2) 777 data |= (0x7 << 8);
712 dev_err(dev, "unsupported ACKMD\n");
713 else
714 data |= (0x7 << 8);
715 break; 778 break;
716 } 779 }
717 780
@@ -728,11 +791,26 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
728 */ 791 */
729static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples) 792static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
730{ 793{
731 u16 *buf = (u16 *)_buf; 794 u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
732 int i; 795 int i;
733 796
734 for (i = 0; i < samples; i++) 797 if (enable_stream) {
735 fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8)); 798 /*
799 * stream mode
800 * see
801 * fsi_pio_push_init()
802 */
803 u32 *buf = (u32 *)_buf;
804
805 for (i = 0; i < samples / 2; i++)
806 fsi_reg_write(fsi, DODT, buf[i]);
807 } else {
808 /* normal mode */
809 u16 *buf = (u16 *)_buf;
810
811 for (i = 0; i < samples; i++)
812 fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
813 }
736} 814}
737 815
738static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples) 816static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
@@ -872,12 +950,44 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
872 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); 950 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
873} 951}
874 952
953static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
954{
955 u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
956
957 /*
958 * we can use 16bit stream mode
959 * when "playback" and "16bit data"
960 * and platform allows "stream mode"
961 * see
962 * fsi_pio_push16()
963 */
964 if (enable_stream)
965 io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
966 BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
967 else
968 io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
969 BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
970 return 0;
971}
972
973static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io)
974{
975 /*
976 * always 24bit bus, package back when "capture"
977 */
978 io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
979 BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
980 return 0;
981}
982
875static struct fsi_stream_handler fsi_pio_push_handler = { 983static struct fsi_stream_handler fsi_pio_push_handler = {
984 .init = fsi_pio_push_init,
876 .transfer = fsi_pio_push, 985 .transfer = fsi_pio_push,
877 .start_stop = fsi_pio_start_stop, 986 .start_stop = fsi_pio_start_stop,
878}; 987};
879 988
880static struct fsi_stream_handler fsi_pio_pop_handler = { 989static struct fsi_stream_handler fsi_pio_pop_handler = {
990 .init = fsi_pio_pop_init,
881 .transfer = fsi_pio_pop, 991 .transfer = fsi_pio_pop,
882 .start_stop = fsi_pio_start_stop, 992 .start_stop = fsi_pio_start_stop,
883}; 993};
@@ -919,6 +1029,13 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
919 enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? 1029 enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
920 DMA_TO_DEVICE : DMA_FROM_DEVICE; 1030 DMA_TO_DEVICE : DMA_FROM_DEVICE;
921 1031
1032 /*
1033 * 24bit data : 24bit bus / package in back
1034 * 16bit data : 16bit bus / stream mode
1035 */
1036 io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
1037 BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
1038
922 io->dma = dma_map_single(dai->dev, runtime->dma_area, 1039 io->dma = dma_map_single(dai->dev, runtime->dma_area,
923 snd_pcm_lib_buffer_bytes(io->substream), dir); 1040 snd_pcm_lib_buffer_bytes(io->substream), dir);
924 return 0; 1041 return 0;
@@ -1055,25 +1172,9 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
1055static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, 1172static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
1056 int start) 1173 int start)
1057{ 1174{
1058 u32 bws; 1175 u32 enable = start ? DMA_ON : 0;
1059 u32 dma;
1060 1176
1061 switch (io->sample_width * start) { 1177 fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
1062 case 2:
1063 bws = CR_BWS_16;
1064 dma = VDMD_STREAM | DMA_ON;
1065 break;
1066 case 4:
1067 bws = CR_BWS_24;
1068 dma = VDMD_BACK | DMA_ON;
1069 break;
1070 default:
1071 bws = 0;
1072 dma = 0;
1073 }
1074
1075 fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
1076 fsi_reg_write(fsi, OUT_DMAC, dma);
1077} 1178}
1078 1179
1079static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) 1180static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
@@ -1176,8 +1277,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
1176 struct fsi_stream *io, 1277 struct fsi_stream *io,
1177 struct device *dev) 1278 struct device *dev)
1178{ 1279{
1179 struct fsi_master *master = fsi_get_master(fsi);
1180 int fsi_ver = master->core->ver;
1181 u32 flags = fsi_get_info_flags(fsi); 1280 u32 flags = fsi_get_info_flags(fsi);
1182 u32 data = 0; 1281 u32 data = 0;
1183 1282
@@ -1200,10 +1299,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
1200 1299
1201 fsi_reg_write(fsi, CKG2, data); 1300 fsi_reg_write(fsi, CKG2, data);
1202 1301
1203 /* set format */
1204 fsi_reg_write(fsi, DO_FMT, fsi->do_fmt);
1205 fsi_reg_write(fsi, DI_FMT, fsi->di_fmt);
1206
1207 /* spdif ? */ 1302 /* spdif ? */
1208 if (fsi_is_spdif(fsi)) { 1303 if (fsi_is_spdif(fsi)) {
1209 fsi_spdif_clk_ctrl(fsi, 1); 1304 fsi_spdif_clk_ctrl(fsi, 1);
@@ -1211,15 +1306,18 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
1211 } 1306 }
1212 1307
1213 /* 1308 /*
1214 * FIXME 1309 * get bus settings
1215 *
1216 * FSI driver assumed that data package is in-back.
1217 * FSI2 chip can select it.
1218 */ 1310 */
1219 if (fsi_ver >= 2) { 1311 data = 0;
1220 fsi_reg_write(fsi, OUT_DMAC, (1 << 4)); 1312 switch (io->sample_width) {
1221 fsi_reg_write(fsi, IN_DMAC, (1 << 4)); 1313 case 2:
1314 data = BUSOP_GET(16, io->bus_option);
1315 break;
1316 case 4:
1317 data = BUSOP_GET(24, io->bus_option);
1318 break;
1222 } 1319 }
1320 fsi_format_bus_setup(fsi, io, data, dev);
1223 1321
1224 /* irq clear */ 1322 /* irq clear */
1225 fsi_irq_disable(fsi, io); 1323 fsi_irq_disable(fsi, io);
@@ -1243,7 +1341,9 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
1243{ 1341{
1244 struct fsi_priv *fsi = fsi_get_priv(substream); 1342 struct fsi_priv *fsi = fsi_get_priv(substream);
1245 1343
1246 return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev); 1344 fsi->rate = 0;
1345
1346 return 0;
1247} 1347}
1248 1348
1249static void fsi_dai_shutdown(struct snd_pcm_substream *substream, 1349static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
@@ -1251,7 +1351,6 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
1251{ 1351{
1252 struct fsi_priv *fsi = fsi_get_priv(substream); 1352 struct fsi_priv *fsi = fsi_get_priv(substream);
1253 1353
1254 fsi_hw_shutdown(fsi, dai->dev);
1255 fsi->rate = 0; 1354 fsi->rate = 0;
1256} 1355}
1257 1356
@@ -1265,11 +1364,13 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
1265 switch (cmd) { 1364 switch (cmd) {
1266 case SNDRV_PCM_TRIGGER_START: 1365 case SNDRV_PCM_TRIGGER_START:
1267 fsi_stream_init(fsi, io, substream); 1366 fsi_stream_init(fsi, io, substream);
1367 fsi_hw_startup(fsi, io, dai->dev);
1268 ret = fsi_stream_transfer(io); 1368 ret = fsi_stream_transfer(io);
1269 if (0 == ret) 1369 if (0 == ret)
1270 fsi_stream_start(fsi, io); 1370 fsi_stream_start(fsi, io);
1271 break; 1371 break;
1272 case SNDRV_PCM_TRIGGER_STOP: 1372 case SNDRV_PCM_TRIGGER_STOP:
1373 fsi_hw_shutdown(fsi, dai->dev);
1273 fsi_stream_stop(fsi, io); 1374 fsi_stream_stop(fsi, io);
1274 fsi_stream_quit(fsi, io); 1375 fsi_stream_quit(fsi, io);
1275 break; 1376 break;
@@ -1280,42 +1381,33 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
1280 1381
1281static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt) 1382static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
1282{ 1383{
1283 u32 data = 0;
1284
1285 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 1384 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1286 case SND_SOC_DAIFMT_I2S: 1385 case SND_SOC_DAIFMT_I2S:
1287 data = CR_I2S; 1386 fsi->fmt = CR_I2S;
1288 fsi->chan_num = 2; 1387 fsi->chan_num = 2;
1289 break; 1388 break;
1290 case SND_SOC_DAIFMT_LEFT_J: 1389 case SND_SOC_DAIFMT_LEFT_J:
1291 data = CR_PCM; 1390 fsi->fmt = CR_PCM;
1292 fsi->chan_num = 2; 1391 fsi->chan_num = 2;
1293 break; 1392 break;
1294 default: 1393 default:
1295 return -EINVAL; 1394 return -EINVAL;
1296 } 1395 }
1297 1396
1298 fsi->do_fmt = data;
1299 fsi->di_fmt = data;
1300
1301 return 0; 1397 return 0;
1302} 1398}
1303 1399
1304static int fsi_set_fmt_spdif(struct fsi_priv *fsi) 1400static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
1305{ 1401{
1306 struct fsi_master *master = fsi_get_master(fsi); 1402 struct fsi_master *master = fsi_get_master(fsi);
1307 u32 data = 0;
1308 1403
1309 if (master->core->ver < 2) 1404 if (fsi_version(master) < 2)
1310 return -EINVAL; 1405 return -EINVAL;
1311 1406
1312 data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; 1407 fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
1313 fsi->chan_num = 2; 1408 fsi->chan_num = 2;
1314 fsi->spdif = 1; 1409 fsi->spdif = 1;
1315 1410
1316 fsi->do_fmt = data;
1317 fsi->di_fmt = data;
1318
1319 return 0; 1411 return 0;
1320} 1412}
1321 1413
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 5331c61faf01..c1c8e955f4d3 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -48,6 +48,16 @@ config SND_SOC_TEGRA30_I2S
48 Tegra30 I2S interface. You will also need to select the individual 48 Tegra30 I2S interface. You will also need to select the individual
49 machine drivers to support below. 49 machine drivers to support below.
50 50
51config SND_SOC_TEGRA_WM8753
52 tristate "SoC Audio support for Tegra boards using a WM8753 codec"
53 depends on SND_SOC_TEGRA && I2C
54 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
55 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
56 select SND_SOC_WM8753
57 help
58 Say Y or M here if you want to add support for SoC audio on Tegra
59 boards using the WM8753 codec, such as Whistler.
60
51config MACH_HAS_SND_SOC_TEGRA_WM8903 61config MACH_HAS_SND_SOC_TEGRA_WM8903
52 bool 62 bool
53 help 63 help
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 98704b48b62a..391e78a34c06 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -16,10 +16,12 @@ obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o
16obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o 16obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
17 17
18# Tegra machine Support 18# Tegra machine Support
19snd-soc-tegra-wm8753-objs := tegra_wm8753.o
19snd-soc-tegra-wm8903-objs := tegra_wm8903.o 20snd-soc-tegra-wm8903-objs := tegra_wm8903.o
20snd-soc-tegra-trimslice-objs := trimslice.o 21snd-soc-tegra-trimslice-objs := trimslice.o
21snd-soc-tegra-alc5632-objs := tegra_alc5632.o 22snd-soc-tegra-alc5632-objs := tegra_alc5632.o
22 23
24obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
23obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o 25obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
24obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o 26obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
25obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o 27obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
new file mode 100644
index 000000000000..4e77026807a2
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -0,0 +1,224 @@
1/*
2 * tegra_wm8753.c - Tegra machine ASoC driver for boards using WM8753 codec.
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010-2012 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
10 *
11 * Copyright 2007 Wolfson Microelectronics PLC.
12 * Author: Graeme Gregory
13 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <asm/mach-types.h>
32
33#include <linux/module.h>
34#include <linux/platform_device.h>
35#include <linux/slab.h>
36#include <linux/gpio.h>
37#include <linux/of_gpio.h>
38
39#include <sound/core.h>
40#include <sound/jack.h>
41#include <sound/pcm.h>
42#include <sound/pcm_params.h>
43#include <sound/soc.h>
44
45#include "../codecs/wm8753.h"
46
47#include "tegra_asoc_utils.h"
48
49#define DRV_NAME "tegra-snd-wm8753"
50
51struct tegra_wm8753 {
52 struct tegra_asoc_utils_data util_data;
53};
54
55static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
56 struct snd_pcm_hw_params *params)
57{
58 struct snd_soc_pcm_runtime *rtd = substream->private_data;
59 struct snd_soc_dai *codec_dai = rtd->codec_dai;
60 struct snd_soc_codec *codec = rtd->codec;
61 struct snd_soc_card *card = codec->card;
62 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
63 int srate, mclk;
64 int err;
65
66 srate = params_rate(params);
67 switch (srate) {
68 case 11025:
69 case 22050:
70 case 44100:
71 case 88200:
72 mclk = 11289600;
73 break;
74 default:
75 mclk = 12288000;
76 break;
77 }
78
79 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
80 if (err < 0) {
81 dev_err(card->dev, "Can't configure clocks\n");
82 return err;
83 }
84
85 err = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, mclk,
86 SND_SOC_CLOCK_IN);
87 if (err < 0) {
88 dev_err(card->dev, "codec_dai clock not set\n");
89 return err;
90 }
91
92 return 0;
93}
94
95static struct snd_soc_ops tegra_wm8753_ops = {
96 .hw_params = tegra_wm8753_hw_params,
97};
98
99static const struct snd_soc_dapm_widget tegra_wm8753_dapm_widgets[] = {
100 SND_SOC_DAPM_HP("Headphone Jack", NULL),
101 SND_SOC_DAPM_MIC("Mic Jack", NULL),
102};
103
104static struct snd_soc_dai_link tegra_wm8753_dai = {
105 .name = "WM8753",
106 .stream_name = "WM8753 PCM",
107 .codec_dai_name = "wm8753-hifi",
108 .ops = &tegra_wm8753_ops,
109 .dai_fmt = SND_SOC_DAIFMT_I2S |
110 SND_SOC_DAIFMT_NB_NF |
111 SND_SOC_DAIFMT_CBS_CFS,
112};
113
114static struct snd_soc_card snd_soc_tegra_wm8753 = {
115 .name = "tegra-wm8753",
116 .owner = THIS_MODULE,
117 .dai_link = &tegra_wm8753_dai,
118 .num_links = 1,
119
120 .dapm_widgets = tegra_wm8753_dapm_widgets,
121 .num_dapm_widgets = ARRAY_SIZE(tegra_wm8753_dapm_widgets),
122 .fully_routed = true,
123};
124
125static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
126{
127 struct snd_soc_card *card = &snd_soc_tegra_wm8753;
128 struct tegra_wm8753 *machine;
129 int ret;
130
131 machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8753),
132 GFP_KERNEL);
133 if (!machine) {
134 dev_err(&pdev->dev, "Can't allocate tegra_wm8753 struct\n");
135 ret = -ENOMEM;
136 goto err;
137 }
138
139 card->dev = &pdev->dev;
140 platform_set_drvdata(pdev, card);
141 snd_soc_card_set_drvdata(card, machine);
142
143 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
144 if (ret)
145 goto err;
146
147 ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
148 if (ret)
149 goto err;
150
151 tegra_wm8753_dai.codec_of_node = of_parse_phandle(
152 pdev->dev.of_node, "nvidia,audio-codec", 0);
153 if (!tegra_wm8753_dai.codec_of_node) {
154 dev_err(&pdev->dev,
155 "Property 'nvidia,audio-codec' missing or invalid\n");
156 ret = -EINVAL;
157 goto err;
158 }
159
160 tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle(
161 pdev->dev.of_node, "nvidia,i2s-controller", 0);
162 if (!tegra_wm8753_dai.cpu_dai_of_node) {
163 dev_err(&pdev->dev,
164 "Property 'nvidia,i2s-controller' missing or invalid\n");
165 ret = -EINVAL;
166 goto err;
167 }
168
169 tegra_wm8753_dai.platform_of_node =
170 tegra_wm8753_dai.cpu_dai_of_node;
171
172 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
173 if (ret)
174 goto err;
175
176 ret = snd_soc_register_card(card);
177 if (ret) {
178 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
179 ret);
180 goto err_fini_utils;
181 }
182
183 return 0;
184
185err_fini_utils:
186 tegra_asoc_utils_fini(&machine->util_data);
187err:
188 return ret;
189}
190
191static int __devexit tegra_wm8753_driver_remove(struct platform_device *pdev)
192{
193 struct snd_soc_card *card = platform_get_drvdata(pdev);
194 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
195
196 snd_soc_unregister_card(card);
197
198 tegra_asoc_utils_fini(&machine->util_data);
199
200 return 0;
201}
202
203static const struct of_device_id tegra_wm8753_of_match[] __devinitconst = {
204 { .compatible = "nvidia,tegra-audio-wm8753", },
205 {},
206};
207
208static struct platform_driver tegra_wm8753_driver = {
209 .driver = {
210 .name = DRV_NAME,
211 .owner = THIS_MODULE,
212 .pm = &snd_soc_pm_ops,
213 .of_match_table = tegra_wm8753_of_match,
214 },
215 .probe = tegra_wm8753_driver_probe,
216 .remove = __devexit_p(tegra_wm8753_driver_remove),
217};
218module_platform_driver(tegra_wm8753_driver);
219
220MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
221MODULE_DESCRIPTION("Tegra+WM8753 machine ASoC driver");
222MODULE_LICENSE("GPL");
223MODULE_ALIAS("platform:" DRV_NAME);
224MODULE_DEVICE_TABLE(of, tegra_wm8753_of_match);