1 --- a/arch/arm/mach-ep93xx/include/mach/hardware.h
2 +++ b/arch/arm/mach-ep93xx/include/mach/hardware.h
4 #define __ASM_ARCH_HARDWARE_H
6 #include "ep93xx-regs.h"
7 +#include "regs_ac97.h"
9 #define pcibios_assign_all_busses() 0
10 #include "regs_raster.h"
12 +++ b/arch/arm/mach-ep93xx/include/mach/regs_ac97.h
14 +/*=============================================================================
17 + * DESCRIPTION: Ac'97 Register Definition
19 + * Copyright Cirrus Logic, 2001-2003
21 + * This program is free software; you can redistribute it and/or modify
22 + * it under the terms of the GNU General Public License as published by
23 + * the Free Software Foundation; either version 2 of the License, or
24 + * (at your option) any later version.
26 + * This program is distributed in the hope that it will be useful,
27 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 + * GNU General Public License for more details.
31 + * You should have received a copy of the GNU General Public License
32 + * along with this program; if not, write to the Free Software
33 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 + *=============================================================================
36 +#ifndef _REGS_AC97_H_
37 +#define _REGS_AC97_H_
39 +//-----------------------------------------------------------------------------
41 +//-----------------------------------------------------------------------------
42 +#define AC97ISR_RIS 8
43 +#define AC97ISR_TIS 4
44 +#define AC97ISR_RTIS 2
45 +#define AC97ISR_TCIS 1
47 +#define AC97RGIS_SLOT1TXCOMPLETE 0x01
48 +#define AC97RGIS_SLOT2RXVALID 0x02
49 +#define AC97RGIS_GPIOTXCOMPLETE 0x04
50 +#define AC97RGIS_GPIOINTRX 0x08
51 +#define AC97RGIS_RWIS 0x10
52 +#define AC97RGIS_CODECREADY 0x20
53 +#define AC97RGIS_SLOT2TXCOMPLETE 0x40
55 +#define AC97SR_RXFE 0x0001
56 +#define AC97SR_TXFE 0x0002
57 +#define AC97SR_RXFF 0x0004
58 +#define AC97SR_TXFF 0x0008
59 +#define AC97SR_TXBUSY 0x0010
60 +#define AC97SR_RXOE 0x0020
61 +#define AC97SR_TXUE 0x0040
63 +#define AC97GSR_IFE 0x1
64 +#define AC97GSR_LOOP 0x2
65 +#define AC97GSR_OVERRIDECODECREADY 0x4
67 +#define AC97RESET_TIMEDRESET 0x1
68 +#define AC97RESET_FORCEDRESET 0x2
69 +#define AC97RESET_EFORCER 0x4
71 +#define AC97RXCR_REN 0x1
73 +#define AC97TXCR_TEN 0x1
76 +//****************************************************************************
78 +// The Ac97 Codec registers, accessable through the Ac-link.
79 +// These are not controller registers and are not memory mapped.
80 +// Includes registers specific to CS4202 (Beavis).
82 +//****************************************************************************
83 +#define AC97_REG_OFFSET_MASK 0x0000007E
85 +#define AC97_00_RESET 0x00000000
86 +#define AC97_02_MASTER_VOL 0x00000002
87 +#define AC97_04_HEADPHONE_VOL 0x00000004
88 +#define AC97_06_MONO_VOL 0x00000006
89 +#define AC97_08_TONE 0x00000008
90 +#define AC97_0A_PC_BEEP_VOL 0x0000000A
91 +#define AC97_0C_PHONE_VOL 0x0000000C
92 +#define AC97_0E_MIC_VOL 0x0000000E
93 +#define AC97_10_LINE_IN_VOL 0x00000010
94 +#define AC97_12_CD_VOL 0x00000012
95 +#define AC97_14_VIDEO_VOL 0x00000014
96 +#define AC97_16_AUX_VOL 0x00000016
97 +#define AC97_18_PCM_OUT_VOL 0x00000018
98 +#define AC97_1A_RECORD_SELECT 0x0000001A
99 +#define AC97_1C_RECORD_GAIN 0x0000001C
100 +#define AC97_1E_RESERVED_1E 0x0000001E
101 +#define AC97_20_GENERAL_PURPOSE 0x00000020
102 +#define AC97_22_3D_CONTROL 0x00000022
103 +#define AC97_24_MODEM_RATE 0x00000024
104 +#define AC97_26_POWERDOWN 0x00000026
105 +#define AC97_28_EXT_AUDIO_ID 0x00000028
106 +#define AC97_2A_EXT_AUDIO_POWER 0x0000002A
107 +#define AC97_2C_PCM_FRONT_DAC_RATE 0x0000002C
108 +#define AC97_2E_PCM_SURR_DAC_RATE 0x0000002E
109 +#define AC97_30_PCM_LFE_DAC_RATE 0x00000030
110 +#define AC97_32_PCM_LR_ADC_RATE 0x00000032
111 +#define AC97_34_MIC_ADC_RATE 0x00000034
112 +#define AC97_36_6CH_VOL_C_LFE 0x00000036
113 +#define AC97_38_6CH_VOL_SURROUND 0x00000038
114 +#define AC97_3A_SPDIF_CONTROL 0x0000003A
115 +#define AC97_3C_EXT_MODEM_ID 0x0000003C
116 +#define AC97_3E_EXT_MODEM_POWER 0x0000003E
117 +#define AC97_40_LINE1_CODEC_RATE 0x00000040
118 +#define AC97_42_LINE2_CODEC_RATE 0x00000042
119 +#define AC97_44_HANDSET_CODEC_RATE 0x00000044
120 +#define AC97_46_LINE1_CODEC_LEVEL 0x00000046
121 +#define AC97_48_LINE2_CODEC_LEVEL 0x00000048
122 +#define AC97_4A_HANDSET_CODEC_LEVEL 0x0000004A
123 +#define AC97_4C_GPIO_PIN_CONFIG 0x0000004C
124 +#define AC97_4E_GPIO_PIN_TYPE 0x0000004E
125 +#define AC97_50_GPIO_PIN_STICKY 0x00000050
126 +#define AC97_52_GPIO_PIN_WAKEUP 0x00000052
127 +#define AC97_54_GPIO_PIN_STATUS 0x00000054
128 +#define AC97_56_RESERVED 0x00000056
129 +#define AC97_58_RESERVED 0x00000058
130 +#define AC97_5A_CRYSTAL_REV_N_FAB_ID 0x0000005A
131 +#define AC97_5C_TEST_AND_MISC_CTRL 0x0000005C
132 +#define AC97_5E_AC_MODE 0x0000005E
133 +#define AC97_60_MISC_CRYSTAL_CONTROL 0x00000060
134 +#define AC97_62_VENDOR_RESERVED 0x00000062
135 +#define AC97_64_DAC_SRC_PHASE_INCR 0x00000064
136 +#define AC97_66_ADC_SRC_PHASE_INCR 0x00000066
137 +#define AC97_68_RESERVED_68 0x00000068
138 +#define AC97_6A_SERIAL_PORT_CONTROL 0x0000006A
139 +#define AC97_6C_VENDOR_RESERVED 0x0000006C
140 +#define AC97_6E_VENDOR_RESERVED 0x0000006E
141 +#define AC97_70_BDI_CONFIG 0x00000070
142 +#define AC97_72_BDI_WAKEUP 0x00000072
143 +#define AC97_74_VENDOR_RESERVED 0x00000074
144 +#define AC97_76_CAL_ADDRESS 0x00000076
145 +#define AC97_78_CAL_DATA 0x00000078
146 +#define AC97_7A_VENDOR_RESERVED 0x0000007A
147 +#define AC97_7C_VENDOR_ID1 0x0000007C
148 +#define AC97_7E_VENDOR_ID2 0x0000007E
151 +#ifndef __ASSEMBLY__
154 +// enum type for use with reg AC97_RECORD_SELECT
157 + RECORD_MIC = 0x0000,
158 + RECORD_CD = 0x0101,
159 + RECORD_VIDEO_IN = 0x0202,
160 + RECORD_AUX_IN = 0x0303,
161 + RECORD_LINE_IN = 0x0404,
162 + RECORD_STEREO_MIX = 0x0505,
163 + RECORD_MONO_MIX = 0x0606,
164 + RECORD_PHONE_IN = 0x0707
165 +} Ac97RecordSources;
167 +#endif /* __ASSEMBLY__ */
170 +// Sample rates supported directly in AC97_PCM_FRONT_DAC_RATE and
171 +// AC97_PCM_LR_ADC_RATE.
173 +#define Ac97_Fs_8000 0x1f40
174 +#define Ac97_Fs_11025 0x2b11
175 +#define Ac97_Fs_16000 0x3e80
176 +#define Ac97_Fs_22050 0x5622
177 +#define Ac97_Fs_32000 0x7d00
178 +#define Ac97_Fs_44100 0xac44
179 +#define Ac97_Fs_48000 0xbb80
182 +// RSIZE and TSIZE in AC97RXCR and AC97TXCR
184 +#define Ac97_SIZE_20 2
185 +#define Ac97_SIZE_18 1
186 +#define Ac97_SIZE_16 0
187 +#define Ac97_SIZE_12 3
189 +//=============================================================================
190 +//=============================================================================
193 +#endif /* _REGS_AC97_H_ */
194 --- a/sound/arm/Kconfig
195 +++ b/sound/arm/Kconfig
196 @@ -11,6 +11,23 @@ menuconfig SND_ARM
200 +config SND_EP93XX_AC97
201 + tristate "AC97 driver for the Cirrus EP93xx chip"
202 + depends on ARCH_EP93XX && SND
203 + select SND_EP93XX_PCM
204 + select SND_AC97_CODEC
206 + Say Y here to use AC'97 audio with a Cirrus Logic EP93xx chip.
208 + To compile this driver as a module, choose M here: the module
209 + will be called snd-ep93xx-ac97.
211 +config SND_EP93XX_PCM
215 + Generic PCM module for EP93xx
218 tristate "ARM PrimeCell PL041 AC Link support"
220 --- a/sound/arm/Makefile
221 +++ b/sound/arm/Makefile
223 obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
224 snd-aaci-objs := aaci.o devdma.o
226 +obj-$(CONFIG_SND_EP93XX_AC97) += snd-ep93xx-ac97.o
227 +snd-ep93xx-ac97-objs := ep93xx-ac97.o
229 obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
230 snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
233 +++ b/sound/arm/ep93xx-ac97.c
236 + * linux/sound/arm/ep93xx-ac97.c -- ALSA PCM interface for the edb93xx ac97 audio
239 +#include <linux/autoconf.h>
240 +#include <linux/module.h>
241 +#include <linux/init.h>
242 +#include <linux/platform_device.h>
243 +#include <linux/delay.h>
244 +#include <linux/soundcard.h>
246 +#include <sound/driver.h>
247 +#include <sound/core.h>
248 +#include <sound/pcm.h>
249 +#include <sound/pcm_params.h>
250 +#include <sound/control.h>
251 +#include <sound/initval.h>
252 +#include <sound/ac97_codec.h>
254 +#include <asm/irq.h>
255 +#include <asm/semaphore.h>
256 +#include <asm/hardware.h>
258 +#include <asm/arch/dma.h>
259 +#include "ep93xx-ac97.h"
261 +#define DRIVER_VERSION "01/05/2009"
262 +#define DRIVER_DESC "EP93xx AC97 Audio driver"
263 +static int ac_link_enabled = 0;
264 +static int codec_supported_mixers;
268 +#define DPRINTK( fmt, arg... ) printk( fmt, ##arg )
270 +#define DPRINTK( fmt, arg... )
276 +#define AUDIO_NAME "ep93xx-ac97"
277 +#define AUDIO_SAMPLE_RATE_DEFAULT 44100
278 +#define AUDIO_DEFAULT_VOLUME 0
279 +#define AUDIO_MAX_VOLUME 181
280 +#define AUDIO_DEFAULT_DMACHANNELS 3
281 +#define PLAYBACK_DEFAULT_DMACHANNELS 3
282 +#define CAPTURE_DEFAULT_DMACHANNELS 3
284 +#define CHANNEL_FRONT (1<<0)
285 +#define CHANNEL_REAR (1<<1)
286 +#define CHANNEL_CENTER_LFE (1<<2)
288 +static void snd_ep93xx_dma_tx_callback( ep93xx_dma_int_t DMAInt,
289 + ep93xx_dma_dev_t device,
290 + unsigned int user_data);
291 +static void snd_ep93xx_dma_rx_callback( ep93xx_dma_int_t DMAInt,
292 + ep93xx_dma_dev_t device,
293 + unsigned int user_data);
295 +static const struct snd_pcm_hardware ep93xx_ac97_pcm_hardware = {
298 + .info = ( SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE ),
299 + .formats = ( SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
300 + SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
301 + SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
302 + SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
303 + SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE ),
304 + .rates = ( SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
305 + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
306 + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
307 + SNDRV_PCM_RATE_48000 ),
310 + .channels_min = 1,/*2,*/
313 + .period_bytes_min = 1 * 1024,
314 + .period_bytes_max = 32 * 1024,
317 + .buffer_bytes_max = 32 * 1024,
321 +static audio_stream_t output_stream;
322 +static audio_stream_t input_stream;
324 +static audio_state_t audio_state =
326 + .output_stream =&output_stream,
327 + .output_dma[0] =DMATx_AAC1,
328 + .output_id[0] ="Ac97 out",
330 + .input_stream =&input_stream,
331 + .input_dma[0] =DMARx_AAC1,
332 + .input_id[0] ="Ac97 in",
334 + .sem = __SEMAPHORE_INIT(audio_state.sem,1),
335 + .codec_set_by_playback = 0,
336 + .codec_set_by_capture = 0,
337 + .DAC_bit_width =16,
346 + * Reads an AC97 codec register. Returns -1 if there was an error.
348 +static int peek(unsigned int uiAddress)
350 + unsigned int uiAC97RGIS;
352 + if( !ac_link_enabled )
354 + printk("ep93xx ac97 peek: attempt to peek before enabling ac-link.\n");
359 + * Check to make sure that the address is aligned on a word boundary
360 + * and is 7E or less.
362 + if( ((uiAddress & 0x1)!=0) || (uiAddress > 0x007e))
368 + * How it is supposed to work is:
369 + * - The ac97 controller sends out a read addr in slot 1.
370 + * - In the next frame, the codec will echo that address back in slot 1
371 + * and send the data in slot 2. SLOT2RXVALID will be set to 1.
373 + * Read until SLOT2RXVALID goes to 1. Reading the data in AC97S2DATA
374 + * clears SLOT2RXVALID.
378 + * First, delay one frame in case of back to back peeks/pokes.
383 + * Write the address to AC97S1DATA, delay 1 frame, read the flags.
385 + outl( uiAddress, AC97S1DATA);
387 + uiAC97RGIS = inl( AC97RGIS );
390 + * Return error if we timed out.
392 + if( ((uiAC97RGIS & AC97RGIS_SLOT1TXCOMPLETE) == 0 ) &&
393 + ((uiAC97RGIS & AC97RGIS_SLOT2RXVALID) == 0 ) )
395 + printk( "ep93xx-ac97 - peek failed reading reg 0x%02x.\n", uiAddress );
399 + return ( inl(AC97S2DATA) & 0x000fffff);
405 + * Writes an AC97 codec Register. Return -1 if error.
407 +static int poke(unsigned int uiAddress, unsigned int uiValue)
409 + unsigned int uiAC97RGIS;
411 + if( !ac_link_enabled )
413 + printk("ep93xx ac97 poke: attempt to poke before enabling ac-link.\n");
418 + * Check to make sure that the address is align on a word boundary and
419 + * is 7E or less. And that the value is a 16 bit value.
421 + if( ((uiAddress & 0x1)!=0) || (uiAddress > 0x007e))
423 + printk("ep93xx ac97 poke: address error.\n");
427 + /*stop the audio loop from the input to the output directly*/
429 + if((uiAddress==AC97_0E_MIC_VOL)||(uiAddress==AC97_10_LINE_IN_VOL))
431 + uiValue = (uiValue | 0x8000);
436 + * First, delay one frame in case of back to back peeks/pokes.
441 + * Write the data to AC97S2DATA, then the address to AC97S1DATA.
443 + outl( uiValue, AC97S2DATA );
444 + outl( uiAddress, AC97S1DATA );
447 + * Wait for the tx to complete, get status.
449 + udelay( 30 );/*21*/
450 + uiAC97RGIS = inl(AC97RGIS);
453 + * Return error if we timed out.
455 + if( !(inl(AC97RGIS) & AC97RGIS_SLOT1TXCOMPLETE) )
457 + printk( "ep93xx-ac97: poke failed writing reg 0x%02x value 0x%02x.\n", uiAddress, uiValue );
466 + * When we get to the multichannel case the pre-fill and enable code
467 + * will go to the dma driver's start routine.
469 +static void ep93xx_audio_enable( int input_or_output_stream )
471 + unsigned int uiTemp;
473 + DPRINTK("ep93xx_audio_enable :%x\n",input_or_output_stream);
476 + * Enable the rx or tx channel depending on the value of
477 + * input_or_output_stream
479 + if( input_or_output_stream )
481 + uiTemp = inl(AC97TXCR1);
482 + outl( (uiTemp | AC97TXCR_TEN), AC97TXCR1 );
486 + uiTemp = inl(AC97RXCR1);
487 + outl( (uiTemp | AC97RXCR_REN), AC97RXCR1 );
491 + //DDEBUG("ep93xx_audio_enable - EXIT\n");
494 +static void ep93xx_audio_disable( int input_or_output_stream )
496 + unsigned int uiTemp;
498 + DPRINTK("ep93xx_audio_disable\n");
501 + * Disable the rx or tx channel depending on the value of
502 + * input_or_output_stream
504 + if( input_or_output_stream )
506 + uiTemp = inl(AC97TXCR1);
507 + outl( (uiTemp & ~AC97TXCR_TEN), AC97TXCR1 );
511 + uiTemp = inl(AC97RXCR1);
512 + outl( (uiTemp & ~AC97RXCR_REN), AC97RXCR1 );
515 + //DDEBUG("ep93xx_audio_disable - EXIT\n");
520 +/*=======================================================================================*/
524 + * Once the ac-link is up and all is good, we want to set the codec to a
527 +static void ep93xx_setup_src(void)
532 + * Set the VRA bit to enable the SRC.
534 + iTemp = peek( AC97_2A_EXT_AUDIO_POWER );
535 + poke( AC97_2A_EXT_AUDIO_POWER, (iTemp | 0x1) );
538 + * Set the DSRC/ASRC bits to enable the variable rate SRC.
540 + iTemp = peek( AC97_60_MISC_CRYSTAL_CONTROL );
541 + poke( AC97_60_MISC_CRYSTAL_CONTROL, (iTemp | 0x0300) );
545 + * ep93xx_set_samplerate
547 + * lFrequency - Sample Rate in Hz
548 + * bCapture - 0 to set Tx sample rate; 1 to set Rx sample rate
550 +static void ep93xx_set_samplerate( long lSampleRate, int bCapture )
552 + unsigned short usDivider, usPhase;
554 + DPRINTK( "ep93xx_set_samplerate - Fs = %d\n", (int)lSampleRate );
556 + if( (lSampleRate < 7200) || (lSampleRate > 48000) )
558 + printk( "ep93xx_set_samplerate - invalid Fs = %d\n",
559 + (int)lSampleRate );
564 + * Calculate divider and phase increment.
566 + * divider = round( 0x1770000 / lSampleRate )
567 + * Note that usually rounding is done by adding 0.5 to a floating
568 + * value and then truncating. To do this without using floating
569 + * point, I multiply the fraction by two, do the division, then add one,
570 + * then divide the whole by 2 and then truncate.
571 + * Same effect, no floating point math.
573 + * Ph incr = trunc( (0x1000000 / usDivider) + 1 )
576 + usDivider = (unsigned short)( ((2 * 0x1770000 / lSampleRate) + 1) / 2 );
578 + usPhase = (0x1000000 / usDivider) + 1;
581 + * Write them in the registers. Spec says divider must be
582 + * written after phase incr.
586 + poke( AC97_2C_PCM_FRONT_DAC_RATE, usDivider);
587 + poke( AC97_64_DAC_SRC_PHASE_INCR, usPhase);
592 + poke( AC97_32_PCM_LR_ADC_RATE, usDivider);
593 + poke( AC97_66_ADC_SRC_PHASE_INCR, usPhase);
596 + DPRINTK( "ep93xx_set_samplerate - phase = %d, divider = %d\n",
597 + (unsigned int)usPhase, (unsigned int)usDivider );
600 + * We sorta should report the actual samplerate back to the calling
601 + * application. But some applications freak out if they don't get
602 + * exactly what they asked for. So we fudge and tell them what
603 + * they want to hear.
605 + //audio_samplerate = lSampleRate;
607 + DPRINTK( "ep93xx_set_samplerate - EXIT\n" );
611 + * ep93xx_set_hw_format
613 + * Sets up whether the controller is expecting 20 bit data in 32 bit words
614 + * or 16 bit data compacted to have a stereo sample in each 32 bit word.
616 +static void ep93xx_set_hw_format( long format,long channel )
623 + * Here's all the <=16 bit formats. We can squeeze both L and R
624 + * into one 32 bit sample so use compact mode.
626 + case SNDRV_PCM_FORMAT_U8:
627 + case SNDRV_PCM_FORMAT_S8:
628 + case SNDRV_PCM_FORMAT_S16_LE:
629 + case SNDRV_PCM_FORMAT_U16_LE:
634 + * Add any other >16 bit formats here...
636 + case SNDRV_PCM_FORMAT_S32_LE:
644 + DPRINTK("ep93xx_set_hw_format - Setting serial mode to 16 bit compact.\n");
647 + * Turn on Compact Mode so we can fit each stereo sample into
648 + * a 32 bit word. Twice as efficent for DMA and FIFOs.
651 + outl( 0x00008018, AC97RXCR1 );
652 + outl( 0x00008018, AC97TXCR1 );
655 + outl( 0x00008018, AC97RXCR1 );
656 + outl( 0x00008018, AC97TXCR1 );
660 + audio_state.DAC_bit_width = 16;
661 + audio_state.bCompactMode = 1;
665 + DPRINTK("ep93xx_set_hw_format - Setting serial mode to 20 bit non-CM.\n");
668 + * Turn off Compact Mode so we can do > 16 bits per channel
671 + outl( 0x00004018, AC97RXCR1 );
672 + outl( 0x00004018, AC97TXCR1 );
675 + outl( 0x00004018, AC97RXCR1 );
676 + outl( 0x00004018, AC97TXCR1 );
679 + audio_state.DAC_bit_width = 20;
680 + audio_state.bCompactMode = 0;
688 + * Once the ac-link is up and all is good, we want to set the codec to a
691 +static void ep93xx_stop_loop(void)
696 + * Set the AC97_0E_MIC_VOL MUTE bit to enable the LOOP.
698 + iTemp = peek( AC97_0E_MIC_VOL );
699 + poke( AC97_0E_MIC_VOL, (iTemp | 0x8000) );
702 + * Set the AC97_10_LINE_IN_VOL MUTE bit to enable the LOOP.
704 + iTemp = peek( AC97_10_LINE_IN_VOL );
705 + poke( AC97_10_LINE_IN_VOL, (iTemp | 0x8000) );
709 + * ep93xx_init_ac97_controller
711 + * This routine sets up the Ac'97 Controller.
713 +static void ep93xx_init_ac97_controller(void)
715 + unsigned int uiDEVCFG, uiTemp;
717 + DPRINTK("ep93xx_init_ac97_controller - enter\n");
720 + * Configure the multiplexed Ac'97 pins to be Ac97 not I2s.
721 + * Configure the EGPIO4 and EGPIO6 to be GPIOS, not to be
722 + * SDOUT's for the second and third I2S controller channels.
724 + uiDEVCFG = inl(EP93XX_SYSCON_DEVICE_CONFIG);
726 + uiDEVCFG &= ~(EP93XX_SYSCON_DEVCFG_CONFIG_I2SONAC97 |
727 + EP93XX_SYSCON_DEVCFG_A1onG |
728 + EP93XX_SYSCON_DEVCFG_A2onG);
730 + SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, uiDEVCFG);
733 + * Disable the AC97 controller internal loopback.
734 + * Disable Override codec ready.
736 + outl( 0, AC97GCR );
739 + * Enable the AC97 Link.
741 + uiTemp = inl(AC97GCR);
742 + outl( (uiTemp | AC97GSR_IFE), AC97GCR );
745 + * Set the TIMEDRESET bit. Will cause a > 1uSec reset of the ac-link.
746 + * This bit is self resetting.
748 + outl( AC97RESET_TIMEDRESET, AC97RESET );
751 + * Delay briefly, but let's not hog the processor.
753 + set_current_state(TASK_INTERRUPTIBLE);
754 + schedule_timeout( 5 ); /* 50 mSec */
757 + * Read the AC97 status register to see if we've seen a CODECREADY
758 + * signal from the AC97 codec.
760 + if( !(inl(AC97RGIS) & AC97RGIS_CODECREADY))
762 + printk( "ep93xx-ac97 - FAIL: CODECREADY still low!\n");
767 + * Delay for a second, not hogging the processor
769 + set_current_state(TASK_INTERRUPTIBLE);
770 + schedule_timeout( HZ ); /* 1 Sec */
773 + * Now the Ac-link is up. We can read and write codec registers.
775 + ac_link_enabled = 1;
778 + * Set up the rx and tx channels
779 + * Set the CM bit, data size=16 bits, enable tx slots 3 & 4.
781 + ep93xx_set_hw_format( EP93XX_DEFAULT_FORMAT,EP93XX_DEFAULT_NUM_CHANNELS );
783 + DPRINTK( "ep93xx-ac97 -- AC97RXCR1: %08x\n", inl(AC97RXCR1) );
784 + DPRINTK( "ep93xx-ac97 -- AC97TXCR1: %08x\n", inl(AC97TXCR1) );
786 + DPRINTK("ep93xx_init_ac97_controller - EXIT - success\n");
790 +#ifdef alsa_ac97_debug
791 +static void ep93xx_dump_ac97_regs(void)
794 + unsigned int reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
796 + DPRINTK( "---------------------------------------------\n");
797 + DPRINTK( " : 0 2 4 6 8 A C E\n" );
799 + for( i=0 ; i < 0x80 ; i+=0x10 )
801 + reg0 = 0xffff & (unsigned int)peek( i );
802 + reg1 = 0xffff & (unsigned int)peek( i + 0x2 );
803 + reg2 = 0xffff & (unsigned int)peek( i + 0x4 );
804 + reg3 = 0xffff & (unsigned int)peek( i + 0x6 );
805 + reg4 = 0xffff & (unsigned int)peek( i + 0x8 );
806 + reg5 = 0xffff & (unsigned int)peek( i + 0xa );
807 + reg6 = 0xffff & (unsigned int)peek( i + 0xc );
808 + reg7 = 0xffff & (unsigned int)peek( i + 0xe );
810 + DPRINTK( " %02x : %04x %04x %04x %04x %04x %04x %04x %04x\n",
811 + i, reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7);
814 + DPRINTK( "---------------------------------------------\n");
819 +#define supported_mixer(FOO) \
821 + (FOO < SOUND_MIXER_NRDEVICES) && \
822 + codec_supported_mixers & (1<<FOO) )
825 + * Available record sources.
826 + * LINE1 refers to AUX in.
827 + * IGAIN refers to input gain which means stereo mix.
829 +#define AC97_RECORD_MASK \
830 + (SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN | SOUND_MASK_VIDEO |\
831 + SOUND_MASK_LINE1 | SOUND_MASK_LINE | SOUND_MASK_PHONEIN)
833 +#define AC97_STEREO_MASK \
834 + (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_CD | \
835 + SOUND_MASK_ALTPCM | SOUND_MASK_IGAIN | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO)
837 +#define AC97_SUPPORTED_MASK \
838 + (AC97_STEREO_MASK | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
839 + SOUND_MASK_SPEAKER | SOUND_MASK_MIC | \
840 + SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT)
845 +/* this table has default mixer values for all OSS mixers. */
848 + unsigned int value;
852 + * Default mixer settings that are set up during boot.
854 + * These values are 16 bit numbers in which the upper byte is right volume
855 + * and the lower byte is left volume or mono volume for mono controls.
857 + * OSS Range for each of left and right volumes is 0 to 100 (0x00 to 0x64).
860 +static mixer_defaults_t mixer_defaults[SOUND_MIXER_NRDEVICES] =
863 + {SOUND_MIXER_VOLUME, 0x6464}, /* 0 dB */ /* -46.5dB to 0 dB */
864 + {SOUND_MIXER_ALTPCM, 0x6464}, /* 0 dB */ /* -46.5dB to 0 dB */
865 + {SOUND_MIXER_PHONEOUT, 0x6464}, /* 0 dB */ /* -46.5dB to 0 dB */
867 + /* PCM playback gain */
868 + {SOUND_MIXER_PCM, 0x4b4b}, /* 0 dB */ /* -34.5dB to +12dB */
871 + {SOUND_MIXER_IGAIN, 0x0000}, /* 0 dB */ /* -34.5dB to +12dB */
874 + {SOUND_MIXER_MIC, 0x0000}, /* mute */ /* -34.5dB to +12dB */
875 + {SOUND_MIXER_LINE, 0x4b4b}, /* 0 dB */ /* -34.5dB to +12dB */
877 + /* Inputs that are not connected. */
878 + {SOUND_MIXER_SPEAKER, 0x0000}, /* mute */ /* -45dB to 0dB */
879 + {SOUND_MIXER_PHONEIN, 0x0000}, /* mute */ /* -34.5dB to +12dB */
880 + {SOUND_MIXER_CD, 0x0000}, /* mute */ /* -34.5dB to +12dB */
881 + {SOUND_MIXER_VIDEO, 0x0000}, /* mute */ /* -34.5dB to +12dB */
882 + {SOUND_MIXER_LINE1, 0x0000}, /* mute */ /* -34.5dB to +12dB */
884 + {-1,0} /* last entry */
887 +/* table to scale scale from OSS mixer value to AC97 mixer register value */
889 + unsigned int offset;
893 +static ac97_mixer_hw_t ac97_hw[SOUND_MIXER_NRDEVICES] =
895 + [SOUND_MIXER_VOLUME] = {AC97_02_MASTER_VOL, 64},
896 + [SOUND_MIXER_BASS] = {0, 0},
897 + [SOUND_MIXER_TREBLE] = {0, 0},
898 + [SOUND_MIXER_SYNTH] = {0, 0},
899 + [SOUND_MIXER_PCM] = {AC97_18_PCM_OUT_VOL, 32},
900 + [SOUND_MIXER_SPEAKER] = {AC97_0A_PC_BEEP_VOL, 32},
901 + [SOUND_MIXER_LINE] = {AC97_10_LINE_IN_VOL, 32},
902 + [SOUND_MIXER_MIC] = {AC97_0E_MIC_VOL, 32},
903 + [SOUND_MIXER_CD] = {AC97_12_CD_VOL, 32},
904 + [SOUND_MIXER_IMIX] = {0, 0},
905 + [SOUND_MIXER_ALTPCM] = {AC97_04_HEADPHONE_VOL, 64},
906 + [SOUND_MIXER_RECLEV] = {0, 0},
907 + [SOUND_MIXER_IGAIN] = {AC97_1C_RECORD_GAIN, 16},
908 + [SOUND_MIXER_OGAIN] = {0, 0},
909 + [SOUND_MIXER_LINE1] = {AC97_16_AUX_VOL, 32},
910 + [SOUND_MIXER_LINE2] = {0, 0},
911 + [SOUND_MIXER_LINE3] = {0, 0},
912 + [SOUND_MIXER_DIGITAL1] = {0, 0},
913 + [SOUND_MIXER_DIGITAL2] = {0, 0},
914 + [SOUND_MIXER_DIGITAL3] = {0, 0},
915 + [SOUND_MIXER_PHONEIN] = {AC97_0C_PHONE_VOL, 32},
916 + [SOUND_MIXER_PHONEOUT] = {AC97_06_MONO_VOL, 64},
917 + [SOUND_MIXER_VIDEO] = {AC97_14_VIDEO_VOL, 32},
918 + [SOUND_MIXER_RADIO] = {0, 0},
919 + [SOUND_MIXER_MONITOR] = {0, 0},
923 +/* the following tables allow us to go from OSS <-> ac97 quickly. */
924 +enum ac97_recsettings
931 + AC97_REC_STEREO, /* combination of all enabled outputs.. */
932 + AC97_REC_MONO, /*.. or the mono equivalent */
936 +static const unsigned int ac97_rm2oss[] =
938 + [AC97_REC_MIC] = SOUND_MIXER_MIC,
939 + [AC97_REC_CD] = SOUND_MIXER_CD,
940 + [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
941 + [AC97_REC_AUX] = SOUND_MIXER_LINE1,
942 + [AC97_REC_LINE] = SOUND_MIXER_LINE,
943 + [AC97_REC_STEREO]= SOUND_MIXER_IGAIN,
944 + [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
947 +/* indexed by bit position */
948 +static const unsigned int ac97_oss_rm[] =
950 + [SOUND_MIXER_MIC] = AC97_REC_MIC,
951 + [SOUND_MIXER_CD] = AC97_REC_CD,
952 + [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
953 + [SOUND_MIXER_LINE1] = AC97_REC_AUX,
954 + [SOUND_MIXER_LINE] = AC97_REC_LINE,
955 + [SOUND_MIXER_IGAIN] = AC97_REC_STEREO,
956 + [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
961 + * ep93xx_write_mixer
964 +static void ep93xx_write_mixer
972 + ac97_mixer_hw_t * mh = &ac97_hw[oss_channel];
974 + DPRINTK("ac97_codec: wrote OSS %2d (ac97 0x%02x), "
976 + oss_channel, mh->offset, left, right);
980 + printk( "ep93xx-ac97.c: ep93xx_write_mixer - not a valid OSS channel\n");
984 + if( AC97_STEREO_MASK & (1 << oss_channel) )
986 + /* stereo mixers */
987 + if (left == 0 && right == 0)
993 + if (oss_channel == SOUND_MIXER_IGAIN)
995 + right = (right * mh->scale) / 100;
996 + left = (left * mh->scale) / 100;
997 + if (right >= mh->scale)
998 + right = mh->scale-1;
999 + if (left >= mh->scale)
1000 + left = mh->scale-1;
1004 + right = ((100 - right) * mh->scale) / 100;
1005 + left = ((100 - left) * mh->scale) / 100;
1006 + if (right >= mh->scale)
1007 + right = mh->scale-1;
1008 + if (left >= mh->scale)
1009 + left = mh->scale-1;
1011 + val = (left << 8) | right;
1014 + else if(left == 0)
1018 + else if( (oss_channel == SOUND_MIXER_SPEAKER) ||
1019 + (oss_channel == SOUND_MIXER_PHONEIN) ||
1020 + (oss_channel == SOUND_MIXER_PHONEOUT) )
1022 + left = ((100 - left) * mh->scale) / 100;
1023 + if (left >= mh->scale)
1024 + left = mh->scale-1;
1027 + else if (oss_channel == SOUND_MIXER_MIC)
1029 + val = peek( mh->offset) & ~0x801f;
1030 + left = ((100 - left) * mh->scale) / 100;
1031 + if (left >= mh->scale)
1032 + left = mh->scale-1;
1036 + * For bass and treble, the low bit is optional. Masking it
1037 + * lets us avoid the 0xf 'bypass'.
1038 + * Do a read, modify, write as we have two contols in one reg.
1040 + else if (oss_channel == SOUND_MIXER_BASS)
1042 + val = peek( mh->offset) & ~0x0f00;
1043 + left = ((100 - left) * mh->scale) / 100;
1044 + if (left >= mh->scale)
1045 + left = mh->scale-1;
1046 + val |= (left << 8) & 0x0e00;
1048 + else if (oss_channel == SOUND_MIXER_TREBLE)
1050 + val = peek( mh->offset) & ~0x000f;
1051 + left = ((100 - left) * mh->scale) / 100;
1052 + if (left >= mh->scale)
1053 + left = mh->scale-1;
1054 + val |= left & 0x000e;
1057 + DPRINTK(" 0x%04x", val);
1059 + poke( mh->offset, val );
1061 +#ifdef alsa_ac97_debug
1062 + val = peek( mh->offset );
1063 + DEBUG(" -> 0x%04x\n", val);
1068 +/* a thin wrapper for write_mixer */
1069 +static void ep93xx_set_mixer
1071 + unsigned int oss_mixer,
1075 + unsigned int left,right;
1077 + /* cleanse input a little */
1078 + right = ((val >> 8) & 0xff) ;
1079 + left = (val & 0xff) ;
1081 + if (right > 100) right = 100;
1082 + if (left > 100) left = 100;
1084 + /*mixer_state[oss_mixer] = (right << 8) | left;*/
1085 + ep93xx_write_mixer( oss_mixer, left, right);
1088 +static void ep93xx_init_mixer(void)
1094 + codec_supported_mixers = AC97_SUPPORTED_MASK;
1096 + cap = peek( AC97_00_RESET );
1097 + if( !(cap & 0x04) )
1099 + codec_supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE);
1101 + if( !(cap & 0x10) )
1103 + codec_supported_mixers &= ~SOUND_MASK_ALTPCM;
1107 + * Detect bit resolution of output volume controls by writing to the
1108 + * 6th bit (not unmuting yet)
1110 + poke( AC97_02_MASTER_VOL, 0xa020 );
1111 + if( peek( AC97_02_MASTER_VOL) != 0xa020 )
1113 + ac97_hw[SOUND_MIXER_VOLUME].scale = 32;
1116 + poke( AC97_04_HEADPHONE_VOL, 0xa020 );
1117 + if( peek( AC97_04_HEADPHONE_VOL) != 0xa020 )
1119 + ac97_hw[AC97_04_HEADPHONE_VOL].scale = 32;
1122 + poke( AC97_06_MONO_VOL, 0x8020 );
1123 + if( peek( AC97_06_MONO_VOL) != 0x8020 )
1125 + ac97_hw[AC97_06_MONO_VOL].scale = 32;
1128 + /* initialize mixer channel volumes */
1130 + (i < SOUND_MIXER_NRDEVICES) && (mixer_defaults[i].mixer != -1) ;
1133 + if( !supported_mixer( mixer_defaults[i].mixer) )
1138 + ep93xx_set_mixer( mixer_defaults[i].mixer, mixer_defaults[i].value);
1143 +static int ep93xx_set_recsource( int mask )
1147 + /* Arg contains a bit for each recording source */
1153 + mask &= AC97_RECORD_MASK;
1161 + * May have more than one bit set. So clear out currently selected
1162 + * record source value first (AC97 supports only 1 input)
1164 + val = (1 << ac97_rm2oss[peek( AC97_1A_RECORD_SELECT ) & 0x07]);
1169 + val = ac97_oss_rm[val-1];
1170 + val |= val << 8; /* set both channels */
1175 + val = peek( AC97_1A_RECORD_SELECT ) & 0x0707;
1176 + if ((val&0x0404)!=0)
1178 + else if((val&0x0000)!=0)
1182 + DPRINTK("ac97_codec: setting ac97 recmask to 0x%04x\n", val);
1184 + poke( AC97_1A_RECORD_SELECT, val);
1190 + * ep93xx_init_ac97_codec
1192 + * Program up the external Ac97 codec.
1195 +static void ep93xx_init_ac97_codec( void )
1197 + DPRINTK("ep93xx_init_ac97_codec - enter\n");
1199 + ep93xx_setup_src();
1200 + ep93xx_set_samplerate( AUDIO_SAMPLE_RATE_DEFAULT, 0 );
1201 + ep93xx_set_samplerate( AUDIO_SAMPLE_RATE_DEFAULT, 1 );
1202 + ep93xx_init_mixer();
1204 + DPRINTK("ep93xx_init_ac97_codec - EXIT\n");
1210 + * ep93xx_audio_init
1213 +static void ep93xx_audio_init(void)
1215 + DPRINTK("ep93xx_audio_init - enter\n");
1217 + * Init the controller, enable the ac-link.
1218 + * Initialize the codec.
1220 + ep93xx_init_ac97_controller();
1221 + ep93xx_init_ac97_codec();
1222 + /*stop the audio loop from the input to the output directly*/
1223 + ep93xx_stop_loop();
1225 +#ifdef alsa_ac97_debug
1226 + ep93xx_dump_ac97_regs();
1228 + DPRINTK("ep93xx_audio_init - EXIT\n");
1231 +/*====================================================================================*/
1234 +static void print_audio_format( long format )
1237 + case SNDRV_PCM_FORMAT_S8:
1238 + DPRINTK( "AFMT_S8\n" );
1241 + case SNDRV_PCM_FORMAT_U8:
1242 + DPRINTK( "AFMT_U8\n" );
1245 + case SNDRV_PCM_FORMAT_S16_LE:
1246 + DPRINTK( "AFMT_S16_LE\n" );
1249 + case SNDRV_PCM_FORMAT_S16_BE:
1250 + DPRINTK( "AFMT_S16_BE\n" );
1253 + case SNDRV_PCM_FORMAT_U16_LE:
1254 + DPRINTK( "AFMT_U16_LE\n" );
1256 + case SNDRV_PCM_FORMAT_U16_BE:
1257 + DPRINTK( "AFMT_U16_BE\n" );
1260 + case SNDRV_PCM_FORMAT_S24_LE:
1261 + DPRINTK( "AFMT_S24_LE\n" );
1264 + case SNDRV_PCM_FORMAT_S24_BE:
1265 + DPRINTK( "AFMT_S24_BE\n" );
1268 + case SNDRV_PCM_FORMAT_U24_LE:
1269 + DPRINTK( "AFMT_U24_LE\n" );
1272 + case SNDRV_PCM_FORMAT_U24_BE:
1273 + DPRINTK( "AFMT_U24_BE\n" );
1275 + case SNDRV_PCM_FORMAT_S32_LE:
1276 + DPRINTK( "AFMT_S24_LE\n" );
1279 + case SNDRV_PCM_FORMAT_S32_BE:
1280 + DPRINTK( "AFMT_S24_BE\n" );
1283 + case SNDRV_PCM_FORMAT_U32_LE:
1284 + DPRINTK( "AFMT_U24_LE\n" );
1287 + case SNDRV_PCM_FORMAT_U32_BE:
1288 + DPRINTK( "AFMT_U24_BE\n" );
1291 + DPRINTK( "ep93xx_i2s_Unsupported Audio Format\n" );
1296 +static void audio_set_format( audio_stream_t * s, long val )
1298 + DPRINTK( "ep93xx_i2s_audio_set_format enter. Format requested (%d) %d ",
1299 + (int)val,SNDRV_PCM_FORMAT_S16_LE);
1300 + print_audio_format( val );
1303 + case SNDRV_PCM_FORMAT_S8:
1304 + s->audio_format = SNDRV_PCM_FORMAT_S8;
1305 + s->audio_stream_bitwidth = 8;
1308 + case SNDRV_PCM_FORMAT_U8:
1309 + s->audio_format = SNDRV_PCM_FORMAT_U8;
1310 + s->audio_stream_bitwidth = 8;
1313 + case SNDRV_PCM_FORMAT_S16_LE:
1314 + case SNDRV_PCM_FORMAT_S16_BE:
1315 + s->audio_format = SNDRV_PCM_FORMAT_S16_LE;
1316 + s->audio_stream_bitwidth = 16;
1319 + case SNDRV_PCM_FORMAT_U16_LE:
1320 + case SNDRV_PCM_FORMAT_U16_BE:
1321 + s->audio_format = SNDRV_PCM_FORMAT_U16_LE;
1322 + s->audio_stream_bitwidth = 16;
1325 + case SNDRV_PCM_FORMAT_S24_LE:
1326 + case SNDRV_PCM_FORMAT_S24_BE:
1327 + s->audio_format = SNDRV_PCM_FORMAT_S24_LE;
1328 + s->audio_stream_bitwidth = 24;
1331 + case SNDRV_PCM_FORMAT_U24_LE:
1332 + case SNDRV_PCM_FORMAT_U24_BE:
1333 + s->audio_format = SNDRV_PCM_FORMAT_U24_LE;
1334 + s->audio_stream_bitwidth = 24;
1337 + case SNDRV_PCM_FORMAT_U32_LE:
1338 + case SNDRV_PCM_FORMAT_U32_BE:
1339 + case SNDRV_PCM_FORMAT_S32_LE:
1340 + case SNDRV_PCM_FORMAT_S32_BE:
1341 + s->audio_format = SNDRV_PCM_FORMAT_S32_LE;
1342 + s->audio_stream_bitwidth = 32;
1345 + DPRINTK( "ep93xx_i2s_Unsupported Audio Format\n" );
1349 + DPRINTK( "ep93xx_i2s_audio_set_format EXIT format set to be (%d) ", (int)s->audio_format );
1350 + print_audio_format( (long)s->audio_format );
1353 +static __inline__ unsigned long copy_to_user_S24_LE
1355 + audio_stream_t *stream,
1357 + unsigned long to_count
1360 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
1361 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1362 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1364 + int total_to_count = to_count;
1365 + int *user_ptr = (int *)to; /* 32 bit user buffer */
1368 + count = 8 * stream->dma_num_channels;
1370 + while (to_count > 0){
1372 + __put_user( (int)( *dma_buffer_0++ ), user_ptr++ );
1373 + __put_user( (int)( *dma_buffer_0++ ), user_ptr++ );
1375 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1376 + __put_user( (int)( *dma_buffer_1++ ), user_ptr++ );
1377 + __put_user( (int)( *dma_buffer_1++ ), user_ptr++ );
1380 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1381 + __put_user( (int)( *dma_buffer_2++ ), user_ptr++ );
1382 + __put_user( (int)( *dma_buffer_2++ ), user_ptr++ );
1384 + to_count -= count;
1386 + return total_to_count;
1389 +static __inline__ unsigned long copy_to_user_U24_LE
1391 + audio_stream_t *stream,
1393 + unsigned long to_count
1396 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
1397 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1398 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1400 + int total_to_count = to_count;
1401 + unsigned int * user_ptr = (unsigned int *)to; /* 32 bit user buffer */
1404 + count = 8 * stream->dma_num_channels;
1406 + while (to_count > 0){
1407 + __put_user( ((unsigned int)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
1408 + __put_user( ((unsigned int)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
1410 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1411 + __put_user( ((unsigned int)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
1412 + __put_user( ((unsigned int)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
1415 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1416 + __put_user( ((unsigned int)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
1417 + __put_user( ((unsigned int)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
1419 + to_count -= count;
1421 + return total_to_count;
1424 +static __inline__ unsigned long copy_to_user_S16_LE
1426 + audio_stream_t *stream,
1428 + unsigned long to_count
1431 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
1432 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1433 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1434 + int total_to_count = to_count;
1435 + short * user_ptr = (short *)to; /* 16 bit user buffer */
1438 + count = 4 * stream->dma_num_channels;
1440 + while (to_count > 0){
1442 + __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
1443 + __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
1445 + if( stream->audio_channels_flag & CHANNEL_REAR ){
1446 + __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
1447 + __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
1450 + if( stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1451 + __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
1452 + __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
1454 + to_count -= count;
1456 + return total_to_count;
1459 +static __inline__ unsigned long copy_to_user_U16_LE
1461 + audio_stream_t *stream,
1463 + unsigned long to_count
1466 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
1467 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1468 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1470 + int total_to_count = to_count;
1471 + short * user_ptr = (short *)to; /* 16 bit user buffer */
1473 + count = 4 * stream->dma_num_channels;
1475 + while (to_count > 0){
1477 + __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
1478 + __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
1480 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1481 + __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
1482 + __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
1485 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1486 + __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
1487 + __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
1489 + to_count -= count;
1491 + return total_to_count;
1494 +static __inline__ unsigned long copy_to_user_S8
1496 + audio_stream_t *stream,
1498 + unsigned long to_count
1501 + char *dma_buffer_0 = (char *)stream->hwbuf[0];
1502 + char *dma_buffer_1 = (char *)stream->hwbuf[1];
1503 + char *dma_buffer_2 = (char *)stream->hwbuf[2];
1505 + int total_to_count = to_count;
1506 + char * user_ptr = (char *)to; /* 8 bit user buffer */
1508 + count = 2 * stream->dma_num_channels;
1514 + while (to_count > 0){
1516 + __put_user( (char)( *dma_buffer_0 ), user_ptr++ );
1517 + dma_buffer_0 += 4;
1518 + __put_user( (char)( *dma_buffer_0 ), user_ptr++ );
1519 + dma_buffer_0 += 4;
1521 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1522 + __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
1523 + dma_buffer_1 += 4;
1524 + __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
1525 + dma_buffer_1 += 4;
1528 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1529 + __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
1530 + dma_buffer_2 += 4;
1531 + __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
1532 + dma_buffer_2 += 4;
1534 + to_count -= count;
1536 + return total_to_count;
1539 +static __inline__ unsigned long copy_to_user_U8
1541 + audio_stream_t *stream,
1543 + unsigned long to_count
1546 + char *dma_buffer_0 = (char *)stream->hwbuf[0];
1547 + char *dma_buffer_1 = (char *)stream->hwbuf[1];
1548 + char *dma_buffer_2 = (char *)stream->hwbuf[2];
1550 + int total_to_count = to_count;
1551 + char * user_ptr = (char *)to; /* 8 bit user buffer */
1553 + count = 2 * stream->dma_num_channels;
1559 + while (to_count > 0){
1561 + __put_user( (char)( *dma_buffer_0 ) ^ 0x80, user_ptr++ );
1562 + dma_buffer_0 += 4;
1563 + __put_user( (char)( *dma_buffer_0 ) ^ 0x80, user_ptr++ );
1564 + dma_buffer_0 += 4;
1566 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1567 + __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
1568 + dma_buffer_1 += 4;
1569 + __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
1570 + dma_buffer_1 += 4;
1573 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1574 + __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
1575 + dma_buffer_2 += 4;
1576 + __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
1577 + dma_buffer_2 += 4;
1579 + to_count -= count;
1581 + return total_to_count;
1587 +static __inline__ unsigned long copy_to_user_S16_LE_CM
1589 + audio_stream_t *stream,
1591 + unsigned long to_count
1594 + short *dma_buffer_0 = (short *)stream->hwbuf[0];
1595 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1596 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1597 + int total_to_count = to_count;
1598 + short * user_ptr = (short *)to; /* 16 bit user buffer */
1602 + count = 4 * stream->dma_num_channels;
1604 + while (to_count > 0){
1605 + if(stream->audio_num_channels == 2){
1606 + __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
1607 + __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
1608 + to_count -= count;
1612 + __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
1616 + if( stream->audio_channels_flag & CHANNEL_REAR ){
1617 + __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
1618 + __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
1621 + if( stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1622 + __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
1623 + __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
1625 + //to_count -= count;
1627 + return total_to_count;
1630 +static __inline__ unsigned long copy_to_user_U16_LE_CM
1632 + audio_stream_t *stream,
1634 + unsigned long to_count
1637 + unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0];
1638 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1639 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1641 + int total_to_count = to_count;
1642 + unsigned short * user_ptr = (unsigned short *)to; /* 16 bit user buffer */
1644 + count = 4 * stream->dma_num_channels;
1646 + while (to_count > 0){
1648 + if(stream->audio_num_channels == 2){
1649 + __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
1650 + __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
1651 + to_count -= count;
1655 + __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
1659 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1660 + __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
1661 + __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
1664 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1665 + __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
1666 + __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
1668 + //to_count -= count;
1670 + return total_to_count;
1673 +static __inline__ unsigned long copy_to_user_S8_CM
1675 + audio_stream_t *stream,
1677 + unsigned long to_count
1680 + unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0];
1681 + char *dma_buffer_1 = (char *)stream->hwbuf[1];
1682 + char *dma_buffer_2 = (char *)stream->hwbuf[2];
1684 + int total_to_count = to_count;
1685 + char * user_ptr = (char *)to; /* 8 bit user buffer */
1687 + count = 2 * stream->dma_num_channels;
1693 + while (to_count > 0){
1694 + if(stream->audio_num_channels == 2){
1695 + __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ );
1696 + //dma_buffer_0 += 4;
1697 + __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ );
1698 + //dma_buffer_0 += 4;
1699 + to_count -= count;
1703 + __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ );
1707 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1708 + __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
1709 + dma_buffer_1 += 4;
1710 + __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
1711 + dma_buffer_1 += 4;
1714 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1715 + __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
1716 + dma_buffer_2 += 4;
1717 + __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
1718 + dma_buffer_2 += 4;
1720 + //to_count -= count;
1722 + return total_to_count;
1725 +static __inline__ unsigned long copy_to_user_U8_CM
1727 + audio_stream_t *stream,
1729 + unsigned long to_count
1732 + unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0];
1733 + char *dma_buffer_1 = (char *)stream->hwbuf[1];
1734 + char *dma_buffer_2 = (char *)stream->hwbuf[2];
1736 + int total_to_count = to_count;
1737 + char * user_ptr = (char *)to; /* 8 bit user buffer */
1739 + count = 2 * stream->dma_num_channels;
1745 + while (to_count > 0){
1746 + if(stream->audio_num_channels == 2){
1747 + __put_user( (char)( *dma_buffer_0++ >>8) ^ 0x80, user_ptr++ );
1748 + //dma_buffer_0 += 4;
1749 + __put_user( (char)( *dma_buffer_0++ >>8) ^ 0x80, user_ptr++ );
1750 + //dma_buffer_0 += 4;
1751 + to_count -= count;
1755 + __put_user( (char)( *dma_buffer_0++ >>8) ^ 0x80, user_ptr++ );
1756 + //dma_buffer_0 += 4;
1760 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1761 + __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
1762 + dma_buffer_1 += 4;
1763 + __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
1764 + dma_buffer_1 += 4;
1767 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1768 + __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
1769 + dma_buffer_2 += 4;
1770 + __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
1771 + dma_buffer_2 += 4;
1773 + //to_count -= count;
1775 + return total_to_count;
1778 +static __inline__ unsigned long copy_to_user_U32
1780 + audio_stream_t *stream,
1782 + unsigned long to_count
1785 + char *dma_buffer_0 = (char *)stream->hwbuf[0];
1787 + if(__copy_to_user( (char *)to, dma_buffer_0, to_count))
1794 +static __inline__ int copy_to_user_with_conversion
1796 + audio_stream_t *stream,
1804 + if( toCount == 0 ){
1805 + DPRINTK("ep93xx_i2s_copy_to_user_with_conversion - nothing to copy!\n");
1808 + if( bCompactMode == 1 ){
1810 + switch( stream->audio_format ){
1812 + case SNDRV_PCM_FORMAT_S8:
1813 + ret = copy_to_user_S8_CM( stream, to, toCount );
1816 + case SNDRV_PCM_FORMAT_U8:
1817 + ret = copy_to_user_U8_CM( stream, to, toCount );
1820 + case SNDRV_PCM_FORMAT_S16_LE:
1821 + ret = copy_to_user_S16_LE_CM( stream, to, toCount );
1824 + case SNDRV_PCM_FORMAT_U16_LE:
1825 + ret = copy_to_user_U16_LE_CM( stream, to, toCount );
1828 + case SNDRV_PCM_FORMAT_S24_LE:
1829 + //ret = copy_to_user_S24_LE( stream, to, toCount );
1832 + case SNDRV_PCM_FORMAT_U24_LE:
1833 + //ret = copy_to_user_U24_LE( stream, to, toCount );
1836 + case SNDRV_PCM_FORMAT_S32_LE:
1838 + DPRINTK( "ep93xx_i2s copy to user unsupported audio format %x\n",stream->audio_format );
1845 + switch( stream->audio_format ){
1847 + case SNDRV_PCM_FORMAT_S8:
1848 + ret = copy_to_user_S8( stream, to, toCount );
1851 + case SNDRV_PCM_FORMAT_U8:
1852 + ret = copy_to_user_U8( stream, to, toCount );
1855 + case SNDRV_PCM_FORMAT_S16_LE:
1856 + ret = copy_to_user_S16_LE( stream, to, toCount );
1859 + case SNDRV_PCM_FORMAT_U16_LE:
1860 + ret = copy_to_user_U16_LE( stream, to, toCount );
1863 + case SNDRV_PCM_FORMAT_S24_LE:
1864 + //ret = copy_to_user_S24_LE( stream, to, toCount );
1867 + case SNDRV_PCM_FORMAT_U24_LE:
1868 + //ret = copy_to_user_U24_LE( stream, to, toCount );
1870 + DPRINTK( "ep93xx_i2s copy to user unsupported audio format %x\n",stream->audio_format );
1873 + case SNDRV_PCM_FORMAT_S32_LE:
1875 + //__copy_to_user( (char *)to, from, toCount);
1876 + ret = copy_to_user_U32( stream, to, toCount );
1879 + DPRINTK( "ep93xx_i2s copy to user unsupported audio format\n" );
1887 +static __inline__ int copy_from_user_S24_LE
1889 + audio_stream_t *stream,
1894 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
1895 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1896 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1899 + unsigned int * user_buffer = (unsigned int *)from;
1900 + unsigned int data;
1902 + int toCount0 = toCount;
1903 + count = 8 * stream->dma_num_channels;
1905 + while (toCount > 0){
1907 + __get_user(data, user_buffer++);
1908 + *dma_buffer_0++ = (unsigned int)data;
1909 + __get_user(data, user_buffer++);
1910 + *dma_buffer_0++ = (unsigned int)data;
1912 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1913 + __get_user(data, user_buffer++);
1914 + *dma_buffer_1++ = (unsigned int)data;
1915 + __get_user(data, user_buffer++);
1916 + *dma_buffer_1++ = (unsigned int)data;
1919 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1920 + __get_user(data, user_buffer++);
1921 + *dma_buffer_2++ = (unsigned int)data;
1922 + __get_user(data, user_buffer++);
1923 + *dma_buffer_2++ = (unsigned int)data;
1927 + return toCount0 / 2;
1930 +static __inline__ int copy_from_user_U24_LE
1932 + audio_stream_t *stream,
1937 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
1938 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1939 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1941 + unsigned int * user_buffer = (unsigned int *)from;
1942 + unsigned int data;
1944 + int toCount0 = toCount;
1945 + count = 8 * stream->dma_num_channels;
1947 + while (toCount > 0){
1949 + __get_user(data, user_buffer++);
1950 + *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
1951 + __get_user(data, user_buffer++);
1952 + *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
1954 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1955 + __get_user(data, user_buffer++);
1956 + *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
1957 + __get_user(data, user_buffer++);
1958 + *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
1961 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
1962 + __get_user(data, user_buffer++);
1963 + *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
1964 + __get_user(data, user_buffer++);
1965 + *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
1969 + return toCount0 / 2;
1972 +static __inline__ int copy_from_user_S16_LE
1974 + audio_stream_t *stream,
1979 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
1980 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
1981 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
1982 + unsigned short *user_buffer = (unsigned short *)from;
1983 + unsigned short data;
1985 + int toCount0 = toCount;
1987 + count = 8 * stream->dma_num_channels;
1989 + while (toCount > 0){
1991 + __get_user(data, user_buffer++);
1992 + *dma_buffer_0++ = data;
1993 + if(stream->audio_num_channels == 2){
1994 + __get_user(data, user_buffer++);
1996 + *dma_buffer_0++ = data;
1998 + if(stream->audio_channels_flag & CHANNEL_REAR ){
1999 + __get_user(data, user_buffer++);
2000 + *dma_buffer_1++ = data;
2001 + __get_user(data, user_buffer++);
2002 + *dma_buffer_1++ = data;
2005 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2006 + __get_user(data, user_buffer++);
2007 + *dma_buffer_2++ = data;
2008 + __get_user(data, user_buffer++);
2009 + *dma_buffer_2++ = data;
2014 + if(stream->audio_num_channels == 1){
2015 + return toCount0 / 4;
2017 + return toCount0 / 2;
2020 +static __inline__ int copy_from_user_U16_LE
2022 + audio_stream_t *stream,
2027 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
2028 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
2029 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
2031 + unsigned short * user_buffer = (unsigned short *)from;
2032 + unsigned short data;
2034 + int toCount0 = toCount;
2035 + count = 8 * stream->dma_num_channels;
2037 + while (toCount > 0){
2039 + __get_user(data, user_buffer++);
2040 + *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
2041 + if(stream->audio_num_channels == 2){
2042 + __get_user(data, user_buffer++);
2044 + *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
2046 + if(stream->audio_channels_flag & CHANNEL_REAR ){
2047 + __get_user(data, user_buffer++);
2048 + *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
2049 + __get_user(data, user_buffer++);
2050 + *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
2053 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2054 + __get_user(data, user_buffer++);
2055 + *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
2056 + __get_user(data, user_buffer++);
2057 + *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
2062 + if(stream->audio_num_channels == 1){
2063 + return toCount0 / 4;
2065 + return toCount0 / 2;
2068 +static __inline__ int copy_from_user_S8
2070 + audio_stream_t *stream,
2075 + char *dma_buffer_0 = (char *)stream->hwbuf[0];
2076 + char *dma_buffer_1 = (char *)stream->hwbuf[1];
2077 + char *dma_buffer_2 = (char *)stream->hwbuf[2];
2079 + unsigned char * user_buffer = (unsigned char *)from;
2080 + unsigned char data;
2082 + int toCount0 = toCount;
2083 + count = 8 * stream->dma_num_channels;
2089 + while (toCount > 0){
2090 + __get_user(data, user_buffer++);
2091 + *dma_buffer_0 = data;
2092 + dma_buffer_0 += 4;
2093 + if(stream->audio_num_channels == 2){
2094 + __get_user(data, user_buffer++);
2096 + *dma_buffer_0 = data;
2097 + dma_buffer_0 += 4;
2099 + if(stream->audio_channels_flag & CHANNEL_REAR ){
2100 + __get_user(data, user_buffer++);
2101 + *dma_buffer_1 = data;
2102 + dma_buffer_1 += 4;
2103 + __get_user(data, user_buffer++);
2104 + *dma_buffer_1 = data;
2105 + dma_buffer_1 += 4;
2108 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2109 + __get_user(data, user_buffer++);
2110 + *dma_buffer_2 = data;
2111 + dma_buffer_2 += 4;
2112 + __get_user(data, user_buffer++);
2113 + *dma_buffer_2 = data;
2114 + dma_buffer_2 += 4;
2119 + if(stream->audio_num_channels == 1){
2120 + return toCount0 / 8;
2122 + return toCount0 / 4;
2125 +static __inline__ int copy_from_user_U8
2127 + audio_stream_t *stream,
2132 + char *dma_buffer_0 = (char *)stream->hwbuf[0];
2133 + char *dma_buffer_1 = (char *)stream->hwbuf[1];
2134 + char *dma_buffer_2 = (char *)stream->hwbuf[2];
2136 + unsigned char *user_buffer = (unsigned char *)from;
2137 + unsigned char data;
2139 + int toCount0 = toCount;
2140 + count = 8 * stream->dma_num_channels;
2146 + while (toCount > 0){
2148 + __get_user(data, user_buffer++);
2149 + *dma_buffer_0 = ((unsigned char)data ^ 0x80);
2150 + dma_buffer_0 += 4;
2151 + if(stream->audio_num_channels == 2){
2152 + __get_user(data, user_buffer++);
2154 + *dma_buffer_0 = ((unsigned char)data ^ 0x80);
2155 + dma_buffer_0 += 4;
2157 + if(stream->audio_channels_flag & CHANNEL_REAR ){
2158 + __get_user(data, user_buffer++);
2159 + *dma_buffer_1 = ((unsigned char)data ^ 0x80);
2160 + dma_buffer_1 += 4;
2161 + __get_user(data, user_buffer++);
2162 + *dma_buffer_1 = ((unsigned char)data ^ 0x80);
2163 + dma_buffer_1 += 4;
2166 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2167 + __get_user(data, user_buffer++);
2168 + *dma_buffer_2 = ((unsigned char)data ^ 0x80);
2169 + dma_buffer_2 += 4;
2170 + __get_user(data, user_buffer++);
2171 + *dma_buffer_2 = ((unsigned char)data ^ 0x80);
2172 + dma_buffer_2 += 4;
2177 + if(stream->audio_num_channels == 1){
2178 + return toCount0 / 8;
2180 + return toCount0 / 4;
2183 +static __inline__ int copy_from_user_S16_LE_CM
2185 + audio_stream_t *stream,
2190 + unsigned int *dma_buffer_0 = (int *)stream->hwbuf[0];
2191 + unsigned int *dma_buffer_1 = (int *)stream->hwbuf[1];
2192 + unsigned int *dma_buffer_2 = (int *)stream->hwbuf[2];
2193 + unsigned short *user_buffer = (unsigned short *)from;
2196 + int toCount0 = toCount;
2198 + count = 4 * stream->dma_num_channels;
2200 + //printk("count=%x tocount\n",count,toCount);
2201 + while (toCount > 0){
2203 + __get_user(data, user_buffer++);
2204 + //*dma_buffer_0++ = data;
2205 + val = (unsigned int)data & 0x0000ffff;
2206 + if(stream->audio_num_channels == 2){
2207 + __get_user(data, user_buffer++);
2209 + *dma_buffer_0++ = ((unsigned int)data << 16) | val;
2211 + if(stream->audio_channels_flag & CHANNEL_REAR ){
2212 + __get_user(data, user_buffer++);
2213 + //*dma_buffer_1++ = data;
2214 + val = (unsigned int)data & 0x0000ffff;
2215 + __get_user(data, user_buffer++);
2216 + *dma_buffer_1++ = ((unsigned int)data << 16) | val;
2219 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2220 + __get_user(data, user_buffer++);
2221 + //*dma_buffer_2++ = data;
2222 + val = (unsigned int)data & 0x0000ffff;
2223 + __get_user(data, user_buffer++);
2224 + *dma_buffer_2++ = ((unsigned int)data << 16) | val;
2229 + if(stream->audio_num_channels == 1){
2230 + return toCount0 /2 ;
2236 +static __inline__ int copy_from_user_U16_LE_CM
2238 + audio_stream_t *stream,
2243 + int *dma_buffer_0 = (int *)stream->hwbuf[0];
2244 + int *dma_buffer_1 = (int *)stream->hwbuf[1];
2245 + int *dma_buffer_2 = (int *)stream->hwbuf[2];
2247 + unsigned short * user_buffer = (unsigned short *)from;
2248 + unsigned short data;
2250 + int toCount0 = toCount;
2251 + count = 4 * stream->dma_num_channels;
2253 + while (toCount > 0){
2255 + __get_user(data, user_buffer++);
2256 + //*dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
2257 + val = (unsigned int)data & 0x0000ffff;
2258 + if(stream->audio_num_channels == 2){
2259 + __get_user(data, user_buffer++);
2261 + //*dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
2262 + *dma_buffer_0++ = (((unsigned int)data << 16) | val) ^ 0x80008000;
2264 + if(stream->audio_channels_flag & CHANNEL_REAR ){
2265 + __get_user(data, user_buffer++);
2266 + //*dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
2267 + val = (unsigned int)data & 0x0000ffff;
2268 + __get_user(data, user_buffer++);
2269 + //*dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
2270 + *dma_buffer_1++ = (((unsigned int)data << 16) | val) ^ 0x80008000;
2273 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2274 + __get_user(data, user_buffer++);
2275 + //*dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
2276 + val = (unsigned int)data & 0x0000ffff;
2277 + __get_user(data, user_buffer++);
2278 + //*dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
2279 + *dma_buffer_2++ = (((unsigned int)data << 16) | val) ^ 0x80008000;
2284 + if(stream->audio_num_channels == 1){
2285 + return toCount0/2;
2290 +static __inline__ int copy_from_user_S8_CM
2292 + audio_stream_t *stream,
2297 + char *dma_buffer_0 = (char *)stream->hwbuf[0];
2298 + char *dma_buffer_1 = (char *)stream->hwbuf[1];
2299 + char *dma_buffer_2 = (char *)stream->hwbuf[2];
2301 + unsigned char * user_buffer = (unsigned char *)from;
2302 + unsigned char data;
2303 + int toCount0 = toCount;
2304 + count = 4 * stream->dma_num_channels;
2310 + while (toCount > 0){
2311 + __get_user(data, user_buffer++);
2312 + *dma_buffer_0 = data;
2313 + *(dma_buffer_0 +1 ) = 0;
2314 + dma_buffer_0 += 2;
2316 + if(stream->audio_num_channels == 2){
2317 + __get_user(data, user_buffer++);
2319 + *dma_buffer_0 = data;
2320 + *(dma_buffer_0 +1 ) = 0;
2321 + dma_buffer_0 += 2;
2323 + if(stream->audio_channels_flag & CHANNEL_REAR ){
2324 + __get_user(data, user_buffer++);
2325 + *dma_buffer_1 = data;
2326 + dma_buffer_1 += 2;
2327 + __get_user(data, user_buffer++);
2328 + *dma_buffer_1 = data;
2329 + dma_buffer_1 += 2;
2332 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2333 + __get_user(data, user_buffer++);
2334 + *dma_buffer_2 = data;
2335 + dma_buffer_2 += 2;
2336 + __get_user(data, user_buffer++);
2337 + *dma_buffer_2 = data;
2338 + dma_buffer_2 += 2;
2343 + if(stream->audio_num_channels == 1){
2344 + return toCount0 / 4;
2347 + return toCount0 / 2;
2350 +static __inline__ int copy_from_user_U8_CM
2352 + audio_stream_t *stream,
2357 + unsigned char *dma_buffer_0 = (unsigned char *)stream->hwbuf[0];
2358 + unsigned char *dma_buffer_1 = (unsigned char *)stream->hwbuf[1];
2359 + unsigned char *dma_buffer_2 = (unsigned char *)stream->hwbuf[2];
2361 + unsigned char *user_buffer = (unsigned char *)from;
2362 + unsigned char data;
2364 + int toCount0 = toCount;
2365 + count = 4 * stream->dma_num_channels;
2371 + while (toCount > 0){
2373 + __get_user(data, user_buffer++);
2374 + *dma_buffer_0 = ((unsigned char)data ^ 0x80);
2375 + *(dma_buffer_0 +1 ) = 0;
2376 + dma_buffer_0 += 2;
2378 + if(stream->audio_num_channels == 2){
2379 + __get_user(data, user_buffer++);
2381 + *dma_buffer_0 = ((unsigned char)data ^ 0x80);
2382 + *(dma_buffer_0 +1 ) = 0;
2383 + dma_buffer_0 += 2;
2386 + if(stream->audio_channels_flag & CHANNEL_REAR ){
2387 + __get_user(data, user_buffer++);
2388 + *dma_buffer_1 = ((unsigned char)data ^ 0x80);
2389 + dma_buffer_1 += 2;
2390 + __get_user(data, user_buffer++);
2391 + *dma_buffer_1 = ((unsigned char)data ^ 0x80);
2392 + dma_buffer_1 += 2;
2395 + if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
2396 + __get_user(data, user_buffer++);
2397 + *dma_buffer_2 = ((unsigned char)data ^ 0x80);
2398 + dma_buffer_2 += 2;
2399 + __get_user(data, user_buffer++);
2400 + *dma_buffer_2 = ((unsigned char)data ^ 0x80);
2401 + dma_buffer_2 += 2;
2406 + if(stream->audio_num_channels == 1){
2407 + return toCount0 / 4;
2410 + return toCount0 / 2;
2413 +static int copy_from_user_U32
2415 + audio_stream_t *stream,
2420 + char *dma_buffer_0 = (char *)stream->hwbuf[0];
2422 + if (copy_from_user( (char *)dma_buffer_0, from, toCount))
2432 + * Returns negative for error
2433 + * Returns # of bytes transferred out of the from buffer
2436 +static __inline__ int copy_from_user_with_conversion
2438 + audio_stream_t *stream,
2445 +// DPRINTK("copy_from_user_with_conversion\n");
2446 + if( toCount == 0 ){
2447 + DPRINTK("ep93xx_i2s_copy_from_user_with_conversion - nothing to copy!\n");
2450 + if( bCompactMode == 1){
2452 + switch( stream->audio_format ){
2454 + case SNDRV_PCM_FORMAT_S8:
2455 + DPRINTK("SNDRV_PCM_FORMAT_S8 CM\n");
2456 + ret = copy_from_user_S8_CM( stream, from, toCount );
2459 + case SNDRV_PCM_FORMAT_U8:
2460 + DPRINTK("SNDRV_PCM_FORMAT_U8 CM\n");
2461 + ret = copy_from_user_U8_CM( stream, from, toCount );
2464 + case SNDRV_PCM_FORMAT_S16_LE:
2465 + DPRINTK("SNDRV_PCM_FORMAT_S16_LE CM\n");
2466 + ret = copy_from_user_S16_LE_CM( stream, from, toCount );
2469 + case SNDRV_PCM_FORMAT_U16_LE:
2470 + DPRINTK("SNDRV_PCM_FORMAT_U16_LE CM\n");
2471 + ret = copy_from_user_U16_LE_CM( stream, from, toCount );
2474 + case SNDRV_PCM_FORMAT_S24_LE:
2475 + DPRINTK("SNDRV_PCM_FORMAT_S24_LE CM\n");
2476 + //ret = copy_from_user_S24_LE( stream, from, toCount );
2479 + case SNDRV_PCM_FORMAT_U24_LE:
2480 + DPRINTK("SNDRV_PCM_FORMAT_U24_LE CM\n");
2481 + //ret = copy_from_user_U24_LE( stream, from, toCount );
2483 + case SNDRV_PCM_FORMAT_S32_LE:
2484 + DPRINTK("SNDRV_PCM_FORMAT_S32_LE CM\n");
2487 + DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" );
2492 + switch( stream->audio_format ){
2494 + case SNDRV_PCM_FORMAT_S8:
2495 + DPRINTK("SNDRV_PCM_FORMAT_S8\n");
2496 + ret = copy_from_user_S8( stream, from, toCount );
2499 + case SNDRV_PCM_FORMAT_U8:
2500 + DPRINTK("SNDRV_PCM_FORMAT_U8\n");
2501 + ret = copy_from_user_U8( stream, from, toCount );
2504 + case SNDRV_PCM_FORMAT_S16_LE:
2505 + DPRINTK("SNDRV_PCM_FORMAT_S16_LE\n");
2506 + ret = copy_from_user_S16_LE( stream, from, toCount );
2509 + case SNDRV_PCM_FORMAT_U16_LE:
2510 + DPRINTK("SNDRV_PCM_FORMAT_U16_LE\n");
2511 + ret = copy_from_user_U16_LE( stream, from, toCount );
2514 + case SNDRV_PCM_FORMAT_S24_LE:
2515 + DPRINTK("SNDRV_PCM_FORMAT_S24_LE\n");
2516 + //ret = copy_from_user_S24_LE( stream, from, toCount );
2519 + case SNDRV_PCM_FORMAT_U24_LE:
2520 + DPRINTK("SNDRV_PCM_FORMAT_U24_LE\n");
2521 + //ret = copy_from_user_U24_LE( stream, from, toCount );
2523 + DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" );
2525 + case SNDRV_PCM_FORMAT_S32_LE:
2526 + DPRINTK("SNDRV_PCM_FORMAT_S32_LE\n");
2527 + ret = copy_from_user_U32( stream, from, toCount );
2530 + DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" );
2541 + * For audio playback, we convert samples of arbitrary format to be 32 bit
2542 + * for our hardware. We're scaling a user buffer to a dma buffer. So when
2543 + * report byte counts, we scale them acording to the ratio of DMA sample
2544 + * size to user buffer sample size. When we report # of DMA fragments,
2545 + * we don't scale that. So:
2547 + * Also adjust the size and number of dma fragments if sample size changed.
2549 + * Input format Input sample Output sample size ratio (out:in)
2550 + * bits channels size (bytes) CM non-CM CM non-CM
2551 + * 8 stereo 2 4 8 2:1 4:1
2552 + * 16 stereo 4 4 8 1:1 2:1
2553 + * 24 stereo 6 4 8 X 8:6 not a real case
2556 +static void snd_ep93xx_dma2usr_ratio( audio_stream_t * stream,int bCompactMode )
2558 + unsigned int dma_sample_size, user_sample_size;
2560 + if(bCompactMode == 1){
2561 + dma_sample_size = 4; /* each stereo sample is 2 * 32 bits */
2564 + dma_sample_size = 8;
2567 + // If stereo 16 bit, user sample is 4 bytes.
2568 + // If stereo 8 bit, user sample is 2 bytes.
2569 + if(stream->audio_num_channels == 1){
2570 + user_sample_size = stream->audio_stream_bitwidth / 8;
2573 + user_sample_size = stream->audio_stream_bitwidth / 4;
2576 + stream->dma2usr_ratio = dma_sample_size / user_sample_size;
2579 +/*---------------------------------------------------------------------------------------------*/
2581 +static int snd_ep93xx_dma_free(struct snd_pcm_substream *substream ){
2584 + audio_state_t *state = substream->private_data;
2585 + audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
2586 + state->output_stream:state->input_stream;
2590 + DPRINTK("snd_ep93xx_dma_free - enter\n");
2591 + for( i = 0 ; i < stream->dma_num_channels ;i++ ){
2592 + ep93xx_dma_free( stream->dmahandles[i] );
2594 + DPRINTK("snd_ep93xx_dma_free - exit\n");
2598 +static int snd_ep93xx_dma_config(struct snd_pcm_substream *substream ){
2600 + audio_state_t *state = substream->private_data;
2601 + audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
2602 + state->output_stream:state->input_stream;
2605 + DPRINTK("snd_ep93xx_dma_config - enter\n");
2607 + for( i = 0 ; i < stream->dma_num_channels ;i++ ){
2609 + err = ep93xx_dma_request(&stream->dmahandles[i],
2610 + stream->devicename,
2611 + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
2612 + state->output_dma[i]:state->input_dma[i] );
2614 + printk("snd_ep93xx_dma_config - exit ERROR dma request failed\n");
2617 + err = ep93xx_dma_config( stream->dmahandles[i],
2618 + IGNORE_CHANNEL_ERROR,
2620 + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
2621 + snd_ep93xx_dma_tx_callback:snd_ep93xx_dma_rx_callback,
2622 + (unsigned int)substream );
2624 + printk("snd_ep93xx_dma_config - exit ERROR dma request failed\n");
2629 + DPRINTK("snd_ep93xx_dma_config - enter\n");
2633 +static void snd_ep93xx_dma_start( audio_state_t * state, audio_stream_t * stream )
2637 + DPRINTK("snd_ep93xx_dma_start - enter\n");
2639 + for(i = 0 ;i < stream->dma_num_channels;i++)
2640 + err = ep93xx_dma_start( stream->dmahandles[i], 1,(unsigned int *) stream->dmahandles );
2642 + stream->active = 1;
2644 + DPRINTK("snd_ep93xx_dma_start - exit\n");
2647 +static void snd_ep93xx_dma_pause( audio_state_t * state, audio_stream_t * stream )
2651 + DPRINTK("snd_ep93xx_dma_pause - enter\n");
2653 + for(i = 0 ;i < stream->dma_num_channels;i++)
2654 + ep93xx_dma_pause( stream->dmahandles[i], 1,(unsigned int *)stream->dmahandles );
2656 + stream->active = 0;
2657 + DPRINTK("snd_ep93xx_dma_pause - exit\n");
2661 +static void snd_ep93xx_dma_flush( audio_state_t * state, audio_stream_t * stream ){
2665 + DPRINTK("snd_ep93xx_dma_flush - enter\n");
2667 + for( i = 0 ; i < stream->dma_num_channels ; i++ )
2668 + ep93xx_dma_flush( stream->dmahandles[i] );
2670 + DPRINTK("snd_ep93xx_dma_flush - exit\n");
2673 +static void snd_ep93xx_deallocate_buffers( struct snd_pcm_substream *substream, audio_stream_t *stream )
2676 + audio_channel_t *dma_chan;
2678 + DPRINTK("snd_ep93xx_deallocate_buffers - enter\n");
2680 + if( stream->dma_channels ){
2682 + for(i = 0;i < stream->dma_num_channels;i++){
2684 + dma_chan = &stream->dma_channels[i];
2686 + if( dma_chan->area ){
2688 + if( dma_chan->audio_buffers ){
2690 + kfree(dma_chan->audio_buffers);
2691 + dma_chan->audio_buffers = NULL;
2695 + kfree(dma_chan->area);
2696 + dma_chan->area = NULL;
2699 + kfree(stream->dma_channels);
2700 + stream->dma_channels = NULL;
2702 + DPRINTK("snd_ep93xx_deallocate_buffers - exit\n");
2705 +static int snd_ep93xx_allocate_buffers(struct snd_pcm_substream *substream, audio_stream_t *stream)
2707 + audio_channel_t *channel;
2708 + unsigned int size,tmpsize,bufsize,bufextsize;
2712 + DPRINTK("snd_ep93xx_allocate_buffers - enter\n" );
2714 + if (stream->dma_channels){
2715 + printk("ep93xx_i2s %s BUSY\n",__FUNCTION__);
2719 + stream->dma_channels = (audio_channel_t *)kmalloc(sizeof(audio_channel_t) * stream->dma_num_channels , GFP_KERNEL);
2721 + if (!stream->dma_channels){
2722 + printk(AUDIO_NAME ": unable to allocate dma_channels memory\n");
2726 + size = ( stream->dmasize / stream->dma_num_channels ) * stream->dma2usr_ratio;
2728 + for( i = 0; i < stream->dma_num_channels;i++){
2729 + channel = &stream->dma_channels[i];
2731 + channel->area = kmalloc( size, GFP_DMA );
2733 + if(!channel->area){
2734 + printk(AUDIO_NAME ": unable to allocate audio memory\n");
2737 + channel->bytes = size;
2738 + channel->addr = __virt_to_phys((int) channel->area);
2739 + memset( channel->area, 0, channel->bytes );
2741 + bufsize = ( stream->fragsize / stream->dma_num_channels ) * stream->dma2usr_ratio;
2742 + channel->audio_buff_count = size / bufsize;
2743 + bufextsize = size % bufsize;
2745 + if( bufextsize > 0 ){
2746 + channel->audio_buff_count++;
2749 + channel->audio_buffers = (audio_buf_t *)kmalloc(sizeof(audio_buf_t) * channel->audio_buff_count , GFP_KERNEL);
2751 + if (!channel->audio_buffers){
2752 + printk(AUDIO_NAME ": unable to allocate audio memory\n ");
2758 + for( j = 0; j < channel->audio_buff_count; j++){
2760 + channel->audio_buffers[j].dma_addr = channel->addr + j * bufsize;
2762 + if( tmpsize >= bufsize ){
2763 + tmpsize -= bufsize;
2764 + channel->audio_buffers[j].bytes = bufsize;
2765 + channel->audio_buffers[j].reportedbytes = bufsize / stream->dma2usr_ratio;
2768 + channel->audio_buffers[j].bytes = bufextsize;
2769 + channel->audio_buffers[j].reportedbytes = bufextsize / stream->dma2usr_ratio;
2774 + DPRINTK("snd_ep93xx_allocate_buffers -- exit SUCCESS\n" );
2779 + * DMA callback functions
2782 +static void snd_ep93xx_dma_tx_callback
2784 + ep93xx_dma_int_t DMAInt,
2785 + ep93xx_dma_dev_t device,
2786 + unsigned int user_data
2791 + unsigned int buf_id;
2793 + struct snd_pcm_substream *substream = (struct snd_pcm_substream *)user_data;
2794 + audio_state_t *state = (audio_state_t *)(substream->private_data);
2795 + audio_stream_t *stream = state->output_stream;
2801 + DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S3\n");
2805 + DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S2\n");
2810 + DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S1\n");
2815 + if(stream->audio_num_channels == 1){
2819 + chan = stream->audio_num_channels / 2 - 1;
2821 + handle = stream->dmahandles[i];
2823 + if(stream->stopped == 0){
2825 + if( ep93xx_dma_remove_buffer( handle, &buf_id ) >= 0 ){
2827 + buf = (audio_buf_t *)buf_id;
2828 + stream->bytecount += buf->reportedbytes;
2829 + ep93xx_dma_add_buffer( stream->dmahandles[i],
2830 + (unsigned int)buf->dma_addr,
2834 + (unsigned int) buf );
2836 + snd_pcm_period_elapsed(substream);
2841 +static void snd_ep93xx_dma_rx_callback
2843 + ep93xx_dma_int_t DMAInt,
2844 + ep93xx_dma_dev_t device,
2845 + unsigned int user_data
2848 + int handle,i,chan;
2849 + unsigned int buf_id;
2852 + struct snd_pcm_substream *substream = (struct snd_pcm_substream *)user_data;
2853 + audio_state_t *state = (audio_state_t *)(substream->private_data);
2854 + audio_stream_t *stream = state->input_stream;
2859 + DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S3\n");
2863 + DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S2\n");
2868 + DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S1\n");
2873 + if(stream->audio_num_channels == 1){
2877 + chan = stream->audio_num_channels / 2 - 1;
2879 + handle = stream->dmahandles[i];
2881 + if( stream->stopped == 0 ){
2883 + if( ep93xx_dma_remove_buffer( handle, &buf_id ) >= 0 ){
2885 + buf = (audio_buf_t *)buf_id;
2886 + stream->bytecount += buf->reportedbytes;
2887 + ep93xx_dma_add_buffer( stream->dmahandles[i],
2888 + (unsigned int)buf->dma_addr,
2892 + (unsigned int) buf );
2894 + snd_pcm_period_elapsed(substream);
2899 +static int snd_ep93xx_release(struct snd_pcm_substream *substream)
2901 + audio_state_t *state = (audio_state_t *)substream->private_data;
2902 + audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
2903 + state->output_stream : state->input_stream;
2905 + DPRINTK("snd_ep93xx_release - enter\n");
2907 + down(&state->sem);
2908 + stream->active = 0;
2909 + stream->stopped = 0;
2910 + snd_ep93xx_deallocate_buffers(substream, stream);
2913 + DPRINTK("snd_ep93xx_release - exit\n");
2918 +static int ep93xx_ac97_pcm_startup(struct snd_pcm_substream *substream)
2920 + struct snd_pcm_runtime *runtime = substream->runtime;
2922 + int iTempMasterVol,iTempHeadphoneVol,iTempMonoVol,iTempRecordSelect;
2923 + /*save the old mixer*/
2924 + iTempRecordSelect = peek(AC97_1A_RECORD_SELECT);
2925 + iTempMasterVol = peek( AC97_02_MASTER_VOL);
2926 + iTempHeadphoneVol = peek( AC97_04_HEADPHONE_VOL);
2927 + iTempMonoVol = peek( AC97_06_MONO_VOL);
2929 + runtime->hw.channels_min = 1;
2930 + runtime->hw.channels_max = 2;
2932 + ep93xx_audio_init();
2933 + /*ep93xx_init_ac97_controller();*/
2935 + /*reset the old output mixer*/
2936 + poke( AC97_02_MASTER_VOL, iTempMasterVol);
2937 + poke( AC97_04_HEADPHONE_VOL,iTempHeadphoneVol );
2938 + poke( AC97_06_MONO_VOL, iTempMonoVol);
2939 + poke( AC97_1A_RECORD_SELECT,iTempRecordSelect);
2941 + r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
2942 + AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
2944 + DPRINTK(" ep93xx_ac97_pcm_startup=%x\n",r);
2950 +static int snd_ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
2951 + struct snd_pcm_hw_params *params)
2953 + DPRINTK("snd_ep93xx_pcm_hw_params - enter\n");
2954 + return snd_pcm_lib_malloc_pages(substream,params_buffer_bytes(params));
2957 +static int snd_ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
2960 + DPRINTK("snd_ep93xx_pcm_hw_free - enter\n");
2961 + return snd_pcm_lib_free_pages(substream);
2965 + *snd_ep93xx_pcm_prepare: need to finish these functions as lower
2966 + *chip_set_sample_format
2967 + *chip_set_sample_rate
2968 + *chip_set_channels
2969 + *chip_set_dma_setup
2972 +static int snd_ep93xx_pcm_prepare_playback( struct snd_pcm_substream *substream)
2974 + audio_state_t *state = (audio_state_t *) substream->private_data;
2975 + struct snd_pcm_runtime *runtime = substream->runtime;
2976 + audio_stream_t *stream = state->output_stream;
2978 + DPRINTK("snd_ep93xx_pcm_prepare_playback - enter\n");
2980 + ep93xx_audio_disable(1);
2981 + ep93xx_ac97_pcm_startup(substream);
2983 + snd_ep93xx_deallocate_buffers(substream,stream);
2985 + //if(runtime->channels % 2 != 0)
2988 + DPRINTK("The runtime item : \n");
2989 + DPRINTK("runtime->dma_addr = 0x%x\n", runtime->dma_addr);
2990 + DPRINTK("runtime->dma_area = 0x%x\n", runtime->dma_area);
2991 + DPRINTK("runtime->dma_bytes = %d\n", runtime->dma_bytes);
2992 + DPRINTK("runtime->frame_bits = %d\n", runtime->frame_bits);
2993 + DPRINTK("runtime->buffer_size = %d\n", runtime->buffer_size);
2994 + DPRINTK("runtime->period_size = %d\n", runtime->period_size);
2995 + DPRINTK("runtime->periods = %d\n", runtime->periods);
2996 + DPRINTK("runtime->rate = %d\n", runtime->rate);
2997 + DPRINTK("runtime->format = %d\n", runtime->format);
2998 + DPRINTK("runtime->channels = %d\n", runtime->channels);
3000 + /* set requestd format when available */
3001 + stream->audio_num_channels = runtime->channels;
3002 + if(stream->audio_num_channels == 1){
3003 + stream->dma_num_channels = 1;
3006 + stream->dma_num_channels = runtime->channels / 2;
3009 + stream->audio_channels_flag = CHANNEL_FRONT;
3010 + if(stream->dma_num_channels == 2)
3011 + stream->audio_channels_flag |= CHANNEL_REAR;
3012 + if(stream->dma_num_channels == 3)
3013 + stream->audio_channels_flag |= CHANNEL_REAR | CHANNEL_CENTER_LFE;
3015 + stream->dmasize = runtime->dma_bytes;
3016 + stream->nbfrags = runtime->periods;
3017 + stream->fragsize = frames_to_bytes (runtime, runtime->period_size);
3018 + stream->bytecount = 0;
3020 + if( !state->codec_set_by_capture ){
3021 + state->codec_set_by_playback = 1;
3023 + if( stream->audio_rate != runtime->rate ){
3024 + ep93xx_set_samplerate( runtime->rate,0 );
3026 + //if( stream->audio_format != runtime->format ){
3027 + // snd_ep93xx_i2s_init((stream->audio_stream_bitwidth == 24));
3031 + audio_stream_t *s = state->input_stream;
3032 + if( runtime->format != s->audio_format)
3034 + if( runtime->rate != s->audio_rate )
3038 + stream->audio_format = runtime->format ;
3039 + ep93xx_set_hw_format(stream->audio_format,stream->audio_num_channels);
3042 + stream->audio_rate = runtime->rate;
3043 + audio_set_format( stream, runtime->format );
3044 + snd_ep93xx_dma2usr_ratio( stream,state->bCompactMode );
3046 + if( snd_ep93xx_allocate_buffers( substream, stream ) != 0 ){
3047 + snd_ep93xx_deallocate_buffers( substream, stream );
3051 + ep93xx_audio_enable(1);
3053 + DPRINTK("snd_ep93xx_pcm_prepare_playback - exit\n");
3057 +static int snd_ep93xx_pcm_prepare_capture( struct snd_pcm_substream *substream)
3059 + audio_state_t *state = (audio_state_t *) substream->private_data;
3060 + struct snd_pcm_runtime *runtime = substream->runtime;
3061 + audio_stream_t *stream = state->input_stream;
3063 + ep93xx_audio_disable(0);
3064 + ep93xx_ac97_pcm_startup(substream);
3066 + snd_ep93xx_deallocate_buffers(substream,stream);
3068 + //if(runtime->channels % 2 != 0)
3071 + DPRINTK("snd_ep93xx_pcm_prepare_capture - enter\n");
3073 +// printk("The runtime item : \n");
3074 +// printk("runtime->dma_addr = 0x%x\n", runtime->dma_addr);
3075 +// printk("runtime->dma_area = 0x%x\n", runtime->dma_area);
3076 +// printk("runtime->dma_bytes = %d\n", runtime->dma_bytes);
3077 +// printk("runtime->frame_bits = %d\n", runtime->frame_bits);
3078 +// printk("runtime->buffer_size = %d\n", runtime->buffer_size);
3079 +// printk("runtime->period_size = %d\n", runtime->period_size);
3080 +// printk("runtime->periods = %d\n", runtime->periods);
3081 +// printk("runtime->rate = %d\n", runtime->rate);
3082 +// printk("runtime->format = %d\n", runtime->format);
3083 +// printk("runtime->channels = %d\n", runtime->channels);
3085 + /* set requestd format when available */
3086 + stream->audio_num_channels = runtime->channels;
3087 + if(stream->audio_num_channels == 1){
3088 + stream->dma_num_channels = 1;
3091 + stream->dma_num_channels = runtime->channels / 2;
3094 + stream->audio_channels_flag = CHANNEL_FRONT;
3095 + if(stream->dma_num_channels == 2)
3096 + stream->audio_channels_flag |= CHANNEL_REAR;
3097 + if(stream->dma_num_channels == 3)
3098 + stream->audio_channels_flag |= CHANNEL_REAR | CHANNEL_CENTER_LFE;
3100 + stream->dmasize = runtime->dma_bytes;
3101 + stream->nbfrags = runtime->periods;
3102 + stream->fragsize = frames_to_bytes (runtime, runtime->period_size);
3103 + stream->bytecount = 0;
3105 + if( !state->codec_set_by_playback ){
3106 + state->codec_set_by_capture = 1;
3109 + if( stream->audio_rate != runtime->rate ){
3110 + ep93xx_set_samplerate( runtime->rate,1 );
3114 + ep93xx_set_recsource(SOUND_MASK_MIC|SOUND_MASK_LINE1 | SOUND_MASK_LINE);
3115 + poke( AC97_1C_RECORD_GAIN, 0);
3118 + //if( stream->audio_format != runtime->format ){
3119 + // snd_ep93xx_i2s_init((stream->audio_stream_bitwidth == 24));
3123 + audio_stream_t *s = state->output_stream;
3124 + if( runtime->format != s->audio_format)
3126 + if( runtime->rate != s->audio_rate )
3130 + stream->audio_format = runtime->format ;
3131 + ep93xx_set_hw_format(stream->audio_format,stream->audio_num_channels);
3134 + stream->audio_rate = runtime->rate;
3135 + audio_set_format( stream, runtime->format );
3136 + snd_ep93xx_dma2usr_ratio( stream,state->bCompactMode );
3138 + if( snd_ep93xx_allocate_buffers( substream, stream ) != 0 ){
3139 + snd_ep93xx_deallocate_buffers( substream, stream );
3143 + ep93xx_audio_enable(0);
3145 + DPRINTK("snd_ep93xx_pcm_prepare_capture - exit\n");
3149 + *start/stop/pause dma translate
3151 +static int snd_ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
3153 + audio_state_t *state = (audio_state_t *)substream->private_data;
3154 + audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
3155 + state->output_stream:state->input_stream;
3157 + audio_channel_t *dma_channel;
3158 + int i,count,ret = 0;
3159 + unsigned long flags;
3161 + DPRINTK("snd_ep93xx_pcm_triger %d - enter \n",cmd);
3165 + case SNDRV_PCM_TRIGGER_START:
3167 + snd_ep93xx_dma_config( substream );
3169 + stream->stopped = 0;
3171 + if( !stream->active && !stream->stopped ){
3172 + stream->active = 1;
3173 + snd_ep93xx_dma_start( state, stream );
3176 + local_irq_save(flags);
3178 + for (i = 0; i < stream->dma_num_channels; i++){
3179 + dma_channel = &stream->dma_channels[i];
3181 + for(count = 0 ;count < dma_channel->audio_buff_count; count++){
3183 + buf = &dma_channel->audio_buffers[count];
3184 + ep93xx_dma_add_buffer( stream->dmahandles[i],
3185 + (unsigned int)buf->dma_addr,
3189 + (unsigned int) buf );
3193 + local_irq_restore(flags);
3196 + case SNDRV_PCM_TRIGGER_STOP:
3197 + stream->stopped = 1;
3198 + snd_ep93xx_dma_pause( state, stream );
3199 + snd_ep93xx_dma_flush( state, stream );
3200 + snd_ep93xx_dma_free( substream );
3203 + case SNDRV_PCM_TRIGGER_SUSPEND:
3205 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
3207 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
3213 + DPRINTK("snd_ep93xx_pcm_triger %d - exit \n",cmd);
3217 +static snd_pcm_uframes_t snd_ep93xx_pcm_pointer_playback(struct snd_pcm_substream *substream)
3219 + audio_state_t *state = (audio_state_t *)(substream->private_data);
3220 + struct snd_pcm_runtime *runtime = substream->runtime;
3221 + audio_stream_t *stream = state->output_stream;
3222 + snd_pcm_uframes_t pointer = 0;
3224 + pointer = bytes_to_frames( runtime,stream->bytecount );
3226 + if (pointer >= runtime->buffer_size){
3228 + stream->bytecount = 0;
3231 + DPRINTK("snd_ep93xx_pcm_pointer_playback - exit\n");
3235 +static snd_pcm_uframes_t snd_ep93xx_pcm_pointer_capture(struct snd_pcm_substream *substream)
3237 + audio_state_t *state = (audio_state_t *)(substream->private_data);
3238 + struct snd_pcm_runtime *runtime = substream->runtime;
3239 + audio_stream_t *stream = state->input_stream;
3240 + snd_pcm_uframes_t pointer = 0;
3242 + pointer = bytes_to_frames( runtime,stream->bytecount );
3244 + if (pointer >= runtime->buffer_size){
3246 + stream->bytecount = 0;
3249 + DPRINTK("snd_ep93xx_pcm_pointer_capture - exit\n");
3253 +static int snd_ep93xx_pcm_open(struct snd_pcm_substream *substream)
3255 + audio_state_t *state = substream->private_data;
3256 + struct snd_pcm_runtime *runtime = substream->runtime;
3257 + audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
3258 + state->output_stream:state->input_stream;
3260 + DPRINTK("snd_ep93xx_pcm_open - enter\n");
3262 + down(&state->sem);
3264 + runtime->hw = ep93xx_ac97_pcm_hardware;
3266 + stream->dma_num_channels = AUDIO_DEFAULT_DMACHANNELS;
3267 + stream->dma_channels = NULL;
3268 + stream->audio_rate = 0;
3269 + stream->audio_stream_bitwidth = 0;
3273 + DPRINTK("snd_ep93xx_pcm_open - exit\n");
3278 + *free the HW dma channel
3279 + *free the HW dma buffer
3280 + *free the Hw dma decrotion using function :kfree
3282 +static int snd_ep93xx_pcm_close(struct snd_pcm_substream *substream)
3284 + audio_state_t *state = (audio_state_t *)(substream->private_data);
3286 + DPRINTK("snd_ep93xx_pcm_close - enter\n");
3288 + snd_ep93xx_release(substream);
3290 + if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3291 + state->codec_set_by_playback = 0;
3293 + state->codec_set_by_capture = 0;
3295 + DPRINTK("snd_ep93xx_pcm_close - exit\n");
3299 +static int snd_ep93xx_pcm_copy_playback(struct snd_pcm_substream * substream,int channel,
3300 + snd_pcm_uframes_t pos,void __user *src, snd_pcm_uframes_t count)
3303 + audio_state_t *state = (audio_state_t *)substream->private_data;
3304 + struct snd_pcm_runtime *runtime = substream->runtime;
3305 + audio_stream_t *stream = state->output_stream ;
3306 + audio_channel_t *dma_channel;
3308 + int tocount = frames_to_bytes(runtime,count);
3310 + for( i = 0; i < stream->dma_num_channels; i++ ){
3312 + dma_channel = &stream->dma_channels[i];
3313 + stream->hwbuf[i] = dma_channel->area + ( frames_to_bytes(runtime,pos) * stream->dma2usr_ratio / stream->dma_num_channels );
3317 + if(copy_from_user_with_conversion(stream ,(const char*)src,(tocount * stream->dma2usr_ratio),state->bCompactMode) <=0 ){
3318 + DPRINTK(KERN_ERR "copy_from_user_with_conversion() failed\n");
3322 + DPRINTK("snd_ep93xx_pcm_copy_playback - exit\n");
3327 +static int snd_ep93xx_pcm_copy_capture(struct snd_pcm_substream * substream,int channel,
3328 + snd_pcm_uframes_t pos,void __user *src, snd_pcm_uframes_t count)
3330 + audio_state_t *state = (audio_state_t *)substream->private_data;
3331 + struct snd_pcm_runtime *runtime = substream->runtime;
3332 + audio_stream_t *stream = state->input_stream ;
3333 + audio_channel_t *dma_channel;
3336 + int tocount = frames_to_bytes(runtime,count);
3338 + for( i = 0; i < stream->dma_num_channels; i++ ){
3340 + dma_channel = &stream->dma_channels[i];
3341 + stream->hwbuf[i] = dma_channel->area + ( frames_to_bytes(runtime,pos) * stream->dma2usr_ratio / stream->dma_num_channels );
3345 + if(copy_to_user_with_conversion(stream,(const char*)src,tocount,state->bCompactMode) <=0 ){
3347 + DPRINTK(KERN_ERR "copy_to_user_with_conversion() failed\n");
3351 + DPRINTK("snd_ep93xx_pcm_copy_capture - exit\n");
3355 +/*----------------------------------------------------------------------------------*/
3356 +static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
3359 + /*volatile u32 *reg_addr;*/
3361 + DPRINTK(" number of codec:%x reg=%x\n",ac97->num,reg);
3364 + printk(KERN_ERR "%s: read error (ac97_reg=%d )val=%x\n",
3365 + __FUNCTION__, reg, val);
3372 +static void ep93xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
3374 + /*volatile u32 *reg_addr;*/
3377 + DPRINTK(" number of codec:%x rge=%x val=%x\n",ac97->num,reg,val);
3378 + ret=poke(reg, val);
3380 + printk(KERN_ERR "%s: write error (ac97_reg=%d val=%x)\n",
3381 + __FUNCTION__, reg, val);
3386 +static void ep93xx_ac97_reset(struct snd_ac97 *ac97)
3389 + DPRINTK(" ep93xx_ac97_reset\n");
3390 + ep93xx_audio_init();
3394 +static struct snd_ac97_bus_ops ep93xx_ac97_ops = {
3395 + .read = ep93xx_ac97_read,
3396 + .write = ep93xx_ac97_write,
3397 + .reset = ep93xx_ac97_reset,
3400 +static struct snd_pcm *ep93xx_ac97_pcm;
3401 +static struct snd_ac97 *ep93xx_ac97_ac97;
3403 +static struct snd_pcm_ops snd_ep93xx_pcm_playback_ops = {
3404 + .open = snd_ep93xx_pcm_open,
3405 + .close = snd_ep93xx_pcm_close,
3406 + .ioctl = snd_pcm_lib_ioctl,
3407 + .hw_params = snd_ep93xx_pcm_hw_params,
3408 + .hw_free = snd_ep93xx_pcm_hw_free,
3409 + .prepare = snd_ep93xx_pcm_prepare_playback,
3410 + .trigger = snd_ep93xx_pcm_trigger,
3411 + .pointer = snd_ep93xx_pcm_pointer_playback,
3412 + .copy = snd_ep93xx_pcm_copy_playback,
3416 +static struct snd_pcm_ops snd_ep93xx_pcm_capture_ops = {
3417 + .open = snd_ep93xx_pcm_open,
3418 + .close = snd_ep93xx_pcm_close,
3419 + .ioctl = snd_pcm_lib_ioctl,
3420 + .hw_params = snd_ep93xx_pcm_hw_params,
3421 + .hw_free = snd_ep93xx_pcm_hw_free,
3422 + .prepare = snd_ep93xx_pcm_prepare_capture,
3423 + .trigger = snd_ep93xx_pcm_trigger,
3424 + .pointer = snd_ep93xx_pcm_pointer_capture,
3425 + .copy = snd_ep93xx_pcm_copy_capture,
3428 +/*--------------------------------------------------------------------------*/
3431 +static int snd_ep93xx_pcm_new(struct snd_card *card, audio_state_t *state, struct snd_pcm **rpcm)
3433 + struct snd_pcm *pcm;
3434 + int play = state->output_stream? 1 : 0;/*SNDRV_PCM_STREAM_PLAYBACK*/
3435 + int capt = state->input_stream ? 1 : 0;/*SNDRV_PCM_STREAM_CAPTURE*/
3438 + DPRINTK("snd_ep93xx_pcm_new - enter\n");
3440 + /* Register the new pcm device interface */
3441 + ret = snd_pcm_new(card, "EP93xx-AC97-PCM", 0, play, capt, &pcm);
3444 + DPRINTK("%s--%x:card=%x,play=%x,capt=%x,&pcm=%x\n",__FUNCTION__,ret,(int)card,play,capt,(int)pcm);
3448 + /* allocate the pcm(DMA) memory */
3449 + ret = snd_pcm_lib_preallocate_pages_for_all(pcm, /*SNDRV_DMA_TYPE_DEV,0,*/SNDRV_DMA_TYPE_CONTINUOUS,snd_dma_continuous_data(GFP_KERNEL),128*1024,128*1024);
3451 + DPRINTK("The substream item : \n");
3452 + DPRINTK("pcm->streams[0].substream->dma_buffer.addr = 0x%x\n", pcm->streams[0].substream->dma_buffer.addr);
3453 + DPRINTK("pcm->streams[0].substream->dma_buffer.area = 0x%x\n", pcm->streams[0].substream->dma_buffer.area);
3454 + DPRINTK("pcm->streams[0].substream->dma_buffer.bytes = 0x%x\n", pcm->streams[0].substream->dma_buffer.bytes);
3455 + DPRINTK("pcm->streams[1].substream->dma_buffer.addr = 0x%x\n", pcm->streams[1].substream->dma_buffer.addr);
3456 + DPRINTK("pcm->streams[1].substream->dma_buffer.area = 0x%x\n", pcm->streams[1].substream->dma_buffer.area);
3457 + DPRINTK("pcm->streams[1].substream->dma_buffer.bytes = 0x%x\n", pcm->streams[1].substream->dma_buffer.bytes);
3459 + pcm->private_data = state;
3461 + /* seem to free the pcm data struct-->self dma buffer */
3462 + pcm->private_free = (void*) snd_pcm_lib_preallocate_free_for_all;
3464 + /* alsa pcm ops setting for SNDRV_PCM_STREAM_PLAYBACK */
3466 + int stream = SNDRV_PCM_STREAM_PLAYBACK;
3467 + snd_pcm_set_ops(pcm, stream, &snd_ep93xx_pcm_playback_ops);
3470 + /* alsa pcm ops setting for SNDRV_PCM_STREAM_CAPTURE */
3472 + int stream = SNDRV_PCM_STREAM_CAPTURE;
3473 + snd_pcm_set_ops(pcm, stream, &snd_ep93xx_pcm_capture_ops);
3478 + DPRINTK("snd_ep93xx_pcm_new - exit\n");
3485 +int ep93xx_ac97_do_suspend(struct snd_card *card, unsigned int state)
3487 + if (card->power_state != SNDRV_CTL_POWER_D3cold) {
3488 + snd_pcm_suspend_all(ep93xx_ac97_pcm);
3489 + snd_ac97_suspend(ep93xx_ac97_ac97);
3490 + snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
3496 +int ep93xx_ac97_do_resume(struct snd_card *card, unsigned int state)
3498 + if (card->power_state != SNDRV_CTL_POWER_D0) {
3500 + snd_ac97_resume(ep93xx_ac97_ac97);
3501 + snd_power_change_state(card, SNDRV_CTL_POWER_D0);
3507 +int ep93xx_ac97_suspend(struct platform_device *_dev, u32 state, u32 level)
3509 + struct snd_card *card = platform_get_drvdata(_dev);
3512 + if (card && level == SUSPEND_DISABLE)
3513 + ret = ep93xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
3518 +int ep93xx_ac97_resume(struct platform_device *_dev, u32 level)
3520 + struct snd_card *card = platform_get_drvdata(_dev);
3523 + if (card && level == RESUME_ENABLE)
3524 + ret = ep93xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
3531 +#define ep93xx_ac97_do_suspend NULL
3532 +#define ep93xx_ac97_do_resume NULL
3533 +#define ep93xx_ac97_suspend NULL
3534 +#define ep93xx_ac97_resume NULL
3537 +int ep93xx_ac97_do_suspend(struct snd_card *card, unsigned int state)
3542 +int ep93xx_ac97_do_resume(struct snd_card *card, unsigned int state)
3547 +int ep93xx_ac97_resume(struct platform_device *_dev, u32 level)
3549 + struct snd_card *card = platform_get_drvdata(_dev);
3552 + //if (card && level == RESUME_ENABLE)
3553 + ret = ep93xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
3558 +int ep93xx_ac97_suspend(struct platform_device *_dev, u32 state, u32 level)
3560 + struct snd_card *card = platform_get_drvdata(_dev);
3563 + //if (card && level == SUSPEND_DISABLE)
3564 + ret = ep93xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
3573 +/* module init & exit */
3574 +static int __devinit ep93xx_ac97_probe(struct platform_device *dev)
3576 + struct snd_card *card;
3577 + struct snd_ac97_bus *ac97_bus;
3578 + struct snd_ac97_template ac97_template;
3579 + int err = -ENOMEM;
3580 + struct resource *res = NULL;
3582 + DPRINTK("snd_ep93xx_probe - enter\n");
3584 + /* Enable audio early on, give the DAC time to come up. */
3585 + res = platform_get_resource( dev, IORESOURCE_MEM, 0);
3588 + printk("error : platform_get_resource \n");
3592 + if (!request_mem_region(res->start,res->end - res->start + 1, "snd-ac97-cs4202" )){
3593 + printk("error : request_mem_region\n");
3597 + /*enable ac97 codec*/
3598 + ep93xx_audio_init();
3600 + /* register the soundcard */
3601 + card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
3604 + printk("AC97: snd_card_new error\n");
3608 + card->dev = &dev->dev;
3609 + /*regist the new pcm device*/
3610 + err = snd_ep93xx_pcm_new(card, &audio_state, &ep93xx_ac97_pcm);
3612 + printk("AC97: ep93xx_ac97_pcm_new error\n");
3615 + if (card == NULL) {
3616 + DPRINTK(KERN_ERR "snd_card_new() failed\n");
3621 + strcpy(card->driver, "CS4202A");
3622 + strcpy(card->shortname, "Cirrus Logic AC97 Audio ");
3623 + strcpy(card->longname, "Cirrus Logic AC97 Audio with CS4202A");
3625 + /*regist the new ac97 device*/
3626 + err = snd_ac97_bus(card, 0, &ep93xx_ac97_ops, NULL, &ac97_bus);
3628 + printk("AC97: snd_ac97_bus error\n");
3632 + memset(&ac97_template, 0, sizeof(ac97_template));
3633 + err = snd_ac97_mixer(ac97_bus, &ac97_template, &ep93xx_ac97_ac97);
3635 + printk("AC97: snd_ac97_mixer error\n");
3640 + ep93xx_audio_init();
3641 + /*setting the card device callback*/
3642 + //err = snd_card_set_pm_callback(card, ep93xx_ac97_do_suspend,ep93xx_ac97_do_resume, (void*)NULL);
3644 + // printk("snd_card_set_pm_callback error\n");
3647 + /*regist the new CARD device*/
3648 + err = snd_card_register(card);
3650 + printk( KERN_INFO "Cirrus Logic ep93xx ac97 audio initialized\n" );
3651 + platform_set_drvdata(dev,card);
3652 + DPRINTK("snd_ep93xx_probe - exit\n");
3657 + snd_card_free(card);
3658 + printk("snd_ep93xx_probe - error\n");
3664 +static int __devexit ep93xx_ac97_remove(struct platform_device *dev)
3666 + struct resource *res;
3667 + struct snd_card *card = platform_get_drvdata(dev);
3669 + res = platform_get_resource( dev, IORESOURCE_MEM, 0);
3670 + release_mem_region(res->start, res->end - res->start + 1);
3672 + DPRINTK("snd_ep93xx_ac97_remove - enter\n");
3675 + snd_card_free(card);
3676 + platform_set_drvdata(dev, NULL);
3678 + DPRINTK("snd_ep93xx_remove - exit\n");
3684 +static struct platform_driver ep93xx_ac97_driver = {
3685 + .probe = ep93xx_ac97_probe,
3686 + .remove = __devexit_p (ep93xx_ac97_remove),
3687 + .suspend = ep93xx_ac97_suspend,
3688 + .resume = ep93xx_ac97_resume,
3690 + .name = "ep93xx-ac97",
3695 +static int __init ep93xx_ac97_init(void)
3699 + DPRINTK(KERN_INFO "%s: version %s\n", DRIVER_DESC, DRIVER_VERSION);
3700 + DPRINTK("snd_ep93xx_AC97_init - enter\n");
3701 + ret = platform_driver_register(&ep93xx_ac97_driver);
3702 + DPRINTK("snd_ep93xx_AC97_init - exit\n");
3706 +static void __exit ep93xx_ac97_exit(void)
3708 + DPRINTK("ep93xx_ac97_exit - enter\n");
3709 + return platform_driver_unregister(&ep93xx_ac97_driver);
3712 +module_init(ep93xx_ac97_init);
3713 +module_exit(ep93xx_ac97_exit);
3715 +MODULE_DESCRIPTION("Cirrus Logic audio module");
3716 +MODULE_LICENSE("GPL");
3718 +++ b/sound/arm/ep93xx-ac97.h
3721 + * linux/sound/arm/ep93xx-ac97.h -- ALSA PCM interface for the edb93xx ac97 audio
3723 + * Author: Fred Wei
3724 + * Created: July 19, 2005
3725 + * Copyright: Cirrus Logic, Inc.
3727 + * This program is free software; you can redistribute it and/or modify
3728 + * it under the terms of the GNU General Public License version 2 as
3729 + * published by the Free Software Foundation.
3732 +#define EP93XX_DEFAULT_NUM_CHANNELS 2
3733 +#define EP93XX_DEFAULT_FORMAT SNDRV_PCM_FORMAT_S16_LE
3734 +#define EP93XX_DEFAULT_BIT_WIDTH 16
3735 +#define MAX_DEVICE_NAME 20
3738 + * Buffer Management
3743 + unsigned char *area; /* virtual pointer */
3744 + dma_addr_t dma_addr; /* physical address */
3746 + size_t reportedbytes; /* buffer size */
3747 + int sent; /* indicates that dma has the buf */
3748 + char *start; /* points to actual buffer */
3755 + unsigned char *area; /* virtual pointer */
3756 + dma_addr_t addr; /* physical address */
3757 + size_t bytes; /* buffer size in bytes */
3758 + unsigned char *buff_pos; /* virtual pointer */
3759 + audio_buf_t *audio_buffers; /* array of audio buffer structures */
3760 + int audio_buff_count;
3765 +typedef struct audio_stream_s {
3768 + int dmahandles[3]; /* handles for dma driver instances */
3769 + char devicename[MAX_DEVICE_NAME]; /* string - name of device */
3770 + int dma_num_channels; /* 1, 2, or 3 DMA channels */
3771 + audio_channel_t *dma_channels;
3772 + u_int nbfrags; /* nbr of fragments i.e. buffers */
3773 + u_int fragsize; /* fragment i.e. buffer size */
3775 + int bytecount; /* nbr of processed bytes */
3776 + int externedbytecount; /* nbr of processed bytes */
3777 + volatile int active; /* actually in progress */
3778 + volatile int stopped; /* might be active but stopped */
3781 + long audio_num_channels; /* Range: 1 to 6 */
3782 + int audio_channels_flag;
3783 + long audio_format;
3784 + long audio_stream_bitwidth; /* Range: 8, 16, 24 */
3785 + int dma2usr_ratio;
3791 + * State structure for one instance
3795 + audio_stream_t *output_stream;
3796 + audio_stream_t *input_stream;
3797 + ep93xx_dma_dev_t output_dma[3];
3798 + ep93xx_dma_dev_t input_dma[3];
3799 + char *output_id[3];
3800 + char *input_id[3];
3801 + struct semaphore sem; /* to protect against races in attach() */
3802 + int codec_set_by_playback;
3803 + int codec_set_by_capture;
3804 + int DAC_bit_width; /* 16, 20, 24 bits */
3805 + int bCompactMode; /* set if 32bits = a stereo sample */