1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
|
#ifndef __YMFPCI_H
#define __YMFPCI_H
/*
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Definitions for Yahama YMF724/740/744/754 chips
*
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/config.h>
/*
* Direct registers
*/
/* #define YMFREG(codec, reg) (codec->port + YDSXGR_##reg) */
#define YDSXGR_INTFLAG 0x0004
#define YDSXGR_ACTIVITY 0x0006
#define YDSXGR_GLOBALCTRL 0x0008
#define YDSXGR_ZVCTRL 0x000A
#define YDSXGR_TIMERCTRL 0x0010
#define YDSXGR_TIMERCTRL_TEN 0x0001
#define YDSXGR_TIMERCTRL_TIEN 0x0002
#define YDSXGR_TIMERCOUNT 0x0012
#define YDSXGR_SPDIFOUTCTRL 0x0018
#define YDSXGR_SPDIFOUTSTATUS 0x001C
#define YDSXGR_EEPROMCTRL 0x0020
#define YDSXGR_SPDIFINCTRL 0x0034
#define YDSXGR_SPDIFINSTATUS 0x0038
#define YDSXGR_DSPPROGRAMDL 0x0048
#define YDSXGR_DLCNTRL 0x004C
#define YDSXGR_GPIOININTFLAG 0x0050
#define YDSXGR_GPIOININTENABLE 0x0052
#define YDSXGR_GPIOINSTATUS 0x0054
#define YDSXGR_GPIOOUTCTRL 0x0056
#define YDSXGR_GPIOFUNCENABLE 0x0058
#define YDSXGR_GPIOTYPECONFIG 0x005A
#define YDSXGR_AC97CMDDATA 0x0060
#define YDSXGR_AC97CMDADR 0x0062
#define YDSXGR_PRISTATUSDATA 0x0064
#define YDSXGR_PRISTATUSADR 0x0066
#define YDSXGR_SECSTATUSDATA 0x0068
#define YDSXGR_SECSTATUSADR 0x006A
#define YDSXGR_SECCONFIG 0x0070
#define YDSXGR_LEGACYOUTVOL 0x0080
#define YDSXGR_LEGACYOUTVOLL 0x0080
#define YDSXGR_LEGACYOUTVOLR 0x0082
#define YDSXGR_NATIVEDACOUTVOL 0x0084
#define YDSXGR_NATIVEDACOUTVOLL 0x0084
#define YDSXGR_NATIVEDACOUTVOLR 0x0086
#define YDSXGR_SPDIFOUTVOL 0x0088
#define YDSXGR_SPDIFOUTVOLL 0x0088
#define YDSXGR_SPDIFOUTVOLR 0x008A
#define YDSXGR_AC3OUTVOL 0x008C
#define YDSXGR_AC3OUTVOLL 0x008C
#define YDSXGR_AC3OUTVOLR 0x008E
#define YDSXGR_PRIADCOUTVOL 0x0090
#define YDSXGR_PRIADCOUTVOLL 0x0090
#define YDSXGR_PRIADCOUTVOLR 0x0092
#define YDSXGR_LEGACYLOOPVOL 0x0094
#define YDSXGR_LEGACYLOOPVOLL 0x0094
#define YDSXGR_LEGACYLOOPVOLR 0x0096
#define YDSXGR_NATIVEDACLOOPVOL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLR 0x009A
#define YDSXGR_SPDIFLOOPVOL 0x009C
#define YDSXGR_SPDIFLOOPVOLL 0x009E
#define YDSXGR_SPDIFLOOPVOLR 0x009E
#define YDSXGR_AC3LOOPVOL 0x00A0
#define YDSXGR_AC3LOOPVOLL 0x00A0
#define YDSXGR_AC3LOOPVOLR 0x00A2
#define YDSXGR_PRIADCLOOPVOL 0x00A4
#define YDSXGR_PRIADCLOOPVOLL 0x00A4
#define YDSXGR_PRIADCLOOPVOLR 0x00A6
#define YDSXGR_NATIVEADCINVOL 0x00A8
#define YDSXGR_NATIVEADCINVOLL 0x00A8
#define YDSXGR_NATIVEADCINVOLR 0x00AA
#define YDSXGR_NATIVEDACINVOL 0x00AC
#define YDSXGR_NATIVEDACINVOLL 0x00AC
#define YDSXGR_NATIVEDACINVOLR 0x00AE
#define YDSXGR_BUF441OUTVOL 0x00B0
#define YDSXGR_BUF441OUTVOLL 0x00B0
#define YDSXGR_BUF441OUTVOLR 0x00B2
#define YDSXGR_BUF441LOOPVOL 0x00B4
#define YDSXGR_BUF441LOOPVOLL 0x00B4
#define YDSXGR_BUF441LOOPVOLR 0x00B6
#define YDSXGR_SPDIFOUTVOL2 0x00B8
#define YDSXGR_SPDIFOUTVOL2L 0x00B8
#define YDSXGR_SPDIFOUTVOL2R 0x00BA
#define YDSXGR_SPDIFLOOPVOL2 0x00BC
#define YDSXGR_SPDIFLOOPVOL2L 0x00BC
#define YDSXGR_SPDIFLOOPVOL2R 0x00BE
#define YDSXGR_ADCSLOTSR 0x00C0
#define YDSXGR_RECSLOTSR 0x00C4
#define YDSXGR_ADCFORMAT 0x00C8
#define YDSXGR_RECFORMAT 0x00CC
#define YDSXGR_P44SLOTSR 0x00D0
#define YDSXGR_STATUS 0x0100
#define YDSXGR_CTRLSELECT 0x0104
#define YDSXGR_MODE 0x0108
#define YDSXGR_SAMPLECOUNT 0x010C
#define YDSXGR_NUMOFSAMPLES 0x0110
#define YDSXGR_CONFIG 0x0114
#define YDSXGR_PLAYCTRLSIZE 0x0140
#define YDSXGR_RECCTRLSIZE 0x0144
#define YDSXGR_EFFCTRLSIZE 0x0148
#define YDSXGR_WORKSIZE 0x014C
#define YDSXGR_MAPOFREC 0x0150
#define YDSXGR_MAPOFEFFECT 0x0154
#define YDSXGR_PLAYCTRLBASE 0x0158
#define YDSXGR_RECCTRLBASE 0x015C
#define YDSXGR_EFFCTRLBASE 0x0160
#define YDSXGR_WORKBASE 0x0164
#define YDSXGR_DSPINSTRAM 0x1000
#define YDSXGR_CTRLINSTRAM 0x4000
#define YDSXG_AC97READCMD 0x8000
#define YDSXG_AC97WRITECMD 0x0000
#define PCIR_LEGCTRL 0x40
#define PCIR_ELEGCTRL 0x42
#define PCIR_DSXGCTRL 0x48
#define PCIR_DSXPWRCTRL1 0x4a
#define PCIR_DSXPWRCTRL2 0x4e
#define PCIR_OPLADR 0x60
#define PCIR_SBADR 0x62
#define PCIR_MPUADR 0x64
#define YDSXG_DSPLENGTH 0x0080
#define YDSXG_CTRLLENGTH 0x3000
#define YDSXG_DEFAULT_WORK_SIZE 0x0400
#define YDSXG_PLAYBACK_VOICES 64
#define YDSXG_CAPTURE_VOICES 2
#define YDSXG_EFFECT_VOICES 5
/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
#define NR_AC97 2
#define YMF_SAMPF 256 /* Samples per frame @48000 */
/*
* The slot/voice control bank (2 of these per voice)
*/
typedef struct stru_ymfpci_playback_bank {
u32 format;
u32 loop_default;
u32 base; /* 32-bit address */
u32 loop_start; /* 32-bit offset */
u32 loop_end; /* 32-bit offset */
u32 loop_frac; /* 8-bit fraction - loop_start */
u32 delta_end; /* pitch delta end */
u32 lpfK_end;
u32 eg_gain_end;
u32 left_gain_end;
u32 right_gain_end;
u32 eff1_gain_end;
u32 eff2_gain_end;
u32 eff3_gain_end;
u32 lpfQ;
u32 status; /* P3: Always 0 for some reason. */
u32 num_of_frames;
u32 loop_count;
u32 start; /* P3: J. reads this to know where chip is. */
u32 start_frac;
u32 delta;
u32 lpfK;
u32 eg_gain;
u32 left_gain;
u32 right_gain;
u32 eff1_gain;
u32 eff2_gain;
u32 eff3_gain;
u32 lpfD1;
u32 lpfD2;
} ymfpci_playback_bank_t;
typedef struct stru_ymfpci_capture_bank {
u32 base; /* 32-bit address (aligned at 4) */
u32 loop_end; /* size in BYTES (aligned at 4) */
u32 start; /* 32-bit offset */
u32 num_of_loops; /* counter */
} ymfpci_capture_bank_t;
typedef struct stru_ymfpci_effect_bank {
u32 base; /* 32-bit address */
u32 loop_end; /* 32-bit offset */
u32 start; /* 32-bit offset */
u32 temp;
} ymfpci_effect_bank_t;
typedef struct ymf_voice ymfpci_voice_t;
/*
* Throughout the code Yaroslav names YMF unit pointer "codec"
* even though it does not correspond to any codec. Must be historic.
* We replace it with "unit" over time.
* AC97 parts use "codec" to denote a codec, naturally.
*/
typedef struct ymf_unit ymfpci_t;
typedef enum {
YMFPCI_PCM,
YMFPCI_SYNTH,
YMFPCI_MIDI
} ymfpci_voice_type_t;
struct ymf_voice {
// ymfpci_t *codec;
int number;
char use, pcm, synth, midi; // bool
ymfpci_playback_bank_t *bank;
struct ymf_pcm *ypcm;
dma_addr_t bank_ba;
};
struct ymf_capture {
// struct ymf_unit *unit;
int use;
ymfpci_capture_bank_t *bank;
struct ymf_pcm *ypcm;
};
struct ymf_unit {
u8 rev; /* PCI revision */
void __iomem *reg_area_virt;
void *dma_area_va;
dma_addr_t dma_area_ba;
unsigned int dma_area_size;
dma_addr_t bank_base_capture;
dma_addr_t bank_base_effect;
dma_addr_t work_base;
unsigned int work_size;
u32 *ctrl_playback;
dma_addr_t ctrl_playback_ba;
ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2];
ymfpci_capture_bank_t *bank_capture[YDSXG_CAPTURE_VOICES][2];
ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2];
int start_count;
int suspended;
u32 active_bank;
struct ymf_voice voices[YDSXG_PLAYBACK_VOICES];
struct ymf_capture capture[YDSXG_CAPTURE_VOICES];
struct ac97_codec *ac97_codec[NR_AC97];
u16 ac97_features;
struct pci_dev *pci;
#ifdef CONFIG_SOUND_YMFPCI_LEGACY
/* legacy hardware resources */
unsigned int iosynth, iomidi;
struct address_info opl3_data, mpu_data;
#endif
spinlock_t reg_lock;
spinlock_t voice_lock;
spinlock_t ac97_lock;
/* soundcore stuff */
int dev_audio;
struct semaphore open_sem;
struct list_head ymf_devs;
struct list_head states; /* List of states for this unit */
};
struct ymf_dmabuf {
dma_addr_t dma_addr;
void *rawbuf;
unsigned buforder;
/* OSS buffer management stuff */
unsigned numfrag;
unsigned fragshift;
/* our buffer acts like a circular ring */
unsigned hwptr; /* where dma last started */
unsigned swptr; /* where driver last clear/filled */
int count; /* fill count */
unsigned total_bytes; /* total bytes dmaed by hardware */
wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize; /* Total rawbuf[] size */
/* OSS stuff */
unsigned mapped:1;
unsigned ready:1;
unsigned ossfragshift;
int ossmaxfrags;
unsigned subdivision;
};
struct ymf_pcm_format {
int format; /* OSS format */
int rate; /* rate in Hz */
int voices; /* number of voices */
int shift; /* redundant, computed from the above */
};
typedef enum {
PLAYBACK_VOICE,
CAPTURE_REC,
CAPTURE_AC97,
EFFECT_DRY_LEFT,
EFFECT_DRY_RIGHT,
EFFECT_EFF1,
EFFECT_EFF2,
EFFECT_EFF3
} ymfpci_pcm_type_t;
/* This is variant record, but we hate unions. Little waste on pointers []. */
struct ymf_pcm {
ymfpci_pcm_type_t type;
struct ymf_state *state;
ymfpci_voice_t *voices[2];
int capture_bank_number;
struct ymf_dmabuf dmabuf;
int running;
int spdif;
};
/*
* "Software" or virtual channel, an instance of opened /dev/dsp.
* It may have two physical channels (pcms) for duplex operations.
*/
struct ymf_state {
struct list_head chain;
struct ymf_unit *unit; /* backpointer */
struct ymf_pcm rpcm, wpcm;
struct ymf_pcm_format format;
};
#endif /* __YMFPCI_H */
|