Exemple #1
0
int emu10k1_init(struct emu10k1_card *card)
{
	/* Init Card */
	if (hw_init(card) < 0)
		return -1;

	voice_init(card);
	addxmgr_init(card);

	DPD(2, "  hw control register -> %#x\n", emu10k1_readfn0(card, HCFG));

	return 0;
}
Exemple #2
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