efxmgr.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. u32 *gpr_used;
  40. int i;
  41. DPD(2, "emu10k1_find_control_gpr(): %s %sn", 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 %xn", addr, val);
  68. if (addr < 0 || addr >= NUM_GPRS)
  69. return;
  70. if (flag)
  71. val += sblive_readptr(card, GPR_BASE + addr, 0);
  72. if (val > mgr->gpr[addr].max)
  73. val = mgr->gpr[addr].max;
  74. else if (val < mgr->gpr[addr].min)
  75. val = mgr->gpr[addr].min;
  76. sblive_writeptr(card, GPR_BASE + addr, 0, val);
  77. }
  78. //TODO: make this configurable:
  79. #define VOLCTRL_CHANNEL SOUND_MIXER_VOLUME
  80. #define VOLCTRL_STEP_SIZE        5
  81. //An internal function for setting OSS mixer controls.
  82. void emu10k1_set_oss_vol(struct emu10k1_card *card, int oss_mixer,
  83.  unsigned int left, unsigned int right)
  84. {
  85. extern char volume_params[SOUND_MIXER_NRDEVICES];
  86. card->ac97.mixer_state[oss_mixer] = (right << 8) | left;
  87. if (!card->isaps)
  88. card->ac97.write_mixer(&card->ac97, oss_mixer, left, right);
  89. emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left,
  90.        volume_params[oss_mixer]);
  91. emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right,
  92.        volume_params[oss_mixer]);
  93. }
  94. //FIXME: mute should unmute when pressed a second time
  95. void emu10k1_mute_irqhandler(struct emu10k1_card *card)
  96. {
  97. int oss_channel = VOLCTRL_CHANNEL;
  98. int left, right;
  99. static int val = 0;
  100. if (val) {
  101. left = val & 0xff;
  102. right = (val >> 8) & 0xff;
  103. val = 0;
  104. } else {
  105. val = card->ac97.mixer_state[oss_channel];
  106. left = 0;
  107. right = 0;
  108. }
  109. emu10k1_set_oss_vol(card, oss_channel, left, right);
  110. }
  111. void emu10k1_volincr_irqhandler(struct emu10k1_card *card)
  112. {
  113. int oss_channel = VOLCTRL_CHANNEL;
  114. int left, right;
  115. left = card->ac97.mixer_state[oss_channel] & 0xff;
  116. right = (card->ac97.mixer_state[oss_channel] >> 8) & 0xff;
  117. if ((left += VOLCTRL_STEP_SIZE) > 100)
  118. left = 100;
  119. if ((right += VOLCTRL_STEP_SIZE) > 100)
  120. right = 100;
  121. emu10k1_set_oss_vol(card, oss_channel, left, right);
  122. }
  123. void emu10k1_voldecr_irqhandler(struct emu10k1_card *card)
  124. {
  125. int oss_channel = VOLCTRL_CHANNEL;
  126. int left, right;
  127. left = card->ac97.mixer_state[oss_channel] & 0xff;
  128. right = (card->ac97.mixer_state[oss_channel] >> 8) & 0xff;
  129. if ((left -= VOLCTRL_STEP_SIZE) < 0)
  130. left = 0;
  131. if ((right -= VOLCTRL_STEP_SIZE) < 0)
  132. right = 0;
  133. emu10k1_set_oss_vol(card, oss_channel, left, right);
  134. }
  135. void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int scale)
  136. {
  137. struct patch_manager *mgr = &card->mgr;
  138. unsigned long flags;
  139. int muting;
  140. static const s32 log2lin[4] ={           //  attenuation (dB)
  141. 0x7fffffff,                      //       0.0         
  142. 0x7fffffff * 0.840896415253715 , //       1.5          
  143. 0x7fffffff * 0.707106781186548,  //       3.0
  144. 0x7fffffff * 0.594603557501361 , //       4.5
  145. };
  146. if (addr < 0)
  147. return;
  148. muting = (scale == 0x10) ? 0x7f: scale;
  149. vol = (100 - vol ) * scale / 100;
  150. // Thanks to the comp.dsp newsgroup for this neat trick:
  151. vol = (vol >= muting) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
  152. spin_lock_irqsave(&mgr->lock, flags);
  153. emu10k1_set_control_gpr(card, addr, vol, 0);
  154. spin_unlock_irqrestore(&mgr->lock, flags);
  155. }
  156. void emu10k1_dsp_irqhandler(struct emu10k1_card *card)
  157. {
  158. unsigned long flags;
  159. if (card->pt.state != PT_STATE_INACTIVE) {
  160. u32 bc;
  161. bc = sblive_readptr(card, GPR_BASE + card->pt.intr_gpr, 0);
  162. if (bc != 0) {
  163. DPD(3, "pt interrupt, bc = %dn", bc);
  164. spin_lock_irqsave(&card->pt.lock, flags);
  165. card->pt.blocks_played = bc;
  166. if (card->pt.blocks_played >= card->pt.blocks_copied) {
  167. DPF(1, "buffer underrun in passthrough playbackn");
  168. emu10k1_pt_stop(card);
  169. }
  170. wake_up_interruptible(&card->pt.wait);
  171. spin_unlock_irqrestore(&card->pt.lock, flags);
  172. }
  173. }
  174. }