Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
3e5f1270
Commit
3e5f1270
authored
Feb 12, 2003
by
Dave Jones
Committed by
Linus Torvalds
Feb 12, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] OSS rme96xx update.
Lingering around for a while. 2.4 forward port.
parent
1b5f52b3
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1161 additions
and
94 deletions
+1161
-94
Documentation/sound/rme96xx
Documentation/sound/rme96xx
+767
-0
sound/oss/rme96xx.c
sound/oss/rme96xx.c
+341
-58
sound/oss/rme96xx.h
sound/oss/rme96xx.h
+53
-36
No files found.
Documentation/sound/rme96xx
0 → 100644
View file @
3e5f1270
Beta release of the rme96xx (driver for RME 96XX cards like the
"Hammerfall" and the "Hammerfall light")
Important: The driver module has to be installed on a freshly rebooted system,
otherwise the driver might not be able to acquire its buffers.
features:
- OSS programming interface (i.e. runs with standard OSS soundsoftware)
- OSS/Multichannel interface (OSS multichannel is done by just aquiring
more than 2 channels). The driver does not use more than one device
( yet .. this feature may be implemented later )
- more than one RME card supported
The driver uses a specific multichannel interface, which I will document
when the driver gets stable. (take a look at the defines in rme96xx.h,
which adds blocked multichannel formats i.e instead of
lrlrlrlr --> llllrrrr etc.
Use the "rmectrl" programm to look at the status of the card ..
or use xrmectrl, a GUI interface for the ctrl program.
What you can do with the rmectrl program is to set the stereo device for
OSS emulation (e.g. if you use SPDIF out).
You do:
./ctrl offset 24 24
which makes the stereo device use channels 25 and 26.
Guenter Geiger <geiger@epy.co.at>
copy the first part of the attached source code into rmectrl.c
and the second part into xrmectrl (or get the program from
http://gige.xdv.org/pages/soft/pages/rme)
to compile: gcc -o rmectrl rmectrl.c
------------------------------ snip ------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/soundcard.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
#include "rme96xx.h"
/*
remctrl.c
(C) 2000 Guenter Geiger <geiger@debian.org>
HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
*/
/* # define DEVICE_NAME "/dev/mixer" */
# define DEVICE_NAME "/dev/mixer1"
void usage(void)
{
fprintf(stderr,"usage: rmectrl [/dev/mixer<n>] [command [options]]\n\n");
fprintf(stderr,"where command is one of:\n");
fprintf(stderr," help show this help\n");
fprintf(stderr," status show status bits\n");
fprintf(stderr," control show control bits\n");
fprintf(stderr," mix show mixer/offset status\n");
fprintf(stderr," master <n> set sync master\n");
fprintf(stderr," pro <n> set spdif out pro\n");
fprintf(stderr," emphasis <n> set spdif out emphasis\n");
fprintf(stderr," dolby <n> set spdif out no audio\n");
fprintf(stderr," optout <n> set spdif out optical\n");
fprintf(stderr," wordclock <n> set sync wordclock\n");
fprintf(stderr," spdifin <n> set spdif in (0=optical,1=coax,2=intern)\n");
fprintf(stderr," syncref <n> set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n");
fprintf(stderr," adat1cd <n> set ADAT1 on internal CD\n");
fprintf(stderr," offset <devnr> <in> <out> set dev (0..3) offset (0..25)\n");
exit(-1);
}
int main(int argc, char* argv[])
{
int cards;
int ret;
int i;
double ft;
int fd, fdwr;
int param,orig;
rme_status_t stat;
rme_ctrl_t ctrl;
char *device;
int argidx;
if (argc < 2)
usage();
if (*argv[1]=='/') {
device = argv[1];
argidx = 2;
}
else {
device = DEVICE_NAME;
argidx = 1;
}
fprintf(stdout,"mixer device %s\n",device);
if ((fd = open(device,O_RDONLY)) < 0) {
fprintf(stdout,"opening device failed\n");
exit(-1);
}
if ((fdwr = open(device,O_WRONLY)) < 0) {
fprintf(stdout,"opening device failed\n");
exit(-1);
}
if (argc < argidx+1)
usage();
if (!strcmp(argv[argidx],"help"))
usage();
if (!strcmp(argv[argidx],"-h"))
usage();
if (!strcmp(argv[argidx],"--help"))
usage();
if (!strcmp(argv[argidx],"status")) {
ioctl(fd,SOUND_MIXER_PRIVATE2,&stat);
fprintf(stdout,"stat.irq %d\n",stat.irq);
fprintf(stdout,"stat.lockmask %d\n",stat.lockmask);
fprintf(stdout,"stat.sr48 %d\n",stat.sr48);
fprintf(stdout,"stat.wclock %d\n",stat.wclock);
fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint);
fprintf(stdout,"stat.syncmask %d\n",stat.syncmask);
fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed);
fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy);
fprintf(stdout,"stat.tc_out %d\n",stat.tc_out);
fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate);
fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error);
fprintf(stdout,"stat.bufid %d\n",stat.bufid);
fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid);
exit (0);
}
if (!strcmp(argv[argidx],"control")) {
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
fprintf(stdout,"ctrl.start %d\n",ctrl.start);
fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency);
fprintf(stdout,"ctrl.master %d\n",ctrl.master);
fprintf(stdout,"ctrl.ie %d\n",ctrl.ie);
fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48);
fprintf(stdout,"ctrl.spare %d\n",ctrl.spare);
fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed);
fprintf(stdout,"ctrl.pro %d\n",ctrl.pro);
fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis);
fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby);
fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out);
fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock);
fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in);
fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref);
fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset);
fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select);
fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock);
fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write);
fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd);
exit (0);
}
if (!strcmp(argv[argidx],"mix")) {
rme_mixer mix;
int i;
for (i=0; i<4; i++) {
mix.devnr = i;
ioctl(fd,SOUND_MIXER_PRIVATE1,&mix);
if (mix.devnr == i) {
fprintf(stdout,"devnr %d\n",mix.devnr);
fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset);
fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset);
}
}
exit (0);
}
/* the control flags */
if (argc < argidx+2)
usage();
if (!strcmp(argv[argidx],"master")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("master = %d\n",val);
ctrl.master = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"pro")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("pro = %d\n",val);
ctrl.pro = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"emphasis")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("emphasis = %d\n",val);
ctrl.emphasis = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"dolby")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("dolby = %d\n",val);
ctrl.dolby = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"optout")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("optout = %d\n",val);
ctrl.opt_out = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"wordclock")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("wordclock = %d\n",val);
ctrl.wordclock = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"spdifin")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("spdifin = %d\n",val);
ctrl.spdif_in = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"syncref")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("syncref = %d\n",val);
ctrl.sync_ref = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
if (!strcmp(argv[argidx],"adat1cd")) {
int val = atoi(argv[argidx+1]);
ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
printf("adat1cd = %d\n",val);
ctrl.adat1_cd = val;
ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
exit (0);
}
/* setting offset */
if (argc < argidx+4)
usage();
if (!strcmp(argv[argidx],"offset")) {
rme_mixer mix;
mix.devnr = atoi(argv[argidx+1]);
mix.i_offset = atoi(argv[argidx+2]);
mix.o_offset = atoi(argv[argidx+3]);
ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix);
fprintf(stdout,"devnr %d\n",mix.devnr);
fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset);
fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset);
exit (0);
}
usage();
exit (0); /* to avoid warning */
}
---------------------------- <snip> --------------------------------
#!/usr/bin/wish
# xrmectrl
# (C) 2000 Guenter Geiger <geiger@debian.org>
# HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
#set defaults "-relief ridged"
set CTRLPROG "./rmectrl"
if {$argc} {
set CTRLPROG "$CTRLPROG $argv"
}
puts "CTRLPROG $CTRLPROG"
frame .butts
button .butts.exit -text "Exit" -command "exit" -relief ridge
#button .butts.state -text "State" -command "get_all"
pack .butts.exit -side left
pack .butts -side bottom
#
# STATUS
#
frame .status
# Sampling Rate
frame .status.sr
label .status.sr.text -text "Sampling Rate" -justify left
radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times
radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times
radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times
radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw -variable srate -value 96000 -font times
pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3
# Lock
frame .status.lock
label .status.lock.text -text "Lock" -justify left
checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times
checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times
checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times
pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3
# Sync
frame .status.sync
label .status.sync.text -text "Sync" -justify left
checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times
checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times
checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times
pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3
# Timecode
frame .status.tc
label .status.tc.text -text "Timecode" -justify left
checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times
checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times
checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times
pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3
# SPDIF In
frame .status.spdif
label .status.spdif.text -text "SPDIF In" -justify left
label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times
checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times
pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3
pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1
#
# CONTROL
#
proc setprof {} {
global CTRLPROG
global spprof
exec $CTRLPROG pro $spprof
}
proc setemph {} {
global CTRLPROG
global spemph
exec $CTRLPROG emphasis $spemph
}
proc setnoaud {} {
global CTRLPROG
global spnoaud
exec $CTRLPROG dolby $spnoaud
}
proc setoptical {} {
global CTRLPROG
global spoptical
exec $CTRLPROG optout $spoptical
}
proc setspdifin {} {
global CTRLPROG
global spdifin
exec $CTRLPROG spdifin [expr $spdifin - 1]
}
proc setsyncsource {} {
global CTRLPROG
global syncsource
exec $CTRLPROG syncref [expr $syncsource -1]
}
proc setmaster {} {
global CTRLPROG
global master
exec $CTRLPROG master $master
}
proc setwordclock {} {
global CTRLPROG
global wordclock
exec $CTRLPROG wordclock $wordclock
}
proc setadat1cd {} {
global CTRLPROG
global adat1cd
exec $CTRLPROG adat1cd $adat1cd
}
frame .control
# SPDIF In & SPDIF Out
frame .control.spdif
frame .control.spdif.in
label .control.spdif.in.text -text "SPDIF In" -justify left
radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times
radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times
radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times
checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times
pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd
label .control.spdif.space
frame .control.spdif.out
label .control.spdif.out.text -text "SPDIF Out" -justify left
checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times
checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times
checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times
checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times
pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom
pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1
# Sync Mode & Sync Source
frame .control.sync
frame .control.sync.mode
label .control.sync.mode.text -text "Sync Mode" -justify left
checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times
checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times
pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc
label .control.sync.space
frame .control.sync.src
label .control.sync.src.text -text "Sync Source" -justify left
radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times
radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times
radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times
radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times
pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom
pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1
label .control.space -text "" -width 10
# Buffer Size
frame .control.buf
label .control.buf.text -text "Buffer Size (Latency)" -justify left
radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times
radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times
radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times
radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times
radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times
radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times
radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times
radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times
pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3
# Offset
frame .control.offset
frame .control.offset.in
label .control.offset.in.text -text "Offset In" -justify left
label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3
label .control.offset.space
frame .control.offset.out
label .control.offset.out.text -text "Offset Out" -justify left
label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom
pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1
pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1
label .statustext -text Status -justify center -relief ridge
label .controltext -text Control -justify center -relief ridge
label .statusspace
label .controlspace
pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1
proc get_bit {output sstr} {
set idx1 [string last [concat $sstr 1] $output]
set idx1 [expr $idx1 != -1]
return $idx1
}
proc get_val {output sstr} {
set val [string wordend $output [string last $sstr $output]]
set val [string range $output $val [expr $val+1]]
return $val
}
proc get_val2 {output sstr} {
set val [string wordend $output [string first $sstr $output]]
set val [string range $output $val [expr $val+2]]
return $val
}
proc get_control {} {
global spprof
global spemph
global spnoaud
global spoptical
global spdifin
global ssrate
global master
global wordclock
global syncsource
global CTRLPROG
set f [open "| $CTRLPROG control" r+]
set ooo [read $f 1000]
close $f
# puts $ooo
set spprof [ get_bit $ooo "pro"]
set spemph [ get_bit $ooo "emphasis"]
set spnoaud [ get_bit $ooo "dolby"]
set spoptical [ get_bit $ooo "opt_out"]
set spdifin [ expr [ get_val $ooo "spdif_in"] + 1]
set ssrate [ expr [ get_val $ooo "latency"] + 1]
set master [ expr [ get_val $ooo "master"]]
set wordclock [ expr [ get_val $ooo "wordclock"]]
set syncsource [ expr [ get_val $ooo "sync_ref"] + 1]
}
proc get_status {} {
global srate
global ctrlcom
global adatlock1
global adatlock2
global adatlock3
global adatsync1
global adatsync2
global adatsync3
global tcbusy
global tcout
global tcvalid
global spdiferr
global crystal
global .status.spdif.text
global CTRLPROG
set f [open "| $CTRLPROG status" r+]
set ooo [read $f 1000]
close $f
# puts $ooo
# samplerate
set idx1 [string last "sr48 1" $ooo]
set idx2 [string last "doublespeed 1" $ooo]
if {$idx1 >= 0} {
set fact1 48000
} else {
set fact1 44100
}
if {$idx2 >= 0} {
set fact2 2
} else {
set fact2 1
}
set srate [expr $fact1 * $fact2]
# ADAT lock
set val [get_val $ooo lockmask]
set adatlock1 0
set adatlock2 0
set adatlock3 0
if {[expr $val & 1]} {
set adatlock3 1
}
if {[expr $val & 2]} {
set adatlock2 1
}
if {[expr $val & 4]} {
set adatlock1 1
}
# ADAT sync
set val [get_val $ooo syncmask]
set adatsync1 0
set adatsync2 0
set adatsync3 0
if {[expr $val & 1]} {
set adatsync3 1
}
if {[expr $val & 2]} {
set adatsync2 1
}
if {[expr $val & 4]} {
set adatsync1 1
}
# TC busy
set tcbusy [get_bit $ooo "busy"]
set tcout [get_bit $ooo "out"]
set tcvalid [get_bit $ooo "valid"]
set spdiferr [expr [get_bit $ooo "spdif_error"] == 0]
# 000=64kHz, 100=88.2kHz, 011=96kHz
# 111=32kHz, 110=44.1kHz, 101=48kHz
set val [get_val $ooo crystalrate]
set crystal "--.- kHz"
if {$val == 0} {
set crystal "64 kHz"
}
if {$val == 4} {
set crystal "88.2 kHz"
}
if {$val == 3} {
set crystal "96 kHz"
}
if {$val == 7} {
set crystal "32 kHz"
}
if {$val == 6} {
set crystal "44.1 kHz"
}
if {$val == 5} {
set crystal "48 kHz"
}
.status.spdif.sr configure -text $crystal
}
proc get_offset {} {
global inoffset
global outoffset
global CTRLPROG
set f [open "| $CTRLPROG mix" r+]
set ooo [read $f 1000]
close $f
# puts $ooo
if { [string match "*devnr*" $ooo] } {
set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
set val [get_val2 $ooo i_offset]
.control.offset.in.off0 configure -text "dev\#0: $val"
set val [get_val2 $ooo o_offset]
.control.offset.out.off0 configure -text "dev\#0: $val"
} else {
.control.offset.in.off0 configure -text "dev\#0: -"
.control.offset.out.off0 configure -text "dev\#0: -"
}
if { [string match "*devnr*" $ooo] } {
set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
set val [get_val2 $ooo i_offset]
.control.offset.in.off1 configure -text "dev\#1: $val"
set val [get_val2 $ooo o_offset]
.control.offset.out.off1 configure -text "dev\#1: $val"
} else {
.control.offset.in.off1 configure -text "dev\#1: -"
.control.offset.out.off1 configure -text "dev\#1: -"
}
if { [string match "*devnr*" $ooo] } {
set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
set val [get_val2 $ooo i_offset]
.control.offset.in.off2 configure -text "dev\#2: $val"
set val [get_val2 $ooo o_offset]
.control.offset.out.off2 configure -text "dev\#2: $val"
} else {
.control.offset.in.off2 configure -text "dev\#2: -"
.control.offset.out.off2 configure -text "dev\#2: -"
}
if { [string match "*devnr*" $ooo] } {
set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
set val [get_val2 $ooo i_offset]
.control.offset.in.off3 configure -text "dev\#3: $val"
set val [get_val2 $ooo o_offset]
.control.offset.out.off3 configure -text "dev\#3: $val"
} else {
.control.offset.in.off3 configure -text "dev\#3: -"
.control.offset.out.off3 configure -text "dev\#3: -"
}
}
proc get_all {} {
get_status
get_control
get_offset
}
# main
while {1} {
after 200
get_all
update
}
sound/oss/rme96xx.c
View file @
3e5f1270
...
@@ -10,6 +10,17 @@
...
@@ -10,6 +10,17 @@
* 11 May 2001: 0.4 fixed for SMP, included into kernel source tree
* 11 May 2001: 0.4 fixed for SMP, included into kernel source tree
* 17 May 2001: 0.5 draining code didn't work on new cards
* 17 May 2001: 0.5 draining code didn't work on new cards
* 18 May 2001: 0.6 remove synchronize_irq() call
* 18 May 2001: 0.6 remove synchronize_irq() call
* 17 Jul 2001: 0.7 updated xrmectrl to make it work for newer cards
* 2 feb 2002: 0.8 fixed pci device handling, see below for patches from Heiko (Thanks!)
Marcus Meissner <Marcus.Meissner@caldera.de>
Modifications - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
HP20020108 fixed handling of "large" read()
HP20020116 towards REV 1.5 support, based on ALSA's card-rme9652.c
HP20020118 made mixer ioctl and handling of devices>1 more safe
HP20020201 fixed handling of "large" read() properly
added REV 1.5 S/P-DIF receiver support
SNDCTL_DSP_SPEED now returns the actual speed
* 10 Aug 2002: added synchronize_irq() again
* 10 Aug 2002: added synchronize_irq() again
TODO:
TODO:
...
@@ -20,15 +31,17 @@
...
@@ -20,15 +31,17 @@
- mixer mmap interface
- mixer mmap interface
- mixer ioctl
- mixer ioctl
- get rid of noise upon first open (why ??)
- get rid of noise upon first open (why ??)
- allow multiple open(at least for read)
- allow multiple open
(at least for read)
- allow multiple open for non overlapping regions
- allow multiple open for non overlapping regions
- recheck the multiple devices part (offsets of different devices, etc)
- recheck the multiple devices part (offsets of different devices, etc)
- do decent draining in _release --- done
- do decent draining in _release --- done
- SMP support
- SMP support
- what about using fragstotal>2 for small fragsize? (HP20020118)
- add support for AFMT_S32_LE
*/
*/
#ifndef RMEVERSION
#ifndef RMEVERSION
#define RMEVERSION "0.
6
"
#define RMEVERSION "0.
8
"
#endif
#endif
#include <linux/version.h>
#include <linux/version.h>
...
@@ -41,6 +54,8 @@
...
@@ -41,6 +54,8 @@
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <asm/dma.h>
#include <asm/hardirq.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/poll.h>
...
@@ -134,45 +149,57 @@ MODULE_LICENSE("GPL");
...
@@ -134,45 +149,57 @@ MODULE_LICENSE("GPL");
#define RME96xx_F_0 0x0400000
/* 000=64kHz, 100=88.2kHz, 011=96kHz */
#define RME96xx_F_0 0x0400000
/* 000=64kHz, 100=88.2kHz, 011=96kHz */
#define RME96xx_F_1 0x0800000
/* 111=32kHz, 110=44.1kHz, 101=48kHz, */
#define RME96xx_F_1 0x0800000
/* 111=32kHz, 110=44.1kHz, 101=48kHz, */
#define RME96xx_F_2 0x1000000
/*
od external Crystal Chip if ERF=1
*/
#define RME96xx_F_2 0x1000000
/*
001=Rev 1.5+ external Crystal Chip
*/
#define RME96xx_ERF 0x2000000
/* Error-Flag of SDPIF Receiver (1=No Lock)*/
#define RME96xx_ERF 0x2000000
/* Error-Flag of SDPIF Receiver (1=No Lock)*/
#define RME96xx_buffer_id 0x4000000
/* toggles by each interrupt on rec/play */
#define RME96xx_buffer_id 0x4000000
/* toggles by each interrupt on rec/play */
#define RME96xx_tc_valid 0x8000000
/* 1 = a signal is detected on time-code input */
#define RME96xx_tc_valid 0x8000000
/* 1 = a signal is detected on time-code input */
#define RME96xx_SPDIF_READ 0x10000000
/* byte available from Rev 1.5+ SPDIF interface */
/* Status Register Fields */
/* Status Register Fields */
#define RME96xx_lock (RME96xx_lock_0|RME96xx_lock_1|RME96xx_lock_2)
#define RME96xx_lock (RME96xx_lock_0|RME96xx_lock_1|RME96xx_lock_2)
#define RME96xx_buf_pos 0x000FFC0
#define RME96xx_sync (RME96xx_sync_0|RME96xx_sync_1|RME96xx_sync_2)
#define RME96xx_sync (RME96xx_sync_0|RME96xx_sync_1|RME96xx_sync_2)
#define RME96xx_F (RME96xx_F_0|RME96xx_F_1|RME96xx_F_2)
#define RME96xx_F (RME96xx_F_0|RME96xx_F_1|RME96xx_F_2)
#define rme96xx_decode_spdif_rate(x) ((x)>>22)
/* Bit 6..15 : h/w buffer pointer */
#define RME96xx_buf_pos 0x000FFC0
/* Bits 31,30,29 are bits 5,4,3 of h/w pointer position on later
Rev G EEPROMS and Rev 1.5 cards or later.
*/
#define RME96xx_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME96xx_buf_pos))
/* Control-Register: */
/* Control-Register: */
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
#define RME96xx_start_bit
0x0001
/* start record/play */
#define RME96xx_start_bit
0x0001
/* start record/play */
#define RME96xx_latency0
0x0002
/* Bit 0 - Buffer size or
latency */
#define RME96xx_latency0
0x0002
/* Buffer size /
latency */
#define RME96xx_latency1
0x0004
/* Bit 1 - Buffer size or latency
*/
#define RME96xx_latency1
0x0004
/* buffersize = 512Bytes * 2^n
*/
#define RME96xx_latency2
0x0008
/* Bit 2 - Buffer size or latency
*/
#define RME96xx_latency2
0x0008
/* 0=64samples ... 7=8192samples
*/
#define RME96xx_Master 0x0010
/* Clock Mode Master=1,Slave/Auto=0 */
#define RME96xx_Master 0x0010
/* Clock Mode 1=Master, 0=Slave/Auto */
#define RME96xx_IE 0x0020
/* Interupt Enable */
#define RME96xx_IE 0x0020
/* Interupt Enable */
#define RME96xx_freq 0x0040
/* samplerate 0=44.1/88.2, 1=48/96 kHz*/
#define RME96xx_freq 0x0040
/* samplerate 0=44.1/88.2, 1=48/96 kHz*/
#define RME96xx_freq1 0x0080
/* samplerate 0=32 kHz, 1=other rates ??? (from ALSA, but may be wrong) */
#define RME96xx_DS 0x0100
/* double speed 0=44.1/48, 1=88.2/96 Khz */
#define RME96xx_PRO 0x0200
/* SPDIF-OUT 0=consumer, 1=professional */
#define RME96xx_EMP 0x0400
/* SPDIF-OUT emphasis 0=off, 1=on */
#define RME96xx_Dolby 0x0800
/* SPDIF-OUT non-audio bit 1=set, 0=unset */
#define RME96xx_opt_out 0x1000
/* use 1st optical OUT as SPDIF: 1=yes, 0=no */
#define RME96xx_wsel 0x2000
/* use Wordclock as sync (overwrites master) */
#define RME96xx_inp_0 0x4000
/* SPDIF-IN 00=optical (ADAT1), */
#define RME96xx_inp_1 0x8000
/* 01=coaxial (Cinch), 10=internal CDROM */
#define RME96xx_DS 0x0100
/* Doule Speed 0=44.1/48, 1=88.2/96 Khz */
#define RME96xx_SyncRef0 0x10000
/* preferred sync-source in autosync */
#define RME96xx_PRO 0x0200
/* spdif 0=consumer, 1=professional Mode*/
#define RME96xx_SyncRef1 0x20000
/* 00=ADAT1, 01=ADAT2, 10=ADAT3, 11=SPDIF */
#define RME96xx_EMP 0x0400
/* spdif Emphasis 0=None, 1=ON */
#define RME96xx_Dolby 0x0800
/* spdif Non-audio bit 1=set, 0=unset */
#define RME96xx_opt_out 0x1000
/* Use 1st optical OUT as SPDIF: 1=yes,0=no */
#define RME96xx_SPDIF_RESET (1<<18)
/* Rev 1.5+: h/w SPDIF receiver */
#define RME96xx_wsel 0x2000
/* use Wordclock as sync (overwrites master)*/
#define RME96xx_SPDIF_SELECT (1<<19)
#define RME96xx_inp_0 0x4000
/* SPDIF-IN: 00=optical (ADAT1), */
#define RME96xx_SPDIF_CLOCK (1<<20)
#define RME96xx_inp_1 0x8000
/* 01=koaxial (Cinch), 10=Internal CDROM*/
#define RME96xx_SPDIF_WRITE (1<<21)
#define RME96xx_ADAT1_INTERNAL (1<<22)
/* Rev 1.5+: if set, internal CD connector carries ADAT */
#define RME96xx_SyncRef0 0x10000
/* preferred sync-source in autosync */
#define RME96xx_SyncRef1 0x20000
/* 00=ADAT1,01=ADAT2,10=ADAT3,11=SPDIF */
#define RME96xx_ctrl_init (RME96xx_latency0 |\
#define RME96xx_ctrl_init (RME96xx_latency0 |\
...
@@ -186,7 +213,9 @@ MODULE_LICENSE("GPL");
...
@@ -186,7 +213,9 @@ MODULE_LICENSE("GPL");
#define RME96xx_latency (RME96xx_latency0|RME96xx_latency1|RME96xx_latency2)
#define RME96xx_latency (RME96xx_latency0|RME96xx_latency1|RME96xx_latency2)
#define RME96xx_inp (RME96xx_inp_0|RME96xx_inp_1)
#define RME96xx_inp (RME96xx_inp_0|RME96xx_inp_1)
#define RME96xx_SyncRef (RME96xx_SyncRef0|RME96xx_SyncRef1)
#define RME96xx_SyncRef (RME96xx_SyncRef0|RME96xx_SyncRef1)
/* latency = 512Bytes * 2^n, where n is made from Bit3 ... Bit0 */
#define RME96xx_mixer_allowed (RME96xx_Master|RME96xx_PRO|RME96xx_EMP|RME96xx_Dolby|RME96xx_opt_out|RME96xx_wsel|RME96xx_inp|RME96xx_SyncRef|RME96xx_ADAT1_INTERNAL)
/* latency = 512Bytes * 2^n, where n is made from Bit3 ... Bit1 (??? HP20020201) */
#define RME96xx_SET_LATENCY(x) (((x)&0x7)<<1)
#define RME96xx_SET_LATENCY(x) (((x)&0x7)<<1)
#define RME96xx_GET_LATENCY(x) (((x)>>1)&0x7)
#define RME96xx_GET_LATENCY(x) (((x)>>1)&0x7)
...
@@ -211,6 +240,7 @@ MODULE_LICENSE("GPL");
...
@@ -211,6 +240,7 @@ MODULE_LICENSE("GPL");
#define RME96xx_MAX_DEVS 4
/* we provide some OSS stereodevs */
#define RME96xx_MAX_DEVS 4
/* we provide some OSS stereodevs */
#define RME96xx_MASK_DEVS 0x3
/* RME96xx_MAX_DEVS-1 */
#define RME_MESS "rme96xx:"
#define RME_MESS "rme96xx:"
/*------------------------------------------------------------------------
/*------------------------------------------------------------------------
...
@@ -259,8 +289,10 @@ typedef struct _rme96xx_info {
...
@@ -259,8 +289,10 @@ typedef struct _rme96xx_info {
u32
thru_bits
;
/* thru 1=on, 0=off channel 1=Bit1... channel 26= Bit26 */
u32
thru_bits
;
/* thru 1=on, 0=off channel 1=Bit1... channel 26= Bit26 */
int
open_count
;
int
hw_rev
;
/* h/w rev * 10 (i.e. 1.5 has hw_rev = 15) */
char
*
card_name
;
/* hammerfall or hammerfall light names */
int
open_count
;
/* unused ??? HP20020201 */
int
rate
;
int
rate
;
int
latency
;
int
latency
;
...
@@ -324,6 +356,181 @@ inline void rme96xx_unset_ctrl(rme96xx_info* s,int mask)
...
@@ -324,6 +356,181 @@ inline void rme96xx_unset_ctrl(rme96xx_info* s,int mask)
}
}
inline
int
rme96xx_get_sample_rate_status
(
rme96xx_info
*
s
)
{
int
val
;
u32
status
;
status
=
readl
(
s
->
iobase
+
RME96xx_status_register
);
val
=
(
status
&
RME96xx_fs48
)
?
48000
:
44100
;
if
(
status
&
RME96xx_DS_rd
)
val
*=
2
;
return
val
;
}
inline
int
rme96xx_get_sample_rate_ctrl
(
rme96xx_info
*
s
)
{
int
val
;
val
=
(
s
->
control_register
&
RME96xx_freq
)
?
48000
:
44100
;
if
(
s
->
control_register
&
RME96xx_DS
)
val
*=
2
;
return
val
;
}
/* code from ALSA card-rme9652.c for rev 1.5 SPDIF receiver HP 20020201 */
static
void
rme96xx_spdif_set_bit
(
rme96xx_info
*
s
,
int
mask
,
int
onoff
)
{
if
(
onoff
)
s
->
control_register
|=
mask
;
else
s
->
control_register
&=
~
mask
;
writel
(
s
->
control_register
,
s
->
iobase
+
RME96xx_control_register
);
}
static
void
rme96xx_spdif_write_byte
(
rme96xx_info
*
s
,
const
int
val
)
{
long
mask
;
long
i
;
for
(
i
=
0
,
mask
=
0x80
;
i
<
8
;
i
++
,
mask
>>=
1
)
{
if
(
val
&
mask
)
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_WRITE
,
1
);
else
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_WRITE
,
0
);
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_CLOCK
,
1
);
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_CLOCK
,
0
);
}
}
static
int
rme96xx_spdif_read_byte
(
rme96xx_info
*
s
)
{
long
mask
;
long
val
;
long
i
;
val
=
0
;
for
(
i
=
0
,
mask
=
0x80
;
i
<
8
;
i
++
,
mask
>>=
1
)
{
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_CLOCK
,
1
);
if
(
readl
(
s
->
iobase
+
RME96xx_status_register
)
&
RME96xx_SPDIF_READ
)
val
|=
mask
;
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_CLOCK
,
0
);
}
return
val
;
}
static
void
rme96xx_write_spdif_codec
(
rme96xx_info
*
s
,
const
int
address
,
const
int
data
)
{
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_SELECT
,
1
);
rme96xx_spdif_write_byte
(
s
,
0x20
);
rme96xx_spdif_write_byte
(
s
,
address
);
rme96xx_spdif_write_byte
(
s
,
data
);
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_SELECT
,
0
);
}
static
int
rme96xx_spdif_read_codec
(
rme96xx_info
*
s
,
const
int
address
)
{
int
ret
;
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_SELECT
,
1
);
rme96xx_spdif_write_byte
(
s
,
0x20
);
rme96xx_spdif_write_byte
(
s
,
address
);
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_SELECT
,
0
);
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_SELECT
,
1
);
rme96xx_spdif_write_byte
(
s
,
0x21
);
ret
=
rme96xx_spdif_read_byte
(
s
);
rme96xx_spdif_set_bit
(
s
,
RME96xx_SPDIF_SELECT
,
0
);
return
ret
;
}
static
void
rme96xx_initialize_spdif_receiver
(
rme96xx_info
*
s
)
{
/* XXX what unsets this ? */
/* no idea ??? HP 20020201 */
s
->
control_register
|=
RME96xx_SPDIF_RESET
;
rme96xx_write_spdif_codec
(
s
,
4
,
0x40
);
rme96xx_write_spdif_codec
(
s
,
17
,
0x13
);
rme96xx_write_spdif_codec
(
s
,
6
,
0x02
);
}
static
inline
int
rme96xx_spdif_sample_rate
(
rme96xx_info
*
s
,
int
*
spdifrate
)
{
unsigned
int
rate_bits
;
*
spdifrate
=
0x1
;
if
(
readl
(
s
->
iobase
+
RME96xx_status_register
)
&
RME96xx_ERF
)
{
return
-
1
;
/* error condition */
}
if
(
s
->
hw_rev
==
15
)
{
int
x
,
y
,
ret
;
x
=
rme96xx_spdif_read_codec
(
s
,
30
);
if
(
x
!=
0
)
y
=
48000
*
64
/
x
;
else
y
=
0
;
if
(
y
>
30400
&&
y
<
33600
)
{
ret
=
32000
;
*
spdifrate
=
0x7
;}
else
if
(
y
>
41900
&&
y
<
46000
)
{
ret
=
44100
;
*
spdifrate
=
0x6
;}
else
if
(
y
>
46000
&&
y
<
50400
)
{
ret
=
48000
;
*
spdifrate
=
0x5
;}
else
if
(
y
>
60800
&&
y
<
67200
)
{
ret
=
64000
;
*
spdifrate
=
0x0
;}
else
if
(
y
>
83700
&&
y
<
92000
)
{
ret
=
88200
;
*
spdifrate
=
0x4
;}
else
if
(
y
>
92000
&&
y
<
100000
)
{
ret
=
96000
;
*
spdifrate
=
0x3
;}
else
{
ret
=
0
;
*
spdifrate
=
0x1
;}
return
ret
;
}
rate_bits
=
readl
(
s
->
iobase
+
RME96xx_status_register
)
&
RME96xx_F
;
switch
(
*
spdifrate
=
rme96xx_decode_spdif_rate
(
rate_bits
))
{
case
0x7
:
return
32000
;
break
;
case
0x6
:
return
44100
;
break
;
case
0x5
:
return
48000
;
break
;
case
0x4
:
return
88200
;
break
;
case
0x3
:
return
96000
;
break
;
case
0x0
:
return
64000
;
break
;
default:
/* was an ALSA warning ...
snd_printk("%s: unknown S/PDIF input rate (bits = 0x%x)\n",
s->card_name, rate_bits);
*/
return
0
;
break
;
}
}
/* end of code from ALSA card-rme9652.c */
/* the hwbuf in the status register seems to have some jitter, to get rid of
/* the hwbuf in the status register seems to have some jitter, to get rid of
...
@@ -662,6 +869,9 @@ static int rme96xx_dmabuf_init(rme96xx_info * s,struct dmabuf* dma,int ioffset,i
...
@@ -662,6 +869,9 @@ static int rme96xx_dmabuf_init(rme96xx_info * s,struct dmabuf* dma,int ioffset,i
int
rme96xx_init
(
rme96xx_info
*
s
)
int
rme96xx_init
(
rme96xx_info
*
s
)
{
{
int
i
;
int
i
;
int
status
;
unsigned
short
rev
;
DBG
(
printk
(
__FUNCTION__
"
\n
"
));
DBG
(
printk
(
__FUNCTION__
"
\n
"
));
numcards
++
;
numcards
++
;
...
@@ -694,6 +904,56 @@ int rme96xx_init(rme96xx_info* s)
...
@@ -694,6 +904,56 @@ int rme96xx_init(rme96xx_info* s)
rme96xx_dmabuf_init
(
s
,
dma
,
2
*
i
,
2
*
i
);
rme96xx_dmabuf_init
(
s
,
dma
,
2
*
i
,
2
*
i
);
}
}
/* code from ALSA card-rme9652.c HP 20020201 */
/* Determine the h/w rev level of the card. This seems like
a particularly kludgy way to encode it, but its what RME
chose to do, so we follow them ...
*/
status
=
readl
(
s
->
iobase
+
RME96xx_status_register
);
if
(
rme96xx_decode_spdif_rate
(
status
&
RME96xx_F
)
==
1
)
{
s
->
hw_rev
=
15
;
}
else
{
s
->
hw_rev
=
11
;
}
/* Differentiate between the standard Hammerfall, and the
"Light", which does not have the expansion board. This
method comes from information received from Mathhias
Clausen at RME. Display the EEPROM and h/w revID where
relevant.
*/
pci_read_config_word
(
s
->
pcidev
,
PCI_CLASS_REVISION
,
&
rev
);
switch
(
rev
&
0xff
)
{
case
8
:
/* original eprom */
if
(
s
->
hw_rev
==
15
)
{
s
->
card_name
=
"RME Digi9636 (Rev 1.5)"
;
}
else
{
s
->
card_name
=
"RME Digi9636"
;
}
break
;
case
9
:
/* W36_G EPROM */
s
->
card_name
=
"RME Digi9636 (Rev G)"
;
break
;
case
4
:
/* W52_G EPROM */
s
->
card_name
=
"RME Digi9652 (Rev G)"
;
break
;
default:
case
3
:
/* original eprom */
if
(
s
->
hw_rev
==
15
)
{
s
->
card_name
=
"RME Digi9652 (Rev 1.5)"
;
}
else
{
s
->
card_name
=
"RME Digi9652"
;
}
break
;
}
printk
(
KERN_INFO
RME_MESS
" detected %s (hw_rev %d)
\n
"
,
s
->
card_name
,
s
->
hw_rev
);
if
(
s
->
hw_rev
==
15
)
rme96xx_initialize_spdif_receiver
(
s
);
s
->
started
=
0
;
s
->
started
=
0
;
rme96xx_setlatency
(
s
,
7
);
rme96xx_setlatency
(
s
,
7
);
...
@@ -734,7 +994,7 @@ static int __devinit rme96xx_probe(struct pci_dev *pcidev, const struct pci_devi
...
@@ -734,7 +994,7 @@ static int __devinit rme96xx_probe(struct pci_dev *pcidev, const struct pci_devi
if
(
pci_enable_device
(
pcidev
))
if
(
pci_enable_device
(
pcidev
))
goto
err_irq
;
goto
err_irq
;
if
(
request_irq
(
s
->
irq
,
rme96xx_interrupt
,
SA_SHIRQ
,
"
es1370
"
,
s
))
{
if
(
request_irq
(
s
->
irq
,
rme96xx_interrupt
,
SA_SHIRQ
,
"
rme96xx
"
,
s
))
{
printk
(
KERN_ERR
RME_MESS
" irq %u in use
\n
"
,
s
->
irq
);
printk
(
KERN_ERR
RME_MESS
" irq %u in use
\n
"
,
s
->
irq
);
goto
err_irq
;
goto
err_irq
;
}
}
...
@@ -836,6 +1096,7 @@ static int __init init_rme96xx(void)
...
@@ -836,6 +1096,7 @@ static int __init init_rme96xx(void)
if
(
!
pci_present
())
/* No PCI bus in this machine! */
if
(
!
pci_present
())
/* No PCI bus in this machine! */
return
-
ENODEV
;
return
-
ENODEV
;
printk
(
KERN_INFO
RME_MESS
" version "
RMEVERSION
" time "
__TIME__
" "
__DATE__
"
\n
"
);
printk
(
KERN_INFO
RME_MESS
" version "
RMEVERSION
" time "
__TIME__
" "
__DATE__
"
\n
"
);
devices
=
((
devices
-
1
)
&
RME96xx_MASK_DEVS
)
+
1
;
printk
(
KERN_INFO
RME_MESS
" reserving %d dsp device(s)
\n
"
,
devices
);
printk
(
KERN_INFO
RME_MESS
" reserving %d dsp device(s)
\n
"
,
devices
);
numcards
=
0
;
numcards
=
0
;
return
pci_module_init
(
&
rme96xx_driver
);
return
pci_module_init
(
&
rme96xx_driver
);
...
@@ -859,13 +1120,11 @@ module_exit(cleanup_rme96xx);
...
@@ -859,13 +1120,11 @@ module_exit(cleanup_rme96xx);
---------------------------------------------------------------------------*/
---------------------------------------------------------------------------*/
#define RME96xx_FMT (AFMT_S16_LE|AFMT_U8|AFMT_S32_BLOCKED)
#define RME96xx_FMT (AFMT_S16_LE|AFMT_U8|AFMT_S32_BLOCKED)
/* AFTM_U8 is not (yet?) supported ... HP20020201 */
static
int
rme96xx_ioctl
(
struct
inode
*
in
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
static
int
rme96xx_ioctl
(
struct
inode
*
in
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
{
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
rme96xx_info
*
s
=
dma
->
s
;
rme96xx_info
*
s
=
dma
->
s
;
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -918,14 +1177,23 @@ static int rme96xx_ioctl(struct inode *in, struct file *file,
...
@@ -918,14 +1177,23 @@ static int rme96xx_ioctl(struct inode *in, struct file *file,
case
96000
:
case
96000
:
rme96xx_set_ctrl
(
s
,
RME96xx_freq
);
rme96xx_set_ctrl
(
s
,
RME96xx_freq
);
break
;
break
;
/* just report current rate as default
e.g. use 0 to "select" current digital input rate
default:
default:
rme96xx_unset_ctrl(s,RME96xx_freq);
rme96xx_unset_ctrl(s,RME96xx_freq);
val = 44100;
val = 44100;
*/
}
}
if
(
val
>
50000
)
if
(
val
>
50000
)
rme96xx_set_ctrl
(
s
,
RME96xx_DS
);
rme96xx_set_ctrl
(
s
,
RME96xx_DS
);
else
else
rme96xx_unset_ctrl
(
s
,
RME96xx_DS
);
rme96xx_unset_ctrl
(
s
,
RME96xx_DS
);
/* set val to actual value HP 20020201 */
/* NOTE: if not "Sync Master", reported rate might be not yet "updated" ... but I don't want to insert a long udelay() here */
if
((
s
->
control_register
&
RME96xx_Master
)
&&
!
(
s
->
control_register
&
RME96xx_wsel
))
val
=
rme96xx_get_sample_rate_ctrl
(
s
);
else
val
=
rme96xx_get_sample_rate_status
(
s
);
s
->
rate
=
val
;
s
->
rate
=
val
;
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
}
}
...
@@ -1146,6 +1414,8 @@ static int rme96xx_ioctl(struct inode *in, struct file *file,
...
@@ -1146,6 +1414,8 @@ static int rme96xx_ioctl(struct inode *in, struct file *file,
return
0
;
return
0
;
case
SOUND_PCM_READ_RATE
:
case
SOUND_PCM_READ_RATE
:
/* HP20020201 */
s
->
rate
=
rme96xx_get_sample_rate_status
(
s
);
return
put_user
(
s
->
rate
,
(
int
*
)
arg
);
return
put_user
(
s
->
rate
,
(
int
*
)
arg
);
case
SOUND_PCM_READ_CHANNELS
:
case
SOUND_PCM_READ_CHANNELS
:
...
@@ -1179,28 +1449,29 @@ static int rme96xx_open(struct inode *in, struct file *f)
...
@@ -1179,28 +1449,29 @@ static int rme96xx_open(struct inode *in, struct file *f)
{
{
int
minor
=
minor
(
in
->
i_rdev
);
int
minor
=
minor
(
in
->
i_rdev
);
struct
list_head
*
list
;
struct
list_head
*
list
;
int
devnum
=
((
minor
-
3
)
/
16
)
%
devices
;
/* default = 0 */
int
devnum
;
rme96xx_info
*
s
;
rme96xx_info
*
s
;
struct
dmabuf
*
dma
;
struct
dmabuf
*
dma
;
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
DBG
(
printk
(
"device num %d open
\n
"
,
devnum
));
DBG
(
printk
(
"device num %d open
\n
"
,
devnum
));
/* ??? */
for
(
list
=
devs
.
next
;
;
list
=
list
->
next
)
{
for
(
list
=
devs
.
next
;
;
list
=
list
->
next
)
{
if
(
list
==
&
devs
)
if
(
list
==
&
devs
)
return
-
ENODEV
;
return
-
ENODEV
;
s
=
list_entry
(
list
,
rme96xx_info
,
devs
);
s
=
list_entry
(
list
,
rme96xx_info
,
devs
);
if
(
!
((
s
->
dspnum
[
devnum
]
^
minor
)
&
~
0xf
))
for
(
devnum
=
0
;
devnum
<
devices
;
devnum
++
)
if
(
!
((
s
->
dspnum
[
devnum
]
^
minor
)
&
~
0xf
))
break
;
if
(
devnum
<
devices
)
break
;
break
;
}
}
VALIDATE_STATE
(
s
);
VALIDATE_STATE
(
s
);
/* ??? */
dma
=
&
s
->
dma
[
devnum
];
dma
=
&
s
->
dma
[
devnum
];
f
->
private_data
=
dma
;
f
->
private_data
=
dma
;
/* wait for device to become free */
/* wait for device to become free */
down
(
&
s
->
dma
[
devnum
].
open_sem
);
down
(
&
dma
->
open_sem
);
while
(
dma
->
open_mode
&
f
->
f_mode
)
{
while
(
dma
->
open_mode
&
f
->
f_mode
)
{
if
(
f
->
f_flags
&
O_NONBLOCK
)
{
if
(
f
->
f_flags
&
O_NONBLOCK
)
{
up
(
&
dma
->
open_sem
);
up
(
&
dma
->
open_sem
);
...
@@ -1219,11 +1490,11 @@ static int rme96xx_open(struct inode *in, struct file *f)
...
@@ -1219,11 +1490,11 @@ static int rme96xx_open(struct inode *in, struct file *f)
COMM
(
"hardware open"
)
COMM
(
"hardware open"
)
if
(
!
s
->
dma
[
devnum
].
opened
)
rme96xx_dmabuf_init
(
dma
->
s
,
dma
,
dma
->
inoffset
,
dma
->
outoffset
);
if
(
!
dma
->
opened
)
rme96xx_dmabuf_init
(
dma
->
s
,
dma
,
dma
->
inoffset
,
dma
->
outoffset
);
s
->
dma
[
devnum
].
open_mode
|=
(
f
->
f_mode
&
(
FMODE_READ
|
FMODE_WRITE
));
dma
->
open_mode
|=
(
f
->
f_mode
&
(
FMODE_READ
|
FMODE_WRITE
));
s
->
dma
[
devnum
].
opened
=
1
;
dma
->
opened
=
1
;
up
(
&
s
->
dma
[
devnum
].
open_sem
);
up
(
&
dma
->
open_sem
);
DBG
(
printk
(
"device num %d open finished
\n
"
,
devnum
));
DBG
(
printk
(
"device num %d open finished
\n
"
,
devnum
));
return
0
;
return
0
;
...
@@ -1232,7 +1503,7 @@ static int rme96xx_open(struct inode *in, struct file *f)
...
@@ -1232,7 +1503,7 @@ static int rme96xx_open(struct inode *in, struct file *f)
static
int
rme96xx_release
(
struct
inode
*
in
,
struct
file
*
file
)
static
int
rme96xx_release
(
struct
inode
*
in
,
struct
file
*
file
)
{
{
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
/* int hwp; */
/* int hwp;
... was unused HP20020201
*/
DBG
(
printk
(
__FUNCTION__
"
\n
"
));
DBG
(
printk
(
__FUNCTION__
"
\n
"
));
COMM
(
"draining"
)
COMM
(
"draining"
)
...
@@ -1261,8 +1532,7 @@ static int rme96xx_release(struct inode *in, struct file *file)
...
@@ -1261,8 +1532,7 @@ static int rme96xx_release(struct inode *in, struct file *file)
}
}
static
ssize_t
rme96xx_write
(
struct
file
*
file
,
const
char
*
buffer
,
static
ssize_t
rme96xx_write
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
size_t
count
,
loff_t
*
ppos
)
{
{
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
ssize_t
ret
=
0
;
ssize_t
ret
=
0
;
...
@@ -1296,7 +1566,6 @@ static ssize_t rme96xx_write(struct file *file, const char *buffer,
...
@@ -1296,7 +1566,6 @@ static ssize_t rme96xx_write(struct file *file, const char *buffer,
dma
->
readptr
=
hwp
;
dma
->
readptr
=
hwp
;
dma
->
writeptr
=
hwp
;
dma
->
writeptr
=
hwp
;
dma
->
started
=
1
;
dma
->
started
=
1
;
COMM
(
"first write done"
)
}
}
while
(
count
>
0
)
{
while
(
count
>
0
)
{
...
@@ -1331,11 +1600,11 @@ static ssize_t rme96xx_write(struct file *file, const char *buffer,
...
@@ -1331,11 +1600,11 @@ static ssize_t rme96xx_write(struct file *file, const char *buffer,
return
ret
;
return
ret
;
}
}
static
ssize_t
rme96xx_read
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
rme96xx_read
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
{
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
struct
dmabuf
*
dma
=
(
struct
dmabuf
*
)
file
->
private_data
;
ssize_t
ret
=
0
;
ssize_t
ret
=
0
;
int
cnt
;
int
cnt
;
/* number of bytes from "buffer" that will/can be used */
int
hop
=
count
/
dma
->
inchannels
;
int
hop
=
count
/
dma
->
inchannels
;
int
hwp
;
int
hwp
;
int
exact
=
(
file
->
f_flags
&
O_NONBLOCK
);
int
exact
=
(
file
->
f_flags
&
O_NONBLOCK
);
...
@@ -1356,9 +1625,6 @@ static ssize_t rme96xx_read(struct file *file, char *buffer,size_t count, loff_t
...
@@ -1356,9 +1625,6 @@ static ssize_t rme96xx_read(struct file *file, char *buffer,size_t count, loff_t
if
(
!
(
dma
->
open_mode
&
FMODE_READ
))
if
(
!
(
dma
->
open_mode
&
FMODE_READ
))
return
-
ENXIO
;
return
-
ENXIO
;
if
(
count
>
((
dma
->
s
->
fragsize
*
dma
->
inchannels
)
>>
dma
->
formatshift
))
return
-
EFAULT
;
if
(
!
dma
->
s
->
started
)
rme96xx_startcard
(
dma
->
s
,
exact
);
if
(
!
dma
->
s
->
started
)
rme96xx_startcard
(
dma
->
s
,
exact
);
hwp
=
rme96xx_gethwptr
(
dma
->
s
,
0
);
hwp
=
rme96xx_gethwptr
(
dma
->
s
,
0
);
...
@@ -1444,7 +1710,7 @@ static int rm96xx_mmap(struct file *file, struct vm_area_struct *vma) {
...
@@ -1444,7 +1710,7 @@ static int rm96xx_mmap(struct file *file, struct vm_area_struct *vma) {
/* this is the mapping */
/* this is the mapping */
vma
->
vm_flags
&=
~
VM_IO
;
dma
->
mmapped
=
1
;
dma
->
mmapped
=
1
;
unlock_kernel
();
unlock_kernel
();
return
0
;
return
0
;
...
@@ -1529,8 +1795,12 @@ static int rme96xx_mixer_ioctl(struct inode *inode, struct file *file, unsigned
...
@@ -1529,8 +1795,12 @@ static int rme96xx_mixer_ioctl(struct inode *inode, struct file *file, unsigned
{
{
rme96xx_info
*
s
=
(
rme96xx_info
*
)
file
->
private_data
;
rme96xx_info
*
s
=
(
rme96xx_info
*
)
file
->
private_data
;
u32
status
;
u32
status
;
int
spdifrate
;
status
=
readl
(
s
->
iobase
+
RME96xx_status_register
);
status
=
readl
(
s
->
iobase
+
RME96xx_status_register
);
/* hack to convert rev 1.5 SPDIF rate to "crystalrate" format HP 20020201 */
rme96xx_spdif_sample_rate
(
s
,
&
spdifrate
);
status
=
(
status
&
~
RME96xx_F
)
|
((
spdifrate
<<
22
)
&
RME96xx_F
);
VALIDATE_STATE
(
s
);
VALIDATE_STATE
(
s
);
if
(
cmd
==
SOUND_MIXER_PRIVATE1
)
{
if
(
cmd
==
SOUND_MIXER_PRIVATE1
)
{
...
@@ -1538,9 +1808,21 @@ static int rme96xx_mixer_ioctl(struct inode *inode, struct file *file, unsigned
...
@@ -1538,9 +1808,21 @@ static int rme96xx_mixer_ioctl(struct inode *inode, struct file *file, unsigned
if
(
copy_from_user
(
&
mixer
,(
void
*
)
arg
,
sizeof
(
mixer
)))
if
(
copy_from_user
(
&
mixer
,(
void
*
)
arg
,
sizeof
(
mixer
)))
return
-
EFAULT
;
return
-
EFAULT
;
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
mixer
.
devnr
&=
RME96xx_MASK_DEVS
;
s
->
dma
[
mixer
.
devnr
].
outoffset
=
mixer
.
o_offset
;
if
(
mixer
.
devnr
>=
devices
)
s
->
dma
[
mixer
.
devnr
].
inoffset
=
mixer
.
i_offset
;
mixer
.
devnr
=
devices
-
1
;
if
(
file
->
f_mode
&
FMODE_WRITE
&&
!
s
->
dma
[
mixer
.
devnr
].
opened
)
{
/* modify only if device not open */
if
(
mixer
.
o_offset
<
0
)
mixer
.
o_offset
=
0
;
if
(
mixer
.
o_offset
>=
RME96xx_CHANNELS_PER_CARD
)
mixer
.
o_offset
=
RME96xx_CHANNELS_PER_CARD
-
1
;
if
(
mixer
.
i_offset
<
0
)
mixer
.
i_offset
=
0
;
if
(
mixer
.
i_offset
>=
RME96xx_CHANNELS_PER_CARD
)
mixer
.
i_offset
=
RME96xx_CHANNELS_PER_CARD
-
1
;
s
->
dma
[
mixer
.
devnr
].
outoffset
=
mixer
.
o_offset
;
s
->
dma
[
mixer
.
devnr
].
inoffset
=
mixer
.
i_offset
;
}
}
mixer
.
o_offset
=
s
->
dma
[
mixer
.
devnr
].
outoffset
;
mixer
.
o_offset
=
s
->
dma
[
mixer
.
devnr
].
outoffset
;
...
@@ -1552,13 +1834,14 @@ static int rme96xx_mixer_ioctl(struct inode *inode, struct file *file, unsigned
...
@@ -1552,13 +1834,14 @@ static int rme96xx_mixer_ioctl(struct inode *inode, struct file *file, unsigned
return
put_user
(
status
,
(
int
*
)
arg
);
return
put_user
(
status
,
(
int
*
)
arg
);
}
}
if
(
cmd
==
SOUND_MIXER_PRIVATE3
)
{
if
(
cmd
==
SOUND_MIXER_PRIVATE3
)
{
u32
control
;
u32
control
;
if
(
copy_from_user
(
&
control
,(
void
*
)
arg
,
sizeof
(
control
)))
if
(
copy_from_user
(
&
control
,(
void
*
)
arg
,
sizeof
(
control
)))
return
-
EFAULT
;
return
-
EFAULT
;
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
s
->
control_register
=
control
;
s
->
control_register
&=
~
RME96xx_mixer_allowed
;
writel
(
control
,
s
->
iobase
+
RME96xx_control_register
);
s
->
control_register
|=
control
&
RME96xx_mixer_allowed
;
}
writel
(
control
,
s
->
iobase
+
RME96xx_control_register
);
}
return
put_user
(
s
->
control_register
,
(
int
*
)
arg
);
return
put_user
(
s
->
control_register
,
(
int
*
)
arg
);
}
}
...
...
sound/oss/rme96xx.h
View file @
3e5f1270
/* (C) 2000 Guenter Geiger <geiger@debian.org>
/* (C) 2000 Guenter Geiger <geiger@debian.org>
with copy/pastes from the driver of Winfried Ritsch <ritsch@iem.kug.ac.at>
with copy/pastes from the driver of Winfried Ritsch <ritsch@iem.kug.ac.at>
Modifications - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
HP20020116 towards REV 1.5 support, based on ALSA's card-rme9652.c
HP20020201 completed?
A text/graphic control panel (rmectrl/xrmectrl) is available from
http://gige.xdv.org/pages/soft/pages/rme
*/
*/
...
@@ -7,55 +14,65 @@
...
@@ -7,55 +14,65 @@
#define AFMT_S32_BLOCKED 0x0000400
#define AFMT_S32_BLOCKED 0x0000400
#endif
#endif
/* AFMT_S16_BLOCKED not yet supported */
#ifndef AFMT_S16_BLOCKED
#ifndef AFMT_S16_BLOCKED
#define AFMT_S16_BLOCKED 0x0000800
#define AFMT_S16_BLOCKED 0x0000800
#endif
#endif
typedef
struct
rme_status
{
typedef
struct
rme_status
{
unsigned
int
irq
:
1
;
/* high or low */
unsigned
int
irq
:
1
;
unsigned
int
lockmask
:
3
;
/* ADAT1, ADAT2, ADAT3 */
unsigned
int
lockmask
:
3
;
/* ADAT input PLLs locked */
unsigned
int
sr48
:
1
;
/* current sample rate */
/* 100=ADAT1, 010=ADAT2, 001=ADAT3 */
unsigned
int
wclock
:
1
;
/* wordclock used ? */
unsigned
int
sr48
:
1
;
/* sample rate: 0=44.1/88.2 1=48/96 kHz */
unsigned
int
bufpoint
:
10
;
unsigned
int
wclock
:
1
;
/* 1=wordclock used */
unsigned
int
bufpoint
:
10
;
unsigned
int
syncmask
:
3
;
/* ADAT1, ADAT2, ADAT3 */
unsigned
int
syncmask
:
3
;
/* ADAT input in sync with system clock */
unsigned
int
doublespeed
:
1
;
/* 100=ADAT1, 010=ADAT2, 001=ADAT3 */
unsigned
int
tc_busy
:
1
;
unsigned
int
doublespeed
:
1
;
/* sample rate: 0=44.1/48 1=88.2/96 kHz */
unsigned
int
tc_out
:
1
;
unsigned
int
tc_busy
:
1
;
unsigned
int
crystalrate
:
3
;
unsigned
int
tc_out
:
1
;
unsigned
int
spdif_error
:
1
;
unsigned
int
crystalrate
:
3
;
/* spdif input sample rate: */
unsigned
int
bufid
:
1
;
/* 000=64kHz, 100=88.2kHz, 011=96kHz */
unsigned
int
tc_valid
:
1
;
/* 111=32kHz, 110=44.1kHz, 101=48kHz */
unsigned
int
spdif_error
:
1
;
/* 1=no spdif lock */
unsigned
int
bufid
:
1
;
unsigned
int
tc_valid
:
1
;
/* 1=timecode input detected */
unsigned
int
spdif_read
:
1
;
}
rme_status_t
;
}
rme_status_t
;
/* only fields marked W: can be modified by writing to SOUND_MIXER_PRIVATE3 */
typedef
struct
rme_control
{
typedef
struct
rme_control
{
unsigned
int
start
:
1
;
unsigned
int
start
:
1
;
unsigned
int
latency
:
3
;
unsigned
int
latency
:
3
;
/* buffer size / latency [samples]: */
/* 0=64 ... 7=8192 */
unsigned
int
master
:
1
;
unsigned
int
master
:
1
;
/* W: clock mode: 1=master 0=slave/auto */
unsigned
int
ie
:
1
;
unsigned
int
ie
:
1
;
unsigned
int
sr48
:
1
;
unsigned
int
sr48
:
1
;
/* samplerate 0=44.1/88.2, 1=48/96 kHz */
unsigned
int
spare
:
1
;
unsigned
int
spare
:
1
;
unsigned
int
doublespeed
:
1
;
/* double speed 0=44.1/48, 1=88.2/96 Khz */
unsigned
int
doublespeed
:
1
;
unsigned
int
pro
:
1
;
/* W: SPDIF-OUT 0=consumer, 1=professional */
unsigned
int
pro
:
1
;
unsigned
int
emphasis
:
1
;
/* W: SPDIF-OUT emphasis 0=off, 1=on */
unsigned
int
emphasis
:
1
;
unsigned
int
dolby
:
1
;
/* W: SPDIF-OUT non-audio bit 1=set, 0=unset */
unsigned
int
dolby
:
1
;
unsigned
int
opt_out
:
1
;
/* W: use 1st optical OUT as SPDIF: 1=yes, 0=no */
unsigned
int
wordclock
:
1
;
/* W: use Wordclock as sync (overwrites master) */
unsigned
int
opt_out
:
1
;
unsigned
int
spdif_in
:
2
;
/* W: SPDIF-IN: */
unsigned
int
wordclock
:
1
;
/* 00=optical (ADAT1), 01=coaxial (Cinch), 10=internal CDROM */
unsigned
int
spdif_in
:
2
;
unsigned
int
sync_ref
:
2
;
/* W: preferred sync-source in autosync */
/* 00=ADAT1, 01=ADAT2, 10=ADAT3, 11=SPDIF */
unsigned
int
sync_ref
:
2
;
unsigned
int
spdif_reset
:
1
;
unsigned
int
spdif_select
:
1
;
unsigned
int
spdif_clock
:
1
;
unsigned
int
spdif_write
:
1
;
unsigned
int
adat1_cd
:
1
;
/* W: Rev 1.5+: if set, internal CD connector carries ADAT */
}
rme_ctrl_t
;
}
rme_ctrl_t
;
typedef
struct
_rme_mixer
{
typedef
struct
_rme_mixer
{
int
i_offset
;
int
i_offset
;
int
o_offset
;
int
o_offset
;
int
devnr
;
int
devnr
;
int
spare
[
8
];
int
spare
[
8
];
}
rme_mixer
;
}
rme_mixer
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment