diff options
| author | Mark Brown <broonie@linaro.org> | 2013-11-08 05:43:27 -0500 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2013-11-08 05:43:27 -0500 |
| commit | ac97d4e00a8356e61806fe7b223c0b7021908577 (patch) | |
| tree | fb20da2e2689ff1f20cd39d9d11de66be6069461 | |
| parent | 1d697db0ab270ec8eff4021926283fa552790e6d (diff) | |
| parent | ee2f615d6e59cea2b9a415661a7f27caffcb3528 (diff) | |
Merge remote-tracking branch 'asoc/topic/davinci' into asoc-next
| -rw-r--r-- | Documentation/devicetree/bindings/sound/davinci-evm-audio.txt | 42 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt | 41 | ||||
| -rw-r--r-- | include/linux/platform_data/davinci_asp.h | 2 | ||||
| -rw-r--r-- | sound/soc/davinci/Kconfig | 18 | ||||
| -rw-r--r-- | sound/soc/davinci/Makefile | 1 | ||||
| -rw-r--r-- | sound/soc/davinci/davinci-evm.c | 188 | ||||
| -rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 169 | ||||
| -rw-r--r-- | sound/soc/davinci/davinci-mcasp.h | 12 |
8 files changed, 382 insertions, 91 deletions
diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt new file mode 100644 index 000000000000..865178d5cdf3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | * Texas Instruments SoC audio setups with TLV320AIC3X Codec | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx | ||
| 5 | - ti,model : The user-visible name of this sound complex. | ||
| 6 | - ti,audio-codec : The phandle of the TLV320AIC3x audio codec | ||
| 7 | - ti,mcasp-controller : The phandle of the McASP controller | ||
| 8 | - ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec | ||
| 9 | - ti,audio-routing : A list of the connections between audio components. | ||
| 10 | Each entry is a pair of strings, the first being the connection's sink, | ||
| 11 | the second being the connection's source. Valid names for sources and | ||
| 12 | sinks are the codec's pins, and the jacks on the board: | ||
| 13 | |||
| 14 | Board connectors: | ||
| 15 | |||
| 16 | * Headphone Jack | ||
| 17 | * Line Out | ||
| 18 | * Mic Jack | ||
| 19 | * Line In | ||
| 20 | |||
| 21 | |||
| 22 | Example: | ||
| 23 | |||
| 24 | sound { | ||
| 25 | compatible = "ti,da830-evm-audio"; | ||
| 26 | ti,model = "DA830 EVM"; | ||
| 27 | ti,audio-codec = <&tlv320aic3x>; | ||
| 28 | ti,mcasp-controller = <&mcasp1>; | ||
| 29 | ti,codec-clock-rate = <12000000>; | ||
| 30 | ti,audio-routing = | ||
| 31 | "Headphone Jack", "HPLOUT", | ||
| 32 | "Headphone Jack", "HPROUT", | ||
| 33 | "Line Out", "LLOUT", | ||
| 34 | "Line Out", "RLOUT", | ||
| 35 | "MIC3L", "Mic Bias 2V", | ||
| 36 | "MIC3R", "Mic Bias 2V", | ||
| 37 | "Mic Bias 2V", "Mic Jack", | ||
| 38 | "LINE1L", "Line In", | ||
| 39 | "LINE2L", "Line In", | ||
| 40 | "LINE1R", "Line In", | ||
| 41 | "LINE2R", "Line In"; | ||
| 42 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index 374e145c2ef1..ed785b3f67be 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt | |||
| @@ -4,17 +4,25 @@ Required properties: | |||
| 4 | - compatible : | 4 | - compatible : |
| 5 | "ti,dm646x-mcasp-audio" : for DM646x platforms | 5 | "ti,dm646x-mcasp-audio" : for DM646x platforms |
| 6 | "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms | 6 | "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms |
| 7 | "ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx) | 7 | "ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, TI81xx) |
| 8 | |||
| 9 | - reg : Should contain McASP registers offset and length | ||
| 10 | - interrupts : Interrupt number for McASP | ||
| 11 | - op-mode : I2S/DIT ops mode. | ||
| 12 | - tdm-slots : Slots for TDM operation. | ||
| 13 | - num-serializer : Serializers used by McASP. | ||
| 14 | - serial-dir : A list of serializer pin mode. The list number should be equal | ||
| 15 | to "num-serializer" parameter. Each entry is a number indication | ||
| 16 | serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX) | ||
| 17 | 8 | ||
| 9 | - reg : Should contain reg specifiers for the entries in the reg-names property. | ||
| 10 | - reg-names : Should contain: | ||
| 11 | * "mpu" for the main registers (required). For compatibility with | ||
| 12 | existing software, it is recommended this is the first entry. | ||
| 13 | * "dat" for separate data port register access (optional). | ||
| 14 | - op-mode : I2S/DIT ops mode. 0 for I2S mode. 1 for DIT mode used for S/PDIF, | ||
| 15 | IEC60958-1, and AES-3 formats. | ||
| 16 | - tdm-slots : Slots for TDM operation. Indicates number of channels transmitted | ||
| 17 | or received over one serializer. | ||
| 18 | - serial-dir : A list of serializer configuration. Each entry is a number | ||
| 19 | indication for serializer pin direction. | ||
| 20 | (0 - INACTIVE, 1 - TX, 2 - RX) | ||
| 21 | - dmas: two element list of DMA controller phandles and DMA request line | ||
| 22 | ordered pairs. | ||
| 23 | - dma-names: identifier string for each DMA request line in the dmas property. | ||
| 24 | These strings correspond 1:1 with the ordered pairs in dmas. The dma | ||
| 25 | identifiers must be "rx" and "tx". | ||
| 18 | 26 | ||
| 19 | Optional properties: | 27 | Optional properties: |
| 20 | 28 | ||
| @@ -23,18 +31,23 @@ Optional properties: | |||
| 23 | - rx-num-evt : FIFO levels. | 31 | - rx-num-evt : FIFO levels. |
| 24 | - sram-size-playback : size of sram to be allocated during playback | 32 | - sram-size-playback : size of sram to be allocated during playback |
| 25 | - sram-size-capture : size of sram to be allocated during capture | 33 | - sram-size-capture : size of sram to be allocated during capture |
| 34 | - interrupts : Interrupt numbers for McASP, currently not used by the driver | ||
| 35 | - interrupt-names : Known interrupt names are "tx" and "rx" | ||
| 36 | - pinctrl-0: Should specify pin control group used for this controller. | ||
| 37 | - pinctrl-names: Should contain only one value - "default", for more details | ||
| 38 | please refer to pinctrl-bindings.txt | ||
| 39 | |||
| 26 | 40 | ||
| 27 | Example: | 41 | Example: |
| 28 | 42 | ||
| 29 | mcasp0: mcasp0@1d00000 { | 43 | mcasp0: mcasp0@1d00000 { |
| 30 | compatible = "ti,da830-mcasp-audio"; | 44 | compatible = "ti,da830-mcasp-audio"; |
| 31 | #address-cells = <1>; | ||
| 32 | #size-cells = <0>; | ||
| 33 | reg = <0x100000 0x3000>; | 45 | reg = <0x100000 0x3000>; |
| 34 | interrupts = <82 83>; | 46 | reg-names "mpu"; |
| 47 | interrupts = <82>, <83>; | ||
| 48 | interrupts-names = "tx", "rx"; | ||
| 35 | op-mode = <0>; /* MCASP_IIS_MODE */ | 49 | op-mode = <0>; /* MCASP_IIS_MODE */ |
| 36 | tdm-slots = <2>; | 50 | tdm-slots = <2>; |
| 37 | num-serializer = <16>; | ||
| 38 | serial-dir = < | 51 | serial-dir = < |
| 39 | 0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */ | 52 | 0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */ |
| 40 | 0 0 0 0 | 53 | 0 0 0 0 |
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 8db5ae03b6e3..689a856b86f9 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h | |||
| @@ -84,6 +84,8 @@ struct snd_platform_data { | |||
| 84 | u8 version; | 84 | u8 version; |
| 85 | u8 txnumevt; | 85 | u8 txnumevt; |
| 86 | u8 rxnumevt; | 86 | u8 rxnumevt; |
| 87 | int tx_dma_channel; | ||
| 88 | int rx_dma_channel; | ||
| 87 | }; | 89 | }; |
| 88 | 90 | ||
| 89 | enum { | 91 | enum { |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index c82f89c9475b..95970f5db3ec 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | config SND_DAVINCI_SOC | 1 | config SND_DAVINCI_SOC |
| 2 | tristate "SoC Audio for the TI DAVINCI chip" | 2 | tristate "SoC Audio for the TI DAVINCI or AM33XX chip" |
| 3 | depends on ARCH_DAVINCI | 3 | depends on ARCH_DAVINCI || SOC_AM33XX |
| 4 | help | 4 | help |
| 5 | Platform driver for daVinci or AM33xx | ||
| 5 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
| 6 | the DAVINCI AC97 or I2S interface. You will also need | 7 | the DAVINCI AC97, I2S, or McASP interface. You will also need |
| 7 | to select the audio interfaces to support below. | 8 | to select the audio interfaces to support below. |
| 8 | 9 | ||
| 9 | config SND_DAVINCI_SOC_I2S | 10 | config SND_DAVINCI_SOC_I2S |
| @@ -15,6 +16,17 @@ config SND_DAVINCI_SOC_MCASP | |||
| 15 | config SND_DAVINCI_SOC_VCIF | 16 | config SND_DAVINCI_SOC_VCIF |
| 16 | tristate | 17 | tristate |
| 17 | 18 | ||
| 19 | config SND_AM33XX_SOC_EVM | ||
| 20 | tristate "SoC Audio for the AM33XX chip based boards" | ||
| 21 | depends on SND_DAVINCI_SOC && SOC_AM33XX | ||
| 22 | select SND_SOC_TLV320AIC3X | ||
| 23 | select SND_DAVINCI_SOC_MCASP | ||
| 24 | help | ||
| 25 | Say Y or M if you want to add support for SoC audio on AM33XX | ||
| 26 | boards using McASP and TLV320AIC3X codec. For example AM335X-EVM, | ||
| 27 | AM335X-EVMSK, and BeagelBone with AudioCape boards have this | ||
| 28 | setup. | ||
| 29 | |||
| 18 | config SND_DAVINCI_SOC_EVM | 30 | config SND_DAVINCI_SOC_EVM |
| 19 | tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" | 31 | tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" |
| 20 | depends on SND_DAVINCI_SOC | 32 | depends on SND_DAVINCI_SOC |
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile index a396ab6d6d5e..bc81e79fc301 100644 --- a/sound/soc/davinci/Makefile +++ b/sound/soc/davinci/Makefile | |||
| @@ -13,6 +13,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o | |||
| 13 | snd-soc-evm-objs := davinci-evm.o | 13 | snd-soc-evm-objs := davinci-evm.o |
| 14 | 14 | ||
| 15 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o | 15 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o |
| 16 | obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o | ||
| 16 | obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o | 17 | obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o |
| 17 | obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o | 18 | obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o |
| 18 | obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o | 19 | obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index fd7c45b9ed5a..623eb5e7c089 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/platform_data/edma.h> | 17 | #include <linux/platform_data/edma.h> |
| 18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
| 19 | #include <linux/of_platform.h> | ||
| 19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
| 20 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
| 21 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
| @@ -23,10 +24,16 @@ | |||
| 23 | #include <asm/dma.h> | 24 | #include <asm/dma.h> |
| 24 | #include <asm/mach-types.h> | 25 | #include <asm/mach-types.h> |
| 25 | 26 | ||
| 27 | #include <linux/edma.h> | ||
| 28 | |||
| 26 | #include "davinci-pcm.h" | 29 | #include "davinci-pcm.h" |
| 27 | #include "davinci-i2s.h" | 30 | #include "davinci-i2s.h" |
| 28 | #include "davinci-mcasp.h" | 31 | #include "davinci-mcasp.h" |
| 29 | 32 | ||
| 33 | struct snd_soc_card_drvdata_davinci { | ||
| 34 | unsigned sysclk; | ||
| 35 | }; | ||
| 36 | |||
| 30 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ | 37 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ |
| 31 | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) | 38 | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) |
| 32 | static int evm_hw_params(struct snd_pcm_substream *substream, | 39 | static int evm_hw_params(struct snd_pcm_substream *substream, |
| @@ -35,27 +42,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
| 35 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 36 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
| 37 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 44 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
| 45 | struct snd_soc_codec *codec = rtd->codec; | ||
| 46 | struct snd_soc_card *soc_card = codec->card; | ||
| 38 | int ret = 0; | 47 | int ret = 0; |
| 39 | unsigned sysclk; | 48 | unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) |
| 40 | 49 | snd_soc_card_get_drvdata(soc_card))->sysclk; | |
| 41 | /* ASP1 on DM355 EVM is clocked by an external oscillator */ | ||
| 42 | if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() || | ||
| 43 | machine_is_davinci_dm365_evm()) | ||
| 44 | sysclk = 27000000; | ||
| 45 | |||
| 46 | /* ASP0 in DM6446 EVM is clocked by U55, as configured by | ||
| 47 | * board-dm644x-evm.c using GPIOs from U18. There are six | ||
| 48 | * options; here we "know" we use a 48 KHz sample rate. | ||
| 49 | */ | ||
| 50 | else if (machine_is_davinci_evm()) | ||
| 51 | sysclk = 12288000; | ||
| 52 | |||
| 53 | else if (machine_is_davinci_da830_evm() || | ||
| 54 | machine_is_davinci_da850_evm()) | ||
| 55 | sysclk = 24576000; | ||
| 56 | |||
| 57 | else | ||
| 58 | return -EINVAL; | ||
| 59 | 50 | ||
| 60 | /* set codec DAI configuration */ | 51 | /* set codec DAI configuration */ |
| 61 | ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); | 52 | ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); |
| @@ -133,13 +124,22 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) | |||
| 133 | { | 124 | { |
| 134 | struct snd_soc_codec *codec = rtd->codec; | 125 | struct snd_soc_codec *codec = rtd->codec; |
| 135 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 126 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
| 127 | struct device_node *np = codec->card->dev->of_node; | ||
| 128 | int ret; | ||
| 136 | 129 | ||
| 137 | /* Add davinci-evm specific widgets */ | 130 | /* Add davinci-evm specific widgets */ |
| 138 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, | 131 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, |
| 139 | ARRAY_SIZE(aic3x_dapm_widgets)); | 132 | ARRAY_SIZE(aic3x_dapm_widgets)); |
| 140 | 133 | ||
| 141 | /* Set up davinci-evm specific audio path audio_map */ | 134 | if (np) { |
| 142 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | 135 | ret = snd_soc_of_parse_audio_routing(codec->card, |
| 136 | "ti,audio-routing"); | ||
| 137 | if (ret) | ||
| 138 | return ret; | ||
| 139 | } else { | ||
| 140 | /* Set up davinci-evm specific audio path audio_map */ | ||
| 141 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
| 142 | } | ||
| 143 | 143 | ||
| 144 | /* not connected */ | 144 | /* not connected */ |
| 145 | snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); | 145 | snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); |
| @@ -243,35 +243,65 @@ static struct snd_soc_dai_link da850_evm_dai = { | |||
| 243 | }; | 243 | }; |
| 244 | 244 | ||
| 245 | /* davinci dm6446 evm audio machine driver */ | 245 | /* davinci dm6446 evm audio machine driver */ |
| 246 | /* | ||
| 247 | * ASP0 in DM6446 EVM is clocked by U55, as configured by | ||
| 248 | * board-dm644x-evm.c using GPIOs from U18. There are six | ||
| 249 | * options; here we "know" we use a 48 KHz sample rate. | ||
| 250 | */ | ||
| 251 | static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = { | ||
| 252 | .sysclk = 12288000, | ||
| 253 | }; | ||
| 254 | |||
| 246 | static struct snd_soc_card dm6446_snd_soc_card_evm = { | 255 | static struct snd_soc_card dm6446_snd_soc_card_evm = { |
| 247 | .name = "DaVinci DM6446 EVM", | 256 | .name = "DaVinci DM6446 EVM", |
| 248 | .owner = THIS_MODULE, | 257 | .owner = THIS_MODULE, |
| 249 | .dai_link = &dm6446_evm_dai, | 258 | .dai_link = &dm6446_evm_dai, |
| 250 | .num_links = 1, | 259 | .num_links = 1, |
| 260 | .drvdata = &dm6446_snd_soc_card_drvdata, | ||
| 251 | }; | 261 | }; |
| 252 | 262 | ||
| 253 | /* davinci dm355 evm audio machine driver */ | 263 | /* davinci dm355 evm audio machine driver */ |
| 264 | /* ASP1 on DM355 EVM is clocked by an external oscillator */ | ||
| 265 | static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = { | ||
| 266 | .sysclk = 27000000, | ||
| 267 | }; | ||
| 268 | |||
| 254 | static struct snd_soc_card dm355_snd_soc_card_evm = { | 269 | static struct snd_soc_card dm355_snd_soc_card_evm = { |
| 255 | .name = "DaVinci DM355 EVM", | 270 | .name = "DaVinci DM355 EVM", |
| 256 | .owner = THIS_MODULE, | 271 | .owner = THIS_MODULE, |
| 257 | .dai_link = &dm355_evm_dai, | 272 | .dai_link = &dm355_evm_dai, |
| 258 | .num_links = 1, | 273 | .num_links = 1, |
| 274 | .drvdata = &dm355_snd_soc_card_drvdata, | ||
| 259 | }; | 275 | }; |
| 260 | 276 | ||
| 261 | /* davinci dm365 evm audio machine driver */ | 277 | /* davinci dm365 evm audio machine driver */ |
| 278 | static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = { | ||
| 279 | .sysclk = 27000000, | ||
| 280 | }; | ||
| 281 | |||
| 262 | static struct snd_soc_card dm365_snd_soc_card_evm = { | 282 | static struct snd_soc_card dm365_snd_soc_card_evm = { |
| 263 | .name = "DaVinci DM365 EVM", | 283 | .name = "DaVinci DM365 EVM", |
| 264 | .owner = THIS_MODULE, | 284 | .owner = THIS_MODULE, |
| 265 | .dai_link = &dm365_evm_dai, | 285 | .dai_link = &dm365_evm_dai, |
| 266 | .num_links = 1, | 286 | .num_links = 1, |
| 287 | .drvdata = &dm365_snd_soc_card_drvdata, | ||
| 267 | }; | 288 | }; |
| 268 | 289 | ||
| 269 | /* davinci dm6467 evm audio machine driver */ | 290 | /* davinci dm6467 evm audio machine driver */ |
| 291 | static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = { | ||
| 292 | .sysclk = 27000000, | ||
| 293 | }; | ||
| 294 | |||
| 270 | static struct snd_soc_card dm6467_snd_soc_card_evm = { | 295 | static struct snd_soc_card dm6467_snd_soc_card_evm = { |
| 271 | .name = "DaVinci DM6467 EVM", | 296 | .name = "DaVinci DM6467 EVM", |
| 272 | .owner = THIS_MODULE, | 297 | .owner = THIS_MODULE, |
| 273 | .dai_link = dm6467_evm_dai, | 298 | .dai_link = dm6467_evm_dai, |
| 274 | .num_links = ARRAY_SIZE(dm6467_evm_dai), | 299 | .num_links = ARRAY_SIZE(dm6467_evm_dai), |
| 300 | .drvdata = &dm6467_snd_soc_card_drvdata, | ||
| 301 | }; | ||
| 302 | |||
| 303 | static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = { | ||
| 304 | .sysclk = 24576000, | ||
| 275 | }; | 305 | }; |
| 276 | 306 | ||
| 277 | static struct snd_soc_card da830_snd_soc_card = { | 307 | static struct snd_soc_card da830_snd_soc_card = { |
| @@ -279,6 +309,11 @@ static struct snd_soc_card da830_snd_soc_card = { | |||
| 279 | .owner = THIS_MODULE, | 309 | .owner = THIS_MODULE, |
| 280 | .dai_link = &da830_evm_dai, | 310 | .dai_link = &da830_evm_dai, |
| 281 | .num_links = 1, | 311 | .num_links = 1, |
| 312 | .drvdata = &da830_snd_soc_card_drvdata, | ||
| 313 | }; | ||
| 314 | |||
| 315 | static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = { | ||
| 316 | .sysclk = 24576000, | ||
| 282 | }; | 317 | }; |
| 283 | 318 | ||
| 284 | static struct snd_soc_card da850_snd_soc_card = { | 319 | static struct snd_soc_card da850_snd_soc_card = { |
| @@ -286,8 +321,101 @@ static struct snd_soc_card da850_snd_soc_card = { | |||
| 286 | .owner = THIS_MODULE, | 321 | .owner = THIS_MODULE, |
| 287 | .dai_link = &da850_evm_dai, | 322 | .dai_link = &da850_evm_dai, |
| 288 | .num_links = 1, | 323 | .num_links = 1, |
| 324 | .drvdata = &da850_snd_soc_card_drvdata, | ||
| 325 | }; | ||
| 326 | |||
| 327 | #if defined(CONFIG_OF) | ||
| 328 | |||
| 329 | /* | ||
| 330 | * The struct is used as place holder. It will be completely | ||
| 331 | * filled with data from dt node. | ||
| 332 | */ | ||
| 333 | static struct snd_soc_dai_link evm_dai_tlv320aic3x = { | ||
| 334 | .name = "TLV320AIC3X", | ||
| 335 | .stream_name = "AIC3X", | ||
| 336 | .codec_dai_name = "tlv320aic3x-hifi", | ||
| 337 | .ops = &evm_ops, | ||
| 338 | .init = evm_aic3x_init, | ||
| 339 | }; | ||
| 340 | |||
| 341 | static const struct of_device_id davinci_evm_dt_ids[] = { | ||
| 342 | { | ||
| 343 | .compatible = "ti,da830-evm-audio", | ||
| 344 | .data = (void *) &evm_dai_tlv320aic3x, | ||
| 345 | }, | ||
| 346 | { /* sentinel */ } | ||
| 347 | }; | ||
| 348 | MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids); | ||
| 349 | |||
| 350 | /* davinci evm audio machine driver */ | ||
| 351 | static struct snd_soc_card evm_soc_card = { | ||
| 352 | .owner = THIS_MODULE, | ||
| 353 | .num_links = 1, | ||
| 289 | }; | 354 | }; |
| 290 | 355 | ||
| 356 | static int davinci_evm_probe(struct platform_device *pdev) | ||
| 357 | { | ||
| 358 | struct device_node *np = pdev->dev.of_node; | ||
| 359 | const struct of_device_id *match = | ||
| 360 | of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); | ||
| 361 | struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; | ||
| 362 | struct snd_soc_card_drvdata_davinci *drvdata = NULL; | ||
| 363 | int ret = 0; | ||
| 364 | |||
| 365 | evm_soc_card.dai_link = dai; | ||
| 366 | |||
| 367 | dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); | ||
| 368 | if (!dai->codec_of_node) | ||
| 369 | return -EINVAL; | ||
| 370 | |||
| 371 | dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0); | ||
| 372 | if (!dai->cpu_of_node) | ||
| 373 | return -EINVAL; | ||
| 374 | |||
| 375 | dai->platform_of_node = dai->cpu_of_node; | ||
| 376 | |||
| 377 | evm_soc_card.dev = &pdev->dev; | ||
| 378 | ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); | ||
| 379 | if (ret) | ||
| 380 | return ret; | ||
| 381 | |||
| 382 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
| 383 | if (!drvdata) | ||
| 384 | return -ENOMEM; | ||
| 385 | |||
| 386 | ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); | ||
| 387 | if (ret < 0) | ||
| 388 | return -EINVAL; | ||
| 389 | |||
| 390 | snd_soc_card_set_drvdata(&evm_soc_card, drvdata); | ||
| 391 | ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); | ||
| 392 | |||
| 393 | if (ret) | ||
| 394 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | ||
| 395 | |||
| 396 | return ret; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int davinci_evm_remove(struct platform_device *pdev) | ||
| 400 | { | ||
| 401 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
| 402 | |||
| 403 | snd_soc_unregister_card(card); | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | static struct platform_driver davinci_evm_driver = { | ||
| 409 | .probe = davinci_evm_probe, | ||
| 410 | .remove = davinci_evm_remove, | ||
| 411 | .driver = { | ||
| 412 | .name = "davinci_evm", | ||
| 413 | .owner = THIS_MODULE, | ||
| 414 | .of_match_table = of_match_ptr(davinci_evm_dt_ids), | ||
| 415 | }, | ||
| 416 | }; | ||
| 417 | #endif | ||
| 418 | |||
| 291 | static struct platform_device *evm_snd_device; | 419 | static struct platform_device *evm_snd_device; |
| 292 | 420 | ||
| 293 | static int __init evm_init(void) | 421 | static int __init evm_init(void) |
| @@ -296,6 +424,15 @@ static int __init evm_init(void) | |||
| 296 | int index; | 424 | int index; |
| 297 | int ret; | 425 | int ret; |
| 298 | 426 | ||
| 427 | /* | ||
| 428 | * If dtb is there, the devices will be created dynamically. | ||
| 429 | * Only register platfrom driver structure. | ||
| 430 | */ | ||
| 431 | #if defined(CONFIG_OF) | ||
| 432 | if (of_have_populated_dt()) | ||
| 433 | return platform_driver_register(&davinci_evm_driver); | ||
| 434 | #endif | ||
| 435 | |||
| 299 | if (machine_is_davinci_evm()) { | 436 | if (machine_is_davinci_evm()) { |
| 300 | evm_snd_dev_data = &dm6446_snd_soc_card_evm; | 437 | evm_snd_dev_data = &dm6446_snd_soc_card_evm; |
| 301 | index = 0; | 438 | index = 0; |
| @@ -331,6 +468,13 @@ static int __init evm_init(void) | |||
| 331 | 468 | ||
| 332 | static void __exit evm_exit(void) | 469 | static void __exit evm_exit(void) |
| 333 | { | 470 | { |
| 471 | #if defined(CONFIG_OF) | ||
| 472 | if (of_have_populated_dt()) { | ||
| 473 | platform_driver_unregister(&davinci_evm_driver); | ||
| 474 | return; | ||
| 475 | } | ||
| 476 | #endif | ||
| 477 | |||
| 334 | platform_device_unregister(evm_snd_device); | 478 | platform_device_unregister(evm_snd_device); |
| 335 | } | 479 | } |
| 336 | 480 | ||
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 32ddb7fe5034..71e14bb3a8cd 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
| @@ -1001,18 +1001,40 @@ static const struct snd_soc_component_driver davinci_mcasp_component = { | |||
| 1001 | .name = "davinci-mcasp", | 1001 | .name = "davinci-mcasp", |
| 1002 | }; | 1002 | }; |
| 1003 | 1003 | ||
| 1004 | /* Some HW specific values and defaults. The rest is filled in from DT. */ | ||
| 1005 | static struct snd_platform_data dm646x_mcasp_pdata = { | ||
| 1006 | .tx_dma_offset = 0x400, | ||
| 1007 | .rx_dma_offset = 0x400, | ||
| 1008 | .asp_chan_q = EVENTQ_0, | ||
| 1009 | .version = MCASP_VERSION_1, | ||
| 1010 | }; | ||
| 1011 | |||
| 1012 | static struct snd_platform_data da830_mcasp_pdata = { | ||
| 1013 | .tx_dma_offset = 0x2000, | ||
| 1014 | .rx_dma_offset = 0x2000, | ||
| 1015 | .asp_chan_q = EVENTQ_0, | ||
| 1016 | .version = MCASP_VERSION_2, | ||
| 1017 | }; | ||
| 1018 | |||
| 1019 | static struct snd_platform_data omap2_mcasp_pdata = { | ||
| 1020 | .tx_dma_offset = 0, | ||
| 1021 | .rx_dma_offset = 0, | ||
| 1022 | .asp_chan_q = EVENTQ_0, | ||
| 1023 | .version = MCASP_VERSION_3, | ||
| 1024 | }; | ||
| 1025 | |||
| 1004 | static const struct of_device_id mcasp_dt_ids[] = { | 1026 | static const struct of_device_id mcasp_dt_ids[] = { |
| 1005 | { | 1027 | { |
| 1006 | .compatible = "ti,dm646x-mcasp-audio", | 1028 | .compatible = "ti,dm646x-mcasp-audio", |
| 1007 | .data = (void *)MCASP_VERSION_1, | 1029 | .data = &dm646x_mcasp_pdata, |
| 1008 | }, | 1030 | }, |
| 1009 | { | 1031 | { |
| 1010 | .compatible = "ti,da830-mcasp-audio", | 1032 | .compatible = "ti,da830-mcasp-audio", |
| 1011 | .data = (void *)MCASP_VERSION_2, | 1033 | .data = &da830_mcasp_pdata, |
| 1012 | }, | 1034 | }, |
| 1013 | { | 1035 | { |
| 1014 | .compatible = "ti,omap2-mcasp-audio", | 1036 | .compatible = "ti,am33xx-mcasp-audio", |
| 1015 | .data = (void *)MCASP_VERSION_3, | 1037 | .data = &omap2_mcasp_pdata, |
| 1016 | }, | 1038 | }, |
| 1017 | { /* sentinel */ } | 1039 | { /* sentinel */ } |
| 1018 | }; | 1040 | }; |
| @@ -1025,9 +1047,9 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
| 1025 | struct snd_platform_data *pdata = NULL; | 1047 | struct snd_platform_data *pdata = NULL; |
| 1026 | const struct of_device_id *match = | 1048 | const struct of_device_id *match = |
| 1027 | of_match_device(mcasp_dt_ids, &pdev->dev); | 1049 | of_match_device(mcasp_dt_ids, &pdev->dev); |
| 1050 | struct of_phandle_args dma_spec; | ||
| 1028 | 1051 | ||
| 1029 | const u32 *of_serial_dir32; | 1052 | const u32 *of_serial_dir32; |
| 1030 | u8 *of_serial_dir; | ||
| 1031 | u32 val; | 1053 | u32 val; |
| 1032 | int i, ret = 0; | 1054 | int i, ret = 0; |
| 1033 | 1055 | ||
| @@ -1035,20 +1057,13 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
| 1035 | pdata = pdev->dev.platform_data; | 1057 | pdata = pdev->dev.platform_data; |
| 1036 | return pdata; | 1058 | return pdata; |
| 1037 | } else if (match) { | 1059 | } else if (match) { |
| 1038 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 1060 | pdata = (struct snd_platform_data *) match->data; |
| 1039 | if (!pdata) { | ||
| 1040 | ret = -ENOMEM; | ||
| 1041 | goto nodata; | ||
| 1042 | } | ||
| 1043 | } else { | 1061 | } else { |
| 1044 | /* control shouldn't reach here. something is wrong */ | 1062 | /* control shouldn't reach here. something is wrong */ |
| 1045 | ret = -EINVAL; | 1063 | ret = -EINVAL; |
| 1046 | goto nodata; | 1064 | goto nodata; |
| 1047 | } | 1065 | } |
| 1048 | 1066 | ||
| 1049 | if (match->data) | ||
| 1050 | pdata->version = (u8)((int)match->data); | ||
| 1051 | |||
| 1052 | ret = of_property_read_u32(np, "op-mode", &val); | 1067 | ret = of_property_read_u32(np, "op-mode", &val); |
| 1053 | if (ret >= 0) | 1068 | if (ret >= 0) |
| 1054 | pdata->op_mode = val; | 1069 | pdata->op_mode = val; |
| @@ -1065,35 +1080,46 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
| 1065 | pdata->tdm_slots = val; | 1080 | pdata->tdm_slots = val; |
| 1066 | } | 1081 | } |
| 1067 | 1082 | ||
| 1068 | ret = of_property_read_u32(np, "num-serializer", &val); | ||
| 1069 | if (ret >= 0) | ||
| 1070 | pdata->num_serializer = val; | ||
| 1071 | |||
| 1072 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); | 1083 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); |
| 1073 | val /= sizeof(u32); | 1084 | val /= sizeof(u32); |
| 1074 | if (val != pdata->num_serializer) { | ||
| 1075 | dev_err(&pdev->dev, | ||
| 1076 | "num-serializer(%d) != serial-dir size(%d)\n", | ||
| 1077 | pdata->num_serializer, val); | ||
| 1078 | ret = -EINVAL; | ||
| 1079 | goto nodata; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | if (of_serial_dir32) { | 1085 | if (of_serial_dir32) { |
| 1083 | of_serial_dir = devm_kzalloc(&pdev->dev, | 1086 | u8 *of_serial_dir = devm_kzalloc(&pdev->dev, |
| 1084 | (sizeof(*of_serial_dir) * val), | 1087 | (sizeof(*of_serial_dir) * val), |
| 1085 | GFP_KERNEL); | 1088 | GFP_KERNEL); |
| 1086 | if (!of_serial_dir) { | 1089 | if (!of_serial_dir) { |
| 1087 | ret = -ENOMEM; | 1090 | ret = -ENOMEM; |
| 1088 | goto nodata; | 1091 | goto nodata; |
| 1089 | } | 1092 | } |
| 1090 | 1093 | ||
| 1091 | for (i = 0; i < pdata->num_serializer; i++) | 1094 | for (i = 0; i < val; i++) |
| 1092 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); | 1095 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); |
| 1093 | 1096 | ||
| 1097 | pdata->num_serializer = val; | ||
| 1094 | pdata->serial_dir = of_serial_dir; | 1098 | pdata->serial_dir = of_serial_dir; |
| 1095 | } | 1099 | } |
| 1096 | 1100 | ||
| 1101 | ret = of_property_match_string(np, "dma-names", "tx"); | ||
| 1102 | if (ret < 0) | ||
| 1103 | goto nodata; | ||
| 1104 | |||
| 1105 | ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, | ||
| 1106 | &dma_spec); | ||
| 1107 | if (ret < 0) | ||
| 1108 | goto nodata; | ||
| 1109 | |||
| 1110 | pdata->tx_dma_channel = dma_spec.args[0]; | ||
| 1111 | |||
| 1112 | ret = of_property_match_string(np, "dma-names", "rx"); | ||
| 1113 | if (ret < 0) | ||
| 1114 | goto nodata; | ||
| 1115 | |||
| 1116 | ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, | ||
| 1117 | &dma_spec); | ||
| 1118 | if (ret < 0) | ||
| 1119 | goto nodata; | ||
| 1120 | |||
| 1121 | pdata->rx_dma_channel = dma_spec.args[0]; | ||
| 1122 | |||
| 1097 | ret = of_property_read_u32(np, "tx-num-evt", &val); | 1123 | ret = of_property_read_u32(np, "tx-num-evt", &val); |
| 1098 | if (ret >= 0) | 1124 | if (ret >= 0) |
| 1099 | pdata->txnumevt = val; | 1125 | pdata->txnumevt = val; |
| @@ -1124,7 +1150,7 @@ nodata: | |||
| 1124 | static int davinci_mcasp_probe(struct platform_device *pdev) | 1150 | static int davinci_mcasp_probe(struct platform_device *pdev) |
| 1125 | { | 1151 | { |
| 1126 | struct davinci_pcm_dma_params *dma_data; | 1152 | struct davinci_pcm_dma_params *dma_data; |
| 1127 | struct resource *mem, *ioarea, *res; | 1153 | struct resource *mem, *ioarea, *res, *dat; |
| 1128 | struct snd_platform_data *pdata; | 1154 | struct snd_platform_data *pdata; |
| 1129 | struct davinci_audio_dev *dev; | 1155 | struct davinci_audio_dev *dev; |
| 1130 | int ret; | 1156 | int ret; |
| @@ -1145,10 +1171,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 1145 | return -EINVAL; | 1171 | return -EINVAL; |
| 1146 | } | 1172 | } |
| 1147 | 1173 | ||
| 1148 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1174 | mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
| 1149 | if (!mem) { | 1175 | if (!mem) { |
| 1150 | dev_err(&pdev->dev, "no mem resource?\n"); | 1176 | dev_warn(dev->dev, |
| 1151 | return -ENODEV; | 1177 | "\"mpu\" mem resource not found, using index 0\n"); |
| 1178 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1179 | if (!mem) { | ||
| 1180 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
| 1181 | return -ENODEV; | ||
| 1182 | } | ||
| 1152 | } | 1183 | } |
| 1153 | 1184 | ||
| 1154 | ioarea = devm_request_mem_region(&pdev->dev, mem->start, | 1185 | ioarea = devm_request_mem_region(&pdev->dev, mem->start, |
| @@ -1182,40 +1213,36 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 1182 | dev->rxnumevt = pdata->rxnumevt; | 1213 | dev->rxnumevt = pdata->rxnumevt; |
| 1183 | dev->dev = &pdev->dev; | 1214 | dev->dev = &pdev->dev; |
| 1184 | 1215 | ||
| 1216 | dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); | ||
| 1217 | if (!dat) | ||
| 1218 | dat = mem; | ||
| 1219 | |||
| 1185 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 1220 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
| 1186 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1221 | dma_data->asp_chan_q = pdata->asp_chan_q; |
| 1187 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1222 | dma_data->ram_chan_q = pdata->ram_chan_q; |
| 1188 | dma_data->sram_pool = pdata->sram_pool; | 1223 | dma_data->sram_pool = pdata->sram_pool; |
| 1189 | dma_data->sram_size = pdata->sram_size_playback; | 1224 | dma_data->sram_size = pdata->sram_size_playback; |
| 1190 | dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + | 1225 | dma_data->dma_addr = dat->start + pdata->tx_dma_offset; |
| 1191 | mem->start); | ||
| 1192 | 1226 | ||
| 1193 | /* first TX, then RX */ | ||
| 1194 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1227 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
| 1195 | if (!res) { | 1228 | if (res) |
| 1196 | dev_err(&pdev->dev, "no DMA resource\n"); | 1229 | dma_data->channel = res->start; |
| 1197 | ret = -ENODEV; | 1230 | else |
| 1198 | goto err_release_clk; | 1231 | dma_data->channel = pdata->tx_dma_channel; |
| 1199 | } | ||
| 1200 | |||
| 1201 | dma_data->channel = res->start; | ||
| 1202 | 1232 | ||
| 1203 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; | 1233 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; |
| 1204 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1234 | dma_data->asp_chan_q = pdata->asp_chan_q; |
| 1205 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1235 | dma_data->ram_chan_q = pdata->ram_chan_q; |
| 1206 | dma_data->sram_pool = pdata->sram_pool; | 1236 | dma_data->sram_pool = pdata->sram_pool; |
| 1207 | dma_data->sram_size = pdata->sram_size_capture; | 1237 | dma_data->sram_size = pdata->sram_size_capture; |
| 1208 | dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + | 1238 | dma_data->dma_addr = dat->start + pdata->rx_dma_offset; |
| 1209 | mem->start); | ||
| 1210 | 1239 | ||
| 1211 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 1240 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
| 1212 | if (!res) { | 1241 | if (res) |
| 1213 | dev_err(&pdev->dev, "no DMA resource\n"); | 1242 | dma_data->channel = res->start; |
| 1214 | ret = -ENODEV; | 1243 | else |
| 1215 | goto err_release_clk; | 1244 | dma_data->channel = pdata->rx_dma_channel; |
| 1216 | } | ||
| 1217 | 1245 | ||
| 1218 | dma_data->channel = res->start; | ||
| 1219 | dev_set_drvdata(&pdev->dev, dev); | 1246 | dev_set_drvdata(&pdev->dev, dev); |
| 1220 | ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, | 1247 | ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, |
| 1221 | &davinci_mcasp_dai[pdata->op_mode], 1); | 1248 | &davinci_mcasp_dai[pdata->op_mode], 1); |
| @@ -1251,12 +1278,51 @@ static int davinci_mcasp_remove(struct platform_device *pdev) | |||
| 1251 | return 0; | 1278 | return 0; |
| 1252 | } | 1279 | } |
| 1253 | 1280 | ||
| 1281 | #ifdef CONFIG_PM_SLEEP | ||
| 1282 | static int davinci_mcasp_suspend(struct device *dev) | ||
| 1283 | { | ||
| 1284 | struct davinci_audio_dev *a = dev_get_drvdata(dev); | ||
| 1285 | void __iomem *base = a->base; | ||
| 1286 | |||
| 1287 | a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG); | ||
| 1288 | a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG); | ||
| 1289 | a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG); | ||
| 1290 | a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG); | ||
| 1291 | a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG); | ||
| 1292 | a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG); | ||
| 1293 | a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG); | ||
| 1294 | |||
| 1295 | return 0; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | static int davinci_mcasp_resume(struct device *dev) | ||
| 1299 | { | ||
| 1300 | struct davinci_audio_dev *a = dev_get_drvdata(dev); | ||
| 1301 | void __iomem *base = a->base; | ||
| 1302 | |||
| 1303 | mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl); | ||
| 1304 | mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl); | ||
| 1305 | mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt); | ||
| 1306 | mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt); | ||
| 1307 | mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl); | ||
| 1308 | mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl); | ||
| 1309 | mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir); | ||
| 1310 | |||
| 1311 | return 0; | ||
| 1312 | } | ||
| 1313 | #endif | ||
| 1314 | |||
| 1315 | SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops, | ||
| 1316 | davinci_mcasp_suspend, | ||
| 1317 | davinci_mcasp_resume); | ||
| 1318 | |||
| 1254 | static struct platform_driver davinci_mcasp_driver = { | 1319 | static struct platform_driver davinci_mcasp_driver = { |
| 1255 | .probe = davinci_mcasp_probe, | 1320 | .probe = davinci_mcasp_probe, |
| 1256 | .remove = davinci_mcasp_remove, | 1321 | .remove = davinci_mcasp_remove, |
| 1257 | .driver = { | 1322 | .driver = { |
| 1258 | .name = "davinci-mcasp", | 1323 | .name = "davinci-mcasp", |
| 1259 | .owner = THIS_MODULE, | 1324 | .owner = THIS_MODULE, |
| 1325 | .pm = &davinci_mcasp_pm_ops, | ||
| 1260 | .of_match_table = mcasp_dt_ids, | 1326 | .of_match_table = mcasp_dt_ids, |
| 1261 | }, | 1327 | }, |
| 1262 | }; | 1328 | }; |
| @@ -1266,4 +1332,3 @@ module_platform_driver(davinci_mcasp_driver); | |||
| 1266 | MODULE_AUTHOR("Steve Chen"); | 1332 | MODULE_AUTHOR("Steve Chen"); |
| 1267 | MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); | 1333 | MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); |
| 1268 | MODULE_LICENSE("GPL"); | 1334 | MODULE_LICENSE("GPL"); |
| 1269 | |||
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index a9ac0c11da71..a2e27e1c32f3 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
| @@ -43,6 +43,18 @@ struct davinci_audio_dev { | |||
| 43 | /* McASP FIFO related */ | 43 | /* McASP FIFO related */ |
| 44 | u8 txnumevt; | 44 | u8 txnumevt; |
| 45 | u8 rxnumevt; | 45 | u8 rxnumevt; |
| 46 | |||
| 47 | #ifdef CONFIG_PM_SLEEP | ||
| 48 | struct { | ||
| 49 | u32 txfmtctl; | ||
| 50 | u32 rxfmtctl; | ||
| 51 | u32 txfmt; | ||
| 52 | u32 rxfmt; | ||
| 53 | u32 aclkxctl; | ||
| 54 | u32 aclkrctl; | ||
| 55 | u32 pdir; | ||
| 56 | } context; | ||
| 57 | #endif | ||
| 46 | }; | 58 | }; |
| 47 | 59 | ||
| 48 | #endif /* DAVINCI_MCASP_H */ | 60 | #endif /* DAVINCI_MCASP_H */ |
