diff options
Diffstat (limited to 'sound/soc/intel/sst/sst_pci.c')
-rw-r--r-- | sound/soc/intel/sst/sst_pci.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/sound/soc/intel/sst/sst_pci.c b/sound/soc/intel/sst/sst_pci.c new file mode 100644 index 000000000000..3a0b3bf0af97 --- /dev/null +++ b/sound/soc/intel/sst/sst_pci.c | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * sst_pci.c - SST (LPE) driver init file for pci enumeration. | ||
3 | * | ||
4 | * Copyright (C) 2008-14 Intel Corp | ||
5 | * Authors: Vinod Koul <vinod.koul@intel.com> | ||
6 | * Harsha Priya <priya.harsha@intel.com> | ||
7 | * Dharageswari R <dharageswari.r@intel.com> | ||
8 | * KP Jeeja <jeeja.kp@intel.com> | ||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; version 2 of the License. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/fs.h> | ||
25 | #include <linux/firmware.h> | ||
26 | #include <linux/pm_runtime.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <asm/platform_sst_audio.h> | ||
30 | #include "../sst-mfld-platform.h" | ||
31 | #include "sst.h" | ||
32 | |||
33 | static int sst_platform_get_resources(struct intel_sst_drv *ctx) | ||
34 | { | ||
35 | int ddr_base, ret = 0; | ||
36 | struct pci_dev *pci = ctx->pci; | ||
37 | |||
38 | ret = pci_request_regions(pci, SST_DRV_NAME); | ||
39 | if (ret) | ||
40 | return ret; | ||
41 | |||
42 | /* map registers */ | ||
43 | /* DDR base */ | ||
44 | if (ctx->dev_id == SST_MRFLD_PCI_ID) { | ||
45 | ctx->ddr_base = pci_resource_start(pci, 0); | ||
46 | /* check that the relocated IMR base matches with FW Binary */ | ||
47 | ddr_base = relocate_imr_addr_mrfld(ctx->ddr_base); | ||
48 | if (!ctx->pdata->lib_info) { | ||
49 | dev_err(ctx->dev, "lib_info pointer NULL\n"); | ||
50 | ret = -EINVAL; | ||
51 | goto do_release_regions; | ||
52 | } | ||
53 | if (ddr_base != ctx->pdata->lib_info->mod_base) { | ||
54 | dev_err(ctx->dev, | ||
55 | "FW LSP DDR BASE does not match with IFWI\n"); | ||
56 | ret = -EINVAL; | ||
57 | goto do_release_regions; | ||
58 | } | ||
59 | ctx->ddr_end = pci_resource_end(pci, 0); | ||
60 | |||
61 | ctx->ddr = pcim_iomap(pci, 0, | ||
62 | pci_resource_len(pci, 0)); | ||
63 | if (!ctx->ddr) { | ||
64 | ret = -EINVAL; | ||
65 | goto do_release_regions; | ||
66 | } | ||
67 | dev_dbg(ctx->dev, "sst: DDR Ptr %p\n", ctx->ddr); | ||
68 | } else { | ||
69 | ctx->ddr = NULL; | ||
70 | } | ||
71 | /* SHIM */ | ||
72 | ctx->shim_phy_add = pci_resource_start(pci, 1); | ||
73 | ctx->shim = pcim_iomap(pci, 1, pci_resource_len(pci, 1)); | ||
74 | if (!ctx->shim) { | ||
75 | ret = -EINVAL; | ||
76 | goto do_release_regions; | ||
77 | } | ||
78 | dev_dbg(ctx->dev, "SST Shim Ptr %p\n", ctx->shim); | ||
79 | |||
80 | /* Shared SRAM */ | ||
81 | ctx->mailbox_add = pci_resource_start(pci, 2); | ||
82 | ctx->mailbox = pcim_iomap(pci, 2, pci_resource_len(pci, 2)); | ||
83 | if (!ctx->mailbox) { | ||
84 | ret = -EINVAL; | ||
85 | goto do_release_regions; | ||
86 | } | ||
87 | dev_dbg(ctx->dev, "SRAM Ptr %p\n", ctx->mailbox); | ||
88 | |||
89 | /* IRAM */ | ||
90 | ctx->iram_end = pci_resource_end(pci, 3); | ||
91 | ctx->iram_base = pci_resource_start(pci, 3); | ||
92 | ctx->iram = pcim_iomap(pci, 3, pci_resource_len(pci, 3)); | ||
93 | if (!ctx->iram) { | ||
94 | ret = -EINVAL; | ||
95 | goto do_release_regions; | ||
96 | } | ||
97 | dev_dbg(ctx->dev, "IRAM Ptr %p\n", ctx->iram); | ||
98 | |||
99 | /* DRAM */ | ||
100 | ctx->dram_end = pci_resource_end(pci, 4); | ||
101 | ctx->dram_base = pci_resource_start(pci, 4); | ||
102 | ctx->dram = pcim_iomap(pci, 4, pci_resource_len(pci, 4)); | ||
103 | if (!ctx->dram) { | ||
104 | ret = -EINVAL; | ||
105 | goto do_release_regions; | ||
106 | } | ||
107 | dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram); | ||
108 | do_release_regions: | ||
109 | pci_release_regions(pci); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * intel_sst_probe - PCI probe function | ||
115 | * | ||
116 | * @pci: PCI device structure | ||
117 | * @pci_id: PCI device ID structure | ||
118 | * | ||
119 | */ | ||
120 | static int intel_sst_probe(struct pci_dev *pci, | ||
121 | const struct pci_device_id *pci_id) | ||
122 | { | ||
123 | int ret = 0; | ||
124 | struct intel_sst_drv *sst_drv_ctx; | ||
125 | struct sst_platform_info *sst_pdata = pci->dev.platform_data; | ||
126 | |||
127 | dev_dbg(&pci->dev, "Probe for DID %x\n", pci->device); | ||
128 | ret = sst_alloc_drv_context(&sst_drv_ctx, &pci->dev, pci->device); | ||
129 | if (ret < 0) | ||
130 | return ret; | ||
131 | |||
132 | sst_drv_ctx->pdata = sst_pdata; | ||
133 | sst_drv_ctx->irq_num = pci->irq; | ||
134 | snprintf(sst_drv_ctx->firmware_name, sizeof(sst_drv_ctx->firmware_name), | ||
135 | "%s%04x%s", "fw_sst_", | ||
136 | sst_drv_ctx->dev_id, ".bin"); | ||
137 | |||
138 | ret = sst_context_init(sst_drv_ctx); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | /* Init the device */ | ||
143 | ret = pcim_enable_device(pci); | ||
144 | if (ret) { | ||
145 | dev_err(sst_drv_ctx->dev, | ||
146 | "device can't be enabled. Returned err: %d\n", ret); | ||
147 | goto do_free_drv_ctx; | ||
148 | } | ||
149 | sst_drv_ctx->pci = pci_dev_get(pci); | ||
150 | ret = sst_platform_get_resources(sst_drv_ctx); | ||
151 | if (ret < 0) | ||
152 | goto do_free_drv_ctx; | ||
153 | |||
154 | pci_set_drvdata(pci, sst_drv_ctx); | ||
155 | sst_configure_runtime_pm(sst_drv_ctx); | ||
156 | |||
157 | return ret; | ||
158 | |||
159 | do_free_drv_ctx: | ||
160 | sst_context_cleanup(sst_drv_ctx); | ||
161 | dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * intel_sst_remove - PCI remove function | ||
167 | * | ||
168 | * @pci: PCI device structure | ||
169 | * | ||
170 | * This function is called by OS when a device is unloaded | ||
171 | * This frees the interrupt etc | ||
172 | */ | ||
173 | static void intel_sst_remove(struct pci_dev *pci) | ||
174 | { | ||
175 | struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci); | ||
176 | |||
177 | sst_context_cleanup(sst_drv_ctx); | ||
178 | pci_dev_put(sst_drv_ctx->pci); | ||
179 | pci_release_regions(pci); | ||
180 | pci_set_drvdata(pci, NULL); | ||
181 | } | ||
182 | |||
183 | /* PCI Routines */ | ||
184 | static struct pci_device_id intel_sst_ids[] = { | ||
185 | { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, | ||
186 | { 0, } | ||
187 | }; | ||
188 | |||
189 | static struct pci_driver sst_driver = { | ||
190 | .name = SST_DRV_NAME, | ||
191 | .id_table = intel_sst_ids, | ||
192 | .probe = intel_sst_probe, | ||
193 | .remove = intel_sst_remove, | ||
194 | #ifdef CONFIG_PM | ||
195 | .driver = { | ||
196 | .pm = &intel_sst_pm, | ||
197 | }, | ||
198 | #endif | ||
199 | }; | ||
200 | |||
201 | module_pci_driver(sst_driver); | ||
202 | |||
203 | MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine PCI Driver"); | ||
204 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); | ||
205 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); | ||
206 | MODULE_AUTHOR("Dharageswari R <dharageswari.r@intel.com>"); | ||
207 | MODULE_AUTHOR("KP Jeeja <jeeja.kp@intel.com>"); | ||
208 | MODULE_LICENSE("GPL v2"); | ||
209 | MODULE_ALIAS("sst"); | ||