OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [soc/] [pxa/] [poodle.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * poodle.c  --  SoC audio for Poodle
3
 *
4
 * Copyright 2005 Wolfson Microelectronics PLC.
5
 * Copyright 2005 Openedhand Ltd.
6
 *
7
 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
8
 *          Richard Purdie <richard@openedhand.com>
9
 *
10
 *  This program is free software; you can redistribute  it and/or modify it
11
 *  under  the terms of  the GNU General  Public License as published by the
12
 *  Free Software Foundation;  either version 2 of the  License, or (at your
13
 *  option) any later version.
14
 *
15
 */
16
 
17
#include <linux/module.h>
18
#include <linux/moduleparam.h>
19
#include <linux/timer.h>
20
#include <linux/interrupt.h>
21
#include <linux/platform_device.h>
22
#include <sound/driver.h>
23
#include <sound/core.h>
24
#include <sound/pcm.h>
25
#include <sound/soc.h>
26
#include <sound/soc-dapm.h>
27
 
28
#include <asm/mach-types.h>
29
#include <asm/hardware/locomo.h>
30
#include <asm/arch/pxa-regs.h>
31
#include <asm/arch/hardware.h>
32
#include <asm/arch/poodle.h>
33
#include <asm/arch/audio.h>
34
 
35
#include "../codecs/wm8731.h"
36
#include "pxa2xx-pcm.h"
37
#include "pxa2xx-i2s.h"
38
 
39
#define POODLE_HP        1
40
#define POODLE_HP_OFF    0
41
#define POODLE_SPK_ON    1
42
#define POODLE_SPK_OFF   0
43
 
44
 /* audio clock in Hz - rounded from 12.235MHz */
45
#define POODLE_AUDIO_CLOCK 12288000
46
 
47
static int poodle_jack_func;
48
static int poodle_spk_func;
49
 
50
static void poodle_ext_control(struct snd_soc_codec *codec)
51
{
52
        int spk = 0;
53
 
54
        /* set up jack connection */
55
        if (poodle_jack_func == POODLE_HP) {
56
                /* set = unmute headphone */
57
                locomo_gpio_write(&poodle_locomo_device.dev,
58
                        POODLE_LOCOMO_GPIO_MUTE_L, 1);
59
                locomo_gpio_write(&poodle_locomo_device.dev,
60
                        POODLE_LOCOMO_GPIO_MUTE_R, 1);
61
                snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
62
        } else {
63
                locomo_gpio_write(&poodle_locomo_device.dev,
64
                        POODLE_LOCOMO_GPIO_MUTE_L, 0);
65
                locomo_gpio_write(&poodle_locomo_device.dev,
66
                        POODLE_LOCOMO_GPIO_MUTE_R, 0);
67
                snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
68
        }
69
 
70
        if (poodle_spk_func == POODLE_SPK_ON)
71
                spk = 1;
72
 
73
        /* set the enpoints to their new connetion states */
74
        snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
75
 
76
        /* signal a DAPM event */
77
        snd_soc_dapm_sync_endpoints(codec);
78
}
79
 
80
static int poodle_startup(struct snd_pcm_substream *substream)
81
{
82
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
83
        struct snd_soc_codec *codec = rtd->socdev->codec;
84
 
85
        /* check the jack status at stream startup */
86
        poodle_ext_control(codec);
87
        return 0;
88
}
89
 
90
/* we need to unmute the HP at shutdown as the mute burns power on poodle */
91
static int poodle_shutdown(struct snd_pcm_substream *substream)
92
{
93
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
94
        struct snd_soc_codec *codec = rtd->socdev->codec;
95
 
96
        /* set = unmute headphone */
97
        locomo_gpio_write(&poodle_locomo_device.dev,
98
                POODLE_LOCOMO_GPIO_MUTE_L, 1);
99
        locomo_gpio_write(&poodle_locomo_device.dev,
100
                POODLE_LOCOMO_GPIO_MUTE_R, 1);
101
        return 0;
102
}
103
 
104
static int poodle_hw_params(struct snd_pcm_substream *substream,
105
        struct snd_pcm_hw_params *params)
106
{
107
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
108
        struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
109
        struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
110
        unsigned int clk = 0;
111
        int ret = 0;
112
 
113
        switch (params_rate(params)) {
114
        case 8000:
115
        case 16000:
116
        case 48000:
117
        case 96000:
118
                clk = 12288000;
119
                break;
120
        case 11025:
121
        case 22050:
122
        case 44100:
123
                clk = 11289600;
124
                break;
125
        }
126
 
127
        /* set codec DAI configuration */
128
        ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
129
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
130
        if (ret < 0)
131
                return ret;
132
 
133
        /* set cpu DAI configuration */
134
        ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
135
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
136
        if (ret < 0)
137
                return ret;
138
 
139
        /* set the codec system clock for DAC and ADC */
140
        ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
141
                SND_SOC_CLOCK_IN);
142
        if (ret < 0)
143
                return ret;
144
 
145
        /* set the I2S system clock as input (unused) */
146
        ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
147
                SND_SOC_CLOCK_IN);
