Пример #1
0
int snd_ca0106_i2c_write(ca0106_t *emu,
				u32 reg,
				u32 value)
{
	u32 tmp;
	int timeout=0;
	int status;
	int retry;
	if ((reg > 0x7f) || (value > 0x1ff))
	{
		snd_printk(KERN_ERR "i2c_write: invalid values.\n");
		return -EINVAL;
	}

	tmp = reg << 25 | value << 16;
	/* Not sure what this I2C channel controls. */
	/* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */

	/* This controls the I2C connected to the WM8775 ADC Codec */
	snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);

	for(retry=0;retry<10;retry++)
	{
		/* Send the data to i2c */
		tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
		tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
		tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
		snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);

		/* Wait till the transaction ends */
		while(1)
		{
			status = snd_ca0106_ptr_read(emu, I2C_A, 0);
                	//snd_printk("I2C:status=0x%x\n", status);
			timeout++;
			if((status & I2C_A_ADC_START)==0)
				break;

			if(timeout>1000)
				break;
		}
		//Read back and see if the transaction is successful
		if((status & I2C_A_ADC_ABORT)==0)
			break;
	}

	if(retry==10)
	{
		snd_printk(KERN_ERR "Writing to ADC failed!\n");
		return -EINVAL;
	}
    
    	return 0;
}
Пример #2
0
static void ca0106_set_capture_source(struct snd_ca0106 *emu)
{
	unsigned int val = emu->capture_source;
	unsigned int source, mask;
	source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
	mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
	snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
}
Пример #3
0
static void ca0106_spdif_enable(struct snd_ca0106 *emu)
{
	unsigned int val;

	if (emu->spdif_enable) {
		/* Digital */
		snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
		snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
		val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
		snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
		val = inl(emu->port + GPIO) & ~0x101;
		outl(val, emu->port + GPIO);

	} else {
		/* Analog */
		snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
		snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
		val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
		snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
		val = inl(emu->port + GPIO) | 0x101;
		outl(val, emu->port + GPIO);
	}
}
Пример #4
0
static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
{
	snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
}
Пример #5
0
static void snd_live24_mixer_write(struct emu10k1_card *card,unsigned int reg,unsigned int value)
{
 unsigned int channel_id=reg>>8;
 reg&=0xff;
 snd_ca0106_ptr_write(card,reg,channel_id,value);
}
Пример #6
0
static void snd_live24_pcm_stop_playback(struct emu10k1_card *card)
{
 const uint32_t channel=0;
 snd_ca0106_ptr_write(card, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(card, BASIC_INTERRUPT, 0) & (~(0x1<<channel)));
 mpxplay_debugf(SBL_DEBUG_OUTPUT,"stop playback");
}
Пример #7
0
static void snd_ca0106_pcm_prepare_playback(struct emu10k1_card *card,struct mpxplay_audioout_info_s *aui)
{
 const uint32_t channel=0;
 uint32_t *table_base =card->virtualpagetable;
 uint32_t period_size_bytes=card->period_size;
 uint32_t i,reg40_set,reg71_set;

 switch(aui->freq_card){
  case 44100:
   reg40_set = 0x10000 << (channel<<1);
   reg71_set = 0x01010000;
   break;
  case 96000:
   reg40_set = 0x20000 << (channel<<1);
   reg71_set = 0x02020000;
   break;
  case 192000:
   reg40_set = 0x30000 << (channel<<1);
   reg71_set = 0x03030000;
   break;
  default: // 48000
   reg40_set = 0;
   reg71_set = 0;
   break;
 }

 i = snd_ca0106_ptr_read(card, 0x40, 0); // control host to fifo
 i = (i & (~(0x30000<<(channel<<1)))) | reg40_set;
 snd_ca0106_ptr_write(card, 0x40, 0, i);

 i = snd_ca0106_ptr_read(card, 0x71, 0); // control DAC rate (SPDIF)
 i = (i & (~0x03030000)) | reg71_set;
 snd_ca0106_ptr_write(card, 0x71, 0, i);

 i=inl(card->iobase+HCFG);               // control bit width
 if(aui->bits_card==32)
  i|=HCFG_PLAYBACK_S32_LE;
 else
  i&=~HCFG_PLAYBACK_S32_LE;
 outl(card->iobase+HCFG,i);

 // build pagetable
 for(i=0; i<CA0106_DMABUF_PERIODS; i++){
  table_base[i*2]=(uint32_t)((char *)card->pcmout_buffer+(i*period_size_bytes));
  table_base[i*2+1]=period_size_bytes<<16;
 }

 snd_ca0106_ptr_write(card, PLAYBACK_LIST_ADDR, channel, (uint32_t)(table_base));
 snd_ca0106_ptr_write(card, PLAYBACK_LIST_SIZE, channel, (CA0106_DMABUF_PERIODS - 1) << 19);
 snd_ca0106_ptr_write(card, PLAYBACK_LIST_PTR, channel, 0);
 snd_ca0106_ptr_write(card, PLAYBACK_DMA_ADDR, channel, (uint32_t)card->pcmout_buffer);
 snd_ca0106_ptr_write(card, PLAYBACK_PERIOD_SIZE, channel, 0);
 //snd_ca0106_ptr_write(card, PLAYBACK_PERIOD_SIZE, channel, period_size_bytes<<16);
 snd_ca0106_ptr_write(card, PLAYBACK_POINTER, channel, 0);
 snd_ca0106_ptr_write(card, 0x07, channel, 0x0);
 snd_ca0106_ptr_write(card, 0x08, channel, 0);
 snd_ca0106_ptr_write(card, PLAYBACK_MUTE, 0x0, 0x0); // unmute output

 mpxplay_debugf(SBL_DEBUG_OUTPUT,"prepare playback end");
}
Пример #8
0
static void snd_live24_hw_close(struct emu10k1_card *card)
{
 snd_ca0106_ptr_write(card, BASIC_INTERRUPT, 0, 0);
 outl(card->iobase + INTE, 0);
 outl(card->iobase + HCFG, 0);
}
Пример #9
0
static void snd_ca0106_hw_init(struct emu10k1_card *card)
{
 unsigned int ch;

 outl(card->iobase + INTE, 0);

 snd_ca0106_ptr_write(card, SPCS0, 0,
                  SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
		  SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
		  SPCS_GENERATIONSTATUS | 0x00001200 |
		  0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
 // Only SPCS1 has been tested
 snd_ca0106_ptr_write(card, SPCS1, 0,
                  SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
		  SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
		  SPCS_GENERATIONSTATUS | 0x00001200 |
		  0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
 snd_ca0106_ptr_write(card, SPCS2, 0,
                  SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
		  SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
		  SPCS_GENERATIONSTATUS | 0x00001200 |
		  0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
 snd_ca0106_ptr_write(card, SPCS3, 0,
                  SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
		  SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
		  SPCS_GENERATIONSTATUS | 0x00001200 |
		  0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);

 snd_ca0106_ptr_write(card, PLAYBACK_MUTE, 0, 0x00fc0000);
 snd_ca0106_ptr_write(card, CAPTURE_MUTE, 0, 0x00fc0000);

 outb(card->iobase + AC97ADDRESS, AC97_RECORD_GAIN);
 outw(card->iobase + AC97DATA, 0x8000); // mute

 snd_ca0106_ptr_write(card, SPDIF_SELECT1, 0, 0xf);
 snd_ca0106_ptr_write(card, SPDIF_SELECT2, 0, 0x01010001); // enable analog,spdif,ac97 front
 //snd_ca0106_ptr_write(card, SPDIF_SELECT2, 0, 0x0f0f0000); // enable analog and spdif 7.1

 snd_ca0106_ptr_write(card, CAPTURE_CONTROL, 0, 0x40c81000); // goes to 0x40c80000 when doing SPDIF IN/OUT
 snd_ca0106_ptr_write(card, CAPTURE_CONTROL, 1, 0xffffffff); // (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter.

 // ??? does this work at all ?
 snd_ca0106_ptr_write(card, PLAYBACK_ROUTING1, 0, 0x32765410);
 //snd_ca0106_ptr_write(card, PLAYBACK_ROUTING1, 0, 0x10765410);
 snd_ca0106_ptr_write(card, PLAYBACK_ROUTING2, 0, 0x76767676);

 // mute unused channels
 for(ch = 0; ch < 4; ch++) {
  snd_ca0106_ptr_write(card, CAPTURE_VOLUME1, ch, 0xffffffff); // Only high 16 bits matter
  snd_ca0106_ptr_write(card, CAPTURE_VOLUME2, ch, 0xffffffff); // mute ???
 }
 for(ch = 1; ch < 4; ch++) { // !!! we keep the playback volume of channel 0
  snd_ca0106_ptr_write(card, PLAYBACK_VOLUME1, ch, 0xffffffff); // Mute
  snd_ca0106_ptr_write(card, PLAYBACK_VOLUME2, ch, 0xffffffff); // Mute
 }

 outl(card->iobase+GPIO, 0x0);
}
Пример #10
0
/* prepare playback callback */
static int snd_ca0106_pcm_prepare_playback(snd_pcm_substream_t *substream)
{
	ca0106_t *emu = snd_pcm_substream_chip(substream);
	snd_pcm_runtime_t *runtime = substream->runtime;
	ca0106_pcm_t *epcm = runtime->private_data;
	int channel = epcm->channel_id;
	u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
	u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
	u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
	u32 hcfg_set = 0x00000000;
	u32 hcfg;
	u32 reg40_mask = 0x30000 << (channel<<1);
	u32 reg40_set = 0;
	u32 reg40;
	/* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
	u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
	u32 reg71_set = 0;
	u32 reg71;
	int i;
	
        //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
	//snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
	/* Rate can be set per channel. */
	/* reg40 control host to fifo */
	/* reg71 controls DAC rate. */
	switch (runtime->rate) {
	case 44100:
		reg40_set = 0x10000 << (channel<<1);
		reg71_set = 0x01010000; 
		break;
        case 48000:
		reg40_set = 0;
		reg71_set = 0; 
		break;
	case 96000:
		reg40_set = 0x20000 << (channel<<1);
		reg71_set = 0x02020000; 
		break;
	case 192000:
		reg40_set = 0x30000 << (channel<<1);
		reg71_set = 0x03030000; 
		break;
	default:
		reg40_set = 0;
		reg71_set = 0; 
		break;
	}
	/* Format is a global setting */
	/* FIXME: Only let the first channel accessed set this. */
	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S16_LE:
		hcfg_set = 0;
		break;
	case SNDRV_PCM_FORMAT_S32_LE:
		hcfg_set = HCFG_PLAYBACK_S32_LE;
		break;
	default:
		hcfg_set = 0;
		break;
	}
	hcfg = inl(emu->port + HCFG) ;
	hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
	outl(hcfg, emu->port + HCFG);
	reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
	reg40 = (reg40 & ~reg40_mask) | reg40_set;
	snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
	reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
	reg71 = (reg71 & ~reg71_mask) | reg71_set;
	snd_ca0106_ptr_write(emu, 0x71, 0, reg71);

	/* FIXME: Check emu->buffer.size before actually writing to it. */
        for(i=0; i < runtime->periods; i++) {
		table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
		table_base[(i*2)+1]=period_size_bytes<<16;
	}
 
	snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
	snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
	snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
	snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
	snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
	/* FIXME  test what 0 bytes does. */
	snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
	snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
	snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
	snd_ca0106_ptr_write(emu, 0x08, channel, 0);
        snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
#if 0
	snd_ca0106_ptr_write(emu, SPCS0, 0,
			       SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
			       SPCS_GENERATIONSTATUS | 0x00001200 |
			       0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
	}