Merge remote-tracking branch 'asoc/topic/davinci' into asoc-next

This commit is contained in:
Mark Brown 2013-11-08 10:43:27 +00:00
commit ac97d4e00a
8 changed files with 382 additions and 91 deletions

View file

@ -0,0 +1,42 @@
* Texas Instruments SoC audio setups with TLV320AIC3X Codec
Required properties:
- compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx
- ti,model : The user-visible name of this sound complex.
- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
- ti,mcasp-controller : The phandle of the McASP controller
- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
- ti,audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the connection's sink,
the second being the connection's source. Valid names for sources and
sinks are the codec's pins, and the jacks on the board:
Board connectors:
* Headphone Jack
* Line Out
* Mic Jack
* Line In
Example:
sound {
compatible = "ti,da830-evm-audio";
ti,model = "DA830 EVM";
ti,audio-codec = <&tlv320aic3x>;
ti,mcasp-controller = <&mcasp1>;
ti,codec-clock-rate = <12000000>;
ti,audio-routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"Line Out", "LLOUT",
"Line Out", "RLOUT",
"MIC3L", "Mic Bias 2V",
"MIC3R", "Mic Bias 2V",
"Mic Bias 2V", "Mic Jack",
"LINE1L", "Line In",
"LINE2L", "Line In",
"LINE1R", "Line In",
"LINE2R", "Line In";
};

View file

