summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-7-8.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-7-8.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-7-8.patch2391
1 files changed, 0 insertions, 2391 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-7-8.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-7-8.patch
deleted file mode 100644
index 557b67d93..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-7-8.patch
+++ /dev/null
@@ -1,2391 +0,0 @@
-From d88bb1ae711414e9bca4a23a7d6375cb4bad18f4 Mon Sep 17 00:00:00 2001
-From: R, Dharageswari <dharageswari.r@intel.com>
-Date: Thu, 29 Apr 2010 20:28:59 +0530
-Subject: [PATCH] ADR-Post-Beta-0.05.002.03-7/8-Moorestown Audio Drivers: sound card ALSA driver
-
-This adds support for Moorestown ALSA Sound card driver.
-This is an ALSA driver for supporting PCM playback/capture in
-traditional ALSA way. Anyone who chooses not to use DSP for
-decoding/encoding can use ALSA path to play/capture, but obvious loss will
-be power. This driver registers the control interface and PCM interface with
-the SST driver which finally sends it to the hardware. This driver allows any
-subsystem in OS which wants to use the audio-subsystems to be routed
-through the ALSA.The patch includes ALSA driver header file for handling
-mixer controls for Intel MAD chipset.This patch also includes enum additions to
-jack.h of ALSA Framework
-
-Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-
- modified: include/sound/jack.h
- new file: sound/pci/sst/intelmid.c
- new file: sound/pci/sst/intelmid.h
- new file: sound/pci/sst/intelmid_ctrl.c
- new file: sound/pci/sst/intelmid_ctrl.h
- new file: sound/pci/sst/intelmid_pvt.c
-Patch-mainline: 2.6.35?
----
- include/sound/jack.h | 2 +
- sound/pci/sst/intelmid.c | 1205 +++++++++++++++++++++++++++++++++++++++++
- sound/pci/sst/intelmid.h | 170 ++++++
- sound/pci/sst/intelmid_ctrl.c | 555 +++++++++++++++++++
- sound/pci/sst/intelmid_ctrl.h | 33 ++
- sound/pci/sst/intelmid_pvt.c | 343 ++++++++++++
- 6 files changed, 2308 insertions(+), 0 deletions(-)
- create mode 100644 sound/pci/sst/intelmid.c
- create mode 100644 sound/pci/sst/intelmid.h
- create mode 100644 sound/pci/sst/intelmid_ctrl.c
- create mode 100644 sound/pci/sst/intelmid_ctrl.h
- create mode 100644 sound/pci/sst/intelmid_pvt.c
-
-diff --git a/include/sound/jack.h b/include/sound/jack.h
-index f236e42..791c550 100644
---- a/include/sound/jack.h
-+++ b/include/sound/jack.h
-@@ -42,6 +42,8 @@ enum snd_jack_types {
- SND_JACK_MECHANICAL = 0x0008, /* If detected separately */
- SND_JACK_VIDEOOUT = 0x0010,
- SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
-+ SND_JACK_HS_SHORT_PRESS = SND_JACK_HEADSET | 0x0020,
-+ SND_JACK_HS_LONG_PRESS = SND_JACK_HEADSET | 0x0040,
- };
-
- struct snd_jack {
-diff --git a/sound/pci/sst/intelmid.c b/sound/pci/sst/intelmid.c
-new file mode 100644
-index 0000000..c5a3b36
---- /dev/null
-+++ b/sound/pci/sst/intelmid.c
-@@ -0,0 +1,1205 @@
-+/*
-+ * intelmid.c - Intel Sound card driver for MID
-+ *
-+ * Copyright (C) 2008-10 Intel Corp
-+ * Authors: Harsha Priya <priya.harsha@intel.com>
-+ * Vinod Koul <vinod.koul@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.
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ * ALSA driver for Intel MID sound card chipset
-+ */
-+#include <linux/spi/spi.h>
-+#include <linux/io.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/moduleparam.h>
-+#include <linux/sched.h>
-+#include <sound/core.h>
-+#include <sound/control.h>
-+#include <sound/pcm.h>
-+#include <sound/jack.h>
-+#include <sound/pcm_params.h>
-+#include <sound/info.h>
-+#include <sound/initval.h>
-+
-+#include <sound/pcm-indirect.h>
-+#include <sound/intel_lpe.h>
-+#include <sound/intel_sst_ioctl.h>
-+/* #include <net/netlink.h>
-+#include <net/genetlink.h> */
-+
-+#include "intelmid_snd_control.h"
-+#include "intelmid.h"
-+#include "intelmid_ctrl.h"
-+
-+MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
-+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-+MODULE_DESCRIPTION("Intel MAD Sound card driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_SUPPORTED_DEVICE("{Intel,Intel_MAD}");
-+
-+
-+static int card_index = SNDRV_DEFAULT_IDX1;/* Index 0-MAX */
-+static char *card_id = SNDRV_DEFAULT_STR1; /* ID for this card */
-+
-+module_param(card_index, int, 0444);
-+MODULE_PARM_DESC(card_index, "Index value for INTELMAD soundcard.");
-+module_param(card_id, charp, 0444);
-+MODULE_PARM_DESC(card_id, "ID string for INTELMAD soundcard.");
-+
-+int sst_card_vendor_id;
-+int audio_interrupt_enable = 0;
-+
-+/* Data path functionalities */
-+static struct snd_pcm_hardware snd_intelmad_stream = {
-+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
-+ SNDRV_PCM_INFO_DOUBLE |
-+ SNDRV_PCM_INFO_PAUSE |
-+ SNDRV_PCM_INFO_RESUME |
-+ SNDRV_PCM_INFO_MMAP|
-+ SNDRV_PCM_INFO_MMAP_VALID |
-+ /* SNDRV_PCM_INFO_BATCH | */
-+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
-+ SNDRV_PCM_INFO_SYNC_START),
-+ .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
-+ /* SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | */
-+ SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24),
-+ .rates = (SNDRV_PCM_RATE_8000|
-+ SNDRV_PCM_RATE_44100 |
-+ SNDRV_PCM_RATE_48000),
-+ .rate_min = MIN_RATE,
-+
-+ .rate_max = MAX_RATE,
-+ .channels_min = MIN_CHANNEL,
-+ .channels_max = MAX_CHANNEL,
-+ .buffer_bytes_max = MAX_BUFFER,
-+ .period_bytes_min = MIN_PERIOD_BYTES,
-+ .period_bytes_max = MAX_PERIOD_BYTES,
-+ .periods_min = MIN_PERIODS,
-+ .periods_max = MAX_PERIODS,
-+ .fifo_size = FIFO_SIZE,
-+};
-+
-+static int snd_intelmad_pcm_ack(struct snd_pcm_substream *substream)
-+{
-+ struct mad_stream_pvt *stream;
-+ struct snd_pcm_indirect *rec;
-+
-+ WARN_ON(!substream);
-+ WARN_ON(!substream->runtime);
-+
-+ stream = substream->runtime->private_data;
-+ WARN_ON(!stream);
-+
-+// printk(KERN_DEBUG "SST DBG:called %d\n", stream->stream_status);
-+ if (stream->stream_status != INIT) {
-+
-+ rec = &stream->pcm_indirect;
-+ if (substream->stream == STREAM_OPS_PLAYBACK) {
-+// printk(KERN_DEBUG "SST DBG:calling indirect playback transfer\n");
-+ snd_pcm_indirect_playback_transfer(substream, rec,
-+ send_buffer_to_sst);
-+ } else if (substream->stream == STREAM_OPS_CAPTURE) {
-+// printk(KERN_DEBUG "SST DBG:calling indirect capture transfer\n");
-+ snd_pcm_indirect_capture_transfer(substream, rec,
-+ send_buffer_to_sst);
-+ }
-+
-+ stream->stream_status = RUNNING;
-+ }
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_pcm_trigger - stream activities are handled here
-+* @substream:substream for which the stream function is called
-+*@cmd:the stream commamd thats requested from upper layer
-+* This function is called whenever an a stream activity is invoked
-+*/
-+static int snd_intelmad_pcm_trigger(struct snd_pcm_substream *substream,
-+ int cmd)
-+{
-+ int ret_val = 0;
-+ struct snd_intelmad *intelmaddata;
-+ struct mad_stream_pvt *stream;
-+ struct stream_buffer buffer_to_sst;
-+
-+// printk(KERN_DEBUG "SST DBG:called\n");
-+
-+ WARN_ON(!substream);
-+
-+ intelmaddata = snd_pcm_substream_chip(substream);
-+ stream = substream->runtime->private_data;
-+
-+ WARN_ON(!intelmaddata->sstdrv_ops);
-+ WARN_ON(!intelmaddata->sstdrv_ops->scard_ops);
-+
-+ switch (cmd) {
-+ case SNDRV_PCM_TRIGGER_START:
-+ stream->substream = substream;
-+/*
-+ printk(KERN_DEBUG "SST DBG:pcm_size+\
-+ =%d\n", snd_pcm_lib_buffer_bytes(substream));
-+*/
-+ stream->stream_status = STARTED;
-+
-+ if (substream->stream == STREAM_OPS_PLAYBACK)
-+ snd_intelmad_pcm_ack(substream);
-+ else if (substream->stream == STREAM_OPS_CAPTURE) {
-+ buffer_to_sst.length =
-+ frames_to_bytes(substream->runtime,
-+ substream->runtime->buffer_size);
-+ buffer_to_sst.addr = (unsigned long)
-+ substream->runtime->dma_area;
-+ ret_val = intelmaddata->sstdrv_ops->send_buffer(
-+ stream->stream_info.str_id,
-+ &buffer_to_sst);
-+ stream->dbg_cum_bytes +=
-+ frames_to_bytes(substream->runtime,
-+ substream->runtime->buffer_size);
-+ stream->stream_status = RUNNING;
-+ }
-+ break;
-+ case SNDRV_PCM_TRIGGER_STOP:
-+// printk(KERN_DEBUG "SST DBG:in stop\n");
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_DROP,
-+ &stream->stream_info.str_id);
-+ if (ret_val)
-+ return ret_val;
-+ stream->stream_status = DROPPED;
-+ break;
-+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+// printk(KERN_DEBUG "SST DBG:in pause\n");
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_PAUSE,
-+ &stream->stream_info.str_id);
-+ if (ret_val)
-+ return ret_val;
-+ stream->stream_status = PAUSED;
-+ break;
-+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+// printk(KERN_DEBUG "SST DBG:in pause release \n");
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_RESUME,
-+ &stream->stream_info.str_id);
-+ if (ret_val)
-+ return ret_val;
-+ stream->stream_status = RUNNING;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_pcm_prepare- internal preparation before starting a stream
-+* @substream: substream for which the function is called
-+* This function is called when a stream is started for internal preparation.
-+*/
-+static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream)
-+{
-+ struct mad_stream_pvt *stream;
-+ int ret_val = 0;
-+ struct snd_intelmad *intelmaddata;
-+
-+ printk(KERN_DEBUG "SST DBG:called \n");
-+
-+ WARN_ON(!substream);
-+ stream = substream->runtime->private_data;
-+ intelmaddata = snd_pcm_substream_chip(substream);
-+ printk(KERN_DEBUG "SST DBG:pb cnt = %d cap cnt = %d\n",\
-+ intelmaddata->playback_cnt,
-+ intelmaddata->capture_cnt);
-+
-+ if(stream->stream_info.str_id) {
-+ printk(KERN_DEBUG "SST DBG:Prepare called for already set stream\n");
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_DROP,
-+ &stream->stream_info.str_id);
-+
-+ } else {
-+ ret_val = snd_intelmad_alloc_stream(substream);
-+ if (ret_val < 0)
-+ return ret_val;
-+ stream->dbg_cum_bytes = 0;
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ intelmaddata->playback_cnt++;
-+ else
-+ intelmaddata->capture_cnt++;
-+ printk(KERN_DEBUG "SST DBG:period size = %d \n",
-+ (int)substream->runtime->period_size);
-+ printk(KERN_DEBUG "SST DBG:buf size = %d \n",
-+ (int)substream->runtime->buffer_size);
-+ memset(&stream->pcm_indirect, 0, sizeof(stream->pcm_indirect));
-+ stream->pcm_indirect.hw_buffer_size =
-+ snd_pcm_lib_buffer_bytes(substream);
-+ stream->pcm_indirect.sw_buffer_size =
-+ stream->pcm_indirect.hw_buffer_size;
-+ /* return back the stream id */
-+ snprintf(substream->pcm->id, sizeof(substream->pcm->id),
-+ "%d", stream->stream_info.str_id);
-+ printk(KERN_DEBUG "SST DBG:stream id to user = %s\n", substream->pcm->id);
-+ }
-+ ret_val = snd_intelmad_init_stream(substream);
-+ if (ret_val)
-+ return ret_val;
-+
-+ return ret_val;
-+}
-+
-+static int snd_intelmad_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *hw_params)
-+{
-+ int ret_val;
-+
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+ ret_val = snd_pcm_lib_malloc_pages(substream,
-+ params_buffer_bytes(hw_params));
-+ memset(substream->runtime->dma_area, 0,
-+ params_buffer_bytes(hw_params));
-+ return ret_val;
-+}
-+
-+static int snd_intelmad_hw_free(struct snd_pcm_substream *substream)
-+{
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+ return snd_pcm_lib_free_pages(substream);
-+}
-+
-+/**
-+* snd_intelmad_pcm_pointer- to send the current buffer pointer processed by hw
-+* @substream: substream for which the function is called
-+* This function is called by ALSA framework to get the current hw buffer ptr
-+* when a period is elapsed
-+*/
-+static snd_pcm_uframes_t snd_intelmad_pcm_pointer
-+ (struct snd_pcm_substream *substream)
-+{
-+ /* struct snd_pcm_runtime *runtime = substream->runtime; */
-+ struct mad_stream_pvt *stream;
-+ struct snd_intelmad *intelmaddata;
-+ int ret_val;
-+ unsigned long buf_size;
-+
-+ WARN_ON(!substream);
-+
-+ intelmaddata = snd_pcm_substream_chip(substream);
-+ stream = substream->runtime->private_data;
-+ if (stream->stream_status == INIT)
-+ return 0;
-+
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_BUFFER_POINTER,
-+ &stream->stream_info);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: error code = 0x%x \n", ret_val);
-+ return ret_val;
-+ }
-+/* printk(KERN_DEBUG "SST DBG:samples reported out 0x%llx \n",
-+ stream->stream_info.buffer_ptr);
-+ printk(KERN_DEBUG "SST DBG:Frame bits:: %d period_count :: %d \n",
-+ (int)substream->runtime->frame_bits,
-+ (int)substream->runtime->period_size);
-+*/
-+ if (substream->stream == STREAM_OPS_PLAYBACK) {
-+ if(SNDRV_PCM_POS_XRUN == stream->stream_info.buffer_ptr)
-+ return SNDRV_PCM_POS_XRUN;
-+ }
-+
-+ buf_size = frames_to_bytes(substream->runtime,
-+ stream->stream_info.buffer_ptr);
-+
-+// printk(KERN_DEBUG "SST DBG: bytes reported out = 0x%lx\n", buf_size);
-+ if (buf_size > stream->dbg_cum_bytes)
-+ dev_err(&intelmaddata->spi->dev, "SST ERR: excess reported \n");
-+
-+ if (substream->stream == STREAM_OPS_PLAYBACK)
-+ return snd_pcm_indirect_playback_pointer(
-+ substream, &stream->pcm_indirect, buf_size);
-+ else
-+ return snd_pcm_indirect_capture_pointer(
-+ substream, &stream->pcm_indirect, buf_size);
-+}
-+
-+/**
-+* snd_intelmad_close- to free parameteres when stream is stopped
-+* @substream: substream for which the function is called
-+* This function is called by ALSA framework when stream is stopped
-+*/
-+static int snd_intelmad_close(struct snd_pcm_substream *substream)
-+{
-+ struct snd_intelmad *intelmaddata;
-+ struct mad_stream_pvt *stream;
-+ int ret_val = 0;
-+
-+ WARN_ON(!substream);
-+
-+ stream = substream->runtime->private_data;
-+
-+ printk(KERN_DEBUG "SST DBG:called \n");
-+ intelmaddata = snd_pcm_substream_chip(substream);
-+
-+ printk(KERN_DEBUG "SST DBG:str id = %d\n", stream->stream_info.str_id);
-+ if (stream->stream_info.str_id) {
-+ /* SST API to actually stop/free the stream */
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_FREE,
-+ &stream->stream_info.str_id);
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ intelmaddata->playback_cnt--;
-+ else
-+ intelmaddata->capture_cnt--;
-+ }
-+ printk(KERN_DEBUG "SST DBG:pb cnt = %d cap cnt = %d\n", intelmaddata->playback_cnt,
-+ intelmaddata->capture_cnt);
-+ kfree(substream->runtime->private_data);
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_open- to set runtime parameters during stream start
-+* @substream: substream for which the function is called
-+* This function is called by ALSA framework when stream is started
-+*/
-+static int snd_intelmad_open(struct snd_pcm_substream *substream)
-+{
-+ struct snd_intelmad *intelmaddata;
-+ struct snd_pcm_runtime *runtime;
-+ struct mad_stream_pvt *stream;
-+
-+ WARN_ON(!substream);
-+
-+ printk(KERN_DEBUG "SST DBG:called \n");
-+
-+ intelmaddata = snd_pcm_substream_chip(substream);
-+ runtime = substream->runtime;
-+ /* set the runtime hw parameter with local snd_pcm_hardware struct */
-+ runtime->hw = snd_intelmad_stream;
-+ /* setup the internal datastruture stream pointers based on it being
-+ playback or capture stream */
-+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
-+ if (!stream)
-+ return -ENOMEM;
-+ stream->stream_info.str_id = 0;
-+ stream->stream_status = INIT;
-+ runtime->private_data = stream;
-+ return snd_pcm_hw_constraint_integer(runtime,
-+ SNDRV_PCM_HW_PARAM_PERIODS);
-+}
-+
-+static struct snd_pcm_ops snd_intelmad_playback_ops = {
-+ .open = snd_intelmad_open,
-+ .close = snd_intelmad_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = snd_intelmad_hw_params,
-+ .hw_free = snd_intelmad_hw_free,
-+ .prepare = snd_intelmad_pcm_prepare,
-+ .trigger = snd_intelmad_pcm_trigger,
-+ .pointer = snd_intelmad_pcm_pointer,
-+ .ack = snd_intelmad_pcm_ack,
-+};
-+
-+static struct snd_pcm_ops snd_intelmad_capture_ops = {
-+ .open = snd_intelmad_open,
-+ .close = snd_intelmad_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = snd_intelmad_hw_params,
-+ .hw_free = snd_intelmad_hw_free,
-+ .prepare = snd_intelmad_pcm_prepare,
-+ .trigger = snd_intelmad_pcm_trigger,
-+ .pointer = snd_intelmad_pcm_pointer,
-+ .ack = snd_intelmad_pcm_ack,
-+};
-+
-+
-+#ifdef REG_IRQ
-+/**
-+* snd_intelmad_intr_handler- interrupt handler
-+*@irq : irq number of the interrupt received
-+*@dev: device context
-+* This function is called when an interrupt is raised at the sound card
-+*/
-+static irqreturn_t snd_intelmad_intr_handler(int irq, void *dev)
-+{
-+ struct snd_intelmad *intelmaddata =
-+ (struct snd_intelmad *)dev;
-+ u8 intsts;
-+
-+ memcpy_fromio(&intsts,
-+ ((void *)(intelmaddata->int_base)),
-+ sizeof(u8));
-+ intelmaddata->mad_jack_msg.intsts = intsts;
-+ intelmaddata->mad_jack_msg.intelmaddata = intelmaddata;
-+
-+ queue_work(intelmaddata->mad_jack_wq, &intelmaddata->mad_jack_msg.wq);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+void sst_mad_send_jack_report(struct snd_jack *jack, int buttonpressevent , int status)
-+{
-+
-+ if (!jack) {
-+ printk(KERN_DEBUG "SST DBG:MAD error jack empty \n");
-+
-+ } else {
-+ printk(KERN_DEBUG "SST DBG:MAD sending jack +\
-+ report for = %d!!!\n", status);
-+ if (jack)
-+ printk(KERN_DEBUG "SST DBG:MAD sending +\
-+ jack report for = %d !!!\n", jack->type);
-+
-+ snd_jack_report(jack, status);
-+
-+ /*button pressed and released */
-+ if (buttonpressevent)
-+ snd_jack_report(jack, 0);
-+ printk(KERN_DEBUG "SST DBG:MAD sending jack report Done !!!\n");
-+ }
-+
-+
-+
-+}
-+
-+void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata)
-+{
-+ struct snd_jack *jack = NULL;
-+ unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
-+ struct sc_reg_access sc_access[] = {
-+ {0x187, 0x00, MASK7},
-+ {0x188, 0x10, MASK4},
-+ {0x18b, 0x10, MASK4},
-+ };
-+
-+ struct sc_reg_access sc_access_write[] = {
-+ {0x198, 0x00, 0x0},
-+ };
-+
-+ if (intsts & 0x4) {
-+
-+ if (!(audio_interrupt_enable)) {
-+ printk(KERN_DEBUG "SST DBG:Audio interrupt enable\n");
-+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
-+
-+ sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
-+ audio_interrupt_enable = 1;
-+ intelmaddata->jack[0].jack_status = 0;
-+ intelmaddata->jack[1].jack_status = 0;
-+
-+ }
-+ /* send headphone detect */
-+ printk(KERN_DEBUG "SST DBG:MAD headphone +\
-+ = %d!!!\n", intsts & 0x4);
-+ jack = &intelmaddata->jack[0].jack;
-+ present = !(intelmaddata->jack[0].jack_status);
-+ intelmaddata->jack[0].jack_status = present;
-+ jack_event_flag = 1;
-+
-+ }
-+
-+ if (intsts & 0x2) {
-+ /* send short push */
-+ printk(KERN_DEBUG "SST DBG:MAD short push +\
-+ = %d!!!\n", intsts & 0x2);
-+ jack = &intelmaddata->jack[2].jack;
-+ present = 1;
-+ jack_event_flag = 1;
-+ buttonpressflag = 1;
-+ }
-+ if (intsts & 0x1) {
-+ /* send long push */
-+ printk(KERN_DEBUG "SST DBG:MAD long push+\
-+ = %d!!!\n", intsts & 0x1);
-+ jack = &intelmaddata->jack[3].jack;
-+ present = 1;
-+ jack_event_flag = 1;
-+ buttonpressflag = 1;
-+ }
-+ if (intsts & 0x8) {
-+ if (!(audio_interrupt_enable)) {
-+ printk(KERN_DEBUG "SST DBG:Audio interrupt enable\n");
-+ sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
-+
-+ sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
-+ audio_interrupt_enable = 1;
-+ intelmaddata->jack[0].jack_status = 0;
-+ intelmaddata->jack[1].jack_status = 0;
-+ }
-+ /* send headset detect */
-+ printk(KERN_DEBUG "SST DBG:MAD headset +\
-+ = %d!!!\n", intsts & 0x8);
-+ jack = &intelmaddata->jack[1].jack;
-+ present = !(intelmaddata->jack[1].jack_status);
-+ intelmaddata->jack[1].jack_status = present;
-+ jack_event_flag = 1;
-+ }
-+
-+
-+ if (jack_event_flag)
-+ sst_mad_send_jack_report( jack, buttonpressflag, present);
-+}
-+
-+
-+void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata)
-+{
-+ u8 value = 0,jack_prev_state = 0;
-+ struct snd_jack *jack = NULL;
-+ unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
-+ time_t timediff;
-+ struct sc_reg_access sc_access_read = {0,};
-+
-+
-+
-+ printk(KERN_DEBUG "SST DBG:previos value: = 0x%x \n" ,intelmaddata->jack_prev_state);
-+
-+ if (!(audio_interrupt_enable)) {
-+ printk(KERN_DEBUG "SST DBG:Audio interrupt enable\n");
-+ intelmaddata->jack_prev_state = 0xC0;
-+ audio_interrupt_enable = 1;
-+ }
-+
-+ if (intsts & 0x2) {
-+ jack_prev_state = intelmaddata->jack_prev_state;
-+ if(intelmaddata->pmic_status == PMIC_INIT) {
-+ sc_access_read.reg_addr = 0x201;
-+ sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
-+ value = (sc_access_read.value);
-+ printk(KERN_DEBUG "value returned = 0x%x\n", value);
-+ }
-+
-+ if ((jack_prev_state == 0xc0) && (value == 0x40) ) {
-+ //headset detected.
-+ printk(KERN_DEBUG "MAD headset inserted\n");
-+ jack = &intelmaddata->jack[1].jack;
-+ present= 1;
-+ jack_event_flag = 1;
-+ intelmaddata->jack[1].jack_status = 1;
-+
-+ }
-+
-+ if ((jack_prev_state == 0xc0 ) && ( value == 0x00) ) {
-+ //headphone detected.
-+ printk(KERN_DEBUG "MAD headphone inserted\n");
-+ jack = &intelmaddata->jack[0].jack;
-+ present= 1;
-+ jack_event_flag = 1;
-+
-+ }
-+
-+ if ( (jack_prev_state == 0x40 ) && ( value == 0xc0) ) {
-+ //headset removed
-+ printk(KERN_DEBUG "Jack headset status %d\n",\
-+ intelmaddata->jack[1].jack_status);
-+ printk(KERN_DEBUG "MAD headset removed \n");
-+ jack = &intelmaddata->jack[1].jack;
-+ present= 0;
-+ jack_event_flag = 1;
-+ intelmaddata->jack[1].jack_status = 0;
-+ }
-+
-+ if ( (jack_prev_state == 0x00 ) && ( value == 0xc0) ) {
-+ //headphone detected.
-+ printk(KERN_DEBUG "Jack headphone status %d\n",\
-+ intelmaddata->jack[0].jack_status);
-+ printk(KERN_DEBUG "MAD headphone removed\n");
-+ jack = &intelmaddata->jack[0].jack;
-+ present= 0;
-+ jack_event_flag = 1;
-+ }
-+
-+ if ( (jack_prev_state == 0x40 ) && (value == 0x00) ) {
-+ //button pressed
-+ do_gettimeofday(&intelmaddata->jack[1].buttonpressed);
-+ printk(KERN_DEBUG "MAD button press detected n");
-+ }
-+
-+
-+ if( (jack_prev_state == 0x00 ) && ( value == 0x40) ) {
-+ if ( intelmaddata->jack[1].jack_status ) {
-+ //button pressed
-+ do_gettimeofday(&intelmaddata->jack[1].buttonreleased);
-+ /*button pressed */
-+ printk(KERN_DEBUG "MAD Button Released detected time \n" );
-+ timediff = intelmaddata->jack[1].buttonreleased.tv_sec -
-+ intelmaddata->jack[1].buttonpressed.tv_sec;
-+ buttonpressflag = 1;
-+ if(timediff > 1) {
-+ printk(KERN_DEBUG "MAD long press detected time \n" );
-+ /* send headphone detect/undetect */
-+ jack = &intelmaddata->jack[3].jack;
-+ present= 1;
-+ jack_event_flag = 1;
-+ }
-+ else {
-+ printk(KERN_DEBUG "MAD short press detected time \n" );
-+ /* send headphone detect/undetect */
-+ jack = &intelmaddata->jack[2].jack;
-+ present= 1;
-+ jack_event_flag = 1;
-+ }
-+ }
-+
-+ }
-+ intelmaddata->jack_prev_state = value ;
-+
-+ }
-+
-+ if (jack_event_flag)
-+ sst_mad_send_jack_report( jack, buttonpressflag, present);
-+}
-+
-+
-+void sst_mad_jackdetection_nec(u8 intsts, struct snd_intelmad *intelmaddata)
-+{
-+ u8 value = 0;
-+ struct snd_jack *jack = NULL;
-+ unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
-+
-+ struct sc_reg_access sc_access_read = {0,};
-+
-+ if (intelmaddata->pmic_status == PMIC_INIT) {
-+ sc_access_read.reg_addr = 0x132;
-+ sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
-+ value = (sc_access_read.value);
-+ printk(KERN_DEBUG "SST DBG:value returned = 0x%x\n", value);
-+ }
-+ if (intsts & 0x1) {
-+ printk(KERN_DEBUG "SST DBG:MAD headset detected\n");
-+ /* send headset detect/undetect */
-+ jack = &intelmaddata->jack[1].jack;
-+ present = (value == 0x1) ? 1 : 0;
-+ jack_event_flag = 1;
-+ }
-+ if (intsts & 0x2) {
-+ printk(KERN_DEBUG "SST DBG:MAD headphone detected\n");
-+ /* send headphone detect/undetect */
-+ jack = &intelmaddata->jack[0].jack;
-+ present = (value == 0x2) ? 1 : 0;
-+ jack_event_flag = 1;
-+ }
-+ if (intsts & 0x4) {
-+ printk(KERN_DEBUG "SST DBG:MAD short push detected\n");
-+ /* send short push */
-+ jack = &intelmaddata->jack[2].jack;
-+ present = 1;
-+ jack_event_flag = 1;
-+ buttonpressflag = 1;
-+ }
-+ if (intsts & 0x8) {
-+ printk(KERN_DEBUG "SST DBG:MAD long push detected\n");
-+ /* send long push */
-+ jack = &intelmaddata->jack[3].jack;
-+ present = 1;
-+ jack_event_flag = 1;
-+ buttonpressflag = 1;
-+ }
-+
-+ if (jack_event_flag)
-+ sst_mad_send_jack_report( jack, buttonpressflag, present);
-+
-+
-+}
-+
-+void sst_process_mad_jack_detection(struct work_struct *work)
-+{
-+ u8 intsts;
-+ struct mad_jack_msg_wq *mad_jack_detect =
-+ container_of(work, struct mad_jack_msg_wq, wq);
-+
-+ struct snd_intelmad *intelmaddata =
-+ mad_jack_detect->intelmaddata;
-+
-+ intsts = mad_jack_detect->intsts;
-+
-+ switch (intelmaddata->sstdrv_ops->vendor_id) {
-+ case SND_FS:
-+ sst_mad_jackdetection_fs(intsts,intelmaddata);
-+ break;
-+ case SND_MX:
-+ sst_mad_jackdetection_mx(intsts,intelmaddata);
-+ break;
-+ case SND_NC:
-+ sst_mad_jackdetection_nec(intsts,intelmaddata);
-+ break;
-+ }
-+}
-+
-+
-+static int __devinit snd_intelmad_register_irq(
-+ struct snd_intelmad *intelmaddata)
-+{
-+ int ret_val;
-+ u32 regbase = AUDINT_BASE, regsize = 8;
-+
-+ printk(KERN_DEBUG "SST DBG:irq reg done, now mapping... regbase 0x%x, regsize 0x%x\n",
-+ regbase, regsize);
-+ intelmaddata->int_base = ioremap_nocache(regbase, regsize);
-+ if (!intelmaddata->int_base)
-+ dev_err(&intelmaddata->spi->dev, "SST ERR: +\
-+ Mapping of cache failed \n");
-+
-+ /* interpret irq field */
-+ printk(KERN_DEBUG "SST DBG:irq = 0x%x\n", intelmaddata->irq);
-+ ret_val = request_irq(intelmaddata->irq,
-+ snd_intelmad_intr_handler,
-+ IRQF_SHARED, DRIVER_NAME,
-+ intelmaddata);
-+ if (ret_val)
-+ dev_err(&intelmaddata->spi->dev, "SST ERR: cannot +\
-+ register IRQ \n");
-+ return ret_val;
-+}
-+
-+/*static int __devinit snd_intelmad_register_netlink(void)
-+{
-+ int ret_val;
-+
-+ ret_val = genl_register_family(&audio_event_genl_family);
-+ if (ret_val) {
-+ printk(KERN_DEBUG "SST DBG:netlink registration failed\n");
-+ return ret_val;
-+ }
-+ ret_val = genl_register_mc_group(&audio_event_genl_family,
-+ &audio_event_mcgrp);
-+ if (ret_val) {
-+ printk(KERN_DEBUG "SST DBG:netlink +\
-+ group registration failed\n");
-+ genl_unregister_family(&audio_event_genl_family);
-+ return ret_val;
-+ }
-+ return ret_val;
-+}*/
-+#endif
-+
-+static int __devinit snd_intelmad_sst_register(
-+ struct snd_intelmad *intelmaddata)
-+{
-+ int ret_val;
-+ struct sc_reg_access pmic_reg = {0,};
-+
-+ pmic_reg.reg_addr = 0;
-+ ret_val = sst_sc_reg_access(&pmic_reg, PMIC_READ, 1);
-+
-+ if (ret_val)
-+ return ret_val;
-+
-+ sst_card_vendor_id = pmic_reg.value & (MASK2|MASK1|MASK0);
-+ printk(KERN_DEBUG "SST DBG:orginal reg n extrated vendor id = 0x%x %d\n",
-+ pmic_reg.value, sst_card_vendor_id);
-+ if (sst_card_vendor_id < 0 || sst_card_vendor_id > 2) {
-+ dev_err(&intelmaddata->spi->dev, \
-+ "SST ERR: vendor card not supported!! \n");
-+ return -EIO;
-+ }
-+ intelmaddata->sstdrv_ops->module_name = SST_CARD_NAMES;
-+ intelmaddata->sstdrv_ops->vendor_id = sst_card_vendor_id;
-+ intelmaddata->sstdrv_ops->scard_ops =
-+ intelmad_vendor_ops[sst_card_vendor_id];
-+
-+ /* registering with SST driver to get access to SST APIs to use */
-+ ret_val = register_sst_card(intelmaddata->sstdrv_ops);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev, \
-+ "SST ERR: sst card registration failed \n");
-+ return ret_val;
-+ }
-+
-+ sst_card_vendor_id = intelmaddata->sstdrv_ops->vendor_id;
-+ intelmaddata->pmic_status = PMIC_UNINIT;
-+ return ret_val;
-+}
-+
-+/* Driver Init/exit functionalities */
-+/**
-+* snd_intelmad_pcm- to setup pcm for the card
-+* @card: pointer to the sound card structure
-+*@intelmaddata: pointer to internal context
-+* This function is called from probe function to set up pcm params and functions
-+*/
-+static int __devinit snd_intelmad_pcm(struct snd_card *card,
-+ struct snd_intelmad *intelmaddata)
-+{
-+ struct snd_pcm *pcm;
-+ int i, ret_val = 0;
-+ char name[32] = INTEL_MAD;
-+
-+ WARN_ON(!card);
-+ WARN_ON(!intelmaddata);
-+
-+ for (i = 0; i < MAX_DEVICES; i++) {
-+ ret_val = snd_pcm_new(card, name, i, PLAYBACK_COUNT,
-+ CAPTURE_COUNT, &pcm);
-+ if (ret_val)
-+ break;
-+ /* setup the ops for playback and capture streams */
-+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+ &snd_intelmad_playback_ops);
-+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-+ &snd_intelmad_capture_ops);
-+ /* setup private data which can be retrieved when required */
-+ pcm->private_data = intelmaddata;
-+ pcm->info_flags = 0;
-+ strncpy(pcm->name, card->shortname, strlen(card->shortname));
-+ /* allocate dma pages for ALSA stream operations */
-+ snd_pcm_lib_preallocate_pages_for_all(pcm,
-+ SNDRV_DMA_TYPE_CONTINUOUS,
-+ snd_dma_continuous_data(GFP_KERNEL),
-+ MIN_BUFFER, MAX_BUFFER);
-+ }
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_jack- to setup jack settings of the card
-+*@intelmaddata: pointer to internal context
-+* This function is called from probe function to set up mixer controls
-+*/
-+static int __devinit snd_intelmad_jack(struct snd_intelmad *intelmaddata)
-+{
-+ struct snd_jack *jack;
-+ int retval;
-+
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+ jack = &intelmaddata->jack[0].jack;
-+ retval = snd_jack_new(intelmaddata->card, "Headphone",
-+ SND_JACK_HEADPHONE, &jack);
-+ if (retval < 0)
-+ return retval;
-+ snd_jack_report(jack, 0);
-+
-+ jack->private_data = jack;
-+ intelmaddata->jack[0].jack = *jack;
-+
-+
-+ jack = &intelmaddata->jack[1].jack;
-+ retval = snd_jack_new(intelmaddata->card, "Headset",
-+ SND_JACK_HEADSET, &jack);
-+ if (retval < 0)
-+ return retval;
-+
-+
-+
-+ jack->private_data = jack;
-+ intelmaddata->jack[1].jack = *jack;
-+
-+
-+ jack = &intelmaddata->jack[2].jack;
-+ retval = snd_jack_new(intelmaddata->card, "Short Press",
-+ SND_JACK_HS_SHORT_PRESS, &jack);
-+ if (retval < 0)
-+ return retval;
-+
-+
-+ jack->private_data = jack;
-+ intelmaddata->jack[2].jack = *jack;
-+
-+
-+ jack = &intelmaddata->jack[3].jack;
-+ retval = snd_jack_new(intelmaddata->card, "Long Press",
-+ SND_JACK_HS_LONG_PRESS, &jack);
-+ if (retval < 0)
-+ return retval;
-+
-+
-+ jack->private_data = jack;
-+ intelmaddata->jack[3].jack = *jack;
-+
-+ return retval;
-+}
-+
-+/**
-+* snd_intelmad_mixer- to setup mixer settings of the card
-+*@intelmaddata: pointer to internal context
-+* This function is called from probe function to set up mixer controls
-+*/
-+static int __devinit snd_intelmad_mixer(struct snd_intelmad *intelmaddata)
-+{
-+ struct snd_card *card;
-+ unsigned int idx;
-+ int ret_val = 0;
-+ char *mixername = "IntelMAD Controls";
-+
-+ WARN_ON(!intelmaddata);
-+
-+ card = intelmaddata->card;
-+
-+ strncpy(card->mixername, mixername, strlen(mixername));
-+ /* add all widget controls and expose the same */
-+ for (idx = 0; idx < MAX_CTRL; idx++) {
-+ ret_val = snd_ctl_add(card,
-+ snd_ctl_new1(&snd_intelmad_controls[idx],
-+ intelmaddata));
-+ printk(KERN_DEBUG "SST DBG:mixer[idx]=%d added \n", idx);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev, \
-+ "SST ERR: adding of control +\
-+ failed index = %d \n", idx);
-+ break;
-+ }
-+ }
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_dev_free- to free device
-+*@device: pointer to the device
-+* This function is called when driver module is removed
-+*/
-+static int snd_intelmad_dev_free(struct snd_device *device)
-+{
-+ struct snd_intelmad *intelmaddata;
-+
-+ WARN_ON(!device);
-+
-+ intelmaddata = device->device_data;
-+
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+ snd_card_free(intelmaddata->card);
-+ /*genl_unregister_family(&audio_event_genl_family);*/
-+ unregister_sst_card(intelmaddata->sstdrv_ops);
-+
-+ /* free allocated memory for internal context */
-+ destroy_workqueue(intelmaddata->mad_jack_wq);
-+ kfree(intelmaddata->sstdrv_ops);
-+ kfree(intelmaddata);
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_create- called from probe to create a snd device
-+*@intelmaddata : pointer to the internal context
-+*@card : pointer to the sound card
-+* This function is called when driver module is started
-+*/
-+static int __devinit snd_intelmad_create(
-+ struct snd_intelmad *intelmaddata,
-+ struct snd_card *card)
-+{
-+ int ret_val;
-+ static struct snd_device_ops ops = {
-+ .dev_free = snd_intelmad_dev_free,
-+ };
-+
-+ WARN_ON(!intelmaddata);
-+ WARN_ON(!card);
-+ /* ALSA api to register for the device */
-+ ret_val = snd_device_new(card, SNDRV_DEV_LOWLEVEL, intelmaddata, &ops);
-+ return ret_val;
-+}
-+
-+/*********************************************************************
-+ * SPI Functions
-+ *********************************************************************/
-+
-+
-+/**
-+* snd_intelmad_probe- function registred for init
-+*@spi : pointer to the spi device context
-+* This function is called when the device is initialized
-+*/
-+int __devinit snd_intelmad_probe(struct spi_device *spi)
-+{
-+ struct snd_card *card;
-+ int ret_val;
-+ struct snd_intelmad *intelmaddata;
-+
-+ printk(KERN_DEBUG "SST DBG:called \n");
-+
-+ /* allocate memory for saving internal context and working */
-+ intelmaddata = kzalloc(sizeof(*intelmaddata), GFP_KERNEL);
-+ if (!intelmaddata)
-+ return -ENOMEM;
-+
-+ /* allocate memory for LPE API set */
-+ intelmaddata->sstdrv_ops = kzalloc(sizeof(struct intel_sst_card_ops),
-+ GFP_KERNEL);
-+ if (!intelmaddata->sstdrv_ops) {
-+ dev_err(&intelmaddata->spi->dev, "SST ERR: +\
-+ mem alloctn fail \n");
-+ kfree(intelmaddata);
-+ return -ENOMEM;
-+ }
-+
-+ /* create a card instance with ALSA framework */
-+ ret_val = snd_card_create(card_index, card_id, THIS_MODULE, 0, &card);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev, "SST +\
-+ ERR: snd_card_create fail \n");
-+ goto free_allocs;
-+ }
-+
-+ intelmaddata->spi = spi;
-+ intelmaddata->irq = spi->irq;
-+ dev_set_drvdata(&spi->dev, intelmaddata);
-+ intelmaddata->card = card;
-+ intelmaddata->card_id = card_id;
-+ intelmaddata->card_index = card_index;
-+ intelmaddata->playback_cnt = intelmaddata->capture_cnt = 0;
-+ strncpy(card->driver, INTEL_MAD, strlen(INTEL_MAD));
-+ strncpy(card->shortname, INTEL_MAD, strlen(INTEL_MAD));
-+
-+
-+ intelmaddata->sstdrv_ops->module_name = SST_CARD_NAMES;
-+ /* registering with LPE driver to get access to SST APIs to use */
-+ ret_val = snd_intelmad_sst_register(intelmaddata);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR:+ snd_intelmad_sst_register failed \n");
-+ goto free_allocs;
-+ }
-+
-+ intelmaddata->pmic_status = PMIC_INIT;
-+
-+ ret_val = snd_intelmad_pcm(card, intelmaddata);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: snd_intelmad_pcm failed \n");
-+ goto free_allocs;
-+ }
-+
-+ ret_val = snd_intelmad_mixer(intelmaddata);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: snd_intelmad_mixer failed \n");
-+ goto free_allocs;
-+ }
-+
-+ ret_val = snd_intelmad_jack(intelmaddata);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: snd_intelmad_jack failed \n");
-+ goto free_allocs;
-+ }
-+
-+ /*create work queue for jack interrupt*/
-+
-+ INIT_WORK(&intelmaddata->mad_jack_msg.wq, \
-+ sst_process_mad_jack_detection);
-+
-+ intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");
-+ if (!intelmaddata->mad_jack_wq)
-+ goto free_mad_jack_wq;
-+
-+#ifdef REG_IRQ
-+ ret_val = snd_intelmad_register_irq(intelmaddata);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: snd_intelmad_register_irq fail \n");
-+ goto free_allocs;
-+ }
-+ /*ret_val = snd_intelmad_register_netlink();
-+ if (ret_val) {
-+ printk(KERN_DEBUG "SST DBG:...complete\n");
-+ return ret_val;
-+ }*/
-+#endif
-+
-+ /* internal function call to register device with ALSA */
-+ ret_val = snd_intelmad_create(intelmaddata, card);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: snd_intelmad_create failed \n");
-+ goto free_allocs;
-+ }
-+ card->private_data = &intelmaddata;
-+ snd_card_set_dev(card, &spi->dev);
-+ ret_val = snd_card_register(card);
-+ if (ret_val) {
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: snd_card_register failed \n");
-+ goto free_allocs;
-+ }
-+
-+ printk(KERN_DEBUG "SST DBG:...complete\n");
-+ return ret_val;
-+
-+free_mad_jack_wq:
-+ destroy_workqueue(intelmaddata->mad_jack_wq);
-+
-+free_allocs:
-+ /* TODO: unregister IRQ */
-+ dev_err(&intelmaddata->spi->dev, "SST ERR: probe failed \n");
-+ /* snd_card_free(card); */
-+ kfree(intelmaddata->sstdrv_ops);
-+ kfree(intelmaddata);
-+ return ret_val;
-+}
-+
-+
-+/**
-+* snd_intelmad_remove- function registred for exit
-+*@spi : pointer to the spi device context
-+* This function is called when the device is uninitialized
-+*/
-+static int snd_intelmad_remove(struct spi_device *spi)
-+{
-+ struct snd_intelmad *intelmaddata =
-+ dev_get_drvdata(&spi->dev);
-+ /*
-+ * TODO:: de-register interrupt handler
-+ */
-+
-+ if (intelmaddata) {
-+ snd_card_free(intelmaddata->card);
-+ /*genl_unregister_family(&audio_event_genl_family);*/
-+ unregister_sst_card(intelmaddata->sstdrv_ops);
-+ /* free allocated memory for internal context */
-+ destroy_workqueue(intelmaddata->mad_jack_wq);
-+ kfree(intelmaddata->sstdrv_ops);
-+ kfree(intelmaddata);
-+ }
-+ return 0;
-+}
-+
-+/*********************************************************************
-+ * Driver initialization and exit
-+ *********************************************************************/
-+
-+static struct spi_driver snd_intelmad_driver = {
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .bus = &spi_bus_type,
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = snd_intelmad_probe,
-+ .remove = __devexit_p(snd_intelmad_remove),
-+};
-+
-+/*
-+* alsa_card_intelmad_init- driver init function
-+* This function is called when driver module is inserted
-+*/
-+static int __init alsa_card_intelmad_init(void)
-+{
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+ return spi_register_driver(&snd_intelmad_driver);
-+}
-+
-+/**
-+* alsa_card_intelmad_exit- driver exit function
-+* This function is called when driver module is removed
-+*/
-+static void __exit alsa_card_intelmad_exit(void)
-+{
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+ spi_unregister_driver(&snd_intelmad_driver);
-+}
-+
-+module_init(alsa_card_intelmad_init)
-+module_exit(alsa_card_intelmad_exit)
-+
-diff --git a/sound/pci/sst/intelmid.h b/sound/pci/sst/intelmid.h
-new file mode 100644
-index 0000000..235115e
---- /dev/null
-+++ b/sound/pci/sst/intelmid.h
-@@ -0,0 +1,170 @@
-+/*
-+ * intelmid.h - Intel Sound card driver for MID
-+ *
-+ * Copyright (C) 2008-10 Intel Corp
-+ * Authors: Harsha Priya <priya.harsha@intel.com>
-+ * Vinod Koul <vinod.koul@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.
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ * ALSA driver header for Intel MAD chipset
-+ */
-+#ifndef __INTELMID_H
-+#define __INTELMID_H
-+
-+#include <linux/time.h>
-+
-+#define DRIVER_NAME "pmic_audio"
-+#define PMIC_SOUND_IRQ_TYPE_MASK (1 << 15)
-+#define AUDINT_BASE (0xFFFFEFF8 + (6 * sizeof(u8)))
-+#define REG_IRQ
-+/* values #defined */
-+/* will differ for different hw - to be taken from config */
-+#define MAX_DEVICES 1
-+#define MIN_RATE 8000
-+#define MAX_RATE 48000
-+#define MAX_BUFFER (128*1024) /* TBD for PCM */
-+#define MIN_BUFFER (128*1024)
-+#define MAX_PERIODS (1024)
-+#define MIN_PERIODS 2
-+#define MAX_PERIOD_BYTES MAX_BUFFER
-+//#define MIN_PERIOD_BYTES 32
-+#define MIN_PERIOD_BYTES 160
-+#define MAX_MUTE 1
-+#define MIN_MUTE 0
-+#define MONO_CNTL 1
-+#define STEREO_CNTL 2
-+#define MIN_CHANNEL 1
-+#define MAX_CHANNEL 2
-+#define FIFO_SIZE 0 /* fifo not being used */
-+#define INTEL_MAD "Intel MAD"
-+#define MAX_CTRL 7
-+#define MAX_VENDORS 3
-+/* TODO +6 db */
-+#define MAX_VOL 64
-+/* TODO -57 db */
-+#define MIN_VOL 0
-+#define PLAYBACK_COUNT 1
-+#define CAPTURE_COUNT 1
-+
-+extern int sst_card_vendor_id;
-+
-+struct mad_jack {
-+ struct snd_jack jack;
-+ int jack_status;
-+ struct timeval buttonpressed;
-+ struct timeval buttonreleased;
-+};
-+struct mad_jack_msg_wq {
-+ u8 intsts;
-+ struct snd_intelmad *intelmaddata;
-+ struct work_struct wq;
-+
-+};
-+struct snd_intelmad {
-+ struct snd_card *card; /* ptr to the card details */
-+ int card_index;/* card index */
-+ char *card_id; /* card id */
-+ struct intel_sst_card_ops *sstdrv_ops;/* ptr to sst driver ops */
-+ struct spi_device *spi;
-+ int irq;
-+ int pmic_status;
-+ void __iomem *int_base;
-+ int output_sel;
-+ int input_sel;
-+ int master_mute;
-+ struct mad_jack jack[4];
-+ int playback_cnt;
-+ int capture_cnt;
-+ struct mad_jack_msg_wq mad_jack_msg;
-+ struct workqueue_struct *mad_jack_wq;
-+ u8 jack_prev_state;
-+};
-+
-+struct snd_control_val {
-+ int playback_vol_max;
-+ int playback_vol_min;
-+ int capture_vol_max;
-+ int capture_vol_min;
-+};
-+
-+struct mad_stream_pvt {
-+ int stream_status;
-+ int stream_ops;
-+ struct snd_pcm_substream *substream;
-+ struct snd_pcm_indirect pcm_indirect;
-+ struct pcm_stream_info stream_info;
-+ ssize_t dbg_cum_bytes;
-+};
-+
-+enum mad_drv_status {
-+ INIT = 1,
-+ STARTED,
-+ RUNNING,
-+ PAUSED,
-+ DROPPED,
-+};
-+
-+enum mad_pmic_status {
-+ PMIC_UNINIT = 1,
-+ PMIC_INIT,
-+};
-+enum _widget_ctrl {
-+ PLAYBACK_VOL = 1 ,
-+ PLAYBACK_MUTE,
-+ CAPTURE_VOL,
-+ CAPTURE_MUTE,
-+ OUTPUT_SEL,
-+ INPUT_SEL,
-+ MASTER_MUTE
-+};
-+
-+/*enum {
-+ AUDIO_GENL_ATTR_UNSPEC = 0,
-+ AUDIO_GENL_ATTR_EVENT,
-+ AUDIO_GENL_ATTR_MAX,
-+};
-+enum {
-+ AUDIO_GENL_CMD_UNSPEC,
-+ AUDIO_GENL_CMD_EVENT,
-+ AUDIO_GENL_CMD_MAX,
-+};
-+
-+enum eaudio_events {
-+ AUDIO_EVENT_HP_DETECT,
-+ AUDIO_EVENT_HS_DETECT,
-+ AUDIO_EVENT_SHORT_PRESS,
-+ AUDIO_EVENT_LONG_PRESS,
-+ AUDIO_EVENT_COUNT,
-+};
-+
-+struct audio_genl_event {
-+ u32 orig;
-+ enum eaudio_events event;
-+};*/
-+
-+
-+void period_elapsed(void *mad_substream);
-+int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream);
-+int snd_intelmad_init_stream(struct snd_pcm_substream *substream);
-+void send_buffer_to_sst(struct snd_pcm_substream *substream,
-+ struct snd_pcm_indirect *rec, size_t bytes);
-+int sst_sc_reg_access(struct sc_reg_access *sc_access,
-+ int type, int num_val);
-+
-+
-+#endif /* __INTELMID_H */
-diff --git a/sound/pci/sst/intelmid_ctrl.c b/sound/pci/sst/intelmid_ctrl.c
-new file mode 100644
-index 0000000..f778628
---- /dev/null
-+++ b/sound/pci/sst/intelmid_ctrl.c
-@@ -0,0 +1,555 @@
-+/*
-+ * intelmid_ctrl.c - Intel Sound card driver for MID
-+ *
-+ * Copyright (C) 2008-10 Intel Corp
-+ * Authors: Harsha Priya <priya.harsha@intel.com>
-+ * Vinod Koul <vinod.koul@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.
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ * ALSA driver handling mixer controls for Intel MAD chipset
-+ */
-+#include <linux/spi/spi.h>
-+#include <linux/io.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/moduleparam.h>
-+#include <linux/sched.h>
-+#include <sound/core.h>
-+#include <sound/control.h>
-+#include <sound/pcm.h>
-+#include <sound/jack.h>
-+#include <sound/pcm_params.h>
-+#include <sound/info.h>
-+#include <sound/initval.h>
-+#include <sound/pcm-indirect.h>
-+#include <sound/intel_lpe.h>
-+#include <sound/intel_sst_ioctl.h>
-+#include "intelmid_snd_control.h"
-+#include "intelmid.h"
-+
-+static char *out_names[] = {"Headphones",
-+ "Internal speakers"};
-+static char *in_names[] = {"HS_MIC",
-+ "AMIC",
-+ "DMIC"};
-+
-+struct snd_pmic_ops *intelmad_vendor_ops[MAX_VENDORS] = {
-+ &snd_pmic_ops_fs,
-+ &snd_pmic_ops_mx,
-+ &snd_pmic_ops_nc
-+};
-+
-+struct snd_control_val intelmad_ctrl_val[MAX_VENDORS] = {
-+ {
-+ .playback_vol_max = 63,
-+ .playback_vol_min = 0,
-+ .capture_vol_max = 63,
-+ .capture_vol_min = 0,
-+ },
-+ {
-+ .playback_vol_max = 0,
-+ .playback_vol_min = -31,
-+ .capture_vol_max = 0,
-+ .capture_vol_min = -20,
-+ },
-+ {
-+ .playback_vol_max = 0,
-+ .playback_vol_min = -126,
-+ .capture_vol_max = 0,
-+ .capture_vol_min = -31,
-+ },
-+};
-+
-+/* control path functionalities */
-+
-+static inline int snd_intelmad_volume_info(struct snd_ctl_elem_info *uinfo,
-+ int control_type, int max, int min)
-+{
-+ WARN_ON(!uinfo);
-+
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-+ uinfo->count = control_type;
-+ uinfo->value.integer.min = min;
-+ uinfo->value.integer.max = max;
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_mute_info - provides information about the mute controls
-+* @kcontrol: pointer to the control
-+* @uinfo: pointer to the structure where the control's info need
-+* to be filled
-+* This function is called when a mixer application requests for control's info
-+*/
-+static int snd_intelmad_mute_info(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ WARN_ON(!uinfo);
-+ WARN_ON(!kcontrol);
-+
-+ /* set up the mute as a boolean mono control with min-max values */
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-+ uinfo->count = MONO_CNTL;
-+ uinfo->value.integer.min = MIN_MUTE;
-+ uinfo->value.integer.max = MAX_MUTE;
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_capture_volume_info - provides info about the volume control
-+* @kcontrol: pointer to the control
-+* @uinfo: pointer to the structure where the control's info need
-+* to be filled
-+* This function is called when a mixer application requests for control's info
-+*/
-+static int snd_intelmad_capture_volume_info(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ snd_intelmad_volume_info(uinfo, MONO_CNTL,
-+ intelmad_ctrl_val[sst_card_vendor_id].capture_vol_max,
-+ intelmad_ctrl_val[sst_card_vendor_id].capture_vol_min);
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_playback_volume_info - provides info about the volume control
-+* @kcontrol: pointer to the control
-+* @uinfo: pointer to the structure where the control's info need
-+* to be filled
-+* This function is called when a mixer application requests for control's info
-+*/
-+static int snd_intelmad_playback_volume_info(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ snd_intelmad_volume_info(uinfo, STEREO_CNTL,
-+ intelmad_ctrl_val[sst_card_vendor_id].playback_vol_max,
-+ intelmad_ctrl_val[sst_card_vendor_id].playback_vol_min);
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_device_info - provides information about the devices available
-+* @kcontrol: pointer to the control
-+* @uinfo: pointer to the structure where the devices's info need
-+* to be filled
-+* This function is called when a mixer application requests for device's info
-+*/
-+static int snd_intelmad_device_info(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ WARN_ON(!kcontrol);
-+ WARN_ON(!uinfo);
-+ /* setup device select as drop down controls with different values */
-+ if (kcontrol->id.numid == OUTPUT_SEL)
-+ uinfo->value.enumerated.items = ARRAY_SIZE(out_names);
-+ else
-+ uinfo->value.enumerated.items = ARRAY_SIZE(in_names);
-+ uinfo->count = MONO_CNTL;
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-+
-+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-+ uinfo->value.enumerated.item = 1;
-+ if (kcontrol->id.numid == OUTPUT_SEL)
-+ strncpy(uinfo->value.enumerated.name,
-+ out_names[uinfo->value.enumerated.item],
-+ strlen(out_names[uinfo->value.enumerated.item]));
-+ else
-+ strncpy(uinfo->value.enumerated.name,
-+ in_names[uinfo->value.enumerated.item],
-+ strlen(in_names[uinfo->value.enumerated.item]));
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_volume_get - gets the current volume for the control
-+* @kcontrol: pointer to the control
-+* @uval: pointer to the structure where the control's info need
-+* to be filled
-+* This function is called when .get function of a control is invoked from app
-+*/
-+static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *uval)
-+{
-+ int ret_val = 0, cntl_list[2] = {0,};
-+ u8 value = 0;
-+ struct snd_intelmad *intelmaddata;
-+ struct snd_pmic_ops *scard_ops;
-+
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+
-+ WARN_ON(!uval);
-+ WARN_ON(!kcontrol);
-+
-+ intelmaddata = kcontrol->private_data;
-+
-+ WARN_ON(!intelmaddata->sstdrv_ops);
-+
-+ scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-+
-+ WARN_ON(!scard_ops);
-+
-+ switch (kcontrol->id.numid) {
-+ case PLAYBACK_VOL:
-+ cntl_list[0] = PMIC_SND_RIGHT_PB_VOL;
-+ cntl_list[1] = PMIC_SND_LEFT_PB_VOL;
-+ break;
-+
-+ case CAPTURE_VOL:
-+ cntl_list[0] = PMIC_SND_CAPTURE_VOL;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ ret_val = scard_ops->get_vol(cntl_list[0], &value);
-+ uval->value.integer.value[0] = value;
-+
-+ if (ret_val)
-+ return ret_val;
-+
-+ if (kcontrol->id.numid == PLAYBACK_VOL) {
-+ ret_val = scard_ops->get_vol(cntl_list[1], &value);
-+ uval->value.integer.value[1] = value;
-+ }
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_mute_get - gets the current mute status for the control
-+* @kcontrol: pointer to the control
-+* @uval: pointer to the structure where the control's info need
-+* to be filled
-+* This function is called when .get function of a control is invoked from app
-+*/
-+static int snd_intelmad_mute_get(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *uval)
-+{
-+
-+ int cntl_list = 0, ret_val = 0;
-+ u8 value = 0;
-+ struct snd_intelmad *intelmaddata;
-+ struct snd_pmic_ops *scard_ops;
-+
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+
-+ WARN_ON(!uval);
-+ WARN_ON(!kcontrol);
-+
-+ intelmaddata = kcontrol->private_data;
-+
-+ WARN_ON(!intelmaddata->sstdrv_ops);
-+
-+ scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-+
-+ WARN_ON(!scard_ops);
-+
-+ switch (kcontrol->id.numid) {
-+ case PLAYBACK_MUTE:
-+ if (intelmaddata->output_sel == STEREO_HEADPHONE)
-+ cntl_list = PMIC_SND_LEFT_HP_MUTE;
-+ else if (intelmaddata->output_sel == INTERNAL_SPKR)
-+ cntl_list = PMIC_SND_LEFT_SPEAKER_MUTE;
-+ break;
-+
-+ case CAPTURE_MUTE:
-+ if (intelmaddata->input_sel == DMIC)
-+ cntl_list = PMIC_SND_DMIC_MUTE;
-+ else if (intelmaddata->input_sel == AMIC)
-+ cntl_list = PMIC_SND_AMIC_MUTE;
-+ else if (intelmaddata->input_sel == HS_MIC)
-+ cntl_list = PMIC_SND_HP_MIC_MUTE;
-+ break;
-+ case MASTER_MUTE:
-+ uval->value.integer.value[0] = intelmaddata->master_mute;
-+ return 0;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ ret_val = scard_ops->get_mute(cntl_list, &value);
-+ uval->value.integer.value[0] = value;
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_volume_set - sets the volume control's info
-+* @kcontrol: pointer to the control
-+* @uval: pointer to the structure where the control's info is
-+* available to be set
-+* This function is called when .set function of a control is invoked from app
-+*/
-+static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *uval)
-+{
-+
-+ int ret_val, cntl_list[2] = {0,};
-+ struct snd_intelmad *intelmaddata;
-+ struct snd_pmic_ops *scard_ops;
-+
-+ printk(KERN_DEBUG "SST DBG:volume set called:%ld %ld \n",
-+ uval->value.integer.value[0],
-+ uval->value.integer.value[1]);
-+
-+ WARN_ON(!uval);
-+ WARN_ON(!kcontrol);
-+
-+ intelmaddata = kcontrol->private_data;
-+
-+ WARN_ON(!intelmaddata->sstdrv_ops);
-+
-+ scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-+
-+ WARN_ON(!scard_ops);
-+
-+ switch (kcontrol->id.numid) {
-+ case PLAYBACK_VOL:
-+ cntl_list[0] = PMIC_SND_LEFT_PB_VOL;
-+ cntl_list[1] = PMIC_SND_RIGHT_PB_VOL;
-+ break;
-+
-+ case CAPTURE_VOL:
-+ cntl_list[0] = PMIC_SND_CAPTURE_VOL;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ ret_val = scard_ops->set_vol(cntl_list[0],
-+ uval->value.integer.value[0]);
-+ if (ret_val)
-+ return ret_val;
-+
-+ if (kcontrol->id.numid == PLAYBACK_VOL)
-+ ret_val = scard_ops->set_vol(cntl_list[1],
-+ uval->value.integer.value[1]);
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_mute_set - sets the mute control's info
-+* @kcontrol: pointer to the control
-+* @uval: pointer to the structure where the control's info is
-+* available to be set
-+* This function is called when .set function of a control is invoked from app
-+*/
-+static int snd_intelmad_mute_set(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *uval)
-+{
-+ int cntl_list[2] = {0,}, ret_val;
-+ struct snd_intelmad *intelmaddata;
-+ struct snd_pmic_ops *scard_ops;
-+
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+
-+ WARN_ON(!uval);
-+ WARN_ON(!kcontrol);
-+
-+ intelmaddata = kcontrol->private_data;
-+
-+ WARN_ON(!intelmaddata->sstdrv_ops);
-+
-+ scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-+
-+ WARN_ON(!scard_ops);
-+
-+ kcontrol->private_value = uval->value.integer.value[0];
-+
-+ switch (kcontrol->id.numid) {
-+ case PLAYBACK_MUTE:
-+ if (intelmaddata->output_sel == STEREO_HEADPHONE) {
-+ cntl_list[0] = PMIC_SND_LEFT_HP_MUTE;
-+ cntl_list[1] = PMIC_SND_RIGHT_HP_MUTE;
-+ } else if (intelmaddata->output_sel == INTERNAL_SPKR) {
-+ cntl_list[0] = PMIC_SND_LEFT_SPEAKER_MUTE;
-+ cntl_list[1] = PMIC_SND_RIGHT_SPEAKER_MUTE;
-+ }
-+ break;
-+
-+ case CAPTURE_MUTE:/*based on sel device mute the i/p dev*/
-+ if (intelmaddata->input_sel == DMIC)
-+ cntl_list[0] = PMIC_SND_DMIC_MUTE;
-+ else if (intelmaddata->input_sel == AMIC)
-+ cntl_list[0] = PMIC_SND_AMIC_MUTE;
-+ else if (intelmaddata->input_sel == HS_MIC)
-+ cntl_list[0] = PMIC_SND_HP_MIC_MUTE;
-+ break;
-+ case MASTER_MUTE:
-+ cntl_list[0] = PMIC_SND_MUTE_ALL;
-+ intelmaddata->master_mute = uval->value.integer.value[0];
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ ret_val = scard_ops->set_mute(cntl_list[0],
-+ uval->value.integer.value[0]);
-+ if (ret_val)
-+ return ret_val;
-+
-+ if (kcontrol->id.numid == PLAYBACK_MUTE)
-+ ret_val = scard_ops->set_mute(cntl_list[1],
-+ uval->value.integer.value[0]);
-+ return ret_val;
-+}
-+
-+/**
-+* snd_intelmad_device_get - get the device select control's info
-+* @kcontrol: pointer to the control
-+* @uval: pointer to the structure where the control's info is
-+* to be filled
-+* This function is called when .get function of a control is invoked from app
-+*/
-+static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *uval)
-+{
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+
-+ WARN_ON(!uval);
-+ WARN_ON(!kcontrol);
-+
-+ uval->value.enumerated.item[0] = kcontrol->private_value;
-+ return 0;
-+}
-+
-+/**
-+* snd_intelmad_device_set - set the device select control's info
-+* @kcontrol: pointer to the control
-+* @uval: pointer to the structure where the control's info is
-+* available to be set
-+* This function is called when .set function of a control is invoked from app
-+*/
-+static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *uval)
-+{
-+ struct snd_intelmad *intelmaddata;
-+ struct snd_pmic_ops *scard_ops;
-+ int ret_val = 0, vendor, status;
-+
-+ printk(KERN_DEBUG "SST DBG:called\n");
-+
-+ WARN_ON(!uval);
-+ WARN_ON(!kcontrol);
-+ status = -1;
-+
-+ intelmaddata = kcontrol->private_data;
-+
-+ WARN_ON(!intelmaddata->sstdrv_ops);
-+
-+ scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-+
-+ WARN_ON(!scard_ops);
-+
-+ /* store value with driver */
-+ kcontrol->private_value = uval->value.enumerated.item[0];
-+
-+ switch (kcontrol->id.numid) {
-+ case OUTPUT_SEL:
-+ ret_val = scard_ops->set_output_dev(
-+ uval->value.enumerated.item[0]);
-+ intelmaddata->output_sel = uval->value.enumerated.item[0];
-+ break;
-+ case INPUT_SEL:
-+ vendor = intelmaddata->sstdrv_ops->vendor_id;
-+ if ((vendor == SND_MX) || (vendor == SND_FS )) {
-+ if(uval->value.enumerated.item[0] == HS_MIC) {
-+ status = 1;
-+ intelmaddata->sstdrv_ops->control_set(SST_ENABLE_RX_TIME_SLOT, &status);
-+ }
-+ else {
-+ status = 0;
-+ intelmaddata->sstdrv_ops->control_set(SST_ENABLE_RX_TIME_SLOT, &status);
-+ }
-+ }
-+ ret_val = scard_ops->set_input_dev(
-+ uval->value.enumerated.item[0]);
-+ intelmaddata->input_sel = uval->value.enumerated.item[0];
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ kcontrol->private_value = uval->value.enumerated.item[0];
-+ return ret_val;
-+}
-+
-+struct snd_kcontrol_new snd_intelmad_controls[MAX_CTRL] __devinitdata = {
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "PCM Playback Volume",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_intelmad_playback_volume_info,
-+ .get = snd_intelmad_volume_get,
-+ .put = snd_intelmad_volume_set,
-+ .private_value = 0,
-+},
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "PCM Playback Switch",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_intelmad_mute_info,
-+ .get = snd_intelmad_mute_get,
-+ .put = snd_intelmad_mute_set,
-+ .private_value = 0,
-+},
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "PCM Capture Volume",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_intelmad_capture_volume_info,
-+ .get = snd_intelmad_volume_get,
-+ .put = snd_intelmad_volume_set,
-+ .private_value = 0,
-+},
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "PCM Capture Switch",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_intelmad_mute_info,
-+ .get = snd_intelmad_mute_get,
-+ .put = snd_intelmad_mute_set,
-+ .private_value = 0,
-+},
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "PCM Playback Source",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_intelmad_device_info,
-+ .get = snd_intelmad_device_get,
-+ .put = snd_intelmad_device_set,
-+ .private_value = 0,
-+},
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "PCM Capture Source",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_intelmad_device_info,
-+ .get = snd_intelmad_device_get,
-+ .put = snd_intelmad_device_set,
-+ .private_value = 0,
-+},
-+{
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "Master Playback Switch",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = snd_intelmad_mute_info,
-+ .get = snd_intelmad_mute_get,
-+ .put = snd_intelmad_mute_set,
-+ .private_value = 0,
-+},
-+};
-diff --git a/sound/pci/sst/intelmid_ctrl.h b/sound/pci/sst/intelmid_ctrl.h
-new file mode 100644
-index 0000000..fa5feaf
---- /dev/null
-+++ b/sound/pci/sst/intelmid_ctrl.h
-@@ -0,0 +1,33 @@
-+/*
-+ * intelmid_ctrl.h - Intel Sound card driver for MID
-+ *
-+ * Copyright (C) 2008-10 Intel Corp
-+ * Authors: Harsha Priya <priya.harsha@intel.com>
-+ * Vinod Koul <vinod.koul@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.
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ * ALSA driver header file for handling mixer controls for Intel MAD chipset
-+ */
-+#ifndef __INTELMID_CTRL_H
-+#define __INTELMID_CTRL_H
-+
-+extern struct snd_control_val intelmad_ctrl_val[];
-+extern struct snd_kcontrol_new snd_intelmad_controls[];
-+extern struct snd_pmic_ops *intelmad_vendor_ops[];
-+
-+#endif /*__INTELMID_CTRL_H*/
-diff --git a/sound/pci/sst/intelmid_pvt.c b/sound/pci/sst/intelmid_pvt.c
-new file mode 100644
-index 0000000..1dd00c3
---- /dev/null
-+++ b/sound/pci/sst/intelmid_pvt.c
-@@ -0,0 +1,343 @@
-+/*
-+ * intelmid_pvt.h - Intel Sound card driver for MID
-+ *
-+ * Copyright (C) 2008-10 Intel Corp
-+ * Authors: Harsha Priya <priya.harsha@intel.com>
-+ * Vinod Koul <vinod.koul@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.
-+ *
-+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+ * ALSA driver for Intel MID sound card chipset - holding private functions
-+ */
-+#include <linux/spi/spi.h>
-+#include <linux/io.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/moduleparam.h>
-+#include <linux/sched.h>
-+#include <asm/ipc_defs.h>
-+#include <sound/core.h>
-+#include <sound/control.h>
-+#include <sound/pcm.h>
-+#include <sound/jack.h>
-+#include <sound/pcm_params.h>
-+#include <sound/info.h>
-+#include <sound/initval.h>
-+#include <sound/pcm-indirect.h>
-+#include <sound/intel_lpe.h>
-+#include <sound/intel_sst_ioctl.h>
-+#include "intelmid_snd_control.h"
-+#include "intelmid.h"
-+
-+
-+/*static unsigned int audio_event_seqnum;
-+static struct genl_family audio_event_genl_family = {
-+ .id = GENL_ID_GENERATE,
-+ .name = "audio events",
-+ .version = 0x01,
-+ .maxattr = 0,
-+};
-+
-+static struct genl_multicast_group audio_event_mcgrp = {
-+ .name = "audio_group",
-+};
-+*/
-+
-+void period_elapsed(void *mad_substream)
-+{
-+ struct snd_pcm_substream *substream = mad_substream;
-+ struct mad_stream_pvt *stream;
-+
-+ if (!substream || !substream->runtime)
-+ return;
-+ stream = substream->runtime->private_data;
-+ if (!stream)
-+ return;
-+
-+// printk(KERN_DEBUG "SST DBG:called\n");
-+ if (stream->stream_status != RUNNING)
-+ return;
-+// printk(KERN_DEBUG "SST DBG:calling period elapsed\n");
-+ snd_pcm_period_elapsed(substream);
-+ return;
-+}
-+
-+
-+int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream)
-+{
-+ struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
-+ struct mad_stream_pvt *stream = substream->runtime->private_data;
-+ unsigned int bits_per_sec = (substream->runtime->sample_bits/8)
-+ * (substream->runtime->channels)
-+ * (substream->runtime->rate);
-+ struct snd_sst_stream_params param = {{{0,},},};
-+ struct snd_sst_params str_params = {0};
-+ int ret_val;
-+
-+ /* set codec params and inform SST driver the same */
-+
-+ param.uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
-+ param.uc.pcm_params.brate = bits_per_sec;
-+ param.uc.pcm_params.num_chan = (u8) substream->runtime->channels;
-+ param.uc.pcm_params.sfreq = substream->runtime->rate;
-+ param.uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
-+// param.uc.pcm_params.frame_size = 0;
-+// param.uc.pcm_params.samples_per_frame = 250; /* FIXME */
-+ param.uc.pcm_params.buffer_size = substream->runtime->buffer_size;
-+ param.uc.pcm_params.period_count = substream->runtime->period_size;
-+ printk(KERN_DEBUG "SST DBG:period_count +\
-+ = %d\n", param.uc.pcm_params.period_count);
-+ printk(KERN_DEBUG "SST DBG:sfreq= %d, wd_sz = %d\n", +\
-+ param.uc.pcm_params.sfreq, param.uc.pcm_params.pcm_wd_sz);
-+
-+ str_params.sparams = param;
-+ str_params.codec = SST_CODEC_TYPE_PCM;
-+
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ str_params.ops = STREAM_OPS_PLAYBACK;
-+ else
-+ str_params.ops = STREAM_OPS_CAPTURE;
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_ALLOC,
-+ &str_params);
-+ printk(KERN_DEBUG "SST DBG:SST_SND_PLAY/CAPTURE ret_val = %x\n",
-+ ret_val);
-+ if (ret_val < 0)
-+ return ret_val;
-+
-+ stream->stream_info.str_id = ret_val;
-+ stream->stream_status = INIT;
-+ stream->stream_info.buffer_ptr = 0;
-+ printk(KERN_DEBUG "SST DBG:str id : %d\n", stream->stream_info.str_id);
-+
-+ return ret_val;
-+}
-+
-+int snd_intelmad_init_stream(struct snd_pcm_substream *substream)
-+{
-+ struct mad_stream_pvt *stream = substream->runtime->private_data;
-+ struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
-+ int ret_val;
-+
-+ printk(KERN_DEBUG "SST DBG:setting buffer ptr param\n");
-+ stream->stream_info.period_elapsed = period_elapsed;
-+ stream->stream_info.mad_substream = substream;
-+ stream->stream_info.buffer_ptr = 0;
-+ stream->stream_info.sfreq = substream->runtime->rate;
-+ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_STREAM_INIT,
-+ &stream->stream_info);
-+ if (ret_val)
-+ dev_err(&intelmaddata->spi->dev,\
-+ "SST ERR: error code = %d \n", ret_val);
-+ return ret_val;
-+
-+}
-+
-+void send_buffer_to_sst(struct snd_pcm_substream *substream,
-+ struct snd_pcm_indirect *rec, size_t bytes)
-+{
-+ struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream);
-+ struct mad_stream_pvt *stream = substream->runtime->private_data;
-+ struct stream_buffer buffer_to_sst = {0,};
-+ int ret_val;
-+
-+ /* sends data to SST to be processed */
-+ stream->dbg_cum_bytes += bytes;
-+ printk(KERN_DEBUG "SST DBG:bytes = %d \n", bytes);
-+ printk(KERN_DEBUG "SST DBG:cum_bytes +\
-+ = 0x%x, \n", stream->dbg_cum_bytes);
-+ buffer_to_sst.length = bytes;
-+ buffer_to_sst.addr = (unsigned long) substream->runtime->dma_area +
-+ rec->sw_data;
-+ /* SST API to actually send the buffer to be played */
-+ ret_val = intelmaddata->sstdrv_ops->send_buffer(
-+ stream->stream_info.str_id,
-+ &buffer_to_sst);
-+ printk(KERN_DEBUG "SST DBG:send_buffer +\
-+ ret_val = 0x%x \n", ret_val);
-+ return;
-+}
-+
-+/*int snd_intelmad_generate_netlink(u32 orig, enum eaudio_events event)
-+{
-+ struct sk_buff *skb = NULL;
-+ struct nlattr *attr = NULL;
-+ struct audio_genl_event *aud_event = NULL;
-+ void *msg_header = NULL;
-+ int size = 0, ret_val = 0;
-+
-+
-+ size = nla_total_size(sizeof(struct audio_genl_event)) + \
-+ nla_total_size(0);
-+
-+ skb = genlmsg_new(size, GFP_ATOMIC);
-+ if (!skb)
-+ return -ENOMEM;
-+
-+
-+ msg_header = genlmsg_put(skb, 0, audio_event_seqnum++,
-+ &audio_event_genl_family, 0,
-+ AUDIO_GENL_CMD_EVENT);
-+ if (!msg_header) {
-+ nlmsg_free(skb);
-+ return -ENOMEM;
-+ }
-+
-+ attr = nla_reserve(skb, AUDIO_GENL_ATTR_EVENT, \
-+ sizeof(struct audio_genl_event));
-+
-+ if (!attr) {
-+ nlmsg_free(skb);
-+ return -EINVAL;
-+ }
-+
-+ aud_event = nla_data(attr);
-+ if (!aud_event) {
-+ nlmsg_free(skb);
-+ return -EINVAL;
-+ }
-+
-+ memset(aud_event, 0, sizeof(struct audio_genl_event));
-+
-+ aud_event->orig = orig;
-+ aud_event->event = event;
-+
-+
-+ ret_val = genlmsg_end(skb, msg_header);
-+ if (ret_val < 0) {
-+ nlmsg_free(skb);
-+ return ret_val;
-+ }
-+
-+ ret_val = genlmsg_multicast(skb, 0, audio_event_mcgrp.id, GFP_ATOMIC);
-+
-+ if (ret_val)
-+ printk(KERN_INFO "Failed to send a Genetlink message!\n");
-+ return 0;
-+}*/
-+
-+
-+/**
-+* Reads/writes/read-modify operations on registers accessed through SCU (sound
-+* card and few SST DSP regsiters that are not accissible to IA)
-+*/
-+int sst_sc_reg_access(struct sc_reg_access *sc_access,
-+ int type, int num_val)
-+{
-+ int i, retval = 0, j = 0, k = 0, count = 0;
-+ struct ipc_pmic_reg_data reg_data;
-+ struct ipc_pmic_mod_reg_data pmic_mod_reg = {0};
-+
-+ reg_data.ioc = TRUE;
-+ if (type == PMIC_WRITE) {
-+ do {
-+ int max_retries = 0;
-+
-+ if (num_val <= 4)
-+ count = num_val;
-+ else
-+ count = 4;
-+retry_write:
-+ for (i = 0; i < count; i++, j++) {
-+ reg_data.pmic_reg_data[i].
-+ register_address = sc_access[j].reg_addr;
-+
-+ reg_data.pmic_reg_data[i].value =
-+ sc_access[j].value;
-+ }
-+ reg_data.num_entries = (u8) count;
-+ retval = ipc_pmic_register_write(&reg_data, 0);
-+ if (retval == E_NO_INTERRUPT_ON_IOC &&
-+ max_retries < 10) {
-+ printk(KERN_ERR "SST ERR: write communcation needs retry \n");
-+ max_retries++;
-+ goto retry_write;
-+ }
-+ if (0 != retval) {
-+ printk(KERN_ERR "SST ERR: pmic write failed \n");
-+ return retval;
-+ }
-+ num_val -= count;
-+ } while (num_val > 0);
-+ } else if (type == PMIC_READ) {
-+ do {
-+ int max_retries = 0;
-+ if (num_val <= 4)
-+ count = num_val;
-+ else
-+ count = 4;
-+retry_read:
-+ for (i = 0; i < count; i++, j++)
-+ reg_data.pmic_reg_data[i].register_address
-+ = sc_access[j].reg_addr;
-+ reg_data.num_entries = count;
-+ retval = ipc_pmic_register_read(&reg_data);
-+ if (retval == E_NO_INTERRUPT_ON_IOC &&
-+ max_retries < 10) {
-+ printk(KERN_ERR "ERR: read communcation needs retry \n");
-+ max_retries++;
-+ goto retry_read;
-+ }
-+ if (0 != retval) {
-+ printk(KERN_ERR "ERR: pmic read failed \n");
-+ return retval;
-+ }
-+
-+ for (i = 0; i < count; i++, k++)
-+ sc_access[k].value =
-+ reg_data.pmic_reg_data[i].value;
-+ num_val -= count;
-+ } while (num_val > 0);
-+ } else {
-+ pmic_mod_reg.ioc = TRUE;
-+ do {
-+ int max_retries = 0;
-+ if (num_val <= 4)
-+ count = num_val;
-+ else
-+ count = 4;
-+retry_readmod:
-+ for (i = 0; i < count; i++, j++) {
-+ pmic_mod_reg.pmic_mod_reg_data[i].
-+ register_address = sc_access[j].reg_addr;
-+ pmic_mod_reg.pmic_mod_reg_data[i].value =
-+ sc_access[j].value;
-+ pmic_mod_reg.pmic_mod_reg_data[i].bit_map =
-+ sc_access[j].mask;
-+ }
-+ pmic_mod_reg.num_entries = count;
-+ printk(KERN_DEBUG "SST DBG:read_modify +\
-+ called for cnt = %d\n", count);
-+ retval = ipc_pmic_register_read_modify(&pmic_mod_reg);
-+ if (retval == E_NO_INTERRUPT_ON_IOC &&
-+ max_retries < 10) {
-+ printk(KERN_ERR "SST ERR: read/modify retry \n");
-+ max_retries++;
-+ goto retry_readmod;
-+ }
-+ if (0 != retval) {
-+ /* pmic communication fails */
-+ printk(KERN_ERR "SST ERR: pmic read_modify failed \n");
-+ return retval;
-+ }
-+ num_val -= count;
-+ } while (num_val > 0);
-+ }
-+ return retval;
-+}
-+
---
-1.6.2.2
-