Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nuc900-ac97.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2010 Nuvoton technology corporation.
3  *
4  * Wan ZongShun <[email protected]>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation;version 2 of the License.
9  *
10  */
11 
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/device.h>
16 #include <linux/delay.h>
17 #include <linux/mutex.h>
18 #include <linux/suspend.h>
19 #include <sound/core.h>
20 #include <sound/pcm.h>
21 #include <sound/initval.h>
22 #include <sound/soc.h>
23 #include <linux/clk.h>
24 
25 #include <mach/mfp.h>
26 
27 #include "nuc900-audio.h"
28 
29 static DEFINE_MUTEX(ac97_mutex);
31 
32 static int nuc900_checkready(void)
33 {
35 
36  if (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS0) & CODEC_READY))
37  return -EPERM;
38 
39  return 0;
40 }
41 
42 /* AC97 controller reads codec register */
43 static unsigned short nuc900_ac97_read(struct snd_ac97 *ac97,
44  unsigned short reg)
45 {
47  unsigned long timeout = 0x10000, val;
48 
49  mutex_lock(&ac97_mutex);
50 
51  val = nuc900_checkready();
52  if (val) {
53  dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
54  goto out;
55  }
56 
57  /* set the R_WB bit and write register index */
58  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, R_WB | reg);
59 
60  /* set the valid frame bit and valid slots */
61  val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
63  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val);
64 
65  udelay(100);
66 
67  /* polling the AC_R_FINISH */
68  while (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_R_FINISH)
69  && timeout--)
70  mdelay(1);
71 
72  if (!timeout) {
73  dev_err(nuc900_audio->dev, "AC97 read register time out !\n");
74  val = -EPERM;
75  goto out;
76  }
77 
78  val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0) ;
79  val &= ~SLOT1_VALID;
80  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val);
81 
82  if (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS1) >> 2 != reg) {
83  dev_err(nuc900_audio->dev,
84  "R_INDEX of REG_ACTL_ACIS1 not match!\n");
85  }
86 
87  udelay(100);
88  val = (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS2) & 0xFFFF);
89 
90 out:
91  mutex_unlock(&ac97_mutex);
92  return val;
93 }
94 
95 /* AC97 controller writes to codec register */
96 static void nuc900_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
97  unsigned short val)
98 {
99  struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
100  unsigned long tmp, timeout = 0x10000;
101 
102  mutex_lock(&ac97_mutex);
103 
104  tmp = nuc900_checkready();
105  if (tmp)
106  dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
107 
108  /* clear the R_WB bit and write register index */
109  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, reg);
110 
111  /* write register value */
112  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS2, val);
113 
114  /* set the valid frame bit and valid slots */
115  tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
117  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
118 
119  udelay(100);
120 
121  /* polling the AC_W_FINISH */
122  while ((AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_W_FINISH)
123  && timeout--)
124  mdelay(1);
125 
126  if (!timeout)
127  dev_err(nuc900_audio->dev, "AC97 write register time out !\n");
128 
129  tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
130  tmp &= ~(SLOT1_VALID | SLOT2_VALID);
131  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
132 
133  mutex_unlock(&ac97_mutex);
134 
135 }
136 
137 static void nuc900_ac97_warm_reset(struct snd_ac97 *ac97)
138 {
139  struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
140  unsigned long val;
141 
142  mutex_lock(&ac97_mutex);
143 
144  /* warm reset AC 97 */
145  val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON);
146  val |= AC_W_RES;
147  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val);
148 
149  udelay(100);
150 
151  val = nuc900_checkready();
152  if (val)
153  dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
154 
155  mutex_unlock(&ac97_mutex);
156 }
157 
158 static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97)
159 {
160  struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
161  unsigned long val;
162 
163  mutex_lock(&ac97_mutex);
164 
165  /* reset Audio Controller */
166  val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
167  val |= ACTL_RESET_BIT;
168  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
169 
170  val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
171  val &= (~ACTL_RESET_BIT);
172  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
173 
174  /* reset AC-link interface */
175 
176  val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
177  val |= AC_RESET;
178  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
179 
180  val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
181  val &= ~AC_RESET;
182  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
183 
184  /* cold reset AC 97 */
185  val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON);
186  val |= AC_C_RES;
187  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val);
188 
189  val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON);
190  val &= (~AC_C_RES);
191  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val);
192 
193  udelay(100);
194 
195  mutex_unlock(&ac97_mutex);
196 
197 }
198 
199 /* AC97 controller operations */
201  .read = nuc900_ac97_read,
202  .write = nuc900_ac97_write,
203  .reset = nuc900_ac97_cold_reset,
204  .warm_reset = nuc900_ac97_warm_reset,
205 }
206 EXPORT_SYMBOL_GPL(soc_ac97_ops);
207 
208 static int nuc900_ac97_trigger(struct snd_pcm_substream *substream,
209  int cmd, struct snd_soc_dai *dai)
210 {
211  struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
212  int ret;
213  unsigned long val, tmp;
214 
215  ret = 0;
216 
217  switch (cmd) {
220  val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
221  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
222  tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
223  tmp |= (SLOT3_VALID | SLOT4_VALID | VALID_FRAME);
224  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
225 
226  tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR);
227  tmp |= (P_DMA_END_IRQ | P_DMA_MIDDLE_IRQ);
228  AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, tmp);
229  val |= AC_PLAY;
230  } else {
231  tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR);
232  tmp |= (R_DMA_END_IRQ | R_DMA_MIDDLE_IRQ);
233 
234  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, tmp);
235  val |= AC_RECORD;
236  }
237 
238  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
239 
240  break;
243  val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
244  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
245  tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
246  tmp &= ~(SLOT3_VALID | SLOT4_VALID);
247  AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
248 
249  AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, RESET_PRSR);
250  val &= ~AC_PLAY;
251  } else {
252  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, RESET_PRSR);
253  val &= ~AC_RECORD;
254  }
255 
256  AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
257 
258  break;
259  default:
260  ret = -EINVAL;
261  }
262 
263  return ret;
264 }
265 
266 static int nuc900_ac97_probe(struct snd_soc_dai *dai)
267 {
268  struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
269  unsigned long val;
270 
271  mutex_lock(&ac97_mutex);
272 
273  /* enable unit clock */
274  clk_enable(nuc900_audio->clk);
275 
276  /* enable audio controller and AC-link interface */
277  val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON);
278  val |= (IIS_AC_PIN_SEL | ACLINK_EN);
279  AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val);
280 
281  mutex_unlock(&ac97_mutex);
282 
283  return 0;
284 }
285 
286 static int nuc900_ac97_remove(struct snd_soc_dai *dai)
287 {
288  struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
289 
290  clk_disable(nuc900_audio->clk);
291  return 0;
292 }
293 
294 static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
295  .trigger = nuc900_ac97_trigger,
296 };
297 
298 static struct snd_soc_dai_driver nuc900_ac97_dai = {
299  .probe = nuc900_ac97_probe,
300  .remove = nuc900_ac97_remove,
301  .ac97_control = 1,
302  .playback = {
303  .rates = SNDRV_PCM_RATE_8000_48000,
304  .formats = SNDRV_PCM_FMTBIT_S16_LE,
305  .channels_min = 1,
306  .channels_max = 2,
307  },
308  .capture = {
309  .rates = SNDRV_PCM_RATE_8000_48000,
310  .formats = SNDRV_PCM_FMTBIT_S16_LE,
311  .channels_min = 1,
312  .channels_max = 2,
313  },
314  .ops = &nuc900_ac97_dai_ops,
315 };
316 
317 static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
318 {
319  struct nuc900_audio *nuc900_audio;
320  int ret;
321 
322  if (nuc900_ac97_data)
323  return -EBUSY;
324 
325  nuc900_audio = kzalloc(sizeof(struct nuc900_audio), GFP_KERNEL);
326  if (!nuc900_audio)
327  return -ENOMEM;
328 
329  spin_lock_init(&nuc900_audio->lock);
330 
331  nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
332  if (!nuc900_audio->res) {
333  ret = -ENODEV;
334  goto out0;
335  }
336 
337  if (!request_mem_region(nuc900_audio->res->start,
338  resource_size(nuc900_audio->res), pdev->name)) {
339  ret = -EBUSY;
340  goto out0;
341  }
342 
343  nuc900_audio->mmio = ioremap(nuc900_audio->res->start,
344  resource_size(nuc900_audio->res));
345  if (!nuc900_audio->mmio) {
346  ret = -ENOMEM;
347  goto out1;
348  }
349 
350  nuc900_audio->clk = clk_get(&pdev->dev, NULL);
351  if (IS_ERR(nuc900_audio->clk)) {
352  ret = PTR_ERR(nuc900_audio->clk);
353  goto out2;
354  }
355 
356  nuc900_audio->irq_num = platform_get_irq(pdev, 0);
357  if (!nuc900_audio->irq_num) {
358  ret = -EBUSY;
359  goto out3;
360  }
361 
362  nuc900_ac97_data = nuc900_audio;
363 
364  ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai);
365  if (ret)
366  goto out3;
367 
368  /* enbale ac97 multifunction pin */
369  mfp_set_groupg(nuc900_audio->dev, NULL);
370 
371  return 0;
372 
373 out3:
374  clk_put(nuc900_audio->clk);
375 out2:
376  iounmap(nuc900_audio->mmio);
377 out1:
378  release_mem_region(nuc900_audio->res->start,
379  resource_size(nuc900_audio->res));
380 out0:
381  kfree(nuc900_audio);
382  return ret;
383 }
384 
385 static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
386 {
387  snd_soc_unregister_dai(&pdev->dev);
388 
389  clk_put(nuc900_ac97_data->clk);
390  iounmap(nuc900_ac97_data->mmio);
391  release_mem_region(nuc900_ac97_data->res->start,
392  resource_size(nuc900_ac97_data->res));
393 
394  kfree(nuc900_ac97_data);
395  nuc900_ac97_data = NULL;
396 
397  return 0;
398 }
399 
400 static struct platform_driver nuc900_ac97_driver = {
401  .driver = {
402  .name = "nuc900-ac97",
403  .owner = THIS_MODULE,
404  },
405  .probe = nuc900_ac97_drvprobe,
406  .remove = __devexit_p(nuc900_ac97_drvremove),
407 };
408 
409 module_platform_driver(nuc900_ac97_driver);
410 
411 MODULE_AUTHOR("Wan ZongShun <[email protected]>");
412 MODULE_DESCRIPTION("NUC900 AC97 SoC driver!");
413 MODULE_LICENSE("GPL");
414 MODULE_ALIAS("platform:nuc900-ac97");