]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/arm/omap/omap-alsa-tsc2101.c
OMAP2EVM: twl4030 keypad Kconfig dependency fix
[linux-2.6-omap-h63xx.git] / sound / arm / omap / omap-alsa-tsc2101.c
1 /*
2  * sound/arm/omap/omap-alsa-tsc2101.c
3  *
4  * Alsa codec Driver for TSC2101 chip for OMAP platform boards.
5  * Code obtained from oss omap drivers
6  *
7  * Copyright (C) 2004 Texas Instruments, Inc.
8  *      Written by Nishanth Menon and Sriram Kannan
9  *
10  * Copyright (C) 2006 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
11  *      Alsa modularization by Daniel Petrini (d.pensator@gmail.com)
12  *
13  * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
14  *
15  * This program is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation; either version 2 of the License, or (at your
18  * option) any later version.
19  */
20
21 #include <linux/delay.h>
22 #include <linux/soundcard.h>
23 #include <linux/platform_device.h>
24 #include <linux/clk.h>
25 #include <linux/spi/tsc2101.h>
26 #include <linux/io.h>
27 #include <linux/slab.h>
28 #ifdef CONFIG_PM
29 #include <linux/pm.h>
30 #endif
31
32 #include <asm/mach-types.h>
33 #include <asm/arch/dma.h>
34 #include <asm/arch/clock.h>
35 #include <asm/arch/mcbsp.h>
36 #include <asm/hardware/tsc2101.h>
37 #include <asm/arch/omap-alsa.h>
38
39 #include "omap-alsa-tsc2101.h"
40
41 struct mcbsp_dev_info mcbsp_dev;
42
43 static struct clk *tsc2101_mclk;
44
45 /* #define DUMP_TSC2101_AUDIO_REGISTERS */
46 #undef DUMP_TSC2101_AUDIO_REGISTERS
47
48 /*
49  * Hardware capabilities
50  */
51
52 /*
53  * DAC USB-mode sampling rates (MCLK = 12 MHz)
54  * The rates and rate_reg_into MUST be in the same order
55  */
56 static unsigned int rates[] = {
57         7350, 8000, 8018, 8727,
58         8820, 9600, 11025, 12000,
59         14700, 16000, 22050, 24000,
60         29400, 32000, 44100, 48000,
61 };
62
63 static struct snd_pcm_hw_constraint_list tsc2101_hw_constraints_rates = {
64         .count = ARRAY_SIZE(rates),
65         .list = rates,
66         .mask = 0,
67 };
68
69 static const struct tsc2101_samplerate_reg_info
70     rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
71         /* Div 6 */
72         {7350, 7, 1},
73         {8000, 7, 0},
74         /* Div 5.5 */
75         {8018, 6, 1},
76         {8727, 6, 0},
77         /* Div 5 */
78         {8820, 5, 1},
79         {9600, 5, 0},
80         /* Div 4 */
81         {11025, 4, 1},
82         {12000, 4, 0},
83         /* Div 3 */
84         {14700, 3, 1},
85         {16000, 3, 0},
86         /* Div 2 */
87         {22050, 2, 1},
88         {24000, 2, 0},
89         /* Div 1.5 */
90         {29400, 1, 1},
91         {32000, 1, 0},
92         /* Div 1 */
93         {44100, 0, 1},
94         {48000, 0, 0},
95 };
96
97 static struct snd_pcm_hardware tsc2101_snd_omap_alsa_playback = {
98         .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
99                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID,
100 #ifdef CONFIG_MACH_OMAP_H6300
101         .formats = SNDRV_PCM_FMTBIT_S8,
102 #else
103         .formats = SNDRV_PCM_FMTBIT_S16_LE,
104 #endif
105         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
106                   SNDRV_PCM_RATE_16000 |
107                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
108                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
109                   SNDRV_PCM_RATE_KNOT,
110         .rate_min = 7350,
111         .rate_max = 48000,
112         .channels_min = 2,
113         .channels_max = 2,
114         .buffer_bytes_max = 128 * 1024,
115         .period_bytes_min = 32,
116         .period_bytes_max = 8 * 1024,
117         .periods_min = 16,
118         .periods_max = 255,
119         .fifo_size = 0,
120 };
121
122 static struct snd_pcm_hardware tsc2101_snd_omap_alsa_capture = {
123         .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
124                  SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID,
125         .formats = SNDRV_PCM_FMTBIT_S16_LE,
126         .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
127                   SNDRV_PCM_RATE_16000 |
128                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
129                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
130                   SNDRV_PCM_RATE_KNOT,
131         .rate_min = 7350,
132         .rate_max = 48000,
133         .channels_min = 2,
134         .channels_max = 2,
135         .buffer_bytes_max = 128 * 1024,
136         .period_bytes_min = 32,
137         .period_bytes_max = 8 * 1024,
138         .periods_min = 16,
139         .periods_max = 255,
140         .fifo_size = 0,
141 };
142
143 /*
144  * Simplified write for tsc2101 audio registers.
145  */
146 inline void tsc2101_audio_write(u8 address, u16 data)
147 {
148         tsc2101_write_sync(mcbsp_dev.tsc2101_dev, PAGE2_AUDIO_CODEC_REGISTERS,
149                                 address, data);
150 }
151
152 /*
153  * Simplified read for tsc2101 audio registers.
154  */
155 inline u16 tsc2101_audio_read(u8 address)
156 {
157         return (tsc2101_read_sync(mcbsp_dev.tsc2101_dev,
158                                         PAGE2_AUDIO_CODEC_REGISTERS, address));
159 }
160
161 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
162 void dump_tsc2101_audio_reg(void)
163 {
164         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
165                 "TSC2101_AUDIO_CTRL_1 = 0x%04x\n",
166                 tsc2101_audio_read(TSC2101_AUDIO_CTRL_1));
167         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
168                 "TSC2101_HEADSET_GAIN_CTRL = 0x%04x\n",
169                 tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL));
170         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
171                 "TSC2101_DAC_GAIN_CTRL = 0x%04x\n",
172                 tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL));
173         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
174                 "TSC2101_MIXER_PGA_CTRL = 0x%04x\n",
175                 tsc2101_audio_read(TSC2101_MIXER_PGA_CTRL));
176         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
177                 "TSC2101_AUDIO_CTRL_2 = 0x%04x\n",
178                 tsc2101_audio_read(TSC2101_AUDIO_CTRL_2));
179         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
180                 "TSC2101_CODEC_POWER_CTRL = 0x%04x\n",
181                 tsc2101_audio_read(TSC2101_CODEC_POWER_CTRL));
182         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
183                 "TSC2101_AUDIO_CTRL_3 = 0x%04x\n",
184                 tsc2101_audio_read(TSC2101_AUDIO_CTRL_3));
185         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
186                 "TSC2101_LCH_BASS_BOOST_N0 = 0x%04x\n",
187                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N0));
188         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
189                 "TSC2101_LCH_BASS_BOOST_N1 = 0x%04x\n",
190                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N1));
191         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
192                 "TSC2101_LCH_BASS_BOOST_N2 = 0x%04x\n",
193                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N2));
194         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
195                 "TSC2101_LCH_BASS_BOOST_N3 = 0x%04x\n",
196                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N3));
197         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
198                 "TSC2101_LCH_BASS_BOOST_N4 = 0x%04x\n",
199                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N4));
200         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
201                 "TSC2101_LCH_BASS_BOOST_N5 = 0x%04x\n",
202                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_N5));
203         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
204                 "TSC2101_LCH_BASS_BOOST_D1 = 0x%04x\n",
205                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D1));
206         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
207                 "TSC2101_LCH_BASS_BOOST_D2 = 0x%04x\n",
208                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D2));
209         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
210                 "TSC2101_LCH_BASS_BOOST_D4 = 0x%04x\n",
211                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D4));
212         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
213                 "TSC2101_LCH_BASS_BOOST_D5 = 0x%04x\n",
214                 tsc2101_audio_read(TSC2101_LCH_BASS_BOOST_D5));
215
216         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
217                 "TSC2101_RCH_BASS_BOOST_N0 = 0x%04x\n",
218                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N0));
219         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
220                 "TSC2101_RCH_BASS_BOOST_N1 = 0x%04x\n",
221                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N1));
222         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
223                 "TSC2101_RCH_BASS_BOOST_N2 = 0x%04x\n",
224                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N2));
225         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
226                 "TSC2101_RCH_BASS_BOOST_N3 = 0x%04x\n",
227                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N3));
228         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
229                 "TSC2101_RCH_BASS_BOOST_N4 = 0x%04x\n",
230                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N4));
231         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
232                 "TSC2101_RCH_BASS_BOOST_N5 = 0x%04x\n",
233                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_N5));
234         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
235                 "TSC2101_RCH_BASS_BOOST_D1 = 0x%04x\n",
236                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D1));
237         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
238                 "TSC2101_RCH_BASS_BOOST_D2 = 0x%04x\n",
239                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D2));
240         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
241                 "TSC2101_RCH_BASS_BOOST_D4 = 0x%04x\n",
242                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D4));
243         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
244                 "TSC2101_RCH_BASS_BOOST_D5 = 0x%04x\n",
245                 tsc2101_audio_read(TSC2101_RCH_BASS_BOOST_D5));
246
247         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
248                 "TSC2101_PLL_PROG_1 = 0x%04x\n",
249                 tsc2101_audio_read(TSC2101_PLL_PROG_1));
250         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
251                 "TSC2101_PLL_PROG_1 = 0x%04x\n",
252                 tsc2101_audio_read(TSC2101_PLL_PROG_2));
253         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
254                 "TSC2101_AUDIO_CTRL_4 = 0x%04x\n",
255                 tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
256         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
257                 "TSC2101_HANDSET_GAIN_CTRL = 0x%04x\n",
258                 tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL));
259         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
260                 "TSC2101_BUZZER_GAIN_CTRL = 0x%04x\n",
261                 tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL));
262         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
263                 "TSC2101_AUDIO_CTRL_5 = 0x%04x\n",
264                 tsc2101_audio_read(TSC2101_AUDIO_CTRL_5));
265         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
266                 "TSC2101_AUDIO_CTRL_6 = 0x%04x\n",
267                 tsc2101_audio_read(TSC2101_AUDIO_CTRL_6));
268         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
269                 "TSC2101_AUDIO_CTRL_7 = 0x%04x\n",
270                 tsc2101_audio_read(TSC2101_AUDIO_CTRL_7));
271         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
272                 "TSC2101_GPIO_CTRL = 0x%04x\n",
273                 tsc2101_audio_read(TSC2101_GPIO_CTRL));
274         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
275                 "TSC2101_AGC_CTRL = 0x%04x\n",
276                 tsc2101_audio_read(TSC2101_AGC_CTRL));
277         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
278                 "TSC2101_POWERDOWN_STS = 0x%04x\n",
279                 tsc2101_audio_read(TSC2101_POWERDOWN_STS));
280         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
281                 "TSC2101_MIC_AGC_CONTROL = 0x%04x\n",
282                 tsc2101_audio_read(TSC2101_MIC_AGC_CONTROL));
283         dev_dbg(&mcbsp_dev.mcbsp_dev->dev,
284                 "TSC2101_CELL_AGC_CONTROL = 0x%04x\n",
285                 tsc2101_audio_read(TSC2101_CELL_AGC_CONTROL));
286 }
287 #endif
288
289 /*
290  * ALSA operations according to board file
291  */
292
293 /*
294  * Sample rate changing
295  */
296 void tsc2101_set_samplerate(long sample_rate)
297 {
298         u8 count = 0;
299         u16 data = 0;
300         int clkgdv = 0;
301
302         u16 srgr1, srgr2;
303         /* wait for any frame to complete */
304         udelay(125);
305         ADEBUG();
306
307         sample_rate     = sample_rate;
308         /* Search for the right sample rate */
309         while ((rate_reg_info[count].sample_rate != sample_rate) &&
310                (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
311                 count++;
312         }
313         if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
314                 printk(KERN_ERR "Invalid Sample Rate %d requested\n",
315                        (int) sample_rate);
316                 return;
317         }
318
319         /* Set AC1 */
320         data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1);
321         /* Clear prev settings */
322         data    &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
323         data    |= AC1_DACFS(rate_reg_info[count].divisor) |
324                         AC1_ADCFS(rate_reg_info[count].divisor);
325         tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data);
326
327         /* Set the AC3 */
328         data    = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3);
329         /*Clear prev settings */
330         data    &= ~(AC3_REFFS | AC3_SLVMS);
331         data    |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
332 #ifdef TSC_MASTER
333         data    |= AC3_SLVMS;
334 #endif                          /* #ifdef TSC_MASTER */
335         tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
336
337         /*
338          * Program the PLLs. This code assumes that the 12 Mhz MCLK is in use.
339          * If MCLK rate is something else, these values must be changed.
340          * See the tsc2101 specification for the details.
341          */
342         if (rate_reg_info[count].fs_44kHz) {
343                 /* samplerate = (44.1kHZ / x), where x is int. */
344                 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
345                                 /* PVAL 1; I_VAL 7 */
346                                 PLL1_PVAL(1) | PLL1_I_VAL(7));
347                 /* D_VAL 5264 */
348                 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));
349         } else {
350                 /* samplerate = (48.kHZ / x), where x is int. */
351                 tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
352                                 /* PVAL 1; I_VAL 8 */
353                                PLL1_PVAL(1) | PLL1_I_VAL(8));
354                 /* D_VAL 1920 */
355                 tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));
356         }
357
358         /* Set the sample rate */
359 #ifndef TSC_MASTER
360         clkgdv  = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1));
361         if (clkgdv)
362                 srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
363         else
364                 return (1);
365
366         /* Stereo Mode */
367         srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
368 #else
369         srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
370         srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
371
372 #endif                          /* end of #ifdef TSC_MASTER */
373         OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2);
374         OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1);
375 }
376
377 void tsc2101_configure(void)
378 {
379 }
380
381 /*
382  *  Omap MCBSP clock and Power Management configuration
383  *
384  *  Here we have some functions that allows clock to be enabled and
385  *   disabled only when needed. Besides doing clock configuration
386  *   it allows turn on/turn off audio when necessary.
387  */
388
389 /*
390  * Do clock framework mclk search
391  */
392 void tsc2101_clock_setup(void)
393 {
394         tsc2101_mclk = clk_get(0, "mclk");
395 }
396
397 /*
398  * Do some sanity check, set clock rate, starts it and turn codec audio on
399  */
400 int tsc2101_clock_on(void)
401 {
402         int     curUseCount;
403         uint    curRate;
404         int     err;
405
406         curUseCount     = clk_get_usecount(tsc2101_mclk);
407         DPRINTK("clock use count = %d\n", curUseCount);
408         if (curUseCount > 0) {
409                 /* MCLK is already in use */
410                 printk(KERN_WARNING
411                        "MCLK already in use at %d Hz. We change it to %d Hz\n",
412                        (uint) clk_get_rate(tsc2101_mclk),
413                        CODEC_CLOCK);
414         }
415         curRate = (uint)clk_get_rate(tsc2101_mclk);
416         if (curRate != CODEC_CLOCK) {
417                 err     = clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
418                 if (err) {
419                         printk(KERN_WARNING "Cannot set MCLK clock rate for "
420                                 "TSC2101 CODEC, error code = %d\n", err);
421                         return -ECANCELED;
422                 }
423         }
424         err             = clk_enable(tsc2101_mclk);
425         curRate         = (uint)clk_get_rate(tsc2101_mclk);
426         curUseCount     = clk_get_usecount(tsc2101_mclk);
427         DPRINTK("MCLK = %d [%d], usecount = %d, clk_enable retval = %d\n",
428                curRate,
429                CODEC_CLOCK,
430                curUseCount,
431                err);
432
433         /* Now turn the audio on */
434         tsc2101_write_sync(mcbsp_dev.tsc2101_dev, PAGE2_AUDIO_CODEC_REGISTERS,
435                                 TSC2101_CODEC_POWER_CTRL,
436                                 0x0000);
437         return 0;
438 }
439
440 /*
441  * Do some sanity check, turn clock off and then turn codec audio off
442  */
443 int tsc2101_clock_off(void)
444 {
445         int curUseCount;
446         int curRate;
447
448         curUseCount     = clk_get_usecount(tsc2101_mclk);
449         DPRINTK("clock use count = %d\n", curUseCount);
450         if  (curUseCount > 0) {
451                 curRate = clk_get_rate(tsc2101_mclk);
452                 DPRINTK("clock rate = %d\n", curRate);
453                 if (curRate != CODEC_CLOCK) {
454                         printk(KERN_WARNING
455                                "MCLK for audio should be %d Hz. But is %d Hz\n",
456                                (uint) clk_get_rate(tsc2101_mclk),
457                                CODEC_CLOCK);
458                 }
459                 clk_disable(tsc2101_mclk);
460                 DPRINTK("clock disabled\n");
461         }
462         tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
463                             ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
464         DPRINTK("audio codec off\n");
465         return 0;
466 }
467
468 int tsc2101_get_default_samplerate(void)
469 {
470         return DEFAULT_SAMPLE_RATE;
471 }
472
473 static int __devinit snd_omap_alsa_tsc2101_probe(struct platform_device *pdev)
474 {
475         struct spi_device *tsc2101;
476         int     ret;
477         struct  omap_alsa_codec_config *codec_cfg;
478
479         tsc2101 = dev_get_drvdata(&pdev->dev);
480         if (tsc2101 == NULL) {
481                 dev_err(&pdev->dev, "no platform data\n");
482                 return -ENODEV;
483         }
484         if (strncmp(tsc2101->modalias, "tsc2101", 8) != 0) {
485                 dev_err(&pdev->dev, "tsc2101 not found\n");
486                 return -EINVAL;
487         }
488         mcbsp_dev.mcbsp_dev = pdev;
489         mcbsp_dev.tsc2101_dev = tsc2101;
490
491         codec_cfg = pdev->dev.platform_data;
492         if (codec_cfg != NULL) {
493                 codec_cfg->hw_constraints_rates =
494                                                 &tsc2101_hw_constraints_rates;
495                 codec_cfg->snd_omap_alsa_playback =
496                                         &tsc2101_snd_omap_alsa_playback;
497                 codec_cfg->snd_omap_alsa_capture =
498                                                 &tsc2101_snd_omap_alsa_capture;
499                 codec_cfg->codec_configure_dev  = tsc2101_configure;
500                 codec_cfg->codec_set_samplerate = tsc2101_set_samplerate;
501                 codec_cfg->codec_clock_setup    = tsc2101_clock_setup;
502                 codec_cfg->codec_clock_on       = tsc2101_clock_on;
503                 codec_cfg->codec_clock_off      = tsc2101_clock_off;
504                 codec_cfg->get_default_samplerate =
505                                                 tsc2101_get_default_samplerate;
506                 ret = snd_omap_alsa_post_probe(pdev, codec_cfg);
507         } else
508                 ret = -ENODEV;
509         return ret;
510 }
511
512 static struct platform_driver omap_alsa_driver = {
513         .probe          = snd_omap_alsa_tsc2101_probe,
514         .remove         = snd_omap_alsa_remove,
515         .suspend        = snd_omap_alsa_suspend,
516         .resume         = snd_omap_alsa_resume,
517         .driver = {
518                 .name = "omap_alsa_mcbsp",
519         },
520 };
521
522 static int __init omap_alsa_tsc2101_init(void)
523 {
524         ADEBUG();
525 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
526         printk(KERN_INFO "omap_alsa_tsc2101_init()\n");
527         dump_tsc2101_audio_reg();
528 #endif
529         return platform_driver_register(&omap_alsa_driver);
530 }
531
532 static void __exit omap_alsa_tsc2101_exit(void)
533 {
534         ADEBUG();
535 #ifdef DUMP_TSC2101_AUDIO_REGISTERS
536         printk(KERN_INFO "omap_alsa_tsc2101_exit()\n");
537         dump_tsc2101_audio_reg();
538 #endif
539         platform_driver_unregister(&omap_alsa_driver);
540 }
541
542 module_init(omap_alsa_tsc2101_init);
543 module_exit(omap_alsa_tsc2101_exit);