Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
[linux-2.6] / sound / soc / s3c24xx / s3c24xx_uda134x.c
1 /*
2  * Modifications by Christian Pellegrin <chripell@evolware.org>
3  *
4  * s3c24xx_uda134x.c  --  S3C24XX_UDA134X ALSA SoC Audio board driver
5  *
6  * Copyright 2007 Dension Audio Systems Ltd.
7  * Author: Zoltan Devai
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include <linux/module.h>
15 #include <linux/clk.h>
16 #include <linux/mutex.h>
17 #include <linux/gpio.h>
18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21 #include <sound/soc-dapm.h>
22 #include <sound/s3c24xx_uda134x.h>
23 #include <sound/uda134x.h>
24
25 #include <plat/regs-iis.h>
26
27 #include "s3c24xx-pcm.h"
28 #include "s3c24xx-i2s.h"
29 #include "../codecs/uda134x.h"
30
31
32 /* #define ENFORCE_RATES 1 */
33 /*
34   Unfortunately the S3C24XX in master mode has a limited capacity of
35   generating the clock for the codec. If you define this only rates
36   that are really available will be enforced. But be careful, most
37   user level application just want the usual sampling frequencies (8,
38   11.025, 22.050, 44.1 kHz) and anyway resampling is a costly
39   operation for embedded systems. So if you aren't very lucky or your
40   hardware engineer wasn't very forward-looking it's better to leave
41   this undefined. If you do so an approximate value for the requested
42   sampling rate in the range -/+ 5% will be chosen. If this in not
43   possible an error will be returned.
44 */
45
46 static struct clk *xtal;
47 static struct clk *pclk;
48 /* this is need because we don't have a place where to keep the
49  * pointers to the clocks in each substream. We get the clocks only
50  * when we are actually using them so we don't block stuff like
51  * frequency change or oscillator power-off */
52 static int clk_users;
53 static DEFINE_MUTEX(clk_lock);
54
55 static unsigned int rates[33 * 2];
56 #ifdef ENFORCE_RATES
57 static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
58         .count  = ARRAY_SIZE(rates),
59         .list   = rates,
60         .mask   = 0,
61 };
62 #endif
63
64 static struct platform_device *s3c24xx_uda134x_snd_device;
65
66 static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
67 {
68         int ret = 0;
69 #ifdef ENFORCE_RATES
70         struct snd_pcm_runtime *runtime = substream->runtime;;
71 #endif
72
73         mutex_lock(&clk_lock);
74         pr_debug("%s %d\n", __func__, clk_users);
75         if (clk_users == 0) {
76                 xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
77                 if (!xtal) {
78                         printk(KERN_ERR "%s cannot get xtal\n", __func__);
79                         ret = -EBUSY;
80                 } else {
81                         pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
82                                        "pclk");
83                         if (!pclk) {
84                                 printk(KERN_ERR "%s cannot get pclk\n",
85                                        __func__);
86                                 clk_put(xtal);
87                                 ret = -EBUSY;
88                         }
89                 }
90                 if (!ret) {
91                         int i, j;
92
93                         for (i = 0; i < 2; i++) {
94                                 int fs = i ? 256 : 384;
95
96                                 rates[i*33] = clk_get_rate(xtal) / fs;
97                                 for (j = 1; j < 33; j++)
98                                         rates[i*33 + j] = clk_get_rate(pclk) /
99                                                 (j * fs);
100                         }
101                 }
102         }
103         clk_users += 1;
104         mutex_unlock(&clk_lock);
105         if (!ret) {
106 #ifdef ENFORCE_RATES
107                 ret = snd_pcm_hw_constraint_list(runtime, 0,
108                                                  SNDRV_PCM_HW_PARAM_RATE,
109                                                  &hw_constraints_rates);
110                 if (ret < 0)
111                         printk(KERN_ERR "%s cannot set constraints\n",
112                                __func__);
113 #endif
114         }
115         return ret;
116 }
117
118 static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
119 {
120         mutex_lock(&clk_lock);
121         pr_debug("%s %d\n", __func__, clk_users);
122         clk_users -= 1;
123         if (clk_users == 0) {
124                 clk_put(xtal);
125                 xtal = NULL;
126                 clk_put(pclk);
127                 pclk = NULL;
128         }
129         mutex_unlock(&clk_lock);
130 }
131
132 static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
133                                         struct snd_pcm_hw_params *params)
134 {
135         struct snd_soc_pcm_runtime *rtd = substream->private_data;
136         struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
137         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
138         unsigned int clk = 0;
139         int ret = 0;
140         int clk_source, fs_mode;
141         unsigned long rate = params_rate(params);
142         long err, cerr;
143         unsigned int div;
144         int i, bi;
145
146         err = 999999;
147         bi = 0;
148         for (i = 0; i < 2*33; i++) {
149                 cerr = rates[i] - rate;
150                 if (cerr < 0)
151                         cerr = -cerr;
152                 if (cerr < err) {
153                         err = cerr;
154                         bi = i;
155                 }
156         }
157         if (bi / 33 == 1)
158                 fs_mode = S3C2410_IISMOD_256FS;
159         else
160                 fs_mode = S3C2410_IISMOD_384FS;
161         if (bi % 33 == 0) {
162                 clk_source = S3C24XX_CLKSRC_MPLL;
163                 div = 1;
164         } else {
165                 clk_source = S3C24XX_CLKSRC_PCLK;
166                 div = bi % 33;
167         }
168         pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
169
170         clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
171         pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
172                  fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
173                  clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
174                  div, clk, err);
175
176         if ((err * 100 / rate) > 5) {
177                 printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
178                        "too different from desired (%ld%%)\n",
179                        err * 100 / rate);
180                 return -EINVAL;
181         }
182
183         ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
184                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
185         if (ret < 0)
186                 return ret;
187
188         ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
189                         SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
190         if (ret < 0)
191                 return ret;
192
193         ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk,
194                         SND_SOC_CLOCK_IN);
195         if (ret < 0)
196                 return ret;
197
198         ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, fs_mode);
199         if (ret < 0)
200                 return ret;
201
202         ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
203                         S3C2410_IISMOD_32FS);
204         if (ret < 0)
205                 return ret;
206
207         ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
208                         S3C24XX_PRESCALE(div, div));
209         if (ret < 0)
210                 return ret;
211
212         /* set the codec system clock for DAC and ADC */
213         ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
214                         SND_SOC_CLOCK_OUT);
215         if (ret < 0)
216                 return ret;
217
218         return 0;
219 }
220
221 static struct snd_soc_ops s3c24xx_uda134x_ops = {
222         .startup = s3c24xx_uda134x_startup,
223         .shutdown = s3c24xx_uda134x_shutdown,
224         .hw_params = s3c24xx_uda134x_hw_params,
225 };
226
227 static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
228         .name = "UDA134X",
229         .stream_name = "UDA134X",
230         .codec_dai = &uda134x_dai,
231         .cpu_dai = &s3c24xx_i2s_dai,
232         .ops = &s3c24xx_uda134x_ops,
233 };
234
235 static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
236         .name = "S3C24XX_UDA134X",
237         .platform = &s3c24xx_soc_platform,
238         .dai_link = &s3c24xx_uda134x_dai_link,
239         .num_links = 1,
240 };
241
242 static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
243
244 static void setdat(int v)
245 {
246         gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
247 }
248
249 static void setclk(int v)
250 {
251         gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
252 }
253
254 static void setmode(int v)
255 {
256         gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
257 }
258
259 static struct uda134x_platform_data s3c24xx_uda134x = {
260         .l3 = {
261                 .setdat = setdat,
262                 .setclk = setclk,
263                 .setmode = setmode,
264                 .data_hold = 1,
265                 .data_setup = 1,
266                 .clock_high = 1,
267                 .mode_hold = 1,
268                 .mode = 1,
269                 .mode_setup = 1,
270         },
271 };
272
273 static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
274         .card = &snd_soc_s3c24xx_uda134x,
275         .codec_dev = &soc_codec_dev_uda134x,
276         .codec_data = &s3c24xx_uda134x,
277 };
278
279 static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
280 {
281         if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
282                 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
283                        "l3 %s pin already in use", fun);
284                 return -EBUSY;
285         }
286         gpio_direction_output(pin, 0);
287         return 0;
288 }
289
290 static int s3c24xx_uda134x_probe(struct platform_device *pdev)
291 {
292         int ret;
293
294         printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
295
296         s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
297         if (s3c24xx_uda134x_l3_pins == NULL) {
298                 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
299                        "unable to find platform data\n");
300                 return -ENODEV;
301         }
302         s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
303         s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
304
305         if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
306                                       "data") < 0)
307                 return -EBUSY;
308         if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
309                                       "clk") < 0) {
310                 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
311                 return -EBUSY;
312         }
313         if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
314                                       "mode") < 0) {
315                 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
316                 gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
317                 return -EBUSY;
318         }
319
320         s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
321         if (!s3c24xx_uda134x_snd_device) {
322                 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
323                        "Unable to register\n");
324                 return -ENOMEM;
325         }
326
327         platform_set_drvdata(s3c24xx_uda134x_snd_device,
328                              &s3c24xx_uda134x_snd_devdata);
329         s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
330         ret = platform_device_add(s3c24xx_uda134x_snd_device);
331         if (ret) {
332                 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
333                 platform_device_put(s3c24xx_uda134x_snd_device);
334         }
335
336         return ret;
337 }
338
339 static int s3c24xx_uda134x_remove(struct platform_device *pdev)
340 {
341         platform_device_unregister(s3c24xx_uda134x_snd_device);
342         gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
343         gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
344         gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
345         return 0;
346 }
347
348 static struct platform_driver s3c24xx_uda134x_driver = {
349         .probe  = s3c24xx_uda134x_probe,
350         .remove = s3c24xx_uda134x_remove,
351         .driver = {
352                 .name = "s3c24xx_uda134x",
353                 .owner = THIS_MODULE,
354         },
355 };
356
357 static int __init s3c24xx_uda134x_init(void)
358 {
359         return platform_driver_register(&s3c24xx_uda134x_driver);
360 }
361
362 static void __exit s3c24xx_uda134x_exit(void)
363 {
364         platform_driver_unregister(&s3c24xx_uda134x_driver);
365 }
366
367
368 module_init(s3c24xx_uda134x_init);
369 module_exit(s3c24xx_uda134x_exit);
370
371 MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
372 MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
373 MODULE_LICENSE("GPL");