2 * SPU processing offload to TI C64x DSP using bsp's c64_tools
3 * (C) GraÅžvydas "notaz" Ignotas, 2015
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is furnished to do
10 * so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #include <libc64_dsp/include/inc_overlay.h>
31 /* dummy deps, some bloat but avoids ifdef hell in SPU code.. */
32 static void thread_work_start(void) {}
33 static void thread_work_wait_sync(struct work_item *work, int force) {}
34 static int thread_get_i_done(void) { return 0; }
35 struct out_driver *out_current;
36 void SetupSound(void) {}
39 static void invalidate_cache(struct work_item *work)
41 syscalls.cache_inv(work, offsetof(typeof(*work), RVB), 1);
42 syscalls.cache_inv(spu.s_chan, sizeof(spu.s_chan[0]) * 24, 0);
43 syscalls.cache_inv(work->SSumLR,
44 sizeof(work->SSumLR[0]) * 2 * work->ns_to, 0);
47 static void writeout_cache(struct work_item *work)
49 int ns_to = work->ns_to;
51 syscalls.cache_wb(work->RVB, sizeof(work->RVB[0]) * 2 * ns_to, 1);
52 syscalls.cache_wb(work->SSumLR, sizeof(work->SSumLR[0]) * 2 * ns_to, 1);
55 static void do_processing(void)
57 struct work_item *work;
60 while (worker->active)
62 // i_ready is in first cacheline
63 syscalls.cache_inv(worker, 64, 1);
65 left = worker->i_ready - worker->i_done;
68 worker->active = ACTIVE_CNT;
69 syscalls.cache_wb(&worker->active, 4, 1);
71 work = &worker->i[worker->i_done & WORK_I_MASK];
72 invalidate_cache(work);
73 do_channel_work(work);
77 syscalls.cache_wb(&worker->i_done, 4, 1);
81 // nothing to do? Write out non-critical caches
83 syscalls.cache_wb(spu.spuMemC + 0x800, 0x800, 1);
84 syscalls.cache_wb(spu.SB, sizeof(spu.SB[0]) * SB_SIZE * 24, 1);
89 // this ->active loop thing is to avoid a race where we miss
90 // new work and clear ->active just after ARM checks it
92 syscalls.cache_wb(&worker->active, 4, 1);
96 static unsigned int exec(dsp_component_cmd_t cmd,
97 unsigned int arg1, unsigned int arg2,
98 unsigned int *ret1, unsigned int *ret2)
100 struct region_mem *mem = (void *)arg1;
106 spu.spuMemC = mem->spu_ram;
108 spu.s_chan = mem->s_chan;
109 worker = &mem->worker;
110 memcpy(&spu_config, &mem->spu_config, sizeof(spu_config));
112 mem->sizeof_region_mem = sizeof(*mem);
113 mem->offsetof_s_chan1 = offsetof(typeof(*mem), s_chan[1]);
114 mem->offsetof_spos_3_20 = offsetof(typeof(*mem), worker.i[3].ch[20]);
115 // seems to be unneeded, no write-alloc? but just in case..
116 syscalls.cache_wb(&mem->sizeof_region_mem, 3 * 4, 1);
120 worker->active = ACTIVE_CNT;
122 syscalls.cache_wb(&worker->i_done, 64, 1);
123 memcpy(&spu_config, &mem->spu_config, sizeof(spu_config));
127 // c64_tools lib does BCACHE_wbInvAll() when it receives mailbox irq,
128 // but invalidate anyway in case c64_tools is ever fixed..
129 syscalls.cache_inv(mem, sizeof(mem->spu_ram) + sizeof(mem->SB), 0);
133 syscalls.printf("bad cmd: %x\n", cmd);
140 #pragma DATA_SECTION(component_test_dsp, ".sec_com");
141 dsp_component_t component_test_dsp = {
145 NULL, /* exec fastcall RPC */
154 // vim:shiftwidth=1:expandtab