efxmgr.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. **********************************************************************
  3. * efxmgr.c
  4. * Copyright 1999, 2000 Creative Labs, Inc.
  5. *
  6. **********************************************************************
  7. *
  8. * Date Author Summary of changes
  9. * ---- ------ ------------------
  10. * October 20, 1999 Bertrand Lee base code release
  11. *
  12. **********************************************************************
  13. *
  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.
  18. *
  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.
  23. *
  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,
  27. * USA.
  28. *
  29. **********************************************************************
  30. */
  31. #include <linux/bitops.h>
  32. #include "hwaccess.h"
  33. #include "efxmgr.h"
  34. int emu10k1_find_control_gpr(struct patch_manager *mgr, const char *patch_name, const char *gpr_name)
  35. {
  36. struct dsp_patch *patch;
  37. struct dsp_rpatch *rpatch;
  38. char s[PATCH_NAME_SIZE + 4];
  39. unsigned long *gpr_used;
  40. int i;
  41. DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name, gpr_name);
  42. rpatch = &mgr->rpatch;
  43. if (!strcmp(rpatch->name, patch_name)) {
  44. gpr_used = rpatch->gpr_used;
  45. goto match;
  46. }
  47. for (i = 0; i < mgr->current_pages * PATCHES_PER_PAGE; i++) {
  48. patch = PATCH(mgr, i);
  49. sprintf(s,"%s", patch->name);
  50. if (!strcmp(s, patch_name)) {
  51. gpr_used = patch->gpr_used;
  52. goto match;
  53. }
  54. }
  55. return -1;
  56. match:
  57. for (i = 0; i < NUM_GPRS; i++)
  58. if (mgr->gpr[i].type == GPR_TYPE_CONTROL &&
  59. test_bit(i, gpr_used) &&
  60. !strcmp(mgr->gpr[i].name, gpr_name))
  61. return i;
  62. return -1;
  63. }
  64. void emu10k1_set_control_gpr(struct emu10k1_card *card, int addr, s32 val, int flag)
  65. {
  66. struct patch_manager *mgr = &card->mgr;
  67. DPD(2, "emu10k1_set_control_gpr(): %d %x\n", addr, val);
  68. if (addr < 0 || addr >= NUM_GPRS)
  69. return;
  70. //fixme: once patch manager is up, remember to fix this for the audigy
  71. if (card->is_audigy) {
  72. sblive_writeptr(card, A_GPR_BASE + addr, 0, val);
  73. } else {
  74. if (flag)
  75. val += sblive_readptr(card, GPR_BASE + addr, 0);
  76. if (val > mgr->gpr[addr].max)
  77. val = mgr->gpr[addr].max;
  78. else if (val < mgr->gpr[addr].min)
  79. val = mgr->gpr[addr].min;
  80. sblive_writeptr(card, GPR_BASE + addr, 0, val);
  81. }
  82. }
  83. //TODO: make this configurable:
  84. #define VOLCTRL_CHANNEL SOUND_MIXER_VOLUME
  85. #define VOLCTRL_STEP_SIZE 5
  86. //An internal function for setting OSS mixer controls.
  87. static void emu10k1_set_oss_vol(struct emu10k1_card *card, int oss_mixer,
  88. unsigned int left, unsigned int right)
  89. {
  90. extern char volume_params[SOUND_MIXER_NRDEVICES];
  91. card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
  92. if (!card->is_aps)
  93. card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
  94. emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left,
  95. volume_params[oss_mixer]);
  96. emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right,
  97. volume_params[oss_mixer]);
  98. }
  99. //FIXME: mute should unmute when pressed a second time
  100. void emu10k1_mute_irqhandler(struct emu10k1_card *card)
  101. {
  102. int oss_channel = VOLCTRL_CHANNEL;
  103. int left, right;
  104. static int val;
  105. if (val) {
  106. left = val & 0xff;
  107. right = (val >> 8) & 0xff;
  108. val = 0;
  109. } else {
  110. val = card->ac97->mixer_state[oss_channel];
  111. left = 0;
  112. right = 0;
  113. }
  114. emu10k1_set_oss_vol(card, oss_channel, left, right);
  115. }
  116. void emu10k1_volincr_irqhandler(struct emu10k1_card *card)
  117. {
  118. int oss_channel = VOLCTRL_CHANNEL;
  119. int left, right;
  120. left = card->ac97->mixer_state[oss_channel] & 0xff;
  121. right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
  122. if ((left += VOLCTRL_STEP_SIZE) > 100)
  123. left = 100;
  124. if ((right += VOLCTRL_STEP_SIZE) > 100)
  125. right = 100;
  126. emu10k1_set_oss_vol(card, oss_channel, left, right);
  127. }
  128. void emu10k1_voldecr_irqhandler(struct emu10k1_card *card)
  129. {
  130. int oss_channel = VOLCTRL_CHANNEL;
  131. int left, right;
  132. left = card->ac97->mixer_state[oss_channel] & 0xff;
  133. right = (card->ac97->mixer_state[oss_channel] >> 8) & 0xff;
  134. if ((left -= VOLCTRL_STEP_SIZE) < 0)
  135. left = 0;
  136. if ((right -= VOLCTRL_STEP_SIZE) < 0)
  137. right = 0;
  138. emu10k1_set_oss_vol(card, oss_channel, left, right);
  139. }
  140. void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int scale)
  141. {
  142. struct patch_manager *mgr = &card->mgr;
  143. unsigned long flags;
  144. static const s32 log2lin[4] ={ // attenuation (dB)
  145. 0x7fffffff, // 0.0
  146. 0x7fffffff * 0.840896415253715 , // 1.5
  147. 0x7fffffff * 0.707106781186548, // 3.0
  148. 0x7fffffff * 0.594603557501361 , // 4.5
  149. };
  150. if (addr < 0)
  151. return;
  152. vol = (100 - vol ) * scale / 100;
  153. // Thanks to the comp.dsp newsgroup for this neat trick:
  154. vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
  155. spin_lock_irqsave(&mgr->lock, flags);
  156. emu10k1_set_control_gpr(card, addr, vol, 0);
  157. spin_unlock_irqrestore(&mgr->lock, flags);
  158. }
  159. void emu10k1_dsp_irqhandler(struct emu10k1_card *card)
  160. {
  161. unsigned long flags;
  162. if (card->pt.state != PT_STATE_INACTIVE) {
  163. u32 bc;
  164. bc = sblive_readptr(card, GPR_BASE + card->pt.intr_gpr, 0);
  165. if (bc != 0) {
  166. DPD(3, "pt interrupt, bc = %d\n", bc);
  167. spin_lock_irqsave(&card->pt.lock, flags);
  168. card->pt.blocks_played = bc;
  169. if (card->pt.blocks_played >= card->pt.blocks_copied) {
  170. DPF(1, "buffer underrun in passthrough playback\n");
  171. emu10k1_pt_stop(card);
  172. }
  173. wake_up_interruptible(&card->pt.wait);
  174. spin_unlock_irqrestore(&card->pt.lock, flags);
  175. }
  176. }
  177. }