@ -4,17 +4,25 @@ Required properties:
- compatible :
"ti,dm646x-mcasp-audio" : for DM646x platforms
"ti,da830-mcasp-audio" : for both DA830 & DA850 platforms
"ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx)
- reg : Should contain McASP registers offset and length
- interrupts : Interrupt number for McASP
- op-mode : I2S/DIT ops mode.
- tdm-slots : Slots for TDM operation.
- num-serializer : Serializers used by McASP.
- serial-dir : A list of serializer pin mode. The list number should be equal
to "num-serializer" parameter. Each entry is a number indication
serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX)
"ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, TI81xx)
- reg : Should contain reg specifiers for the entries in the reg-names property.
- reg-names : Should contain:
* "mpu" for the main registers (required). For compatibility with
existing software, it is recommended this is the first entry.
* "dat" for separate data port register access (optional).
- op-mode : I2S/DIT ops mode. 0 for I2S mode. 1 for DIT mode used for S/PDIF,
IEC60958-1, and AES-3 formats.
- tdm-slots : Slots for TDM operation. Indicates number of channels transmitted
or received over one serializer.
- serial-dir : A list of serializer configuration. Each entry is a number
indication for serializer pin direction.
(0 - INACTIVE, 1 - TX, 2 - RX)
- dmas: two element list of DMA controller phandles and DMA request line
ordered pairs.
- dma-names: identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas. The dma
identifiers must be "rx" and "tx".
Optional properties:
@ -23,18 +31,23 @@ Optional properties:
- rx-num-evt : FIFO levels.
- sram-size-playback : size of sram to be allocated during playback
- sram-size-capture : size of sram to be allocated during capture
- interrupts : Interrupt numbers for McASP, currently not used by the driver
- interrupt-names : Known interrupt names are "tx" and "rx"
- pinctrl-0: Should specify pin control group used for this controller.
- pinctrl-names: Should contain only one value - "default", for more details
please refer to pinctrl-bindings.txt
Example:
mcasp0: mcasp0@1d00000 {
compatible = "ti,da830-mcasp-audio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x100000 0x3000>;
interrupts = <82 83>;
reg-names "mpu";
interrupts = <82>, <83>;
interrupts-names = "tx", "rx";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
num-serializer = <16>;
serial-dir = <
0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */
0 0 0 0

View file

@ -84,6 +84,8 @@ struct snd_platform_data {
u8 version;
u8 txnumevt;
u8 rxnumevt;
int tx_dma_channel;
int rx_dma_channel;
};
enum {

View file

@ -1,9 +1,10 @@
config SND_DAVINCI_SOC
tristate "SoC Audio for the TI DAVINCI chip"
depends on ARCH_DAVINCI
tristate "SoC Audio for the TI DAVINCI or AM33XX chip"
depends on ARCH_DAVINCI || SOC_AM33XX
help
Platform driver for daVinci or AM33xx
Say Y or M if you want to add support for codecs attached to
the DAVINCI AC97 or I2S interface. You will also need
the DAVINCI AC97, I2S, or McASP interface. You will also need
to select the audio interfaces to support below.
config SND_DAVINCI_SOC_I2S
@ -15,6 +16,17 @@ config SND_DAVINCI_SOC_MCASP
config SND_DAVINCI_SOC_VCIF
tristate
config SND_AM33XX_SOC_EVM
tristate "SoC Audio for the AM33XX chip based boards"
depends on SND_DAVINCI_SOC && SOC_AM33XX
select SND_SOC_TLV320AIC3X
select SND_DAVINCI_SOC_MCASP
help
Say Y or M if you want to add support for SoC audio on AM33XX
boards using McASP and TLV320AIC3X codec. For example AM335X-EVM,
AM335X-EVMSK, and BeagelBone with AudioCape boards have this
setup.
config SND_DAVINCI_SOC_EVM
tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
depends on SND_DAVINCI_SOC

View file

@ -13,6 +13,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
snd-soc-evm-objs := davinci-evm.o
obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o
obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o

View file

@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/platform_data/edma.h>
#include <linux/i2c.h>
#include <linux/of_platform.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@ -23,10 +24,16 @@
#include <asm/dma.h>
#include <asm/mach-types.h>
#include <linux/edma.h>
#include "davinci-pcm.h"
#include "davinci-i2s.h"
#include "davinci-mcasp.h"
struct snd_soc_card_drvdata_davinci {
unsigned sysclk;
};
#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
static int evm_hw_params(struct snd_pcm_substream *substream,
@ -35,27 +42,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *soc_card = codec->card;
int ret = 0;
unsigned sysclk;
/* ASP1 on DM355 EVM is clocked by an external oscillator */
if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
machine_is_davinci_dm365_evm())
sysclk = 27000000;
/* ASP0 in DM6446 EVM is clocked by U55, as configured by
* board-dm644x-evm.c using GPIOs from U18. There are six
* options; here we "know" we use a 48 KHz sample rate.
*/
else if (machine_is_davinci_evm())
sysclk = 12288000;
else if (machine_is_davinci_da830_evm() ||
machine_is_davinci_da850_evm())
sysclk = 24576000;
else
return -EINVAL;
unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
snd_soc_card_get_drvdata(soc_card))->sysclk;
/* set codec DAI configuration */
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)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct device_node *np = codec->card->dev->of_node;
int ret;
/* Add davinci-evm specific widgets */
snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
ARRAY_SIZE(aic3x_dapm_widgets));
/* Set up davinci-evm specific audio path audio_map */
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
if (np) {
ret = snd_soc_of_parse_audio_routing(codec->card,
"ti,audio-routing");
if (ret)
return ret;
} else {
/* Set up davinci-evm specific audio path audio_map */
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
}
/* not connected */
snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
@ -243,35 +243,65 @@ static struct snd_soc_dai_link da850_evm_dai = {
};
/* davinci dm6446 evm audio machine driver */
/*
* ASP0 in DM6446 EVM is clocked by U55, as configured by
* board-dm644x-evm.c using GPIOs from U18. There are six
* options; here we "know" we use a 48 KHz sample rate.
*/
static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
.sysclk = 12288000,
};
static struct snd_soc_card dm6446_snd_soc_card_evm = {
.name = "DaVinci DM6446 EVM",
.owner = THIS_MODULE,
.dai_link = &dm6446_evm_dai,
.num_links = 1,
.drvdata = &dm6446_snd_soc_card_drvdata,
};
/* davinci dm355 evm audio machine driver */
/* ASP1 on DM355 EVM is clocked by an external oscillator */
static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
.sysclk = 27000000,
};
static struct snd_soc_card dm355_snd_soc_card_evm = {
.name = "DaVinci DM355 EVM",
.owner = THIS_MODULE,
.dai_link = &dm355_evm_dai,
.num_links = 1,
.drvdata = &dm355_snd_soc_card_drvdata,
};
/* davinci dm365 evm audio machine driver */
static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
.sysclk = 27000000,
};
static struct snd_soc_card dm365_snd_soc_card_evm = {
.name = "DaVinci DM365 EVM",
.owner = THIS_MODULE,
.dai_link = &dm365_evm_dai,
.num_links = 1,
.drvdata = &dm365_snd_soc_card_drvdata,
};
/* davinci dm6467 evm audio machine driver */
static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
.sysclk = 27000000,
};
static struct snd_soc_card dm6467_snd_soc_card_evm = {
.name = "DaVinci DM6467 EVM",
.owner = THIS_MODULE,
.dai_link = dm6467_evm_dai,
.num_links = ARRAY_SIZE(dm6467_evm_dai),
.drvdata = &dm6467_snd_soc_card_drvdata,
};
static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
.sysclk = 24576000,
};
static struct snd_soc_card da830_snd_soc_card = {
@ -279,6 +309,11 @@ static struct snd_soc_card da830_snd_soc_card = {
.owner = THIS_MODULE,
.dai_link = &da830_evm_dai,
.num_links = 1,
.drvdata = &da830_snd_soc_card_drvdata,
};
static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
.sysclk = 24576000,
};
static struct snd_soc_card da850_snd_soc_card = {
@ -286,8 +321,101 @@ static struct snd_soc_card da850_snd_soc_card = {
.owner = THIS_MODULE,
.dai_link = &da850_evm_dai,
.num_links = 1,
.drvdata = &da850_snd_soc_card_drvdata,
};
#if defined(CONFIG_OF)
/*
* The struct is used as place holder. It will be completely
* filled with data from dt node.
*/
static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
.name = "TLV320AIC3X",
.stream_name = "AIC3X",
.codec_dai_name = "tlv320aic3x-hifi",
.ops = &evm_ops,
.init = evm_aic3x_init,
};
static const struct of_device_id davinci_evm_dt_ids[] = {
{
.compatible = "ti,da830-evm-audio",
.data = (void *) &evm_dai_tlv320aic3x,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
/* davinci evm audio machine driver */
static struct snd_soc_card evm_soc_card = {
.owner = THIS_MODULE,
.num_links = 1,
};
static int davinci_evm_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match =
of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data;
struct snd_soc_card_drvdata_davinci *drvdata = NULL;
int ret = 0;
evm_soc_card.dai_link = dai;
dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
if (!dai->codec_of_node)
return -EINVAL;
dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
if (!dai->cpu_of_node)
return -EINVAL;
dai->platform_of_node = dai->cpu_of_node;
evm_soc_card.dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
if (ret)
return ret;
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
if (ret < 0)
return -EINVAL;
snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
return ret;
}
static int davinci_evm_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
return 0;
}
static struct platform_driver davinci_evm_driver = {
.probe = davinci_evm_probe,
.remove = davinci_evm_remove,
.driver = {
.name = "davinci_evm",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(davinci_evm_dt_ids),
},
};
#endif
static struct platform_device *evm_snd_device;
static int __init evm_init(void)
@ -296,6 +424,15 @@ static int __init evm_init(void)
int index;
int ret;
/*
* If dtb is there, the devices will be created dynamically.
* Only register platfrom driver structure.
*/
#if defined(CONFIG_OF)
if (of_have_populated_dt())
return platform_driver_register(&davinci_evm_driver);
#endif
if (machine_is_davinci_evm()) {
evm_snd_dev_data = &dm6446_snd_soc_card_evm;
index = 0;
@ -331,6 +468,13 @@ static int __init evm_init(void)
static void __exit evm_exit(void)
{
#if defined(CONFIG_OF)
if (of_have_populated_dt()) {
platform_driver_unregister(&davinci_evm_driver);
return;
}
#endif
platform_device_unregister(evm_snd_device);
}

View file

@ -1001,18 +1001,40 @@ static const struct snd_soc_component_driver davinci_mcasp_component = {
.name = "davinci-mcasp",
};
/* Some HW specific values and defaults. The rest is filled in from DT. */
static struct snd_platform_data dm646x_mcasp_pdata = {
.tx_dma_offset = 0x400,
.rx_dma_offset = 0x400,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_1,
};
static struct snd_platform_data da830_mcasp_pdata = {
.tx_dma_offset = 0x2000,
.rx_dma_offset = 0x2000,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_2,
};
static struct snd_platform_data omap2_mcasp_pdata = {
.tx_dma_offset = 0,
.rx_dma_offset = 0,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_3,
};
static const struct of_device_id mcasp_dt_ids[] = {
{
.compatible = "ti,dm646x-mcasp-audio",
.data = (void *)MCASP_VERSION_1,
.data = &dm646x_mcasp_pdata,
},
{
.compatible = "ti,da830-mcasp-audio",
.data = (void *)MCASP_VERSION_2,
.data = &da830_mcasp_pdata,
},
{
.compatible = "ti,omap2-mcasp-audio",
.data = (void *)MCASP_VERSION_3,
.compatible = "ti,am33xx-mcasp-audio",
.data = &omap2_mcasp_pdata,
},
{ /* sentinel */ }
};
@ -1025,9 +1047,9 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
struct snd_platform_data *pdata = NULL;
const struct of_device_id *match =
of_match_device(mcasp_dt_ids, &pdev->dev);
struct of_phandle_args dma_spec;
const u32 *of_serial_dir32;
u8 *of_serial_dir;
u32 val;
int i, ret = 0;
@ -1035,20 +1057,13 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
pdata = pdev->dev.platform_data;
return pdata;
} else if (match) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
ret = -ENOMEM;
goto nodata;
}
pdata = (struct snd_platform_data *) match->data;
} else {
/* control shouldn't reach here. something is wrong */
ret = -EINVAL;
goto nodata;
}
if (match->data)
pdata->version = (u8)((int)match->data);
ret = of_property_read_u32(np, "op-mode", &val);
if (ret >= 0)
pdata->op_mode = val;
@ -1065,35 +1080,46 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
pdata->tdm_slots = val;
}
ret = of_property_read_u32(np, "num-serializer", &val);
if (ret >= 0)
pdata->num_serializer = val;
of_serial_dir32 = of_get_property(np, "serial-dir", &val);
val /= sizeof(u32);
if (val != pdata->num_serializer) {
dev_err(&pdev->dev,
"num-serializer(%d) != serial-dir size(%d)\n",
pdata->num_serializer, val);
ret = -EINVAL;
goto nodata;
}
if (of_serial_dir32) {
of_serial_dir = devm_kzalloc(&pdev->dev,
(sizeof(*of_serial_dir) * val),
GFP_KERNEL);
u8 *of_serial_dir = devm_kzalloc(&pdev->dev,
(sizeof(*of_serial_dir) * val),
GFP_KERNEL);
if (!of_serial_dir) {
ret = -ENOMEM;
goto nodata;
}
for (i = 0; i < pdata->num_serializer; i++)
for (i = 0; i < val; i++)
of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]);
pdata->num_serializer = val;
pdata->serial_dir = of_serial_dir;
}
ret = of_property_match_string(np, "dma-names", "tx");
if (ret < 0)
goto nodata;
ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
&dma_spec);
if (ret < 0)
goto nodata;
pdata->tx_dma_channel = dma_spec.args[0];
ret = of_property_match_string(np, "dma-names", "rx");
if (ret < 0)
goto nodata;
ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
&dma_spec);
if (ret < 0)
goto nodata;
pdata->rx_dma_channel = dma_spec.args[0];
ret = of_property_read_u32(np, "tx-num-evt", &val);
if (ret >= 0)
pdata->txnumevt = val;
@ -1124,7 +1150,7 @@ nodata:
static int davinci_mcasp_probe(struct platform_device *pdev)
{
struct davinci_pcm_dma_params *dma_data;
struct resource *mem, *ioarea, *res;
struct resource *mem, *ioarea, *res, *dat;
struct snd_platform_data *pdata;
struct davinci_audio_dev *dev;
int ret;
@ -1145,10 +1171,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
return -EINVAL;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
if (!mem) {
dev_err(&pdev->dev, "no mem resource?\n");
return -ENODEV;
dev_warn(dev->dev,
"\"mpu\" mem resource not found, using index 0\n");
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?\n");
return -ENODEV;
}
}
ioarea = devm_request_mem_region(&pdev->dev, mem->start,
@ -1182,40 +1213,36 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
dev->rxnumevt = pdata->rxnumevt;
dev->dev = &pdev->dev;
dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
if (!dat)
dat = mem;
dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
dma_data->asp_chan_q = pdata->asp_chan_q;
dma_data->ram_chan_q = pdata->ram_chan_q;
dma_data->sram_pool = pdata->sram_pool;
dma_data->sram_size = pdata->sram_size_playback;
dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
mem->start);
dma_data->dma_addr = dat->start + pdata->tx_dma_offset;
/* first TX, then RX */
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENODEV;
goto err_release_clk;
}
dma_data->channel = res->start;
if (res)
dma_data->channel = res->start;
else
dma_data->channel = pdata->tx_dma_channel;
dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
dma_data->asp_chan_q = pdata->asp_chan_q;
dma_data->ram_chan_q = pdata->ram_chan_q;
dma_data->sram_pool = pdata->sram_pool;
dma_data->sram_size = pdata->sram_size_capture;
dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
mem->start);
dma_data->dma_addr = dat->start + pdata->rx_dma_offset;
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENODEV;
goto err_release_clk;
}
if (res)
dma_data->channel = res->start;
else
dma_data->channel = pdata->rx_dma_channel;
dma_data->channel = res->start;
dev_set_drvdata(&pdev->dev, dev);
ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
&davinci_mcasp_dai[pdata->op_mode], 1);
@ -1251,12 +1278,51 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int davinci_mcasp_suspend(struct device *dev)
{
struct davinci_audio_dev *a = dev_get_drvdata(dev);
void __iomem *base = a->base;
a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG);
a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG);
a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG);
a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG);
a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG);
a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG);
a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG);
return 0;
}
static int davinci_mcasp_resume(struct device *dev)
{
struct davinci_audio_dev *a = dev_get_drvdata(dev);
void __iomem *base = a->base;
mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl);
mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl);
mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt);
mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt);
mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl);
mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl);
mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir);
return 0;
}
#endif
SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops,
davinci_mcasp_suspend,
davinci_mcasp_resume);
static struct platform_driver davinci_mcasp_driver = {
.probe = davinci_mcasp_probe,
.remove = davinci_mcasp_remove,
.driver = {
.name = "davinci-mcasp",
.owner = THIS_MODULE,
.pm = &davinci_mcasp_pm_ops,
.of_match_table = mcasp_dt_ids,
},
};
@ -1266,4 +1332,3 @@ module_platform_driver(davinci_mcasp_driver);
MODULE_AUTHOR("Steve Chen");
MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
MODULE_LICENSE("GPL");

View file

@ -43,6 +43,18 @@ struct davinci_audio_dev {
/* McASP FIFO related */
u8 txnumevt;
u8 rxnumevt;
#ifdef CONFIG_PM_SLEEP
struct {
u32 txfmtctl;
u32 rxfmtctl;
u32 txfmt;
u32 rxfmt;
u32 aclkxctl;
u32 aclkrctl;
u32 pdir;
} context;
#endif
};
#endif /* DAVINCI_MCASP_H */