diff -urN linux-2.4.5-rmk7-np2/drivers/sound/Config.in linux-2.4.5-rmk7-np2-ssv1/drivers/sound/Config.in --- linux-2.4.5-rmk7-np2/drivers/sound/Config.in Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/Config.in Wed Oct 10 18:56:03 2001 @@ -6,16 +6,12 @@ # Prompt user for primary drivers. -dep_tristate ' Assabet audio (UDA1341) support' CONFIG_SOUND_ASSABET_UDA1341 $CONFIG_SA1100_ASSABET $CONFIG_SOUND -dep_tristate ' Compaq iPAQ audio support' CONFIG_SOUND_BITSY_UDA1341 $CONFIG_SA1100_BITSY $CONFIG_SOUND -dep_tristate ' Audio support for SA1111/UDA1341' CONFIG_SOUND_SA1111_UDA1341 $CONFIG_SA1111 $CONFIG_SOUND -dep_tristate ' Generic DAC on the SA11x0 SSP port' CONFIG_SOUND_SA1100SSP $CONFIG_ARCH_SA1100 $CONFIG_SOUND - if [ "$CONFIG_SA1100_ASSABET" = "y" -o "$CONFIG_SA1100_BITSY" = "y" -o \ "$CONFIG_SA1100_PANGOLIN" = "y" -o "$CONFIG_SA1100_FREEBIRD" = "y" -o \ "$CONFIG_SA1100_YOPY" = "y" -o "$CONFIG_SA1100_JORNADA720" = "y" ]; then - dep_tristate ' Old Assabet/Bitsy/Pangolin/Yopy/Freebird/Jornada720 audio support (UDA1341)' CONFIG_SOUND_UDA1341 $CONFIG_SOUND + dep_tristate ' Assabet/Bitsy/Pangolin/Yopy/Freebird/Jornada720 audio support (UDA1341)' CONFIG_SOUND_UDA1341 $CONFIG_SOUND fi +dep_tristate ' SA-1100 SSP sound' CONFIG_SOUND_SA1100_SSP $CONFIG_SOUND dep_tristate ' C-Media PCI (CMI8338/8378)' CONFIG_SOUND_CMPCI $CONFIG_SOUND $CONFIG_PCI if [ "$CONFIG_SOUND_CMPCI" = "y" -o "$CONFIG_SOUND_CMPCI" = "m" ]; then diff -urN linux-2.4.5-rmk7-np2/drivers/sound/Makefile linux-2.4.5-rmk7-np2-ssv1/drivers/sound/Makefile --- linux-2.4.5-rmk7-np2/drivers/sound/Makefile Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/Makefile Wed Oct 10 18:56:03 2001 @@ -66,10 +66,7 @@ obj-$(CONFIG_SOUND_MAESTRO3) += maestro3.o ac97_codec.o obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o obj-$(CONFIG_SOUND_UDA1341) += sa1100-uda1341.o -obj-$(CONFIG_SOUND_ASSABET_UDA1341) += assabet-uda1341.o uda1341.o sa1100-audio.o -obj-$(CONFIG_SOUND_BITSY_UDA1341) += bitsy-uda1341.o uda1341.o sa1100-audio.o -obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o uda1341.o sa1100-audio.o -obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o sa1100-audio.o +obj-$(CONFIG_SOUND_SA1100_SSP) += sa1100_ssp.o subdir-$(CONFIG_SOUND_EMU10K1) += emu10k1 subdir-$(CONFIG_SOUND_CS4281) += cs4281 diff -urN linux-2.4.5-rmk7-np2/drivers/sound/assabet-uda1341.c linux-2.4.5-rmk7-np2-ssv1/drivers/sound/assabet-uda1341.c --- linux-2.4.5-rmk7-np2/drivers/sound/assabet-uda1341.c Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/assabet-uda1341.c Thu Jan 1 01:00:00 1970 @@ -1,466 +0,0 @@ -/* - * Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec. - * - * Copyright (c) 2000 Nicolas Pitre - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * This is the machine specific part of the Assabet/UDA1341 support. - * This driver makes use of the UDA1341 and the sa1100-audio modules. - * - * History: - * - * 2000-05-21 Nicolas Pitre Initial release. - * - * 2001-06-03 Nicolas Pitre Made this file a separate module, based on - * the former sa1100-uda1341.c driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "sa1100-audio.h" -#include "uda1341.h" - - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK( x... ) printk( ##x ) -#else -#define DPRINTK( x... ) -#endif - - -#define AUDIO_NAME "Assabet_UDA1341" - -#define AUDIO_FMT_MASK (AFMT_S16_LE) -#define AUDIO_FMT_DEFAULT (AFMT_S16_LE) -#define AUDIO_CHANNELS_DEFAULT 2 -#define AUDIO_RATE_DEFAULT 44100 - - -/* - * GPIO based L3 bus support. - * - * This provides control of Philips L3 type devices. - * GPIO lines are used for clock, data and mode pins. - * - * Note: On Assabet the L3 pins are shared with I2C devices. This should not - * present any problems as long as an I2C start sequence is not generated. - * This is defined as a 1->0 transition on the data lines when the clock is - * high. It is critical this code only allow data transitions when the clock - * is low. This is always legal in L3. - * - * The IIC interface requires the clock and data pin to be LOW when idle. We - * must make sure we leave them in this state. - * - * It appears the read data is generated on the falling edge of the clock - * and should be held stable during the clock high time. - */ - -/* - * L3 bus GPIO pin definitions - */ - -#define L3_DataPin GPIO_GPIO(15) -#define L3_ClockPin GPIO_GPIO(18) -#define L3_ModePin GPIO_GPIO(17) - -/* - * L3 setup and hold times (expressed in us) - */ -#define L3_DataSetupTime 1 /* 190 ns */ -#define L3_DataHoldTime 1 /* 30 ns */ -#define L3_ModeSetupTime 1 /* 190 ns */ -#define L3_ModeHoldTime 1 /* 190 ns */ -#define L3_ClockHighTime 1 /* 250 ns (min is 64*fs, 35us @ 44.1 Khz) */ -#define L3_ClockLowTime 1 /* 250 ns (min is 64*fs, 35us @ 44.1 Khz) */ -#define L3_HaltTime 1 /* 190 ns */ - -/* - * Grab control of the IIC/L3 shared pins - */ -static inline void L3_acquirepins(void) -{ - GPSR = (L3_ModePin | L3_ClockPin | L3_DataPin); - GPDR |= (L3_ModePin | L3_ClockPin | L3_DataPin); -} - -/* - * Release control of the IIC/L3 shared pins - */ -static inline void L3_releasepins(void) -{ - GPDR &= ~(L3_ModePin | L3_ClockPin | L3_DataPin); -} - -/* - * Initialize the interface - */ -static void L3_init(void) -{ - GAFR &= ~(L3_DataPin | L3_ClockPin | L3_ModePin); - L3_releasepins(); -} - -/* - * Get a bit. The clock is high on entry and on exit. Data is read after - * the clock low time has expired. - */ -static inline int L3_getbit(void) -{ - int data; - - GPCR = L3_ClockPin; - udelay(L3_ClockLowTime); - - data = (GPLR & L3_DataPin) ? 1 : 0; - - GPSR = L3_ClockPin; - udelay(L3_ClockHighTime); - - return data; -} - -/* - * Send a bit. The clock is high on entry and on exit. Data is sent only - * when the clock is low (I2C compatibility). - */ -static inline void L3_sendbit(int bit) -{ - GPCR = L3_ClockPin; - - if (bit & 1) - GPSR = L3_DataPin; - else - GPCR = L3_DataPin; - - /* Assumes L3_DataSetupTime < L3_ClockLowTime */ - udelay(L3_ClockLowTime); - - GPSR = L3_ClockPin; - udelay(L3_ClockHighTime); -} - -/* - * Send a byte. The mode line is set or pulsed based on the mode sequence - * count. The mode line is high on entry and exit. The mod line is pulsed - * before the second data byte and before ech byte thereafter. - */ -static void L3_sendbyte(char data, int mode) -{ - int i; - - switch (mode) { - case 0: /* Address mode */ - GPCR = L3_ModePin; - break; - case 1: /* First data byte */ - break; - default: /* Subsequent bytes */ - GPCR = L3_ModePin; - udelay(L3_HaltTime); - GPSR = L3_ModePin; - break; - } - - udelay(L3_ModeSetupTime); - - for (i = 0; i < 8; i++) - L3_sendbit(data >> i); - - if (mode == 0) /* Address mode */ - GPSR = L3_ModePin; - - udelay(L3_ModeHoldTime); -} - -/* - * Get a byte. The mode line is set or pulsed based on the mode sequence - * count. The mode line is high on entry and exit. The mod line is pulsed - * before the second data byte and before each byte thereafter. This - * function is never valid with mode == 0 (address cycle) as the address - * is always sent on the bus, not read. - * L3_DataPin must be set to an input before calling this function! - */ -static char L3_getbyte(int mode) -{ - char data = 0; - int i; - - switch (mode) { - case 0: /* Address mode - never valid */ - break; - case 1: /* First data byte */ - break; - default: /* Subsequent bytes */ - GPCR = L3_ModePin; - udelay(L3_HaltTime); - GPSR = L3_ModePin; - break; - } - - udelay(L3_ModeSetupTime); - - for (i = 0; i < 8; i++) - data |= (L3_getbit() << i); - - udelay(L3_ModeHoldTime); - - return data; -} - -/* - * Write data to a device on the L3 bus. The address is passed as well as - * the data and length. The length written is returned. The register space - * is encoded in the address (low two bits are set and device address is - * in the upper 6 bits). - */ -static int L3_write(char addr, char *data, int len) -{ - int bytes = len; - int mode = 0; - - DPRINTK("%s(0x%x, %d)\n", __FUNCTION__, addr, len); - - L3_acquirepins(); - L3_sendbyte(addr, mode++); - while(len--) - L3_sendbyte(*data++, mode++); - L3_releasepins(); - - return bytes; -} - -/* - * Read data from a device on the L3 bus. The address is passed as well as - * the data and length. The length read is returned. The register space - * is encoded in the address (low two bits are set and device address is - * in the upper 6 bits). - */ -static int L3_read(char addr, char *data, int len) -{ - int bytes = len; - int mode = 0; - - DPRINTK("%s(0x%x, %d)\n", __FUNCTION__, addr, len); - - L3_acquirepins(); - L3_sendbyte(addr, mode++); - GPDR &= ~(L3_DataPin); - while(len--) - *data++ = L3_getbyte(mode++); - L3_releasepins(); - - return bytes; -} - - -/* - * Mixer (UDA1341) interface - */ - -static UDA1341_regs_t UDA1341_regs = UDA1341_REGS_DFLT; - -static UDA1341_state_t uda1341_state = { - regs: &UDA1341_regs, - L3_write: L3_write, - L3_read: L3_read, -}; - -static int mixer_ioctl (struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - return uda1341_mixer_ioctl(&uda1341_state, cmd, arg); -} - -static struct file_operations assabet_mixer_fops = { - ioctl: mixer_ioctl, - owner: THIS_MODULE -}; - - -/* - * Audio interface - */ - -static void assabet_audio_init(void) -{ - /* Setup the uarts */ - GAFR |= (GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | - GPIO_SSP_SFRM | GPIO_SSP_CLK); - GPDR |= (GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM); - GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK); - PPAR |= PPAR_SPR; - Ser4SSCR0 = SSCR0_SSE + SSCR0_DataSize(16) + SSCR0_TI; - Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; - - L3_init(); - - /* Enable the audio power */ - BCR_clear(BCR_STEREO_LB | BCR_QMUTE | BCR_SPK_OFF); - BCR_set(BCR_CODEC_RST | BCR_AUDIO_ON); - - /* - * The assabet board uses the SDRAM clock as the source clock for - * audio. This is supplied to the SA11x0 from the CPLD on pin 19. - * At 206Mhz we need to run the audio clock (SDRAM bank 2) - * at half speed. This clock will scale with core frequency so - * the audio sample rate will also scale. The CPLD on Assabet - * will need to be programmed to match the core frequency. - */ - MDREFR |= (MDREFR_K2DB2 | MDREFR_K2RUN); - /* Make sure EAPD and KAPD are clear to run the clocks at all times. */ - MDREFR &= ~(MDREFR_EAPD | MDREFR_KAPD); - - /* Wait for the UDA1341 to wake up */ - mdelay(1); - - /* initialize the UDA1341 internal state */ - uda1341_state.active = 1; - uda1341_reset(&uda1341_state); -} - -static void assabet_audio_shutdown(void) -{ - uda1341_state.active = 0; - /* disable the audio power */ - BCR_set(BCR_STEREO_LB | BCR_QMUTE | BCR_SPK_OFF); - BCR_clear(BCR_AUDIO_ON); - /* - * We can't clear BCR_CODEC_RST without knowing if - * the UCB1300 driver is still active... A global - * count would be required for this. - */ -} - -static int assabet_audio_ioctl( struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - long val; - int ret = 0; - - /* - * These are platform dependent ioctls which are not handled by the - * generic sa1100-audio module. - */ - switch (cmd) { - case SNDCTL_DSP_SETFMT: - ret = get_user(val, (long *) arg); - if (ret) break; - if (val & AUDIO_FMT_MASK) { - break; - } else - return -EINVAL; - - case SNDCTL_DSP_CHANNELS: - case SNDCTL_DSP_STEREO: - ret = get_user(val, (long *) arg); - if (ret) break; - if (cmd == SNDCTL_DSP_STEREO) - val = val ? 2 : 1; - /* the UDA1341 is stereo only */ - if (val != 2) - return -EINVAL; - break; - - case SOUND_PCM_READ_CHANNELS: - return put_user(2, (long *) arg); - - case SNDCTL_DSP_SPEED: - /* - * FIXME: we need to modify the clock rate for DRAM bank 2 - * (our clock source) accordingly. - */ - val = 44100; - return put_user(44100, (long *) arg); - - case SOUND_PCM_READ_RATE: - return put_user(44100, (long *) arg); - - case SNDCTL_DSP_GETFMTS: - return put_user(AUDIO_FMT_MASK, (long *) arg); - - default: - /* Maybe this is meant for the mixer (As per OSS Docs) */ - return uda1341_mixer_ioctl(&uda1341_state, cmd, arg); - } - - return ret; -} - -static audio_stream_t output_stream, input_stream; - -static audio_state_t audio_state = { - output_stream: &output_stream, - input_stream: &input_stream, - need_tx_for_rx: 1, - hw_init: assabet_audio_init, - hw_shutdown: assabet_audio_shutdown, - client_ioctl: assabet_audio_ioctl, -}; - -static int assabet_audio_open(struct inode *inode, struct file *file) -{ - return sa1100_audio_instance(inode, file, &audio_state); -} - -/* - * Missing fields of this structure will be patched with the call - * to sa1100_audio_instance() - */ -static struct file_operations assabet_audio_fops = { - open: assabet_audio_open, - owner: THIS_MODULE -}; - - -static int audio_dev_id, mixer_dev_id; - -static int __init assabet_uda1341_init(void) -{ - if (!machine_is_assabet()) - return -ENODEV; - - /* Acquire and initialize DMA */ - if (sa1100_request_dma(&output_stream.dma_ch, "UDA1341 out") < 0 || - sa1100_request_dma(&input_stream.dma_ch, "UDA1341 in") < 0) { - sa1100_free_dma(output_stream.dma_ch); - printk( KERN_ERR AUDIO_NAME ": unable to get DMA channels\n" ); - return -EBUSY; - } - sa1100_dma_set_device(output_stream.dma_ch, DMA_Ser4SSPWr); - sa1100_dma_set_device(input_stream.dma_ch, DMA_Ser4SSPRd); - - /* register devices */ - audio_dev_id = register_sound_dsp(&assabet_audio_fops, -1); - mixer_dev_id = register_sound_mixer(&assabet_mixer_fops, -1); - - printk( KERN_INFO AUDIO_NAME " initialized\n" ); - return 0; -} - -module_init(assabet_uda1341_init); - - -static void __exit assabet_uda1341_exit(void) -{ - unregister_sound_dsp(audio_dev_id); - unregister_sound_mixer(mixer_dev_id); - sa1100_free_dma(output_stream.dma_ch); - sa1100_free_dma(input_stream.dma_ch); -} - -module_exit(assabet_uda1341_exit); diff -urN linux-2.4.5-rmk7-np2/drivers/sound/bitsy-uda1341.c linux-2.4.5-rmk7-np2-ssv1/drivers/sound/bitsy-uda1341.c --- linux-2.4.5-rmk7-np2/drivers/sound/bitsy-uda1341.c Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/bitsy-uda1341.c Thu Jan 1 01:00:00 1970 @@ -1,511 +0,0 @@ -/* - * Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec. - * - * Copyright (c) 2000 Nicolas Pitre - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * This is the machine specific part of the Compaq iPAQ (aka Bitsy) support. - * This driver makes use of the UDA1341 and the sa1100-audio modules. - * - * History: - * - * 2000-05-21 Nicolas Pitre Initial UDA1341 driver release. - * - * 2000-07-?? George France Bitsy support. - * - * 2000-12-13 Deborah Wallach Fixed power handling for iPAQ/bitsy - * - * 2001-06-03 Nicolas Pitre Made this file a separate module, based on - * the former sa1100-uda1341.c driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "sa1100-audio.h" -#include "uda1341.h" - - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK( x... ) printk( ##x ) -#else -#define DPRINTK( x... ) -#endif - - -#define AUDIO_NAME "Bitsy_UDA1341" - -#define AUDIO_FMT_MASK (AFMT_S16_LE) -#define AUDIO_FMT_DEFAULT (AFMT_S16_LE) -#define AUDIO_CHANNELS_DEFAULT 2 -#define AUDIO_RATE_DEFAULT 44100 - - -/* - * GPIO based L3 bus support. - * - * This provides control of Philips L3 type devices. - * GPIO lines are used for clock, data and mode pins. - * It appears the read data is generated on the falling edge of the clock - * and should be held stable during the clock high time. - */ - -/* - * L3 bus GPIO pin definitions - */ - -#define L3_DataPin GPIO_BITSY_L3_DATA -#define L3_ClockPin GPIO_BITSY_L3_CLOCK -#define L3_ModePin GPIO_BITSY_L3_MODE - -/* - * L3 setup and hold times (expressed in us) - */ -#define L3_DataSetupTime 1 /* 190 ns */ -#define L3_DataHoldTime 1 /* 30 ns */ -#define L3_ModeSetupTime 1 /* 190 ns */ -#define L3_ModeHoldTime 1 /* 190 ns */ -#define L3_ClockHighTime 1 /* 250 ns (min is 64*fs, 35us @ 44.1 Khz) */ -#define L3_ClockLowTime 1 /* 250 ns (min is 64*fs, 35us @ 44.1 Khz) */ -#define L3_HaltTime 1 /* 190 ns */ - -/* - * Grab control of the IIC/L3 shared pins - */ -static inline void L3_acquirepins(void) -{ - GPSR = (L3_ModePin | L3_ClockPin | L3_DataPin); - GPDR |= (L3_ModePin | L3_ClockPin | L3_DataPin); -} - -/* - * Release control of the IIC/L3 shared pins - */ -static inline void L3_releasepins(void) -{ - GPDR &= ~(L3_ModePin | L3_ClockPin | L3_DataPin); -} - -/* - * Initialize the interface - */ -static void L3_init(void) -{ - GAFR &= ~(L3_DataPin | L3_ClockPin | L3_ModePin); - L3_releasepins(); -} - -/* - * Get a bit. The clock is high on entry and on exit. Data is read after - * the clock low time has expired. - */ -static inline int L3_getbit(void) -{ - int data; - - GPCR = L3_ClockPin; - udelay(L3_ClockLowTime); - - data = (GPLR & L3_DataPin) ? 1 : 0; - - GPSR = L3_ClockPin; - udelay(L3_ClockHighTime); - - return data; -} - -/* - * Send a bit. The clock is high on entry and on exit. Data is sent only - * when the clock is low (I2C compatibility). - */ -static inline void L3_sendbit(int bit) -{ - GPCR = L3_ClockPin; - - if (bit & 1) - GPSR = L3_DataPin; - else - GPCR = L3_DataPin; - - /* Assumes L3_DataSetupTime < L3_ClockLowTime */ - udelay(L3_ClockLowTime); - - GPSR = L3_ClockPin; - udelay(L3_ClockHighTime); -} - -/* - * Send a byte. The mode line is set or pulsed based on the mode sequence - * count. The mode line is high on entry and exit. The mod line is pulsed - * before the second data byte and before ech byte thereafter. - */ -static void L3_sendbyte(char data, int mode) -{ - int i; - - switch (mode) { - case 0: /* Address mode */ - GPCR = L3_ModePin; - break; - case 1: /* First data byte */ - break; - default: /* Subsequent bytes */ - GPCR = L3_ModePin; - udelay(L3_HaltTime); - GPSR = L3_ModePin; - break; - } - - udelay(L3_ModeSetupTime); - - for (i = 0; i < 8; i++) - L3_sendbit(data >> i); - - if (mode == 0) /* Address mode */ - GPSR = L3_ModePin; - - udelay(L3_ModeHoldTime); -} - -/* - * Get a byte. The mode line is set or pulsed based on the mode sequence - * count. The mode line is high on entry and exit. The mod line is pulsed - * before the second data byte and before each byte thereafter. This - * function is never valid with mode == 0 (address cycle) as the address - * is always sent on the bus, not read. - * L3_DataPin must be set to an input before calling this function! - */ -static char L3_getbyte(int mode) -{ - char data = 0; - int i; - - switch (mode) { - case 0: /* Address mode - never valid */ - break; - case 1: /* First data byte */ - break; - default: /* Subsequent bytes */ - GPCR = L3_ModePin; - udelay(L3_HaltTime); - GPSR = L3_ModePin; - break; - } - - udelay(L3_ModeSetupTime); - - for (i = 0; i < 8; i++) - data |= (L3_getbit() << i); - - udelay(L3_ModeHoldTime); - - return data; -} - -/* - * Write data to a device on the L3 bus. The address is passed as well as - * the data and length. The length written is returned. The register space - * is encoded in the address (low two bits are set and device address is - * in the upper 6 bits). - */ -static int L3_write(char addr, char *data, int len) -{ - int bytes = len; - int mode = 0; - - DPRINTK("%s(0x%x, %d)\n", __FUNCTION__, addr, len); - - L3_acquirepins(); - L3_sendbyte(addr, mode++); - while(len--) - L3_sendbyte(*data++, mode++); - L3_releasepins(); - - return bytes; -} - -/* - * Read data from a device on the L3 bus. The address is passed as well as - * the data and length. The length read is returned. The register space - * is encoded in the address (low two bits are set and device address is - * in the upper 6 bits). - */ -static int L3_read(char addr, char *data, int len) -{ - int bytes = len; - int mode = 0; - - DPRINTK("%s(0x%x, %d)\n", __FUNCTION__, addr, len); - - L3_acquirepins(); - L3_sendbyte(addr, mode++); - GPDR &= ~(L3_DataPin); - while(len--) - *data++ = L3_getbyte(mode++); - L3_releasepins(); - - return bytes; -} - - -/* - * Mixer (UDA1341) interface - */ - -static UDA1341_regs_t UDA1341_regs = UDA1341_REGS_DFLT; - -static UDA1341_state_t uda1341_state = { - regs: &UDA1341_regs, - L3_write: L3_write, - L3_read: L3_read, -}; - -static int mixer_ioctl (struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - return uda1341_mixer_ioctl(&uda1341_state, cmd, arg); -} - -static struct file_operations bitsy_mixer_fops = { - ioctl: mixer_ioctl, - owner: THIS_MODULE -}; - - -/* - * Audio interface - */ - -static long audio_samplerate = AUDIO_RATE_DEFAULT; - -static void bitsy_set_samplerate(long val) -{ - if (val >= 48000) - val = 48000; - else if (val >= 44100) - val = 44100; - else if (val >= 32000) - val = 32000; - else if (val >= 22050) - val = 22050; - else if (val >= 16000) - val = 16000; - else if (val >= 11025) - val = 11025; - else - val = 8000; - - /* set the external clock generator */ - switch (val) { - case 32000: - case 48000: - /* 00: 12.288 MHz */ - GPCR = GPIO_BITSY_CLK_SET0 | GPIO_BITSY_CLK_SET1; - break; - case 44100: - case 22050: - /* 01: 11.2896 MHz */ - GPSR = GPIO_BITSY_CLK_SET0; - GPCR = GPIO_BITSY_CLK_SET1; - break; - case 8000: - case 16000: - /* 10: 4.096 MHz */ - GPCR = GPIO_BITSY_CLK_SET0; - GPSR = GPIO_BITSY_CLK_SET1; - break; - case 11025: - /* 11: 5.6245 MHz */ - GPSR = GPIO_BITSY_CLK_SET0 | GPIO_BITSY_CLK_SET1; - break; - } - switch (val) { - case 8000: - case 11025: - case 22050: - UDA1341_regs.status_0.system_clk = UDA_STATUS0_SC_512FS; - break; - case 16000: - case 44100: - case 48000: - UDA1341_regs.status_0.system_clk = UDA_STATUS0_SC_256FS; - break; - case 32000: - UDA1341_regs.status_0.system_clk = UDA_STATUS0_SC_384FS; - break; - } - L3_write((UDA1341_L3Addr << 2) | UDA1341_STATUS, - (char *)&UDA1341_regs.status_0, 1); - audio_samplerate = val; -} - -static void bitsy_audio_init(void) -{ - /* Setup the uarts */ - GAFR &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM); - GAFR |= (GPIO_SSP_CLK); - GPDR &= ~(GPIO_SSP_CLK); - Ser4SSCR0 = 0; - Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI; - Ser4SSCR0 |= SSCR0_SerClkDiv(8); - Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; - Ser4SSCR0 |= SSCR0_SSE; - - /* Setup L3 bus */ - L3_init(); - - /* Enable the audio power */ - set_bitsy_egpio(EGPIO_BITSY_CODEC_NRESET | EGPIO_BITSY_AUD_AMP_ON | - EGPIO_BITSY_AUD_PWR_ON); - clr_bitsy_egpio(EGPIO_BITSY_QMUTE); - - /* external clock configuration */ - GPDR |= (GPIO_BITSY_CLK_SET0 | GPIO_BITSY_CLK_SET1); - bitsy_set_samplerate(audio_samplerate); - - /* Wait for the UDA1341 to wake up */ - mdelay(1); - - /* Initialize the UDA1341 internal state */ - uda1341_state.active = 1; - uda1341_reset(&uda1341_state); -} - -static void bitsy_audio_shutdown(void) -{ - uda1341_state.active = 0; - /* disable the audio power and all signals leading to the audio chip */ - clr_bitsy_egpio(EGPIO_BITSY_CODEC_NRESET | EGPIO_BITSY_AUD_AMP_ON | - EGPIO_BITSY_AUD_PWR_ON | EGPIO_BITSY_QMUTE); -} - -static int bitsy_audio_ioctl(struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - long val; - int ret = 0; - - /* - * These are platform dependent ioctls which are not handled by the - * generic sa1100-audio module. - */ - switch (cmd) { - case SNDCTL_DSP_SETFMT: - ret = get_user(val, (long *) arg); - if (ret) break; - if (val & AUDIO_FMT_MASK) { - break; - } else - return -EINVAL; - - case SNDCTL_DSP_CHANNELS: - case SNDCTL_DSP_STEREO: - ret = get_user(val, (long *) arg); - if (ret) break; - if (cmd == SNDCTL_DSP_STEREO) - val = val ? 2 : 1; - /* the UDA1341 is stereo only */ - if (val != 2) - return -EINVAL; - break; - - case SOUND_PCM_READ_CHANNELS: - return put_user(2, (long *) arg); - - case SNDCTL_DSP_SPEED: - ret = get_user(val, (long *) arg); - if (ret) break; - bitsy_set_samplerate(val); - /* fall through */ - - case SOUND_PCM_READ_RATE: - return put_user(audio_samplerate, (long *) arg); - - case SNDCTL_DSP_GETFMTS: - return put_user(AUDIO_FMT_MASK, (long *) arg); - - default: - /* Maybe this is meant for the mixer (As per OSS Docs) */ - return uda1341_mixer_ioctl(&uda1341_state, cmd, arg); - } - - return ret; -} - -static audio_stream_t output_stream, input_stream; - -static audio_state_t audio_state = { - output_stream: &output_stream, - input_stream: &input_stream, - need_tx_for_rx: 1, - hw_init: bitsy_audio_init, - hw_shutdown: bitsy_audio_shutdown, - client_ioctl: bitsy_audio_ioctl, -}; - -static int bitsy_audio_open(struct inode *inode, struct file *file) -{ - return sa1100_audio_instance(inode, file, &audio_state); -} - -/* - * Missing fields of this structure will be patched with the call - * to sa1100_audio_instance() - */ -static struct file_operations bitsy_audio_fops = { - open: bitsy_audio_open, - owner: THIS_MODULE -}; - - -static int audio_dev_id, mixer_dev_id; - -static int __init bitsy_uda1341_init(void) -{ - if (!machine_is_bitsy()) - return -ENODEV; - - /* Acquire and initialize DMA */ - if (sa1100_request_dma(&output_stream.dma_ch, "UDA1341 out") < 0 || - sa1100_request_dma(&input_stream.dma_ch, "UDA1341 in") < 0) { - sa1100_free_dma(output_stream.dma_ch); - printk( KERN_ERR AUDIO_NAME ": unable to get DMA channels\n" ); - return -EBUSY; - } - sa1100_dma_set_device(output_stream.dma_ch, DMA_Ser4SSPWr); - sa1100_dma_set_device(input_stream.dma_ch, DMA_Ser4SSPRd); - - /* register devices */ - audio_dev_id = register_sound_dsp(&bitsy_audio_fops, -1); - mixer_dev_id = register_sound_mixer(&bitsy_mixer_fops, -1); - - printk( KERN_INFO AUDIO_NAME " initialized\n" ); - return 0; -} - -module_init(bitsy_uda1341_init); - - -static void __exit bitsy_uda1341_exit(void) -{ - unregister_sound_dsp(audio_dev_id); - unregister_sound_mixer(mixer_dev_id); - sa1100_free_dma(output_stream.dma_ch); - sa1100_free_dma(input_stream.dma_ch); -} - -module_exit(bitsy_uda1341_exit); diff -urN linux-2.4.5-rmk7-np2/drivers/sound/sa1100-audio.c linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1100-audio.c --- linux-2.4.5-rmk7-np2/drivers/sound/sa1100-audio.c Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1100-audio.c Thu Jan 1 01:00:00 1970 @@ -1,729 +0,0 @@ -/* - * Common audio handling for the SA11x0 processor - * - * Copyright (c) 2000 Nicolas Pitre - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * - * This module handles the generic buffering/DMA/mmap audio interface for - * codecs connected to the SA1100 chip. All features depending on specific - * hardware implementations like supported audio formats or samplerates are - * relegated to separate specific modules. - * - * - * History: - * - * 2000-05-21 Nicolas Pitre Initial release. - * - * 2000-06-10 Erik Bunce Add initial poll support. - * - * 2000-08-22 Nicolas Pitre Removed all DMA stuff. Now using the - * generic SA1100 DMA interface. - * - * 2000-11-30 Nicolas Pitre - Validation of opened instances; - * - Power handling at open/release time instead - * of driver load/unload; - * - * 2001-06-03 Nicolas Pitre Made this file a separate module, based on - * the former sa1100-uda1341.c driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sa1100-audio.h" - - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK( x... ) printk( ##x ) -#else -#define DPRINTK( x... ) -#endif - - -#define AUDIO_NAME "sa1100-audio" -#define AUDIO_NBFRAGS_DEFAULT 8 -#define AUDIO_FRAGSIZE_DEFAULT 8192 - -#define NEXT_BUF(_s_,_b_) { \ - (_s_)->_b_##_idx++; \ - (_s_)->_b_##_idx %= (_s_)->nbfrags; \ - (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; } - -#define AUDIO_ACTIVE(state) ((state)->rd_refcount || (state)->wr_refcount) - -/* - * This function frees all buffers - */ - -static void audio_clear_buf(audio_stream_t * s) -{ - DPRINTK("audio_clear_buf\n"); - - /* ensure DMA won't run anymore */ - sa1100_dma_flush_all(s->dma_ch); - - if (s->buffers) { - int frag; - for (frag = 0; frag < s->nbfrags; frag++) { - if (!s->buffers[frag].master) - continue; - consistent_free(s->buffers[frag].start, - s->buffers[frag].master, - s->buffers[frag].dma_addr); - } - kfree(s->buffers); - s->buffers = NULL; - } - - s->buf_idx = 0; - s->buf = NULL; -} - - -/* - * This function allocates the buffer structure array and buffer data space - * according to the current number of fragments and fragment size. - */ - -static int audio_setup_buf(audio_stream_t * s) -{ - int frag; - int dmasize = 0; - char *dmabuf = NULL; - dma_addr_t dmaphys = 0; - - if (s->buffers) - return -EBUSY; - - s->buffers = (audio_buf_t *) - kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL); - if (!s->buffers) - goto err; - memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags); - - for (frag = 0; frag < s->nbfrags; frag++) { - audio_buf_t *b = &s->buffers[frag]; - - /* - * Let's allocate non-cached memory for DMA buffers. - * We try to allocate all memory at once. - * If this fails (a common reason is memory fragmentation), - * then we allocate more smaller buffers. - */ - if (!dmasize) { - dmasize = (s->nbfrags - frag) * s->fragsize; - do { - dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA, - dmasize, - &dmaphys); - if (!dmabuf) - dmasize -= s->fragsize; - } while (!dmabuf && dmasize); - if (!dmabuf) - goto err; - b->master = dmasize; - } - - b->start = dmabuf; - b->dma_addr = dmaphys; - sema_init(&b->sem, 1); - DPRINTK("buf %d: start %p dma %p\n", frag, b->start, - b->dma_addr); - - dmabuf += s->fragsize; - dmaphys += s->fragsize; - dmasize -= s->fragsize; - } - - s->buf_idx = 0; - s->buf = &s->buffers[0]; - - return 0; - -err: - printk(AUDIO_NAME ": unable to allocate audio memory\n "); - audio_clear_buf(s); - return -ENOMEM; -} - - -/* - * DMA callback functions - */ - -static void audio_dmaout_done_callback(void *buf_id, int size) -{ - audio_buf_t *b = (audio_buf_t *) buf_id; - /* - * Current buffer is sent: wake up any process waiting for it. - */ - up(&b->sem); - /* And any process polling on write. */ - wake_up(&b->sem.wait); -} - -static void audio_dmain_done_callback(void *buf_id, int size) -{ - audio_buf_t *b = (audio_buf_t *) buf_id; - /* - * Current buffer is full: set its size and wake up any - * process waiting for it. - */ - b->size = size; - up(&b->sem); - /* And any process polling on read. */ - wake_up(&b->sem.wait); -} - - -static int audio_sync(struct file *file) -{ - audio_state_t *state = (audio_state_t *)file->private_data; - audio_stream_t *s = state->output_stream; - audio_buf_t *b = s->buf; - - DPRINTK("audio_sync\n"); - - if (!s->buffers) - return 0; - - /* Send half-full buffers */ - if (b->size != 0) { - down(&b->sem); - sa1100_dma_queue_buffer(s->dma_ch, (void *) b, - b->dma_addr, b->size); - b->size = 0; - NEXT_BUF(s, buf); - } - - /* - * Let's wait for the last buffer we sent i.e. the one before the - * current buf_idx. When we acquire the semaphore, this means either: - * - DMA on the buffer completed or - * - the buffer was already free thus nothing else to sync. - */ - b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags); - if (down_interruptible(&b->sem)) - return -EINTR; - up(&b->sem); - return 0; -} - - -static int audio_write(struct file *file, const char *buffer, - size_t count, loff_t * ppos) -{ - const char *buffer0 = buffer; - audio_state_t *state = (audio_state_t *)file->private_data; - audio_stream_t *s = state->output_stream; - int chunksize, ret = 0; - - DPRINTK("audio_write: count=%d\n", count); - - switch (file->f_flags & O_ACCMODE) { - case O_WRONLY: - case O_RDWR: - break; - default: - return -EPERM; - } - - if (!s->buffers && audio_setup_buf(s)) - return -ENOMEM; - - /* be sure to have a full sample byte count */ - count &= ~0x03; - - while (count > 0) { - audio_buf_t *b = s->buf; - - /* Wait for a buffer to become free */ - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - if (down_trylock(&b->sem)) - break; - } else { - ret = -ERESTARTSYS; - if (down_interruptible(&b->sem)) - break; - } - - /* Feed the current buffer */ - chunksize = s->fragsize - b->size; - if (chunksize > count) - chunksize = count; - DPRINTK("write %d to %d\n", chunksize, s->buf_idx); - if (copy_from_user(b->start + b->size, buffer, chunksize)) { - up(&b->sem); - return -EFAULT; - } - b->size += chunksize; - buffer += chunksize; - count -= chunksize; - if (b->size < s->fragsize) { - up(&b->sem); - break; - } - - /* Send current buffer to dma */ - sa1100_dma_queue_buffer(s->dma_ch, (void *) b, - b->dma_addr, b->size); - b->size = 0; /* indicate that the buffer has been sent */ - NEXT_BUF(s, buf); - } - - if ((buffer - buffer0)) - ret = buffer - buffer0; - DPRINTK("audio_write: return=%d\n", ret); - return ret; -} - - -static int audio_recording(audio_state_t *state) -{ - audio_stream_t *s = state->input_stream; - int i; - - if (!s->buffers) { - if (audio_setup_buf(s)) - return -ENOMEM; - - /* - * With some chips like the UDA1341 we must ensure there is - * an output stream at any time while recording since this is - * how the UDA1341 gets its clock from the SA1100. - * So while there is no playback data to send, the output DMA - * will spin with all zeroes. We use the cache flush special - * area for that. - */ - if (state->need_tx_for_rx) - sa1100_dma_set_spin(state->output_stream->dma_ch, - (dma_addr_t)FLUSH_BASE_PHYS, 2048); - - /* - * Since we just allocated all buffers, we must send them to - * the DMA code before receiving data. - */ - for (i = 0; i < s->nbfrags; i++) { - audio_buf_t *b = s->buf; - down(&b->sem); - sa1100_dma_queue_buffer(s->dma_ch, (void *) b, - b->dma_addr, s->fragsize); - NEXT_BUF(s, buf); - } - } - return 0; -} - - -static int audio_read(struct file *file, char *buffer, - size_t count, loff_t * ppos) -{ - char *buffer0 = buffer; - audio_state_t *state = (audio_state_t *)file->private_data; - audio_stream_t *s = state->input_stream; - int chunksize, ret = 0; - - DPRINTK("audio_read: count=%d\n", count); - - switch (file->f_flags & O_ACCMODE) { - case O_RDONLY: - case O_RDWR: - break; - default: - return -EPERM; - } - - ret = audio_recording(state); - if (ret) - return ret; - - /* be sure to have a full sample byte count */ - count &= ~0x03; - - while (count > 0) { - audio_buf_t *b = s->buf; - - /* Wait for a buffer to become full */ - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - if (down_trylock(&b->sem)) - break; - } else { - ret = -ERESTARTSYS; - if (down_interruptible(&b->sem)) - break; - } - - /* Grab data from the current buffer */ - chunksize = b->size; - if (chunksize > count) - chunksize = count; - DPRINTK("read %d from %d\n", chunksize, s->buf_idx); - if (copy_to_user(buffer, - b->start + s->fragsize - b->size, - chunksize)) { - up(&b->sem); - return -EFAULT; - } - b->size -= chunksize; - buffer += chunksize; - count -= chunksize; - if (b->size > 0) { - up(&b->sem); - break; - } - - /* Make current buffer available for DMA again */ - sa1100_dma_queue_buffer(s->dma_ch, (void *) b, - b->dma_addr, s->fragsize); - NEXT_BUF(s, buf); - } - - if ((buffer - buffer0)) - ret = buffer - buffer0; - DPRINTK("audio_read: return=%d\n", ret); - return ret; -} - - -static unsigned int audio_poll(struct file *file, - struct poll_table_struct *wait) -{ - audio_state_t *state = (audio_state_t *)file->private_data; - audio_stream_t *is = state->input_stream; - audio_stream_t *os = state->output_stream; - unsigned int mask = 0; - int i; - int ret; - - DPRINTK("audio_poll(): mode=%s%s\n", - (file->f_mode & FMODE_READ) ? "r" : "", - (file->f_mode & FMODE_WRITE) ? "w" : ""); - - if (file->f_mode & FMODE_READ) { - /* Start audio input if not already active */ - ret = audio_recording(state); - if (ret < 0) - return ret; - poll_wait(file, &is->buf->sem.wait, wait); - } - - if (file->f_mode & FMODE_WRITE) { - if (!os->buffers && audio_setup_buf(os)) - return -ENOMEM; - poll_wait(file, &os->buf->sem.wait, wait); - } - - if (file->f_mode & FMODE_READ) { - for (i = 0; i < is->nbfrags; i++) { - if (atomic_read(&is->buffers[i].sem.count) > 0) { - mask |= POLLIN | POLLRDNORM; - break; - } - } - } - if (file->f_mode & FMODE_WRITE) { - for (i = 0; i < os->nbfrags; i++) { - if (atomic_read(&os->buffers[i].sem.count) > 0) { - mask |= POLLOUT | POLLWRNORM; - break; - } - } - } - - DPRINTK("audio_poll() returned mask of %s%s\n", - (mask & POLLIN) ? "r" : "", - (mask & POLLOUT) ? "w" : ""); - - return mask; -} - - -static loff_t audio_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - - -static int audio_set_fragments(audio_stream_t *s, int val) -{ - if (s->buffers) - return -EBUSY; - s->fragsize = 1 << (val & 0xFFFF); - if (s->fragsize < 16) - s->fragsize = 16; - if (s->fragsize > 16384) - s->fragsize = 16384; - s->nbfrags = (val >> 16) & 0x7FFF; - if (s->nbfrags < 2) - s->nbfrags = 2; - if (s->nbfrags * s->fragsize > 128 * 1024) - s->nbfrags = 128 * 1024 / s->fragsize; - return audio_setup_buf(s); -} - -static int audio_ioctl(struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - audio_state_t *state = (audio_state_t *)file->private_data; - audio_stream_t *os = state->output_stream; - audio_stream_t *is = state->input_stream; - long val; - - /* dispatch based on command */ - switch (cmd) { - case SNDCTL_DSP_GETBLKSIZE: - return put_user(os->fragsize, (long *) arg); - break; - - case SNDCTL_DSP_SETFRAGMENT: - if (get_user(val, (long *) arg)) - return -EFAULT; - return audio_set_fragments(os, val); - break; - - case SNDCTL_DSP_SYNC: - return audio_sync(file); - - case SNDCTL_DSP_GETOSPACE: - { - audio_buf_info *inf = (audio_buf_info *) arg; - int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf)); - int i; - int frags = 0, bytes = 0; - - if (err) - return err; - for (i = 0; i < os->nbfrags; i++) { - if (atomic_read(&os->buffers[i].sem.count) > 0) { - if (os->buffers[i].size == 0) frags++; - bytes += os->fragsize - os->buffers[i].size; - } - } - put_user(frags, &inf->fragments); - put_user(os->nbfrags, &inf->fragstotal); - put_user(os->fragsize, &inf->fragsize); - put_user(bytes, &inf->bytes); - break; - } - - case SNDCTL_DSP_GETISPACE: - { - audio_buf_info *inf = (audio_buf_info *) arg; - int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf)); - int i; - int frags = 0, bytes = 0; - - if (err) - return err; - for (i = 0; i < is->nbfrags; i++) { - if (atomic_read(&is->buffers[i].sem.count) > 0) { - if (is->buffers[i].size == is->fragsize) frags++; - bytes += is->buffers[i].size; - } - } - put_user(frags, &inf->fragments); - put_user(is->nbfrags, &inf->fragstotal); - put_user(is->fragsize, &inf->fragsize); - put_user(bytes, &inf->bytes); - break; - } - - case SNDCTL_DSP_RESET: - switch (file->f_flags & O_ACCMODE) { - case O_RDONLY: - case O_RDWR: - if (state->need_tx_for_rx) - sa1100_dma_set_spin(os->dma_ch, 0, 0); - audio_clear_buf(is); - } - switch (file->f_flags & O_ACCMODE) { - case O_WRONLY: - case O_RDWR: - audio_clear_buf(os); - } - return 0; - - case SNDCTL_DSP_POST: - case SNDCTL_DSP_SUBDIVIDE: - case SNDCTL_DSP_NONBLOCK: - case SNDCTL_DSP_GETCAPS: - case SNDCTL_DSP_GETTRIGGER: - case SNDCTL_DSP_SETTRIGGER: - case SNDCTL_DSP_GETIPTR: - case SNDCTL_DSP_GETOPTR: - case SNDCTL_DSP_MAPINBUF: - case SNDCTL_DSP_MAPOUTBUF: - case SNDCTL_DSP_SETSYNCRO: - case SNDCTL_DSP_SETDUPLEX: - return -ENOSYS; - default: - /* - * Let the client of this module handle the - * non generic ioctls - */ - return state->client_ioctl(inode, file, cmd, arg); - } - - return 0; -} - - -static int audio_release(struct inode *inode, struct file *file) -{ - audio_state_t *state = (audio_state_t *)file->private_data; - DPRINTK("audio_release\n"); - - switch (file->f_flags & O_ACCMODE) { - case O_RDONLY: - case O_RDWR: - if (state->rd_refcount == 1) { - if (state->need_tx_for_rx) - sa1100_dma_set_spin(state->output_stream->dma_ch, 0, 0); - audio_clear_buf(state->input_stream); - state->rd_refcount = 0; - } - } - - switch (file->f_flags & O_ACCMODE) { - case O_WRONLY: - case O_RDWR: - if (state->wr_refcount == 1) { - audio_sync(file); - audio_clear_buf(state->output_stream); - state->wr_refcount = 0; - } - } - - if (!AUDIO_ACTIVE(state)) { - if (state->hw_shutdown) - state->hw_shutdown(); -#ifdef CONFIG_PM - pm_unregister(state->pm_dev); -#endif - } - - return 0; -} - - -#ifdef CONFIG_PM - -static int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) -{ - audio_state_t *state = (audio_state_t *)pm_dev->data; - - switch (req) { - case PM_SUSPEND: /* enter D1-D3 */ - if (state->output_stream) - sa1100_dma_sleep(state->output_stream->dma_ch); - if (state->input_stream) - sa1100_dma_sleep(state->input_stream->dma_ch); - if (AUDIO_ACTIVE(state) && state->hw_shutdown) - state->hw_shutdown(); - break; - case PM_RESUME: /* enter D0 */ - if (AUDIO_ACTIVE(state) && state->hw_init) - state->hw_init(); - if (state->input_stream) - sa1100_dma_wakeup(state->input_stream->dma_ch); - if (state->output_stream) - sa1100_dma_wakeup(state->output_stream->dma_ch); - break; - } - return 0; -} - -#endif - - -int sa1100_audio_instance(struct inode *inode, struct file *file, - audio_state_t *state) -{ - int in = 0, out = 0; - - DPRINTK("audio_open\n"); - - if ((file->f_flags & O_ACCMODE) == O_RDONLY) { - if (!state->input_stream) - return -ENODEV; - if (state->rd_refcount) - return -EBUSY; - in = 1; - } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { - if (!state->input_stream) - return -ENODEV; - if (state->wr_refcount) - return -EBUSY; - out = 1; - } else if ((file->f_flags & O_ACCMODE) == O_RDWR) { - if (!state->input_stream || !state->output_stream) - return -EINVAL; - if (state->rd_refcount || state->wr_refcount) - return -EBUSY; - in = out = 1; - } else - return -EINVAL; - - if (!AUDIO_ACTIVE(state)) { - if (state->hw_init) - state->hw_init(); -#ifdef CONFIG_PM - state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback); - if (state->pm_dev) - state->pm_dev->data = state; -#endif - } - - if (in) { - audio_clear_buf(state->input_stream); - state->rd_refcount = 1; - state->input_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT; - state->input_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT; - sa1100_dma_set_callback(state->input_stream->dma_ch, - audio_dmain_done_callback); - } - - if (out) { - audio_clear_buf(state->output_stream); - state->wr_refcount = 1; - state->output_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT; - state->output_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT; - sa1100_dma_set_callback(state->output_stream->dma_ch, - audio_dmaout_done_callback); - } - - file->private_data = state; - file->f_op->release = audio_release; - file->f_op->write = audio_write; - file->f_op->read = audio_read; - file->f_op->poll = audio_poll; - file->f_op->ioctl = audio_ioctl; - file->f_op->llseek = audio_llseek; - - return 0; -} - -EXPORT_SYMBOL(sa1100_audio_instance); - diff -urN linux-2.4.5-rmk7-np2/drivers/sound/sa1100-audio.h linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1100-audio.h --- linux-2.4.5-rmk7-np2/drivers/sound/sa1100-audio.h Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1100-audio.h Thu Jan 1 01:00:00 1970 @@ -1,53 +0,0 @@ -/* - * Common audio handling for the SA11x0 - * - * Copyright (c) 2000 Nicolas Pitre - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - */ - - -/* - * Buffer Management - */ - -typedef struct { - int size; /* buffer size */ - char *start; /* points to actual buffer */ - dma_addr_t dma_addr; /* physical buffer address */ - struct semaphore sem; /* down before touching the buffer */ - int master; /* owner for buffer allocation, contain size when true */ -} audio_buf_t; - -typedef struct { - audio_buf_t *buffers; /* pointer to audio buffer structures */ - audio_buf_t *buf; /* current buffer used by read/write */ - u_int buf_idx; /* index for the pointer above... */ - u_int fragsize; /* fragment i.e. buffer size */ - u_int nbfrags; /* nbr of fragments i.e. buffers */ - dmach_t dma_ch; /* DMA channel ID */ -} audio_stream_t; - -/* - * State structure for one instance - */ - -typedef struct { - audio_stream_t *output_stream; - audio_stream_t *input_stream; - int rd_refcount; /* nbr of concurrent open() for recording */ - int wr_refcount; /* nbr of concurrent open() for playback */ - int need_tx_for_rx; /* true if data must be sent while receiving */ - void (*hw_init)(void); - void (*hw_shutdown)(void); - int (*client_ioctl)(struct inode *, struct file *, uint, ulong); - struct pm_dev *pm_dev; -} audio_state_t; - -/* - * Functions exported by this module - */ -extern int sa1100_audio_instance(struct inode *inode, struct file *file, - audio_state_t *state); - diff -urN linux-2.4.5-rmk7-np2/drivers/sound/sa1100ssp.c linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1100ssp.c --- linux-2.4.5-rmk7-np2/drivers/sound/sa1100ssp.c Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1100ssp.c Thu Jan 1 01:00:00 1970 @@ -1,178 +0,0 @@ -/* - * Glue audio driver for a simple DAC on the SA1100's SSP port - * - * Copyright (c) 2001 Nicolas Pitre - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * History: - * - * 2001-06-04 Nicolas Pitre Initial release. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "sa1100-audio.h" - - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK( x... ) printk( ##x ) -#else -#define DPRINTK( x... ) -#endif - - -#define AUDIO_NAME "SA1100 SSP audio" - -#define AUDIO_FMT_MASK (AFMT_S16_LE) -#define AUDIO_FMT_DEFAULT (AFMT_S16_LE) -#define AUDIO_CHANNELS_DEFAULT 2 -#define AUDIO_RATE_DEFAULT 44100 - - -/* - * Audio interface - */ - -static void ssp_audio_init(void) -{ - if (machine_is_lart()) { - /* LART has the SSP port rewired to GPIO 10-13, 19 */ - /* alternate functions for the GPIOs */ - GAFR |= ( GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | - GPIO_SSP_SFRM | GPIO_SSP_CLK ); - - /* Set the direction: 10, 12, 13 output; 11, 19 input */ - GPDR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM ); - GPDR &= ~( GPIO_SSP_RXD | GPIO_SSP_CLK ); - - /* enable SSP pin swap */ - PPAR |= PPAR_SPR; - } - - /* turn on the SSP */ - Ser4SSCR0 = (SSCR0_DataSize(16) | SSCR0_TI | SSCR0_SerClkDiv(2) | - SSCR0_SSE); - Ser4SSCR1 = (SSCR1_SClkIactL | SSCR1_SClk1P | SSCR1_ExtClk); -} - -static int ssp_audio_ioctl( struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - long val; - int ret = 0; - - /* - * These are platform dependent ioctls which are not handled by the - * generic sa1100-audio module. - */ - switch (cmd) { - case SNDCTL_DSP_SETFMT: - ret = get_user(val, (long *) arg); - if (ret) break; - if (val & AUDIO_FMT_MASK) { - break; - } else - return -EINVAL; - - case SNDCTL_DSP_CHANNELS: - case SNDCTL_DSP_STEREO: - ret = get_user(val, (long *) arg); - if (ret) break; - if (cmd == SNDCTL_DSP_STEREO) - val = val ? 2 : 1; - /* Simple standard DACs are stereo only */ - if (val != 2) - return -EINVAL; - break; - - case SOUND_PCM_READ_CHANNELS: - return put_user(2, (long *) arg); - - case SNDCTL_DSP_SPEED: - case SOUND_PCM_READ_RATE: - /* We assume the clock doesn't change */ - return put_user(AUDIO_RATE_DEFAULT, (long *) arg); - - case SNDCTL_DSP_GETFMTS: - return put_user(AUDIO_FMT_MASK, (long *) arg); - - default: - return -EINVAL; - } - - return ret; -} - -static audio_stream_t output_stream; - -static audio_state_t audio_state = { - output_stream: &output_stream, - hw_init: ssp_audio_init, - client_ioctl: ssp_audio_ioctl, -}; - -static int ssp_audio_open(struct inode *inode, struct file *file) -{ - return sa1100_audio_instance(inode, file, &audio_state); -} - -/* - * Missing fields of this structure will be patched with the call - * to sa1100_audio_instance() - */ -static struct file_operations ssp_audio_fops = { - open: ssp_audio_open, - owner: THIS_MODULE -}; - - -static int audio_dev_id; - -static int __init sa1100ssp_audio_init(void) -{ - if (!machine_is_lart()) { - printk(KERN_ERR AUDIO_NAME ": no support for this SA-1100 design!\n"); - /* look at ssp_audio_init() for specific initialisations */ - return -ENODEV; - } - - /* Acquire and initialize DMA */ - if (sa1100_request_dma(&output_stream.dma_ch, "UDA1341 out") < 0) { - printk( KERN_ERR AUDIO_NAME ": unable to get DMA channels\n" ); - return -EBUSY; - } - sa1100_dma_set_device(output_stream.dma_ch, DMA_Ser4SSPWr); - - /* register devices */ - audio_dev_id = register_sound_dsp(&ssp_audio_fops, -1); - - printk( KERN_INFO AUDIO_NAME " initialized\n" ); - return 0; -} - -module_init(sa1100ssp_audio_init); - - -static void __exit sa1100ssp_audio_exit(void) -{ - unregister_sound_dsp(audio_dev_id); - sa1100_free_dma(output_stream.dma_ch); -} - -module_exit(sa1100ssp_audio_exit); diff -urN linux-2.4.5-rmk7-np2/drivers/sound/sa1111-uda1341.c linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1111-uda1341.c --- linux-2.4.5-rmk7-np2/drivers/sound/sa1111-uda1341.c Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/sa1111-uda1341.c Thu Jan 1 01:00:00 1970 @@ -1,323 +0,0 @@ -/* - * Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec. - * - * Copyright (c) 2000 John Dorsey - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * History: - * - * 2000-09-04 John Dorsey SA-1111 Serial Audio Controller support - * was initially added to the sa1100-uda1341.c - * driver. - * - * 2001-06-03 Nicolas Pitre Made this file a separate module, based on - * the former sa1100-uda1341.c driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "uda1341.h" -#include "sa1100-audio.h" - - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK( x... ) printk( ##x ) -#else -#define DPRINTK( x... ) -#endif - - -/* - * Definitions - */ - -#define AUDIO_NAME "SA1111/UDA1341" - -#define AUDIO_FMT_MASK (AFMT_S16_LE) -#define AUDIO_FMT_DEFAULT (AFMT_S16_LE) -#define AUDIO_CHANNELS_DEFAULT 2 -#define AUDIO_RATE_DEFAULT 22050 - -#define AUDIO_CLK_BASE 561600 - - -/* - * Write data to a device on the L3 bus. The address is passed as well as - * the data and length. The length written is returned. The register space - * is encoded in the address (low two bits are set and device address is - * in the upper 6 bits). - */ -static int L3_write(char addr, char *data, int len) -{ - int bytes = len; - - DPRINTK("%s(0x%x, %d)\n", __FUNCTION__, addr, len); - - if( len > 1 ){ - SACR1 |= SACR1_L3MB; - while( (len--) > 1 ){ - L3_CAR = addr; - L3_CDR = *data++; - while((SASR0 & SASR0_L3WD) == 0) - mdelay(1); - SASCR = SASCR_DTS; - } - } - SACR1 &= ~SACR1_L3MB; - L3_CAR = addr; - L3_CDR = *data; - while((SASR0 & SASR0_L3WD) == 0) - mdelay(1); - SASCR = SASCR_DTS; - - return bytes; -} - -/* - * Read data from a device on the L3 bus. The address is passed as well as - * the data and length. The length read is returned. The register space - * is encoded in the address (low two bits are set and device address is - * in the upper 6 bits). - */ -static int L3_read(char addr, char *data, int len) -{ - int bytes = len; - - DPRINTK("%s(0x%x, %d)\n", __FUNCTION__, addr, len); - - if( len > 1 ){ - SACR1 |= SACR1_L3MB; - while( (len--) > 1 ){ - L3_CAR = addr; - while((SASR0 & SASR0_L3RD) == 0) - mdelay(1); - *data++ = L3_CDR; - SASCR = SASCR_RDD; - } - } - SACR1 &= ~SACR1_L3MB; - L3_CAR = addr; - while((SASR0 & SASR0_L3RD) == 0) - mdelay(1); - *data = L3_CDR; - SASCR = SASCR_RDD; - - return bytes; -} - - -/* - * Mixer (UDA1341) interface - */ - -static UDA1341_regs_t UDA1341_regs = UDA1341_REGS_DFLT; - -static UDA1341_state_t uda1341_state = { - regs: &UDA1341_regs, - L3_write: L3_write, - L3_read: L3_read, -}; - -static int mixer_ioctl (struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - return uda1341_mixer_ioctl(&uda1341_state, cmd, arg); -} - -static struct file_operations uda1341_mixer_fops = { - ioctl: mixer_ioctl, - owner: THIS_MODULE -}; - - -/* - * Audio interface - */ - -static int audio_clk_div = AUDIO_CLK_BASE/AUDIO_RATE_DEFAULT - 1; - -static void sa1111_audio_init(void) -{ -#ifdef CONFIG_ASSABET_NEPONSET - if (machine_is_assabet()) { - /* Select I2S audio (instead of AC-Link) */ - AUD_CTL = AUD_SEL_1341; - } -#endif -#ifdef CONFIG_SA1100_JORNADA720 - if (machine_is_jornada720()) { - /* LDD4 is speaker, LDD3 is microphone */ - PPSR &= ~(PPC_LDD3 | PPC_LDD4); - PPDR |= PPC_LDD3 | PPC_LDD4; - PPSR |= PPC_LDD4; /* enable speaker */ - PPSR |= PPC_LDD3; /* enable microphone */ - } -#endif - - SKCR &= ~SKCR_SELAC; - - /* Enable the I2S clock and L3 bus clock: */ - SKPCR |= (SKPCR_I2SCLKEN | SKPCR_L3CLKEN); - - /* Activate and reset the Serial Audio Controller */ - SACR0 |= (SACR0_ENB | SACR0_RST); - mdelay(5); - SACR0 &= ~SACR0_RST; - - /* For I2S, BIT_CLK is supplied internally. The "SA-1111 - * Specification Update" mentions that the BCKD bit should - * be interpreted as "0 = output". Default clock divider - * is 22.05kHz. - * - * Select I2S, L3 bus. "Recording" and "Replaying" - * (receive and transmit) are enabled. - */ - SACR1 = SACR1_L3EN; - SKAUD = audio_clk_div; - - /* Initialize the UDA1341 internal state */ - uda1341_state.active = 1; - uda1341_reset(&uda1341_state); -} - -static void sa1111_audio_shutdown(void) -{ - uda1341_state.active = 0; - SACR0 &= ~SACR0_ENB; -} - -static int sa1111_audio_ioctl( struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - long val; - int ret = 0; - - switch (cmd) { - case SNDCTL_DSP_SETFMT: - ret = get_user(val, (long *) arg); - if (ret) break; - if (val & AUDIO_FMT_MASK) { - break; - } else - return -EINVAL; - - case SNDCTL_DSP_CHANNELS: - case SNDCTL_DSP_STEREO: - ret = get_user(val, (long *) arg); - if (ret) break; - if (cmd == SNDCTL_DSP_STEREO) - val = val ? 2 : 1; - /* the UDA1341 is stereo only */ - if (val != 2) - return -EINVAL; - break; - - case SOUND_PCM_READ_CHANNELS: - return put_user(2, (long *) arg); - - case SNDCTL_DSP_SPEED: - ret = get_user(val, (long *) arg); - if (ret) break; - if (val < 8000) val = 8000; - if (val > 48000) val = 48000; - SKAUD = audio_clk_div = AUDIO_CLK_BASE/val - 1; - /* fall through */ - - case SOUND_PCM_READ_RATE: - return put_user(AUDIO_CLK_BASE/(audio_clk_div+1), (long *) arg); - - case SNDCTL_DSP_GETFMTS: - return put_user(AUDIO_FMT_MASK, (long *) arg); - - default: - /* Maybe this is meant for the mixer (as per OSS Docs) */ - return uda1341_mixer_ioctl(&uda1341_state, cmd, arg); - } - - return ret; -} - -static audio_stream_t output_stream, input_stream; - -static audio_state_t audio_state = { - output_stream: &output_stream, - input_stream: &input_stream, - hw_init: sa1111_audio_init, - hw_shutdown: sa1111_audio_shutdown, - client_ioctl: sa1111_audio_ioctl, -}; - -static int sa1111_audio_open(struct inode *inode, struct file *file) -{ - return sa1100_audio_instance(inode, file, &audio_state); -} - -/* - * Missing fields of this structure will be patched with the call - * to sa1100_audio_instance() - */ -static struct file_operations sa1111_audio_fops = { - open: sa1111_audio_open, - owner: THIS_MODULE -}; - - -static int audio_dev_id, mixer_dev_id; - -static int __init sa1111_uda1341_init(void) -{ - if ( !( (machine_is_assabet() && machine_has_neponset()) || - machine_is_jornada720() )) - return -ENODEV; - - /* Acquire and initialize DMA */ - if (sa1111_sac_request_dma(&output_stream.dma_ch, "UDA1341 out", SA1111_SAC_XMT_CHANNEL) < 0 || - sa1111_sac_request_dma(&input_stream.dma_ch, "UDA1341 in", SA1111_SAC_RCV_CHANNEL) < 0) { - sa1100_free_dma(output_stream.dma_ch); - printk( KERN_ERR AUDIO_NAME ": unable to get DMA channels\n" ); - return -EBUSY; - } - - /* Settings which differ from the default initialisation */ - UDA1341_regs.status_0.input_fmt = UDA_STATUS0_IF_I2S; - UDA1341_regs.status_0.system_clk = UDA_STATUS0_SC_256FS; - - /* register devices */ - audio_dev_id = register_sound_dsp(&sa1111_audio_fops, -1); - mixer_dev_id = register_sound_mixer(&uda1341_mixer_fops, -1); - - printk( KERN_INFO AUDIO_NAME " initialized\n" ); - return 0; -} - -module_init(sa1111_uda1341_init); - - -static void __exit sa1111_uda1341_exit(void) -{ - unregister_sound_dsp(audio_dev_id); - unregister_sound_mixer(mixer_dev_id); - sa1100_free_dma(output_stream.dma_ch); - sa1100_free_dma(input_stream.dma_ch); -} - -module_exit(sa1111_uda1341_exit); - diff -urN linux-2.4.5-rmk7-np2/drivers/sound/uda1341.c linux-2.4.5-rmk7-np2-ssv1/drivers/sound/uda1341.c --- linux-2.4.5-rmk7-np2/drivers/sound/uda1341.c Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/uda1341.c Thu Jan 1 01:00:00 1970 @@ -1,332 +0,0 @@ -/* - * Philips UDA1341 mixer device driver - * - * Copyright (c) 2000 Nicolas Pitre - * - * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * History: - * - * 2000-05-21 Nicolas Pitre Initial release. - * - * 2000-08-19 Erik Bunce More inline w/ OSS API and UDA1341 docs - * including fixed AGC and audio source handling - * - * 2000-11-30 Nicolas Pitre - More mixer functionalities. - * - * 2001-06-03 Nicolas Pitre Made this file a separate module, based on - * the former sa1100-uda1341.c driver. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "uda1341.h" - - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK( x... ) printk( ##x ) -#else -#define DPRINTK( x... ) -#endif - - -#define SET(adr, reg, len) \ - if (active) state->L3_write((UDA1341_L3Addr << 2)|(adr), (char*)®s->reg, (len)) - -int uda1341_mixer_ioctl (UDA1341_state_t *state, uint cmd, ulong arg) -{ - UDA1341_regs_t *regs = state->regs; - int active = state->active; - int ret; - long val = 0; - - /* - * Dispatch based on command. - * Exit with break if modifications occurred. - */ - switch (cmd) { - case SOUND_MIXER_INFO: - { - mixer_info info; - strncpy(info.id, "UDA1341", sizeof(info.id)); - strncpy(info.name, "Philips UDA1341", sizeof(info.name)); - info.modify_counter = state->mix_modcnt; - return copy_to_user((void *)arg, &info, sizeof(info)); - } - - case SOUND_OLD_MIXER_INFO: - { - _old_mixer_info info; - strncpy(info.id, "UDA1341", sizeof(info.id)); - strncpy(info.name, "Philips UDA1341", sizeof(info.name)); - return copy_to_user((void *)arg, &info, sizeof(info)); - } - - case SOUND_MIXER_READ_DEVMASK: - val = (SOUND_MASK_VOLUME | - SOUND_MASK_TREBLE | - SOUND_MASK_BASS | - SOUND_MASK_LINE1 | - SOUND_MASK_LINE2 | - SOUND_MASK_MIC); - return put_user(val, (long *) arg); - - case SOUND_MIXER_READ_RECMASK: - val = (SOUND_MASK_MIC | - SOUND_MASK_LINE1 | - SOUND_MASK_LINE2 | - SOUND_MASK_LINE3); - return put_user(val, (long *) arg); - - case SOUND_MIXER_READ_STEREODEVS: - return put_user(0, (long *) arg); - - case SOUND_MIXER_READ_CAPS: - val = SOUND_CAP_EXCL_INPUT; - return put_user(val, (long *) arg); - - case SOUND_MIXER_AGC: - /* - * (as found in sb_mixer.c) - * Use ioctl(fd, SOUND_MIXER_AGC, &mode) to turn AGC off (0) or on (1). - */ - regs->data0_ext4.AGC_ctrl = val ? 1 : 0; - SET (UDA1341_DATA0, data0_ext4, 2); - ret = put_user(regs->data0_ext4.AGC_ctrl, (long *) arg); - if (ret) - return ret; - break; - - case SOUND_MIXER_WRITE_RECSRC: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - /* Recording source is selected by mixer_mode */ - switch (val) { - case SOUND_MASK_LINE1: - /* input channel 1 select */ - regs->data0_ext2.mixer_mode = 1; - break; - case SOUND_MASK_LINE2: - /* Double differential mode */ - regs->data0_ext2.mixer_mode = 0; - break; - case SOUND_MASK_LINE3: - /* - * digital mixer mode - * (input 1 x MA + input2 x MB) - */ - regs->data0_ext2.mixer_mode = 3; - break; - case SOUND_MASK_MIC: - default: - /* Input channel 2 select */ - regs->data0_ext2.mixer_mode = 2; - break; - } - SET (UDA1341_DATA0, data0_ext2, 2); - break; - - case SOUND_MIXER_READ_RECSRC: - /* Recording source is specified by mixer_mode */ - switch (regs->data0_ext2.mixer_mode) { - case 0: - /* Double differential mode */ - val = SOUND_MASK_LINE2; - break; - case 1: - /* input channel 1 select */ - val = SOUND_MASK_LINE1; - break; - case 3: - /* - * digital mixer mode - * (input 1 x MA + input2 x MB) - */ - val = SOUND_MASK_LINE3; - break; - case 2: - default: - /* Input channel 2 select */ - val = SOUND_MASK_MIC; - break; - } - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_VOLUME: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - regs->data0_0.volume = 63 - (((val & 0xff) + 1) * 63) / 100; - SET (UDA1341_DATA0, data0_0, 1); - break; - - case SOUND_MIXER_READ_VOLUME: - val = ((63 - regs->data0_0.volume) * 100) / 63; - val |= val << 8; - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_TREBLE: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - regs->data0_1.treble = (((val & 0xff) + 1) * 3) / 100; - SET (UDA1341_DATA0, data0_1, 1); - break; - - case SOUND_MIXER_READ_TREBLE: - val = (regs->data0_1.treble * 100) / 3; - val |= val << 8; - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_BASS: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - regs->data0_1.bass = (((val & 0xff) + 1) * 15) / 100; - SET (UDA1341_DATA0, data0_1, 1); - break; - - case SOUND_MIXER_READ_BASS: - val = (regs->data0_1.bass * 100) / 15; - val |= val << 8; - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_LINE1: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - regs->data0_ext0.ch1_gain = (((val & 0xff) + 1) * 31) / 100; - SET (UDA1341_DATA0, data0_ext0, 2); - break; - - case SOUND_MIXER_READ_LINE1: - val = (regs->data0_ext0.ch1_gain * 100) / 31; - val |= val << 8; - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_LINE2: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - regs->data0_ext1.ch2_gain = (((val & 0xff) + 1) * 31) / 100; - SET (UDA1341_DATA0, data0_ext1, 2); - break; - - case SOUND_MIXER_READ_LINE2: - val = (regs->data0_ext1.ch2_gain * 100) / 31; - val |= val << 8; - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_MIC: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - /* Use different registers depending on AGC setting */ - if (regs->data0_ext4.AGC_ctrl == 1) { - /* AGC On, play with MIC sensitivity */ - /* even if 3 bits, value 7 is not used */ - regs->data0_ext2.mic_level = - (((val & 0xff) + 1) * 6) / 100; - SET (UDA1341_DATA0, data0_ext2, 2); - } else { - /* AGC Off, plain with Input channel 2 amplifier gain */ - val = ((val & 0xff) * 127) / 100; - regs->data0_ext4.ch2_igain_l = val & 3; - regs->data0_ext5.ch2_igain_h = val >> 2; - SET (UDA1341_DATA0, data0_ext4, 2); - SET (UDA1341_DATA0, data0_ext5, 2); - } - break; - - case SOUND_MIXER_READ_MIC: - /* Use different registers depending on AGC setting */ - if (regs->data0_ext4.AGC_ctrl == 1) { - val = (regs->data0_ext2.mic_level * 100) / 6; - val |= val << 8; - } else { - val = regs->data0_ext4.ch2_igain_l + - (regs->data0_ext5.ch2_igain_h << 2); - val = (val * 100) / 127; - val |= val << 8; - } - return put_user(val, (long *) arg); - -#if 0 /* Experimental. What those should produce is still not obvious to me. */ - case SOUND_MIXER_WRITE_OGAIN: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - regs->data0_ext6.AGC_level = (((val & 0xff) + 1) * 3) / 100; - SET (UDA1341_DATA0, data0_ext6, 2); - break; - - case SOUND_MIXER_READ_OGAIN: - val = (regs->data0_ext6.AGC_level * 100) / 3; - val |= val << 8; - return put_user(val, (long *) arg); - - case SOUND_MIXER_WRITE_IMIX: - ret = get_user(val, (long *) arg); - if (ret) - return ret; - regs->data0_ext2.mixer_mode = val; - SET (UDA1341_DATA0, data0_ext2, 2); - break; - - case SOUND_MIXER_READ_IMIX: - val = regs->data0_ext2.mixer_mode; - return put_user(val, (long *) arg); -#endif - - case SOUND_MIXER_WRITE_RECLEV: - case SOUND_MIXER_READ_RECLEV: - default: - return -ENOSYS; - } - - state->mix_modcnt++; - return 0; -} - -void uda1341_reset (UDA1341_state_t *state) -{ - UDA1341_regs_t *regs = state->regs; - int active = 1; - - DPRINTK("uda1341_reset\n"); - - /* Reset the chip */ - regs->status_0.reset = 1; - SET (UDA1341_STATUS, status_0, 1); - regs->status_0.reset = 0; - - /* Restore chip state, mixer values, etc... */ - SET (UDA1341_STATUS, status_0, 1); - SET (UDA1341_STATUS, status_1, 1); - SET (UDA1341_DATA0, data0_0, 1); - SET (UDA1341_DATA0, data0_1, 1); - SET (UDA1341_DATA0, data0_2, 1); - SET (UDA1341_DATA0, data0_ext0, 2); - SET (UDA1341_DATA0, data0_ext1, 2); - SET (UDA1341_DATA0, data0_ext2, 2); - SET (UDA1341_DATA0, data0_ext4, 2); - SET (UDA1341_DATA0, data0_ext5, 2); - SET (UDA1341_DATA0, data0_ext6, 2); -} - -EXPORT_SYMBOL(uda1341_mixer_ioctl); -EXPORT_SYMBOL(uda1341_reset); - diff -urN linux-2.4.5-rmk7-np2/drivers/sound/uda1341.h linux-2.4.5-rmk7-np2-ssv1/drivers/sound/uda1341.h --- linux-2.4.5-rmk7-np2/drivers/sound/uda1341.h Sat Jul 13 19:40:18 2002 +++ linux-2.4.5-rmk7-np2-ssv1/drivers/sound/uda1341.h Thu Jan 1 01:00:00 1970 @@ -1,205 +0,0 @@ -/* - * Philips UDA1341 mixer device driver - * - * Copyright (c) 2000 Nicolas Pitre - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - */ - -/* - * UDA1341 L3 address and command types - */ -#define UDA1341_L3Addr 5 -#define UDA1341_DATA0 0 -#define UDA1341_DATA1 1 -#define UDA1341_STATUS 2 - - -/* - * UDA1341 internal state variables. - * The default values are defined to sane initial operating values. - */ - -/* UDA1341 status settings */ - -#define UDA_STATUS0_IF_I2S 0 -#define UDA_STATUS0_IF_LSB16 1 -#define UDA_STATUS0_IF_LSB18 2 -#define UDA_STATUS0_IF_LSB20 3 -#define UDA_STATUS0_IF_MSB 4 -#define UDA_STATUS0_IF_MSB16 5 -#define UDA_STATUS0_IF_MSB18 6 -#define UDA_STATUS0_IF_MSB20 7 - -#define UDA_STATUS0_SC_512FS 0 -#define UDA_STATUS0_SC_384FS 1 -#define UDA_STATUS0_SC_256FS 2 - -typedef struct { - u_int DC_filter:1; /* DC filter */ - u_int input_fmt:3; /* data input format */ - u_int system_clk:2; /* system clock frequency */ - u_int reset:1; /* reset */ - const u_int select:1; /* must be set to 0 */ -} UDA_STATUS_0; - -#define UDA_STATUS_0_DFLT \ - (UDA_STATUS_0){0, UDA_STATUS0_IF_LSB16, UDA_STATUS0_SC_256FS, 0, 0} - -typedef struct { - u_int DAC_on:1; /* DAC powered */ - u_int ADC_on:1; /* ADC powered */ - u_int double_speed:1; /* double speed playback */ - u_int DAC_pol:1; /* polarity of DAC */ - u_int ADC_pol:1; /* polarity of ADC */ - u_int ADC_gain:1; /* gain of ADC */ - u_int DAC_gain:1; /* gain of DAC */ - const u_int select:1; /* must be set to 1 */ -} UDA_STATUS_1; - -#define UDA_STATUS_1_DFLT (UDA_STATUS_1){1, 1, 0, 0, 0, 1, 1, 1} - -/* UDA1341 direct control settings */ - -typedef struct { - u_int volume:6; /* volume control */ - const u_int select:2; /* must be set to 0 */ -} UDA_DATA0_0; - -#define UDA_DATA0_0_DFLT (UDA_DATA0_0){15, 0} - -typedef struct { - u_int treble:2; - u_int bass:4; - const u_int select:2; /* must be set to 1 */ -} UDA_DATA0_1; - -#define UDA_DATA0_1_DFLT (UDA_DATA0_1){0, 0, 1} - -typedef struct { - u_int mode:2; /* mode switch */ - u_int mute:1; - u_int deemphasis:2; - u_int peak_detect:1; - const u_int select:2; /* must be set to 2 */ -} UDA_DATA0_2; - -#define UDA_DATA0_2_DFLT (UDA_DATA0_2){3, 0, 0, 1, 2} - -/* DATA0 extended programming registers */ - -typedef struct { - const u_int ext_addr:3; /* must be set to 0 */ - const u_int select1:5; /* must be set to 24 */ - u_int ch1_gain:5; /* mixer gain channel 1 */ - const u_int select2:3; /* must be set to 7 */ -} UDA_DATA0_ext0; - -#define UDA_DATA0_ext0_DFLT (UDA_DATA0_ext0){0, 24, 4, 7} - -typedef struct { - const u_int ext_addr:3; /* must be set to 1 */ - const u_int select1:5; /* must be set to 24 */ - u_int ch2_gain:5; /* mixer gain channel 2 */ - const u_int select2:3; /* must be set to 7 */ -} UDA_DATA0_ext1; - -#define UDA_DATA0_ext1_DFLT (UDA_DATA0_ext1){1, 24, 4, 7} - -typedef struct { - const u_int ext_addr:3; /* must be set to 2 */ - const u_int select1:5; /* must be set to 24 */ - u_int mixer_mode:2; - u_int mic_level:3; /* MIC sensitivity level */ - const u_int select2:3; /* must be set to 7 */ -} UDA_DATA0_ext2; - -#define UDA_DATA0_ext2_DFLT (UDA_DATA0_ext2){2, 24, 2, 4, 7} - -typedef struct { - const u_int ext_addr:3; /* must be set to 4 */ - const u_int select1:5; /* must be set to 24 */ - u_int ch2_igain_l:2; /* input amplifier gain channel 2 (bits 1-0) */ - const u_int reserved:2; /* must be set to 0 */ - u_int AGC_ctrl:1; /* AGC control */ - const u_int select2:3; /* must be set to 7 */ -} UDA_DATA0_ext4; - -#define UDA_DATA0_ext4_DFLT (UDA_DATA0_ext4){4, 24, 0 & 3, 0, 1, 7} - -typedef struct { - const u_int ext_addr:3; /* must be set to 5 */ - const u_int select1:5; /* must be set to 24 */ - u_int ch2_igain_h:5; /* input amplifier gain channel 2 (bits 6-2) */ - const u_int select2:3; /* must be set to 7 */ -} UDA_DATA0_ext5; - -#define UDA_DATA0_ext5_DFLT (UDA_DATA0_ext5){5, 24, 0 >> 2, 7} - -typedef struct { - const u_int ext_addr:3; /* must be set to 6 */ - const u_int select1:5; /* must be set to 24 */ - u_int AGC_level:2; /* AGC output level */ - u_int AGC_const:3; /* AGC time constant */ - const u_int select2:3; /* must be set to 7 */ -} UDA_DATA0_ext6; - -#define UDA_DATA0_ext6_DFLT (UDA_DATA0_ext6){6, 24, 3, 0, 7} - -typedef struct { - u_int peak:6; /* peak level value */ -} UDA_DATA1; - -#define UDA_DATA1_DFLT (UDA_DATA1){0} - -/* - * All registers - */ -typedef struct { - UDA_STATUS_0 status_0; - UDA_STATUS_1 status_1; - UDA_DATA0_0 data0_0; - UDA_DATA0_1 data0_1; - UDA_DATA0_2 data0_2; - UDA_DATA0_ext0 data0_ext0; - UDA_DATA0_ext1 data0_ext1; - UDA_DATA0_ext2 data0_ext2; - UDA_DATA0_ext4 data0_ext4; - UDA_DATA0_ext5 data0_ext5; - UDA_DATA0_ext6 data0_ext6; - UDA_DATA1 data1; -} UDA1341_regs_t; - -#define UDA1341_REGS_DFLT { \ - UDA_STATUS_0_DFLT, \ - UDA_STATUS_1_DFLT, \ - UDA_DATA0_0_DFLT, \ - UDA_DATA0_1_DFLT, \ - UDA_DATA0_2_DFLT, \ - UDA_DATA0_ext0_DFLT, \ - UDA_DATA0_ext1_DFLT, \ - UDA_DATA0_ext2_DFLT, \ - UDA_DATA0_ext4_DFLT, \ - UDA_DATA0_ext5_DFLT, \ - UDA_DATA0_ext6_DFLT, \ - UDA_DATA1_DFLT } - -/* - * Structure containing the necessary variables - * for one instance of this chip. - */ -typedef struct { - UDA1341_regs_t *regs; - int (*L3_write)(char addr, char *data, int len); - int (*L3_read)(char addr, char *data, int len); - int active; /* non zero if powered */ - int mix_modcnt; /* mixer mods count */ -} UDA1341_state_t; - -/* - * Function prototypes exported by this module - */ -extern int uda1341_mixer_ioctl (UDA1341_state_t *state, uint cmd, ulong arg); -extern void uda1341_reset (UDA1341_state_t *state); -