Ejemplo n.º 1
0
void emu10k1_cleanup(struct emu10k1_card *card)
{
  int ch;

  emu10k1_writefn0(card, INTE, 0);

  /** Shutdown the chip **/
  for (ch = 0; ch < NUM_G; ch++)
    sblive_writeptr(card, DCYSUSV, ch, 0);

  for (ch = 0; ch < NUM_G; ch++) {
    sblive_writeptr_tag(card, ch,
			VTFT, 0,
			CVCF, 0,
			PTRX, 0,
			//CPF, 0,
			TAGLIST_END);
    sblive_writeptr(card, CPF, ch, 0);
  }

  /* Disable audio and lock cache */
  emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);

  sblive_writeptr_tag(card, 0,
		      PTB, 0,

		      /* Reset recording buffers */
		      MICBS, ADCBS_BUFSIZE_NONE,
		      MICBA, 0,
		      FXBS, ADCBS_BUFSIZE_NONE,
		      FXBA, 0,
		      FXWC, 0,
		      ADCBS, ADCBS_BUFSIZE_NONE,
		      ADCBA, 0,
		      TCBS, 0,
		      TCB, 0,
		      DBG, 0x8000,

		      /* Disable channel interrupt */
		      CLIEL, 0,
		      CLIEH, 0,
		      SOLEL, 0,
		      SOLEH, 0,
		      TAGLIST_END);


  pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
  pci_free_consistent(card->pci_dev, card->silentpage.size, card->silentpage.addr, card->silentpage.dma_handle);
  
  if(card->tankmem.size != 0)
    pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);

  /* release patch storage memory */
  fx_cleanup(&card->mgr);
}
Ejemplo n.º 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
Ejemplo n.º 3
0
static int hw_init(struct emu10k1_card *card)
{
	int nCh;
	u32 pagecount; /* tmp */
	int ret;

	/* Disable audio and lock cache */
	emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);

	/* Reset recording buffers */
	sblive_writeptr_tag(card, 0,
			    MICBS, ADCBS_BUFSIZE_NONE,
			    MICBA, 0,
			    FXBS, ADCBS_BUFSIZE_NONE,
			    FXBA, 0,
			    ADCBS, ADCBS_BUFSIZE_NONE,
			    ADCBA, 0,
			    TAGLIST_END);

	/* Disable channel interrupt */
	emu10k1_writefn0(card, INTE, 0);
	sblive_writeptr_tag(card, 0,
			    CLIEL, 0,
			    CLIEH, 0,
			    SOLEL, 0,
			    SOLEH, 0,
			    TAGLIST_END);

	/* Init envelope engine */
	for (nCh = 0; nCh < NUM_G; nCh++) {
		sblive_writeptr_tag(card, nCh,
				    DCYSUSV, 0,
				    IP, 0,
				    VTFT, 0xffff,
				    CVCF, 0xffff,
				    PTRX, 0,
				    //CPF, 0,
				    CCR, 0,

				    PSST, 0,
				    DSL, 0x10,
				    CCCA, 0,
				    Z1, 0,
				    Z2, 0,
				    FXRT, 0xd01c0000,

				    ATKHLDM, 0,
				    DCYSUSM, 0,
				    IFATN, 0xffff,
				    PEFE, 0,
				    FMMOD, 0,
				    TREMFRQ, 24,	/* 1 Hz */
				    FM2FRQ2, 24,	/* 1 Hz */
				    TEMPENV, 0,

				    /*** These are last so OFF prevents writing ***/
				    LFOVAL2, 0,
				    LFOVAL1, 0,
				    ATKHLDV, 0,
				    ENVVOL, 0,
				    ENVVAL, 0,
                                    TAGLIST_END);
		sblive_writeptr(card, CPF, nCh, 0);
	}
	

	/*
	 ** Init to 0x02109204 :
	 ** Clock accuracy    = 0     (1000ppm)
	 ** Sample Rate       = 2     (48kHz)
	 ** Audio Channel     = 1     (Left of 2)
	 ** Source Number     = 0     (Unspecified)
	 ** Generation Status = 1     (Original for Cat Code 12)
	 ** Cat Code          = 12    (Digital Signal Mixer)
	 ** Mode              = 0     (Mode 0)
	 ** Emphasis          = 0     (None)
	 ** CP                = 1     (Copyright unasserted)
	 ** AN                = 0     (Digital audio)
	 ** P                 = 0     (Consumer)
	 */

	sblive_writeptr_tag(card, 0,

			    /* SPDIF0 */
			    SPCS0, (SPCS_CLKACCY_1000PPM | 0x002000000 |
				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),

			    /* SPDIF1 */
			    SPCS1, (SPCS_CLKACCY_1000PPM | 0x002000000 |
				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),

			    /* SPDIF2 & SPDIF3 */
			    SPCS2, (SPCS_CLKACCY_1000PPM | 0x002000000 |
				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),

			    TAGLIST_END);

	ret = fx_init(card);		/* initialize effects engine */
	if (ret < 0)
		return ret;

	card->tankmem.size = 0;

	card->virtualpagetable.size = MAXPAGES * sizeof(u32);

	card->virtualpagetable.addr = pci_alloc_consistent(card->pci_dev, card->virtualpagetable.size, &card->virtualpagetable.dma_handle);
	if (card->virtualpagetable.addr == NULL) {
		ERROR();
		ret = -ENOMEM;
		goto err0;
	}

	card->silentpage.size = EMUPAGESIZE;

	card->silentpage.addr = pci_alloc_consistent(card->pci_dev, card->silentpage.size, &card->silentpage.dma_handle);
	if (card->silentpage.addr == NULL) {
		ERROR();
		ret = -ENOMEM;
		goto err1;
	}

	for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
		((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32((card->silentpage.dma_handle * 2) | pagecount);

	/* Init page table & tank memory base register */
	sblive_writeptr_tag(card, 0,
			    PTB, card->virtualpagetable.dma_handle,
			    TCB, 0,
			    TCBS, 0,
			    TAGLIST_END);

	for (nCh = 0; nCh < NUM_G; nCh++) {
		sblive_writeptr_tag(card, nCh,
				    MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
				    MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
				    TAGLIST_END);
	}

	/* Hokay, now enable the AUD bit */
	/* Enable Audio = 1 */
	/* Mute Disable Audio = 0 */
	/* Lock Tank Memory = 1 */
	/* Lock Sound Memory = 0 */
	/* Auto Mute = 1 */

	if (card->model == 0x20 || card->model == 0xc400 ||
	  (card->model == 0x21 && card->chiprev < 6))
	        emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
	else
		emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);

	/* Enable Vol_Ctrl irqs */
	emu10k1_irq_enable(card, INTE_VOLINCRENABLE | INTE_VOLDECRENABLE | INTE_MUTEENABLE | INTE_FXDSPENABLE);

	/* FIXME: TOSLink detection */
	card->has_toslink = 0;
#ifdef lcs
	/* Initialize digital passthrough variables */
	card->pt.pos_gpr = card->pt.intr_gpr = card->pt.enable_gpr = -1;
	card->pt.selected = 0;
	card->pt.state = PT_STATE_INACTIVE;
	card->pt.spcs_to_use = 0x01;
	card->pt.patch_name = "AC3pass";
	card->pt.intr_gpr_name = "count";
	card->pt.enable_gpr_name = "enable";
	card->pt.pos_gpr_name = "ptr";
	spin_lock_init(&card->pt.lock);
	init_waitqueue_head(&card->pt.wait);
#endif
/*	tmp = sblive_readfn0(card, HCFG);
	if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
		sblive_writefn0(card, HCFG, tmp | 0x800);

		udelay(512);

		if (tmp != (sblive_readfn0(card, HCFG) & ~0x800)) {
			card->has_toslink = 1;
			sblive_writefn0(card, HCFG, tmp);
		}
	}
*/
	return 0;

  err1:
	pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
  err0:
	fx_cleanup(&card->mgr);

	return ret;
}