示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
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