148
        if (ret < 0)
149
                return ret;
150
 
151
        return 0;
152
}
153
 
154
static struct snd_soc_ops poodle_ops = {
155
        .startup = poodle_startup,
156
        .hw_params = poodle_hw_params,
157
        .shutdown = poodle_shutdown,
158
};
159
 
160
static int poodle_get_jack(struct snd_kcontrol *kcontrol,
161
        struct snd_ctl_elem_value *ucontrol)
162
{
163
        ucontrol->value.integer.value[0] = poodle_jack_func;
164
        return 0;
165
}
166
 
167
static int poodle_set_jack(struct snd_kcontrol *kcontrol,
168
        struct snd_ctl_elem_value *ucontrol)
169
{
170
        struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
171
 
172
        if (poodle_jack_func == ucontrol->value.integer.value[0])
173
                return 0;
174
 
175
        poodle_jack_func = ucontrol->value.integer.value[0];
176
        poodle_ext_control(codec);
177
        return 1;
178
}
179
 
180
static int poodle_get_spk(struct snd_kcontrol *kcontrol,
181
        struct snd_ctl_elem_value *ucontrol)
182
{
183
        ucontrol->value.integer.value[0] = poodle_spk_func;
184
        return 0;
185
}
186
 
187
static int poodle_set_spk(struct snd_kcontrol *kcontrol,
188
        struct snd_ctl_elem_value *ucontrol)
189
{
190
        struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
191
 
192
        if (poodle_spk_func == ucontrol->value.integer.value[0])
193
                return 0;
194
 
195
        poodle_spk_func = ucontrol->value.integer.value[0];
196
        poodle_ext_control(codec);
197
        return 1;
198
}
199
 
200
static int poodle_amp_event(struct snd_soc_dapm_widget *w, int event)
201
{
202
        if (SND_SOC_DAPM_EVENT_ON(event))
203
                locomo_gpio_write(&poodle_locomo_device.dev,
204
                        POODLE_LOCOMO_GPIO_AMP_ON, 0);
205
        else
206
                locomo_gpio_write(&poodle_locomo_device.dev,
207
                        POODLE_LOCOMO_GPIO_AMP_ON, 1);
208
 
209
        return 0;
210
}
211
 
212
/* poodle machine dapm widgets */
213
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
214
SND_SOC_DAPM_HP("Headphone Jack", NULL),
215
SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
216
};
217
 
218
/* Corgi machine audio_mapnections to the codec pins */
219
static const char *audio_map[][3] = {
220
 
221
        /* headphone connected to LHPOUT1, RHPOUT1 */
222
        {"Headphone Jack", NULL, "LHPOUT"},
223
        {"Headphone Jack", NULL, "RHPOUT"},
224
 
225
        /* speaker connected to LOUT, ROUT */
226
        {"Ext Spk", NULL, "ROUT"},
227
        {"Ext Spk", NULL, "LOUT"},
228
 
229
        {NULL, NULL, NULL},
230
};
231
 
