Blame view

sound/soc/au1x/psc-i2s.c 10.5 KB
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
1
2
3
4
  /*
   * Au12x0/Au1550 PSC ALSA ASoC audio support.
   *
   * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
5
   *	Manuel Lauss <manuel.lauss@gmail.com>
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
6
7
8
9
10
11
12
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   * Au1xxx-PSC I2S glue.
   *
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
13
14
15
16
17
   * NOTE: so far only PSC slave mode (bit- and frameclock) is supported.
   */
  
  #include <linux/init.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
18
  #include <linux/slab.h>
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  #include <linux/suspend.h>
  #include <sound/core.h>
  #include <sound/pcm.h>
  #include <sound/initval.h>
  #include <sound/soc.h>
  #include <asm/mach-au1x00/au1000.h>
  #include <asm/mach-au1x00/au1xxx_psc.h>
  
  #include "psc.h"
  
  /* supported I2S DAI hardware formats */
  #define AU1XPSC_I2S_DAIFMT \
  	(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J |	\
  	 SND_SOC_DAIFMT_NB_NF)
  
  /* supported I2S direction */
  #define AU1XPSC_I2S_DIR \
  	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
  
  #define AU1XPSC_I2S_RATES \
  	SNDRV_PCM_RATE_8000_192000
  
  #define AU1XPSC_I2S_FMTS \
  	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
  
  #define I2SSTAT_BUSY(stype)	\
25942fdc8   Manuel Lauss   ASoC: au1x: use s...
45
  	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
46
  #define I2SPCR_START(stype)	\
25942fdc8   Manuel Lauss   ASoC: au1x: use s...
47
  	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TS : PSC_I2SPCR_RS)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
48
  #define I2SPCR_STOP(stype)	\
25942fdc8   Manuel Lauss   ASoC: au1x: use s...
49
  	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TP : PSC_I2SPCR_RP)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
50
  #define I2SPCR_CLRFIFO(stype)	\
25942fdc8   Manuel Lauss   ASoC: au1x: use s...
51
  	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
52

4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
53
54
55
  static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
  			       unsigned int fmt)
  {
ffc4fdbbe   Manuel Lauss   ASoC: fix au1x pl...
56
  	struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(cpu_dai);
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	unsigned long ct;
  	int ret;
  
  	ret = -EINVAL;
  
  	ct = pscdata->cfg;
  
  	ct &= ~(PSC_I2SCFG_XM | PSC_I2SCFG_MLJ);	/* left-justified */
  	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  	case SND_SOC_DAIFMT_I2S:
  		ct |= PSC_I2SCFG_XM;	/* enable I2S mode */
  		break;
  	case SND_SOC_DAIFMT_MSB:
  		break;
  	case SND_SOC_DAIFMT_LSB:
  		ct |= PSC_I2SCFG_MLJ;	/* LSB (right-) justified */
  		break;
  	default:
  		goto out;
  	}
  
  	ct &= ~(PSC_I2SCFG_BI | PSC_I2SCFG_WI);		/* IB-IF */
  	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  	case SND_SOC_DAIFMT_NB_NF:
  		ct |= PSC_I2SCFG_BI | PSC_I2SCFG_WI;
  		break;
  	case SND_SOC_DAIFMT_NB_IF:
  		ct |= PSC_I2SCFG_BI;
  		break;
  	case SND_SOC_DAIFMT_IB_NF:
  		ct |= PSC_I2SCFG_WI;
  		break;
  	case SND_SOC_DAIFMT_IB_IF:
  		break;
  	default:
  		goto out;
  	}
  
  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  	case SND_SOC_DAIFMT_CBM_CFM:	/* CODEC master */
  		ct |= PSC_I2SCFG_MS;	/* PSC I2S slave mode */
  		break;
  	case SND_SOC_DAIFMT_CBS_CFS:	/* CODEC slave */
  		ct &= ~PSC_I2SCFG_MS;	/* PSC I2S Master mode */
  		break;
  	default:
  		goto out;
  	}
  
  	pscdata->cfg = ct;
  	ret = 0;
  out:
  	return ret;
  }
  
  static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
