2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 * Routines for control of EMU10K1 chips / proc interface routines
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sound/driver.h>
29 #include <linux/slab.h>
30 #include <linux/init.h>
31 #include <sound/core.h>
32 #include <sound/emu10k1.h>
34 static void snd_emu10k1_proc_spdif_status(emu10k1_t
* emu
,
35 snd_info_buffer_t
* buffer
,
40 static char *clkaccy
[4] = { "1000ppm", "50ppm", "variable", "unknown" };
41 static int samplerate
[16] = { 44100, 1, 48000, 32000, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
42 static char *channel
[16] = { "unspec", "left", "right", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
43 static char *emphasis
[8] = { "none", "50/15 usec 2 channel", "2", "3", "4", "5", "6", "7" };
44 unsigned int status
, rate
= 0;
46 status
= snd_emu10k1_ptr_read(emu
, status_reg
, 0);
48 rate
= snd_emu10k1_ptr_read(emu
, rate_reg
, 0);
50 snd_iprintf(buffer
, "\n%s\n", title
);
52 snd_iprintf(buffer
, "Professional Mode : %s\n", (status
& SPCS_PROFESSIONAL
) ? "yes" : "no");
53 snd_iprintf(buffer
, "Not Audio Data : %s\n", (status
& SPCS_NOTAUDIODATA
) ? "yes" : "no");
54 snd_iprintf(buffer
, "Copyright : %s\n", (status
& SPCS_COPYRIGHT
) ? "yes" : "no");
55 snd_iprintf(buffer
, "Emphasis : %s\n", emphasis
[(status
& SPCS_EMPHASISMASK
) >> 3]);
56 snd_iprintf(buffer
, "Mode : %i\n", (status
& SPCS_MODEMASK
) >> 6);
57 snd_iprintf(buffer
, "Category Code : 0x%x\n", (status
& SPCS_CATEGORYCODEMASK
) >> 8);
58 snd_iprintf(buffer
, "Generation Status : %s\n", status
& SPCS_GENERATIONSTATUS
? "original" : "copy");
59 snd_iprintf(buffer
, "Source Mask : %i\n", (status
& SPCS_SOURCENUMMASK
) >> 16);
60 snd_iprintf(buffer
, "Channel Number : %s\n", channel
[(status
& SPCS_CHANNELNUMMASK
) >> 20]);
61 snd_iprintf(buffer
, "Sample Rate : %iHz\n", samplerate
[(status
& SPCS_SAMPLERATEMASK
) >> 24]);
62 snd_iprintf(buffer
, "Clock Accuracy : %s\n", clkaccy
[(status
& SPCS_CLKACCYMASK
) >> 28]);
65 snd_iprintf(buffer
, "S/PDIF Locked : %s\n", rate
& SRCS_SPDIFLOCKED
? "on" : "off");
66 snd_iprintf(buffer
, "Rate Locked : %s\n", rate
& SRCS_RATELOCKED
? "on" : "off");
67 snd_iprintf(buffer
, "Estimated Sample Rate : 0x%x\n", rate
& SRCS_ESTSAMPLERATE
);
71 static void snd_emu10k1_proc_read(snd_info_entry_t
*entry
,
72 snd_info_buffer_t
* buffer
)
74 /* FIXME - output names are in emufx.c too */
75 static char *creative_outs
[32] = {
77 /* 01 */ "AC97 Right",
78 /* 02 */ "Optical IEC958 Left",
79 /* 03 */ "Optical IEC958 Right",
82 /* 06 */ "Headphone Left",
83 /* 07 */ "Headphone Right",
84 /* 08 */ "Surround Left",
85 /* 09 */ "Surround Right",
86 /* 10 */ "PCM Capture Left",
87 /* 11 */ "PCM Capture Right",
88 /* 12 */ "MIC Capture",
89 /* 13 */ "AC97 Surround Left",
90 /* 14 */ "AC97 Surround Right",
93 /* 17 */ "Analog Center",
94 /* 18 */ "Analog LFE",
110 static char *audigy_outs
[64] = {
111 /* 00 */ "Digital Front Left",
112 /* 01 */ "Digital Front Right",
113 /* 02 */ "Digital Center",
114 /* 03 */ "Digital LEF",
115 /* 04 */ "Headphone Left",
116 /* 05 */ "Headphone Right",
117 /* 06 */ "Digital Rear Left",
118 /* 07 */ "Digital Rear Right",
119 /* 08 */ "Front Left",
120 /* 09 */ "Front Right",
125 /* 14 */ "Rear Left",
126 /* 15 */ "Rear Right",
127 /* 16 */ "AC97 Front Left",
128 /* 17 */ "AC97 Front Right",
129 /* 18 */ "ADC Caputre Left",
130 /* 19 */ "ADC Capture Right",
177 emu10k1_t
*emu
= entry
->private_data
;
179 int nefx
= emu
->audigy
? 64 : 32;
180 char **outputs
= emu
->audigy
? audigy_outs
: creative_outs
;
183 snd_iprintf(buffer
, "EMU10K1\n\n");
185 snd_emu10k1_ptr_read(emu
, A_FXRT1
, 0) :
186 snd_emu10k1_ptr_read(emu
, FXRT
, 0);
187 snd_iprintf(buffer
, "Card : %s\n",
188 emu
->audigy
? "Audigy" : (emu
->APS
? "EMU APS" : "Creative"));
189 snd_iprintf(buffer
, "Internal TRAM (words) : 0x%x\n", emu
->fx8010
.itram_size
);
190 snd_iprintf(buffer
, "External TRAM (words) : 0x%x\n", (int)emu
->fx8010
.etram_pages
.bytes
);
191 snd_iprintf(buffer
, "\n");
193 snd_iprintf(buffer
, "Effect Send Routing : A=%i, B=%i, C=%i, D=%i\n",
199 snd_iprintf(buffer
, "Effect Send Routing : A=%i, B=%i, C=%i, D=%i\n",
205 snd_iprintf(buffer
, "\nCaptured FX Outputs :\n");
206 for (idx
= 0; idx
< nefx
; idx
++) {
207 if (emu
->efx_voices_mask
[idx
/32] & (1 << (idx
%32)))
208 snd_iprintf(buffer
, " Output %02i [%s]\n", idx
, outputs
[idx
]);
210 snd_iprintf(buffer
, "\nAll FX Outputs :\n");
211 for (idx
= 0; idx
< 32; idx
++)
212 snd_iprintf(buffer
, " Output %02i [%s]\n", idx
, outputs
[idx
]);
213 snd_emu10k1_proc_spdif_status(emu
, buffer
, "S/PDIF Output 0", SPCS0
, -1);
214 snd_emu10k1_proc_spdif_status(emu
, buffer
, "S/PDIF Output 1", SPCS1
, -1);
215 snd_emu10k1_proc_spdif_status(emu
, buffer
, "S/PDIF Output 2/3", SPCS2
, -1);
216 snd_emu10k1_proc_spdif_status(emu
, buffer
, "CD-ROM S/PDIF", CDCS
, CDSRCS
);
217 snd_emu10k1_proc_spdif_status(emu
, buffer
, "General purpose S/PDIF", GPSCS
, GPSRCS
);
218 val
= snd_emu10k1_ptr_read(emu
, ZVSRCS
, 0);
219 snd_iprintf(buffer
, "\nZoomed Video\n");
220 snd_iprintf(buffer
, "Rate Locked : %s\n", val
& SRCS_RATELOCKED
? "on" : "off");
221 snd_iprintf(buffer
, "Estimated Sample Rate : 0x%x\n", val
& SRCS_ESTSAMPLERATE
);
224 static void snd_emu10k1_proc_acode_read(snd_info_entry_t
*entry
,
225 snd_info_buffer_t
* buffer
)
228 emu10k1_t
*emu
= entry
->private_data
;
230 snd_iprintf(buffer
, "FX8010 Instruction List '%s'\n", emu
->fx8010
.name
);
231 snd_iprintf(buffer
, " Code dump :\n");
232 for (pc
= 0; pc
< 512; pc
++) {
235 low
= snd_emu10k1_efx_read(emu
, pc
* 2);
236 high
= snd_emu10k1_efx_read(emu
, pc
* 2 + 1);
238 snd_iprintf(buffer
, " OP(0x%02x, 0x%03x, 0x%03x, 0x%03x, 0x%03x) /* 0x%04x: 0x%08x%08x */\n",
240 (high
>> 12) & 0x7ff,
247 snd_iprintf(buffer
, " OP(0x%02x, 0x%03x, 0x%03x, 0x%03x, 0x%03x) /* 0x%04x: 0x%08x%08x */\n",
249 (high
>> 10) & 0x3ff,
258 #define TOTAL_SIZE_GPR (0x100*4)
259 #define TOTAL_SIZE_TANKMEM_DATA (0xa0*4)
260 #define TOTAL_SIZE_TANKMEM_ADDR (0xa0*4)
261 #define TOTAL_SIZE_CODE (0x200*8)
263 static long snd_emu10k1_fx8010_read(snd_info_entry_t
*entry
, void *file_private_data
,
264 struct file
*file
, char __user
*buf
,
265 unsigned long count
, unsigned long pos
)
268 emu10k1_t
*emu
= entry
->private_data
;
271 if (!strcmp(entry
->name
, "fx8010_tram_addr")) {
272 if (emu
->audigy
) return -EINVAL
;
273 offset
= TANKMEMADDRREGBASE
;
274 } else if (!strcmp(entry
->name
, "fx8010_tram_data")) {
275 if (emu
->audigy
) return -EINVAL
;
276 offset
= TANKMEMDATAREGBASE
;
277 } else if (!strcmp(entry
->name
, "fx8010_code")) {
278 offset
= emu
->audigy
? A_MICROCODEBASE
: MICROCODEBASE
;
280 offset
= emu
->audigy
? A_FXGPREGBASE
: FXGPREGBASE
;
283 if (pos
+ size
> entry
->size
)
284 size
= (long)entry
->size
- pos
;
289 if ((tmp
= kmalloc(size
+ 8, GFP_KERNEL
)) == NULL
)
291 for (idx
= 0; idx
< ((pos
& 3) + size
+ 3) >> 2; idx
++)
292 tmp
[idx
] = snd_emu10k1_ptr_read(emu
, offset
+ idx
+ (pos
>> 2), 0);
293 if (copy_to_user(buf
, ((char *)tmp
) + (pos
& 3), size
))
304 static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010
= {
305 .read
= snd_emu10k1_fx8010_read
,
308 int __devinit
snd_emu10k1_proc_init(emu10k1_t
* emu
)
310 snd_info_entry_t
*entry
;
312 if (! snd_card_proc_new(emu
->card
, "emu10k1", &entry
))
313 snd_info_set_text_ops(entry
, emu
, 1024, snd_emu10k1_proc_read
);
315 if (! snd_card_proc_new(emu
->card
, "fx8010_gpr", &entry
)) {
316 entry
->content
= SNDRV_INFO_CONTENT_DATA
;
317 entry
->private_data
= emu
;
318 entry
->mode
= S_IFREG
| S_IRUGO
/*| S_IWUSR*/;
319 entry
->size
= TOTAL_SIZE_GPR
;
320 entry
->c
.ops
= &snd_emu10k1_proc_ops_fx8010
;
322 if (!emu
->audigy
&& ! snd_card_proc_new(emu
->card
, "fx8010_tram_data", &entry
)) {
323 entry
->content
= SNDRV_INFO_CONTENT_DATA
;
324 entry
->private_data
= emu
;
325 entry
->mode
= S_IFREG
| S_IRUGO
/*| S_IWUSR*/;
326 entry
->size
= TOTAL_SIZE_TANKMEM_DATA
;
327 entry
->c
.ops
= &snd_emu10k1_proc_ops_fx8010
;
329 if (!emu
->audigy
&& ! snd_card_proc_new(emu
->card
, "fx8010_tram_addr", &entry
)) {
330 entry
->content
= SNDRV_INFO_CONTENT_DATA
;
331 entry
->private_data
= emu
;
332 entry
->mode
= S_IFREG
| S_IRUGO
/*| S_IWUSR*/;
333 entry
->size
= TOTAL_SIZE_TANKMEM_ADDR
;
334 entry
->c
.ops
= &snd_emu10k1_proc_ops_fx8010
;
336 if (! snd_card_proc_new(emu
->card
, "fx8010_code", &entry
)) {
337 entry
->content
= SNDRV_INFO_CONTENT_DATA
;
338 entry
->private_data
= emu
;
339 entry
->mode
= S_IFREG
| S_IRUGO
/*| S_IWUSR*/;
340 entry
->size
= TOTAL_SIZE_CODE
;
341 entry
->c
.ops
= &snd_emu10k1_proc_ops_fx8010
;
343 if (! snd_card_proc_new(emu
->card
, "fx8010_acode", &entry
)) {
344 entry
->content
= SNDRV_INFO_CONTENT_TEXT
;
345 entry
->private_data
= emu
;
346 entry
->mode
= S_IFREG
| S_IRUGO
/*| S_IWUSR*/;
347 entry
->c
.text
.read_size
= 64*1024;
348 entry
->c
.text
.read
= snd_emu10k1_proc_acode_read
;