static snd_pcm_uframes_t snd_stm_pcm_player_pointer(struct snd_pcm_substream *substream) { struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int residue, hwptr; snd_pcm_uframes_t pointer; snd_stm_printd(2, "snd_stm_pcm_player_pointer(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); BUG_ON(!runtime); residue = get_dma_residue(pcm_player->fdma_channel); hwptr = (runtime->dma_bytes - residue) % runtime->dma_bytes; pointer = bytes_to_frames(runtime, hwptr); snd_stm_printd(2, "FDMA residue value is %i and buffer size is %u" " bytes...\n", residue, runtime->dma_bytes); snd_stm_printd(2, "... so HW pointer in frames is %lu (0x%lx)!\n", pointer, pointer); return pointer; }
static int snd_stm_conv_i2sspdif_disable(struct snd_stm_conv_i2sspdif *conv_i2sspdif) { snd_stm_printd(1, "snd_stm_conv_i2sspdif_disable(conv_i2sspdif=%p)\n", conv_i2sspdif); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); BUG_ON(!conv_i2sspdif->enabled); if (snd_stm_conv_i2sspdif_iec958_set(conv_i2sspdif, &snd_stm_conv_i2sspdif_iec958_zeroed) != 0) snd_stm_printe("WARNING! Failed to clear channel status " "registers!\n"); set__AUD_SPDIFPC_CFG(conv_i2sspdif, mask__AUD_SPDIFPC_CFG__DEVICE_EN__DISABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__SW_RESET__RESET(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__FIFO_EN__DISABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__REQ_ACK_EN__DISABLED(conv_i2sspdif)); set__AUD_SPDIFPC_CTRL(conv_i2sspdif, mask__AUD_SPDIFPC_CTRL__OPERATION__OFF(conv_i2sspdif)); conv_i2sspdif->enabled = 0; return 0; }
static int snd_stm_conv_i2sspdif_disconnect(struct snd_device *snd_device) { struct snd_stm_conv_i2sspdif *conv_i2sspdif = snd_device->device_data; snd_stm_printd(1, "%s(snd_device=0x%p)\n", __func__, snd_device); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); BUG_ON(conv_i2sspdif->enabled); /* Remove procfs entry */ snd_stm_info_unregister(conv_i2sspdif->proc_entry); /* Power done mode, just to be sure :-) */ set__AUD_SPDIFPC_CFG(conv_i2sspdif, mask__AUD_SPDIFPC_CFG__DEVICE_EN__DISABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__SW_RESET__RESET(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__FIFO_EN__DISABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__REQ_ACK_EN__DISABLED(conv_i2sspdif)); set__AUD_SPDIFPC_CTRL(conv_i2sspdif, mask__AUD_SPDIFPC_CTRL__OPERATION__OFF(conv_i2sspdif)); return 0; }
static int snd_stm_conv_dac_mem_get_oversampling(void *priv) { snd_stm_printd(1, "snd_stm_conv_dac_mem_get_oversampling(priv=%p)\n", priv); return 256; }
static int snd_stm_pcm_player_hw_free(struct snd_pcm_substream *substream) { struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; snd_stm_printd(1, "snd_stm_pcm_player_hw_free(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); BUG_ON(!runtime); /* This callback may be called more than once... */ if (snd_stm_buffer_is_allocated(pcm_player->buffer)) { /* Let the FDMA stop */ dma_wait_for_completion(pcm_player->fdma_channel); /* Free buffer */ snd_stm_buffer_free(pcm_player->buffer); /* Free FDMA parameters & configuration */ dma_params_free(&pcm_player->fdma_params); dma_req_free(pcm_player->fdma_channel, pcm_player->fdma_request); } return 0; }
static int snd_stm_conv_dac_sc_get_oversampling(void *priv) { snd_stm_printd(1, "snd_stm_conv_dac_sc_get_oversampling(priv=%p)\n", priv); return OVERSAMPLING; }
static irqreturn_t snd_stm_pcm_player_irq_handler(int irq, void *dev_id) { irqreturn_t result = IRQ_NONE; struct snd_stm_pcm_player *pcm_player = dev_id; unsigned int status; snd_stm_printd(2, "snd_stm_pcm_player_irq_handler(irq=%d, " "dev_id=0x%p)\n", irq, dev_id); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); /* Get interrupt status & clear them immediately */ preempt_disable(); status = get__AUD_PCMOUT_ITS(pcm_player); set__AUD_PCMOUT_ITS_CLR(pcm_player, status); preempt_enable(); /* Underflow? */ if (unlikely(status & mask__AUD_PCMOUT_ITS__UNF__PENDING(pcm_player))) { snd_stm_printe("Underflow detected in PCM player '%s'!\n", dev_name(pcm_player->device)); snd_pcm_stop(pcm_player->substream, SNDRV_PCM_STATE_XRUN); result = IRQ_HANDLED; } else if (likely(status & mask__AUD_PCMOUT_ITS__NSAMPLE__PENDING(pcm_player))) { /* Period successfully played */ do { BUG_ON(!pcm_player->substream); snd_stm_printd(2, "Period elapsed ('%s')\n", dev_name(pcm_player->device)); snd_pcm_period_elapsed(pcm_player->substream); result = IRQ_HANDLED; } while (0); } /* Some alien interrupt??? */ BUG_ON(result != IRQ_HANDLED); return result; }
static int snd_stm_conv_i2sspdif_set_enabled(int enabled, void *priv) { struct snd_stm_conv_i2sspdif *conv_i2sspdif = priv; snd_stm_printd(1, "snd_stm_conv_i2sspdif_set_enabled(enabled=%d, " "priv=%p)\n", enabled, priv); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); snd_stm_printd(1, "%sabling I2S to SPDIF converter '%s'.\n", enabled ? "En" : "Dis", dev_name(conv_i2sspdif->device)); if (enabled) return snd_stm_conv_i2sspdif_enable(conv_i2sspdif); else return snd_stm_conv_i2sspdif_disable(conv_i2sspdif); }
static int snd_stm_conv_dac_sc_set_muted(int muted, void *priv) { struct snd_stm_conv_dac_sc *conv_dac_sc = priv; snd_stm_printd(1, "snd_stm_conv_dac_sc_set_muted(muted=%d, priv=%p)\n", muted, priv); BUG_ON(!conv_dac_sc); BUG_ON(!snd_stm_magic_valid(conv_dac_sc)); snd_stm_printd(1, "%suting DAC %s.\n", muted ? "M" : "Unm", conv_dac_sc->bus_id); if (muted) sysconf_write(conv_dac_sc->softmute, 1); /* MUTE */ else sysconf_write(conv_dac_sc->softmute, 0); /* NORMAL */ return 0; }
static int snd_stm_conv_i2sspdif_oversampling(struct snd_stm_conv_i2sspdif *conv_i2sspdif) { snd_stm_printd(1, "snd_stm_conv_i2sspdif_oversampling(" "conv_i2sspdif=%p)\n", conv_i2sspdif); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); return DEFAULT_OVERSAMPLING; }
static int snd_stm_conv_i2sspdif_get_oversampling(void *priv) { struct snd_stm_conv_i2sspdif *conv_i2sspdif = priv; snd_stm_printd(1, "snd_stm_conv_i2sspdif_get_oversampling(priv=%p)\n", priv); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); return snd_stm_conv_i2sspdif_oversampling(conv_i2sspdif); }
static int snd_stm_conv_i2sspdif_register(struct snd_device *snd_device) { struct snd_stm_conv_i2sspdif *conv_i2sspdif = snd_device->device_data; int i; snd_stm_printd(1, "%s(snd_device=0x%p)\n", __func__, snd_device); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); BUG_ON(conv_i2sspdif->enabled); /* Initialize converter's input & SPDIF player as disabled */ set__AUD_SPDIFPC_CFG(conv_i2sspdif, mask__AUD_SPDIFPC_CFG__DEVICE_EN__DISABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__SW_RESET__RESET(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__FIFO_EN__DISABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__REQ_ACK_EN__DISABLED(conv_i2sspdif)); set__AUD_SPDIFPC_CTRL(conv_i2sspdif, mask__AUD_SPDIFPC_CTRL__OPERATION__OFF(conv_i2sspdif)); /* Additional procfs info */ snd_stm_info_register(&conv_i2sspdif->proc_entry, dev_name(conv_i2sspdif->device), snd_stm_conv_i2sspdif_dump_registers, conv_i2sspdif); /* Create ALSA controls */ for (i = 0; i < ARRAY_SIZE(snd_stm_conv_i2sspdif_ctls); i++) { int result; snd_stm_conv_i2sspdif_ctls[i].device = snd_stm_conv_get_card_device( conv_i2sspdif->converter); snd_stm_conv_i2sspdif_ctls[i].index = conv_i2sspdif->index; result = snd_ctl_add(snd_stm_card_get(), snd_ctl_new1(&snd_stm_conv_i2sspdif_ctls[i], conv_i2sspdif)); if (result < 0) { snd_stm_printe("Failed to add I2S-SPDIF converter " "ALSA control!\n"); return result; } } return 0; }
static int snd_stm_conv_dac_sc_set_enabled(int enabled, void *priv) { struct snd_stm_conv_dac_sc *conv_dac_sc = priv; snd_stm_printd(1, "snd_stm_conv_dac_sc_set_enabled(enabled=%d, " "priv=%p)\n", enabled, priv); BUG_ON(!conv_dac_sc); BUG_ON(!snd_stm_magic_valid(conv_dac_sc)); snd_stm_printd(1, "%sabling DAC %s's digital part.\n", enabled ? "En" : "Dis", conv_dac_sc->bus_id); if (enabled) { sysconf_write(conv_dac_sc->nsb, 1); /* NORMAL */ sysconf_write(conv_dac_sc->nrst, 1); /* NORMAL */ } else { sysconf_write(conv_dac_sc->nrst, 0); /* RESET */ sysconf_write(conv_dac_sc->nsb, 0); /* POWER_DOWN */ } return 0; }
static int snd_stm_conv_dac_mem_set_muted(int muted, void *priv) { struct snd_stm_conv_dac_mem *conv_dac_mem = priv; unsigned long value; snd_stm_printd(1, "snd_stm_conv_dac_mem_set_muted(muted=%d, priv=%p)\n", muted, priv); BUG_ON(!conv_dac_mem); BUG_ON(!snd_stm_magic_valid(conv_dac_mem)); snd_stm_printd(1, "%suting DAC %s.\n", muted ? "M" : "Unm", conv_dac_mem->dev_name); value = readl(ADAC_CTRL(conv_dac_mem->base)); value &= ~SOFTMUTE__MASK; if (muted) value |= SOFTMUTE__MUTE; else value |= SOFTMUTE__NORMAL; writel(value, ADAC_CTRL(conv_dac_mem->base)); return 0; }
static int __exit snd_stm_pcm_player_disconnect(struct snd_device *snd_device) { struct snd_stm_pcm_player *pcm_player = snd_device->device_data; snd_stm_printd(1, "%s(snd_device=0x%p)\n", __func__, snd_device); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); snd_stm_clk_put(pcm_player->clock); snd_stm_info_unregister(pcm_player->proc_entry); return 0; }
static int snd_stm_conv_dac_mem_set_enabled(int enabled, void *priv) { struct snd_stm_conv_dac_mem *conv_dac_mem = priv; unsigned long value; snd_stm_printd(1, "snd_stm_conv_dac_mem_set_enabled(enabled=%d, " "priv=%p)\n", enabled, priv); BUG_ON(!conv_dac_mem); BUG_ON(!snd_stm_magic_valid(conv_dac_mem)); snd_stm_printd(1, "%sabling DAC %s's digital part.\n", enabled ? "En" : "Dis", conv_dac_mem->dev_name); value = readl(ADAC_CTRL(conv_dac_mem->base)); value &= ~(NSB__MASK | NRST__MASK); if (enabled) value |= NSB__NORMAL | NRST__NORMAL; else value |= NSB__POWER_DOWN | NRST__RESET; writel(value, ADAC_CTRL(conv_dac_mem->base)); return 0; }
static int snd_stm_conv_i2sspdif_enable(struct snd_stm_conv_i2sspdif *conv_i2sspdif) { int oversampling; struct snd_aes_iec958 iec958; snd_stm_printd(1, "snd_stm_conv_i2sspdif_enable(conv_i2sspdif=%p)\n", conv_i2sspdif); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); BUG_ON(conv_i2sspdif->enabled); oversampling = snd_stm_conv_i2sspdif_oversampling(conv_i2sspdif); BUG_ON(oversampling <= 0); BUG_ON((oversampling % 128) != 0); set__AUD_SPDIFPC_CFG(conv_i2sspdif, mask__AUD_SPDIFPC_CFG__DEVICE_EN__ENABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__SW_RESET__RUNNING(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__FIFO_EN__ENABLED(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__AUDIO_WORD_SIZE__24_BITS(conv_i2sspdif) | mask__AUD_SPDIFPC_CFG__REQ_ACK_EN__ENABLED(conv_i2sspdif)); set__AUD_SPDIFPC_CTRL(conv_i2sspdif, mask__AUD_SPDIFPC_CTRL__OPERATION__PCM(conv_i2sspdif) | mask__AUD_SPDIFPC_CTRL__ROUNDING__NO_ROUNDING(conv_i2sspdif)); set__AUD_SPDIFPC_CTRL__DIVIDER(conv_i2sspdif, oversampling / 128); /* Full channel status processing - an undocumented feature that * exists in some hardware... Normally channel status registers * provides bits for each subframe, so only for 96 frames (a half * of SPDIF block) - pathetic! ;-) Setting bit 6 of config register * enables a mode in which channel status bits in L/R subframes * are identical, and whole block is served... */ if (conv_i2sspdif->ver >= 4) set__AUD_SPDIFPC_CFG__CHA_STA_BITS__FRAME(conv_i2sspdif); spin_lock(&conv_i2sspdif->iec958_default_lock); iec958 = conv_i2sspdif->iec958_default; spin_unlock(&conv_i2sspdif->iec958_default_lock); if (snd_stm_conv_i2sspdif_iec958_set(conv_i2sspdif, &iec958) != 0) snd_stm_printe("WARNING! Can't set channel status " "registers!\n"); conv_i2sspdif->enabled = 1; return 0; }
static int snd_stm_pcm_player_release(struct snd_pcm_substream *substream) { struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); snd_stm_printd(1, "snd_stm_pcm_player_release(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); /* "Unmute" player */ set__AUD_PCMOUT_CTRL__MODE__PCM(pcm_player); return 0; }
static int snd_stm_conv_i2sspdif_ctl_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_stm_conv_i2sspdif *conv_i2sspdif = snd_kcontrol_chip(kcontrol); snd_stm_printd(1, "snd_stm_conv_i2sspdif_ctl_default_get(" "kcontrol=0x%p, ucontrol=0x%p)\n", kcontrol, ucontrol); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); spin_lock(&conv_i2sspdif->iec958_default_lock); ucontrol->value.iec958 = conv_i2sspdif->iec958_default; spin_unlock(&conv_i2sspdif->iec958_default_lock); return 0; }
static int snd_stm_pcm_player_pause(struct snd_pcm_substream *substream) { struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); snd_stm_printd(1, "snd_stm_pcm_player_pause(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); /* "Mute" player * Documentation describes this mode in a wrong way - data is _not_ * consumed in the "mute" mode, so it is actually a "pause" mode */ set__AUD_PCMOUT_CTRL__MODE__MUTE(pcm_player); return 0; }
static int snd_stm_pcm_player_trigger(struct snd_pcm_substream *substream, int command) { snd_stm_printd(1, "snd_stm_pcm_player_trigger(substream=0x%p," " command=%d)\n", substream, command); switch (command) { case SNDRV_PCM_TRIGGER_START: return snd_stm_pcm_player_start(substream); case SNDRV_PCM_TRIGGER_STOP: return snd_stm_pcm_player_stop(substream); case SNDRV_PCM_TRIGGER_PAUSE_PUSH: return snd_stm_pcm_player_pause(substream); case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: return snd_stm_pcm_player_release(substream); default: return -EINVAL; } }
static int snd_stm_pcm_player_close(struct snd_pcm_substream *substream) { struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); snd_stm_printd(1, "snd_stm_pcm_player_close(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); if (pcm_player->conv_group) { snd_stm_conv_release_group(pcm_player->conv_group); pcm_player->conv_group = NULL; } pcm_player->substream = NULL; return 0; }
static int __exit snd_stm_fli75xx_glue_remove(struct platform_device *pdev) { struct snd_stm_fli75xx_glue *fli75xx_glue = platform_get_drvdata(pdev); snd_stm_printd(0, "%s('%s')\n", __func__, dev_name(&pdev->dev)); BUG_ON(!fli75xx_glue); BUG_ON(!snd_stm_magic_valid(fli75xx_glue)); /* Remove procfs entry */ snd_stm_info_unregister(fli75xx_glue->proc_entry); /* Disable audio outputs */ snd_stm_memory_release(fli75xx_glue->mem_region, fli75xx_glue->base); snd_stm_magic_clear(fli75xx_glue); kfree(fli75xx_glue); return 0; }
static int snd_stm_pcm_player_remove(struct platform_device *pdev) { struct snd_stm_pcm_player *pcm_player = platform_get_drvdata(pdev); snd_stm_printd(1, "snd_stm_pcm_player_remove(pdev=%p)\n", pdev); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); if (pcm_player->pads) stm_pad_release(pcm_player->pads); snd_stm_conv_unregister_source(pcm_player->conv_source); snd_stm_buffer_dispose(pcm_player->buffer); snd_stm_fdma_release(pcm_player->fdma_channel); snd_stm_irq_release(pcm_player->irq, pcm_player); snd_stm_memory_release(pcm_player->mem_region, pcm_player->base); snd_stm_magic_clear(pcm_player); kfree(pcm_player); return 0; }
static int snd_stm_pcm_player_register(struct snd_device *snd_device) { struct snd_stm_pcm_player *pcm_player = snd_device->device_data; snd_stm_printd(1, "%s(snd_device=0x%p)\n", __func__, snd_device); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); /* Set reset mode */ set__AUD_PCMOUT_RST__SRSTP__RESET(pcm_player); /* TODO: well, hardcoded - shall anyone use it? * And what does it actually mean? */ if (pcm_player->ver > 5) set__AUD_PCMOUT_FMT__BACK_STALLING__DISABLED(pcm_player); set__AUD_PCMOUT_CTRL__RND__NO_ROUNDING(pcm_player); /* Get frequency synthesizer channel */ pcm_player->clock = snd_stm_clk_get(pcm_player->device, "pcm_player_clk", snd_device->card, pcm_player->info->card_device); if (!pcm_player->clock || IS_ERR(pcm_player->clock)) { snd_stm_printe("Failed to get a clock for '%s'!\n", dev_name(pcm_player->device)); return -EINVAL; } /* Registers view in ALSA's procfs */ snd_stm_info_register(&pcm_player->proc_entry, dev_name(pcm_player->device), snd_stm_pcm_player_dump_registers, pcm_player); return 0; }
static int snd_stm_pcm_player_stop(struct snd_pcm_substream *substream) { struct snd_stm_pcm_player *pcm_player = snd_pcm_substream_chip(substream); snd_stm_printd(1, "snd_stm_pcm_player_stop(substream=0x%p)\n", substream); BUG_ON(!pcm_player); BUG_ON(!snd_stm_magic_valid(pcm_player)); /* Mute & shutdown DAC */ if (pcm_player->conv_group) { snd_stm_conv_mute(pcm_player->conv_group); snd_stm_conv_disable(pcm_player->conv_group); } /* Disable interrupts */ set__AUD_PCMOUT_IT_EN_CLR__NSAMPLE__CLEAR(pcm_player); set__AUD_PCMOUT_IT_EN_CLR__UNF__CLEAR(pcm_player); disable_irq_nosync(pcm_player->irq); /* Stop PCM player */ set__AUD_PCMOUT_CTRL__MODE__OFF(pcm_player); /* Stop FDMA transfer */ dma_stop_channel(pcm_player->fdma_channel); /* Stop the clock & reset PCM player */ clk_disable(pcm_player->clock); set__AUD_PCMOUT_RST__SRSTP__RESET(pcm_player); return 0; }
static int __init snd_stm_fli75xx_init(void) { int result; snd_stm_printd(0, "%s()\n", __func__); switch (cpu_data->type) { case CPU_FLI7510: case CPU_FLI7520: case CPU_FLI7530: case CPU_FLI7540: case CPU_FLI7560: break; default: snd_stm_printe("Unsupported (non-Freeman) SOC detected!\n"); result = -EINVAL; goto error_soc_type; } result = platform_driver_register(&snd_stm_fli75xx_glue_driver); if (result != 0) { snd_stm_printe("Failed to register audio glue driver!\n"); goto error_glue_driver_register; } result = snd_stm_card_register(); if (result != 0) { snd_stm_printe("Failed to register ALSA cards!\n"); goto error_card_register; } return 0; error_card_register: platform_driver_unregister(&snd_stm_fli75xx_glue_driver); error_glue_driver_register: error_soc_type: return result; }
static int snd_stm_conv_i2sspdif_ctl_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_stm_conv_i2sspdif *conv_i2sspdif = snd_kcontrol_chip(kcontrol); int changed = 0; snd_stm_printd(1, "snd_stm_conv_i2sspdif_ctl_default_put(" "kcontrol=0x%p, ucontrol=0x%p)\n", kcontrol, ucontrol); BUG_ON(!conv_i2sspdif); BUG_ON(!snd_stm_magic_valid(conv_i2sspdif)); spin_lock(&conv_i2sspdif->iec958_default_lock); if (snd_stm_iec958_cmp(&conv_i2sspdif->iec958_default, &ucontrol->value.iec958) != 0) { conv_i2sspdif->iec958_default = ucontrol->value.iec958; changed = 1; } spin_unlock(&conv_i2sspdif->iec958_default_lock); return changed; }
static unsigned int snd_stm_conv_dac_sc_get_format(void *priv) { snd_stm_printd(1, "snd_stm_conv_dac_sc_get_format(priv=%p)\n", priv); return FORMAT; }
static int snd_stm_conv_dac_sc_probe(struct platform_device *pdev) { int result = 0; struct snd_stm_conv_dac_sc_info *info = pdev->dev.platform_data; struct snd_stm_conv_dac_sc *conv_dac_sc; struct snd_card *card = snd_stm_card_get(); snd_stm_printd(0, "%s('%s')\n", __func__, dev_name(&pdev->dev)); BUG_ON(!card); BUG_ON(!info); conv_dac_sc = kzalloc(sizeof(*conv_dac_sc), GFP_KERNEL); if (!conv_dac_sc) { snd_stm_printe("Can't allocate memory " "for a device description!\n"); result = -ENOMEM; goto error_alloc; } snd_stm_magic_set(conv_dac_sc); conv_dac_sc->bus_id = dev_name(&pdev->dev); /* Get resources */ conv_dac_sc->nrst = sysconf_claim(info->nrst.group, info->nrst.num, info->nrst.lsb, info->nrst.msb, "NRST"); BUG_ON(!conv_dac_sc->nrst); conv_dac_sc->mode = sysconf_claim(info->mode.group, info->mode.num, info->mode.lsb, info->mode.msb, "MODE"); BUG_ON(!conv_dac_sc->mode); conv_dac_sc->nsb = sysconf_claim(info->nsb.group, info->nsb.num, info->nsb.lsb, info->nsb.msb, "NSB"); BUG_ON(!conv_dac_sc->nsb); conv_dac_sc->softmute = sysconf_claim(info->softmute.group, info->softmute.num, info->softmute.lsb, info->softmute.msb, "SOFTMUTE"); BUG_ON(!conv_dac_sc->softmute); conv_dac_sc->pdana = sysconf_claim(info->pdana.group, info->pdana.num, info->pdana.lsb, info->pdana.msb, "PDANA"); BUG_ON(!conv_dac_sc->pdana); conv_dac_sc->pndbg = sysconf_claim(info->pndbg.group, info->pndbg.num, info->pndbg.lsb, info->pndbg.msb, "PNDBG"); BUG_ON(!conv_dac_sc->pndbg); /* Get connections */ BUG_ON(!info->source_bus_id); snd_stm_printd(0, "This DAC is attached to PCM player '%s'.\n", info->source_bus_id); conv_dac_sc->converter = snd_stm_conv_register_converter( "Analog Output", &snd_stm_conv_dac_sc_ops, conv_dac_sc, &platform_bus_type, info->source_bus_id, info->channel_from, info->channel_to, NULL); if (!conv_dac_sc->converter) { snd_stm_printe("Can't attach to PCM player!\n"); goto error_attach; } /* Create ALSA lowlevel device*/ result = snd_device_new(card, SNDRV_DEV_LOWLEVEL, conv_dac_sc, &snd_stm_conv_dac_sc_snd_device_ops); if (result < 0) { snd_stm_printe("ALSA low level device creation failed!\n"); goto error_device; } /* Done now */ platform_set_drvdata(pdev, conv_dac_sc); return 0; error_device: error_attach: snd_stm_magic_clear(conv_dac_sc); kfree(conv_dac_sc); error_alloc: return result; }