dee89c4d9   Mark Brown   ASoC: Merge snd_s...
113
114
  				 struct snd_pcm_hw_params *params,
  				 struct snd_soc_dai *dai)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
115
  {
ffc4fdbbe   Manuel Lauss   ASoC: fix au1x pl...
116
  	struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  
  	int cfgbits;
  	unsigned long stat;
  
  	/* check if the PSC is already streaming data */
  	stat = au_readl(I2S_STAT(pscdata));
  	if (stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB)) {
  		/* reject parameters not currently set up in hardware */
  		cfgbits = au_readl(I2S_CFG(pscdata));
  		if ((PSC_I2SCFG_GET_LEN(cfgbits) != params->msbits) ||
  		    (params_rate(params) != pscdata->rate))
  			return -EINVAL;
  	} else {
  		/* set sample bitdepth */
  		pscdata->cfg &= ~(0x1f << 4);
  		pscdata->cfg |= PSC_I2SCFG_SET_LEN(params->msbits);
  		/* remember current rate for other stream */
  		pscdata->rate = params_rate(params);
  	}
  	return 0;
  }
  
  /* Configure PSC late:  on my devel systems the codec  is I2S master and
   * supplies the i2sbitclock __AND__ i2sMclk (!) to the PSC unit.  ASoC
   * uses aggressive PM and  switches the codec off  when it is not in use
   * which also means the PSC unit doesn't get any clocks and is therefore
   * dead. That's why this chunk here gets called from the trigger callback
   * because I can be reasonably certain the codec is driving the clocks.
   */
  static int au1xpsc_i2s_configure(struct au1xpsc_audio_data *pscdata)
  {
  	unsigned long tmo;
  
  	/* bring PSC out of sleep, and configure I2S unit */
  	au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
  	au_sync();
  
  	tmo = 1000000;
  	while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo)
  		tmo--;
  
  	if (!tmo)
  		goto psc_err;
  
  	au_writel(0, I2S_CFG(pscdata));
  	au_sync();
  	au_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata));
  	au_sync();
  
  	/* wait for I2S controller to become ready */
  	tmo = 1000000;
  	while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo)
  		tmo--;
  
  	if (tmo)
  		return 0;
  
  psc_err:
  	au_writel(0, I2S_CFG(pscdata));
  	au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
  	au_sync();
  	return -ETIMEDOUT;
  }
  
  static int au1xpsc_i2s_start(struct au1xpsc_audio_data *pscdata, int stype)
  {
  	unsigned long tmo, stat;
  	int ret;
  
  	ret = 0;
  
  	/* if both TX and RX are idle, configure the PSC  */
  	stat = au_readl(I2S_STAT(pscdata));
  	if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
  		ret = au1xpsc_i2s_configure(pscdata);
  		if (ret)
  			goto out;
  	}
  
  	au_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata));
  	au_sync();
  	au_writel(I2SPCR_START(stype), I2S_PCR(pscdata));
  	au_sync();
  
  	/* wait for start confirmation */
  	tmo = 1000000;
  	while (!(au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
  		tmo--;
  
  	if (!tmo) {
  		au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
  		au_sync();
  		ret = -ETIMEDOUT;
  	}
  out:
  	return ret;
  }
  
  static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
  {
  	unsigned long tmo, stat;
  
  	au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
  	au_sync();
  
  	/* wait for stop confirmation */
  	tmo = 1000000;
  	while ((au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
  		tmo--;
  
  	/* if both TX and RX are idle, disable PSC */
  	stat = au_readl(I2S_STAT(pscdata));
2b30a55d4   Roel Kluin   ALSA: Au1xpsc: ps...
229
  	if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
230
231
232
233
234
235
236
  		au_writel(0, I2S_CFG(pscdata));
  		au_sync();
  		au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
  		au_sync();
  	}
  	return 0;
  }
dee89c4d9   Mark Brown   ASoC: Merge snd_s...
237
238
  static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
  			       struct snd_soc_dai *dai)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
239
  {
ffc4fdbbe   Manuel Lauss   ASoC: fix au1x pl...
240
  	struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
25942fdc8   Manuel Lauss   ASoC: au1x: use s...
241
  	int ret, stype = substream->stream;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  
  	switch (cmd) {
  	case SNDRV_PCM_TRIGGER_START:
  	case SNDRV_PCM_TRIGGER_RESUME:
  		ret = au1xpsc_i2s_start(pscdata, stype);
  		break;
  	case SNDRV_PCM_TRIGGER_STOP:
  	case SNDRV_PCM_TRIGGER_SUSPEND:
  		ret = au1xpsc_i2s_stop(pscdata, stype);
  		break;
  	default:
  		ret = -EINVAL;
  	}
  	return ret;
  }
5b0912be7   Manuel Lauss   ASoC: au1x: remov...
257
258
259
260
261
262
263
  static int au1xpsc_i2s_startup(struct snd_pcm_substream *substream,
  			       struct snd_soc_dai *dai)
  {
  	struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
  	snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
  	return 0;
  }
85e7652d8   Lars-Peter Clausen   ASoC: Constify sn...
264
  static const struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
5b0912be7   Manuel Lauss   ASoC: au1x: remov...
265
  	.startup	= au1xpsc_i2s_startup,
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
266
267
268
269
  	.trigger	= au1xpsc_i2s_trigger,
  	.hw_params	= au1xpsc_i2s_hw_params,
  	.set_fmt	= au1xpsc_i2s_set_fmt,
  };
