A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 Cástor Muñoz
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _PL080_H
22#define _PL080_H
23
24/*
25 * ARM PrimeCell PL080 Multiple Master DMA controller
26 */
27#include <stdint.h>
28#include <stddef.h>
29#include <stdbool.h>
30
31/* general defines */
32#define DMAC_CH_COUNT 8
33#define DMAC_LLI_MAX_COUNT 0xfff
34#define DMAC_CH_PRIO(x) (x)
35#define DMAC_CH_BASE(dmac_ba,ch_n) ((dmac_ba) + 0x100 + ((ch_n) << 5))
36
37/* PL080 controller registers */
38#define DMACINTSTS(base) (*((uint32_t volatile*)((base) + 0x00)))
39#define DMACINTTCSTS(base) (*((uint32_t volatile*)((base) + 0x04)))
40#define DMACINTTCCLR(base) (*((uint32_t volatile*)((base) + 0x08)))
41#define DMACINTERRSTS(base) (*((uint32_t volatile*)((base) + 0x0c)))
42#define DMACINTERRCLR(base) (*((uint32_t volatile*)((base) + 0x10)))
43#define DMACRAWINTTCSTS(base) (*((uint32_t volatile*)((base) + 0x14)))
44#define DMACRAWINTERRSTS(base) (*((uint32_t volatile*)((base) + 0x18)))
45#define DMACENABLEDCHANS(base) (*((uint32_t volatile*)((base) + 0x1c)))
46#define DMACSOFTBREQ(base) (*((uint32_t volatile*)((base) + 0x20)))
47#define DMACSOFTSREQ(base) (*((uint32_t volatile*)((base) + 0x24)))
48#define DMACSOFTLBREQ(base) (*((uint32_t volatile*)((base) + 0x28)))
49#define DMACSOFTLSREQ(base) (*((uint32_t volatile*)((base) + 0x2c)))
50#define DMACCONFIG(base) (*((uint32_t volatile*)((base) + 0x30)))
51#define DMACSYNC(base) (*((uint32_t volatile*)((base) + 0x34)))
52
53/* PL080 controller channel registers */
54#define DMACCxSRCADDR(base) (*((void* volatile*)((base) + 0x00)))
55#define DMACCxDESTADDR(base) (*((void* volatile*)((base) + 0x04)))
56#define DMACCxLINK(base) (*((uint32_t volatile*)((base) + 0x08)))
57#define DMACCxCONTROL(base) (*((uint32_t volatile*)((base) + 0x0c)))
58#define DMACCxCONFIG(base) (*((uint32_t volatile*)((base) + 0x10)))
59
60/* PL080 controller channel LLI */
61#define DMACCxLLI(base) ((struct dmac_lli volatile*)(base))
62
63/* PL080 DMA controller configuration register */
64#define DMACCONFIG_E_POS 0 /* DMAC enable */
65#define DMACCONFIG_E_MSK 0x1
66#define DMACCONFIG_M1_POS 1 /* AHB Master 1 endianness */
67#define DMACCONFIG_M1_MSK 0x1
68#define DMACCONFIG_M2_POS 2 /* AHB Master 2 endianness */
69#define DMACCONFIG_M2_MSK 0x1
70
71#define DMACCONFIG_E_BIT (1 << DMACCONFIG_E_POS)
72#define DMACCONFIG_M1_BIT (1 << DMACCCONFI_M1_POS)
73#define DMACCONFIG_M2_BIT (1 << DMACCCONFI_M2_POS)
74
75#define DMACCONFIG_M_LITTLE_ENDIAN 0
76#define DMACCONFIG_M_BIG_ENDIAN 1
77
78/* PL080 DMA controller channel LLI register */
79#define DMACCxLINK_LM_POS 0
80#define DMACCxLINK_LM_MSK 0x1
81#define DMACCxLINK_NEXTLLI_POS 2
82#define DMACCxLINK_NEXTLLI_MSK 0x3fffffff
83
84/* PL080 channel control register */
85#define DMACCxCONTROL_I_POS 31 /* terminal count interrupt */
86#define DMACCxCONTROL_I_MSK 0x1
87#define DMACCxCONTROL_PROT_POS 28 /* protection bits */
88#define DMACCxCONTROL_PROT_MSK 0x7
89#define DMACCxCONTROL_DI_POS 27 /* destination addr increment */
90#define DMACCxCONTROL_DI_MSK 0x1
91#define DMACCxCONTROL_SI_POS 26 /* source addr increment */
92#define DMACCxCONTROL_SI_MSK 0x1
93#define DMACCxCONTROL_D_POS 25 /* destinantion AHB master */
94#define DMACCxCONTROL_D_MSK 0x1
95#define DMACCxCONTROL_S_POS 24 /* source AHB master */
96#define DMACCxCONTROL_S_MSK 0x1
97#define DMACCxCONTROL_DWIDTH_POS 21 /* destinantion transfer width */
98#define DMACCxCONTROL_DWIDTH_MSK 0x7
99#define DMACCxCONTROL_SWIDTH_POS 18 /* source transfer width */
100#define DMACCxCONTROL_SWIDTH_MSK 0x7
101#define DMACCxCONTROL_DBSIZE_POS 15 /* destinantion burst size */
102#define DMACCxCONTROL_DBSIZE_MSK 0x7
103#define DMACCxCONTROL_SBSIZE_POS 12 /* source burst size */
104#define DMACCxCONTROL_SBSIZE_MSK 0x7
105#define DMACCxCONTROL_COUNT_POS 0 /* n SWIDTH size transfers */
106#define DMACCxCONTROL_COUNT_MSK 0xfff
107
108#define DMACCxCONTROL_WIDTH_8 0
109#define DMACCxCONTROL_WIDTH_16 1
110#define DMACCxCONTROL_WIDTH_32 2
111
112#define DMACCxCONTROL_BSIZE_1 0
113#define DMACCxCONTROL_BSIZE_4 1
114#define DMACCxCONTROL_BSIZE_8 2
115#define DMACCxCONTROL_BSIZE_16 3
116#define DMACCxCONTROL_BSIZE_32 4
117#define DMACCxCONTROL_BSIZE_64 5
118#define DMACCxCONTROL_BSIZE_128 6
119#define DMACCxCONTROL_BSIZE_256 7
120
121#define DMACCxCONTROL_INC_DISABLE 0
122#define DMACCxCONTROL_INC_ENABLE 1
123
124#define DMACCxCONTROL_I_BIT (1 << DMACCxCONTROL_I_POS)
125
126/* protection bits */
127#define DMAC_PROT_PRIV (1 << 0)
128#define DMAC_PROT_BUFF (1 << 1)
129#define DMAC_PROT_CACH (1 << 2)
130
131/* bus */
132#define DMAC_MASTER_AHB1 0
133#define DMAC_MASTER_AHB2 1
134
135/* PL080 channel configuration register */
136#define DMACCxCONFIG_E_POS 0 /* enable */
137#define DMACCxCONFIG_E_MSK 0x1
138#define DMACCxCONFIG_SRCPERI_POS 1 /* source peripheral */
139#define DMACCxCONFIG_SRCPERI_MSK 0xf
140#define DMACCxCONFIG_DESTPERI_POS 6 /* destination peripheral */
141#define DMACCxCONFIG_DESTPERI_MSK 0xf
142#define DMACCxCONFIG_FLOWCNTRL_POS 11 /* DMA transfer type */
143#define DMACCxCONFIG_FLOWCNTRL_MSK 0x7
144#define DMACCxCONFIG_IE_POS 14 /* interrupt error mask */
145#define DMACCxCONFIG_IE_MSK 0x1
146#define DMACCxCONFIG_ITC_POS 15 /* interrupt terminal count mask */
147#define DMACCxCONFIG_ITC_MSK 0x1
148#define DMACCxCONFIG_L_POS 16 /* lock */
149#define DMACCxCONFIG_L_MSK 0x1
150#define DMACCxCONFIG_A_POS 17 /* active */
151#define DMACCxCONFIG_A_MSK 0x1
152#define DMACCxCONFIG_H_POS 18 /* halt */
153#define DMACCxCONFIG_H_MSK 0x1
154
155#define DMACCxCONFIG_E_BIT (1 << DMACCxCONFIG_E_POS)
156#define DMACCxCONFIG_IE_BIT (1 << DMACCxCONFIG_IE_POS)
157#define DMACCxCONFIG_ITC_BIT (1 << DMACCxCONFIG_ITC_POS)
158#define DMACCxCONFIG_L_BIT (1 << DMACCxCONFIG_L_POS)
159#define DMACCxCONFIG_A_BIT (1 << DMACCxCONFIG_A_POS)
160#define DMACCxCONFIG_H_BIT (1 << DMACCxCONFIG_H_POS)
161
162#define DMACCxCONFIG_FLOWCNTRL_MEMMEM_DMA 0
163#define DMACCxCONFIG_FLOWCNTRL_MEMPERI_DMA 1
164#define DMACCxCONFIG_FLOWCNTRL_PERIMEM_DMA 2
165#define DMACCxCONFIG_FLOWCNTRL_PERIPERI_DMA 3
166#define DMACCxCONFIG_FLOWCNTRL_PERIPERI_DSTPERI 4
167#define DMACCxCONFIG_FLOWCNTRL_MEMPERI_PERI 5
168#define DMACCxCONFIG_FLOWCNTRL_PERIMEM_PERI 6
169#define DMACCxCONFIG_FLOWCNTRL_PERIPERI_SRCPERI 7
170
171/*
172 * types
173 */
174struct dmac_lli {
175 void* srcaddr;
176 void* dstaddr;
177 uint32_t link;
178 uint32_t control;
179} __attribute__((aligned(16)));
180
181struct dmac_tsk {
182 struct dmac_lli volatile *start_lli;
183 struct dmac_lli volatile *end_lli;
184 uint32_t size;
185 void *cb_data;
186};
187
188/* used when src/dst peri is memory */
189#define DMAC_PERI_NONE 0x80
190
191struct dmac_ch_cfg {
192 uint8_t srcperi;
193 uint8_t dstperi;
194 uint8_t sbsize;
195 uint8_t dbsize;
196 uint8_t swidth;
197 uint8_t dwidth;
198 uint8_t sbus;
199 uint8_t dbus;
200 uint8_t sinc;
201 uint8_t dinc;
202 uint8_t prot;
203 uint16_t lli_xfer_max_count;
204};
205
206struct dmac_ch {
207 /** user configurable data **/
208 struct dmac *dmac;
209 unsigned int prio;
210 void (*cb_fn)(void *cb_data);
211 /* tsk circular buffer */
212 struct dmac_tsk *tskbuf;
213 uint32_t tskbuf_mask;
214 uint32_t queue_mode;
215 /* lli circular buffer */
216 struct dmac_lli volatile *llibuf;
217 uint32_t llibuf_mask;
218 uint32_t llibuf_bus;
219
220 /** private driver data **/
221 uint32_t baddr;
222 struct dmac_lli volatile *llibuf_top;
223 uint32_t tasks_queued; /* roll-over counter */
224 uint32_t tasks_done; /* roll-over counter */
225 uint32_t control;
226 struct dmac_ch_cfg *cfg;
227};
228
229struct dmac {
230 /* user configurable data */
231 const uint32_t baddr;
232 const uint8_t m1;
233 const uint8_t m2;
234
235 /* driver private data */
236 struct dmac_ch *ch_l[DMAC_CH_COUNT];
237 uint32_t ch_run_status; /* channel running status mask */
238};
239
240/* dmac_ch->queue_mode */
241enum {
242 QUEUE_NORMAL,
243 QUEUE_LINK,
244};
245
246/*
247 * prototypes
248 */
249void dmac_callback(struct dmac *dmac);
250
251void dmac_open(struct dmac *dmac);
252
253void dmac_ch_init(struct dmac_ch *ch, struct dmac_ch_cfg *cfg);
254
255void dmac_ch_lock_int(struct dmac_ch *ch);
256void dmac_ch_unlock_int(struct dmac_ch *ch);
257
258void dmac_ch_queue_2d(struct dmac_ch *ch, void *srcaddr, void *dstaddr,
259 size_t size, size_t width, size_t stride, void *cb_data);
260#define dmac_ch_queue(ch, srcaddr, dstaddr, size, cb_data) \
261 dmac_ch_queue_2d(ch, srcaddr, dstaddr, size, 0, 0, cb_data)
262
263void dmac_ch_stop(struct dmac_ch* ch);
264
265bool dmac_ch_running(struct dmac_ch *ch);
266
267void *dmac_ch_get_info(struct dmac_ch *ch,
268 size_t *bytes, size_t *t_bytes);
269
270#endif /* _PL080_H */