2 **********************************************************************
4 * Copyright 1999, 2000 Creative Labs, Inc.
6 **********************************************************************
8 * Date Author Summary of changes
9 * ---- ------ ------------------
10 * October 20, 1999 Bertrand Lee base code release
12 **********************************************************************
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public
25 * License along with this program; if not, write to the Free
26 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
29 **********************************************************************
32 #include <linux/bitops.h>
36 int emu10k1_find_control_gpr(struct patch_manager
*mgr
, const char *patch_name
, const char *gpr_name
)
38 struct dsp_patch
*patch
;
39 struct dsp_rpatch
*rpatch
;
40 char s
[PATCH_NAME_SIZE
+ 4];
41 unsigned long *gpr_used
;
44 DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name
, gpr_name
);
46 rpatch
= &mgr
->rpatch
;
47 if (!strcmp(rpatch
->name
, patch_name
)) {
48 gpr_used
= rpatch
->gpr_used
;
52 for (i
= 0; i
< mgr
->current_pages
* PATCHES_PER_PAGE
; i
++) {
53 patch
= PATCH(mgr
, i
);
54 sprintf(s
,"%s", patch
->name
);
56 if (!strcmp(s
, patch_name
)) {
57 gpr_used
= patch
->gpr_used
;
65 for (i
= 0; i
< NUM_GPRS
; i
++)
66 if (mgr
->gpr
[i
].type
== GPR_TYPE_CONTROL
&&
67 test_bit(i
, gpr_used
) &&
68 !strcmp(mgr
->gpr
[i
].name
, gpr_name
))
74 void emu10k1_set_control_gpr(struct emu10k1_card
*card
, int addr
, s32 val
, int flag
)
76 struct patch_manager
*mgr
= &card
->mgr
;
78 DPD(2, "emu10k1_set_control_gpr(): %d %x\n", addr
, val
);
80 if (addr
< 0 || addr
>= NUM_GPRS
)
83 //fixme: once patch manager is up, remember to fix this for the audigy
84 if (card
->is_audigy
) {
85 sblive_writeptr(card
, A_GPR_BASE
+ addr
, 0, val
);
88 val
+= sblive_readptr(card
, GPR_BASE
+ addr
, 0);
89 if (val
> mgr
->gpr
[addr
].max
)
90 val
= mgr
->gpr
[addr
].max
;
91 else if (val
< mgr
->gpr
[addr
].min
)
92 val
= mgr
->gpr
[addr
].min
;
93 sblive_writeptr(card
, GPR_BASE
+ addr
, 0, val
);
99 //TODO: make this configurable:
100 #define VOLCTRL_CHANNEL SOUND_MIXER_VOLUME
101 #define VOLCTRL_STEP_SIZE 5
103 //An internal function for setting OSS mixer controls.
104 static void emu10k1_set_oss_vol(struct emu10k1_card
*card
, int oss_mixer
,
105 unsigned int left
, unsigned int right
)
107 extern char volume_params
[SOUND_MIXER_NRDEVICES
];
109 card
->ac97
->mixer_state
[oss_mixer
] = (right
<< 8) | left
;
112 card
->ac97
->write_mixer(card
->ac97
, oss_mixer
, left
, right
);
114 emu10k1_set_volume_gpr(card
, card
->mgr
.ctrl_gpr
[oss_mixer
][0], left
,
115 volume_params
[oss_mixer
]);
117 emu10k1_set_volume_gpr(card
, card
->mgr
.ctrl_gpr
[oss_mixer
][1], right
,
118 volume_params
[oss_mixer
]);
121 //FIXME: mute should unmute when pressed a second time
122 void emu10k1_mute_irqhandler(struct emu10k1_card
*card
)
124 int oss_channel
= VOLCTRL_CHANNEL
;
130 right
= (val
>> 8) & 0xff;
133 val
= card
->ac97
->mixer_state
[oss_channel
];
138 emu10k1_set_oss_vol(card
, oss_channel
, left
, right
);
141 void emu10k1_volincr_irqhandler(struct emu10k1_card
*card
)
143 int oss_channel
= VOLCTRL_CHANNEL
;
146 left
= card
->ac97
->mixer_state
[oss_channel
] & 0xff;
147 right
= (card
->ac97
->mixer_state
[oss_channel
] >> 8) & 0xff;
149 if ((left
+= VOLCTRL_STEP_SIZE
) > 100)
152 if ((right
+= VOLCTRL_STEP_SIZE
) > 100)
155 emu10k1_set_oss_vol(card
, oss_channel
, left
, right
);
158 void emu10k1_voldecr_irqhandler(struct emu10k1_card
*card
)
160 int oss_channel
= VOLCTRL_CHANNEL
;
163 left
= card
->ac97
->mixer_state
[oss_channel
] & 0xff;
164 right
= (card
->ac97
->mixer_state
[oss_channel
] >> 8) & 0xff;
166 if ((left
-= VOLCTRL_STEP_SIZE
) < 0)
169 if ((right
-= VOLCTRL_STEP_SIZE
) < 0)
172 emu10k1_set_oss_vol(card
, oss_channel
, left
, right
);
175 void emu10k1_set_volume_gpr(struct emu10k1_card
*card
, int addr
, s32 vol
, int scale
)
177 struct patch_manager
*mgr
= &card
->mgr
;
180 static const s32 log2lin
[4] ={ // attenuation (dB)
182 0x7fffffff * 0.840896415253715 , // 1.5
183 0x7fffffff * 0.707106781186548, // 3.0
184 0x7fffffff * 0.594603557501361 , // 4.5
190 vol
= (100 - vol
) * scale
/ 100;
192 // Thanks to the comp.dsp newsgroup for this neat trick:
193 vol
= (vol
>= scale
) ? 0 : (log2lin
[vol
& 3] >> (vol
>> 2));
195 spin_lock_irqsave(&mgr
->lock
, flags
);
196 emu10k1_set_control_gpr(card
, addr
, vol
, 0);
197 spin_unlock_irqrestore(&mgr
->lock
, flags
);
200 void emu10k1_dsp_irqhandler(struct emu10k1_card
*card
)
204 if (card
->pt
.state
!= PT_STATE_INACTIVE
) {
206 bc
= sblive_readptr(card
, GPR_BASE
+ card
->pt
.intr_gpr
, 0);
208 DPD(3, "pt interrupt, bc = %d\n", bc
);
209 spin_lock_irqsave(&card
->pt
.lock
, flags
);
210 card
->pt
.blocks_played
= bc
;
211 if (card
->pt
.blocks_played
>= card
->pt
.blocks_copied
) {
212 DPF(1, "buffer underrun in passthrough playback\n");
213 emu10k1_pt_stop(card
);
215 wake_up_interruptible(&card
->pt
.wait
);
216 spin_unlock_irqrestore(&card
->pt
.lock
, flags
);