ffc4fdbbe   Manuel Lauss   ASoC: fix au1x pl...
270
  static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  	.playback = {
  		.rates		= AU1XPSC_I2S_RATES,
  		.formats	= AU1XPSC_I2S_FMTS,
  		.channels_min	= 2,
  		.channels_max	= 8,	/* 2 without external help */
  	},
  	.capture = {
  		.rates		= AU1XPSC_I2S_RATES,
  		.formats	= AU1XPSC_I2S_FMTS,
  		.channels_min	= 2,
  		.channels_max	= 8,	/* 2 without external help */
  	},
  	.ops = &au1xpsc_i2s_dai_ops,
  };
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
285

0c74a939d   Manuel Lauss   ASoC: au1x: fix s...
286
  static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
287
  {
226d0f22d   Julia Lawall   ASoC: keep pointe...
288
  	struct resource *iores, *dmares;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
289
290
  	unsigned long sel;
  	int ret;
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
291
  	struct au1xpsc_audio_data *wd;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
292

aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
293
294
  	wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data),
  			  GFP_KERNEL);
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
295
  	if (!wd)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
296
  		return -ENOMEM;
226d0f22d   Julia Lawall   ASoC: keep pointe...
297
  	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
298
299
  	if (!iores)
  		return -ENODEV;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
300
301
  
  	ret = -EBUSY;
aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
302
303
304
305
  	if (!devm_request_mem_region(&pdev->dev, iores->start,
  				     resource_size(iores),
  				     pdev->name))
  		return -EBUSY;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
306

aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
307
308
  	wd->mmio = devm_ioremap(&pdev->dev, iores->start,
  				resource_size(iores));
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
309
  	if (!wd->mmio)
aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
310
  		return -EBUSY;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
311

226d0f22d   Julia Lawall   ASoC: keep pointe...
312
313
  	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
  	if (!dmares)
aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
314
  		return -EBUSY;
226d0f22d   Julia Lawall   ASoC: keep pointe...
315
  	wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
5b0912be7   Manuel Lauss   ASoC: au1x: remov...
316

226d0f22d   Julia Lawall   ASoC: keep pointe...
317
318
  	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
  	if (!dmares)
aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
319
  		return -EBUSY;
226d0f22d   Julia Lawall   ASoC: keep pointe...
320
  	wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
5b0912be7   Manuel Lauss   ASoC: au1x: remov...
321

