diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/pci/mixart')
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/Makefile | 8 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart.c | 1401 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart.h | 228 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart_core.c | 598 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart_core.h | 571 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c | 653 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h | 155 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c | 1186 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h | 31 |
9 files changed, 0 insertions, 4831 deletions
diff --git a/ANDROID_3.4.5/sound/pci/mixart/Makefile b/ANDROID_3.4.5/sound/pci/mixart/Makefile deleted file mode 100644 index cce159ec..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o - -obj-$(CONFIG_SND_MIXART) += snd-mixart.o diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart.c b/ANDROID_3.4.5/sound/pci/mixart/mixart.c deleted file mode 100644 index 487837c0..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * main file with alsa callbacks - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/slab.h> - -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/info.h> -#include <sound/control.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include "mixart.h" -#include "mixart_hwdep.h" -#include "mixart_core.h" -#include "mixart_mixer.h" - -#define CARD_NAME "miXart" - -MODULE_AUTHOR("Digigram <alsa@digigram.com>"); -MODULE_DESCRIPTION("Digigram " CARD_NAME); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); - -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_PNP; /* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); - -/* - */ - -static DEFINE_PCI_DEVICE_TABLE(snd_mixart_ids) = { - { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_mixart_ids); - - -static int mixart_set_pipe_state(struct mixart_mgr *mgr, - struct mixart_pipe *pipe, int start) -{ - struct mixart_group_state_req group_state; - struct mixart_group_state_resp group_state_resp; - struct mixart_msg request; - int err; - u32 system_msg_uid; - - switch(pipe->status) { - case PIPE_RUNNING: - case PIPE_CLOCK_SET: - if(start) return 0; /* already started */ - break; - case PIPE_STOPPED: - if(!start) return 0; /* already stopped */ - break; - default: - snd_printk(KERN_ERR "error mixart_set_pipe_state called with wrong pipe->status!\n"); - return -EINVAL; /* function called with wrong pipe status */ - } - - system_msg_uid = 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */ - - /* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */ - - request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD; - request.uid = (struct mixart_uid){0,0}; - request.data = &system_msg_uid; - request.size = sizeof(system_msg_uid); - - err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid); - if(err) { - snd_printk(KERN_ERR "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n"); - return err; - } - - /* start or stop the pipe (1 pipe) */ - - memset(&group_state, 0, sizeof(group_state)); - group_state.pipe_count = 1; - group_state.pipe_uid[0] = pipe->group_uid; - - if(start) - request.message_id = MSG_STREAM_START_STREAM_GRP_PACKET; - else - request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET; - - request.uid = pipe->group_uid; /*(struct mixart_uid){0,0};*/ - request.data = &group_state; - request.size = sizeof(group_state); - - err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp); - if (err < 0 || group_state_resp.txx_status != 0) { - snd_printk(KERN_ERR "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status); - return -EINVAL; - } - - if(start) { - u32 stat; - - group_state.pipe_count = 0; /* in case of start same command once again with pipe_count=0 */ - - err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp); - if (err < 0 || group_state_resp.txx_status != 0) { - snd_printk(KERN_ERR "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status); - return -EINVAL; - } - - /* in case of start send a synchro top */ - - request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD; - request.uid = (struct mixart_uid){0,0}; - request.data = NULL; - request.size = 0; - - err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat); - if (err < 0 || stat != 0) { - snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n", err, stat); - return -EINVAL; - } - - pipe->status = PIPE_RUNNING; - } - else /* !start */ - pipe->status = PIPE_STOPPED; - - return 0; -} - - -static int mixart_set_clock(struct mixart_mgr *mgr, - struct mixart_pipe *pipe, unsigned int rate) -{ - struct mixart_msg request; - struct mixart_clock_properties clock_properties; - struct mixart_clock_properties_resp clock_prop_resp; - int err; - - switch(pipe->status) { - case PIPE_CLOCK_SET: - break; - case PIPE_RUNNING: - if(rate != 0) - break; - default: - if(rate == 0) - return 0; /* nothing to do */ - else { - snd_printk(KERN_ERR "error mixart_set_clock(%d) called with wrong pipe->status !\n", rate); - return -EINVAL; - } - } - - memset(&clock_properties, 0, sizeof(clock_properties)); - clock_properties.clock_generic_type = (rate != 0) ? CGT_INTERNAL_CLOCK : CGT_NO_CLOCK; - clock_properties.clock_mode = CM_STANDALONE; - clock_properties.frequency = rate; - clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */ - clock_properties.uid_caller[0] = pipe->group_uid; - - snd_printdd("mixart_set_clock to %d kHz\n", rate); - - request.message_id = MSG_CLOCK_SET_PROPERTIES; - request.uid = mgr->uid_console_manager; - request.data = &clock_properties; - request.size = sizeof(clock_properties); - - err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), &clock_prop_resp); - if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != CM_STANDALONE) { - snd_printk(KERN_ERR "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n", err, clock_prop_resp.status, clock_prop_resp.clock_mode); - return -EINVAL; - } - - if(rate) pipe->status = PIPE_CLOCK_SET; - else pipe->status = PIPE_RUNNING; - - return 0; -} - - -/* - * Allocate or reference output pipe for analog IOs (pcmp0/1) - */ -struct mixart_pipe * -snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture, - int monitoring) -{ - int stream_count; - struct mixart_pipe *pipe; - struct mixart_msg request; - - if(capture) { - if (pcm_number == MIXART_PCM_ANALOG) { - pipe = &(chip->pipe_in_ana); /* analog inputs */ - } else { - pipe = &(chip->pipe_in_dig); /* digital inputs */ - } - request.message_id = MSG_STREAM_ADD_OUTPUT_GROUP; - stream_count = MIXART_CAPTURE_STREAMS; - } else { - if (pcm_number == MIXART_PCM_ANALOG) { - pipe = &(chip->pipe_out_ana); /* analog outputs */ - } else { - pipe = &(chip->pipe_out_dig); /* digital outputs */ - } - request.message_id = MSG_STREAM_ADD_INPUT_GROUP; - stream_count = MIXART_PLAYBACK_STREAMS; - } - - /* a new stream is opened and there are already all streams in use */ - if( (monitoring == 0) && (pipe->references >= stream_count) ) { - return NULL; - } - - /* pipe is not yet defined */ - if( pipe->status == PIPE_UNDEFINED ) { - int err, i; - struct { - struct mixart_streaming_group_req sgroup_req; - struct mixart_streaming_group sgroup_resp; - } *buf; - - snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number); - - buf = kmalloc(sizeof(*buf), GFP_KERNEL); - if (!buf) - return NULL; - - request.uid = (struct mixart_uid){0,0}; /* should be StreamManagerUID, but zero is OK if there is only one ! */ - request.data = &buf->sgroup_req; - request.size = sizeof(buf->sgroup_req); - - memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req)); - - buf->sgroup_req.stream_count = stream_count; - buf->sgroup_req.channel_count = 2; - buf->sgroup_req.latency = 256; - buf->sgroup_req.connector = pipe->uid_left_connector; /* the left connector */ - - for (i=0; i<stream_count; i++) { - int j; - struct mixart_flowinfo *flowinfo; - struct mixart_bufferinfo *bufferinfo; - - /* we don't yet know the format, so config 16 bit pcm audio for instance */ - buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024; - buf->sgroup_req.stream_info[i].size_max_sample_frame = 256; - buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */ - - /* find the right bufferinfo_array */ - j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i; - if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */ - - buf->sgroup_req.flow_entry[i] = j; - - flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area; - flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(struct mixart_bufferinfo)); - flowinfo[j].bufferinfo_count = 1; /* 1 will set the miXart to ring-buffer mode ! */ - - bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area; - bufferinfo[j].buffer_address = 0; /* buffer is not yet allocated */ - bufferinfo[j].available_length = 0; /* buffer is not yet allocated */ - - /* construct the identifier of the stream buffer received in the interrupts ! */ - bufferinfo[j].buffer_id = (chip->chip_idx << MIXART_NOTIFY_CARD_OFFSET) + (pcm_number << MIXART_NOTIFY_PCM_OFFSET ) + i; - if(capture) { - bufferinfo[j].buffer_id |= MIXART_NOTIFY_CAPT_MASK; - } - } - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp); - if((err < 0) || (buf->sgroup_resp.status != 0)) { - snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, buf->sgroup_resp.status); - kfree(buf); - return NULL; - } - - pipe->group_uid = buf->sgroup_resp.group; /* id of the pipe, as returned by embedded */ - pipe->stream_count = buf->sgroup_resp.stream_count; - /* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */ - - pipe->status = PIPE_STOPPED; - kfree(buf); - } - - if(monitoring) pipe->monitoring = 1; - else pipe->references++; - - return pipe; -} - - -int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr, - struct mixart_pipe *pipe, int monitoring) -{ - int err = 0; - - if(pipe->status == PIPE_UNDEFINED) - return 0; - - if(monitoring) - pipe->monitoring = 0; - else - pipe->references--; - - if((pipe->references <= 0) && (pipe->monitoring == 0)) { - - struct mixart_msg request; - struct mixart_delete_group_resp delete_resp; - - /* release the clock */ - err = mixart_set_clock( mgr, pipe, 0); - if( err < 0 ) { - snd_printk(KERN_ERR "mixart_set_clock(0) return error!\n"); - } - - /* stop the pipe */ - err = mixart_set_pipe_state(mgr, pipe, 0); - if( err < 0 ) { - snd_printk(KERN_ERR "error stopping pipe!\n"); - } - - request.message_id = MSG_STREAM_DELETE_GROUP; - request.uid = (struct mixart_uid){0,0}; - request.data = &pipe->group_uid; /* the streaming group ! */ - request.size = sizeof(pipe->group_uid); - - /* delete the pipe */ - err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp); - if ((err < 0) || (delete_resp.status != 0)) { - snd_printk(KERN_ERR "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", err, delete_resp.status); - } - - pipe->group_uid = (struct mixart_uid){0,0}; - pipe->stream_count = 0; - pipe->status = PIPE_UNDEFINED; - } - - return err; -} - -static int mixart_set_stream_state(struct mixart_stream *stream, int start) -{ - struct snd_mixart *chip; - struct mixart_stream_state_req stream_state_req; - struct mixart_msg request; - - if(!stream->substream) - return -EINVAL; - - memset(&stream_state_req, 0, sizeof(stream_state_req)); - stream_state_req.stream_count = 1; - stream_state_req.stream_info.stream_desc.uid_pipe = stream->pipe->group_uid; - stream_state_req.stream_info.stream_desc.stream_idx = stream->substream->number; - - if (stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - request.message_id = start ? MSG_STREAM_START_INPUT_STAGE_PACKET : MSG_STREAM_STOP_INPUT_STAGE_PACKET; - else - request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET; - - request.uid = (struct mixart_uid){0,0}; - request.data = &stream_state_req; - request.size = sizeof(stream_state_req); - - stream->abs_period_elapsed = 0; /* reset stream pos */ - stream->buf_periods = 0; - stream->buf_period_frag = 0; - - chip = snd_pcm_substream_chip(stream->substream); - - return snd_mixart_send_msg_nonblock(chip->mgr, &request); -} - -/* - * Trigger callback - */ - -static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct mixart_stream *stream = subs->runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - - snd_printdd("SNDRV_PCM_TRIGGER_START\n"); - - /* START_STREAM */ - if( mixart_set_stream_state(stream, 1) ) - return -EINVAL; - - stream->status = MIXART_STREAM_STATUS_RUNNING; - - break; - case SNDRV_PCM_TRIGGER_STOP: - - /* STOP_STREAM */ - if( mixart_set_stream_state(stream, 0) ) - return -EINVAL; - - stream->status = MIXART_STREAM_STATUS_OPEN; - - snd_printdd("SNDRV_PCM_TRIGGER_STOP\n"); - - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - /* TODO */ - stream->status = MIXART_STREAM_STATUS_PAUSE; - snd_printdd("SNDRV_PCM_PAUSE_PUSH\n"); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* TODO */ - stream->status = MIXART_STREAM_STATUS_RUNNING; - snd_printdd("SNDRV_PCM_PAUSE_RELEASE\n"); - break; - default: - return -EINVAL; - } - return 0; -} - -static int mixart_sync_nonblock_events(struct mixart_mgr *mgr) -{ - unsigned long timeout = jiffies + HZ; - while (atomic_read(&mgr->msg_processed) > 0) { - if (time_after(jiffies, timeout)) { - snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); - return -EBUSY; - } - schedule_timeout_uninterruptible(1); - } - return 0; -} - -/* - * prepare callback for all pcms - */ -static int snd_mixart_prepare(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_stream *stream = subs->runtime->private_data; - - /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */ - - snd_printdd("snd_mixart_prepare\n"); - - mixart_sync_nonblock_events(chip->mgr); - - /* only the first stream can choose the sample rate */ - /* the further opened streams will be limited to its frequency (see open) */ - if(chip->mgr->ref_count_rate == 1) - chip->mgr->sample_rate = subs->runtime->rate; - - /* set the clock only once (first stream) on the same pipe */ - if(stream->pipe->references == 1) { - if( mixart_set_clock(chip->mgr, stream->pipe, subs->runtime->rate) ) - return -EINVAL; - } - - return 0; -} - - -static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t format) -{ - int err; - struct snd_mixart *chip; - struct mixart_msg request; - struct mixart_stream_param_desc stream_param; - struct mixart_return_uid resp; - - chip = snd_pcm_substream_chip(stream->substream); - - memset(&stream_param, 0, sizeof(stream_param)); - - stream_param.coding_type = CT_LINEAR; - stream_param.number_of_channel = stream->channels; - - stream_param.sampling_freq = chip->mgr->sample_rate; - if(stream_param.sampling_freq == 0) - stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */ - - switch(format){ - case SNDRV_PCM_FORMAT_U8: - stream_param.sample_type = ST_INTEGER_8; - stream_param.sample_size = 8; - break; - case SNDRV_PCM_FORMAT_S16_LE: - stream_param.sample_type = ST_INTEGER_16LE; - stream_param.sample_size = 16; - break; - case SNDRV_PCM_FORMAT_S16_BE: - stream_param.sample_type = ST_INTEGER_16BE; - stream_param.sample_size = 16; - break; - case SNDRV_PCM_FORMAT_S24_3LE: - stream_param.sample_type = ST_INTEGER_24LE; - stream_param.sample_size = 24; - break; - case SNDRV_PCM_FORMAT_S24_3BE: - stream_param.sample_type = ST_INTEGER_24BE; - stream_param.sample_size = 24; - break; - case SNDRV_PCM_FORMAT_FLOAT_LE: - stream_param.sample_type = ST_FLOATING_POINT_32LE; - stream_param.sample_size = 32; - break; - case SNDRV_PCM_FORMAT_FLOAT_BE: - stream_param.sample_type = ST_FLOATING_POINT_32BE; - stream_param.sample_size = 32; - break; - default: - snd_printk(KERN_ERR "error mixart_set_format() : unknown format\n"); - return -EINVAL; - } - - snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n", - stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels); - - /* TODO: what else to configure ? */ - /* stream_param.samples_per_frame = 2; */ - /* stream_param.bytes_per_frame = 4; */ - /* stream_param.bytes_per_sample = 2; */ - - stream_param.pipe_count = 1; /* set to 1 */ - stream_param.stream_count = 1; /* set to 1 */ - stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid; - stream_param.stream_desc[0].stream_idx = stream->substream->number; - - request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM; - request.uid = (struct mixart_uid){0,0}; - request.data = &stream_param; - request.size = sizeof(stream_param); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); - if((err < 0) || resp.error_code) { - snd_printk(KERN_ERR "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", err, resp.error_code); - return -EINVAL; - } - return 0; -} - - -/* - * HW_PARAMS callback for all pcms - */ -static int snd_mixart_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct mixart_stream *stream = subs->runtime->private_data; - snd_pcm_format_t format; - int err; - int channels; - - /* set up channels */ - channels = params_channels(hw); - - /* set up format for the stream */ - format = params_format(hw); - - mutex_lock(&mgr->setup_mutex); - - /* update the stream levels */ - if( stream->pcm_number <= MIXART_PCM_DIGITAL ) { - int is_aes = stream->pcm_number > MIXART_PCM_ANALOG; - if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) - mixart_update_playback_stream_level(chip, is_aes, subs->number); - else - mixart_update_capture_stream_level( chip, is_aes); - } - - stream->channels = channels; - - /* set the format to the board */ - err = mixart_set_format(stream, format); - if(err < 0) { - mutex_unlock(&mgr->setup_mutex); - return err; - } - - /* allocate buffer */ - err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw)); - - if (err > 0) { - struct mixart_bufferinfo *bufferinfo; - int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number; - if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) { - i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */ - } - - bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area; - bufferinfo[i].buffer_address = subs->runtime->dma_addr; - bufferinfo[i].available_length = subs->runtime->dma_bytes; - /* bufferinfo[i].buffer_id is already defined */ - - snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i, - bufferinfo[i].buffer_address, - bufferinfo[i].available_length, - subs->number); - } - mutex_unlock(&mgr->setup_mutex); - - return err; -} - -static int snd_mixart_hw_free(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - snd_pcm_lib_free_pages(subs); - mixart_sync_nonblock_events(chip->mgr); - return 0; -} - - - -/* - * TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max - */ -static struct snd_pcm_hardware snd_mixart_analog_caps = -{ - .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = ( SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | - SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 256, /* 256 frames U8 mono*/ - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = (32*1024/256), -}; - -static struct snd_pcm_hardware snd_mixart_digital_caps = -{ - .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = ( SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | - SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ), - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 256, /* 256 frames U8 mono*/ - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = (32*1024/256), -}; - - -static int snd_mixart_playback_open(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct snd_pcm_runtime *runtime = subs->runtime; - struct snd_pcm *pcm = subs->pcm; - struct mixart_stream *stream; - struct mixart_pipe *pipe; - int err = 0; - int pcm_number; - - mutex_lock(&mgr->setup_mutex); - - if ( pcm == chip->pcm ) { - pcm_number = MIXART_PCM_ANALOG; - runtime->hw = snd_mixart_analog_caps; - } else { - snd_BUG_ON(pcm != chip->pcm_dig); - pcm_number = MIXART_PCM_DIGITAL; - runtime->hw = snd_mixart_digital_caps; - } - snd_printdd("snd_mixart_playback_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number); - - /* get stream info */ - stream = &(chip->playback_stream[pcm_number][subs->number]); - - if (stream->status != MIXART_STREAM_STATUS_FREE){ - /* streams in use */ - snd_printk(KERN_ERR "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); - err = -EBUSY; - goto _exit_open; - } - - /* get pipe pointer (out pipe) */ - pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0); - - if (pipe == NULL) { - err = -EINVAL; - goto _exit_open; - } - - /* start the pipe if necessary */ - err = mixart_set_pipe_state(chip->mgr, pipe, 1); - if( err < 0 ) { - snd_printk(KERN_ERR "error starting pipe!\n"); - snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); - err = -EINVAL; - goto _exit_open; - } - - stream->pipe = pipe; - stream->pcm_number = pcm_number; - stream->status = MIXART_STREAM_STATUS_OPEN; - stream->substream = subs; - stream->channels = 0; /* not configured yet */ - - runtime->private_data = stream; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64); - - /* if a sample rate is already used, another stream cannot change */ - if(mgr->ref_count_rate++) { - if(mgr->sample_rate) { - runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate; - } - } - - _exit_open: - mutex_unlock(&mgr->setup_mutex); - - return err; -} - - -static int snd_mixart_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct snd_pcm_runtime *runtime = subs->runtime; - struct snd_pcm *pcm = subs->pcm; - struct mixart_stream *stream; - struct mixart_pipe *pipe; - int err = 0; - int pcm_number; - - mutex_lock(&mgr->setup_mutex); - - if ( pcm == chip->pcm ) { - pcm_number = MIXART_PCM_ANALOG; - runtime->hw = snd_mixart_analog_caps; - } else { - snd_BUG_ON(pcm != chip->pcm_dig); - pcm_number = MIXART_PCM_DIGITAL; - runtime->hw = snd_mixart_digital_caps; - } - - runtime->hw.channels_min = 2; /* for instance, no mono */ - - snd_printdd("snd_mixart_capture_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number); - - /* get stream info */ - stream = &(chip->capture_stream[pcm_number]); - - if (stream->status != MIXART_STREAM_STATUS_FREE){ - /* streams in use */ - snd_printk(KERN_ERR "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); - err = -EBUSY; - goto _exit_open; - } - - /* get pipe pointer (in pipe) */ - pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0); - - if (pipe == NULL) { - err = -EINVAL; - goto _exit_open; - } - - /* start the pipe if necessary */ - err = mixart_set_pipe_state(chip->mgr, pipe, 1); - if( err < 0 ) { - snd_printk(KERN_ERR "error starting pipe!\n"); - snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); - err = -EINVAL; - goto _exit_open; - } - - stream->pipe = pipe; - stream->pcm_number = pcm_number; - stream->status = MIXART_STREAM_STATUS_OPEN; - stream->substream = subs; - stream->channels = 0; /* not configured yet */ - - runtime->private_data = stream; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64); - - /* if a sample rate is already used, another stream cannot change */ - if(mgr->ref_count_rate++) { - if(mgr->sample_rate) { - runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate; - } - } - - _exit_open: - mutex_unlock(&mgr->setup_mutex); - - return err; -} - - - -static int snd_mixart_close(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct mixart_stream *stream = subs->runtime->private_data; - - mutex_lock(&mgr->setup_mutex); - - snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number); - - /* sample rate released */ - if(--mgr->ref_count_rate == 0) { - mgr->sample_rate = 0; - } - - /* delete pipe */ - if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) { - - snd_printk(KERN_ERR "error snd_mixart_kill_ref_pipe C%dP%d\n", chip->chip_idx, stream->pcm_number); - } - - stream->pipe = NULL; - stream->status = MIXART_STREAM_STATUS_FREE; - stream->substream = NULL; - - mutex_unlock(&mgr->setup_mutex); - return 0; -} - - -static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct mixart_stream *stream = runtime->private_data; - - return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag); -} - - - -static struct snd_pcm_ops snd_mixart_playback_ops = { - .open = snd_mixart_playback_open, - .close = snd_mixart_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = snd_mixart_prepare, - .hw_params = snd_mixart_hw_params, - .hw_free = snd_mixart_hw_free, - .trigger = snd_mixart_trigger, - .pointer = snd_mixart_stream_pointer, -}; - -static struct snd_pcm_ops snd_mixart_capture_ops = { - .open = snd_mixart_capture_open, - .close = snd_mixart_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = snd_mixart_prepare, - .hw_params = snd_mixart_hw_params, - .hw_free = snd_mixart_hw_free, - .trigger = snd_mixart_trigger, - .pointer = snd_mixart_stream_pointer, -}; - -static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm) -{ -#if 0 - struct snd_pcm_substream *subs; - int stream; - - for (stream = 0; stream < 2; stream++) { - int idx = 0; - for (subs = pcm->streams[stream].substream; subs; subs = subs->next, idx++) - /* set up the unique device id with the chip index */ - subs->dma_device.id = subs->pcm->device << 16 | - subs->stream << 8 | (subs->number + 1) | - (chip->chip_idx + 1) << 24; - } -#endif - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->mgr->pci), 32*1024, 32*1024); -} - -/* - */ -static int snd_mixart_pcm_analog(struct snd_mixart *chip) -{ - int err; - struct snd_pcm *pcm; - char name[32]; - - sprintf(name, "miXart analog %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG, - MIXART_PLAYBACK_STREAMS, - MIXART_CAPTURE_STREAMS, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create the analog pcm %d\n", chip->chip_idx); - return err; - } - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, name); - - preallocate_buffers(chip, pcm); - - chip->pcm = pcm; - return 0; -} - - -/* - */ -static int snd_mixart_pcm_digital(struct snd_mixart *chip) -{ - int err; - struct snd_pcm *pcm; - char name[32]; - - sprintf(name, "miXart AES/EBU %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL, - MIXART_PLAYBACK_STREAMS, - MIXART_CAPTURE_STREAMS, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create the digital pcm %d\n", chip->chip_idx); - return err; - } - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, name); - - preallocate_buffers(chip, pcm); - - chip->pcm_dig = pcm; - return 0; -} - -static int snd_mixart_chip_free(struct snd_mixart *chip) -{ - kfree(chip); - return 0; -} - -static int snd_mixart_chip_dev_free(struct snd_device *device) -{ - struct snd_mixart *chip = device->device_data; - return snd_mixart_chip_free(chip); -} - - -/* - */ -static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx) -{ - int err; - struct snd_mixart *chip; - static struct snd_device_ops ops = { - .dev_free = snd_mixart_chip_dev_free, - }; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (! chip) { - snd_printk(KERN_ERR "cannot allocate chip\n"); - return -ENOMEM; - } - - chip->card = card; - chip->chip_idx = idx; - chip->mgr = mgr; - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_mixart_chip_free(chip); - return err; - } - - mgr->chip[idx] = chip; - snd_card_set_dev(card, &mgr->pci->dev); - - return 0; -} - -int snd_mixart_create_pcm(struct snd_mixart* chip) -{ - int err; - - err = snd_mixart_pcm_analog(chip); - if (err < 0) - return err; - - if(chip->mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { - - err = snd_mixart_pcm_digital(chip); - if (err < 0) - return err; - } - return err; -} - - -/* - * release all the cards assigned to a manager instance - */ -static int snd_mixart_free(struct mixart_mgr *mgr) -{ - unsigned int i; - - for (i = 0; i < mgr->num_cards; i++) { - if (mgr->chip[i]) - snd_card_free(mgr->chip[i]->card); - } - - /* stop mailbox */ - snd_mixart_exit_mailbox(mgr); - - /* release irq */ - if (mgr->irq >= 0) - free_irq(mgr->irq, mgr); - - /* reset board if some firmware was loaded */ - if(mgr->dsp_loaded) { - snd_mixart_reset_board(mgr); - snd_printdd("reset miXart !\n"); - } - - /* release the i/o ports */ - for (i = 0; i < 2; i++) { - if (mgr->mem[i].virt) - iounmap(mgr->mem[i].virt); - } - pci_release_regions(mgr->pci); - - /* free flowarray */ - if(mgr->flowinfo.area) { - snd_dma_free_pages(&mgr->flowinfo); - mgr->flowinfo.area = NULL; - } - /* free bufferarray */ - if(mgr->bufferinfo.area) { - snd_dma_free_pages(&mgr->bufferinfo); - mgr->bufferinfo.area = NULL; - } - - pci_disable_device(mgr->pci); - kfree(mgr); - return 0; -} - -/* - * proc interface - */ - -/* - mixart_BA0 proc interface for BAR 0 - read callback - */ -static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct mixart_mgr *mgr = entry->private_data; - - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) - return -EFAULT; - return count; -} - -/* - mixart_BA1 proc interface for BAR 1 - read callback - */ -static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct mixart_mgr *mgr = entry->private_data; - - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) - return -EFAULT; - return count; -} - -static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = { - .read = snd_mixart_BA0_read, -}; - -static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = { - .read = snd_mixart_BA1_read, -}; - - -static void snd_mixart_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_mixart *chip = entry->private_data; - u32 ref; - - snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx); - - /* stats available when embedded OS is running */ - if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) { - snd_iprintf(buffer, "- hardware -\n"); - switch (chip->mgr->board_type ) { - case MIXART_DAUGHTER_TYPE_NONE : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break; - case MIXART_DAUGHTER_TYPE_AES : snd_iprintf(buffer, "\tmiXart8 AES/EBU\n\n"); break; - case MIXART_DAUGHTER_TYPE_COBRANET : snd_iprintf(buffer, "\tmiXart8 Cobranet\n\n"); break; - default: snd_iprintf(buffer, "\tUNKNOWN!\n\n"); break; - } - - snd_iprintf(buffer, "- system load -\n"); - - /* get perf reference */ - - ref = readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET)); - - if (ref) { - u32 mailbox = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET)) / ref; - u32 streaming = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET)) / ref; - u32 interr = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET)) / ref; - - snd_iprintf(buffer, "\tstreaming : %d\n", streaming); - snd_iprintf(buffer, "\tmailbox : %d\n", mailbox); - snd_iprintf(buffer, "\tinterrups handling : %d\n\n", interr); - } - } /* endif elf loaded */ -} - -static void __devinit snd_mixart_proc_init(struct snd_mixart *chip) -{ - struct snd_info_entry *entry; - - /* text interface to read perf and temp meters */ - if (! snd_card_proc_new(chip->card, "board_info", &entry)) { - entry->private_data = chip; - entry->c.text.read = snd_mixart_proc_read; - } - - if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = chip->mgr; - entry->c.ops = &snd_mixart_proc_ops_BA0; - entry->size = MIXART_BA0_SIZE; - } - if (! snd_card_proc_new(chip->card, "mixart_BA1", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = chip->mgr; - entry->c.ops = &snd_mixart_proc_ops_BA1; - entry->size = MIXART_BA1_SIZE; - } -} -/* end of proc interface */ - - -/* - * probe function - creates the card manager - */ -static int __devinit snd_mixart_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct mixart_mgr *mgr; - unsigned int i; - int err; - size_t size; - - /* - */ - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (! enable[dev]) { - dev++; - return -ENOENT; - } - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - pci_set_master(pci); - - /* check if we can restrict PCI DMA transfers to 32 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - /* - */ - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - if (! mgr) { - pci_disable_device(pci); - return -ENOMEM; - } - - mgr->pci = pci; - mgr->irq = -1; - - /* resource assignment */ - if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { - kfree(mgr); - pci_disable_device(pci); - return err; - } - for (i = 0; i < 2; i++) { - mgr->mem[i].phys = pci_resource_start(pci, i); - mgr->mem[i].virt = pci_ioremap_bar(pci, i); - if (!mgr->mem[i].virt) { - printk(KERN_ERR "unable to remap resource 0x%lx\n", - mgr->mem[i].phys); - snd_mixart_free(mgr); - return -EBUSY; - } - } - - if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, - KBUILD_MODNAME, mgr)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_mixart_free(mgr); - return -EBUSY; - } - mgr->irq = pci->irq; - - sprintf(mgr->shortname, "Digigram miXart"); - sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq); - - /* ISR spinlock */ - spin_lock_init(&mgr->lock); - - /* init mailbox */ - mgr->msg_fifo_readptr = 0; - mgr->msg_fifo_writeptr = 0; - - spin_lock_init(&mgr->msg_lock); - mutex_init(&mgr->msg_mutex); - init_waitqueue_head(&mgr->msg_sleep); - atomic_set(&mgr->msg_processed, 0); - - /* init setup mutex*/ - mutex_init(&mgr->setup_mutex); - - /* init message taslket */ - tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr); - - /* card assignment */ - mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */ - for (i = 0; i < mgr->num_cards; i++) { - struct snd_card *card; - char tmpid[16]; - int idx; - - if (index[dev] < 0) - idx = index[dev]; - else - idx = index[dev] + i; - snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); - err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); - - if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card %d\n", i); - snd_mixart_free(mgr); - return err; - } - - strcpy(card->driver, CARD_NAME); - sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i); - sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); - - if ((err = snd_mixart_create(mgr, card, i)) < 0) { - snd_card_free(card); - snd_mixart_free(mgr); - return err; - } - - if(i==0) { - /* init proc interface only for chip0 */ - snd_mixart_proc_init(mgr->chip[i]); - } - - if ((err = snd_card_register(card)) < 0) { - snd_mixart_free(mgr); - return err; - } - } - - /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */ - mgr->board_type = MIXART_DAUGHTER_TYPE_NONE; - - /* create array of streaminfo */ - size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * - sizeof(struct mixart_flowinfo)) ); - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, &mgr->flowinfo) < 0) { - snd_mixart_free(mgr); - return -ENOMEM; - } - /* init streaminfo_array */ - memset(mgr->flowinfo.area, 0, size); - - /* create array of bufferinfo */ - size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * - sizeof(struct mixart_bufferinfo)) ); - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, &mgr->bufferinfo) < 0) { - snd_mixart_free(mgr); - return -ENOMEM; - } - /* init bufferinfo_array */ - memset(mgr->bufferinfo.area, 0, size); - - /* set up firmware */ - err = snd_mixart_setup_firmware(mgr); - if (err < 0) { - snd_mixart_free(mgr); - return err; - } - - pci_set_drvdata(pci, mgr); - dev++; - return 0; -} - -static void __devexit snd_mixart_remove(struct pci_dev *pci) -{ - snd_mixart_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_mixart_ids, - .probe = snd_mixart_probe, - .remove = __devexit_p(snd_mixart_remove), -}; - -static int __init alsa_card_mixart_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_mixart_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_mixart_init) -module_exit(alsa_card_mixart_exit) diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart.h b/ANDROID_3.4.5/sound/pci/mixart/mixart.h deleted file mode 100644 index 561634d5..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * main header file - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SOUND_MIXART_H -#define __SOUND_MIXART_H - -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <sound/pcm.h> - -#define MIXART_DRIVER_VERSION 0x000100 /* 0.1.0 */ - - -/* - */ - -struct mixart_uid { - u32 object_id; - u32 desc; -}; - -struct mem_area { - unsigned long phys; - void __iomem *virt; - struct resource *res; -}; - - -struct mixart_route { - unsigned char connected; - unsigned char phase_inv; - int volume; -}; - - -/* firmware status codes */ -#define MIXART_MOTHERBOARD_XLX_INDEX 0 -#define MIXART_MOTHERBOARD_ELF_INDEX 1 -#define MIXART_AESEBUBOARD_XLX_INDEX 2 -#define MIXART_HARDW_FILES_MAX_INDEX 3 /* xilinx, elf, AESEBU xilinx */ - -#define MIXART_MAX_CARDS 4 -#define MSG_FIFO_SIZE 16 - -#define MIXART_MAX_PHYS_CONNECTORS (MIXART_MAX_CARDS * 2 * 2) /* 4 * stereo * (analog+digital) */ - -struct mixart_mgr { - unsigned int num_cards; - struct snd_mixart *chip[MIXART_MAX_CARDS]; - - struct pci_dev *pci; - - int irq; - - /* memory-maps */ - struct mem_area mem[2]; - - /* share the name */ - char shortname[32]; /* short name of this soundcard */ - char longname[80]; /* name of this soundcard */ - - /* message tasklet */ - struct tasklet_struct msg_taskq; - - /* one and only blocking message or notification may be pending */ - u32 pending_event; - wait_queue_head_t msg_sleep; - - /* messages stored for tasklet */ - u32 msg_fifo[MSG_FIFO_SIZE]; - int msg_fifo_readptr; - int msg_fifo_writeptr; - atomic_t msg_processed; /* number of messages to be processed in takslet */ - - spinlock_t lock; /* interrupt spinlock */ - spinlock_t msg_lock; /* mailbox spinlock */ - struct mutex msg_mutex; /* mutex for blocking_requests */ - - struct mutex setup_mutex; /* mutex used in hw_params, open and close */ - - /* hardware interface */ - unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ - unsigned int board_type; /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */ - - struct snd_dma_buffer flowinfo; - struct snd_dma_buffer bufferinfo; - - struct mixart_uid uid_console_manager; - int sample_rate; - int ref_count_rate; - - struct mutex mixer_mutex; /* mutex for mixer */ - -}; - - -#define MIXART_STREAM_STATUS_FREE 0 -#define MIXART_STREAM_STATUS_OPEN 1 -#define MIXART_STREAM_STATUS_RUNNING 2 -#define MIXART_STREAM_STATUS_DRAINING 3 -#define MIXART_STREAM_STATUS_PAUSE 4 - -#define MIXART_PLAYBACK_STREAMS 4 -#define MIXART_CAPTURE_STREAMS 1 - -#define MIXART_PCM_ANALOG 0 -#define MIXART_PCM_DIGITAL 1 -#define MIXART_PCM_TOTAL 2 - -#define MIXART_MAX_STREAM_PER_CARD (MIXART_PCM_TOTAL * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS) ) - - -#define MIXART_NOTIFY_CARD_MASK 0xF000 -#define MIXART_NOTIFY_CARD_OFFSET 12 -#define MIXART_NOTIFY_PCM_MASK 0x0F00 -#define MIXART_NOTIFY_PCM_OFFSET 8 -#define MIXART_NOTIFY_CAPT_MASK 0x0080 -#define MIXART_NOTIFY_SUBS_MASK 0x007F - - -struct mixart_stream { - struct snd_pcm_substream *substream; - struct mixart_pipe *pipe; - int pcm_number; - - int status; /* nothing, running, draining */ - - u64 abs_period_elapsed; /* last absolute stream position where period_elapsed was called (multiple of runtime->period_size) */ - u32 buf_periods; /* periods counter in the buffer (< runtime->periods) */ - u32 buf_period_frag; /* defines with buf_period_pos the exact position in the buffer (< runtime->period_size) */ - - int channels; -}; - - -enum mixart_pipe_status { - PIPE_UNDEFINED, - PIPE_STOPPED, - PIPE_RUNNING, - PIPE_CLOCK_SET -}; - -struct mixart_pipe { - struct mixart_uid group_uid; /* id of the pipe, as returned by embedded */ - int stream_count; - struct mixart_uid uid_left_connector; /* UID's for the audio connectors */ - struct mixart_uid uid_right_connector; - enum mixart_pipe_status status; - int references; /* number of subs openned */ - int monitoring; /* pipe used for monitoring issue */ -}; - - -struct snd_mixart { - struct snd_card *card; - struct mixart_mgr *mgr; - int chip_idx; /* zero based */ - struct snd_hwdep *hwdep; /* DSP loader, only for the first card */ - - struct snd_pcm *pcm; /* PCM analog i/o */ - struct snd_pcm *pcm_dig; /* PCM digital i/o */ - - /* allocate stereo pipe for instance */ - struct mixart_pipe pipe_in_ana; - struct mixart_pipe pipe_out_ana; - - /* if AES/EBU daughter board is available, additional pipes possible on pcm_dig */ - struct mixart_pipe pipe_in_dig; - struct mixart_pipe pipe_out_dig; - - struct mixart_stream playback_stream[MIXART_PCM_TOTAL][MIXART_PLAYBACK_STREAMS]; /* 0 = pcm, 1 = pcm_dig */ - struct mixart_stream capture_stream[MIXART_PCM_TOTAL]; /* 0 = pcm, 1 = pcm_dig */ - - /* UID's for the physical io's */ - struct mixart_uid uid_out_analog_physio; - struct mixart_uid uid_in_analog_physio; - - int analog_playback_active[2]; /* Mixer : Master Playback active (!mute) */ - int analog_playback_volume[2]; /* Mixer : Master Playback Volume */ - int analog_capture_volume[2]; /* Mixer : Master Capture Volume */ - int digital_playback_active[2*MIXART_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Active [(analog+AES output)*streams][stereo]*/ - int digital_playback_volume[2*MIXART_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Volume [(analog+AES output)*streams][stereo]*/ - int digital_capture_volume[2][2]; /* Mixer : Digital Capture Volume [analog+AES output][stereo] */ - int monitoring_active[2]; /* Mixer : Monitoring Active */ - int monitoring_volume[2]; /* Mixer : Monitoring Volume */ -}; - -struct mixart_bufferinfo -{ - u32 buffer_address; - u32 reserved[5]; - u32 available_length; - u32 buffer_id; -}; - -struct mixart_flowinfo -{ - u32 bufferinfo_array_phy_address; - u32 reserved[11]; - u32 bufferinfo_count; - u32 capture; -}; - -/* exported */ -int snd_mixart_create_pcm(struct snd_mixart * chip); -struct mixart_pipe *snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture, int monitoring); -int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr, struct mixart_pipe *pipe, int monitoring); - -#endif /* __SOUND_MIXART_H */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.c b/ANDROID_3.4.5/sound/pci/mixart/mixart_core.c deleted file mode 100644 index 3df0f530..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * low level interface with interrupt handling and mail box implementation - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/interrupt.h> -#include <linux/mutex.h> - -#include <asm/io.h> -#include <sound/core.h> -#include "mixart.h" -#include "mixart_hwdep.h" -#include "mixart_core.h" - - -#define MSG_TIMEOUT_JIFFIES (400 * HZ) / 1000 /* 400 ms */ - -#define MSG_DESCRIPTOR_SIZE 0x24 -#define MSG_HEADER_SIZE (MSG_DESCRIPTOR_SIZE + 4) - -#define MSG_DEFAULT_SIZE 512 - -#define MSG_TYPE_MASK 0x00000003 /* mask for following types */ -#define MSG_TYPE_NOTIFY 0 /* embedded -> driver (only notification, do not get_msg() !) */ -#define MSG_TYPE_COMMAND 1 /* driver <-> embedded (a command has no answer) */ -#define MSG_TYPE_REQUEST 2 /* driver -> embedded (request will get an answer back) */ -#define MSG_TYPE_ANSWER 3 /* embedded -> driver */ -#define MSG_CANCEL_NOTIFY_MASK 0x80000000 /* this bit is set for a notification that has been canceled */ - - -static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame) -{ - /* read the message frame fifo */ - u32 headptr, tailptr; - - tailptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL)); - headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_HEAD)); - - if (tailptr == headptr) - return 0; /* no message posted */ - - if (tailptr < MSG_OUTBOUND_POST_STACK) - return 0; /* error */ - if (tailptr >= MSG_OUTBOUND_POST_STACK + MSG_BOUND_STACK_SIZE) - return 0; /* error */ - - *msg_frame = readl_be(MIXART_MEM(mgr, tailptr)); - - /* increment the tail index */ - tailptr += 4; - if( tailptr >= (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) ) - tailptr = MSG_OUTBOUND_POST_STACK; - writel_be(tailptr, MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL)); - - return 1; -} - -static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, - u32 msg_frame_address ) -{ - unsigned long flags; - u32 headptr; - u32 size; - int err; -#ifndef __BIG_ENDIAN - unsigned int i; -#endif - - spin_lock_irqsave(&mgr->msg_lock, flags); - err = 0; - - /* copy message descriptor from miXart to driver */ - size = readl_be(MIXART_MEM(mgr, msg_frame_address)); /* size of descriptor + response */ - resp->message_id = readl_be(MIXART_MEM(mgr, msg_frame_address + 4)); /* dwMessageID */ - resp->uid.object_id = readl_be(MIXART_MEM(mgr, msg_frame_address + 8)); /* uidDest */ - resp->uid.desc = readl_be(MIXART_MEM(mgr, msg_frame_address + 12)); /* */ - - if( (size < MSG_DESCRIPTOR_SIZE) || (resp->size < (size - MSG_DESCRIPTOR_SIZE))) { - err = -EINVAL; - snd_printk(KERN_ERR "problem with response size = %d\n", size); - goto _clean_exit; - } - size -= MSG_DESCRIPTOR_SIZE; - - memcpy_fromio(resp->data, MIXART_MEM(mgr, msg_frame_address + MSG_HEADER_SIZE ), size); - resp->size = size; - - /* swap if necessary */ -#ifndef __BIG_ENDIAN - size /= 4; /* u32 size */ - for(i=0; i < size; i++) { - ((u32*)resp->data)[i] = be32_to_cpu(((u32*)resp->data)[i]); - } -#endif - - /* - * free message frame address - */ - headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); - - if( (headptr < MSG_OUTBOUND_FREE_STACK) || ( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) { - err = -EINVAL; - goto _clean_exit; - } - - /* give address back to outbound fifo */ - writel_be(msg_frame_address, MIXART_MEM(mgr, headptr)); - - /* increment the outbound free head */ - headptr += 4; - if( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) ) - headptr = MSG_OUTBOUND_FREE_STACK; - - writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); - - _clean_exit: - spin_unlock_irqrestore(&mgr->msg_lock, flags); - - return err; -} - - -/* - * send a message to miXart. return: the msg_frame used for this message - */ -/* call with mgr->msg_lock held! */ -static int send_msg( struct mixart_mgr *mgr, - struct mixart_msg *msg, - int max_answersize, - int mark_pending, - u32 *msg_event) -{ - u32 headptr, tailptr; - u32 msg_frame_address; - int err, i; - - if (snd_BUG_ON(msg->size % 4)) - return -EINVAL; - - err = 0; - - /* get message frame address */ - tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); - headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); - - if (tailptr == headptr) { - snd_printk(KERN_ERR "error: no message frame available\n"); - return -EBUSY; - } - - if( (tailptr < MSG_INBOUND_FREE_STACK) || (tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) { - return -EINVAL; - } - - msg_frame_address = readl_be(MIXART_MEM(mgr, tailptr)); - writel(0, MIXART_MEM(mgr, tailptr)); /* set address to zero on this fifo position */ - - /* increment the inbound free tail */ - tailptr += 4; - if( tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) ) - tailptr = MSG_INBOUND_FREE_STACK; - - writel_be(tailptr, MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); - - /* TODO : use memcpy_toio() with intermediate buffer to copy the message */ - - /* copy message descriptor to card memory */ - writel_be( msg->size + MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address) ); /* size of descriptor + request */ - writel_be( msg->message_id , MIXART_MEM(mgr, msg_frame_address + 4) ); /* dwMessageID */ - writel_be( msg->uid.object_id, MIXART_MEM(mgr, msg_frame_address + 8) ); /* uidDest */ - writel_be( msg->uid.desc, MIXART_MEM(mgr, msg_frame_address + 12) ); /* */ - writel_be( MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address + 16) ); /* SizeHeader */ - writel_be( MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address + 20) ); /* OffsetDLL_T16 */ - writel_be( msg->size, MIXART_MEM(mgr, msg_frame_address + 24) ); /* SizeDLL_T16 */ - writel_be( MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address + 28) ); /* OffsetDLL_DRV */ - writel_be( 0, MIXART_MEM(mgr, msg_frame_address + 32) ); /* SizeDLL_DRV */ - writel_be( MSG_DESCRIPTOR_SIZE + max_answersize, MIXART_MEM(mgr, msg_frame_address + 36) ); /* dwExpectedAnswerSize */ - - /* copy message data to card memory */ - for( i=0; i < msg->size; i+=4 ) { - writel_be( *(u32*)(msg->data + i), MIXART_MEM(mgr, MSG_HEADER_SIZE + msg_frame_address + i) ); - } - - if( mark_pending ) { - if( *msg_event ) { - /* the pending event is the notification we wait for ! */ - mgr->pending_event = *msg_event; - } - else { - /* the pending event is the answer we wait for (same address than the request)! */ - mgr->pending_event = msg_frame_address; - - /* copy address back to caller */ - *msg_event = msg_frame_address; - } - } - - /* mark the frame as a request (will have an answer) */ - msg_frame_address |= MSG_TYPE_REQUEST; - - /* post the frame */ - headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD)); - - if( (headptr < MSG_INBOUND_POST_STACK) || (headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE))) { - return -EINVAL; - } - - writel_be(msg_frame_address, MIXART_MEM(mgr, headptr)); - - /* increment the inbound post head */ - headptr += 4; - if( headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) ) - headptr = MSG_INBOUND_POST_STACK; - - writel_be(headptr, MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD)); - - return 0; -} - - -int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data) -{ - struct mixart_msg resp; - u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */ - int err; - wait_queue_t wait; - long timeout; - - mutex_lock(&mgr->msg_mutex); - - init_waitqueue_entry(&wait, current); - - spin_lock_irq(&mgr->msg_lock); - /* send the message */ - err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ - if (err) { - spin_unlock_irq(&mgr->msg_lock); - mutex_unlock(&mgr->msg_mutex); - return err; - } - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&mgr->msg_sleep, &wait); - spin_unlock_irq(&mgr->msg_lock); - timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); - remove_wait_queue(&mgr->msg_sleep, &wait); - - if (! timeout) { - /* error - no ack */ - mutex_unlock(&mgr->msg_mutex); - snd_printk(KERN_ERR "error: no response on msg %x\n", msg_frame); - return -EIO; - } - - /* retrieve the answer into the same struct mixart_msg */ - resp.message_id = 0; - resp.uid = (struct mixart_uid){0,0}; - resp.data = resp_data; - resp.size = max_resp_size; - - err = get_msg(mgr, &resp, msg_frame); - - if( request->message_id != resp.message_id ) - snd_printk(KERN_ERR "RESPONSE ERROR!\n"); - - mutex_unlock(&mgr->msg_mutex); - return err; -} - - -int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, - struct mixart_msg *request, u32 notif_event) -{ - int err; - wait_queue_t wait; - long timeout; - - if (snd_BUG_ON(!notif_event)) - return -EINVAL; - if (snd_BUG_ON((notif_event & MSG_TYPE_MASK) != MSG_TYPE_NOTIFY)) - return -EINVAL; - if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK)) - return -EINVAL; - - mutex_lock(&mgr->msg_mutex); - - init_waitqueue_entry(&wait, current); - - spin_lock_irq(&mgr->msg_lock); - /* send the message */ - err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ - if(err) { - spin_unlock_irq(&mgr->msg_lock); - mutex_unlock(&mgr->msg_mutex); - return err; - } - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&mgr->msg_sleep, &wait); - spin_unlock_irq(&mgr->msg_lock); - timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); - remove_wait_queue(&mgr->msg_sleep, &wait); - - if (! timeout) { - /* error - no ack */ - mutex_unlock(&mgr->msg_mutex); - snd_printk(KERN_ERR "error: notification %x not received\n", notif_event); - return -EIO; - } - - mutex_unlock(&mgr->msg_mutex); - return 0; -} - - -int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request) -{ - u32 message_frame; - unsigned long flags; - int err; - - /* just send the message (do not mark it as a pending one) */ - spin_lock_irqsave(&mgr->msg_lock, flags); - err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame); - spin_unlock_irqrestore(&mgr->msg_lock, flags); - - /* the answer will be handled by snd_struct mixart_msgasklet() */ - atomic_inc(&mgr->msg_processed); - - return err; -} - - -/* common buffer of tasklet and interrupt to send/receive messages */ -static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4]; - - -void snd_mixart_msg_tasklet(unsigned long arg) -{ - struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg); - struct mixart_msg resp; - u32 msg, addr, type; - int err; - - spin_lock(&mgr->lock); - - while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) { - msg = mgr->msg_fifo[mgr->msg_fifo_readptr]; - mgr->msg_fifo_readptr++; - mgr->msg_fifo_readptr %= MSG_FIFO_SIZE; - - /* process the message ... */ - addr = msg & ~MSG_TYPE_MASK; - type = msg & MSG_TYPE_MASK; - - switch (type) { - case MSG_TYPE_ANSWER: - /* answer to a message on that we did not wait for (send_msg_nonblock) */ - resp.message_id = 0; - resp.data = mixart_msg_data; - resp.size = sizeof(mixart_msg_data); - err = get_msg(mgr, &resp, addr); - if( err < 0 ) { - snd_printk(KERN_ERR "tasklet: error(%d) reading mf %x\n", err, msg); - break; - } - - switch(resp.message_id) { - case MSG_STREAM_START_INPUT_STAGE_PACKET: - case MSG_STREAM_START_OUTPUT_STAGE_PACKET: - case MSG_STREAM_STOP_INPUT_STAGE_PACKET: - case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET: - if(mixart_msg_data[0]) - snd_printk(KERN_ERR "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]); - break; - default: - snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n", - msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size); - break; - } - break; - case MSG_TYPE_NOTIFY: - /* msg contains no address ! do not get_msg() ! */ - case MSG_TYPE_COMMAND: - /* get_msg() necessary */ - default: - snd_printk(KERN_ERR "tasklet doesn't know what to do with message %x\n", msg); - } /* switch type */ - - /* decrement counter */ - atomic_dec(&mgr->msg_processed); - - } /* while there is a msg in fifo */ - - spin_unlock(&mgr->lock); -} - - -irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) -{ - struct mixart_mgr *mgr = dev_id; - int err; - struct mixart_msg resp; - - u32 msg; - u32 it_reg; - - spin_lock(&mgr->lock); - - it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET)); - if( !(it_reg & MIXART_OIDI) ) { - /* this device did not cause the interrupt */ - spin_unlock(&mgr->lock); - return IRQ_NONE; - } - - /* mask all interrupts */ - writel_le(MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG(mgr, MIXART_PCI_OMIMR_OFFSET)); - - /* outdoorbell register clear */ - it_reg = readl(MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET)); - writel(it_reg, MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET)); - - /* clear interrupt */ - writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) ); - - /* process interrupt */ - while (retrieve_msg_frame(mgr, &msg)) { - - switch (msg & MSG_TYPE_MASK) { - case MSG_TYPE_COMMAND: - resp.message_id = 0; - resp.data = mixart_msg_data; - resp.size = sizeof(mixart_msg_data); - err = get_msg(mgr, &resp, msg & ~MSG_TYPE_MASK); - if( err < 0 ) { - snd_printk(KERN_ERR "interrupt: error(%d) reading mf %x\n", err, msg); - break; - } - - if(resp.message_id == MSG_SERVICES_TIMER_NOTIFY) { - int i; - struct mixart_timer_notify *notify; - notify = (struct mixart_timer_notify *)mixart_msg_data; - - for(i=0; i<notify->stream_count; i++) { - - u32 buffer_id = notify->streams[i].buffer_id; - unsigned int chip_number = (buffer_id & MIXART_NOTIFY_CARD_MASK) >> MIXART_NOTIFY_CARD_OFFSET; /* card0 to 3 */ - unsigned int pcm_number = (buffer_id & MIXART_NOTIFY_PCM_MASK ) >> MIXART_NOTIFY_PCM_OFFSET; /* pcm0 to 3 */ - unsigned int sub_number = buffer_id & MIXART_NOTIFY_SUBS_MASK; /* 0 to MIXART_PLAYBACK_STREAMS */ - unsigned int is_capture = ((buffer_id & MIXART_NOTIFY_CAPT_MASK) != 0); /* playback == 0 / capture == 1 */ - - struct snd_mixart *chip = mgr->chip[chip_number]; - struct mixart_stream *stream; - - if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) { - snd_printk(KERN_ERR "error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n", - buffer_id, notify->streams[i].sample_pos_low_part); - break; - } - - if (is_capture) - stream = &chip->capture_stream[pcm_number]; - else - stream = &chip->playback_stream[pcm_number][sub_number]; - - if (stream->substream && (stream->status == MIXART_STREAM_STATUS_RUNNING)) { - struct snd_pcm_runtime *runtime = stream->substream->runtime; - int elapsed = 0; - u64 sample_count = ((u64)notify->streams[i].sample_pos_high_part) << 32; - sample_count |= notify->streams[i].sample_pos_low_part; - - while (1) { - u64 new_elapse_pos = stream->abs_period_elapsed + runtime->period_size; - - if (new_elapse_pos > sample_count) { - break; /* while */ - } - else { - elapsed = 1; - stream->buf_periods++; - if (stream->buf_periods >= runtime->periods) - stream->buf_periods = 0; - - stream->abs_period_elapsed = new_elapse_pos; - } - } - stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed ); - - if(elapsed) { - spin_unlock(&mgr->lock); - snd_pcm_period_elapsed(stream->substream); - spin_lock(&mgr->lock); - } - } - } - break; - } - if(resp.message_id == MSG_SERVICES_REPORT_TRACES) { - if(resp.size > 1) { -#ifndef __BIG_ENDIAN - /* Traces are text: the swapped msg_data has to be swapped back ! */ - int i; - for(i=0; i<(resp.size/4); i++) { - (mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]); - } -#endif - ((char*)mixart_msg_data)[resp.size - 1] = 0; - snd_printdd("MIXART TRACE : %s\n", (char*)mixart_msg_data); - } - break; - } - - snd_printdd("command %x not handled\n", resp.message_id); - break; - - case MSG_TYPE_NOTIFY: - if(msg & MSG_CANCEL_NOTIFY_MASK) { - msg &= ~MSG_CANCEL_NOTIFY_MASK; - snd_printk(KERN_ERR "canceled notification %x !\n", msg); - } - /* no break, continue ! */ - case MSG_TYPE_ANSWER: - /* answer or notification to a message we are waiting for*/ - spin_lock(&mgr->msg_lock); - if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) { - wake_up(&mgr->msg_sleep); - mgr->pending_event = 0; - } - /* answer to a message we did't want to wait for */ - else { - mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg; - mgr->msg_fifo_writeptr++; - mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE; - tasklet_schedule(&mgr->msg_taskq); - } - spin_unlock(&mgr->msg_lock); - break; - case MSG_TYPE_REQUEST: - default: - snd_printdd("interrupt received request %x\n", msg); - /* TODO : are there things to do here ? */ - break; - } /* switch on msg type */ - } /* while there are msgs */ - - /* allow interrupt again */ - writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); - - spin_unlock(&mgr->lock); - - return IRQ_HANDLED; -} - - -void snd_mixart_init_mailbox(struct mixart_mgr *mgr) -{ - writel( 0, MIXART_MEM( mgr, MSG_HOST_RSC_PROTECTION ) ); - writel( 0, MIXART_MEM( mgr, MSG_AGENT_RSC_PROTECTION ) ); - - /* allow outbound messagebox to generate interrupts */ - if(mgr->irq >= 0) { - writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); - } - return; -} - -void snd_mixart_exit_mailbox(struct mixart_mgr *mgr) -{ - /* no more interrupts on outbound messagebox */ - writel_le( MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); - return; -} - -void snd_mixart_reset_board(struct mixart_mgr *mgr) -{ - /* reset miXart */ - writel_be( 1, MIXART_REG(mgr, MIXART_BA1_BRUTAL_RESET_OFFSET) ); - return; -} diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.h b/ANDROID_3.4.5/sound/pci/mixart/mixart_core.h deleted file mode 100644 index c919b734..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.h +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * low level interface with interrupt handling and mail box implementation - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SOUND_MIXART_CORE_H -#define __SOUND_MIXART_CORE_H - - -enum mixart_message_id { - MSG_CONNECTOR_GET_AUDIO_INFO = 0x050008, - MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL = 0x050009, - MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL = 0x05000A, - - MSG_CONSOLE_MANAGER = 0x070000, - MSG_CONSOLE_GET_CLOCK_UID = 0x070003, - - MSG_PHYSICALIO_SET_LEVEL = 0x0F0008, - - MSG_STREAM_ADD_INPUT_GROUP = 0x130000, - MSG_STREAM_ADD_OUTPUT_GROUP = 0x130001, - MSG_STREAM_DELETE_GROUP = 0x130004, - MSG_STREAM_START_STREAM_GRP_PACKET = 0x130006, - MSG_STREAM_START_INPUT_STAGE_PACKET = 0x130007, - MSG_STREAM_START_OUTPUT_STAGE_PACKET = 0x130008, - MSG_STREAM_STOP_STREAM_GRP_PACKET = 0x130009, - MSG_STREAM_STOP_INPUT_STAGE_PACKET = 0x13000A, - MSG_STREAM_STOP_OUTPUT_STAGE_PACKET = 0x13000B, - MSG_STREAM_SET_INPUT_STAGE_PARAM = 0x13000F, - MSG_STREAM_SET_OUTPUT_STAGE_PARAM = 0x130010, - MSG_STREAM_SET_IN_AUDIO_LEVEL = 0x130015, - MSG_STREAM_SET_OUT_STREAM_LEVEL = 0x130017, - - MSG_SYSTEM_FIRST_ID = 0x160000, - MSG_SYSTEM_ENUM_PHYSICAL_IO = 0x16000E, - MSG_SYSTEM_ENUM_PLAY_CONNECTOR = 0x160017, - MSG_SYSTEM_ENUM_RECORD_CONNECTOR = 0x160018, - MSG_SYSTEM_WAIT_SYNCHRO_CMD = 0x16002C, - MSG_SYSTEM_SEND_SYNCHRO_CMD = 0x16002D, - - MSG_SERVICES_TIMER_NOTIFY = 0x1D0404, - MSG_SERVICES_REPORT_TRACES = 0x1D0700, - - MSG_CLOCK_CHECK_PROPERTIES = 0x200001, - MSG_CLOCK_SET_PROPERTIES = 0x200002, -}; - - -struct mixart_msg -{ - u32 message_id; - struct mixart_uid uid; - void* data; - size_t size; -}; - -/* structs used to communicate with miXart */ - -struct mixart_enum_connector_resp -{ - u32 error_code; - u32 first_uid_offset; - u32 uid_count; - u32 current_uid_index; - struct mixart_uid uid[MIXART_MAX_PHYS_CONNECTORS]; -} __attribute__((packed)); - - -/* used for following struct */ -#define MIXART_FLOAT_P_22_0_TO_HEX 0x41b00000 /* 22.0f */ -#define MIXART_FLOAT_M_20_0_TO_HEX 0xc1a00000 /* -20.0f */ -#define MIXART_FLOAT____0_0_TO_HEX 0x00000000 /* 0.0f */ - -struct mixart_audio_info_req -{ - u32 line_max_level; /* float */ - u32 micro_max_level; /* float */ - u32 cd_max_level; /* float */ -} __attribute__((packed)); - -struct mixart_analog_hw_info -{ - u32 is_present; - u32 hw_connection_type; - u32 max_level; /* float */ - u32 min_var_level; /* float */ - u32 max_var_level; /* float */ - u32 step_var_level; /* float */ - u32 fix_gain; /* float */ - u32 zero_var; /* float */ -} __attribute__((packed)); - -struct mixart_digital_hw_info -{ - u32 hw_connection_type; - u32 presence; - u32 clock; - u32 reserved; -} __attribute__((packed)); - -struct mixart_analog_info -{ - u32 type_mask; - struct mixart_analog_hw_info micro_info; - struct mixart_analog_hw_info line_info; - struct mixart_analog_hw_info cd_info; - u32 analog_level_present; -} __attribute__((packed)); - -struct mixart_digital_info -{ - u32 type_mask; - struct mixart_digital_hw_info aes_info; - struct mixart_digital_hw_info adat_info; -} __attribute__((packed)); - -struct mixart_audio_info -{ - u32 clock_type_mask; - struct mixart_analog_info analog_info; - struct mixart_digital_info digital_info; -} __attribute__((packed)); - -struct mixart_audio_info_resp -{ - u32 txx_status; - struct mixart_audio_info info; -} __attribute__((packed)); - - -/* used for nb_bytes_max_per_sample */ -#define MIXART_FLOAT_P__4_0_TO_HEX 0x40800000 /* +4.0f */ -#define MIXART_FLOAT_P__8_0_TO_HEX 0x41000000 /* +8.0f */ - -struct mixart_stream_info -{ - u32 size_max_byte_frame; - u32 size_max_sample_frame; - u32 nb_bytes_max_per_sample; /* float */ -} __attribute__((packed)); - -/* MSG_STREAM_ADD_INPUT_GROUP */ -/* MSG_STREAM_ADD_OUTPUT_GROUP */ - -struct mixart_streaming_group_req -{ - u32 stream_count; - u32 channel_count; - u32 user_grp_number; - u32 first_phys_audio; - u32 latency; - struct mixart_stream_info stream_info[32]; - struct mixart_uid connector; - u32 flow_entry[32]; -} __attribute__((packed)); - -struct mixart_stream_desc -{ - struct mixart_uid stream_uid; - u32 stream_desc; -} __attribute__((packed)); - -struct mixart_streaming_group -{ - u32 status; - struct mixart_uid group; - u32 pipe_desc; - u32 stream_count; - struct mixart_stream_desc stream[32]; -} __attribute__((packed)); - -/* MSG_STREAM_DELETE_GROUP */ - -/* request : mixart_uid_t group */ - -struct mixart_delete_group_resp -{ - u32 status; - u32 unused[2]; -} __attribute__((packed)); - - -/* MSG_STREAM_START_INPUT_STAGE_PACKET = 0x130000 + 7, - MSG_STREAM_START_OUTPUT_STAGE_PACKET = 0x130000 + 8, - MSG_STREAM_STOP_INPUT_STAGE_PACKET = 0x130000 + 10, - MSG_STREAM_STOP_OUTPUT_STAGE_PACKET = 0x130000 + 11, - */ - -struct mixart_fx_couple_uid -{ - struct mixart_uid uid_fx_code; - struct mixart_uid uid_fx_data; -} __attribute__((packed)); - -struct mixart_txx_stream_desc -{ - struct mixart_uid uid_pipe; - u32 stream_idx; - u32 fx_number; - struct mixart_fx_couple_uid uid_fx[4]; -} __attribute__((packed)); - -struct mixart_flow_info -{ - struct mixart_txx_stream_desc stream_desc; - u32 flow_entry; - u32 flow_phy_addr; -} __attribute__((packed)); - -struct mixart_stream_state_req -{ - u32 delayed; - u64 scheduler; - u32 reserved4np[3]; - u32 stream_count; /* set to 1 for instance */ - struct mixart_flow_info stream_info; /* could be an array[stream_count] */ -} __attribute__((packed)); - -/* MSG_STREAM_START_STREAM_GRP_PACKET = 0x130000 + 6 - MSG_STREAM_STOP_STREAM_GRP_PACKET = 0x130000 + 9 - */ - -struct mixart_group_state_req -{ - u32 delayed; - u64 scheduler; - u32 reserved4np[2]; - u32 pipe_count; /* set to 1 for instance */ - struct mixart_uid pipe_uid[1]; /* could be an array[pipe_count] */ -} __attribute__((packed)); - -struct mixart_group_state_resp -{ - u32 txx_status; - u64 scheduler; -} __attribute__((packed)); - - - -/* Structures used by the MSG_SERVICES_TIMER_NOTIFY command */ - -struct mixart_sample_pos -{ - u32 buffer_id; - u32 validity; - u32 sample_pos_high_part; - u32 sample_pos_low_part; -} __attribute__((packed)); - -struct mixart_timer_notify -{ - u32 stream_count; - struct mixart_sample_pos streams[MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS]; -} __attribute__((packed)); - - -/* MSG_CONSOLE_GET_CLOCK_UID = 0x070003, - */ - -/* request is a uid with desc = MSG_CONSOLE_MANAGER | cardindex */ - -struct mixart_return_uid -{ - u32 error_code; - struct mixart_uid uid; -} __attribute__((packed)); - -/* MSG_CLOCK_CHECK_PROPERTIES = 0x200001, - MSG_CLOCK_SET_PROPERTIES = 0x200002, -*/ - -enum mixart_clock_generic_type { - CGT_NO_CLOCK, - CGT_INTERNAL_CLOCK, - CGT_PROGRAMMABLE_CLOCK, - CGT_INTERNAL_ENSLAVED_CLOCK, - CGT_EXTERNAL_CLOCK, - CGT_CURRENT_CLOCK -}; - -enum mixart_clock_mode { - CM_UNDEFINED, - CM_MASTER, - CM_SLAVE, - CM_STANDALONE, - CM_NOT_CONCERNED -}; - - -struct mixart_clock_properties -{ - u32 error_code; - u32 validation_mask; - u32 frequency; - u32 reference_frequency; - u32 clock_generic_type; - u32 clock_mode; - struct mixart_uid uid_clock_source; - struct mixart_uid uid_event_source; - u32 event_mode; - u32 synchro_signal_presence; - u32 format; - u32 board_mask; - u32 nb_callers; /* set to 1 (see below) */ - struct mixart_uid uid_caller[1]; -} __attribute__((packed)); - -struct mixart_clock_properties_resp -{ - u32 status; - u32 clock_mode; -} __attribute__((packed)); - - -/* MSG_STREAM_SET_INPUT_STAGE_PARAM = 0x13000F */ -/* MSG_STREAM_SET_OUTPUT_STAGE_PARAM = 0x130010 */ - -enum mixart_coding_type { - CT_NOT_DEFINED, - CT_LINEAR, - CT_MPEG_L1, - CT_MPEG_L2, - CT_MPEG_L3, - CT_MPEG_L3_LSF, - CT_GSM -}; -enum mixart_sample_type { - ST_NOT_DEFINED, - ST_FLOATING_POINT_32BE, - ST_FLOATING_POINT_32LE, - ST_FLOATING_POINT_64BE, - ST_FLOATING_POINT_64LE, - ST_FIXED_POINT_8, - ST_FIXED_POINT_16BE, - ST_FIXED_POINT_16LE, - ST_FIXED_POINT_24BE, - ST_FIXED_POINT_24LE, - ST_FIXED_POINT_32BE, - ST_FIXED_POINT_32LE, - ST_INTEGER_8, - ST_INTEGER_16BE, - ST_INTEGER_16LE, - ST_INTEGER_24BE, - ST_INTEGER_24LE, - ST_INTEGER_32BE, - ST_INTEGER_32LE -}; - -struct mixart_stream_param_desc -{ - u32 coding_type; /* use enum mixart_coding_type */ - u32 sample_type; /* use enum mixart_sample_type */ - - union { - struct { - u32 linear_endian_ness; - u32 linear_bits; - u32 is_signed; - u32 is_float; - } linear_format_info; - - struct { - u32 mpeg_layer; - u32 mpeg_mode; - u32 mpeg_mode_extension; - u32 mpeg_pre_emphasis; - u32 mpeg_has_padding_bit; - u32 mpeg_has_crc; - u32 mpeg_has_extension; - u32 mpeg_is_original; - u32 mpeg_has_copyright; - } mpeg_format_info; - } format_info; - - u32 delayed; - u64 scheduler; - u32 sample_size; - u32 has_header; - u32 has_suffix; - u32 has_bitrate; - u32 samples_per_frame; - u32 bytes_per_frame; - u32 bytes_per_sample; - u32 sampling_freq; - u32 number_of_channel; - u32 stream_number; - u32 buffer_size; - u32 differed_time; - u32 reserved4np[3]; - u32 pipe_count; /* set to 1 (array size !) */ - u32 stream_count; /* set to 1 (array size !) */ - struct mixart_txx_stream_desc stream_desc[1]; /* only one stream per command, but this could be an array */ - -} __attribute__((packed)); - - -/* MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL = 0x050009, - */ - - -struct mixart_get_out_audio_level -{ - u32 txx_status; - u32 digital_level; /* float */ - u32 analog_level; /* float */ - u32 monitor_level; /* float */ - u32 mute; - u32 monitor_mute1; - u32 monitor_mute2; -} __attribute__((packed)); - - -/* MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL = 0x05000A, - */ - -/* used for valid_mask below */ -#define MIXART_AUDIO_LEVEL_ANALOG_MASK 0x01 -#define MIXART_AUDIO_LEVEL_DIGITAL_MASK 0x02 -#define MIXART_AUDIO_LEVEL_MONITOR_MASK 0x04 -#define MIXART_AUDIO_LEVEL_MUTE_MASK 0x08 -#define MIXART_AUDIO_LEVEL_MUTE_M1_MASK 0x10 -#define MIXART_AUDIO_LEVEL_MUTE_M2_MASK 0x20 - -struct mixart_set_out_audio_level -{ - u32 delayed; - u64 scheduler; - u32 valid_mask1; - u32 valid_mask2; - u32 digital_level; /* float */ - u32 analog_level; /* float */ - u32 monitor_level; /* float */ - u32 mute; - u32 monitor_mute1; - u32 monitor_mute2; - u32 reserved4np; -} __attribute__((packed)); - - -/* MSG_SYSTEM_ENUM_PHYSICAL_IO = 0x16000E, - */ - -#define MIXART_MAX_PHYS_IO (MIXART_MAX_CARDS * 2 * 2) /* 4 * (analog+digital) * (playback+capture) */ - -struct mixart_uid_enumeration -{ - u32 error_code; - u32 first_uid_offset; - u32 nb_uid; - u32 current_uid_index; - struct mixart_uid uid[MIXART_MAX_PHYS_IO]; -} __attribute__((packed)); - - -/* MSG_PHYSICALIO_SET_LEVEL = 0x0F0008, - MSG_PHYSICALIO_GET_LEVEL = 0x0F000C, -*/ - -struct mixart_io_channel_level -{ - u32 analog_level; /* float */ - u32 unused[2]; -} __attribute__((packed)); - -struct mixart_io_level -{ - s32 channel; /* 0=left, 1=right, -1=both, -2=both same */ - struct mixart_io_channel_level level[2]; -} __attribute__((packed)); - - -/* MSG_STREAM_SET_IN_AUDIO_LEVEL = 0x130015, - */ - -struct mixart_in_audio_level_info -{ - struct mixart_uid connector; - u32 valid_mask1; - u32 valid_mask2; - u32 digital_level; - u32 analog_level; -} __attribute__((packed)); - -struct mixart_set_in_audio_level_req -{ - u32 delayed; - u64 scheduler; - u32 audio_count; /* set to <= 2 */ - u32 reserved4np; - struct mixart_in_audio_level_info level[2]; -} __attribute__((packed)); - -/* response is a 32 bit status */ - - -/* MSG_STREAM_SET_OUT_STREAM_LEVEL = 0x130017, - */ - -/* defines used for valid_mask1 */ -#define MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO1 0x01 -#define MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO2 0x02 -#define MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO1 0x04 -#define MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO2 0x08 -#define MIXART_OUT_STREAM_SET_LEVEL_STREAM_1 0x10 -#define MIXART_OUT_STREAM_SET_LEVEL_STREAM_2 0x20 -#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_1 0x40 -#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_2 0x80 - -struct mixart_out_stream_level_info -{ - u32 valid_mask1; - u32 valid_mask2; - u32 left_to_out1_level; - u32 left_to_out2_level; - u32 right_to_out1_level; - u32 right_to_out2_level; - u32 digital_level1; - u32 digital_level2; - u32 mute1; - u32 mute2; -} __attribute__((packed)); - -struct mixart_set_out_stream_level -{ - struct mixart_txx_stream_desc desc; - struct mixart_out_stream_level_info out_level; -} __attribute__((packed)); - -struct mixart_set_out_stream_level_req -{ - u32 delayed; - u64 scheduler; - u32 reserved4np[2]; - u32 nb_of_stream; /* set to 1 */ - struct mixart_set_out_stream_level stream_level; /* could be an array */ -} __attribute__((packed)); - -/* response to this request is a u32 status value */ - - -/* exported */ -void snd_mixart_init_mailbox(struct mixart_mgr *mgr); -void snd_mixart_exit_mailbox(struct mixart_mgr *mgr); - -int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data); -int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *request, u32 notif_event); -int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request); - -irqreturn_t snd_mixart_interrupt(int irq, void *dev_id); -void snd_mixart_msg_tasklet(unsigned long arg); - -void snd_mixart_reset_board(struct mixart_mgr *mgr); - -#endif /* __SOUND_MIXART_CORE_H */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c b/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c deleted file mode 100644 index bfbdc91e..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * DSP firmware management - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/firmware.h> -#include <linux/vmalloc.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <asm/io.h> -#include <sound/core.h> -#include "mixart.h" -#include "mixart_mixer.h" -#include "mixart_core.h" -#include "mixart_hwdep.h" - - -/** - * wait for a value on a peudo register, exit with a timeout - * - * @param mgr pointer to miXart manager structure - * @param offset unsigned pseudo_register base + offset of value - * @param value value - * @param timeout timeout in centisenconds - */ -static int mixart_wait_nice_for_register_value(struct mixart_mgr *mgr, - u32 offset, int is_egal, - u32 value, unsigned long timeout) -{ - unsigned long end_time = jiffies + (timeout * HZ / 100); - u32 read; - - do { /* we may take too long time in this loop. - * so give controls back to kernel if needed. - */ - cond_resched(); - - read = readl_be( MIXART_MEM( mgr, offset )); - if(is_egal) { - if(read == value) return 0; - } - else { /* wait for different value */ - if(read != value) return 0; - } - } while ( time_after_eq(end_time, jiffies) ); - - return -EBUSY; -} - - -/* - structures needed to upload elf code packets - */ -struct snd_mixart_elf32_ehdr { - u8 e_ident[16]; - u16 e_type; - u16 e_machine; - u32 e_version; - u32 e_entry; - u32 e_phoff; - u32 e_shoff; - u32 e_flags; - u16 e_ehsize; - u16 e_phentsize; - u16 e_phnum; - u16 e_shentsize; - u16 e_shnum; - u16 e_shstrndx; -}; - -struct snd_mixart_elf32_phdr { - u32 p_type; - u32 p_offset; - u32 p_vaddr; - u32 p_paddr; - u32 p_filesz; - u32 p_memsz; - u32 p_flags; - u32 p_align; -}; - -static int mixart_load_elf(struct mixart_mgr *mgr, const struct firmware *dsp ) -{ - char elf32_magic_number[4] = {0x7f,'E','L','F'}; - struct snd_mixart_elf32_ehdr *elf_header; - int i; - - elf_header = (struct snd_mixart_elf32_ehdr *)dsp->data; - for( i=0; i<4; i++ ) - if ( elf32_magic_number[i] != elf_header->e_ident[i] ) - return -EINVAL; - - if( elf_header->e_phoff != 0 ) { - struct snd_mixart_elf32_phdr elf_programheader; - - for( i=0; i < be16_to_cpu(elf_header->e_phnum); i++ ) { - u32 pos = be32_to_cpu(elf_header->e_phoff) + (u32)(i * be16_to_cpu(elf_header->e_phentsize)); - - memcpy( &elf_programheader, dsp->data + pos, sizeof(elf_programheader) ); - - if(elf_programheader.p_type != 0) { - if( elf_programheader.p_filesz != 0 ) { - memcpy_toio( MIXART_MEM( mgr, be32_to_cpu(elf_programheader.p_vaddr)), - dsp->data + be32_to_cpu( elf_programheader.p_offset ), - be32_to_cpu( elf_programheader.p_filesz )); - } - } - } - } - return 0; -} - -/* - * get basic information and init miXart - */ - -/* audio IDs for request to the board */ -#define MIXART_FIRST_ANA_AUDIO_ID 0 -#define MIXART_FIRST_DIG_AUDIO_ID 8 - -static int mixart_enum_connectors(struct mixart_mgr *mgr) -{ - u32 k; - int err; - struct mixart_msg request; - struct mixart_enum_connector_resp *connector; - struct mixart_audio_info_req *audio_info_req; - struct mixart_audio_info_resp *audio_info; - - connector = kmalloc(sizeof(*connector), GFP_KERNEL); - audio_info_req = kmalloc(sizeof(*audio_info_req), GFP_KERNEL); - audio_info = kmalloc(sizeof(*audio_info), GFP_KERNEL); - if (! connector || ! audio_info_req || ! audio_info) { - err = -ENOMEM; - goto __error; - } - - audio_info_req->line_max_level = MIXART_FLOAT_P_22_0_TO_HEX; - audio_info_req->micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX; - audio_info_req->cd_max_level = MIXART_FLOAT____0_0_TO_HEX; - - request.message_id = MSG_SYSTEM_ENUM_PLAY_CONNECTOR; - request.uid = (struct mixart_uid){0,0}; /* board num = 0 */ - request.data = NULL; - request.size = 0; - - err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); - if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n"); - err = -EINVAL; - goto __error; - } - - for(k=0; k < connector->uid_count; k++) { - struct mixart_pipe *pipe; - - if(k < MIXART_FIRST_DIG_AUDIO_ID) { - pipe = &mgr->chip[k/2]->pipe_out_ana; - } else { - pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_out_dig; - } - if(k & 1) { - pipe->uid_right_connector = connector->uid[k]; /* odd */ - } else { - pipe->uid_left_connector = connector->uid[k]; /* even */ - } - - /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ - - /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ - request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; - request.uid = connector->uid[k]; - request.data = audio_info_req; - request.size = sizeof(*audio_info_req); - - err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); - if( err < 0 ) { - snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); - goto __error; - } - /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ - } - - request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR; - request.uid = (struct mixart_uid){0,0}; /* board num = 0 */ - request.data = NULL; - request.size = 0; - - err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); - if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n"); - err = -EINVAL; - goto __error; - } - - for(k=0; k < connector->uid_count; k++) { - struct mixart_pipe *pipe; - - if(k < MIXART_FIRST_DIG_AUDIO_ID) { - pipe = &mgr->chip[k/2]->pipe_in_ana; - } else { - pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_in_dig; - } - if(k & 1) { - pipe->uid_right_connector = connector->uid[k]; /* odd */ - } else { - pipe->uid_left_connector = connector->uid[k]; /* even */ - } - - /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ - - /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ - request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; - request.uid = connector->uid[k]; - request.data = audio_info_req; - request.size = sizeof(*audio_info_req); - - err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); - if( err < 0 ) { - snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); - goto __error; - } - /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ - } - err = 0; - - __error: - kfree(connector); - kfree(audio_info_req); - kfree(audio_info); - - return err; -} - -static int mixart_enum_physio(struct mixart_mgr *mgr) -{ - u32 k; - int err; - struct mixart_msg request; - struct mixart_uid get_console_mgr; - struct mixart_return_uid console_mgr; - struct mixart_uid_enumeration phys_io; - - /* get the uid for the console manager */ - get_console_mgr.object_id = 0; - get_console_mgr.desc = MSG_CONSOLE_MANAGER | 0; /* cardindex = 0 */ - - request.message_id = MSG_CONSOLE_GET_CLOCK_UID; - request.uid = get_console_mgr; - request.data = &get_console_mgr; - request.size = sizeof(get_console_mgr); - - err = snd_mixart_send_msg(mgr, &request, sizeof(console_mgr), &console_mgr); - - if( (err < 0) || (console_mgr.error_code != 0) ) { - snd_printk(KERN_DEBUG "error MSG_CONSOLE_GET_CLOCK_UID : err=%x\n", console_mgr.error_code); - return -EINVAL; - } - - /* used later for clock issues ! */ - mgr->uid_console_manager = console_mgr.uid; - - request.message_id = MSG_SYSTEM_ENUM_PHYSICAL_IO; - request.uid = (struct mixart_uid){0,0}; - request.data = &console_mgr.uid; - request.size = sizeof(console_mgr.uid); - - err = snd_mixart_send_msg(mgr, &request, sizeof(phys_io), &phys_io); - if( (err < 0) || ( phys_io.error_code != 0 ) ) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PHYSICAL_IO err(%x) error_code(%x)\n", err, phys_io.error_code ); - return -EINVAL; - } - - /* min 2 phys io per card (analog in + analog out) */ - if (phys_io.nb_uid < MIXART_MAX_CARDS * 2) - return -EINVAL; - - for(k=0; k<mgr->num_cards; k++) { - mgr->chip[k]->uid_in_analog_physio = phys_io.uid[k]; - mgr->chip[k]->uid_out_analog_physio = phys_io.uid[phys_io.nb_uid/2 + k]; - } - - return 0; -} - - -static int mixart_first_init(struct mixart_mgr *mgr) -{ - u32 k; - int err; - struct mixart_msg request; - - if((err = mixart_enum_connectors(mgr)) < 0) return err; - - if((err = mixart_enum_physio(mgr)) < 0) return err; - - /* send a synchro command to card (necessary to do this before first MSG_STREAM_START_STREAM_GRP_PACKET) */ - /* though why not here */ - request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD; - request.uid = (struct mixart_uid){0,0}; - request.data = NULL; - request.size = 0; - /* this command has no data. response is a 32 bit status */ - err = snd_mixart_send_msg(mgr, &request, sizeof(k), &k); - if( (err < 0) || (k != 0) ) { - snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD\n"); - return err == 0 ? -EINVAL : err; - } - - return 0; -} - - -/* firmware base addresses (when hard coded) */ -#define MIXART_MOTHERBOARD_XLX_BASE_ADDRESS 0x00600000 - -static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmware *dsp) -{ - int err, card_index; - u32 status_xilinx, status_elf, status_daught; - u32 val; - - /* read motherboard xilinx status */ - status_xilinx = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); - /* read elf status */ - status_elf = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); - /* read daughterboard xilinx status */ - status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); - - /* motherboard xilinx status 5 will say that the board is performing a reset */ - if (status_xilinx == 5) { - snd_printk(KERN_ERR "miXart is resetting !\n"); - return -EAGAIN; /* try again later */ - } - - switch (index) { - case MIXART_MOTHERBOARD_XLX_INDEX: - - /* xilinx already loaded ? */ - if (status_xilinx == 4) { - snd_printk(KERN_DEBUG "xilinx is already loaded !\n"); - return 0; - } - /* the status should be 0 == "idle" */ - if (status_xilinx != 0) { - snd_printk(KERN_ERR "xilinx load error ! status = %d\n", - status_xilinx); - return -EIO; /* modprob -r may help ? */ - } - - /* check xilinx validity */ - if (((u32*)(dsp->data))[0] == 0xffffffff) - return -EINVAL; - if (dsp->size % 4) - return -EINVAL; - - /* set xilinx status to copying */ - writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); - - /* setup xilinx base address */ - writel_be( MIXART_MOTHERBOARD_XLX_BASE_ADDRESS, MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_BASE_ADDR_OFFSET )); - /* setup code size for xilinx file */ - writel_be( dsp->size, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_SIZE_OFFSET )); - - /* copy xilinx code */ - memcpy_toio( MIXART_MEM( mgr, MIXART_MOTHERBOARD_XLX_BASE_ADDRESS), dsp->data, dsp->size); - - /* set xilinx status to copy finished */ - writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); - - /* return, because no further processing needed */ - return 0; - - case MIXART_MOTHERBOARD_ELF_INDEX: - - if (status_elf == 4) { - snd_printk(KERN_DEBUG "elf file already loaded !\n"); - return 0; - } - - /* the status should be 0 == "idle" */ - if (status_elf != 0) { - snd_printk(KERN_ERR "elf load error ! status = %d\n", - status_elf); - return -EIO; /* modprob -r may help ? */ - } - - /* wait for xilinx status == 4 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */ - if (err < 0) { - snd_printk(KERN_ERR "xilinx was not loaded or " - "could not be started\n"); - return err; - } - - /* init some data on the card */ - writel_be( 0, MIXART_MEM( mgr, MIXART_PSEUDOREG_BOARDNUMBER ) ); /* set miXart boardnumber to 0 */ - writel_be( 0, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) ); /* reset pointer to flow table on miXart */ - - /* set elf status to copying */ - writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); - - /* process the copying of the elf packets */ - err = mixart_load_elf( mgr, dsp ); - if (err < 0) return err; - - /* set elf status to copy finished */ - writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); - - /* wait for elf status == 4 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */ - if (err < 0) { - snd_printk(KERN_ERR "elf could not be started\n"); - return err; - } - - /* miXart waits at this point on the pointer to the flow table */ - writel_be( (u32)mgr->flowinfo.addr, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) ); /* give pointer of flow table to miXart */ - - return 0; /* return, another xilinx file has to be loaded before */ - - case MIXART_AESEBUBOARD_XLX_INDEX: - default: - - /* elf and xilinx should be loaded */ - if (status_elf != 4 || status_xilinx != 4) { - printk(KERN_ERR "xilinx or elf not " - "successfully loaded\n"); - return -EIO; /* modprob -r may help ? */ - } - - /* wait for daughter detection != 0 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */ - if (err < 0) { - snd_printk(KERN_ERR "error starting elf file\n"); - return err; - } - - /* the board type can now be retrieved */ - mgr->board_type = (DAUGHTER_TYPE_MASK & readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DBRD_TYPE_OFFSET))); - - if (mgr->board_type == MIXART_DAUGHTER_TYPE_NONE) - break; /* no daughter board; the file does not have to be loaded, continue after the switch */ - - /* only if aesebu daughter board presence (elf code must run) */ - if (mgr->board_type != MIXART_DAUGHTER_TYPE_AES ) - return -EINVAL; - - /* daughter should be idle */ - if (status_daught != 0) { - printk(KERN_ERR "daughter load error ! status = %d\n", - status_daught); - return -EIO; /* modprob -r may help ? */ - } - - /* check daughterboard xilinx validity */ - if (((u32*)(dsp->data))[0] == 0xffffffff) - return -EINVAL; - if (dsp->size % 4) - return -EINVAL; - - /* inform mixart about the size of the file */ - writel_be( dsp->size, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_SIZE_OFFSET )); - - /* set daughterboard status to 1 */ - writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); - - /* wait for status == 2 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */ - if (err < 0) { - snd_printk(KERN_ERR "daughter board load error\n"); - return err; - } - - /* get the address where to write the file */ - val = readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET )); - if (!val) - return -EINVAL; - - /* copy daughterboard xilinx code */ - memcpy_toio( MIXART_MEM( mgr, val), dsp->data, dsp->size); - - /* set daughterboard status to 4 */ - writel_be( 4, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); - - /* continue with init */ - break; - } /* end of switch file index*/ - - /* wait for daughter status == 3 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */ - if (err < 0) { - snd_printk(KERN_ERR - "daughter board could not be initialised\n"); - return err; - } - - /* init mailbox (communication with embedded) */ - snd_mixart_init_mailbox(mgr); - - /* first communication with embedded */ - err = mixart_first_init(mgr); - if (err < 0) { - snd_printk(KERN_ERR "miXart could not be set up\n"); - return err; - } - - /* create devices and mixer in accordance with HW options*/ - for (card_index = 0; card_index < mgr->num_cards; card_index++) { - struct snd_mixart *chip = mgr->chip[card_index]; - - if ((err = snd_mixart_create_pcm(chip)) < 0) - return err; - - if (card_index == 0) { - if ((err = snd_mixart_create_mixer(chip->mgr)) < 0) - return err; - } - - if ((err = snd_card_register(chip->card)) < 0) - return err; - }; - - snd_printdd("miXart firmware downloaded and successfully set up\n"); - - return 0; -} - - -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) -#if !defined(CONFIG_USE_MIXARTLOADER) && !defined(CONFIG_SND_MIXART) /* built-in kernel */ -#define SND_MIXART_FW_LOADER /* use the standard firmware loader */ -#endif -#endif - -#ifdef SND_MIXART_FW_LOADER - -int snd_mixart_setup_firmware(struct mixart_mgr *mgr) -{ - static char *fw_files[3] = { - "miXart8.xlx", "miXart8.elf", "miXart8AES.xlx" - }; - char path[32]; - - const struct firmware *fw_entry; - int i, err; - - for (i = 0; i < 3; i++) { - sprintf(path, "mixart/%s", fw_files[i]); - if (request_firmware(&fw_entry, path, &mgr->pci->dev)) { - snd_printk(KERN_ERR "miXart: can't load firmware %s\n", path); - return -ENOENT; - } - /* fake hwdep dsp record */ - err = mixart_dsp_load(mgr, i, fw_entry); - release_firmware(fw_entry); - if (err < 0) - return err; - mgr->dsp_loaded |= 1 << i; - } - return 0; -} - -MODULE_FIRMWARE("mixart/miXart8.xlx"); -MODULE_FIRMWARE("mixart/miXart8.elf"); -MODULE_FIRMWARE("mixart/miXart8AES.xlx"); - -#else /* old style firmware loading */ - -/* miXart hwdep interface id string */ -#define SND_MIXART_HWDEP_ID "miXart Loader" - -static int mixart_hwdep_dsp_status(struct snd_hwdep *hw, - struct snd_hwdep_dsp_status *info) -{ - struct mixart_mgr *mgr = hw->private_data; - - strcpy(info->id, "miXart"); - info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX; - - if (mgr->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX)) - info->chip_ready = 1; - - info->version = MIXART_DRIVER_VERSION; - return 0; -} - -static int mixart_hwdep_dsp_load(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image *dsp) -{ - struct mixart_mgr* mgr = hw->private_data; - struct firmware fw; - int err; - - fw.size = dsp->length; - fw.data = vmalloc(dsp->length); - if (! fw.data) { - snd_printk(KERN_ERR "miXart: cannot allocate image size %d\n", - (int)dsp->length); - return -ENOMEM; - } - if (copy_from_user((void *) fw.data, dsp->image, dsp->length)) { - vfree(fw.data); - return -EFAULT; - } - err = mixart_dsp_load(mgr, dsp->index, &fw); - vfree(fw.data); - if (err < 0) - return err; - mgr->dsp_loaded |= 1 << dsp->index; - return err; -} - -int snd_mixart_setup_firmware(struct mixart_mgr *mgr) -{ - int err; - struct snd_hwdep *hw; - - /* only create hwdep interface for first cardX (see "index" module parameter)*/ - if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_MIXART; - hw->private_data = mgr; - hw->ops.dsp_status = mixart_hwdep_dsp_status; - hw->ops.dsp_load = mixart_hwdep_dsp_load; - hw->exclusive = 1; - sprintf(hw->name, SND_MIXART_HWDEP_ID); - mgr->dsp_loaded = 0; - - return snd_card_register(mgr->chip[0]->card); -} - -#endif /* SND_MIXART_FW_LOADER */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h b/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h deleted file mode 100644 index 812e288e..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * definitions and makros for basic card access - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SOUND_MIXART_HWDEP_H -#define __SOUND_MIXART_HWDEP_H - -#include <sound/hwdep.h> - -#ifndef readl_be -#define readl_be(x) be32_to_cpu(__raw_readl(x)) -#endif - -#ifndef writel_be -#define writel_be(data,addr) __raw_writel(cpu_to_be32(data),addr) -#endif - -#ifndef readl_le -#define readl_le(x) le32_to_cpu(__raw_readl(x)) -#endif - -#ifndef writel_le -#define writel_le(data,addr) __raw_writel(cpu_to_le32(data),addr) -#endif - -#define MIXART_MEM(mgr,x) ((mgr)->mem[0].virt + (x)) -#define MIXART_REG(mgr,x) ((mgr)->mem[1].virt + (x)) - - -/* Daughter board Type */ -#define DAUGHTER_TYPE_MASK 0x0F -#define DAUGHTER_VER_MASK 0xF0 -#define DAUGHTER_TYPEVER_MASK (DAUGHTER_TYPE_MASK|DAUGHTER_VER_MASK) - -#define MIXART_DAUGHTER_TYPE_NONE 0x00 -#define MIXART_DAUGHTER_TYPE_COBRANET 0x08 -#define MIXART_DAUGHTER_TYPE_AES 0x0E - - - -#define MIXART_BA0_SIZE (16 * 1024 * 1024) /* 16M */ -#define MIXART_BA1_SIZE (4 * 1024) /* 4k */ - -/* - * -----------BAR 0 -------------------------------------------------------------------------------------------------------- - */ -#define MIXART_PSEUDOREG 0x2000 /* base address for pseudoregister */ - -#define MIXART_PSEUDOREG_BOARDNUMBER MIXART_PSEUDOREG+0 /* board number */ - -/* perfmeter (available when elf loaded)*/ -#define MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET MIXART_PSEUDOREG+0x70 /* streaming load */ -#define MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET MIXART_PSEUDOREG+0x78 /* system load (reference)*/ -#define MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET MIXART_PSEUDOREG+0x7C /* mailbox load */ -#define MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET MIXART_PSEUDOREG+0x74 /* interrupt handling load */ - -/* motherboard xilinx loader info */ -#define MIXART_PSEUDOREG_MXLX_BASE_ADDR_OFFSET MIXART_PSEUDOREG+0x9C /* 0x00600000 */ -#define MIXART_PSEUDOREG_MXLX_SIZE_OFFSET MIXART_PSEUDOREG+0xA0 /* xilinx size in bytes */ -#define MIXART_PSEUDOREG_MXLX_STATUS_OFFSET MIXART_PSEUDOREG+0xA4 /* status = EMBEBBED_STAT_XXX */ - -/* elf loader info */ -#define MIXART_PSEUDOREG_ELF_STATUS_OFFSET MIXART_PSEUDOREG+0xB0 /* status = EMBEBBED_STAT_XXX */ - -/* -* after the elf code is loaded, and the flowtable info was passed to it, -* the driver polls on this address, until it shows 1 (presence) or 2 (absence) -* once it is non-zero, the daughter board type may be read -*/ -#define MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET MIXART_PSEUDOREG+0x990 - -/* Global info structure */ -#define MIXART_PSEUDOREG_DBRD_TYPE_OFFSET MIXART_PSEUDOREG+0x994 /* Type and version of daughterboard */ - - -/* daughterboard xilinx loader info */ -#define MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET MIXART_PSEUDOREG+0x998 /* get the address here where to write the file */ -#define MIXART_PSEUDOREG_DXLX_SIZE_OFFSET MIXART_PSEUDOREG+0x99C /* xilinx size in bytes */ -#define MIXART_PSEUDOREG_DXLX_STATUS_OFFSET MIXART_PSEUDOREG+0x9A0 /* status = EMBEBBED_STAT_XXX */ - -/* */ -#define MIXART_FLOWTABLE_PTR 0x3000 /* pointer to flow table */ - -/* mailbox addresses */ - -/* message DRV -> EMB */ -#define MSG_INBOUND_POST_HEAD 0x010008 /* DRV posts MF + increment4 */ -#define MSG_INBOUND_POST_TAIL 0x01000C /* EMB gets MF + increment4 */ -/* message EMB -> DRV */ -#define MSG_OUTBOUND_POST_TAIL 0x01001C /* DRV gets MF + increment4 */ -#define MSG_OUTBOUND_POST_HEAD 0x010018 /* EMB posts MF + increment4 */ -/* Get Free Frames */ -#define MSG_INBOUND_FREE_TAIL 0x010004 /* DRV gets MFA + increment4 */ -#define MSG_OUTBOUND_FREE_TAIL 0x010014 /* EMB gets MFA + increment4 */ -/* Put Free Frames */ -#define MSG_OUTBOUND_FREE_HEAD 0x010010 /* DRV puts MFA + increment4 */ -#define MSG_INBOUND_FREE_HEAD 0x010000 /* EMB puts MFA + increment4 */ - -/* firmware addresses of the message fifos */ -#define MSG_BOUND_STACK_SIZE 0x004000 /* size of each following stack */ -/* posted messages */ -#define MSG_OUTBOUND_POST_STACK 0x108000 /* stack of messages to the DRV */ -#define MSG_INBOUND_POST_STACK 0x104000 /* stack of messages to the EMB */ -/* available empty messages */ -#define MSG_OUTBOUND_FREE_STACK 0x10C000 /* stack of free enveloped for EMB */ -#define MSG_INBOUND_FREE_STACK 0x100000 /* stack of free enveloped for DRV */ - - -/* defines for mailbox message frames */ -#define MSG_FRAME_OFFSET 0x64 -#define MSG_FRAME_SIZE 0x6400 -#define MSG_FRAME_NUMBER 32 -#define MSG_FROM_AGENT_ITMF_OFFSET (MSG_FRAME_OFFSET + (MSG_FRAME_SIZE * MSG_FRAME_NUMBER)) -#define MSG_TO_AGENT_ITMF_OFFSET (MSG_FROM_AGENT_ITMF_OFFSET + MSG_FRAME_SIZE) -#define MSG_HOST_RSC_PROTECTION (MSG_TO_AGENT_ITMF_OFFSET + MSG_FRAME_SIZE) -#define MSG_AGENT_RSC_PROTECTION (MSG_HOST_RSC_PROTECTION + 4) - - -/* - * -----------BAR 1 -------------------------------------------------------------------------------------------------------- - */ - -/* interrupt addresses and constants */ -#define MIXART_PCI_OMIMR_OFFSET 0x34 /* outbound message interrupt mask register */ -#define MIXART_PCI_OMISR_OFFSET 0x30 /* outbound message interrupt status register */ -#define MIXART_PCI_ODBR_OFFSET 0x60 /* outbound doorbell register */ - -#define MIXART_BA1_BRUTAL_RESET_OFFSET 0x68 /* write 1 in LSBit to reset board */ - -#define MIXART_HOST_ALL_INTERRUPT_MASKED 0x02B /* 0000 0010 1011 */ -#define MIXART_ALLOW_OUTBOUND_DOORBELL 0x023 /* 0000 0010 0011 */ -#define MIXART_OIDI 0x008 /* 0000 0000 1000 */ - - -int snd_mixart_setup_firmware(struct mixart_mgr *mgr); - -#endif /* __SOUND_MIXART_HWDEP_H */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c b/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c deleted file mode 100644 index 3ba6174c..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * mixer callbacks - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/time.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/mutex.h> - -#include <sound/core.h> -#include "mixart.h" -#include "mixart_core.h" -#include "mixart_hwdep.h" -#include <sound/control.h> -#include <sound/tlv.h> -#include "mixart_mixer.h" - -static u32 mixart_analog_level[256] = { - 0xc2c00000, /* [000] -96.0 dB */ - 0xc2bf0000, /* [001] -95.5 dB */ - 0xc2be0000, /* [002] -95.0 dB */ - 0xc2bd0000, /* [003] -94.5 dB */ - 0xc2bc0000, /* [004] -94.0 dB */ - 0xc2bb0000, /* [005] -93.5 dB */ - 0xc2ba0000, /* [006] -93.0 dB */ - 0xc2b90000, /* [007] -92.5 dB */ - 0xc2b80000, /* [008] -92.0 dB */ - 0xc2b70000, /* [009] -91.5 dB */ - 0xc2b60000, /* [010] -91.0 dB */ - 0xc2b50000, /* [011] -90.5 dB */ - 0xc2b40000, /* [012] -90.0 dB */ - 0xc2b30000, /* [013] -89.5 dB */ - 0xc2b20000, /* [014] -89.0 dB */ - 0xc2b10000, /* [015] -88.5 dB */ - 0xc2b00000, /* [016] -88.0 dB */ - 0xc2af0000, /* [017] -87.5 dB */ - 0xc2ae0000, /* [018] -87.0 dB */ - 0xc2ad0000, /* [019] -86.5 dB */ - 0xc2ac0000, /* [020] -86.0 dB */ - 0xc2ab0000, /* [021] -85.5 dB */ - 0xc2aa0000, /* [022] -85.0 dB */ - 0xc2a90000, /* [023] -84.5 dB */ - 0xc2a80000, /* [024] -84.0 dB */ - 0xc2a70000, /* [025] -83.5 dB */ - 0xc2a60000, /* [026] -83.0 dB */ - 0xc2a50000, /* [027] -82.5 dB */ - 0xc2a40000, /* [028] -82.0 dB */ - 0xc2a30000, /* [029] -81.5 dB */ - 0xc2a20000, /* [030] -81.0 dB */ - 0xc2a10000, /* [031] -80.5 dB */ - 0xc2a00000, /* [032] -80.0 dB */ - 0xc29f0000, /* [033] -79.5 dB */ - 0xc29e0000, /* [034] -79.0 dB */ - 0xc29d0000, /* [035] -78.5 dB */ - 0xc29c0000, /* [036] -78.0 dB */ - 0xc29b0000, /* [037] -77.5 dB */ - 0xc29a0000, /* [038] -77.0 dB */ - 0xc2990000, /* [039] -76.5 dB */ - 0xc2980000, /* [040] -76.0 dB */ - 0xc2970000, /* [041] -75.5 dB */ - 0xc2960000, /* [042] -75.0 dB */ - 0xc2950000, /* [043] -74.5 dB */ - 0xc2940000, /* [044] -74.0 dB */ - 0xc2930000, /* [045] -73.5 dB */ - 0xc2920000, /* [046] -73.0 dB */ - 0xc2910000, /* [047] -72.5 dB */ - 0xc2900000, /* [048] -72.0 dB */ - 0xc28f0000, /* [049] -71.5 dB */ - 0xc28e0000, /* [050] -71.0 dB */ - 0xc28d0000, /* [051] -70.5 dB */ - 0xc28c0000, /* [052] -70.0 dB */ - 0xc28b0000, /* [053] -69.5 dB */ - 0xc28a0000, /* [054] -69.0 dB */ - 0xc2890000, /* [055] -68.5 dB */ - 0xc2880000, /* [056] -68.0 dB */ - 0xc2870000, /* [057] -67.5 dB */ - 0xc2860000, /* [058] -67.0 dB */ - 0xc2850000, /* [059] -66.5 dB */ - 0xc2840000, /* [060] -66.0 dB */ - 0xc2830000, /* [061] -65.5 dB */ - 0xc2820000, /* [062] -65.0 dB */ - 0xc2810000, /* [063] -64.5 dB */ - 0xc2800000, /* [064] -64.0 dB */ - 0xc27e0000, /* [065] -63.5 dB */ - 0xc27c0000, /* [066] -63.0 dB */ - 0xc27a0000, /* [067] -62.5 dB */ - 0xc2780000, /* [068] -62.0 dB */ - 0xc2760000, /* [069] -61.5 dB */ - 0xc2740000, /* [070] -61.0 dB */ - 0xc2720000, /* [071] -60.5 dB */ - 0xc2700000, /* [072] -60.0 dB */ - 0xc26e0000, /* [073] -59.5 dB */ - 0xc26c0000, /* [074] -59.0 dB */ - 0xc26a0000, /* [075] -58.5 dB */ - 0xc2680000, /* [076] -58.0 dB */ - 0xc2660000, /* [077] -57.5 dB */ - 0xc2640000, /* [078] -57.0 dB */ - 0xc2620000, /* [079] -56.5 dB */ - 0xc2600000, /* [080] -56.0 dB */ - 0xc25e0000, /* [081] -55.5 dB */ - 0xc25c0000, /* [082] -55.0 dB */ - 0xc25a0000, /* [083] -54.5 dB */ - 0xc2580000, /* [084] -54.0 dB */ - 0xc2560000, /* [085] -53.5 dB */ - 0xc2540000, /* [086] -53.0 dB */ - 0xc2520000, /* [087] -52.5 dB */ - 0xc2500000, /* [088] -52.0 dB */ - 0xc24e0000, /* [089] -51.5 dB */ - 0xc24c0000, /* [090] -51.0 dB */ - 0xc24a0000, /* [091] -50.5 dB */ - 0xc2480000, /* [092] -50.0 dB */ - 0xc2460000, /* [093] -49.5 dB */ - 0xc2440000, /* [094] -49.0 dB */ - 0xc2420000, /* [095] -48.5 dB */ - 0xc2400000, /* [096] -48.0 dB */ - 0xc23e0000, /* [097] -47.5 dB */ - 0xc23c0000, /* [098] -47.0 dB */ - 0xc23a0000, /* [099] -46.5 dB */ - 0xc2380000, /* [100] -46.0 dB */ - 0xc2360000, /* [101] -45.5 dB */ - 0xc2340000, /* [102] -45.0 dB */ - 0xc2320000, /* [103] -44.5 dB */ - 0xc2300000, /* [104] -44.0 dB */ - 0xc22e0000, /* [105] -43.5 dB */ - 0xc22c0000, /* [106] -43.0 dB */ - 0xc22a0000, /* [107] -42.5 dB */ - 0xc2280000, /* [108] -42.0 dB */ - 0xc2260000, /* [109] -41.5 dB */ - 0xc2240000, /* [110] -41.0 dB */ - 0xc2220000, /* [111] -40.5 dB */ - 0xc2200000, /* [112] -40.0 dB */ - 0xc21e0000, /* [113] -39.5 dB */ - 0xc21c0000, /* [114] -39.0 dB */ - 0xc21a0000, /* [115] -38.5 dB */ - 0xc2180000, /* [116] -38.0 dB */ - 0xc2160000, /* [117] -37.5 dB */ - 0xc2140000, /* [118] -37.0 dB */ - 0xc2120000, /* [119] -36.5 dB */ - 0xc2100000, /* [120] -36.0 dB */ - 0xc20e0000, /* [121] -35.5 dB */ - 0xc20c0000, /* [122] -35.0 dB */ - 0xc20a0000, /* [123] -34.5 dB */ - 0xc2080000, /* [124] -34.0 dB */ - 0xc2060000, /* [125] -33.5 dB */ - 0xc2040000, /* [126] -33.0 dB */ - 0xc2020000, /* [127] -32.5 dB */ - 0xc2000000, /* [128] -32.0 dB */ - 0xc1fc0000, /* [129] -31.5 dB */ - 0xc1f80000, /* [130] -31.0 dB */ - 0xc1f40000, /* [131] -30.5 dB */ - 0xc1f00000, /* [132] -30.0 dB */ - 0xc1ec0000, /* [133] -29.5 dB */ - 0xc1e80000, /* [134] -29.0 dB */ - 0xc1e40000, /* [135] -28.5 dB */ - 0xc1e00000, /* [136] -28.0 dB */ - 0xc1dc0000, /* [137] -27.5 dB */ - 0xc1d80000, /* [138] -27.0 dB */ - 0xc1d40000, /* [139] -26.5 dB */ - 0xc1d00000, /* [140] -26.0 dB */ - 0xc1cc0000, /* [141] -25.5 dB */ - 0xc1c80000, /* [142] -25.0 dB */ - 0xc1c40000, /* [143] -24.5 dB */ - 0xc1c00000, /* [144] -24.0 dB */ - 0xc1bc0000, /* [145] -23.5 dB */ - 0xc1b80000, /* [146] -23.0 dB */ - 0xc1b40000, /* [147] -22.5 dB */ - 0xc1b00000, /* [148] -22.0 dB */ - 0xc1ac0000, /* [149] -21.5 dB */ - 0xc1a80000, /* [150] -21.0 dB */ - 0xc1a40000, /* [151] -20.5 dB */ - 0xc1a00000, /* [152] -20.0 dB */ - 0xc19c0000, /* [153] -19.5 dB */ - 0xc1980000, /* [154] -19.0 dB */ - 0xc1940000, /* [155] -18.5 dB */ - 0xc1900000, /* [156] -18.0 dB */ - 0xc18c0000, /* [157] -17.5 dB */ - 0xc1880000, /* [158] -17.0 dB */ - 0xc1840000, /* [159] -16.5 dB */ - 0xc1800000, /* [160] -16.0 dB */ - 0xc1780000, /* [161] -15.5 dB */ - 0xc1700000, /* [162] -15.0 dB */ - 0xc1680000, /* [163] -14.5 dB */ - 0xc1600000, /* [164] -14.0 dB */ - 0xc1580000, /* [165] -13.5 dB */ - 0xc1500000, /* [166] -13.0 dB */ - 0xc1480000, /* [167] -12.5 dB */ - 0xc1400000, /* [168] -12.0 dB */ - 0xc1380000, /* [169] -11.5 dB */ - 0xc1300000, /* [170] -11.0 dB */ - 0xc1280000, /* [171] -10.5 dB */ - 0xc1200000, /* [172] -10.0 dB */ - 0xc1180000, /* [173] -9.5 dB */ - 0xc1100000, /* [174] -9.0 dB */ - 0xc1080000, /* [175] -8.5 dB */ - 0xc1000000, /* [176] -8.0 dB */ - 0xc0f00000, /* [177] -7.5 dB */ - 0xc0e00000, /* [178] -7.0 dB */ - 0xc0d00000, /* [179] -6.5 dB */ - 0xc0c00000, /* [180] -6.0 dB */ - 0xc0b00000, /* [181] -5.5 dB */ - 0xc0a00000, /* [182] -5.0 dB */ - 0xc0900000, /* [183] -4.5 dB */ - 0xc0800000, /* [184] -4.0 dB */ - 0xc0600000, /* [185] -3.5 dB */ - 0xc0400000, /* [186] -3.0 dB */ - 0xc0200000, /* [187] -2.5 dB */ - 0xc0000000, /* [188] -2.0 dB */ - 0xbfc00000, /* [189] -1.5 dB */ - 0xbf800000, /* [190] -1.0 dB */ - 0xbf000000, /* [191] -0.5 dB */ - 0x00000000, /* [192] 0.0 dB */ - 0x3f000000, /* [193] 0.5 dB */ - 0x3f800000, /* [194] 1.0 dB */ - 0x3fc00000, /* [195] 1.5 dB */ - 0x40000000, /* [196] 2.0 dB */ - 0x40200000, /* [197] 2.5 dB */ - 0x40400000, /* [198] 3.0 dB */ - 0x40600000, /* [199] 3.5 dB */ - 0x40800000, /* [200] 4.0 dB */ - 0x40900000, /* [201] 4.5 dB */ - 0x40a00000, /* [202] 5.0 dB */ - 0x40b00000, /* [203] 5.5 dB */ - 0x40c00000, /* [204] 6.0 dB */ - 0x40d00000, /* [205] 6.5 dB */ - 0x40e00000, /* [206] 7.0 dB */ - 0x40f00000, /* [207] 7.5 dB */ - 0x41000000, /* [208] 8.0 dB */ - 0x41080000, /* [209] 8.5 dB */ - 0x41100000, /* [210] 9.0 dB */ - 0x41180000, /* [211] 9.5 dB */ - 0x41200000, /* [212] 10.0 dB */ - 0x41280000, /* [213] 10.5 dB */ - 0x41300000, /* [214] 11.0 dB */ - 0x41380000, /* [215] 11.5 dB */ - 0x41400000, /* [216] 12.0 dB */ - 0x41480000, /* [217] 12.5 dB */ - 0x41500000, /* [218] 13.0 dB */ - 0x41580000, /* [219] 13.5 dB */ - 0x41600000, /* [220] 14.0 dB */ - 0x41680000, /* [221] 14.5 dB */ - 0x41700000, /* [222] 15.0 dB */ - 0x41780000, /* [223] 15.5 dB */ - 0x41800000, /* [224] 16.0 dB */ - 0x41840000, /* [225] 16.5 dB */ - 0x41880000, /* [226] 17.0 dB */ - 0x418c0000, /* [227] 17.5 dB */ - 0x41900000, /* [228] 18.0 dB */ - 0x41940000, /* [229] 18.5 dB */ - 0x41980000, /* [230] 19.0 dB */ - 0x419c0000, /* [231] 19.5 dB */ - 0x41a00000, /* [232] 20.0 dB */ - 0x41a40000, /* [233] 20.5 dB */ - 0x41a80000, /* [234] 21.0 dB */ - 0x41ac0000, /* [235] 21.5 dB */ - 0x41b00000, /* [236] 22.0 dB */ - 0x41b40000, /* [237] 22.5 dB */ - 0x41b80000, /* [238] 23.0 dB */ - 0x41bc0000, /* [239] 23.5 dB */ - 0x41c00000, /* [240] 24.0 dB */ - 0x41c40000, /* [241] 24.5 dB */ - 0x41c80000, /* [242] 25.0 dB */ - 0x41cc0000, /* [243] 25.5 dB */ - 0x41d00000, /* [244] 26.0 dB */ - 0x41d40000, /* [245] 26.5 dB */ - 0x41d80000, /* [246] 27.0 dB */ - 0x41dc0000, /* [247] 27.5 dB */ - 0x41e00000, /* [248] 28.0 dB */ - 0x41e40000, /* [249] 28.5 dB */ - 0x41e80000, /* [250] 29.0 dB */ - 0x41ec0000, /* [251] 29.5 dB */ - 0x41f00000, /* [252] 30.0 dB */ - 0x41f40000, /* [253] 30.5 dB */ - 0x41f80000, /* [254] 31.0 dB */ - 0x41fc0000, /* [255] 31.5 dB */ -}; - -#define MIXART_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB + 8.0 dB = -88.0 dB */ -#define MIXART_ANALOG_CAPTURE_LEVEL_MAX 255 /* 31.5 dB + 8.0 dB = 39.5 dB */ -#define MIXART_ANALOG_CAPTURE_ZERO_LEVEL 176 /* -8.0 dB + 8.0 dB = 0.0 dB */ - -#define MIXART_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -96.0 dB + 1.5 dB = -94.5 dB (possible is down to (-114.0+1.5)dB) */ -#define MIXART_ANALOG_PLAYBACK_LEVEL_MAX 192 /* 0.0 dB + 1.5 dB = 1.5 dB */ -#define MIXART_ANALOG_PLAYBACK_ZERO_LEVEL 189 /* -1.5 dB + 1.5 dB = 0.0 dB */ - -static int mixart_update_analog_audio_level(struct snd_mixart* chip, int is_capture) -{ - int i, err; - struct mixart_msg request; - struct mixart_io_level io_level; - struct mixart_return_uid resp; - - memset(&io_level, 0, sizeof(io_level)); - io_level.channel = -1; /* left and right */ - - for(i=0; i<2; i++) { - if(is_capture) { - io_level.level[i].analog_level = mixart_analog_level[chip->analog_capture_volume[i]]; - } else { - if(chip->analog_playback_active[i]) - io_level.level[i].analog_level = mixart_analog_level[chip->analog_playback_volume[i]]; - else - io_level.level[i].analog_level = mixart_analog_level[MIXART_ANALOG_PLAYBACK_LEVEL_MIN]; - } - } - - if(is_capture) request.uid = chip->uid_in_analog_physio; - else request.uid = chip->uid_out_analog_physio; - request.message_id = MSG_PHYSICALIO_SET_LEVEL; - request.data = &io_level; - request.size = sizeof(io_level); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); - if((err<0) || (resp.error_code)) { - snd_printk(KERN_DEBUG "error MSG_PHYSICALIO_SET_LEVEL card(%d) is_capture(%d) error_code(%x)\n", chip->chip_idx, is_capture, resp.error_code); - return -EINVAL; - } - return 0; -} - -/* - * analog level control - */ -static int mixart_analog_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - if(kcontrol->private_value == 0) { /* playback */ - uinfo->value.integer.min = MIXART_ANALOG_PLAYBACK_LEVEL_MIN; /* -96 dB */ - uinfo->value.integer.max = MIXART_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */ - } else { /* capture */ - uinfo->value.integer.min = MIXART_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */ - uinfo->value.integer.max = MIXART_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */ - } - return 0; -} - -static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - if(kcontrol->private_value == 0) { /* playback */ - ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; - ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; - } else { /* capture */ - ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; - ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; - } - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int is_capture, i; - - mutex_lock(&chip->mgr->mixer_mutex); - is_capture = (kcontrol->private_value != 0); - for (i = 0; i < 2; i++) { - int new_volume = ucontrol->value.integer.value[i]; - int *stored_volume = is_capture ? - &chip->analog_capture_volume[i] : - &chip->analog_playback_volume[i]; - if (is_capture) { - if (new_volume < MIXART_ANALOG_CAPTURE_LEVEL_MIN || - new_volume > MIXART_ANALOG_CAPTURE_LEVEL_MAX) - continue; - } else { - if (new_volume < MIXART_ANALOG_PLAYBACK_LEVEL_MIN || - new_volume > MIXART_ANALOG_PLAYBACK_LEVEL_MAX) - continue; - } - if (*stored_volume != new_volume) { - *stored_volume = new_volume; - changed = 1; - } - } - if (changed) - mixart_update_analog_audio_level(chip, is_capture); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); - -static struct snd_kcontrol_new mixart_control_analog_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - .info = mixart_analog_vol_info, - .get = mixart_analog_vol_get, - .put = mixart_analog_vol_put, - .tlv = { .p = db_scale_analog }, -}; - -/* shared */ -#define mixart_sw_info snd_ctl_boolean_stereo_info - -static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; - ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int i, changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->analog_playback_active[i] != - ucontrol->value.integer.value[i]) { - chip->analog_playback_active[i] = - !!ucontrol->value.integer.value[i]; - changed = 1; - } - } - if (changed) /* update playback levels */ - mixart_update_analog_audio_level(chip, 0); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new mixart_control_output_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = mixart_sw_info, /* shared */ - .get = mixart_audio_sw_get, - .put = mixart_audio_sw_put -}; - -static u32 mixart_digital_level[256] = { - 0x00000000, /* [000] = 0.00e+000 = mute if <= -109.5dB */ - 0x366e1c7a, /* [001] = 3.55e-006 = pow(10.0, 0.05 * -109.0dB) */ - 0x367c3860, /* [002] = 3.76e-006 = pow(10.0, 0.05 * -108.5dB) */ - 0x36859525, /* [003] = 3.98e-006 = pow(10.0, 0.05 * -108.0dB) */ - 0x368d7f74, /* [004] = 4.22e-006 = pow(10.0, 0.05 * -107.5dB) */ - 0x3695e1d4, /* [005] = 4.47e-006 = pow(10.0, 0.05 * -107.0dB) */ - 0x369ec362, /* [006] = 4.73e-006 = pow(10.0, 0.05 * -106.5dB) */ - 0x36a82ba8, /* [007] = 5.01e-006 = pow(10.0, 0.05 * -106.0dB) */ - 0x36b222a0, /* [008] = 5.31e-006 = pow(10.0, 0.05 * -105.5dB) */ - 0x36bcb0c1, /* [009] = 5.62e-006 = pow(10.0, 0.05 * -105.0dB) */ - 0x36c7defd, /* [010] = 5.96e-006 = pow(10.0, 0.05 * -104.5dB) */ - 0x36d3b6d3, /* [011] = 6.31e-006 = pow(10.0, 0.05 * -104.0dB) */ - 0x36e0424e, /* [012] = 6.68e-006 = pow(10.0, 0.05 * -103.5dB) */ - 0x36ed8c14, /* [013] = 7.08e-006 = pow(10.0, 0.05 * -103.0dB) */ - 0x36fb9f6c, /* [014] = 7.50e-006 = pow(10.0, 0.05 * -102.5dB) */ - 0x37054423, /* [015] = 7.94e-006 = pow(10.0, 0.05 * -102.0dB) */ - 0x370d29a5, /* [016] = 8.41e-006 = pow(10.0, 0.05 * -101.5dB) */ - 0x371586f0, /* [017] = 8.91e-006 = pow(10.0, 0.05 * -101.0dB) */ - 0x371e631b, /* [018] = 9.44e-006 = pow(10.0, 0.05 * -100.5dB) */ - 0x3727c5ac, /* [019] = 1.00e-005 = pow(10.0, 0.05 * -100.0dB) */ - 0x3731b69a, /* [020] = 1.06e-005 = pow(10.0, 0.05 * -99.5dB) */ - 0x373c3e53, /* [021] = 1.12e-005 = pow(10.0, 0.05 * -99.0dB) */ - 0x374765c8, /* [022] = 1.19e-005 = pow(10.0, 0.05 * -98.5dB) */ - 0x3753366f, /* [023] = 1.26e-005 = pow(10.0, 0.05 * -98.0dB) */ - 0x375fba4f, /* [024] = 1.33e-005 = pow(10.0, 0.05 * -97.5dB) */ - 0x376cfc07, /* [025] = 1.41e-005 = pow(10.0, 0.05 * -97.0dB) */ - 0x377b06d5, /* [026] = 1.50e-005 = pow(10.0, 0.05 * -96.5dB) */ - 0x3784f352, /* [027] = 1.58e-005 = pow(10.0, 0.05 * -96.0dB) */ - 0x378cd40b, /* [028] = 1.68e-005 = pow(10.0, 0.05 * -95.5dB) */ - 0x37952c42, /* [029] = 1.78e-005 = pow(10.0, 0.05 * -95.0dB) */ - 0x379e030e, /* [030] = 1.88e-005 = pow(10.0, 0.05 * -94.5dB) */ - 0x37a75fef, /* [031] = 2.00e-005 = pow(10.0, 0.05 * -94.0dB) */ - 0x37b14ad5, /* [032] = 2.11e-005 = pow(10.0, 0.05 * -93.5dB) */ - 0x37bbcc2c, /* [033] = 2.24e-005 = pow(10.0, 0.05 * -93.0dB) */ - 0x37c6ecdd, /* [034] = 2.37e-005 = pow(10.0, 0.05 * -92.5dB) */ - 0x37d2b65a, /* [035] = 2.51e-005 = pow(10.0, 0.05 * -92.0dB) */ - 0x37df32a3, /* [036] = 2.66e-005 = pow(10.0, 0.05 * -91.5dB) */ - 0x37ec6c50, /* [037] = 2.82e-005 = pow(10.0, 0.05 * -91.0dB) */ - 0x37fa6e9b, /* [038] = 2.99e-005 = pow(10.0, 0.05 * -90.5dB) */ - 0x3804a2b3, /* [039] = 3.16e-005 = pow(10.0, 0.05 * -90.0dB) */ - 0x380c7ea4, /* [040] = 3.35e-005 = pow(10.0, 0.05 * -89.5dB) */ - 0x3814d1cc, /* [041] = 3.55e-005 = pow(10.0, 0.05 * -89.0dB) */ - 0x381da33c, /* [042] = 3.76e-005 = pow(10.0, 0.05 * -88.5dB) */ - 0x3826fa6f, /* [043] = 3.98e-005 = pow(10.0, 0.05 * -88.0dB) */ - 0x3830df51, /* [044] = 4.22e-005 = pow(10.0, 0.05 * -87.5dB) */ - 0x383b5a49, /* [045] = 4.47e-005 = pow(10.0, 0.05 * -87.0dB) */ - 0x3846743b, /* [046] = 4.73e-005 = pow(10.0, 0.05 * -86.5dB) */ - 0x38523692, /* [047] = 5.01e-005 = pow(10.0, 0.05 * -86.0dB) */ - 0x385eab48, /* [048] = 5.31e-005 = pow(10.0, 0.05 * -85.5dB) */ - 0x386bdcf1, /* [049] = 5.62e-005 = pow(10.0, 0.05 * -85.0dB) */ - 0x3879d6bc, /* [050] = 5.96e-005 = pow(10.0, 0.05 * -84.5dB) */ - 0x38845244, /* [051] = 6.31e-005 = pow(10.0, 0.05 * -84.0dB) */ - 0x388c2971, /* [052] = 6.68e-005 = pow(10.0, 0.05 * -83.5dB) */ - 0x3894778d, /* [053] = 7.08e-005 = pow(10.0, 0.05 * -83.0dB) */ - 0x389d43a4, /* [054] = 7.50e-005 = pow(10.0, 0.05 * -82.5dB) */ - 0x38a6952c, /* [055] = 7.94e-005 = pow(10.0, 0.05 * -82.0dB) */ - 0x38b0740f, /* [056] = 8.41e-005 = pow(10.0, 0.05 * -81.5dB) */ - 0x38bae8ac, /* [057] = 8.91e-005 = pow(10.0, 0.05 * -81.0dB) */ - 0x38c5fbe2, /* [058] = 9.44e-005 = pow(10.0, 0.05 * -80.5dB) */ - 0x38d1b717, /* [059] = 1.00e-004 = pow(10.0, 0.05 * -80.0dB) */ - 0x38de2440, /* [060] = 1.06e-004 = pow(10.0, 0.05 * -79.5dB) */ - 0x38eb4de8, /* [061] = 1.12e-004 = pow(10.0, 0.05 * -79.0dB) */ - 0x38f93f3a, /* [062] = 1.19e-004 = pow(10.0, 0.05 * -78.5dB) */ - 0x39040206, /* [063] = 1.26e-004 = pow(10.0, 0.05 * -78.0dB) */ - 0x390bd472, /* [064] = 1.33e-004 = pow(10.0, 0.05 * -77.5dB) */ - 0x39141d84, /* [065] = 1.41e-004 = pow(10.0, 0.05 * -77.0dB) */ - 0x391ce445, /* [066] = 1.50e-004 = pow(10.0, 0.05 * -76.5dB) */ - 0x39263027, /* [067] = 1.58e-004 = pow(10.0, 0.05 * -76.0dB) */ - 0x3930090d, /* [068] = 1.68e-004 = pow(10.0, 0.05 * -75.5dB) */ - 0x393a7753, /* [069] = 1.78e-004 = pow(10.0, 0.05 * -75.0dB) */ - 0x394583d2, /* [070] = 1.88e-004 = pow(10.0, 0.05 * -74.5dB) */ - 0x395137ea, /* [071] = 2.00e-004 = pow(10.0, 0.05 * -74.0dB) */ - 0x395d9d8a, /* [072] = 2.11e-004 = pow(10.0, 0.05 * -73.5dB) */ - 0x396abf37, /* [073] = 2.24e-004 = pow(10.0, 0.05 * -73.0dB) */ - 0x3978a814, /* [074] = 2.37e-004 = pow(10.0, 0.05 * -72.5dB) */ - 0x3983b1f8, /* [075] = 2.51e-004 = pow(10.0, 0.05 * -72.0dB) */ - 0x398b7fa6, /* [076] = 2.66e-004 = pow(10.0, 0.05 * -71.5dB) */ - 0x3993c3b2, /* [077] = 2.82e-004 = pow(10.0, 0.05 * -71.0dB) */ - 0x399c8521, /* [078] = 2.99e-004 = pow(10.0, 0.05 * -70.5dB) */ - 0x39a5cb5f, /* [079] = 3.16e-004 = pow(10.0, 0.05 * -70.0dB) */ - 0x39af9e4d, /* [080] = 3.35e-004 = pow(10.0, 0.05 * -69.5dB) */ - 0x39ba063f, /* [081] = 3.55e-004 = pow(10.0, 0.05 * -69.0dB) */ - 0x39c50c0b, /* [082] = 3.76e-004 = pow(10.0, 0.05 * -68.5dB) */ - 0x39d0b90a, /* [083] = 3.98e-004 = pow(10.0, 0.05 * -68.0dB) */ - 0x39dd1726, /* [084] = 4.22e-004 = pow(10.0, 0.05 * -67.5dB) */ - 0x39ea30db, /* [085] = 4.47e-004 = pow(10.0, 0.05 * -67.0dB) */ - 0x39f81149, /* [086] = 4.73e-004 = pow(10.0, 0.05 * -66.5dB) */ - 0x3a03621b, /* [087] = 5.01e-004 = pow(10.0, 0.05 * -66.0dB) */ - 0x3a0b2b0d, /* [088] = 5.31e-004 = pow(10.0, 0.05 * -65.5dB) */ - 0x3a136a16, /* [089] = 5.62e-004 = pow(10.0, 0.05 * -65.0dB) */ - 0x3a1c2636, /* [090] = 5.96e-004 = pow(10.0, 0.05 * -64.5dB) */ - 0x3a2566d5, /* [091] = 6.31e-004 = pow(10.0, 0.05 * -64.0dB) */ - 0x3a2f33cd, /* [092] = 6.68e-004 = pow(10.0, 0.05 * -63.5dB) */ - 0x3a399570, /* [093] = 7.08e-004 = pow(10.0, 0.05 * -63.0dB) */ - 0x3a44948c, /* [094] = 7.50e-004 = pow(10.0, 0.05 * -62.5dB) */ - 0x3a503a77, /* [095] = 7.94e-004 = pow(10.0, 0.05 * -62.0dB) */ - 0x3a5c9112, /* [096] = 8.41e-004 = pow(10.0, 0.05 * -61.5dB) */ - 0x3a69a2d7, /* [097] = 8.91e-004 = pow(10.0, 0.05 * -61.0dB) */ - 0x3a777ada, /* [098] = 9.44e-004 = pow(10.0, 0.05 * -60.5dB) */ - 0x3a83126f, /* [099] = 1.00e-003 = pow(10.0, 0.05 * -60.0dB) */ - 0x3a8ad6a8, /* [100] = 1.06e-003 = pow(10.0, 0.05 * -59.5dB) */ - 0x3a9310b1, /* [101] = 1.12e-003 = pow(10.0, 0.05 * -59.0dB) */ - 0x3a9bc784, /* [102] = 1.19e-003 = pow(10.0, 0.05 * -58.5dB) */ - 0x3aa50287, /* [103] = 1.26e-003 = pow(10.0, 0.05 * -58.0dB) */ - 0x3aaec98e, /* [104] = 1.33e-003 = pow(10.0, 0.05 * -57.5dB) */ - 0x3ab924e5, /* [105] = 1.41e-003 = pow(10.0, 0.05 * -57.0dB) */ - 0x3ac41d56, /* [106] = 1.50e-003 = pow(10.0, 0.05 * -56.5dB) */ - 0x3acfbc31, /* [107] = 1.58e-003 = pow(10.0, 0.05 * -56.0dB) */ - 0x3adc0b51, /* [108] = 1.68e-003 = pow(10.0, 0.05 * -55.5dB) */ - 0x3ae91528, /* [109] = 1.78e-003 = pow(10.0, 0.05 * -55.0dB) */ - 0x3af6e4c6, /* [110] = 1.88e-003 = pow(10.0, 0.05 * -54.5dB) */ - 0x3b02c2f2, /* [111] = 2.00e-003 = pow(10.0, 0.05 * -54.0dB) */ - 0x3b0a8276, /* [112] = 2.11e-003 = pow(10.0, 0.05 * -53.5dB) */ - 0x3b12b782, /* [113] = 2.24e-003 = pow(10.0, 0.05 * -53.0dB) */ - 0x3b1b690d, /* [114] = 2.37e-003 = pow(10.0, 0.05 * -52.5dB) */ - 0x3b249e76, /* [115] = 2.51e-003 = pow(10.0, 0.05 * -52.0dB) */ - 0x3b2e5f8f, /* [116] = 2.66e-003 = pow(10.0, 0.05 * -51.5dB) */ - 0x3b38b49f, /* [117] = 2.82e-003 = pow(10.0, 0.05 * -51.0dB) */ - 0x3b43a669, /* [118] = 2.99e-003 = pow(10.0, 0.05 * -50.5dB) */ - 0x3b4f3e37, /* [119] = 3.16e-003 = pow(10.0, 0.05 * -50.0dB) */ - 0x3b5b85e0, /* [120] = 3.35e-003 = pow(10.0, 0.05 * -49.5dB) */ - 0x3b6887cf, /* [121] = 3.55e-003 = pow(10.0, 0.05 * -49.0dB) */ - 0x3b764f0e, /* [122] = 3.76e-003 = pow(10.0, 0.05 * -48.5dB) */ - 0x3b8273a6, /* [123] = 3.98e-003 = pow(10.0, 0.05 * -48.0dB) */ - 0x3b8a2e77, /* [124] = 4.22e-003 = pow(10.0, 0.05 * -47.5dB) */ - 0x3b925e89, /* [125] = 4.47e-003 = pow(10.0, 0.05 * -47.0dB) */ - 0x3b9b0ace, /* [126] = 4.73e-003 = pow(10.0, 0.05 * -46.5dB) */ - 0x3ba43aa2, /* [127] = 5.01e-003 = pow(10.0, 0.05 * -46.0dB) */ - 0x3badf5d1, /* [128] = 5.31e-003 = pow(10.0, 0.05 * -45.5dB) */ - 0x3bb8449c, /* [129] = 5.62e-003 = pow(10.0, 0.05 * -45.0dB) */ - 0x3bc32fc3, /* [130] = 5.96e-003 = pow(10.0, 0.05 * -44.5dB) */ - 0x3bcec08a, /* [131] = 6.31e-003 = pow(10.0, 0.05 * -44.0dB) */ - 0x3bdb00c0, /* [132] = 6.68e-003 = pow(10.0, 0.05 * -43.5dB) */ - 0x3be7facc, /* [133] = 7.08e-003 = pow(10.0, 0.05 * -43.0dB) */ - 0x3bf5b9b0, /* [134] = 7.50e-003 = pow(10.0, 0.05 * -42.5dB) */ - 0x3c02248a, /* [135] = 7.94e-003 = pow(10.0, 0.05 * -42.0dB) */ - 0x3c09daac, /* [136] = 8.41e-003 = pow(10.0, 0.05 * -41.5dB) */ - 0x3c1205c6, /* [137] = 8.91e-003 = pow(10.0, 0.05 * -41.0dB) */ - 0x3c1aacc8, /* [138] = 9.44e-003 = pow(10.0, 0.05 * -40.5dB) */ - 0x3c23d70a, /* [139] = 1.00e-002 = pow(10.0, 0.05 * -40.0dB) */ - 0x3c2d8c52, /* [140] = 1.06e-002 = pow(10.0, 0.05 * -39.5dB) */ - 0x3c37d4dd, /* [141] = 1.12e-002 = pow(10.0, 0.05 * -39.0dB) */ - 0x3c42b965, /* [142] = 1.19e-002 = pow(10.0, 0.05 * -38.5dB) */ - 0x3c4e4329, /* [143] = 1.26e-002 = pow(10.0, 0.05 * -38.0dB) */ - 0x3c5a7bf1, /* [144] = 1.33e-002 = pow(10.0, 0.05 * -37.5dB) */ - 0x3c676e1e, /* [145] = 1.41e-002 = pow(10.0, 0.05 * -37.0dB) */ - 0x3c7524ac, /* [146] = 1.50e-002 = pow(10.0, 0.05 * -36.5dB) */ - 0x3c81d59f, /* [147] = 1.58e-002 = pow(10.0, 0.05 * -36.0dB) */ - 0x3c898712, /* [148] = 1.68e-002 = pow(10.0, 0.05 * -35.5dB) */ - 0x3c91ad39, /* [149] = 1.78e-002 = pow(10.0, 0.05 * -35.0dB) */ - 0x3c9a4efc, /* [150] = 1.88e-002 = pow(10.0, 0.05 * -34.5dB) */ - 0x3ca373af, /* [151] = 2.00e-002 = pow(10.0, 0.05 * -34.0dB) */ - 0x3cad2314, /* [152] = 2.11e-002 = pow(10.0, 0.05 * -33.5dB) */ - 0x3cb76563, /* [153] = 2.24e-002 = pow(10.0, 0.05 * -33.0dB) */ - 0x3cc24350, /* [154] = 2.37e-002 = pow(10.0, 0.05 * -32.5dB) */ - 0x3ccdc614, /* [155] = 2.51e-002 = pow(10.0, 0.05 * -32.0dB) */ - 0x3cd9f773, /* [156] = 2.66e-002 = pow(10.0, 0.05 * -31.5dB) */ - 0x3ce6e1c6, /* [157] = 2.82e-002 = pow(10.0, 0.05 * -31.0dB) */ - 0x3cf49003, /* [158] = 2.99e-002 = pow(10.0, 0.05 * -30.5dB) */ - 0x3d0186e2, /* [159] = 3.16e-002 = pow(10.0, 0.05 * -30.0dB) */ - 0x3d0933ac, /* [160] = 3.35e-002 = pow(10.0, 0.05 * -29.5dB) */ - 0x3d1154e1, /* [161] = 3.55e-002 = pow(10.0, 0.05 * -29.0dB) */ - 0x3d19f169, /* [162] = 3.76e-002 = pow(10.0, 0.05 * -28.5dB) */ - 0x3d231090, /* [163] = 3.98e-002 = pow(10.0, 0.05 * -28.0dB) */ - 0x3d2cba15, /* [164] = 4.22e-002 = pow(10.0, 0.05 * -27.5dB) */ - 0x3d36f62b, /* [165] = 4.47e-002 = pow(10.0, 0.05 * -27.0dB) */ - 0x3d41cd81, /* [166] = 4.73e-002 = pow(10.0, 0.05 * -26.5dB) */ - 0x3d4d494a, /* [167] = 5.01e-002 = pow(10.0, 0.05 * -26.0dB) */ - 0x3d597345, /* [168] = 5.31e-002 = pow(10.0, 0.05 * -25.5dB) */ - 0x3d6655c3, /* [169] = 5.62e-002 = pow(10.0, 0.05 * -25.0dB) */ - 0x3d73fbb4, /* [170] = 5.96e-002 = pow(10.0, 0.05 * -24.5dB) */ - 0x3d813856, /* [171] = 6.31e-002 = pow(10.0, 0.05 * -24.0dB) */ - 0x3d88e078, /* [172] = 6.68e-002 = pow(10.0, 0.05 * -23.5dB) */ - 0x3d90fcbf, /* [173] = 7.08e-002 = pow(10.0, 0.05 * -23.0dB) */ - 0x3d99940e, /* [174] = 7.50e-002 = pow(10.0, 0.05 * -22.5dB) */ - 0x3da2adad, /* [175] = 7.94e-002 = pow(10.0, 0.05 * -22.0dB) */ - 0x3dac5156, /* [176] = 8.41e-002 = pow(10.0, 0.05 * -21.5dB) */ - 0x3db68738, /* [177] = 8.91e-002 = pow(10.0, 0.05 * -21.0dB) */ - 0x3dc157fb, /* [178] = 9.44e-002 = pow(10.0, 0.05 * -20.5dB) */ - 0x3dcccccd, /* [179] = 1.00e-001 = pow(10.0, 0.05 * -20.0dB) */ - 0x3dd8ef67, /* [180] = 1.06e-001 = pow(10.0, 0.05 * -19.5dB) */ - 0x3de5ca15, /* [181] = 1.12e-001 = pow(10.0, 0.05 * -19.0dB) */ - 0x3df367bf, /* [182] = 1.19e-001 = pow(10.0, 0.05 * -18.5dB) */ - 0x3e00e9f9, /* [183] = 1.26e-001 = pow(10.0, 0.05 * -18.0dB) */ - 0x3e088d77, /* [184] = 1.33e-001 = pow(10.0, 0.05 * -17.5dB) */ - 0x3e10a4d3, /* [185] = 1.41e-001 = pow(10.0, 0.05 * -17.0dB) */ - 0x3e1936ec, /* [186] = 1.50e-001 = pow(10.0, 0.05 * -16.5dB) */ - 0x3e224b06, /* [187] = 1.58e-001 = pow(10.0, 0.05 * -16.0dB) */ - 0x3e2be8d7, /* [188] = 1.68e-001 = pow(10.0, 0.05 * -15.5dB) */ - 0x3e361887, /* [189] = 1.78e-001 = pow(10.0, 0.05 * -15.0dB) */ - 0x3e40e2bb, /* [190] = 1.88e-001 = pow(10.0, 0.05 * -14.5dB) */ - 0x3e4c509b, /* [191] = 2.00e-001 = pow(10.0, 0.05 * -14.0dB) */ - 0x3e586bd9, /* [192] = 2.11e-001 = pow(10.0, 0.05 * -13.5dB) */ - 0x3e653ebb, /* [193] = 2.24e-001 = pow(10.0, 0.05 * -13.0dB) */ - 0x3e72d424, /* [194] = 2.37e-001 = pow(10.0, 0.05 * -12.5dB) */ - 0x3e809bcc, /* [195] = 2.51e-001 = pow(10.0, 0.05 * -12.0dB) */ - 0x3e883aa8, /* [196] = 2.66e-001 = pow(10.0, 0.05 * -11.5dB) */ - 0x3e904d1c, /* [197] = 2.82e-001 = pow(10.0, 0.05 * -11.0dB) */ - 0x3e98da02, /* [198] = 2.99e-001 = pow(10.0, 0.05 * -10.5dB) */ - 0x3ea1e89b, /* [199] = 3.16e-001 = pow(10.0, 0.05 * -10.0dB) */ - 0x3eab8097, /* [200] = 3.35e-001 = pow(10.0, 0.05 * -9.5dB) */ - 0x3eb5aa1a, /* [201] = 3.55e-001 = pow(10.0, 0.05 * -9.0dB) */ - 0x3ec06dc3, /* [202] = 3.76e-001 = pow(10.0, 0.05 * -8.5dB) */ - 0x3ecbd4b4, /* [203] = 3.98e-001 = pow(10.0, 0.05 * -8.0dB) */ - 0x3ed7e89b, /* [204] = 4.22e-001 = pow(10.0, 0.05 * -7.5dB) */ - 0x3ee4b3b6, /* [205] = 4.47e-001 = pow(10.0, 0.05 * -7.0dB) */ - 0x3ef240e2, /* [206] = 4.73e-001 = pow(10.0, 0.05 * -6.5dB) */ - 0x3f004dce, /* [207] = 5.01e-001 = pow(10.0, 0.05 * -6.0dB) */ - 0x3f07e80b, /* [208] = 5.31e-001 = pow(10.0, 0.05 * -5.5dB) */ - 0x3f0ff59a, /* [209] = 5.62e-001 = pow(10.0, 0.05 * -5.0dB) */ - 0x3f187d50, /* [210] = 5.96e-001 = pow(10.0, 0.05 * -4.5dB) */ - 0x3f21866c, /* [211] = 6.31e-001 = pow(10.0, 0.05 * -4.0dB) */ - 0x3f2b1896, /* [212] = 6.68e-001 = pow(10.0, 0.05 * -3.5dB) */ - 0x3f353bef, /* [213] = 7.08e-001 = pow(10.0, 0.05 * -3.0dB) */ - 0x3f3ff911, /* [214] = 7.50e-001 = pow(10.0, 0.05 * -2.5dB) */ - 0x3f4b5918, /* [215] = 7.94e-001 = pow(10.0, 0.05 * -2.0dB) */ - 0x3f5765ac, /* [216] = 8.41e-001 = pow(10.0, 0.05 * -1.5dB) */ - 0x3f642905, /* [217] = 8.91e-001 = pow(10.0, 0.05 * -1.0dB) */ - 0x3f71adf9, /* [218] = 9.44e-001 = pow(10.0, 0.05 * -0.5dB) */ - 0x3f800000, /* [219] = 1.00e+000 = pow(10.0, 0.05 * 0.0dB) */ - 0x3f8795a0, /* [220] = 1.06e+000 = pow(10.0, 0.05 * 0.5dB) */ - 0x3f8f9e4d, /* [221] = 1.12e+000 = pow(10.0, 0.05 * 1.0dB) */ - 0x3f9820d7, /* [222] = 1.19e+000 = pow(10.0, 0.05 * 1.5dB) */ - 0x3fa12478, /* [223] = 1.26e+000 = pow(10.0, 0.05 * 2.0dB) */ - 0x3faab0d5, /* [224] = 1.33e+000 = pow(10.0, 0.05 * 2.5dB) */ - 0x3fb4ce08, /* [225] = 1.41e+000 = pow(10.0, 0.05 * 3.0dB) */ - 0x3fbf84a6, /* [226] = 1.50e+000 = pow(10.0, 0.05 * 3.5dB) */ - 0x3fcaddc8, /* [227] = 1.58e+000 = pow(10.0, 0.05 * 4.0dB) */ - 0x3fd6e30d, /* [228] = 1.68e+000 = pow(10.0, 0.05 * 4.5dB) */ - 0x3fe39ea9, /* [229] = 1.78e+000 = pow(10.0, 0.05 * 5.0dB) */ - 0x3ff11b6a, /* [230] = 1.88e+000 = pow(10.0, 0.05 * 5.5dB) */ - 0x3fff64c1, /* [231] = 2.00e+000 = pow(10.0, 0.05 * 6.0dB) */ - 0x40074368, /* [232] = 2.11e+000 = pow(10.0, 0.05 * 6.5dB) */ - 0x400f4735, /* [233] = 2.24e+000 = pow(10.0, 0.05 * 7.0dB) */ - 0x4017c496, /* [234] = 2.37e+000 = pow(10.0, 0.05 * 7.5dB) */ - 0x4020c2bf, /* [235] = 2.51e+000 = pow(10.0, 0.05 * 8.0dB) */ - 0x402a4952, /* [236] = 2.66e+000 = pow(10.0, 0.05 * 8.5dB) */ - 0x40346063, /* [237] = 2.82e+000 = pow(10.0, 0.05 * 9.0dB) */ - 0x403f1082, /* [238] = 2.99e+000 = pow(10.0, 0.05 * 9.5dB) */ - 0x404a62c2, /* [239] = 3.16e+000 = pow(10.0, 0.05 * 10.0dB) */ - 0x405660bd, /* [240] = 3.35e+000 = pow(10.0, 0.05 * 10.5dB) */ - 0x406314a0, /* [241] = 3.55e+000 = pow(10.0, 0.05 * 11.0dB) */ - 0x40708933, /* [242] = 3.76e+000 = pow(10.0, 0.05 * 11.5dB) */ - 0x407ec9e1, /* [243] = 3.98e+000 = pow(10.0, 0.05 * 12.0dB) */ - 0x4086f161, /* [244] = 4.22e+000 = pow(10.0, 0.05 * 12.5dB) */ - 0x408ef052, /* [245] = 4.47e+000 = pow(10.0, 0.05 * 13.0dB) */ - 0x4097688d, /* [246] = 4.73e+000 = pow(10.0, 0.05 * 13.5dB) */ - 0x40a06142, /* [247] = 5.01e+000 = pow(10.0, 0.05 * 14.0dB) */ - 0x40a9e20e, /* [248] = 5.31e+000 = pow(10.0, 0.05 * 14.5dB) */ - 0x40b3f300, /* [249] = 5.62e+000 = pow(10.0, 0.05 * 15.0dB) */ - 0x40be9ca5, /* [250] = 5.96e+000 = pow(10.0, 0.05 * 15.5dB) */ - 0x40c9e807, /* [251] = 6.31e+000 = pow(10.0, 0.05 * 16.0dB) */ - 0x40d5debc, /* [252] = 6.68e+000 = pow(10.0, 0.05 * 16.5dB) */ - 0x40e28aeb, /* [253] = 7.08e+000 = pow(10.0, 0.05 * 17.0dB) */ - 0x40eff755, /* [254] = 7.50e+000 = pow(10.0, 0.05 * 17.5dB) */ - 0x40fe2f5e, /* [255] = 7.94e+000 = pow(10.0, 0.05 * 18.0dB) */ -}; - -#define MIXART_DIGITAL_LEVEL_MIN 0 /* -109.5 dB */ -#define MIXART_DIGITAL_LEVEL_MAX 255 /* 18.0 dB */ -#define MIXART_DIGITAL_ZERO_LEVEL 219 /* 0.0 dB */ - - -int mixart_update_playback_stream_level(struct snd_mixart* chip, int is_aes, int idx) -{ - int err, i; - int volume[2]; - struct mixart_msg request; - struct mixart_set_out_stream_level_req set_level; - u32 status; - struct mixart_pipe *pipe; - - memset(&set_level, 0, sizeof(set_level)); - set_level.nb_of_stream = 1; - set_level.stream_level.desc.stream_idx = idx; - - if(is_aes) { - pipe = &chip->pipe_out_dig; /* AES playback */ - idx += MIXART_PLAYBACK_STREAMS; - } else { - pipe = &chip->pipe_out_ana; /* analog playback */ - } - - /* only when pipe exists ! */ - if(pipe->status == PIPE_UNDEFINED) - return 0; - - set_level.stream_level.desc.uid_pipe = pipe->group_uid; - - for(i=0; i<2; i++) { - if(chip->digital_playback_active[idx][i]) - volume[i] = chip->digital_playback_volume[idx][i]; - else - volume[i] = MIXART_DIGITAL_LEVEL_MIN; - } - - set_level.stream_level.out_level.valid_mask1 = MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO1 | MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO2; - set_level.stream_level.out_level.left_to_out1_level = mixart_digital_level[volume[0]]; - set_level.stream_level.out_level.right_to_out2_level = mixart_digital_level[volume[1]]; - - request.message_id = MSG_STREAM_SET_OUT_STREAM_LEVEL; - request.uid = (struct mixart_uid){0,0}; - request.data = &set_level; - request.size = sizeof(set_level); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status); - if((err<0) || status) { - snd_printk(KERN_DEBUG "error MSG_STREAM_SET_OUT_STREAM_LEVEL card(%d) status(%x)\n", chip->chip_idx, status); - return -EINVAL; - } - return 0; -} - -int mixart_update_capture_stream_level(struct snd_mixart* chip, int is_aes) -{ - int err, i, idx; - struct mixart_pipe *pipe; - struct mixart_msg request; - struct mixart_set_in_audio_level_req set_level; - u32 status; - - if(is_aes) { - idx = 1; - pipe = &chip->pipe_in_dig; - } else { - idx = 0; - pipe = &chip->pipe_in_ana; - } - - /* only when pipe exists ! */ - if(pipe->status == PIPE_UNDEFINED) - return 0; - - memset(&set_level, 0, sizeof(set_level)); - set_level.audio_count = 2; - set_level.level[0].connector = pipe->uid_left_connector; - set_level.level[1].connector = pipe->uid_right_connector; - - for(i=0; i<2; i++) { - set_level.level[i].valid_mask1 = MIXART_AUDIO_LEVEL_DIGITAL_MASK; - set_level.level[i].digital_level = mixart_digital_level[chip->digital_capture_volume[idx][i]]; - } - - request.message_id = MSG_STREAM_SET_IN_AUDIO_LEVEL; - request.uid = (struct mixart_uid){0,0}; - request.data = &set_level; - request.size = sizeof(set_level); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status); - if((err<0) || status) { - snd_printk(KERN_DEBUG "error MSG_STREAM_SET_IN_AUDIO_LEVEL card(%d) status(%x)\n", chip->chip_idx, status); - return -EINVAL; - } - return 0; -} - - -/* shared */ -static int mixart_digital_vol_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 = MIXART_DIGITAL_LEVEL_MIN; /* -109.5 dB */ - uinfo->value.integer.max = MIXART_DIGITAL_LEVEL_MAX; /* 18.0 dB */ - return 0; -} - -#define MIXART_VOL_REC_MASK 1 -#define MIXART_VOL_AES_MASK 2 - -static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int *stored_volume; - int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; - int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - mutex_lock(&chip->mgr->mixer_mutex); - if(is_capture) { - if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ - else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ - } else { - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - if(is_aes) stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; /* AES playback */ - else stored_volume = chip->digital_playback_volume[idx]; /* analog playback */ - } - ucontrol->value.integer.value[0] = stored_volume[0]; - ucontrol->value.integer.value[1] = stored_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int changed = 0; - int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; - int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - int* stored_volume; - int i; - mutex_lock(&chip->mgr->mixer_mutex); - if (is_capture) { - if (is_aes) /* AES capture */ - stored_volume = chip->digital_capture_volume[1]; - else /* analog capture */ - stored_volume = chip->digital_capture_volume[0]; - } else { - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - if (is_aes) /* AES playback */ - stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; - else /* analog playback */ - stored_volume = chip->digital_playback_volume[idx]; - } - for (i = 0; i < 2; i++) { - int vol = ucontrol->value.integer.value[i]; - if (vol < MIXART_DIGITAL_LEVEL_MIN || - vol > MIXART_DIGITAL_LEVEL_MAX) - continue; - if (stored_volume[i] != vol) { - stored_volume[i] = vol; - changed = 1; - } - } - if (changed) { - if (is_capture) - mixart_update_capture_stream_level(chip, is_aes); - else - mixart_update_playback_stream_level(chip, is_aes, idx); - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); - -static struct snd_kcontrol_new snd_mixart_pcm_vol = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - /* count will be filled later */ - .info = mixart_digital_vol_info, /* shared */ - .get = mixart_pcm_vol_get, - .put = mixart_pcm_vol_put, - .tlv = { .p = db_scale_digital }, -}; - - -static int mixart_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - mutex_lock(&chip->mgr->mixer_mutex); - if(kcontrol->private_value & MIXART_VOL_AES_MASK) /* AES playback */ - idx += MIXART_PLAYBACK_STREAMS; - ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; - ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int i, j; - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - mutex_lock(&chip->mgr->mixer_mutex); - j = idx; - if (is_aes) - j += MIXART_PLAYBACK_STREAMS; - for (i = 0; i < 2; i++) { - if (chip->digital_playback_active[j][i] != - ucontrol->value.integer.value[i]) { - chip->digital_playback_active[j][i] = - !!ucontrol->value.integer.value[i]; - changed = 1; - } - } - if (changed) - mixart_update_playback_stream_level(chip, is_aes, idx); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new mixart_control_pcm_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* name will be filled later */ - .count = MIXART_PLAYBACK_STREAMS, - .info = mixart_sw_info, /* shared */ - .get = mixart_pcm_sw_get, - .put = mixart_pcm_sw_put -}; - -static int mixart_update_monitoring(struct snd_mixart* chip, int channel) -{ - int err; - struct mixart_msg request; - struct mixart_set_out_audio_level audio_level; - u32 resp; - - if(chip->pipe_out_ana.status == PIPE_UNDEFINED) - return -EINVAL; /* no pipe defined */ - - if(!channel) request.uid = chip->pipe_out_ana.uid_left_connector; - else request.uid = chip->pipe_out_ana.uid_right_connector; - request.message_id = MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL; - request.data = &audio_level; - request.size = sizeof(audio_level); - - memset(&audio_level, 0, sizeof(audio_level)); - audio_level.valid_mask1 = MIXART_AUDIO_LEVEL_MONITOR_MASK | MIXART_AUDIO_LEVEL_MUTE_M1_MASK; - audio_level.monitor_level = mixart_digital_level[chip->monitoring_volume[channel!=0]]; - audio_level.monitor_mute1 = !chip->monitoring_active[channel!=0]; - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); - if((err<0) || resp) { - snd_printk(KERN_DEBUG "error MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL card(%d) resp(%x)\n", chip->chip_idx, resp); - return -EINVAL; - } - return 0; -} - -/* - * monitoring level control - */ - -static int mixart_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; - ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int i; - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->monitoring_volume[i] != - ucontrol->value.integer.value[i]) { - chip->monitoring_volume[i] = - !!ucontrol->value.integer.value[i]; - mixart_update_monitoring(chip, i); - changed = 1; - } - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new mixart_control_monitor_vol = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Monitoring Volume", - .info = mixart_digital_vol_info, /* shared */ - .get = mixart_monitor_vol_get, - .put = mixart_monitor_vol_put, - .tlv = { .p = db_scale_digital }, -}; - -/* - * monitoring switch control - */ - -static int mixart_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->monitoring_active[0]; - ucontrol->value.integer.value[1] = chip->monitoring_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int i; - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->monitoring_active[i] != - ucontrol->value.integer.value[i]) { - chip->monitoring_active[i] = - !!ucontrol->value.integer.value[i]; - changed |= (1<<i); /* mask 0x01 ans 0x02 */ - } - } - if (changed) { - /* allocate or release resources for monitoring */ - int allocate = chip->monitoring_active[0] || - chip->monitoring_active[1]; - if (allocate) { - /* allocate the playback pipe for monitoring */ - snd_mixart_add_ref_pipe(chip, MIXART_PCM_ANALOG, 0, 1); - /* allocate the capture pipe for monitoring */ - snd_mixart_add_ref_pipe(chip, MIXART_PCM_ANALOG, 1, 1); - } - if (changed & 0x01) - mixart_update_monitoring(chip, 0); - if (changed & 0x02) - mixart_update_monitoring(chip, 1); - if (!allocate) { - /* release the capture pipe for monitoring */ - snd_mixart_kill_ref_pipe(chip->mgr, - &chip->pipe_in_ana, 1); - /* release the playback pipe for monitoring */ - snd_mixart_kill_ref_pipe(chip->mgr, - &chip->pipe_out_ana, 1); - } - } - - mutex_unlock(&chip->mgr->mixer_mutex); - return (changed != 0); -} - -static struct snd_kcontrol_new mixart_control_monitor_sw = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitoring Switch", - .info = mixart_sw_info, /* shared */ - .get = mixart_monitor_sw_get, - .put = mixart_monitor_sw_put -}; - - -static void mixart_reset_audio_levels(struct snd_mixart *chip) -{ - /* analog volumes can be set even if there is no pipe */ - mixart_update_analog_audio_level(chip, 0); - /* analog levels for capture only on the first two chips */ - if(chip->chip_idx < 2) { - mixart_update_analog_audio_level(chip, 1); - } - return; -} - - -int snd_mixart_create_mixer(struct mixart_mgr *mgr) -{ - struct snd_mixart *chip; - int err, i; - - mutex_init(&mgr->mixer_mutex); /* can be in another place */ - - for(i=0; i<mgr->num_cards; i++) { - struct snd_kcontrol_new temp; - chip = mgr->chip[i]; - - /* analog output level control */ - temp = mixart_control_analog_level; - temp.name = "Master Playback Volume"; - temp.private_value = 0; /* playback */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - /* output mute controls */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_output_switch, chip))) < 0) - return err; - - /* analog input level control only on first two chips !*/ - if(i<2) { - temp = mixart_control_analog_level; - temp.name = "Master Capture Volume"; - temp.private_value = 1; /* capture */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - temp = snd_mixart_pcm_vol; - temp.name = "PCM Playback Volume"; - temp.count = MIXART_PLAYBACK_STREAMS; - temp.private_value = 0; /* playback analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - temp.name = "PCM Capture Volume"; - temp.count = 1; - temp.private_value = MIXART_VOL_REC_MASK; /* capture analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { - temp.name = "AES Playback Volume"; - temp.count = MIXART_PLAYBACK_STREAMS; - temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - temp.name = "AES Capture Volume"; - temp.count = 0; - temp.private_value = MIXART_VOL_REC_MASK | MIXART_VOL_AES_MASK; /* capture AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - temp = mixart_control_pcm_switch; - temp.name = "PCM Playback Switch"; - temp.private_value = 0; /* playback analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { - temp.name = "AES Playback Switch"; - temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - /* monitoring */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_vol, chip))) < 0) - return err; - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_sw, chip))) < 0) - return err; - - /* init all mixer data and program the master volumes/switches */ - mixart_reset_audio_levels(chip); - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h b/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h deleted file mode 100644 index 04aa24e3..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * include file for mixer - * - * Copyright (c) 2003 by Digigram <alsa@digigram.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SOUND_MIXART_MIXER_H -#define __SOUND_MIXART_MIXER_H - -/* exported */ -int mixart_update_playback_stream_level(struct snd_mixart* chip, int is_aes, int idx); -int mixart_update_capture_stream_level(struct snd_mixart* chip, int is_aes); -int snd_mixart_create_mixer(struct mixart_mgr* mgr); - -#endif /* __SOUND_MIXART_MIXER_H */ |