diff options
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-3-8.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-3-8.patch | 2532 |
1 files changed, 0 insertions, 2532 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-3-8.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-3-8.patch deleted file mode 100644 index aca3e467d..000000000 --- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-3-8.patch +++ /dev/null @@ -1,2532 +0,0 @@ -From 3657fc661cea2b120a7516cb66002fcd3af34e35 Mon Sep 17 00:00:00 2001 -From: R, Dharageswari <dharageswari.r@intel.com> -Date: Thu, 29 Apr 2010 20:23:41 +0530 -Subject: [PATCH] ADR-Post-Beta-0.05.002.03-3/8-Moorestown Audio Drivers: SST interface modules - -This patch adds the SST driver interface module. Interface module is the -one which talks to upper/other layer in the SST Driver -intel_sst_interface.c - implements the MAD driver registration & deregistration -functions. SST driver is also a character driver, so that player/middleware can -communicate with SST driver. All char driver routines like open, close, read, -write and ioctl are implemented here. The ioctl operations are used by -middleware/players to open/close, control and configure astream as well as to -transfer the data. -intel_sst_ioctl.h - exposes the IOCTL definition for players/middleware -as well as the various structure for passing stream parameters - -Signed-off-by: Vinod Koul <vinod.koul@intel.com> - - new file: include/sound/intel_sst_ioctl.h - new file: sound/pci/sst/intel_sst_interface.c -Patch-mainline: 2.6.35? ---- - include/sound/intel_sst_ioctl.h | 390 +++++++ - sound/pci/sst/intel_sst_interface.c | 2099 +++++++++++++++++++++++++++++++++++ - 2 files changed, 2489 insertions(+), 0 deletions(-) - create mode 100644 include/sound/intel_sst_ioctl.h - create mode 100644 sound/pci/sst/intel_sst_interface.c - -diff --git a/include/sound/intel_sst_ioctl.h b/include/sound/intel_sst_ioctl.h -new file mode 100644 -index 0000000..442b388 ---- /dev/null -+++ b/include/sound/intel_sst_ioctl.h -@@ -0,0 +1,390 @@ -+#ifndef __INTEL_SST_IOCTL_H__ -+#define __INTEL_SST_IOCTL_H__ -+/* -+ * intel_sst_ipc.h - Intel SST Driver for audio engine -+ * -+ * Copyright (C) 2008-10 Intel Corporation -+ * Authors: Vinod Koul <vinod.koul@intel.com> -+ * Harsha Priya <priya.harsha@intel.com> -+ * Dharageswari R <dharageswari.r@intel.com> -+ * KP Jeeja <jeeja.kp@intel.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; version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -+ * -+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+ * -+ * This file defines all sst ioctls -+ */ -+ -+/* codec and post/pre processing related info */ -+ -+enum sst_codec_types { -+/* AUDIO/MUSIC CODEC Type Definitions */ -+ SST_CODEC_TYPE_UNKNOWN = 0, -+ SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ -+ SST_CODEC_TYPE_MP3, -+ SST_CODEC_TYPE_MP24, -+ SST_CODEC_TYPE_AAC, -+ SST_CODEC_TYPE_AACP, -+ SST_CODEC_TYPE_eAACP, -+ SST_CODEC_TYPE_WMA9, -+ SST_CODEC_TYPE_WMA10, -+ SST_CODEC_TYPE_WMA10P, -+ SST_CODEC_TYPE_RA, -+ SST_CODEC_TYPE_DDAC3, -+ SST_CODEC_TYPE_STEREO_TRUE_HD, -+ SST_CODEC_TYPE_STEREO_HD_PLUS, -+ -+ /* VOICE CODEC Type Definitions */ -+ SST_CODEC_TYPE_VOICE_PCM = 0x21, /* Pass through voice codec */ -+ SST_CODEC_SRC = 0x64, -+ SST_CODEC_MIXER = 0x65, -+ SST_CODEC_DOWN_MIXER = 0x66, -+ SST_CODEC_VOLUME_CONTROL = 0x67, -+ SST_CODEC_OEM1 = 0xC8, -+ SST_CODEC_OEM2 = 0xC9, -+}; -+ -+enum snd_sst_stream_ops { -+ STREAM_OPS_PLAYBACK = 0, /* Decode */ -+ STREAM_OPS_CAPTURE, /* Encode */ -+ STREAM_OPS_PLAYBACK_DRM, /* Play Audio/Voice */ -+ STREAM_OPS_PLAYBACK_ALERT, /* Play Audio/Voice */ -+ STREAM_OPS_CAPTURE_VOICE_CALL, /* CSV Voice recording */ -+}; -+ -+enum stream_type { -+ STREAM_TYPE_MUSIC = 1, -+ STREAM_TYPE_VOICE -+}; -+ -+/* Firmware Version info */ -+struct snd_sst_fw_version { -+ __u8 build; /* build number*/ -+ __u8 minor; /* minor number*/ -+ __u8 major; /* major number*/ -+ __u8 type; /* build type */ -+}; -+ -+/* Port info structure */ -+struct snd_sst_port_info { -+ __u16 port_type; -+ __u16 reserved; -+}; -+ -+/* Mixer info structure */ -+struct snd_sst_mix_info { -+ __u16 max_streams; -+ __u16 reserved; -+}; -+ -+/* PCM Parameters */ -+struct snd_pcm_params { -+ __u16 codec; /* codec type */ -+ __u8 num_chan; /* 1=Mono, 2=Stereo */ -+ __u8 pcm_wd_sz; /* 16/24 - bit*/ -+ __u32 brate; /* Bitrate in bits per second */ -+ __u32 sfreq; /* Sampling rate in Hz */ -+// __u16 frame_size; -+// __u16 samples_per_frame; /* Frame size num samples per frame */ -+ __u32 buffer_size; -+ __u32 period_count; /* period elapsed time count, in samples,*/ -+}; -+ -+/* MP3 Music Parameters Message */ -+struct snd_mp3_params { -+ __u16 codec; -+ __u8 num_chan; /* 1=Mono, 2=Stereo */ -+ __u8 pcm_wd_sz; /* 16/24 - bit*/ -+ __u32 brate; /* Use the hard coded value. */ -+ __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ -+ __u8 crc_check; /* crc_check - disable (0) or enable (1) */ -+ __u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB*/ -+ __u16 reserved; /* Unused */ -+}; -+ -+#define AAC_BIT_STREAM_ADTS 0 -+#define AAC_BIT_STREAM_ADIF 1 -+#define AAC_BIT_STREAM_RAW 2 -+ -+/* AAC Music Parameters Message */ -+struct snd_aac_params { -+ __u16 codec; -+ __u8 num_chan; /* 1=Mono, 2=Stereo*/ -+ __u8 pcm_wd_sz; /* 16/24 - bit*/ -+ __u32 brate; -+ __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ -+ __u32 aac_srate; /* Plain AAC decoder operating sample rate */ -+ __u8 mpg_id; /* 0=MPEG-2, 1=MPEG-4 */ -+ __u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ -+ __u8 aac_profile; /* 0=Main Profile, 1=LC profile, 3=SSR profile */ -+ __u8 ext_chl; /* No.of external channels */ -+ __u8 aot; /* Audio object type. 1=Main , 2=LC , 3=SSR, 4=SBR*/ -+ __u8 op_align; /* output alignment 0=16 bit , 1=MSB, 2= LSB align */ -+ __u8 brate_type; /* 0=CBR, 1=VBR */ -+ __u8 crc_check; /* crc check 0= disable, 1=enable */ -+ __s8 bit_stream_format[8]; /* input bit stream format adts/adif/raw */ -+ __u8 jstereo; /* Joint stereo Flag */ -+ __u8 sbr_present; /* 1 = SBR Present, 0 = SBR absent, for RAW */ -+ __u8 downsample; /* 1 = Downsampling ON, 0 = Downsampling OFF */ -+ __u8 num_syntc_elems; /* 1- Mono/stereo, 0 - Dual Mono, 0 - for raw */ -+ __s8 syntc_id[2]; /* 0 for ID_SCE(Dula Mono), -1 for raw */ -+ __s8 syntc_tag[2]; /* raw - -1 and 0 -16 for rest of the streams */ -+ __u8 pce_present; /* Flag. 1- present 0 - not present, for RAW */ -+ __u8 sbr_type; /* sbr_type: 0-plain aac, 1-aac-v1, 2-aac-v2 */ -+ __u8 outchmode; /* 0- mono, 1-stereo, 2-dual mono 3-Parametric stereo */ -+ __u8 ps_present; -+ -+}; -+ -+/* WMA Music Parameters Message */ -+struct snd_wma_params { -+ __u16 codec; -+ __u8 num_chan; /* 1=Mono, 2=Stereo */ -+ __u8 pcm_wd_sz; /* 16/24 - bit*/ -+ __u32 brate; /* Use the hard coded value. */ -+ __u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ -+ __u32 channel_mask; /* Channel Mask */ -+ __u16 format_tag; /* Format Tag */ -+ __u16 block_align; /* packet size */ -+ __u16 wma_encode_opt;/* Encoder option */ -+ __u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ -+ __u8 pcm_src; /* input pcm bit width */ -+}; -+ -+/* Pre processing param structure */ -+struct snd_prp_params { -+ __u32 reserved; /* No pre-processing defined yet */ -+}; -+ -+/* Post processing Capability info structure */ -+struct snd_sst_postproc_info { -+ __u32 src_min; /* Supported SRC Min sampling freq */ -+ __u32 src_max; /* Supported SRC Max sampling freq */ -+ __u8 src; /* 0=Not supported, 1=Supported */ -+ __u8 bass_boost; /* 0=Not Supported, 1=Supported */ -+ __u8 stereo_widening; /* 0=Not Supported, 1=Supported */ -+ __u8 volume_control; /* 0=Not Supported, 1=Supported */ -+ __s16 min_vol; /* Minimum value of Volume in dB */ -+ __s16 max_vol; /* Maximum value of Volume in dB */ -+ __u8 mute_control; /* 0=No Mute, 1=Mute */ -+ __u8 reserved1; -+ __u16 reserved2; -+}; -+ -+/* pre processing Capability info structure */ -+struct snd_sst_prp_info { -+ __s16 min_vol; /* Minimum value of Volume in dB */ -+ __s16 max_vol; /* Maximum value of Volume in dB */ -+ __u8 volume_control; /* 0=Not Supported, 1=Supported */ -+ __u8 reserved1; /* for 32 bit alignment */ -+ __u16 reserved2; /* for 32 bit alignment */ -+} __attribute__ ((packed)); -+ -+/* Firmware capabilities info */ -+struct snd_sst_fw_info { -+ struct snd_sst_fw_version fw_version; /* Firmware version */ -+ __u8 audio_codecs_supported[8]; /* Codecs supported by FW */ -+ __u32 recommend_min_duration; /* Min duration for Lowpower Playback */ -+ __u8 max_pcm_streams_supported; /* Max num of PCM streams supported */ -+ __u8 max_enc_streams_supported; /* Max number of Encoded streams */ -+ __u16 reserved; /* 32 bit alignment*/ -+ struct snd_sst_postproc_info pop_info; /* Post processing capability */ -+ struct snd_sst_prp_info prp_info; /* pre_processing mod cap info */ -+ struct snd_sst_port_info port_info[2]; /* Port info */ -+ struct snd_sst_mix_info mix_info; /* Mixer info */ -+ __u32 min_input_buf; /* minmum i/p buffer for decode */ -+}; -+ -+/* Add the codec parameter structures for new codecs to be supported */ -+#define CODEC_PARAM_STRUCTURES \ -+ struct snd_pcm_params pcm_params; \ -+ struct snd_mp3_params mp3_params; \ -+ struct snd_aac_params aac_params; \ -+ struct snd_wma_params wma_params; -+ -+/* Pre and Post Processing param structures */ -+#define PPP_PARAM_STRUCTURES \ -+ struct snd_prp_params prp_params; -+ -+/* Codec params struture */ -+union snd_sst_codec_params { -+ CODEC_PARAM_STRUCTURES; -+}; -+ -+/* Pre-processing params struture */ -+union snd_sst_ppp_params{ -+ PPP_PARAM_STRUCTURES; -+}; -+ -+struct snd_sst_stream_params { -+ union snd_sst_codec_params uc; -+} __attribute__ ((packed)); -+ -+struct snd_sst_params { -+ __u32 result; -+ __u32 stream_id; -+ __u8 codec; -+ __u8 ops; -+ __u8 stream_type; -+ struct snd_sst_stream_params sparams; -+}; -+ -+/* ioctl related stuff here */ -+struct snd_sst_pmic_config { -+ __u32 sfreq; /* Sampling rate in Hz */ -+ __u16 num_chan; /* Mono =1 or Stereo =2 */ -+ __u16 pcm_wd_sz; /* Number of bits per sample */ -+} __attribute__ ((packed)); -+ -+struct snd_sst_get_stream_params { -+ struct snd_sst_params codec_params; -+ struct snd_sst_pmic_config pcm_params; -+}; -+ -+enum snd_sst_target_type { -+ SND_SST_TARGET_PMIC = 1, -+ SND_SST_TARGET_LPE, -+ SND_SST_TARGET_OTHER, -+}; -+ -+enum snd_sst_device_type { -+ SND_SST_DEVICE_SSP = 1, -+ SND_SST_DEVICE_PCM, -+ SND_SST_DEVICE_OTHER, -+}; -+ -+/*enum snd_sst_device_mode { -+ SND_SST_PCM_MODE_I2S = 0, -+ SND_SST_PCM_MODE_PCM1, -+};*/ -+enum snd_sst_device_mode { -+ -+ SND_SST_DEV_MODE_PCM_MODE1 = 1, /*(1 16-bit word, bit-length frame sync)*/ -+ SND_SST_DEV_MODE_PCM_MODE2, -+ SND_SST_DEV_MODE_PCM_MODE3, -+ SND_SST_DEV_MODE_PCM_MODE4_RIGHT_JUSTIFIED, -+ SND_SST_DEV_MODE_PCM_MODE4_LEFT_JUSTIFIED, -+ SND_SST_DEV_MODE_PCM_MODE4_I2S, /*(I2S mode, 16-bit words)*/ -+}; -+ -+enum snd_sst_port_action { -+ SND_SST_PORT_PREPARE = 1, -+ SND_SST_PORT_ACTIVATE, -+}; -+ -+/* Target selection per device structure */ -+struct snd_sst_slot_info { -+ __u8 mix_enable; /* Mixer enable or disable */ -+ __u8 device_type; -+ __u8 device_instance; /* 0, 1, 2 */ -+ __u8 target_type; -+ __u16 slot[2]; -+ __u8 master; -+ __u8 action; -+ __u16 device_mode; -+ struct snd_sst_pmic_config pcm_params; -+} __attribute__ ((packed)); -+ -+#define SST_MAX_TARGET_DEVICES 3 -+/* Target device list structure */ -+struct snd_sst_target_device { -+ __u32 device_route; -+ struct snd_sst_slot_info devices[SST_MAX_TARGET_DEVICES]; -+} __attribute__ ((packed)); -+ -+struct snd_sst_driver_info { -+ __u32 version; /* Version of the driver */ -+ __u32 active_pcm_streams; -+ __u32 active_enc_streams; -+ __u32 max_pcm_streams; -+ __u32 max_enc_streams; -+ __u32 buf_per_stream; -+}; -+ -+struct snd_sst_vol { -+ __u32 stream_id; -+ __s32 volume; -+ __u32 ramp_duration; -+ __u32 ramp_type; /* Ramp type, default=0 */ -+}; -+ -+struct snd_sst_mute { -+ __u32 stream_id; -+ __u32 mute; -+}; -+ -+enum snd_sst_buff_type { -+ SST_BUF_USER = 1, -+ SST_BUF_MMAP, -+ SST_BUF_RAR, -+}; -+ -+struct snd_sst_mmap_buff_entry { -+ unsigned int offset; -+ unsigned int size; -+}; -+ -+struct snd_sst_mmap_buffs { -+ unsigned int entries; -+ enum snd_sst_buff_type type; -+ struct snd_sst_mmap_buff_entry *buff; -+}; -+ -+struct snd_sst_buff_entry { -+ void *buffer; -+ unsigned int size; -+}; -+ -+struct snd_sst_buffs { -+ unsigned int entries; -+ __u8 type; -+ struct snd_sst_buff_entry *buff_entry; -+}; -+ -+struct snd_sst_dbufs { -+ unsigned long long input_bytes_consumed; -+ unsigned long long output_bytes_produced; -+ struct snd_sst_buffs *ibufs; -+ struct snd_sst_buffs *obufs; -+}; -+ -+/*IOCTL defined here */ -+/*SST MMF IOCTLS only */ -+#define SNDRV_SST_STREAM_SET_PARAMS _IOR('L', 0x00, \ -+ struct snd_sst_stream_params *) -+#define SNDRV_SST_STREAM_GET_PARAMS _IOWR('L', 0x01, \ -+ struct snd_sst_get_stream_params *) -+#define SNDRV_SST_STREAM_GET_TSTAMP _IOWR('L', 0x02, __u64 *) -+#define SNDRV_SST_STREAM_DECODE _IOWR('L', 0x03, struct snd_sst_dbufs *) -+#define SNDRV_SST_STREAM_BYTES_DECODED _IOWR('L', 0x04, __u64 *) -+#define SNDRV_SST_STREAM_START _IO('A', 0x42) -+#define SNDRV_SST_STREAM_DROP _IO('A', 0x43) -+#define SNDRV_SST_STREAM_DRAIN _IO('A', 0x44) -+#define SNDRV_SST_STREAM_PAUSE _IOW('A', 0x45, int) -+#define SNDRV_SST_STREAM_RESUME _IO('A', 0x47) -+#define SNDRV_SST_MMAP_PLAY _IOW('L', 0x05, struct snd_sst_mmap_buffs *) -+#define SNDRV_SST_MMAP_CAPTURE _IOW('L', 0x06, struct snd_sst_mmap_buffs *) -+/*SST common ioctls */ -+#define SNDRV_SST_DRIVER_INFO _IOR('L', 0x10, struct snd_sst_driver_info *) -+#define SNDRV_SST_SET_VOL _IOW('L', 0x11, struct snd_sst_vol *) -+#define SNDRV_SST_GET_VOL _IOW('L', 0x12, struct snd_sst_vol *) -+#define SNDRV_SST_MUTE _IOW('L', 0x13, struct snd_sst_mute *) -+/*AM Ioctly only */ -+#define SNDRV_SST_FW_INFO _IOR('L', 0x20, struct snd_sst_fw_info *) -+#define SNDRV_SST_SET_TARGET_DEVICE _IOW('L', 0x21, \ -+ struct snd_sst_target_device *) -+ -+#endif /* __INTEL_SST_IOCTL_H__ */ -diff --git a/sound/pci/sst/intel_sst_interface.c b/sound/pci/sst/intel_sst_interface.c -new file mode 100644 -index 0000000..5f84245 ---- /dev/null -+++ b/sound/pci/sst/intel_sst_interface.c -@@ -0,0 +1,2099 @@ -+/* -+ * intel_sst_interface.c - Intel SST Driver for audio engine -+ * -+ * Copyright (C) 2008-10 Intel Corporation -+ * Authors: Vinod Koul <vinod.koul@intel.com> -+ * Harsha Priya <priya.harsha@intel.com> -+ * Dharageswari R <dharageswari.r@intel.com> -+ * KP Jeeja <jeeja.kp@intel.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; version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -+ * -+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+ * This driver exposes the audio engine functionalities to the ALSA -+ * and middleware. -+ * Upper layer interfaces (MAD driver, MMF) to SST driver -+ */ -+ -+#include <linux/cdev.h> -+#include <linux/pci.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/syscalls.h> -+#include <linux/delay.h> -+#include <linux/fs.h> -+#include <linux/file.h> -+#include <linux/fcntl.h> -+#include <linux/uaccess.h> -+#include <linux/interrupt.h> -+#include <linux/list.h> -+#include <linux/slab.h> -+#include <linux/mm.h> -+#include <linux/workqueue.h> -+#include <linux/pci.h> -+#include <linux/firmware.h> -+#include <linux/ioctl.h> -+#include <linux/rar/rar_register.h> -+#include <linux/rar/memrar.h> -+#include <asm/div64.h> -+#include <sound/intel_lpe.h> -+#include <sound/intel_sst_ioctl.h> -+#include "intel_sst_fw_ipc.h" -+#include "intel_sst_common.h" -+ -+#define AM_MODULE 1 -+#define STREAM_MODULE 0 -+ -+/** -+* This function is called when the FW needs to be downloaded to SST DSP engine -+*/ -+static int sst_download_fw(void) -+{ -+ int retval; -+ const struct firmware *fw_sst; -+ -+ printk(KERN_DEBUG "SST DBG:SST Downloading FW now...\n"); -+ retval = request_firmware(&fw_sst, -+ SST_FW_STD_FILENAME, -+ &sst_drv_ctx->pci->dev); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: req fw failed %d \n", retval); -+ return retval; -+ } -+ sst_drv_ctx->alloc_block[0].sst_id = FW_DWNL_ID; -+ retval = sst_load_fw(fw_sst, NULL); -+ if (retval) -+ goto end_restore; -+ -+ sst_drv_ctx->alloc_block[0].ops_block.condition = false; -+ retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[0]); -+ if (retval) -+ printk(KERN_ERR -+ "SST ERR: fw download failed %d \n" , retval); -+end_restore: -+ release_firmware(fw_sst); -+ sst_drv_ctx->alloc_block[0].sst_id = BLOCK_UNINIT; -+ return retval; -+} -+ -+/** -+* intel_sst_open - opens a handle to driver -+* @i_node: inode structure -+* @file_ptr:pointer to file -+* -+* This function is called by OS when a user space component -+* tries to get a driver handle. Only one handle at a time -+* will be allowed -+*/ -+int intel_sst_open(struct inode *i_node, struct file *file_ptr) -+{ -+ dev_t device = i_node->i_rdev; -+ unsigned int retval = 0; -+ -+ if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) { -+ printk(KERN_ERR -+ "SST ERR: Sound card not availble \n "); -+ return -EIO; -+ } -+ -+ if (sst_drv_ctx->sst_state == SST_UN_INIT) { -+ /* FW is not downloaded */ -+ retval = sst_download_fw(); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: FW download failed...abort\n"); -+ return -ENODEV; -+ } -+ } -+ if (device == MKDEV(INTEL_SST_MAJOR, 0)) { -+ /* app open */ -+ mutex_lock(&sst_drv_ctx->stream_cnt_lock); -+ if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) { -+ struct ioctl_pvt_data *data = -+ kzalloc(sizeof(struct ioctl_pvt_data), -+ GFP_KERNEL); -+ if (!data) { -+ printk(KERN_ERR -+ "SST ERR:error rsrvin data mry\n"); -+ mutex_unlock(&sst_drv_ctx->stream_cnt_lock); -+ return -ENOMEM; -+ } -+ -+ -+ sst_drv_ctx->encoded_cnt++; -+ /*sst_drv_ctx->stream_cnt++;*/ -+ mutex_unlock(&sst_drv_ctx->stream_cnt_lock); -+ data->pvt_id = sst_assign_pvt_id(sst_drv_ctx); -+ data->str_id = 0; -+ file_ptr->private_data = (void *)data; -+ printk(KERN_DEBUG "SST DBG:sst id allocated = %d!\n", data->pvt_id); -+ } else -+ retval = -EACCES; -+ } else if (device == MKDEV(INTEL_SST_MAJOR, 1)) { -+ /* audio manager open */ -+ mutex_lock(&sst_drv_ctx->stream_cnt_lock); -+ if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) { -+ sst_drv_ctx->am_cnt++; -+ printk(KERN_DEBUG "SST DBG:AM handle opened...\n"); -+ } else -+ retval = -EACCES; -+ -+ mutex_unlock(&sst_drv_ctx->stream_cnt_lock); -+ } else -+ retval = -EINVAL; -+ return retval; -+} -+ -+void free_stream_context(unsigned int str_id) -+{ -+ struct stream_info *stream; -+ -+ if (!sst_validate_strid(str_id)) { -+ /* str_id is valid, so stream is alloacted */ -+ stream = &sst_drv_ctx->streams[str_id]; -+ if (stream->ops == STREAM_OPS_PLAYBACK || -+ stream->ops == STREAM_OPS_PLAYBACK_DRM) { -+ sst_drv_ctx->pb_streams--; -+ if (sst_drv_ctx->pb_streams == 0 && sst_drv_ctx->cp_streams > 0) -+ sst_drv_ctx->scard_ops->power_down_pmic_pb(); -+ } else if (stream->ops == STREAM_OPS_CAPTURE) { -+ sst_drv_ctx->cp_streams--; -+ if (sst_drv_ctx->cp_streams == 0 && sst_drv_ctx->pb_streams > 0) -+ sst_drv_ctx->scard_ops->power_down_pmic_cp(); -+ } -+#ifdef CONFIG_MSTWN_POWER_MGMT -+ if(stream->codec == SST_CODEC_TYPE_MP3){ -+ sst_drv_ctx->lpaudio_start--; -+ if(!sst_drv_ctx->lpaudio_start) { -+ sst_ospm_send_event(OSPM_EVENT_LPAUDIO_STOP); -+ printk(KERN_DEBUG "SST DBG:Free_stream:lpaudio_start:%d", sst_drv_ctx->lpaudio_start); -+ printk(KERN_DEBUG "SST DBG:Free_stream:Sending OSPM_EVENT_LPAUDIO_STOP...\n"); -+ } -+ }else { -+ sst_drv_ctx->audio_start--; -+ if(!sst_drv_ctx->audio_start) { -+ sst_ospm_send_event(OSPM_EVENT_SUBSYS_STOP_PLAY); -+ printk(KERN_DEBUG "SST DBG:Free_stream:audio_start:%d", sst_drv_ctx->audio_start); -+ printk(KERN_DEBUG "SST DBG:Free_stream:Sending OSPM_EVENT_SUBSYS_STOP_PLAY...\n"); -+ } -+ } -+#endif -+ if(sst_drv_ctx->pb_streams == 0 && -+ sst_drv_ctx->cp_streams == 0) { -+ sst_drv_ctx->scard_ops->power_down_pmic(); -+ } -+ -+ if (sst_free_stream(str_id)) -+ sst_clean_stream(&sst_drv_ctx->streams[str_id]); -+ } -+} -+ -+/** -+* intel_sst_release - releases a handle to driver -+* @i_node: inode structure -+* @file_ptr: pointer to file -+* -+* This function is called by OS when a user space component -+* tries to release a driver handle. -+*/ -+int intel_sst_release(struct inode *i_node, struct file *file_ptr) -+{ -+ dev_t device = i_node->i_rdev; -+ -+ printk(KERN_DEBUG "SST DBG:Release called \n"); -+ if (device == MKDEV(INTEL_SST_MAJOR, 0)) { -+ struct ioctl_pvt_data *data = -+ (struct ioctl_pvt_data *)file_ptr->private_data; -+ -+ /* app close */ -+ printk(KERN_DEBUG "SST DBG:Closing app handle \n"); -+ mutex_lock(&sst_drv_ctx->stream_cnt_lock); -+ sst_drv_ctx->encoded_cnt--; -+ sst_drv_ctx->stream_cnt--; -+ mutex_unlock(&sst_drv_ctx->stream_cnt_lock); -+ free_stream_context(data->str_id); -+ kfree(data); -+ } else if (device == MKDEV(INTEL_SST_MAJOR, 1)) { -+ /* audio manager close */ -+ mutex_lock(&sst_drv_ctx->stream_cnt_lock); -+ sst_drv_ctx->am_cnt--; -+ mutex_unlock(&sst_drv_ctx->stream_cnt_lock); -+ printk(KERN_DEBUG "SST DBG:AM handle closed \n"); -+ } -+ return 0; -+} -+ -+/** -+* intel_sst_mmap - mmaps a kernel buffer to user space for copying data -+* @vma: vm area structure instance -+* @file_ptr: pointer to file -+* -+* This function is called by OS when a user space component -+* tries to get mmap memory from driver -+*/ -+int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma) -+{ -+ int retval, length; -+ struct ioctl_pvt_data *data = -+ (struct ioctl_pvt_data *)file_ptr->private_data; -+ int str_id = data->str_id; -+ void *mem_area; -+ -+ retval = sst_validate_strid(str_id); -+ if (retval) -+ return -EINVAL; -+ -+ length = vma->vm_end - vma->vm_start; -+ printk(KERN_DEBUG "SST DBG:called for stream %d length 0x%x\n", str_id, length); -+ -+ if (length > sst_drv_ctx->mmap_len) -+ return -ENOMEM; -+ if (!sst_drv_ctx->mmap_mem) -+ return -EIO; -+ -+ /* round it up to the page bondary */ -+ /*mem_area = (void *)((((unsigned long)sst_drv_ctx->mmap_mem) -+ + PAGE_SIZE - 1) & PAGE_MASK);*/ -+ mem_area = (void *) PAGE_ALIGN((unsigned int) sst_drv_ctx->mmap_mem); -+ -+ /* map the whole physically contiguous area in one piece */ -+ retval = remap_pfn_range(vma, -+ vma->vm_start, -+ virt_to_phys((void *)mem_area) >> PAGE_SHIFT, -+ length, -+ vma->vm_page_prot); -+ if (retval) { -+ sst_drv_ctx->streams[str_id].mmapped = false; -+ printk(KERN_ERR "SST ERR: mapping failed %d ",retval); -+ } else -+ sst_drv_ctx->streams[str_id].mmapped = true; -+ -+ printk(KERN_DEBUG "SST DBG:mmap ret 0x%x \n", retval); -+ return retval; -+} -+ -+/** -+* intel_sst_mmap_play_capture - sets mmap data buffers to play/capture -+*/ -+static int intel_sst_mmap_play_capture(u32 str_id, -+ struct snd_sst_mmap_buffs *mmap_buf) -+{ -+ struct sst_stream_bufs *bufs; -+ int retval, i; -+ struct stream_info *stream; -+ struct snd_sst_mmap_buff_entry *buf_entry; -+ -+ printk(KERN_DEBUG "SST DBG:called for str_id %d \n", str_id); -+ retval = sst_validate_strid(str_id); -+ if (retval) { -+ printk(KERN_ERR "SST ERR: val +\ -+ failed %d ", retval); -+ return -EINVAL; -+ } -+ BUG_ON(!mmap_buf); -+ -+ stream = &sst_drv_ctx->streams[str_id]; -+ if (stream->mmapped != true) { -+ printk(KERN_ERR "SST ERR: stream not mapped! "); -+ return -EIO; -+ } -+ -+ if (stream->status == STREAM_UN_INIT || -+ stream->status == STREAM_DECODE) { -+ printk(KERN_ERR -+ "SST ERR: BAD REQUEST!, streamstate +\ -+ is %d\n", stream->status); -+ return -EBADRQC; -+ } -+ stream->curr_bytes = 0; -+ stream->cumm_bytes = 0; -+ -+ printk(KERN_DEBUG "SST DBG:new buffers count %d status %d\n", -+ mmap_buf->entries, stream->status); -+ buf_entry = mmap_buf->buff; -+ for (i = 0; i < mmap_buf->entries; i++) { -+ BUG_ON(!buf_entry); -+ bufs = kzalloc(sizeof(*bufs), GFP_KERNEL); -+ if (!bufs) { -+ printk(KERN_ERR -+ "SST ERR: mem allocation failed \n "); -+ return -ENOMEM; -+ } -+ bufs->size = buf_entry->size; -+ bufs->offset = buf_entry->offset; -+ bufs->addr = sst_drv_ctx->mmap_mem; -+ bufs->in_use = false; -+ buf_entry++; -+ /* locking here */ -+ mutex_lock(&stream->lock); -+ list_add_tail(&bufs->node, &stream->bufs); -+ mutex_unlock(&stream->lock); -+ } -+ -+ mutex_lock(&stream->lock); -+ stream->data_blk.condition = false; -+ stream->data_blk.ret_code = 0; -+ if (stream->status == STREAM_INIT && -+ stream->prev != STREAM_UN_INIT && -+ stream->need_draining != true) { -+ stream->prev = stream->status; -+ stream->status = STREAM_RUNNING; -+ if (stream->ops == STREAM_OPS_PLAYBACK) { -+ printk(KERN_DEBUG "SST DBG:play frames...\n"); -+ if (sst_play_frame(str_id) < 0) { -+ printk(KERN_ERR -+ "SST ERR: play frames failed \n"); -+ mutex_unlock(&stream->lock); -+ return -EIO; -+ } -+ } else if (stream->ops == STREAM_OPS_CAPTURE) { -+ printk(KERN_DEBUG "SST DBG:capture frames...\n"); -+ if (sst_capture_frame(str_id) < 0) { -+ printk(KERN_ERR -+ "SST ERR: capture frames failed \n"); -+ mutex_unlock(&stream->lock); -+ return -EIO; -+ } -+ } -+ } -+ mutex_unlock(&stream->lock); -+ /* Block the call for reply */ -+ if (!list_empty(&stream->bufs)) { -+ printk(KERN_DEBUG "SST DBG:ioctl waiting...\n"); -+ stream->data_blk.on = true; -+ retval = sst_wait_interruptible(sst_drv_ctx, -+ &stream->data_blk); -+ } -+ -+ if (retval >= 0) -+ retval = stream->cumm_bytes; -+ printk(KERN_DEBUG "SST DBG:end of play/rec +\ -+ ioctl bytes = %d!!\n", retval); -+ return retval; -+} -+ -+/** -+* intel_sst_play_capture - sets user data buffers to play/capture -+*/ -+static int intel_sst_play_capture(struct stream_info *stream, int str_id) -+{ -+ int retval; -+ -+ stream->data_blk.ret_code = 0; -+ stream->data_blk.on = true; -+ stream->data_blk.condition = false; -+ -+ mutex_lock(&stream->lock); -+ if (stream->status == STREAM_INIT && stream->prev != STREAM_UN_INIT) { -+ /* stream is started */ -+ stream->prev = stream->status; -+ stream->status = STREAM_RUNNING; -+ } -+ -+ if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) { -+ /* stream is not started yet */ -+ printk(KERN_DEBUG "SST DBG:Stream isnt started yet state %d, prev %d \n", -+ stream->status, stream->prev); -+ } else if ((stream->status == STREAM_RUNNING || -+ stream->status == STREAM_PAUSED) && -+ stream->need_draining != true) { -+ /* stream is started */ -+ if (stream->ops == STREAM_OPS_PLAYBACK || -+ stream->ops == STREAM_OPS_PLAYBACK_DRM) { -+ if (sst_play_frame(str_id) < 0) { -+ printk(KERN_ERR -+ "SST ERR: play frames failed \n"); -+ mutex_unlock(&stream->lock); -+ return -EIO; -+ } -+ } else if (stream->ops == STREAM_OPS_CAPTURE) { -+ if (sst_capture_frame(str_id) < 0) { -+ printk(KERN_ERR -+ "SST ERR: capture frames failed \n "); -+ mutex_unlock(&stream->lock); -+ return -EIO; -+ } -+ } -+ } else { -+ printk(KERN_ERR -+ "SST ERR: Streamstate %d invalid,prev %d\n",\ -+ stream->status, stream->prev); -+ mutex_unlock(&stream->lock); -+ return -EIO; -+ } -+ mutex_unlock(&stream->lock); -+ /* Block the call for reply */ -+ printk(KERN_DEBUG "SST DBG:write waiting...\n"); -+ -+ retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk); -+ if (retval) { -+ stream->status = STREAM_INIT; -+ printk(KERN_DEBUG "SST DBG:wait returned error...\n"); -+ } -+ printk(KERN_DEBUG "SST DBG:write returning\n"); -+ return retval; -+} -+ -+/** -+* snd_sst_fill_kernel_list - fills kernel list with buffer addresses for -+* SST DSP driver to process -+*/ -+static int snd_sst_fill_kernel_list(struct stream_info *stream, -+ const struct iovec *iovec, unsigned long nr_segs, -+ struct list_head *copy_to_list) -+{ -+ struct sst_stream_bufs *stream_bufs; -+ unsigned long index, data_not_copied, mmap_len; -+ unsigned char *bufp; -+ unsigned long size, copied_size; -+ int retval = 0, add_to_list = 0; -+ static int sent_offset; -+ static unsigned long sent_index; -+ -+ stream_bufs = kzalloc(sizeof(*stream_bufs), GFP_KERNEL); -+ if (!stream_bufs) { -+ printk(KERN_ERR -+ "SST ERR: memory allocation failed \n "); -+ return -ENOMEM; -+ } -+ stream_bufs->addr = sst_drv_ctx->mmap_mem; -+ if (stream->ops == STREAM_OPS_PLAYBACK_DRM) { -+ for (index = stream->sg_index; index < nr_segs; index++) { -+ __u32 rar_handle; -+ struct sst_stream_bufs *stream_bufs = -+ kzalloc(sizeof(*stream_bufs), GFP_KERNEL); -+ -+ stream->sg_index = index; -+ if (!stream_bufs) { -+ printk(KERN_ERR -+ "SST ERR: mry alocation failed \n"); -+ return -ENOMEM; -+ } -+ retval = copy_from_user((void *) &rar_handle, -+ iovec[index].iov_base, -+ sizeof(__u32)); -+ if (retval != 0) { -+ printk(KERN_ERR -+ "SST ERR: copy from user +\ -+ failed\n"); -+ return -EIO; -+ } -+ stream_bufs->addr = (char *)rar_handle; -+ printk(KERN_DEBUG "SST DBG:rar handle +\ -+ received = 0x%x\n", (__u32)stream_bufs->addr); -+ stream_bufs->in_use = false; -+ stream_bufs->size = iovec[0].iov_len; -+ printk(KERN_DEBUG "size = 0x%x", stream_bufs->size); -+ /* locking here */ -+ mutex_lock(&stream->lock); -+ list_add_tail(&stream_bufs->node, &stream->bufs); -+ mutex_unlock(&stream->lock); -+ } -+ stream->sg_index = index; -+ return retval; -+ } -+ mmap_len = sst_drv_ctx->mmap_len; -+ stream_bufs->addr = sst_drv_ctx->mmap_mem; -+ bufp = stream->cur_ptr; -+ -+ printk(KERN_DEBUG "SST DBG:mmap_len - %lx\n", mmap_len); -+ copied_size = 0; -+ -+ if (!stream->sg_index) -+ sent_index = sent_offset = 0; -+ -+ for (index = stream->sg_index; index < nr_segs; index++) { -+ stream->sg_index = index; -+ printk(KERN_DEBUG "SST DBG:index - %lx, cur_ptr - %p\n", index, stream->cur_ptr); -+ printk(KERN_DEBUG "SST DBG:base - %p, size - 0x%x\n", iovec[index].iov_base, -+ iovec[index].iov_len); -+ printk(KERN_DEBUG "SST DBG:bufp - %p\n", bufp); -+ if (!stream->cur_ptr) -+ bufp = iovec[index].iov_base; -+ -+ size = ((unsigned long)iovec[index].iov_base -+ + iovec[index].iov_len) - (unsigned long) bufp; -+ -+ printk(KERN_DEBUG "SST DBG:size - %lx\n", size); -+ if ((copied_size + size) > mmap_len) -+ size = mmap_len - copied_size; -+ -+ printk(KERN_DEBUG "SST DBG:size - %lx\n", size); -+ -+ if (stream->ops == STREAM_OPS_PLAYBACK) { -+ printk(KERN_DEBUG "SST DBG:Playback stream copying now....\n"); -+ data_not_copied = copy_from_user( -+ (void *)(stream_bufs->addr + copied_size), -+ bufp, size); -+ if (data_not_copied > 0) { -+ /* Clean up the list and return error code */ -+ printk(KERN_ERR -+ "SST ERR: cpyfrmusr not coped -%ld", data_not_copied); -+ retval = -EIO; -+ break; -+ } -+ } else if (stream->ops == STREAM_OPS_CAPTURE) { -+ struct snd_sst_user_cap_list *entry = -+ kzalloc(sizeof(*entry), GFP_KERNEL); -+ -+ if (!entry) { -+ printk(KERN_ERR -+ "SST ERR: mem allocation failed \n"); -+ /* FIXME cleanup prev */ -+ return -ENOMEM; -+ } -+ entry->iov_index = index; -+ entry->iov_offset = (unsigned long) bufp - -+ (unsigned long)iovec[index].iov_base; -+ entry->offset = copied_size; -+ entry->size = size; -+ printk(KERN_DEBUG "SST DBG:ENTRY:ioindx %d,iooff %ld,koff %ld,ksz %ld \n", -+ entry->iov_index, entry->iov_offset, -+ entry->offset, entry->size); -+ list_add_tail(&entry->node, copy_to_list); -+ } -+ -+ printk(KERN_DEBUG "SST DBG:cur_ptr - %lx\n", (unsigned long) stream->cur_ptr); -+ stream->cur_ptr = bufp + size; -+ -+ if (((unsigned long)iovec[index].iov_base -+ + iovec[index].iov_len) < ((unsigned long)iovec[index].iov_base) ) { -+ printk(KERN_DEBUG "SST DBG:Buffer overflows"); -+ return -EINVAL; -+ } -+ -+ if (((unsigned long)iovec[index].iov_base -+ + iovec[index].iov_len) == -+ (unsigned long)stream->cur_ptr) { -+ stream->cur_ptr = NULL; -+ stream->sg_index++; -+ } -+ -+ copied_size += size; -+ printk(KERN_DEBUG "SST DBG:copied_size - %lx\n", copied_size); -+ if ((copied_size >= mmap_len) || -+ (stream->sg_index == nr_segs)) { -+ add_to_list = 1; -+ } -+ -+ if (add_to_list) { -+ stream_bufs->in_use = false; -+ stream_bufs->size = copied_size; -+ /* locking here */ -+ mutex_lock(&stream->lock); -+ list_add_tail(&stream_bufs->node, &stream->bufs); -+ mutex_unlock(&stream->lock); -+ break; -+ } -+ } -+ return retval; -+} -+ -+/** -+* snd_sst_copy_userbuf_capture - This function copies the captured data -+* returned from SST DSP engine to the user buffers -+*/ -+static int snd_sst_copy_userbuf_capture(struct stream_info *stream, -+ const struct iovec *iovec, -+ struct list_head *copy_to_list) -+{ -+ struct snd_sst_user_cap_list *entry, *_entry; -+ struct sst_stream_bufs *kbufs = NULL, *_kbufs; -+ int retval = 0; -+ unsigned long data_not_copied; -+ -+ /* copy sent buffers */ -+ /* FIXME optimze */ -+ printk(KERN_DEBUG "SST DBG:capture stream copying to user now...\n"); -+ list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) { -+ if (kbufs->in_use == true) { -+ /* copy to user */ -+ list_for_each_entry_safe(entry, _entry, -+ copy_to_list, node) { -+ printk(KERN_DEBUG "SST DBG:filling now... \n"); -+ printk(KERN_DEBUG "SST DBG:iindx %d,ioff %ld,koff %ld,ksz %ld \n", -+ entry->iov_index, entry->iov_offset, -+ entry->offset, entry->size); -+ printk(KERN_DEBUG "SST DBG:Copying at %p size %lx\n", -+ iovec[entry->iov_index].iov_base + -+ entry->iov_offset, -+ entry->size); -+ data_not_copied = copy_to_user((void *) -+ iovec[entry->iov_index].iov_base + -+ entry->iov_offset, -+ kbufs->addr + entry->offset, -+ entry->size); -+ if (data_not_copied > 0) { -+ /* Clean up the list and return error */ -+ printk(KERN_ERR -+ "SST ERR: copy to user err -%ld\n ", data_not_copied); -+ retval = -EIO; -+ break; -+ } -+ list_del(&entry->node); -+ kfree(entry); -+ } -+ printk(KERN_DEBUG "SST DBG:coming out of loop\n"); -+ } -+ } -+ printk(KERN_DEBUG "SST DBG:end of cap copy\n"); -+ return retval; -+} -+ -+/* -+ * snd_sst_userbufs_play_cap - constructs the list from user buffers -+ * @iovec: pointer to iovec structure -+ * @nr_segs: number entries in the iovec structure -+ * @str_id: stream id -+ * @stream: pointer to stream_info structure -+ * This function will traverse the user list and copy the data to the kernel -+ * space buffers. -+ */ /* FIXME cleanups in this fn no mem leaks due to link list */ -+static int snd_sst_userbufs_play_cap(const struct iovec *iovec, -+ unsigned long nr_segs, unsigned int str_id, -+ struct stream_info *stream) -+{ -+ int retval; -+ LIST_HEAD(copy_to_list); -+ -+ -+ retval = snd_sst_fill_kernel_list(stream, iovec, nr_segs, -+ ©_to_list); -+ -+ retval = intel_sst_play_capture(stream, str_id); -+ if (retval < 0) -+ return retval; -+ -+ if (stream->ops == STREAM_OPS_CAPTURE) { -+ retval = snd_sst_copy_userbuf_capture(stream, iovec, -+ ©_to_list); -+ } -+ return retval; -+} -+ -+/** -+* intel_sst_read_write - This function is common function across read/write -+* for user buffers called from system calls -+*/ -+static int intel_sst_read_write(unsigned int str_id, char __user *buf, -+ size_t count) -+{ -+ int retval; -+ struct stream_info *stream; -+ struct iovec iovec; -+ unsigned long nr_segs; -+ -+ retval = sst_validate_strid(str_id); -+ if (retval) -+ return -EINVAL; -+ stream = &sst_drv_ctx->streams[str_id]; -+ if (stream->mmapped == true) { -+ printk(KERN_ERR -+ "SST ERR: user write and stream is mapped"); -+ return -EIO; -+ } -+ if (!count) { -+ printk(KERN_ERR -+ "SST ERR: args invalid %d", retval); -+ return -EINVAL; -+ } -+ stream->curr_bytes = 0; -+ stream->cumm_bytes = 0; -+ /* copy user buf details */ -+ printk(KERN_DEBUG "SST DBG:new buffers %p, copy size %d, status %d\n" , -+ buf, (int) count, (int) stream->status); -+ -+ stream->buf_type = SST_BUF_USER_STATIC; -+ iovec.iov_base = (void *)buf; -+ iovec.iov_len = count; -+ nr_segs = 1; -+ -+ do { -+ retval = snd_sst_userbufs_play_cap(&iovec, nr_segs, -+ str_id, stream); -+ -+ if (retval < 0) -+ break; -+ -+ } while (stream->sg_index < nr_segs); -+ -+ stream->sg_index = 0; -+ stream->cur_ptr = NULL; -+ if (retval >= 0) -+ retval = stream->cumm_bytes; -+ printk(KERN_DEBUG "SST DBG:end of play/rec bytes = %d!!\n", retval); -+ return retval; -+} -+ -+/* -+ * intel_sst_write - This function is called when user tries to play out data -+ * @file_ptr: pointer to file -+ * @buf: user buffer to be played out -+ * @count: size of tthe buffer -+ * @offset: offset to start from -+ */ -+int intel_sst_write(struct file *file_ptr, const char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct ioctl_pvt_data *data = -+ (struct ioctl_pvt_data *)file_ptr->private_data; -+ int str_id = data->str_id; -+ struct stream_info *stream = &sst_drv_ctx->streams[str_id]; -+ -+ printk(KERN_DEBUG "SST DBG:called for %d\n", str_id); -+ if (stream->status == STREAM_UN_INIT || -+ stream->status == STREAM_DECODE) { -+ printk(KERN_ERR "SST ERR: BAD REQUEST "); -+ return -EBADRQC; -+ } -+ return intel_sst_read_write(str_id, (char __user *)buf, count); -+} -+ -+/* -+ * intel_sst_aio_write - This function is called when user tries to play out -+ * multiple data buffers -+ * @kiocb: pointer to a structure containing file pointer -+ * @iov: list of user buffer to be played out -+ * @nr_segs: number of entries -+ * @offset: offset to start from -+ */ -+ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov, -+ unsigned long nr_segs, loff_t offset) -+{ -+ int retval; -+ struct ioctl_pvt_data *data = -+ (struct ioctl_pvt_data *)kiocb->ki_filp->private_data; -+ int str_id = data->str_id; -+ struct stream_info *stream; -+ -+ printk(KERN_DEBUG "SST DBG:entry - %ld\n", nr_segs); -+ -+ if (is_sync_kiocb(kiocb) == false) { -+ printk(KERN_ERR -+ "SST ERR: aio_writ frm userspace is not alowed\n"); -+ return -EINVAL; -+ } -+ -+ printk(KERN_DEBUG "SST DBG:called for str_id %d \n", str_id); -+ retval = sst_validate_strid(str_id); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: invalid stream id \n "); -+ return -EINVAL; -+ } -+ stream = &sst_drv_ctx->streams[str_id]; -+ if (stream->mmapped == true) { -+ printk(KERN_ERR -+ "SST ERR: user write & stream is mapped"); -+ return -EIO; -+ } -+ if (stream->status == STREAM_UN_INIT || -+ stream->status == STREAM_DECODE) { -+ printk(KERN_ERR "SST ERR: BAD REQUEST"); -+ return -EBADRQC; -+ } -+ stream->curr_bytes = 0; -+ stream->cumm_bytes = 0; -+ printk(KERN_DEBUG "SST DBG:new segs %ld, offset %d, status %d\n" , -+ nr_segs, (int) offset, (int) stream->status); -+ stream->buf_type = SST_BUF_USER_STATIC; -+ do { -+ retval = snd_sst_userbufs_play_cap(iov, nr_segs, -+ str_id, stream); -+ if (retval < 0) -+ break; -+ -+ } while (stream->sg_index < nr_segs); -+ -+ stream->sg_index = 0; -+ stream->cur_ptr = NULL; -+ if (retval >= 0) -+ retval = stream->cumm_bytes; -+ printk(KERN_DEBUG "SST DBG:end of play/rec bytes = %d!!\n", retval); -+ return retval; -+} -+ -+/* -+ * intel_sst_read - This function is called when user tries to capture data -+ * @file_ptr: pointer to file -+ * @buf: user buffer to be filled with captured data -+ * @count: size of tthe buffer -+ * @offset: offset to start from -+ */ -+int intel_sst_read(struct file *file_ptr, char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct ioctl_pvt_data *data = -+ (struct ioctl_pvt_data *)file_ptr->private_data; -+ int str_id = data->str_id; -+ struct stream_info *stream = &sst_drv_ctx->streams[str_id]; -+ -+ printk(KERN_DEBUG "SST DBG:called for %d\n", str_id); -+ if (stream->status == STREAM_UN_INIT || -+ stream->status == STREAM_DECODE) { -+ printk(KERN_ERR"SST ERR: BAD REQUEST!\n"); -+ return -EBADRQC; -+ } -+ return intel_sst_read_write(str_id, buf, count); -+} -+ -+/* -+ * intel_sst_aio_read - This function is called when user tries to capture out -+ * multiple data buffers -+ * @kiocb: pointer to a structure containing file pointer -+ * @iov: list of user buffer to be filled with captured -+ * @nr_segs: number of entries -+ * @offset: offset to start from -+ */ -+ -+ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov, -+ unsigned long nr_segs, loff_t offset) -+{ -+ int retval; -+ struct ioctl_pvt_data *data = -+ (struct ioctl_pvt_data *)kiocb->ki_filp->private_data; -+ int str_id = data->str_id; -+ struct stream_info *stream; -+ -+ printk(KERN_DEBUG "SST DBG:entry - %ld\n", nr_segs); -+ -+ if (is_sync_kiocb(kiocb) == false) { -+ printk(KERN_DEBUG "SST DBG:aio_read from user space is not allowed\n"); -+ return -EINVAL; -+ } -+ -+ printk(KERN_DEBUG "SST DBG:called for str_id %d \n", str_id); -+ retval = sst_validate_strid(str_id); -+ if (retval) -+ return -EINVAL; -+ stream = &sst_drv_ctx->streams[str_id]; -+ if (stream->mmapped == true) { -+ printk(KERN_ERR -+ "SST ERR: user write stream is mapped!!! "); -+ return -EIO; -+ } -+ if (stream->status == STREAM_UN_INIT || -+ stream->status == STREAM_DECODE) { -+ printk(KERN_ERR "SST ERR: BAD REQUEST!\n "); -+ return -EBADRQC; -+ } -+ stream->curr_bytes = 0; -+ stream->cumm_bytes = 0; -+ -+ printk(KERN_DEBUG "SST DBG:new segs %ld, offset %d, status %d\n" , -+ nr_segs, (int) offset, (int) stream->status); -+ stream->buf_type = SST_BUF_USER_STATIC; -+ do { -+ retval = snd_sst_userbufs_play_cap(iov, nr_segs, -+ str_id, stream); -+ if (retval < 0) -+ break; -+ -+ } while (stream->sg_index < nr_segs); -+ -+ stream->sg_index = 0; -+ stream->cur_ptr = NULL; -+ if (retval >= 0) -+ retval = stream->cumm_bytes; -+ printk(KERN_DEBUG "SST DBG:end of play/rec bytes = %d!!\n", retval); -+ return retval; -+} -+ -+/* -+ * sst_print_stream_params - prints the stream parameters (debug fn) -+ */ -+static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm) -+{ -+ printk(KERN_DEBUG "SST DBG:codec params:result =%d\n", -+ get_prm->codec_params.result); -+ printk(KERN_DEBUG "SST DBG:codec params:stream = %d\n", -+ get_prm->codec_params.stream_id); -+ printk(KERN_DEBUG "SST DBG:codec params:codec = %d\n", -+ get_prm->codec_params.codec); -+ printk(KERN_DEBUG "SST DBG:codec params:ops = %d\n", -+ get_prm->codec_params.ops); -+ printk(KERN_DEBUG "SST DBG:codec params:stream_type= %d\n", -+ get_prm->codec_params.stream_type); -+ printk(KERN_DEBUG "SST DBG:pcmparams:sfreq= %d\n", -+ get_prm->pcm_params.sfreq); -+ printk(KERN_DEBUG "SST DBG:pcmparams:num_chan= %d\n", -+ get_prm->pcm_params.num_chan); -+ printk(KERN_DEBUG "SST DBG:pcmparams:pcm_wd_sz= %d\n", -+ get_prm->pcm_params.pcm_wd_sz); -+ return; -+} -+ -+/* -+ * sst_print_fw_info - prints the firmware information (debug fn) -+ */ -+static void sst_print_fw_info(struct snd_sst_fw_info *fw_info) -+{ -+ printk(KERN_DEBUG "SST DBG:build = %d\n", fw_info->fw_version.build); -+ printk(KERN_DEBUG "SST DBG:minor = %d\n", fw_info->fw_version.minor); -+ printk(KERN_DEBUG "SST DBG:major= %d\n", fw_info->fw_version.major); -+ printk(KERN_DEBUG "SST DBG:max pcm = %d\n", fw_info->max_pcm_streams_supported); -+ printk(KERN_DEBUG "SST DBG:max enc = %d\n", fw_info->max_enc_streams_supported); -+ printk(KERN_DEBUG "SST DBG:min input buf = %d\n", fw_info->min_input_buf); -+ printk(KERN_DEBUG "SST DBG:pop:src_min= %d\n", fw_info->pop_info.src_min); -+ printk(KERN_DEBUG "SST DBG:pop:src_max= %d\n", fw_info->pop_info.src_max); -+ printk(KERN_DEBUG "SST DBG:pop:src= %d\n", fw_info->pop_info.src); -+ printk(KERN_DEBUG "SST DBG:pop:bass_boost= %d\n", fw_info->pop_info.bass_boost); -+ printk(KERN_DEBUG "SST DBG:pop:stereo_widening= %d\n", fw_info->pop_info.stereo_widening); -+ printk(KERN_DEBUG "SST DBG:pop:volume_control= %d\n", fw_info->pop_info.volume_control); -+ printk(KERN_DEBUG "SST DBG:pop:min_vol= %d\n", fw_info->pop_info.min_vol); -+ printk(KERN_DEBUG "SST DBG:pop:max_vol= %d\n", fw_info->pop_info.max_vol); -+ printk(KERN_DEBUG "SST DBG:prp:min_vol= %d\n", fw_info->prp_info.min_vol); -+ printk(KERN_DEBUG "SST DBG:prp:max_vol= %d\n", fw_info->prp_info.max_vol); -+ printk(KERN_DEBUG "SST DBG:prp:volume_control= %d\n", fw_info->prp_info.volume_control); -+ printk(KERN_DEBUG "SST DBG:mix:max streams = %d\n", fw_info->mix_info.max_streams); -+ printk(KERN_DEBUG "SST DBG:port0:port_type = %d\n", fw_info->port_info[0].port_type); -+ printk(KERN_DEBUG "SST DBG:port1:port_type = %d\n", fw_info->port_info[1].port_type); -+ return; -+} -+ -+/* -+ * sst_get_stream_allocated - this function gets a stream allocated with -+ * the given params -+ */ -+static int sst_get_stream_allocated(struct snd_sst_params *str_param, -+ u32 block, u32 pvt_id) -+{ -+ int retval; -+ retval = sst_alloc_stream((char *) &str_param->sparams, str_param->ops, -+ str_param->codec, pvt_id); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: sst_alloc_stream failed %d \n", retval); -+ return retval; -+ } -+ /* Block the call for reply */ -+ retval = sst_wait_timeout(sst_drv_ctx, -+ &sst_drv_ctx->alloc_block[block]); -+ -+ return retval; -+} -+ -+/* -+ * set_port_params - this function sets the port parameters at Sound card end -+ */ -+static void set_port_params(struct snd_sst_params *str_param, -+ enum snd_sst_stream_ops ops) -+{ -+ /*int sfreq = str_param->sparams.uc.pcm_params.sfreq; -+ int word_size = str_param->sparams.uc.pcm_params.pcm_wd_sz; -+ -+ printk(KERN_DEBUG "SST DBG:sampling frequency = %d wd_size = %d \n", sfreq, word_size); -+ -+ if (ops == STREAM_OPS_PLAYBACK || -+ ops == STREAM_OPS_PLAYBACK_DRM) { -+ printk(KERN_DEBUG "SST DBG:Setting playback path and port settings...\n"); -+ sst_drv_ctx->scard_ops.set_pcm_audio_params(sfreq, -+ word_size); -+ } else if (ops == STREAM_OPS_CAPTURE) { -+ printk(KERN_DEBUG "SST DBG:Setting capture path...\n"); -+ sst_drv_ctx->scard_ops->set_pcm_audio_params(sfreq, word_size); -+ }*/ -+ return; -+} -+ -+/* -+ * sst_get_sfreq - this function returns the frequency of the stream -+ */ -+static int sst_get_sfreq(struct snd_sst_params *str_param) -+{ -+ switch (str_param->codec) { -+ case SST_CODEC_TYPE_PCM: -+ return str_param->sparams.uc.pcm_params.sfreq; -+ case SST_CODEC_TYPE_MP3: -+ return str_param->sparams.uc.mp3_params.sfreq; -+ case SST_CODEC_TYPE_AAC: -+ return str_param->sparams.uc.aac_params.sfreq;; -+ case SST_CODEC_TYPE_WMA9: -+ return str_param->sparams.uc.wma_params.sfreq;; -+ default: -+ return 0; -+ } -+} -+ -+/* -+ * sst_stalled - this function checks if the lpe is in stalled state -+ */ -+int sst_stalled(void) -+{ -+ int retry = 1000; -+ int retval = -1; -+ -+ while(retry) { -+ if ( !sst_drv_ctx->lpe_stalled ) -+ return 0; -+ //wait for time and re-check -+ mdelay(1); -+ -+ retry--; -+ } -+ -+ printk(KERN_DEBUG "SST DBG:LPE is in Stalled State\n"); -+ return retval; -+} -+/* -+ * sst_get_stream - this function prepares for stream allocation -+ */ -+static int sst_get_stream(struct snd_sst_params *str_param, u32 pvt_id) -+{ -+ int i, retval; -+ struct stream_info *str_info; -+ -+ /* stream is not allocated, we are allocating */ -+ i = sst_get_block_stream(sst_drv_ctx); -+ printk(KERN_DEBUG "SST DBG:alloc block allocated = %d\n", i); -+ if (i < 0) -+ return -ENOMEM; -+ sst_drv_ctx->alloc_block[i].sst_id = pvt_id; -+ -+ retval = sst_get_stream_allocated(str_param, i, pvt_id); -+ if (retval == -(SST_LIB_ERR_LIB_DNLD_REQUIRED)) { -+ /* codec download is required */ -+ struct snd_sst_alloc_response *response = -+ sst_drv_ctx->alloc_block[i].ops_block.data; -+ printk(KERN_DEBUG "SST DBG:Codec is required.... trying that\n"); -+ retval = sst_load_library(&response->lib_dnld, -+ str_param->ops, pvt_id); -+ kfree(response); -+ -+ if (!retval) { -+ printk(KERN_DEBUG "SST DBG:codec was downloaded sucesfully \n"); -+ printk(KERN_DEBUG "SST DBG:try alloac again\n"); -+ sst_drv_ctx->alloc_block[i].ops_block.condition = false; -+ -+ retval = sst_get_stream_allocated(str_param, i, pvt_id); -+ -+ if (retval <= 0) -+ goto err; -+ set_port_params(str_param, str_param->ops); -+ -+ printk(KERN_DEBUG "SST DBG:Allocation done stream id %d \n", retval); -+ } else { -+ printk(KERN_DEBUG "SST DBG:codec download failed \n"); -+ retval = -EIO; -+ goto err; -+ } -+ } else if (retval <= 0) -+ goto err; -+ else -+ set_port_params(str_param, str_param->ops); -+ -+ /* store sampling freq */ -+ str_info = &sst_drv_ctx->streams[retval]; -+ str_info->sfreq = sst_get_sfreq(str_param); -+ -+ /* power on the analog, if reqd */ -+ if (str_param->ops == STREAM_OPS_PLAYBACK || -+ str_param->ops == STREAM_OPS_PLAYBACK_DRM) { -+ -+ sst_drv_ctx->scard_ops->power_up_pmic_pb( -+ sst_drv_ctx->pmic_port_instance); -+ /*Only if the playback is MP3 - Send a message*/ -+#ifdef CONFIG_MSTWN_POWER_MGMT -+ if(str_info->codec == SST_CODEC_TYPE_MP3) { -+ sst_ospm_send_event(OSPM_EVENT_LPAUDIO_START); -+ sst_drv_ctx->lpaudio_start++; -+ printk(KERN_DEBUG "SST DBG:lpaudio_start:%d", sst_drv_ctx->lpaudio_start); -+ printk(KERN_DEBUG "SST DBG:Sending OSPM_EVENT_LPAUDIO_START...\n"); -+ }else {/*Only if the playback is non - MP3- Send a messageif not sent already*/ -+ if(sst_drv_ctx->audio_start == 0) { -+ sst_ospm_send_event(OSPM_EVENT_SUBSYS_START_PLAY); -+ sst_drv_ctx->audio_start++; -+ printk(KERN_DEBUG "SST DBG:audio_start:%d", sst_drv_ctx->audio_start); -+ printk(KERN_DEBUG "SST DBG:Sending OSPM_EVENT_SUBSYS_START_PLAY...\n"); -+ -+ } -+ else { -+ sst_drv_ctx->audio_start++; -+ } -+ } -+#endif -+ sst_drv_ctx->pb_streams++; -+ } else if (str_param->ops == STREAM_OPS_CAPTURE) { -+ -+ sst_drv_ctx->scard_ops->power_up_pmic_cp( -+ sst_drv_ctx->pmic_port_instance); -+ /*Send a messageif not sent already*/ -+#ifdef CONFIG_MSTWN_POWER_MGMT -+ if(sst_drv_ctx->audio_start == 0) { -+ sst_ospm_send_event(OSPM_EVENT_SUBSYS_START_PLAY); -+ printk(KERN_DEBUG "SST DBG:audio_start:%d", sst_drv_ctx->audio_start); -+ printk(KERN_DEBUG "SST DBG:Sending OSPM_EVENT_SUBSYS_START_PLAY...\n"); -+ sst_drv_ctx->audio_start++; -+ }else { -+ sst_drv_ctx->audio_start++; -+ } -+#endif -+ sst_drv_ctx->cp_streams++; -+ } -+ -+err: -+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; -+ return retval; -+} -+ -+/** -+* intel_sst_ioctl - recieves the device ioctl's -+* @i_node: inode structure -+* @file_ptr: pointer to file -+* @cmd: Ioctl cmd -+* @arg: data -+* -+* This function is called by OS when a user space component -+* sends an Ioctl to SST driver -+*/ -+int intel_sst_ioctl(struct inode *i_node, struct file *file_ptr, -+ unsigned int cmd, unsigned long arg) -+{ -+ int retval = 0; -+ struct ioctl_pvt_data *data = NULL; -+ int str_id = 0, minor = 0; -+ dev_t device = i_node->i_rdev; -+ -+ if (device == MKDEV(INTEL_SST_MAJOR, 0)) { -+ minor = 0; -+ data = (struct ioctl_pvt_data *) -+ file_ptr->private_data; -+ str_id = data->str_id; -+ } else if (device == MKDEV(INTEL_SST_MAJOR, 1)) -+ minor = 1; -+ else -+ return -EINVAL; -+ -+ if (sst_drv_ctx->sst_state != SST_FW_RUNNING) { -+ printk(KERN_ERR -+ "SST ERR: SST Not runng %d\n " , sst_drv_ctx->sst_state); -+ return -EBUSY; -+ } -+ -+ switch (_IOC_NR(cmd)) { -+ case _IOC_NR(SNDRV_SST_STREAM_PAUSE): -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_IOCTL_PAUSE recieved for %d!\n", str_id); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: called for AM handle minor%d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ retval = sst_pause_stream(str_id); -+ break; -+ -+ case _IOC_NR(SNDRV_SST_STREAM_RESUME): -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_IOCTL_RESUME recieved!\n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: caled for AM handle minor %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ retval = sst_resume_stream(str_id); -+ break; -+ -+ case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): { -+ struct snd_sst_params *str_param = (struct snd_sst_params *)arg; -+ -+ printk(KERN_DEBUG "SST DBG:IOCTL_SET_PARAMS recieved!\n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: caled for AM handle minor %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ sst_print_params(str_param); -+ -+ if (!str_id) { -+ retval = sst_get_stream(str_param, data->pvt_id); -+ if (retval > 0) { -+ struct stream_info *str_info; -+ sst_drv_ctx->stream_cnt++; -+ data->str_id = retval; -+ str_info = &sst_drv_ctx->streams[retval]; -+ str_info->src = SST_DRV; -+ retval = copy_to_user(&str_param->stream_id, -+ &retval, sizeof(__u32)); -+ } else { -+ if (retval == -SST_ERR_INVALID_PARAMS) -+ retval = -EINVAL; -+ } -+ } else { -+ printk(KERN_DEBUG "SST DBG:SET_STREAM_PARAMS recieved!\n"); -+ /* allocated set params only */ -+ retval = sst_set_stream_param(str_id, str_param); -+ /* Block the call for reply */ -+ if (!retval) { -+ int sfreq = 0, word_size = 0, num_channel = 0; -+ sfreq = str_param->sparams.uc.pcm_params.sfreq; -+ word_size = str_param->sparams. -+ uc.pcm_params.pcm_wd_sz; -+ num_channel = str_param->sparams.uc.pcm_params.num_chan; -+ if (str_param->ops == STREAM_OPS_CAPTURE) { -+ printk(KERN_DEBUG "SST DBG:SST sampling frequency= %d\n", -+ sfreq); -+ sst_drv_ctx->scard_ops->\ -+ set_pcm_audio_params(sfreq, word_size, num_channel); -+ } -+ } -+ } -+ break; -+ } -+ case _IOC_NR(SNDRV_SST_SET_VOL): { -+ struct snd_sst_vol *set_vol; -+ struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg; -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_SET_VOLUME recieved for %d!\n", -+ rec_vol->stream_id); -+ if (minor == STREAM_MODULE && rec_vol->stream_id == 0) { -+ printk(KERN_DEBUG "SST DBG:invalid operation!\n"); -+ retval = -EPERM; -+ break; -+ } -+ set_vol = kzalloc(sizeof(*set_vol), GFP_ATOMIC); -+ if (!set_vol) { -+ printk(KERN_DEBUG "SST DBG:mem allocation failed\n"); -+ retval = -ENOMEM; -+ break; -+ } -+ retval = copy_from_user(set_vol, rec_vol, sizeof(*set_vol)); -+ if (retval) { -+ printk(KERN_DEBUG "SST DBG:copy failed\n"); -+ retval = -EAGAIN; -+ break; -+ } -+ retval = sst_set_vol(set_vol); -+ kfree(set_vol); -+ break; -+ } -+ case _IOC_NR(SNDRV_SST_GET_VOL): { -+ struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg; -+ struct snd_sst_vol get_vol; -+ printk(KERN_DEBUG "SST DBG:IOCTL_GET_VOLUME recieved for stream = %d!\n", -+ rec_vol->stream_id); -+ if (minor == STREAM_MODULE && rec_vol->stream_id == 0) { -+ printk(KERN_DEBUG "SST DBG:invalid operation!\n"); -+ retval = -EPERM; -+ break; -+ } -+ get_vol.stream_id = rec_vol->stream_id; -+ retval = sst_get_vol(&get_vol); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: Get volume failed = %d\n", retval); -+ retval = -EIO; -+ break; -+ } -+ printk(KERN_DEBUG "SST DBG:id = %d\n, vol = %d, ramp_dur = %d, ramp_type=%d\n", -+ get_vol.stream_id, get_vol.volume, -+ get_vol.ramp_duration, get_vol.ramp_type); -+ retval = copy_to_user((struct snd_sst_vol *)arg, -+ &get_vol, sizeof(get_vol)); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: copy to user failed %d\n", retval); -+ retval = -EIO; -+ break; -+ } -+ /*sst_print_get_vol_info(str_id, &get_vol);*/ -+ break; -+ } -+ -+ case _IOC_NR(SNDRV_SST_MUTE): { -+ struct snd_sst_mute *set_mute; -+ struct snd_sst_vol *rec_mute = (struct snd_sst_vol *)arg; -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_SET_VOLUME recieved for %d!\n", -+ rec_mute->stream_id); -+ if (minor == STREAM_MODULE && rec_mute->stream_id == 0) { -+ printk(KERN_DEBUG "SST DBG:invalid operation!\n"); -+ retval = -EPERM; -+ break; -+ } -+ set_mute = kzalloc(sizeof(*set_mute), GFP_ATOMIC); -+ if (!set_mute) { -+ printk(KERN_DEBUG "SST DBG:mem allocation failed\n"); -+ retval = -ENOMEM; -+ break; -+ } -+ retval = copy_from_user(set_mute, rec_mute, sizeof(*set_mute)); -+ if (retval) { -+ printk(KERN_DEBUG "SST DBG:copy failed\n"); -+ retval = -EAGAIN; -+ break; -+ } -+ retval = sst_set_mute(set_mute); -+ kfree(set_mute); -+ break; -+ } -+ case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): { -+ struct snd_sst_get_stream_params get_params; -+ -+ printk(KERN_DEBUG "SST DBG:IOCTL_GET_PARAMS recieved!\n"); -+ if (minor != 0) { -+ printk(KERN_ERR -+ "SST ERR: called for AM handle minor %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ -+ retval = sst_get_stream_params(str_id, &get_params); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: Get params failed = %d\n", retval); -+ retval = -EIO; -+ break; -+ } -+ retval = copy_to_user((struct snd_sst_get_stream_params *)arg, -+ &get_params, sizeof(get_params)); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: copy to user failed %d\n" , retval); -+ retval = -EIO; -+ break; -+ } -+ sst_print_stream_params(&get_params); -+ break; -+ } -+ -+ case _IOC_NR(SNDRV_SST_MMAP_PLAY): -+ case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: called for AM handle minor %d\n" , minor); -+ retval = -EINVAL; -+ break; -+ } -+ retval = intel_sst_mmap_play_capture(str_id, -+ (struct snd_sst_mmap_buffs *)arg); -+ break; -+ -+ case _IOC_NR(SNDRV_SST_STREAM_DROP): -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_IOCTL_DROP recieved!\n"); -+ if (minor != STREAM_MODULE) { -+ retval = -EINVAL; -+ break; -+ } -+ retval = sst_drop_stream(str_id); -+ break; -+ -+ case _IOC_NR(SNDRV_SST_STREAM_GET_TSTAMP): { -+ unsigned long long *ms = (unsigned long long *)arg; -+ struct snd_sst_tstamp tstamp = {0}; -+ unsigned long long time, freq, mod; -+ -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_STREAM_GET_TSTAMP recieved!\n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: called for AM handle minor %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ memcpy_fromio(&tstamp, -+ ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP) -+ +(str_id * sizeof(tstamp))), -+ sizeof(tstamp)); -+ time = tstamp.samples_rendered; -+ printk(KERN_DEBUG "SST DBG:samples rendered! = 0x%llx\n", time); -+ freq = (unsigned long long) tstamp.sampling_frequency; -+ printk(KERN_DEBUG "SST DBG:freq = %llx\n", freq); -+ time = time * 1000; /* converting it to ms */ -+ mod = do_div(time, freq); -+ printk(KERN_DEBUG "SST DBG:mod = 0x%llx\n", mod); -+ printk(KERN_DEBUG "SST DBG:msec = 0x%llx\n", time); -+ retval = copy_to_user(ms, &time, sizeof(*ms)); -+ if (retval) -+ printk(KERN_ERR -+ "SST ERR: copy failed = %d\n", retval); -+ break; -+ } -+ -+ case _IOC_NR(SNDRV_SST_STREAM_START):{ -+ struct stream_info *stream; -+ -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_STREAM_START recieved!\n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: called for AM handle minor %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ retval = sst_validate_strid(str_id); -+ if (retval) -+ break; -+ stream = &sst_drv_ctx->streams[str_id]; -+ mutex_lock(&stream->lock); -+ if (stream->status == STREAM_INIT && -+ stream->need_draining != true) { -+ printk(KERN_DEBUG "SST DBG:calling play frames...\n"); -+ stream->prev = stream->status; -+ stream->status = STREAM_RUNNING; -+ if (stream->ops == STREAM_OPS_PLAYBACK || -+ stream->ops == STREAM_OPS_PLAYBACK_DRM) { -+ retval = sst_play_frame(str_id); -+ /*sst_ospm_send_event( -+ OSPM_EVENT_SUBSYS_START_PLAY);*/ -+ } else if (stream->ops == STREAM_OPS_CAPTURE) -+ retval = sst_capture_frame(str_id); -+ else { -+ printk(KERN_ERR -+ "SST ERR: Invalid ops 0x%x\n" , stream->ops); -+ retval = -EINVAL; -+ mutex_unlock( -+ &sst_drv_ctx->streams[str_id].lock); -+ break; -+ } -+ if (retval < 0) { -+ printk(KERN_ERR -+ "SST ERR: play/cptur frame fail \n"); -+ stream->status = STREAM_INIT; -+ mutex_unlock( -+ &sst_drv_ctx->streams[str_id].lock); -+ break; -+ } -+ } else { -+ printk(KERN_ERR -+ "SST ERR: Inv strt for stream%d state0x%x\n", \ -+ str_id, stream->status); -+ retval = -EINVAL; -+ } -+ mutex_unlock(&sst_drv_ctx->streams[str_id].lock); -+ break; -+ } -+ -+ case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): { -+ struct snd_sst_target_device *target_device; -+ -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_SET_TARGET_PLAYBACK DEVICE recieved!\n"); -+ target_device = (struct snd_sst_target_device *)arg; -+ BUG_ON(!target_device); -+ if (minor != AM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: called for non AM handle minor %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ retval = sst_target_device_select(target_device); -+ break; -+ } -+ -+ case _IOC_NR(SNDRV_SST_DRIVER_INFO): { -+ struct snd_sst_driver_info *info = -+ (struct snd_sst_driver_info *)arg; -+ -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_DRIVER_INFO recived \n"); -+ info->version = SST_VERSION_NUM; -+ /* hard coding, shud get sumhow later */ -+ info->active_pcm_streams = sst_drv_ctx->stream_cnt - -+ sst_drv_ctx->encoded_cnt; -+ info->active_enc_streams = sst_drv_ctx->encoded_cnt; -+ info->max_pcm_streams = MAX_ACTIVE_STREAM - MAX_ENC_STREAM; -+ info->max_enc_streams = MAX_ENC_STREAM; -+ info->buf_per_stream = sst_drv_ctx->mmap_len; -+ break; -+ } -+ -+ case _IOC_NR(SNDRV_SST_STREAM_DECODE): { -+ struct snd_sst_dbufs *param = -+ (struct snd_sst_dbufs *)arg, dbufs_local; -+ int i; -+ struct snd_sst_buffs ibufs, obufs; -+ struct snd_sst_buff_entry ibuf_temp[param->ibufs->entries], -+ obuf_temp[param->obufs->entries]; -+ -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_STREAM_DECODE recived \n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: called for AM handle minor %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ if (!param) { -+ printk(KERN_ERR "SST ERR: null param passed\n"); -+ retval = -EINVAL; -+ break; -+ } -+ -+ dbufs_local.input_bytes_consumed = param->input_bytes_consumed; -+ dbufs_local.output_bytes_produced = -+ param->output_bytes_produced; -+ dbufs_local.ibufs = &ibufs; -+ dbufs_local.obufs = &obufs; -+ dbufs_local.ibufs->entries = param->ibufs->entries; -+ dbufs_local.ibufs->type = param->ibufs->type; -+ dbufs_local.obufs->entries = param->obufs->entries; -+ dbufs_local.obufs->type = param->obufs->type; -+ -+ dbufs_local.ibufs->buff_entry = ibuf_temp; -+ for (i = 0; i < dbufs_local.ibufs->entries; i++) { -+ ibuf_temp[i].buffer = -+ param->ibufs->buff_entry[i].buffer; -+ ibuf_temp[i].size = -+ param->ibufs->buff_entry[i].size; -+ } -+ dbufs_local.obufs->buff_entry = obuf_temp; -+ for (i = 0; i < dbufs_local.obufs->entries; i++) { -+ obuf_temp[i].buffer = -+ param->obufs->buff_entry[i].buffer; -+ obuf_temp[i].size = -+ param->obufs->buff_entry[i].size; -+ } -+ retval = sst_decode(str_id, &dbufs_local); -+ if (retval) { -+ printk(KERN_ERR"SST ERR: decoding failed \n"); -+ retval = -EAGAIN; -+ } -+ retval = copy_to_user(¶m->input_bytes_consumed, -+ &dbufs_local.input_bytes_consumed, -+ sizeof(unsigned long long)); -+ if (retval) { -+ printk(KERN_ERR"SST ERR: copy to user failed \n"); -+ retval = -EAGAIN; -+ break; -+ } -+ retval = copy_to_user(¶m->output_bytes_produced, -+ &dbufs_local.output_bytes_produced, -+ sizeof(unsigned long long)); -+ if (retval) { -+ printk(KERN_ERR"SST ERR: copy to user failed \n"); -+ retval = -EAGAIN; -+ break; -+ } -+ printk(KERN_DEBUG "SST DBG:input_bytes_consumed=%lld\n", -+ param->input_bytes_consumed); -+ printk(KERN_DEBUG "SST DBG:output_bytes_produced=%lld\n", -+ param->output_bytes_produced); -+ printk(KERN_DEBUG "SST DBG:ibufs->entries=%d\n", param->ibufs->entries); -+ printk(KERN_DEBUG "SST DBG:input_consumed = %lld, output_produced = %lld \n", -+ param->input_bytes_consumed, -+ param->output_bytes_produced); -+ printk(KERN_DEBUG "SST DBG:first ibufs size=%d\n", -+ param->ibufs->buff_entry[0].size); -+ printk(KERN_DEBUG "SST DBG:first ibufs addr=%p\n", -+ param->ibufs->buff_entry[0].buffer); -+ printk(KERN_DEBUG "SST DBG:obufs->entries=%d\n", param->obufs->entries); -+ printk(KERN_DEBUG "SST DBG:first obufs size=%d\n", -+ param->obufs->buff_entry[0].size); -+ printk(KERN_DEBUG "SST DBG:first obufs addr=%p\n", -+ param->obufs->buff_entry[0].buffer); -+ break; -+ } -+ -+ case _IOC_NR(SNDRV_SST_STREAM_DRAIN): -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_STREAM_DRAIN recived \n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: caled for AM handle minr %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ retval = sst_drain_stream(str_id); -+ break; -+ -+ case _IOC_NR(SNDRV_SST_STREAM_BYTES_DECODED): { -+ unsigned long long *bytes = (unsigned long long *)arg; -+ struct snd_sst_tstamp tstamp = {0}; -+ -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_STREAM_BYTES_DECODED recieved!\n"); -+ if (minor != STREAM_MODULE) { -+ printk(KERN_ERR -+ "SST ERR: caled for AM hndle minr %d\n", minor); -+ retval = -EINVAL; -+ break; -+ } -+ memcpy_fromio(&tstamp, -+ ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP) -+ +(str_id * sizeof(tstamp))), -+ sizeof(tstamp)); -+ retval = copy_to_user(bytes, &tstamp.bytes_processed, -+ sizeof(*bytes)); -+ printk(KERN_DEBUG "SST DBG:bytes processed =%lld\n", tstamp.bytes_processed); -+ if (retval) -+ printk(KERN_ERR -+ "SST ERR: copy failed = %d\n", retval); -+ break; -+ } -+ case _IOC_NR(SNDRV_SST_FW_INFO): { -+ struct snd_sst_fw_info *fw_info; -+ -+ printk(KERN_DEBUG "SST DBG:SNDRV_SST_FW_INFO recived \n"); -+ -+ fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC); -+ if (!fw_info) { -+ printk(KERN_ERR "SST ERR: mem alocation fail\n"); -+ retval = -ENOMEM; -+ break; -+ } -+ retval = sst_get_fw_info(fw_info); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: sst_get_fw_info fail = %d\n", retval); -+ kfree(fw_info); -+ break; -+ } -+ retval = copy_to_user((struct snd_sst_dbufs *)arg, -+ fw_info, sizeof(*fw_info)); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: copy to user failed %d\n", retval); -+ kfree(fw_info); -+ retval = -EIO; -+ break; -+ } -+ sst_print_fw_info(fw_info); -+ kfree(fw_info); -+ break; -+ } -+ default: -+ printk(KERN_DEBUG "SST DBG:IOCTL not supported yet !\n"); -+ retval = -ENOTTY; -+ } -+ printk(KERN_DEBUG "SST DBG:...complete ret code = %d\n", retval); -+ -+ return retval; -+} -+ -+/* -+ Intelmid driver interface Routines -+*/ -+ -+void sst_process_mad_ops(struct work_struct *work) -+{ -+ struct mad_ops_wq *mad_ops = -+ container_of(work, struct mad_ops_wq, wq); -+ int retval = 0; -+ struct stream_info *stream; -+ -+ switch (mad_ops->control_op) { -+ case SST_SND_PAUSE: -+ retval = sst_pause_stream(mad_ops->stream_id); -+ break; -+ case SST_SND_RESUME: -+ retval = sst_resume_stream(mad_ops->stream_id); -+ break; -+ case SST_SND_DROP: -+ retval = sst_drop_stream(mad_ops->stream_id); -+ break; -+ case SST_SND_STREAM_PROCESS: -+ printk(KERN_DEBUG "SST DBG:play/capt frames...\n"); -+ stream = &sst_drv_ctx->streams[mad_ops->stream_id]; -+ if (stream->status == STREAM_UN_INIT) -+ return; -+ stream->prev = stream->status; -+ stream->status = STREAM_RUNNING; -+ stream->data_blk.on = false; -+ if (stream->ops == STREAM_OPS_PLAYBACK) -+ retval = sst_play_frame(mad_ops->stream_id); -+ else if (stream->ops == STREAM_OPS_CAPTURE) -+ retval = sst_capture_frame(mad_ops->stream_id); -+ else -+ printk(KERN_ERR -+ "SST ERR: invalid stream ops invoked \n"); -+ if (retval < 0) -+ printk(KERN_ERR -+ "SST ERR: play/captur frames failed \n"); -+ break; -+ default: -+ printk(KERN_ERR -+ "SST ERR: wrong control_ops reported\n"); -+ } -+ return; -+} -+/** -+* sst_control_set - Set Control params -+* @control_list: list of controls to be set -+* -+* This function is called by MID sound card driver to set -+* SST/Sound card controls. This is registered with MID driver -+*/ -+int sst_control_set(int control_element, void *value) -+{ -+ int retval = 0, str_id = 0, status; -+ struct stream_info *stream; -+ -+ if (sst_drv_ctx->sst_state == SST_UN_INIT) { -+ /* FW is not downloaded */ -+ printk(KERN_DEBUG "SST DBG:DSP Downloading FW now...\n"); -+ retval = sst_download_fw(); -+ if (retval) { -+ printk(KERN_ERR -+ "SST ERR: FW download failed = 0x%x, abort\n", retval); -+ return retval; -+ } -+ } -+ -+ switch (control_element) { -+ case SST_SND_ALLOC: { -+ struct snd_sst_params *str_param; -+ int pcm_id = sst_assign_pvt_id(sst_drv_ctx); -+ struct stream_info *str_info; -+ -+ str_param = (struct snd_sst_params *)value; -+ BUG_ON(!str_param); -+ sst_print_params(str_param); -+ retval = sst_get_stream(str_param, pcm_id); -+ if (retval >= 0) -+ sst_drv_ctx->stream_cnt++; -+ /*if (str_param->ops == STREAM_OPS_PLAYBACK || -+ str_param->ops == STREAM_OPS_PLAYBACK_DRM) -+ sst_ospm_send_event(OSPM_EVENT_SUBSYS_START_PLAY);*/ -+ str_info = &sst_drv_ctx->streams[retval]; -+ str_info->src = MAD_DRV; -+ break; -+ } -+ -+ case SST_SND_PAUSE: -+ case SST_SND_RESUME: -+ case SST_SND_DROP: -+ sst_drv_ctx->mad_ops.control_op = control_element; -+ sst_drv_ctx->mad_ops.stream_id = *(int *)value; -+ queue_work(sst_drv_ctx->mad_wq, &sst_drv_ctx->mad_ops.wq); -+ break; -+ -+ case SST_SND_FREE: -+ str_id = *(int *)value; -+ stream = &sst_drv_ctx->streams[str_id]; -+ free_stream_context(str_id); -+ stream->pcm_substream = NULL; -+ stream->period_elapsed = NULL; -+ sst_drv_ctx->stream_cnt--; -+ break; -+ -+ case SST_SND_STREAM_INIT: { -+ struct pcm_stream_info *str_info; -+ struct stream_info *stream; -+ -+ printk(KERN_DEBUG "SST DBG:stream init called\n"); -+ str_info = (struct pcm_stream_info *)value; -+ str_id = str_info->str_id; -+ retval = sst_validate_strid(str_id); -+ if (retval) -+ break; -+ -+ stream = &sst_drv_ctx->streams[str_id]; -+ printk(KERN_DEBUG "SST DBG:setting the period ptrs\n"); -+ stream->pcm_substream = str_info->mad_substream; -+ stream->period_elapsed = str_info->period_elapsed; -+ stream->sfreq = str_info->sfreq; -+ stream->prev = stream->status; -+ stream->status = STREAM_INIT; -+ break; -+ } -+ -+ case SST_SND_BUFFER_POINTER: { -+ struct pcm_stream_info *stream_info; -+ struct snd_sst_tstamp fw_tstamp = {0,}; -+ struct stream_info *stream; -+ -+ // printk(KERN_DEBUG "SST DBG:buffer pointer query\n"); -+ -+ stream_info = (struct pcm_stream_info *)value; -+ str_id = stream_info->str_id; -+ retval = sst_validate_strid(str_id); -+ if (retval) -+ break; -+ stream = &sst_drv_ctx->streams[str_id]; -+ -+ if (!stream->pcm_substream) -+ break; -+ memcpy_fromio(&fw_tstamp, -+ ((void *)(sst_drv_ctx->mailbox + SST_TIME_STAMP) -+ +(str_id * sizeof(fw_tstamp))), -+ sizeof(fw_tstamp)); -+ -+ // printk(KERN_DEBUG "SST DBG:strid = %d\n", str_id); -+ -+ if (stream->ops == STREAM_OPS_PLAYBACK) -+ stream_info->buffer_ptr = fw_tstamp.samples_rendered; -+ else -+ stream_info->buffer_ptr = fw_tstamp.samples_processed; -+ /* printk(KERN_DEBUG "SST DBG:samples played = %lld\n", -+ stream_info->buffer_ptr); -+ */ -+ break; -+ } -+ case SST_ENABLE_RX_TIME_SLOT: { -+ status = *(int *)value; -+ sst_drv_ctx->rx_time_slot_status = status ; -+ printk(KERN_DEBUG "SST DBG:in case:: **********SST_ENABLE_RX_TIME_SLOT*********** \n"); -+ sst_enable_rx_timeslot(status); -+ break; -+ } -+ default: -+ /* Illegal case */ -+ printk(KERN_ERR"SST ERR: illegal req\n"); -+ return -EINVAL; -+ } -+// printk(KERN_DEBUG "SST DBG:...complete ret code = %d\n", retval); -+ -+ return retval; -+} -+ -+ -+/** -+* sst_send_data_to_HW - send data buffers -+* @buffer_data: user buffer -+* -+* This function is called by MID sound card driver to send buffer -+* to HW. This is registered with MID driver -+*/ -+int sst_send_buffer_to_HW(int str_id, struct stream_buffer *mad_buf) -+{ -+ /* recvd a buffer map it to stream */ -+ /* this is a PCM stream and playback */ -+ int retval = 0; -+ bool flag_add = false; -+ struct sst_stream_bufs *sst_buf = NULL, *_sst_buf; -+ struct stream_info *stream; -+ -+ if (!mad_buf || !mad_buf->addr || !mad_buf->length) { -+ printk(KERN_ERR -+ "SST ERR: Null Ptr or buf size = 0\n"); -+ return -EINVAL; -+ } -+ -+ if (sst_drv_ctx->sst_state != SST_FW_RUNNING) { -+ printk(KERN_ERR -+ "SST ERR: SST Not runng: %d\n", sst_drv_ctx->sst_state); -+ return -EBUSY; -+ } -+ -+ retval = sst_validate_strid(str_id); -+ if (retval < 0) -+ return -EINVAL; -+ -+ stream = &sst_drv_ctx->streams[str_id]; -+ printk(KERN_DEBUG "SST DBG:stream status = %d strid=%d\n", stream->status, str_id); -+ printk(KERN_DEBUG "SST DBG:stream codec = %d, prevstate=%d\n", -+ stream->codec, stream->prev); -+ if (stream->status == STREAM_UN_INIT) { -+ printk(KERN_ERR"SST ERR: BAD REQUEST!\n"); -+ return -EBADRQC; -+ } -+ printk(KERN_DEBUG "SST DBG:received addr=0x%x size = 0x%x\n", -+ (unsigned int)mad_buf->addr, mad_buf->length); -+ /* list is not empty */ -+ list_for_each_entry_safe(sst_buf, _sst_buf, &stream->bufs, node) { -+ if (sst_buf->in_use == true) -+ continue; -+ else if ((int) mad_buf->addr != -+ (int)sst_buf->addr + sst_buf->size) -+ continue; -+ else { -+ sst_buf->size += mad_buf->length; -+ flag_add = true; -+ printk(KERN_DEBUG "SST DBG:inc addr = 0x%p, base = 0x%x inc_val = 0x%x\n", -+ sst_buf->addr, sst_buf->size, mad_buf->length); -+ break; -+ } -+ } -+ -+ if (flag_add == false) { -+ sst_buf = kzalloc(sizeof(*sst_buf), GFP_ATOMIC); -+ if (!sst_buf) -+ return -ENOMEM; -+ sst_buf->size = mad_buf->length; -+ sst_buf->addr = (void *)mad_buf->addr; -+ sst_buf->offset = 0; -+ sst_buf->in_use = false; -+ /*adding without locking FIXME*/ -+ if( in_interrupt()) { -+ list_add_tail(&sst_buf->node, &stream->bufs); -+ } else { -+ spin_lock(&stream->pcm_lock); -+ list_add_tail(&sst_buf->node, &stream->bufs); -+ spin_unlock(&stream->pcm_lock); -+ } -+ -+ -+ flag_add = true; -+ printk(KERN_DEBUG "SST DBG:entry added addr = 0x%x size = 0x%x\n", -+ (unsigned int)mad_buf->addr, mad_buf->length); -+ } -+ -+ if (stream->status == STREAM_INIT) { -+ sst_drv_ctx->mad_ops.control_op = SST_SND_STREAM_PROCESS; -+ sst_drv_ctx->mad_ops.stream_id = str_id; -+ queue_work(sst_drv_ctx->mad_wq, &sst_drv_ctx->mad_ops.wq); -+ } -+ -+ return retval; -+} -+ -+struct intel_sst_card_ops sst_pmic_ops = { -+ .control_set = sst_control_set, -+ .send_buffer = sst_send_buffer_to_HW, -+}; -+ -+/** -+* register_sst_card- function for sound card to register -+* @card: pointer to structure of operations -+* This function is called card driver loads and is ready for registration -+*/ -+int register_sst_card(struct intel_sst_card_ops *card) -+{ -+ -+ if (!card || !card->module_name) { -+ printk(KERN_ERR "SST ERR: Null Pointer Passed\n"); -+ return -EINVAL; -+ } -+ -+ if (sst_drv_ctx->pmic_state == SND_MAD_UN_INIT) { -+ /* register this driver */ -+ if ((strncmp(SST_CARD_NAMES, card->module_name, -+ strlen(SST_CARD_NAMES))) == 0) { -+ sst_drv_ctx->pmic_vendor = card->vendor_id; -+ sst_drv_ctx->scard_ops = card->scard_ops; -+ sst_pmic_ops.module_name = card->module_name; -+ sst_drv_ctx->pmic_state = SND_MAD_INIT_DONE; -+ sst_drv_ctx->rx_time_slot_status = RX_TIMESLOT_UNINIT; -+ card->control_set = sst_pmic_ops.control_set; -+ card->send_buffer = sst_pmic_ops.send_buffer; -+ sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT; -+ /* initialize card to know good state */ -+ /*sst_drv_ctx->scard_ops->init_card();*/ -+ return 0; -+ } else { -+ printk(KERN_ERR -+ "SST ERR: strcmp failed %s \n", card->module_name); -+ return -EINVAL; -+ } -+ -+ } else { -+ /* already registered a driver */ -+ printk(KERN_ERR -+ "SST ERR: Repeat for register..denied\n"); -+ return -EBADRQC; -+ } -+ return 0; -+} -+EXPORT_SYMBOL_GPL(register_sst_card); -+ -+/** -+* unregister_sst_card- function for sound card to un-register -+* @card: pointer to structure of operations -+* This function is called when card driver unloads -+*/ -+void unregister_sst_card(struct intel_sst_card_ops *card) -+{ -+ if (sst_pmic_ops.module_name == card->module_name) { -+ /* unreg */ -+ sst_pmic_ops.module_name = ""; -+ sst_drv_ctx->pmic_state = SND_MAD_UN_INIT; -+ printk(KERN_DEBUG "SST DBG:Unregistered %s\n", card->module_name); -+ } -+ return; -+} -+EXPORT_SYMBOL_GPL(unregister_sst_card); -+ -+/** -+* lpe_mask_periphral_intr- function to mask SST DSP peripheral interrupt -+* @device: device interrupt that needs masking -+*/ -+int lpe_mask_periphral_intr(enum lpe_periphral device) -+{ -+ union sst_pimr_reg pimr = {{0},}; -+ if (!sst_drv_ctx) -+ return -EIO; -+ -+ pimr.full = readl(sst_drv_ctx->shim + SST_PIMR); -+ -+ switch (device) { -+ case LPE_DMA: -+ pimr.part.dmac_sc = 1; -+ /* dummy register for shim workaround */ -+ writel(pimr.full, sst_drv_ctx->shim + SST_ISRD); -+ writel(pimr.full, sst_drv_ctx->shim + SST_PIMR); -+ break; -+ -+ case LPE_SSP0: -+ break; -+ -+ case LPE_SSP1: -+ break; -+ -+ default: -+ break; -+ } -+ return 0; -+} -+EXPORT_SYMBOL_GPL(lpe_mask_periphral_intr); -+ -+/** -+* lpe_unmask_periphral_intr- function to unmask SST DSP peripheral interrupt -+* @device: device interrupt that needs unmasking -+*/ -+int lpe_unmask_periphral_intr(enum lpe_periphral device) -+{ -+ union sst_pimr_reg pimr = {{0},}; -+ if (!sst_drv_ctx) -+ return -EIO; -+ -+ pimr.full = readl(sst_drv_ctx->shim + SST_PIMR); -+ -+ switch (device) { -+ case LPE_DMA: -+ pimr.part.dmac_sc = 0; -+ /* dummy register for shim workaround */ -+ writel(pimr.full, sst_drv_ctx->shim + SST_ISRD); -+ writel(pimr.full, sst_drv_ctx->shim + SST_PIMR); -+ break; -+ -+ case LPE_SSP0: -+ break; -+ -+ case LPE_SSP1: -+ break; -+ -+ default: -+ break; -+ } -+ return 0; -+ -+} -+EXPORT_SYMBOL_GPL(lpe_unmask_periphral_intr); -+ -+/** -+* lpe_periphral_intr_status- function returns SST peripheral interrupt status -+* @device: device for which the status is enquired -+* @status: out parameters with the status of the peripheral device -+*/ -+int lpe_periphral_intr_status(enum lpe_periphral device, int *status) -+{ -+ union sst_pisr_reg pisr = {{0},}; -+ if (!sst_drv_ctx) -+ return -EIO; -+ -+ pisr.full = readl(sst_drv_ctx->shim + SST_PISR); -+ -+ switch (device) { -+ case LPE_DMA: -+ *status = pisr.part.dmac; -+ break; -+ -+ case LPE_SSP0: -+ break; -+ -+ case LPE_SSP1: -+ break; -+ -+ default: -+ break; -+ } -+ return 0; -+} -+EXPORT_SYMBOL_GPL(lpe_periphral_intr_status); --- -1.6.2.2 - |