void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev) { struct woinst *woinst = wave_dev->woinst; struct pt_data *pt = &wave_dev->card->pt; u32 pos; if (pt->state == PT_STATE_PLAYING && pt->pos_gpr >= 0) { pos = sblive_readptr(wave_dev->card, GPR_BASE + pt->pos_gpr, 0); if (pos > PT_BLOCKSAMPLES) pos = PT_BLOCKSAMPLES; pos = 4 * (PT_BLOCKSAMPLES - pos); } else pos = 0; woinst->total_played = pt->blocks_played * woinst->buffer.fragment_size + pos; woinst->buffer.hw_pos = pos; }
void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst) { u32 hw_pos; u32 diff; /* There is no actual start yet */ if (!(wiinst->state & WAVE_STATE_STARTED)) { hw_pos = wiinst->buffer.hw_pos; } else { /* hw_pos in byte units */ hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov; } diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size; wiinst->total_recorded += diff; wiinst->buffer.bytestocopy += diff; wiinst->buffer.hw_pos = hw_pos; }
int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev) { u32 bits; struct emu10k1_card *card = wave_dev->card; struct pt_data *pt = &card->pt; int i; for (i = 0; i < 3; i++) { pt->old_spcs[i] = sblive_readptr(card, SPCS0 + i, 0); if (pt->spcs_to_use & (1 << i)) { DPD(2, "using S/PDIF port %d\n", i); bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; if (pt->ac3data) bits |= SPCS_NOTAUDIODATA; sblive_writeptr(card, SPCS0 + i, 0, bits); } } return 0; }
/* Mixer file operations */ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, unsigned long arg) { struct mixer_private_ioctl *ctl; struct dsp_patch *patch; u32 size, page; int addr, size_reg, i, ret; unsigned int id, ch; void __user *argp = (void __user *)arg; switch (cmd) { case SOUND_MIXER_PRIVATE3: ctl = kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL); if (ctl == NULL) return -ENOMEM; if (copy_from_user(ctl, argp, sizeof(struct mixer_private_ioctl))) { kfree(ctl); return -EFAULT; } ret = 0; switch (ctl->cmd) { #ifdef DBGEMU case CMD_WRITEFN0: emu10k1_writefn0_2(card, ctl->val[0], ctl->val[1], ctl->val[2]); break; #endif case CMD_WRITEPTR: #ifdef DBGEMU if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000) { #else if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000 || ((ctl->val[0] < 0x100 ) && //Any register allowed raw access goes here: (ctl->val[0] != A_SPDIF_SAMPLERATE) && (ctl->val[0] != A_DBG) ) ) { #endif ret = -EINVAL; break; } sblive_writeptr(card, ctl->val[0], ctl->val[1], ctl->val[2]); break; case CMD_READFN0: ctl->val[2] = emu10k1_readfn0(card, ctl->val[0]); if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; break; case CMD_READPTR: if (ctl->val[1] >= 0x40 || (ctl->val[0] & 0x7ff) > 0xff) { ret = -EINVAL; break; } if ((ctl->val[0] & 0x7ff) > 0x3f) ctl->val[1] = 0x00; ctl->val[2] = sblive_readptr(card, ctl->val[0], ctl->val[1]); if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; break; case CMD_SETRECSRC: switch (ctl->val[0]) { case WAVERECORD_AC97: if (card->is_aps) { ret = -EINVAL; break; } card->wavein.recsrc = WAVERECORD_AC97; break; case WAVERECORD_MIC: card->wavein.recsrc = WAVERECORD_MIC; break; case WAVERECORD_FX: card->wavein.recsrc = WAVERECORD_FX; card->wavein.fxwc = ctl->val[1] & 0xffff; if (!card->wavein.fxwc) ret = -EINVAL; break; default: ret = -EINVAL; break; } break; case CMD_GETRECSRC: ctl->val[0] = card->wavein.recsrc; ctl->val[1] = card->wavein.fxwc; if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; break; case CMD_GETVOICEPARAM: ctl->val[0] = card->waveout.send_routing[0]; ctl->val[1] = card->waveout.send_dcba[0]; ctl->val[2] = card->waveout.send_routing[1]; ctl->val[3] = card->waveout.send_dcba[1]; ctl->val[4] = card->waveout.send_routing[2]; ctl->val[5] = card->waveout.send_dcba[2]; if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; break; case CMD_SETVOICEPARAM: card->waveout.send_routing[0] = ctl->val[0]; card->waveout.send_dcba[0] = ctl->val[1]; card->waveout.send_routing[1] = ctl->val[2]; card->waveout.send_dcba[1] = ctl->val[3]; card->waveout.send_routing[2] = ctl->val[4]; card->waveout.send_dcba[2] = ctl->val[5]; break; case CMD_SETMCH_FX: card->mchannel_fx = ctl->val[0] & 0x000f; break; case CMD_GETPATCH: if (ctl->val[0] == 0) { if (copy_to_user(argp, &card->mgr.rpatch, sizeof(struct dsp_rpatch))) ret = -EFAULT; } else { if ((ctl->val[0] - 1) / PATCHES_PER_PAGE >= card->mgr.current_pages) { ret = -EINVAL; break; } if (copy_to_user(argp, PATCH(&card->mgr, ctl->val[0] - 1), sizeof(struct dsp_patch))) ret = -EFAULT; } break; case CMD_GETGPR: id = ctl->val[0]; if (id > NUM_GPRS) { ret = -EINVAL; break; } if (copy_to_user(argp, &card->mgr.gpr[id], sizeof(struct dsp_gpr))) ret = -EFAULT; break; case CMD_GETCTLGPR: addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, &((char *) ctl->val)[PATCH_NAME_SIZE]); ctl->val[0] = sblive_readptr(card, addr, 0); if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; break; case CMD_SETPATCH: if (ctl->val[0] == 0) memcpy(&card->mgr.rpatch, &ctl->val[1], sizeof(struct dsp_rpatch)); else { page = (ctl->val[0] - 1) / PATCHES_PER_PAGE; if (page > MAX_PATCHES_PAGES) { ret = -EINVAL; break; } if (page >= card->mgr.current_pages) { for (i = card->mgr.current_pages; i < page + 1; i++) { card->mgr.patch[i] = (void *)__get_free_page(GFP_KERNEL); if(card->mgr.patch[i] == NULL) { card->mgr.current_pages = i; ret = -ENOMEM; break; } memset(card->mgr.patch[i], 0, PAGE_SIZE); } card->mgr.current_pages = page + 1; } patch = PATCH(&card->mgr, ctl->val[0] - 1); memcpy(patch, &ctl->val[1], sizeof(struct dsp_patch)); if (patch->code_size == 0) { for(i = page + 1; i < card->mgr.current_pages; i++) free_page((unsigned long) card->mgr.patch[i]); card->mgr.current_pages = page + 1; } } break; case CMD_SETGPR: if (ctl->val[0] > NUM_GPRS) { ret = -EINVAL; break; } memcpy(&card->mgr.gpr[ctl->val[0]], &ctl->val[1], sizeof(struct dsp_gpr)); break; case CMD_SETCTLGPR: addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, (char *) ctl->val + PATCH_NAME_SIZE); emu10k1_set_control_gpr(card, addr, *((s32 *)((char *) ctl->val + 2 * PATCH_NAME_SIZE)), 0); break; case CMD_SETGPOUT: if ( ((ctl->val[0] > 2) && (!card->is_audigy)) || (ctl->val[0] > 15) || ctl->val[1] > 1) { ret= -EINVAL; break; } if (card->is_audigy) emu10k1_writefn0(card, (1 << 24) | ((ctl->val[0]) << 16) | A_IOCFG, ctl->val[1]); else emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]); break; case CMD_GETGPR2OSS: id = ctl->val[0]; ch = ctl->val[1]; if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) { ret = -EINVAL; break; } ctl->val[2] = card->mgr.ctrl_gpr[id][ch]; if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; break; case CMD_SETGPR2OSS: id = ctl->val[0]; /* 0 == left, 1 == right */ ch = ctl->val[1]; addr = ctl->val[2]; if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) { ret = -EINVAL; break; } card->mgr.ctrl_gpr[id][ch] = addr; if (card->is_aps) break; if (addr >= 0) { unsigned int state = card->ac97->mixer_state[id]; if (ch == 1) { state >>= 8; card->ac97->stereo_mixers |= (1 << id); } card->ac97->supported_mixers |= (1 << id); if (id == SOUND_MIXER_TREBLE) { set_treble(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff); } else if (id == SOUND_MIXER_BASS) { set_bass(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff); } else