diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/drivers')
46 files changed, 0 insertions, 20206 deletions
diff --git a/ANDROID_3.4.5/sound/drivers/Kconfig b/ANDROID_3.4.5/sound/drivers/Kconfig deleted file mode 100644 index fe5ae09f..00000000 --- a/ANDROID_3.4.5/sound/drivers/Kconfig +++ /dev/null @@ -1,223 +0,0 @@ -config SND_MPU401_UART - tristate - select SND_RAWMIDI - -config SND_OPL3_LIB - tristate - select SND_TIMER - select SND_HWDEP - -config SND_OPL4_LIB - tristate - select SND_TIMER - select SND_HWDEP - -config SND_VX_LIB - tristate - select SND_HWDEP - select SND_PCM - -config SND_AC97_CODEC - tristate - select SND_PCM - select AC97_BUS - select SND_VMASTER - -menuconfig SND_DRIVERS - bool "Generic sound devices" - default y - help - Support for generic sound devices. - -if SND_DRIVERS - -config SND_PCSP - tristate "PC-Speaker support (READ HELP!)" - depends on PCSPKR_PLATFORM && X86 && HIGH_RES_TIMERS - depends on INPUT - depends on EXPERIMENTAL - select SND_PCM - help - If you don't have a sound card in your computer, you can include a - driver for the PC speaker which allows it to act like a primitive - sound card. - This driver also replaces the pcspkr driver for beeps. - - You can compile this as a module which will be called snd-pcsp. - - WARNING: if you already have a soundcard, enabling this - driver may lead to a problem. Namely, it may get loaded - before the other sound driver of yours, making the - pc-speaker a default sound device. Which is likely not - what you want. To make this driver play nicely with other - sound driver, you can add this in a configuration file under - /etc/modprobe.d/ directory: - options snd-pcsp index=2 - - You don't need this driver if you only want your pc-speaker to beep. - You don't need this driver if you have a tablet piezo beeper - in your PC instead of the real speaker. - - Say N if you have a sound card. - Say M if you don't. - Say Y only if you really know what you do. - -config SND_DUMMY - tristate "Dummy (/dev/null) soundcard" - select SND_PCM - help - Say Y here to include the dummy driver. This driver does - nothing, but emulates various mixer controls and PCM devices. - - You don't need this unless you're testing the hardware support - of programs using the ALSA API. - - To compile this driver as a module, choose M here: the module - will be called snd-dummy. - -config SND_ALOOP - tristate "Generic loopback driver (PCM)" - select SND_PCM - help - Say 'Y' or 'M' to include support for the PCM loopback device. - This module returns played samples back to the user space using - the standard ALSA PCM device. The devices are routed 0->1 and - 1->0, where first number is the playback PCM device and second - number is the capture device. Module creates two PCM devices and - configured number of substreams (see the pcm_substreams module - parameter). - - The looback device allow time sychronization with an external - timing source using the time shift universal control (+-20% - of system time). - - To compile this driver as a module, choose M here: the module - will be called snd-aloop. - -config SND_VIRMIDI - tristate "Virtual MIDI soundcard" - depends on SND_SEQUENCER - select SND_TIMER - select SND_RAWMIDI - help - Say Y here to include the virtual MIDI driver. This driver - allows to connect applications using raw MIDI devices to - sequencer clients. - - If you don't know what MIDI is, say N here. - - To compile this driver as a module, choose M here: the module - will be called snd-virmidi. - -config SND_MTPAV - tristate "MOTU MidiTimePiece AV multiport MIDI" - select SND_RAWMIDI - help - To use a MOTU MidiTimePiece AV multiport MIDI adapter - connected to the parallel port, say Y here and make sure that - the standard parallel port driver isn't used for the port. - - To compile this driver as a module, choose M here: the module - will be called snd-mtpav. - -config SND_MTS64 - tristate "ESI Miditerminal 4140 driver" - depends on PARPORT - select SND_RAWMIDI - help - The ESI Miditerminal 4140 is a 4 In 4 Out MIDI Interface with - additional SMPTE Timecode capabilities for the parallel port. - - Say 'Y' to include support for this device. - - To compile this driver as a module, chose 'M' here: the module - will be called snd-mts64. - -config SND_SERIAL_U16550 - tristate "UART16550 serial MIDI driver" - select SND_RAWMIDI - help - To include support for MIDI serial port interfaces, say Y here - and read <file:Documentation/sound/alsa/serial-u16550.txt>. - This driver works with serial UARTs 16550 and better. - - This driver accesses the serial port hardware directly, so - make sure that the standard serial driver isn't used or - deactivated with setserial before loading this driver. - - To compile this driver as a module, choose M here: the module - will be called snd-serial-u16550. - -config SND_MPU401 - tristate "Generic MPU-401 UART driver" - select SND_MPU401_UART - help - Say Y here to include support for MIDI ports compatible with - the Roland MPU-401 interface in UART mode. - - To compile this driver as a module, choose M here: the module - will be called snd-mpu401. - -config SND_PORTMAN2X4 - tristate "Portman 2x4 driver" - depends on PARPORT - select SND_RAWMIDI - help - Say Y here to include support for Midiman Portman 2x4 parallel - port MIDI device. - - To compile this driver as a module, choose M here: the module - will be called snd-portman2x4. - -config SND_ML403_AC97CR - tristate "Xilinx ML403 AC97 Controller Reference" - depends on XILINX_VIRTEX - select SND_AC97_CODEC - help - Say Y here to include support for the - opb_ac97_controller_ref_v1_00_a ip core found in Xilinx's ML403 - reference design. - - To compile this driver as a module, choose M here: the module - will be called snd-ml403_ac97cr. - -config SND_AC97_POWER_SAVE - bool "AC97 Power-Saving Mode" - depends on SND_AC97_CODEC - default n - help - Say Y here to enable the aggressive power-saving support of - AC97 codecs. In this mode, the power-mode is dynamically - controlled at each open/close. - - The mode is activated by passing 'power_save=X' to the - snd-ac97-codec driver module, where 'X' is the time-out - value, a nonnegative integer that specifies how many - seconds of idle time the driver must count before it may - put the AC97 into power-save mode; a value of 0 (zero) - disables the use of this power-save mode. - - After the snd-ac97-codec driver module has been loaded, - the 'power_save' parameter can be set via sysfs as follows: - - echo 10 > /sys/module/snd_ac97_codec/parameters/power_save - - In this case, the time-out is set to 10 seconds; setting - the time-out to 1 second (the minimum activation value) - isn't recommended because many applications try to reopen - the device frequently. A value of 10 seconds would be a - good choice for normal operations. - - See Documentation/sound/alsa/powersave.txt for more details. - -config SND_AC97_POWER_SAVE_DEFAULT - int "Default time-out for AC97 power-save mode" - depends on SND_AC97_POWER_SAVE - default 0 - help - The default time-out value in seconds for AC97 automatic - power-save mode. 0 means to disable the power-save mode. - - See SND_AC97_POWER_SAVE for more details. - -endif # SND_DRIVERS diff --git a/ANDROID_3.4.5/sound/drivers/Makefile b/ANDROID_3.4.5/sound/drivers/Makefile deleted file mode 100644 index 1a8440c8..00000000 --- a/ANDROID_3.4.5/sound/drivers/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-dummy-objs := dummy.o -snd-aloop-objs := aloop.o -snd-mtpav-objs := mtpav.o -snd-mts64-objs := mts64.o -snd-portman2x4-objs := portman2x4.o -snd-serial-u16550-objs := serial-u16550.o -snd-virmidi-objs := virmidi.o -snd-ml403-ac97cr-objs := ml403-ac97cr.o pcm-indirect2.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_DUMMY) += snd-dummy.o -obj-$(CONFIG_SND_ALOOP) += snd-aloop.o -obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o -obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o -obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o -obj-$(CONFIG_SND_MTS64) += snd-mts64.o -obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o -obj-$(CONFIG_SND_ML403_AC97CR) += snd-ml403-ac97cr.o - -obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ pcsp/ diff --git a/ANDROID_3.4.5/sound/drivers/aloop.c b/ANDROID_3.4.5/sound/drivers/aloop.c deleted file mode 100644 index ad079b63..00000000 --- a/ANDROID_3.4.5/sound/drivers/aloop.c +++ /dev/null @@ -1,1258 +0,0 @@ -/* - * Loopback soundcard - * - * Original code: - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * More accurate positioning and full-duplex support: - * Copyright (c) Ahmet İnan <ainan at mathematik.uni-freiburg.de> - * - * Major (almost complete) rewrite: - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * - * A next major update in 2010 (separate timers for playback and capture): - * Copyright (c) Jaroslav Kysela <perex@perex.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/init.h> -#include <linux/jiffies.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/pcm.h> -#include <sound/info.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("A loopback soundcard"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); - -#define MAX_PCM_SUBSTREAMS 8 - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; -static int pcm_notify[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for loopback soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for loopback soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this loopback soundcard."); -module_param_array(pcm_substreams, int, NULL, 0444); -MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver."); -module_param_array(pcm_notify, int, NULL, 0444); -MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes."); - -#define NO_PITCH 100000 - -struct loopback_pcm; - -struct loopback_cable { - spinlock_t lock; - struct loopback_pcm *streams[2]; - struct snd_pcm_hardware hw; - /* flags */ - unsigned int valid; - unsigned int running; - unsigned int pause; -}; - -struct loopback_setup { - unsigned int notify: 1; - unsigned int rate_shift; - unsigned int format; - unsigned int rate; - unsigned int channels; - struct snd_ctl_elem_id active_id; - struct snd_ctl_elem_id format_id; - struct snd_ctl_elem_id rate_id; - struct snd_ctl_elem_id channels_id; -}; - -struct loopback { - struct snd_card *card; - struct mutex cable_lock; - struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2]; - struct snd_pcm *pcm[2]; - struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2]; -}; - -struct loopback_pcm { - struct loopback *loopback; - struct snd_pcm_substream *substream; - struct loopback_cable *cable; - unsigned int pcm_buffer_size; - unsigned int buf_pos; /* position in buffer */ - unsigned int silent_size; - /* PCM parameters */ - unsigned int pcm_period_size; - unsigned int pcm_bps; /* bytes per second */ - unsigned int pcm_salign; /* bytes per sample * channels */ - unsigned int pcm_rate_shift; /* rate shift value */ - /* flags */ - unsigned int period_update_pending :1; - /* timer stuff */ - unsigned int irq_pos; /* fractional IRQ position */ - unsigned int period_size_frac; - unsigned long last_jiffies; - struct timer_list timer; -}; - -static struct platform_device *devices[SNDRV_CARDS]; - -static inline unsigned int byte_pos(struct loopback_pcm *dpcm, unsigned int x) -{ - if (dpcm->pcm_rate_shift == NO_PITCH) { - x /= HZ; - } else { - x = div_u64(NO_PITCH * (unsigned long long)x, - HZ * (unsigned long long)dpcm->pcm_rate_shift); - } - return x - (x % dpcm->pcm_salign); -} - -static inline unsigned int frac_pos(struct loopback_pcm *dpcm, unsigned int x) -{ - if (dpcm->pcm_rate_shift == NO_PITCH) { /* no pitch */ - return x * HZ; - } else { - x = div_u64(dpcm->pcm_rate_shift * (unsigned long long)x * HZ, - NO_PITCH); - } - return x; -} - -static inline struct loopback_setup *get_setup(struct loopback_pcm *dpcm) -{ - int device = dpcm->substream->pstr->pcm->device; - - if (dpcm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - device ^= 1; - return &dpcm->loopback->setup[dpcm->substream->number][device]; -} - -static inline unsigned int get_notify(struct loopback_pcm *dpcm) -{ - return get_setup(dpcm)->notify; -} - -static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm) -{ - return get_setup(dpcm)->rate_shift; -} - -static void loopback_timer_start(struct loopback_pcm *dpcm) -{ - unsigned long tick; - unsigned int rate_shift = get_rate_shift(dpcm); - - if (rate_shift != dpcm->pcm_rate_shift) { - dpcm->pcm_rate_shift = rate_shift; - dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); - } - if (dpcm->period_size_frac <= dpcm->irq_pos) { - dpcm->irq_pos %= dpcm->period_size_frac; - dpcm->period_update_pending = 1; - } - tick = dpcm->period_size_frac - dpcm->irq_pos; - tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; - dpcm->timer.expires = jiffies + tick; - add_timer(&dpcm->timer); -} - -static inline void loopback_timer_stop(struct loopback_pcm *dpcm) -{ - del_timer(&dpcm->timer); - dpcm->timer.expires = 0; -} - -#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) -#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE) -#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE) - -static int loopback_check_format(struct loopback_cable *cable, int stream) -{ - struct snd_pcm_runtime *runtime, *cruntime; - struct loopback_setup *setup; - struct snd_card *card; - int check; - - if (cable->valid != CABLE_VALID_BOTH) { - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - goto __notify; - return 0; - } - runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]-> - substream->runtime; - cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]-> - substream->runtime; - check = runtime->format != cruntime->format || - runtime->rate != cruntime->rate || - runtime->channels != cruntime->channels; - if (!check) - return 0; - if (stream == SNDRV_PCM_STREAM_CAPTURE) { - return -EIO; - } else { - snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]-> - substream, SNDRV_PCM_STATE_DRAINING); - __notify: - runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]-> - substream->runtime; - setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]); - card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card; - if (setup->format != runtime->format) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &setup->format_id); - setup->format = runtime->format; - } - if (setup->rate != runtime->rate) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &setup->rate_id); - setup->rate = runtime->rate; - } - if (setup->channels != runtime->channels) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &setup->channels_id); - setup->channels = runtime->channels; - } - } - return 0; -} - -static void loopback_active_notify(struct loopback_pcm *dpcm) -{ - snd_ctl_notify(dpcm->loopback->card, - SNDRV_CTL_EVENT_MASK_VALUE, - &get_setup(dpcm)->active_id); -} - -static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - int err, stream = 1 << substream->stream; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - err = loopback_check_format(cable, substream->stream); - if (err < 0) - return err; - dpcm->last_jiffies = jiffies; - dpcm->pcm_rate_shift = 0; - spin_lock(&cable->lock); - cable->running |= stream; - cable->pause &= ~stream; - spin_unlock(&cable->lock); - loopback_timer_start(dpcm); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - loopback_active_notify(dpcm); - break; - case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&cable->lock); - cable->running &= ~stream; - cable->pause &= ~stream; - spin_unlock(&cable->lock); - loopback_timer_stop(dpcm); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - loopback_active_notify(dpcm); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock(&cable->lock); - cable->pause |= stream; - spin_unlock(&cable->lock); - loopback_timer_stop(dpcm); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock(&cable->lock); - dpcm->last_jiffies = jiffies; - cable->pause &= ~stream; - spin_unlock(&cable->lock); - loopback_timer_start(dpcm); - break; - default: - return -EINVAL; - } - return 0; -} - -static void params_change_substream(struct loopback_pcm *dpcm, - struct snd_pcm_runtime *runtime) -{ - struct snd_pcm_runtime *dst_runtime; - - if (dpcm == NULL || dpcm->substream == NULL) - return; - dst_runtime = dpcm->substream->runtime; - if (dst_runtime == NULL) - return; - dst_runtime->hw = dpcm->cable->hw; -} - -static void params_change(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - - cable->hw.formats = (1ULL << runtime->format); - cable->hw.rate_min = runtime->rate; - cable->hw.rate_max = runtime->rate; - cable->hw.channels_min = runtime->channels; - cable->hw.channels_max = runtime->channels; - params_change_substream(cable->streams[SNDRV_PCM_STREAM_PLAYBACK], - runtime); - params_change_substream(cable->streams[SNDRV_PCM_STREAM_CAPTURE], - runtime); -} - -static int loopback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - int bps, salign; - - salign = (snd_pcm_format_width(runtime->format) * - runtime->channels) / 8; - bps = salign * runtime->rate; - if (bps <= 0 || salign <= 0) - return -EINVAL; - - dpcm->buf_pos = 0; - dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - /* clear capture buffer */ - dpcm->silent_size = dpcm->pcm_buffer_size; - snd_pcm_format_set_silence(runtime->format, runtime->dma_area, - runtime->buffer_size * runtime->channels); - } - - dpcm->irq_pos = 0; - dpcm->period_update_pending = 0; - dpcm->pcm_bps = bps; - dpcm->pcm_salign = salign; - dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size); - - mutex_lock(&dpcm->loopback->cable_lock); - if (!(cable->valid & ~(1 << substream->stream)) || - (get_setup(dpcm)->notify && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) - params_change(substream); - cable->valid |= 1 << substream->stream; - mutex_unlock(&dpcm->loopback->cable_lock); - - return 0; -} - -static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes) -{ - struct snd_pcm_runtime *runtime = dpcm->substream->runtime; - char *dst = runtime->dma_area; - unsigned int dst_off = dpcm->buf_pos; - - if (dpcm->silent_size >= dpcm->pcm_buffer_size) - return; - if (dpcm->silent_size + bytes > dpcm->pcm_buffer_size) - bytes = dpcm->pcm_buffer_size - dpcm->silent_size; - - for (;;) { - unsigned int size = bytes; - if (dst_off + size > dpcm->pcm_buffer_size) - size = dpcm->pcm_buffer_size - dst_off; - snd_pcm_format_set_silence(runtime->format, dst + dst_off, - bytes_to_frames(runtime, size) * - runtime->channels); - dpcm->silent_size += size; - bytes -= size; - if (!bytes) - break; - dst_off = 0; - } -} - -static void copy_play_buf(struct loopback_pcm *play, - struct loopback_pcm *capt, - unsigned int bytes) -{ - struct snd_pcm_runtime *runtime = play->substream->runtime; - char *src = runtime->dma_area; - char *dst = capt->substream->runtime->dma_area; - unsigned int src_off = play->buf_pos; - unsigned int dst_off = capt->buf_pos; - unsigned int clear_bytes = 0; - - /* check if playback is draining, trim the capture copy size - * when our pointer is at the end of playback ring buffer */ - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && - snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) { - snd_pcm_uframes_t appl_ptr, appl_ptr1, diff; - appl_ptr = appl_ptr1 = runtime->control->appl_ptr; - appl_ptr1 -= appl_ptr1 % runtime->buffer_size; - appl_ptr1 += play->buf_pos / play->pcm_salign; - if (appl_ptr < appl_ptr1) - appl_ptr1 -= runtime->buffer_size; - diff = (appl_ptr - appl_ptr1) * play->pcm_salign; - if (diff < bytes) { - clear_bytes = bytes - diff; - bytes = diff; - } - } - - for (;;) { - unsigned int size = bytes; - if (src_off + size > play->pcm_buffer_size) - size = play->pcm_buffer_size - src_off; - if (dst_off + size > capt->pcm_buffer_size) - size = capt->pcm_buffer_size - dst_off; - memcpy(dst + dst_off, src + src_off, size); - capt->silent_size = 0; - bytes -= size; - if (!bytes) - break; - src_off = (src_off + size) % play->pcm_buffer_size; - dst_off = (dst_off + size) % capt->pcm_buffer_size; - } - - if (clear_bytes > 0) { - clear_capture_buf(capt, clear_bytes); - capt->silent_size = 0; - } -} - -#define BYTEPOS_UPDATE_POSONLY 0 -#define BYTEPOS_UPDATE_CLEAR 1 -#define BYTEPOS_UPDATE_COPY 2 - -static void loopback_bytepos_update(struct loopback_pcm *dpcm, - unsigned int delta, - unsigned int cmd) -{ - unsigned int count; - unsigned long last_pos; - - last_pos = byte_pos(dpcm, dpcm->irq_pos); - dpcm->irq_pos += delta * dpcm->pcm_bps; - count = byte_pos(dpcm, dpcm->irq_pos) - last_pos; - if (!count) - return; - if (cmd == BYTEPOS_UPDATE_CLEAR) - clear_capture_buf(dpcm, count); - else if (cmd == BYTEPOS_UPDATE_COPY) - copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK], - dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE], - count); - dpcm->buf_pos += count; - dpcm->buf_pos %= dpcm->pcm_buffer_size; - if (dpcm->irq_pos >= dpcm->period_size_frac) { - dpcm->irq_pos %= dpcm->period_size_frac; - dpcm->period_update_pending = 1; - } -} - -static unsigned int loopback_pos_update(struct loopback_cable *cable) -{ - struct loopback_pcm *dpcm_play = - cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; - struct loopback_pcm *dpcm_capt = - cable->streams[SNDRV_PCM_STREAM_CAPTURE]; - unsigned long delta_play = 0, delta_capt = 0; - unsigned int running; - unsigned long flags; - - spin_lock_irqsave(&cable->lock, flags); - running = cable->running ^ cable->pause; - if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { - delta_play = jiffies - dpcm_play->last_jiffies; - dpcm_play->last_jiffies += delta_play; - } - - if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { - delta_capt = jiffies - dpcm_capt->last_jiffies; - dpcm_capt->last_jiffies += delta_capt; - } - - if (delta_play == 0 && delta_capt == 0) - goto unlock; - - if (delta_play > delta_capt) { - loopback_bytepos_update(dpcm_play, delta_play - delta_capt, - BYTEPOS_UPDATE_POSONLY); - delta_play = delta_capt; - } else if (delta_play < delta_capt) { - loopback_bytepos_update(dpcm_capt, delta_capt - delta_play, - BYTEPOS_UPDATE_CLEAR); - delta_capt = delta_play; - } - - if (delta_play == 0 && delta_capt == 0) - goto unlock; - - /* note delta_capt == delta_play at this moment */ - loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); - loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); - unlock: - spin_unlock_irqrestore(&cable->lock, flags); - return running; -} - -static void loopback_timer_function(unsigned long data) -{ - struct loopback_pcm *dpcm = (struct loopback_pcm *)data; - unsigned int running; - - running = loopback_pos_update(dpcm->cable); - if (running & (1 << dpcm->substream->stream)) { - loopback_timer_start(dpcm); - if (dpcm->period_update_pending) { - dpcm->period_update_pending = 0; - snd_pcm_period_elapsed(dpcm->substream); - } - } -} - -static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - - loopback_pos_update(dpcm->cable); - return bytes_to_frames(runtime, dpcm->buf_pos); -} - -static struct snd_pcm_hardware loopback_pcm_hardware = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | - SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 32, - .buffer_bytes_max = 2 * 1024 * 1024, - .period_bytes_min = 64, - /* note check overflow in frac_pos() using pcm_rate_shift before - changing period_bytes_max value */ - .period_bytes_max = 1024 * 1024, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static void loopback_runtime_free(struct snd_pcm_runtime *runtime) -{ - struct loopback_pcm *dpcm = runtime->private_data; - kfree(dpcm); -} - -static int loopback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(params)); -} - -static int loopback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - - mutex_lock(&dpcm->loopback->cable_lock); - cable->valid &= ~(1 << substream->stream); - mutex_unlock(&dpcm->loopback->cable_lock); - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static unsigned int get_cable_index(struct snd_pcm_substream *substream) -{ - if (!substream->pcm->device) - return substream->stream; - else - return !substream->stream; -} - -static int rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - - struct snd_pcm_hardware *hw = rule->private; - struct snd_mask *maskp = hw_param_mask(params, rule->var); - - maskp->bits[0] &= (u_int32_t)hw->formats; - maskp->bits[1] &= (u_int32_t)(hw->formats >> 32); - memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */ - if (! maskp->bits[0] && ! maskp->bits[1]) - return -EINVAL; - return 0; -} - -static int rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hardware *hw = rule->private; - struct snd_interval t; - - t.min = hw->rate_min; - t.max = hw->rate_max; - t.openmin = t.openmax = 0; - t.integer = 0; - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int rule_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hardware *hw = rule->private; - struct snd_interval t; - - t.min = hw->channels_min; - t.max = hw->channels_max; - t.openmin = t.openmax = 0; - t.integer = 0; - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int loopback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback *loopback = substream->private_data; - struct loopback_pcm *dpcm; - struct loopback_cable *cable; - int err = 0; - int dev = get_cable_index(substream); - - mutex_lock(&loopback->cable_lock); - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (!dpcm) { - err = -ENOMEM; - goto unlock; - } - dpcm->loopback = loopback; - dpcm->substream = substream; - setup_timer(&dpcm->timer, loopback_timer_function, - (unsigned long)dpcm); - - cable = loopback->cables[substream->number][dev]; - if (!cable) { - cable = kzalloc(sizeof(*cable), GFP_KERNEL); - if (!cable) { - kfree(dpcm); - err = -ENOMEM; - goto unlock; - } - spin_lock_init(&cable->lock); - cable->hw = loopback_pcm_hardware; - loopback->cables[substream->number][dev] = cable; - } - dpcm->cable = cable; - cable->streams[substream->stream] = dpcm; - - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - - /* use dynamic rules based on actual runtime->hw values */ - /* note that the default rules created in the PCM midlevel code */ - /* are cached -> they do not reflect the actual state */ - err = snd_pcm_hw_rule_add(runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - rule_format, &runtime->hw, - SNDRV_PCM_HW_PARAM_FORMAT, -1); - if (err < 0) - goto unlock; - err = snd_pcm_hw_rule_add(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - rule_rate, &runtime->hw, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - goto unlock; - err = snd_pcm_hw_rule_add(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - rule_channels, &runtime->hw, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (err < 0) - goto unlock; - - runtime->private_data = dpcm; - runtime->private_free = loopback_runtime_free; - if (get_notify(dpcm)) - runtime->hw = loopback_pcm_hardware; - else - runtime->hw = cable->hw; - unlock: - mutex_unlock(&loopback->cable_lock); - return err; -} - -static int loopback_close(struct snd_pcm_substream *substream) -{ - struct loopback *loopback = substream->private_data; - struct loopback_pcm *dpcm = substream->runtime->private_data; - struct loopback_cable *cable; - int dev = get_cable_index(substream); - - loopback_timer_stop(dpcm); - mutex_lock(&loopback->cable_lock); - cable = loopback->cables[substream->number][dev]; - if (cable->streams[!substream->stream]) { - /* other stream is still alive */ - cable->streams[substream->stream] = NULL; - } else { - /* free the cable */ - loopback->cables[substream->number][dev] = NULL; - kfree(cable); - } - mutex_unlock(&loopback->cable_lock); - return 0; -} - -static struct snd_pcm_ops loopback_playback_ops = { - .open = loopback_open, - .close = loopback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = loopback_hw_params, - .hw_free = loopback_hw_free, - .prepare = loopback_prepare, - .trigger = loopback_trigger, - .pointer = loopback_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops loopback_capture_ops = { - .open = loopback_open, - .close = loopback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = loopback_hw_params, - .hw_free = loopback_hw_free, - .prepare = loopback_prepare, - .trigger = loopback_trigger, - .pointer = loopback_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static int __devinit loopback_pcm_new(struct loopback *loopback, - int device, int substreams) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(loopback->card, "Loopback PCM", device, - substreams, substreams, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops); - - pcm->private_data = loopback; - pcm->info_flags = 0; - strcpy(pcm->name, "Loopback PCM"); - - loopback->pcm[device] = pcm; - return 0; -} - -static int loopback_rate_shift_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 80000; - uinfo->value.integer.max = 120000; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate_shift; - return 0; -} - -static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.integer.value[0]; - if (val < 80000) - val = 80000; - if (val > 120000) - val = 120000; - mutex_lock(&loopback->cable_lock); - if (val != loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate_shift) { - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate_shift = val; - change = 1; - } - mutex_unlock(&loopback->cable_lock); - return change; -} - -static int loopback_notify_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].notify; - return 0; -} - -static int loopback_notify_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.integer.value[0] ? 1 : 0; - if (val != loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].notify) { - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].notify = val; - change = 1; - } - return change; -} - -static int loopback_active_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - struct loopback_cable *cable = loopback->cables - [kcontrol->id.subdevice][kcontrol->id.device ^ 1]; - unsigned int val = 0; - - if (cable != NULL) - val = (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? - 1 : 0; - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int loopback_format_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_format_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].format; - return 0; -} - -static int loopback_rate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 192000; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate; - return 0; -} - -static int loopback_channels_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 1; - uinfo->value.integer.max = 1024; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_channels_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].channels; - return 0; -} - -static struct snd_kcontrol_new loopback_controls[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Rate Shift 100000", - .info = loopback_rate_shift_info, - .get = loopback_rate_shift_get, - .put = loopback_rate_shift_put, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Notify", - .info = snd_ctl_boolean_mono_info, - .get = loopback_notify_get, - .put = loopback_notify_put, -}, -#define ACTIVE_IDX 2 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Active", - .info = snd_ctl_boolean_mono_info, - .get = loopback_active_get, -}, -#define FORMAT_IDX 3 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Format", - .info = loopback_format_info, - .get = loopback_format_get -}, -#define RATE_IDX 4 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Rate", - .info = loopback_rate_info, - .get = loopback_rate_get -}, -#define CHANNELS_IDX 5 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Channels", - .info = loopback_channels_info, - .get = loopback_channels_get -} -}; - -static int __devinit loopback_mixer_new(struct loopback *loopback, int notify) -{ - struct snd_card *card = loopback->card; - struct snd_pcm *pcm; - struct snd_kcontrol *kctl; - struct loopback_setup *setup; - int err, dev, substr, substr_count, idx; - - strcpy(card->mixername, "Loopback Mixer"); - for (dev = 0; dev < 2; dev++) { - pcm = loopback->pcm[dev]; - substr_count = - pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count; - for (substr = 0; substr < substr_count; substr++) { - setup = &loopback->setup[substr][dev]; - setup->notify = notify; - setup->rate_shift = NO_PITCH; - setup->format = SNDRV_PCM_FORMAT_S16_LE; - setup->rate = 48000; - setup->channels = 2; - for (idx = 0; idx < ARRAY_SIZE(loopback_controls); - idx++) { - kctl = snd_ctl_new1(&loopback_controls[idx], - loopback); - if (!kctl) - return -ENOMEM; - kctl->id.device = dev; - kctl->id.subdevice = substr; - switch (idx) { - case ACTIVE_IDX: - setup->active_id = kctl->id; - break; - case FORMAT_IDX: - setup->format_id = kctl->id; - break; - case RATE_IDX: - setup->rate_id = kctl->id; - break; - case CHANNELS_IDX: - setup->channels_id = kctl->id; - break; - default: - break; - } - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - } - } - } - return 0; -} - -#ifdef CONFIG_PROC_FS - -static void print_dpcm_info(struct snd_info_buffer *buffer, - struct loopback_pcm *dpcm, - const char *id) -{ - snd_iprintf(buffer, " %s\n", id); - if (dpcm == NULL) { - snd_iprintf(buffer, " inactive\n"); - return; - } - snd_iprintf(buffer, " buffer_size:\t%u\n", dpcm->pcm_buffer_size); - snd_iprintf(buffer, " buffer_pos:\t\t%u\n", dpcm->buf_pos); - snd_iprintf(buffer, " silent_size:\t%u\n", dpcm->silent_size); - snd_iprintf(buffer, " period_size:\t%u\n", dpcm->pcm_period_size); - snd_iprintf(buffer, " bytes_per_sec:\t%u\n", dpcm->pcm_bps); - snd_iprintf(buffer, " sample_align:\t%u\n", dpcm->pcm_salign); - snd_iprintf(buffer, " rate_shift:\t\t%u\n", dpcm->pcm_rate_shift); - snd_iprintf(buffer, " update_pending:\t%u\n", - dpcm->period_update_pending); - snd_iprintf(buffer, " irq_pos:\t\t%u\n", dpcm->irq_pos); - snd_iprintf(buffer, " period_frac:\t%u\n", dpcm->period_size_frac); - snd_iprintf(buffer, " last_jiffies:\t%lu (%lu)\n", - dpcm->last_jiffies, jiffies); - snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires); -} - -static void print_substream_info(struct snd_info_buffer *buffer, - struct loopback *loopback, - int sub, - int num) -{ - struct loopback_cable *cable = loopback->cables[sub][num]; - - snd_iprintf(buffer, "Cable %i substream %i:\n", num, sub); - if (cable == NULL) { - snd_iprintf(buffer, " inactive\n"); - return; - } - snd_iprintf(buffer, " valid: %u\n", cable->valid); - snd_iprintf(buffer, " running: %u\n", cable->running); - snd_iprintf(buffer, " pause: %u\n", cable->pause); - print_dpcm_info(buffer, cable->streams[0], "Playback"); - print_dpcm_info(buffer, cable->streams[1], "Capture"); -} - -static void print_cable_info(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct loopback *loopback = entry->private_data; - int sub, num; - - mutex_lock(&loopback->cable_lock); - num = entry->name[strlen(entry->name)-1]; - num = num == '0' ? 0 : 1; - for (sub = 0; sub < MAX_PCM_SUBSTREAMS; sub++) - print_substream_info(buffer, loopback, sub, num); - mutex_unlock(&loopback->cable_lock); -} - -static int __devinit loopback_proc_new(struct loopback *loopback, int cidx) -{ - char name[32]; - struct snd_info_entry *entry; - int err; - - snprintf(name, sizeof(name), "cable#%d", cidx); - err = snd_card_proc_new(loopback->card, name, &entry); - if (err < 0) - return err; - - snd_info_set_text_ops(entry, loopback, print_cable_info); - return 0; -} - -#else /* !CONFIG_PROC_FS */ - -#define loopback_proc_new(loopback, cidx) do { } while (0) - -#endif - -static int __devinit loopback_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct loopback *loopback; - int dev = devptr->id; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct loopback), &card); - if (err < 0) - return err; - loopback = card->private_data; - - if (pcm_substreams[dev] < 1) - pcm_substreams[dev] = 1; - if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS) - pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; - - loopback->card = card; - mutex_init(&loopback->cable_lock); - - err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]); - if (err < 0) - goto __nodev; - err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]); - if (err < 0) - goto __nodev; - err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0); - if (err < 0) - goto __nodev; - loopback_proc_new(loopback, 0); - loopback_proc_new(loopback, 1); - strcpy(card->driver, "Loopback"); - strcpy(card->shortname, "Loopback"); - sprintf(card->longname, "Loopback %i", dev + 1); - err = snd_card_register(card); - if (!err) { - platform_set_drvdata(devptr, card); - return 0; - } - __nodev: - snd_card_free(card); - return err; -} - -static int __devexit loopback_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int loopback_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct loopback *loopback = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(loopback->pcm[0]); - snd_pcm_suspend_all(loopback->pcm[1]); - return 0; -} - -static int loopback_resume(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -#define SND_LOOPBACK_DRIVER "snd_aloop" - -static struct platform_driver loopback_driver = { - .probe = loopback_probe, - .remove = __devexit_p(loopback_remove), -#ifdef CONFIG_PM - .suspend = loopback_suspend, - .resume = loopback_resume, -#endif - .driver = { - .name = SND_LOOPBACK_DRIVER - }, -}; - -static void loopback_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&loopback_driver); -} - -static int __init alsa_card_loopback_init(void) -{ - int i, err, cards; - - err = platform_driver_register(&loopback_driver); - if (err < 0) - return err; - - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (!enable[i]) - continue; - device = platform_device_register_simple(SND_LOOPBACK_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "aloop: No loopback enabled\n"); -#endif - loopback_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_loopback_exit(void) -{ - loopback_unregister_all(); -} - -module_init(alsa_card_loopback_init) -module_exit(alsa_card_loopback_exit) diff --git a/ANDROID_3.4.5/sound/drivers/dummy.c b/ANDROID_3.4.5/sound/drivers/dummy.c deleted file mode 100644 index ad9434fd..00000000 --- a/ANDROID_3.4.5/sound/drivers/dummy.c +++ /dev/null @@ -1,1157 +0,0 @@ -/* - * Dummy soundcard - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/jiffies.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/hrtimer.h> -#include <linux/math64.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/tlv.h> -#include <sound/pcm.h> -#include <sound/rawmidi.h> -#include <sound/info.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Dummy soundcard (/dev/null)"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}"); - -#define MAX_PCM_DEVICES 4 -#define MAX_PCM_SUBSTREAMS 128 -#define MAX_MIDI_DEVICES 2 - -/* defaults */ -#define MAX_BUFFER_SIZE (64*1024) -#define MIN_PERIOD_SIZE 64 -#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE -#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) -#define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000 -#define USE_RATE_MIN 5500 -#define USE_RATE_MAX 48000 -#define USE_CHANNELS_MIN 1 -#define USE_CHANNELS_MAX 2 -#define USE_PERIODS_MIN 1 -#define USE_PERIODS_MAX 1024 - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL}; -static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; -//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; -#ifdef CONFIG_HIGH_RES_TIMERS -static bool hrtimer = 1; -#endif -static bool fake_buffer = 1; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for dummy soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for dummy soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this dummy soundcard."); -module_param_array(model, charp, NULL, 0444); -MODULE_PARM_DESC(model, "Soundcard model."); -module_param_array(pcm_devs, int, NULL, 0444); -MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver."); -module_param_array(pcm_substreams, int, NULL, 0444); -MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver."); -//module_param_array(midi_devs, int, NULL, 0444); -//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver."); -module_param(fake_buffer, bool, 0444); -MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations."); -#ifdef CONFIG_HIGH_RES_TIMERS -module_param(hrtimer, bool, 0644); -MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source."); -#endif - -static struct platform_device *devices[SNDRV_CARDS]; - -#define MIXER_ADDR_MASTER 0 -#define MIXER_ADDR_LINE 1 -#define MIXER_ADDR_MIC 2 -#define MIXER_ADDR_SYNTH 3 -#define MIXER_ADDR_CD 4 -#define MIXER_ADDR_LAST 4 - -struct dummy_timer_ops { - int (*create)(struct snd_pcm_substream *); - void (*free)(struct snd_pcm_substream *); - int (*prepare)(struct snd_pcm_substream *); - int (*start)(struct snd_pcm_substream *); - int (*stop)(struct snd_pcm_substream *); - snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); -}; - -struct dummy_model { - const char *name; - int (*playback_constraints)(struct snd_pcm_runtime *runtime); - int (*capture_constraints)(struct snd_pcm_runtime *runtime); - u64 formats; - size_t buffer_bytes_max; - size_t period_bytes_min; - size_t period_bytes_max; - unsigned int periods_min; - unsigned int periods_max; - unsigned int rates; - unsigned int rate_min; - unsigned int rate_max; - unsigned int channels_min; - unsigned int channels_max; -}; - -struct snd_dummy { - struct snd_card *card; - struct dummy_model *model; - struct snd_pcm *pcm; - struct snd_pcm_hardware pcm_hw; - spinlock_t mixer_lock; - int mixer_volume[MIXER_ADDR_LAST+1][2]; - int capture_source[MIXER_ADDR_LAST+1][2]; - const struct dummy_timer_ops *timer_ops; -}; - -/* - * card models - */ - -static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime) -{ - int err; - err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - return err; - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX); - if (err < 0) - return err; - return 0; -} - -struct dummy_model model_emu10k1 = { - .name = "emu10k1", - .playback_constraints = emu10k1_playback_constraints, - .buffer_bytes_max = 128 * 1024, -}; - -struct dummy_model model_rme9652 = { - .name = "rme9652", - .buffer_bytes_max = 26 * 64 * 1024, - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .channels_min = 26, - .channels_max = 26, - .periods_min = 2, - .periods_max = 2, -}; - -struct dummy_model model_ice1712 = { - .name = "ice1712", - .buffer_bytes_max = 256 * 1024, - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .channels_min = 10, - .channels_max = 10, - .periods_min = 1, - .periods_max = 1024, -}; - -struct dummy_model model_uda1341 = { - .name = "uda1341", - .buffer_bytes_max = 16380, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 2, - .channels_max = 2, - .periods_min = 2, - .periods_max = 255, -}; - -struct dummy_model model_ac97 = { - .name = "ac97", - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, -}; - -struct dummy_model model_ca0106 = { - .name = "ca0106", - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .buffer_bytes_max = ((65536-64)*8), - .period_bytes_max = (65536-64), - .periods_min = 2, - .periods_max = 8, - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000, - .rate_min = 48000, - .rate_max = 192000, -}; - -struct dummy_model *dummy_models[] = { - &model_emu10k1, - &model_rme9652, - &model_ice1712, - &model_uda1341, - &model_ac97, - &model_ca0106, - NULL -}; - -/* - * system timer interface - */ - -struct dummy_systimer_pcm { - spinlock_t lock; - struct timer_list timer; - unsigned long base_time; - unsigned int frac_pos; /* fractional sample position (based HZ) */ - unsigned int frac_period_rest; - unsigned int frac_buffer_size; /* buffer_size * HZ */ - unsigned int frac_period_size; /* period_size * HZ */ - unsigned int rate; - int elapsed; - struct snd_pcm_substream *substream; -}; - -static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) -{ - dpcm->timer.expires = jiffies + - (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate; - add_timer(&dpcm->timer); -} - -static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) -{ - unsigned long delta; - - delta = jiffies - dpcm->base_time; - if (!delta) - return; - dpcm->base_time += delta; - delta *= dpcm->rate; - dpcm->frac_pos += delta; - while (dpcm->frac_pos >= dpcm->frac_buffer_size) - dpcm->frac_pos -= dpcm->frac_buffer_size; - while (dpcm->frac_period_rest <= delta) { - dpcm->elapsed++; - dpcm->frac_period_rest += dpcm->frac_period_size; - } - dpcm->frac_period_rest -= delta; -} - -static int dummy_systimer_start(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - spin_lock(&dpcm->lock); - dpcm->base_time = jiffies; - dummy_systimer_rearm(dpcm); - spin_unlock(&dpcm->lock); - return 0; -} - -static int dummy_systimer_stop(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - spin_lock(&dpcm->lock); - del_timer(&dpcm->timer); - spin_unlock(&dpcm->lock); - return 0; -} - -static int dummy_systimer_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct dummy_systimer_pcm *dpcm = runtime->private_data; - - dpcm->frac_pos = 0; - dpcm->rate = runtime->rate; - dpcm->frac_buffer_size = runtime->buffer_size * HZ; - dpcm->frac_period_size = runtime->period_size * HZ; - dpcm->frac_period_rest = dpcm->frac_period_size; - dpcm->elapsed = 0; - - return 0; -} - -static void dummy_systimer_callback(unsigned long data) -{ - struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data; - unsigned long flags; - int elapsed = 0; - - spin_lock_irqsave(&dpcm->lock, flags); - dummy_systimer_update(dpcm); - dummy_systimer_rearm(dpcm); - elapsed = dpcm->elapsed; - dpcm->elapsed = 0; - spin_unlock_irqrestore(&dpcm->lock, flags); - if (elapsed) - snd_pcm_period_elapsed(dpcm->substream); -} - -static snd_pcm_uframes_t -dummy_systimer_pointer(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - snd_pcm_uframes_t pos; - - spin_lock(&dpcm->lock); - dummy_systimer_update(dpcm); - pos = dpcm->frac_pos / HZ; - spin_unlock(&dpcm->lock); - return pos; -} - -static int dummy_systimer_create(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm; - - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (!dpcm) - return -ENOMEM; - substream->runtime->private_data = dpcm; - init_timer(&dpcm->timer); - dpcm->timer.data = (unsigned long) dpcm; - dpcm->timer.function = dummy_systimer_callback; - spin_lock_init(&dpcm->lock); - dpcm->substream = substream; - return 0; -} - -static void dummy_systimer_free(struct snd_pcm_substream *substream) -{ - kfree(substream->runtime->private_data); -} - -static struct dummy_timer_ops dummy_systimer_ops = { - .create = dummy_systimer_create, - .free = dummy_systimer_free, - .prepare = dummy_systimer_prepare, - .start = dummy_systimer_start, - .stop = dummy_systimer_stop, - .pointer = dummy_systimer_pointer, -}; - -#ifdef CONFIG_HIGH_RES_TIMERS -/* - * hrtimer interface - */ - -struct dummy_hrtimer_pcm { - ktime_t base_time; - ktime_t period_time; - atomic_t running; - struct hrtimer timer; - struct tasklet_struct tasklet; - struct snd_pcm_substream *substream; -}; - -static void dummy_hrtimer_pcm_elapsed(unsigned long priv) -{ - struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv; - if (atomic_read(&dpcm->running)) - snd_pcm_period_elapsed(dpcm->substream); -} - -static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer) -{ - struct dummy_hrtimer_pcm *dpcm; - - dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer); - if (!atomic_read(&dpcm->running)) - return HRTIMER_NORESTART; - tasklet_schedule(&dpcm->tasklet); - hrtimer_forward_now(timer, dpcm->period_time); - return HRTIMER_RESTART; -} - -static int dummy_hrtimer_start(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; - - dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer); - hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL); - atomic_set(&dpcm->running, 1); - return 0; -} - -static int dummy_hrtimer_stop(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; - - atomic_set(&dpcm->running, 0); - hrtimer_cancel(&dpcm->timer); - return 0; -} - -static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm) -{ - tasklet_kill(&dpcm->tasklet); -} - -static snd_pcm_uframes_t -dummy_hrtimer_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct dummy_hrtimer_pcm *dpcm = runtime->private_data; - u64 delta; - u32 pos; - - delta = ktime_us_delta(hrtimer_cb_get_time(&dpcm->timer), - dpcm->base_time); - delta = div_u64(delta * runtime->rate + 999999, 1000000); - div_u64_rem(delta, runtime->buffer_size, &pos); - return pos; -} - -static int dummy_hrtimer_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct dummy_hrtimer_pcm *dpcm = runtime->private_data; - unsigned int period, rate; - long sec; - unsigned long nsecs; - - dummy_hrtimer_sync(dpcm); - period = runtime->period_size; - rate = runtime->rate; - sec = period / rate; - period %= rate; - nsecs = div_u64((u64)period * 1000000000UL + rate - 1, rate); - dpcm->period_time = ktime_set(sec, nsecs); - - return 0; -} - -static int dummy_hrtimer_create(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm; - - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (!dpcm) - return -ENOMEM; - substream->runtime->private_data = dpcm; - hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - dpcm->timer.function = dummy_hrtimer_callback; - dpcm->substream = substream; - atomic_set(&dpcm->running, 0); - tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed, - (unsigned long)dpcm); - return 0; -} - -static void dummy_hrtimer_free(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; - dummy_hrtimer_sync(dpcm); - kfree(dpcm); -} - -static struct dummy_timer_ops dummy_hrtimer_ops = { - .create = dummy_hrtimer_create, - .free = dummy_hrtimer_free, - .prepare = dummy_hrtimer_prepare, - .start = dummy_hrtimer_start, - .stop = dummy_hrtimer_stop, - .pointer = dummy_hrtimer_pointer, -}; - -#endif /* CONFIG_HIGH_RES_TIMERS */ - -/* - * PCM interface - */ - -static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - return dummy->timer_ops->start(substream); - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - return dummy->timer_ops->stop(substream); - } - return -EINVAL; -} - -static int dummy_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - - return dummy->timer_ops->prepare(substream); -} - -static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - - return dummy->timer_ops->pointer(substream); -} - -static struct snd_pcm_hardware dummy_pcm_hardware = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = USE_FORMATS, - .rates = USE_RATE, - .rate_min = USE_RATE_MIN, - .rate_max = USE_RATE_MAX, - .channels_min = USE_CHANNELS_MIN, - .channels_max = USE_CHANNELS_MAX, - .buffer_bytes_max = MAX_BUFFER_SIZE, - .period_bytes_min = MIN_PERIOD_SIZE, - .period_bytes_max = MAX_PERIOD_SIZE, - .periods_min = USE_PERIODS_MIN, - .periods_max = USE_PERIODS_MAX, - .fifo_size = 0, -}; - -static int dummy_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - if (fake_buffer) { - /* runtime->dma_bytes has to be set manually to allow mmap */ - substream->runtime->dma_bytes = params_buffer_bytes(hw_params); - return 0; - } - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int dummy_pcm_hw_free(struct snd_pcm_substream *substream) -{ - if (fake_buffer) - return 0; - return snd_pcm_lib_free_pages(substream); -} - -static int dummy_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - struct dummy_model *model = dummy->model; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - dummy->timer_ops = &dummy_systimer_ops; -#ifdef CONFIG_HIGH_RES_TIMERS - if (hrtimer) - dummy->timer_ops = &dummy_hrtimer_ops; -#endif - - err = dummy->timer_ops->create(substream); - if (err < 0) - return err; - - runtime->hw = dummy->pcm_hw; - if (substream->pcm->device & 1) { - runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; - runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; - } - if (substream->pcm->device & 2) - runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID); - - if (model == NULL) - return 0; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (model->playback_constraints) - err = model->playback_constraints(substream->runtime); - } else { - if (model->capture_constraints) - err = model->capture_constraints(substream->runtime); - } - if (err < 0) { - dummy->timer_ops->free(substream); - return err; - } - return 0; -} - -static int dummy_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - dummy->timer_ops->free(substream); - return 0; -} - -/* - * dummy buffer handling - */ - -static void *dummy_page[2]; - -static void free_fake_buffer(void) -{ - if (fake_buffer) { - int i; - for (i = 0; i < 2; i++) - if (dummy_page[i]) { - free_page((unsigned long)dummy_page[i]); - dummy_page[i] = NULL; - } - } -} - -static int alloc_fake_buffer(void) -{ - int i; - - if (!fake_buffer) - return 0; - for (i = 0; i < 2; i++) { - dummy_page[i] = (void *)get_zeroed_page(GFP_KERNEL); - if (!dummy_page[i]) { - free_fake_buffer(); - return -ENOMEM; - } - } - return 0; -} - -static int dummy_pcm_copy(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) -{ - return 0; /* do nothing */ -} - -static int dummy_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - return 0; /* do nothing */ -} - -static struct page *dummy_pcm_page(struct snd_pcm_substream *substream, - unsigned long offset) -{ - return virt_to_page(dummy_page[substream->stream]); /* the same page */ -} - -static struct snd_pcm_ops dummy_pcm_ops = { - .open = dummy_pcm_open, - .close = dummy_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = dummy_pcm_hw_params, - .hw_free = dummy_pcm_hw_free, - .prepare = dummy_pcm_prepare, - .trigger = dummy_pcm_trigger, - .pointer = dummy_pcm_pointer, -}; - -static struct snd_pcm_ops dummy_pcm_ops_no_buf = { - .open = dummy_pcm_open, - .close = dummy_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = dummy_pcm_hw_params, - .hw_free = dummy_pcm_hw_free, - .prepare = dummy_pcm_prepare, - .trigger = dummy_pcm_trigger, - .pointer = dummy_pcm_pointer, - .copy = dummy_pcm_copy, - .silence = dummy_pcm_silence, - .page = dummy_pcm_page, -}; - -static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, - int substreams) -{ - struct snd_pcm *pcm; - struct snd_pcm_ops *ops; - int err; - - err = snd_pcm_new(dummy->card, "Dummy PCM", device, - substreams, substreams, &pcm); - if (err < 0) - return err; - dummy->pcm = pcm; - if (fake_buffer) - ops = &dummy_pcm_ops_no_buf; - else - ops = &dummy_pcm_ops; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, ops); - pcm->private_data = dummy; - pcm->info_flags = 0; - strcpy(pcm->name, "Dummy PCM"); - if (!fake_buffer) { - snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, 64*1024); - } - return 0; -} - -/* - * mixer interface - */ - -#define DUMMY_VOLUME(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_dummy_volume_info, \ - .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \ - .private_value = addr, \ - .tlv = { .p = db_scale_dummy } } - -static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = -50; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int addr = kcontrol->private_value; - - spin_lock_irq(&dummy->mixer_lock); - ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0]; - ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1]; - spin_unlock_irq(&dummy->mixer_lock); - return 0; -} - -static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; - int left, right; - - left = ucontrol->value.integer.value[0]; - if (left < -50) - left = -50; - if (left > 100) - left = 100; - right = ucontrol->value.integer.value[1]; - if (right < -50) - right = -50; - if (right > 100) - right = 100; - spin_lock_irq(&dummy->mixer_lock); - change = dummy->mixer_volume[addr][0] != left || - dummy->mixer_volume[addr][1] != right; - dummy->mixer_volume[addr][0] = left; - dummy->mixer_volume[addr][1] = right; - spin_unlock_irq(&dummy->mixer_lock); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); - -#define DUMMY_CAPSRC(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_dummy_capsrc_info, \ - .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \ - .private_value = addr } - -#define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info - -static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int addr = kcontrol->private_value; - - spin_lock_irq(&dummy->mixer_lock); - ucontrol->value.integer.value[0] = dummy->capture_source[addr][0]; - ucontrol->value.integer.value[1] = dummy->capture_source[addr][1]; - spin_unlock_irq(&dummy->mixer_lock); - return 0; -} - -static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; - int left, right; - - left = ucontrol->value.integer.value[0] & 1; - right = ucontrol->value.integer.value[1] & 1; - spin_lock_irq(&dummy->mixer_lock); - change = dummy->capture_source[addr][0] != left && - dummy->capture_source[addr][1] != right; - dummy->capture_source[addr][0] = left; - dummy->capture_source[addr][1] = right; - spin_unlock_irq(&dummy->mixer_lock); - return change; -} - -static struct snd_kcontrol_new snd_dummy_controls[] = { -DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER), -DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER), -DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH), -DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_SYNTH), -DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE), -DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE), -DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC), -DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC), -DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD), -DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD) -}; - -static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) -{ - struct snd_card *card = dummy->card; - unsigned int idx; - int err; - - spin_lock_init(&dummy->mixer_lock); - strcpy(card->mixername, "Dummy Mixer"); - - for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy)); - if (err < 0) - return err; - } - return 0; -} - -#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_PROC_FS) -/* - * proc interface - */ -static void print_formats(struct snd_dummy *dummy, - struct snd_info_buffer *buffer) -{ - int i; - - for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { - if (dummy->pcm_hw.formats & (1ULL << i)) - snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); - } -} - -static void print_rates(struct snd_dummy *dummy, - struct snd_info_buffer *buffer) -{ - static int rates[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, - 64000, 88200, 96000, 176400, 192000, - }; - int i; - - if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_CONTINUOUS) - snd_iprintf(buffer, " continuous"); - if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_KNOT) - snd_iprintf(buffer, " knot"); - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (dummy->pcm_hw.rates & (1 << i)) - snd_iprintf(buffer, " %d", rates[i]); -} - -#define get_dummy_int_ptr(dummy, ofs) \ - (unsigned int *)((char *)&((dummy)->pcm_hw) + (ofs)) -#define get_dummy_ll_ptr(dummy, ofs) \ - (unsigned long long *)((char *)&((dummy)->pcm_hw) + (ofs)) - -struct dummy_hw_field { - const char *name; - const char *format; - unsigned int offset; - unsigned int size; -}; -#define FIELD_ENTRY(item, fmt) { \ - .name = #item, \ - .format = fmt, \ - .offset = offsetof(struct snd_pcm_hardware, item), \ - .size = sizeof(dummy_pcm_hardware.item) } - -static struct dummy_hw_field fields[] = { - FIELD_ENTRY(formats, "%#llx"), - FIELD_ENTRY(rates, "%#x"), - FIELD_ENTRY(rate_min, "%d"), - FIELD_ENTRY(rate_max, "%d"), - FIELD_ENTRY(channels_min, "%d"), - FIELD_ENTRY(channels_max, "%d"), - FIELD_ENTRY(buffer_bytes_max, "%ld"), - FIELD_ENTRY(period_bytes_min, "%ld"), - FIELD_ENTRY(period_bytes_max, "%ld"), - FIELD_ENTRY(periods_min, "%d"), - FIELD_ENTRY(periods_max, "%d"), -}; - -static void dummy_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_dummy *dummy = entry->private_data; - int i; - - for (i = 0; i < ARRAY_SIZE(fields); i++) { - snd_iprintf(buffer, "%s ", fields[i].name); - if (fields[i].size == sizeof(int)) - snd_iprintf(buffer, fields[i].format, - *get_dummy_int_ptr(dummy, fields[i].offset)); - else - snd_iprintf(buffer, fields[i].format, - *get_dummy_ll_ptr(dummy, fields[i].offset)); - if (!strcmp(fields[i].name, "formats")) - print_formats(dummy, buffer); - else if (!strcmp(fields[i].name, "rates")) - print_rates(dummy, buffer); - snd_iprintf(buffer, "\n"); - } -} - -static void dummy_proc_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_dummy *dummy = entry->private_data; - char line[64]; - - while (!snd_info_get_line(buffer, line, sizeof(line))) { - char item[20]; - const char *ptr; - unsigned long long val; - int i; - - ptr = snd_info_get_str(item, line, sizeof(item)); - for (i = 0; i < ARRAY_SIZE(fields); i++) { - if (!strcmp(item, fields[i].name)) - break; - } - if (i >= ARRAY_SIZE(fields)) - continue; - snd_info_get_str(item, ptr, sizeof(item)); - if (strict_strtoull(item, 0, &val)) - continue; - if (fields[i].size == sizeof(int)) - *get_dummy_int_ptr(dummy, fields[i].offset) = val; - else - *get_dummy_ll_ptr(dummy, fields[i].offset) = val; - } -} - -static void __devinit dummy_proc_init(struct snd_dummy *chip) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) { - snd_info_set_text_ops(entry, chip, dummy_proc_read); - entry->c.text.write = dummy_proc_write; - entry->mode |= S_IWUSR; - entry->private_data = chip; - } -} -#else -#define dummy_proc_init(x) -#endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */ - -static int __devinit snd_dummy_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_dummy *dummy; - struct dummy_model *m = NULL, **mdl; - int idx, err; - int dev = devptr->id; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dummy), &card); - if (err < 0) - return err; - dummy = card->private_data; - dummy->card = card; - for (mdl = dummy_models; *mdl && model[dev]; mdl++) { - if (strcmp(model[dev], (*mdl)->name) == 0) { - printk(KERN_INFO - "snd-dummy: Using model '%s' for card %i\n", - (*mdl)->name, card->number); - m = dummy->model = *mdl; - break; - } - } - for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { - if (pcm_substreams[dev] < 1) - pcm_substreams[dev] = 1; - if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS) - pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; - err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]); - if (err < 0) - goto __nodev; - } - - dummy->pcm_hw = dummy_pcm_hardware; - if (m) { - if (m->formats) - dummy->pcm_hw.formats = m->formats; - if (m->buffer_bytes_max) - dummy->pcm_hw.buffer_bytes_max = m->buffer_bytes_max; - if (m->period_bytes_min) - dummy->pcm_hw.period_bytes_min = m->period_bytes_min; - if (m->period_bytes_max) - dummy->pcm_hw.period_bytes_max = m->period_bytes_max; - if (m->periods_min) - dummy->pcm_hw.periods_min = m->periods_min; - if (m->periods_max) - dummy->pcm_hw.periods_max = m->periods_max; - if (m->rates) - dummy->pcm_hw.rates = m->rates; - if (m->rate_min) - dummy->pcm_hw.rate_min = m->rate_min; - if (m->rate_max) - dummy->pcm_hw.rate_max = m->rate_max; - if (m->channels_min) - dummy->pcm_hw.channels_min = m->channels_min; - if (m->channels_max) - dummy->pcm_hw.channels_max = m->channels_max; - } - - err = snd_card_dummy_new_mixer(dummy); - if (err < 0) - goto __nodev; - strcpy(card->driver, "Dummy"); - strcpy(card->shortname, "Dummy"); - sprintf(card->longname, "Dummy %i", dev + 1); - - dummy_proc_init(dummy); - - snd_card_set_dev(card, &devptr->dev); - - err = snd_card_register(card); - if (err == 0) { - platform_set_drvdata(devptr, card); - return 0; - } - __nodev: - snd_card_free(card); - return err; -} - -static int __devexit snd_dummy_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct snd_dummy *dummy = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(dummy->pcm); - return 0; -} - -static int snd_dummy_resume(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -#define SND_DUMMY_DRIVER "snd_dummy" - -static struct platform_driver snd_dummy_driver = { - .probe = snd_dummy_probe, - .remove = __devexit_p(snd_dummy_remove), -#ifdef CONFIG_PM - .suspend = snd_dummy_suspend, - .resume = snd_dummy_resume, -#endif - .driver = { - .name = SND_DUMMY_DRIVER - }, -}; - -static void snd_dummy_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_dummy_driver); - free_fake_buffer(); -} - -static int __init alsa_card_dummy_init(void) -{ - int i, cards, err; - - err = platform_driver_register(&snd_dummy_driver); - if (err < 0) - return err; - - err = alloc_fake_buffer(); - if (err < 0) { - platform_driver_unregister(&snd_dummy_driver); - return err; - } - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_DUMMY_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "Dummy soundcard not found or device busy\n"); -#endif - snd_dummy_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_dummy_exit(void) -{ - snd_dummy_unregister_all(); -} - -module_init(alsa_card_dummy_init) -module_exit(alsa_card_dummy_exit) diff --git a/ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c b/ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c deleted file mode 100644 index 6c83b1ae..00000000 --- a/ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* - * ALSA driver for Xilinx ML403 AC97 Controller Reference - * IP: opb_ac97_controller_ref_v1_00_a (EDK 8.1i) - * IP: opb_ac97_controller_ref_v1_00_a (EDK 9.1i) - * - * Copyright (c) by 2007 Joachim Foerster <JOFT@gmx.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* Some notes / status of this driver: - * - * - Don't wonder about some strange implementations of things - especially the - * (heavy) shadowing of codec registers, with which I tried to reduce read - * accesses to a minimum, because after a variable amount of accesses, the AC97 - * controller doesn't raise the register access finished bit anymore ... - * - * - Playback support seems to be pretty stable - no issues here. - * - Capture support "works" now, too. Overruns don't happen any longer so often. - * But there might still be some ... - */ - -#include <linux/init.h> -#include <linux/module.h> - -#include <linux/platform_device.h> - -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/interrupt.h> - -/* HZ */ -#include <linux/param.h> -/* jiffies, time_*() */ -#include <linux/jiffies.h> -/* schedule_timeout*() */ -#include <linux/sched.h> -/* spin_lock*() */ -#include <linux/spinlock.h> -/* struct mutex, mutex_init(), mutex_*lock() */ -#include <linux/mutex.h> - -/* snd_printk(), snd_printd() */ -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/initval.h> -#include <sound/ac97_codec.h> - -#include "pcm-indirect2.h" - - -#define SND_ML403_AC97CR_DRIVER "ml403-ac97cr" - -MODULE_AUTHOR("Joachim Foerster <JOFT@gmx.de>"); -MODULE_DESCRIPTION("Xilinx ML403 AC97 Controller Reference"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Xilinx,ML403 AC97 Controller Reference}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ML403 AC97 Controller Reference."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ML403 AC97 Controller Reference."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this ML403 AC97 Controller Reference."); - -/* Special feature options */ -/*#define CODEC_WRITE_CHECK_RAF*/ /* don't return after a write to a codec - * register, while RAF bit is not set - */ -/* Debug options for code which may be removed completely in a final version */ -#ifdef CONFIG_SND_DEBUG -/*#define CODEC_STAT*/ /* turn on some minimal "statistics" - * about codec register usage - */ -#define SND_PCM_INDIRECT2_STAT /* turn on some "statistics" about the - * process of copying bytes from the - * intermediate buffer to the hardware - * fifo and the other way round - */ -#endif - -/* Definition of a "level/facility dependent" printk(); may be removed - * completely in a final version - */ -#undef PDEBUG -#ifdef CONFIG_SND_DEBUG -/* "facilities" for PDEBUG */ -#define UNKNOWN (1<<0) -#define CODEC_SUCCESS (1<<1) -#define CODEC_FAKE (1<<2) -#define INIT_INFO (1<<3) -#define INIT_FAILURE (1<<4) -#define WORK_INFO (1<<5) -#define WORK_FAILURE (1<<6) - -#define PDEBUG_FACILITIES (UNKNOWN | INIT_FAILURE | WORK_FAILURE) - -#define PDEBUG(fac, fmt, args...) do { \ - if (fac & PDEBUG_FACILITIES) \ - snd_printd(KERN_DEBUG SND_ML403_AC97CR_DRIVER ": " \ - fmt, ##args); \ - } while (0) -#else -#define PDEBUG(fac, fmt, args...) /* nothing */ -#endif - - - -/* Defines for "waits"/timeouts (portions of HZ=250 on arch/ppc by default) */ -#define CODEC_TIMEOUT_ON_INIT 5 /* timeout for checking for codec - * readiness (after insmod) - */ -#ifndef CODEC_WRITE_CHECK_RAF -#define CODEC_WAIT_AFTER_WRITE 100 /* general, static wait after a write - * access to a codec register, may be - * 0 to completely remove wait - */ -#else -#define CODEC_TIMEOUT_AFTER_WRITE 5 /* timeout after a write access to a - * codec register, if RAF bit is used - */ -#endif -#define CODEC_TIMEOUT_AFTER_READ 5 /* timeout after a read access to a - * codec register (checking RAF bit) - */ - -/* Infrastructure for codec register shadowing */ -#define LM4550_REG_OK (1<<0) /* register exists */ -#define LM4550_REG_DONEREAD (1<<1) /* read register once, value should be - * the same currently in the register - */ -#define LM4550_REG_NOSAVE (1<<2) /* values written to this register will - * not be saved in the register - */ -#define LM4550_REG_NOSHADOW (1<<3) /* don't do register shadowing, use plain - * hardware access - */ -#define LM4550_REG_READONLY (1<<4) /* register is read only */ -#define LM4550_REG_FAKEPROBE (1<<5) /* fake write _and_ read actions during - * probe() correctly - */ -#define LM4550_REG_FAKEREAD (1<<6) /* fake read access, always return - * default value - */ -#define LM4550_REG_ALLFAKE (LM4550_REG_FAKEREAD | LM4550_REG_FAKEPROBE) - -struct lm4550_reg { - u16 value; - u16 flag; - u16 wmask; - u16 def; -}; - -struct lm4550_reg lm4550_regfile[64] = { - [AC97_RESET / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_NOSAVE \ - | LM4550_REG_FAKEREAD, - .def = 0x0D50}, - [AC97_MASTER / 2] = {.flag = LM4550_REG_OK - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8000}, - [AC97_HEADPHONE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8000}, - [AC97_MASTER_MONO / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x801F, - .def = 0x8000}, - [AC97_PC_BEEP / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x801E, - .def = 0x0}, - [AC97_PHONE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x801F, - .def = 0x8008}, - [AC97_MIC / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x805F, - .def = 0x8008}, - [AC97_LINE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_CD / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_VIDEO / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_AUX / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_PCM / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8008}, - [AC97_REC_SEL / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x707, - .def = 0x0}, - [AC97_REC_GAIN / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x8F0F, - .def = 0x8000}, - [AC97_GENERAL_PURPOSE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .def = 0x0, - .wmask = 0xA380}, - [AC97_3D_CONTROL / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEREAD \ - | LM4550_REG_READONLY, - .def = 0x0101}, - [AC97_POWERDOWN / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_NOSHADOW \ - | LM4550_REG_NOSAVE, - .wmask = 0xFF00}, - /* may not write ones to - * REF/ANL/DAC/ADC bits - * FIXME: Is this ok? - */ - [AC97_EXTENDED_ID / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEREAD \ - | LM4550_REG_READONLY, - .def = 0x0201}, /* primary codec */ - [AC97_EXTENDED_STATUS / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_NOSHADOW \ - | LM4550_REG_NOSAVE, - .wmask = 0x1}, - [AC97_PCM_FRONT_DAC_RATE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .def = 0xBB80, - .wmask = 0xFFFF}, - [AC97_PCM_LR_ADC_RATE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .def = 0xBB80, - .wmask = 0xFFFF}, - [AC97_VENDOR_ID1 / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_READONLY \ - | LM4550_REG_FAKEREAD, - .def = 0x4E53}, - [AC97_VENDOR_ID2 / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_READONLY \ - | LM4550_REG_FAKEREAD, - .def = 0x4350} -}; - -#define LM4550_RF_OK(reg) (lm4550_regfile[reg / 2].flag & LM4550_REG_OK) - -static void lm4550_regfile_init(void) -{ - int i; - for (i = 0; i < 64; i++) - if (lm4550_regfile[i].flag & LM4550_REG_FAKEPROBE) - lm4550_regfile[i].value = lm4550_regfile[i].def; -} - -static void lm4550_regfile_write_values_after_init(struct snd_ac97 *ac97) -{ - int i; - for (i = 0; i < 64; i++) - if ((lm4550_regfile[i].flag & LM4550_REG_FAKEPROBE) && - (lm4550_regfile[i].value != lm4550_regfile[i].def)) { - PDEBUG(CODEC_FAKE, "lm4550_regfile_write_values_after_" - "init(): reg=0x%x value=0x%x / %d is different " - "from def=0x%x / %d\n", - i, lm4550_regfile[i].value, - lm4550_regfile[i].value, lm4550_regfile[i].def, - lm4550_regfile[i].def); - snd_ac97_write(ac97, i * 2, lm4550_regfile[i].value); - lm4550_regfile[i].flag |= LM4550_REG_DONEREAD; - } -} - - -/* direct registers */ -#define CR_REG(ml403_ac97cr, x) ((ml403_ac97cr)->port + CR_REG_##x) - -#define CR_REG_PLAYFIFO 0x00 -#define CR_PLAYDATA(a) ((a) & 0xFFFF) - -#define CR_REG_RECFIFO 0x04 -#define CR_RECDATA(a) ((a) & 0xFFFF) - -#define CR_REG_STATUS 0x08 -#define CR_RECOVER (1<<7) -#define CR_PLAYUNDER (1<<6) -#define CR_CODECREADY (1<<5) -#define CR_RAF (1<<4) -#define CR_RECEMPTY (1<<3) -#define CR_RECFULL (1<<2) -#define CR_PLAYHALF (1<<1) -#define CR_PLAYFULL (1<<0) - -#define CR_REG_RESETFIFO 0x0C -#define CR_RECRESET (1<<1) -#define CR_PLAYRESET (1<<0) - -#define CR_REG_CODEC_ADDR 0x10 -/* UG082 says: - * #define CR_CODEC_ADDR(a) ((a) << 1) - * #define CR_CODEC_READ (1<<0) - * #define CR_CODEC_WRITE (0<<0) - */ -/* RefDesign example says: */ -#define CR_CODEC_ADDR(a) ((a) << 0) -#define CR_CODEC_READ (1<<7) -#define CR_CODEC_WRITE (0<<7) - -#define CR_REG_CODEC_DATAREAD 0x14 -#define CR_CODEC_DATAREAD(v) ((v) & 0xFFFF) - -#define CR_REG_CODEC_DATAWRITE 0x18 -#define CR_CODEC_DATAWRITE(v) ((v) & 0xFFFF) - -#define CR_FIFO_SIZE 32 - -struct snd_ml403_ac97cr { - /* lock for access to (controller) registers */ - spinlock_t reg_lock; - /* mutex for the whole sequence of accesses to (controller) registers - * which affect codec registers - */ - struct mutex cdc_mutex; - - int irq; /* for playback */ - int enable_irq; /* for playback */ - - int capture_irq; - int enable_capture_irq; - - struct resource *res_port; - void *port; - - struct snd_ac97 *ac97; - int ac97_fake; -#ifdef CODEC_STAT - int ac97_read; - int ac97_write; -#endif - - struct platform_device *pfdev; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - - struct snd_pcm_indirect2 ind_rec; /* for playback */ - struct snd_pcm_indirect2 capture_ind2_rec; -}; - -static struct snd_pcm_hardware snd_ml403_ac97cr_playback = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000), - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = CR_FIFO_SIZE/2, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = (128*1024)/(CR_FIFO_SIZE/2), - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ml403_ac97cr_capture = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000), - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = CR_FIFO_SIZE/2, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = (128*1024)/(CR_FIFO_SIZE/2), - .fifo_size = 0, -}; - -static size_t -snd_ml403_ac97cr_playback_ind2_zero(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int copied_words = 0; - u32 full = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - spin_lock(&ml403_ac97cr->reg_lock); - while ((full = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_PLAYFULL)) != CR_PLAYFULL) { - out_be32(CR_REG(ml403_ac97cr, PLAYFIFO), 0); - copied_words++; - } - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static size_t -snd_ml403_ac97cr_playback_ind2_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - size_t bytes) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - u16 *src; - int copied_words = 0; - u32 full = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - src = (u16 *)(substream->runtime->dma_area + rec->sw_data); - - spin_lock(&ml403_ac97cr->reg_lock); - while (((full = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_PLAYFULL)) != CR_PLAYFULL) && (bytes > 1)) { - out_be32(CR_REG(ml403_ac97cr, PLAYFIFO), - CR_PLAYDATA(src[copied_words])); - copied_words++; - bytes = bytes - 2; - } - if (full != CR_PLAYFULL) - rec->hw_ready = 1; - else - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static size_t -snd_ml403_ac97cr_capture_ind2_null(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int copied_words = 0; - u32 empty = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - spin_lock(&ml403_ac97cr->reg_lock); - while ((empty = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RECEMPTY)) != CR_RECEMPTY) { - volatile u32 trash; - - trash = CR_RECDATA(in_be32(CR_REG(ml403_ac97cr, RECFIFO))); - /* Hmmmm, really necessary? Don't want call to in_be32() - * to be optimised away! - */ - trash++; - copied_words++; - } - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static size_t -snd_ml403_ac97cr_capture_ind2_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, size_t bytes) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - u16 *dst; - int copied_words = 0; - u32 empty = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - dst = (u16 *)(substream->runtime->dma_area + rec->sw_data); - - spin_lock(&ml403_ac97cr->reg_lock); - while (((empty = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RECEMPTY)) != CR_RECEMPTY) && (bytes > 1)) { - dst[copied_words] = CR_RECDATA(in_be32(CR_REG(ml403_ac97cr, - RECFIFO))); - copied_words++; - bytes = bytes - 2; - } - if (empty != CR_RECEMPTY) - rec->hw_ready = 1; - else - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static snd_pcm_uframes_t -snd_ml403_ac97cr_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_indirect2 *ind2_rec = NULL; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - if (substream == ml403_ac97cr->playback_substream) - ind2_rec = &ml403_ac97cr->ind_rec; - if (substream == ml403_ac97cr->capture_substream) - ind2_rec = &ml403_ac97cr->capture_ind2_rec; - - if (ind2_rec != NULL) - return snd_pcm_indirect2_pointer(substream, ind2_rec); - return (snd_pcm_uframes_t) 0; -} - -static int -snd_ml403_ac97cr_pcm_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int err = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - PDEBUG(WORK_INFO, "trigger(playback): START\n"); - ml403_ac97cr->ind_rec.hw_ready = 1; - - /* clear play FIFO */ - out_be32(CR_REG(ml403_ac97cr, RESETFIFO), CR_PLAYRESET); - - /* enable play irq */ - ml403_ac97cr->enable_irq = 1; - enable_irq(ml403_ac97cr->irq); - break; - case SNDRV_PCM_TRIGGER_STOP: - PDEBUG(WORK_INFO, "trigger(playback): STOP\n"); - ml403_ac97cr->ind_rec.hw_ready = 0; -#ifdef SND_PCM_INDIRECT2_STAT - snd_pcm_indirect2_stat(substream, &ml403_ac97cr->ind_rec); -#endif - /* disable play irq */ - disable_irq_nosync(ml403_ac97cr->irq); - ml403_ac97cr->enable_irq = 0; - break; - default: - err = -EINVAL; - break; - } - PDEBUG(WORK_INFO, "trigger(playback): (done)\n"); - return err; -} - -static int -snd_ml403_ac97cr_pcm_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int err = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - PDEBUG(WORK_INFO, "trigger(capture): START\n"); - ml403_ac97cr->capture_ind2_rec.hw_ready = 0; - - /* clear record FIFO */ - out_be32(CR_REG(ml403_ac97cr, RESETFIFO), CR_RECRESET); - - /* enable record irq */ - ml403_ac97cr->enable_capture_irq = 1; - enable_irq(ml403_ac97cr->capture_irq); - break; - case SNDRV_PCM_TRIGGER_STOP: - PDEBUG(WORK_INFO, "trigger(capture): STOP\n"); - ml403_ac97cr->capture_ind2_rec.hw_ready = 0; -#ifdef SND_PCM_INDIRECT2_STAT - snd_pcm_indirect2_stat(substream, - &ml403_ac97cr->capture_ind2_rec); -#endif - /* disable capture irq */ - disable_irq_nosync(ml403_ac97cr->capture_irq); - ml403_ac97cr->enable_capture_irq = 0; - break; - default: - err = -EINVAL; - break; - } - PDEBUG(WORK_INFO, "trigger(capture): (done)\n"); - return err; -} - -static int -snd_ml403_ac97cr_pcm_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, - "prepare(): period_bytes=%d, minperiod_bytes=%d\n", - snd_pcm_lib_period_bytes(substream), CR_FIFO_SIZE / 2); - - /* set sampling rate */ - snd_ac97_set_rate(ml403_ac97cr->ac97, AC97_PCM_FRONT_DAC_RATE, - runtime->rate); - PDEBUG(WORK_INFO, "prepare(): rate=%d\n", runtime->rate); - - /* init struct for intermediate buffer */ - memset(&ml403_ac97cr->ind_rec, 0, - sizeof(struct snd_pcm_indirect2)); - ml403_ac97cr->ind_rec.hw_buffer_size = CR_FIFO_SIZE; - ml403_ac97cr->ind_rec.sw_buffer_size = - snd_pcm_lib_buffer_bytes(substream); - ml403_ac97cr->ind_rec.min_periods = -1; - ml403_ac97cr->ind_rec.min_multiple = - snd_pcm_lib_period_bytes(substream) / (CR_FIFO_SIZE / 2); - PDEBUG(WORK_INFO, "prepare(): hw_buffer_size=%d, " - "sw_buffer_size=%d, min_multiple=%d\n", - CR_FIFO_SIZE, ml403_ac97cr->ind_rec.sw_buffer_size, - ml403_ac97cr->ind_rec.min_multiple); - return 0; -} - -static int -snd_ml403_ac97cr_pcm_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, - "prepare(capture): period_bytes=%d, minperiod_bytes=%d\n", - snd_pcm_lib_period_bytes(substream), CR_FIFO_SIZE / 2); - - /* set sampling rate */ - snd_ac97_set_rate(ml403_ac97cr->ac97, AC97_PCM_LR_ADC_RATE, - runtime->rate); - PDEBUG(WORK_INFO, "prepare(capture): rate=%d\n", runtime->rate); - - /* init struct for intermediate buffer */ - memset(&ml403_ac97cr->capture_ind2_rec, 0, - sizeof(struct snd_pcm_indirect2)); - ml403_ac97cr->capture_ind2_rec.hw_buffer_size = CR_FIFO_SIZE; - ml403_ac97cr->capture_ind2_rec.sw_buffer_size = - snd_pcm_lib_buffer_bytes(substream); - ml403_ac97cr->capture_ind2_rec.min_multiple = - snd_pcm_lib_period_bytes(substream) / (CR_FIFO_SIZE / 2); - PDEBUG(WORK_INFO, "prepare(capture): hw_buffer_size=%d, " - "sw_buffer_size=%d, min_multiple=%d\n", CR_FIFO_SIZE, - ml403_ac97cr->capture_ind2_rec.sw_buffer_size, - ml403_ac97cr->capture_ind2_rec.min_multiple); - return 0; -} - -static int snd_ml403_ac97cr_hw_free(struct snd_pcm_substream *substream) -{ - PDEBUG(WORK_INFO, "hw_free()\n"); - return snd_pcm_lib_free_pages(substream); -} - -static int -snd_ml403_ac97cr_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - PDEBUG(WORK_INFO, "hw_params(): desired buffer bytes=%d, desired " - "period bytes=%d\n", - params_buffer_bytes(hw_params), params_period_bytes(hw_params)); - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int snd_ml403_ac97cr_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, "open(playback)\n"); - ml403_ac97cr->playback_substream = substream; - runtime->hw = snd_ml403_ac97cr_playback; - - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - CR_FIFO_SIZE / 2); - return 0; -} - -static int snd_ml403_ac97cr_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, "open(capture)\n"); - ml403_ac97cr->capture_substream = substream; - runtime->hw = snd_ml403_ac97cr_capture; - - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - CR_FIFO_SIZE / 2); - return 0; -} - -static int snd_ml403_ac97cr_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - PDEBUG(WORK_INFO, "close(playback)\n"); - ml403_ac97cr->playback_substream = NULL; - return 0; -} - -static int snd_ml403_ac97cr_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - PDEBUG(WORK_INFO, "close(capture)\n"); - ml403_ac97cr->capture_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_ml403_ac97cr_playback_ops = { - .open = snd_ml403_ac97cr_playback_open, - .close = snd_ml403_ac97cr_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ml403_ac97cr_hw_params, - .hw_free = snd_ml403_ac97cr_hw_free, - .prepare = snd_ml403_ac97cr_pcm_playback_prepare, - .trigger = snd_ml403_ac97cr_pcm_playback_trigger, - .pointer = snd_ml403_ac97cr_pcm_pointer, -}; - -static struct snd_pcm_ops snd_ml403_ac97cr_capture_ops = { - .open = snd_ml403_ac97cr_capture_open, - .close = snd_ml403_ac97cr_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ml403_ac97cr_hw_params, - .hw_free = snd_ml403_ac97cr_hw_free, - .prepare = snd_ml403_ac97cr_pcm_capture_prepare, - .trigger = snd_ml403_ac97cr_pcm_capture_trigger, - .pointer = snd_ml403_ac97cr_pcm_pointer, -}; - -static irqreturn_t snd_ml403_ac97cr_irq(int irq, void *dev_id) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct platform_device *pfdev; - int cmp_irq; - - ml403_ac97cr = (struct snd_ml403_ac97cr *)dev_id; - if (ml403_ac97cr == NULL) - return IRQ_NONE; - - pfdev = ml403_ac97cr->pfdev; - - /* playback interrupt */ - cmp_irq = platform_get_irq(pfdev, 0); - if (irq == cmp_irq) { - if (ml403_ac97cr->enable_irq) - snd_pcm_indirect2_playback_interrupt( - ml403_ac97cr->playback_substream, - &ml403_ac97cr->ind_rec, - snd_ml403_ac97cr_playback_ind2_copy, - snd_ml403_ac97cr_playback_ind2_zero); - else - goto __disable_irq; - } else { - /* record interrupt */ - cmp_irq = platform_get_irq(pfdev, 1); - if (irq == cmp_irq) { - if (ml403_ac97cr->enable_capture_irq) - snd_pcm_indirect2_capture_interrupt( - ml403_ac97cr->capture_substream, - &ml403_ac97cr->capture_ind2_rec, - snd_ml403_ac97cr_capture_ind2_copy, - snd_ml403_ac97cr_capture_ind2_null); - else - goto __disable_irq; - } else - return IRQ_NONE; - } - return IRQ_HANDLED; - -__disable_irq: - PDEBUG(INIT_INFO, "irq(): irq %d is meant to be disabled! So, now try " - "to disable it _really_!\n", irq); - disable_irq_nosync(irq); - return IRQ_HANDLED; -} - -static unsigned short -snd_ml403_ac97cr_codec_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = ac97->private_data; -#ifdef CODEC_STAT - u32 stat; - u32 rafaccess = 0; -#endif - unsigned long end_time; - u16 value = 0; - - if (!LM4550_RF_OK(reg)) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "access to unknown/unused codec register 0x%x " - "ignored!\n", reg); - return 0; - } - /* check if we can fake/answer this access from our shadow register */ - if ((lm4550_regfile[reg / 2].flag & - (LM4550_REG_DONEREAD | LM4550_REG_ALLFAKE)) && - !(lm4550_regfile[reg / 2].flag & LM4550_REG_NOSHADOW)) { - if (lm4550_regfile[reg / 2].flag & LM4550_REG_FAKEREAD) { - PDEBUG(CODEC_FAKE, "codec_read(): faking read from " - "reg=0x%x, val=0x%x / %d\n", - reg, lm4550_regfile[reg / 2].def, - lm4550_regfile[reg / 2].def); - return lm4550_regfile[reg / 2].def; - } else if ((lm4550_regfile[reg / 2].flag & - LM4550_REG_FAKEPROBE) && - ml403_ac97cr->ac97_fake) { - PDEBUG(CODEC_FAKE, "codec_read(): faking read from " - "reg=0x%x, val=0x%x / %d (probe)\n", - reg, lm4550_regfile[reg / 2].value, - lm4550_regfile[reg / 2].value); - return lm4550_regfile[reg / 2].value; - } else { -#ifdef CODEC_STAT - PDEBUG(CODEC_FAKE, "codec_read(): read access " - "answered by shadow register 0x%x (value=0x%x " - "/ %d) (cw=%d cr=%d)\n", - reg, lm4550_regfile[reg / 2].value, - lm4550_regfile[reg / 2].value, - ml403_ac97cr->ac97_write, - ml403_ac97cr->ac97_read); -#else - PDEBUG(CODEC_FAKE, "codec_read(): read access " - "answered by shadow register 0x%x (value=0x%x " - "/ %d)\n", - reg, lm4550_regfile[reg / 2].value, - lm4550_regfile[reg / 2].value); -#endif - return lm4550_regfile[reg / 2].value; - } - } - /* if we are here, we _have_ to access the codec really, no faking */ - if (mutex_lock_interruptible(&ml403_ac97cr->cdc_mutex) != 0) - return 0; -#ifdef CODEC_STAT - ml403_ac97cr->ac97_read++; -#endif - spin_lock(&ml403_ac97cr->reg_lock); - out_be32(CR_REG(ml403_ac97cr, CODEC_ADDR), - CR_CODEC_ADDR(reg) | CR_CODEC_READ); - spin_unlock(&ml403_ac97cr->reg_lock); - end_time = jiffies + (HZ / CODEC_TIMEOUT_AFTER_READ); - do { - spin_lock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_STAT - rafaccess++; - stat = in_be32(CR_REG(ml403_ac97cr, STATUS)); - if ((stat & CR_RAF) == CR_RAF) { - value = CR_CODEC_DATAREAD( - in_be32(CR_REG(ml403_ac97cr, CODEC_DATAREAD))); - PDEBUG(CODEC_SUCCESS, "codec_read(): (done) reg=0x%x, " - "value=0x%x / %d (STATUS=0x%x)\n", - reg, value, value, stat); -#else - if ((in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RAF) == CR_RAF) { - value = CR_CODEC_DATAREAD( - in_be32(CR_REG(ml403_ac97cr, CODEC_DATAREAD))); - PDEBUG(CODEC_SUCCESS, "codec_read(): (done) " - "reg=0x%x, value=0x%x / %d\n", - reg, value, value); -#endif - lm4550_regfile[reg / 2].value = value; - lm4550_regfile[reg / 2].flag |= LM4550_REG_DONEREAD; - spin_unlock(&ml403_ac97cr->reg_lock); - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return value; - } - spin_unlock(&ml403_ac97cr->reg_lock); - schedule_timeout_uninterruptible(1); - } while (time_after(end_time, jiffies)); - /* read the DATAREAD register anyway, see comment below */ - spin_lock(&ml403_ac97cr->reg_lock); - value = - CR_CODEC_DATAREAD(in_be32(CR_REG(ml403_ac97cr, CODEC_DATAREAD))); - spin_unlock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_STAT - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec read! " - "(reg=0x%x, last STATUS=0x%x, DATAREAD=0x%x / %d, %d) " - "(cw=%d, cr=%d)\n", - reg, stat, value, value, rafaccess, - ml403_ac97cr->ac97_write, ml403_ac97cr->ac97_read); -#else - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec read! " - "(reg=0x%x, DATAREAD=0x%x / %d)\n", - reg, value, value); -#endif - /* BUG: This is PURE speculation! But after _most_ read timeouts the - * value in the register is ok! - */ - lm4550_regfile[reg / 2].value = value; - lm4550_regfile[reg / 2].flag |= LM4550_REG_DONEREAD; - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return value; -} - -static void -snd_ml403_ac97cr_codec_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = ac97->private_data; - -#ifdef CODEC_STAT - u32 stat; - u32 rafaccess = 0; -#endif -#ifdef CODEC_WRITE_CHECK_RAF - unsigned long end_time; -#endif - - if (!LM4550_RF_OK(reg)) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "access to unknown/unused codec register 0x%x " - "ignored!\n", reg); - return; - } - if (lm4550_regfile[reg / 2].flag & LM4550_REG_READONLY) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "write access to read only codec register 0x%x " - "ignored!\n", reg); - return; - } - if ((val & lm4550_regfile[reg / 2].wmask) != val) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "write access to codec register 0x%x " - "with bad value 0x%x / %d!\n", - reg, val, val); - val = val & lm4550_regfile[reg / 2].wmask; - } - if (((lm4550_regfile[reg / 2].flag & LM4550_REG_FAKEPROBE) && - ml403_ac97cr->ac97_fake) && - !(lm4550_regfile[reg / 2].flag & LM4550_REG_NOSHADOW)) { - PDEBUG(CODEC_FAKE, "codec_write(): faking write to reg=0x%x, " - "val=0x%x / %d\n", reg, val, val); - lm4550_regfile[reg / 2].value = (val & - lm4550_regfile[reg / 2].wmask); - return; - } - if (mutex_lock_interruptible(&ml403_ac97cr->cdc_mutex) != 0) - return; -#ifdef CODEC_STAT - ml403_ac97cr->ac97_write++; -#endif - spin_lock(&ml403_ac97cr->reg_lock); - out_be32(CR_REG(ml403_ac97cr, CODEC_DATAWRITE), - CR_CODEC_DATAWRITE(val)); - out_be32(CR_REG(ml403_ac97cr, CODEC_ADDR), - CR_CODEC_ADDR(reg) | CR_CODEC_WRITE); - spin_unlock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_WRITE_CHECK_RAF - /* check CR_CODEC_RAF bit to see if write access to register is done; - * loop until bit is set or timeout happens - */ - end_time = jiffies + HZ / CODEC_TIMEOUT_AFTER_WRITE; - do { - spin_lock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_STAT - rafaccess++; - stat = in_be32(CR_REG(ml403_ac97cr, STATUS)) - if ((stat & CR_RAF) == CR_RAF) { -#else - if ((in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RAF) == CR_RAF) { -#endif - PDEBUG(CODEC_SUCCESS, "codec_write(): (done) " - "reg=0x%x, value=%d / 0x%x\n", - reg, val, val); - if (!(lm4550_regfile[reg / 2].flag & - LM4550_REG_NOSHADOW) && - !(lm4550_regfile[reg / 2].flag & - LM4550_REG_NOSAVE)) - lm4550_regfile[reg / 2].value = val; - lm4550_regfile[reg / 2].flag |= LM4550_REG_DONEREAD; - spin_unlock(&ml403_ac97cr->reg_lock); - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return; - } - spin_unlock(&ml403_ac97cr->reg_lock); - schedule_timeout_uninterruptible(1); - } while (time_after(end_time, jiffies)); -#ifdef CODEC_STAT - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec write " - "(reg=0x%x, val=0x%x / %d, last STATUS=0x%x, %d) " - "(cw=%d, cr=%d)\n", - reg, val, val, stat, rafaccess, ml403_ac97cr->ac97_write, - ml403_ac97cr->ac97_read); -#else - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec write (reg=0x%x, val=0x%x / %d)\n", - reg, val, val); -#endif -#else /* CODEC_WRITE_CHECK_RAF */ -#if CODEC_WAIT_AFTER_WRITE > 0 - /* officially, in AC97 spec there is no possibility for a AC97 - * controller to determine, if write access is done or not - so: How - * is Xilinx able to provide a RAF bit for write access? - * => very strange, thus just don't check RAF bit (compare with - * Xilinx's example app in EDK 8.1i) and wait - */ - schedule_timeout_uninterruptible(HZ / CODEC_WAIT_AFTER_WRITE); -#endif - PDEBUG(CODEC_SUCCESS, "codec_write(): (done) " - "reg=0x%x, value=%d / 0x%x (no RAF check)\n", - reg, val, val); -#endif - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return; -} - -static int __devinit -snd_ml403_ac97cr_chip_init(struct snd_ml403_ac97cr *ml403_ac97cr) -{ - unsigned long end_time; - PDEBUG(INIT_INFO, "chip_init():\n"); - end_time = jiffies + HZ / CODEC_TIMEOUT_ON_INIT; - do { - if (in_be32(CR_REG(ml403_ac97cr, STATUS)) & CR_CODECREADY) { - /* clear both hardware FIFOs */ - out_be32(CR_REG(ml403_ac97cr, RESETFIFO), - CR_RECRESET | CR_PLAYRESET); - PDEBUG(INIT_INFO, "chip_init(): (done)\n"); - return 0; - } - schedule_timeout_uninterruptible(1); - } while (time_after(end_time, jiffies)); - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "timeout while waiting for codec, " - "not ready!\n"); - return -EBUSY; -} - -static int snd_ml403_ac97cr_free(struct snd_ml403_ac97cr *ml403_ac97cr) -{ - PDEBUG(INIT_INFO, "free():\n"); - /* irq release */ - if (ml403_ac97cr->irq >= 0) - free_irq(ml403_ac97cr->irq, ml403_ac97cr); - if (ml403_ac97cr->capture_irq >= 0) - free_irq(ml403_ac97cr->capture_irq, ml403_ac97cr); - /* give back "port" */ - if (ml403_ac97cr->port != NULL) - iounmap(ml403_ac97cr->port); - kfree(ml403_ac97cr); - PDEBUG(INIT_INFO, "free(): (done)\n"); - return 0; -} - -static int snd_ml403_ac97cr_dev_free(struct snd_device *snddev) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = snddev->device_data; - PDEBUG(INIT_INFO, "dev_free():\n"); - return snd_ml403_ac97cr_free(ml403_ac97cr); -} - -static int __devinit -snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev, - struct snd_ml403_ac97cr **rml403_ac97cr) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_ml403_ac97cr_dev_free, - }; - struct resource *resource; - int irq; - - *rml403_ac97cr = NULL; - ml403_ac97cr = kzalloc(sizeof(*ml403_ac97cr), GFP_KERNEL); - if (ml403_ac97cr == NULL) - return -ENOMEM; - spin_lock_init(&ml403_ac97cr->reg_lock); - mutex_init(&ml403_ac97cr->cdc_mutex); - ml403_ac97cr->card = card; - ml403_ac97cr->pfdev = pfdev; - ml403_ac97cr->irq = -1; - ml403_ac97cr->enable_irq = 0; - ml403_ac97cr->capture_irq = -1; - ml403_ac97cr->enable_capture_irq = 0; - ml403_ac97cr->port = NULL; - ml403_ac97cr->res_port = NULL; - - PDEBUG(INIT_INFO, "Trying to reserve resources now ...\n"); - resource = platform_get_resource(pfdev, IORESOURCE_MEM, 0); - /* get "port" */ - ml403_ac97cr->port = ioremap_nocache(resource->start, - (resource->end) - - (resource->start) + 1); - if (ml403_ac97cr->port == NULL) { - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "unable to remap memory region (%pR)\n", - resource); - snd_ml403_ac97cr_free(ml403_ac97cr); - return -EBUSY; - } - snd_printk(KERN_INFO SND_ML403_AC97CR_DRIVER ": " - "remap controller memory region to " - "0x%x done\n", (unsigned int)ml403_ac97cr->port); - /* get irq */ - irq = platform_get_irq(pfdev, 0); - if (request_irq(irq, snd_ml403_ac97cr_irq, 0, - dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "unable to grab IRQ %d\n", - irq); - snd_ml403_ac97cr_free(ml403_ac97cr); - return -EBUSY; - } - ml403_ac97cr->irq = irq; - snd_printk(KERN_INFO SND_ML403_AC97CR_DRIVER ": " - "request (playback) irq %d done\n", - ml403_ac97cr->irq); - irq = platform_get_irq(pfdev, 1); - if (request_irq(irq, snd_ml403_ac97cr_irq, 0, - dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "unable to grab IRQ %d\n", - irq); - snd_ml403_ac97cr_free(ml403_ac97cr); - return -EBUSY; - } - ml403_ac97cr->capture_irq = irq; - snd_printk(KERN_INFO SND_ML403_AC97CR_DRIVER ": " - "request (capture) irq %d done\n", - ml403_ac97cr->capture_irq); - - err = snd_ml403_ac97cr_chip_init(ml403_ac97cr); - if (err < 0) { - snd_ml403_ac97cr_free(ml403_ac97cr); - return err; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ml403_ac97cr, &ops); - if (err < 0) { - PDEBUG(INIT_FAILURE, "probe(): snd_device_new() failed!\n"); - snd_ml403_ac97cr_free(ml403_ac97cr); - return err; - } - - *rml403_ac97cr = ml403_ac97cr; - return 0; -} - -static void snd_ml403_ac97cr_mixer_free(struct snd_ac97 *ac97) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = ac97->private_data; - PDEBUG(INIT_INFO, "mixer_free():\n"); - ml403_ac97cr->ac97 = NULL; - PDEBUG(INIT_INFO, "mixer_free(): (done)\n"); -} - -static int __devinit -snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr) -{ - struct snd_ac97_bus *bus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_ml403_ac97cr_codec_write, - .read = snd_ml403_ac97cr_codec_read, - }; - PDEBUG(INIT_INFO, "mixer():\n"); - err = snd_ac97_bus(ml403_ac97cr->card, 0, &ops, NULL, &bus); - if (err < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ml403_ac97cr->ac97_fake = 1; - lm4550_regfile_init(); -#ifdef CODEC_STAT - ml403_ac97cr->ac97_read = 0; - ml403_ac97cr->ac97_write = 0; -#endif - ac97.private_data = ml403_ac97cr; - ac97.private_free = snd_ml403_ac97cr_mixer_free; - ac97.scaps = AC97_SCAP_AUDIO | AC97_SCAP_SKIP_MODEM | - AC97_SCAP_NO_SPDIF; - err = snd_ac97_mixer(bus, &ac97, &ml403_ac97cr->ac97); - ml403_ac97cr->ac97_fake = 0; - lm4550_regfile_write_values_after_init(ml403_ac97cr->ac97); - PDEBUG(INIT_INFO, "mixer(): (done) snd_ac97_mixer()=%d\n", err); - return err; -} - -static int __devinit -snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device, - struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - err = snd_pcm_new(ml403_ac97cr->card, "ML403AC97CR/1", device, 1, 1, - &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_ml403_ac97cr_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_ml403_ac97cr_capture_ops); - pcm->private_data = ml403_ac97cr; - pcm->info_flags = 0; - strcpy(pcm->name, "ML403AC97CR DAC/ADC"); - ml403_ac97cr->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 64 * 1024, - 128 * 1024); - if (rpcm) - *rpcm = pcm; - return 0; -} - -static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev) -{ - struct snd_card *card; - struct snd_ml403_ac97cr *ml403_ac97cr = NULL; - int err; - int dev = pfdev->id; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) - return -ENOENT; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr); - if (err < 0) { - PDEBUG(INIT_FAILURE, "probe(): create failed!\n"); - snd_card_free(card); - return err; - } - PDEBUG(INIT_INFO, "probe(): create done\n"); - card->private_data = ml403_ac97cr; - err = snd_ml403_ac97cr_mixer(ml403_ac97cr); - if (err < 0) { - snd_card_free(card); - return err; - } - PDEBUG(INIT_INFO, "probe(): mixer done\n"); - err = snd_ml403_ac97cr_pcm(ml403_ac97cr, 0, NULL); - if (err < 0) { - snd_card_free(card); - return err; - } - PDEBUG(INIT_INFO, "probe(): PCM done\n"); - strcpy(card->driver, SND_ML403_AC97CR_DRIVER); - strcpy(card->shortname, "ML403 AC97 Controller Reference"); - sprintf(card->longname, "%s %s at 0x%lx, irq %i & %i, device %i", - card->shortname, card->driver, - (unsigned long)ml403_ac97cr->port, ml403_ac97cr->irq, - ml403_ac97cr->capture_irq, dev + 1); - - snd_card_set_dev(card, &pfdev->dev); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(pfdev, card); - PDEBUG(INIT_INFO, "probe(): (done)\n"); - return 0; -} - -static int snd_ml403_ac97cr_remove(struct platform_device *pfdev) -{ - snd_card_free(platform_get_drvdata(pfdev)); - platform_set_drvdata(pfdev, NULL); - return 0; -} - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:" SND_ML403_AC97CR_DRIVER); - -static struct platform_driver snd_ml403_ac97cr_driver = { - .probe = snd_ml403_ac97cr_probe, - .remove = snd_ml403_ac97cr_remove, - .driver = { - .name = SND_ML403_AC97CR_DRIVER, - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(snd_ml403_ac97cr_driver); diff --git a/ANDROID_3.4.5/sound/drivers/mpu401/Makefile b/ANDROID_3.4.5/sound/drivers/mpu401/Makefile deleted file mode 100644 index 918f83f3..00000000 --- a/ANDROID_3.4.5/sound/drivers/mpu401/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-mpu401-objs := mpu401.o -snd-mpu401-uart-objs := mpu401_uart.o - -obj-$(CONFIG_SND_MPU401_UART) += snd-mpu401-uart.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_MPU401) += snd-mpu401.o diff --git a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c b/ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c deleted file mode 100644 index 86f5fbc2..00000000 --- a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Driver for generic MPU-401 boards (UART mode only) - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr> - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/init.h> -#include <linux/pnp.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/mpu401.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("MPU-401 UART"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -#ifdef CONFIG_PNP -static bool pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ -static bool uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for MPU-401 device."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for MPU-401 device."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable MPU-401 device."); -#ifdef CONFIG_PNP -module_param_array(pnp, bool, NULL, 0444); -MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for MPU-401 device."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); -module_param_array(uart_enter, bool, NULL, 0444); -MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open."); - -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int pnp_registered; -static unsigned int snd_mpu401_devices; - -static int snd_mpu401_create(int dev, struct snd_card **rcard) -{ - struct snd_card *card; - int err; - - if (!uart_enter[dev]) - snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); - - *rcard = NULL; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - strcpy(card->driver, "MPU-401 UART"); - strcpy(card->shortname, card->driver); - sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); - if (irq[dev] >= 0) { - sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]); - } else { - strcat(card->longname, "polled"); - } - - err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, - irq[dev], NULL); - if (err < 0) { - printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); - goto _err; - } - - *rcard = card; - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devinit snd_mpu401_probe(struct platform_device *devptr) -{ - int dev = devptr->id; - int err; - struct snd_card *card; - - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify port\n"); - return -EINVAL; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "specify or disable IRQ\n"); - return -EINVAL; - } - err = snd_mpu401_create(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, &devptr->dev); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(devptr, card); - return 0; -} - -static int __devexit snd_mpu401_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_MPU401_DRIVER "snd_mpu401" - -static struct platform_driver snd_mpu401_driver = { - .probe = snd_mpu401_probe, - .remove = __devexit_p(snd_mpu401_remove), - .driver = { - .name = SND_MPU401_DRIVER - }, -}; - - -#ifdef CONFIG_PNP - -#define IO_EXTENT 2 - -static struct pnp_device_id snd_mpu401_pnpids[] = { - { .id = "PNPb006" }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); - -static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device, - const struct pnp_device_id *id) -{ - if (!pnp_port_valid(device, 0) || - pnp_port_flags(device, 0) & IORESOURCE_DISABLED) { - snd_printk(KERN_ERR "no PnP port\n"); - return -ENODEV; - } - if (pnp_port_len(device, 0) < IO_EXTENT) { - snd_printk(KERN_ERR "PnP port length is %llu, expected %d\n", - (unsigned long long)pnp_port_len(device, 0), - IO_EXTENT); - return -ENODEV; - } - port[dev] = pnp_port_start(device, 0); - - if (!pnp_irq_valid(device, 0) || - pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) { - snd_printk(KERN_WARNING "no PnP irq, using polling\n"); - irq[dev] = -1; - } else { - irq[dev] = pnp_irq(device, 0); - } - return 0; -} - -static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, - const struct pnp_device_id *id) -{ - static int dev; - struct snd_card *card; - int err; - - for ( ; dev < SNDRV_CARDS; ++dev) { - if (!enable[dev] || !pnp[dev]) - continue; - err = snd_mpu401_pnp(dev, pnp_dev, id); - if (err < 0) - return err; - err = snd_mpu401_create(dev, &card); - if (err < 0) - return err; - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pnp_dev->dev); - pnp_set_drvdata(pnp_dev, card); - snd_mpu401_devices++; - ++dev; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev) -{ - struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev); - - snd_card_disconnect(card); - snd_card_free_when_closed(card); -} - -static struct pnp_driver snd_mpu401_pnp_driver = { - .name = "mpu401", - .id_table = snd_mpu401_pnpids, - .probe = snd_mpu401_pnp_probe, - .remove = __devexit_p(snd_mpu401_pnp_remove), -}; -#else -static struct pnp_driver snd_mpu401_pnp_driver; -#endif - -static void snd_mpu401_unregister_all(void) -{ - int i; - - if (pnp_registered) - pnp_unregister_driver(&snd_mpu401_pnp_driver); - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_mpu401_driver); -} - -static int __init alsa_card_mpu401_init(void) -{ - int i, err; - - if ((err = platform_driver_register(&snd_mpu401_driver)) < 0) - return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; -#ifdef CONFIG_PNP - if (pnp[i]) - continue; -#endif - device = platform_device_register_simple(SND_MPU401_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - snd_mpu401_devices++; - } - err = pnp_register_driver(&snd_mpu401_pnp_driver); - if (!err) - pnp_registered = 1; - - if (!snd_mpu401_devices) { -#ifdef MODULE - printk(KERN_ERR "MPU-401 device not found or device busy\n"); -#endif - snd_mpu401_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_mpu401_exit(void) -{ - snd_mpu401_unregister_all(); -} - -module_init(alsa_card_mpu401_init) -module_exit(alsa_card_mpu401_exit) diff --git a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c b/ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c deleted file mode 100644 index 1cff331a..00000000 --- a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of MPU-401 in UART mode - * - * MPU-401 supports UART mode which is not capable generate transmit - * interrupts thus output is done via polling. Without interrupt, - * input is done also via polling. Do not expect good performance. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * 13-03-2003: - * Added support for different kind of hardware I/O. Build in choices - * are port and mmio. For other kind of I/O, set mpu->read and - * mpu->write to your own I/O functions. - * - */ - -#include <asm/io.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <sound/core.h> -#include <sound/mpu401.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode"); -MODULE_LICENSE("GPL"); - -static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu); -static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu); - -/* - - */ - -#define snd_mpu401_input_avail(mpu) \ - (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY)) -#define snd_mpu401_output_ready(mpu) \ - (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL)) - -/* Build in lowlevel io */ -static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, - unsigned long addr) -{ - outb(data, addr); -} - -static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, - unsigned long addr) -{ - return inb(addr); -} - -static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, - unsigned long addr) -{ - writeb(data, (void __iomem *)addr); -} - -static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, - unsigned long addr) -{ - return readb((void __iomem *)addr); -} -/* */ - -static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) -{ - int timeout = 100000; - for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--) - mpu->read(mpu, MPU401D(mpu)); -#ifdef CONFIG_SND_DEBUG - if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", - mpu->read(mpu, MPU401C(mpu))); -#endif -} - -static void uart_interrupt_tx(struct snd_mpu401 *mpu) -{ - unsigned long flags; - - if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && - test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { - spin_lock_irqsave(&mpu->output_lock, flags); - snd_mpu401_uart_output_write(mpu); - spin_unlock_irqrestore(&mpu->output_lock, flags); - } -} - -static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) -{ - unsigned long flags; - - if (mpu->info_flags & MPU401_INFO_INPUT) { - spin_lock_irqsave(&mpu->input_lock, flags); - if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) - snd_mpu401_uart_input_read(mpu); - else - snd_mpu401_uart_clear_rx(mpu); - spin_unlock_irqrestore(&mpu->input_lock, flags); - } - if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) - /* ok. for better Tx performance try do some output - when input is done */ - uart_interrupt_tx(mpu); -} - -/** - * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler - * @irq: the irq number - * @dev_id: mpu401 instance - * - * Processes the interrupt for MPU401-UART i/o. - */ -irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id) -{ - struct snd_mpu401 *mpu = dev_id; - - if (mpu == NULL) - return IRQ_NONE; - _snd_mpu401_uart_interrupt(mpu); - return IRQ_HANDLED; -} - -EXPORT_SYMBOL(snd_mpu401_uart_interrupt); - -/** - * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler - * @irq: the irq number - * @dev_id: mpu401 instance - * - * Processes the interrupt for MPU401-UART output. - */ -irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id) -{ - struct snd_mpu401 *mpu = dev_id; - - if (mpu == NULL) - return IRQ_NONE; - uart_interrupt_tx(mpu); - return IRQ_HANDLED; -} - -EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx); - -/* - * timer callback - * reprogram the timer and call the interrupt job - */ -static void snd_mpu401_uart_timer(unsigned long data) -{ - struct snd_mpu401 *mpu = (struct snd_mpu401 *)data; - unsigned long flags; - - spin_lock_irqsave(&mpu->timer_lock, flags); - /*mpu->mode |= MPU401_MODE_TIMER;*/ - mpu->timer.expires = 1 + jiffies; - add_timer(&mpu->timer); - spin_unlock_irqrestore(&mpu->timer_lock, flags); - if (mpu->rmidi) - _snd_mpu401_uart_interrupt(mpu); -} - -/* - * initialize the timer callback if not programmed yet - */ -static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) -{ - unsigned long flags; - - spin_lock_irqsave (&mpu->timer_lock, flags); - if (mpu->timer_invoked == 0) { - init_timer(&mpu->timer); - mpu->timer.data = (unsigned long)mpu; - mpu->timer.function = snd_mpu401_uart_timer; - mpu->timer.expires = 1 + jiffies; - add_timer(&mpu->timer); - } - mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : - MPU401_MODE_OUTPUT_TIMER; - spin_unlock_irqrestore (&mpu->timer_lock, flags); -} - -/* - * remove the timer callback if still active - */ -static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) -{ - unsigned long flags; - - spin_lock_irqsave (&mpu->timer_lock, flags); - if (mpu->timer_invoked) { - mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : - ~MPU401_MODE_OUTPUT_TIMER; - if (! mpu->timer_invoked) - del_timer(&mpu->timer); - } - spin_unlock_irqrestore (&mpu->timer_lock, flags); -} - -/* - * send a UART command - * return zero if successful, non-zero for some errors - */ - -static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, - int ack) -{ - unsigned long flags; - int timeout, ok; - - spin_lock_irqsave(&mpu->input_lock, flags); - if (mpu->hardware != MPU401_HW_TRID4DWAVE) { - mpu->write(mpu, 0x00, MPU401D(mpu)); - /*snd_mpu401_uart_clear_rx(mpu);*/ - } - /* ok. standard MPU-401 initialization */ - if (mpu->hardware != MPU401_HW_SB) { - for (timeout = 1000; timeout > 0 && - !snd_mpu401_output_ready(mpu); timeout--) - udelay(10); -#ifdef CONFIG_SND_DEBUG - if (!timeout) - snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n", - mpu->read(mpu, MPU401C(mpu))); -#endif - } - mpu->write(mpu, cmd, MPU401C(mpu)); - if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (snd_mpu401_input_avail(mpu)) { - if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) - ok = 1; - } - } - if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) - ok = 1; - } else - ok = 1; - spin_unlock_irqrestore(&mpu->input_lock, flags); - if (!ok) { - snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx " - "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port, - mpu->read(mpu, MPU401C(mpu)), - mpu->read(mpu, MPU401D(mpu))); - return 1; - } - return 0; -} - -static int snd_mpu401_do_reset(struct snd_mpu401 *mpu) -{ - if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) - return -EIO; - if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 0)) - return -EIO; - return 0; -} - -/* - * input/output open/close - protected by open_mutex in rawmidi.c - */ -static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err; - - mpu = substream->rmidi->private_data; - if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) - return err; - if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { - if (snd_mpu401_do_reset(mpu) < 0) - goto error_out; - } - mpu->substream_input = substream; - set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); - return 0; - -error_out: - if (mpu->open_input && mpu->close_input) - mpu->close_input(mpu); - return -EIO; -} - -static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err; - - mpu = substream->rmidi->private_data; - if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) - return err; - if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { - if (snd_mpu401_do_reset(mpu) < 0) - goto error_out; - } - mpu->substream_output = substream; - set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); - return 0; - -error_out: - if (mpu->open_output && mpu->close_output) - mpu->close_output(mpu); - return -EIO; -} - -static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err = 0; - - mpu = substream->rmidi->private_data; - clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); - mpu->substream_input = NULL; - if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) - err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); - if (mpu->close_input) - mpu->close_input(mpu); - if (err) - return -EIO; - return 0; -} - -static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err = 0; - - mpu = substream->rmidi->private_data; - clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); - mpu->substream_output = NULL; - if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) - err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); - if (mpu->close_output) - mpu->close_output(mpu); - if (err) - return -EIO; - return 0; -} - -/* - * trigger input callback - */ -static void -snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_mpu401 *mpu; - int max = 64; - - mpu = substream->rmidi->private_data; - if (up) { - if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) { - /* first time - flush FIFO */ - while (max-- > 0) - mpu->read(mpu, MPU401D(mpu)); - if (mpu->info_flags & MPU401_INFO_USE_TIMER) - snd_mpu401_uart_add_timer(mpu, 1); - } - - /* read data in advance */ - spin_lock_irqsave(&mpu->input_lock, flags); - snd_mpu401_uart_input_read(mpu); - spin_unlock_irqrestore(&mpu->input_lock, flags); - } else { - if (mpu->info_flags & MPU401_INFO_USE_TIMER) - snd_mpu401_uart_remove_timer(mpu, 1); - clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode); - } - -} - -/* - * transfer input pending data - * call with input_lock spinlock held - */ -static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu) -{ - int max = 128; - unsigned char byte; - - while (max-- > 0) { - if (! snd_mpu401_input_avail(mpu)) - break; /* input not available */ - byte = mpu->read(mpu, MPU401D(mpu)); - if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) - snd_rawmidi_receive(mpu->substream_input, &byte, 1); - } -} - -/* - * Tx FIFO sizes: - * CS4237B - 16 bytes - * AudioDrive ES1688 - 12 bytes - * S3 SonicVibes - 8 bytes - * SoundBlaster AWE 64 - 2 bytes (ugly hardware) - */ - -/* - * write output pending bytes - * call with output_lock spinlock held - */ -static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) -{ - unsigned char byte; - int max = 256; - - do { - if (snd_rawmidi_transmit_peek(mpu->substream_output, - &byte, 1) == 1) { - /* - * Try twice because there is hardware that insists on - * setting the output busy bit after each write. - */ - if (!snd_mpu401_output_ready(mpu) && - !snd_mpu401_output_ready(mpu)) - break; /* Tx FIFO full - try again later */ - mpu->write(mpu, byte, MPU401D(mpu)); - snd_rawmidi_transmit_ack(mpu->substream_output, 1); - } else { - snd_mpu401_uart_remove_timer (mpu, 0); - break; /* no other data - leave the tx loop */ - } - } while (--max > 0); -} - -/* - * output trigger callback - */ -static void -snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_mpu401 *mpu; - - mpu = substream->rmidi->private_data; - if (up) { - set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); - - /* try to add the timer at each output trigger, - * since the output timer might have been removed in - * snd_mpu401_uart_output_write(). - */ - if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) - snd_mpu401_uart_add_timer(mpu, 0); - - /* output pending data */ - spin_lock_irqsave(&mpu->output_lock, flags); - snd_mpu401_uart_output_write(mpu); - spin_unlock_irqrestore(&mpu->output_lock, flags); - } else { - if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) - snd_mpu401_uart_remove_timer(mpu, 0); - clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); - } -} - -/* - - */ - -static struct snd_rawmidi_ops snd_mpu401_uart_output = -{ - .open = snd_mpu401_uart_output_open, - .close = snd_mpu401_uart_output_close, - .trigger = snd_mpu401_uart_output_trigger, -}; - -static struct snd_rawmidi_ops snd_mpu401_uart_input = -{ - .open = snd_mpu401_uart_input_open, - .close = snd_mpu401_uart_input_close, - .trigger = snd_mpu401_uart_input_trigger, -}; - -static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) -{ - struct snd_mpu401 *mpu = rmidi->private_data; - if (mpu->irq >= 0) - free_irq(mpu->irq, (void *) mpu); - release_and_free_resource(mpu->res); - kfree(mpu); -} - -/** - * snd_mpu401_uart_new - create an MPU401-UART instance - * @card: the card instance - * @device: the device index, zero-based - * @hardware: the hardware type, MPU401_HW_XXXX - * @port: the base address of MPU401 port - * @info_flags: bitflags MPU401_INFO_XXX - * @irq: the ISA irq number, -1 if not to be allocated - * @rrawmidi: the pointer to store the new rawmidi instance - * - * Creates a new MPU-401 instance. - * - * Note that the rawmidi instance is returned on the rrawmidi argument, - * not the mpu401 instance itself. To access to the mpu401 instance, - * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast). - * - * Returns zero if successful, or a negative error code. - */ -int snd_mpu401_uart_new(struct snd_card *card, int device, - unsigned short hardware, - unsigned long port, - unsigned int info_flags, - int irq, - struct snd_rawmidi ** rrawmidi) -{ - struct snd_mpu401 *mpu; - struct snd_rawmidi *rmidi; - int in_enable, out_enable; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT))) - info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT; - in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0; - out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0; - if ((err = snd_rawmidi_new(card, "MPU-401U", device, - out_enable, in_enable, &rmidi)) < 0) - return err; - mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); - if (mpu == NULL) { - snd_printk(KERN_ERR "mpu401_uart: cannot allocate\n"); - snd_device_free(card, rmidi); - return -ENOMEM; - } - rmidi->private_data = mpu; - rmidi->private_free = snd_mpu401_uart_free; - spin_lock_init(&mpu->input_lock); - spin_lock_init(&mpu->output_lock); - spin_lock_init(&mpu->timer_lock); - mpu->hardware = hardware; - if (! (info_flags & MPU401_INFO_INTEGRATED)) { - int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; - mpu->res = request_region(port, res_size, "MPU401 UART"); - if (mpu->res == NULL) { - snd_printk(KERN_ERR "mpu401_uart: " - "unable to grab port 0x%lx size %d\n", - port, res_size); - snd_device_free(card, rmidi); - return -EBUSY; - } - } - if (info_flags & MPU401_INFO_MMIO) { - mpu->write = mpu401_write_mmio; - mpu->read = mpu401_read_mmio; - } else { - mpu->write = mpu401_write_port; - mpu->read = mpu401_read_port; - } - mpu->port = port; - if (hardware == MPU401_HW_PC98II) - mpu->cport = port + 2; - else - mpu->cport = port + 1; - if (irq >= 0) { - if (request_irq(irq, snd_mpu401_uart_interrupt, 0, - "MPU401 UART", (void *) mpu)) { - snd_printk(KERN_ERR "mpu401_uart: " - "unable to grab IRQ %d\n", irq); - snd_device_free(card, rmidi); - return -EBUSY; - } - } - if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK)) - info_flags |= MPU401_INFO_USE_TIMER; - mpu->info_flags = info_flags; - mpu->irq = irq; - if (card->shortname[0]) - snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", - card->shortname); - else - sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); - if (out_enable) { - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_mpu401_uart_output); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; - } - if (in_enable) { - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_mpu401_uart_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; - if (out_enable) - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; - } - mpu->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return 0; -} - -EXPORT_SYMBOL(snd_mpu401_uart_new); - -/* - * INIT part - */ - -static int __init alsa_mpu401_uart_init(void) -{ - return 0; -} - -static void __exit alsa_mpu401_uart_exit(void) -{ -} - -module_init(alsa_mpu401_uart_init) -module_exit(alsa_mpu401_uart_exit) diff --git a/ANDROID_3.4.5/sound/drivers/mtpav.c b/ANDROID_3.4.5/sound/drivers/mtpav.c deleted file mode 100644 index 76930793..00000000 --- a/ANDROID_3.4.5/sound/drivers/mtpav.c +++ /dev/null @@ -1,792 +0,0 @@ -/* - * MOTU Midi Timepiece ALSA Main routines - * Copyright by Michael T. Mayers (c) Jan 09, 2000 - * mail: michael@tweakoz.com - * Thanks to John Galbraith - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * This driver is for the 'Mark Of The Unicorn' (MOTU) - * MidiTimePiece AV multiport MIDI interface - * - * IOPORTS - * ------- - * 8 MIDI Ins and 8 MIDI outs - * Video Sync In (BNC), Word Sync Out (BNC), - * ADAT Sync Out (DB9) - * SMPTE in/out (1/4") - * 2 programmable pedal/footswitch inputs and 4 programmable MIDI controller knobs. - * Macintosh RS422 serial port - * RS422 "network" port for ganging multiple MTP's - * PC Parallel Port ( which this driver currently uses ) - * - * MISC FEATURES - * ------------- - * Hardware MIDI routing, merging, and filtering - * MIDI Synchronization to Video, ADAT, SMPTE and other Clock sources - * 128 'scene' memories, recallable from MIDI program change - * - * - * ChangeLog - * Jun 11 2001 Takashi Iwai <tiwai@suse.de> - * - Recoded & debugged - * - Added timer interrupt for midi outputs - * - hwports is between 1 and 8, which specifies the number of hardware ports. - * The three global ports, computer, adat and broadcast ports, are created - * always after h/w and remote ports. - * - */ - -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/moduleparam.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/rawmidi.h> -#include <linux/delay.h> - -/* - * globals - */ -MODULE_AUTHOR("Michael T. Mayers"); -MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{MOTU,MidiTimePiece AV multiport MIDI}}"); - -// io resources -#define MTPAV_IOBASE 0x378 -#define MTPAV_IRQ 7 -#define MTPAV_MAX_PORTS 8 - -static int index = SNDRV_DEFAULT_IDX1; -static char *id = SNDRV_DEFAULT_STR1; -static long port = MTPAV_IOBASE; /* 0x378, 0x278 */ -static int irq = MTPAV_IRQ; /* 7, 5 */ -static int hwports = MTPAV_MAX_PORTS; /* use hardware ports 1-8 */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI."); -module_param(port, long, 0444); -MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI."); -module_param(irq, int, 0444); -MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI."); -module_param(hwports, int, 0444); -MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI."); - -static struct platform_device *device; - -/* - * defines - */ -//#define USE_FAKE_MTP // don't actually read/write to MTP device (for debugging without an actual unit) (does not work yet) - -// parallel port usage masks -#define SIGS_BYTE 0x08 -#define SIGS_RFD 0x80 -#define SIGS_IRQ 0x40 -#define SIGS_IN0 0x10 -#define SIGS_IN1 0x20 - -#define SIGC_WRITE 0x04 -#define SIGC_READ 0x08 -#define SIGC_INTEN 0x10 - -#define DREG 0 -#define SREG 1 -#define CREG 2 - -// -#define MTPAV_MODE_INPUT_OPENED 0x01 -#define MTPAV_MODE_OUTPUT_OPENED 0x02 -#define MTPAV_MODE_INPUT_TRIGGERED 0x04 -#define MTPAV_MODE_OUTPUT_TRIGGERED 0x08 - -#define NUMPORTS (0x12+1) - - -/* - */ - -struct mtpav_port { - u8 number; - u8 hwport; - u8 mode; - u8 running_status; - struct snd_rawmidi_substream *input; - struct snd_rawmidi_substream *output; -}; - -struct mtpav { - struct snd_card *card; - unsigned long port; - struct resource *res_port; - int irq; /* interrupt (for inputs) */ - spinlock_t spinlock; - int share_irq; /* number of accesses to input interrupts */ - int istimer; /* number of accesses to timer interrupts */ - struct timer_list timer; /* timer interrupts for outputs */ - struct snd_rawmidi *rmidi; - int num_ports; /* number of hw ports (1-8) */ - struct mtpav_port ports[NUMPORTS]; /* all ports including computer, adat and bc */ - - u32 inmidiport; /* selected input midi port */ - u32 inmidistate; /* during midi command 0xf5 */ - - u32 outmidihwport; /* selected output midi hw port */ -}; - - -/* - * possible hardware ports (selected by 0xf5 port message) - * 0x00 all ports - * 0x01 .. 0x08 this MTP's ports 1..8 - * 0x09 .. 0x10 networked MTP's ports (9..16) - * 0x11 networked MTP's computer port - * 0x63 to ADAT - * - * mappig: - * subdevice 0 - (X-1) ports - * X - (2*X-1) networked ports - * X computer - * X+1 ADAT - * X+2 all ports - * - * where X = chip->num_ports - */ - -#define MTPAV_PIDX_COMPUTER 0 -#define MTPAV_PIDX_ADAT 1 -#define MTPAV_PIDX_BROADCAST 2 - - -static int translate_subdevice_to_hwport(struct mtpav *chip, int subdev) -{ - if (subdev < 0) - return 0x01; /* invalid - use port 0 as default */ - else if (subdev < chip->num_ports) - return subdev + 1; /* single mtp port */ - else if (subdev < chip->num_ports * 2) - return subdev - chip->num_ports + 0x09; /* remote port */ - else if (subdev == chip->num_ports * 2 + MTPAV_PIDX_COMPUTER) - return 0x11; /* computer port */ - else if (subdev == chip->num_ports + MTPAV_PIDX_ADAT) - return 0x63; /* ADAT */ - return 0; /* all ports */ -} - -static int translate_hwport_to_subdevice(struct mtpav *chip, int hwport) -{ - int p; - if (hwport <= 0x00) /* all ports */ - return chip->num_ports + MTPAV_PIDX_BROADCAST; - else if (hwport <= 0x08) { /* single port */ - p = hwport - 1; - if (p >= chip->num_ports) - p = 0; - return p; - } else if (hwport <= 0x10) { /* remote port */ - p = hwport - 0x09 + chip->num_ports; - if (p >= chip->num_ports * 2) - p = chip->num_ports; - return p; - } else if (hwport == 0x11) /* computer port */ - return chip->num_ports + MTPAV_PIDX_COMPUTER; - else /* ADAT */ - return chip->num_ports + MTPAV_PIDX_ADAT; -} - - -/* - */ - -static u8 snd_mtpav_getreg(struct mtpav *chip, u16 reg) -{ - u8 rval = 0; - - if (reg == SREG) { - rval = inb(chip->port + SREG); - rval = (rval & 0xf8); - } else if (reg == CREG) { - rval = inb(chip->port + CREG); - rval = (rval & 0x1c); - } - - return rval; -} - -/* - */ - -static inline void snd_mtpav_mputreg(struct mtpav *chip, u16 reg, u8 val) -{ - if (reg == DREG || reg == CREG) - outb(val, chip->port + reg); -} - -/* - */ - -static void snd_mtpav_wait_rfdhi(struct mtpav *chip) -{ - int counts = 10000; - u8 sbyte; - - sbyte = snd_mtpav_getreg(chip, SREG); - while (!(sbyte & SIGS_RFD) && counts--) { - sbyte = snd_mtpav_getreg(chip, SREG); - udelay(10); - } -} - -static void snd_mtpav_send_byte(struct mtpav *chip, u8 byte) -{ - u8 tcbyt; - u8 clrwrite; - u8 setwrite; - - snd_mtpav_wait_rfdhi(chip); - - ///////////////// - - tcbyt = snd_mtpav_getreg(chip, CREG); - clrwrite = tcbyt & (SIGC_WRITE ^ 0xff); - setwrite = tcbyt | SIGC_WRITE; - - snd_mtpav_mputreg(chip, DREG, byte); - snd_mtpav_mputreg(chip, CREG, clrwrite); // clear write bit - - snd_mtpav_mputreg(chip, CREG, setwrite); // set write bit - -} - - -/* - */ - -/* call this with spin lock held */ -static void snd_mtpav_output_port_write(struct mtpav *mtp_card, - struct mtpav_port *portp, - struct snd_rawmidi_substream *substream) -{ - u8 outbyte; - - // Get the outbyte first, so we can emulate running status if - // necessary - if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1) - return; - - // send port change command if necessary - - if (portp->hwport != mtp_card->outmidihwport) { - mtp_card->outmidihwport = portp->hwport; - - snd_mtpav_send_byte(mtp_card, 0xf5); - snd_mtpav_send_byte(mtp_card, portp->hwport); - /* - snd_printk(KERN_DEBUG "new outport: 0x%x\n", - (unsigned int) portp->hwport); - */ - if (!(outbyte & 0x80) && portp->running_status) - snd_mtpav_send_byte(mtp_card, portp->running_status); - } - - // send data - - do { - if (outbyte & 0x80) - portp->running_status = outbyte; - - snd_mtpav_send_byte(mtp_card, outbyte); - } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1); -} - -static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - snd_mtpav_output_port_write(mtp_card, portp, substream); - spin_unlock_irqrestore(&mtp_card->spinlock, flags); -} - - -/* - * mtpav control - */ - -static void snd_mtpav_portscan(struct mtpav *chip) // put mtp into smart routing mode -{ - u8 p; - - for (p = 0; p < 8; p++) { - snd_mtpav_send_byte(chip, 0xf5); - snd_mtpav_send_byte(chip, p); - snd_mtpav_send_byte(chip, 0xfe); - } -} - -/* - */ - -static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode |= MTPAV_MODE_INPUT_OPENED; - portp->input = substream; - if (mtp_card->share_irq++ == 0) - snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE)); // enable pport interrupts - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -} - -/* - */ - -static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode &= ~MTPAV_MODE_INPUT_OPENED; - portp->input = NULL; - if (--mtp_card->share_irq == 0) - snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -} - -/* - */ - -static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - if (up) - portp->mode |= MTPAV_MODE_INPUT_TRIGGERED; - else - portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - -} - - -/* - * timer interrupt for outputs - */ - -static void snd_mtpav_output_timer(unsigned long data) -{ - unsigned long flags; - struct mtpav *chip = (struct mtpav *)data; - int p; - - spin_lock_irqsave(&chip->spinlock, flags); - /* reprogram timer */ - chip->timer.expires = 1 + jiffies; - add_timer(&chip->timer); - /* process each port */ - for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) { - struct mtpav_port *portp = &chip->ports[p]; - if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output) - snd_mtpav_output_port_write(chip, portp, portp->output); - } - spin_unlock_irqrestore(&chip->spinlock, flags); -} - -/* spinlock held! */ -static void snd_mtpav_add_output_timer(struct mtpav *chip) -{ - chip->timer.expires = 1 + jiffies; - add_timer(&chip->timer); -} - -/* spinlock held! */ -static void snd_mtpav_remove_output_timer(struct mtpav *chip) -{ - del_timer(&chip->timer); -} - -/* - */ - -static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode |= MTPAV_MODE_OUTPUT_OPENED; - portp->output = substream; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -}; - -/* - */ - -static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED; - portp->output = NULL; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -}; - -/* - */ - -static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - if (up) { - if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) { - if (mtp_card->istimer++ == 0) - snd_mtpav_add_output_timer(mtp_card); - portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED; - } - } else { - portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED; - if (--mtp_card->istimer == 0) - snd_mtpav_remove_output_timer(mtp_card); - } - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - - if (up) - snd_mtpav_output_write(substream); -} - -/* - * midi interrupt for inputs - */ - -static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte) -{ - struct mtpav_port *portp; - - if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST) - return; - - portp = &mcrd->ports[mcrd->inmidiport]; - if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(portp->input, &inbyte, 1); -} - -static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte) -{ - if (inbyte >= 0xf8) { - /* real-time midi code */ - snd_mtpav_inmidi_process(mcrd, inbyte); - return; - } - - if (mcrd->inmidistate == 0) { // awaiting command - if (inbyte == 0xf5) // MTP port # - mcrd->inmidistate = 1; - else - snd_mtpav_inmidi_process(mcrd, inbyte); - } else if (mcrd->inmidistate) { - mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte); - mcrd->inmidistate = 0; - } -} - -static void snd_mtpav_read_bytes(struct mtpav *mcrd) -{ - u8 clrread, setread; - u8 mtp_read_byte; - u8 sr, cbyt; - int i; - - u8 sbyt = snd_mtpav_getreg(mcrd, SREG); - - /* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */ - - if (!(sbyt & SIGS_BYTE)) - return; - - cbyt = snd_mtpav_getreg(mcrd, CREG); - clrread = cbyt & (SIGC_READ ^ 0xff); - setread = cbyt | SIGC_READ; - - do { - - mtp_read_byte = 0; - for (i = 0; i < 4; i++) { - snd_mtpav_mputreg(mcrd, CREG, setread); - sr = snd_mtpav_getreg(mcrd, SREG); - snd_mtpav_mputreg(mcrd, CREG, clrread); - - sr &= SIGS_IN0 | SIGS_IN1; - sr >>= 4; - mtp_read_byte |= sr << (i * 2); - } - - snd_mtpav_inmidi_h(mcrd, mtp_read_byte); - - sbyt = snd_mtpav_getreg(mcrd, SREG); - - } while (sbyt & SIGS_BYTE); -} - -static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) -{ - struct mtpav *mcard = dev_id; - - spin_lock(&mcard->spinlock); - snd_mtpav_read_bytes(mcard); - spin_unlock(&mcard->spinlock); - return IRQ_HANDLED; -} - -/* - * get ISA resources - */ -static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard) -{ - if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { - snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port); - return -EBUSY; - } - mcard->port = port; - if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) { - snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq); - return -EBUSY; - } - mcard->irq = irq; - return 0; -} - - -/* - */ - -static struct snd_rawmidi_ops snd_mtpav_output = { - .open = snd_mtpav_output_open, - .close = snd_mtpav_output_close, - .trigger = snd_mtpav_output_trigger, -}; - -static struct snd_rawmidi_ops snd_mtpav_input = { - .open = snd_mtpav_input_open, - .close = snd_mtpav_input_close, - .trigger = snd_mtpav_input_trigger, -}; - - -/* - * get RAWMIDI resources - */ - -static void __devinit snd_mtpav_set_name(struct mtpav *chip, - struct snd_rawmidi_substream *substream) -{ - if (substream->number >= 0 && substream->number < chip->num_ports) - sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1); - else if (substream->number >= 8 && substream->number < chip->num_ports * 2) - sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1); - else if (substream->number == chip->num_ports * 2) - strcpy(substream->name, "MTP computer"); - else if (substream->number == chip->num_ports * 2 + 1) - strcpy(substream->name, "MTP ADAT"); - else - strcpy(substream->name, "MTP broadcast"); -} - -static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard) -{ - int rval; - struct snd_rawmidi *rawmidi; - struct snd_rawmidi_substream *substream; - struct list_head *list; - - if (hwports < 1) - hwports = 1; - else if (hwports > 8) - hwports = 8; - mcard->num_ports = hwports; - - if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, - mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, - mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, - &mcard->rmidi)) < 0) - return rval; - rawmidi = mcard->rmidi; - rawmidi->private_data = mcard; - - list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - snd_mtpav_set_name(mcard, substream); - substream->ops = &snd_mtpav_input; - } - list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - snd_mtpav_set_name(mcard, substream); - substream->ops = &snd_mtpav_output; - mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number); - } - rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - sprintf(rawmidi->name, "MTP AV MIDI"); - return 0; -} - -/* - */ - -static void snd_mtpav_free(struct snd_card *card) -{ - struct mtpav *crd = card->private_data; - unsigned long flags; - - spin_lock_irqsave(&crd->spinlock, flags); - if (crd->istimer > 0) - snd_mtpav_remove_output_timer(crd); - spin_unlock_irqrestore(&crd->spinlock, flags); - if (crd->irq >= 0) - free_irq(crd->irq, (void *)crd); - release_and_free_resource(crd->res_port); -} - -/* - */ -static int __devinit snd_mtpav_probe(struct platform_device *dev) -{ - struct snd_card *card; - int err; - struct mtpav *mtp_card; - - err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card); - if (err < 0) - return err; - - mtp_card = card->private_data; - spin_lock_init(&mtp_card->spinlock); - init_timer(&mtp_card->timer); - mtp_card->card = card; - mtp_card->irq = -1; - mtp_card->share_irq = 0; - mtp_card->inmidistate = 0; - mtp_card->outmidihwport = 0xffffffff; - init_timer(&mtp_card->timer); - mtp_card->timer.function = snd_mtpav_output_timer; - mtp_card->timer.data = (unsigned long) mtp_card; - - card->private_free = snd_mtpav_free; - - err = snd_mtpav_get_RAWMIDI(mtp_card); - if (err < 0) - goto __error; - - mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST; - - err = snd_mtpav_get_ISA(mtp_card); - if (err < 0) - goto __error; - - strcpy(card->driver, "MTPAV"); - strcpy(card->shortname, "MTPAV on parallel port"); - snprintf(card->longname, sizeof(card->longname), - "MTPAV on parallel port at 0x%lx", port); - - snd_mtpav_portscan(mtp_card); - - snd_card_set_dev(card, &dev->dev); - err = snd_card_register(mtp_card->card); - if (err < 0) - goto __error; - - platform_set_drvdata(dev, card); - printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port); - return 0; - - __error: - snd_card_free(card); - return err; -} - -static int __devexit snd_mtpav_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_MTPAV_DRIVER "snd_mtpav" - -static struct platform_driver snd_mtpav_driver = { - .probe = snd_mtpav_probe, - .remove = __devexit_p(snd_mtpav_remove), - .driver = { - .name = SND_MTPAV_DRIVER - }, -}; - -static int __init alsa_card_mtpav_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_mtpav_driver)) < 0) - return err; - - device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); - if (!IS_ERR(device)) { - if (platform_get_drvdata(device)) - return 0; - platform_device_unregister(device); - err = -ENODEV; - } else - err = PTR_ERR(device); - platform_driver_unregister(&snd_mtpav_driver); - return err; -} - -static void __exit alsa_card_mtpav_exit(void) -{ - platform_device_unregister(device); - platform_driver_unregister(&snd_mtpav_driver); -} - -module_init(alsa_card_mtpav_init) -module_exit(alsa_card_mtpav_exit) diff --git a/ANDROID_3.4.5/sound/drivers/mts64.c b/ANDROID_3.4.5/sound/drivers/mts64.c deleted file mode 100644 index 621e60e2..00000000 --- a/ANDROID_3.4.5/sound/drivers/mts64.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * ALSA Driver for Ego Systems Inc. (ESI) Miditerminal 4140 - * Copyright (c) 2006 by Matthias König <mk@phasorlab.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/parport.h> -#include <linux/spinlock.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/rawmidi.h> -#include <sound/control.h> - -#define CARD_NAME "Miditerminal 4140" -#define DRIVER_NAME "MTS64" -#define PLATFORM_DRIVER "snd_mts64" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int device_count; - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, S_IRUGO); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -MODULE_AUTHOR("Matthias Koenig <mk@phasorlab.de>"); -MODULE_DESCRIPTION("ESI Miditerminal 4140"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESI,Miditerminal 4140}}"); - -/********************************************************************* - * Chip specific - *********************************************************************/ -#define MTS64_NUM_INPUT_PORTS 5 -#define MTS64_NUM_OUTPUT_PORTS 4 -#define MTS64_SMPTE_SUBSTREAM 4 - -struct mts64 { - spinlock_t lock; - struct snd_card *card; - struct snd_rawmidi *rmidi; - struct pardevice *pardev; - int pardev_claimed; - - int open_count; - int current_midi_output_port; - int current_midi_input_port; - u8 mode[MTS64_NUM_INPUT_PORTS]; - struct snd_rawmidi_substream *midi_input_substream[MTS64_NUM_INPUT_PORTS]; - int smpte_switch; - u8 time[4]; /* [0]=hh, [1]=mm, [2]=ss, [3]=ff */ - u8 fps; -}; - -static int snd_mts64_free(struct mts64 *mts) -{ - kfree(mts); - return 0; -} - -static int __devinit snd_mts64_create(struct snd_card *card, - struct pardevice *pardev, - struct mts64 **rchip) -{ - struct mts64 *mts; - - *rchip = NULL; - - mts = kzalloc(sizeof(struct mts64), GFP_KERNEL); - if (mts == NULL) - return -ENOMEM; - - /* Init chip specific data */ - spin_lock_init(&mts->lock); - mts->card = card; - mts->pardev = pardev; - mts->current_midi_output_port = -1; - mts->current_midi_input_port = -1; - - *rchip = mts; - - return 0; -} - -/********************************************************************* - * HW register related constants - *********************************************************************/ - -/* Status Bits */ -#define MTS64_STAT_BSY 0x80 -#define MTS64_STAT_BIT_SET 0x20 /* readout process, bit is set */ -#define MTS64_STAT_PORT 0x10 /* read byte is a port number */ - -/* Control Bits */ -#define MTS64_CTL_READOUT 0x08 /* enable readout */ -#define MTS64_CTL_WRITE_CMD 0x06 -#define MTS64_CTL_WRITE_DATA 0x02 -#define MTS64_CTL_STROBE 0x01 - -/* Command */ -#define MTS64_CMD_RESET 0xfe -#define MTS64_CMD_PROBE 0x8f /* Used in probing procedure */ -#define MTS64_CMD_SMPTE_SET_TIME 0xe8 -#define MTS64_CMD_SMPTE_SET_FPS 0xee -#define MTS64_CMD_SMPTE_STOP 0xef -#define MTS64_CMD_SMPTE_FPS_24 0xe3 -#define MTS64_CMD_SMPTE_FPS_25 0xe2 -#define MTS64_CMD_SMPTE_FPS_2997 0xe4 -#define MTS64_CMD_SMPTE_FPS_30D 0xe1 -#define MTS64_CMD_SMPTE_FPS_30 0xe0 -#define MTS64_CMD_COM_OPEN 0xf8 /* setting the communication mode */ -#define MTS64_CMD_COM_CLOSE1 0xff /* clearing communication mode */ -#define MTS64_CMD_COM_CLOSE2 0xf5 - -/********************************************************************* - * Hardware specific functions - *********************************************************************/ -static void mts64_enable_readout(struct parport *p); -static void mts64_disable_readout(struct parport *p); -static int mts64_device_ready(struct parport *p); -static int mts64_device_init(struct parport *p); -static int mts64_device_open(struct mts64 *mts); -static int mts64_device_close(struct mts64 *mts); -static u8 mts64_map_midi_input(u8 c); -static int mts64_probe(struct parport *p); -static u16 mts64_read(struct parport *p); -static u8 mts64_read_char(struct parport *p); -static void mts64_smpte_start(struct parport *p, - u8 hours, u8 minutes, - u8 seconds, u8 frames, - u8 idx); -static void mts64_smpte_stop(struct parport *p); -static void mts64_write_command(struct parport *p, u8 c); -static void mts64_write_data(struct parport *p, u8 c); -static void mts64_write_midi(struct mts64 *mts, u8 c, int midiport); - - -/* Enables the readout procedure - * - * Before we can read a midi byte from the device, we have to set - * bit 3 of control port. - */ -static void mts64_enable_readout(struct parport *p) -{ - u8 c; - - c = parport_read_control(p); - c |= MTS64_CTL_READOUT; - parport_write_control(p, c); -} - -/* Disables readout - * - * Readout is disabled by clearing bit 3 of control - */ -static void mts64_disable_readout(struct parport *p) -{ - u8 c; - - c = parport_read_control(p); - c &= ~MTS64_CTL_READOUT; - parport_write_control(p, c); -} - -/* waits for device ready - * - * Checks if BUSY (Bit 7 of status) is clear - * 1 device ready - * 0 failure - */ -static int mts64_device_ready(struct parport *p) -{ - int i; - u8 c; - - for (i = 0; i < 0xffff; ++i) { - c = parport_read_status(p); - c &= MTS64_STAT_BSY; - if (c != 0) - return 1; - } - - return 0; -} - -/* Init device (LED blinking startup magic) - * - * Returns: - * 0 init ok - * -EIO failure - */ -static int __devinit mts64_device_init(struct parport *p) -{ - int i; - - mts64_write_command(p, MTS64_CMD_RESET); - - for (i = 0; i < 64; ++i) { - msleep(100); - - if (mts64_probe(p) == 0) { - /* success */ - mts64_disable_readout(p); - return 0; - } - } - mts64_disable_readout(p); - - return -EIO; -} - -/* - * Opens the device (set communication mode) - */ -static int mts64_device_open(struct mts64 *mts) -{ - int i; - struct parport *p = mts->pardev->port; - - for (i = 0; i < 5; ++i) - mts64_write_command(p, MTS64_CMD_COM_OPEN); - - return 0; -} - -/* - * Close device (clear communication mode) - */ -static int mts64_device_close(struct mts64 *mts) -{ - int i; - struct parport *p = mts->pardev->port; - - for (i = 0; i < 5; ++i) { - mts64_write_command(p, MTS64_CMD_COM_CLOSE1); - mts64_write_command(p, MTS64_CMD_COM_CLOSE2); - } - - return 0; -} - -/* map hardware port to substream number - * - * When reading a byte from the device, the device tells us - * on what port the byte is. This HW port has to be mapped to - * the midiport (substream number). - * substream 0-3 are Midiports 1-4 - * substream 4 is SMPTE Timecode - * The mapping is done by the table: - * HW | 0 | 1 | 2 | 3 | 4 - * SW | 0 | 1 | 4 | 2 | 3 - */ -static u8 mts64_map_midi_input(u8 c) -{ - static u8 map[] = { 0, 1, 4, 2, 3 }; - - return map[c]; -} - - -/* Probe parport for device - * - * Do we have a Miditerminal 4140 on parport? - * Returns: - * 0 device found - * -ENODEV no device - */ -static int __devinit mts64_probe(struct parport *p) -{ - u8 c; - - mts64_smpte_stop(p); - mts64_write_command(p, MTS64_CMD_PROBE); - - msleep(50); - - c = mts64_read(p); - - c &= 0x00ff; - if (c != MTS64_CMD_PROBE) - return -ENODEV; - else - return 0; - -} - -/* Read byte incl. status from device - * - * Returns: - * data in lower 8 bits and status in upper 8 bits - */ -static u16 mts64_read(struct parport *p) -{ - u8 data, status; - - mts64_device_ready(p); - mts64_enable_readout(p); - status = parport_read_status(p); - data = mts64_read_char(p); - mts64_disable_readout(p); - - return (status << 8) | data; -} - -/* Read a byte from device - * - * Note, that readout mode has to be enabled. - * readout procedure is as follows: - * - Write number of the Bit to read to DATA - * - Read STATUS - * - Bit 5 of STATUS indicates if Bit is set - * - * Returns: - * Byte read from device - */ -static u8 mts64_read_char(struct parport *p) -{ - u8 c = 0; - u8 status; - u8 i; - - for (i = 0; i < 8; ++i) { - parport_write_data(p, i); - c >>= 1; - status = parport_read_status(p); - if (status & MTS64_STAT_BIT_SET) - c |= 0x80; - } - - return c; -} - -/* Starts SMPTE Timecode generation - * - * The device creates SMPTE Timecode by hardware. - * 0 24 fps - * 1 25 fps - * 2 29.97 fps - * 3 30 fps (Drop-frame) - * 4 30 fps - */ -static void mts64_smpte_start(struct parport *p, - u8 hours, u8 minutes, - u8 seconds, u8 frames, - u8 idx) -{ - static u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24, - MTS64_CMD_SMPTE_FPS_25, - MTS64_CMD_SMPTE_FPS_2997, - MTS64_CMD_SMPTE_FPS_30D, - MTS64_CMD_SMPTE_FPS_30 }; - - mts64_write_command(p, MTS64_CMD_SMPTE_SET_TIME); - mts64_write_command(p, frames); - mts64_write_command(p, seconds); - mts64_write_command(p, minutes); - mts64_write_command(p, hours); - - mts64_write_command(p, MTS64_CMD_SMPTE_SET_FPS); - mts64_write_command(p, fps[idx]); -} - -/* Stops SMPTE Timecode generation - */ -static void mts64_smpte_stop(struct parport *p) -{ - mts64_write_command(p, MTS64_CMD_SMPTE_STOP); -} - -/* Write a command byte to device - */ -static void mts64_write_command(struct parport *p, u8 c) -{ - mts64_device_ready(p); - - parport_write_data(p, c); - - parport_write_control(p, MTS64_CTL_WRITE_CMD); - parport_write_control(p, MTS64_CTL_WRITE_CMD | MTS64_CTL_STROBE); - parport_write_control(p, MTS64_CTL_WRITE_CMD); -} - -/* Write a data byte to device - */ -static void mts64_write_data(struct parport *p, u8 c) -{ - mts64_device_ready(p); - - parport_write_data(p, c); - - parport_write_control(p, MTS64_CTL_WRITE_DATA); - parport_write_control(p, MTS64_CTL_WRITE_DATA | MTS64_CTL_STROBE); - parport_write_control(p, MTS64_CTL_WRITE_DATA); -} - -/* Write a MIDI byte to midiport - * - * midiport ranges from 0-3 and maps to Ports 1-4 - * assumptions: communication mode is on - */ -static void mts64_write_midi(struct mts64 *mts, u8 c, - int midiport) -{ - struct parport *p = mts->pardev->port; - - /* check current midiport */ - if (mts->current_midi_output_port != midiport) - mts64_write_command(p, midiport); - - /* write midi byte */ - mts64_write_data(p, c); -} - -/********************************************************************* - * Control elements - *********************************************************************/ - -/* SMPTE Switch */ -#define snd_mts64_ctl_smpte_switch_info snd_ctl_boolean_mono_info - -static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - - spin_lock_irq(&mts->lock); - uctl->value.integer.value[0] = mts->smpte_switch; - spin_unlock_irq(&mts->lock); - - return 0; -} - -/* smpte_switch is not accessed from IRQ handler, so we just need - to protect the HW access */ -static int snd_mts64_ctl_smpte_switch_put(struct snd_kcontrol* kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; - int val = !!uctl->value.integer.value[0]; - - spin_lock_irq(&mts->lock); - if (mts->smpte_switch == val) - goto __out; - - changed = 1; - mts->smpte_switch = val; - if (mts->smpte_switch) { - mts64_smpte_start(mts->pardev->port, - mts->time[0], mts->time[1], - mts->time[2], mts->time[3], - mts->fps); - } else { - mts64_smpte_stop(mts->pardev->port); - } -__out: - spin_unlock_irq(&mts->lock); - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_switch __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Playback Switch", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_switch_info, - .get = snd_mts64_ctl_smpte_switch_get, - .put = snd_mts64_ctl_smpte_switch_put -}; - -/* Time */ -static int snd_mts64_ctl_smpte_time_h_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 23; - return 0; -} - -static int snd_mts64_ctl_smpte_time_f_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 99; - return 0; -} - -static int snd_mts64_ctl_smpte_time_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 59; - return 0; -} - -static int snd_mts64_ctl_smpte_time_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int idx = kctl->private_value; - - spin_lock_irq(&mts->lock); - uctl->value.integer.value[0] = mts->time[idx]; - spin_unlock_irq(&mts->lock); - - return 0; -} - -static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int idx = kctl->private_value; - unsigned int time = uctl->value.integer.value[0] % 60; - int changed = 0; - - spin_lock_irq(&mts->lock); - if (mts->time[idx] != time) { - changed = 1; - mts->time[idx] = time; - } - spin_unlock_irq(&mts->lock); - - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Hours", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_time_h_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Minutes", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 1, - .info = snd_mts64_ctl_smpte_time_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Seconds", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 2, - .info = snd_mts64_ctl_smpte_time_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_frames __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Frames", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 3, - .info = snd_mts64_ctl_smpte_time_f_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -/* FPS */ -static int snd_mts64_ctl_smpte_fps_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[5] = { "24", - "25", - "29.97", - "30D", - "30" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_mts64_ctl_smpte_fps_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - - spin_lock_irq(&mts->lock); - uctl->value.enumerated.item[0] = mts->fps; - spin_unlock_irq(&mts->lock); - - return 0; -} - -static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; - - if (uctl->value.enumerated.item[0] >= 5) - return -EINVAL; - spin_lock_irq(&mts->lock); - if (mts->fps != uctl->value.enumerated.item[0]) { - changed = 1; - mts->fps = uctl->value.enumerated.item[0]; - } - spin_unlock_irq(&mts->lock); - - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Fps", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_fps_info, - .get = snd_mts64_ctl_smpte_fps_get, - .put = snd_mts64_ctl_smpte_fps_put -}; - - -static int __devinit snd_mts64_ctl_create(struct snd_card *card, - struct mts64 *mts) -{ - int err, i; - static struct snd_kcontrol_new *control[] __devinitdata = { - &mts64_ctl_smpte_switch, - &mts64_ctl_smpte_time_hours, - &mts64_ctl_smpte_time_minutes, - &mts64_ctl_smpte_time_seconds, - &mts64_ctl_smpte_time_frames, - &mts64_ctl_smpte_fps, - NULL }; - - for (i = 0; control[i]; ++i) { - err = snd_ctl_add(card, snd_ctl_new1(control[i], mts)); - if (err < 0) { - snd_printd("Cannot create control: %s\n", - control[i]->name); - return err; - } - } - - return 0; -} - -/********************************************************************* - * Rawmidi - *********************************************************************/ -#define MTS64_MODE_INPUT_TRIGGERED 0x01 - -static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream) -{ - struct mts64 *mts = substream->rmidi->private_data; - - if (mts->open_count == 0) { - /* We don't need a spinlock here, because this is just called - if the device has not been opened before. - So there aren't any IRQs from the device */ - mts64_device_open(mts); - - msleep(50); - } - ++(mts->open_count); - - return 0; -} - -static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream) -{ - struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; - - --(mts->open_count); - if (mts->open_count == 0) { - /* We need the spinlock_irqsave here because we can still - have IRQs at this point */ - spin_lock_irqsave(&mts->lock, flags); - mts64_device_close(mts); - spin_unlock_irqrestore(&mts->lock, flags); - - msleep(500); - - } else if (mts->open_count < 0) - mts->open_count = 0; - - return 0; -} - -static void snd_mts64_rawmidi_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct mts64 *mts = substream->rmidi->private_data; - u8 data; - unsigned long flags; - - spin_lock_irqsave(&mts->lock, flags); - while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) { - mts64_write_midi(mts, data, substream->number+1); - snd_rawmidi_transmit_ack(substream, 1); - } - spin_unlock_irqrestore(&mts->lock, flags); -} - -static void snd_mts64_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&mts->lock, flags); - if (up) - mts->mode[substream->number] |= MTS64_MODE_INPUT_TRIGGERED; - else - mts->mode[substream->number] &= ~MTS64_MODE_INPUT_TRIGGERED; - - spin_unlock_irqrestore(&mts->lock, flags); -} - -static struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = { - .open = snd_mts64_rawmidi_open, - .close = snd_mts64_rawmidi_close, - .trigger = snd_mts64_rawmidi_output_trigger -}; - -static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = { - .open = snd_mts64_rawmidi_open, - .close = snd_mts64_rawmidi_close, - .trigger = snd_mts64_rawmidi_input_trigger -}; - -/* Create and initialize the rawmidi component */ -static int __devinit snd_mts64_rawmidi_create(struct snd_card *card) -{ - struct mts64 *mts = card->private_data; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream; - struct list_head *list; - int err; - - err = snd_rawmidi_new(card, CARD_NAME, 0, - MTS64_NUM_OUTPUT_PORTS, - MTS64_NUM_INPUT_PORTS, - &rmidi); - if (err < 0) - return err; - - rmidi->private_data = mts; - strcpy(rmidi->name, CARD_NAME); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - mts->rmidi = rmidi; - - /* register rawmidi ops */ - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_mts64_rawmidi_output_ops); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_mts64_rawmidi_input_ops); - - /* name substreams */ - /* output */ - list_for_each(list, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - sprintf(substream->name, - "Miditerminal %d", substream->number+1); - } - /* input */ - list_for_each(list, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - mts->midi_input_substream[substream->number] = substream; - switch(substream->number) { - case MTS64_SMPTE_SUBSTREAM: - strcpy(substream->name, "Miditerminal SMPTE"); - break; - default: - sprintf(substream->name, - "Miditerminal %d", substream->number+1); - } - } - - /* controls */ - err = snd_mts64_ctl_create(card, mts); - - return err; -} - -/********************************************************************* - * parport stuff - *********************************************************************/ -static void snd_mts64_interrupt(void *private) -{ - struct mts64 *mts = ((struct snd_card*)private)->private_data; - u16 ret; - u8 status, data; - struct snd_rawmidi_substream *substream; - - spin_lock(&mts->lock); - ret = mts64_read(mts->pardev->port); - data = ret & 0x00ff; - status = ret >> 8; - - if (status & MTS64_STAT_PORT) { - mts->current_midi_input_port = mts64_map_midi_input(data); - } else { - if (mts->current_midi_input_port == -1) - goto __out; - substream = mts->midi_input_substream[mts->current_midi_input_port]; - if (mts->mode[substream->number] & MTS64_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(substream, &data, 1); - } -__out: - spin_unlock(&mts->lock); -} - -static int __devinit snd_mts64_probe_port(struct parport *p) -{ - struct pardevice *pardev; - int res; - - pardev = parport_register_device(p, DRIVER_NAME, - NULL, NULL, NULL, - 0, NULL); - if (!pardev) - return -EIO; - - if (parport_claim(pardev)) { - parport_unregister_device(pardev); - return -EIO; - } - - res = mts64_probe(p); - - parport_release(pardev); - parport_unregister_device(pardev); - - return res; -} - -static void __devinit snd_mts64_attach(struct parport *p) -{ - struct platform_device *device; - - device = platform_device_alloc(PLATFORM_DRIVER, device_count); - if (!device) - return; - - /* Temporary assignment to forward the parport */ - platform_set_drvdata(device, p); - - if (platform_device_add(device) < 0) { - platform_device_put(device); - return; - } - - /* Since we dont get the return value of probe - * We need to check if device probing succeeded or not */ - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - return; - } - - /* register device in global table */ - platform_devices[device_count] = device; - device_count++; -} - -static void snd_mts64_detach(struct parport *p) -{ - /* nothing to do here */ -} - -static struct parport_driver mts64_parport_driver = { - .name = "mts64", - .attach = snd_mts64_attach, - .detach = snd_mts64_detach -}; - -/********************************************************************* - * platform stuff - *********************************************************************/ -static void snd_mts64_card_private_free(struct snd_card *card) -{ - struct mts64 *mts = card->private_data; - struct pardevice *pardev = mts->pardev; - - if (pardev) { - if (mts->pardev_claimed) - parport_release(pardev); - parport_unregister_device(pardev); - } - - snd_mts64_free(mts); -} - -static int __devinit snd_mts64_probe(struct platform_device *pdev) -{ - struct pardevice *pardev; - struct parport *p; - int dev = pdev->id; - struct snd_card *card = NULL; - struct mts64 *mts = NULL; - int err; - - p = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) - return -ENOENT; - if ((err = snd_mts64_probe_port(p)) < 0) - return err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printd("Cannot create card\n"); - return err; - } - strcpy(card->driver, DRIVER_NAME); - strcpy(card->shortname, "ESI " CARD_NAME); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, p->base, p->irq); - - pardev = parport_register_device(p, /* port */ - DRIVER_NAME, /* name */ - NULL, /* preempt */ - NULL, /* wakeup */ - snd_mts64_interrupt, /* ISR */ - PARPORT_DEV_EXCL, /* flags */ - (void *)card); /* private */ - if (pardev == NULL) { - snd_printd("Cannot register pardevice\n"); - err = -EIO; - goto __err; - } - - if ((err = snd_mts64_create(card, pardev, &mts)) < 0) { - snd_printd("Cannot create main component\n"); - parport_unregister_device(pardev); - goto __err; - } - card->private_data = mts; - card->private_free = snd_mts64_card_private_free; - - if ((err = snd_mts64_rawmidi_create(card)) < 0) { - snd_printd("Creating Rawmidi component failed\n"); - goto __err; - } - - /* claim parport */ - if (parport_claim(pardev)) { - snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); - err = -EIO; - goto __err; - } - mts->pardev_claimed = 1; - - /* init device */ - if ((err = mts64_device_init(p)) < 0) - goto __err; - - platform_set_drvdata(pdev, card); - - snd_card_set_dev(card, &pdev->dev); - - /* At this point card will be usable */ - if ((err = snd_card_register(card)) < 0) { - snd_printd("Cannot register card\n"); - goto __err; - } - - snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base); - return 0; - -__err: - snd_card_free(card); - return err; -} - -static int __devexit snd_mts64_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - if (card) - snd_card_free(card); - - return 0; -} - - -static struct platform_driver snd_mts64_driver = { - .probe = snd_mts64_probe, - .remove = __devexit_p(snd_mts64_remove), - .driver = { - .name = PLATFORM_DRIVER - } -}; - -/********************************************************************* - * module init stuff - *********************************************************************/ -static void snd_mts64_unregister_all(void) -{ - int i; - - for (i = 0; i < SNDRV_CARDS; ++i) { - if (platform_devices[i]) { - platform_device_unregister(platform_devices[i]); - platform_devices[i] = NULL; - } - } - platform_driver_unregister(&snd_mts64_driver); - parport_unregister_driver(&mts64_parport_driver); -} - -static int __init snd_mts64_module_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_mts64_driver)) < 0) - return err; - - if (parport_register_driver(&mts64_parport_driver) != 0) { - platform_driver_unregister(&snd_mts64_driver); - return -EIO; - } - - if (device_count == 0) { - snd_mts64_unregister_all(); - return -ENODEV; - } - - return 0; -} - -static void __exit snd_mts64_module_exit(void) -{ - snd_mts64_unregister_all(); -} - -module_init(snd_mts64_module_init); -module_exit(snd_mts64_module_exit); diff --git a/ANDROID_3.4.5/sound/drivers/opl3/Makefile b/ANDROID_3.4.5/sound/drivers/opl3/Makefile deleted file mode 100644 index 7f2c2a10..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-opl3-lib-objs := opl3_lib.o opl3_synth.o -snd-opl3-synth-y := opl3_seq.o opl3_midi.o opl3_drums.o -snd-opl3-synth-$(CONFIG_SND_SEQUENCER_OSS) += opl3_oss.o - -obj-$(CONFIG_SND_OPL3_LIB) += snd-opl3-lib.o -obj-$(CONFIG_SND_OPL4_LIB) += snd-opl3-lib.o -obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-opl3-synth.o diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c deleted file mode 100644 index 73694380..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak <uros@kss-loka.si> - * - * OPL2/OPL3/OPL4 FM routines for internal percussion channels - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "opl3_voice.h" - -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - -static char snd_opl3_drum_table[47] = -{ - OPL3_BASSDRUM_ON, OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, /* 35 - 37 */ - OPL3_SNAREDRUM_ON, OPL3_HIHAT_ON, OPL3_SNAREDRUM_ON, /* 38 - 40 */ - OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, OPL3_BASSDRUM_ON, /* 41 - 43 */ - OPL3_HIHAT_ON, OPL3_TOMTOM_ON, OPL3_HIHAT_ON, /* 44 - 46 */ - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_CYMBAL_ON, /* 47 - 49 */ - - OPL3_TOMTOM_ON, OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, /* 50 - 52 */ - OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, /* 53 - 55 */ - OPL3_HIHAT_ON, OPL3_CYMBAL_ON, OPL3_TOMTOM_ON, /* 56 - 58 */ - OPL3_CYMBAL_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 59 - 61 */ - OPL3_HIHAT_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 62 - 64 */ - - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 65 - 67 */ - OPL3_TOMTOM_ON, OPL3_HIHAT_ON, OPL3_HIHAT_ON, /* 68 - 70 */ - OPL3_HIHAT_ON, OPL3_HIHAT_ON, OPL3_TOMTOM_ON, /* 71 - 73 */ - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 74 - 76 */ - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 77 - 79 */ - OPL3_CYMBAL_ON, OPL3_CYMBAL_ON /* 80 - 81 */ -}; - -struct snd_opl3_drum_voice { - int voice; - int op; - unsigned char am_vib; - unsigned char ksl_level; - unsigned char attack_decay; - unsigned char sustain_release; - unsigned char feedback_connection; - unsigned char wave_select; -}; - -struct snd_opl3_drum_note { - int voice; - unsigned char fnum; - unsigned char octave_f; - unsigned char feedback_connection; -}; - -static struct snd_opl3_drum_voice bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00}; -static struct snd_opl3_drum_voice bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00}; -static struct snd_opl3_drum_note bass_note = {6, 0x90, 0x09}; - -static struct snd_opl3_drum_voice hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00}; - -static struct snd_opl3_drum_voice snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02}; -static struct snd_opl3_drum_note snare_note = {7, 0xf4, 0x0d}; - -static struct snd_opl3_drum_voice tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00}; -static struct snd_opl3_drum_note tomtom_note = {8, 0xf4, 0x09}; - -static struct snd_opl3_drum_voice cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00}; - -/* - * set drum voice characteristics - */ -static void snd_opl3_drum_voice_set(struct snd_opl3 *opl3, - struct snd_opl3_drum_voice *data) -{ - unsigned char op_offset = snd_opl3_regmap[data->voice][data->op]; - unsigned char voice_offset = data->voice; - unsigned short opl3_reg; - - /* Set OPL3 AM_VIB register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_AM_VIB + op_offset); - opl3->command(opl3, opl3_reg, data->am_vib); - - /* Set OPL3 KSL_LEVEL register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, data->ksl_level); - - /* Set OPL3 ATTACK_DECAY register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_ATTACK_DECAY + op_offset); - opl3->command(opl3, opl3_reg, data->attack_decay); - - /* Set OPL3 SUSTAIN_RELEASE register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_SUSTAIN_RELEASE + op_offset); - opl3->command(opl3, opl3_reg, data->sustain_release); - - /* Set OPL3 FEEDBACK_CONNECTION register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, data->feedback_connection); - - /* Select waveform */ - opl3_reg = OPL3_LEFT | (OPL3_REG_WAVE_SELECT + op_offset); - opl3->command(opl3, opl3_reg, data->wave_select); -} - -/* - * Set drum voice pitch - */ -static void snd_opl3_drum_note_set(struct snd_opl3 *opl3, - struct snd_opl3_drum_note *data) -{ - unsigned char voice_offset = data->voice; - unsigned short opl3_reg; - - /* Set OPL3 FNUM_LOW register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, data->fnum); - - /* Set OPL3 KEYON_BLOCK register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, data->octave_f); -} - -/* - * Set drum voice volume and position - */ -static void snd_opl3_drum_vol_set(struct snd_opl3 *opl3, - struct snd_opl3_drum_voice *data, - int vel, struct snd_midi_channel *chan) -{ - unsigned char op_offset = snd_opl3_regmap[data->voice][data->op]; - unsigned char voice_offset = data->voice; - unsigned char reg_val; - unsigned short opl3_reg; - - /* Set OPL3 KSL_LEVEL register */ - reg_val = data->ksl_level; - snd_opl3_calc_volume(®_val, vel, chan); - opl3_reg = OPL3_LEFT | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 FEEDBACK_CONNECTION register */ - /* Set output voice connection */ - reg_val = data->feedback_connection | OPL3_STEREO_BITS; - if (chan->gm_pan < 43) - reg_val &= ~OPL3_VOICE_TO_RIGHT; - if (chan->gm_pan > 85) - reg_val &= ~OPL3_VOICE_TO_LEFT; - opl3_reg = OPL3_LEFT | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); -} - -/* - * Loads drum voices at init time - */ -void snd_opl3_load_drums(struct snd_opl3 *opl3) -{ - snd_opl3_drum_voice_set(opl3, &bass_op0); - snd_opl3_drum_voice_set(opl3, &bass_op1); - snd_opl3_drum_note_set(opl3, &bass_note); - - snd_opl3_drum_voice_set(opl3, &hihat); - - snd_opl3_drum_voice_set(opl3, &snare); - snd_opl3_drum_note_set(opl3, &snare_note); - - snd_opl3_drum_voice_set(opl3, &tomtom); - snd_opl3_drum_note_set(opl3, &tomtom_note); - - snd_opl3_drum_voice_set(opl3, &cymbal); -} - -/* - * Switch drum voice on or off - */ -void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int vel, int on_off, - struct snd_midi_channel *chan) -{ - unsigned char drum_mask; - struct snd_opl3_drum_voice *drum_voice; - - if (!(opl3->drum_reg & OPL3_PERCUSSION_ENABLE)) - return; - - if ((note < 35) || (note > 81)) - return; - drum_mask = snd_opl3_drum_table[note - 35]; - - if (on_off) { - switch (drum_mask) { - case OPL3_BASSDRUM_ON: - drum_voice = &bass_op1; - break; - case OPL3_HIHAT_ON: - drum_voice = &hihat; - break; - case OPL3_SNAREDRUM_ON: - drum_voice = &snare; - break; - case OPL3_TOMTOM_ON: - drum_voice = &tomtom; - break; - case OPL3_CYMBAL_ON: - drum_voice = &cymbal; - break; - default: - drum_voice = &tomtom; - } - - snd_opl3_drum_vol_set(opl3, drum_voice, vel, chan); - opl3->drum_reg |= drum_mask; - } else { - opl3->drum_reg &= ~drum_mask; - } - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, - opl3->drum_reg); -} diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c deleted file mode 100644 index 33d9a857..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, - * Hannu Savolainen 1993-1996, - * Rob Hooft - * - * Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips) - * - * Most if code is ported from OSS/Lite. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <sound/opl3.h> -#include <asm/io.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <sound/minors.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Hannu Savolainen 1993-1996, Rob Hooft"); -MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)"); -MODULE_LICENSE("GPL"); - -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - -static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) -{ - unsigned long flags; - unsigned long port; - - /* - * The original 2-OP synth requires a quite long delay - * after writing to a register. - */ - - port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port; - - spin_lock_irqsave(&opl3->reg_lock, flags); - - outb((unsigned char) cmd, port); - udelay(10); - - outb((unsigned char) val, port + 1); - udelay(30); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); -} - -static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) -{ - unsigned long flags; - unsigned long port; - - /* - * The OPL-3 survives with just two INBs - * after writing to a register. - */ - - port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port; - - spin_lock_irqsave(&opl3->reg_lock, flags); - - outb((unsigned char) cmd, port); - inb(opl3->l_port); - inb(opl3->l_port); - - outb((unsigned char) val, port + 1); - inb(opl3->l_port); - inb(opl3->l_port); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); -} - -static int snd_opl3_detect(struct snd_opl3 * opl3) -{ - /* - * This function returns 1 if the FM chip is present at the given I/O port - * The detection algorithm plays with the timer built in the FM chip and - * looks for a change in the status register. - * - * Note! The timers of the FM chip are not connected to AdLib (and compatible) - * boards. - * - * Note2! The chip is initialized if detected. - */ - - unsigned char stat1, stat2, signature; - - /* Reset timers 1 and 2 */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK); - /* Reset the IRQ of the FM chip */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET); - signature = stat1 = inb(opl3->l_port); /* Status register */ - if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */ - snd_printd("OPL3: stat1 = 0x%x\n", stat1); - return -ENODEV; - } - /* Set timer1 to 0xff */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 0xff); - /* Unmask and start timer 1 */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER2_MASK | OPL3_TIMER1_START); - /* Now we have to delay at least 80us */ - udelay(200); - /* Read status after timers have expired */ - stat2 = inb(opl3->l_port); - /* Stop the timers */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK); - /* Reset the IRQ of the FM chip */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET); - if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */ - snd_printd("OPL3: stat2 = 0x%x\n", stat2); - return -ENODEV; - } - - /* If the toplevel code knows exactly the type of chip, don't try - to detect it. */ - if (opl3->hardware != OPL3_HW_AUTO) - return 0; - - /* There is a FM chip on this address. Detect the type (OPL2 to OPL4) */ - if (signature == 0x06) { /* OPL2 */ - opl3->hardware = OPL3_HW_OPL2; - } else { - /* - * If we had an OPL4 chip, opl3->hardware would have been set - * by the OPL4 driver; so we can assume OPL3 here. - */ - if (snd_BUG_ON(!opl3->r_port)) - return -ENODEV; - opl3->hardware = OPL3_HW_OPL3; - } - return 0; -} - -/* - * AdLib timers - */ - -/* - * Timer 1 - 80us - */ - -static int snd_opl3_timer1_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - ticks = timer->sticks; - tmp = (opl3->timer_enable | OPL3_TIMER1_START) & ~OPL3_TIMER1_MASK; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 256 - ticks); /* timer 1 count */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -static int snd_opl3_timer1_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - tmp = (opl3->timer_enable | OPL3_TIMER1_MASK) & ~OPL3_TIMER1_START; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -/* - * Timer 2 - 320us - */ - -static int snd_opl3_timer2_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - ticks = timer->sticks; - tmp = (opl3->timer_enable | OPL3_TIMER2_START) & ~OPL3_TIMER2_MASK; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER2, 256 - ticks); /* timer 1 count */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -static int snd_opl3_timer2_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - tmp = (opl3->timer_enable | OPL3_TIMER2_MASK) & ~OPL3_TIMER2_START; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -/* - - */ - -static struct snd_timer_hardware snd_opl3_timer1 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 80000, - .ticks = 256, - .start = snd_opl3_timer1_start, - .stop = snd_opl3_timer1_stop, -}; - -static struct snd_timer_hardware snd_opl3_timer2 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 320000, - .ticks = 256, - .start = snd_opl3_timer2_start, - .stop = snd_opl3_timer2_stop, -}; - -static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = opl3->card->number; - tid.device = timer_no; - tid.subdevice = 0; - if ((err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer)) >= 0) { - strcpy(timer->name, "AdLib timer #1"); - timer->private_data = opl3; - timer->hw = snd_opl3_timer1; - } - opl3->timer1 = timer; - return err; -} - -static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = opl3->card->number; - tid.device = timer_no; - tid.subdevice = 0; - if ((err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer)) >= 0) { - strcpy(timer->name, "AdLib timer #2"); - timer->private_data = opl3; - timer->hw = snd_opl3_timer2; - } - opl3->timer2 = timer; - return err; -} - -/* - - */ - -void snd_opl3_interrupt(struct snd_hwdep * hw) -{ - unsigned char status; - struct snd_opl3 *opl3; - struct snd_timer *timer; - - if (hw == NULL) - return; - - opl3 = hw->private_data; - status = inb(opl3->l_port); -#if 0 - snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status); -#endif - if (!(status & 0x80)) - return; - - if (status & 0x40) { - timer = opl3->timer1; - snd_timer_interrupt(timer, timer->sticks); - } - if (status & 0x20) { - timer = opl3->timer2; - snd_timer_interrupt(timer, timer->sticks); - } -} - -EXPORT_SYMBOL(snd_opl3_interrupt); - -/* - - */ - -static int snd_opl3_free(struct snd_opl3 *opl3) -{ - if (snd_BUG_ON(!opl3)) - return -ENXIO; - if (opl3->private_free) - opl3->private_free(opl3); - snd_opl3_clear_patches(opl3); - release_and_free_resource(opl3->res_l_port); - release_and_free_resource(opl3->res_r_port); - kfree(opl3); - return 0; -} - -static int snd_opl3_dev_free(struct snd_device *device) -{ - struct snd_opl3 *opl3 = device->device_data; - return snd_opl3_free(opl3); -} - -int snd_opl3_new(struct snd_card *card, - unsigned short hardware, - struct snd_opl3 **ropl3) -{ - static struct snd_device_ops ops = { - .dev_free = snd_opl3_dev_free, - }; - struct snd_opl3 *opl3; - int err; - - *ropl3 = NULL; - opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL); - if (opl3 == NULL) { - snd_printk(KERN_ERR "opl3: cannot allocate\n"); - return -ENOMEM; - } - - opl3->card = card; - opl3->hardware = hardware; - spin_lock_init(&opl3->reg_lock); - spin_lock_init(&opl3->timer_lock); - - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) { - snd_opl3_free(opl3); - return err; - } - - *ropl3 = opl3; - return 0; -} - -EXPORT_SYMBOL(snd_opl3_new); - -int snd_opl3_init(struct snd_opl3 *opl3) -{ - if (! opl3->command) { - printk(KERN_ERR "snd_opl3_init: command not defined!\n"); - return -EINVAL; - } - - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); - /* Melodic mode */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); - - switch (opl3->hardware & OPL3_HW_MASK) { - case OPL3_HW_OPL2: - opl3->max_voices = MAX_OPL2_VOICES; - break; - case OPL3_HW_OPL3: - case OPL3_HW_OPL4: - opl3->max_voices = MAX_OPL3_VOICES; - /* Enter OPL3 mode */ - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE); - } - return 0; -} - -EXPORT_SYMBOL(snd_opl3_init); - -int snd_opl3_create(struct snd_card *card, - unsigned long l_port, - unsigned long r_port, - unsigned short hardware, - int integrated, - struct snd_opl3 ** ropl3) -{ - struct snd_opl3 *opl3; - int err; - - *ropl3 = NULL; - if ((err = snd_opl3_new(card, hardware, &opl3)) < 0) - return err; - if (! integrated) { - if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) { - snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port); - snd_device_free(card, opl3); - return -EBUSY; - } - if (r_port != 0 && - (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) { - snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); - snd_device_free(card, opl3); - return -EBUSY; - } - } - opl3->l_port = l_port; - opl3->r_port = r_port; - - switch (opl3->hardware) { - /* some hardware doesn't support timers */ - case OPL3_HW_OPL3_SV: - case OPL3_HW_OPL3_CS: - case OPL3_HW_OPL3_FM801: - opl3->command = &snd_opl3_command; - break; - default: - opl3->command = &snd_opl2_command; - if ((err = snd_opl3_detect(opl3)) < 0) { - snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n", - opl3->l_port, opl3->r_port); - snd_device_free(card, opl3); - return err; - } - /* detect routine returns correct hardware type */ - switch (opl3->hardware & OPL3_HW_MASK) { - case OPL3_HW_OPL3: - case OPL3_HW_OPL4: - opl3->command = &snd_opl3_command; - } - } - - snd_opl3_init(opl3); - - *ropl3 = opl3; - return 0; -} - -EXPORT_SYMBOL(snd_opl3_create); - -int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) -{ - int err; - - if (timer1_dev >= 0) - if ((err = snd_opl3_timer1_init(opl3, timer1_dev)) < 0) - return err; - if (timer2_dev >= 0) { - if ((err = snd_opl3_timer2_init(opl3, timer2_dev)) < 0) { - snd_device_free(opl3->card, opl3->timer1); - opl3->timer1 = NULL; - return err; - } - } - return 0; -} - -EXPORT_SYMBOL(snd_opl3_timer_new); - -int snd_opl3_hwdep_new(struct snd_opl3 * opl3, - int device, int seq_device, - struct snd_hwdep ** rhwdep) -{ - struct snd_hwdep *hw; - struct snd_card *card = opl3->card; - int err; - - if (rhwdep) - *rhwdep = NULL; - - /* create hardware dependent device (direct FM) */ - - if ((err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw)) < 0) { - snd_device_free(card, opl3); - return err; - } - hw->private_data = opl3; - hw->exclusive = 1; -#ifdef CONFIG_SND_OSSEMUL - if (device == 0) { - hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM; - sprintf(hw->oss_dev, "dmfm%i", card->number); - } -#endif - strcpy(hw->name, hw->id); - switch (opl3->hardware & OPL3_HW_MASK) { - case OPL3_HW_OPL2: - strcpy(hw->name, "OPL2 FM"); - hw->iface = SNDRV_HWDEP_IFACE_OPL2; - break; - case OPL3_HW_OPL3: - strcpy(hw->name, "OPL3 FM"); - hw->iface = SNDRV_HWDEP_IFACE_OPL3; - break; - case OPL3_HW_OPL4: - strcpy(hw->name, "OPL4 FM"); - hw->iface = SNDRV_HWDEP_IFACE_OPL4; - break; - } - - /* operators - only ioctl */ - hw->ops.open = snd_opl3_open; - hw->ops.ioctl = snd_opl3_ioctl; - hw->ops.write = snd_opl3_write; - hw->ops.release = snd_opl3_release; - - opl3->hwdep = hw; - opl3->seq_dev_num = seq_device; -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3, - sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) { - strcpy(opl3->seq_dev->name, hw->name); - *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3; - } -#endif - if (rhwdep) - *rhwdep = hw; - return 0; -} - -EXPORT_SYMBOL(snd_opl3_hwdep_new); - -/* - * INIT part - */ - -static int __init alsa_opl3_init(void) -{ - return 0; -} - -static void __exit alsa_opl3_exit(void) -{ -} - -module_init(alsa_opl3_init) -module_exit(alsa_opl3_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c deleted file mode 100644 index 2bfe4bcb..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak <uros@kss-loka.si> - * - * Midi synth routines for OPL2/OPL3/OPL4 FM - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#undef DEBUG_ALLOC -#undef DEBUG_MIDI - -#include "opl3_voice.h" -#include <sound/asoundef.h> - -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - -extern bool use_internal_drums; - -static void snd_opl3_note_off_unsafe(void *p, int note, int vel, - struct snd_midi_channel *chan); -/* - * The next table looks magical, but it certainly is not. Its values have - * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception - * for i=0. This log-table converts a linear volume-scaling (0..127) to a - * logarithmic scaling as present in the FM-synthesizer chips. so : Volume - * 64 = 0 db = relative volume 0 and: Volume 32 = -6 db = relative - * volume -8 it was implemented as a table because it is only 128 bytes and - * it saves a lot of log() calculations. (Rob Hooft <hooft@chem.ruu.nl>) - */ - -static char opl3_volume_table[128] = -{ - -63, -48, -40, -35, -32, -29, -27, -26, - -24, -23, -21, -20, -19, -18, -18, -17, - -16, -15, -15, -14, -13, -13, -12, -12, - -11, -11, -10, -10, -10, -9, -9, -8, - -8, -8, -7, -7, -7, -6, -6, -6, - -5, -5, -5, -5, -4, -4, -4, -4, - -3, -3, -3, -3, -2, -2, -2, -2, - -2, -1, -1, -1, -1, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 4, - 4, 4, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 8 -}; - -void snd_opl3_calc_volume(unsigned char *volbyte, int vel, - struct snd_midi_channel *chan) -{ - int oldvol, newvol, n; - int volume; - - volume = (vel * chan->gm_volume * chan->gm_expression) / (127*127); - if (volume > 127) - volume = 127; - - oldvol = OPL3_TOTAL_LEVEL_MASK - (*volbyte & OPL3_TOTAL_LEVEL_MASK); - - newvol = opl3_volume_table[volume] + oldvol; - if (newvol > OPL3_TOTAL_LEVEL_MASK) - newvol = OPL3_TOTAL_LEVEL_MASK; - else if (newvol < 0) - newvol = 0; - - n = OPL3_TOTAL_LEVEL_MASK - (newvol & OPL3_TOTAL_LEVEL_MASK); - - *volbyte = (*volbyte & OPL3_KSL_MASK) | (n & OPL3_TOTAL_LEVEL_MASK); -} - -/* - * Converts the note frequency to block and fnum values for the FM chip - */ -static short opl3_note_table[16] = -{ - 305, 323, /* for pitch bending, -2 semitones */ - 343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647, - 686, 726 /* for pitch bending, +2 semitones */ -}; - -static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum, - int note, struct snd_midi_channel *chan) -{ - int block = ((note / 12) & 0x07) - 1; - int idx = (note % 12) + 2; - int freq; - - if (chan->midi_pitchbend) { - int pitchbend = chan->midi_pitchbend; - int segment; - - if (pitchbend > 0x1FFF) - pitchbend = 0x1FFF; - - segment = pitchbend / 0x1000; - freq = opl3_note_table[idx+segment]; - freq += ((opl3_note_table[idx+segment+1] - freq) * - (pitchbend % 0x1000)) / 0x1000; - } else { - freq = opl3_note_table[idx]; - } - - *fnum = (unsigned char) freq; - *blocknum = ((freq >> 8) & OPL3_FNUM_HIGH_MASK) | - ((block << 2) & OPL3_BLOCKNUM_MASK); -} - - -#ifdef DEBUG_ALLOC -static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) { - int i; - char *str = "x.24"; - - printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); - for (i = 0; i < opl3->max_voices; i++) - printk("%c", *(str + opl3->voices[i].state + 1)); - printk("\n"); -} -#endif - -/* - * Get a FM voice (channel) to play a note on. - */ -static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, - struct snd_midi_channel *chan) { - int chan_4op_1; /* first voice for 4op instrument */ - int chan_4op_2; /* second voice for 4op instrument */ - - struct snd_opl3_voice *vp, *vp2; - unsigned int voice_time; - int i; - -#ifdef DEBUG_ALLOC - char *alloc_type[3] = { "FREE ", "CHEAP ", "EXPENSIVE" }; -#endif - - /* This is our "allocation cost" table */ - enum { - FREE = 0, CHEAP, EXPENSIVE, END - }; - - /* Keeps track of what we are finding */ - struct best { - unsigned int time; - int voice; - } best[END]; - struct best *bp; - - for (i = 0; i < END; i++) { - best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */; - best[i].voice = -1; - } - - /* Look through all the channels for the most suitable. */ - for (i = 0; i < opl3->max_voices; i++) { - vp = &opl3->voices[i]; - - if (vp->state == SNDRV_OPL3_ST_NOT_AVAIL) - /* skip unavailable channels, allocated by - drum voices or by bounded 4op voices) */ - continue; - - voice_time = vp->time; - bp = best; - - chan_4op_1 = ((i < 3) || (i > 8 && i < 12)); - chan_4op_2 = ((i > 2 && i < 6) || (i > 11 && i < 15)); - if (instr_4op) { - /* allocate 4op voice */ - /* skip channels unavailable to 4op instrument */ - if (!chan_4op_1) - continue; - - if (vp->state) - /* kill one voice, CHEAP */ - bp++; - /* get state of bounded 2op channel - to be allocated for 4op instrument */ - vp2 = &opl3->voices[i + 3]; - if (vp2->state == SNDRV_OPL3_ST_ON_2OP) { - /* kill two voices, EXPENSIVE */ - bp++; - voice_time = (voice_time > vp->time) ? - voice_time : vp->time; - } - } else { - /* allocate 2op voice */ - if ((chan_4op_1) || (chan_4op_2)) - /* use bounded channels for 2op, CHEAP */ - bp++; - else if (vp->state) - /* kill one voice on 2op channel, CHEAP */ - bp++; - /* raise kill cost to EXPENSIVE for all channels */ - if (vp->state) - bp++; - } - if (voice_time < bp->time) { - bp->time = voice_time; - bp->voice = i; - } - } - - for (i = 0; i < END; i++) { - if (best[i].voice >= 0) { -#ifdef DEBUG_ALLOC - printk(KERN_DEBUG "%s %iop allocation on voice %i\n", - alloc_type[i], instr_4op ? 4 : 2, - best[i].voice); -#endif - return best[i].voice; - } - } - /* not found */ - return -1; -} - -/* ------------------------------ */ - -/* - * System timer interrupt function - */ -void snd_opl3_timer_func(unsigned long data) -{ - - struct snd_opl3 *opl3 = (struct snd_opl3 *)data; - unsigned long flags; - int again = 0; - int i; - - spin_lock_irqsave(&opl3->voice_lock, flags); - for (i = 0; i < opl3->max_voices; i++) { - struct snd_opl3_voice *vp = &opl3->voices[i]; - if (vp->state > 0 && vp->note_off_check) { - if (vp->note_off == jiffies) - snd_opl3_note_off_unsafe(opl3, vp->note, 0, - vp->chan); - else - again++; - } - } - spin_unlock_irqrestore(&opl3->voice_lock, flags); - - spin_lock_irqsave(&opl3->sys_timer_lock, flags); - if (again) { - opl3->tlist.expires = jiffies + 1; /* invoke again */ - add_timer(&opl3->tlist); - } else { - opl3->sys_timer_status = 0; - } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); -} - -/* - * Start system timer - */ -static void snd_opl3_start_timer(struct snd_opl3 *opl3) -{ - unsigned long flags; - spin_lock_irqsave(&opl3->sys_timer_lock, flags); - if (! opl3->sys_timer_status) { - opl3->tlist.expires = jiffies + 1; - add_timer(&opl3->tlist); - opl3->sys_timer_status = 1; - } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); -} - -/* ------------------------------ */ - - -static int snd_opl3_oss_map[MAX_OPL3_VOICES] = { - 0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17, 3, 4 ,5, 12, 13, 14 -}; - -/* - * Start a note. - */ -void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - int instr_4op; - - int voice; - struct snd_opl3_voice *vp, *vp2; - unsigned short connect_mask; - unsigned char connection; - unsigned char vol_op[4]; - - int extra_prg = 0; - - unsigned short reg_side; - unsigned char op_offset; - unsigned char voice_offset; - unsigned short opl3_reg; - unsigned char reg_val; - unsigned char prg, bank; - - int key = note; - unsigned char fnum, blocknum; - int i; - - struct fm_patch *patch; - struct fm_instrument *fm; - unsigned long flags; - - opl3 = p; - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n", - chan->number, chan->midi_program, note, vel); -#endif - - /* in SYNTH mode, application takes care of voices */ - /* in SEQ mode, drum voice numbers are notes on drum channel */ - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - if (chan->drum_channel) { - /* percussion instruments are located in bank 128 */ - bank = 128; - prg = note; - } else { - bank = chan->gm_bank_select; - prg = chan->midi_program; - } - } else { - /* Prepare for OSS mode */ - if (chan->number >= MAX_OPL3_VOICES) - return; - - /* OSS instruments are located in bank 127 */ - bank = 127; - prg = chan->midi_program; - } - - spin_lock_irqsave(&opl3->voice_lock, flags); - - if (use_internal_drums) { - snd_opl3_drum_switch(opl3, note, vel, 1, chan); - spin_unlock_irqrestore(&opl3->voice_lock, flags); - return; - } - - __extra_prg: - patch = snd_opl3_find_patch(opl3, prg, bank, 0); - if (!patch) { - spin_unlock_irqrestore(&opl3->voice_lock, flags); - return; - } - - fm = &patch->inst; - switch (patch->type) { - case FM_PATCH_OPL2: - instr_4op = 0; - break; - case FM_PATCH_OPL3: - if (opl3->hardware >= OPL3_HW_OPL3) { - instr_4op = 1; - break; - } - default: - spin_unlock_irqrestore(&opl3->voice_lock, flags); - return; - } -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> OPL%i instrument: %s\n", - instr_4op ? 3 : 2, patch->name); -#endif - /* in SYNTH mode, application takes care of voices */ - /* in SEQ mode, allocate voice on free OPL3 channel */ - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - voice = opl3_get_voice(opl3, instr_4op, chan); - } else { - /* remap OSS voice */ - voice = snd_opl3_oss_map[chan->number]; - } - - if (voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice; - connect_mask = (OPL3_LEFT_4OP_0 << voice_offset) & 0x07; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice - MAX_OPL2_VOICES; - connect_mask = (OPL3_RIGHT_4OP_0 << voice_offset) & 0x38; - } - - /* kill voice on channel */ - vp = &opl3->voices[voice]; - if (vp->state > 0) { - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT; - opl3->command(opl3, opl3_reg, reg_val); - } - if (instr_4op) { - vp2 = &opl3->voices[voice + 3]; - if (vp->state > 0) { - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + - voice_offset + 3); - reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT; - opl3->command(opl3, opl3_reg, reg_val); - } - } - - /* set connection register */ - if (instr_4op) { - if ((opl3->connection_reg ^ connect_mask) & connect_mask) { - opl3->connection_reg |= connect_mask; - /* set connection bit */ - opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT; - opl3->command(opl3, opl3_reg, opl3->connection_reg); - } - } else { - if ((opl3->connection_reg ^ ~connect_mask) & connect_mask) { - opl3->connection_reg &= ~connect_mask; - /* clear connection bit */ - opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT; - opl3->command(opl3, opl3_reg, opl3->connection_reg); - } - } - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> setting OPL3 connection: 0x%x\n", - opl3->connection_reg); -#endif - /* - * calculate volume depending on connection - * between FM operators (see include/opl3.h) - */ - for (i = 0; i < (instr_4op ? 4 : 2); i++) - vol_op[i] = fm->op[i].ksl_level; - - connection = fm->feedback_connection[0] & 0x01; - if (instr_4op) { - connection <<= 1; - connection |= fm->feedback_connection[1] & 0x01; - - snd_opl3_calc_volume(&vol_op[3], vel, chan); - switch (connection) { - case 0x03: - snd_opl3_calc_volume(&vol_op[2], vel, chan); - /* fallthru */ - case 0x02: - snd_opl3_calc_volume(&vol_op[0], vel, chan); - break; - case 0x01: - snd_opl3_calc_volume(&vol_op[1], vel, chan); - } - } else { - snd_opl3_calc_volume(&vol_op[1], vel, chan); - if (connection) - snd_opl3_calc_volume(&vol_op[0], vel, chan); - } - - /* Program the FM voice characteristics */ - for (i = 0; i < (instr_4op ? 4 : 2); i++) { -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> programming operator %i\n", i); -#endif - op_offset = snd_opl3_regmap[voice_offset][i]; - - /* Set OPL3 AM_VIB register of requested voice/operator */ - reg_val = fm->op[i].am_vib; - opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 KSL_LEVEL register of requested voice/operator */ - reg_val = vol_op[i]; - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ - reg_val = fm->op[i].attack_decay; - opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ - reg_val = fm->op[i].sustain_release; - opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Select waveform */ - reg_val = fm->op[i].wave_select; - opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - } - - /* Set operator feedback and 2op inter-operator connection */ - reg_val = fm->feedback_connection[0]; - /* Set output voice connection */ - reg_val |= OPL3_STEREO_BITS; - if (chan->gm_pan < 43) - reg_val &= ~OPL3_VOICE_TO_RIGHT; - if (chan->gm_pan > 85) - reg_val &= ~OPL3_VOICE_TO_LEFT; - opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - if (instr_4op) { - /* Set 4op inter-operator connection */ - reg_val = fm->feedback_connection[1] & OPL3_CONNECTION_BIT; - /* Set output voice connection */ - reg_val |= OPL3_STEREO_BITS; - if (chan->gm_pan < 43) - reg_val &= ~OPL3_VOICE_TO_RIGHT; - if (chan->gm_pan > 85) - reg_val &= ~OPL3_VOICE_TO_LEFT; - opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + - voice_offset + 3); - opl3->command(opl3, opl3_reg, reg_val); - } - - /* - * Special treatment of percussion notes for fm: - * Requested pitch is really program, and pitch for - * device is whatever was specified in the patch library. - */ - if (fm->fix_key) - note = fm->fix_key; - /* - * use transpose if defined in patch library - */ - if (fm->trnsps) - note += (fm->trnsps - 64); - - snd_opl3_calc_pitch(&fnum, &blocknum, note, chan); - - /* Set OPL3 FNUM_LOW register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, fnum); - - opl3->voices[voice].keyon_reg = blocknum; - - /* Set output sound flag */ - blocknum |= OPL3_KEYON_BIT; - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> trigger voice %i\n", voice); -#endif - /* Set OPL3 KEYON_BLOCK register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, blocknum); - - /* kill note after fixed duration (in centiseconds) */ - if (fm->fix_dur) { - opl3->voices[voice].note_off = jiffies + - (fm->fix_dur * HZ) / 100; - snd_opl3_start_timer(opl3); - opl3->voices[voice].note_off_check = 1; - } else - opl3->voices[voice].note_off_check = 0; - - /* get extra pgm, but avoid possible loops */ - extra_prg = (extra_prg) ? 0 : fm->modes; - - /* do the bookkeeping */ - vp->time = opl3->use_time++; - vp->note = key; - vp->chan = chan; - - if (instr_4op) { - vp->state = SNDRV_OPL3_ST_ON_4OP; - - vp2 = &opl3->voices[voice + 3]; - vp2->time = opl3->use_time++; - vp2->note = key; - vp2->chan = chan; - vp2->state = SNDRV_OPL3_ST_NOT_AVAIL; - } else { - if (vp->state == SNDRV_OPL3_ST_ON_4OP) { - /* 4op killed by 2op, release bounded voice */ - vp2 = &opl3->voices[voice + 3]; - vp2->time = opl3->use_time++; - vp2->state = SNDRV_OPL3_ST_OFF; - } - vp->state = SNDRV_OPL3_ST_ON_2OP; - } - -#ifdef DEBUG_ALLOC - debug_alloc(opl3, "note on ", voice); -#endif - - /* allocate extra program if specified in patch library */ - if (extra_prg) { - if (extra_prg > 128) { - bank = 128; - /* percussions start at 35 */ - prg = extra_prg - 128 + 35 - 1; - } else { - bank = 0; - prg = extra_prg - 1; - } -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " *** allocating extra program\n"); -#endif - goto __extra_prg; - } - spin_unlock_irqrestore(&opl3->voice_lock, flags); -} - -static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) -{ - unsigned short reg_side; - unsigned char voice_offset; - unsigned short opl3_reg; - - struct snd_opl3_voice *vp, *vp2; - - if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) - return; - - vp = &opl3->voices[voice]; - if (voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice - MAX_OPL2_VOICES; - } - - /* kill voice */ -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> kill voice %i\n", voice); -#endif - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - /* clear Key ON bit */ - opl3->command(opl3, opl3_reg, vp->keyon_reg); - - /* do the bookkeeping */ - vp->time = opl3->use_time++; - - if (vp->state == SNDRV_OPL3_ST_ON_4OP) { - vp2 = &opl3->voices[voice + 3]; - - vp2->time = opl3->use_time++; - vp2->state = SNDRV_OPL3_ST_OFF; - } - vp->state = SNDRV_OPL3_ST_OFF; -#ifdef DEBUG_ALLOC - debug_alloc(opl3, "note off", voice); -#endif - -} - -/* - * Release a note in response to a midi note off. - */ -static void snd_opl3_note_off_unsafe(void *p, int note, int vel, - struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - int voice; - struct snd_opl3_voice *vp; - - opl3 = p; - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n", - chan->number, chan->midi_program, note); -#endif - - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - if (chan->drum_channel && use_internal_drums) { - snd_opl3_drum_switch(opl3, note, vel, 0, chan); - return; - } - /* this loop will hopefully kill all extra voices, because - they are grouped by the same channel and note values */ - for (voice = 0; voice < opl3->max_voices; voice++) { - vp = &opl3->voices[voice]; - if (vp->state > 0 && vp->chan == chan && vp->note == note) { - snd_opl3_kill_voice(opl3, voice); - } - } - } else { - /* remap OSS voices */ - if (chan->number < MAX_OPL3_VOICES) { - voice = snd_opl3_oss_map[chan->number]; - snd_opl3_kill_voice(opl3, voice); - } - } -} - -void snd_opl3_note_off(void *p, int note, int vel, - struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3 = p; - unsigned long flags; - - spin_lock_irqsave(&opl3->voice_lock, flags); - snd_opl3_note_off_unsafe(p, note, vel, chan); - spin_unlock_irqrestore(&opl3->voice_lock, flags); -} - -/* - * key pressure change - */ -void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif -} - -/* - * terminate note - */ -void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif -} - -static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice) -{ - unsigned short reg_side; - unsigned char voice_offset; - unsigned short opl3_reg; - - unsigned char fnum, blocknum; - - struct snd_opl3_voice *vp; - - if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) - return; - - vp = &opl3->voices[voice]; - if (vp->chan == NULL) - return; /* not allocated? */ - - if (voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice - MAX_OPL2_VOICES; - } - - snd_opl3_calc_pitch(&fnum, &blocknum, vp->note, vp->chan); - - /* Set OPL3 FNUM_LOW register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, fnum); - - vp->keyon_reg = blocknum; - - /* Set output sound flag */ - blocknum |= OPL3_KEYON_BIT; - - /* Set OPL3 KEYON_BLOCK register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, blocknum); - - vp->time = opl3->use_time++; -} - -/* - * Update voice pitch controller - */ -static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel *chan) -{ - int voice; - struct snd_opl3_voice *vp; - - unsigned long flags; - - spin_lock_irqsave(&opl3->voice_lock, flags); - - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - for (voice = 0; voice < opl3->max_voices; voice++) { - vp = &opl3->voices[voice]; - if (vp->state > 0 && vp->chan == chan) { - snd_opl3_update_pitch(opl3, voice); - } - } - } else { - /* remap OSS voices */ - if (chan->number < MAX_OPL3_VOICES) { - voice = snd_opl3_oss_map[chan->number]; - snd_opl3_update_pitch(opl3, voice); - } - } - spin_unlock_irqrestore(&opl3->voice_lock, flags); -} - -/* - * Deal with a controller type event. This includes all types of - * control events, not just the midi controllers - */ -void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n", - type, chan->number, chan->midi_program); -#endif - - switch (type) { - case MIDI_CTL_MSB_MODWHEEL: - if (chan->control[MIDI_CTL_MSB_MODWHEEL] > 63) - opl3->drum_reg |= OPL3_VIBRATO_DEPTH; - else - opl3->drum_reg &= ~OPL3_VIBRATO_DEPTH; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, - opl3->drum_reg); - break; - case MIDI_CTL_E2_TREMOLO_DEPTH: - if (chan->control[MIDI_CTL_E2_TREMOLO_DEPTH] > 63) - opl3->drum_reg |= OPL3_TREMOLO_DEPTH; - else - opl3->drum_reg &= ~OPL3_TREMOLO_DEPTH; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, - opl3->drum_reg); - break; - case MIDI_CTL_PITCHBEND: - snd_opl3_pitch_ctrl(opl3, chan); - break; - } -} - -/* - * NRPN events - */ -void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif -} - -/* - * receive sysex - */ -void snd_opl3_sysex(void *p, unsigned char *buf, int len, - int parsed, struct snd_midi_channel_set *chset) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "SYSEX\n"); -#endif -} diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c deleted file mode 100644 index c1cb249a..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Interface for OSS sequencer emulation - * - * Copyright (C) 2000 Uros Bizjak <uros@kss-loka.si> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/export.h> -#include "opl3_voice.h" - -static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure); -static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg); -static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg); -static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count); -static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg); - -/* */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* operators */ - -extern struct snd_midi_op opl3_ops; - -static struct snd_seq_oss_callback oss_callback = { - .owner = THIS_MODULE, - .open = snd_opl3_open_seq_oss, - .close = snd_opl3_close_seq_oss, - .ioctl = snd_opl3_ioctl_seq_oss, - .load_patch = snd_opl3_load_patch_seq_oss, - .reset = snd_opl3_reset_seq_oss, -}; - -static int snd_opl3_oss_event_input(struct snd_seq_event *ev, int direct, - void *private_data, int atomic, int hop) -{ - struct snd_opl3 *opl3 = private_data; - - if (ev->type != SNDRV_SEQ_EVENT_OSS) - snd_midi_process_event(&opl3_ops, ev, opl3->oss_chset); - return 0; -} - -/* ------------------------------ */ - -static void snd_opl3_oss_free_port(void *private_data) -{ - struct snd_opl3 *opl3 = private_data; - - snd_midi_channel_free_set(opl3->oss_chset); -} - -static int snd_opl3_oss_create_port(struct snd_opl3 * opl3) -{ - struct snd_seq_port_callback callbacks; - char name[32]; - int voices, opl_ver; - - voices = (opl3->hardware < OPL3_HW_OPL3) ? - MAX_OPL2_VOICES : MAX_OPL3_VOICES; - opl3->oss_chset = snd_midi_channel_alloc_set(voices); - if (opl3->oss_chset == NULL) - return -ENOMEM; - opl3->oss_chset->private_data = opl3; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.owner = THIS_MODULE; - callbacks.event_input = snd_opl3_oss_event_input; - callbacks.private_free = snd_opl3_oss_free_port; - callbacks.private_data = opl3; - - opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; - sprintf(name, "OPL%i OSS Port", opl_ver); - - opl3->oss_chset->client = opl3->seq_client; - opl3->oss_chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks, - SNDRV_SEQ_PORT_CAP_WRITE, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_HARDWARE | - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, - voices, voices, - name); - if (opl3->oss_chset->port < 0) { - int port; - port = opl3->oss_chset->port; - snd_midi_channel_free_set(opl3->oss_chset); - return port; - } - return 0; -} - -/* ------------------------------ */ - -/* register OSS synth */ -void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name) -{ - struct snd_seq_oss_reg *arg; - struct snd_seq_device *dev; - - if (snd_seq_device_new(opl3->card, 0, SNDRV_SEQ_DEV_ID_OSS, - sizeof(struct snd_seq_oss_reg), &dev) < 0) - return; - - opl3->oss_seq_dev = dev; - strlcpy(dev->name, name, sizeof(dev->name)); - arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); - arg->type = SYNTH_TYPE_FM; - if (opl3->hardware < OPL3_HW_OPL3) { - arg->subtype = FM_TYPE_ADLIB; - arg->nvoices = MAX_OPL2_VOICES; - } else { - arg->subtype = FM_TYPE_OPL3; - arg->nvoices = MAX_OPL3_VOICES; - } - arg->oper = oss_callback; - arg->private_data = opl3; - - if (snd_opl3_oss_create_port(opl3)) { - /* register to OSS synth table */ - snd_device_register(opl3->card, dev); - } -} - -/* unregister */ -void snd_opl3_free_seq_oss(struct snd_opl3 *opl3) -{ - if (opl3->oss_seq_dev) { - /* The instance should have been released in prior */ - opl3->oss_seq_dev = NULL; - } -} - -/* ------------------------------ */ - -/* open OSS sequencer */ -static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) -{ - struct snd_opl3 *opl3 = closure; - int err; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - - if ((err = snd_opl3_synth_setup(opl3)) < 0) - return err; - - /* fill the argument data */ - arg->private_data = opl3; - arg->addr.client = opl3->oss_chset->client; - arg->addr.port = opl3->oss_chset->port; - - if ((err = snd_opl3_synth_use_inc(opl3)) < 0) - return err; - - opl3->synth_mode = SNDRV_OPL3_MODE_SYNTH; - return 0; -} - -/* close OSS sequencer */ -static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg) -{ - struct snd_opl3 *opl3; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - - snd_opl3_synth_cleanup(opl3); - - snd_opl3_synth_use_dec(opl3); - return 0; -} - -/* load patch */ - -/* from sound_config.h */ -#define SBFM_MAXINSTR 256 - -static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, - const char __user *buf, int offs, int count) -{ - struct snd_opl3 *opl3; - struct sbi_instrument sbi; - char name[32]; - int err, type; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - - if (format == FM_PATCH) - type = FM_PATCH_OPL2; - else if (format == OPL3_PATCH) - type = FM_PATCH_OPL3; - else - return -EINVAL; - - if (count < (int)sizeof(sbi)) { - snd_printk(KERN_ERR "FM Error: Patch record too short\n"); - return -EINVAL; - } - if (copy_from_user(&sbi, buf, sizeof(sbi))) - return -EFAULT; - - if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { - snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n", - sbi.channel); - return -EINVAL; - } - - memset(name, 0, sizeof(name)); - sprintf(name, "Chan%d", sbi.channel); - - err = snd_opl3_load_patch(opl3, sbi.channel, 127, type, name, NULL, - sbi.operators); - if (err < 0) - return err; - - return sizeof(sbi); -} - -/* ioctl */ -static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, - unsigned long ioarg) -{ - struct snd_opl3 *opl3; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - switch (cmd) { - case SNDCTL_FM_LOAD_INSTR: - snd_printk(KERN_ERR "OPL3: " - "Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. " - "Fix the program.\n"); - return -EINVAL; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - - case SNDCTL_FM_4OP_ENABLE: - // handled automatically by OPL instrument type - return 0; - - default: - return -EINVAL; - } - return 0; -} - -/* reset device */ -static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg) -{ - struct snd_opl3 *opl3; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c deleted file mode 100644 index 68399538..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak <uros@kss-loka.si> - * - * Midi Sequencer interface routines for OPL2/OPL3/OPL4 FM - * - * OPL2/3 FM instrument loader: - * alsa-tools/seq/sbiload/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "opl3_voice.h" -#include <linux/init.h> -#include <linux/moduleparam.h> -#include <linux/module.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ALSA driver for OPL3 FM synth"); - -bool use_internal_drums = 0; -module_param(use_internal_drums, bool, 0444); -MODULE_PARM_DESC(use_internal_drums, "Enable internal OPL2/3 drums."); - -int snd_opl3_synth_use_inc(struct snd_opl3 * opl3) -{ - if (!try_module_get(opl3->card->module)) - return -EFAULT; - return 0; - -} - -void snd_opl3_synth_use_dec(struct snd_opl3 * opl3) -{ - module_put(opl3->card->module); -} - -int snd_opl3_synth_setup(struct snd_opl3 * opl3) -{ - int idx; - struct snd_hwdep *hwdep = opl3->hwdep; - - mutex_lock(&hwdep->open_mutex); - if (hwdep->used) { - mutex_unlock(&hwdep->open_mutex); - return -EBUSY; - } - hwdep->used++; - mutex_unlock(&hwdep->open_mutex); - - snd_opl3_reset(opl3); - - for (idx = 0; idx < MAX_OPL3_VOICES; idx++) { - opl3->voices[idx].state = SNDRV_OPL3_ST_OFF; - opl3->voices[idx].time = 0; - opl3->voices[idx].keyon_reg = 0x00; - } - opl3->use_time = 0; - opl3->connection_reg = 0x00; - if (opl3->hardware >= OPL3_HW_OPL3) { - /* Clear 4-op connections */ - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, - opl3->connection_reg); - opl3->max_voices = MAX_OPL3_VOICES; - } - return 0; -} - -void snd_opl3_synth_cleanup(struct snd_opl3 * opl3) -{ - unsigned long flags; - struct snd_hwdep *hwdep; - - /* Stop system timer */ - spin_lock_irqsave(&opl3->sys_timer_lock, flags); - if (opl3->sys_timer_status) { - del_timer(&opl3->tlist); - opl3->sys_timer_status = 0; - } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); - - snd_opl3_reset(opl3); - hwdep = opl3->hwdep; - mutex_lock(&hwdep->open_mutex); - hwdep->used--; - mutex_unlock(&hwdep->open_mutex); - wake_up(&hwdep->open_wait); -} - -static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe * info) -{ - struct snd_opl3 *opl3 = private_data; - int err; - - if ((err = snd_opl3_synth_setup(opl3)) < 0) - return err; - - if (use_internal_drums) { - /* Percussion mode */ - opl3->voices[6].state = opl3->voices[7].state = - opl3->voices[8].state = SNDRV_OPL3_ST_NOT_AVAIL; - snd_opl3_load_drums(opl3); - opl3->drum_reg = OPL3_PERCUSSION_ENABLE; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, opl3->drum_reg); - } else { - opl3->drum_reg = 0x00; - } - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { - if ((err = snd_opl3_synth_use_inc(opl3)) < 0) - return err; - } - opl3->synth_mode = SNDRV_OPL3_MODE_SEQ; - return 0; -} - -static int snd_opl3_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info) -{ - struct snd_opl3 *opl3 = private_data; - - snd_opl3_synth_cleanup(opl3); - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) - snd_opl3_synth_use_dec(opl3); - return 0; -} - -/* - * MIDI emulation operators - */ -struct snd_midi_op opl3_ops = { - .note_on = snd_opl3_note_on, - .note_off = snd_opl3_note_off, - .key_press = snd_opl3_key_press, - .note_terminate = snd_opl3_terminate_note, - .control = snd_opl3_control, - .nrpn = snd_opl3_nrpn, - .sysex = snd_opl3_sysex, -}; - -static int snd_opl3_synth_event_input(struct snd_seq_event * ev, int direct, - void *private_data, int atomic, int hop) -{ - struct snd_opl3 *opl3 = private_data; - - snd_midi_process_event(&opl3_ops, ev, opl3->chset); - return 0; -} - -/* ------------------------------ */ - -static void snd_opl3_synth_free_port(void *private_data) -{ - struct snd_opl3 *opl3 = private_data; - - snd_midi_channel_free_set(opl3->chset); -} - -static int snd_opl3_synth_create_port(struct snd_opl3 * opl3) -{ - struct snd_seq_port_callback callbacks; - char name[32]; - int voices, opl_ver; - - voices = (opl3->hardware < OPL3_HW_OPL3) ? - MAX_OPL2_VOICES : MAX_OPL3_VOICES; - opl3->chset = snd_midi_channel_alloc_set(16); - if (opl3->chset == NULL) - return -ENOMEM; - opl3->chset->private_data = opl3; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.owner = THIS_MODULE; - callbacks.use = snd_opl3_synth_use; - callbacks.unuse = snd_opl3_synth_unuse; - callbacks.event_input = snd_opl3_synth_event_input; - callbacks.private_free = snd_opl3_synth_free_port; - callbacks.private_data = opl3; - - opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; - sprintf(name, "OPL%i FM Port", opl_ver); - - opl3->chset->client = opl3->seq_client; - opl3->chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks, - SNDRV_SEQ_PORT_CAP_WRITE | - SNDRV_SEQ_PORT_CAP_SUBS_WRITE, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | - SNDRV_SEQ_PORT_TYPE_HARDWARE | - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, - 16, voices, - name); - if (opl3->chset->port < 0) { - int port; - port = opl3->chset->port; - snd_midi_channel_free_set(opl3->chset); - return port; - } - return 0; -} - -/* ------------------------------ */ - -static int snd_opl3_seq_new_device(struct snd_seq_device *dev) -{ - struct snd_opl3 *opl3; - int client, err; - char name[32]; - int opl_ver; - - opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (opl3 == NULL) - return -EINVAL; - - spin_lock_init(&opl3->voice_lock); - - opl3->seq_client = -1; - - /* allocate new client */ - opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; - sprintf(name, "OPL%i FM synth", opl_ver); - client = opl3->seq_client = - snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num, - name); - if (client < 0) - return client; - - if ((err = snd_opl3_synth_create_port(opl3)) < 0) { - snd_seq_delete_kernel_client(client); - opl3->seq_client = -1; - return err; - } - - /* setup system timer */ - init_timer(&opl3->tlist); - opl3->tlist.function = snd_opl3_timer_func; - opl3->tlist.data = (unsigned long) opl3; - spin_lock_init(&opl3->sys_timer_lock); - opl3->sys_timer_status = 0; - -#ifdef CONFIG_SND_SEQUENCER_OSS - snd_opl3_init_seq_oss(opl3, name); -#endif - return 0; -} - -static int snd_opl3_seq_delete_device(struct snd_seq_device *dev) -{ - struct snd_opl3 *opl3; - - opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (opl3 == NULL) - return -EINVAL; - -#ifdef CONFIG_SND_SEQUENCER_OSS - snd_opl3_free_seq_oss(opl3); -#endif - if (opl3->seq_client >= 0) { - snd_seq_delete_kernel_client(opl3->seq_client); - opl3->seq_client = -1; - } - return 0; -} - -static int __init alsa_opl3_seq_init(void) -{ - static struct snd_seq_dev_ops ops = - { - snd_opl3_seq_new_device, - snd_opl3_seq_delete_device - }; - - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL3, &ops, - sizeof(struct snd_opl3 *)); -} - -static void __exit alsa_opl3_seq_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL3); -} - -module_init(alsa_opl3_seq_init) -module_exit(alsa_opl3_seq_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c deleted file mode 100644 index 742a4b64..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak <uros@kss-loka.si> - * - * Routines for OPL2/OPL3/OPL4 control - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/slab.h> -#include <linux/export.h> -#include <sound/opl3.h> -#include <sound/asound_fm.h> - -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) -#define OPL3_SUPPORT_SYNTH -#endif - -/* - * There is 18 possible 2 OP voices - * (9 in the left and 9 in the right). - * The first OP is the modulator and 2nd is the carrier. - * - * The first three voices in the both sides may be connected - * with another voice to a 4 OP voice. For example voice 0 - * can be connected with voice 3. The operators of voice 3 are - * used as operators 3 and 4 of the new 4 OP voice. - * In this case the 2 OP voice number 0 is the 'first half' and - * voice 3 is the second. - */ - - -/* - * Register offset table for OPL2/3 voices, - * OPL2 / one OPL3 register array side only - */ - -char snd_opl3_regmap[MAX_OPL2_VOICES][4] = -{ -/* OP1 OP2 OP3 OP4 */ -/* ------------------------ */ - { 0x00, 0x03, 0x08, 0x0b }, - { 0x01, 0x04, 0x09, 0x0c }, - { 0x02, 0x05, 0x0a, 0x0d }, - - { 0x08, 0x0b, 0x00, 0x00 }, - { 0x09, 0x0c, 0x00, 0x00 }, - { 0x0a, 0x0d, 0x00, 0x00 }, - - { 0x10, 0x13, 0x00, 0x00 }, /* used by percussive voices */ - { 0x11, 0x14, 0x00, 0x00 }, /* if the percussive mode */ - { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ -}; - -EXPORT_SYMBOL(snd_opl3_regmap); - -/* - * prototypes - */ -static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note); -static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice); -static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params); -static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode); -static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection); - -/* ------------------------------ */ - -/* - * open the device exclusively - */ -int snd_opl3_open(struct snd_hwdep * hw, struct file *file) -{ - return 0; -} - -/* - * ioctl for hwdep device: - */ -int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct snd_opl3 *opl3 = hw->private_data; - void __user *argp = (void __user *)arg; - - if (snd_BUG_ON(!opl3)) - return -EINVAL; - - switch (cmd) { - /* get information */ - case SNDRV_DM_FM_IOCTL_INFO: - { - struct snd_dm_fm_info info; - - info.fm_mode = opl3->fm_mode; - info.rhythm = opl3->rhythm; - if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info))) - return -EFAULT; - return 0; - } - - case SNDRV_DM_FM_IOCTL_RESET: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_RESET: -#endif - snd_opl3_reset(opl3); - return 0; - - case SNDRV_DM_FM_IOCTL_PLAY_NOTE: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE: -#endif - { - struct snd_dm_fm_note note; - if (copy_from_user(¬e, argp, sizeof(struct snd_dm_fm_note))) - return -EFAULT; - return snd_opl3_play_note(opl3, ¬e); - } - - case SNDRV_DM_FM_IOCTL_SET_VOICE: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE: -#endif - { - struct snd_dm_fm_voice voice; - if (copy_from_user(&voice, argp, sizeof(struct snd_dm_fm_voice))) - return -EFAULT; - return snd_opl3_set_voice(opl3, &voice); - } - - case SNDRV_DM_FM_IOCTL_SET_PARAMS: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS: -#endif - { - struct snd_dm_fm_params params; - if (copy_from_user(¶ms, argp, sizeof(struct snd_dm_fm_params))) - return -EFAULT; - return snd_opl3_set_params(opl3, ¶ms); - } - - case SNDRV_DM_FM_IOCTL_SET_MODE: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_MODE: -#endif - return snd_opl3_set_mode(opl3, (int) arg); - - case SNDRV_DM_FM_IOCTL_SET_CONNECTION: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_OPL: -#endif - return snd_opl3_set_connection(opl3, (int) arg); - -#ifdef OPL3_SUPPORT_SYNTH - case SNDRV_DM_FM_IOCTL_CLEAR_PATCHES: - snd_opl3_clear_patches(opl3); - return 0; -#endif - -#ifdef CONFIG_SND_DEBUG - default: - snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd); -#endif - } - return -ENOTTY; -} - -/* - * close the device - */ -int snd_opl3_release(struct snd_hwdep * hw, struct file *file) -{ - struct snd_opl3 *opl3 = hw->private_data; - - snd_opl3_reset(opl3); - return 0; -} - -#ifdef OPL3_SUPPORT_SYNTH -/* - * write the device - load patches - */ -long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count, - loff_t *offset) -{ - struct snd_opl3 *opl3 = hw->private_data; - long result = 0; - int err = 0; - struct sbi_patch inst; - - while (count >= sizeof(inst)) { - unsigned char type; - if (copy_from_user(&inst, buf, sizeof(inst))) - return -EFAULT; - if (!memcmp(inst.key, FM_KEY_SBI, 4) || - !memcmp(inst.key, FM_KEY_2OP, 4)) - type = FM_PATCH_OPL2; - else if (!memcmp(inst.key, FM_KEY_4OP, 4)) - type = FM_PATCH_OPL3; - else /* invalid type */ - break; - err = snd_opl3_load_patch(opl3, inst.prog, inst.bank, type, - inst.name, inst.extension, - inst.data); - if (err < 0) - break; - result += sizeof(inst); - count -= sizeof(inst); - } - return result > 0 ? result : err; -} - - -/* - * Patch management - */ - -/* offsets for SBI params */ -#define AM_VIB 0 -#define KSL_LEVEL 2 -#define ATTACK_DECAY 4 -#define SUSTAIN_RELEASE 6 -#define WAVE_SELECT 8 - -/* offset for SBI instrument */ -#define CONNECTION 10 -#define OFFSET_4OP 11 - -/* - * load a patch, obviously. - * - * loaded on the given program and bank numbers with the given type - * (FM_PATCH_OPLx). - * data is the pointer of SBI record _without_ header (key and name). - * name is the name string of the patch. - * ext is the extension data of 7 bytes long (stored in name of SBI - * data up to offset 25), or NULL to skip. - * return 0 if successful or a negative error code. - */ -int snd_opl3_load_patch(struct snd_opl3 *opl3, - int prog, int bank, int type, - const char *name, - const unsigned char *ext, - const unsigned char *data) -{ - struct fm_patch *patch; - int i; - - patch = snd_opl3_find_patch(opl3, prog, bank, 1); - if (!patch) - return -ENOMEM; - - patch->type = type; - - for (i = 0; i < 2; i++) { - patch->inst.op[i].am_vib = data[AM_VIB + i]; - patch->inst.op[i].ksl_level = data[KSL_LEVEL + i]; - patch->inst.op[i].attack_decay = data[ATTACK_DECAY + i]; - patch->inst.op[i].sustain_release = data[SUSTAIN_RELEASE + i]; - patch->inst.op[i].wave_select = data[WAVE_SELECT + i]; - } - patch->inst.feedback_connection[0] = data[CONNECTION]; - - if (type == FM_PATCH_OPL3) { - for (i = 0; i < 2; i++) { - patch->inst.op[i+2].am_vib = - data[OFFSET_4OP + AM_VIB + i]; - patch->inst.op[i+2].ksl_level = - data[OFFSET_4OP + KSL_LEVEL + i]; - patch->inst.op[i+2].attack_decay = - data[OFFSET_4OP + ATTACK_DECAY + i]; - patch->inst.op[i+2].sustain_release = - data[OFFSET_4OP + SUSTAIN_RELEASE + i]; - patch->inst.op[i+2].wave_select = - data[OFFSET_4OP + WAVE_SELECT + i]; - } - patch->inst.feedback_connection[1] = - data[OFFSET_4OP + CONNECTION]; - } - - if (ext) { - patch->inst.echo_delay = ext[0]; - patch->inst.echo_atten = ext[1]; - patch->inst.chorus_spread = ext[2]; - patch->inst.trnsps = ext[3]; - patch->inst.fix_dur = ext[4]; - patch->inst.modes = ext[5]; - patch->inst.fix_key = ext[6]; - } - - if (name) - strlcpy(patch->name, name, sizeof(patch->name)); - - return 0; -} -EXPORT_SYMBOL(snd_opl3_load_patch); - -/* - * find a patch with the given program and bank numbers, returns its pointer - * if no matching patch is found and create_patch is set, it creates a - * new patch object. - */ -struct fm_patch *snd_opl3_find_patch(struct snd_opl3 *opl3, int prog, int bank, - int create_patch) -{ - /* pretty dumb hash key */ - unsigned int key = (prog + bank) % OPL3_PATCH_HASH_SIZE; - struct fm_patch *patch; - - for (patch = opl3->patch_table[key]; patch; patch = patch->next) { - if (patch->prog == prog && patch->bank == bank) - return patch; - } - if (!create_patch) - return NULL; - - patch = kzalloc(sizeof(*patch), GFP_KERNEL); - if (!patch) - return NULL; - patch->prog = prog; - patch->bank = bank; - patch->next = opl3->patch_table[key]; - opl3->patch_table[key] = patch; - return patch; -} -EXPORT_SYMBOL(snd_opl3_find_patch); - -/* - * Clear all patches of the given OPL3 instance - */ -void snd_opl3_clear_patches(struct snd_opl3 *opl3) -{ - int i; - for (i = 0; i < OPL3_PATCH_HASH_SIZE; i++) { - struct fm_patch *patch, *next; - for (patch = opl3->patch_table[i]; patch; patch = next) { - next = patch->next; - kfree(patch); - } - } - memset(opl3->patch_table, 0, sizeof(opl3->patch_table)); -} -#endif /* OPL3_SUPPORT_SYNTH */ - -/* ------------------------------ */ - -void snd_opl3_reset(struct snd_opl3 * opl3) -{ - unsigned short opl3_reg; - - unsigned short reg_side; - unsigned char voice_offset; - - int max_voices, i; - - max_voices = (opl3->hardware < OPL3_HW_OPL3) ? - MAX_OPL2_VOICES : MAX_OPL3_VOICES; - - for (i = 0; i < max_voices; i++) { - /* Get register array side and offset of voice */ - if (i < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = i; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = i - MAX_OPL2_VOICES; - } - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][0]); - opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 1 volume */ - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][1]); - opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 2 volume */ - - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, 0x00); /* Note off */ - } - - opl3->max_voices = MAX_OPL2_VOICES; - opl3->fm_mode = SNDRV_DM_FM_MODE_OPL2; - - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */ - opl3->rhythm = 0; -} - -EXPORT_SYMBOL(snd_opl3_reset); - -static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note) -{ - unsigned short reg_side; - unsigned char voice_offset; - - unsigned short opl3_reg; - unsigned char reg_val; - - /* Voices 0 - 8 in OPL2 mode */ - /* Voices 0 - 17 in OPL3 mode */ - if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? - MAX_OPL3_VOICES : MAX_OPL2_VOICES)) - return -EINVAL; - - /* Get register array side and offset of voice */ - if (note->voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = note->voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = note->voice - MAX_OPL2_VOICES; - } - - /* Set lower 8 bits of note frequency */ - reg_val = (unsigned char) note->fnum; - opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - reg_val = 0x00; - /* Set output sound flag */ - if (note->key_on) - reg_val |= OPL3_KEYON_BIT; - /* Set octave */ - reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK; - /* Set higher 2 bits of note frequency */ - reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK; - - /* Set OPL3 KEYON_BLOCK register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - return 0; -} - - -static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice) -{ - unsigned short reg_side; - unsigned char op_offset; - unsigned char voice_offset; - - unsigned short opl3_reg; - unsigned char reg_val; - - /* Only operators 1 and 2 */ - if (voice->op > 1) - return -EINVAL; - /* Voices 0 - 8 in OPL2 mode */ - /* Voices 0 - 17 in OPL3 mode */ - if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? - MAX_OPL3_VOICES : MAX_OPL2_VOICES)) - return -EINVAL; - - /* Get register array side and offset of voice */ - if (voice->voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice->voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice->voice - MAX_OPL2_VOICES; - } - /* Get register offset of operator */ - op_offset = snd_opl3_regmap[voice_offset][voice->op]; - - reg_val = 0x00; - /* Set amplitude modulation (tremolo) effect */ - if (voice->am) - reg_val |= OPL3_TREMOLO_ON; - /* Set vibrato effect */ - if (voice->vibrato) - reg_val |= OPL3_VIBRATO_ON; - /* Set sustaining sound phase */ - if (voice->do_sustain) - reg_val |= OPL3_SUSTAIN_ON; - /* Set keyboard scaling bit */ - if (voice->kbd_scale) - reg_val |= OPL3_KSR; - /* Set harmonic or frequency multiplier */ - reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK; - - /* Set OPL3 AM_VIB register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set decreasing volume of higher notes */ - reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK; - /* Set output volume */ - reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK; - - /* Set OPL3 KSL_LEVEL register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set attack phase level */ - reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK; - /* Set decay phase level */ - reg_val |= voice->decay & OPL3_DECAY_MASK; - - /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set sustain phase level */ - reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK; - /* Set release phase level */ - reg_val |= voice->release & OPL3_RELEASE_MASK; - - /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set inter-operator feedback */ - reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK; - /* Set inter-operator connection */ - if (voice->connection) - reg_val |= OPL3_CONNECTION_BIT; - /* OPL-3 only */ - if (opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) { - if (voice->left) - reg_val |= OPL3_VOICE_TO_LEFT; - if (voice->right) - reg_val |= OPL3_VOICE_TO_RIGHT; - } - /* Feedback/connection bits are applicable to voice */ - opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Select waveform */ - reg_val = voice->waveform & OPL3_WAVE_SELECT_MASK; - opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - return 0; -} - -static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params) -{ - unsigned char reg_val; - - reg_val = 0x00; - /* Set keyboard split method */ - if (params->kbd_split) - reg_val |= OPL3_KEYBOARD_SPLIT; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_KBD_SPLIT, reg_val); - - reg_val = 0x00; - /* Set amplitude modulation (tremolo) depth */ - if (params->am_depth) - reg_val |= OPL3_TREMOLO_DEPTH; - /* Set vibrato depth */ - if (params->vib_depth) - reg_val |= OPL3_VIBRATO_DEPTH; - /* Set percussion mode */ - if (params->rhythm) { - reg_val |= OPL3_PERCUSSION_ENABLE; - opl3->rhythm = 1; - } else { - opl3->rhythm = 0; - } - /* Play percussion instruments */ - if (params->bass) - reg_val |= OPL3_BASSDRUM_ON; - if (params->snare) - reg_val |= OPL3_SNAREDRUM_ON; - if (params->tomtom) - reg_val |= OPL3_TOMTOM_ON; - if (params->cymbal) - reg_val |= OPL3_CYMBAL_ON; - if (params->hihat) - reg_val |= OPL3_HIHAT_ON; - - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, reg_val); - return 0; -} - -static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode) -{ - if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3)) - return -EINVAL; - - opl3->fm_mode = mode; - if (opl3->hardware >= OPL3_HW_OPL3) - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 0x00); /* Clear 4-op connections */ - - return 0; -} - -static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection) -{ - unsigned char reg_val; - - /* OPL-3 only */ - if (opl3->fm_mode != SNDRV_DM_FM_MODE_OPL3) - return -EINVAL; - - reg_val = connection & (OPL3_RIGHT_4OP_0 | OPL3_RIGHT_4OP_1 | OPL3_RIGHT_4OP_2 | - OPL3_LEFT_4OP_0 | OPL3_LEFT_4OP_1 | OPL3_LEFT_4OP_2); - /* Set 4-op connections */ - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val); - - return 0; -} - diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h b/ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h deleted file mode 100644 index a371c075..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __OPL3_VOICE_H -#define __OPL3_VOICE_H - -/* - * Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <sound/opl3.h> - -/* Prototypes for opl3_seq.c */ -int snd_opl3_synth_use_inc(struct snd_opl3 * opl3); -void snd_opl3_synth_use_dec(struct snd_opl3 * opl3); -int snd_opl3_synth_setup(struct snd_opl3 * opl3); -void snd_opl3_synth_cleanup(struct snd_opl3 * opl3); - -/* Prototypes for opl3_midi.c */ -void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan); -void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan); -void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, struct snd_midi_channel_set *chset); -void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset); - -void snd_opl3_calc_volume(unsigned char *reg, int vel, struct snd_midi_channel *chan); -void snd_opl3_timer_func(unsigned long data); - -/* Prototypes for opl3_drums.c */ -void snd_opl3_load_drums(struct snd_opl3 *opl3); -void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int on_off, int vel, struct snd_midi_channel *chan); - -/* Prototypes for opl3_oss.c */ -#ifdef CONFIG_SND_SEQUENCER_OSS -void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name); -void snd_opl3_free_seq_oss(struct snd_opl3 *opl3); -#endif - -#endif diff --git a/ANDROID_3.4.5/sound/drivers/opl4/Makefile b/ANDROID_3.4.5/sound/drivers/opl4/Makefile deleted file mode 100644 index b94009b0..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o -snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o - -obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o -obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-opl4-synth.o diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c deleted file mode 100644 index b953fb4a..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Functions for accessing OPL4 devices - * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "opl4_local.h" -#include <sound/initval.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/module.h> -#include <asm/io.h> - -MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); -MODULE_DESCRIPTION("OPL4 driver"); -MODULE_LICENSE("GPL"); - -static void inline snd_opl4_wait(struct snd_opl4 *opl4) -{ - int timeout = 10; - while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0) - ; -} - -void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value) -{ - snd_opl4_wait(opl4); - outb(reg, opl4->pcm_port); - - snd_opl4_wait(opl4); - outb(value, opl4->pcm_port + 1); -} - -EXPORT_SYMBOL(snd_opl4_write); - -u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) -{ - snd_opl4_wait(opl4); - outb(reg, opl4->pcm_port); - - snd_opl4_wait(opl4); - return inb(opl4->pcm_port + 1); -} - -EXPORT_SYMBOL(snd_opl4_read); - -void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) -{ - unsigned long flags; - u8 memcfg; - - spin_lock_irqsave(&opl4->reg_lock, flags); - - memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); - - snd_opl4_wait(opl4); - outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port); - snd_opl4_wait(opl4); - insb(opl4->pcm_port + 1, buf, size); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); - - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -EXPORT_SYMBOL(snd_opl4_read_memory); - -void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) -{ - unsigned long flags; - u8 memcfg; - - spin_lock_irqsave(&opl4->reg_lock, flags); - - memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); - - snd_opl4_wait(opl4); - outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port); - snd_opl4_wait(opl4); - outsb(opl4->pcm_port + 1, buf, size); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); - - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -EXPORT_SYMBOL(snd_opl4_write_memory); - -static void snd_opl4_enable_opl4(struct snd_opl4 *opl4) -{ - outb(OPL3_REG_MODE, opl4->fm_port + 2); - inb(opl4->fm_port); - inb(opl4->fm_port); - outb(OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE, opl4->fm_port + 3); - inb(opl4->fm_port); - inb(opl4->fm_port); -} - -static int snd_opl4_detect(struct snd_opl4 *opl4) -{ - u8 id1, id2; - - snd_opl4_enable_opl4(opl4); - - id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); - snd_printdd("OPL4[02]=%02x\n", id1); - switch (id1 & OPL4_DEVICE_ID_MASK) { - case 0x20: - opl4->hardware = OPL3_HW_OPL4; - break; - case 0x40: - opl4->hardware = OPL3_HW_OPL4_ML; - break; - default: - return -ENODEV; - } - - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00); - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff); - id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM); - id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM); - snd_printdd("OPL4 id1=%02x id2=%02x\n", id1, id2); - if (id1 != 0x00 || id2 != 0xff) - return -ENODEV; - - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f); - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f); - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00); - return 0; -} - -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) -static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev) -{ - struct snd_opl4 *opl4 = seq_dev->private_data; - opl4->seq_dev = NULL; -} - -static int snd_opl4_create_seq_dev(struct snd_opl4 *opl4, int seq_device) -{ - opl4->seq_dev_num = seq_device; - if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4, - sizeof(struct snd_opl4 *), &opl4->seq_dev) >= 0) { - strcpy(opl4->seq_dev->name, "OPL4 Wavetable"); - *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4; - opl4->seq_dev->private_data = opl4; - opl4->seq_dev->private_free = snd_opl4_seq_dev_free; - } - return 0; -} -#endif - -static void snd_opl4_free(struct snd_opl4 *opl4) -{ -#ifdef CONFIG_PROC_FS - snd_opl4_free_proc(opl4); -#endif - release_and_free_resource(opl4->res_fm_port); - release_and_free_resource(opl4->res_pcm_port); - kfree(opl4); -} - -static int snd_opl4_dev_free(struct snd_device *device) -{ - struct snd_opl4 *opl4 = device->device_data; - snd_opl4_free(opl4); - return 0; -} - -int snd_opl4_create(struct snd_card *card, - unsigned long fm_port, unsigned long pcm_port, - int seq_device, - struct snd_opl3 **ropl3, struct snd_opl4 **ropl4) -{ - struct snd_opl4 *opl4; - struct snd_opl3 *opl3; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_opl4_dev_free - }; - - if (ropl3) - *ropl3 = NULL; - if (ropl4) - *ropl4 = NULL; - - opl4 = kzalloc(sizeof(*opl4), GFP_KERNEL); - if (!opl4) - return -ENOMEM; - - opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM"); - opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX"); - if (!opl4->res_fm_port || !opl4->res_pcm_port) { - snd_printk(KERN_ERR "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port); - snd_opl4_free(opl4); - return -EBUSY; - } - - opl4->card = card; - opl4->fm_port = fm_port; - opl4->pcm_port = pcm_port; - spin_lock_init(&opl4->reg_lock); - mutex_init(&opl4->access_mutex); - - err = snd_opl4_detect(opl4); - if (err < 0) { - snd_opl4_free(opl4); - snd_printd("OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port); - return err; - } - - err = snd_device_new(card, SNDRV_DEV_CODEC, opl4, &ops); - if (err < 0) { - snd_opl4_free(opl4); - return err; - } - - err = snd_opl3_create(card, fm_port, fm_port + 2, opl4->hardware, 1, &opl3); - if (err < 0) { - snd_device_free(card, opl4); - return err; - } - - /* opl3 initialization disabled opl4, so reenable */ - snd_opl4_enable_opl4(opl4); - - snd_opl4_create_mixer(opl4); -#ifdef CONFIG_PROC_FS - snd_opl4_create_proc(opl4); -#endif - -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - opl4->seq_client = -1; - if (opl4->hardware < OPL3_HW_OPL4_ML) - snd_opl4_create_seq_dev(opl4, seq_device); -#endif - - if (ropl3) - *ropl3 = opl3; - if (ropl4) - *ropl4 = opl4; - return 0; -} - -EXPORT_SYMBOL(snd_opl4_create); - -static int __init alsa_opl4_init(void) -{ - return 0; -} - -static void __exit alsa_opl4_exit(void) -{ -} - -module_init(alsa_opl4_init) -module_exit(alsa_opl4_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h b/ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h deleted file mode 100644 index 470e5a75..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Local definitions for the OPL4 driver - * - * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef __OPL4_LOCAL_H -#define __OPL4_LOCAL_H - -#include <sound/opl4.h> - -/* - * Register numbers - */ - -#define OPL4_REG_TEST0 0x00 -#define OPL4_REG_TEST1 0x01 - -#define OPL4_REG_MEMORY_CONFIGURATION 0x02 -#define OPL4_MODE_BIT 0x01 -#define OPL4_MTYPE_BIT 0x02 -#define OPL4_TONE_HEADER_MASK 0x1c -#define OPL4_DEVICE_ID_MASK 0xe0 - -#define OPL4_REG_MEMORY_ADDRESS_HIGH 0x03 -#define OPL4_REG_MEMORY_ADDRESS_MID 0x04 -#define OPL4_REG_MEMORY_ADDRESS_LOW 0x05 -#define OPL4_REG_MEMORY_DATA 0x06 - -/* - * Offsets to the register banks for voices. To get the - * register number just add the voice number to the bank offset. - * - * Wave Table Number low bits (0x08 to 0x1F) - */ -#define OPL4_REG_TONE_NUMBER 0x08 - -/* Wave Table Number high bit, F-Number low bits (0x20 to 0x37) */ -#define OPL4_REG_F_NUMBER 0x20 -#define OPL4_TONE_NUMBER_BIT8 0x01 -#define OPL4_F_NUMBER_LOW_MASK 0xfe - -/* F-Number high bits, Octave, Pseudo-Reverb (0x38 to 0x4F) */ -#define OPL4_REG_OCTAVE 0x38 -#define OPL4_F_NUMBER_HIGH_MASK 0x07 -#define OPL4_BLOCK_MASK 0xf0 -#define OPL4_PSEUDO_REVERB_BIT 0x08 - -/* Total Level, Level Direct (0x50 to 0x67) */ -#define OPL4_REG_LEVEL 0x50 -#define OPL4_TOTAL_LEVEL_MASK 0xfe -#define OPL4_LEVEL_DIRECT_BIT 0x01 - -/* Key On, Damp, LFO RST, CH, Panpot (0x68 to 0x7F) */ -#define OPL4_REG_MISC 0x68 -#define OPL4_KEY_ON_BIT 0x80 -#define OPL4_DAMP_BIT 0x40 -#define OPL4_LFO_RESET_BIT 0x20 -#define OPL4_OUTPUT_CHANNEL_BIT 0x10 -#define OPL4_PAN_POT_MASK 0x0f - -/* LFO, VIB (0x80 to 0x97) */ -#define OPL4_REG_LFO_VIBRATO 0x80 -#define OPL4_LFO_FREQUENCY_MASK 0x38 -#define OPL4_VIBRATO_DEPTH_MASK 0x07 -#define OPL4_CHORUS_SEND_MASK 0xc0 /* ML only */ - -/* Attack / Decay 1 rate (0x98 to 0xAF) */ -#define OPL4_REG_ATTACK_DECAY1 0x98 -#define OPL4_ATTACK_RATE_MASK 0xf0 -#define OPL4_DECAY1_RATE_MASK 0x0f - -/* Decay level / 2 rate (0xB0 to 0xC7) */ -#define OPL4_REG_LEVEL_DECAY2 0xb0 -#define OPL4_DECAY_LEVEL_MASK 0xf0 -#define OPL4_DECAY2_RATE_MASK 0x0f - -/* Release rate / Rate correction (0xC8 to 0xDF) */ -#define OPL4_REG_RELEASE_CORRECTION 0xc8 -#define OPL4_RELEASE_RATE_MASK 0x0f -#define OPL4_RATE_INTERPOLATION_MASK 0xf0 - -/* AM (0xE0 to 0xF7) */ -#define OPL4_REG_TREMOLO 0xe0 -#define OPL4_TREMOLO_DEPTH_MASK 0x07 -#define OPL4_REVERB_SEND_MASK 0xe0 /* ML only */ - -/* Mixer */ -#define OPL4_REG_MIX_CONTROL_FM 0xf8 -#define OPL4_REG_MIX_CONTROL_PCM 0xf9 -#define OPL4_MIX_LEFT_MASK 0x07 -#define OPL4_MIX_RIGHT_MASK 0x38 - -#define OPL4_REG_ATC 0xfa -#define OPL4_ATC_BIT 0x01 /* ???, ML only */ - -/* bits in the OPL3 Status register */ -#define OPL4_STATUS_BUSY 0x01 -#define OPL4_STATUS_LOAD 0x02 - - -#define OPL4_MAX_VOICES 24 - -#define SNDRV_SEQ_DEV_ID_OPL4 "opl4-synth" - - -struct opl4_sound { - u16 tone; - s16 pitch_offset; - u8 key_scaling; - s8 panpot; - u8 vibrato; - u8 tone_attenuate; - u8 volume_factor; - u8 reg_lfo_vibrato; - u8 reg_attack_decay1; - u8 reg_level_decay2; - u8 reg_release_correction; - u8 reg_tremolo; -}; - -struct opl4_region { - u8 key_min, key_max; - struct opl4_sound sound; -}; - -struct opl4_region_ptr { - int count; - const struct opl4_region *regions; -}; - -struct opl4_voice { - struct list_head list; - int number; - struct snd_midi_channel *chan; - int note; - int velocity; - const struct opl4_sound *sound; - u8 level_direct; - u8 reg_f_number; - u8 reg_misc; - u8 reg_lfo_vibrato; -}; - -struct snd_opl4 { - unsigned long fm_port; - unsigned long pcm_port; - struct resource *res_fm_port; - struct resource *res_pcm_port; - unsigned short hardware; - spinlock_t reg_lock; - struct snd_card *card; - -#ifdef CONFIG_PROC_FS - struct snd_info_entry *proc_entry; - int memory_access; -#endif - struct mutex access_mutex; - -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) - int used; - - int seq_dev_num; - int seq_client; - struct snd_seq_device *seq_dev; - - struct snd_midi_channel_set *chset; - struct opl4_voice voices[OPL4_MAX_VOICES]; - struct list_head off_voices; - struct list_head on_voices; -#endif -}; - -/* opl4_lib.c */ -void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value); -u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg); -void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size); -void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size); - -/* opl4_mixer.c */ -int snd_opl4_create_mixer(struct snd_opl4 *opl4); - -#ifdef CONFIG_PROC_FS -/* opl4_proc.c */ -int snd_opl4_create_proc(struct snd_opl4 *opl4); -void snd_opl4_free_proc(struct snd_opl4 *opl4); -#endif - -/* opl4_seq.c */ -extern int volume_boost; - -/* opl4_synth.c */ -void snd_opl4_synth_reset(struct snd_opl4 *opl4); -void snd_opl4_synth_shutdown(struct snd_opl4 *opl4); -void snd_opl4_note_on(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl4_note_off(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl4_terminate_note(void *p, int note, struct snd_midi_channel *chan); -void snd_opl4_control(void *p, int type, struct snd_midi_channel *chan); -void snd_opl4_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset); - -/* yrw801.c */ -int snd_yrw801_detect(struct snd_opl4 *opl4); -extern const struct opl4_region_ptr snd_yrw801_regions[]; - -#endif /* __OPL4_LOCAL_H */ diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c deleted file mode 100644 index 04079de4..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * OPL4 mixer functions - * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "opl4_local.h" -#include <sound/control.h> - -static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 7; - return 0; -} - -static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); - unsigned long flags; - u8 reg = kcontrol->private_value; - u8 value; - - spin_lock_irqsave(&opl4->reg_lock, flags); - value = snd_opl4_read(opl4, reg); - spin_unlock_irqrestore(&opl4->reg_lock, flags); - ucontrol->value.integer.value[0] = 7 - (value & 7); - ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); - return 0; -} - -static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); - unsigned long flags; - u8 reg = kcontrol->private_value; - u8 value, old_value; - - value = (7 - (ucontrol->value.integer.value[0] & 7)) | - ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); - spin_lock_irqsave(&opl4->reg_lock, flags); - old_value = snd_opl4_read(opl4, reg); - snd_opl4_write(opl4, reg, value); - spin_unlock_irqrestore(&opl4->reg_lock, flags); - return value != old_value; -} - -static struct snd_kcontrol_new snd_opl4_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "FM Playback Volume", - .info = snd_opl4_ctl_info, - .get = snd_opl4_ctl_get, - .put = snd_opl4_ctl_put, - .private_value = OPL4_REG_MIX_CONTROL_FM - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Wavetable Playback Volume", - .info = snd_opl4_ctl_info, - .get = snd_opl4_ctl_get, - .put = snd_opl4_ctl_put, - .private_value = OPL4_REG_MIX_CONTROL_PCM - } -}; - -int snd_opl4_create_mixer(struct snd_opl4 *opl4) -{ - struct snd_card *card = opl4->card; - int i, err; - - strcat(card->mixername, ",OPL4"); - - for (i = 0; i < 2; ++i) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4)); - if (err < 0) - return err; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c deleted file mode 100644 index 9b824bfc..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Functions for the OPL4 proc file - * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "opl4_local.h" -#include <linux/vmalloc.h> -#include <linux/export.h> -#include <sound/info.h> - -#ifdef CONFIG_PROC_FS - -static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, - unsigned short mode, void **file_private_data) -{ - struct snd_opl4 *opl4 = entry->private_data; - - mutex_lock(&opl4->access_mutex); - if (opl4->memory_access) { - mutex_unlock(&opl4->access_mutex); - return -EBUSY; - } - opl4->memory_access++; - mutex_unlock(&opl4->access_mutex); - return 0; -} - -static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, - unsigned short mode, void *file_private_data) -{ - struct snd_opl4 *opl4 = entry->private_data; - - mutex_lock(&opl4->access_mutex); - opl4->memory_access--; - mutex_unlock(&opl4->access_mutex); - return 0; -} - -static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *_buf, - size_t count, loff_t pos) -{ - struct snd_opl4 *opl4 = entry->private_data; - char* buf; - - buf = vmalloc(count); - if (!buf) - return -ENOMEM; - snd_opl4_read_memory(opl4, buf, pos, count); - if (copy_to_user(_buf, buf, count)) { - vfree(buf); - return -EFAULT; - } - vfree(buf); - return count; -} - -static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, - const char __user *_buf, - size_t count, loff_t pos) -{ - struct snd_opl4 *opl4 = entry->private_data; - char *buf; - - buf = vmalloc(count); - if (!buf) - return -ENOMEM; - if (copy_from_user(buf, _buf, count)) { - vfree(buf); - return -EFAULT; - } - snd_opl4_write_memory(opl4, buf, pos, count); - vfree(buf); - return count; -} - -static struct snd_info_entry_ops snd_opl4_mem_proc_ops = { - .open = snd_opl4_mem_proc_open, - .release = snd_opl4_mem_proc_release, - .read = snd_opl4_mem_proc_read, - .write = snd_opl4_mem_proc_write, -}; - -int snd_opl4_create_proc(struct snd_opl4 *opl4) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root); - if (entry) { - if (opl4->hardware < OPL3_HW_OPL4_ML) { - /* OPL4 can access 4 MB external ROM/SRAM */ - entry->mode |= S_IWUSR; - entry->size = 4 * 1024 * 1024; - } else { - /* OPL4-ML has 1 MB internal ROM */ - entry->size = 1 * 1024 * 1024; - } - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->c.ops = &snd_opl4_mem_proc_ops; - entry->module = THIS_MODULE; - entry->private_data = opl4; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - opl4->proc_entry = entry; - return 0; -} - -void snd_opl4_free_proc(struct snd_opl4 *opl4) -{ - snd_info_free_entry(opl4->proc_entry); -} - -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c deleted file mode 100644 index 99197699..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * OPL4 sequencer functions - * - * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "opl4_local.h" -#include <linux/init.h> -#include <linux/moduleparam.h> -#include <linux/module.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); -MODULE_DESCRIPTION("OPL4 wavetable synth driver"); -MODULE_LICENSE("Dual BSD/GPL"); - -int volume_boost = 8; - -module_param(volume_boost, int, 0644); -MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds."); - -static int snd_opl4_seq_use_inc(struct snd_opl4 *opl4) -{ - if (!try_module_get(opl4->card->module)) - return -EFAULT; - return 0; -} - -static void snd_opl4_seq_use_dec(struct snd_opl4 *opl4) -{ - module_put(opl4->card->module); -} - -static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct snd_opl4 *opl4 = private_data; - int err; - - mutex_lock(&opl4->access_mutex); - - if (opl4->used) { - mutex_unlock(&opl4->access_mutex); - return -EBUSY; - } - opl4->used++; - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { - err = snd_opl4_seq_use_inc(opl4); - if (err < 0) { - mutex_unlock(&opl4->access_mutex); - return err; - } - } - - mutex_unlock(&opl4->access_mutex); - - snd_opl4_synth_reset(opl4); - return 0; -} - -static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct snd_opl4 *opl4 = private_data; - - snd_opl4_synth_shutdown(opl4); - - mutex_lock(&opl4->access_mutex); - opl4->used--; - mutex_unlock(&opl4->access_mutex); - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) - snd_opl4_seq_use_dec(opl4); - return 0; -} - -static struct snd_midi_op opl4_ops = { - .note_on = snd_opl4_note_on, - .note_off = snd_opl4_note_off, - .note_terminate = snd_opl4_terminate_note, - .control = snd_opl4_control, - .sysex = snd_opl4_sysex, -}; - -static int snd_opl4_seq_event_input(struct snd_seq_event *ev, int direct, - void *private_data, int atomic, int hop) -{ - struct snd_opl4 *opl4 = private_data; - - snd_midi_process_event(&opl4_ops, ev, opl4->chset); - return 0; -} - -static void snd_opl4_seq_free_port(void *private_data) -{ - struct snd_opl4 *opl4 = private_data; - - snd_midi_channel_free_set(opl4->chset); -} - -static int snd_opl4_seq_new_device(struct snd_seq_device *dev) -{ - struct snd_opl4 *opl4; - int client; - struct snd_seq_port_callback pcallbacks; - - opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (!opl4) - return -EINVAL; - - if (snd_yrw801_detect(opl4) < 0) - return -ENODEV; - - opl4->chset = snd_midi_channel_alloc_set(16); - if (!opl4->chset) - return -ENOMEM; - opl4->chset->private_data = opl4; - - /* allocate new client */ - client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num, - "OPL4 Wavetable"); - if (client < 0) { - snd_midi_channel_free_set(opl4->chset); - return client; - } - opl4->seq_client = client; - opl4->chset->client = client; - - /* create new port */ - memset(&pcallbacks, 0, sizeof(pcallbacks)); - pcallbacks.owner = THIS_MODULE; - pcallbacks.use = snd_opl4_seq_use; - pcallbacks.unuse = snd_opl4_seq_unuse; - pcallbacks.event_input = snd_opl4_seq_event_input; - pcallbacks.private_free = snd_opl4_seq_free_port; - pcallbacks.private_data = opl4; - - opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks, - SNDRV_SEQ_PORT_CAP_WRITE | - SNDRV_SEQ_PORT_CAP_SUBS_WRITE, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_HARDWARE | - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, - 16, 24, - "OPL4 Wavetable Port"); - if (opl4->chset->port < 0) { - int err = opl4->chset->port; - snd_midi_channel_free_set(opl4->chset); - snd_seq_delete_kernel_client(client); - opl4->seq_client = -1; - return err; - } - return 0; -} - -static int snd_opl4_seq_delete_device(struct snd_seq_device *dev) -{ - struct snd_opl4 *opl4; - - opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (!opl4) - return -EINVAL; - - if (opl4->seq_client >= 0) { - snd_seq_delete_kernel_client(opl4->seq_client); - opl4->seq_client = -1; - } - return 0; -} - -static int __init alsa_opl4_synth_init(void) -{ - static struct snd_seq_dev_ops ops = { - snd_opl4_seq_new_device, - snd_opl4_seq_delete_device - }; - - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL4, &ops, - sizeof(struct snd_opl4 *)); -} - -static void __exit alsa_opl4_synth_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL4); -} - -module_init(alsa_opl4_synth_init) -module_exit(alsa_opl4_synth_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c deleted file mode 100644 index 49b9e240..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * OPL4 MIDI synthesizer functions - * - * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "opl4_local.h" -#include <linux/delay.h> -#include <asm/io.h> -#include <sound/asoundef.h> - -/* GM2 controllers */ -#ifndef MIDI_CTL_RELEASE_TIME -#define MIDI_CTL_RELEASE_TIME 0x48 -#define MIDI_CTL_ATTACK_TIME 0x49 -#define MIDI_CTL_DECAY_TIME 0x4b -#define MIDI_CTL_VIBRATO_RATE 0x4c -#define MIDI_CTL_VIBRATO_DEPTH 0x4d -#define MIDI_CTL_VIBRATO_DELAY 0x4e -#endif - -/* - * This table maps 100/128 cents to F_NUMBER. - */ -static const s16 snd_opl4_pitch_map[0x600] = { - 0x000,0x000,0x001,0x001,0x002,0x002,0x003,0x003, - 0x004,0x004,0x005,0x005,0x006,0x006,0x006,0x007, - 0x007,0x008,0x008,0x009,0x009,0x00a,0x00a,0x00b, - 0x00b,0x00c,0x00c,0x00d,0x00d,0x00d,0x00e,0x00e, - 0x00f,0x00f,0x010,0x010,0x011,0x011,0x012,0x012, - 0x013,0x013,0x014,0x014,0x015,0x015,0x015,0x016, - 0x016,0x017,0x017,0x018,0x018,0x019,0x019,0x01a, - 0x01a,0x01b,0x01b,0x01c,0x01c,0x01d,0x01d,0x01e, - 0x01e,0x01e,0x01f,0x01f,0x020,0x020,0x021,0x021, - 0x022,0x022,0x023,0x023,0x024,0x024,0x025,0x025, - 0x026,0x026,0x027,0x027,0x028,0x028,0x029,0x029, - 0x029,0x02a,0x02a,0x02b,0x02b,0x02c,0x02c,0x02d, - 0x02d,0x02e,0x02e,0x02f,0x02f,0x030,0x030,0x031, - 0x031,0x032,0x032,0x033,0x033,0x034,0x034,0x035, - 0x035,0x036,0x036,0x037,0x037,0x038,0x038,0x038, - 0x039,0x039,0x03a,0x03a,0x03b,0x03b,0x03c,0x03c, - 0x03d,0x03d,0x03e,0x03e,0x03f,0x03f,0x040,0x040, - 0x041,0x041,0x042,0x042,0x043,0x043,0x044,0x044, - 0x045,0x045,0x046,0x046,0x047,0x047,0x048,0x048, - 0x049,0x049,0x04a,0x04a,0x04b,0x04b,0x04c,0x04c, - 0x04d,0x04d,0x04e,0x04e,0x04f,0x04f,0x050,0x050, - 0x051,0x051,0x052,0x052,0x053,0x053,0x054,0x054, - 0x055,0x055,0x056,0x056,0x057,0x057,0x058,0x058, - 0x059,0x059,0x05a,0x05a,0x05b,0x05b,0x05c,0x05c, - 0x05d,0x05d,0x05e,0x05e,0x05f,0x05f,0x060,0x060, - 0x061,0x061,0x062,0x062,0x063,0x063,0x064,0x064, - 0x065,0x065,0x066,0x066,0x067,0x067,0x068,0x068, - 0x069,0x069,0x06a,0x06a,0x06b,0x06b,0x06c,0x06c, - 0x06d,0x06d,0x06e,0x06e,0x06f,0x06f,0x070,0x071, - 0x071,0x072,0x072,0x073,0x073,0x074,0x074,0x075, - 0x075,0x076,0x076,0x077,0x077,0x078,0x078,0x079, - 0x079,0x07a,0x07a,0x07b,0x07b,0x07c,0x07c,0x07d, - 0x07d,0x07e,0x07e,0x07f,0x07f,0x080,0x081,0x081, - 0x082,0x082,0x083,0x083,0x084,0x084,0x085,0x085, - 0x086,0x086,0x087,0x087,0x088,0x088,0x089,0x089, - 0x08a,0x08a,0x08b,0x08b,0x08c,0x08d,0x08d,0x08e, - 0x08e,0x08f,0x08f,0x090,0x090,0x091,0x091,0x092, - 0x092,0x093,0x093,0x094,0x094,0x095,0x096,0x096, - 0x097,0x097,0x098,0x098,0x099,0x099,0x09a,0x09a, - 0x09b,0x09b,0x09c,0x09c,0x09d,0x09d,0x09e,0x09f, - 0x09f,0x0a0,0x0a0,0x0a1,0x0a1,0x0a2,0x0a2,0x0a3, - 0x0a3,0x0a4,0x0a4,0x0a5,0x0a6,0x0a6,0x0a7,0x0a7, - 0x0a8,0x0a8,0x0a9,0x0a9,0x0aa,0x0aa,0x0ab,0x0ab, - 0x0ac,0x0ad,0x0ad,0x0ae,0x0ae,0x0af,0x0af,0x0b0, - 0x0b0,0x0b1,0x0b1,0x0b2,0x0b2,0x0b3,0x0b4,0x0b4, - 0x0b5,0x0b5,0x0b6,0x0b6,0x0b7,0x0b7,0x0b8,0x0b8, - 0x0b9,0x0ba,0x0ba,0x0bb,0x0bb,0x0bc,0x0bc,0x0bd, - 0x0bd,0x0be,0x0be,0x0bf,0x0c0,0x0c0,0x0c1,0x0c1, - 0x0c2,0x0c2,0x0c3,0x0c3,0x0c4,0x0c4,0x0c5,0x0c6, - 0x0c6,0x0c7,0x0c7,0x0c8,0x0c8,0x0c9,0x0c9,0x0ca, - 0x0cb,0x0cb,0x0cc,0x0cc,0x0cd,0x0cd,0x0ce,0x0ce, - 0x0cf,0x0d0,0x0d0,0x0d1,0x0d1,0x0d2,0x0d2,0x0d3, - 0x0d3,0x0d4,0x0d5,0x0d5,0x0d6,0x0d6,0x0d7,0x0d7, - 0x0d8,0x0d8,0x0d9,0x0da,0x0da,0x0db,0x0db,0x0dc, - 0x0dc,0x0dd,0x0de,0x0de,0x0df,0x0df,0x0e0,0x0e0, - 0x0e1,0x0e1,0x0e2,0x0e3,0x0e3,0x0e4,0x0e4,0x0e5, - 0x0e5,0x0e6,0x0e7,0x0e7,0x0e8,0x0e8,0x0e9,0x0e9, - 0x0ea,0x0eb,0x0eb,0x0ec,0x0ec,0x0ed,0x0ed,0x0ee, - 0x0ef,0x0ef,0x0f0,0x0f0,0x0f1,0x0f1,0x0f2,0x0f3, - 0x0f3,0x0f4,0x0f4,0x0f5,0x0f5,0x0f6,0x0f7,0x0f7, - 0x0f8,0x0f8,0x0f9,0x0f9,0x0fa,0x0fb,0x0fb,0x0fc, - 0x0fc,0x0fd,0x0fd,0x0fe,0x0ff,0x0ff,0x100,0x100, - 0x101,0x101,0x102,0x103,0x103,0x104,0x104,0x105, - 0x106,0x106,0x107,0x107,0x108,0x108,0x109,0x10a, - 0x10a,0x10b,0x10b,0x10c,0x10c,0x10d,0x10e,0x10e, - 0x10f,0x10f,0x110,0x111,0x111,0x112,0x112,0x113, - 0x114,0x114,0x115,0x115,0x116,0x116,0x117,0x118, - 0x118,0x119,0x119,0x11a,0x11b,0x11b,0x11c,0x11c, - 0x11d,0x11e,0x11e,0x11f,0x11f,0x120,0x120,0x121, - 0x122,0x122,0x123,0x123,0x124,0x125,0x125,0x126, - 0x126,0x127,0x128,0x128,0x129,0x129,0x12a,0x12b, - 0x12b,0x12c,0x12c,0x12d,0x12e,0x12e,0x12f,0x12f, - 0x130,0x131,0x131,0x132,0x132,0x133,0x134,0x134, - 0x135,0x135,0x136,0x137,0x137,0x138,0x138,0x139, - 0x13a,0x13a,0x13b,0x13b,0x13c,0x13d,0x13d,0x13e, - 0x13e,0x13f,0x140,0x140,0x141,0x141,0x142,0x143, - 0x143,0x144,0x144,0x145,0x146,0x146,0x147,0x148, - 0x148,0x149,0x149,0x14a,0x14b,0x14b,0x14c,0x14c, - 0x14d,0x14e,0x14e,0x14f,0x14f,0x150,0x151,0x151, - 0x152,0x153,0x153,0x154,0x154,0x155,0x156,0x156, - 0x157,0x157,0x158,0x159,0x159,0x15a,0x15b,0x15b, - 0x15c,0x15c,0x15d,0x15e,0x15e,0x15f,0x160,0x160, - 0x161,0x161,0x162,0x163,0x163,0x164,0x165,0x165, - 0x166,0x166,0x167,0x168,0x168,0x169,0x16a,0x16a, - 0x16b,0x16b,0x16c,0x16d,0x16d,0x16e,0x16f,0x16f, - 0x170,0x170,0x171,0x172,0x172,0x173,0x174,0x174, - 0x175,0x175,0x176,0x177,0x177,0x178,0x179,0x179, - 0x17a,0x17a,0x17b,0x17c,0x17c,0x17d,0x17e,0x17e, - 0x17f,0x180,0x180,0x181,0x181,0x182,0x183,0x183, - 0x184,0x185,0x185,0x186,0x187,0x187,0x188,0x188, - 0x189,0x18a,0x18a,0x18b,0x18c,0x18c,0x18d,0x18e, - 0x18e,0x18f,0x190,0x190,0x191,0x191,0x192,0x193, - 0x193,0x194,0x195,0x195,0x196,0x197,0x197,0x198, - 0x199,0x199,0x19a,0x19a,0x19b,0x19c,0x19c,0x19d, - 0x19e,0x19e,0x19f,0x1a0,0x1a0,0x1a1,0x1a2,0x1a2, - 0x1a3,0x1a4,0x1a4,0x1a5,0x1a6,0x1a6,0x1a7,0x1a8, - 0x1a8,0x1a9,0x1a9,0x1aa,0x1ab,0x1ab,0x1ac,0x1ad, - 0x1ad,0x1ae,0x1af,0x1af,0x1b0,0x1b1,0x1b1,0x1b2, - 0x1b3,0x1b3,0x1b4,0x1b5,0x1b5,0x1b6,0x1b7,0x1b7, - 0x1b8,0x1b9,0x1b9,0x1ba,0x1bb,0x1bb,0x1bc,0x1bd, - 0x1bd,0x1be,0x1bf,0x1bf,0x1c0,0x1c1,0x1c1,0x1c2, - 0x1c3,0x1c3,0x1c4,0x1c5,0x1c5,0x1c6,0x1c7,0x1c7, - 0x1c8,0x1c9,0x1c9,0x1ca,0x1cb,0x1cb,0x1cc,0x1cd, - 0x1cd,0x1ce,0x1cf,0x1cf,0x1d0,0x1d1,0x1d1,0x1d2, - 0x1d3,0x1d3,0x1d4,0x1d5,0x1d5,0x1d6,0x1d7,0x1d7, - 0x1d8,0x1d9,0x1d9,0x1da,0x1db,0x1db,0x1dc,0x1dd, - 0x1dd,0x1de,0x1df,0x1df,0x1e0,0x1e1,0x1e1,0x1e2, - 0x1e3,0x1e4,0x1e4,0x1e5,0x1e6,0x1e6,0x1e7,0x1e8, - 0x1e8,0x1e9,0x1ea,0x1ea,0x1eb,0x1ec,0x1ec,0x1ed, - 0x1ee,0x1ee,0x1ef,0x1f0,0x1f0,0x1f1,0x1f2,0x1f3, - 0x1f3,0x1f4,0x1f5,0x1f5,0x1f6,0x1f7,0x1f7,0x1f8, - 0x1f9,0x1f9,0x1fa,0x1fb,0x1fb,0x1fc,0x1fd,0x1fe, - 0x1fe,0x1ff,0x200,0x200,0x201,0x202,0x202,0x203, - 0x204,0x205,0x205,0x206,0x207,0x207,0x208,0x209, - 0x209,0x20a,0x20b,0x20b,0x20c,0x20d,0x20e,0x20e, - 0x20f,0x210,0x210,0x211,0x212,0x212,0x213,0x214, - 0x215,0x215,0x216,0x217,0x217,0x218,0x219,0x21a, - 0x21a,0x21b,0x21c,0x21c,0x21d,0x21e,0x21e,0x21f, - 0x220,0x221,0x221,0x222,0x223,0x223,0x224,0x225, - 0x226,0x226,0x227,0x228,0x228,0x229,0x22a,0x22b, - 0x22b,0x22c,0x22d,0x22d,0x22e,0x22f,0x230,0x230, - 0x231,0x232,0x232,0x233,0x234,0x235,0x235,0x236, - 0x237,0x237,0x238,0x239,0x23a,0x23a,0x23b,0x23c, - 0x23c,0x23d,0x23e,0x23f,0x23f,0x240,0x241,0x241, - 0x242,0x243,0x244,0x244,0x245,0x246,0x247,0x247, - 0x248,0x249,0x249,0x24a,0x24b,0x24c,0x24c,0x24d, - 0x24e,0x24f,0x24f,0x250,0x251,0x251,0x252,0x253, - 0x254,0x254,0x255,0x256,0x257,0x257,0x258,0x259, - 0x259,0x25a,0x25b,0x25c,0x25c,0x25d,0x25e,0x25f, - 0x25f,0x260,0x261,0x262,0x262,0x263,0x264,0x265, - 0x265,0x266,0x267,0x267,0x268,0x269,0x26a,0x26a, - 0x26b,0x26c,0x26d,0x26d,0x26e,0x26f,0x270,0x270, - 0x271,0x272,0x273,0x273,0x274,0x275,0x276,0x276, - 0x277,0x278,0x279,0x279,0x27a,0x27b,0x27c,0x27c, - 0x27d,0x27e,0x27f,0x27f,0x280,0x281,0x282,0x282, - 0x283,0x284,0x285,0x285,0x286,0x287,0x288,0x288, - 0x289,0x28a,0x28b,0x28b,0x28c,0x28d,0x28e,0x28e, - 0x28f,0x290,0x291,0x291,0x292,0x293,0x294,0x294, - 0x295,0x296,0x297,0x298,0x298,0x299,0x29a,0x29b, - 0x29b,0x29c,0x29d,0x29e,0x29e,0x29f,0x2a0,0x2a1, - 0x2a1,0x2a2,0x2a3,0x2a4,0x2a5,0x2a5,0x2a6,0x2a7, - 0x2a8,0x2a8,0x2a9,0x2aa,0x2ab,0x2ab,0x2ac,0x2ad, - 0x2ae,0x2af,0x2af,0x2b0,0x2b1,0x2b2,0x2b2,0x2b3, - 0x2b4,0x2b5,0x2b5,0x2b6,0x2b7,0x2b8,0x2b9,0x2b9, - 0x2ba,0x2bb,0x2bc,0x2bc,0x2bd,0x2be,0x2bf,0x2c0, - 0x2c0,0x2c1,0x2c2,0x2c3,0x2c4,0x2c4,0x2c5,0x2c6, - 0x2c7,0x2c7,0x2c8,0x2c9,0x2ca,0x2cb,0x2cb,0x2cc, - 0x2cd,0x2ce,0x2ce,0x2cf,0x2d0,0x2d1,0x2d2,0x2d2, - 0x2d3,0x2d4,0x2d5,0x2d6,0x2d6,0x2d7,0x2d8,0x2d9, - 0x2da,0x2da,0x2db,0x2dc,0x2dd,0x2dd,0x2de,0x2df, - 0x2e0,0x2e1,0x2e1,0x2e2,0x2e3,0x2e4,0x2e5,0x2e5, - 0x2e6,0x2e7,0x2e8,0x2e9,0x2e9,0x2ea,0x2eb,0x2ec, - 0x2ed,0x2ed,0x2ee,0x2ef,0x2f0,0x2f1,0x2f1,0x2f2, - 0x2f3,0x2f4,0x2f5,0x2f5,0x2f6,0x2f7,0x2f8,0x2f9, - 0x2f9,0x2fa,0x2fb,0x2fc,0x2fd,0x2fd,0x2fe,0x2ff, - 0x300,0x301,0x302,0x302,0x303,0x304,0x305,0x306, - 0x306,0x307,0x308,0x309,0x30a,0x30a,0x30b,0x30c, - 0x30d,0x30e,0x30f,0x30f,0x310,0x311,0x312,0x313, - 0x313,0x314,0x315,0x316,0x317,0x318,0x318,0x319, - 0x31a,0x31b,0x31c,0x31c,0x31d,0x31e,0x31f,0x320, - 0x321,0x321,0x322,0x323,0x324,0x325,0x326,0x326, - 0x327,0x328,0x329,0x32a,0x32a,0x32b,0x32c,0x32d, - 0x32e,0x32f,0x32f,0x330,0x331,0x332,0x333,0x334, - 0x334,0x335,0x336,0x337,0x338,0x339,0x339,0x33a, - 0x33b,0x33c,0x33d,0x33e,0x33e,0x33f,0x340,0x341, - 0x342,0x343,0x343,0x344,0x345,0x346,0x347,0x348, - 0x349,0x349,0x34a,0x34b,0x34c,0x34d,0x34e,0x34e, - 0x34f,0x350,0x351,0x352,0x353,0x353,0x354,0x355, - 0x356,0x357,0x358,0x359,0x359,0x35a,0x35b,0x35c, - 0x35d,0x35e,0x35f,0x35f,0x360,0x361,0x362,0x363, - 0x364,0x364,0x365,0x366,0x367,0x368,0x369,0x36a, - 0x36a,0x36b,0x36c,0x36d,0x36e,0x36f,0x370,0x370, - 0x371,0x372,0x373,0x374,0x375,0x376,0x377,0x377, - 0x378,0x379,0x37a,0x37b,0x37c,0x37d,0x37d,0x37e, - 0x37f,0x380,0x381,0x382,0x383,0x383,0x384,0x385, - 0x386,0x387,0x388,0x389,0x38a,0x38a,0x38b,0x38c, - 0x38d,0x38e,0x38f,0x390,0x391,0x391,0x392,0x393, - 0x394,0x395,0x396,0x397,0x398,0x398,0x399,0x39a, - 0x39b,0x39c,0x39d,0x39e,0x39f,0x39f,0x3a0,0x3a1, - 0x3a2,0x3a3,0x3a4,0x3a5,0x3a6,0x3a7,0x3a7,0x3a8, - 0x3a9,0x3aa,0x3ab,0x3ac,0x3ad,0x3ae,0x3ae,0x3af, - 0x3b0,0x3b1,0x3b2,0x3b3,0x3b4,0x3b5,0x3b6,0x3b6, - 0x3b7,0x3b8,0x3b9,0x3ba,0x3bb,0x3bc,0x3bd,0x3be, - 0x3bf,0x3bf,0x3c0,0x3c1,0x3c2,0x3c3,0x3c4,0x3c5, - 0x3c6,0x3c7,0x3c7,0x3c8,0x3c9,0x3ca,0x3cb,0x3cc, - 0x3cd,0x3ce,0x3cf,0x3d0,0x3d1,0x3d1,0x3d2,0x3d3, - 0x3d4,0x3d5,0x3d6,0x3d7,0x3d8,0x3d9,0x3da,0x3da, - 0x3db,0x3dc,0x3dd,0x3de,0x3df,0x3e0,0x3e1,0x3e2, - 0x3e3,0x3e4,0x3e4,0x3e5,0x3e6,0x3e7,0x3e8,0x3e9, - 0x3ea,0x3eb,0x3ec,0x3ed,0x3ee,0x3ef,0x3ef,0x3f0, - 0x3f1,0x3f2,0x3f3,0x3f4,0x3f5,0x3f6,0x3f7,0x3f8, - 0x3f9,0x3fa,0x3fa,0x3fb,0x3fc,0x3fd,0x3fe,0x3ff -}; - -/* - * Attenuation according to GM recommendations, in -0.375 dB units. - * table[v] = 40 * log(v / 127) / -0.375 - */ -static unsigned char snd_opl4_volume_table[128] = { - 255,224,192,173,160,150,141,134, - 128,122,117,113,109,105,102, 99, - 96, 93, 90, 88, 85, 83, 81, 79, - 77, 75, 73, 71, 70, 68, 67, 65, - 64, 62, 61, 59, 58, 57, 56, 54, - 53, 52, 51, 50, 49, 48, 47, 46, - 45, 44, 43, 42, 41, 40, 39, 39, - 38, 37, 36, 35, 34, 34, 33, 32, - 31, 31, 30, 29, 29, 28, 27, 27, - 26, 25, 25, 24, 24, 23, 22, 22, - 21, 21, 20, 19, 19, 18, 18, 17, - 17, 16, 16, 15, 15, 14, 14, 13, - 13, 12, 12, 11, 11, 10, 10, 9, - 9, 9, 8, 8, 7, 7, 6, 6, - 6, 5, 5, 4, 4, 4, 3, 3, - 2, 2, 2, 1, 1, 0, 0, 0 -}; - -/* - * Initializes all voices. - */ -void snd_opl4_synth_reset(struct snd_opl4 *opl4) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) - snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT); - spin_unlock_irqrestore(&opl4->reg_lock, flags); - - INIT_LIST_HEAD(&opl4->off_voices); - INIT_LIST_HEAD(&opl4->on_voices); - memset(opl4->voices, 0, sizeof(opl4->voices)); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - opl4->voices[i].number = i; - list_add_tail(&opl4->voices[i].list, &opl4->off_voices); - } - - snd_midi_channel_set_clear(opl4->chset); -} - -/* - * Shuts down all voices. - */ -void snd_opl4_synth_shutdown(struct snd_opl4 *opl4) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) - snd_opl4_write(opl4, OPL4_REG_MISC + i, - opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT); - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -/* - * Executes the callback for all voices playing the specified note. - */ -static void snd_opl4_do_for_note(struct snd_opl4 *opl4, int note, struct snd_midi_channel *chan, - void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) -{ - int i; - unsigned long flags; - struct opl4_voice *voice; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - voice = &opl4->voices[i]; - if (voice->chan == chan && voice->note == note) { - func(opl4, voice); - } - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -/* - * Executes the callback for all voices of to the specified channel. - */ -static void snd_opl4_do_for_channel(struct snd_opl4 *opl4, - struct snd_midi_channel *chan, - void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) -{ - int i; - unsigned long flags; - struct opl4_voice *voice; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - voice = &opl4->voices[i]; - if (voice->chan == chan) { - func(opl4, voice); - } - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -/* - * Executes the callback for all active voices. - */ -static void snd_opl4_do_for_all(struct snd_opl4 *opl4, - void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) -{ - int i; - unsigned long flags; - struct opl4_voice *voice; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - voice = &opl4->voices[i]; - if (voice->chan) - func(opl4, voice); - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -static void snd_opl4_update_volume(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - int att; - - att = voice->sound->tone_attenuate; - att += snd_opl4_volume_table[opl4->chset->gs_master_volume & 0x7f]; - att += snd_opl4_volume_table[voice->chan->gm_volume & 0x7f]; - att += snd_opl4_volume_table[voice->chan->gm_expression & 0x7f]; - att += snd_opl4_volume_table[voice->velocity]; - att = 0x7f - (0x7f - att) * (voice->sound->volume_factor) / 0xfe - volume_boost; - if (att < 0) - att = 0; - else if (att > 0x7e) - att = 0x7e; - snd_opl4_write(opl4, OPL4_REG_LEVEL + voice->number, - (att << 1) | voice->level_direct); - voice->level_direct = 0; -} - -static void snd_opl4_update_pan(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - int pan = voice->sound->panpot; - - if (!voice->chan->drum_channel) - pan += (voice->chan->control[MIDI_CTL_MSB_PAN] - 0x40) >> 3; - if (pan < -7) - pan = -7; - else if (pan > 7) - pan = 7; - voice->reg_misc = (voice->reg_misc & ~OPL4_PAN_POT_MASK) - | (pan & OPL4_PAN_POT_MASK); - snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); -} - -static void snd_opl4_update_vibrato_depth(struct snd_opl4 *opl4, - struct opl4_voice *voice) -{ - int depth; - - if (voice->chan->drum_channel) - return; - depth = (7 - voice->sound->vibrato) - * (voice->chan->control[MIDI_CTL_VIBRATO_DEPTH] & 0x7f); - depth = (depth >> 7) + voice->sound->vibrato; - voice->reg_lfo_vibrato &= ~OPL4_VIBRATO_DEPTH_MASK; - voice->reg_lfo_vibrato |= depth & OPL4_VIBRATO_DEPTH_MASK; - snd_opl4_write(opl4, OPL4_REG_LFO_VIBRATO + voice->number, - voice->reg_lfo_vibrato); -} - -static void snd_opl4_update_pitch(struct snd_opl4 *opl4, - struct opl4_voice *voice) -{ - struct snd_midi_channel *chan = voice->chan; - int note, pitch, octave; - - note = chan->drum_channel ? 60 : voice->note; - /* - * pitch is in 100/128 cents, so 0x80 is one semitone and - * 0x600 is one octave. - */ - pitch = ((note - 60) << 7) * voice->sound->key_scaling / 100 + (60 << 7); - pitch += voice->sound->pitch_offset; - if (!chan->drum_channel) - pitch += chan->gm_rpn_coarse_tuning; - pitch += chan->gm_rpn_fine_tuning >> 7; - pitch += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 0x2000; - if (pitch < 0) - pitch = 0; - else if (pitch >= 0x6000) - pitch = 0x5fff; - octave = pitch / 0x600 - 8; - pitch = snd_opl4_pitch_map[pitch % 0x600]; - - snd_opl4_write(opl4, OPL4_REG_OCTAVE + voice->number, - (octave << 4) | ((pitch >> 7) & OPL4_F_NUMBER_HIGH_MASK)); - voice->reg_f_number = (voice->reg_f_number & OPL4_TONE_NUMBER_BIT8) - | ((pitch << 1) & OPL4_F_NUMBER_LOW_MASK); - snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice->number, voice->reg_f_number); -} - -static void snd_opl4_update_tone_parameters(struct snd_opl4 *opl4, - struct opl4_voice *voice) -{ - snd_opl4_write(opl4, OPL4_REG_ATTACK_DECAY1 + voice->number, - voice->sound->reg_attack_decay1); - snd_opl4_write(opl4, OPL4_REG_LEVEL_DECAY2 + voice->number, - voice->sound->reg_level_decay2); - snd_opl4_write(opl4, OPL4_REG_RELEASE_CORRECTION + voice->number, - voice->sound->reg_release_correction); - snd_opl4_write(opl4, OPL4_REG_TREMOLO + voice->number, - voice->sound->reg_tremolo); -} - -/* allocate one voice */ -static struct opl4_voice *snd_opl4_get_voice(struct snd_opl4 *opl4) -{ - /* first, try to get the oldest key-off voice */ - if (!list_empty(&opl4->off_voices)) - return list_entry(opl4->off_voices.next, struct opl4_voice, list); - /* then get the oldest key-on voice */ - snd_BUG_ON(list_empty(&opl4->on_voices)); - return list_entry(opl4->on_voices.next, struct opl4_voice, list); -} - -static void snd_opl4_wait_for_wave_headers(struct snd_opl4 *opl4) -{ - int timeout = 200; - - while ((inb(opl4->fm_port) & OPL4_STATUS_LOAD) && --timeout > 0) - udelay(10); -} - -void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - const struct opl4_region_ptr *regions; - struct opl4_voice *voice[2]; - const struct opl4_sound *sound[2]; - int voices = 0, i; - unsigned long flags; - - /* determine the number of voices and voice parameters */ - i = chan->drum_channel ? 0x80 : (chan->midi_program & 0x7f); - regions = &snd_yrw801_regions[i]; - for (i = 0; i < regions->count; i++) { - if (note >= regions->regions[i].key_min && - note <= regions->regions[i].key_max) { - sound[voices] = ®ions->regions[i].sound; - if (++voices >= 2) - break; - } - } - - /* allocate and initialize the needed voices */ - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < voices; i++) { - voice[i] = snd_opl4_get_voice(opl4); - list_del(&voice[i]->list); - list_add_tail(&voice[i]->list, &opl4->on_voices); - voice[i]->chan = chan; - voice[i]->note = note; - voice[i]->velocity = vel & 0x7f; - voice[i]->sound = sound[i]; - } - - /* set tone number (triggers header loading) */ - for (i = 0; i < voices; i++) { - voice[i]->reg_f_number = - (sound[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8; - snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice[i]->number, - voice[i]->reg_f_number); - snd_opl4_write(opl4, OPL4_REG_TONE_NUMBER + voice[i]->number, - sound[i]->tone & 0xff); - } - - /* set parameters which can be set while loading */ - for (i = 0; i < voices; i++) { - voice[i]->reg_misc = OPL4_LFO_RESET_BIT; - snd_opl4_update_pan(opl4, voice[i]); - snd_opl4_update_pitch(opl4, voice[i]); - voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT; - snd_opl4_update_volume(opl4, voice[i]); - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); - - /* wait for completion of loading */ - snd_opl4_wait_for_wave_headers(opl4); - - /* set remaining parameters */ - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < voices; i++) { - snd_opl4_update_tone_parameters(opl4, voice[i]); - voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato; - snd_opl4_update_vibrato_depth(opl4, voice[i]); - } - - /* finally, switch on all voices */ - for (i = 0; i < voices; i++) { - voice[i]->reg_misc = - (voice[i]->reg_misc & 0x1f) | OPL4_KEY_ON_BIT; - snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number, - voice[i]->reg_misc); - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - list_del(&voice->list); - list_add_tail(&voice->list, &opl4->off_voices); - - voice->reg_misc &= ~OPL4_KEY_ON_BIT; - snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); -} - -void snd_opl4_note_off(void *private_data, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - - snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off); -} - -static void snd_opl4_terminate_voice(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - list_del(&voice->list); - list_add_tail(&voice->list, &opl4->off_voices); - - voice->reg_misc = (voice->reg_misc & ~OPL4_KEY_ON_BIT) | OPL4_DAMP_BIT; - snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); -} - -void snd_opl4_terminate_note(void *private_data, int note, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - - snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice); -} - -void snd_opl4_control(void *private_data, int type, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - - switch (type) { - case MIDI_CTL_MSB_MODWHEEL: - chan->control[MIDI_CTL_VIBRATO_DEPTH] = chan->control[MIDI_CTL_MSB_MODWHEEL]; - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth); - break; - case MIDI_CTL_MSB_MAIN_VOLUME: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume); - break; - case MIDI_CTL_MSB_PAN: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pan); - break; - case MIDI_CTL_MSB_EXPRESSION: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume); - break; - case MIDI_CTL_VIBRATO_RATE: - /* not yet supported */ - break; - case MIDI_CTL_VIBRATO_DEPTH: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth); - break; - case MIDI_CTL_VIBRATO_DELAY: - /* not yet supported */ - break; - case MIDI_CTL_E1_REVERB_DEPTH: - /* - * Each OPL4 voice has a bit called "Pseudo-Reverb", but - * IMHO _not_ using it enhances the listening experience. - */ - break; - case MIDI_CTL_PITCHBEND: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pitch); - break; - } -} - -void snd_opl4_sysex(void *private_data, unsigned char *buf, int len, - int parsed, struct snd_midi_channel_set *chset) -{ - struct snd_opl4 *opl4 = private_data; - - if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME) - snd_opl4_do_for_all(opl4, snd_opl4_update_volume); -} diff --git a/ANDROID_3.4.5/sound/drivers/opl4/yrw801.c b/ANDROID_3.4.5/sound/drivers/opl4/yrw801.c deleted file mode 100644 index 6c335492..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/yrw801.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Information about the Yamaha YRW801 wavetable ROM chip - * - * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "opl4_local.h" - -int snd_yrw801_detect(struct snd_opl4 *opl4) -{ - char buf[15]; - - snd_opl4_read_memory(opl4, buf, 0x001200, 15); - if (memcmp(buf, "CopyrightYAMAHA", 15)) - return -ENODEV; - snd_opl4_read_memory(opl4, buf, 0x1ffffe, 2); - if (buf[0] != 0x01) - return -ENODEV; - snd_printdd("YRW801 ROM version %02x.%02x\n", buf[0], buf[1]); - return 0; -} - -/* - * The instrument definitions are stored statically because, in practice, the - * OPL4 is always coupled with a YRW801. Dynamic instrument loading would be - * required if downloading sample data to external SRAM was actually supported - * by this driver. - */ - -static const struct opl4_region regions_00[] = { /* Acoustic Grand Piano */ - {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xc8,0x20,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xc8,0x20,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_01[] = { /* Bright Acoustic Piano */ - {0x14, 0x2d, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}}, - {0x2e, 0x33, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x53, 0x58, {0x133,2081,100, 0,0,0x07,0xc8,0x20,0xf2,0x14,0x18,0x0}}, - {0x59, 0x5e, {0x134,1444,100, 0,0,0x0a,0xc8,0x20,0xf3,0x14,0x18,0x0}}, - {0x5f, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_02[] = { /* Electric Grand Piano */ - {0x14, 0x2d, {0x12c,7476,100, 1,0,0x00,0xae,0x20,0xf2,0x13,0x07,0x0}}, - {0x2e, 0x33, {0x12d,6818,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x34, 0x39, {0x12e,5901,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x3a, 0x3f, {0x12f,5292,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x40, 0x45, {0x130,4262,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x46, 0x4b, {0x131,3627,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x4c, 0x52, {0x132,3118,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x53, 0x58, {0x133,2083,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x17,0x0}}, - {0x59, 0x5e, {0x134,1446,100, 1,0,0x00,0xae,0x20,0xf3,0x14,0x17,0x0}}, - {0x5f, 0x6d, {0x135,1917,100, 1,0,0x00,0xae,0x20,0xf4,0x15,0x07,0x0}}, - {0x00, 0x7f, {0x06c,6375,100,-1,0,0x00,0xc2,0x28,0xf4,0x23,0x18,0x0}} -}; -static const struct opl4_region regions_03[] = { /* Honky-Tonk Piano */ - {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xb4,0x20,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xb4,0x20,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}}, - {0x14, 0x27, {0x12c,7486,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6803,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5912,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5275,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4274,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3611,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3129,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2074,100, 0,0,0x07,0xb4,0x20,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1457,100, 0,0,0x01,0xb4,0x20,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1903,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_04[] = { /* Electric Piano 1 */ - {0x15, 0x6c, {0x00b,6570,100, 0,0,0x00,0x28,0x38,0xf0,0x00,0x0c,0x0}}, - {0x00, 0x7f, {0x06c,6375,100, 0,2,0x00,0xb0,0x22,0xf4,0x23,0x19,0x0}} -}; -static const struct opl4_region regions_05[] = { /* Electric Piano 2 */ - {0x14, 0x27, {0x12c,7476,100, 0,3,0x00,0xa2,0x1b,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6818,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5901,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5292,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4262,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3627,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3118,100, 0,3,0x04,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2083,100, 0,3,0x03,0xa2,0x1b,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1446,100, 0,3,0x07,0xa2,0x1b,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1917,100, 0,3,0x00,0xa2,0x1b,0xf4,0x15,0x08,0x0}}, - {0x14, 0x2d, {0x12c,7472,100, 0,0,0x00,0xa2,0x18,0xf2,0x13,0x08,0x0}}, - {0x2e, 0x33, {0x12d,6814,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12e,5897,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x12f,5288,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x130,4258,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x131,3623,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x132,3114,100, 0,0,0x04,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x53, 0x58, {0x133,2079,100, 0,0,0x07,0xa2,0x18,0xf2,0x14,0x18,0x0}}, - {0x59, 0x5e, {0x134,1442,100, 0,0,0x0a,0xa2,0x18,0xf3,0x14,0x18,0x0}}, - {0x5f, 0x6d, {0x135,1913,100, 0,0,0x00,0xa2,0x18,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_06[] = { /* Harpsichord */ - {0x15, 0x39, {0x080,5158,100, 0,0,0x00,0xb2,0x20,0xf5,0x24,0x19,0x0}}, - {0x3a, 0x3f, {0x081,4408,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}}, - {0x40, 0x45, {0x082,3622,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}}, - {0x46, 0x4d, {0x083,2843,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x19,0x0}}, - {0x4e, 0x6c, {0x084,1307,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x29,0x0}} -}; -static const struct opl4_region regions_07[] = { /* Clavinet */ - {0x15, 0x51, {0x027,5009,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x2b,0x0}}, - {0x52, 0x6c, {0x028,3495,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x3b,0x0}} -}; -static const struct opl4_region regions_08[] = { /* Celesta */ - {0x15, 0x6c, {0x02b,3267,100, 0,0,0x00,0xdc,0x20,0xf4,0x15,0x07,0x3}} -}; -static const struct opl4_region regions_09[] = { /* Glockenspiel */ - {0x15, 0x78, {0x0f3, 285,100, 0,0,0x00,0xc2,0x28,0xf6,0x25,0x25,0x0}} -}; -static const struct opl4_region regions_0a[] = { /* Music Box */ - {0x15, 0x6c, {0x0f3,3362,100, 0,0,0x00,0xb6,0x20,0xa6,0x25,0x25,0x0}}, - {0x15, 0x6c, {0x101,4773,100, 0,0,0x00,0xaa,0x20,0xd4,0x14,0x16,0x0}} -}; -static const struct opl4_region regions_0b[] = { /* Vibraphone */ - {0x15, 0x6c, {0x101,4778,100, 0,0,0x00,0xc0,0x28,0xf4,0x14,0x16,0x4}} -}; -static const struct opl4_region regions_0c[] = { /* Marimba */ - {0x15, 0x3f, {0x0f4,4778,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}}, - {0x40, 0x4c, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}}, - {0x4d, 0x5a, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x08,0x0}}, - {0x5b, 0x7f, {0x0f5,3218,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x18,0x0}} -}; -static const struct opl4_region regions_0d[] = { /* Xylophone */ - {0x00, 0x7f, {0x136,1729,100, 0,0,0x00,0xd2,0x38,0xf0,0x06,0x36,0x0}} -}; -static const struct opl4_region regions_0e[] = { /* Tubular Bell */ - {0x01, 0x7f, {0x0ff,3999,100, 0,1,0x00,0x90,0x21,0xf4,0xa3,0x25,0x1}} -}; -static const struct opl4_region regions_0f[] = { /* Dulcimer */ - {0x00, 0x7f, {0x03f,4236,100, 0,1,0x00,0xbc,0x29,0xf5,0x16,0x07,0x0}}, - {0x00, 0x7f, {0x040,4236,100, 0,2,0x0e,0x94,0x2a,0xf5,0x16,0x07,0x0}} -}; -static const struct opl4_region regions_10[] = { /* Drawbar Organ */ - {0x01, 0x7f, {0x08e,4394,100, 0,2,0x14,0xc2,0x3a,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_11[] = { /* Percussive Organ */ - {0x15, 0x3b, {0x08c,6062,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}}, - {0x3c, 0x6c, {0x08d,2984,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_12[] = { /* Rock Organ */ - {0x15, 0x30, {0x128,6574,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x31, 0x3c, {0x129,5040,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x3d, 0x48, {0x12a,3498,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x49, 0x54, {0x12b,1957,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x55, 0x6c, {0x127, 423,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_13[] = { /* Church Organ */ - {0x15, 0x29, {0x087,7466,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x2a, 0x30, {0x088,6456,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x31, 0x38, {0x089,5428,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x39, 0x41, {0x08a,4408,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x42, 0x6c, {0x08b,3406,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_14[] = { /* Reed Organ */ - {0x00, 0x53, {0x0ac,5570,100, 0,0,0x06,0xc0,0x38,0xf0,0x00,0x09,0x1}}, - {0x54, 0x7f, {0x0ad,2497,100, 0,0,0x00,0xc0,0x38,0xf0,0x00,0x09,0x1}} -}; -static const struct opl4_region regions_15[] = { /* Accordion */ - {0x15, 0x4c, {0x006,4261,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}}, - {0x4d, 0x6c, {0x007,1530,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}}, - {0x15, 0x6c, {0x070,4391,100, 0,3,0x00,0x8a,0x23,0xa0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_16[] = { /* Harmonica */ - {0x15, 0x6c, {0x070,4408,100, 0,0,0x00,0xae,0x30,0xa0,0x00,0x09,0x2}} -}; -static const struct opl4_region regions_17[] = { /* Tango Accordion */ - {0x00, 0x53, {0x0ac,5573,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}}, - {0x54, 0x7f, {0x0ad,2500,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}}, - {0x15, 0x6c, {0x041,8479,100, 0,2,0x00,0x6a,0x3a,0x75,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_18[] = { /* Nylon Guitar */ - {0x15, 0x2f, {0x0b3,6964,100, 0,0,0x05,0xca,0x28,0xf5,0x34,0x09,0x0}}, - {0x30, 0x36, {0x0b7,5567,100, 0,0,0x0c,0xca,0x28,0xf5,0x34,0x09,0x0}}, - {0x37, 0x3c, {0x0b5,4653,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, - {0x3d, 0x43, {0x0b4,3892,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x09,0x0}}, - {0x44, 0x60, {0x0b6,2723,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x19,0x0}} -}; -static const struct opl4_region regions_19[] = { /* Steel Guitar */ - {0x15, 0x31, {0x00c,6937,100, 0,0,0x00,0xbc,0x28,0xf0,0x04,0x19,0x0}}, - {0x32, 0x38, {0x00d,5410,100, 0,0,0x00,0xbc,0x28,0xf0,0x05,0x09,0x0}}, - {0x39, 0x47, {0x00e,4379,100, 0,0,0x00,0xbc,0x28,0xf5,0x94,0x09,0x0}}, - {0x48, 0x6c, {0x00f,2843,100, 0,0,0x00,0xbc,0x28,0xf6,0x95,0x09,0x0}} -}; -static const struct opl4_region regions_1a[] = { /* Jazz Guitar */ - {0x15, 0x31, {0x05a,6832,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, - {0x32, 0x3f, {0x05b,4897,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, - {0x40, 0x6c, {0x05c,3218,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}} -}; -static const struct opl4_region regions_1b[] = { /* Clean Guitar */ - {0x15, 0x2c, {0x061,7053,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}}, - {0x2d, 0x31, {0x060,6434,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}}, - {0x32, 0x38, {0x063,5764,100, 0,1,0x00,0xbe,0x29,0xf5,0x55,0x0a,0x0}}, - {0x39, 0x3f, {0x062,4627,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x0a,0x0}}, - {0x40, 0x44, {0x065,3963,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}}, - {0x45, 0x4b, {0x064,3313,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}}, - {0x4c, 0x54, {0x066,2462,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x2a,0x0}}, - {0x55, 0x6c, {0x067,1307,100, 0,1,0x00,0xb4,0x29,0xf6,0x56,0x0a,0x0}} -}; -static const struct opl4_region regions_1c[] = { /* Muted Guitar */ - {0x01, 0x7f, {0x068,4408,100, 0,0,0x00,0xcc,0x28,0xf6,0x15,0x09,0x0}} -}; -static const struct opl4_region regions_1d[] = { /* Overdriven Guitar */ - {0x00, 0x40, {0x0a5,6589,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}}, - {0x41, 0x7f, {0x0a6,5428,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}} -}; -static const struct opl4_region regions_1e[] = { /* Distortion Guitar */ - {0x15, 0x2a, {0x051,6928,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x2b, 0x2e, {0x052,6433,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x2f, 0x32, {0x053,5944,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x33, 0x36, {0x054,5391,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x37, 0x3a, {0x055,4897,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x3b, 0x3e, {0x056,4408,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x3f, 0x42, {0x057,3892,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x43, 0x46, {0x058,3361,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x47, 0x6c, {0x059,2784,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}} -}; -static const struct opl4_region regions_1f[] = { /* Guitar Harmonics */ - {0x15, 0x44, {0x05e,5499,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}}, - {0x45, 0x49, {0x05d,4850,100, 0,0,0x00,0xe2,0x28,0xf4,0x24,0x09,0x0}}, - {0x4a, 0x6c, {0x05f,4259,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}} -}; -static const struct opl4_region regions_20[] = { /* Acoustic Bass */ - {0x15, 0x30, {0x004,8053,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}}, - {0x31, 0x6c, {0x005,4754,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}} -}; -static const struct opl4_region regions_21[] = { /* Fingered Bass */ - {0x01, 0x20, {0x04a,8762,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, - {0x21, 0x25, {0x04b,8114,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, - {0x26, 0x2a, {0x04c,7475,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, - {0x2b, 0x7f, {0x04d,6841,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}} -}; -static const struct opl4_region regions_22[] = { /* Picked Bass */ - {0x15, 0x23, {0x04f,7954,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x0a,0x0}}, - {0x24, 0x2a, {0x050,7318,100, 0,0,0x05,0xcc,0x18,0xf3,0x90,0x1a,0x0}}, - {0x2b, 0x2f, {0x06b,6654,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x2a,0x0}}, - {0x30, 0x47, {0x069,6031,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}}, - {0x48, 0x6c, {0x06a,5393,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}} -}; -static const struct opl4_region regions_23[] = { /* Fretless Bass */ - {0x01, 0x7f, {0x04e,5297,100, 0,0,0x00,0xd2,0x10,0xf3,0x63,0x19,0x0}} -}; -static const struct opl4_region regions_24[] = { /* Slap Bass 1 */ - {0x15, 0x6c, {0x0a3,7606,100, 0,1,0x00,0xde,0x19,0xf5,0x32,0x1a,0x0}} -}; -static const struct opl4_region regions_25[] = { /* Slap Bass 2 */ - {0x01, 0x7f, {0x0a2,6694,100, 0,0,0x00,0xda,0x20,0xb0,0x02,0x09,0x0}} -}; -static const struct opl4_region regions_26[] = { /* Synth Bass 1 */ - {0x15, 0x6c, {0x0be,7466,100, 0,1,0x00,0xb8,0x39,0xf4,0x14,0x09,0x0}} -}; -static const struct opl4_region regions_27[] = { /* Synth Bass 2 */ - {0x00, 0x7f, {0x117,8103,100, 0,1,0x00,0xca,0x39,0xf3,0x50,0x08,0x0}} -}; -static const struct opl4_region regions_28[] = { /* Violin */ - {0x15, 0x3a, {0x105,5158,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x3b, 0x3f, {0x102,4754,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x40, 0x41, {0x106,4132,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x42, 0x44, {0x107,4033,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x45, 0x47, {0x108,3580,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x48, 0x4a, {0x10a,2957,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x4b, 0x4c, {0x10b,2724,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x4d, 0x4e, {0x10c,2530,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x4f, 0x51, {0x10d,2166,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x52, 0x6c, {0x109,1825,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_29[] = { /* Viola */ - {0x15, 0x32, {0x103,5780,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x33, 0x35, {0x104,5534,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x36, 0x38, {0x105,5158,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x39, 0x3d, {0x102,4754,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, - {0x3e, 0x3f, {0x106,4132,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x40, 0x42, {0x107,4033,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x43, 0x45, {0x108,3580,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, - {0x46, 0x48, {0x10a,2957,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, - {0x49, 0x4a, {0x10b,2724,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, - {0x4b, 0x4c, {0x10c,2530,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, - {0x4d, 0x4f, {0x10d,2166,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, - {0x50, 0x6c, {0x109,1825,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_2a[] = { /* Cello */ - {0x15, 0x2d, {0x112,6545,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}}, - {0x2e, 0x37, {0x113,5764,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}}, - {0x38, 0x3e, {0x115,4378,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}, - {0x3f, 0x44, {0x116,3998,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}, - {0x45, 0x6c, {0x114,3218,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}} -}; -static const struct opl4_region regions_2b[] = { /* Contrabass */ - {0x15, 0x29, {0x110,7713,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}}, - {0x2a, 0x6c, {0x111,6162,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_2c[] = { /* Tremolo Strings */ - {0x15, 0x3b, {0x0b0,4810,100, 0,0,0x0a,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x3c, 0x41, {0x035,4035,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x42, 0x47, {0x033,3129,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x48, 0x52, {0x034,2625,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x53, 0x6c, {0x0af, 936,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x07,0x6}} -}; -static const struct opl4_region regions_2d[] = { /* Pizzicato Strings */ - {0x15, 0x32, {0x0b8,6186,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, - {0x33, 0x3b, {0x0b9,5031,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, - {0x3c, 0x42, {0x0bb,4146,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, - {0x43, 0x48, {0x0ba,3245,100, 0,0,0x00,0xc2,0x28,0xf0,0x00,0x05,0x0}}, - {0x49, 0x6c, {0x0bc,2352,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}} -}; -static const struct opl4_region regions_2e[] = { /* Harp */ - {0x15, 0x46, {0x07e,3740,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}}, - {0x47, 0x6c, {0x07f,2319,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}} -}; -static const struct opl4_region regions_2f[] = { /* Timpani */ - {0x15, 0x6c, {0x100,6570,100, 0,0,0x00,0xf8,0x28,0xf0,0x05,0x16,0x0}} -}; -static const struct opl4_region regions_30[] = { /* Strings */ - {0x15, 0x3b, {0x13c,4806,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, - {0x3c, 0x41, {0x13e,4035,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, - {0x42, 0x47, {0x13d,3122,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, - {0x48, 0x52, {0x13f,2629,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}}, - {0x53, 0x6c, {0x140, 950,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}} -}; -static const struct opl4_region regions_31[] = { /* Slow Strings */ - {0x15, 0x3b, {0x0b0,4810,100, 0,1,0x0a,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x3c, 0x41, {0x035,4035,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x42, 0x47, {0x033,3129,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x48, 0x52, {0x034,2625,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x53, 0x6c, {0x0af, 936,100, 0,1,0x00,0xbe,0x19,0xf0,0x00,0x07,0x0}} -}; -static const struct opl4_region regions_32[] = { /* Synth Strings 1 */ - {0x05, 0x71, {0x002,6045,100,-2,0,0x00,0xa6,0x20,0x93,0x22,0x06,0x0}}, - {0x15, 0x6c, {0x0ae,3261,100, 2,0,0x00,0xc6,0x20,0x70,0x01,0x06,0x0}} -}; -static const struct opl4_region regions_33[] = { /* Synth Strings 2 */ - {0x15, 0x6c, {0x002,4513,100, 5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}}, - {0x15, 0x6c, {0x002,4501,100,-5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}} -}; -static const struct opl4_region regions_34[] = { /* Choir Aahs */ - {0x15, 0x3a, {0x018,5010,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, - {0x3b, 0x40, {0x019,4370,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, - {0x41, 0x47, {0x01a,3478,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, - {0x48, 0x6c, {0x01b,2197,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}} -}; -static const struct opl4_region regions_35[] = { /* Voice Oohs */ - {0x15, 0x6c, {0x029,3596,100, 0,0,0x00,0xe6,0x20,0xf7,0x20,0x08,0x0}} -}; -static const struct opl4_region regions_36[] = { /* Synth Voice */ - {0x15, 0x6c, {0x02a,3482,100, 0,1,0x00,0xc2,0x19,0x85,0x21,0x07,0x0}} -}; -static const struct opl4_region regions_37[] = { /* Orchestra Hit */ - {0x15, 0x6c, {0x049,4394,100, 0,0,0x00,0xfe,0x30,0x80,0x05,0x05,0x0}} -}; -static const struct opl4_region regions_38[] = { /* Trumpet */ - {0x15, 0x3c, {0x0f6,4706,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x3d, 0x43, {0x0f8,3894,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x44, 0x48, {0x0f7,3118,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x49, 0x4e, {0x0fa,2322,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x4f, 0x55, {0x0f9,1634,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x56, 0x6c, {0x0fb, 786,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_39[] = { /* Trombone */ - {0x15, 0x3a, {0x0f0,5053,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}, - {0x3b, 0x3f, {0x0f1,4290,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}, - {0x40, 0x6c, {0x0f2,3580,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_3a[] = { /* Tuba */ - {0x15, 0x2d, {0x085,7096,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}}, - {0x2e, 0x6c, {0x086,6014,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}} -}; -static const struct opl4_region regions_3b[] = { /* Muted Trumpet */ - {0x15, 0x45, {0x0b1,4135,100, 0,0,0x00,0xcc,0x28,0xf3,0x10,0x0a,0x1}}, - {0x46, 0x6c, {0x0b2,2599,100, 0,0,0x00,0xcc,0x28,0x83,0x10,0x0a,0x1}} -}; -static const struct opl4_region regions_3c[] = { /* French Horns */ - {0x15, 0x49, {0x07c,3624,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}}, - {0x4a, 0x6c, {0x07d,2664,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_3d[] = { /* Brass Section */ - {0x15, 0x42, {0x0fc,4375,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}}, - {0x43, 0x6c, {0x0fd,2854,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_3e[] = { /* Synth Brass 1 */ - {0x01, 0x27, {0x0d3,9094,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x28, 0x2d, {0x0da,8335,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x2e, 0x33, {0x0d4,7558,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x34, 0x39, {0x0db,6785,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x3a, 0x3f, {0x0d5,6042,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x40, 0x45, {0x0dc,5257,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x46, 0x4b, {0x0d6,4493,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x4c, 0x51, {0x0dd,3741,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x52, 0x57, {0x0d7,3012,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x58, 0x5d, {0x0de,2167,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x5e, 0x63, {0x0d8,1421,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x64, 0x7f, {0x0d9,-115,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x01, 0x27, {0x118,9103,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x28, 0x2d, {0x119,8340,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x2e, 0x33, {0x11a,7565,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x34, 0x39, {0x11b,6804,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x3a, 0x3f, {0x11c,6042,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x40, 0x45, {0x11d,5277,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x46, 0x4b, {0x11e,4520,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x4c, 0x51, {0x11f,3741,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x52, 0x57, {0x120,3012,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x58, 0x5d, {0x121,2166,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x5e, 0x64, {0x122,1421,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x65, 0x7f, {0x123,-115,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}} -}; -static const struct opl4_region regions_3f[] = { /* Synth Brass 2 */ - {0x01, 0x27, {0x118,9113,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x28, 0x2d, {0x119,8350,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x2e, 0x33, {0x11a,7575,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x34, 0x39, {0x11b,6814,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x3a, 0x3f, {0x11c,6052,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x40, 0x45, {0x11d,5287,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x46, 0x4b, {0x11e,4530,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x4c, 0x51, {0x11f,3751,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x52, 0x57, {0x120,3022,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x58, 0x5d, {0x121,2176,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x5e, 0x64, {0x122,1431,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x65, 0x7f, {0x123,-105,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x00, 0x7f, {0x124,4034,100,-3,2,0x00,0xea,0x22,0x85,0x23,0x08,0x0}} -}; -static const struct opl4_region regions_40[] = { /* Soprano Sax */ - {0x15, 0x3f, {0x0e3,4228,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}, - {0x40, 0x45, {0x0e4,3495,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}, - {0x46, 0x4b, {0x0e5,2660,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, - {0x4c, 0x51, {0x0e6,2002,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, - {0x52, 0x59, {0x0e7,1186,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, - {0x59, 0x6c, {0x0e8,1730,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_41[] = { /* Alto Sax */ - {0x15, 0x32, {0x092,6204,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x33, 0x35, {0x096,5812,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x36, 0x3a, {0x099,5318,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x3b, 0x3b, {0x08f,5076,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x3c, 0x3e, {0x093,4706,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x3f, 0x41, {0x097,4321,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x42, 0x44, {0x09a,3893,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x45, 0x47, {0x090,3497,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x48, 0x4a, {0x094,3119,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x4b, 0x4d, {0x098,2726,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x4e, 0x50, {0x09b,2393,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x51, 0x53, {0x091,2088,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x54, 0x6c, {0x095,1732,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}} -}; -static const struct opl4_region regions_42[] = { /* Tenor Sax */ - {0x24, 0x30, {0x0e9,6301,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x31, 0x34, {0x0ea,5781,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x35, 0x3a, {0x0eb,5053,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x3b, 0x41, {0x0ed,4165,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x42, 0x47, {0x0ec,3218,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x48, 0x51, {0x0ee,2462,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x52, 0x6c, {0x0ef,1421,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}} -}; -static const struct opl4_region regions_43[] = { /* Baritone Sax */ - {0x15, 0x2d, {0x0df,6714,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, - {0x2e, 0x34, {0x0e1,5552,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, - {0x35, 0x39, {0x0e2,5178,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, - {0x3a, 0x6c, {0x0e0,4437,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_44[] = { /* Oboe */ - {0x15, 0x3c, {0x042,4493,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}}, - {0x3d, 0x43, {0x044,3702,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x44, 0x49, {0x043,2956,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x4a, 0x4f, {0x046,2166,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x50, 0x55, {0x045,1420,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x56, 0x6c, {0x047, 630,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}} -}; -static const struct opl4_region regions_45[] = { /* English Horn */ - {0x15, 0x38, {0x03c,5098,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}, - {0x39, 0x3e, {0x03b,4291,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}, - {0x3f, 0x6c, {0x03d,3540,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_46[] = { /* Bassoon */ - {0x15, 0x22, {0x038,7833,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}, - {0x23, 0x2e, {0x03a,7070,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}, - {0x2f, 0x6c, {0x039,6302,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}} -}; -static const struct opl4_region regions_47[] = { /* Clarinet */ - {0x15, 0x3b, {0x09e,5900,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, - {0x3c, 0x41, {0x0a0,5158,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, - {0x42, 0x4a, {0x09f,4260,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, - {0x4b, 0x6c, {0x0a1,2957,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_48[] = { /* Piccolo */ - {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x4e, 0x53, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x54, 0x5f, {0x074,2085,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x60, 0x6c, {0x075,1421,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}} -}; -static const struct opl4_region regions_49[] = { /* Flute */ - {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}}, - {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}}, - {0x4e, 0x6c, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}} -}; -static const struct opl4_region regions_4a[] = { /* Recorder */ - {0x15, 0x6f, {0x0bd,4897,100, 0,0,0x00,0xec,0x30,0x70,0x00,0x09,0x1}} -}; -static const struct opl4_region regions_4b[] = { /* Pan Flute */ - {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x09,0x3}} -}; -static const struct opl4_region regions_4c[] = { /* Bottle Blow */ - {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xc8,0x38,0xf0,0x00,0x09,0x1}}, - {0x01, 0x7f, {0x125,7372,100, 0,0,0x1e,0x80,0x00,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_4d[] = { /* Shakuhachi */ - {0x00, 0x7f, {0x0ab,4548,100, 0,0,0x00,0xd6,0x30,0xf0,0x00,0x0a,0x3}}, - {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xa2,0x28,0x70,0x00,0x09,0x2}} -}; -static const struct opl4_region regions_4e[] = { /* Whistle */ - {0x00, 0x7f, {0x0aa,1731,100, 0,4,0x00,0xd2,0x2c,0x70,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_4f[] = { /* Ocarina */ - {0x00, 0x7f, {0x0aa,1731,100, 0,1,0x00,0xce,0x29,0x90,0x00,0x0a,0x1}} -}; -static const struct opl4_region regions_50[] = { /* Square Lead */ - {0x01, 0x2a, {0x0cc,9853,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x2b, 0x36, {0x0cd,6785,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x37, 0x42, {0x0ca,5248,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x43, 0x4e, {0x0cf,3713,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x4f, 0x5a, {0x0ce,2176,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x5b, 0x7f, {0x0cb, 640,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x01, 0x2a, {0x0cc,9844,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x2b, 0x36, {0x0cd,6776,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x37, 0x42, {0x0ca,5239,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x43, 0x4e, {0x0cf,3704,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x4f, 0x5a, {0x0ce,2167,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x5b, 0x7f, {0x0cb, 631,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}} -}; -static const struct opl4_region regions_51[] = { /* Sawtooth Lead */ - {0x01, 0x27, {0x118,9108,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x28, 0x2d, {0x119,8345,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x2e, 0x33, {0x11a,7570,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x34, 0x39, {0x11b,6809,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x3a, 0x3f, {0x11c,6047,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x40, 0x45, {0x11d,5282,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x46, 0x4b, {0x11e,4525,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x4c, 0x51, {0x11f,3746,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x52, 0x57, {0x120,3017,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x58, 0x5d, {0x121,2171,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x5e, 0x66, {0x122,1426,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x67, 0x7f, {0x123,-110,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x01, 0x27, {0x118,9098,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x28, 0x2d, {0x119,8335,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x2e, 0x33, {0x11a,7560,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x34, 0x39, {0x11b,6799,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x3a, 0x3f, {0x11c,6037,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x40, 0x45, {0x11d,5272,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x46, 0x4b, {0x11e,4515,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x4c, 0x51, {0x11f,3736,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x52, 0x57, {0x120,3007,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x58, 0x5d, {0x121,2161,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x5e, 0x66, {0x122,1416,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x67, 0x7f, {0x123,-120,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}} -}; -static const struct opl4_region regions_52[] = { /* Calliope Lead */ - {0x00, 0x7f, {0x0aa,1731,100, 0,0,0x00,0xc2,0x28,0x90,0x00,0x0a,0x2}}, - {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xb6,0x28,0xb0,0x00,0x09,0x2}} -}; -static const struct opl4_region regions_53[] = { /* Chiffer Lead */ - {0x00, 0x7f, {0x13a,3665,100, 0,2,0x00,0xcc,0x2a,0xf0,0x10,0x09,0x1}}, - {0x01, 0x7f, {0x0fe,3660,100, 0,0,0x00,0xbe,0x28,0xf3,0x10,0x17,0x0}} -}; -static const struct opl4_region regions_54[] = { /* Charang Lead */ - {0x00, 0x40, {0x0a5,6594,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}}, - {0x41, 0x7f, {0x0a6,5433,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}}, - {0x01, 0x27, {0x118,9098,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x28, 0x2d, {0x119,8335,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x2e, 0x33, {0x11a,7560,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x34, 0x39, {0x11b,6799,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x3a, 0x3f, {0x11c,6037,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x40, 0x45, {0x11d,5272,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x46, 0x4b, {0x11e,4515,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x4c, 0x51, {0x11f,3736,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x52, 0x57, {0x120,3007,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x58, 0x5d, {0x121,2161,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x5e, 0x66, {0x122,1416,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x67, 0x7f, {0x123,-120,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}} -}; -static const struct opl4_region regions_55[] = { /* Voice Lead */ - {0x00, 0x7f, {0x0aa,1739,100, 0,6,0x00,0x8c,0x2e,0x90,0x00,0x0a,0x0}}, - {0x15, 0x6c, {0x02a,3474,100, 0,1,0x00,0xd8,0x29,0xf0,0x05,0x0a,0x0}} -}; -static const struct opl4_region regions_56[] = { /* 5ths Lead */ - {0x01, 0x27, {0x118,8468,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x28, 0x2d, {0x119,7705,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x2e, 0x33, {0x11a,6930,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x34, 0x39, {0x11b,6169,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x3a, 0x3f, {0x11c,5407,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x40, 0x45, {0x11d,4642,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x46, 0x4b, {0x11e,3885,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x4c, 0x51, {0x11f,3106,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x52, 0x57, {0x120,2377,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x58, 0x5d, {0x121,1531,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x5e, 0x64, {0x122, 786,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x65, 0x7f, {0x123,-750,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x05, 0x71, {0x002,4503,100, 0,1,0x00,0xb8,0x31,0xb3,0x20,0x0b,0x0}} -}; -static const struct opl4_region regions_57[] = { /* Bass & Lead */ - {0x00, 0x7f, {0x117,8109,100, 0,1,0x00,0xbc,0x29,0xf3,0x50,0x08,0x0}}, - {0x01, 0x27, {0x118,9097,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x28, 0x2d, {0x119,8334,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x2e, 0x33, {0x11a,7559,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x34, 0x39, {0x11b,6798,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x3a, 0x3f, {0x11c,6036,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x40, 0x45, {0x11d,5271,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x46, 0x4b, {0x11e,4514,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x4c, 0x51, {0x11f,3735,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x52, 0x57, {0x120,3006,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x58, 0x5d, {0x121,2160,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x5e, 0x66, {0x122,1415,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x67, 0x7f, {0x123,-121,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_58[] = { /* New Age Pad */ - {0x15, 0x6c, {0x002,4501,100, 0,4,0x00,0xa4,0x24,0x80,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x0f3,4253,100, 0,3,0x00,0x8c,0x23,0xa2,0x14,0x06,0x1}} -}; -static const struct opl4_region regions_59[] = { /* Warm Pad */ - {0x15, 0x6c, {0x04e,5306,100, 2,2,0x00,0x92,0x2a,0x34,0x23,0x05,0x2}}, - {0x15, 0x6c, {0x029,3575,100,-2,2,0x00,0xbe,0x22,0x31,0x23,0x06,0x0}} -}; -static const struct opl4_region regions_5a[] = { /* Polysynth Pad */ - {0x01, 0x27, {0x118,9111,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x28, 0x2d, {0x119,8348,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x2e, 0x33, {0x11a,7573,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x34, 0x39, {0x11b,6812,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x3a, 0x3f, {0x11c,6050,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x40, 0x45, {0x11d,5285,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x46, 0x4b, {0x11e,4528,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x4c, 0x51, {0x11f,3749,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x52, 0x57, {0x120,3020,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x58, 0x5d, {0x121,2174,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x5e, 0x66, {0x122,1429,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x67, 0x7f, {0x123,-107,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x00, 0x7f, {0x124,4024,100, 0,2,0x00,0xae,0x22,0xe5,0x20,0x08,0x0}} -}; -static const struct opl4_region regions_5b[] = { /* Choir Pad */ - {0x15, 0x3a, {0x018,5010,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x3b, 0x40, {0x019,4370,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x41, 0x47, {0x01a,3478,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x48, 0x6c, {0x01b,2197,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x15, 0x6c, {0x02a,3482,100, 0,4,0x00,0x98,0x24,0x65,0x21,0x06,0x0}} -}; -static const struct opl4_region regions_5c[] = { /* Bowed Pad */ - {0x15, 0x6c, {0x101,4790,100,-1,1,0x00,0xbe,0x19,0x44,0x14,0x16,0x0}}, - {0x00, 0x7f, {0x0aa,1720,100, 1,1,0x00,0x94,0x19,0x40,0x00,0x06,0x0}} -}; -static const struct opl4_region regions_5d[] = { /* Metallic Pad */ - {0x15, 0x31, {0x00c,6943,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x32, 0x38, {0x00d,5416,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x39, 0x47, {0x00e,4385,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x48, 0x6c, {0x00f,2849,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x00, 0x7f, {0x03f,4224,100, 0,1,0x00,0x9c,0x31,0x65,0x16,0x07,0x0}} -}; -static const struct opl4_region regions_5e[] = { /* Halo Pad */ - {0x00, 0x7f, {0x124,4038,100, 0,2,0x00,0xa6,0x1a,0x85,0x23,0x08,0x0}}, - {0x15, 0x6c, {0x02a,3471,100, 0,3,0x00,0xc0,0x1b,0xc0,0x05,0x06,0x0}} -}; -static const struct opl4_region regions_5f[] = { /* Sweep Pad */ - {0x01, 0x27, {0x0d3,9100,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x28, 0x2d, {0x0da,8341,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x2e, 0x33, {0x0d4,7564,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x34, 0x39, {0x0db,6791,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x3a, 0x3f, {0x0d5,6048,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x40, 0x45, {0x0dc,5263,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x46, 0x4b, {0x0d6,4499,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x4c, 0x51, {0x0dd,3747,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x52, 0x57, {0x0d7,3018,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x58, 0x5d, {0x0de,2173,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x5e, 0x63, {0x0d8,1427,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x64, 0x7f, {0x0d9,-109,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x01, 0x27, {0x0d3,9088,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x28, 0x2d, {0x0da,8329,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x2e, 0x33, {0x0d4,7552,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x34, 0x39, {0x0db,6779,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x3a, 0x3f, {0x0d5,6036,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x40, 0x45, {0x0dc,5251,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x46, 0x4b, {0x0d6,4487,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x4c, 0x51, {0x0dd,3735,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x52, 0x57, {0x0d7,3006,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x58, 0x5d, {0x0de,2161,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x5e, 0x63, {0x0d8,1415,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x64, 0x7f, {0x0d9,-121,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}} -}; -static const struct opl4_region regions_60[] = { /* Ice Rain */ - {0x01, 0x7f, {0x04e,9345,100, 0,2,0x00,0xcc,0x22,0xa3,0x63,0x17,0x0}}, - {0x00, 0x7f, {0x143,5586, 20, 0,2,0x00,0x6e,0x2a,0xf0,0x05,0x05,0x0}} -}; -static const struct opl4_region regions_61[] = { /* Soundtrack */ - {0x15, 0x6c, {0x002,4501,100, 0,2,0x00,0xb6,0x2a,0x60,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x0f3,1160,100, 0,5,0x00,0xa8,0x2d,0x52,0x14,0x06,0x2}} -}; -static const struct opl4_region regions_62[] = { /* Crystal */ - {0x15, 0x6c, {0x0f3,1826,100, 0,3,0x00,0xb8,0x33,0xf6,0x25,0x25,0x0}}, - {0x15, 0x2c, {0x06d,7454,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}}, - {0x2d, 0x36, {0x06e,5925,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}}, - {0x37, 0x6c, {0x06f,4403,100, 0,3,0x09,0xac,0x3b,0x85,0x24,0x06,0x0}} -}; -static const struct opl4_region regions_63[] = { /* Atmosphere */ - {0x05, 0x71, {0x002,4509,100, 0,2,0x00,0xc8,0x32,0x73,0x22,0x06,0x1}}, - {0x15, 0x2f, {0x0b3,6964,100, 0,2,0x05,0xc2,0x32,0xf5,0x34,0x07,0x2}}, - {0x30, 0x36, {0x0b7,5567,100, 0,2,0x0c,0xc2,0x32,0xf5,0x34,0x07,0x2}}, - {0x37, 0x3c, {0x0b5,4653,100, 0,2,0x00,0xc2,0x32,0xf6,0x34,0x07,0x2}}, - {0x3d, 0x43, {0x0b4,3892,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x07,0x2}}, - {0x44, 0x60, {0x0b6,2723,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x17,0x2}} -}; -static const struct opl4_region regions_64[] = { /* Brightness */ - {0x00, 0x7f, {0x137,5285,100, 0,2,0x00,0xbe,0x2a,0xa5,0x18,0x08,0x0}}, - {0x15, 0x6c, {0x02a,3481,100, 0,1,0x00,0xc8,0x29,0x80,0x05,0x05,0x0}} -}; -static const struct opl4_region regions_65[] = { /* Goblins */ - {0x15, 0x6c, {0x002,4501,100,-1,2,0x00,0xca,0x2a,0x40,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x009,9679, 20, 1,4,0x00,0x3c,0x0c,0x22,0x11,0x06,0x0}} -}; -static const struct opl4_region regions_66[] = { /* Echoes */ - {0x15, 0x6c, {0x02a,3487,100, 0,3,0x00,0xae,0x2b,0xf5,0x21,0x06,0x0}}, - {0x00, 0x7f, {0x124,4027,100, 0,3,0x00,0xae,0x2b,0x85,0x23,0x07,0x0}} -}; -static const struct opl4_region regions_67[] = { /* Sci-Fi */ - {0x15, 0x31, {0x00c,6940,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x32, 0x38, {0x00d,5413,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x39, 0x47, {0x00e,4382,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x48, 0x6c, {0x00f,2846,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x15, 0x6c, {0x002,4498,100, 0,2,0x00,0xd4,0x22,0x80,0x01,0x05,0x0}} -}; -static const struct opl4_region regions_68[] = { /* Sitar */ - {0x00, 0x7f, {0x10f,4408,100, 0,2,0x00,0xc4,0x32,0xf4,0x15,0x16,0x1}} -}; -static const struct opl4_region regions_69[] = { /* Banjo */ - {0x15, 0x34, {0x013,5685,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x35, 0x38, {0x014,5009,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x39, 0x3c, {0x012,4520,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x3d, 0x44, {0x015,3622,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x45, 0x4c, {0x017,2661,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x4d, 0x6d, {0x016,1632,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}} -}; -static const struct opl4_region regions_6a[] = { /* Shamisen */ - {0x15, 0x6c, {0x10e,3273,100, 0,0,0x00,0xc0,0x28,0xf7,0x76,0x08,0x0}} -}; -static const struct opl4_region regions_6b[] = { /* Koto */ - {0x00, 0x7f, {0x0a9,4033,100, 0,0,0x00,0xc6,0x20,0xf0,0x06,0x07,0x0}} -}; -static const struct opl4_region regions_6c[] = { /* Kalimba */ - {0x00, 0x7f, {0x137,3749,100, 0,0,0x00,0xce,0x38,0xf5,0x18,0x08,0x0}} -}; -static const struct opl4_region regions_6d[] = { /* Bagpipe */ - {0x15, 0x39, {0x0a4,7683,100, 0,4,0x00,0xc0,0x1c,0xf0,0x00,0x09,0x0}}, - {0x15, 0x39, {0x0a7,7680,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}}, - {0x3a, 0x6c, {0x0a8,3697,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_6e[] = { /* Fiddle */ - {0x15, 0x3a, {0x105,5158,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x3b, 0x3f, {0x102,4754,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x40, 0x41, {0x106,4132,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x42, 0x44, {0x107,4033,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x45, 0x47, {0x108,3580,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x48, 0x4a, {0x10a,2957,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x4b, 0x4c, {0x10b,2724,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x4d, 0x4e, {0x10c,2530,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x4f, 0x51, {0x10d,2166,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x52, 0x6c, {0x109,1825,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_6f[] = { /* Shanai */ - {0x15, 0x6c, {0x041,6946,100, 0,1,0x00,0xc4,0x31,0x95,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_70[] = { /* Tinkle Bell */ - {0x15, 0x73, {0x0f3,1821,100, 0,3,0x00,0xc8,0x3b,0xd6,0x25,0x25,0x0}}, - {0x00, 0x7f, {0x137,5669,100, 0,3,0x00,0x66,0x3b,0xf5,0x18,0x08,0x0}} -}; -static const struct opl4_region regions_71[] = { /* Agogo */ - {0x15, 0x74, {0x00b,2474,100, 0,0,0x00,0xd2,0x38,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_72[] = { /* Steel Drums */ - {0x01, 0x7f, {0x0fe,3670,100, 0,0,0x00,0xca,0x38,0xf3,0x06,0x17,0x1}}, - {0x15, 0x6c, {0x100,9602,100, 0,0,0x00,0x54,0x38,0xb0,0x05,0x16,0x1}} -}; -static const struct opl4_region regions_73[] = { /* Woodblock */ - {0x15, 0x6c, {0x02c,2963, 50, 0,0,0x07,0xd4,0x00,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_74[] = { /* Taiko Drum */ - {0x13, 0x6c, {0x03e,1194, 50, 0,0,0x00,0xaa,0x38,0xf0,0x04,0x04,0x0}} -}; -static const struct opl4_region regions_75[] = { /* Melodic Tom */ - {0x15, 0x6c, {0x0c7,6418, 50, 0,0,0x00,0xe4,0x38,0xf0,0x05,0x01,0x0}} -}; -static const struct opl4_region regions_76[] = { /* Synth Drum */ - {0x15, 0x6c, {0x026,3898, 50, 0,0,0x00,0xd0,0x38,0xf0,0x04,0x04,0x0}} -}; -static const struct opl4_region regions_77[] = { /* Reverse Cymbal */ - {0x15, 0x6c, {0x031,4138, 50, 0,0,0x00,0xfe,0x38,0x3a,0xf0,0x09,0x0}} -}; -static const struct opl4_region regions_78[] = { /* Guitar Fret Noise */ - {0x15, 0x6c, {0x138,5266,100, 0,0,0x00,0xa0,0x38,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_79[] = { /* Breath Noise */ - {0x01, 0x7f, {0x125,4269,100, 0,0,0x1e,0xd0,0x38,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_7a[] = { /* Seashore */ - {0x15, 0x6c, {0x008,2965, 20,-2,0,0x00,0xfe,0x00,0x20,0x03,0x04,0x0}}, - {0x01, 0x7f, {0x037,4394, 20, 2,0,0x14,0xfe,0x00,0x20,0x04,0x05,0x0}} -}; -static const struct opl4_region regions_7b[] = { /* Bird Tweet */ - {0x15, 0x6c, {0x009,8078, 5,-4,7,0x00,0xc2,0x0f,0x22,0x12,0x07,0x0}}, - {0x15, 0x6c, {0x009,3583, 5, 4,5,0x00,0xae,0x15,0x72,0x12,0x07,0x0}} -}; -static const struct opl4_region regions_7c[] = { /* Telephone Ring */ - {0x15, 0x6c, {0x003,3602, 10, 0,0,0x00,0xce,0x00,0xf0,0x00,0x0f,0x0}} -}; -static const struct opl4_region regions_7d[] = { /* Helicopter */ - {0x0c, 0x7f, {0x001,2965, 10,-2,0,0x00,0xe0,0x08,0x30,0x01,0x07,0x0}}, - {0x01, 0x7f, {0x037,4394, 10, 2,0,0x44,0x76,0x00,0x30,0x01,0x07,0x0}} -}; -static const struct opl4_region regions_7e[] = { /* Applause */ - {0x15, 0x6c, {0x036,8273, 20,-6,7,0x00,0xc4,0x0f,0x70,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x036,8115, 5, 6,7,0x00,0xc6,0x07,0x70,0x01,0x05,0x0}} -}; -static const struct opl4_region regions_7f[] = { /* Gun Shot */ - {0x15, 0x6c, {0x139,2858, 20, 0,0,0x00,0xbe,0x38,0xf0,0x03,0x00,0x0}} -}; -static const struct opl4_region regions_drums[] = { - {0x18, 0x18, {0x0cb,6397,100, 3,0,0x00,0xf4,0x38,0xc9,0x1c,0x0c,0x0}}, - {0x19, 0x19, {0x0c4,3714,100, 0,0,0x00,0xe0,0x00,0x97,0x19,0x09,0x0}}, - {0x1a, 0x1a, {0x0c4,3519,100, 0,0,0x00,0xea,0x00,0x61,0x01,0x07,0x0}}, - {0x1b, 0x1b, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0xf7,0x19,0x09,0x0}}, - {0x1c, 0x1c, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0x81,0x01,0x07,0x0}}, - {0x1e, 0x1e, {0x0c3,4783,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x1f, 0x1f, {0x0d1,4042,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, - {0x20, 0x20, {0x0d2,5943,100, 0,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}}, - {0x21, 0x21, {0x011,3842,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}}, - {0x23, 0x23, {0x011,4098,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}}, - {0x24, 0x24, {0x011,4370,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x06,0x0}}, - {0x25, 0x25, {0x0d2,4404,100, 0,0,0x00,0xd6,0x00,0xf0,0x00,0x06,0x0}}, - {0x26, 0x26, {0x0d1,4298,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, - {0x27, 0x27, {0x00a,4403,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x28, 0x28, {0x0d1,4554,100, 0,0,0x00,0xdc,0x00,0xf0,0x07,0x07,0x0}}, - {0x29, 0x29, {0x0c8,4242,100,-4,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, - {0x2a, 0x2a, {0x079,6160,100, 2,0,0x00,0xe0,0x00,0xf5,0x19,0x09,0x0}}, - {0x2b, 0x2b, {0x0c8,4626,100,-3,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, - {0x2c, 0x2c, {0x07b,6039,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x2d, 0x2d, {0x0c8,5394,100,-2,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, - {0x2e, 0x2e, {0x07a,5690,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x05,0x0}}, - {0x2f, 0x2f, {0x0c7,5185,100, 2,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, - {0x30, 0x30, {0x0c7,5650,100, 3,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, - {0x31, 0x31, {0x031,4395,100, 2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}}, - {0x32, 0x32, {0x0c7,6162,100, 4,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, - {0x33, 0x33, {0x02e,4391,100,-2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}}, - {0x34, 0x34, {0x07a,3009,100,-2,0,0x00,0xea,0x00,0xf2,0x15,0x05,0x0}}, - {0x35, 0x35, {0x021,4522,100,-3,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, - {0x36, 0x36, {0x025,5163,100, 1,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x37, 0x37, {0x031,5287,100,-1,0,0x00,0xea,0x00,0xf5,0x16,0x06,0x0}}, - {0x38, 0x38, {0x01d,4395,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x39, 0x39, {0x031,4647,100,-2,0,0x00,0xea,0x00,0xf4,0x16,0x06,0x0}}, - {0x3a, 0x3a, {0x09d,4426,100,-4,0,0x00,0xe0,0x00,0xf4,0x17,0x07,0x0}}, - {0x3b, 0x3b, {0x02e,4659,100,-2,0,0x00,0xea,0x00,0xf0,0x06,0x06,0x0}}, - {0x3c, 0x3c, {0x01c,4769,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x3d, 0x3d, {0x01c,4611,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x3e, 0x3e, {0x01e,4402,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x3f, 0x3f, {0x01f,4387,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x40, 0x40, {0x01f,3983,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x41, 0x41, {0x09c,4526,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x42, 0x42, {0x09c,4016,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x43, 0x43, {0x00b,4739,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x44, 0x44, {0x00b,4179,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x45, 0x45, {0x02f,4787,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x46, 0x46, {0x030,4665,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x47, 0x47, {0x144,4519,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}}, - {0x48, 0x48, {0x144,4111,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}}, - {0x49, 0x49, {0x024,6408,100, 3,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x4a, 0x4a, {0x024,4144,100, 3,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}}, - {0x4b, 0x4b, {0x020,4001,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x4c, 0x4c, {0x02c,4402,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x4d, 0x4d, {0x02c,3612,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x4e, 0x4e, {0x022,4129,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x4f, 0x4f, {0x023,4147,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x50, 0x50, {0x032,4412,100,-4,0,0x00,0xd6,0x00,0xf0,0x08,0x09,0x0}}, - {0x51, 0x51, {0x032,4385,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x52, 0x52, {0x02f,5935,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}} -}; - -#define REGION(num) { ARRAY_SIZE(regions ## num), regions ## num } -const struct opl4_region_ptr snd_yrw801_regions[0x81] = { - REGION(_00), REGION(_01), REGION(_02), REGION(_03), - REGION(_04), REGION(_05), REGION(_06), REGION(_07), - REGION(_08), REGION(_09), REGION(_0a), REGION(_0b), - REGION(_0c), REGION(_0d), REGION(_0e), REGION(_0f), - REGION(_10), REGION(_11), REGION(_12), REGION(_13), - REGION(_14), REGION(_15), REGION(_16), REGION(_17), - REGION(_18), REGION(_19), REGION(_1a), REGION(_1b), - REGION(_1c), REGION(_1d), REGION(_1e), REGION(_1f), - REGION(_20), REGION(_21), REGION(_22), REGION(_23), - REGION(_24), REGION(_25), REGION(_26), REGION(_27), - REGION(_28), REGION(_29), REGION(_2a), REGION(_2b), - REGION(_2c), REGION(_2d), REGION(_2e), REGION(_2f), - REGION(_30), REGION(_31), REGION(_32), REGION(_33), - REGION(_34), REGION(_35), REGION(_36), REGION(_37), - REGION(_38), REGION(_39), REGION(_3a), REGION(_3b), - REGION(_3c), REGION(_3d), REGION(_3e), REGION(_3f), - REGION(_40), REGION(_41), REGION(_42), REGION(_43), - REGION(_44), REGION(_45), REGION(_46), REGION(_47), - REGION(_48), REGION(_49), REGION(_4a), REGION(_4b), - REGION(_4c), REGION(_4d), REGION(_4e), REGION(_4f), - REGION(_50), REGION(_51), REGION(_52), REGION(_53), - REGION(_54), REGION(_55), REGION(_56), REGION(_57), - REGION(_58), REGION(_59), REGION(_5a), REGION(_5b), - REGION(_5c), REGION(_5d), REGION(_5e), REGION(_5f), - REGION(_60), REGION(_61), REGION(_62), REGION(_63), - REGION(_64), REGION(_65), REGION(_66), REGION(_67), - REGION(_68), REGION(_69), REGION(_6a), REGION(_6b), - REGION(_6c), REGION(_6d), REGION(_6e), REGION(_6f), - REGION(_70), REGION(_71), REGION(_72), REGION(_73), - REGION(_74), REGION(_75), REGION(_76), REGION(_77), - REGION(_78), REGION(_79), REGION(_7a), REGION(_7b), - REGION(_7c), REGION(_7d), REGION(_7e), REGION(_7f), - REGION(_drums) -}; diff --git a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.c b/ANDROID_3.4.5/sound/drivers/pcm-indirect2.c deleted file mode 100644 index e73fafd7..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Helper functions for indirect PCM data transfer to a simple FIFO in - * hardware (small, no possibility to read "hardware io position", - * updating position done by interrupt, ...) - * - * Copyright (c) by 2007 Joachim Foerster <JOFT@gmx.de> - * - * Based on "pcm-indirect.h" (alsa-driver-1.0.13) by - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * Jaroslav Kysela <perex@suse.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* snd_printk/d() */ -#include <sound/core.h> -/* struct snd_pcm_substream, struct snd_pcm_runtime, snd_pcm_uframes_t - * snd_pcm_period_elapsed() */ -#include <sound/pcm.h> - -#include "pcm-indirect2.h" - -#ifdef SND_PCM_INDIRECT2_STAT -/* jiffies */ -#include <linux/jiffies.h> - -void snd_pcm_indirect2_stat(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int i; - int j; - int k; - int seconds = (rec->lastbytetime - rec->firstbytetime) / HZ; - - snd_printk(KERN_DEBUG "STAT: mul_elapsed: %u, mul_elapsed_real: %d, " - "irq_occured: %d\n", - rec->mul_elapsed, rec->mul_elapsed_real, rec->irq_occured); - snd_printk(KERN_DEBUG "STAT: min_multiple: %d (irqs/period)\n", - rec->min_multiple); - snd_printk(KERN_DEBUG "STAT: firstbytetime: %lu, lastbytetime: %lu, " - "firstzerotime: %lu\n", - rec->firstbytetime, rec->lastbytetime, rec->firstzerotime); - snd_printk(KERN_DEBUG "STAT: bytes2hw: %u Bytes => (by runtime->rate) " - "length: %d s\n", - rec->bytes2hw, rec->bytes2hw / 2 / 2 / runtime->rate); - snd_printk(KERN_DEBUG "STAT: (by measurement) length: %d => " - "rate: %d Bytes/s = %d Frames/s|Hz\n", - seconds, rec->bytes2hw / seconds, - rec->bytes2hw / 2 / 2 / seconds); - snd_printk(KERN_DEBUG - "STAT: zeros2hw: %u = %d ms ~ %d * %d zero copies\n", - rec->zeros2hw, ((rec->zeros2hw / 2 / 2) * 1000) / - runtime->rate, - rec->zeros2hw / (rec->hw_buffer_size / 2), - (rec->hw_buffer_size / 2)); - snd_printk(KERN_DEBUG "STAT: pointer_calls: %u, lastdifftime: %u\n", - rec->pointer_calls, rec->lastdifftime); - snd_printk(KERN_DEBUG "STAT: sw_io: %d, sw_data: %d\n", rec->sw_io, - rec->sw_data); - snd_printk(KERN_DEBUG "STAT: byte_sizes[]:\n"); - k = 0; - for (j = 0; j < 8; j++) { - for (i = j * 8; i < (j + 1) * 8; i++) - if (rec->byte_sizes[i] != 0) { - snd_printk(KERN_DEBUG "%u: %u", - i, rec->byte_sizes[i]); - k++; - } - if (((k % 8) == 0) && (k != 0)) { - snd_printk(KERN_DEBUG "\n"); - k = 0; - } - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG "STAT: zero_sizes[]:\n"); - for (j = 0; j < 8; j++) { - k = 0; - for (i = j * 8; i < (j + 1) * 8; i++) - if (rec->zero_sizes[i] != 0) - snd_printk(KERN_DEBUG "%u: %u", - i, rec->zero_sizes[i]); - else - k++; - if (!k) - snd_printk(KERN_DEBUG "\n"); - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG "STAT: min_adds[]:\n"); - for (j = 0; j < 8; j++) { - if (rec->min_adds[j] != 0) - snd_printk(KERN_DEBUG "%u: %u", j, rec->min_adds[j]); - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG "STAT: mul_adds[]:\n"); - for (j = 0; j < 8; j++) { - if (rec->mul_adds[j] != 0) - snd_printk(KERN_DEBUG "%u: %u", j, rec->mul_adds[j]); - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG - "STAT: zero_times_saved: %d, zero_times_notsaved: %d\n", - rec->zero_times_saved, rec->zero_times_notsaved); - /* snd_printk(KERN_DEBUG "STAT: zero_times[]\n"); - i = 0; - for (j = 0; j < 3750; j++) { - if (rec->zero_times[j] != 0) { - snd_printk(KERN_DEBUG "%u: %u", j, rec->zero_times[j]); - i++; - } - if (((i % 8) == 0) && (i != 0)) - snd_printk(KERN_DEBUG "\n"); - } - snd_printk(KERN_DEBUG "\n"); */ - return; -} -#endif - -/* - * _internal_ helper function for playback/capture transfer function - */ -static void -snd_pcm_indirect2_increase_min_periods(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - int isplay, int iscopy, - unsigned int bytes) -{ - if (rec->min_periods >= 0) { - if (iscopy) { - rec->sw_io += bytes; - if (rec->sw_io >= rec->sw_buffer_size) - rec->sw_io -= rec->sw_buffer_size; - } else if (isplay) { - /* If application does not write data in multiples of - * a period, move sw_data to the next correctly aligned - * position, so that sw_io can converge to it (in the - * next step). - */ - if (!rec->check_alignment) { - if (rec->bytes2hw % - snd_pcm_lib_period_bytes(substream)) { - unsigned bytes2hw_aligned = - (1 + - (rec->bytes2hw / - snd_pcm_lib_period_bytes - (substream))) * - snd_pcm_lib_period_bytes - (substream); - rec->sw_data = - bytes2hw_aligned % - rec->sw_buffer_size; -#ifdef SND_PCM_INDIRECT2_STAT - snd_printk(KERN_DEBUG - "STAT: @re-align: aligned " - "bytes2hw to next period " - "size boundary: %d " - "(instead of %d)\n", - bytes2hw_aligned, - rec->bytes2hw); - snd_printk(KERN_DEBUG - "STAT: @re-align: sw_data " - "moves to: %d\n", - rec->sw_data); -#endif - } - rec->check_alignment = 1; - } - /* We are at the end and are copying zeros into the - * fifo. - * Now, we have to make sure that sw_io is increased - * until the position of sw_data: Filling the fifo with - * the first zeros means, the last bytes were played. - */ - if (rec->sw_io != rec->sw_data) { - unsigned int diff; - if (rec->sw_data > rec->sw_io) - diff = rec->sw_data - rec->sw_io; - else - diff = (rec->sw_buffer_size - - rec->sw_io) + - rec->sw_data; - if (bytes >= diff) - rec->sw_io = rec->sw_data; - else { - rec->sw_io += bytes; - if (rec->sw_io >= rec->sw_buffer_size) - rec->sw_io -= - rec->sw_buffer_size; - } - } - } - rec->min_period_count += bytes; - if (rec->min_period_count >= (rec->hw_buffer_size / 2)) { - rec->min_periods += (rec->min_period_count / - (rec->hw_buffer_size / 2)); -#ifdef SND_PCM_INDIRECT2_STAT - if ((rec->min_period_count / - (rec->hw_buffer_size / 2)) > 7) - snd_printk(KERN_DEBUG - "STAT: more than 7 (%d) min_adds " - "at once - too big to save!\n", - (rec->min_period_count / - (rec->hw_buffer_size / 2))); - else - rec->min_adds[(rec->min_period_count / - (rec->hw_buffer_size / 2))]++; -#endif - rec->min_period_count = (rec->min_period_count % - (rec->hw_buffer_size / 2)); - } - } else if (isplay && iscopy) - rec->min_periods = 0; -} - -/* - * helper function for playback/capture pointer callback - */ -snd_pcm_uframes_t -snd_pcm_indirect2_pointer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ -#ifdef SND_PCM_INDIRECT2_STAT - rec->pointer_calls++; -#endif - return bytes_to_frames(substream->runtime, rec->sw_io); -} - -/* - * _internal_ helper function for playback interrupt callback - */ -static void -snd_pcm_indirect2_playback_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t zero) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; - - /* runtime->control->appl_ptr: position where ALSA will write next time - * rec->appl_ptr: position where ALSA was last time - * diff: obviously ALSA wrote that much bytes into the intermediate - * buffer since we checked last time - */ - snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr; - - if (diff) { -#ifdef SND_PCM_INDIRECT2_STAT - rec->lastdifftime = jiffies; -#endif - if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) - diff += runtime->boundary; - /* number of bytes "added" by ALSA increases the number of - * bytes which are ready to "be transferred to HW"/"played" - * Then, set rec->appl_ptr to not count bytes twice next time. - */ - rec->sw_ready += (int)frames_to_bytes(runtime, diff); - rec->appl_ptr = appl_ptr; - } - if (rec->hw_ready && (rec->sw_ready <= 0)) { - unsigned int bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstzerotime == 0) { - rec->firstzerotime = jiffies; - snd_printk(KERN_DEBUG - "STAT: @firstzerotime: mul_elapsed: %d, " - "min_period_count: %d\n", - rec->mul_elapsed, rec->min_period_count); - snd_printk(KERN_DEBUG - "STAT: @firstzerotime: sw_io: %d, " - "sw_data: %d, appl_ptr: %u\n", - rec->sw_io, rec->sw_data, - (unsigned int)appl_ptr); - } - if ((jiffies - rec->firstzerotime) < 3750) { - rec->zero_times[(jiffies - rec->firstzerotime)]++; - rec->zero_times_saved++; - } else - rec->zero_times_notsaved++; -#endif - bytes = zero(substream, rec); - -#ifdef SND_PCM_INDIRECT2_STAT - rec->zeros2hw += bytes; - if (bytes < 64) - rec->zero_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: %d zero Bytes copied to hardware at " - "once - too big to save!\n", - bytes); -#endif - snd_pcm_indirect2_increase_min_periods(substream, rec, 1, 0, - bytes); - return; - } - while (rec->hw_ready && (rec->sw_ready > 0)) { - /* sw_to_end: max. number of bytes that can be read/take from - * the current position (sw_data) in _one_ step - */ - unsigned int sw_to_end = rec->sw_buffer_size - rec->sw_data; - - /* bytes: number of bytes we have available (for reading) */ - unsigned int bytes = rec->sw_ready; - - if (sw_to_end < bytes) - bytes = sw_to_end; - if (!bytes) - break; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstbytetime == 0) - rec->firstbytetime = jiffies; - rec->lastbytetime = jiffies; -#endif - /* copy bytes from intermediate buffer position sw_data to the - * HW and return number of bytes actually written - * Furthermore, set hw_ready to 0, if the fifo isn't empty - * now => more could be transferred to fifo - */ - bytes = copy(substream, rec, bytes); - rec->bytes2hw += bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (bytes < 64) - rec->byte_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: %d Bytes copied to hardware at once " - "- too big to save!\n", - bytes); -#endif - /* increase sw_data by the number of actually written bytes - * (= number of taken bytes from intermediate buffer) - */ - rec->sw_data += bytes; - if (rec->sw_data == rec->sw_buffer_size) - rec->sw_data = 0; - /* now sw_data is the position where ALSA is going to write - * in the intermediate buffer next time = position we are going - * to read from next time - */ - - snd_pcm_indirect2_increase_min_periods(substream, rec, 1, 1, - bytes); - - /* we read bytes from intermediate buffer, so we need to say - * that the number of bytes ready for transfer are decreased - * now - */ - rec->sw_ready -= bytes; - } - return; -} - -/* - * helper function for playback interrupt routine - */ -void -snd_pcm_indirect2_playback_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t zero) -{ -#ifdef SND_PCM_INDIRECT2_STAT - rec->irq_occured++; -#endif - /* hardware played some bytes, so there is room again (in fifo) */ - rec->hw_ready = 1; - - /* don't call ack() now, instead call transfer() function directly - * (normally called by ack() ) - */ - snd_pcm_indirect2_playback_transfer(substream, rec, copy, zero); - - if (rec->min_periods >= rec->min_multiple) { -#ifdef SND_PCM_INDIRECT2_STAT - if ((rec->min_periods / rec->min_multiple) > 7) - snd_printk(KERN_DEBUG - "STAT: more than 7 (%d) mul_adds - too big " - "to save!\n", - (rec->min_periods / rec->min_multiple)); - else - rec->mul_adds[(rec->min_periods / - rec->min_multiple)]++; - rec->mul_elapsed_real += (rec->min_periods / - rec->min_multiple); - rec->mul_elapsed++; -#endif - rec->min_periods = (rec->min_periods % rec->min_multiple); - snd_pcm_period_elapsed(substream); - } -} - -/* - * _internal_ helper function for capture interrupt callback - */ -static void -snd_pcm_indirect2_capture_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t null) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; - snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr; - - if (diff) { -#ifdef SND_PCM_INDIRECT2_STAT - rec->lastdifftime = jiffies; -#endif - if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) - diff += runtime->boundary; - rec->sw_ready -= frames_to_bytes(runtime, diff); - rec->appl_ptr = appl_ptr; - } - /* if hardware has something, but the intermediate buffer is full - * => skip contents of buffer - */ - if (rec->hw_ready && (rec->sw_ready >= (int)rec->sw_buffer_size)) { - unsigned int bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstzerotime == 0) { - rec->firstzerotime = jiffies; - snd_printk(KERN_DEBUG "STAT: (capture) " - "@firstzerotime: mul_elapsed: %d, " - "min_period_count: %d\n", - rec->mul_elapsed, rec->min_period_count); - snd_printk(KERN_DEBUG "STAT: (capture) " - "@firstzerotime: sw_io: %d, sw_data: %d, " - "appl_ptr: %u\n", - rec->sw_io, rec->sw_data, - (unsigned int)appl_ptr); - } - if ((jiffies - rec->firstzerotime) < 3750) { - rec->zero_times[(jiffies - rec->firstzerotime)]++; - rec->zero_times_saved++; - } else - rec->zero_times_notsaved++; -#endif - bytes = null(substream, rec); - -#ifdef SND_PCM_INDIRECT2_STAT - rec->zeros2hw += bytes; - if (bytes < 64) - rec->zero_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: (capture) %d zero Bytes copied to " - "hardware at once - too big to save!\n", - bytes); -#endif - snd_pcm_indirect2_increase_min_periods(substream, rec, 0, 0, - bytes); - /* report an overrun */ - rec->sw_io = SNDRV_PCM_POS_XRUN; - return; - } - while (rec->hw_ready && (rec->sw_ready < (int)rec->sw_buffer_size)) { - /* sw_to_end: max. number of bytes that we can write to the - * intermediate buffer (until it's end) - */ - size_t sw_to_end = rec->sw_buffer_size - rec->sw_data; - - /* bytes: max. number of bytes, which may be copied to the - * intermediate buffer without overflow (in _one_ step) - */ - size_t bytes = rec->sw_buffer_size - rec->sw_ready; - - /* limit number of bytes (for transfer) by available room in - * the intermediate buffer - */ - if (sw_to_end < bytes) - bytes = sw_to_end; - if (!bytes) - break; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstbytetime == 0) - rec->firstbytetime = jiffies; - rec->lastbytetime = jiffies; -#endif - /* copy bytes from the intermediate buffer (position sw_data) - * to the HW at most and return number of bytes actually copied - * from HW - * Furthermore, set hw_ready to 0, if the fifo is empty now. - */ - bytes = copy(substream, rec, bytes); - rec->bytes2hw += bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (bytes < 64) - rec->byte_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: (capture) %d Bytes copied to " - "hardware at once - too big to save!\n", - bytes); -#endif - /* increase sw_data by the number of actually copied bytes from - * HW - */ - rec->sw_data += bytes; - if (rec->sw_data == rec->sw_buffer_size) - rec->sw_data = 0; - - snd_pcm_indirect2_increase_min_periods(substream, rec, 0, 1, - bytes); - - /* number of bytes in the intermediate buffer, which haven't - * been fetched by ALSA yet. - */ - rec->sw_ready += bytes; - } - return; -} - -/* - * helper function for capture interrupt routine - */ -void -snd_pcm_indirect2_capture_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t null) -{ -#ifdef SND_PCM_INDIRECT2_STAT - rec->irq_occured++; -#endif - /* hardware recorded some bytes, so there is something to read from the - * record fifo: - */ - rec->hw_ready = 1; - - /* don't call ack() now, instead call transfer() function directly - * (normally called by ack() ) - */ - snd_pcm_indirect2_capture_transfer(substream, rec, copy, null); - - if (rec->min_periods >= rec->min_multiple) { - -#ifdef SND_PCM_INDIRECT2_STAT - if ((rec->min_periods / rec->min_multiple) > 7) - snd_printk(KERN_DEBUG - "STAT: more than 7 (%d) mul_adds - " - "too big to save!\n", - (rec->min_periods / rec->min_multiple)); - else - rec->mul_adds[(rec->min_periods / - rec->min_multiple)]++; - rec->mul_elapsed_real += (rec->min_periods / - rec->min_multiple); - rec->mul_elapsed++; -#endif - rec->min_periods = (rec->min_periods % rec->min_multiple); - snd_pcm_period_elapsed(substream); - } -} diff --git a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.h b/ANDROID_3.4.5/sound/drivers/pcm-indirect2.h deleted file mode 100644 index 2ea6e460..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Helper functions for indirect PCM data transfer to a simple FIFO in - * hardware (small, no possibility to read "hardware io position", - * updating position done by interrupt, ...) - * - * Copyright (c) by 2007 Joachim Foerster <JOFT@gmx.de> - * - * Based on "pcm-indirect.h" (alsa-driver-1.0.13) by - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * Jaroslav Kysela <perex@suse.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __SOUND_PCM_INDIRECT2_H -#define __SOUND_PCM_INDIRECT2_H - -/* struct snd_pcm_substream, struct snd_pcm_runtime, snd_pcm_uframes_t */ -#include <sound/pcm.h> - -/* Debug options for code which may be removed completely in a final version */ -#ifdef CONFIG_SND_DEBUG -#define SND_PCM_INDIRECT2_STAT /* turn on some "statistics" about the - * process of copying bytes from the - * intermediate buffer to the hardware - * fifo and the other way round - */ -#endif - -struct snd_pcm_indirect2 { - unsigned int hw_buffer_size; /* Byte size of hardware buffer */ - int hw_ready; /* playback: 1 = hw fifo has room left, - * 0 = hw fifo is full - */ - unsigned int min_multiple; - int min_periods; /* counts number of min. periods until - * min_multiple is reached - */ - int min_period_count; /* counts bytes to count number of - * min. periods - */ - - unsigned int sw_buffer_size; /* Byte size of software buffer */ - - /* sw_data: position in intermediate buffer, where we will read (or - * write) from/to next time (to transfer data to/from HW) - */ - unsigned int sw_data; /* Offset to next dst (or src) in sw - * ring buffer - */ - /* easiest case (playback): - * sw_data is nearly the same as ~ runtime->control->appl_ptr, with the - * exception that sw_data is "behind" by the number if bytes ALSA wrote - * to the intermediate buffer last time. - * A call to ack() callback synchronizes both indirectly. - */ - - /* We have no real sw_io pointer here. Usually sw_io is pointing to the - * current playback/capture position _inside_ the hardware. Devices - * with plain FIFOs often have no possibility to publish this position. - * So we say: if sw_data is updated, that means bytes were copied to - * the hardware, we increase sw_io by that amount, because there have - * to be as much bytes which were played. So sw_io will stay behind - * sw_data all the time and has to converge to sw_data at the end of - * playback. - */ - unsigned int sw_io; /* Current software pointer in bytes */ - - /* sw_ready: number of bytes ALSA copied to the intermediate buffer, so - * it represents the number of bytes which wait for transfer to the HW - */ - int sw_ready; /* Bytes ready to be transferred to/from hw */ - - /* appl_ptr: last known position of ALSA (where ALSA is going to write - * next time into the intermediate buffer - */ - snd_pcm_uframes_t appl_ptr; /* Last seen appl_ptr */ - - unsigned int bytes2hw; - int check_alignment; - -#ifdef SND_PCM_INDIRECT2_STAT - unsigned int zeros2hw; - unsigned int mul_elapsed; - unsigned int mul_elapsed_real; - unsigned long firstbytetime; - unsigned long lastbytetime; - unsigned long firstzerotime; - unsigned int byte_sizes[64]; - unsigned int zero_sizes[64]; - unsigned int min_adds[8]; - unsigned int mul_adds[8]; - unsigned int zero_times[3750]; /* = 15s */ - unsigned int zero_times_saved; - unsigned int zero_times_notsaved; - unsigned int irq_occured; - unsigned int pointer_calls; - unsigned int lastdifftime; -#endif -}; - -typedef size_t (*snd_pcm_indirect2_copy_t) (struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - size_t bytes); -typedef size_t (*snd_pcm_indirect2_zero_t) (struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec); - -#ifdef SND_PCM_INDIRECT2_STAT -void snd_pcm_indirect2_stat(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec); -#endif - -snd_pcm_uframes_t -snd_pcm_indirect2_pointer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec); -void -snd_pcm_indirect2_playback_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t zero); -void -snd_pcm_indirect2_capture_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t null); - -#endif /* __SOUND_PCM_INDIRECT2_H */ diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/Makefile b/ANDROID_3.4.5/sound/drivers/pcsp/Makefile deleted file mode 100644 index b19555b4..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -snd-pcsp-objs := pcsp.o pcsp_lib.o pcsp_mixer.o pcsp_input.o -obj-$(CONFIG_SND_PCSP) += snd-pcsp.o diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c deleted file mode 100644 index 99704e6a..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 1997-2001 David Woodhouse - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <linux/input.h> -#include <linux/delay.h> -#include <asm/bitops.h> -#include "pcsp_input.h" -#include "pcsp.h" - -MODULE_AUTHOR("Stas Sergeev <stsp@users.sourceforge.net>"); -MODULE_DESCRIPTION("PC-Speaker driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{PC-Speaker, pcsp}}"); -MODULE_ALIAS("platform:pcspkr"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ -static bool nopcm; /* Disable PCM capability of the driver */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for pcsp soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for pcsp soundcard."); -module_param(enable, bool, 0444); -MODULE_PARM_DESC(enable, "Enable PC-Speaker sound."); -module_param(nopcm, bool, 0444); -MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain."); - -struct snd_pcsp pcsp_chip; - -static int __devinit snd_pcsp_create(struct snd_card *card) -{ - static struct snd_device_ops ops = { }; - struct timespec tp; - int err; - int div, min_div, order; - - if (!nopcm) { - hrtimer_get_res(CLOCK_MONOTONIC, &tp); - if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { - printk(KERN_ERR "PCSP: Timer resolution is not sufficient " - "(%linS)\n", tp.tv_nsec); - printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " - "enabled.\n"); - printk(KERN_ERR "PCSP: Turned into nopcm mode.\n"); - nopcm = 1; - } - } - - if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS) - min_div = MIN_DIV; - else - min_div = MAX_DIV; -#if PCSP_DEBUG - printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%li\n", - loops_per_jiffy, min_div, tp.tv_nsec); -#endif - - div = MAX_DIV / min_div; - order = fls(div) - 1; - - pcsp_chip.max_treble = min(order, PCSP_MAX_TREBLE); - pcsp_chip.treble = min(pcsp_chip.max_treble, PCSP_DEFAULT_TREBLE); - pcsp_chip.playback_ptr = 0; - pcsp_chip.period_ptr = 0; - atomic_set(&pcsp_chip.timer_active, 0); - pcsp_chip.enable = 1; - pcsp_chip.pcspkr = 1; - - spin_lock_init(&pcsp_chip.substream_lock); - - pcsp_chip.card = card; - pcsp_chip.port = 0x61; - pcsp_chip.irq = -1; - pcsp_chip.dma = -1; - - /* Register device */ - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops); - if (err < 0) - return err; - - return 0; -} - -static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) -{ - struct snd_card *card; - int err; - - if (devnum != 0) - return -EINVAL; - - hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - pcsp_chip.timer.function = pcsp_do_timer; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_pcsp_create(card); - if (err < 0) { - snd_card_free(card); - return err; - } - if (!nopcm) { - err = snd_pcsp_new_pcm(&pcsp_chip); - if (err < 0) { - snd_card_free(card); - return err; - } - } - err = snd_pcsp_new_mixer(&pcsp_chip, nopcm); - if (err < 0) { - snd_card_free(card); - return err; - } - - snd_card_set_dev(pcsp_chip.card, dev); - - strcpy(card->driver, "PC-Speaker"); - strcpy(card->shortname, "pcsp"); - sprintf(card->longname, "Internal PC-Speaker at port 0x%x", - pcsp_chip.port); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - - return 0; -} - -static int __devinit alsa_card_pcsp_init(struct device *dev) -{ - int err; - - err = snd_card_pcsp_probe(0, dev); - if (err) { - printk(KERN_ERR "PC-Speaker initialization failed.\n"); - return err; - } - -#ifdef CONFIG_DEBUG_PAGEALLOC - /* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */ - printk(KERN_WARNING "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, " - "which may make the sound noisy.\n"); -#endif - - return 0; -} - -static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip) -{ - snd_card_free(chip->card); -} - -static int __devinit pcsp_probe(struct platform_device *dev) -{ - int err; - - err = pcspkr_input_init(&pcsp_chip.input_dev, &dev->dev); - if (err < 0) - return err; - - err = alsa_card_pcsp_init(&dev->dev); - if (err < 0) { - pcspkr_input_remove(pcsp_chip.input_dev); - return err; - } - - platform_set_drvdata(dev, &pcsp_chip); - return 0; -} - -static int __devexit pcsp_remove(struct platform_device *dev) -{ - struct snd_pcsp *chip = platform_get_drvdata(dev); - alsa_card_pcsp_exit(chip); - pcspkr_input_remove(chip->input_dev); - platform_set_drvdata(dev, NULL); - return 0; -} - -static void pcsp_stop_beep(struct snd_pcsp *chip) -{ - pcsp_sync_stop(chip); - pcspkr_stop_sound(); -} - -#ifdef CONFIG_PM -static int pcsp_suspend(struct platform_device *dev, pm_message_t state) -{ - struct snd_pcsp *chip = platform_get_drvdata(dev); - pcsp_stop_beep(chip); - snd_pcm_suspend_all(chip->pcm); - return 0; -} -#else -#define pcsp_suspend NULL -#endif /* CONFIG_PM */ - -static void pcsp_shutdown(struct platform_device *dev) -{ - struct snd_pcsp *chip = platform_get_drvdata(dev); - pcsp_stop_beep(chip); -} - -static struct platform_driver pcsp_platform_driver = { - .driver = { - .name = "pcspkr", - .owner = THIS_MODULE, - }, - .probe = pcsp_probe, - .remove = __devexit_p(pcsp_remove), - .suspend = pcsp_suspend, - .shutdown = pcsp_shutdown, -}; - -static int __init pcsp_init(void) -{ - if (!enable) - return -ENODEV; - return platform_driver_register(&pcsp_platform_driver); -} - -static void __exit pcsp_exit(void) -{ - platform_driver_unregister(&pcsp_platform_driver); -} - -module_init(pcsp_init); -module_exit(pcsp_exit); diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h deleted file mode 100644 index fc7a2dc4..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 1993-1997 Michael Beck - * Copyright (C) 1997-2001 David Woodhouse - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#ifndef __PCSP_H__ -#define __PCSP_H__ - -#include <linux/hrtimer.h> -#include <linux/i8253.h> -#include <linux/timex.h> - -#define PCSP_SOUND_VERSION 0x400 /* read 4.00 */ -#define PCSP_DEBUG 0 - -/* default timer freq for PC-Speaker: 18643 Hz */ -#define DIV_18KHZ 64 -#define MAX_DIV DIV_18KHZ -#define CALC_DIV(d) (MAX_DIV >> (d)) -#define CUR_DIV() CALC_DIV(chip->treble) -#define PCSP_MAX_TREBLE 1 - -/* unfortunately, with hrtimers 37KHz does not work very well :( */ -#define PCSP_DEFAULT_TREBLE 0 -#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE) - -/* wild guess */ -#define PCSP_MIN_LPJ 1000000 -#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1) -#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV) -#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble)) -#define PCSP_CALC_RATE(i) (PIT_TICK_RATE / CALC_DIV(i)) -#define PCSP_RATE() PCSP_CALC_RATE(chip->treble) -#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE -#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE -#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1) -#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1) -#define PCSP_CALC_NS(div) ({ \ - u64 __val = 1000000000ULL * (div); \ - do_div(__val, PIT_TICK_RATE); \ - __val; \ -}) -#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV()) - -#define PCSP_MAX_PERIOD_SIZE (64*1024) -#define PCSP_MAX_PERIODS 512 -#define PCSP_BUFFER_SIZE (128*1024) - -struct snd_pcsp { - struct snd_card *card; - struct snd_pcm *pcm; - struct input_dev *input_dev; - struct hrtimer timer; - unsigned short port, irq, dma; - spinlock_t substream_lock; - struct snd_pcm_substream *playback_substream; - unsigned int fmt_size; - unsigned int is_signed; - size_t playback_ptr; - size_t period_ptr; - atomic_t timer_active; - int thalf; - u64 ns_rem; - unsigned char val61; - int enable; - int max_treble; - int treble; - int pcspkr; -}; - -extern struct snd_pcsp pcsp_chip; - -extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); -extern void pcsp_sync_stop(struct snd_pcsp *chip); - -extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); -extern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm); - -#endif diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c deleted file mode 100644 index b5e2b54c..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * PC Speaker beeper driver for Linux - * - * Copyright (c) 2002 Vojtech Pavlik - * Copyright (c) 1992 Orest Zborowski - * - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation - */ - -#include <linux/init.h> -#include <linux/input.h> -#include <asm/io.h> -#include "pcsp.h" - -static void pcspkr_do_sound(unsigned int count) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&i8253_lock, flags); - - if (count) { - /* set command for counter 2, 2 byte write */ - outb_p(0xB6, 0x43); - /* select desired HZ */ - outb_p(count & 0xff, 0x42); - outb((count >> 8) & 0xff, 0x42); - /* enable counter 2 */ - outb_p(inb_p(0x61) | 3, 0x61); - } else { - /* disable counter 2 */ - outb(inb_p(0x61) & 0xFC, 0x61); - } - - raw_spin_unlock_irqrestore(&i8253_lock, flags); -} - -void pcspkr_stop_sound(void) -{ - pcspkr_do_sound(0); -} - -static int pcspkr_input_event(struct input_dev *dev, unsigned int type, - unsigned int code, int value) -{ - unsigned int count = 0; - - if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr) - return 0; - - switch (type) { - case EV_SND: - switch (code) { - case SND_BELL: - if (value) - value = 1000; - case SND_TONE: - break; - default: - return -1; - } - break; - - default: - return -1; - } - - if (value > 20 && value < 32767) - count = PIT_TICK_RATE / value; - - pcspkr_do_sound(count); - - return 0; -} - -int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev) -{ - int err; - - struct input_dev *input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - input_dev->name = "PC Speaker"; - input_dev->phys = "isa0061/input0"; - input_dev->id.bustype = BUS_ISA; - input_dev->id.vendor = 0x001f; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - input_dev->dev.parent = dev; - - input_dev->evbit[0] = BIT(EV_SND); - input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - input_dev->event = pcspkr_input_event; - - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } - - *rdev = input_dev; - return 0; -} - -int pcspkr_input_remove(struct input_dev *dev) -{ - pcspkr_stop_sound(); - input_unregister_device(dev); /* this also does kfree() */ - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h deleted file mode 100644 index e66738c7..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#ifndef __PCSP_INPUT_H__ -#define __PCSP_INPUT_H__ - -int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev); -int pcspkr_input_remove(struct input_dev *dev); -void pcspkr_stop_sound(void); - -#endif diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c deleted file mode 100644 index 434981dd..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 1993-1997 Michael Beck - * Copyright (C) 1997-2001 David Woodhouse - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#include <linux/module.h> -#include <linux/gfp.h> -#include <linux/moduleparam.h> -#include <linux/interrupt.h> -#include <sound/pcm.h> -#include <asm/io.h> -#include "pcsp.h" - -static bool nforce_wa; -module_param(nforce_wa, bool, 0444); -MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " - "(expect bad sound)"); - -#define DMIX_WANTS_S16 1 - -/* - * Call snd_pcm_period_elapsed in a tasklet - * This avoids spinlock messes and long-running irq contexts - */ -static void pcsp_call_pcm_elapsed(unsigned long priv) -{ - if (atomic_read(&pcsp_chip.timer_active)) { - struct snd_pcm_substream *substream; - substream = pcsp_chip.playback_substream; - if (substream) - snd_pcm_period_elapsed(substream); - } -} - -static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); - -/* write the port and returns the next expire time in ns; - * called at the trigger-start and in hrtimer callback - */ -static u64 pcsp_timer_update(struct snd_pcsp *chip) -{ - unsigned char timer_cnt, val; - u64 ns; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned long flags; - - if (chip->thalf) { - outb(chip->val61, 0x61); - chip->thalf = 0; - return chip->ns_rem; - } - - substream = chip->playback_substream; - if (!substream) - return 0; - - runtime = substream->runtime; - /* assume it is mono! */ - val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1]; - if (chip->is_signed) - val ^= 0x80; - timer_cnt = val * CUR_DIV() / 256; - - if (timer_cnt && chip->enable) { - raw_spin_lock_irqsave(&i8253_lock, flags); - if (!nforce_wa) { - outb_p(chip->val61, 0x61); - outb_p(timer_cnt, 0x42); - outb(chip->val61 ^ 1, 0x61); - } else { - outb(chip->val61 ^ 2, 0x61); - chip->thalf = 1; - } - raw_spin_unlock_irqrestore(&i8253_lock, flags); - } - - chip->ns_rem = PCSP_PERIOD_NS(); - ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); - chip->ns_rem -= ns; - return ns; -} - -static void pcsp_pointer_update(struct snd_pcsp *chip) -{ - struct snd_pcm_substream *substream; - size_t period_bytes, buffer_bytes; - int periods_elapsed; - unsigned long flags; - - /* update the playback position */ - substream = chip->playback_substream; - if (!substream) - return; - - period_bytes = snd_pcm_lib_period_bytes(substream); - buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - - spin_lock_irqsave(&chip->substream_lock, flags); - chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size; - periods_elapsed = chip->playback_ptr - chip->period_ptr; - if (periods_elapsed < 0) { -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: buffer_bytes mod period_bytes != 0 ? " - "(%zi %zi %zi)\n", - chip->playback_ptr, period_bytes, buffer_bytes); -#endif - periods_elapsed += buffer_bytes; - } - periods_elapsed /= period_bytes; - /* wrap the pointer _before_ calling snd_pcm_period_elapsed(), - * or ALSA will BUG on us. */ - chip->playback_ptr %= buffer_bytes; - - if (periods_elapsed) { - chip->period_ptr += periods_elapsed * period_bytes; - chip->period_ptr %= buffer_bytes; - } - spin_unlock_irqrestore(&chip->substream_lock, flags); - - if (periods_elapsed) - tasklet_schedule(&pcsp_pcm_tasklet); -} - -enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) -{ - struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); - int pointer_update; - u64 ns; - - if (!atomic_read(&chip->timer_active) || !chip->playback_substream) - return HRTIMER_NORESTART; - - pointer_update = !chip->thalf; - ns = pcsp_timer_update(chip); - if (!ns) { - printk(KERN_WARNING "PCSP: unexpected stop\n"); - return HRTIMER_NORESTART; - } - - if (pointer_update) - pcsp_pointer_update(chip); - - hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns)); - - return HRTIMER_RESTART; -} - -static int pcsp_start_playing(struct snd_pcsp *chip) -{ -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: start_playing called\n"); -#endif - if (atomic_read(&chip->timer_active)) { - printk(KERN_ERR "PCSP: Timer already active\n"); - return -EIO; - } - - raw_spin_lock(&i8253_lock); - chip->val61 = inb(0x61) | 0x03; - outb_p(0x92, 0x43); /* binary, mode 1, LSB only, ch 2 */ - raw_spin_unlock(&i8253_lock); - atomic_set(&chip->timer_active, 1); - chip->thalf = 0; - - hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); - return 0; -} - -static void pcsp_stop_playing(struct snd_pcsp *chip) -{ -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: stop_playing called\n"); -#endif - if (!atomic_read(&chip->timer_active)) - return; - - atomic_set(&chip->timer_active, 0); - raw_spin_lock(&i8253_lock); - /* restore the timer */ - outb_p(0xb6, 0x43); /* binary, mode 3, LSB/MSB, ch 2 */ - outb(chip->val61 & 0xFC, 0x61); - raw_spin_unlock(&i8253_lock); -} - -/* - * Force to stop and sync the stream - */ -void pcsp_sync_stop(struct snd_pcsp *chip) -{ - local_irq_disable(); - pcsp_stop_playing(chip); - local_irq_enable(); - hrtimer_cancel(&chip->timer); - tasklet_kill(&pcsp_pcm_tasklet); -} - -static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: close called\n"); -#endif - pcsp_sync_stop(chip); - chip->playback_substream = NULL; - return 0; -} - -static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - int err; - pcsp_sync_stop(chip); - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - return 0; -} - -static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: hw_free called\n"); -#endif - pcsp_sync_stop(chip); - return snd_pcm_lib_free_pages(substream); -} - -static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - pcsp_sync_stop(chip); - chip->playback_ptr = 0; - chip->period_ptr = 0; - chip->fmt_size = - snd_pcm_format_physical_width(substream->runtime->format) >> 3; - chip->is_signed = snd_pcm_format_signed(substream->runtime->format); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: prepare called, " - "size=%zi psize=%zi f=%zi f1=%i fsize=%i\n", - snd_pcm_lib_buffer_bytes(substream), - snd_pcm_lib_period_bytes(substream), - snd_pcm_lib_buffer_bytes(substream) / - snd_pcm_lib_period_bytes(substream), - substream->runtime->periods, - chip->fmt_size); -#endif - return 0; -} - -static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: trigger called\n"); -#endif - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - return pcsp_start_playing(chip); - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - pcsp_stop_playing(chip); - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream - *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - unsigned int pos; - spin_lock(&chip->substream_lock); - pos = chip->playback_ptr; - spin_unlock(&chip->substream_lock); - return bytes_to_frames(substream->runtime, pos); -} - -static struct snd_pcm_hardware snd_pcsp_playback = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_HALF_DUPLEX | - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 -#if DMIX_WANTS_S16 - | SNDRV_PCM_FMTBIT_S16_LE -#endif - ), - .rates = SNDRV_PCM_RATE_KNOT, - .rate_min = PCSP_DEFAULT_SRATE, - .rate_max = PCSP_DEFAULT_SRATE, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = PCSP_BUFFER_SIZE, - .period_bytes_min = 64, - .period_bytes_max = PCSP_MAX_PERIOD_SIZE, - .periods_min = 2, - .periods_max = PCSP_MAX_PERIODS, - .fifo_size = 0, -}; - -static int snd_pcsp_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: open called\n"); -#endif - if (atomic_read(&chip->timer_active)) { - printk(KERN_ERR "PCSP: still active!!\n"); - return -EBUSY; - } - runtime->hw = snd_pcsp_playback; - chip->playback_substream = substream; - return 0; -} - -static struct snd_pcm_ops snd_pcsp_playback_ops = { - .open = snd_pcsp_playback_open, - .close = snd_pcsp_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pcsp_playback_hw_params, - .hw_free = snd_pcsp_playback_hw_free, - .prepare = snd_pcsp_playback_prepare, - .trigger = snd_pcsp_trigger, - .pointer = snd_pcsp_playback_pointer, -}; - -int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip) -{ - int err; - - err = snd_pcm_new(chip->card, "pcspeaker", 0, 1, 0, &chip->pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(chip->pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_pcsp_playback_ops); - - chip->pcm->private_data = chip; - chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - strcpy(chip->pcm->name, "pcsp"); - - snd_pcm_lib_preallocate_pages_for_all(chip->pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data - (GFP_KERNEL), PCSP_BUFFER_SIZE, - PCSP_BUFFER_SIZE); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c deleted file mode 100644 index 6f633f4f..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Mixer implementation. - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#include <sound/core.h> -#include <sound/control.h> -#include "pcsp.h" - - -static int pcsp_enable_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int pcsp_enable_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->enable; - return 0; -} - -static int pcsp_enable_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int enab = ucontrol->value.integer.value[0]; - if (enab != chip->enable) { - chip->enable = enab; - changed = 1; - } - return changed; -} - -static int pcsp_treble_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = chip->max_treble + 1; - if (uinfo->value.enumerated.item > chip->max_treble) - uinfo->value.enumerated.item = chip->max_treble; - sprintf(uinfo->value.enumerated.name, "%lu", - (unsigned long)PCSP_CALC_RATE(uinfo->value.enumerated.item)); - return 0; -} - -static int pcsp_treble_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = chip->treble; - return 0; -} - -static int pcsp_treble_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int treble = ucontrol->value.enumerated.item[0]; - if (treble != chip->treble) { - chip->treble = treble; -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE()); -#endif - changed = 1; - } - return changed; -} - -static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->pcspkr; - return 0; -} - -static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int spkr = ucontrol->value.integer.value[0]; - if (spkr != chip->pcspkr) { - chip->pcspkr = spkr; - changed = 1; - } - return changed; -} - -#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = ctl_name, \ - .info = pcsp_##ctl_type##_info, \ - .get = pcsp_##ctl_type##_get, \ - .put = pcsp_##ctl_type##_put, \ -} - -static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_pcm[] = { - PCSP_MIXER_CONTROL(enable, "Master Playback Switch"), - PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"), -}; - -static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_spkr[] = { - PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"), -}; - -static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip, - struct snd_kcontrol_new *ctls, int num) -{ - int i, err; - struct snd_card *card = chip->card; - for (i = 0; i < num; i++) { - err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip)); - if (err < 0) - return err; - } - return 0; -} - -int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm) -{ - int err; - struct snd_card *card = chip->card; - - if (!nopcm) { - err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm, - ARRAY_SIZE(snd_pcsp_controls_pcm)); - if (err < 0) - return err; - } - err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_spkr, - ARRAY_SIZE(snd_pcsp_controls_spkr)); - if (err < 0) - return err; - - strcpy(card->mixername, "PC-Speaker"); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/portman2x4.c b/ANDROID_3.4.5/sound/drivers/portman2x4.c deleted file mode 100644 index 3e32bd3d..00000000 --- a/ANDROID_3.4.5/sound/drivers/portman2x4.c +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Driver for Midiman Portman2x4 parallel port midi interface - * - * Copyright (c) by Levent Guendogdu <levon@feature-it.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * ChangeLog - * Jan 24 2007 Matthias Koenig <mkoenig@suse.de> - * - cleanup and rewrite - * Sep 30 2004 Tobias Gehrig <tobias@gehrig.tk> - * - source code cleanup - * Sep 03 2004 Tobias Gehrig <tobias@gehrig.tk> - * - fixed compilation problem with alsa 1.0.6a (removed MODULE_CLASSES, - * MODULE_PARM_SYNTAX and changed MODULE_DEVICES to - * MODULE_SUPPORTED_DEVICE) - * Mar 24 2004 Tobias Gehrig <tobias@gehrig.tk> - * - added 2.6 kernel support - * Mar 18 2004 Tobias Gehrig <tobias@gehrig.tk> - * - added parport_unregister_driver to the startup routine if the driver fails to detect a portman - * - added support for all 4 output ports in portman_putmidi - * Mar 17 2004 Tobias Gehrig <tobias@gehrig.tk> - * - added checks for opened input device in interrupt handler - * Feb 20 2004 Tobias Gehrig <tobias@gehrig.tk> - * - ported from alsa 0.5 to 1.0 - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/parport.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/rawmidi.h> -#include <sound/control.h> - -#define CARD_NAME "Portman 2x4" -#define DRIVER_NAME "portman" -#define PLATFORM_DRIVER "snd_portman2x4" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int device_count; - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, S_IRUGO); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -MODULE_AUTHOR("Levent Guendogdu, Tobias Gehrig, Matthias Koenig"); -MODULE_DESCRIPTION("Midiman Portman2x4"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Midiman,Portman2x4}}"); - -/********************************************************************* - * Chip specific - *********************************************************************/ -#define PORTMAN_NUM_INPUT_PORTS 2 -#define PORTMAN_NUM_OUTPUT_PORTS 4 - -struct portman { - spinlock_t reg_lock; - struct snd_card *card; - struct snd_rawmidi *rmidi; - struct pardevice *pardev; - int pardev_claimed; - - int open_count; - int mode[PORTMAN_NUM_INPUT_PORTS]; - struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS]; -}; - -static int portman_free(struct portman *pm) -{ - kfree(pm); - return 0; -} - -static int __devinit portman_create(struct snd_card *card, - struct pardevice *pardev, - struct portman **rchip) -{ - struct portman *pm; - - *rchip = NULL; - - pm = kzalloc(sizeof(struct portman), GFP_KERNEL); - if (pm == NULL) - return -ENOMEM; - - /* Init chip specific data */ - spin_lock_init(&pm->reg_lock); - pm->card = card; - pm->pardev = pardev; - - *rchip = pm; - - return 0; -} - -/********************************************************************* - * HW related constants - *********************************************************************/ - -/* Standard PC parallel port status register equates. */ -#define PP_STAT_BSY 0x80 /* Busy status. Inverted. */ -#define PP_STAT_ACK 0x40 /* Acknowledge. Non-Inverted. */ -#define PP_STAT_POUT 0x20 /* Paper Out. Non-Inverted. */ -#define PP_STAT_SEL 0x10 /* Select. Non-Inverted. */ -#define PP_STAT_ERR 0x08 /* Error. Non-Inverted. */ - -/* Standard PC parallel port command register equates. */ -#define PP_CMD_IEN 0x10 /* IRQ Enable. Non-Inverted. */ -#define PP_CMD_SELI 0x08 /* Select Input. Inverted. */ -#define PP_CMD_INIT 0x04 /* Init Printer. Non-Inverted. */ -#define PP_CMD_FEED 0x02 /* Auto Feed. Inverted. */ -#define PP_CMD_STB 0x01 /* Strobe. Inverted. */ - -/* Parallel Port Command Register as implemented by PCP2x4. */ -#define INT_EN PP_CMD_IEN /* Interrupt enable. */ -#define STROBE PP_CMD_STB /* Command strobe. */ - -/* The parallel port command register field (b1..b3) selects the - * various "registers" within the PC/P 2x4. These are the internal - * address of these "registers" that must be written to the parallel - * port command register. - */ -#define RXDATA0 (0 << 1) /* PCP RxData channel 0. */ -#define RXDATA1 (1 << 1) /* PCP RxData channel 1. */ -#define GEN_CTL (2 << 1) /* PCP General Control Register. */ -#define SYNC_CTL (3 << 1) /* PCP Sync Control Register. */ -#define TXDATA0 (4 << 1) /* PCP TxData channel 0. */ -#define TXDATA1 (5 << 1) /* PCP TxData channel 1. */ -#define TXDATA2 (6 << 1) /* PCP TxData channel 2. */ -#define TXDATA3 (7 << 1) /* PCP TxData channel 3. */ - -/* Parallel Port Status Register as implemented by PCP2x4. */ -#define ESTB PP_STAT_POUT /* Echoed strobe. */ -#define INT_REQ PP_STAT_ACK /* Input data int request. */ -#define BUSY PP_STAT_ERR /* Interface Busy. */ - -/* Parallel Port Status Register BUSY and SELECT lines are multiplexed - * between several functions. Depending on which 2x4 "register" is - * currently selected (b1..b3), the BUSY and SELECT lines are - * assigned as follows: - * - * SELECT LINE: A3 A2 A1 - * -------- - */ -#define RXAVAIL PP_STAT_SEL /* Rx Available, channel 0. 0 0 0 */ -// RXAVAIL1 PP_STAT_SEL /* Rx Available, channel 1. 0 0 1 */ -#define SYNC_STAT PP_STAT_SEL /* Reserved - Sync Status. 0 1 0 */ -// /* Reserved. 0 1 1 */ -#define TXEMPTY PP_STAT_SEL /* Tx Empty, channel 0. 1 0 0 */ -// TXEMPTY1 PP_STAT_SEL /* Tx Empty, channel 1. 1 0 1 */ -// TXEMPTY2 PP_STAT_SEL /* Tx Empty, channel 2. 1 1 0 */ -// TXEMPTY3 PP_STAT_SEL /* Tx Empty, channel 3. 1 1 1 */ - -/* BUSY LINE: A3 A2 A1 - * -------- - */ -#define RXDATA PP_STAT_BSY /* Rx Input Data, channel 0. 0 0 0 */ -// RXDATA1 PP_STAT_BSY /* Rx Input Data, channel 1. 0 0 1 */ -#define SYNC_DATA PP_STAT_BSY /* Reserved - Sync Data. 0 1 0 */ - /* Reserved. 0 1 1 */ -#define DATA_ECHO PP_STAT_BSY /* Parallel Port Data Echo. 1 0 0 */ -#define A0_ECHO PP_STAT_BSY /* Address 0 Echo. 1 0 1 */ -#define A1_ECHO PP_STAT_BSY /* Address 1 Echo. 1 1 0 */ -#define A2_ECHO PP_STAT_BSY /* Address 2 Echo. 1 1 1 */ - -#define PORTMAN2X4_MODE_INPUT_TRIGGERED 0x01 - -/********************************************************************* - * Hardware specific functions - *********************************************************************/ -static inline void portman_write_command(struct portman *pm, u8 value) -{ - parport_write_control(pm->pardev->port, value); -} - -static inline u8 portman_read_command(struct portman *pm) -{ - return parport_read_control(pm->pardev->port); -} - -static inline u8 portman_read_status(struct portman *pm) -{ - return parport_read_status(pm->pardev->port); -} - -static inline u8 portman_read_data(struct portman *pm) -{ - return parport_read_data(pm->pardev->port); -} - -static inline void portman_write_data(struct portman *pm, u8 value) -{ - parport_write_data(pm->pardev->port, value); -} - -static void portman_write_midi(struct portman *pm, - int port, u8 mididata) -{ - int command = ((port + 4) << 1); - - /* Get entering data byte and port number in BL and BH respectively. - * Set up Tx Channel address field for use with PP Cmd Register. - * Store address field in BH register. - * Inputs: AH = Output port number (0..3). - * AL = Data byte. - * command = TXDATA0 | INT_EN; - * Align port num with address field (b1...b3), - * set address for TXDatax, Strobe=0 - */ - command |= INT_EN; - - /* Disable interrupts so that the process is not interrupted, then - * write the address associated with the current Tx channel to the - * PP Command Reg. Do not set the Strobe signal yet. - */ - - do { - portman_write_command(pm, command); - - /* While the address lines settle, write parallel output data to - * PP Data Reg. This has no effect until Strobe signal is asserted. - */ - - portman_write_data(pm, mididata); - - /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP - * Status Register), then go write data. Else go back and wait. - */ - } while ((portman_read_status(pm) & TXEMPTY) != TXEMPTY); - - /* TxEmpty is set. Maintain PC/P destination address and assert - * Strobe through the PP Command Reg. This will Strobe data into - * the PC/P transmitter and set the PC/P BUSY signal. - */ - - portman_write_command(pm, command | STROBE); - - /* Wait for strobe line to settle and echo back through hardware. - * Once it has echoed back, assume that the address and data lines - * have settled! - */ - - while ((portman_read_status(pm) & ESTB) == 0) - cpu_relax(); - - /* Release strobe and immediately re-allow interrupts. */ - portman_write_command(pm, command); - - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); - - /* PC/P BUSY is now set. We must wait until BUSY resets itself. - * We'll reenable ints while we're waiting. - */ - - while ((portman_read_status(pm) & BUSY) == BUSY) - cpu_relax(); - - /* Data sent. */ -} - - -/* - * Read MIDI byte from port - * Attempt to read input byte from specified hardware input port (0..). - * Return -1 if no data - */ -static int portman_read_midi(struct portman *pm, int port) -{ - unsigned char midi_data = 0; - unsigned char cmdout; /* Saved address+IE bit. */ - - /* Make sure clocking edge is down before starting... */ - portman_write_data(pm, 0); /* Make sure edge is down. */ - - /* Set destination address to PCP. */ - cmdout = (port << 1) | INT_EN; /* Address + IE + No Strobe. */ - portman_write_command(pm, cmdout); - - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); /* Wait for strobe echo. */ - - /* After the address lines settle, check multiplexed RxAvail signal. - * If data is available, read it. - */ - if ((portman_read_status(pm) & RXAVAIL) == 0) - return -1; /* No data. */ - - /* Set the Strobe signal to enable the Rx clocking circuitry. */ - portman_write_command(pm, cmdout | STROBE); /* Write address+IE+Strobe. */ - - while ((portman_read_status(pm) & ESTB) == 0) - cpu_relax(); /* Wait for strobe echo. */ - - /* The first data bit (msb) is already sitting on the input line. */ - midi_data = (portman_read_status(pm) & 128); - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 6. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 1) & 64; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 5. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 2) & 32; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 4. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 3) & 16; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 3. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 4) & 8; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 2. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 5) & 4; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 1. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 6) & 2; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 0. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 7) & 1; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - portman_write_data(pm, 0); /* Return data clock low. */ - - - /* De-assert Strobe and return data. */ - portman_write_command(pm, cmdout); /* Output saved address+IE. */ - - /* Wait for strobe echo. */ - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); - - return (midi_data & 255); /* Shift back and return value. */ -} - -/* - * Checks if any input data on the given channel is available - * Checks RxAvail - */ -static int portman_data_avail(struct portman *pm, int channel) -{ - int command = INT_EN; - switch (channel) { - case 0: - command |= RXDATA0; - break; - case 1: - command |= RXDATA1; - break; - } - /* Write hardware (assumme STROBE=0) */ - portman_write_command(pm, command); - /* Check multiplexed RxAvail signal */ - if ((portman_read_status(pm) & RXAVAIL) == RXAVAIL) - return 1; /* Data available */ - - /* No Data available */ - return 0; -} - - -/* - * Flushes any input - */ -static void portman_flush_input(struct portman *pm, unsigned char port) -{ - /* Local variable for counting things */ - unsigned int i = 0; - unsigned char command = 0; - - switch (port) { - case 0: - command = RXDATA0; - break; - case 1: - command = RXDATA1; - break; - default: - snd_printk(KERN_WARNING - "portman_flush_input() Won't flush port %i\n", - port); - return; - } - - /* Set address for specified channel in port and allow to settle. */ - portman_write_command(pm, command); - - /* Assert the Strobe and wait for echo back. */ - portman_write_command(pm, command | STROBE); - - /* Wait for ESTB */ - while ((portman_read_status(pm) & ESTB) == 0) - cpu_relax(); - - /* Output clock cycles to the Rx circuitry. */ - portman_write_data(pm, 0); - - /* Flush 250 bits... */ - for (i = 0; i < 250; i++) { - portman_write_data(pm, 1); - portman_write_data(pm, 0); - } - - /* Deassert the Strobe signal of the port and wait for it to settle. */ - portman_write_command(pm, command | INT_EN); - - /* Wait for settling */ - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); -} - -static int portman_probe(struct parport *p) -{ - /* Initialize the parallel port data register. Will set Rx clocks - * low in case we happen to be addressing the Rx ports at this time. - */ - /* 1 */ - parport_write_data(p, 0); - - /* Initialize the parallel port command register, thus initializing - * hardware handshake lines to midi box: - * - * Strobe = 0 - * Interrupt Enable = 0 - */ - /* 2 */ - parport_write_control(p, 0); - - /* Check if Portman PC/P 2x4 is out there. */ - /* 3 */ - parport_write_control(p, RXDATA0); /* Write Strobe=0 to command reg. */ - - /* Check for ESTB to be clear */ - /* 4 */ - if ((parport_read_status(p) & ESTB) == ESTB) - return 1; /* CODE 1 - Strobe Failure. */ - - /* Set for RXDATA0 where no damage will be done. */ - /* 5 */ - parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */ - - /* 6 */ - if ((parport_read_status(p) & ESTB) != ESTB) - return 1; /* CODE 1 - Strobe Failure. */ - - /* 7 */ - parport_write_control(p, 0); /* Reset Strobe=0. */ - - /* Check if Tx circuitry is functioning properly. If initialized - * unit TxEmpty is false, send out char and see if if goes true. - */ - /* 8 */ - parport_write_control(p, TXDATA0); /* Tx channel 0, strobe off. */ - - /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP - * Status Register), then go write data. Else go back and wait. - */ - /* 9 */ - if ((parport_read_status(p) & TXEMPTY) == 0) - return 2; - - /* Return OK status. */ - return 0; -} - -static int portman_device_init(struct portman *pm) -{ - portman_flush_input(pm, 0); - portman_flush_input(pm, 1); - - return 0; -} - -/********************************************************************* - * Rawmidi - *********************************************************************/ -static int snd_portman_midi_open(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static int snd_portman_midi_close(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct portman *pm = substream->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&pm->reg_lock, flags); - if (up) - pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED; - else - pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&pm->reg_lock, flags); -} - -static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct portman *pm = substream->rmidi->private_data; - unsigned long flags; - unsigned char byte; - - spin_lock_irqsave(&pm->reg_lock, flags); - if (up) { - while ((snd_rawmidi_transmit(substream, &byte, 1) == 1)) - portman_write_midi(pm, substream->number, byte); - } - spin_unlock_irqrestore(&pm->reg_lock, flags); -} - -static struct snd_rawmidi_ops snd_portman_midi_output = { - .open = snd_portman_midi_open, - .close = snd_portman_midi_close, - .trigger = snd_portman_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_portman_midi_input = { - .open = snd_portman_midi_open, - .close = snd_portman_midi_close, - .trigger = snd_portman_midi_input_trigger, -}; - -/* Create and initialize the rawmidi component */ -static int __devinit snd_portman_rawmidi_create(struct snd_card *card) -{ - struct portman *pm = card->private_data; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream; - int err; - - err = snd_rawmidi_new(card, CARD_NAME, 0, - PORTMAN_NUM_OUTPUT_PORTS, - PORTMAN_NUM_INPUT_PORTS, - &rmidi); - if (err < 0) - return err; - - rmidi->private_data = pm; - strcpy(rmidi->name, CARD_NAME); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - pm->rmidi = rmidi; - - /* register rawmidi ops */ - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_portman_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_portman_midi_input); - - /* name substreams */ - /* output */ - list_for_each_entry(substream, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams, - list) { - sprintf(substream->name, - "Portman2x4 %d", substream->number+1); - } - /* input */ - list_for_each_entry(substream, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams, - list) { - pm->midi_input[substream->number] = substream; - sprintf(substream->name, - "Portman2x4 %d", substream->number+1); - } - - return err; -} - -/********************************************************************* - * parport stuff - *********************************************************************/ -static void snd_portman_interrupt(void *userdata) -{ - unsigned char midivalue = 0; - struct portman *pm = ((struct snd_card*)userdata)->private_data; - - spin_lock(&pm->reg_lock); - - /* While any input data is waiting */ - while ((portman_read_status(pm) & INT_REQ) == INT_REQ) { - /* If data available on channel 0, - read it and stuff it into the queue. */ - if (portman_data_avail(pm, 0)) { - /* Read Midi */ - midivalue = portman_read_midi(pm, 0); - /* put midi into queue... */ - if (pm->mode[0] & PORTMAN2X4_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(pm->midi_input[0], - &midivalue, 1); - - } - /* If data available on channel 1, - read it and stuff it into the queue. */ - if (portman_data_avail(pm, 1)) { - /* Read Midi */ - midivalue = portman_read_midi(pm, 1); - /* put midi into queue... */ - if (pm->mode[1] & PORTMAN2X4_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(pm->midi_input[1], - &midivalue, 1); - } - - } - - spin_unlock(&pm->reg_lock); -} - -static int __devinit snd_portman_probe_port(struct parport *p) -{ - struct pardevice *pardev; - int res; - - pardev = parport_register_device(p, DRIVER_NAME, - NULL, NULL, NULL, - 0, NULL); - if (!pardev) - return -EIO; - - if (parport_claim(pardev)) { - parport_unregister_device(pardev); - return -EIO; - } - - res = portman_probe(p); - - parport_release(pardev); - parport_unregister_device(pardev); - - return res ? -EIO : 0; -} - -static void __devinit snd_portman_attach(struct parport *p) -{ - struct platform_device *device; - - device = platform_device_alloc(PLATFORM_DRIVER, device_count); - if (!device) - return; - - /* Temporary assignment to forward the parport */ - platform_set_drvdata(device, p); - - if (platform_device_add(device) < 0) { - platform_device_put(device); - return; - } - - /* Since we dont get the return value of probe - * We need to check if device probing succeeded or not */ - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - return; - } - - /* register device in global table */ - platform_devices[device_count] = device; - device_count++; -} - -static void snd_portman_detach(struct parport *p) -{ - /* nothing to do here */ -} - -static struct parport_driver portman_parport_driver = { - .name = "portman2x4", - .attach = snd_portman_attach, - .detach = snd_portman_detach -}; - -/********************************************************************* - * platform stuff - *********************************************************************/ -static void snd_portman_card_private_free(struct snd_card *card) -{ - struct portman *pm = card->private_data; - struct pardevice *pardev = pm->pardev; - - if (pardev) { - if (pm->pardev_claimed) - parport_release(pardev); - parport_unregister_device(pardev); - } - - portman_free(pm); -} - -static int __devinit snd_portman_probe(struct platform_device *pdev) -{ - struct pardevice *pardev; - struct parport *p; - int dev = pdev->id; - struct snd_card *card = NULL; - struct portman *pm = NULL; - int err; - - p = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) - return -ENOENT; - - if ((err = snd_portman_probe_port(p)) < 0) - return err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printd("Cannot create card\n"); - return err; - } - strcpy(card->driver, DRIVER_NAME); - strcpy(card->shortname, CARD_NAME); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, p->base, p->irq); - - pardev = parport_register_device(p, /* port */ - DRIVER_NAME, /* name */ - NULL, /* preempt */ - NULL, /* wakeup */ - snd_portman_interrupt, /* ISR */ - PARPORT_DEV_EXCL, /* flags */ - (void *)card); /* private */ - if (pardev == NULL) { - snd_printd("Cannot register pardevice\n"); - err = -EIO; - goto __err; - } - - if ((err = portman_create(card, pardev, &pm)) < 0) { - snd_printd("Cannot create main component\n"); - parport_unregister_device(pardev); - goto __err; - } - card->private_data = pm; - card->private_free = snd_portman_card_private_free; - - if ((err = snd_portman_rawmidi_create(card)) < 0) { - snd_printd("Creating Rawmidi component failed\n"); - goto __err; - } - - /* claim parport */ - if (parport_claim(pardev)) { - snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); - err = -EIO; - goto __err; - } - pm->pardev_claimed = 1; - - /* init device */ - if ((err = portman_device_init(pm)) < 0) - goto __err; - - platform_set_drvdata(pdev, card); - - snd_card_set_dev(card, &pdev->dev); - - /* At this point card will be usable */ - if ((err = snd_card_register(card)) < 0) { - snd_printd("Cannot register card\n"); - goto __err; - } - - snd_printk(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base); - return 0; - -__err: - snd_card_free(card); - return err; -} - -static int __devexit snd_portman_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - if (card) - snd_card_free(card); - - return 0; -} - - -static struct platform_driver snd_portman_driver = { - .probe = snd_portman_probe, - .remove = __devexit_p(snd_portman_remove), - .driver = { - .name = PLATFORM_DRIVER - } -}; - -/********************************************************************* - * module init stuff - *********************************************************************/ -static void snd_portman_unregister_all(void) -{ - int i; - - for (i = 0; i < SNDRV_CARDS; ++i) { - if (platform_devices[i]) { - platform_device_unregister(platform_devices[i]); - platform_devices[i] = NULL; - } - } - platform_driver_unregister(&snd_portman_driver); - parport_unregister_driver(&portman_parport_driver); -} - -static int __init snd_portman_module_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_portman_driver)) < 0) - return err; - - if (parport_register_driver(&portman_parport_driver) != 0) { - platform_driver_unregister(&snd_portman_driver); - return -EIO; - } - - if (device_count == 0) { - snd_portman_unregister_all(); - return -ENODEV; - } - - return 0; -} - -static void __exit snd_portman_module_exit(void) -{ - snd_portman_unregister_all(); -} - -module_init(snd_portman_module_init); -module_exit(snd_portman_module_exit); diff --git a/ANDROID_3.4.5/sound/drivers/serial-u16550.c b/ANDROID_3.4.5/sound/drivers/serial-u16550.c deleted file mode 100644 index b2d0e8e4..00000000 --- a/ANDROID_3.4.5/sound/drivers/serial-u16550.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* - * serial.c - * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, - * Isaku Yamahata <yamahata@private.email.ne.jp>, - * George Hansper <ghansper@apana.org.au>, - * Hannu Savolainen - * - * This code is based on the code from ALSA 0.5.9, but heavily rewritten. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Sat Mar 31 17:27:57 PST 2001 tim.mann@compaq.com - * Added support for the Midiator MS-124T and for the MS-124W in - * Single Addressed (S/A) or Multiple Burst (M/B) mode, with - * power derived either parasitically from the serial port or - * from a separate power supply. - * - * More documentation can be found in serial-u16550.txt. - */ - -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/rawmidi.h> -#include <sound/initval.h> - -#include <linux/serial_reg.h> -#include <linux/jiffies.h> - -#include <asm/io.h> - -MODULE_DESCRIPTION("MIDI serial u16550"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}"); - -#define SNDRV_SERIAL_SOUNDCANVAS 0 /* Roland Soundcanvas; F5 NN selects part */ -#define SNDRV_SERIAL_MS124T 1 /* Midiator MS-124T */ -#define SNDRV_SERIAL_MS124W_SA 2 /* Midiator MS-124W in S/A mode */ -#define SNDRV_SERIAL_MS124W_MB 3 /* Midiator MS-124W in M/B mode */ -#define SNDRV_SERIAL_GENERIC 4 /* Generic Interface */ -#define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_GENERIC -static char *adaptor_names[] = { - "Soundcanvas", - "MS-124T", - "MS-124W S/A", - "MS-124W M/B", - "Generic" -}; - -#define SNDRV_SERIAL_NORMALBUFF 0 /* Normal blocking buffer operation */ -#define SNDRV_SERIAL_DROPBUFF 1 /* Non-blocking discard operation */ - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x3f8,0x2f8,0x3e8,0x2e8 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,4,5,7,9,10,11,14,15 */ -static int speed[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 38400}; /* 9600,19200,38400,57600,115200 */ -static int base[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 115200}; /* baud base */ -static int outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */ -static int ins[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */ -static int adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS}; -static bool droponfull[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS -1)] = SNDRV_SERIAL_NORMALBUFF }; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Serial MIDI."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Serial MIDI."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable UART16550A chip."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for UART16550A chip."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for UART16550A chip."); -module_param_array(speed, int, NULL, 0444); -MODULE_PARM_DESC(speed, "Speed in bauds."); -module_param_array(base, int, NULL, 0444); -MODULE_PARM_DESC(base, "Base for divisor in bauds."); -module_param_array(outs, int, NULL, 0444); -MODULE_PARM_DESC(outs, "Number of MIDI outputs."); -module_param_array(ins, int, NULL, 0444); -MODULE_PARM_DESC(ins, "Number of MIDI inputs."); -module_param_array(droponfull, bool, NULL, 0444); -MODULE_PARM_DESC(droponfull, "Flag to enable drop-on-full buffer mode"); - -module_param_array(adaptor, int, NULL, 0444); -MODULE_PARM_DESC(adaptor, "Type of adaptor."); - -/*#define SNDRV_SERIAL_MS124W_MB_NOCOMBO 1*/ /* Address outs as 0-3 instead of bitmap */ - -#define SNDRV_SERIAL_MAX_OUTS 16 /* max 64, min 16 */ -#define SNDRV_SERIAL_MAX_INS 16 /* max 64, min 16 */ - -#define TX_BUFF_SIZE (1<<15) /* Must be 2^n */ -#define TX_BUFF_MASK (TX_BUFF_SIZE - 1) - -#define SERIAL_MODE_NOT_OPENED (0) -#define SERIAL_MODE_INPUT_OPEN (1 << 0) -#define SERIAL_MODE_OUTPUT_OPEN (1 << 1) -#define SERIAL_MODE_INPUT_TRIGGERED (1 << 2) -#define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3) - -struct snd_uart16550 { - struct snd_card *card; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS]; - struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS]; - - int filemode; /* open status of file */ - - spinlock_t open_lock; - - int irq; - - unsigned long base; - struct resource *res_base; - - unsigned int speed; - unsigned int speed_base; - unsigned char divisor; - - unsigned char old_divisor_lsb; - unsigned char old_divisor_msb; - unsigned char old_line_ctrl_reg; - - /* parameter for using of write loop */ - short int fifo_limit; /* used in uart16550 */ - short int fifo_count; /* used in uart16550 */ - - /* type of adaptor */ - int adaptor; - - /* inputs */ - int prev_in; - unsigned char rstatus; - - /* outputs */ - int prev_out; - unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS]; - - /* write buffer and its writing/reading position */ - unsigned char tx_buff[TX_BUFF_SIZE]; - int buff_in_count; - int buff_in; - int buff_out; - int drop_on_full; - - /* wait timer */ - unsigned int timer_running:1; - struct timer_list buffer_timer; - -}; - -static struct platform_device *devices[SNDRV_CARDS]; - -static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart) -{ - if (!uart->timer_running) { - /* timer 38600bps * 10bit * 16byte */ - uart->buffer_timer.expires = jiffies + (HZ+255)/256; - uart->timer_running = 1; - add_timer(&uart->buffer_timer); - } -} - -static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart) -{ - if (uart->timer_running) { - del_timer(&uart->buffer_timer); - uart->timer_running = 0; - } -} - -/* This macro is only used in snd_uart16550_io_loop */ -static inline void snd_uart16550_buffer_output(struct snd_uart16550 *uart) -{ - unsigned short buff_out = uart->buff_out; - if (uart->buff_in_count > 0) { - outb(uart->tx_buff[buff_out], uart->base + UART_TX); - uart->fifo_count++; - buff_out++; - buff_out &= TX_BUFF_MASK; - uart->buff_out = buff_out; - uart->buff_in_count--; - } -} - -/* This loop should be called with interrupts disabled - * We don't want to interrupt this, - * as we're already handling an interrupt - */ -static void snd_uart16550_io_loop(struct snd_uart16550 * uart) -{ - unsigned char c, status; - int substream; - - /* recall previous stream */ - substream = uart->prev_in; - - /* Read Loop */ - while ((status = inb(uart->base + UART_LSR)) & UART_LSR_DR) { - /* while receive data ready */ - c = inb(uart->base + UART_RX); - - /* keep track of last status byte */ - if (c & 0x80) - uart->rstatus = c; - - /* handle stream switch */ - if (uart->adaptor == SNDRV_SERIAL_GENERIC) { - if (uart->rstatus == 0xf5) { - if (c <= SNDRV_SERIAL_MAX_INS && c > 0) - substream = c - 1; - if (c != 0xf5) - /* prevent future bytes from being - interpreted as streams */ - uart->rstatus = 0; - } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) - && uart->midi_input[substream]) - snd_rawmidi_receive(uart->midi_input[substream], - &c, 1); - } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && - uart->midi_input[substream]) - snd_rawmidi_receive(uart->midi_input[substream], &c, 1); - - if (status & UART_LSR_OE) - snd_printk(KERN_WARNING - "%s: Overrun on device at 0x%lx\n", - uart->rmidi->name, uart->base); - } - - /* remember the last stream */ - uart->prev_in = substream; - - /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not, - buffer is never filled. */ - /* Check write status */ - if (status & UART_LSR_THRE) - uart->fifo_count = 0; - if (uart->adaptor == SNDRV_SERIAL_MS124W_SA - || uart->adaptor == SNDRV_SERIAL_GENERIC) { - /* Can't use FIFO, must send only when CTS is true */ - status = inb(uart->base + UART_MSR); - while (uart->fifo_count == 0 && (status & UART_MSR_CTS) && - uart->buff_in_count > 0) { - snd_uart16550_buffer_output(uart); - status = inb(uart->base + UART_MSR); - } - } else { - /* Write loop */ - while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ - && uart->buff_in_count > 0) /* Do we want to? */ - snd_uart16550_buffer_output(uart); - } - if (uart->irq < 0 && uart->buff_in_count > 0) - snd_uart16550_add_timer(uart); -} - -/* NOTES ON SERVICING INTERUPTS - * --------------------------- - * After receiving a interrupt, it is important to indicate to the UART that - * this has been done. - * For a Rx interrupt, this is done by reading the received byte. - * For a Tx interrupt this is done by either: - * a) Writing a byte - * b) Reading the IIR - * It is particularly important to read the IIR if a Tx interrupt is received - * when there is no data in tx_buff[], as in this case there no other - * indication that the interrupt has been serviced, and it remains outstanding - * indefinitely. This has the curious side effect that and no further interrupts - * will be generated from this device AT ALL!!. - * It is also desirable to clear outstanding interrupts when the device is - * opened/closed. - * - * - * Note that some devices need OUT2 to be set before they will generate - * interrupts at all. (Possibly tied to an internal pull-up on CTS?) - */ -static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) -{ - struct snd_uart16550 *uart; - - uart = dev_id; - spin_lock(&uart->open_lock); - if (uart->filemode == SERIAL_MODE_NOT_OPENED) { - spin_unlock(&uart->open_lock); - return IRQ_NONE; - } - /* indicate to the UART that the interrupt has been serviced */ - inb(uart->base + UART_IIR); - snd_uart16550_io_loop(uart); - spin_unlock(&uart->open_lock); - return IRQ_HANDLED; -} - -/* When the polling mode, this function calls snd_uart16550_io_loop. */ -static void snd_uart16550_buffer_timer(unsigned long data) -{ - unsigned long flags; - struct snd_uart16550 *uart; - - uart = (struct snd_uart16550 *)data; - spin_lock_irqsave(&uart->open_lock, flags); - snd_uart16550_del_timer(uart); - snd_uart16550_io_loop(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); -} - -/* - * this method probes, if an uart sits on given port - * return 0 if found - * return negative error if not found - */ -static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart) -{ - unsigned long io_base = uart->base; - int ok; - unsigned char c; - - /* Do some vague tests for the presence of the uart */ - if (io_base == 0 || io_base == SNDRV_AUTO_PORT) { - return -ENODEV; /* Not configured */ - } - - uart->res_base = request_region(io_base, 8, "Serial MIDI"); - if (uart->res_base == NULL) { - snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base); - return -EBUSY; - } - - /* uart detected unless one of the following tests should fail */ - ok = 1; - /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */ - outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */ - c = inb(io_base + UART_IER); - /* The top four bits of the IER should always == 0 */ - if ((c & 0xf0) != 0) - ok = 0; /* failed */ - - outb(0xaa, io_base + UART_SCR); - /* Write arbitrary data into the scratch reg */ - c = inb(io_base + UART_SCR); - /* If it comes back, it's OK */ - if (c != 0xaa) - ok = 0; /* failed */ - - outb(0x55, io_base + UART_SCR); - /* Write arbitrary data into the scratch reg */ - c = inb(io_base + UART_SCR); - /* If it comes back, it's OK */ - if (c != 0x55) - ok = 0; /* failed */ - - return ok; -} - -static void snd_uart16550_do_open(struct snd_uart16550 * uart) -{ - char byte; - - /* Initialize basic variables */ - uart->buff_in_count = 0; - uart->buff_in = 0; - uart->buff_out = 0; - uart->fifo_limit = 1; - uart->fifo_count = 0; - uart->timer_running = 0; - - outb(UART_FCR_ENABLE_FIFO /* Enable FIFO's (if available) */ - | UART_FCR_CLEAR_RCVR /* Clear receiver FIFO */ - | UART_FCR_CLEAR_XMIT /* Clear transmitter FIFO */ - | UART_FCR_TRIGGER_4 /* Set FIFO trigger at 4-bytes */ - /* NOTE: interrupt generated after T=(time)4-bytes - * if less than UART_FCR_TRIGGER bytes received - */ - ,uart->base + UART_FCR); /* FIFO Control Register */ - - if ((inb(uart->base + UART_IIR) & 0xf0) == 0xc0) - uart->fifo_limit = 16; - if (uart->divisor != 0) { - uart->old_line_ctrl_reg = inb(uart->base + UART_LCR); - outb(UART_LCR_DLAB /* Divisor latch access bit */ - ,uart->base + UART_LCR); /* Line Control Register */ - uart->old_divisor_lsb = inb(uart->base + UART_DLL); - uart->old_divisor_msb = inb(uart->base + UART_DLM); - - outb(uart->divisor - ,uart->base + UART_DLL); /* Divisor Latch Low */ - outb(0 - ,uart->base + UART_DLM); /* Divisor Latch High */ - /* DLAB is reset to 0 in next outb() */ - } - /* Set serial parameters (parity off, etc) */ - outb(UART_LCR_WLEN8 /* 8 data-bits */ - | 0 /* 1 stop-bit */ - | 0 /* parity off */ - | 0 /* DLAB = 0 */ - ,uart->base + UART_LCR); /* Line Control Register */ - - switch (uart->adaptor) { - default: - outb(UART_MCR_RTS /* Set Request-To-Send line active */ - | UART_MCR_DTR /* Set Data-Terminal-Ready line active */ - | UART_MCR_OUT2 /* Set OUT2 - not always required, but when - * it is, it is ESSENTIAL for enabling interrupts - */ - ,uart->base + UART_MCR); /* Modem Control Register */ - break; - case SNDRV_SERIAL_MS124W_SA: - case SNDRV_SERIAL_MS124W_MB: - /* MS-124W can draw power from RTS and DTR if they - are in opposite states. */ - outb(UART_MCR_RTS | (0&UART_MCR_DTR) | UART_MCR_OUT2, - uart->base + UART_MCR); - break; - case SNDRV_SERIAL_MS124T: - /* MS-124T can draw power from RTS and/or DTR (preferably - both) if they are both asserted. */ - outb(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2, - uart->base + UART_MCR); - break; - } - - if (uart->irq < 0) { - byte = (0 & UART_IER_RDI) /* Disable Receiver data interrupt */ - |(0 & UART_IER_THRI) /* Disable Transmitter holding register empty interrupt */ - ; - } else if (uart->adaptor == SNDRV_SERIAL_MS124W_SA) { - byte = UART_IER_RDI /* Enable Receiver data interrupt */ - | UART_IER_MSI /* Enable Modem status interrupt */ - ; - } else if (uart->adaptor == SNDRV_SERIAL_GENERIC) { - byte = UART_IER_RDI /* Enable Receiver data interrupt */ - | UART_IER_MSI /* Enable Modem status interrupt */ - | UART_IER_THRI /* Enable Transmitter holding register empty interrupt */ - ; - } else { - byte = UART_IER_RDI /* Enable Receiver data interrupt */ - | UART_IER_THRI /* Enable Transmitter holding register empty interrupt */ - ; - } - outb(byte, uart->base + UART_IER); /* Interrupt enable Register */ - - inb(uart->base + UART_LSR); /* Clear any pre-existing overrun indication */ - inb(uart->base + UART_IIR); /* Clear any pre-existing transmit interrupt */ - inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */ -} - -static void snd_uart16550_do_close(struct snd_uart16550 * uart) -{ - if (uart->irq < 0) - snd_uart16550_del_timer(uart); - - /* NOTE: may need to disable interrupts before de-registering out handler. - * For now, the consequences are harmless. - */ - - outb((0 & UART_IER_RDI) /* Disable Receiver data interrupt */ - |(0 & UART_IER_THRI) /* Disable Transmitter holding register empty interrupt */ - ,uart->base + UART_IER); /* Interrupt enable Register */ - - switch (uart->adaptor) { - default: - outb((0 & UART_MCR_RTS) /* Deactivate Request-To-Send line */ - |(0 & UART_MCR_DTR) /* Deactivate Data-Terminal-Ready line */ - |(0 & UART_MCR_OUT2) /* Deactivate OUT2 */ - ,uart->base + UART_MCR); /* Modem Control Register */ - break; - case SNDRV_SERIAL_MS124W_SA: - case SNDRV_SERIAL_MS124W_MB: - /* MS-124W can draw power from RTS and DTR if they - are in opposite states; leave it powered. */ - outb(UART_MCR_RTS | (0&UART_MCR_DTR) | (0&UART_MCR_OUT2), - uart->base + UART_MCR); - break; - case SNDRV_SERIAL_MS124T: - /* MS-124T can draw power from RTS and/or DTR (preferably - both) if they are both asserted; leave it powered. */ - outb(UART_MCR_RTS | UART_MCR_DTR | (0&UART_MCR_OUT2), - uart->base + UART_MCR); - break; - } - - inb(uart->base + UART_IIR); /* Clear any outstanding interrupts */ - - /* Restore old divisor */ - if (uart->divisor != 0) { - outb(UART_LCR_DLAB /* Divisor latch access bit */ - ,uart->base + UART_LCR); /* Line Control Register */ - outb(uart->old_divisor_lsb - ,uart->base + UART_DLL); /* Divisor Latch Low */ - outb(uart->old_divisor_msb - ,uart->base + UART_DLM); /* Divisor Latch High */ - /* Restore old LCR (data bits, stop bits, parity, DLAB) */ - outb(uart->old_line_ctrl_reg - ,uart->base + UART_LCR); /* Line Control Register */ - } -} - -static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_open(uart); - uart->filemode |= SERIAL_MODE_INPUT_OPEN; - uart->midi_input[substream->number] = substream; - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -} - -static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - uart->filemode &= ~SERIAL_MODE_INPUT_OPEN; - uart->midi_input[substream->number] = NULL; - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_close(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -} - -static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (up) - uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED; - else - uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&uart->open_lock, flags); -} - -static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_open(uart); - uart->filemode |= SERIAL_MODE_OUTPUT_OPEN; - uart->midi_output[substream->number] = substream; - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -}; - -static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN; - uart->midi_output[substream->number] = NULL; - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_close(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -}; - -static inline int snd_uart16550_buffer_can_write(struct snd_uart16550 *uart, - int Num) -{ - if (uart->buff_in_count + Num < TX_BUFF_SIZE) - return 1; - else - return 0; -} - -static inline int snd_uart16550_write_buffer(struct snd_uart16550 *uart, - unsigned char byte) -{ - unsigned short buff_in = uart->buff_in; - if (uart->buff_in_count < TX_BUFF_SIZE) { - uart->tx_buff[buff_in] = byte; - buff_in++; - buff_in &= TX_BUFF_MASK; - uart->buff_in = buff_in; - uart->buff_in_count++; - if (uart->irq < 0) /* polling mode */ - snd_uart16550_add_timer(uart); - return 1; - } else - return 0; -} - -static int snd_uart16550_output_byte(struct snd_uart16550 *uart, - struct snd_rawmidi_substream *substream, - unsigned char midi_byte) -{ - if (uart->buff_in_count == 0 /* Buffer empty? */ - && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA && - uart->adaptor != SNDRV_SERIAL_GENERIC) || - (uart->fifo_count == 0 /* FIFO empty? */ - && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */ - - /* Tx Buffer Empty - try to write immediately */ - if ((inb(uart->base + UART_LSR) & UART_LSR_THRE) != 0) { - /* Transmitter holding register (and Tx FIFO) empty */ - uart->fifo_count = 1; - outb(midi_byte, uart->base + UART_TX); - } else { - if (uart->fifo_count < uart->fifo_limit) { - uart->fifo_count++; - outb(midi_byte, uart->base + UART_TX); - } else { - /* Cannot write (buffer empty) - - * put char in buffer */ - snd_uart16550_write_buffer(uart, midi_byte); - } - } - } else { - if (!snd_uart16550_write_buffer(uart, midi_byte)) { - snd_printk(KERN_WARNING - "%s: Buffer overrun on device at 0x%lx\n", - uart->rmidi->name, uart->base); - return 0; - } - } - - return 1; -} - -static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - unsigned char midi_byte, addr_byte; - struct snd_uart16550 *uart = substream->rmidi->private_data; - char first; - static unsigned long lasttime = 0; - - /* Interrupts are disabled during the updating of the tx_buff, - * since it is 'bad' to have two processes updating the same - * variables (ie buff_in & buff_out) - */ - - spin_lock_irqsave(&uart->open_lock, flags); - - if (uart->irq < 0) /* polling */ - snd_uart16550_io_loop(uart); - - if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) { - while (1) { - /* buffer full? */ - /* in this mode we need two bytes of space */ - if (uart->buff_in_count > TX_BUFF_SIZE - 2) - break; - if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1) - break; -#ifdef SNDRV_SERIAL_MS124W_MB_NOCOMBO - /* select exactly one of the four ports */ - addr_byte = (1 << (substream->number + 4)) | 0x08; -#else - /* select any combination of the four ports */ - addr_byte = (substream->number << 4) | 0x08; - /* ...except none */ - if (addr_byte == 0x08) - addr_byte = 0xf8; -#endif - snd_uart16550_output_byte(uart, substream, addr_byte); - /* send midi byte */ - snd_uart16550_output_byte(uart, substream, midi_byte); - } - } else { - first = 0; - while (snd_rawmidi_transmit_peek(substream, &midi_byte, 1) == 1) { - /* Also send F5 after 3 seconds with no data - * to handle device disconnect */ - if (first == 0 && - (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || - uart->adaptor == SNDRV_SERIAL_GENERIC) && - (uart->prev_out != substream->number || - time_after(jiffies, lasttime + 3*HZ))) { - - if (snd_uart16550_buffer_can_write(uart, 3)) { - /* Roland Soundcanvas part selection */ - /* If this substream of the data is - * different previous substream - * in this uart, send the change part - * event - */ - uart->prev_out = substream->number; - /* change part */ - snd_uart16550_output_byte(uart, substream, - 0xf5); - /* data */ - snd_uart16550_output_byte(uart, substream, - uart->prev_out + 1); - /* If midi_byte is a data byte, - * send the previous status byte */ - if (midi_byte < 0x80 && - uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS) - snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); - } else if (!uart->drop_on_full) - break; - - } - - /* send midi byte */ - if (!snd_uart16550_output_byte(uart, substream, midi_byte) && - !uart->drop_on_full ) - break; - - if (midi_byte >= 0x80 && midi_byte < 0xf0) - uart->prev_status[uart->prev_out] = midi_byte; - first = 1; - - snd_rawmidi_transmit_ack( substream, 1 ); - } - lasttime = jiffies; - } - spin_unlock_irqrestore(&uart->open_lock, flags); -} - -static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (up) - uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; - else - uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; - spin_unlock_irqrestore(&uart->open_lock, flags); - if (up) - snd_uart16550_output_write(substream); -} - -static struct snd_rawmidi_ops snd_uart16550_output = -{ - .open = snd_uart16550_output_open, - .close = snd_uart16550_output_close, - .trigger = snd_uart16550_output_trigger, -}; - -static struct snd_rawmidi_ops snd_uart16550_input = -{ - .open = snd_uart16550_input_open, - .close = snd_uart16550_input_close, - .trigger = snd_uart16550_input_trigger, -}; - -static int snd_uart16550_free(struct snd_uart16550 *uart) -{ - if (uart->irq >= 0) - free_irq(uart->irq, uart); - release_and_free_resource(uart->res_base); - kfree(uart); - return 0; -}; - -static int snd_uart16550_dev_free(struct snd_device *device) -{ - struct snd_uart16550 *uart = device->device_data; - return snd_uart16550_free(uart); -} - -static int __devinit snd_uart16550_create(struct snd_card *card, - unsigned long iobase, - int irq, - unsigned int speed, - unsigned int base, - int adaptor, - int droponfull, - struct snd_uart16550 **ruart) -{ - static struct snd_device_ops ops = { - .dev_free = snd_uart16550_dev_free, - }; - struct snd_uart16550 *uart; - int err; - - - if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL) - return -ENOMEM; - uart->adaptor = adaptor; - uart->card = card; - spin_lock_init(&uart->open_lock); - uart->irq = -1; - uart->base = iobase; - uart->drop_on_full = droponfull; - - if ((err = snd_uart16550_detect(uart)) <= 0) { - printk(KERN_ERR "no UART detected at 0x%lx\n", iobase); - snd_uart16550_free(uart); - return -ENODEV; - } - - if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { - if (request_irq(irq, snd_uart16550_interrupt, - 0, "Serial MIDI", uart)) { - snd_printk(KERN_WARNING - "irq %d busy. Using Polling.\n", irq); - } else { - uart->irq = irq; - } - } - uart->divisor = base / speed; - uart->speed = base / (unsigned int)uart->divisor; - uart->speed_base = base; - uart->prev_out = -1; - uart->prev_in = 0; - uart->rstatus = 0; - memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS); - init_timer(&uart->buffer_timer); - uart->buffer_timer.function = snd_uart16550_buffer_timer; - uart->buffer_timer.data = (unsigned long)uart; - uart->timer_running = 0; - - /* Register device */ - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops)) < 0) { - snd_uart16550_free(uart); - return err; - } - - switch (uart->adaptor) { - case SNDRV_SERIAL_MS124W_SA: - case SNDRV_SERIAL_MS124W_MB: - /* MS-124W can draw power from RTS and DTR if they - are in opposite states. */ - outb(UART_MCR_RTS | (0&UART_MCR_DTR), uart->base + UART_MCR); - break; - case SNDRV_SERIAL_MS124T: - /* MS-124T can draw power from RTS and/or DTR (preferably - both) if they are asserted. */ - outb(UART_MCR_RTS | UART_MCR_DTR, uart->base + UART_MCR); - break; - default: - break; - } - - if (ruart) - *ruart = uart; - - return 0; -} - -static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream) -{ - struct snd_rawmidi_substream *substream; - - list_for_each_entry(substream, &stream->substreams, list) { - sprintf(substream->name, "Serial MIDI %d", substream->number + 1); - } -} - -static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device, - int outs, int ins, - struct snd_rawmidi **rmidi) -{ - struct snd_rawmidi *rrawmidi; - int err; - - err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, - outs, ins, &rrawmidi); - if (err < 0) - return err; - snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_uart16550_input); - snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_uart16550_output); - strcpy(rrawmidi->name, "Serial MIDI"); - snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); - snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); - rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rrawmidi->private_data = uart; - if (rmidi) - *rmidi = rrawmidi; - return 0; -} - -static int __devinit snd_serial_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_uart16550 *uart; - int err; - int dev = devptr->id; - - switch (adaptor[dev]) { - case SNDRV_SERIAL_SOUNDCANVAS: - ins[dev] = 1; - break; - case SNDRV_SERIAL_MS124T: - case SNDRV_SERIAL_MS124W_SA: - outs[dev] = 1; - ins[dev] = 1; - break; - case SNDRV_SERIAL_MS124W_MB: - outs[dev] = 16; - ins[dev] = 1; - break; - case SNDRV_SERIAL_GENERIC: - break; - default: - snd_printk(KERN_ERR - "Adaptor type is out of range 0-%d (%d)\n", - SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]); - return -ENODEV; - } - - if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) { - snd_printk(KERN_ERR - "Count of outputs is out of range 1-%d (%d)\n", - SNDRV_SERIAL_MAX_OUTS, outs[dev]); - return -ENODEV; - } - - if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) { - snd_printk(KERN_ERR - "Count of inputs is out of range 1-%d (%d)\n", - SNDRV_SERIAL_MAX_INS, ins[dev]); - return -ENODEV; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - strcpy(card->driver, "Serial"); - strcpy(card->shortname, "Serial MIDI (UART16550A)"); - - if ((err = snd_uart16550_create(card, - port[dev], - irq[dev], - speed[dev], - base[dev], - adaptor[dev], - droponfull[dev], - &uart)) < 0) - goto _err; - - err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi); - if (err < 0) - goto _err; - - sprintf(card->longname, "%s [%s] at %#lx, irq %d", - card->shortname, - adaptor_names[uart->adaptor], - uart->base, - uart->irq); - - snd_card_set_dev(card, &devptr->dev); - - if ((err = snd_card_register(card)) < 0) - goto _err; - - platform_set_drvdata(devptr, card); - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devexit snd_serial_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_SERIAL_DRIVER "snd_serial_u16550" - -static struct platform_driver snd_serial_driver = { - .probe = snd_serial_probe, - .remove = __devexit_p( snd_serial_remove), - .driver = { - .name = SND_SERIAL_DRIVER - }, -}; - -static void snd_serial_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_serial_driver); -} - -static int __init alsa_card_serial_init(void) -{ - int i, cards, err; - - if ((err = platform_driver_register(&snd_serial_driver)) < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_SERIAL_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (! cards) { -#ifdef MODULE - printk(KERN_ERR "serial midi soundcard not found or device busy\n"); -#endif - snd_serial_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_serial_exit(void) -{ - snd_serial_unregister_all(); -} - -module_init(alsa_card_serial_init) -module_exit(alsa_card_serial_exit) diff --git a/ANDROID_3.4.5/sound/drivers/virmidi.c b/ANDROID_3.4.5/sound/drivers/virmidi.c deleted file mode 100644 index 9d97478a..00000000 --- a/ANDROID_3.4.5/sound/drivers/virmidi.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Dummy soundcard for virtual rawmidi devices - * - * Copyright (c) 2000 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * VIRTUAL RAW MIDI DEVICE CARDS - * - * This dummy card contains up to 4 virtual rawmidi devices. - * They are not real rawmidi devices but just associated with sequencer - * clients, so that any input/output sources can be connected as a raw - * MIDI device arbitrary. - * Also, multiple access is allowed to a single rawmidi device. - * - * Typical usage is like following: - * - Load snd-virmidi module. - * # modprobe snd-virmidi index=2 - * Then, sequencer clients 72:0 to 75:0 will be created, which are - * mapped from /dev/snd/midiC1D0 to /dev/snd/midiC1D3, respectively. - * - * - Connect input/output via aconnect. - * % aconnect 64:0 72:0 # keyboard input redirection 64:0 -> 72:0 - * % aconnect 72:0 65:0 # output device redirection 72:0 -> 65:0 - * - * - Run application using a midi device (eg. /dev/snd/midiC1D0) - */ - -#include <linux/init.h> -#include <linux/wait.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/seq_kernel.h> -#include <sound/seq_virmidi.h> -#include <sound/initval.h> - -/* hack: OSS defines midi_devs, so undefine it (versioned symbols) */ -#undef midi_devs - -MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); -MODULE_DESCRIPTION("Dummy soundcard for virtual rawmidi devices"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}"); - -#define MAX_MIDI_DEVICES 4 - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for virmidi soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for virmidi soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this soundcard."); -module_param_array(midi_devs, int, NULL, 0444); -MODULE_PARM_DESC(midi_devs, "MIDI devices # (1-4)"); - -struct snd_card_virmidi { - struct snd_card *card; - struct snd_rawmidi *midi[MAX_MIDI_DEVICES]; -}; - -static struct platform_device *devices[SNDRV_CARDS]; - - -static int __devinit snd_virmidi_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_card_virmidi *vmidi; - int idx, err; - int dev = devptr->id; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_virmidi), &card); - if (err < 0) - return err; - vmidi = card->private_data; - vmidi->card = card; - - if (midi_devs[dev] > MAX_MIDI_DEVICES) { - snd_printk(KERN_WARNING - "too much midi devices for virmidi %d: " - "force to use %d\n", dev, MAX_MIDI_DEVICES); - midi_devs[dev] = MAX_MIDI_DEVICES; - } - for (idx = 0; idx < midi_devs[dev]; idx++) { - struct snd_rawmidi *rmidi; - struct snd_virmidi_dev *rdev; - if ((err = snd_virmidi_new(card, idx, &rmidi)) < 0) - goto __nodev; - rdev = rmidi->private_data; - vmidi->midi[idx] = rmidi; - strcpy(rmidi->name, "Virtual Raw MIDI"); - rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; - } - - strcpy(card->driver, "VirMIDI"); - strcpy(card->shortname, "VirMIDI"); - sprintf(card->longname, "Virtual MIDI Card %i", dev + 1); - - snd_card_set_dev(card, &devptr->dev); - - if ((err = snd_card_register(card)) == 0) { - platform_set_drvdata(devptr, card); - return 0; - } - __nodev: - snd_card_free(card); - return err; -} - -static int __devexit snd_virmidi_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_VIRMIDI_DRIVER "snd_virmidi" - -static struct platform_driver snd_virmidi_driver = { - .probe = snd_virmidi_probe, - .remove = __devexit_p(snd_virmidi_remove), - .driver = { - .name = SND_VIRMIDI_DRIVER - }, -}; - -static void snd_virmidi_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_virmidi_driver); -} - -static int __init alsa_card_virmidi_init(void) -{ - int i, cards, err; - - if ((err = platform_driver_register(&snd_virmidi_driver)) < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_VIRMIDI_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n"); -#endif - snd_virmidi_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_virmidi_exit(void) -{ - snd_virmidi_unregister_all(); -} - -module_init(alsa_card_virmidi_init) -module_exit(alsa_card_virmidi_exit) diff --git a/ANDROID_3.4.5/sound/drivers/vx/Makefile b/ANDROID_3.4.5/sound/drivers/vx/Makefile deleted file mode 100644 index 9a168a3c..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o - -obj-$(CONFIG_SND_VX_LIB) += snd-vx-lib.o diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c b/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c deleted file mode 100644 index 23f4857f..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * DSP commands - * - * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/vx_core.h> -#include "vx_cmd.h" - -/* - * Array of DSP commands - */ -static struct vx_cmd_info vx_dsp_cmds[] = { -[CMD_VERSION] = { 0x010000, 2, RMH_SSIZE_FIXED, 1 }, -[CMD_SUPPORTED] = { 0x020000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_SEND_IRQA] = { 0x070001, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_IBL] = { 0x080000, 1, RMH_SSIZE_FIXED, 4 }, -[CMD_ASYNC] = { 0x0A0000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_RES_PIPE] = { 0x400000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_FREE_PIPE] = { 0x410000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_CONF_PIPE] = { 0x42A101, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_ABORT_CONF_PIPE] = { 0x42A100, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_PARAM_OUTPUT_PIPE] = { 0x43A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_STOP_PIPE] = { 0x470004, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_PIPE_STATE] = { 0x480000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_PIPE_SPL_COUNT] = { 0x49A000, 2, RMH_SSIZE_FIXED, 2 }, -[CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_SIZE_HBUFFER] = { 0x4C0000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_START_STREAM] = { 0x80A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_START_ONE_STREAM] = { 0x800000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_PAUSE_STREAM] = { 0x81A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_PAUSE_ONE_STREAM] = { 0x810000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x828000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_STOP_STREAM] = { 0x830000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_FORMAT_STREAM_OUT] = { 0x868000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_FORMAT_STREAM_IN] = { 0x878800, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_STREAM_STATE] = { 0x890001, 2, RMH_SSIZE_FIXED, 1 }, -[CMD_DROP_BYTES_AWAY] = { 0x8A8000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_REMAINING_BYTES] = { 0x8D0800, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_CONNECT_AUDIO] = { 0xC10000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_AUDIO_LEVEL_ADJUST] = { 0xC2A000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_AUDIO_VU_PIC_METER] = { 0xC3A003, 2, RMH_SSIZE_FIXED, 1 }, -[CMD_GET_AUDIO_LEVELS] = { 0xC4A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_NOTIFY_EVENT] = { 0x4D0000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_INFO_NOTIFIED] = { 0x0B0000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_ACCESS_IO_FCT] = { 0x098000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_STATUS_R_BUFFERS] = { 0x440000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_UPDATE_R_BUFFERS] = { 0x848000, 4, RMH_SSIZE_FIXED, 0 }, -[CMD_LOAD_EFFECT_CONTEXT] = { 0x0c8000, 3, RMH_SSIZE_FIXED, 1 }, -[CMD_EFFECT_ONE_PIPE] = { 0x458000, 0, RMH_SSIZE_FIXED, 0 }, -[CMD_MODIFY_CLOCK] = { 0x0d0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM1_OUT_SET_N_LEVELS] ={ 0x858000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_PURGE_STREAM_DCMDS] = { 0x8b8000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_NOTIFY_PIPE_TIME] = { 0x4e0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_LOAD_EFFECT_CONTEXT_PACKET] = { 0x0c8000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_RELIC_R_BUFFER] = { 0x8e0800, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_NOTIFY_STREAM_TIME] = { 0x8f0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM_SAMPLE_COUNT] = { 0x900000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_CONFIG_TIME_CODE] = { 0x050000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_TIME_CODE] = { 0x060000, 1, RMH_SSIZE_FIXED, 5 }, -[CMD_MANAGE_SIGNAL] = { 0x0f0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_PARAMETER_STREAM_OUT] = { 0x91A000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_READ_BOARD_FREQ] = { 0x030000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_GET_STREAM_LEVELS] = { 0x8c0000, 1, RMH_SSIZE_FIXED, 3 }, -[CMD_PURGE_PIPE_DCMDS] = { 0x4f8000, 3, RMH_SSIZE_FIXED, 0 }, -// [CMD_SET_STREAM_OUT_EFFECTS] = { 0x888000, 34, RMH_SSIZE_FIXED, 0 }, -// [CMD_GET_STREAM_OUT_EFFECTS] = { 0x928000, 2, RMH_SSIZE_FIXED, 32 }, -[CMD_CONNECT_MONITORING] = { 0xC00000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM2_OUT_SET_N_LEVELS] = { 0x938000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_CANCEL_R_BUFFERS] = { 0x948000, 4, RMH_SSIZE_FIXED, 0 }, -[CMD_NOTIFY_END_OF_BUFFER] = { 0x950000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_STREAM_VU_METER] = { 0x95A000, 2, RMH_SSIZE_ARG, 0 }, -}; - -/** - * vx_init_rmh - initialize the RMH instance - * @rmh: the rmh pointer to be initialized - * @cmd: the rmh command to be set - */ -void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd) -{ - if (snd_BUG_ON(cmd >= CMD_LAST_INDEX)) - return; - rmh->LgCmd = vx_dsp_cmds[cmd].length; - rmh->LgStat = vx_dsp_cmds[cmd].st_length; - rmh->DspStat = vx_dsp_cmds[cmd].st_type; - rmh->Cmd[0] = vx_dsp_cmds[cmd].opcode; -} - diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h b/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h deleted file mode 100644 index a85248ba..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * Definitions of DSP commands - * - * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __VX_CMD_H -#define __VX_CMD_H - -enum { - CMD_VERSION, - CMD_SUPPORTED, - CMD_TEST_IT, - CMD_SEND_IRQA, - CMD_IBL, - CMD_ASYNC, - CMD_RES_PIPE, - CMD_FREE_PIPE, - CMD_CONF_PIPE, - CMD_ABORT_CONF_PIPE, - CMD_PARAM_OUTPUT_PIPE, - CMD_STOP_PIPE, - CMD_PIPE_STATE, - CMD_PIPE_SPL_COUNT, - CMD_CAN_START_PIPE, - CMD_SIZE_HBUFFER, - CMD_START_STREAM, - CMD_START_ONE_STREAM, - CMD_PAUSE_STREAM, - CMD_PAUSE_ONE_STREAM, - CMD_STREAM_OUT_LEVEL_ADJUST, - CMD_STOP_STREAM, - CMD_FORMAT_STREAM_OUT, - CMD_FORMAT_STREAM_IN, - CMD_GET_STREAM_STATE, - CMD_DROP_BYTES_AWAY, - CMD_GET_REMAINING_BYTES, - CMD_CONNECT_AUDIO, - CMD_AUDIO_LEVEL_ADJUST, - CMD_AUDIO_VU_PIC_METER, - CMD_GET_AUDIO_LEVELS, - CMD_GET_NOTIFY_EVENT, - CMD_INFO_NOTIFIED, - CMD_ACCESS_IO_FCT, - CMD_STATUS_R_BUFFERS, - CMD_UPDATE_R_BUFFERS, - CMD_LOAD_EFFECT_CONTEXT, - CMD_EFFECT_ONE_PIPE, - CMD_MODIFY_CLOCK, - CMD_STREAM1_OUT_SET_N_LEVELS, - CMD_PURGE_STREAM_DCMDS, - CMD_NOTIFY_PIPE_TIME, - CMD_LOAD_EFFECT_CONTEXT_PACKET, - CMD_RELIC_R_BUFFER, - CMD_RESYNC_AUDIO_INPUTS, - CMD_NOTIFY_STREAM_TIME, - CMD_STREAM_SAMPLE_COUNT, - CMD_CONFIG_TIME_CODE, - CMD_GET_TIME_CODE, - CMD_MANAGE_SIGNAL, - CMD_PARAMETER_STREAM_OUT, - CMD_READ_BOARD_FREQ, - CMD_GET_STREAM_LEVELS, - CMD_PURGE_PIPE_DCMDS, - // CMD_SET_STREAM_OUT_EFFECTS, - // CMD_GET_STREAM_OUT_EFFECTS, - CMD_CONNECT_MONITORING, - CMD_STREAM2_OUT_SET_N_LEVELS, - CMD_CANCEL_R_BUFFERS, - CMD_NOTIFY_END_OF_BUFFER, - CMD_GET_STREAM_VU_METER, - CMD_LAST_INDEX -}; - -struct vx_cmd_info { - unsigned int opcode; /* command word */ - int length; /* command length (in words) */ - int st_type; /* status type (RMH_SSIZE_XXX) */ - int st_length; /* fixed length */ -}; - -/* Family and code op of some DSP requests. */ -#define CODE_OP_PIPE_TIME 0x004e0000 -#define CODE_OP_START_STREAM 0x00800000 -#define CODE_OP_PAUSE_STREAM 0x00810000 -#define CODE_OP_OUT_STREAM_LEVEL 0x00820000 -#define CODE_OP_UPDATE_R_BUFFERS 0x00840000 -#define CODE_OP_OUT_STREAM1_LEVEL_CURVE 0x00850000 -#define CODE_OP_OUT_STREAM2_LEVEL_CURVE 0x00930000 -#define CODE_OP_OUT_STREAM_FORMAT 0x00860000 -#define CODE_OP_STREAM_TIME 0x008f0000 -#define CODE_OP_OUT_STREAM_EXTRAPARAMETER 0x00910000 -#define CODE_OP_OUT_AUDIO_LEVEL 0x00c20000 - -#define NOTIFY_LAST_COMMAND 0x00400000 - -/* Values for a user delay */ -#define DC_DIFFERED_DELAY (1<<BIT_DIFFERED_COMMAND) -#define DC_NOTIFY_DELAY (1<<BIT_NOTIFIED_COMMAND) -#define DC_HBUFFER_DELAY (1<<BIT_TIME_RELATIVE_TO_BUFFER) -#define DC_MULTIPLE_DELAY (1<<BIT_RESERVED) -#define DC_STREAM_TIME_DELAY (1<<BIT_STREAM_TIME) -#define DC_CANCELLED_DELAY (1<<BIT_CANCELLED_COMMAND) - -/* Values for tiDelayed field in TIME_INFO structure, - * and for pbPause field in PLAY_BUFFER_INFO structure - */ -#define BIT_DIFFERED_COMMAND 0 -#define BIT_NOTIFIED_COMMAND 1 -#define BIT_TIME_RELATIVE_TO_BUFFER 2 -#define BIT_RESERVED 3 -#define BIT_STREAM_TIME 4 -#define BIT_CANCELLED_COMMAND 5 - -/* Access to the "Size" field of the response of the CMD_GET_NOTIFY_EVENT request. */ -#define GET_NOTIFY_EVENT_SIZE_FIELD_MASK 0x000000ff - -/* DSP commands general masks */ -#define OPCODE_MASK 0x00ff0000 -#define DSP_DIFFERED_COMMAND_MASK 0x0000C000 - -/* Notifications (NOTIFY_INFO) */ -#define ALL_CMDS_NOTIFIED 0x0000 // reserved -#define START_STREAM_NOTIFIED 0x0001 -#define PAUSE_STREAM_NOTIFIED 0x0002 -#define OUT_STREAM_LEVEL_NOTIFIED 0x0003 -#define OUT_STREAM_PARAMETER_NOTIFIED 0x0004 // left for backward compatibility -#define OUT_STREAM_FORMAT_NOTIFIED 0x0004 -#define PIPE_TIME_NOTIFIED 0x0005 -#define OUT_AUDIO_LEVEL_NOTIFIED 0x0006 -#define OUT_STREAM_LEVEL_CURVE_NOTIFIED 0x0007 -#define STREAM_TIME_NOTIFIED 0x0008 -#define OUT_STREAM_EXTRAPARAMETER_NOTIFIED 0x0009 -#define UNKNOWN_COMMAND_NOTIFIED 0xffff - -/* Output pipe parameters setting */ -#define MASK_VALID_PIPE_MPEG_PARAM 0x000040 -#define MASK_VALID_PIPE_BACKWARD_PARAM 0x000020 -#define MASK_SET_PIPE_MPEG_PARAM 0x000002 -#define MASK_SET_PIPE_BACKWARD_PARAM 0x000001 - -#define MASK_DSP_WORD 0x00FFFFFF -#define MASK_ALL_STREAM 0x00FFFFFF -#define MASK_DSP_WORD_LEVEL 0x000001FF -#define MASK_FIRST_FIELD 0x0000001F -#define FIELD_SIZE 5 - -#define COMMAND_RECORD_MASK 0x000800 - -/* PipeManagement definition bits (PIPE_DECL_INFO) */ -#define P_UNDERRUN_SKIP_SOUND_MASK 0x01 -#define P_PREPARE_FOR_MPEG3_MASK 0x02 -#define P_DO_NOT_RESET_ANALOG_LEVELS 0x04 -#define P_ALLOW_UNDER_ALLOCATION_MASK 0x08 -#define P_DATA_MODE_MASK 0x10 -#define P_ASIO_BUFFER_MANAGEMENT_MASK 0x20 - -#define BIT_SKIP_SOUND 0x08 // bit 3 -#define BIT_DATA_MODE 0x10 // bit 4 - -/* Bits in the CMD_MODIFY_CLOCK request. */ -#define CMD_MODIFY_CLOCK_FD_BIT 0x00000001 -#define CMD_MODIFY_CLOCK_T_BIT 0x00000002 -#define CMD_MODIFY_CLOCK_S_BIT 0x00000004 - -/* Access to the results of the CMD_GET_TIME_CODE RMH. */ -#define TIME_CODE_V_MASK 0x00800000 -#define TIME_CODE_N_MASK 0x00400000 -#define TIME_CODE_B_MASK 0x00200000 -#define TIME_CODE_W_MASK 0x00100000 - -/* Values for the CMD_MANAGE_SIGNAL RMH. */ -#define MANAGE_SIGNAL_TIME_CODE 0x01 -#define MANAGE_SIGNAL_MIDI 0x02 - -/* Values for the CMD_CONFIG_TIME_CODE RMH. */ -#define CONFIG_TIME_CODE_CANCEL 0x00001000 - -/* Mask to get only the effective time from the - * high word out of the 2 returned by the DSP - */ -#define PCX_TIME_HI_MASK 0x000fffff - -/* Values for setting a H-Buffer time */ -#define HBUFFER_TIME_HIGH 0x00200000 -#define HBUFFER_TIME_LOW 0x00000000 - -#define NOTIFY_MASK_TIME_HIGH 0x00400000 -#define MULTIPLE_MASK_TIME_HIGH 0x00100000 -#define STREAM_MASK_TIME_HIGH 0x00800000 - - -/* - * - */ -void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd); - -/** - * vx_send_pipe_cmd_params - fill first command word for pipe commands - * @rmh: the rmh to be modified - * @is_capture: 0 = playback, 1 = capture operation - * @param1: first pipe-parameter - * @param2: second pipe-parameter - */ -static inline void vx_set_pipe_cmd_params(struct vx_rmh *rmh, int is_capture, - int param1, int param2) -{ - if (is_capture) - rmh->Cmd[0] |= COMMAND_RECORD_MASK; - rmh->Cmd[0] |= (((u32)param1 & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD; - - if (param2) - rmh->Cmd[0] |= ((u32)param2 & MASK_FIRST_FIELD) & MASK_DSP_WORD; - -} - -/** - * vx_set_stream_cmd_params - fill first command word for stream commands - * @rmh: the rmh to be modified - * @is_capture: 0 = playback, 1 = capture operation - * @pipe: the pipe index (zero-based) - */ -static inline void vx_set_stream_cmd_params(struct vx_rmh *rmh, int is_capture, int pipe) -{ - if (is_capture) - rmh->Cmd[0] |= COMMAND_RECORD_MASK; - rmh->Cmd[0] |= (((u32)pipe & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD; -} - -#endif /* __VX_CMD_H */ diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_core.c b/ANDROID_3.4.5/sound/drivers/vx/vx_core.c deleted file mode 100644 index b8e51599..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_core.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * Hardware core part - * - * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/firmware.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/asoundef.h> -#include <sound/info.h> -#include <asm/io.h> -#include <sound/vx_core.h> -#include "vx_cmd.h" - -MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); -MODULE_DESCRIPTION("Common routines for Digigram VX drivers"); -MODULE_LICENSE("GPL"); - - -/* - * vx_check_reg_bit - wait for the specified bit is set/reset on a register - * @reg: register to check - * @mask: bit mask - * @bit: resultant bit to be checked - * @time: time-out of loop in msec - * - * returns zero if a bit matches, or a negative error code. - */ -int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int time) -{ - unsigned long end_time = jiffies + (time * HZ + 999) / 1000; -#ifdef CONFIG_SND_DEBUG - static char *reg_names[VX_REG_MAX] = { - "ICR", "CVR", "ISR", "IVR", "RXH", "RXM", "RXL", - "DMA", "CDSP", "RFREQ", "RUER/V2", "DATA", "MEMIRQ", - "ACQ", "BIT0", "BIT1", "MIC0", "MIC1", "MIC2", - "MIC3", "INTCSR", "CNTRL", "GPIOC", - "LOFREQ", "HIFREQ", "CSUER", "RUER" - }; -#endif - do { - if ((snd_vx_inb(chip, reg) & mask) == bit) - return 0; - //msleep(10); - } while (time_after_eq(end_time, jiffies)); - snd_printd(KERN_DEBUG "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n", reg_names[reg], mask, snd_vx_inb(chip, reg)); - return -EIO; -} - -EXPORT_SYMBOL(snd_vx_check_reg_bit); - -/* - * vx_send_irq_dsp - set command irq bit - * @num: the requested IRQ type, IRQ_XXX - * - * this triggers the specified IRQ request - * returns 0 if successful, or a negative error code. - * - */ -static int vx_send_irq_dsp(struct vx_core *chip, int num) -{ - int nirq; - - /* wait for Hc = 0 */ - if (snd_vx_check_reg_bit(chip, VX_CVR, CVR_HC, 0, 200) < 0) - return -EIO; - - nirq = num; - if (vx_has_new_dsp(chip)) - nirq += VXP_IRQ_OFFSET; - vx_outb(chip, CVR, (nirq >> 1) | CVR_HC); - return 0; -} - - -/* - * vx_reset_chk - reset CHK bit on ISR - * - * returns 0 if successful, or a negative error code. - */ -static int vx_reset_chk(struct vx_core *chip) -{ - /* Reset irq CHK */ - if (vx_send_irq_dsp(chip, IRQ_RESET_CHK) < 0) - return -EIO; - /* Wait until CHK = 0 */ - if (vx_check_isr(chip, ISR_CHK, 0, 200) < 0) - return -EIO; - return 0; -} - -/* - * vx_transfer_end - terminate message transfer - * @cmd: IRQ message to send (IRQ_MESS_XXX_END) - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * NB: call with spinlock held! - */ -static int vx_transfer_end(struct vx_core *chip, int cmd) -{ - int err; - - if ((err = vx_reset_chk(chip)) < 0) - return err; - - /* irq MESS_READ/WRITE_END */ - if ((err = vx_send_irq_dsp(chip, cmd)) < 0) - return err; - - /* Wait CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - - /* If error, Read RX */ - if ((err = vx_inb(chip, ISR)) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) { - snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n"); - return err; - } - err = vx_inb(chip, RXH) << 16; - err |= vx_inb(chip, RXM) << 8; - err |= vx_inb(chip, RXL); - snd_printd(KERN_DEBUG "transfer_end: error = 0x%x\n", err); - return -(VX_ERR_MASK | err); - } - return 0; -} - -/* - * vx_read_status - return the status rmh - * @rmh: rmh record to store the status - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * NB: call with spinlock held! - */ -static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh) -{ - int i, err, val, size; - - /* no read necessary? */ - if (rmh->DspStat == RMH_SSIZE_FIXED && rmh->LgStat == 0) - return 0; - - /* Wait for RX full (with timeout protection) - * The first word of status is in RX - */ - err = vx_wait_for_rx_full(chip); - if (err < 0) - return err; - - /* Read RX */ - val = vx_inb(chip, RXH) << 16; - val |= vx_inb(chip, RXM) << 8; - val |= vx_inb(chip, RXL); - - /* If status given by DSP, let's decode its size */ - switch (rmh->DspStat) { - case RMH_SSIZE_ARG: - size = val & 0xff; - rmh->Stat[0] = val & 0xffff00; - rmh->LgStat = size + 1; - break; - case RMH_SSIZE_MASK: - /* Let's count the arg numbers from a mask */ - rmh->Stat[0] = val; - size = 0; - while (val) { - if (val & 0x01) - size++; - val >>= 1; - } - rmh->LgStat = size + 1; - break; - default: - /* else retrieve the status length given by the driver */ - size = rmh->LgStat; - rmh->Stat[0] = val; /* Val is the status 1st word */ - size--; /* hence adjust remaining length */ - break; - } - - if (size < 1) - return 0; - if (snd_BUG_ON(size > SIZE_MAX_STATUS)) - return -EINVAL; - - for (i = 1; i <= size; i++) { - /* trigger an irq MESS_WRITE_NEXT */ - err = vx_send_irq_dsp(chip, IRQ_MESS_WRITE_NEXT); - if (err < 0) - return err; - /* Wait for RX full (with timeout protection) */ - err = vx_wait_for_rx_full(chip); - if (err < 0) - return err; - rmh->Stat[i] = vx_inb(chip, RXH) << 16; - rmh->Stat[i] |= vx_inb(chip, RXM) << 8; - rmh->Stat[i] |= vx_inb(chip, RXL); - } - - return vx_transfer_end(chip, IRQ_MESS_WRITE_END); -} - - -#define MASK_MORE_THAN_1_WORD_COMMAND 0x00008000 -#define MASK_1_WORD_COMMAND 0x00ff7fff - -/* - * vx_send_msg_nolock - send a DSP message and read back the status - * @rmh: the rmh record to send and receive - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * - * this function doesn't call spinlock at all. - */ -int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) -{ - int i, err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - if ((err = vx_reset_chk(chip)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n"); - return err; - } - -#if 0 - printk(KERN_DEBUG "rmh: cmd = 0x%06x, length = %d, stype = %d\n", - rmh->Cmd[0], rmh->LgCmd, rmh->DspStat); - if (rmh->LgCmd > 1) { - printk(KERN_DEBUG " "); - for (i = 1; i < rmh->LgCmd; i++) - printk("0x%06x ", rmh->Cmd[i]); - printk("\n"); - } -#endif - /* Check bit M is set according to length of the command */ - if (rmh->LgCmd > 1) - rmh->Cmd[0] |= MASK_MORE_THAN_1_WORD_COMMAND; - else - rmh->Cmd[0] &= MASK_1_WORD_COMMAND; - - /* Wait for TX empty */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n"); - return err; - } - - /* Write Cmd[0] */ - vx_outb(chip, TXH, (rmh->Cmd[0] >> 16) & 0xff); - vx_outb(chip, TXM, (rmh->Cmd[0] >> 8) & 0xff); - vx_outb(chip, TXL, rmh->Cmd[0] & 0xff); - - /* Trigger irq MESSAGE */ - if ((err = vx_send_irq_dsp(chip, IRQ_MESSAGE)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n"); - return err; - } - - /* Wait for CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - - /* If error, get error value from RX */ - if (vx_inb(chip, ISR) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n"); - return err; - } - err = vx_inb(chip, RXH) << 16; - err |= vx_inb(chip, RXM) << 8; - err |= vx_inb(chip, RXL); - snd_printd(KERN_DEBUG "msg got error = 0x%x at cmd[0]\n", err); - err = -(VX_ERR_MASK | err); - return err; - } - - /* Send the other words */ - if (rmh->LgCmd > 1) { - for (i = 1; i < rmh->LgCmd; i++) { - /* Wait for TX ready */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n"); - return err; - } - - /* Write Cmd[i] */ - vx_outb(chip, TXH, (rmh->Cmd[i] >> 16) & 0xff); - vx_outb(chip, TXM, (rmh->Cmd[i] >> 8) & 0xff); - vx_outb(chip, TXL, rmh->Cmd[i] & 0xff); - - /* Trigger irq MESS_READ_NEXT */ - if ((err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n"); - return err; - } - } - /* Wait for TX empty */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n"); - return err; - } - /* End of transfer */ - err = vx_transfer_end(chip, IRQ_MESS_READ_END); - if (err < 0) - return err; - } - - return vx_read_status(chip, rmh); -} - - -/* - * vx_send_msg - send a DSP message with spinlock - * @rmh: the rmh record to send and receive - * - * returns 0 if successful, or a negative error code. - * see vx_send_msg_nolock(). - */ -int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&chip->lock, flags); - err = vx_send_msg_nolock(chip, rmh); - spin_unlock_irqrestore(&chip->lock, flags); - return err; -} - - -/* - * vx_send_rih_nolock - send an RIH to xilinx - * @cmd: the command to send - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * - * this function doesn't call spinlock at all. - * - * unlike RMH, no command is sent to DSP. - */ -int vx_send_rih_nolock(struct vx_core *chip, int cmd) -{ - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - -#if 0 - printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd); -#endif - if ((err = vx_reset_chk(chip)) < 0) - return err; - /* send the IRQ */ - if ((err = vx_send_irq_dsp(chip, cmd)) < 0) - return err; - /* Wait CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - /* If error, read RX */ - if (vx_inb(chip, ISR) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) - return err; - err = vx_inb(chip, RXH) << 16; - err |= vx_inb(chip, RXM) << 8; - err |= vx_inb(chip, RXL); - return -(VX_ERR_MASK | err); - } - return 0; -} - - -/* - * vx_send_rih - send an RIH with spinlock - * @cmd: the command to send - * - * see vx_send_rih_nolock(). - */ -int vx_send_rih(struct vx_core *chip, int cmd) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&chip->lock, flags); - err = vx_send_rih_nolock(chip, cmd); - spin_unlock_irqrestore(&chip->lock, flags); - return err; -} - -#define END_OF_RESET_WAIT_TIME 500 /* us */ - -/** - * snd_vx_boot_xilinx - boot up the xilinx interface - * @boot: the boot record to load - */ -int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot) -{ - unsigned int i; - int no_fillup = vx_has_new_dsp(chip); - - /* check the length of boot image */ - if (boot->size <= 0) - return -EINVAL; - if (boot->size % 3) - return -EINVAL; -#if 0 - { - /* more strict check */ - unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2]; - if (boot->size != (c + 2) * 3) - return -EINVAL; - } -#endif - - /* reset dsp */ - vx_reset_dsp(chip); - - udelay(END_OF_RESET_WAIT_TIME); /* another wait? */ - - /* download boot strap */ - for (i = 0; i < 0x600; i += 3) { - if (i >= boot->size) { - if (no_fillup) - break; - if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { - snd_printk(KERN_ERR "dsp boot failed at %d\n", i); - return -EIO; - } - vx_outb(chip, TXH, 0); - vx_outb(chip, TXM, 0); - vx_outb(chip, TXL, 0); - } else { - const unsigned char *image = boot->data + i; - if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { - snd_printk(KERN_ERR "dsp boot failed at %d\n", i); - return -EIO; - } - vx_outb(chip, TXH, image[0]); - vx_outb(chip, TXM, image[1]); - vx_outb(chip, TXL, image[2]); - } - } - return 0; -} - -EXPORT_SYMBOL(snd_vx_load_boot_image); - -/* - * vx_test_irq_src - query the source of interrupts - * - * called from irq handler only - */ -static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret) -{ - int err; - - vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT); - spin_lock(&chip->lock); - err = vx_send_msg_nolock(chip, &chip->irq_rmh); - if (err < 0) - *ret = 0; - else - *ret = chip->irq_rmh.Stat[0]; - spin_unlock(&chip->lock); - return err; -} - - -/* - * vx_interrupt - soft irq handler - */ -static void vx_interrupt(unsigned long private_data) -{ - struct vx_core *chip = (struct vx_core *) private_data; - unsigned int events; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - if (vx_test_irq_src(chip, &events) < 0) - return; - -#if 0 - if (events & 0x000800) - printk(KERN_ERR "DSP Stream underrun ! IRQ events = 0x%x\n", events); -#endif - // printk(KERN_DEBUG "IRQ events = 0x%x\n", events); - - /* We must prevent any application using this DSP - * and block any further request until the application - * either unregisters or reloads the DSP - */ - if (events & FATAL_DSP_ERROR) { - snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n"); - return; - } - - /* The start on time code conditions are filled (ie the time code - * received by the board is equal to one of those given to it). - */ - if (events & TIME_CODE_EVENT_PENDING) - ; /* so far, nothing to do yet */ - - /* The frequency has changed on the board (UER mode). */ - if (events & FREQUENCY_CHANGE_EVENT_PENDING) - vx_change_frequency(chip); - - /* update the pcm streams */ - vx_pcm_update_intr(chip, events); -} - - -/** - * snd_vx_irq_handler - interrupt handler - */ -irqreturn_t snd_vx_irq_handler(int irq, void *dev) -{ - struct vx_core *chip = dev; - - if (! (chip->chip_status & VX_STAT_CHIP_INIT) || - (chip->chip_status & VX_STAT_IS_STALE)) - return IRQ_NONE; - if (! vx_test_and_ack(chip)) - tasklet_schedule(&chip->tq); - return IRQ_HANDLED; -} - -EXPORT_SYMBOL(snd_vx_irq_handler); - -/* - */ -static void vx_reset_board(struct vx_core *chip, int cold_reset) -{ - if (snd_BUG_ON(!chip->ops->reset_board)) - return; - - /* current source, later sync'ed with target */ - chip->audio_source = VX_AUDIO_SRC_LINE; - if (cold_reset) { - chip->audio_source_target = chip->audio_source; - chip->clock_source = INTERNAL_QUARTZ; - chip->clock_mode = VX_CLOCK_MODE_AUTO; - chip->freq = 48000; - chip->uer_detected = VX_UER_MODE_NOT_PRESENT; - chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF; - } - - chip->ops->reset_board(chip, cold_reset); - - vx_reset_codec(chip, cold_reset); - - vx_set_internal_clock(chip, chip->freq); - - /* Reset the DSP */ - vx_reset_dsp(chip); - - if (vx_is_pcmcia(chip)) { - /* Acknowledge any pending IRQ and reset the MEMIRQ flag. */ - vx_test_and_ack(chip); - vx_validate_irq(chip, 1); - } - - /* init CBits */ - vx_set_iec958_status(chip, chip->uer_bits); -} - - -/* - * proc interface - */ - -static void vx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct vx_core *chip = entry->private_data; - static char *audio_src_vxp[] = { "Line", "Mic", "Digital" }; - static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" }; - static char *clock_mode[] = { "Auto", "Internal", "External" }; - static char *clock_src[] = { "Internal", "External" }; - static char *uer_type[] = { "Consumer", "Professional", "Not Present" }; - - snd_iprintf(buffer, "%s\n", chip->card->longname); - snd_iprintf(buffer, "Xilinx Firmware: %s\n", - chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No"); - snd_iprintf(buffer, "Device Initialized: %s\n", - chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No"); - snd_iprintf(buffer, "DSP audio info:"); - if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME) - snd_iprintf(buffer, " realtime"); - if (chip->audio_info & VX_AUDIO_INFO_OFFLINE) - snd_iprintf(buffer, " offline"); - if (chip->audio_info & VX_AUDIO_INFO_MPEG1) - snd_iprintf(buffer, " mpeg1"); - if (chip->audio_info & VX_AUDIO_INFO_MPEG2) - snd_iprintf(buffer, " mpeg2"); - if (chip->audio_info & VX_AUDIO_INFO_LINEAR_8) - snd_iprintf(buffer, " linear8"); - if (chip->audio_info & VX_AUDIO_INFO_LINEAR_16) - snd_iprintf(buffer, " linear16"); - if (chip->audio_info & VX_AUDIO_INFO_LINEAR_24) - snd_iprintf(buffer, " linear24"); - snd_iprintf(buffer, "\n"); - snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ? - audio_src_vxp[chip->audio_source] : - audio_src_vx2[chip->audio_source]); - snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]); - snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]); - snd_iprintf(buffer, "Frequency: %d\n", chip->freq); - snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected); - snd_iprintf(buffer, "Detected UER type: %s\n", uer_type[chip->uer_detected]); - snd_iprintf(buffer, "Min/Max/Cur IBL: %d/%d/%d (granularity=%d)\n", - chip->ibl.min_size, chip->ibl.max_size, chip->ibl.size, - chip->ibl.granularity); -} - -static void vx_proc_init(struct vx_core *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "vx-status", &entry)) - snd_info_set_text_ops(entry, chip, vx_proc_read); -} - - -/** - * snd_vx_dsp_boot - load the DSP boot - */ -int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot) -{ - int err; - int cold_reset = !(chip->chip_status & VX_STAT_DEVICE_INIT); - - vx_reset_board(chip, cold_reset); - vx_validate_irq(chip, 0); - - if ((err = snd_vx_load_boot_image(chip, boot)) < 0) - return err; - msleep(10); - - return 0; -} - -EXPORT_SYMBOL(snd_vx_dsp_boot); - -/** - * snd_vx_dsp_load - load the DSP image - */ -int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) -{ - unsigned int i; - int err; - unsigned int csum = 0; - const unsigned char *image, *cptr; - - if (dsp->size % 3) - return -EINVAL; - - vx_toggle_dac_mute(chip, 1); - - /* Transfert data buffer from PC to DSP */ - for (i = 0; i < dsp->size; i += 3) { - image = dsp->data + i; - /* Wait DSP ready for a new read */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { - printk(KERN_ERR - "dsp loading error at position %d\n", i); - return err; - } - cptr = image; - csum ^= *cptr; - csum = (csum >> 24) | (csum << 8); - vx_outb(chip, TXH, *cptr++); - csum ^= *cptr; - csum = (csum >> 24) | (csum << 8); - vx_outb(chip, TXM, *cptr++); - csum ^= *cptr; - csum = (csum >> 24) | (csum << 8); - vx_outb(chip, TXL, *cptr++); - } - snd_printdd(KERN_DEBUG "checksum = 0x%08x\n", csum); - - msleep(200); - - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - - vx_toggle_dac_mute(chip, 0); - - vx_test_and_ack(chip); - vx_validate_irq(chip, 1); - - return 0; -} - -EXPORT_SYMBOL(snd_vx_dsp_load); - -#ifdef CONFIG_PM -/* - * suspend - */ -int snd_vx_suspend(struct vx_core *chip, pm_message_t state) -{ - unsigned int i; - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - chip->chip_status |= VX_STAT_IN_SUSPEND; - for (i = 0; i < chip->hw->num_codecs; i++) - snd_pcm_suspend_all(chip->pcm[i]); - - return 0; -} - -EXPORT_SYMBOL(snd_vx_suspend); - -/* - * resume - */ -int snd_vx_resume(struct vx_core *chip) -{ - int i, err; - - chip->chip_status &= ~VX_STAT_CHIP_INIT; - - for (i = 0; i < 4; i++) { - if (! chip->firmware[i]) - continue; - err = chip->ops->load_dsp(chip, i, chip->firmware[i]); - if (err < 0) { - snd_printk(KERN_ERR "vx: firmware resume error at DSP %d\n", i); - return -EIO; - } - } - - chip->chip_status |= VX_STAT_CHIP_INIT; - chip->chip_status &= ~VX_STAT_IN_SUSPEND; - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); - return 0; -} - -EXPORT_SYMBOL(snd_vx_resume); -#endif - -/** - * snd_vx_create - constructor for struct vx_core - * @hw: hardware specific record - * - * this function allocates the instance and prepare for the hardware - * initialization. - * - * return the instance pointer if successful, NULL in error. - */ -struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, - struct snd_vx_ops *ops, - int extra_size) -{ - struct vx_core *chip; - - if (snd_BUG_ON(!card || !hw || !ops)) - return NULL; - - chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL); - if (! chip) { - snd_printk(KERN_ERR "vx_core: no memory\n"); - return NULL; - } - spin_lock_init(&chip->lock); - spin_lock_init(&chip->irq_lock); - chip->irq = -1; - chip->hw = hw; - chip->type = hw->type; - chip->ops = ops; - tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip); - mutex_init(&chip->mixer_mutex); - - chip->card = card; - card->private_data = chip; - strcpy(card->driver, hw->name); - sprintf(card->shortname, "Digigram %s", hw->name); - - vx_proc_init(chip); - - return chip; -} - -EXPORT_SYMBOL(snd_vx_create); - -/* - * module entries - */ -static int __init alsa_vx_core_init(void) -{ - return 0; -} - -static void __exit alsa_vx_core_exit(void) -{ -} - -module_init(alsa_vx_core_init) -module_exit(alsa_vx_core_exit) diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c b/ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c deleted file mode 100644 index 4a1fae99..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * DSP firmware management - * - * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/device.h> -#include <linux/firmware.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/hwdep.h> -#include <sound/vx_core.h> - -#ifdef SND_VX_FW_LOADER - -MODULE_FIRMWARE("vx/bx_1_vxp.b56"); -MODULE_FIRMWARE("vx/bx_1_vp4.b56"); -MODULE_FIRMWARE("vx/x1_1_vx2.xlx"); -MODULE_FIRMWARE("vx/x1_2_v22.xlx"); -MODULE_FIRMWARE("vx/x1_1_vxp.xlx"); -MODULE_FIRMWARE("vx/x1_1_vp4.xlx"); -MODULE_FIRMWARE("vx/bd56002.boot"); -MODULE_FIRMWARE("vx/bd563v2.boot"); -MODULE_FIRMWARE("vx/bd563s3.boot"); -MODULE_FIRMWARE("vx/l_1_vx2.d56"); -MODULE_FIRMWARE("vx/l_1_v22.d56"); -MODULE_FIRMWARE("vx/l_1_vxp.d56"); -MODULE_FIRMWARE("vx/l_1_vp4.d56"); - -int snd_vx_setup_firmware(struct vx_core *chip) -{ - static char *fw_files[VX_TYPE_NUMS][4] = { - [VX_TYPE_BOARD] = { - NULL, "x1_1_vx2.xlx", "bd56002.boot", "l_1_vx2.d56", - }, - [VX_TYPE_V2] = { - NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56", - }, - [VX_TYPE_MIC] = { - NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56", - }, - [VX_TYPE_VXPOCKET] = { - "bx_1_vxp.b56", "x1_1_vxp.xlx", "bd563s3.boot", "l_1_vxp.d56" - }, - [VX_TYPE_VXP440] = { - "bx_1_vp4.b56", "x1_1_vp4.xlx", "bd563s3.boot", "l_1_vp4.d56" - }, - }; - - int i, err; - - for (i = 0; i < 4; i++) { - char path[32]; - const struct firmware *fw; - if (! fw_files[chip->type][i]) - continue; - sprintf(path, "vx/%s", fw_files[chip->type][i]); - if (request_firmware(&fw, path, chip->dev)) { - snd_printk(KERN_ERR "vx: can't load firmware %s\n", path); - return -ENOENT; - } - err = chip->ops->load_dsp(chip, i, fw); - if (err < 0) { - release_firmware(fw); - return err; - } - if (i == 1) - chip->chip_status |= VX_STAT_XILINX_LOADED; -#ifdef CONFIG_PM - chip->firmware[i] = fw; -#else - release_firmware(fw); -#endif - } - - /* ok, we reached to the last one */ - /* create the devices if not built yet */ - if ((err = snd_vx_pcm_new(chip)) < 0) - return err; - - if ((err = snd_vx_mixer_new(chip)) < 0) - return err; - - if (chip->ops->add_controls) - if ((err = chip->ops->add_controls(chip)) < 0) - return err; - - chip->chip_status |= VX_STAT_DEVICE_INIT; - chip->chip_status |= VX_STAT_CHIP_INIT; - - return snd_card_register(chip->card); -} - -/* exported */ -void snd_vx_free_firmware(struct vx_core *chip) -{ -#ifdef CONFIG_PM - int i; - for (i = 0; i < 4; i++) - release_firmware(chip->firmware[i]); -#endif -} - -#else /* old style firmware loading */ - -static int vx_hwdep_dsp_status(struct snd_hwdep *hw, - struct snd_hwdep_dsp_status *info) -{ - static char *type_ids[VX_TYPE_NUMS] = { - [VX_TYPE_BOARD] = "vxboard", - [VX_TYPE_V2] = "vx222", - [VX_TYPE_MIC] = "vx222", - [VX_TYPE_VXPOCKET] = "vxpocket", - [VX_TYPE_VXP440] = "vxp440", - }; - struct vx_core *vx = hw->private_data; - - if (snd_BUG_ON(!type_ids[vx->type])) - return -EINVAL; - strcpy(info->id, type_ids[vx->type]); - if (vx_is_pcmcia(vx)) - info->num_dsps = 4; - else - info->num_dsps = 3; - if (vx->chip_status & VX_STAT_CHIP_INIT) - info->chip_ready = 1; - info->version = VX_DRIVER_VERSION; - return 0; -} - -static void free_fw(const struct firmware *fw) -{ - if (fw) { - vfree(fw->data); - kfree(fw); - } -} - -static int vx_hwdep_dsp_load(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image *dsp) -{ - struct vx_core *vx = hw->private_data; - int index, err; - struct firmware *fw; - - if (snd_BUG_ON(!vx->ops->load_dsp)) - return -ENXIO; - - fw = kmalloc(sizeof(*fw), GFP_KERNEL); - if (! fw) { - snd_printk(KERN_ERR "cannot allocate firmware\n"); - return -ENOMEM; - } - fw->size = dsp->length; - fw->data = vmalloc(fw->size); - if (! fw->data) { - snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n", - (int)fw->size); - kfree(fw); - return -ENOMEM; - } - if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) { - free_fw(fw); - return -EFAULT; - } - - index = dsp->index; - if (! vx_is_pcmcia(vx)) - index++; - err = vx->ops->load_dsp(vx, index, fw); - if (err < 0) { - free_fw(fw); - return err; - } -#ifdef CONFIG_PM - vx->firmware[index] = fw; -#else - free_fw(fw); -#endif - - if (index == 1) - vx->chip_status |= VX_STAT_XILINX_LOADED; - if (index < 3) - return 0; - - /* ok, we reached to the last one */ - /* create the devices if not built yet */ - if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) { - if ((err = snd_vx_pcm_new(vx)) < 0) - return err; - - if ((err = snd_vx_mixer_new(vx)) < 0) - return err; - - if (vx->ops->add_controls) - if ((err = vx->ops->add_controls(vx)) < 0) - return err; - - if ((err = snd_card_register(vx->card)) < 0) - return err; - - vx->chip_status |= VX_STAT_DEVICE_INIT; - } - vx->chip_status |= VX_STAT_CHIP_INIT; - return 0; -} - - -/* exported */ -int snd_vx_setup_firmware(struct vx_core *chip) -{ - int err; - struct snd_hwdep *hw; - - if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_VX; - hw->private_data = chip; - hw->ops.dsp_status = vx_hwdep_dsp_status; - hw->ops.dsp_load = vx_hwdep_dsp_load; - hw->exclusive = 1; - sprintf(hw->name, "VX Loader (%s)", chip->card->driver); - chip->hwdep = hw; - - return snd_card_register(chip->card); -} - -/* exported */ -void snd_vx_free_firmware(struct vx_core *chip) -{ -#ifdef CONFIG_PM - int i; - for (i = 0; i < 4; i++) - free_fw(chip->firmware[i]); -#endif -} - -#endif /* SND_VX_FW_LOADER */ - -EXPORT_SYMBOL(snd_vx_setup_firmware); -EXPORT_SYMBOL(snd_vx_free_firmware); diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c b/ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c deleted file mode 100644 index c71b8d14..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * Common mixer part - * - * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <sound/core.h> -#include <sound/control.h> -#include <sound/tlv.h> -#include <sound/vx_core.h> -#include "vx_cmd.h" - - -/* - * write a codec data (24bit) - */ -static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data) -{ - unsigned long flags; - - if (snd_BUG_ON(!chip->ops->write_codec)) - return; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - spin_lock_irqsave(&chip->lock, flags); - chip->ops->write_codec(chip, codec, data); - spin_unlock_irqrestore(&chip->lock, flags); -} - -/* - * Data type used to access the Codec - */ -union vx_codec_data { - u32 l; -#ifdef SNDRV_BIG_ENDIAN - struct w { - u16 h; - u16 l; - } w; - struct b { - u8 hh; - u8 mh; - u8 ml; - u8 ll; - } b; -#else /* LITTLE_ENDIAN */ - struct w { - u16 l; - u16 h; - } w; - struct b { - u8 ll; - u8 ml; - u8 mh; - u8 hh; - } b; -#endif -}; - -#define SET_CDC_DATA_SEL(di,s) ((di).b.mh = (u8) (s)) -#define SET_CDC_DATA_REG(di,r) ((di).b.ml = (u8) (r)) -#define SET_CDC_DATA_VAL(di,d) ((di).b.ll = (u8) (d)) -#define SET_CDC_DATA_INIT(di) ((di).l = 0L, SET_CDC_DATA_SEL(di,XX_CODEC_SELECTOR)) - -/* - * set up codec register and write the value - * @codec: the codec id, 0 or 1 - * @reg: register index - * @val: data value - */ -static void vx_set_codec_reg(struct vx_core *chip, int codec, int reg, int val) -{ - union vx_codec_data data; - /* DAC control register */ - SET_CDC_DATA_INIT(data); - SET_CDC_DATA_REG(data, reg); - SET_CDC_DATA_VAL(data, val); - vx_write_codec_reg(chip, codec, data.l); -} - - -/* - * vx_set_analog_output_level - set the output attenuation level - * @codec: the output codec, 0 or 1. (1 for VXP440 only) - * @left: left output level, 0 = mute - * @right: right output level - */ -static void vx_set_analog_output_level(struct vx_core *chip, int codec, int left, int right) -{ - left = chip->hw->output_level_max - left; - right = chip->hw->output_level_max - right; - - if (chip->ops->akm_write) { - chip->ops->akm_write(chip, XX_CODEC_LEVEL_LEFT_REGISTER, left); - chip->ops->akm_write(chip, XX_CODEC_LEVEL_RIGHT_REGISTER, right); - } else { - /* convert to attenuation level: 0 = 0dB (max), 0xe3 = -113.5 dB (min) */ - vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_LEFT_REGISTER, left); - vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_RIGHT_REGISTER, right); - } -} - - -/* - * vx_toggle_dac_mute - mute/unmute DAC - * @mute: 0 = unmute, 1 = mute - */ - -#define DAC_ATTEN_MIN 0x08 -#define DAC_ATTEN_MAX 0x38 - -void vx_toggle_dac_mute(struct vx_core *chip, int mute) -{ - unsigned int i; - for (i = 0; i < chip->hw->num_codecs; i++) { - if (chip->ops->akm_write) - chip->ops->akm_write(chip, XX_CODEC_DAC_CONTROL_REGISTER, mute); /* XXX */ - else - vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, - mute ? DAC_ATTEN_MAX : DAC_ATTEN_MIN); - } -} - -/* - * vx_reset_codec - reset and initialize the codecs - */ -void vx_reset_codec(struct vx_core *chip, int cold_reset) -{ - unsigned int i; - int port = chip->type >= VX_TYPE_VXPOCKET ? 0x75 : 0x65; - - chip->ops->reset_codec(chip); - - /* AKM codecs should be initialized in reset_codec callback */ - if (! chip->ops->akm_write) { - /* initialize old codecs */ - for (i = 0; i < chip->hw->num_codecs; i++) { - /* DAC control register (change level when zero crossing + mute) */ - vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, DAC_ATTEN_MAX); - /* ADC control register */ - vx_set_codec_reg(chip, i, XX_CODEC_ADC_CONTROL_REGISTER, 0x00); - /* Port mode register */ - vx_set_codec_reg(chip, i, XX_CODEC_PORT_MODE_REGISTER, port); - /* Clock control register */ - vx_set_codec_reg(chip, i, XX_CODEC_CLOCK_CONTROL_REGISTER, 0x00); - } - } - - /* mute analog output */ - for (i = 0; i < chip->hw->num_codecs; i++) { - chip->output_level[i][0] = 0; - chip->output_level[i][1] = 0; - vx_set_analog_output_level(chip, i, 0, 0); - } -} - -/* - * change the audio input source - * @src: the target source (VX_AUDIO_SRC_XXX) - */ -static void vx_change_audio_source(struct vx_core *chip, int src) -{ - unsigned long flags; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - spin_lock_irqsave(&chip->lock, flags); - chip->ops->change_audio_source(chip, src); - spin_unlock_irqrestore(&chip->lock, flags); -} - - -/* - * change the audio source if necessary and possible - * returns 1 if the source is actually changed. - */ -int vx_sync_audio_source(struct vx_core *chip) -{ - if (chip->audio_source_target == chip->audio_source || - chip->pcm_running) - return 0; - vx_change_audio_source(chip, chip->audio_source_target); - chip->audio_source = chip->audio_source_target; - return 1; -} - - -/* - * audio level, mute, monitoring - */ -struct vx_audio_level { - unsigned int has_level: 1; - unsigned int has_monitor_level: 1; - unsigned int has_mute: 1; - unsigned int has_monitor_mute: 1; - unsigned int mute; - unsigned int monitor_mute; - short level; - short monitor_level; -}; - -static int vx_adjust_audio_level(struct vx_core *chip, int audio, int capture, - struct vx_audio_level *info) -{ - struct vx_rmh rmh; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - vx_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST); - if (capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - /* Add Audio IO mask */ - rmh.Cmd[1] = 1 << audio; - rmh.Cmd[2] = 0; - if (info->has_level) { - rmh.Cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL; - rmh.Cmd[2] |= info->level; - } - if (info->has_monitor_level) { - rmh.Cmd[0] |= VALID_AUDIO_IO_MONITORING_LEVEL; - rmh.Cmd[2] |= ((unsigned int)info->monitor_level << 10); - } - if (info->has_mute) { - rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_LEVEL; - if (info->mute) - rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_LEVEL; - } - if (info->has_monitor_mute) { - /* validate flag for M2 at least to unmute it */ - rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_MONITORING_1 | VALID_AUDIO_IO_MUTE_MONITORING_2; - if (info->monitor_mute) - rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_MONITORING_1; - } - - return vx_send_msg(chip, &rmh); -} - - -#if 0 // not used -static int vx_read_audio_level(struct vx_core *chip, int audio, int capture, - struct vx_audio_level *info) -{ - int err; - struct vx_rmh rmh; - - memset(info, 0, sizeof(*info)); - vx_init_rmh(&rmh, CMD_GET_AUDIO_LEVELS); - if (capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - /* Add Audio IO mask */ - rmh.Cmd[1] = 1 << audio; - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - info.level = rmh.Stat[0] & MASK_DSP_WORD_LEVEL; - info.monitor_level = (rmh.Stat[0] >> 10) & MASK_DSP_WORD_LEVEL; - info.mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_LEVEL) ? 1 : 0; - info.monitor_mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_MONITORING_1) ? 1 : 0; - return 0; -} -#endif // not used - -/* - * set the monitoring level and mute state of the given audio - * no more static, because must be called from vx_pcm to demute monitoring - */ -int vx_set_monitor_level(struct vx_core *chip, int audio, int level, int active) -{ - struct vx_audio_level info; - - memset(&info, 0, sizeof(info)); - info.has_monitor_level = 1; - info.monitor_level = level; - info.has_monitor_mute = 1; - info.monitor_mute = !active; - chip->audio_monitor[audio] = level; - chip->audio_monitor_active[audio] = active; - return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */ -} - - -/* - * set the mute status of the given audio - */ -static int vx_set_audio_switch(struct vx_core *chip, int audio, int active) -{ - struct vx_audio_level info; - - memset(&info, 0, sizeof(info)); - info.has_mute = 1; - info.mute = !active; - chip->audio_active[audio] = active; - return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */ -} - -/* - * set the mute status of the given audio - */ -static int vx_set_audio_gain(struct vx_core *chip, int audio, int capture, int level) -{ - struct vx_audio_level info; - - memset(&info, 0, sizeof(info)); - info.has_level = 1; - info.level = level; - chip->audio_gain[capture][audio] = level; - return vx_adjust_audio_level(chip, audio, capture, &info); -} - -/* - * reset all audio levels - */ -static void vx_reset_audio_levels(struct vx_core *chip) -{ - unsigned int i, c; - struct vx_audio_level info; - - memset(chip->audio_gain, 0, sizeof(chip->audio_gain)); - memset(chip->audio_active, 0, sizeof(chip->audio_active)); - memset(chip->audio_monitor, 0, sizeof(chip->audio_monitor)); - memset(chip->audio_monitor_active, 0, sizeof(chip->audio_monitor_active)); - - for (c = 0; c < 2; c++) { - for (i = 0; i < chip->hw->num_ins * 2; i++) { - memset(&info, 0, sizeof(info)); - if (c == 0) { - info.has_monitor_level = 1; - info.has_mute = 1; - info.has_monitor_mute = 1; - } - info.has_level = 1; - info.level = CVAL_0DB; /* default: 0dB */ - vx_adjust_audio_level(chip, i, c, &info); - chip->audio_gain[c][i] = CVAL_0DB; - chip->audio_monitor[i] = CVAL_0DB; - } - } -} - - -/* - * VU, peak meter record - */ - -#define VU_METER_CHANNELS 2 - -struct vx_vu_meter { - int saturated; - int vu_level; - int peak_level; -}; - -/* - * get the VU and peak meter values - * @audio: the audio index - * @capture: 0 = playback, 1 = capture operation - * @info: the array of vx_vu_meter records (size = 2). - */ -static int vx_get_audio_vu_meter(struct vx_core *chip, int audio, int capture, struct vx_vu_meter *info) -{ - struct vx_rmh rmh; - int i, err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - vx_init_rmh(&rmh, CMD_AUDIO_VU_PIC_METER); - rmh.LgStat += 2 * VU_METER_CHANNELS; - if (capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - - /* Add Audio IO mask */ - rmh.Cmd[1] = 0; - for (i = 0; i < VU_METER_CHANNELS; i++) - rmh.Cmd[1] |= 1 << (audio + i); - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - /* Read response */ - for (i = 0; i < 2 * VU_METER_CHANNELS; i +=2) { - info->saturated = (rmh.Stat[0] & (1 << (audio + i))) ? 1 : 0; - info->vu_level = rmh.Stat[i + 1]; - info->peak_level = rmh.Stat[i + 2]; - info++; - } - return 0; -} - - -/* - * control API entries - */ - -/* - * output level control - */ -static int vx_output_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = chip->hw->output_level_max; - return 0; -} - -static int vx_output_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->id.index; - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->output_level[codec][0]; - ucontrol->value.integer.value[1] = chip->output_level[codec][1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->id.index; - unsigned int val[2], vmax; - - vmax = chip->hw->output_level_max; - val[0] = ucontrol->value.integer.value[0]; - val[1] = ucontrol->value.integer.value[1]; - if (val[0] > vmax || val[1] > vmax) - return -EINVAL; - mutex_lock(&chip->mixer_mutex); - if (val[0] != chip->output_level[codec][0] || - val[1] != chip->output_level[codec][1]) { - vx_set_analog_output_level(chip, codec, val[0], val[1]); - chip->output_level[codec][0] = val[0]; - chip->output_level[codec][1] = val[1]; - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_output_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Master Playback Volume", - .info = vx_output_level_info, - .get = vx_output_level_get, - .put = vx_output_level_put, - /* tlv will be filled later */ -}; - -/* - * audio source select - */ -static int vx_audio_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts_mic[3] = { - "Digital", "Line", "Mic" - }; - static char *texts_vx2[2] = { - "Digital", "Analog" - }; - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - if (chip->type >= VX_TYPE_VXPOCKET) { - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, - texts_mic[uinfo->value.enumerated.item]); - } else { - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - texts_vx2[uinfo->value.enumerated.item]); - } - return 0; -} - -static int vx_audio_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = chip->audio_source_target; - return 0; -} - -static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - if (chip->type >= VX_TYPE_VXPOCKET) { - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - } else { - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - } - mutex_lock(&chip->mixer_mutex); - if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) { - chip->audio_source_target = ucontrol->value.enumerated.item[0]; - vx_sync_audio_source(chip); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_audio_src = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = vx_audio_src_info, - .get = vx_audio_src_get, - .put = vx_audio_src_put, -}; - -/* - * clock mode selection - */ -static int vx_clock_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { - "Auto", "Internal", "External" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int vx_clock_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = chip->clock_mode; - return 0; -} - -static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - mutex_lock(&chip->mixer_mutex); - if (chip->clock_mode != ucontrol->value.enumerated.item[0]) { - chip->clock_mode = ucontrol->value.enumerated.item[0]; - vx_set_clock(chip, chip->freq); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_clock_mode = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Clock Mode", - .info = vx_clock_mode_info, - .get = vx_clock_mode_get, - .put = vx_clock_mode_put, -}; - -/* - * Audio Gain - */ -static int vx_audio_gain_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = CVAL_MAX; - return 0; -} - -static int vx_audio_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio]; - ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - unsigned int val[2]; - - val[0] = ucontrol->value.integer.value[0]; - val[1] = ucontrol->value.integer.value[1]; - if (val[0] > CVAL_MAX || val[1] > CVAL_MAX) - return -EINVAL; - mutex_lock(&chip->mixer_mutex); - if (val[0] != chip->audio_gain[capture][audio] || - val[1] != chip->audio_gain[capture][audio+1]) { - vx_set_audio_gain(chip, audio, capture, val[0]); - vx_set_audio_gain(chip, audio+1, capture, val[1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_monitor[audio]; - ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - unsigned int val[2]; - - val[0] = ucontrol->value.integer.value[0]; - val[1] = ucontrol->value.integer.value[1]; - if (val[0] > CVAL_MAX || val[1] > CVAL_MAX) - return -EINVAL; - - mutex_lock(&chip->mixer_mutex); - if (val[0] != chip->audio_monitor[audio] || - val[1] != chip->audio_monitor[audio+1]) { - vx_set_monitor_level(chip, audio, val[0], - chip->audio_monitor_active[audio]); - vx_set_monitor_level(chip, audio+1, val[1], - chip->audio_monitor_active[audio+1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -#define vx_audio_sw_info snd_ctl_boolean_stereo_info - -static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_active[audio]; - ucontrol->value.integer.value[1] = chip->audio_active[audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - if (ucontrol->value.integer.value[0] != chip->audio_active[audio] || - ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) { - vx_set_audio_switch(chip, audio, - !!ucontrol->value.integer.value[0]); - vx_set_audio_switch(chip, audio+1, - !!ucontrol->value.integer.value[1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio]; - ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] || - ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) { - vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], - !!ucontrol->value.integer.value[0]); - vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], - !!ucontrol->value.integer.value[1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); - -static struct snd_kcontrol_new vx_control_audio_gain = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - .info = vx_audio_gain_info, - .get = vx_audio_gain_get, - .put = vx_audio_gain_put, - .tlv = { .p = db_scale_audio_gain }, -}; -static struct snd_kcontrol_new vx_control_output_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .info = vx_audio_sw_info, - .get = vx_audio_sw_get, - .put = vx_audio_sw_put -}; -static struct snd_kcontrol_new vx_control_monitor_gain = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitoring Volume", - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .info = vx_audio_gain_info, /* shared */ - .get = vx_audio_monitor_get, - .put = vx_audio_monitor_put, - .tlv = { .p = db_scale_audio_gain }, -}; -static struct snd_kcontrol_new vx_control_monitor_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitoring Switch", - .info = vx_audio_sw_info, /* shared */ - .get = vx_monitor_sw_get, - .put = vx_monitor_sw_put -}; - - -/* - * IEC958 status bits - */ -static int vx_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int vx_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_iec958_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - unsigned int val; - - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - mutex_lock(&chip->mixer_mutex); - if (chip->uer_bits != val) { - chip->uer_bits = val; - vx_set_iec958_status(chip, val); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_iec958_mask = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .info = vx_iec958_info, /* shared */ - .get = vx_iec958_mask_get, -}; - -static struct snd_kcontrol_new vx_control_iec958 = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = vx_iec958_info, - .get = vx_iec958_get, - .put = vx_iec958_put -}; - - -/* - * VU meter - */ - -#define METER_MAX 0xff -#define METER_SHIFT 16 - -static int vx_vu_meter_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = METER_MAX; - return 0; -} - -static int vx_vu_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - struct vx_vu_meter meter[2]; - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - - vx_get_audio_vu_meter(chip, audio, capture, meter); - ucontrol->value.integer.value[0] = meter[0].vu_level >> METER_SHIFT; - ucontrol->value.integer.value[1] = meter[1].vu_level >> METER_SHIFT; - return 0; -} - -static int vx_peak_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - struct vx_vu_meter meter[2]; - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - - vx_get_audio_vu_meter(chip, audio, capture, meter); - ucontrol->value.integer.value[0] = meter[0].peak_level >> METER_SHIFT; - ucontrol->value.integer.value[1] = meter[1].peak_level >> METER_SHIFT; - return 0; -} - -#define vx_saturation_info snd_ctl_boolean_stereo_info - -static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - struct vx_vu_meter meter[2]; - int audio = kcontrol->private_value & 0xff; - - vx_get_audio_vu_meter(chip, audio, 1, meter); /* capture only */ - ucontrol->value.integer.value[0] = meter[0].saturated; - ucontrol->value.integer.value[1] = meter[1].saturated; - return 0; -} - -static struct snd_kcontrol_new vx_control_vu_meter = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - /* name will be filled later */ - .info = vx_vu_meter_info, - .get = vx_vu_meter_get, -}; - -static struct snd_kcontrol_new vx_control_peak_meter = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - /* name will be filled later */ - .info = vx_vu_meter_info, /* shared */ - .get = vx_peak_meter_get, -}; - -static struct snd_kcontrol_new vx_control_saturation = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Saturation", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = vx_saturation_info, - .get = vx_saturation_get, -}; - - - -/* - * - */ - -int snd_vx_mixer_new(struct vx_core *chip) -{ - unsigned int i, c; - int err; - struct snd_kcontrol_new temp; - struct snd_card *card = chip->card; - char name[32]; - - strcpy(card->mixername, card->driver); - - /* output level controls */ - for (i = 0; i < chip->hw->num_outs; i++) { - temp = vx_control_output_level; - temp.index = i; - temp.tlv.p = chip->hw->output_level_db_scale; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - /* PCM volumes, switches, monitoring */ - for (i = 0; i < chip->hw->num_outs; i++) { - int val = i * 2; - temp = vx_control_audio_gain; - temp.index = i; - temp.name = "PCM Playback Volume"; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - temp = vx_control_output_switch; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - temp = vx_control_monitor_gain; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - temp = vx_control_monitor_switch; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - for (i = 0; i < chip->hw->num_outs; i++) { - temp = vx_control_audio_gain; - temp.index = i; - temp.name = "PCM Capture Volume"; - temp.private_value = (i * 2) | (1 << 8); - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - /* Audio source */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0) - return err; - /* clock mode */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0) - return err; - /* IEC958 controls */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0) - return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0) - return err; - /* VU, peak, saturation meters */ - for (c = 0; c < 2; c++) { - static char *dir[2] = { "Output", "Input" }; - for (i = 0; i < chip->hw->num_ins; i++) { - int val = (i * 2) | (c << 8); - if (c == 1) { - temp = vx_control_saturation; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - sprintf(name, "%s VU Meter", dir[c]); - temp = vx_control_vu_meter; - temp.index = i; - temp.name = name; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - sprintf(name, "%s Peak Meter", dir[c]); - temp = vx_control_peak_meter; - temp.index = i; - temp.name = name; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - } - vx_reset_audio_levels(chip); - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c b/ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c deleted file mode 100644 index 5e897b23..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c +++ /dev/null @@ -1,1283 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * PCM part - * - * Copyright (c) 2002,2003 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * STRATEGY - * for playback, we send series of "chunks", which size is equal with the - * IBL size, typically 126 samples. at each end of chunk, the end-of-buffer - * interrupt is notified, and the interrupt handler will feed the next chunk. - * - * the current position is calculated from the sample count RMH. - * pipe->transferred is the counter of data which has been already transferred. - * if this counter reaches to the period size, snd_pcm_period_elapsed() will - * be issued. - * - * for capture, the situation is much easier. - * to get a low latency response, we'll check the capture streams at each - * interrupt (capture stream has no EOB notification). if the pending - * data is accumulated to the period size, snd_pcm_period_elapsed() is - * called and the pointer is updated. - * - * the current point of read buffer is kept in pipe->hw_ptr. note that - * this is in bytes. - * - * - * TODO - * - linked trigger for full-duplex mode. - * - scheduled action on the stream. - */ - -#include <linux/slab.h> -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/asoundef.h> -#include <sound/pcm.h> -#include <sound/vx_core.h> -#include "vx_cmd.h" - - -/* - * read three pending pcm bytes via inb() - */ -static void vx_pcm_read_per_bytes(struct vx_core *chip, struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe) -{ - int offset = pipe->hw_ptr; - unsigned char *buf = (unsigned char *)(runtime->dma_area + offset); - *buf++ = vx_inb(chip, RXH); - if (++offset >= pipe->buffer_bytes) { - offset = 0; - buf = (unsigned char *)runtime->dma_area; - } - *buf++ = vx_inb(chip, RXM); - if (++offset >= pipe->buffer_bytes) { - offset = 0; - buf = (unsigned char *)runtime->dma_area; - } - *buf++ = vx_inb(chip, RXL); - if (++offset >= pipe->buffer_bytes) { - offset = 0; - buf = (unsigned char *)runtime->dma_area; - } - pipe->hw_ptr = offset; -} - -/* - * vx_set_pcx_time - convert from the PC time to the RMH status time. - * @pc_time: the pointer for the PC-time to set - * @dsp_time: the pointer for RMH status time array - */ -static void vx_set_pcx_time(struct vx_core *chip, pcx_time_t *pc_time, - unsigned int *dsp_time) -{ - dsp_time[0] = (unsigned int)((*pc_time) >> 24) & PCX_TIME_HI_MASK; - dsp_time[1] = (unsigned int)(*pc_time) & MASK_DSP_WORD; -} - -/* - * vx_set_differed_time - set the differed time if specified - * @rmh: the rmh record to modify - * @pipe: the pipe to be checked - * - * if the pipe is programmed with the differed time, set the DSP time - * on the rmh and changes its command length. - * - * returns the increase of the command length. - */ -static int vx_set_differed_time(struct vx_core *chip, struct vx_rmh *rmh, - struct vx_pipe *pipe) -{ - /* Update The length added to the RMH command by the timestamp */ - if (! (pipe->differed_type & DC_DIFFERED_DELAY)) - return 0; - - /* Set the T bit */ - rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK; - - /* Time stamp is the 1st following parameter */ - vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]); - - /* Add the flags to a notified differed command */ - if (pipe->differed_type & DC_NOTIFY_DELAY) - rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ; - - /* Add the flags to a multiple differed command */ - if (pipe->differed_type & DC_MULTIPLE_DELAY) - rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH; - - /* Add the flags to a stream-time differed command */ - if (pipe->differed_type & DC_STREAM_TIME_DELAY) - rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH; - - rmh->LgCmd += 2; - return 2; -} - -/* - * vx_set_stream_format - send the stream format command - * @pipe: the affected pipe - * @data: format bitmask - */ -static int vx_set_stream_format(struct vx_core *chip, struct vx_pipe *pipe, - unsigned int data) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, pipe->is_capture ? - CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT); - rmh.Cmd[0] |= pipe->number << FIELD_SIZE; - - /* Command might be longer since we may have to add a timestamp */ - vx_set_differed_time(chip, &rmh, pipe); - - rmh.Cmd[rmh.LgCmd] = (data & 0xFFFFFF00) >> 8; - rmh.Cmd[rmh.LgCmd + 1] = (data & 0xFF) << 16 /*| (datal & 0xFFFF00) >> 8*/; - rmh.LgCmd += 2; - - return vx_send_msg(chip, &rmh); -} - - -/* - * vx_set_format - set the format of a pipe - * @pipe: the affected pipe - * @runtime: pcm runtime instance to be referred - * - * returns 0 if successful, or a negative error code. - */ -static int vx_set_format(struct vx_core *chip, struct vx_pipe *pipe, - struct snd_pcm_runtime *runtime) -{ - unsigned int header = HEADER_FMT_BASE; - - if (runtime->channels == 1) - header |= HEADER_FMT_MONO; - if (snd_pcm_format_little_endian(runtime->format)) - header |= HEADER_FMT_INTEL; - if (runtime->rate < 32000 && runtime->rate > 11025) - header |= HEADER_FMT_UPTO32; - else if (runtime->rate <= 11025) - header |= HEADER_FMT_UPTO11; - - switch (snd_pcm_format_physical_width(runtime->format)) { - // case 8: break; - case 16: header |= HEADER_FMT_16BITS; break; - case 24: header |= HEADER_FMT_24BITS; break; - default : - snd_BUG(); - return -EINVAL; - }; - - return vx_set_stream_format(chip, pipe, header); -} - -/* - * set / query the IBL size - */ -static int vx_set_ibl(struct vx_core *chip, struct vx_ibl_info *info) -{ - int err; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_IBL); - rmh.Cmd[0] |= info->size & 0x03ffff; - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - info->size = rmh.Stat[0]; - info->max_size = rmh.Stat[1]; - info->min_size = rmh.Stat[2]; - info->granularity = rmh.Stat[3]; - snd_printdd(KERN_DEBUG "vx_set_ibl: size = %d, max = %d, min = %d, gran = %d\n", - info->size, info->max_size, info->min_size, info->granularity); - return 0; -} - - -/* - * vx_get_pipe_state - get the state of a pipe - * @pipe: the pipe to be checked - * @state: the pointer for the returned state - * - * checks the state of a given pipe, and stores the state (1 = running, - * 0 = paused) on the given pointer. - * - * called from trigger callback only - */ -static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state) -{ - int err; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_PIPE_STATE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ - if (! err) - *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0; - return err; -} - - -/* - * vx_query_hbuffer_size - query available h-buffer size in bytes - * @pipe: the pipe to be checked - * - * return the available size on h-buffer in bytes, - * or a negative error code. - * - * NOTE: calling this function always switches to the stream mode. - * you'll need to disconnect the host to get back to the - * normal mode. - */ -static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe) -{ - int result; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_SIZE_HBUFFER); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - if (pipe->is_capture) - rmh.Cmd[0] |= 0x00000001; - result = vx_send_msg(chip, &rmh); - if (! result) - result = rmh.Stat[0] & 0xffff; - return result; -} - - -/* - * vx_pipe_can_start - query whether a pipe is ready for start - * @pipe: the pipe to be checked - * - * return 1 if ready, 0 if not ready, and negative value on error. - * - * called from trigger callback only - */ -static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe) -{ - int err; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_CAN_START_PIPE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - rmh.Cmd[0] |= 1; - - err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ - if (! err) { - if (rmh.Stat[0]) - err = 1; - } - return err; -} - -/* - * vx_conf_pipe - tell the pipe to stand by and wait for IRQA. - * @pipe: the pipe to be configured - */ -static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_CONF_PIPE); - if (pipe->is_capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - rmh.Cmd[1] = 1 << pipe->number; - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - -/* - * vx_send_irqa - trigger IRQA - */ -static int vx_send_irqa(struct vx_core *chip) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_SEND_IRQA); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -#define MAX_WAIT_FOR_DSP 250 -/* - * vx boards do not support inter-card sync, besides - * only 126 samples require to be prepared before a pipe can start - */ -#define CAN_START_DELAY 2 /* wait 2ms only before asking if the pipe is ready*/ -#define WAIT_STATE_DELAY 2 /* wait 2ms after irqA was requested and check if the pipe state toggled*/ - -/* - * vx_toggle_pipe - start / pause a pipe - * @pipe: the pipe to be triggered - * @state: start = 1, pause = 0 - * - * called from trigger callback only - * - */ -static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state) -{ - int err, i, cur_state; - - /* Check the pipe is not already in the requested state */ - if (vx_get_pipe_state(chip, pipe, &cur_state) < 0) - return -EBADFD; - if (state == cur_state) - return 0; - - /* If a start is requested, ask the DSP to get prepared - * and wait for a positive acknowledge (when there are - * enough sound buffer for this pipe) - */ - if (state) { - for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) { - err = vx_pipe_can_start(chip, pipe); - if (err > 0) - break; - /* Wait for a few, before asking again - * to avoid flooding the DSP with our requests - */ - mdelay(1); - } - } - - if ((err = vx_conf_pipe(chip, pipe)) < 0) - return err; - - if ((err = vx_send_irqa(chip)) < 0) - return err; - - /* If it completes successfully, wait for the pipes - * reaching the expected state before returning - * Check one pipe only (since they are synchronous) - */ - for (i = 0; i < MAX_WAIT_FOR_DSP; i++) { - err = vx_get_pipe_state(chip, pipe, &cur_state); - if (err < 0 || cur_state == state) - break; - err = -EIO; - mdelay(1); - } - return err < 0 ? -EIO : 0; -} - - -/* - * vx_stop_pipe - stop a pipe - * @pipe: the pipe to be stopped - * - * called from trigger callback only - */ -static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - vx_init_rmh(&rmh, CMD_STOP_PIPE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -/* - * vx_alloc_pipe - allocate a pipe and initialize the pipe instance - * @capture: 0 = playback, 1 = capture operation - * @audioid: the audio id to be assigned - * @num_audio: number of audio channels - * @pipep: the returned pipe instance - * - * return 0 on success, or a negative error code. - */ -static int vx_alloc_pipe(struct vx_core *chip, int capture, - int audioid, int num_audio, - struct vx_pipe **pipep) -{ - int err; - struct vx_pipe *pipe; - struct vx_rmh rmh; - int data_mode; - - *pipep = NULL; - vx_init_rmh(&rmh, CMD_RES_PIPE); - vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio); -#if 0 // NYI - if (underrun_skip_sound) - rmh.Cmd[0] |= BIT_SKIP_SOUND; -#endif // NYI - data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; - if (! capture && data_mode) - rmh.Cmd[0] |= BIT_DATA_MODE; - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - - /* initialize the pipe record */ - pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); - if (! pipe) { - /* release the pipe */ - vx_init_rmh(&rmh, CMD_FREE_PIPE); - vx_set_pipe_cmd_params(&rmh, capture, audioid, 0); - vx_send_msg(chip, &rmh); - return -ENOMEM; - } - - /* the pipe index should be identical with the audio index */ - pipe->number = audioid; - pipe->is_capture = capture; - pipe->channels = num_audio; - pipe->differed_type = 0; - pipe->pcx_time = 0; - pipe->data_mode = data_mode; - *pipep = pipe; - - return 0; -} - - -/* - * vx_free_pipe - release a pipe - * @pipe: pipe to be released - */ -static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_FREE_PIPE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - vx_send_msg(chip, &rmh); - - kfree(pipe); - return 0; -} - - -/* - * vx_start_stream - start the stream - * - * called from trigger callback only - */ -static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_START_ONE_STREAM); - vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); - vx_set_differed_time(chip, &rmh, pipe); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -/* - * vx_stop_stream - stop the stream - * - * called from trigger callback only - */ -static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_STOP_STREAM); - vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -/* - * playback hw information - */ - -static struct snd_pcm_hardware vx_pcm_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/ - /*SNDRV_PCM_INFO_RESUME*/), - .formats = (/*SNDRV_PCM_FMTBIT_U8 |*/ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 126, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = VX_MAX_PERIODS, - .fifo_size = 126, -}; - - -static void vx_pcm_delayed_start(unsigned long arg); - -/* - * vx_pcm_playback_open - open callback for playback - */ -static int vx_pcm_playback_open(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe = NULL; - unsigned int audio; - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - audio = subs->pcm->device * 2; - if (snd_BUG_ON(audio >= chip->audio_outs)) - return -EINVAL; - - /* playback pipe may have been already allocated for monitoring */ - pipe = chip->playback_pipes[audio]; - if (! pipe) { - /* not allocated yet */ - err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */ - if (err < 0) - return err; - chip->playback_pipes[audio] = pipe; - } - /* open for playback */ - pipe->references++; - - pipe->substream = subs; - tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); - chip->playback_pipes[audio] = pipe; - - runtime->hw = vx_pcm_playback_hw; - runtime->hw.period_bytes_min = chip->ibl.size; - runtime->private_data = pipe; - - /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); - - return 0; -} - -/* - * vx_pcm_playback_close - close callback for playback - */ -static int vx_pcm_playback_close(struct snd_pcm_substream *subs) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe; - - if (! subs->runtime->private_data) - return -EINVAL; - - pipe = subs->runtime->private_data; - - if (--pipe->references == 0) { - chip->playback_pipes[pipe->number] = NULL; - vx_free_pipe(chip, pipe); - } - - return 0; - -} - - -/* - * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe - * @pipe: the pipe to notify - * - * NB: call with a certain lock. - */ -static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe) -{ - int err; - struct vx_rmh rmh; /* use a temporary rmh here */ - - /* Toggle Dsp Host Interface into Message mode */ - vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT); - vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER); - vx_set_stream_cmd_params(&rmh, 0, pipe->number); - err = vx_send_msg_nolock(chip, &rmh); - if (err < 0) - return err; - /* Toggle Dsp Host Interface back to sound transfer mode */ - vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT); - return 0; -} - -/* - * vx_pcm_playback_transfer_chunk - transfer a single chunk - * @subs: substream - * @pipe: the pipe to transfer - * @size: chunk size in bytes - * - * transfer a single buffer chunk. EOB notificaton is added after that. - * called from the interrupt handler, too. - * - * return 0 if ok. - */ -static int vx_pcm_playback_transfer_chunk(struct vx_core *chip, - struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe, int size) -{ - int space, err = 0; - - space = vx_query_hbuffer_size(chip, pipe); - if (space < 0) { - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); - snd_printd("error hbuffer\n"); - return space; - } - if (space < size) { - vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); - snd_printd("no enough hbuffer space %d\n", space); - return -EIO; /* XRUN */ - } - - /* we don't need irqsave here, because this function - * is called from either trigger callback or irq handler - */ - spin_lock(&chip->lock); - vx_pseudo_dma_write(chip, runtime, pipe, size); - err = vx_notify_end_of_buffer(chip, pipe); - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); - spin_unlock(&chip->lock); - return err; -} - -/* - * update the position of the given pipe. - * pipe->position is updated and wrapped within the buffer size. - * pipe->transferred is updated, too, but the size is not wrapped, - * so that the caller can check the total transferred size later - * (to call snd_pcm_period_elapsed). - */ -static int vx_update_pipe_position(struct vx_core *chip, - struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - int err, update; - u64 count; - - vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - - count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1]; - update = (int)(count - pipe->cur_count); - pipe->cur_count = count; - pipe->position += update; - if (pipe->position >= (int)runtime->buffer_size) - pipe->position %= runtime->buffer_size; - pipe->transferred += update; - return 0; -} - -/* - * transfer the pending playback buffer data to DSP - * called from interrupt handler - */ -static void vx_pcm_playback_transfer(struct vx_core *chip, - struct snd_pcm_substream *subs, - struct vx_pipe *pipe, int nchunks) -{ - int i, err; - struct snd_pcm_runtime *runtime = subs->runtime; - - if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) - return; - for (i = 0; i < nchunks; i++) { - if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe, - chip->ibl.size)) < 0) - return; - } -} - -/* - * update the playback position and call snd_pcm_period_elapsed() if necessary - * called from interrupt handler - */ -static void vx_pcm_playback_update(struct vx_core *chip, - struct snd_pcm_substream *subs, - struct vx_pipe *pipe) -{ - int err; - struct snd_pcm_runtime *runtime = subs->runtime; - - if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) { - if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0) - return; - if (pipe->transferred >= (int)runtime->period_size) { - pipe->transferred %= runtime->period_size; - snd_pcm_period_elapsed(subs); - } - } -} - -/* - * start the stream and pipe. - * this function is called from tasklet, which is invoked by the trigger - * START callback. - */ -static void vx_pcm_delayed_start(unsigned long arg) -{ - struct snd_pcm_substream *subs = (struct snd_pcm_substream *)arg; - struct vx_core *chip = subs->pcm->private_data; - struct vx_pipe *pipe = subs->runtime->private_data; - int err; - - /* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/ - - if ((err = vx_start_stream(chip, pipe)) < 0) { - snd_printk(KERN_ERR "vx: cannot start stream\n"); - return; - } - if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) { - snd_printk(KERN_ERR "vx: cannot start pipe\n"); - return; - } - /* printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/ -} - -/* - * vx_pcm_playback_trigger - trigger callback for playback - */ -static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe = subs->runtime->private_data; - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (! pipe->is_capture) - vx_pcm_playback_transfer(chip, subs, pipe, 2); - /* FIXME: - * we trigger the pipe using tasklet, so that the interrupts are - * issued surely after the trigger is completed. - */ - tasklet_schedule(&pipe->start_tq); - chip->pcm_running++; - pipe->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - vx_toggle_pipe(chip, pipe, 0); - vx_stop_pipe(chip, pipe); - vx_stop_stream(chip, pipe); - chip->pcm_running--; - pipe->running = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0) - return err; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) - return err; - break; - default: - return -EINVAL; - } - return 0; -} - -/* - * vx_pcm_playback_pointer - pointer callback for playback - */ -static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_pipe *pipe = runtime->private_data; - return pipe->position; -} - -/* - * vx_pcm_hw_params - hw_params callback for playback and capture - */ -static int vx_pcm_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_alloc_vmalloc_32_buffer - (subs, params_buffer_bytes(hw_params)); -} - -/* - * vx_pcm_hw_free - hw_free callback for playback and capture - */ -static int vx_pcm_hw_free(struct snd_pcm_substream *subs) -{ - return snd_pcm_lib_free_vmalloc_buffer(subs); -} - -/* - * vx_pcm_prepare - prepare callback for playback and capture - */ -static int vx_pcm_prepare(struct snd_pcm_substream *subs) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_pipe *pipe = runtime->private_data; - int err, data_mode; - // int max_size, nchunks; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; - if (data_mode != pipe->data_mode && ! pipe->is_capture) { - /* IEC958 status (raw-mode) was changed */ - /* we reopen the pipe */ - struct vx_rmh rmh; - snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode); - vx_init_rmh(&rmh, CMD_FREE_PIPE); - vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0); - if ((err = vx_send_msg(chip, &rmh)) < 0) - return err; - vx_init_rmh(&rmh, CMD_RES_PIPE); - vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels); - if (data_mode) - rmh.Cmd[0] |= BIT_DATA_MODE; - if ((err = vx_send_msg(chip, &rmh)) < 0) - return err; - pipe->data_mode = data_mode; - } - - if (chip->pcm_running && chip->freq != runtime->rate) { - snd_printk(KERN_ERR "vx: cannot set different clock %d " - "from the current %d\n", runtime->rate, chip->freq); - return -EINVAL; - } - vx_set_clock(chip, runtime->rate); - - if ((err = vx_set_format(chip, pipe, runtime)) < 0) - return err; - - if (vx_is_pcmcia(chip)) { - pipe->align = 2; /* 16bit word */ - } else { - pipe->align = 4; /* 32bit word */ - } - - pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); - pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size); - pipe->hw_ptr = 0; - - /* set the timestamp */ - vx_update_pipe_position(chip, runtime, pipe); - /* clear again */ - pipe->transferred = 0; - pipe->position = 0; - - pipe->prepared = 1; - - return 0; -} - - -/* - * operators for PCM playback - */ -static struct snd_pcm_ops vx_pcm_playback_ops = { - .open = vx_pcm_playback_open, - .close = vx_pcm_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = vx_pcm_hw_params, - .hw_free = vx_pcm_hw_free, - .prepare = vx_pcm_prepare, - .trigger = vx_pcm_trigger, - .pointer = vx_pcm_playback_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - - -/* - * playback hw information - */ - -static struct snd_pcm_hardware vx_pcm_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/ - /*SNDRV_PCM_INFO_RESUME*/), - .formats = (/*SNDRV_PCM_FMTBIT_U8 |*/ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 126, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = VX_MAX_PERIODS, - .fifo_size = 126, -}; - - -/* - * vx_pcm_capture_open - open callback for capture - */ -static int vx_pcm_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe; - struct vx_pipe *pipe_out_monitoring = NULL; - unsigned int audio; - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - audio = subs->pcm->device * 2; - if (snd_BUG_ON(audio >= chip->audio_ins)) - return -EINVAL; - err = vx_alloc_pipe(chip, 1, audio, 2, &pipe); - if (err < 0) - return err; - pipe->substream = subs; - tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); - chip->capture_pipes[audio] = pipe; - - /* check if monitoring is needed */ - if (chip->audio_monitor_active[audio]) { - pipe_out_monitoring = chip->playback_pipes[audio]; - if (! pipe_out_monitoring) { - /* allocate a pipe */ - err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring); - if (err < 0) - return err; - chip->playback_pipes[audio] = pipe_out_monitoring; - } - pipe_out_monitoring->references++; - /* - if an output pipe is available, it's audios still may need to be - unmuted. hence we'll have to call a mixer entry point. - */ - vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], - chip->audio_monitor_active[audio]); - /* assuming stereo */ - vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], - chip->audio_monitor_active[audio+1]); - } - - pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */ - - runtime->hw = vx_pcm_capture_hw; - runtime->hw.period_bytes_min = chip->ibl.size; - runtime->private_data = pipe; - - /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); - - return 0; -} - -/* - * vx_pcm_capture_close - close callback for capture - */ -static int vx_pcm_capture_close(struct snd_pcm_substream *subs) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe; - struct vx_pipe *pipe_out_monitoring; - - if (! subs->runtime->private_data) - return -EINVAL; - pipe = subs->runtime->private_data; - chip->capture_pipes[pipe->number] = NULL; - - pipe_out_monitoring = pipe->monitoring_pipe; - - /* - if an output pipe is attached to this input, - check if it needs to be released. - */ - if (pipe_out_monitoring) { - if (--pipe_out_monitoring->references == 0) { - vx_free_pipe(chip, pipe_out_monitoring); - chip->playback_pipes[pipe->number] = NULL; - pipe->monitoring_pipe = NULL; - } - } - - vx_free_pipe(chip, pipe); - return 0; -} - - - -#define DMA_READ_ALIGN 6 /* hardware alignment for read */ - -/* - * vx_pcm_capture_update - update the capture buffer - */ -static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs, - struct vx_pipe *pipe) -{ - int size, space, count; - struct snd_pcm_runtime *runtime = subs->runtime; - - if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) - return; - - size = runtime->buffer_size - snd_pcm_capture_avail(runtime); - if (! size) - return; - size = frames_to_bytes(runtime, size); - space = vx_query_hbuffer_size(chip, pipe); - if (space < 0) - goto _error; - if (size > space) - size = space; - size = (size / 3) * 3; /* align to 3 bytes */ - if (size < DMA_READ_ALIGN) - goto _error; - - /* keep the last 6 bytes, they will be read after disconnection */ - count = size - DMA_READ_ALIGN; - /* read bytes until the current pointer reaches to the aligned position - * for word-transfer - */ - while (count > 0) { - if ((pipe->hw_ptr % pipe->align) == 0) - break; - if (vx_wait_for_rx_full(chip) < 0) - goto _error; - vx_pcm_read_per_bytes(chip, runtime, pipe); - count -= 3; - } - if (count > 0) { - /* ok, let's accelerate! */ - int align = pipe->align * 3; - space = (count / align) * align; - vx_pseudo_dma_read(chip, runtime, pipe, space); - count -= space; - } - /* read the rest of bytes */ - while (count > 0) { - if (vx_wait_for_rx_full(chip) < 0) - goto _error; - vx_pcm_read_per_bytes(chip, runtime, pipe); - count -= 3; - } - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); - /* read the last pending 6 bytes */ - count = DMA_READ_ALIGN; - while (count > 0) { - vx_pcm_read_per_bytes(chip, runtime, pipe); - count -= 3; - } - /* update the position */ - pipe->transferred += size; - if (pipe->transferred >= pipe->period_bytes) { - pipe->transferred %= pipe->period_bytes; - snd_pcm_period_elapsed(subs); - } - return; - - _error: - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); - return; -} - -/* - * vx_pcm_capture_pointer - pointer callback for capture - */ -static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_pipe *pipe = runtime->private_data; - return bytes_to_frames(runtime, pipe->hw_ptr); -} - -/* - * operators for PCM capture - */ -static struct snd_pcm_ops vx_pcm_capture_ops = { - .open = vx_pcm_capture_open, - .close = vx_pcm_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = vx_pcm_hw_params, - .hw_free = vx_pcm_hw_free, - .prepare = vx_pcm_prepare, - .trigger = vx_pcm_trigger, - .pointer = vx_pcm_capture_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - - -/* - * interrupt handler for pcm streams - */ -void vx_pcm_update_intr(struct vx_core *chip, unsigned int events) -{ - unsigned int i; - struct vx_pipe *pipe; - -#define EVENT_MASK (END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING) - - if (events & EVENT_MASK) { - vx_init_rmh(&chip->irq_rmh, CMD_ASYNC); - if (events & ASYNC_EVENTS_PENDING) - chip->irq_rmh.Cmd[0] |= 0x00000001; /* SEL_ASYNC_EVENTS */ - if (events & END_OF_BUFFER_EVENTS_PENDING) - chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */ - - if (vx_send_msg(chip, &chip->irq_rmh) < 0) { - snd_printdd(KERN_ERR "msg send error!!\n"); - return; - } - - i = 1; - while (i < chip->irq_rmh.LgStat) { - int p, buf, capture, eob; - p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD; - capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0; - eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0; - i++; - if (events & ASYNC_EVENTS_PENDING) - i++; - buf = 1; /* force to transfer */ - if (events & END_OF_BUFFER_EVENTS_PENDING) { - if (eob) - buf = chip->irq_rmh.Stat[i]; - i++; - } - if (capture) - continue; - if (snd_BUG_ON(p < 0 || p >= chip->audio_outs)) - continue; - pipe = chip->playback_pipes[p]; - if (pipe && pipe->substream) { - vx_pcm_playback_update(chip, pipe->substream, pipe); - vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf); - } - } - } - - /* update the capture pcm pointers as frequently as possible */ - for (i = 0; i < chip->audio_ins; i++) { - pipe = chip->capture_pipes[i]; - if (pipe && pipe->substream) - vx_pcm_capture_update(chip, pipe->substream, pipe); - } -} - - -/* - * vx_init_audio_io - check the available audio i/o and allocate pipe arrays - */ -static int vx_init_audio_io(struct vx_core *chip) -{ - struct vx_rmh rmh; - int preferred; - - vx_init_rmh(&rmh, CMD_SUPPORTED); - if (vx_send_msg(chip, &rmh) < 0) { - snd_printk(KERN_ERR "vx: cannot get the supported audio data\n"); - return -ENXIO; - } - - chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD; - chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD; - chip->audio_info = rmh.Stat[1]; - - /* allocate pipes */ - chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL); - if (!chip->playback_pipes) - return -ENOMEM; - chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL); - if (!chip->capture_pipes) { - kfree(chip->playback_pipes); - return -ENOMEM; - } - - preferred = chip->ibl.size; - chip->ibl.size = 0; - vx_set_ibl(chip, &chip->ibl); /* query the info */ - if (preferred > 0) { - chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / - chip->ibl.granularity) * chip->ibl.granularity; - if (chip->ibl.size > chip->ibl.max_size) - chip->ibl.size = chip->ibl.max_size; - } else - chip->ibl.size = chip->ibl.min_size; /* set to the minimum */ - vx_set_ibl(chip, &chip->ibl); - - return 0; -} - - -/* - * free callback for pcm - */ -static void snd_vx_pcm_free(struct snd_pcm *pcm) -{ - struct vx_core *chip = pcm->private_data; - chip->pcm[pcm->device] = NULL; - kfree(chip->playback_pipes); - chip->playback_pipes = NULL; - kfree(chip->capture_pipes); - chip->capture_pipes = NULL; -} - -/* - * snd_vx_pcm_new - create and initialize a pcm - */ -int snd_vx_pcm_new(struct vx_core *chip) -{ - struct snd_pcm *pcm; - unsigned int i; - int err; - - if ((err = vx_init_audio_io(chip)) < 0) - return err; - - for (i = 0; i < chip->hw->num_codecs; i++) { - unsigned int outs, ins; - outs = chip->audio_outs > i * 2 ? 1 : 0; - ins = chip->audio_ins > i * 2 ? 1 : 0; - if (! outs && ! ins) - break; - err = snd_pcm_new(chip->card, "VX PCM", i, - outs, ins, &pcm); - if (err < 0) - return err; - if (outs) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops); - if (ins) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops); - - pcm->private_data = chip; - pcm->private_free = snd_vx_pcm_free; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - chip->pcm[i] = pcm; - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_uer.c b/ANDROID_3.4.5/sound/drivers/vx/vx_uer.c deleted file mode 100644 index b0560fec..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_uer.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * IEC958 stuff - * - * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/vx_core.h> -#include "vx_cmd.h" - - -/* - * vx_modify_board_clock - tell the board that its clock has been modified - * @sync: DSP needs to resynchronize its FIFO - */ -static int vx_modify_board_clock(struct vx_core *chip, int sync) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_MODIFY_CLOCK); - /* Ask the DSP to resynchronize its FIFO. */ - if (sync) - rmh.Cmd[0] |= CMD_MODIFY_CLOCK_S_BIT; - return vx_send_msg(chip, &rmh); -} - -/* - * vx_modify_board_inputs - resync audio inputs - */ -static int vx_modify_board_inputs(struct vx_core *chip) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS); - rmh.Cmd[0] |= 1 << 0; /* reference: AUDIO 0 */ - return vx_send_msg(chip, &rmh); -} - -/* - * vx_read_one_cbit - read one bit from UER config - * @index: the bit index - * returns 0 or 1. - */ -static int vx_read_one_cbit(struct vx_core *chip, int index) -{ - unsigned long flags; - int val; - spin_lock_irqsave(&chip->lock, flags); - if (chip->type >= VX_TYPE_VXPOCKET) { - vx_outb(chip, CSUER, 1); /* read */ - vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); - val = (vx_inb(chip, RUER) >> 7) & 0x01; - } else { - vx_outl(chip, CSUER, 1); /* read */ - vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); - val = (vx_inl(chip, RUER) >> 7) & 0x01; - } - spin_unlock_irqrestore(&chip->lock, flags); - return val; -} - -/* - * vx_write_one_cbit - write one bit to UER config - * @index: the bit index - * @val: bit value, 0 or 1 - */ -static void vx_write_one_cbit(struct vx_core *chip, int index, int val) -{ - unsigned long flags; - val = !!val; /* 0 or 1 */ - spin_lock_irqsave(&chip->lock, flags); - if (vx_is_pcmcia(chip)) { - vx_outb(chip, CSUER, 0); /* write */ - vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); - } else { - vx_outl(chip, CSUER, 0); /* write */ - vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - -/* - * vx_read_uer_status - read the current UER status - * @mode: pointer to store the UER mode, VX_UER_MODE_XXX - * - * returns the frequency of UER, or 0 if not sync, - * or a negative error code. - */ -static int vx_read_uer_status(struct vx_core *chip, unsigned int *mode) -{ - int val, freq; - - /* Default values */ - freq = 0; - - /* Read UER status */ - if (vx_is_pcmcia(chip)) - val = vx_inb(chip, CSUER); - else - val = vx_inl(chip, CSUER); - if (val < 0) - return val; - /* If clock is present, read frequency */ - if (val & VX_SUER_CLOCK_PRESENT_MASK) { - switch (val & VX_SUER_FREQ_MASK) { - case VX_SUER_FREQ_32KHz_MASK: - freq = 32000; - break; - case VX_SUER_FREQ_44KHz_MASK: - freq = 44100; - break; - case VX_SUER_FREQ_48KHz_MASK: - freq = 48000; - break; - } - } - if (val & VX_SUER_DATA_PRESENT_MASK) - /* bit 0 corresponds to consumer/professional bit */ - *mode = vx_read_one_cbit(chip, 0) ? - VX_UER_MODE_PROFESSIONAL : VX_UER_MODE_CONSUMER; - else - *mode = VX_UER_MODE_NOT_PRESENT; - - return freq; -} - - -/* - * compute the sample clock value from frequency - * - * The formula is as follows: - * - * HexFreq = (dword) ((double) ((double) 28224000 / (double) Frequency)) - * switch ( HexFreq & 0x00000F00 ) - * case 0x00000100: ; - * case 0x00000200: - * case 0x00000300: HexFreq -= 0x00000201 ; - * case 0x00000400: - * case 0x00000500: - * case 0x00000600: - * case 0x00000700: HexFreq = (dword) (((double) 28224000 / (double) (Frequency*2)) - 1) - * default : HexFreq = (dword) ((double) 28224000 / (double) (Frequency*4)) - 0x000001FF - */ - -static int vx_calc_clock_from_freq(struct vx_core *chip, int freq) -{ - int hexfreq; - - if (snd_BUG_ON(freq <= 0)) - return 0; - - hexfreq = (28224000 * 10) / freq; - hexfreq = (hexfreq + 5) / 10; - - /* max freq = 55125 Hz */ - if (snd_BUG_ON(hexfreq <= 0x00000200)) - return 0; - - if (hexfreq <= 0x03ff) - return hexfreq - 0x00000201; - if (hexfreq <= 0x07ff) - return (hexfreq / 2) - 1; - if (hexfreq <= 0x0fff) - return (hexfreq / 4) + 0x000001ff; - - return 0x5fe; /* min freq = 6893 Hz */ -} - - -/* - * vx_change_clock_source - change the clock source - * @source: the new source - */ -static void vx_change_clock_source(struct vx_core *chip, int source) -{ - unsigned long flags; - - /* we mute DAC to prevent clicks */ - vx_toggle_dac_mute(chip, 1); - spin_lock_irqsave(&chip->lock, flags); - chip->ops->set_clock_source(chip, source); - chip->clock_source = source; - spin_unlock_irqrestore(&chip->lock, flags); - /* unmute */ - vx_toggle_dac_mute(chip, 0); -} - - -/* - * set the internal clock - */ -void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) -{ - int clock; - unsigned long flags; - /* Get real clock value */ - clock = vx_calc_clock_from_freq(chip, freq); - snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq); - spin_lock_irqsave(&chip->lock, flags); - if (vx_is_pcmcia(chip)) { - vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f); - vx_outb(chip, LOFREQ, clock & 0xff); - } else { - vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f); - vx_outl(chip, LOFREQ, clock & 0xff); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - - -/* - * set the iec958 status bits - * @bits: 32-bit status bits - */ -void vx_set_iec958_status(struct vx_core *chip, unsigned int bits) -{ - int i; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - for (i = 0; i < 32; i++) - vx_write_one_cbit(chip, i, bits & (1 << i)); -} - - -/* - * vx_set_clock - change the clock and audio source if necessary - */ -int vx_set_clock(struct vx_core *chip, unsigned int freq) -{ - int src_changed = 0; - - if (chip->chip_status & VX_STAT_IS_STALE) - return 0; - - /* change the audio source if possible */ - vx_sync_audio_source(chip); - - if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL || - (chip->clock_mode == VX_CLOCK_MODE_AUTO && - chip->audio_source == VX_AUDIO_SRC_DIGITAL)) { - if (chip->clock_source != UER_SYNC) { - vx_change_clock_source(chip, UER_SYNC); - mdelay(6); - src_changed = 1; - } - } else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL || - (chip->clock_mode == VX_CLOCK_MODE_AUTO && - chip->audio_source != VX_AUDIO_SRC_DIGITAL)) { - if (chip->clock_source != INTERNAL_QUARTZ) { - vx_change_clock_source(chip, INTERNAL_QUARTZ); - src_changed = 1; - } - if (chip->freq == freq) - return 0; - vx_set_internal_clock(chip, freq); - if (src_changed) - vx_modify_board_inputs(chip); - } - if (chip->freq == freq) - return 0; - chip->freq = freq; - vx_modify_board_clock(chip, 1); - return 0; -} - - -/* - * vx_change_frequency - called from interrupt handler - */ -int vx_change_frequency(struct vx_core *chip) -{ - int freq; - - if (chip->chip_status & VX_STAT_IS_STALE) - return 0; - - if (chip->clock_source == INTERNAL_QUARTZ) - return 0; - /* - * Read the real UER board frequency - */ - freq = vx_read_uer_status(chip, &chip->uer_detected); - if (freq < 0) - return freq; - /* - * The frequency computed by the DSP is good and - * is different from the previous computed. - */ - if (freq == 48000 || freq == 44100 || freq == 32000) - chip->freq_detected = freq; - - return 0; -} |