u32 lx_plx_mbox_read(struct lx6464es *chip, int mbox_nr) { int index; switch (mbox_nr) { case 1: index = ePLX_MBOX1; break; case 2: index = ePLX_MBOX2; break; case 3: index = ePLX_MBOX3; break; case 4: index = ePLX_MBOX4; break; case 5: index = ePLX_MBOX5; break; case 6: index = ePLX_MBOX6; break; case 7: index = ePLX_MBOX7; break; case 0: /* reserved for HF flags */ snd_BUG(); default: return 0xdeadbeef; } return lx_plx_reg_read(chip, index); }
int lx_plx_mbox_write(struct lx6464es *chip, int mbox_nr, u32 value) { int index = -1; switch (mbox_nr) { case 1: index = ePLX_MBOX1; break; case 3: index = ePLX_MBOX3; break; case 4: index = ePLX_MBOX4; break; case 5: index = ePLX_MBOX5; break; case 6: index = ePLX_MBOX6; break; case 7: index = ePLX_MBOX7; break; case 0: /* reserved for HF flags */ case 2: /* reserved for Pipe States * the DSP keeps an image of it */ snd_BUG(); return -EBADRQC; } lx_plx_reg_write(chip, index, value); return 0; }
int snd_hdjmidi_output_open(snd_rawmidi_substream_t *substream) #endif { struct snd_hdjmidi* umidi = substream->rmidi->private_data; struct hdjmidi_out_port* port = NULL; int i, j; #ifdef RENDER_DUMP_URB_THROTTLE render_dump_urb_throttle = 0; #endif snd_printk(KERN_DEBUG"%s()\n",__FUNCTION__); for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { if (umidi->endpoints[i].out) { for (j = 0; j < 0x10; ++j) { if (umidi->endpoints[i].out->ports[j].substream == substream) { port = &umidi->endpoints[i].out->ports[j]; #ifdef THROTTLE_MP3_RENDER umidi->endpoints[i].out->last_send_time = jiffies + (THROTTLE_MP3_RENDER_RATE*HZ)/1000; #endif break; } } } } if (!port) { snd_BUG(); return -ENXIO; } substream->runtime->private_data = port; port->state = STATE_UNKNOWN; return 0; }
/* * vxp_load_dsp - load_dsp callback */ static int vxp_load_dsp(vx_core_t *vx, int index, const struct firmware *fw) { int err; switch (index) { case 0: /* xilinx boot */ if ((err = vx_check_magic(vx)) < 0) return err; if ((err = snd_vx_load_boot_image(vx, fw)) < 0) return err; return 0; case 1: /* xilinx image */ return vxp_load_xilinx_binary(vx, fw); case 2: /* DSP boot */ return snd_vx_dsp_boot(vx, fw); case 3: /* DSP image */ return snd_vx_dsp_load(vx, fw); default: snd_BUG(); return -EINVAL; } }
static int __devinit phase22_init(struct snd_ice1712 *ice) { struct snd_akm4xxx *ak; int err; // Configure DAC/ADC description for generic part of ice1724 switch (ice->eeprom.subvendor) { case VT1724_SUBDEVICE_PHASE22: ice->num_total_dacs = 2; ice->num_total_adcs = 2; ice->vt1720 = 1; // Envy24HT-S have 16 bit wide GPIO break; default: snd_BUG(); return -EINVAL; } // Initialize analog chips ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (! ak) return -ENOMEM; ice->akm_codecs = 1; switch (ice->eeprom.subvendor) { case VT1724_SUBDEVICE_PHASE22: if ((err = snd_ice1712_akm4xxx_init(ak, &akm_phase22, &akm_phase22_priv, ice)) < 0) return err; break; } return 0; }
/* * return the index of the target rate */ static int snd_nm256_fixed_rate(unsigned int rate) { unsigned int i; for (i = 0; i < ARRAY_SIZE(samplerates); i++) { if (rate == samplerates[i]) return i; } snd_BUG(); return 0; }
/* * get a stream of the opposite direction */ static struct pmac_stream *snd_pmac_get_stream(struct snd_pmac *chip, int stream) { switch (stream) { case SNDRV_PCM_STREAM_PLAYBACK: return &chip->playback; case SNDRV_PCM_STREAM_CAPTURE: return &chip->capture; default: snd_BUG(); return NULL; } }
static unsigned char divisor_to_rate_register(unsigned int divisor) { switch (divisor) { case 353: return 1; case 529: return 2; case 617: return 3; case 1058: return 4; case 1764: return 5; case 2117: return 6; case 2558: return 7; default: if (divisor < 21 || divisor > 192) { snd_BUG(); return 192; } return divisor; } }
/* this is called in atomic context with IRQ disabled. Must be as fast as possible and not sleep. DMA should be *triggered* by this call. The WSMC "WAEN" bit triggers DMA Wave On/Off */ static int snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd) { u16 wsmc; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); wsmc = ad1889_readw(chip, AD_DS_WSMC); switch (cmd) { case SNDRV_PCM_TRIGGER_START: /* enable DMA loop & interrupts */ ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT); wsmc |= AD_DS_WSMC_WAEN; /* 1 to clear CHSS bit */ ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS); ad1889_unmute(chip); break; case SNDRV_PCM_TRIGGER_STOP: ad1889_mute(chip); wsmc &= ~AD_DS_WSMC_WAEN; break; default: snd_BUG(); return -EINVAL; } chip->wave.reg = wsmc; ad1889_writew(chip, AD_DS_WSMC, wsmc); ad1889_readw(chip, AD_DS_WSMC); /* flush */ /* reset the chip when STOP - will disable IRQs */ if (cmd == SNDRV_PCM_TRIGGER_STOP) ad1889_channel_reset(chip, AD_CHAN_WAV); return 0; }
static int snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd) { u16 wsmc; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); wsmc = ad1889_readw(chip, AD_DS_WSMC); switch (cmd) { case SNDRV_PCM_TRIGGER_START: ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT); wsmc |= AD_DS_WSMC_WAEN; ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS); ad1889_unmute(chip); break; case SNDRV_PCM_TRIGGER_STOP: ad1889_mute(chip); wsmc &= ~AD_DS_WSMC_WAEN; break; default: snd_BUG(); return -EINVAL; } chip->wave.reg = wsmc; ad1889_writew(chip, AD_DS_WSMC, wsmc); ad1889_readw(chip, AD_DS_WSMC); if (cmd == SNDRV_PCM_TRIGGER_STOP) ad1889_channel_reset(chip, AD_CHAN_WAV); return 0; }
/* * initialize all the ak4xxx chips */ void snd_akm4xxx_init(struct snd_akm4xxx *ak) { static unsigned char inits_ak4524[] = { 0x00, 0x07, /* 0: all power up */ 0x01, 0x00, /* 1: ADC/DAC reset */ 0x02, 0x60, /* 2: 24bit I2S */ 0x03, 0x19, /* 3: deemphasis off */ 0x01, 0x03, /* 1: ADC/DAC enable */ 0x04, 0x00, /* 4: ADC left muted */ 0x05, 0x00, /* 5: ADC right muted */ 0x04, 0x80, /* 4: ADC IPGA gain 0dB */ 0x05, 0x80, /* 5: ADC IPGA gain 0dB */ 0x06, 0x00, /* 6: DAC left muted */ 0x07, 0x00, /* 7: DAC right muted */ 0xff, 0xff }; static unsigned char inits_ak4528[] = { 0x00, 0x07, /* 0: all power up */ 0x01, 0x00, /* 1: ADC/DAC reset */ 0x02, 0x60, /* 2: 24bit I2S */ 0x03, 0x0d, /* 3: deemphasis off, turn LR highpass filters on */ 0x01, 0x03, /* 1: ADC/DAC enable */ 0x04, 0x00, /* 4: ADC left muted */ 0x05, 0x00, /* 5: ADC right muted */ 0xff, 0xff }; static unsigned char inits_ak4529[] = { 0x09, 0x01, /* 9: ATS=0, RSTN=1 */ 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */ 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */ 0x01, 0x00, /* 1: ACKS=0, ADC, loop off */ 0x02, 0xff, /* 2: LOUT1 muted */ 0x03, 0xff, /* 3: ROUT1 muted */ 0x04, 0xff, /* 4: LOUT2 muted */ 0x05, 0xff, /* 5: ROUT2 muted */ 0x06, 0xff, /* 6: LOUT3 muted */ 0x07, 0xff, /* 7: ROUT3 muted */ 0x0b, 0xff, /* B: LOUT4 muted */ 0x0c, 0xff, /* C: ROUT4 muted */ 0x08, 0x55, /* 8: deemphasis all off */ 0xff, 0xff }; static unsigned char inits_ak4355[] = { 0x01, 0x02, /* 1: reset and soft-mute */ 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ // 0x02, 0x2e, /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ 0x04, 0x00, /* 4: LOUT1 volume muted */ 0x05, 0x00, /* 5: ROUT1 volume muted */ 0x06, 0x00, /* 6: LOUT2 volume muted */ 0x07, 0x00, /* 7: ROUT2 volume muted */ 0x08, 0x00, /* 8: LOUT3 volume muted */ 0x09, 0x00, /* 9: ROUT3 volume muted */ 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */ 0x01, 0x01, /* 1: un-reset, unmute */ 0xff, 0xff }; static unsigned char inits_ak4358[] = { 0x01, 0x02, /* 1: reset and soft-mute */ 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ // 0x02, 0x2e, /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ 0x04, 0x00, /* 4: LOUT1 volume muted */ 0x05, 0x00, /* 5: ROUT1 volume muted */ 0x06, 0x00, /* 6: LOUT2 volume muted */ 0x07, 0x00, /* 7: ROUT2 volume muted */ 0x08, 0x00, /* 8: LOUT3 volume muted */ 0x09, 0x00, /* 9: ROUT3 volume muted */ 0x0b, 0x00, /* b: LOUT4 volume muted */ 0x0c, 0x00, /* c: ROUT4 volume muted */ 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */ 0x01, 0x01, /* 1: un-reset, unmute */ 0xff, 0xff }; static unsigned char inits_ak4381[] = { 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ 0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */ // 0x01, 0x12, /* quad speed */ 0x02, 0x00, /* 2: DZF disabled */ 0x03, 0x00, /* 3: LATT 0 */ 0x04, 0x00, /* 4: RATT 0 */ 0x00, 0x0f, /* 0: power-up, un-reset */ 0xff, 0xff }; int chip, num_chips; unsigned char *ptr, reg, data, *inits; switch (ak->type) { case SND_AK4524: inits = inits_ak4524; num_chips = ak->num_dacs / 2; break; case SND_AK4528: inits = inits_ak4528; num_chips = ak->num_dacs / 2; break; case SND_AK4529: inits = inits_ak4529; num_chips = 1; break; case SND_AK4355: inits = inits_ak4355; num_chips = 1; break; case SND_AK4358: inits = inits_ak4358; num_chips = 1; break; case SND_AK4381: inits = inits_ak4381; num_chips = ak->num_dacs / 2; break; default: snd_BUG(); return; } for (chip = 0; chip < num_chips; chip++) { ptr = inits; while (*ptr != 0xff) { reg = *ptr++; data = *ptr++; snd_akm4xxx_write(ak, chip, reg, data); } } }
/* * initialize all the ak4xxx chips */ void snd_akm4xxx_init(struct snd_akm4xxx *ak) { static const unsigned char inits_ak4524[] = { 0x00, 0x07, /* 0: all power up */ 0x01, 0x00, /* 1: ADC/DAC reset */ 0x02, 0x60, /* 2: 24bit I2S */ 0x03, 0x19, /* 3: deemphasis off */ 0x01, 0x03, /* 1: ADC/DAC enable */ 0x04, 0x00, /* 4: ADC left muted */ 0x05, 0x00, /* 5: ADC right muted */ 0x06, 0x00, /* 6: DAC left muted */ 0x07, 0x00, /* 7: DAC right muted */ 0xff, 0xff }; static const unsigned char inits_ak4528[] = { 0x00, 0x07, /* 0: all power up */ 0x01, 0x00, /* 1: ADC/DAC reset */ 0x02, 0x60, /* 2: 24bit I2S */ 0x03, 0x0d, /* 3: deemphasis off, turn LR highpass filters on */ 0x01, 0x03, /* 1: ADC/DAC enable */ 0x04, 0x00, /* 4: ADC left muted */ 0x05, 0x00, /* 5: ADC right muted */ 0xff, 0xff }; static const unsigned char inits_ak4529[] = { 0x09, 0x01, /* 9: ATS=0, RSTN=1 */ 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */ 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */ 0x01, 0x00, /* 1: ACKS=0, ADC, loop off */ 0x02, 0xff, /* 2: LOUT1 muted */ 0x03, 0xff, /* 3: ROUT1 muted */ 0x04, 0xff, /* 4: LOUT2 muted */ 0x05, 0xff, /* 5: ROUT2 muted */ 0x06, 0xff, /* 6: LOUT3 muted */ 0x07, 0xff, /* 7: ROUT3 muted */ 0x0b, 0xff, /* B: LOUT4 muted */ 0x0c, 0xff, /* C: ROUT4 muted */ 0x08, 0x55, /* 8: deemphasis all off */ 0xff, 0xff }; static const unsigned char inits_ak4355[] = { 0x01, 0x02, /* 1: reset and soft-mute */ 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, * disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ // 0x02, 0x2e, /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ 0x04, 0x00, /* 4: LOUT1 volume muted */ 0x05, 0x00, /* 5: ROUT1 volume muted */ 0x06, 0x00, /* 6: LOUT2 volume muted */ 0x07, 0x00, /* 7: ROUT2 volume muted */ 0x08, 0x00, /* 8: LOUT3 volume muted */ 0x09, 0x00, /* 9: ROUT3 volume muted */ 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */ 0x01, 0x01, /* 1: un-reset, unmute */ 0xff, 0xff }; static const unsigned char inits_ak4358[] = { 0x01, 0x02, /* 1: reset and soft-mute */ 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, * disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x4e, /* 2: DA's power up, normal speed, RSTN#=0 */ /* 0x02, 0x6e,*/ /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ 0x04, 0x00, /* 4: LOUT1 volume muted */ 0x05, 0x00, /* 5: ROUT1 volume muted */ 0x06, 0x00, /* 6: LOUT2 volume muted */ 0x07, 0x00, /* 7: ROUT2 volume muted */ 0x08, 0x00, /* 8: LOUT3 volume muted */ 0x09, 0x00, /* 9: ROUT3 volume muted */ 0x0b, 0x00, /* b: LOUT4 volume muted */ 0x0c, 0x00, /* c: ROUT4 volume muted */ 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */ 0x01, 0x01, /* 1: un-reset, unmute */ 0xff, 0xff }; static const unsigned char inits_ak4381[] = { 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ 0x01, 0x02, /* 1: de-emphasis off, normal speed, * sharp roll-off, DZF off */ // 0x01, 0x12, /* quad speed */ 0x02, 0x00, /* 2: DZF disabled */ 0x03, 0x00, /* 3: LATT 0 */ 0x04, 0x00, /* 4: RATT 0 */ 0x00, 0x0f, /* 0: power-up, un-reset */ 0xff, 0xff }; static const unsigned char inits_ak4620[] = { 0x00, 0x07, /* 0: normal */ 0x01, 0x00, /* 0: reset */ 0x01, 0x02, /* 1: RSTAD */ 0x01, 0x03, /* 1: RSTDA */ 0x01, 0x0f, /* 1: normal */ 0x02, 0x60, /* 2: 24bit I2S */ 0x03, 0x01, /* 3: deemphasis off */ 0x04, 0x00, /* 4: LIN muted */ 0x05, 0x00, /* 5: RIN muted */ 0x06, 0x00, /* 6: LOUT muted */ 0x07, 0x00, /* 7: ROUT muted */ 0xff, 0xff }; int chip; const unsigned char *ptr, *inits; unsigned char reg, data; memset(ak->images, 0, sizeof(ak->images)); memset(ak->volumes, 0, sizeof(ak->volumes)); switch (ak->type) { case SND_AK4524: inits = inits_ak4524; ak->num_chips = ak->num_dacs / 2; ak->name = "ak4524"; ak->total_regs = 0x08; break; case SND_AK4528: inits = inits_ak4528; ak->num_chips = ak->num_dacs / 2; ak->name = "ak4528"; ak->total_regs = 0x06; break; case SND_AK4529: inits = inits_ak4529; ak->num_chips = 1; ak->name = "ak4529"; ak->total_regs = 0x0d; break; case SND_AK4355: inits = inits_ak4355; ak->num_chips = 1; ak->name = "ak4355"; ak->total_regs = 0x0b; break; case SND_AK4358: inits = inits_ak4358; ak->num_chips = 1; ak->name = "ak4358"; ak->total_regs = 0x10; break; case SND_AK4381: inits = inits_ak4381; ak->num_chips = ak->num_dacs / 2; ak->name = "ak4381"; ak->total_regs = 0x05; break; case SND_AK5365: /* FIXME: any init sequence? */ ak->num_chips = 1; ak->name = "ak5365"; ak->total_regs = 0x08; return; case SND_AK4620: inits = inits_ak4620; ak->num_chips = ak->num_dacs / 2; ak->name = "ak4620"; ak->total_regs = 0x08; break; default: snd_BUG(); return; } for (chip = 0; chip < ak->num_chips; chip++) { ptr = inits; while (*ptr != 0xff) { reg = *ptr++; data = *ptr++; snd_akm4xxx_write(ak, chip, reg, data); udelay(10); } } }
static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) { int err; struct snd_akm4xxx *ak; unsigned char tmp; if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010 && ice->eeprom.gpiodir == 0x7b) ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA1010E; if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA66 && ice->eeprom.gpiodir == 0xfb) ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA66E; /* determine I2C, DACs and ADCs */ switch (ice->eeprom.subvendor) { case ICE1712_SUBDEVICE_AUDIOPHILE: ice->num_total_dacs = 2; ice->num_total_adcs = 2; break; case ICE1712_SUBDEVICE_DELTA410: ice->num_total_dacs = 8; ice->num_total_adcs = 2; break; case ICE1712_SUBDEVICE_DELTA44: case ICE1712_SUBDEVICE_DELTA66: ice->num_total_dacs = ice->omni ? 8 : 4; ice->num_total_adcs = ice->omni ? 8 : 4; break; case ICE1712_SUBDEVICE_DELTA1010: case ICE1712_SUBDEVICE_DELTA1010E: case ICE1712_SUBDEVICE_DELTA1010LT: case ICE1712_SUBDEVICE_MEDIASTATION: case ICE1712_SUBDEVICE_EDIROLDA2496: ice->num_total_dacs = 8; ice->num_total_adcs = 8; break; case ICE1712_SUBDEVICE_DELTADIO2496: ice->num_total_dacs = 4; /* two AK4324 codecs */ break; case ICE1712_SUBDEVICE_VX442: case ICE1712_SUBDEVICE_DELTA66E: /* omni not suported yet */ ice->num_total_dacs = 4; ice->num_total_adcs = 4; break; } /* initialize the SPI clock to high */ tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); tmp |= ICE1712_DELTA_AP_CCLK; snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); udelay(5); /* initialize spdif */ switch (ice->eeprom.subvendor) { case ICE1712_SUBDEVICE_AUDIOPHILE: case ICE1712_SUBDEVICE_DELTA410: case ICE1712_SUBDEVICE_DELTA1010E: case ICE1712_SUBDEVICE_DELTA1010LT: case ICE1712_SUBDEVICE_VX442: case ICE1712_SUBDEVICE_DELTA66E: if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { snd_printk(KERN_ERR "unable to create I2C bus\n"); return err; } ice->i2c->private_data = ice; ice->i2c->ops = &ap_cs8427_i2c_ops; if ((err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR)) < 0) return err; break; case ICE1712_SUBDEVICE_DELTA1010: case ICE1712_SUBDEVICE_MEDIASTATION: ice->gpio.set_pro_rate = delta_1010_set_rate_val; break; case ICE1712_SUBDEVICE_DELTADIO2496: ice->gpio.set_pro_rate = delta_1010_set_rate_val; /* fall thru */ case ICE1712_SUBDEVICE_DELTA66: ice->spdif.ops.open = delta_open_spdif; ice->spdif.ops.setup_rate = delta_setup_spdif; ice->spdif.ops.default_get = delta_spdif_default_get; ice->spdif.ops.default_put = delta_spdif_default_put; ice->spdif.ops.stream_get = delta_spdif_stream_get; ice->spdif.ops.stream_put = delta_spdif_stream_put; /* Set spdif defaults */ snd_ice1712_delta_cs8403_spdif_write(ice, ice->spdif.cs8403_bits); break; } /* no analog? */ switch (ice->eeprom.subvendor) { case ICE1712_SUBDEVICE_DELTA1010: case ICE1712_SUBDEVICE_DELTA1010E: case ICE1712_SUBDEVICE_DELTADIO2496: case ICE1712_SUBDEVICE_MEDIASTATION: return 0; } /* second stage of initialization, analog parts and others */ ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (! ak) return -ENOMEM; ice->akm_codecs = 1; switch (ice->eeprom.subvendor) { case ICE1712_SUBDEVICE_AUDIOPHILE: err = snd_ice1712_akm4xxx_init(ak, &akm_audiophile, &akm_audiophile_priv, ice); break; case ICE1712_SUBDEVICE_DELTA410: err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice); break; case ICE1712_SUBDEVICE_DELTA1010LT: case ICE1712_SUBDEVICE_EDIROLDA2496: err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice); break; case ICE1712_SUBDEVICE_DELTA66: case ICE1712_SUBDEVICE_DELTA44: err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice); break; case ICE1712_SUBDEVICE_VX442: err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice); break; case ICE1712_SUBDEVICE_DELTA66E: err = snd_ice1712_akm4xxx_init(ak, &akm_delta66e, &akm_delta66e_priv, ice); break; default: snd_BUG(); return -EINVAL; } return err; }
static int snd_stm_pcm_player_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { int result; struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int buffer_bytes, frame_bytes, transfer_bytes; unsigned int transfer_size; struct stm_dma_req_config fdma_req_config = { .rw = REQ_CONFIG_WRITE, .opcode = REQ_CONFIG_OPCODE_4, .increment = 0, .hold_off = 0, .initiator = pcm_player->info->fdma_initiator, }; snd_stm_printd(1, "snd_stm_pcm_player_hw_params(substream=0x%p," " hw_params=0x%p)\n", substream, hw_params); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); BUG_ON(!runtime); /* This function may be called many times, so let's be prepared... */ if (snd_stm_buffer_is_allocated(pcm_player->buffer)) snd_stm_pcm_player_hw_free(substream); /* Allocate buffer */ buffer_bytes = params_buffer_bytes(hw_params); result = snd_stm_buffer_alloc(pcm_player->buffer, substream, buffer_bytes); if (result != 0) { snd_stm_printe("Can't allocate %d bytes buffer for '%s'!\n", buffer_bytes, dev_name(pcm_player->device)); result = -ENOMEM; goto error_buf_alloc; } /* Set FDMA transfer size (number of opcodes generated * after request line assertion) */ frame_bytes = snd_pcm_format_physical_width(params_format(hw_params)) * params_channels(hw_params) / 8; transfer_bytes = snd_stm_pcm_transfer_bytes(frame_bytes, pcm_player->fdma_max_transfer_size * 4); transfer_size = transfer_bytes / 4; snd_stm_printd(1, "FDMA request trigger limit and transfer size set " "to %d.\n", transfer_size); BUG_ON(buffer_bytes % transfer_bytes != 0); BUG_ON(transfer_size > pcm_player->fdma_max_transfer_size); fdma_req_config.count = transfer_size; BUG_ON(transfer_size != 1 && transfer_size % 2 != 0); BUG_ON(transfer_size > mask__AUD_PCMOUT_FMT__DMA_REQ_TRIG_LMT(pcm_player)); set__AUD_PCMOUT_FMT__DMA_REQ_TRIG_LMT(pcm_player, transfer_size); /* Configure FDMA transfer */ pcm_player->fdma_request = dma_req_config(pcm_player->fdma_channel, pcm_player->info->fdma_request_line, &fdma_req_config); if (!pcm_player->fdma_request) { snd_stm_printe("Can't configure FDMA pacing channel for player" " '%s'!\n", dev_name(pcm_player->device)); result = -EINVAL; goto error_req_config; } dma_params_init(&pcm_player->fdma_params, MODE_PACED, STM_DMA_LIST_CIRC); dma_params_DIM_1_x_0(&pcm_player->fdma_params); dma_params_req(&pcm_player->fdma_params, pcm_player->fdma_request); dma_params_addrs(&pcm_player->fdma_params, runtime->dma_addr, pcm_player->fifo_phys_address, buffer_bytes); result = dma_compile_list(pcm_player->fdma_channel, &pcm_player->fdma_params, GFP_KERNEL); if (result < 0) { snd_stm_printe("Can't compile FDMA parameters for player" " '%s'!\n", dev_name(pcm_player->device)); goto error_compile_list; } return 0; error_compile_list: dma_req_free(pcm_player->fdma_channel, pcm_player->fdma_request); error_req_config: snd_stm_buffer_free(pcm_player->buffer); error_buf_alloc: return result; } static int snd_stm_pcm_player_prepare(struct snd_pcm_substream *substream) { struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; unsigned int format, lr_pol; int oversampling, bits_in_output_frame; int result; snd_stm_printd(1, "snd_stm_pcm_player_prepare(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); BUG_ON(!runtime); BUG_ON(runtime->period_size * runtime->channels >= MAX_SAMPLES_PER_PERIOD); /* Configure SPDIF synchronisation */ /* TODO */ /* Get format & oversampling value from connected converter */ if (pcm_player->conv_group) { format = snd_stm_conv_get_format(pcm_player->conv_group); oversampling = snd_stm_conv_get_oversampling( pcm_player->conv_group); if (oversampling == 0) oversampling = DEFAULT_OVERSAMPLING; } else { format = DEFAULT_FORMAT; oversampling = DEFAULT_OVERSAMPLING; } snd_stm_printd(1, "Player %s: sampling frequency %d, oversampling %d\n", dev_name(pcm_player->device), runtime->rate, oversampling); BUG_ON(oversampling < 0); /* For 32 bits subframe oversampling must be a multiple of 128, * for 16 bits - of 64 */ BUG_ON((format & SND_STM_FORMAT__SUBFRAME_32_BITS) && (oversampling % 128 != 0)); BUG_ON(!(format & SND_STM_FORMAT__SUBFRAME_16_BITS) && (oversampling % 64 != 0)); /* Set up frequency synthesizer */ result = clk_enable(pcm_player->clock); if (result != 0) { snd_stm_printe("Can't enable clock for player '%s'!\n", dev_name(pcm_player->device)); return result; } result = clk_set_rate(pcm_player->clock, runtime->rate * oversampling); if (result != 0) { snd_stm_printe("Can't configure clock for player '%s'!\n", dev_name(pcm_player->device)); clk_disable(pcm_player->clock); return result; } /* Set up player hardware */ snd_stm_printd(1, "Player %s format configuration:\n", dev_name(pcm_player->device)); /* Number of bits per subframe (which is one channel sample) * on output - it determines serial clock frequency, which is * 64 times sampling rate for 32 bits subframe (2 channels 32 * bits each means 64 bits per frame) and 32 times sampling * rate for 16 bits subframe * (you know why, don't you? :-) */ switch (format & SND_STM_FORMAT__SUBFRAME_MASK) { case SND_STM_FORMAT__SUBFRAME_32_BITS: snd_stm_printd(1, "- 32 bits per subframe\n"); set__AUD_PCMOUT_FMT__NBIT__32_BITS(pcm_player); if (pcm_player->ver > 5) set__AUD_PCMOUT_FMT__DATA_SIZE__32_BITS(pcm_player); else set__AUD_PCMOUT_FMT__DATA_SIZE__24_BITS(pcm_player); bits_in_output_frame = 64; /* frame = 2 * subframe */ break; case SND_STM_FORMAT__SUBFRAME_16_BITS: snd_stm_printd(1, "- 16 bits per subframe\n"); set__AUD_PCMOUT_FMT__NBIT__16_BITS(pcm_player); set__AUD_PCMOUT_FMT__DATA_SIZE__16_BITS(pcm_player); bits_in_output_frame = 32; /* frame = 2 * subframe */ break; default: snd_BUG(); return -EINVAL; } /* Serial audio interface format - for detailed explanation * see ie.: * http://www.cirrus.com/en/pubs/appNote/AN282REV1.pdf */ set__AUD_PCMOUT_FMT__ORDER__MSB_FIRST(pcm_player); /* Value FALLING of SCLK_EDGE bit in AUD_PCMOUT_FMT register that * actually means "data clocking (changing) on the falling edge" * (and we usually want this...) - STx7100 and cuts < 3.0 of * STx7109 have this bit inverted comparing to what their * datasheets claim... (specs say 1) */ set__AUD_PCMOUT_FMT__SCLK_EDGE__FALLING(pcm_player); switch (format & SND_STM_FORMAT__MASK) { case SND_STM_FORMAT__I2S: snd_stm_printd(1, "- I2S\n"); set__AUD_PCMOUT_FMT__ALIGN__LEFT(pcm_player); set__AUD_PCMOUT_FMT__PADDING__1_CYCLE_DELAY(pcm_player); lr_pol = value__AUD_PCMOUT_FMT__LR_POL__LEFT_LOW(pcm_player); break; case SND_STM_FORMAT__LEFT_JUSTIFIED: snd_stm_printd(1, "- left justified\n"); set__AUD_PCMOUT_FMT__ALIGN__LEFT(pcm_player); set__AUD_PCMOUT_FMT__PADDING__NO_DELAY(pcm_player); lr_pol = value__AUD_PCMOUT_FMT__LR_POL__LEFT_HIGH(pcm_player); break; case SND_STM_FORMAT__RIGHT_JUSTIFIED: snd_stm_printd(1, "- right justified\n"); set__AUD_PCMOUT_FMT__ALIGN__RIGHT(pcm_player); set__AUD_PCMOUT_FMT__PADDING__NO_DELAY(pcm_player); lr_pol = value__AUD_PCMOUT_FMT__LR_POL__LEFT_HIGH(pcm_player); break; default: snd_BUG(); return -EINVAL; } /* Configure PCM player frequency divider * * Fdacclk Fs * oversampling * divider = ----------- = ------------------------------- = * 2 * Fsclk 2 * Fs * bits_in_output_frame * * oversampling * = -------------------------- * 2 * bits_in_output_frame * where: * - Fdacclk - frequency of DAC clock signal, known also as PCMCLK, * MCLK (master clock), "system clock" etc. * - Fsclk - frequency of SCLK (serial clock) aka BICK (bit clock) * - Fs - sampling rate (frequency) * - bits_in_output_frame - number of bits in output signal _frame_ * (32 or 64, depending on NBIT field of FMT register) */ set__AUD_PCMOUT_CTRL__CLK_DIV(pcm_player, oversampling / (2 * bits_in_output_frame)); /* Configure data memory format & NSAMPLE interrupt */ switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: /* One data word contains two samples */ set__AUD_PCMOUT_CTRL__MEM_FMT__16_BITS_16_BITS(pcm_player); /* Workaround for a problem with L/R channels swap in case of * 16/16 memory model: PCM player expects left channel data in * word's upper two bytes, but due to little endianess * character of our memory there is right channel data there; * the workaround is to invert L/R signal, however it is * cheating, because in such case channel phases are shifted * by one sample... * (ask me for more details if above is not clear ;-) * TODO this somehow better... */ set__AUD_PCMOUT_FMT__LR_POL(pcm_player, !lr_pol); /* One word of data is two samples (two channels...) */ set__AUD_PCMOUT_CTRL__NSAMPLE(pcm_player, runtime->period_size * runtime->channels / 2); break; case SNDRV_PCM_FORMAT_S32_LE: /* Actually "16 bits/0 bits" means "32/28/24/20/18/16 bits * on the left than zeros (if less than 32 bites)"... ;-) */ set__AUD_PCMOUT_CTRL__MEM_FMT__16_BITS_0_BITS(pcm_player); /* In x/0 bits memory mode there is no problem with * L/R polarity */ set__AUD_PCMOUT_FMT__LR_POL(pcm_player, lr_pol); /* One word of data is one sample, so period size * times channels */ set__AUD_PCMOUT_CTRL__NSAMPLE(pcm_player, runtime->period_size * runtime->channels); break; default: snd_BUG(); return -EINVAL; } /* Number of channels... */ BUG_ON(runtime->channels % 2 != 0); BUG_ON(runtime->channels < 2); BUG_ON(runtime->channels > 10); set__AUD_PCMOUT_FMT__NUM_CH(pcm_player, runtime->channels / 2); return 0; } static int snd_stm_pcm_player_start(struct snd_pcm_substream *substream) { int result; struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); snd_stm_printd(1, "snd_stm_pcm_player_start(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); /* Un-reset PCM player */ set__AUD_PCMOUT_RST__SRSTP__RUNNING(pcm_player); /* Launch FDMA transfer */ result = dma_xfer_list(pcm_player->fdma_channel, &pcm_player->fdma_params); if (result != 0) { snd_stm_printe("Can't launch FDMA transfer for player '%s'!\n", dev_name(pcm_player->device)); clk_disable(pcm_player->clock); return -EINVAL; } while (dma_get_status(pcm_player->fdma_channel) != DMA_CHANNEL_STATUS_RUNNING) udelay(5); /* Enable player interrupts (and clear possible stalled ones) */ enable_irq(pcm_player->irq); set__AUD_PCMOUT_ITS_CLR__NSAMPLE__CLEAR(pcm_player); set__AUD_PCMOUT_IT_EN_SET__NSAMPLE__SET(pcm_player); set__AUD_PCMOUT_ITS_CLR__UNF__CLEAR(pcm_player); set__AUD_PCMOUT_IT_EN_SET__UNF__SET(pcm_player); /* Launch the player */ set__AUD_PCMOUT_CTRL__MODE__PCM(pcm_player); /* Wake up & unmute DAC */ if (pcm_player->conv_group) { snd_stm_conv_enable(pcm_player->conv_group, 0, substream->runtime->channels - 1); snd_stm_conv_unmute(pcm_player->conv_group); } return 0; }