diff options
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.patch | 1433 |
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 - |