summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-1-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-1-8.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-1-8.patch1433
1 files changed, 0 insertions, 1433 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-1-8.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-1-8.patch
deleted file mode 100644
index 795bf1a3b..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-audio-driver-6.0-1-8.patch
+++ /dev/null
@@ -1,1433 +0,0 @@
-From c3cccfca9868aaf6e67a77c46a859a18d6384492 Mon Sep 17 00:00:00 2001
-From: R, Dharageswari <dharageswari.r@intel.com>
-Date: Thu, 29 Apr 2010 20:14:06 +0530
-Subject: [PATCH] ADR-Post-Beta-0.05.002.03-1/8-Adding Moorestown Audio Drivers - SST driver
-
-This patch is the first patch in the series of eight patches which add up SST
-driver and MAD driver. The SST driver is a driver for the SST DSP engine.This
-patch adds the SST driver main file intel_sst.c which contains the init, exit,
-probe, interrupt routine, as well as PCI suspend and resume implementations.
-intel_sst_dsp.c file implements the SST FW initialization as well as FW and
-library download steps.This patch also contains the intel_lpe.h header file
-which is placed in include folder for MAD driver (ALSA Sound card driver for
-Moorestown given in patch 7/8) to use. This file contains the definition of
-interfaces exposed by SST drivers along with definition of all the controls
-for the sound card to be used by MAD Driver
-
-Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-
- new file: include/sound/intel_lpe.h
- new file: sound/pci/sst/intel_sst.c
- new file: sound/pci/sst/intel_sst_dsp.c
-Patch-mainline: 2.6.35?
----
- include/sound/intel_lpe.h | 148 +++++++++
- sound/pci/sst/intel_sst.c | 527 ++++++++++++++++++++++++++++++
- sound/pci/sst/intel_sst_dsp.c | 706 +++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 1381 insertions(+), 0 deletions(-)
- create mode 100644 include/sound/intel_lpe.h
- create mode 100644 sound/pci/sst/intel_sst.c
- create mode 100644 sound/pci/sst/intel_sst_dsp.c
-
-diff --git a/include/sound/intel_lpe.h b/include/sound/intel_lpe.h
-new file mode 100644
-index 0000000..70e7a1f
---- /dev/null
-+++ b/include/sound/intel_lpe.h
-@@ -0,0 +1,148 @@
-+#ifndef __INTEL_SST_H__
-+#define __INTEL_SST_H__
-+/*
-+ * intel_lpe.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 driver exposes the audio engine functionalities to the ALSA
-+ * and middleware.
-+ * This file is shared between the SST and MAD drivers
-+ */
-+
-+#define SST_CARD_NAMES "intel_mid_card"
-+
-+/* control list Pmic & Lpe */
-+/* Input controls */
-+enum port_status {
-+ ACTIVATE = 1,
-+ DEACTIVATE,
-+};
-+
-+/* Card states */
-+enum sst_card_states {
-+ SND_CARD_UN_INIT = 0,
-+ SND_CARD_INIT_DONE,
-+};
-+
-+enum sst_controls {
-+ SST_SND_ALLOC = 0x1000,
-+ SST_SND_PAUSE = 0x1001,
-+ SST_SND_RESUME = 0x1002,
-+ SST_SND_DROP = 0x1003,
-+ SST_SND_FREE = 0x1004,
-+ SST_SND_BUFFER_POINTER = 0x1005,
-+ SST_SND_STREAM_INIT = 0x1006,
-+ SST_SND_START = 0x1007,
-+ SST_SND_STREAM_PROCESS = 0x1008,
-+ SST_MAX_CONTROLS = 0x1008,
-+ SST_CONTROL_BASE = 0x1000,
-+ SST_ENABLE_RX_TIME_SLOT = 0x1009,
-+
-+};
-+
-+struct pcm_stream_info {
-+ int str_id;
-+ void *mad_substream;
-+ void (*period_elapsed) (void *mad_substream);
-+ unsigned long long buffer_ptr;
-+ int sfreq;
-+};
-+
-+struct stream_buffer {
-+ unsigned long addr;
-+ int length;
-+};
-+
-+static inline long sst_get_time(void)
-+{
-+ struct timeval t;
-+ do_gettimeofday(&t);
-+ return t.tv_usec;
-+}
-+
-+#ifndef CONFIG_SND_AUDIO_DBG_PRINT
-+#define printk(format, arg...) do {} while (0);
-+#endif
-+
-+struct snd_pmic_ops {
-+ int card_status;
-+ int num_channel;
-+ int input_dev_id;
-+ int mute_status;
-+ int output_dev_id;
-+ int (*set_input_dev) (u8 value);
-+ int (*set_output_dev) (u8 value);
-+
-+ int (*set_mute) (int dev_id, u8 value);
-+ int (*get_mute) (int dev_id, u8 *value);
-+
-+ int (*set_vol) (int dev_id, u8 value);
-+ int (*get_vol) (int dev_id, u8 *value);
-+
-+ int (*init_card) (void);
-+ int (*set_pcm_audio_params) (int sfreq, int word_size ,int num_channel);
-+ int (*set_pcm_voice_params) (void);
-+ int (*set_voice_port) (int status);
-+ int (*set_audio_port) (int status);
-+
-+ int (*power_up_pmic_pb) (unsigned int port);
-+ int (*power_up_pmic_cp) (unsigned int port);
-+ int (*power_down_pmic_pb) (void);
-+ int (*power_down_pmic_cp) (void);
-+ int (*power_down_pmic) (void);
-+};
-+
-+struct intel_sst_card_ops {
-+ char *module_name;
-+ int vendor_id;
-+ int (*control_set) (int control_element, void *value);
-+ int (*send_buffer) (int str_id, struct stream_buffer *mad_buf);
-+ struct snd_pmic_ops *scard_ops;
-+};
-+
-+/* periphral interrupt interface */
-+enum lpe_periphral {
-+ LPE_DMA = 1,
-+ LPE_SSP0,
-+ LPE_SSP1
-+};
-+
-+/* modified for generic access */
-+struct sc_reg_access {
-+ u16 reg_addr;
-+ u8 value;
-+ u8 mask;
-+};
-+enum sc_reg_access_type {
-+ PMIC_READ = 0,
-+ PMIC_WRITE,
-+ PMIC_READ_MODIFY,
-+};
-+
-+int register_sst_card(struct intel_sst_card_ops *card);
-+void unregister_sst_card(struct intel_sst_card_ops *card);
-+int lpe_mask_periphral_intr(enum lpe_periphral device);
-+int lpe_unmask_periphral_intr(enum lpe_periphral device);
-+int lpe_periphral_intr_status(enum lpe_periphral device, int *status);
-+#endif /* __INTEL_SST_H__ */
-diff --git a/sound/pci/sst/intel_sst.c b/sound/pci/sst/intel_sst.c
-new file mode 100644
-index 0000000..c6e68b8
---- /dev/null
-+++ b/sound/pci/sst/intel_sst.c
-@@ -0,0 +1,527 @@
-+/*
-+ * intel_sst.c - Intel SST Driver for audio engine
-+ *
-+ * Copyright (C) 2008-10 Intel Corp
-+ * 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.
-+ *
-+ * This file contains all init functions
-+ */
-+
-+#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/fs.h>
-+#include <linux/file.h>
-+#include <linux/interrupt.h>
-+#include <linux/list.h>
-+#include <linux/workqueue.h>
-+#include <linux/firmware.h>
-+#include <linux/mutex.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#ifdef CONFIG_MSTWN_POWER_MGMT
-+#include <linux/intel_mid.h>
-+#endif
-+#include <sound/intel_lpe.h>
-+#include <sound/intel_sst_ioctl.h>
-+#include "intel_sst_fw_ipc.h"
-+#include "intel_sst_common.h"
-+
-+
-+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-+MODULE_DESCRIPTION("Intel (R) Moorestown Audio Engine Driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_VERSION(SST_DRIVER_VERSION);
-+
-+struct intel_sst_drv *sst_drv_ctx;
-+
-+/* fops Routines */
-+static const struct file_operations intel_sst_fops = {
-+ .owner = THIS_MODULE,
-+ .open = intel_sst_open,
-+ .release = intel_sst_release,
-+ .read = intel_sst_read,
-+ .write = intel_sst_write,
-+ .ioctl = intel_sst_ioctl,
-+ .mmap = intel_sst_mmap,
-+ .aio_read = intel_sst_aio_read,
-+ .aio_write = intel_sst_aio_write,
-+};
-+
-+spinlock_t pe_slock;
-+unsigned int pe_inprogress = 0;
-+
-+/**
-+* intel_sst_interrupt - Interrupt service routine for SST
-+* @irq: irq number of interrupt
-+* @dev_id: pointer to device structre
-+*
-+* This function is called by OS when SST device raises
-+* an interrupt. This will be result of write in IPC register
-+* Source can be busy or done interrupt
-+*/
-+static irqreturn_t intel_sst_interrupt(int irq, void *context)
-+{
-+ union interrupt_reg isr;
-+ union ipc_header header;
-+ union interrupt_reg imr;
-+ struct intel_sst_drv *drv = (struct intel_sst_drv *) context;
-+ unsigned int size = 0;
-+ int str_id;
-+ struct stream_info *stream ;
-+
-+
-+ /* Interrupt arrived, check src */
-+ isr.full = readl(drv->shim + SST_ISRX);
-+
-+ if (isr.part.busy_interrupt) {
-+ header.full = readl(drv->shim + SST_IPCD);
-+ if (header.part.large)
-+ size = header.part.data;
-+ if (header.part.msg_id & REPLY_MSG) {
-+ sst_drv_ctx->ipc_process_msg.header = header;
-+
-+ if (header.part.msg_id == IPC_SST_PERIOD_ELAPSED) {
-+ sst_clear_interrupt();
-+
-+ /*spin_lock(&pe_slock);*/
-+ if (pe_inprogress == 1) {
-+ /*spin_unlock(&pe_slock);*/
-+ return IRQ_HANDLED;
-+ }
-+
-+ pe_inprogress = 1;
-+ //spin_unlock(&pe_slock);
-+
-+ str_id = header.part.str_id;
-+ stream = &sst_drv_ctx->streams[str_id];
-+ if (stream->period_elapsed)
-+ stream->period_elapsed(stream->pcm_substream);
-+ //spin_lock(&pe_slock);
-+ pe_inprogress = 0;
-+ //spin_unlock(&pe_slock);
-+ return IRQ_HANDLED;
-+ } else {
-+ memcpy_fromio(sst_drv_ctx->ipc_process_msg.mailbox,
-+ drv->mailbox + SST_MAILBOX_RCV, size);
-+ queue_work(sst_drv_ctx->process_msg_wq,
-+ &sst_drv_ctx->ipc_process_msg.wq);
-+ }
-+ } else {
-+ sst_drv_ctx->ipc_process_reply.header = header;
-+ memcpy_fromio(sst_drv_ctx->ipc_process_reply.mailbox,
-+ drv->mailbox + SST_MAILBOX_RCV, size);
-+ queue_work(sst_drv_ctx->process_reply_wq,
-+ &sst_drv_ctx->ipc_process_reply.wq);
-+ }
-+ /* mask busy inetrrupt */
-+ imr.full = readl(drv->shim + SST_IMRX);
-+ imr.part.busy_interrupt = 1;
-+ /* dummy register for shim workaround */
-+ writel(imr.full, sst_drv_ctx->shim + SST_ISRD);
-+ writel(imr.full, drv->shim + SST_IMRX);
-+ return IRQ_HANDLED;
-+ } else if (isr.part.done_interrupt) {
-+ /* Clear done bit */
-+ header.full = readl(drv->shim + SST_IPCX);
-+ header.part.done = 0;
-+ /* dummy register for shim workaround */
-+ writel(header.full, sst_drv_ctx->shim + SST_ISRD);
-+ writel(header.full, drv->shim + SST_IPCX);
-+ /* write 1 to clear status register */;
-+ isr.part.done_interrupt = 1;
-+ /* dummy register for shim workaround */
-+ writel(isr.full, sst_drv_ctx->shim + SST_ISRD);
-+ writel(isr.full, drv->shim + SST_ISRX);
-+ queue_work(sst_drv_ctx->post_msg_wq,
-+ &sst_drv_ctx->ipc_post_msg.wq);
-+ return IRQ_HANDLED;
-+ } else
-+ return IRQ_NONE;
-+
-+}
-+
-+
-+/* PCI Routines */
-+
-+static struct pci_device_id intel_sst_ids[] = {
-+ { 0x8086, 0x080A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-+ { 0, }
-+};
-+MODULE_DEVICE_TABLE(pci, intel_sst_ids);
-+
-+
-+/*
-+* intel_sst_probe - PCI probe function
-+* @pci: PCI device structure
-+* @pci_id: PCI device ID structure
-+*
-+* This function is called by OS when a device is found
-+* This enables the device, interrupt etc
-+*/
-+static int __devinit intel_sst_probe(struct pci_dev *pci,
-+ const struct pci_device_id *pci_id)
-+{
-+ int i, ret = 0;
-+ static struct mutex drv_ctx_lock;
-+ mutex_init(&drv_ctx_lock);
-+
-+ mutex_lock(&drv_ctx_lock);
-+ if (sst_drv_ctx) {
-+ printk(KERN_ERR
-+ "SST ERR: Only one sst handle is supported\n");
-+ mutex_unlock(&drv_ctx_lock);
-+ return -EBUSY;
-+ }
-+
-+ sst_drv_ctx = kzalloc(sizeof(*sst_drv_ctx), GFP_KERNEL);
-+ if (!sst_drv_ctx) {
-+ printk(KERN_ERR
-+ "SST ERR: intel_sst malloc fail\n");
-+ mutex_unlock(&drv_ctx_lock);
-+ return -ENOMEM;
-+ }
-+ mutex_unlock(&drv_ctx_lock);
-+
-+ mutex_init(&sst_drv_ctx->stream_cnt_lock);
-+ sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
-+
-+ mutex_lock(&sst_drv_ctx->stream_cnt_lock);
-+ sst_drv_ctx->stream_cnt = 0;
-+ sst_drv_ctx->encoded_cnt = 0;
-+ sst_drv_ctx->am_cnt = 0;
-+ mutex_unlock(&sst_drv_ctx->stream_cnt_lock);
-+ sst_drv_ctx->pb_streams = 0;
-+ sst_drv_ctx->cp_streams = 0;
-+ sst_drv_ctx->unique_id = 0;
-+ sst_drv_ctx->pmic_port_instance = SST_DEFAULT_PMIC_PORT;
-+
-+ INIT_LIST_HEAD(&sst_drv_ctx->ipc_dispatch_list);
-+ INIT_WORK(&sst_drv_ctx->ipc_post_msg.wq, sst_post_message);
-+ INIT_WORK(&sst_drv_ctx->ipc_process_msg.wq, sst_process_message);
-+ INIT_WORK(&sst_drv_ctx->ipc_process_reply.wq, sst_process_reply);
-+ INIT_WORK(&sst_drv_ctx->mad_ops.wq, sst_process_mad_ops);
-+ init_waitqueue_head(&sst_drv_ctx->wait_queue);
-+
-+ sst_drv_ctx->mad_wq = create_workqueue("sst_mad_wq");
-+ if (!sst_drv_ctx->mad_wq)
-+ goto do_free_drv_ctx;
-+ sst_drv_ctx->post_msg_wq = create_workqueue("sst_post_msg_wq");
-+ if (!sst_drv_ctx->post_msg_wq)
-+ goto free_mad_wq;
-+ sst_drv_ctx->process_msg_wq = create_workqueue("sst_process_msg_wqq");
-+ if (!sst_drv_ctx->process_msg_wq)
-+ goto free_post_msg_wq;
-+ sst_drv_ctx->process_reply_wq = create_workqueue("sst_proces_reply_wq");
-+ if (!sst_drv_ctx->process_reply_wq)
-+ goto free_process_msg_wq;
-+
-+ for (i = 0; i < MAX_ACTIVE_STREAM; i++) {
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ sst_drv_ctx->alloc_block[i].ops_block.condition = false;
-+ }
-+ mutex_init(&sst_drv_ctx->list_lock);
-+
-+ for (i = 1; i < MAX_NUM_STREAMS; i++) {
-+ struct stream_info *stream = &sst_drv_ctx->streams[i];
-+ INIT_LIST_HEAD(&stream->bufs);
-+ mutex_init(&stream->lock);
-+ spin_lock_init(&stream->pcm_lock);
-+ }
-+ sst_drv_ctx->mmap_mem = NULL;
-+ sst_drv_ctx->mmap_len = SST_MMAP_PAGES * PAGE_SIZE;
-+ while (sst_drv_ctx->mmap_len > 0) {
-+ sst_drv_ctx->mmap_mem =
-+ kzalloc(sst_drv_ctx->mmap_len, GFP_KERNEL);
-+ if (sst_drv_ctx->mmap_mem) {
-+ printk(KERN_DEBUG "SST DBG:Got memory %p size 0x%x \n",
-+ sst_drv_ctx->mmap_mem,
-+ sst_drv_ctx->mmap_len);
-+ break;
-+ }
-+ sst_drv_ctx->mmap_len -= (SST_MMAP_STEP * PAGE_SIZE);
-+ if (sst_drv_ctx->mmap_len <= 0) {
-+ printk(KERN_ERR
-+ "SST ERR: Couldnt get any +\
-+ mem...abort!!\n");
-+ ret = -ENOMEM;
-+ goto free_process_reply_wq;
-+ }
-+ printk(KERN_DEBUG "SST DBG:Failed...trying %d\n", \
-+ sst_drv_ctx->mmap_len);
-+ }
-+
-+ /* Init the device */
-+ ret = pci_enable_device(pci);
-+ if (ret) {
-+ printk(KERN_ERR
-+ "SST ERR: device cant be enabled\n");
-+ goto do_free_mem;
-+ }
-+ sst_drv_ctx->pci = pci_dev_get(pci);
-+ ret = pci_request_regions(pci, SST_DRV_NAME);
-+ if (ret)
-+ goto do_disable_device;
-+ /* map registers */
-+ /* SST Shim */
-+ sst_drv_ctx->shim_phy_add =
-+ (unsigned long) pci_resource_start(pci, 1);
-+ sst_drv_ctx->shim = pci_ioremap_bar(pci, 1);
-+ if (!sst_drv_ctx->shim)
-+ goto do_release_regions;
-+ printk(KERN_DEBUG "SST DBG:SST Shim Ptr %p \n", sst_drv_ctx->shim);
-+
-+ /* Shared SRAM */
-+ sst_drv_ctx->mailbox = pci_ioremap_bar(pci, 2);
-+ if (!sst_drv_ctx->mailbox)
-+ goto do_unmap_shim;
-+ printk(KERN_DEBUG "SST DBG:SRAM Ptr %p \n", sst_drv_ctx->mailbox);
-+
-+ /* IRAM */
-+ sst_drv_ctx->iram = pci_ioremap_bar(pci, 3);
-+ if (!sst_drv_ctx->iram)
-+ goto do_unmap_sram;
-+ printk(KERN_DEBUG "SST DBG:IRAM Ptr %p \n", sst_drv_ctx->iram);
-+
-+ /* DRAM */
-+ sst_drv_ctx->dram = pci_ioremap_bar(pci, 4);
-+ if (!sst_drv_ctx->dram)
-+ goto do_unmap_iram;
-+ printk(KERN_DEBUG "SST DBG:DRAM Ptr %p \n", sst_drv_ctx->dram);
-+
-+ sst_drv_ctx->sst_state = SST_UN_INIT;
-+ /* Register the ISR */
-+ ret = request_irq(pci->irq, intel_sst_interrupt,
-+ IRQF_SHARED, SST_DRV_NAME, sst_drv_ctx);
-+ if (ret)
-+ goto do_unmap_dram;
-+ printk(KERN_DEBUG "SST DBG:Registered IRQ 0x%x\n", pci->irq);
-+
-+ /* Register with /dev */
-+ ret = register_chrdev(INTEL_SST_MAJOR, SST_DRV_NAME, &intel_sst_fops);
-+ if (ret) {
-+ printk(KERN_ERR
-+ "SST ERR: couldn't register +\
-+ device number\n");
-+ goto do_free_irq;
-+ }
-+
-+ sst_drv_ctx->lpe_stalled = 0;
-+ printk(KERN_DEBUG "SST DBG:...successfully done!!!\n");
-+ return ret;
-+
-+do_free_irq:
-+ free_irq(pci->irq, sst_drv_ctx);
-+do_unmap_dram:
-+ iounmap(sst_drv_ctx->dram);
-+do_unmap_iram:
-+ iounmap(sst_drv_ctx->iram);
-+do_unmap_sram:
-+ iounmap(sst_drv_ctx->mailbox);
-+do_unmap_shim:
-+ iounmap(sst_drv_ctx->shim);
-+do_release_regions:
-+ pci_release_regions(pci);
-+do_disable_device:
-+ pci_disable_device(pci);
-+do_free_mem:
-+ kfree(sst_drv_ctx->mmap_mem);
-+free_process_reply_wq:
-+ destroy_workqueue(sst_drv_ctx->process_reply_wq);
-+free_process_msg_wq:
-+ destroy_workqueue(sst_drv_ctx->process_msg_wq);
-+free_post_msg_wq:
-+ destroy_workqueue(sst_drv_ctx->post_msg_wq);
-+free_mad_wq:
-+ destroy_workqueue(sst_drv_ctx->mad_wq);
-+do_free_drv_ctx:
-+ kfree(sst_drv_ctx);
-+ printk(KERN_ERR
-+ "SST ERR: Probe failed with 0x%x \n", ret);
-+ return ret;
-+}
-+
-+/**
-+* intel_sst_remove - PCI remove function
-+* @pci: PCI device structure
-+*
-+* This function is called by OS when a device is unloaded
-+* This frees the interrupt etc
-+*/
-+static void __devexit intel_sst_remove(struct pci_dev *pci)
-+{
-+ pci_dev_put(sst_drv_ctx->pci);
-+ sst_drv_ctx->sst_state = SST_UN_INIT;
-+ unregister_chrdev(INTEL_SST_MAJOR, SST_DRV_NAME);
-+ free_irq(pci->irq, sst_drv_ctx);
-+ iounmap(sst_drv_ctx->dram);
-+ iounmap(sst_drv_ctx->iram);
-+ iounmap(sst_drv_ctx->mailbox);
-+ iounmap(sst_drv_ctx->shim);
-+ sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
-+ kfree(sst_drv_ctx->mmap_mem);
-+ destroy_workqueue(sst_drv_ctx->process_reply_wq);
-+ destroy_workqueue(sst_drv_ctx->process_msg_wq);
-+ destroy_workqueue(sst_drv_ctx->post_msg_wq);
-+ destroy_workqueue(sst_drv_ctx->mad_wq);
-+ kfree(sst_drv_ctx);
-+ pci_release_region(pci, 2);
-+ pci_release_region(pci, 3);
-+ pci_release_region(pci, 4);
-+ pci_release_region(pci, 5);
-+ pci_set_drvdata(pci, NULL);
-+}
-+
-+/* Power Management */
-+
-+/**
-+* intel_sst_suspend - PCI suspend function
-+* @pci: PCI device structure
-+* @state: PM message
-+*
-+* This function is called by OS when a power event occurs
-+*/
-+static int intel_sst_suspend(struct pci_dev *pci, pm_message_t state)
-+{
-+ int i;
-+ printk(KERN_DEBUG "SST DBG:intel_sst_suspend called\n");
-+
-+ /* Pause all running streams */
-+ for (i = 1; i < MAX_NUM_STREAMS; i++) {
-+ if (sst_drv_ctx->streams[i].status == STREAM_RUNNING) {
-+ sst_drv_ctx->active_streams[i] = true;
-+ sst_pause_stream(i);
-+ } else
-+ sst_drv_ctx->active_streams[i] = false;
-+ }
-+
-+ pci_set_drvdata(pci, sst_drv_ctx);
-+
-+ /* Send msg to FW FIXME */
-+
-+ /* Disable everything */
-+ /* free_irq(pci->irq, sst_drv_ctx); */
-+ pci_disable_device(pci);
-+ pci_save_state(pci);
-+ pci_set_power_state(pci, pci_choose_state(pci, state));
-+ return 0;
-+}
-+
-+/**
-+* intel_sst_resume - PCI resume function
-+* @pci: PCI device structure
-+* @state: PM message
-+*
-+* This function is called by OS when a power event occurs
-+*/
-+static int intel_sst_resume(struct pci_dev *pci)
-+{
-+ int i;
-+
-+ printk(KERN_DEBUG "SST DBG:\nintel_sst_resume called\n");
-+ sst_drv_ctx = pci_get_drvdata(pci);
-+ if (pci->irq)
-+ printk(KERN_DEBUG "SST DBG:irq %d \n", pci->irq);
-+
-+ pci_set_power_state(pci, PCI_D0);
-+ pci_restore_state(pci);
-+
-+ /* ret = request_irq(pci->irq, intel_sst_interrupt,
-+ IRQF_SHARED, "intel_sst_engine", sst_drv_ctx);
-+ if (ret) {
-+ return ret;
-+ } */
-+
-+ /* Send msg to FW FIXME */
-+
-+ /* Start all paused streams */
-+ for (i = 1; i < MAX_NUM_STREAMS; i++) {
-+ if (sst_drv_ctx->active_streams[i] == true)
-+ sst_resume_stream(i);
-+ }
-+ return 0;
-+}
-+
-+
-+static struct pci_driver driver = {
-+ .name = SST_DRV_NAME,
-+ .id_table = intel_sst_ids,
-+ .probe = intel_sst_probe,
-+ .remove = __devexit_p(intel_sst_remove),
-+ .suspend = intel_sst_suspend,
-+ .resume = intel_sst_resume,
-+};
-+
-+/**
-+* intel_sst_init - Module init function
-+*
-+* Registers with PCI
-+* Registers with /dev
-+*Init all data strutures
-+*/
-+static int __init intel_sst_init(void)
-+{
-+ /* Init all variables, data structure etc....*/
-+ int ret = 0;
-+ printk(KERN_ERR
-+ "INFO: ******** SST DRIVER +\
-+ loading.. Ver: %s\n", SST_DRIVER_VERSION);
-+
-+ /* Register with PCI */
-+ ret = pci_register_driver(&driver);
-+ if (ret)
-+ printk(KERN_ERR
-+ "SST ERR: PCI register failed \n");
-+ sst_spi_mode_enable();
-+ return ret;
-+}
-+
-+/**
-+* intel_sst_exit - Module exit function
-+*
-+* Unregisters with PCI
-+* Unregisters with /dev
-+* Frees all data strutures
-+*/
-+static void __exit intel_sst_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < MAX_NUM_STREAMS; i++)
-+ sst_free_stream(i);
-+
-+ /* Send msg to FW TBD */
-+ pci_unregister_driver(&driver);
-+
-+ flush_scheduled_work();
-+ printk(KERN_DEBUG "SST DBG:...unloaded\n");
-+ return;
-+}
-+
-+module_init(intel_sst_init);
-+module_exit(intel_sst_exit);
-diff --git a/sound/pci/sst/intel_sst_dsp.c b/sound/pci/sst/intel_sst_dsp.c
-new file mode 100644
-index 0000000..bc78918
---- /dev/null
-+++ b/sound/pci/sst/intel_sst_dsp.c
-@@ -0,0 +1,706 @@
-+/*
-+ * intel_sst_dsp.h - Intel SST Driver for audio engine
-+ *
-+ * Copyright (C) 2008-10 Intel Corp
-+ * 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.
-+ *
-+ * This file contains all dsp controlling functions like firmware download,
-+ * setting/resetting dsp cores, etc
-+ */
-+#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/fs.h>
-+#include <linux/file.h>
-+#include <linux/interrupt.h>
-+#include <linux/list.h>
-+#include <linux/workqueue.h>
-+#include <linux/firmware.h>
-+#include <linux/mutex.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <asm/ipc_defs.h>
-+#include <sound/intel_lpe.h>
-+#include <sound/intel_sst_ioctl.h>
-+#include "intel_sst_fw_ipc.h"
-+#include "intel_sst_common.h"
-+
-+
-+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
-+MODULE_DESCRIPTION("Intel (R) Moorestown Audio Engine Driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_VERSION(SST_DRIVER_VERSION);
-+
-+/**
-+* this function writes registers through SCU IPC
-+*/
-+static int sst_scu_ipc_write(u32 addr, u32 value)
-+{
-+ int retval = 0, retry = 3;
-+ struct ipc_reg_data ipc_reg = {0};
-+
-+ ipc_reg.address = addr;
-+ ipc_reg.data = value;
-+ ipc_reg.ioc = 1;
-+
-+ while (retry) {
-+ retval = mrst_ipc_write32(&ipc_reg);
-+ if (!retval)
-+ break;
-+ retry--;
-+ /* error */
-+ printk(KERN_ERR "SST ERR: IPC +\
-+ write failed %x\n", retval);
-+ }
-+ return retval;
-+}
-+
-+/**
-+* this function reads registers through SCU IPC
-+*/
-+static int sst_scu_ipc_read(u32 addr, u32 *value)
-+{
-+ int retval = 0, retry = 3;
-+ struct ipc_reg_data ipc_reg = {0};
-+
-+ ipc_reg.address = addr;
-+ ipc_reg.data = 0;
-+ ipc_reg.ioc = 1;
-+
-+ while (retry) {
-+ retval = mrst_ipc_read32(&ipc_reg);
-+ if (!retval)
-+ break;
-+ retry--;
-+ printk(KERN_ERR
-+ "SST ERR: IPC read failed %x\n ", retval);
-+ }
-+ *value = ipc_reg.data;
-+ printk(KERN_DEBUG "SST DBG:The read value +\
-+ from the mrst_ipc is ::0x%08x\n", *value);
-+ return retval;
-+}
-+/**
-+* Resetting SST DSP
-+*/
-+static int intel_sst_reset_dsp(void)
-+{
-+ union config_status_reg csr;
-+ int retval;
-+ unsigned int value = 0;
-+
-+ retval = sst_scu_ipc_read(CHIP_REV_REG, &value);
-+ if (retval)
-+ return retval;
-+
-+#if 0
-+ /* A2-CHANGES */
-+ if (((value & CHIP_REV_ADDR) >> 3) == CHIP_REV_A1) {
-+ sst_drv_ctx->chip_rev_id = CHIP_A1_50;
-+ /* SCU FW Changes*/
-+ retval = sst_scu_ipc_write(AUD_SHIM_BASE_ADDR,
-+ AUD_SHIM_RATIO_1_1);
-+ } else {
-+ if (DSP_CLOCK_SPEED == CLK_100MHZ) {
-+ sst_drv_ctx->chip_rev_id = CHIP_A2_100;
-+ /* SCU FW Changes*/
-+ retval = sst_scu_ipc_write(AUD_SHIM_BASE_ADDR,
-+ AUD_SHIM_RATIO);
-+ } else if (DSP_CLOCK_SPEED == CLK_50MHZ) {
-+ sst_drv_ctx->chip_rev_id = CHIP_A2_50;
-+ /* SCU FW Changes*/
-+
-+ retval = sst_scu_ipc_write(AUD_SHIM_BASE_ADDR,
-+ AUD_SHIM_RATIO_1_1);
-+ } else {
-+ printk(KERN_ERR "SST ERR: +\
-+ Invalid clock speed\n ");
-+ return -EIO;
-+ }
-+ } /*else {
-+ printk(KERN_ERR
-+ "SST ERR: Invalid chip revision Type\n");
-+ return -EIO;
-+ }*/
-+#endif
-+ /* to fix SPI driver bug, which sets to 1 */
-+ csr.full = 0x3a2;
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+ /* ----------- */
-+
-+ csr.full = readl(sst_drv_ctx->shim + SST_CSR);
-+ csr.part.strb_cntr_rst = 0;
-+ csr.part.run_stall = 0x1;
-+ csr.part.bypass = 0x7;
-+ csr.part.sst_reset = 0x1;
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+
-+ printk(KERN_DEBUG "SST DBG:Chip version +\
-+ is:: %d\n", value);
-+ return retval;
-+}
-+
-+/**
-+* Start the SST DSP processor
-+*/
-+static int sst_start(void)
-+{
-+ union config_status_reg csr;
-+
-+ csr.full = readl(sst_drv_ctx->shim + SST_CSR);
-+ csr.part.bypass = 0;
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+
-+#if 0
-+ retval = sst_scu_ipc_write(
-+ sst_drv_ctx->shim_phy_add + SST_CSR, csr.full);
-+ if (retval != 0)
-+ printk(KERN_ERR
-+ "SST ERR: scu ipc write start failed %d ", retval);
-+ csr.full = readl(sst_drv_ctx->shim + SST_CSR);
-+ csr.part.sst_reset = 0;
-+ csr.part.run_stall = 0;
-+ if ((sst_drv_ctx->chip_rev_id == CHIP_A2_50) ||
-+ (sst_drv_ctx->chip_rev_id == CHIP_A2_100)) {
-+ csr.part.strb_cntr_rst = 1;
-+ if (sst_drv_ctx->chip_rev_id == CHIP_A2_100)
-+ csr.part.sst_clk = 1;
-+ }
-+#endif
-+ csr.part.run_stall = 0;
-+ csr.part.sst_reset = 0;
-+ csr.part.strb_cntr_rst = 1;
-+ printk(KERN_DEBUG "SST DBG:Setting SST to execute 0x%x \n", csr.full);
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+
-+#if 0
-+ return sst_scu_ipc_write(
-+ sst_drv_ctx->shim_phy_add + SST_CSR, csr.full);
-+#endif
-+ return 0;
-+}
-+
-+/**
-+* Parse modules that need to be placed in SST IRAM and DRAM
-+*/
-+static int sst_parse_module(struct fw_module_header *module)
-+{
-+ struct dma_block_info *block;
-+ u32 count;
-+ void __iomem *ram;
-+
-+ printk(KERN_DEBUG "SST DBG:module sign=%s sz=0x%x blks=0x%x typ=0x%x ep=0x%x sz=0x%x\n",
-+ module->signature, module->mod_size,
-+ module->blocks, module->type,
-+ module->entry_point, sizeof(*module));
-+
-+ block = (void *)module + sizeof(*module);
-+
-+ for (count = 0; count < module->blocks; count++) {
-+ if (block->size <= 0) {
-+ printk(KERN_ERR "SST ERR: +\
-+ block size invalid\n ");
-+ return -EINVAL;
-+ }
-+ switch (block->type) {
-+ case SST_IRAM:
-+ ram = sst_drv_ctx->iram;
-+ break;
-+ case SST_DRAM:
-+ ram = sst_drv_ctx->dram;
-+ break;
-+ default:
-+ printk(KERN_ERR
-+ "SST ERR:wrng ram typ0x%x +\
-+ inblock0x%x\n", block->type, count);
-+ return -EINVAL;
-+ }
-+ memcpy_toio(ram + block->ram_offset,
-+ (void *)block + sizeof(*block), block->size);
-+ block = (void *)block + sizeof(*block) + block->size;
-+ }
-+ return 0;
-+}
-+
-+/**
-+* sst_parse_fw_image - FW parse and load
-+* This function is called to parse and download the FW image
-+*/
-+static int sst_parse_fw_image(const struct firmware *sst_fw)
-+{
-+ struct fw_header *header;
-+ u32 count;
-+ int ret_val;
-+ struct fw_module_header *module;
-+
-+ BUG_ON(!sst_fw);
-+
-+ /* Read the header information from the data pointer */
-+ header = (struct fw_header *)sst_fw->data;
-+
-+ /* verify FW */
-+ if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) ||
-+ (sst_fw->size != header->file_size + sizeof(*header))) {
-+ /* Invalid FW signature */
-+ printk(KERN_ERR
-+ "SST ERR: InvalidFW sgn/filesiz mismtch\n ");
-+ return -EINVAL;
-+ }
-+ printk(KERN_DEBUG "SST DBG:header sign=%s size=0x%x modules=0x%x fmt=0x%x size=0x%x\n",
-+ header->signature, header->file_size, header->modules,
-+ header->file_format, sizeof(*header));
-+ module = (void *)sst_fw->data + sizeof(*header);
-+ for (count = 0; count < header->modules; count++) {
-+ /* module */
-+ ret_val = sst_parse_module(module);
-+ if (ret_val)
-+ return ret_val;
-+ module = (void *)module + sizeof(*module) + module->mod_size ;
-+ }
-+
-+ printk(KERN_DEBUG "SST DBG:done....\n");
-+ return 0;
-+}
-+
-+/**
-+* sst_load_fw - function to reset FW
-+* @fw: Pointer to loaded FW
-+* This function is called when the FW is loaded
-+*/
-+int sst_load_fw(const struct firmware *fw, void *context)
-+{
-+ int ret_val;
-+
-+ printk(KERN_DEBUG "SST DBG:called \n");
-+ BUG_ON(!fw);
-+
-+ /* TBD: Checksum, tamper check etc */
-+ ret_val = intel_sst_reset_dsp();
-+ if (ret_val)
-+ return ret_val;
-+ /* putting the sst state to init */
-+ sst_drv_ctx->sst_state = SST_UN_INIT;
-+
-+ ret_val = sst_parse_fw_image(fw);
-+ if (ret_val)
-+ return ret_val;
-+
-+ sst_drv_ctx->sst_state = SST_FW_LOADED;
-+ /* 7. ask scu to reset the bypass bits */
-+ /* 8.bring sst out of reset */
-+ ret_val = sst_start();
-+ if (ret_val)
-+ return ret_val;
-+
-+ printk(KERN_DEBUG "SST DBG:...successful!!!\n");
-+ return ret_val;
-+}
-+
-+/**
-+* This function is called when any codec/post processing library
-+* needs to be downloaded
-+*/
-+static int sst_download_library(const struct firmware *fw_lib,
-+ struct snd_sst_lib_download_info *lib)
-+{
-+ /* send IPC message and wait */
-+ int i;
-+ u8 pvt_id;
-+ struct ipc_post *msg = NULL;
-+ union config_status_reg csr;
-+ struct snd_sst_str_type str_type = {0};
-+ int retval = 0;
-+
-+ if (sst_create_large_msg(&msg))
-+ return -ENOMEM;
-+
-+ pvt_id = sst_assign_pvt_id(sst_drv_ctx);
-+ i = sst_get_block_stream(sst_drv_ctx);
-+ printk(KERN_DEBUG "SST DBG:alloc block +\
-+ allocated = %d, pvt_id %d\n", i, pvt_id);
-+ if (i < 0) {
-+ kfree(msg);
-+ return -ENOMEM;
-+ }
-+ sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
-+ sst_fill_header(&msg->header, IPC_IA_PREP_LIB_DNLD, 1, 0);
-+ msg->header.part.data = sizeof(u32) + sizeof(str_type);
-+ str_type.codec_type = lib->dload_lib.lib_info.lib_type;
-+ str_type.pvt_id = pvt_id;
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), &str_type, sizeof(str_type));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]);
-+ if (retval) {
-+ /* error */
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ printk(KERN_ERR
-+ "SST ERR: Prep codec downloaded failed %d\n", retval);
-+ return -EIO;
-+ }
-+ printk(KERN_DEBUG "SST DBG:FW responded, ready for download now...\n");
-+ /* downloading on success */
-+ sst_drv_ctx->sst_state = SST_FW_LOADED;
-+ csr.full = readl(sst_drv_ctx->shim + SST_CSR);
-+ printk(KERN_DEBUG "SST DBG:CSR reg 0x%x \n", csr.full);
-+ csr.part.run_stall = 1;
-+ printk(KERN_DEBUG "SST DBG:HALT CSR reg setting to 0x%x \n", csr.full);
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+#if 0
-+ retval = sst_scu_ipc_write(
-+ sst_drv_ctx->shim_phy_add + SST_CSR, csr.full);
-+ if (retval) {
-+ /* error */
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ printk(KERN_ERR
-+ "SST ERR: IPC failed to Halt SST 0x%x\n", retval);
-+ return -EAGAIN;
-+ }
-+#endif
-+ csr.full = readl(sst_drv_ctx->shim + SST_CSR);
-+ csr.part.bypass = 0x7;
-+ printk(KERN_DEBUG "SST DBG:Bypass CSR reg +\
-+ setting to 0x%x \n", csr.full);
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+#if 0
-+ retval = sst_scu_ipc_write(
-+ sst_drv_ctx->shim_phy_add + SST_CSR, csr.full);
-+ if (retval) {
-+ /* error */
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ printk(KERN_ERR
-+ "SST ERR: IPC failed to Bypass SST 0x%x\n", retval);
-+ csr.part.bypass = 0x0;
-+ /* bring LPE out of run stall */
-+ /* send error mesages to FW- TBD FIXME */
-+ csr.part.run_stall = 0x0;
-+ printk(KERN_DEBUG "SST DBG:Bypass CSR reg +\
-+ setting to 0x%x \n", csr.full);
-+ retval = sst_scu_ipc_write(sst_drv_ctx->shim_phy_add + SST_CSR,
-+ csr.full);
-+ if (retval) {
-+ /* prepare to download firmware again
-+ for the next time TBD FIXME
-+ sst_drv_ctx->sst_state = SST_UN_INIT;*/
-+ }
-+ return -EAGAIN;
-+ }
-+#endif
-+ sst_parse_fw_image(fw_lib);
-+
-+ /* set the FW to running again */
-+ csr.full = readl(sst_drv_ctx->shim + SST_CSR);
-+ csr.part.bypass = 0x0;
-+ printk(KERN_DEBUG "SST DBG:Bypass CSR reg +\
-+ setting to 0x%x \n", csr.full);
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+#if 0
-+ retval = sst_scu_ipc_write(
-+ sst_drv_ctx->shim_phy_add + SST_CSR, csr.full);
-+ if (retval) {
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ printk(KERN_ERR\
-+ "SST ERR: BypassCSR regclear failed 0x%x\n", retval);
-+ /* bring LPE out of run stall */
-+ /* send error mesages to FW- TBD FIXME */
-+ csr.part.run_stall = 0x0;
-+ printk(KERN_DEBUG "SST DBG:Bypass CSR +\
-+ reg setting to 0x%x \n", csr.full);
-+ retval = sst_scu_ipc_write(sst_drv_ctx->shim_phy_add + SST_CSR,
-+ csr.full);
-+ if (retval) {
-+ /* prepare to download firmware again
-+ for the next time TBD FIXME
-+ sst_drv_ctx->sst_state = SST_UN_INIT;*/
-+ }
-+ return -EAGAIN;
-+ }
-+#endif
-+ csr.full = readl(sst_drv_ctx->shim + SST_CSR);
-+ csr.part.run_stall = 0;
-+ printk(KERN_DEBUG "SST DBG:Stalll CSR reg +\
-+ setting to 0x%x \n", csr.full);
-+ writel(csr.full, sst_drv_ctx->shim + SST_ISRX);
-+ writel(csr.full, sst_drv_ctx->shim + SST_CSR);
-+#if 0
-+ retval = sst_scu_ipc_write(
-+ sst_drv_ctx->shim_phy_add + SST_CSR, csr.full);
-+ if (retval) {
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ printk(KERN_ERR
-+ "SST ERR: Stall CSR reg clear failed 0x%x \n", retval);
-+ if (retval) {
-+ /* prepare to download firmware again
-+ for the next time TBD FIXME
-+ sst_drv_ctx->sst_state = SST_UN_INIT;*/
-+ }
-+ return -EAGAIN;
-+ }
-+#endif
-+ /* send download complete and wait */
-+ if (sst_create_large_msg(&msg)) {
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ return -ENOMEM;
-+ }
-+
-+ sst_fill_header(&msg->header, IPC_IA_LIB_DNLD_CMPLT, 1, 0);
-+ msg->header.part.data = sizeof(u32) + sizeof(*lib);
-+ lib->pvt_id = pvt_id;
-+ memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
-+ memcpy(msg->mailbox_data + sizeof(u32), lib, sizeof(*lib));
-+ mutex_lock(&sst_drv_ctx->list_lock);
-+ list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
-+ mutex_unlock(&sst_drv_ctx->list_lock);
-+ sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
-+ printk(KERN_DEBUG "SST DBG:Waiting for FW to respond on Download complete \n");
-+ sst_drv_ctx->alloc_block[i].ops_block.condition = false;
-+ retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]);
-+ if (retval) {
-+ /* error */
-+ sst_drv_ctx->sst_state = SST_FW_RUNNING;
-+ /* shouldnt we set it to error state??? TBD */
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ return -EIO;
-+ }
-+
-+ printk(KERN_DEBUG "SST DBG:FW responded sucess on Download complete \n");
-+ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
-+ sst_drv_ctx->sst_state = SST_FW_RUNNING;
-+ return 0;
-+
-+}
-+
-+/**
-+* This function is called befoer downloading the codec/postprocessing
-+* library is set for download to SST DSP
-+*/
-+static int sst_validate_library(const struct firmware *fw_lib,
-+ struct lib_slot_info *slot,
-+ u32 *entry_point)
-+{
-+ struct fw_header *header;
-+ struct fw_module_header *module;
-+ struct dma_block_info *block;
-+ unsigned int n_blk, isize = 0, dsize = 0;
-+ int err = 0;
-+
-+ header = (struct fw_header *)fw_lib->data;
-+ if (header->modules != 1) {
-+ printk(KERN_ERR\
-+ "SST ERR: Module no mismatch found\n ");
-+ err = -EINVAL;
-+ goto exit;
-+ }
-+ module = (void *)fw_lib->data + sizeof(*header);
-+ *entry_point = module->entry_point;
-+ printk(KERN_DEBUG "SST DBG:Module entry point 0x%x \n", *entry_point);
-+ printk(KERN_DEBUG "SST DBG:Module Sign %s, Size 0x%x, Blocks 0x%x Type 0x%x \n",
-+ module->signature, module->mod_size,
-+ module->blocks, module->type);
-+
-+ block = (void *)module + sizeof(*module);
-+ for (n_blk = 0; n_blk < module->blocks; n_blk++) {
-+ switch (block->type) {
-+ case SST_IRAM:
-+ isize += block->size;
-+ break;
-+ case SST_DRAM:
-+ dsize += block->size;
-+ break;
-+ default:
-+ printk(KERN_ERR
-+ "SST ERR: Invalid blk type for 0x%x\n ", n_blk);
-+ err = -EINVAL;
-+ goto exit;
-+ }
-+ block = (void *)block + sizeof(*block) + block->size;
-+ }
-+ if (isize > slot->iram_size || dsize > slot->dram_size) {
-+ printk(KERN_ERR
-+ "SST ERR: library exceeds size allocated \n");
-+ err = -EINVAL;
-+ goto exit;
-+ } else
-+ printk(KERN_DEBUG "SST DBG:Library is safe for download...\n");
-+
-+ printk(KERN_DEBUG "SST DBG:iram 0x%x, dram 0x%x, allowed iram 0x%x, allowed dram 0x%x\n",
-+ isize, dsize, slot->iram_size, slot->dram_size);
-+exit:
-+ return err;
-+
-+}
-+
-+/**
-+* This function is called when FW requests for a particular libary download
-+* This function prepares the library to download
-+*/
-+int sst_load_library(struct snd_sst_lib_download *lib, u8 ops, u32 pvt_id)
-+{
-+ char buf[20];
-+ const char *type, *dir;
-+ int len = 0, error = 0;
-+ u32 entry_point;
-+ const struct firmware *fw_lib;
-+ struct snd_sst_lib_download_info dload_info = {{{0},},};
-+
-+ memset(buf, 0, sizeof(buf));
-+
-+ printk(KERN_DEBUG "SST DBG:Lib Type 0x%x, Slot 0x%x, ops 0x%x \n",
-+ lib->lib_info.lib_type, lib->slot_info.slot_num, ops);
-+ printk(KERN_DEBUG "SST DBG:Version 0x%x, name %s, caps 0x%x media type 0x%x \n",
-+ lib->lib_info.lib_version, lib->lib_info.lib_name,
-+ lib->lib_info.lib_caps, lib->lib_info.media_type);
-+
-+ printk(KERN_DEBUG "SST DBG:IRAM Size 0x%x, offset 0x%x, DRAM Size 0x%x, offset 0x%x \n",
-+ lib->slot_info.iram_size, lib->slot_info.iram_offset,
-+ lib->slot_info.dram_size, lib->slot_info.dram_offset);
-+
-+ switch (lib->lib_info.lib_type) {
-+ case SST_CODEC_TYPE_MP3:
-+ type = "mp3_";
-+ break;
-+ case SST_CODEC_TYPE_AAC:
-+ type = "aac_";
-+ break;
-+ case SST_CODEC_TYPE_AACP:
-+ type = "aac_v1_";
-+ break;
-+ case SST_CODEC_TYPE_eAACP:
-+ type = "aac_v2_";
-+ break;
-+ case SST_CODEC_TYPE_WMA9:
-+ type = "wma9_";
-+ break;
-+ default:
-+ printk(KERN_ERR "SST ERR: +\
-+ Invalid codec type \n");
-+ error = -EINVAL;
-+ goto wake;
-+ }
-+
-+ if (ops == STREAM_OPS_CAPTURE)
-+ dir = "enc_";
-+ else
-+ dir = "dec_";
-+ strncpy(buf, type, strlen(type));
-+ strncpy(buf + strlen(type), dir, strlen(dir));
-+ len = strlen(type) + strlen(dir);
-+ len += snprintf(buf + len, sizeof(buf) - len, "%d",
-+ lib->slot_info.slot_num);
-+ len += snprintf(buf + len, sizeof(buf) - len, ".bin");
-+
-+ printk(KERN_DEBUG "SST DBG:Requesting %s \n", buf);
-+
-+ error = request_firmware(&fw_lib, buf, &sst_drv_ctx->pci->dev);
-+ if (error) {
-+ printk(KERN_ERR
-+ "SST ERR: library load failed %d \n", error);
-+ goto wake;
-+ }
-+ error = sst_validate_library(fw_lib, &lib->slot_info, &entry_point);
-+ if (error)
-+ goto wake_free;
-+
-+ lib->mod_entry_pt = entry_point;
-+ memcpy(&dload_info.dload_lib, lib, sizeof(*lib));
-+ error = sst_download_library(fw_lib, &dload_info);
-+ if (error)
-+ goto wake_free;
-+
-+ /* lib is downloaded and init send alloc again */
-+ printk(KERN_DEBUG "SST DBG:Library is downloaded now... \n");
-+wake_free:
-+ /* sst_wake_up_alloc_block(sst_drv_ctx, pvt_id, error, NULL); */
-+ release_firmware(fw_lib);
-+wake:
-+ return error;
-+}
-+
-+/* This Function set the bit banging*/
-+int sst_spi_mode_enable()
-+{
-+
-+ void __iomem *logical_ptr_to_bang;
-+ u32 regbase = SPI_MODE_ENABLE_BASE_ADDR, range = 0x38;
-+ u32 data;
-+ u32 mask = 0x400000;
-+ int retval;
-+ int i = 0;
-+
-+
-+ logical_ptr_to_bang = ioremap_nocache(regbase, range);
-+ if (!logical_ptr_to_bang) {
-+ dev_err(&sst_drv_ctx->pci->dev, \
-+ "SST ERR: SSP0 bit bang -IOREMAP Failed \n");
-+ return -1;
-+ }
-+
-+ /* spi mode enable */
-+ iowrite32(0x0000000f, logical_ptr_to_bang);
-+ iowrite32(0x33301dc3, logical_ptr_to_bang + 0x4);
-+ iowrite32(0x02010007, logical_ptr_to_bang + 0x2c);
-+ iowrite32(0x00000000, logical_ptr_to_bang + 0x30);
-+ iowrite32(0x00000000, logical_ptr_to_bang + 0x34);
-+ iowrite32(0x0000008f, logical_ptr_to_bang);
-+
-+
-+ retval = sst_scu_ipc_write(0xff12b004, 0x3);
-+ retval = sst_scu_ipc_write(0xff12b000, 0x01070034);
-+ retval = sst_scu_ipc_write(0xff12b004, 0x99);
-+ retval = sst_scu_ipc_write(0xff12b000, 0x01070038);
-+
-+ data = ioread32(logical_ptr_to_bang+0x8);
-+ dev_err(&sst_drv_ctx->pci->dev,\
-+ "SST ERR: SSP0 bit bang SSCR val = 0x%08x \n", data);
-+ data = data & mask;
-+ while (data == mask) {
-+ retval = sst_scu_ipc_write(0xff12b004, 0x3);
-+ retval = sst_scu_ipc_write(0xff12b000, 0x01070034);
-+ retval = sst_scu_ipc_write(0xff12b004, 0x2);
-+ retval = sst_scu_ipc_write(0xff12b000, 0x01070034);
-+ data = ioread32(logical_ptr_to_bang+0x8);
-+ data = data & mask;
-+ i++;
-+ }
-+ dev_err(&sst_drv_ctx->pci->dev, \
-+ "SST ERR: SSP0 bit bang while loop counter= %4d \n ", i);
-+ retval = sst_scu_ipc_write(0xff12b004, 0x0);
-+ retval = sst_scu_ipc_write(0xff12b000, 0x01070038);
-+
-+ return retval;
-+}
---
-1.6.2.2
-