4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
322
323
324
  	/* preserve PSC clock source set up by platform (dev.platform_data
  	 * is already occupied by soc layer)
  	 */
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
325
326
  	sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
  	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
327
  	au_sync();
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
328
329
  	au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd));
  	au_writel(0, I2S_CFG(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
330
331
332
  	au_sync();
  
  	/* preconfigure: set max rx/tx fifo depths */
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
333
  	wd->cfg |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
334
335
336
337
338
  
  	/* don't wait for I2S core to become ready now; clocks may not
  	 * be running yet; depending on clock input for PSC a wait might
  	 * time out.
  	 */
ffc4fdbbe   Manuel Lauss   ASoC: fix au1x pl...
339
340
341
342
343
344
  	/* name the DAI like this device instance ("au1xpsc-i2s.PSCINDEX") */
  	memcpy(&wd->dai_drv, &au1xpsc_i2s_dai_template,
  	       sizeof(struct snd_soc_dai_driver));
  	wd->dai_drv.name = dev_name(&pdev->dev);
  
  	platform_set_drvdata(pdev, wd);
aa4079c11   Julia Lawall   ASoC: psc-i2s.c: ...
345
  	return snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
346
  }
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
347
  static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
348
  {
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
349
  	struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
f0fba2ad1   Liam Girdwood   ASoC: multi-compo...
350
  	snd_soc_unregister_dai(&pdev->dev);
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
351
352
  
  	au_writel(0, I2S_CFG(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
353
  	au_sync();
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
354
  	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
355
  	au_sync();
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
356
  	return 0;
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
357
  }
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
358
359
  #ifdef CONFIG_PM
  static int au1xpsc_i2s_drvsuspend(struct device *dev)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
360
  {
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
361
  	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
362
  	/* save interesting register and disable PSC */
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
363
  	wd->pm[0] = au_readl(PSC_SEL(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
364

0f83d639d   Manuel Lauss   ASoC: au1x: conve...
365
  	au_writel(0, I2S_CFG(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
366
  	au_sync();
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
367
  	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
368
369
370
371
  	au_sync();
  
  	return 0;
  }
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
372
  static int au1xpsc_i2s_drvresume(struct device *dev)
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
373
  {
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
374
  	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
375
  	/* select I2S mode and PSC clock */
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
376
  	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
377
  	au_sync();
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
378
  	au_writel(0, PSC_SEL(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
379
  	au_sync();
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
380
  	au_writel(wd->pm[0], PSC_SEL(wd));
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
381
382
383
384
  	au_sync();
  
  	return 0;
  }
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
385
386
387
  static struct dev_pm_ops au1xpsci2s_pmops = {
  	.suspend	= au1xpsc_i2s_drvsuspend,
  	.resume		= au1xpsc_i2s_drvresume,
6335d0554   Eric Miao   ASoC: make ops a ...
388
  };
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
389
390
391
392
393
394
395
396
397
398
  #define AU1XPSCI2S_PMOPS &au1xpsci2s_pmops
  
  #else
  
  #define AU1XPSCI2S_PMOPS NULL
  
  #endif
  
  static struct platform_driver au1xpsc_i2s_driver = {
  	.driver		= {
ffc4fdbbe   Manuel Lauss   ASoC: fix au1x pl...
399
  		.name	= "au1xpsc_i2s",
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
400
401
  		.owner	= THIS_MODULE,
  		.pm	= AU1XPSCI2S_PMOPS,
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
402
  	},
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
403
404
  	.probe		= au1xpsc_i2s_drvprobe,
  	.remove		= __devexit_p(au1xpsc_i2s_drvremove),
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
405
  };
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
406

8a124f9cc   Axel Lin   ASoC: Convert au1...
407
  module_platform_driver(au1xpsc_i2s_driver);
4a161d235   Manuel Lauss   ALSA: ASoC: Au12x...
408
409
410
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
0f83d639d   Manuel Lauss   ASoC: au1x: conve...
411
  MODULE_AUTHOR("Manuel Lauss");