summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baluta <daniel.baluta@nxp.com>2019-08-07 11:02:01 -0400
committerMark Brown <broonie@kernel.org>2019-08-09 08:26:20 -0400
commit83ee7ab1627b7597bbb9acc26b37e9f96fff40c9 (patch)
treee59fc8ffa0bdef3cd195dbe335993f60242aebca
parente17422cda9d60339d71e117d3fdfd444e83669a4 (diff)
ASoC: SOF: Intel: byt: Refactor fw ready / mem windows creation
There is a lot of duplicate code when processing IPC firmware ready notification and creating memory windows. First step in reducing the code duplication is to introduce generic functions: * sof_get_windows * sof_fw_ready that will replace, in the first step, the specific implementation related to baytrail related platforms: * byt_get_windows * byt_fw_ready So we are basically moving code from intel/byt.c to loader.c keeping in mind that mbox_offset is a per platform constant so we need to use newly introduced snd_sof_dsp_get_mailbox_offset / snd_sof_dsp_get_window_offset in order to get the correct mbox offset / window offset value. Also, bar is a per platform constant so we use snd_sof_dsp_get_bar_index instead of the hardcoded BYT_DSP_BAR. Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20190807150203.26359-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/sof/intel/byt.c164
-rw-r--r--sound/soc/sof/loader.c168
-rw-r--r--sound/soc/sof/sof-priv.h2
3 files changed, 189 insertions, 145 deletions
diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c
index cb8f02ee09f2..5e7a6aaa627a 100644
--- a/sound/soc/sof/intel/byt.c
+++ b/sound/soc/sof/intel/byt.c
@@ -110,148 +110,6 @@ static void byt_dsp_done(struct snd_sof_dev *sdev);
110static void byt_get_reply(struct snd_sof_dev *sdev); 110static void byt_get_reply(struct snd_sof_dev *sdev);
111 111
112/* 112/*
113 * IPC Firmware ready.
114 */
115static void byt_get_windows(struct snd_sof_dev *sdev)
116{
117 struct sof_ipc_window_elem *elem;
118 u32 outbox_offset = 0;
119 u32 stream_offset = 0;
120 u32 inbox_offset = 0;
121 u32 outbox_size = 0;
122 u32 stream_size = 0;
123 u32 inbox_size = 0;
124 int i;
125
126 if (!sdev->info_window) {
127 dev_err(sdev->dev, "error: have no window info\n");
128 return;
129 }
130
131 for (i = 0; i < sdev->info_window->num_windows; i++) {
132 elem = &sdev->info_window->window[i];
133
134 switch (elem->type) {
135 case SOF_IPC_REGION_UPBOX:
136 inbox_offset = elem->offset + MBOX_OFFSET;
137 inbox_size = elem->size;
138 snd_sof_debugfs_io_item(sdev,
139 sdev->bar[BYT_DSP_BAR] +
140 inbox_offset,
141 elem->size, "inbox",
142 SOF_DEBUGFS_ACCESS_D0_ONLY);
143 break;
144 case SOF_IPC_REGION_DOWNBOX:
145 outbox_offset = elem->offset + MBOX_OFFSET;
146 outbox_size = elem->size;
147 snd_sof_debugfs_io_item(sdev,
148 sdev->bar[BYT_DSP_BAR] +
149 outbox_offset,
150 elem->size, "outbox",
151 SOF_DEBUGFS_ACCESS_D0_ONLY);
152 break;
153 case SOF_IPC_REGION_TRACE:
154 snd_sof_debugfs_io_item(sdev,
155 sdev->bar[BYT_DSP_BAR] +
156 elem->offset +
157 MBOX_OFFSET,
158 elem->size, "etrace",
159 SOF_DEBUGFS_ACCESS_D0_ONLY);
160 break;
161 case SOF_IPC_REGION_DEBUG:
162 snd_sof_debugfs_io_item(sdev,
163 sdev->bar[BYT_DSP_BAR] +
164 elem->offset +
165 MBOX_OFFSET,
166 elem->size, "debug",
167 SOF_DEBUGFS_ACCESS_D0_ONLY);
168 break;
169 case SOF_IPC_REGION_STREAM:
170 stream_offset = elem->offset + MBOX_OFFSET;
171 stream_size = elem->size;
172 snd_sof_debugfs_io_item(sdev,
173 sdev->bar[BYT_DSP_BAR] +
174 stream_offset,
175 elem->size, "stream",
176 SOF_DEBUGFS_ACCESS_D0_ONLY);
177 break;
178 case SOF_IPC_REGION_REGS:
179 snd_sof_debugfs_io_item(sdev,
180 sdev->bar[BYT_DSP_BAR] +
181 elem->offset +
182 MBOX_OFFSET,
183 elem->size, "regs",
184 SOF_DEBUGFS_ACCESS_D0_ONLY);
185 break;
186 case SOF_IPC_REGION_EXCEPTION:
187 sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET;
188 snd_sof_debugfs_io_item(sdev,
189 sdev->bar[BYT_DSP_BAR] +
190 elem->offset +
191 MBOX_OFFSET,
192 elem->size, "exception",
193 SOF_DEBUGFS_ACCESS_D0_ONLY);
194 break;
195 default:
196 dev_err(sdev->dev, "error: get illegal window info\n");
197 return;
198 }
199 }
200
201 if (outbox_size == 0 || inbox_size == 0) {
202 dev_err(sdev->dev, "error: get illegal mailbox window\n");
203 return;
204 }
205
206 snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
207 outbox_offset, outbox_size);
208 sdev->stream_box.offset = stream_offset;
209 sdev->stream_box.size = stream_size;
210
211 dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n",
212 inbox_offset, inbox_size);
213 dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n",
214 outbox_offset, outbox_size);
215 dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n",
216 stream_offset, stream_size);
217}
218
219/* check for ABI compatibility and create memory windows on first boot */
220static int byt_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
221{
222 struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready;
223 u32 offset;
224 int ret;
225
226 /* mailbox must be on 4k boundary */
227 offset = MBOX_OFFSET;
228
229 dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n",
230 msg_id, offset);
231
232 /* no need to re-check version/ABI for subsequent boots */
233 if (!sdev->first_boot)
234 return 0;
235
236 /* copy data from the DSP FW ready offset */
237 sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready,
238 sizeof(*fw_ready));
239
240 /* make sure ABI version is compatible */
241 ret = snd_sof_ipc_valid(sdev);
242 if (ret < 0)
243 return ret;
244
245 /* now check for extended data */
246 snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, MBOX_OFFSET +
247 sizeof(struct sof_ipc_fw_ready));
248
249 byt_get_windows(sdev);
250
251 return 0;
252}
253
254/*
255 * Debug 113 * Debug
256 */ 114 */
257 115
@@ -418,6 +276,16 @@ static void byt_get_reply(struct snd_sof_dev *sdev)
418 msg->reply_error = ret; 276 msg->reply_error = ret;
419} 277}
420 278
279static int byt_get_mailbox_offset(struct snd_sof_dev *sdev)
280{
281 return MBOX_OFFSET;
282}
283
284static int byt_get_window_offset(struct snd_sof_dev *sdev, u32 id)
285{
286 return MBOX_OFFSET;
287}
288
421static void byt_host_done(struct snd_sof_dev *sdev) 289static void byt_host_done(struct snd_sof_dev *sdev)
422{ 290{
423 /* clear BUSY bit and set DONE bit - accept new messages */ 291 /* clear BUSY bit and set DONE bit - accept new messages */
@@ -612,7 +480,9 @@ const struct snd_sof_dsp_ops sof_tng_ops = {
612 480
613 /* ipc */ 481 /* ipc */
614 .send_msg = byt_send_msg, 482 .send_msg = byt_send_msg,
615 .fw_ready = byt_fw_ready, 483 .fw_ready = sof_fw_ready,
484 .get_mailbox_offset = byt_get_mailbox_offset,
485 .get_window_offset = byt_get_window_offset,
616 486
617 .ipc_msg_data = intel_ipc_msg_data, 487 .ipc_msg_data = intel_ipc_msg_data,
618 .ipc_pcm_params = intel_ipc_pcm_params, 488 .ipc_pcm_params = intel_ipc_pcm_params,
@@ -771,7 +641,9 @@ const struct snd_sof_dsp_ops sof_byt_ops = {
771 641
772 /* ipc */ 642 /* ipc */
773 .send_msg = byt_send_msg, 643 .send_msg = byt_send_msg,
774 .fw_ready = byt_fw_ready, 644 .fw_ready = sof_fw_ready,
645 .get_mailbox_offset = byt_get_mailbox_offset,
646 .get_window_offset = byt_get_window_offset,
775 647
776 .ipc_msg_data = intel_ipc_msg_data, 648 .ipc_msg_data = intel_ipc_msg_data,
777 .ipc_pcm_params = intel_ipc_pcm_params, 649 .ipc_pcm_params = intel_ipc_pcm_params,
@@ -828,7 +700,9 @@ const struct snd_sof_dsp_ops sof_cht_ops = {
828 700
829 /* ipc */ 701 /* ipc */
830 .send_msg = byt_send_msg, 702 .send_msg = byt_send_msg,
831 .fw_ready = byt_fw_ready, 703 .fw_ready = sof_fw_ready,
704 .get_mailbox_offset = byt_get_mailbox_offset,
705 .get_window_offset = byt_get_window_offset,
832 706
833 .ipc_msg_data = intel_ipc_msg_data, 707 .ipc_msg_data = intel_ipc_msg_data,
834 .ipc_pcm_params = intel_ipc_pcm_params, 708 .ipc_pcm_params = intel_ipc_pcm_params,
diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c
index 93cb8fd0844f..d7f32745fefe 100644
--- a/sound/soc/sof/loader.c
+++ b/sound/soc/sof/loader.c
@@ -87,6 +87,174 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
87} 87}
88EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); 88EXPORT_SYMBOL(snd_sof_fw_parse_ext_data);
89 89
90/*
91 * IPC Firmware ready.
92 */
93static void sof_get_windows(struct snd_sof_dev *sdev)
94{
95 struct sof_ipc_window_elem *elem;
96 u32 outbox_offset = 0;
97 u32 stream_offset = 0;
98 u32 inbox_offset = 0;
99 u32 outbox_size = 0;
100 u32 stream_size = 0;
101 u32 inbox_size = 0;
102 int window_offset;
103 int bar;
104 int i;
105
106 if (!sdev->info_window) {
107 dev_err(sdev->dev, "error: have no window info\n");
108 return;
109 }
110
111 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM);
112 if (bar < 0) {
113 dev_err(sdev->dev, "error: have no bar mapping\n");
114 return;
115 }
116
117 for (i = 0; i < sdev->info_window->num_windows; i++) {
118 elem = &sdev->info_window->window[i];
119
120 window_offset = snd_sof_dsp_get_window_offset(sdev, elem->id);
121 if (window_offset < 0) {
122 dev_warn(sdev->dev, "warn: no offset for window %d\n",
123 elem->id);
124 continue;
125 }
126
127 switch (elem->type) {
128 case SOF_IPC_REGION_UPBOX:
129 inbox_offset = window_offset + elem->offset;
130 inbox_size = elem->size;
131 snd_sof_debugfs_io_item(sdev,
132 sdev->bar[bar] +
133 inbox_offset,
134 elem->size, "inbox",
135 SOF_DEBUGFS_ACCESS_D0_ONLY);
136 break;
137 case SOF_IPC_REGION_DOWNBOX:
138 outbox_offset = window_offset + elem->offset;
139 outbox_size = elem->size;
140 snd_sof_debugfs_io_item(sdev,
141 sdev->bar[bar] +
142 outbox_offset,
143 elem->size, "outbox",
144 SOF_DEBUGFS_ACCESS_D0_ONLY);
145 break;
146 case SOF_IPC_REGION_TRACE:
147 snd_sof_debugfs_io_item(sdev,
148 sdev->bar[bar] +
149 window_offset +
150 elem->offset,
151 elem->size, "etrace",
152 SOF_DEBUGFS_ACCESS_D0_ONLY);
153 break;
154 case SOF_IPC_REGION_DEBUG:
155 snd_sof_debugfs_io_item(sdev,
156 sdev->bar[bar] +
157 window_offset +
158 elem->offset,
159 elem->size, "debug",
160 SOF_DEBUGFS_ACCESS_D0_ONLY);
161 break;
162 case SOF_IPC_REGION_STREAM:
163 stream_offset = window_offset + elem->offset;
164 stream_size = elem->size;
165 snd_sof_debugfs_io_item(sdev,
166 sdev->bar[bar] +
167 stream_offset,
168 elem->size, "stream",
169 SOF_DEBUGFS_ACCESS_D0_ONLY);
170 break;
171 case SOF_IPC_REGION_REGS:
172 snd_sof_debugfs_io_item(sdev,
173 sdev->bar[bar] +
174 window_offset +
175 elem->offset,
176 elem->size, "regs",
177 SOF_DEBUGFS_ACCESS_D0_ONLY);
178 break;
179 case SOF_IPC_REGION_EXCEPTION:
180 sdev->dsp_oops_offset = window_offset + elem->offset;
181 snd_sof_debugfs_io_item(sdev,
182 sdev->bar[bar] +
183 window_offset +
184 elem->offset,
185 elem->size, "exception",
186 SOF_DEBUGFS_ACCESS_D0_ONLY);
187 break;
188 default:
189 dev_err(sdev->dev, "error: get illegal window info\n");
190 return;
191 }
192 }
193
194 if (outbox_size == 0 || inbox_size == 0) {
195 dev_err(sdev->dev, "error: get illegal mailbox window\n");
196 return;
197 }
198
199 snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
200 outbox_offset, outbox_size);
201 sdev->stream_box.offset = stream_offset;
202 sdev->stream_box.size = stream_size;
203
204 dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n",
205 inbox_offset, inbox_size);
206 dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n",
207 outbox_offset, outbox_size);
208 dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n",
209 stream_offset, stream_size);
210}
211
212/* check for ABI compatibility and create memory windows on first boot */
213int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
214{
215 struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready;
216 int offset;
217 int bar;
218 int ret;
219
220 /* mailbox must be on 4k boundary */
221 offset = snd_sof_dsp_get_mailbox_offset(sdev);
222 if (offset < 0) {
223 dev_err(sdev->dev, "error: have no mailbox offset\n");
224 return offset;
225 }
226
227 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM);
228 if (bar < 0) {
229 dev_err(sdev->dev, "error: have no bar mapping\n");
230 return -EINVAL;
231 }
232
233 dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n",
234 msg_id, offset);
235
236 /* no need to re-check version/ABI for subsequent boots */
237 if (!sdev->first_boot)
238 return 0;
239
240 /* copy data from the DSP FW ready offset */
241 sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready));
242
243 /* make sure ABI version is compatible */
244 ret = snd_sof_ipc_valid(sdev);
245 if (ret < 0)
246 return ret;
247
248 /* now check for extended data */
249 snd_sof_fw_parse_ext_data(sdev, bar, offset +
250 sizeof(struct sof_ipc_fw_ready));
251
252 sof_get_windows(sdev);
253
254 return 0;
255}
256EXPORT_SYMBOL(sof_fw_ready);
257
90/* generic module parser for mmaped DSPs */ 258/* generic module parser for mmaped DSPs */
91int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, 259int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev,
92 struct snd_sof_mod_hdr *module) 260 struct snd_sof_mod_hdr *module)
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index de11f28bae3a..730f3259dd02 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -642,6 +642,8 @@ void sof_block_write(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *src,
642void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest, 642void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest,
643 size_t size); 643 size_t size);
644 644
645int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id);
646
645void intel_ipc_msg_data(struct snd_sof_dev *sdev, 647void intel_ipc_msg_data(struct snd_sof_dev *sdev,
646 struct snd_pcm_substream *substream, 648 struct snd_pcm_substream *substream,
647 void *p, size_t sz); 649 void *p, size_t sz);