static int mv88fx_i2s_hw_free(struct snd_pcm_substream *stream, struct snd_soc_dai *dai) { mv88fx_snd_debug(""); return 0; }
static int mv88fx_i2s_resume(struct snd_soc_dai *cpu_dai) { struct mv88fx_snd_chip *chip = mv88fx_pcm_snd_chip[cpu_dai->id]; mv88fx_snd_debug(""); if (!cpu_dai->active) return 0; mv88fx_i2_hw_init(chip->port); spin_lock(&chip->reg_lock); mv88fx_snd_writel(chip->base, MV_AUDIO_INT_CAUSE_REG(chip->port), 0xffffffff); /* restore registers */ mv88fx_snd_writel(chip->base, MV_AUDIO_RECORD_CTRL_REG(chip->port), mv88fx_i2s_info[chip->port].capture_cntrl_reg); mv88fx_snd_writel(chip->base, MV_AUDIO_PLAYBACK_CTRL_REG(chip->port), mv88fx_i2s_info[chip->port].playback_cntrl_reg); /* enable interrupts */ mv88fx_snd_writel(chip->base, MV_AUDIO_INT_MASK_REG(chip->port), mv88fx_i2s_info[chip->port].irq_mask); spin_unlock(&chip->reg_lock); return 0; }
static int mv88fx_snd_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol); struct mv88fx_snd_stream *pbstream = &chip->stream[SNDRV_PCM_STREAM_PLAYBACK]; int port = chip->port; int i, change = 0, word; unsigned int val; mv88fx_snd_debug(""); port = port; val = 0; spin_lock_irq(&chip->reg_lock); for (word = 0; word < 4; word++) { for (i = 0; i < 4; i++) { pbstream->spdif_status[word] |= ucontrol->value.iec958.status[word + i] << (i * 8); } mv88fx_snd_writel(chip->base, MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(port, word), pbstream->spdif_status[word]); mv88fx_snd_writel(chip->base, MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(port, word), pbstream->spdif_status[word]); } if (pbstream->spdif_status[0] & IEC958_AES0_NONAUDIO) chip->pcm_mode = NON_PCM; spin_unlock_irq(&chip->reg_lock); return change; }
static int mv88fx_snd_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol); struct mv88fx_snd_stream *pbstream = &chip->stream[SNDRV_PCM_STREAM_PLAYBACK]; int port = chip->port; int i, word; mv88fx_snd_debug(""); port = port; spin_lock_irq(&chip->reg_lock); for (word = 0; word < 4; word++) { pbstream->spdif_status[word] = mv88fx_snd_readl(chip->base, MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(port, word)); for (i = 0; i < 4; i++) ucontrol->value.iec958.status[word + i] = (pbstream->spdif_status[word] >> (i * 8)) & 0xff; } spin_unlock_irq(&chip->reg_lock); return 0; }
static int mv88fx_i2s_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { mv88fx_snd_debug(""); return 0; }
static int mv88fx_i2s_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { mv88fx_snd_debug(""); return 0; }
int mv88fx_snd_mixer_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { unsigned int val, *rec; struct mv88fx_snd_mixer_enum *mixer_enum = (struct mv88fx_snd_mixer_enum *)kcontrol->private_value; int i; mv88fx_snd_debug(""); rec = (unsigned int *)mixer_enum->rec; val = ucontrol->value.enumerated.item[0]; if (val < 0) val = 0; if (val > mixer_enum->count) val = mixer_enum->count; for (i = 0; i < mixer_enum->count; i++) { if (val == i) { *rec = (unsigned int)mixer_enum->values[i]; break; } } return 0; }
int mv88fx_snd_hw_init(struct mv88fx_snd_chip *chip) { /* Clear ints */ cs42l51_init(); mv88fx_snd_writel(chip, MV_AUDIO_INT_CAUSE_REG, 0xffffffff); mv88fx_snd_writel(chip, MV_AUDIO_INT_MASK_REG, 0); mv88fx_snd_writel(chip, MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG, 0); if (MV_OK != mvAudioInit()) return EIO; /* Disable all playback/recording */ mv88fx_snd_bitreset(chip, MV_AUDIO_PLAYBACK_CTRL_REG, (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK)); mv88fx_snd_bitreset(chip, MV_AUDIO_RECORD_CTRL_REG, (ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK)); if (MV_OK != mvSPDIFRecordTclockSet()) { mv88fx_snd_debug("Marvell ALSA driver ERR. mvSPDIFRecordTclockSet failed\n"); return -ENOMEM; } return 0; }
static int mv88fx_i2_hw_init(int port) { mv88fx_snd_debug(""); mv88fx_snd_writel(mv88fx_i2s_info[port].base, MV_AUDIO_INT_CAUSE_REG(port), 0xffffffff); mv88fx_snd_writel(mv88fx_i2s_info[port].base, MV_AUDIO_INT_MASK_REG(port), 0); mv88fx_snd_writel(mv88fx_i2s_info[port].base, MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG(port), 0); // if (MV_OK != mvAudioInit(mv88fx_i2s_info.port)) // return -EIO; mvSysAudioInit(port); /* Disable all playback/recording */ mv88fx_snd_bitreset(mv88fx_i2s_info[port].base, MV_AUDIO_PLAYBACK_CTRL_REG(port), (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK)); mv88fx_snd_bitreset(mv88fx_i2s_info[port].base, MV_AUDIO_RECORD_CTRL_REG(port), (ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK)); if (MV_OK != mvSPDIFRecordTclockSet(port)) { mv88fx_snd_error("mvSPDIFRecordTclockSet failed"); return -ENOMEM; } return 0; }
static int mv88fx_i2s_probe(struct platform_device *pdev) { int ret; struct snd_soc_dai_driver *soc_dai_driver; if (pdev->id) soc_dai_driver = &mv88fx_i2s_dai1; else soc_dai_driver = &mv88fx_i2s_dai0; mv88fx_snd_debug(">%s\n",__FUNCTION__); //soc_dai->id = pdev->id; //soc_dai->dev = &pdev->dev; mv88fx_snd_debug("pdev->dev = 0x%p\n pdev->id=%d",&pdev->dev, pdev->id); ret = snd_soc_register_dai(&pdev->dev, soc_dai_driver); mv88fx_snd_debug("ret=%d",ret); return ret; }
static int mv88fx_snd_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { mv88fx_snd_debug(""); uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0; }
static int __init mv88fx_snd_init(void) { if (!machine_is_dove_rd_avng() && !machine_is_dove_avng_v3()) return -ENODEV; mv88fx_snd_debug(""); return platform_driver_register(&mv88fx_snd_driver); }
static int mv88fx_initalize_machine_data(struct platform_device *pdev) { struct resource *r = NULL; int err = 0; mv88fx_snd_debug(""); mv88fx_machine_data.port = pdev->id; mv88fx_machine_data.pdata = (struct orion_i2s_platform_data *)pdev->dev.platform_data; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { mv88fx_snd_error(""); err = -ENXIO; goto error; } r = request_mem_region(r->start, SZ_16K, DRIVER_NAME); if (!r) { mv88fx_snd_error(""); err = -EBUSY; goto error; } mv88fx_machine_data.res = r; mv88fx_machine_data.base = ioremap(r->start, SZ_16K); if (!mv88fx_machine_data.base) { mv88fx_snd_error("ioremap failed"); err = -ENOMEM; goto error; } mv88fx_machine_data.base -= AUDIO_REG_BASE(mv88fx_machine_data.port); mv88fx_machine_data.irq = platform_get_irq(pdev, 0); if (mv88fx_machine_data.irq == NO_IRQ) { mv88fx_snd_error(""); err = -ENXIO; goto error; } #if defined(CONFIG_HAVE_CLK) mv88fx_machine_data.clk = clk_get(&pdev->dev, NULL); if (IS_ERR(mv88fx_machine_data.clk)) dev_notice(&pdev->dev, "cannot get clkdev\n"); else clk_enable(mv88fx_machine_data.clk); #endif return 0; error: if (mv88fx_machine_data.base) { iounmap(mv88fx_machine_data.base); mv88fx_machine_data.base = NULL; } release_mem_region(mv88fx_machine_data.res->start, SZ_16K); return err; }
static int __init mv88fx_snd_init(void) { #ifdef CONFIG_ARCH_DOVE if (!machine_is_dove_db() && !machine_is_dove_db_z0()) return -ENODEV; #endif mv88fx_snd_debug(""); return platform_driver_register(&mv88fx_snd_driver); }
static int mv88fx_machine_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; unsigned int clk = 0; int ret = 0; unsigned int format; // printk("%s\n",__func__); /* set codec DAI configuration */ mv88fx_snd_debug("mv88fx_machine_hifi_hw_params"); switch (params_rate(params)) { case 44100: clk = 11289600; break; case 48000: clk = 12288000; break; case 96000: clk = 24576000; break; } format = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF; ret = codec_dai->ops->set_fmt(codec_dai, format); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = cpu_dai->ops->set_fmt(cpu_dai, format); if (ret < 0) return ret; /* cpu clock is the mv88fx master clock sent to codec */ ret = cpu_dai->ops->set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN); if (ret < 0) return ret; /* codec system clock is supplied by codec pll1*/ ret = codec_dai->ops->set_pll(codec_dai, RT5630_PLL1_FROM_MCLK, clk,clk*2); if (ret < 0) return ret; /* codec system clock is supplied by mv88fx*/ ret = codec_dai->ops->set_sysclk(codec_dai, 0, clk*2, SND_SOC_CLOCK_IN); if (ret < 0) return ret; return 0; }
static int mv88fx_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip(substream); mv88fx_snd_debug(""); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) return mv88fx_i2s_snd_hw_capture_set(chip, substream); else return mv88fx_i2s_snd_hw_playback_set(chip, substream); }
static int mv88fx_snd_probe(struct platform_device *pdev) { int ret = 0; mv88fx_snd_debug(""); if (mv88fx_initalize_machine_data(pdev) != 0) goto error; mv88fx_machine_data.snd_dev = platform_device_alloc("soc-audio", 1); if (!mv88fx_machine_data.snd_dev) { ret = -ENOMEM; goto error; } platform_set_drvdata(mv88fx_machine_data.snd_dev, &mv88fx_snd_devdata); mv88fx_snd_devdata.dev = &mv88fx_machine_data.snd_dev->dev; mv88fx_machine_data.snd_dev->dev.platform_data = &mv88fx_machine_data; ret = platform_device_add(mv88fx_machine_data.snd_dev); mv88fx_snd_debug(""); return 0; error: mv88fx_snd_error(""); #if defined(CONFIG_HAVE_CLK) if (!IS_ERR(mv88fx_machine_data.clk)) { clk_disable(mv88fx_machine_data.clk); clk_put(mv88fx_machine_data.clk); } #endif if (mv88fx_machine_data.snd_dev) platform_device_unregister(mv88fx_machine_data.snd_dev); return ret; }
static int mv88fx_cs42l51_init(struct snd_soc_codec *codec) { mv88fx_snd_debug(""); #ifdef CONFIG_MACH_DOVE_RD_AVNG /* Default Gain */ snd_soc_update_bits(codec, CS42L51_REG_DAC_OUTPUT_CTRL, 0xE0, 0xE0); #endif mv88fx_snd_ctrl_new(codec->card); return 0; }
static int mv88fx_snd_probe(struct platform_device *pdev) { int ret = 0; mv88fx_snd_debug("mv88fx_snd_probe"); if (mv88fx_initalize_machine_data(pdev) != 0) goto error; mv88fx_machine_data.snd_dev = platform_device_alloc("soc-audio", 0); if (!mv88fx_machine_data.snd_dev) { ret = -ENOMEM; goto error; } if(machine_is_dove_avng_v3()) { platform_set_drvdata(mv88fx_machine_data.snd_dev, &mv88fx_snd_devdata_avd1_v3); mv88fx_snd_devdata_avd1_v3.dev = &mv88fx_machine_data.snd_dev->dev; } else { platform_set_drvdata(mv88fx_machine_data.snd_dev, &mv88fx_snd_devdata); mv88fx_snd_devdata.dev = &mv88fx_machine_data.snd_dev->dev; } mv88fx_machine_data.snd_dev->dev.platform_data = &mv88fx_machine_data; ret = platform_device_add(mv88fx_machine_data.snd_dev); if(ret) { platform_device_put(mv88fx_machine_data.snd_dev); } ret = platform_device_register(&rt5630_codec_dev); if(ret) platform_device_unregister(&rt5630_codec_dev); return ret; error: mv88fx_snd_error(""); #if defined(CONFIG_HAVE_CLK) if (!IS_ERR(mv88fx_machine_data.clk)) { clk_disable(mv88fx_machine_data.clk); clk_put(mv88fx_machine_data.clk); } #endif if (mv88fx_machine_data.snd_dev) platform_device_unregister(mv88fx_machine_data.snd_dev); return ret; }
static int mv88fx_snd_remove(struct platform_device *dev) { mv88fx_snd_debug(""); #if defined(CONFIG_HAVE_CLK) if (!IS_ERR(mv88fx_machine_data.clk)) { clk_disable(mv88fx_machine_data.clk); clk_put(mv88fx_machine_data.clk); } #endif mv88fx_machine_data.snd_dev->dev.platform_data = NULL; platform_device_unregister(mv88fx_machine_data.snd_dev); release_mem_region(mv88fx_machine_data.res->start, SZ_16K); return 0; }
static int mv88fx_i2s_dai_probe( struct snd_soc_dai *dai ) { struct platform_device *pdev; struct snd_soc_card *card = dai->card; pdev = container_of(card->dev, struct platform_device, dev); struct mv88fx_snd_machine_data *machine_data = pdev->dev.platform_data; mv88fx_snd_debug(">%s machine_data=0x%p", __FUNCTION__, machine_data); mv88fx_i2s_info[machine_data->port].base = machine_data->base; mv88fx_i2_hw_init(machine_data->port); return 0; }
int mv88fx_snd_mixer_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct mv88fx_snd_mixer_enum *mixer_enum = (struct mv88fx_snd_mixer_enum *)kcontrol->private_value; mv88fx_snd_debug(""); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = mixer_enum->count; if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; strcpy(uinfo->value.enumerated.name, mixer_enum->names[uinfo->value.enumerated.item]); return 0; }
int mv88fx_snd_mixer_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct mv88fx_snd_mixer_enum *mixer_enum = (struct mv88fx_snd_mixer_enum *)kcontrol->private_value; int i; unsigned int val; mv88fx_snd_debug(""); val = *(unsigned int *)mixer_enum->rec; for (i = 0; i < mixer_enum->count; i++) { if (val == (unsigned int)mixer_enum->values[i]) { ucontrol->value.enumerated.item[0] = i; break; } } return 0; }
static int mv88fx_i2s_suspend(struct snd_soc_dai *cpu_dai) { struct mv88fx_snd_chip *chip = mv88fx_pcm_snd_chip[cpu_dai->id]; mv88fx_snd_debug(""); if (!cpu_dai->active) return 0; spin_lock(&chip->reg_lock); /* save registers */ mv88fx_i2s_info[chip->port].irq_mask = mv88fx_snd_readl(chip->base, MV_AUDIO_INT_MASK_REG(chip->port)); mv88fx_i2s_info[chip->port].capture_cntrl_reg = mv88fx_snd_readl(chip->base, MV_AUDIO_RECORD_CTRL_REG(chip->port)); mv88fx_i2s_info[chip->port].playback_cntrl_reg = mv88fx_snd_readl(chip->base, MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)); /* clear all interrupts */ mv88fx_snd_writel(chip->base, MV_AUDIO_INT_CAUSE_REG(chip->port), 0xffffffff); /* disable all interrupts */ mv88fx_snd_writel(chip->base, MV_AUDIO_INT_MASK_REG(chip->port), 0); /* pause dma */ mv88fx_snd_bitset(chip->base, MV_AUDIO_RECORD_CTRL_REG(chip->port), ARCR_RECORD_PAUSE_MASK); mv88fx_snd_bitset(chip->base, MV_AUDIO_PLAYBACK_CTRL_REG(chip->port), APCR_PLAY_PAUSE_MASK); spin_unlock(&chip->reg_lock); return 0; }
int mv88fx_snd_hw_capture_set(struct mv88fx_snd_chip *chip) { struct mv88fx_snd_stream *audio_stream = chip->stream[CAPTURE]; struct snd_pcm_substream *substream = audio_stream->substream; struct snd_pcm_runtime *runtime = substream->runtime; MV_AUDIO_RECORD_CTRL pcm_rec_ctrl; MV_I2S_RECORD_CTRL i2s_rec_ctrl; MV_AUDIO_FREQ_DATA dco_ctrl; dco_ctrl.offset = chip->dco_ctrl_offst; switch(audio_stream->rate) { case 44100: dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH; break; case 48000: dco_ctrl.baseFreq = AUDIO_FREQ_48KH; break; case 96000: dco_ctrl.baseFreq = AUDIO_FREQ_96KH; break; default: snd_printk("Requested rate %d is not supported\n", runtime->rate); return -1; } pcm_rec_ctrl.burst = (chip->burst == 128)?AUDIO_128BYTE_BURST: AUDIO_32BYTE_BURST; if (audio_stream->format == SAMPLE_16IN16) { pcm_rec_ctrl.sampleSize = SAMPLE_16BIT; } else if (audio_stream->format == SAMPLE_24IN32) { pcm_rec_ctrl.sampleSize = SAMPLE_24BIT; } else if (audio_stream->format == SAMPLE_32IN32) { pcm_rec_ctrl.sampleSize = SAMPLE_32BIT; } else { snd_printk("Requested format %d is not supported\n", runtime->format); return -1; } pcm_rec_ctrl.mono = (audio_stream->stereo) ? MV_FALSE : MV_TRUE; if (pcm_rec_ctrl.mono) { switch (audio_stream->mono_mode) { case MONO_LEFT: pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO; break; default: case MONO_RIGHT: pcm_rec_ctrl.monoChannel = AUDIO_REC_RIGHT_MONO; break; } } else pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO; pcm_rec_ctrl.bufferPhyBase = audio_stream->dma_addr; pcm_rec_ctrl.bufferSize = audio_stream->dma_size; pcm_rec_ctrl.intByteCount = audio_stream->period_size; /* I2S record streem stuff */ i2s_rec_ctrl.sample = pcm_rec_ctrl.sampleSize; i2s_rec_ctrl.justf = I2S_JUSTIFIED; spin_lock_irq(&chip->reg_lock); /* set clock only if record is not enabled*/ if (!(mv88fx_snd_readl(chip, MV_AUDIO_RECORD_CTRL_REG) & (ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK))) { if (MV_OK != mvAudioDCOCtrlSet(&dco_ctrl)) { snd_printk("Failed to initialize DCO clock control.\n"); return -1; } } if (MV_OK != mvAudioRecordControlSet(&pcm_rec_ctrl)) { snd_printk("Failed to initialize PCM record control.\n"); return -1; } if (MV_OK != mvI2SRecordCntrlSet(&i2s_rec_ctrl)) { snd_printk("Failed to initialize I2S record control.\n"); return -1; } spin_unlock_irq(&chip->reg_lock); #if 0 mv88fx_snd_debug("pcm_rec_ctrl.bufferSize=0x%x\n",(int)pcm_rec_ctrl.bufferSize); mv88fx_snd_debug("pcm_rec_ctrl.intByteCount=0x%x\n",(int)pcm_rec_ctrl.intByteCount); mv88fx_snd_debug("runtime->xfer_align=%d\n",(int)runtime->xfer_align); mv88fx_snd_debug("runtime->format=%d\n",runtime->format); mv88fx_snd_debug("runtime->channels=%d\n",runtime->channels); mv88fx_snd_debug("runtime->rate=%d\n",runtime->rate); mv88fx_snd_debug("runtime->dma_addr=0x%x\n",runtime->dma_addr); mv88fx_snd_debug("runtime->dma_area=0x%x\n",(unsigned int)runtime->dma_area); mv88fx_snd_debug("runtime->frame_bits=0x%x\n",runtime->frame_bits); mv88fx_snd_debug("runtime->period_size=0x%x\n", (unsigned int)runtime->period_size); mv88fx_snd_debug("runtime->buffer_size=0x%x\n", (unsigned int)runtime->buffer_size); mv88fx_snd_debug("bufferPhyBase=0x%x\n",runtime->dma_addr); #endif return 0; }
static void __exit mv88fx_snd_exit(void) { mv88fx_snd_debug(""); platform_driver_unregister(&mv88fx_snd_driver); }
int mv88fx_snd_hw_playback_set(struct mv88fx_snd_chip *chip) { struct mv88fx_snd_stream *audio_stream = chip->stream[PLAYBACK]; struct snd_pcm_substream *substream = audio_stream->substream; struct snd_pcm_runtime *runtime = substream->runtime; MV_AUDIO_PLAYBACK_CTRL pcm_play_ctrl; MV_I2S_PLAYBACK_CTRL i2s_play_ctrl; MV_SPDIF_PLAYBACK_CTRL spdif_play_ctrl; MV_AUDIO_FREQ_DATA dco_ctrl; dco_ctrl.offset = chip->dco_ctrl_offst; switch(audio_stream->rate) { case 44100: dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH; break; case 48000: dco_ctrl.baseFreq = AUDIO_FREQ_48KH; break; case 96000: dco_ctrl.baseFreq = AUDIO_FREQ_96KH; break; default: snd_printk("Requested rate %d is not supported\n", runtime->rate); return -1; } pcm_play_ctrl.burst = (chip->burst == 128)?AUDIO_128BYTE_BURST: AUDIO_32BYTE_BURST; pcm_play_ctrl.loopBack = chip->loopback; if (audio_stream->stereo) { pcm_play_ctrl.monoMode = AUDIO_PLAY_MONO_OFF; } else { switch (audio_stream->mono_mode) { case MONO_LEFT: pcm_play_ctrl.monoMode = AUDIO_PLAY_LEFT_MONO; break; case MONO_RIGHT: pcm_play_ctrl.monoMode = AUDIO_PLAY_RIGHT_MONO; break; case MONO_BOTH: default: pcm_play_ctrl.monoMode = AUDIO_PLAY_BOTH_MONO; break; } } if (audio_stream->format == SAMPLE_16IN16) { pcm_play_ctrl.sampleSize = SAMPLE_16BIT; i2s_play_ctrl.sampleSize = SAMPLE_16BIT; } else if (audio_stream->format == SAMPLE_24IN32) { pcm_play_ctrl.sampleSize = SAMPLE_24BIT; i2s_play_ctrl.sampleSize = SAMPLE_24BIT; } else if (audio_stream->format == SAMPLE_32IN32) { pcm_play_ctrl.sampleSize = SAMPLE_32BIT; i2s_play_ctrl.sampleSize = SAMPLE_32BIT; } else { snd_printk("Requested format %d is not supported\n", runtime->format); return -1; } /* buffer and period sizes in frame */ pcm_play_ctrl.bufferPhyBase = audio_stream->dma_addr; pcm_play_ctrl.bufferSize = audio_stream->dma_size; pcm_play_ctrl.intByteCount = audio_stream->period_size; /* I2S playback streem stuff */ /*i2s_play_ctrl.sampleSize = pcm_play_ctrl.sampleSize;*/ i2s_play_ctrl.justification = I2S_JUSTIFIED; i2s_play_ctrl.sendLastFrame = 0; spdif_play_ctrl.nonPcm = MV_FALSE; spdif_play_ctrl.validity = chip->ch_stat_valid; if (audio_stream->stat_mem) { spdif_play_ctrl.userBitsFromMemory = MV_TRUE; spdif_play_ctrl.validityFromMemory = MV_TRUE; spdif_play_ctrl.blockStartInternally = MV_FALSE; } else { spdif_play_ctrl.userBitsFromMemory = MV_FALSE; spdif_play_ctrl.validityFromMemory = MV_FALSE; spdif_play_ctrl.blockStartInternally = MV_TRUE; } /* If this is non-PCM sound, mute I2S channel */ spin_lock_irq(&chip->reg_lock); if (!(mv88fx_snd_readl(chip, MV_AUDIO_PLAYBACK_CTRL_REG) & (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) { if (MV_OK != mvAudioDCOCtrlSet(&dco_ctrl)) { snd_printk("Failed to initialize DCO clock control.\n"); return -1; } } if (audio_stream->clock_src == DCO_CLOCK) while ((mv88fx_snd_readl(chip, MV_AUDIO_SPCR_DCO_STATUS_REG) & ASDSR_DCO_LOCK_MASK) == 0); else if (audio_stream->clock_src == SPCR_CLOCK) while ((mv88fx_snd_readl(chip, MV_AUDIO_SPCR_DCO_STATUS_REG) & ASDSR_SPCR_LOCK_MASK) == 0); if (MV_OK != mvAudioPlaybackControlSet(&pcm_play_ctrl)) { snd_printk("Failed to initialize PCM playback control.\n"); return -1; } if (MV_OK != mvI2SPlaybackCtrlSet(&i2s_play_ctrl)) { snd_printk("Failed to initialize I2S playback control.\n"); return -1; } mvSPDIFPlaybackCtrlSet(&spdif_play_ctrl); spin_unlock_irq(&chip->reg_lock); #if 0 mv88fx_snd_debug("runtime->xfer_align=%d\n",(int)runtime->xfer_align); mv88fx_snd_debug("runtime->format=%d\n",runtime->format); mv88fx_snd_debug("runtime->channels=%d\n",runtime->channels); mv88fx_snd_debug("runtime->rate=%d\n",runtime->rate); mv88fx_snd_debug("runtime->dma_addr=0x%x\n",runtime->dma_addr); mv88fx_snd_debug("runtime->dma_area=0x%x\n",(unsigned int)runtime->dma_area); mv88fx_snd_debug("runtime->frame_bits=0x%x\n",runtime->frame_bits); mv88fx_snd_debug("runtime->period_size=0x%x\n", (unsigned int)runtime->period_size); mv88fx_snd_debug("runtime->buffer_size=0x%x\n", (unsigned int)runtime->buffer_size); mv88fx_snd_debug("bufferPhyBase=0x%x\n",runtime->dma_addr); mv88fx_snd_debug("bufferSize=0x%x\n",pcm_play_ctrl.bufferSize); mv88fx_snd_debug("intByteCount=0x%x.\n",pcm_play_ctrl.intByteCount); #endif return 0; }
static int mv88fx_rt5630_init(struct snd_soc_codec *codec) { mv88fx_snd_debug(""); // mvmpp_gpio_set_value(MPP_Amp_PwrDn,0); return 0; }
static int __init mv88fx_i2s_init(void) { mv88fx_snd_debug(""); return platform_driver_register(&mv88fx_i2s_driver); }
static int mv88fx_i2s_snd_hw_playback_set(struct mv88fx_snd_chip *chip, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct mv88fx_snd_stream *audio_stream = runtime->private_data; MV_AUDIO_PLAYBACK_CTRL pcm_play_ctrl; MV_I2S_PLAYBACK_CTRL i2s_play_ctrl; MV_SPDIF_PLAYBACK_CTRL spdif_play_ctrl; MV_AUDIO_FREQ_DATA dco_ctrl; mv88fx_snd_debug("chip=%p chip->base=%p", chip, chip->base); memset(&pcm_play_ctrl, 0, sizeof(pcm_play_ctrl)); memset(&dco_ctrl, 0, sizeof(dco_ctrl)); memset(&i2s_play_ctrl, 0, sizeof(i2s_play_ctrl)); memset(&spdif_play_ctrl, 0, sizeof(spdif_play_ctrl)); dco_ctrl.offset = chip->dco_ctrl_offst; mv88fx_snd_debug("rate: %u ", runtime->rate); switch (runtime->rate) { case 44100: dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH; break; case 48000: dco_ctrl.baseFreq = AUDIO_FREQ_48KH; break; case 96000: dco_ctrl.baseFreq = AUDIO_FREQ_96KH; break; default: mv88fx_snd_error("Requested rate %d is not supported", runtime->rate); return -1; } pcm_play_ctrl.burst = (chip->burst == 128) ? AUDIO_128BYTE_BURST : AUDIO_32BYTE_BURST; pcm_play_ctrl.loopBack = chip->loopback; if (mv88fx_pcm_is_stereo(runtime)) { pcm_play_ctrl.monoMode = AUDIO_PLAY_MONO_OFF; } else { switch (audio_stream->mono_mode) { case MONO_LEFT: pcm_play_ctrl.monoMode = AUDIO_PLAY_LEFT_MONO; break; case MONO_RIGHT: pcm_play_ctrl.monoMode = AUDIO_PLAY_RIGHT_MONO; break; case MONO_BOTH: default: pcm_play_ctrl.monoMode = AUDIO_PLAY_BOTH_MONO; break; } } if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) { pcm_play_ctrl.sampleSize = SAMPLE_16BIT; i2s_play_ctrl.sampleSize = SAMPLE_16BIT; } else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) { pcm_play_ctrl.sampleSize = SAMPLE_24BIT; i2s_play_ctrl.sampleSize = SAMPLE_24BIT; } else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) { pcm_play_ctrl.sampleSize = SAMPLE_32BIT; i2s_play_ctrl.sampleSize = SAMPLE_32BIT; } else { mv88fx_snd_error("Requested format %d is not supported", runtime->format); return -1; } /* buffer and period sizes in frame */ pcm_play_ctrl.bufferPhyBase = runtime->dma_addr; pcm_play_ctrl.bufferSize = frames_to_bytes(runtime, runtime->buffer_size); pcm_play_ctrl.intByteCount = frames_to_bytes(runtime, runtime->period_size); /* I2S playback streem stuff */ /*i2s_play_ctrl.sampleSize = pcm_play_ctrl.sampleSize; */ i2s_play_ctrl.justification = I2S_JUSTIFIED; i2s_play_ctrl.sendLastFrame = 0; spdif_play_ctrl.nonPcm = MV_FALSE; spdif_play_ctrl.validity = chip->ch_stat_valid; if (audio_stream->stat_mem) { spdif_play_ctrl.userBitsFromMemory = MV_TRUE; spdif_play_ctrl.validityFromMemory = MV_TRUE; spdif_play_ctrl.blockStartInternally = MV_FALSE; } else { spdif_play_ctrl.userBitsFromMemory = MV_FALSE; spdif_play_ctrl.validityFromMemory = MV_FALSE; spdif_play_ctrl.blockStartInternally = MV_TRUE; } mv88fx_snd_debug(""); /* If this is non-PCM sound, mute I2S channel */ spin_lock_irq(&chip->reg_lock); mv88fx_snd_debug("chip=%p chip->base=%p port=%d", chip, chip->base, chip->port); if (!(mv88fx_snd_readl(chip->base, MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)) & (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) { mv88fx_snd_debug(""); if (MV_OK != mvAudioDCOCtrlSet(chip->port, &dco_ctrl)) { mv88fx_snd_error ("Failed to initialize DCO clock control."); return -1; mv88fx_snd_debug(""); } } mv88fx_snd_debug(""); if (audio_stream->clock_src == DCO_CLOCK) while ((mv88fx_snd_readl(chip->base, MV_AUDIO_SPCR_DCO_STATUS_REG(chip->port)) & ASDSR_DCO_LOCK_MASK) == 0) ; else if (audio_stream->clock_src == SPCR_CLOCK) while ((mv88fx_snd_readl(chip->base, MV_AUDIO_SPCR_DCO_STATUS_REG(chip->port)) & ASDSR_SPCR_LOCK_MASK) == 0) ; mv88fx_snd_debug(""); if (MV_OK != mvAudioPlaybackControlSet(chip->port, &pcm_play_ctrl)) { mv88fx_snd_error("Failed to initialize PCM playback control."); return -1; } mv88fx_snd_debug(""); if (MV_OK != mvI2SPlaybackCtrlSet(chip->port, &i2s_play_ctrl)) { mv88fx_snd_error("Failed to initialize I2S playback control."); return -1; } mv88fx_snd_debug(""); mvSPDIFPlaybackCtrlSet(chip->port, &spdif_play_ctrl); mv88fx_snd_debug(""); spin_unlock_irq(&chip->reg_lock); return 0; }