232
static const char *jack_function[] = {"Off", "Headphone"};
233
static const char *spk_function[] = {"Off", "On"};
234
static const struct soc_enum poodle_enum[] = {
235
        SOC_ENUM_SINGLE_EXT(2, jack_function),
236
        SOC_ENUM_SINGLE_EXT(2, spk_function),
237
};
238
 
239
static const snd_kcontrol_new_t wm8731_poodle_controls[] = {
240
        SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack,
241
                poodle_set_jack),
242
        SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
243
                poodle_set_spk),
244
};
245
 
246
/*
247
 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
248
 */
249
static int poodle_wm8731_init(struct snd_soc_codec *codec)
250
{
251
        int i, err;
252
 
253
        snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
254
        snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
255
        snd_soc_dapm_set_endpoint(codec, "MICIN", 1);
256
 
257
        /* Add poodle specific controls */
258
        for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
259
                err = snd_ctl_add(codec->card,
260
                        snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
261
                if (err < 0)
262
                        return err;
263
        }
264
 
265
        /* Add poodle specific widgets */
266
        for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
267
                snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
268
        }
269
 
270
        /* Set up poodle specific audio path audio_map */
271
        for (i = 0; audio_map[i][0] != NULL; i++) {
272
                snd_soc_dapm_connect_input(codec, audio_map[i][0],
273
                        audio_map[i][1], audio_map[i][2]);
274
        }
275
 
276
        snd_soc_dapm_sync_endpoints(codec);
277
        return 0;
278
}
279
 
280
/* poodle digital audio interface glue - connects codec <--> CPU */
281
static struct snd_soc_dai_link poodle_dai = {
282
        .name = "WM8731",
283
        .stream_name = "WM8731",
284
        .cpu_dai = &pxa_i2s_dai,
285
        .codec_dai = &wm8731_dai,
286
        .init = poodle_wm8731_init,
287
        .ops = &poodle_ops,
288
};
289
 
290
/* poodle audio machine driver */
291
static struct snd_soc_machine snd_soc_machine_poodle = {
292
        .name = "Poodle",
293
        .dai_link = &poodle_dai,
294
        .num_links = 1,
295
};
296
 
297
/* poodle audio private data */
298
static struct wm8731_setup_data poodle_wm8731_setup = {
299
        .i2c_address = 0x1b,
300
};
301
 
302
/* poodle audio subsystem */
303
static struct snd_soc_device poodle_snd_devdata = {
304
        .machine = &snd_soc_machine_poodle,
305
        .platform = &pxa2xx_soc_platform,
306
        .codec_dev = &soc_codec_dev_wm8731,
307
        .codec_data = &poodle_wm8731_setup,
308
};
309
 
310
static struct platform_device *poodle_snd_device;
311
 
312
static int __init poodle_init(void)
313
{
314
        int ret;
315
 
316
        if (!machine_is_poodle())
317
                return -ENODEV;
318
 
319
        locomo_gpio_set_dir(&poodle_locomo_device.dev,
320
                POODLE_LOCOMO_GPIO_AMP_ON, 0);
321
        /* should we mute HP at startup - burning power ?*/
322
        locomo_gpio_set_dir(&poodle_locomo_device.dev,
323
                POODLE_LOCOMO_GPIO_MUTE_L, 0);
324
        locomo_gpio_set_dir(&poodle_locomo_device.dev,
325
                POODLE_LOCOMO_GPIO_MUTE_R, 0);
326
 
327
        poodle_snd_device = platform_device_alloc("soc-audio", -1);
328
        if (!poodle_snd_device)
329
                return -ENOMEM;
330
 
331
        platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata);
332
        poodle_snd_devdata.dev = &poodle_snd_device->dev;
333
        ret = platform_device_add(poodle_snd_device);
334
 
335
        if (ret)
336
                platform_device_put(poodle_snd_device);
337
 
338
        return ret;
339
}
340
 
341
static void __exit poodle_exit(void)
342
{
343
        platform_device_unregister(poodle_snd_device);
344
}
345
 
346
module_init(poodle_init);
347
module_exit(poodle_exit);
348
 
349
/* Module information */
350
MODULE_AUTHOR("Richard Purdie");
351
MODULE_DESCRIPTION("ALSA SoC Poodle");
352
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.