From: Mark Brown Date: Thu, 16 Jan 2014 12:44:01 +0000 (+0000) Subject: Merge remote-tracking branches 'asoc/topic/adsp', 'asoc/topic/atmel', 'asoc/topic... X-Git-Tag: v3.14-rc1~16^2~11^2^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=701caa51a2ce74182d39380ca11defeb163d98c1;p=platform%2Fkernel%2Flinux-stable.git Merge remote-tracking branches 'asoc/topic/adsp', 'asoc/topic/atmel', 'asoc/topic/bcm2835', 'asoc/topic/docs', 'asoc/topic/fsl', 'asoc/topic/generic', 'asoc/topic/kirkwood', 'asoc/topic/mc13783', 'asoc/topic/mxs', 'asoc/topic/nuc900', 'asoc/topic/sai', 'asoc/topic/sh', 'asoc/topic/ssm2602', 'asoc/topic/tlv320aic3x', 'asoc/topic/twl4030', 'asoc/topic/ux500', 'asoc/topic/width' and 'asoc/topic/x86' into for-tiwai --- 701caa51a2ce74182d39380ca11defeb163d98c1 diff --cc sound/soc/codecs/ad1836.c index d7c9838,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,9a92b79,af490be,9a92b79..77f4598 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@@@@@@@@@@@@@@@@@@@ -168,19 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 -168,17 +168,19 @@@@@@@@@@@@@@@@@@@@ static int ad1836_hw_params(struct snd_ int word_len = 0; /* bit size */ ----------------- - switch (params_format(params)) { ----------------- - case SNDRV_PCM_FORMAT_S16_LE: +++++++++++++++++ + switch (params_width(params)) { +++++++++++++++++ + case 16: word_len = AD1836_WORD_LEN_16; break; ----------------- - case SNDRV_PCM_FORMAT_S20_3LE: +++++++++++++++++ + case 20: word_len = AD1836_WORD_LEN_20; break; ----------------- - case SNDRV_PCM_FORMAT_S24_LE: ----------------- - case SNDRV_PCM_FORMAT_S32_LE: +++++++++++++++++ + case 24: +++++++++++++++++ + case 32: word_len = AD1836_WORD_LEN_24; break; ++++++++++++++++++ default: ++++++++++++++++++ return -EINVAL; } regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1, diff --cc sound/soc/codecs/wm_adsp.c index fb0c678,f6e317c,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9,46ec0e9..444626f --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@@@@@@@@@@@@@@@@@@@ -1497,107 -1492,149 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 -1493,107 +1497,149 @@@@@@@@@@@@@@@@@@@@ static int wm_adsp2_ena(struct wm_adsp return 0; } - -----------------int wm_adsp2_event(struct snd_soc_dapm_widget *w, - ----------------- struct snd_kcontrol *kcontrol, int event) + +++++++++++++++++static void wm_adsp2_boot_work(struct work_struct *work) { - ----------------- struct snd_soc_codec *codec = w->codec; - ----------------- struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); - ----------------- struct wm_adsp *dsp = &dsps[w->shift]; - ----------------- struct wm_adsp_alg_region *alg_region; - ----------------- struct wm_coeff_ctl *ctl; - ----------------- unsigned int val; + +++++++++++++++++ struct wm_adsp *dsp = container_of(work, + +++++++++++++++++ struct wm_adsp, + +++++++++++++++++ boot_work); int ret; + +++++++++++++++++ unsigned int val; - ----------------- dsp->card = codec->card; + +++++++++++++++++ /* + +++++++++++++++++ * For simplicity set the DSP clock rate to be the + +++++++++++++++++ * SYSCLK rate rather than making it configurable. + +++++++++++++++++ */ + +++++++++++++++++ ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); + +++++++++++++++++ if (ret != 0) { + +++++++++++++++++ adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); + +++++++++++++++++ return; + +++++++++++++++++ } + +++++++++++++++++ val = (val & ARIZONA_SYSCLK_FREQ_MASK) + +++++++++++++++++ >> ARIZONA_SYSCLK_FREQ_SHIFT; - ----------------- switch (event) { - ----------------- case SND_SOC_DAPM_POST_PMU: - ----------------- /* - ----------------- * For simplicity set the DSP clock rate to be the - ----------------- * SYSCLK rate rather than making it configurable. - ----------------- */ - ----------------- ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); - ----------------- if (ret != 0) { - ----------------- adsp_err(dsp, "Failed to read SYSCLK state: %d\n", - ----------------- ret); - ----------------- return ret; - ----------------- } - ----------------- val = (val & ARIZONA_SYSCLK_FREQ_MASK) - ----------------- >> ARIZONA_SYSCLK_FREQ_SHIFT; + +++++++++++++++++ ret = regmap_update_bits_async(dsp->regmap, + +++++++++++++++++ dsp->base + ADSP2_CLOCKING, + +++++++++++++++++ ADSP2_CLK_SEL_MASK, val); + +++++++++++++++++ if (ret != 0) { + +++++++++++++++++ adsp_err(dsp, "Failed to set clock rate: %d\n", ret); + +++++++++++++++++ return; + +++++++++++++++++ } - ret = regmap_update_bits_async(dsp->regmap, - dsp->base + ADSP2_CLOCKING, - ADSP2_CLK_SEL_MASK, val); ----------------- ret = regmap_update_bits(dsp->regmap, ----------------- dsp->base + ADSP2_CLOCKING, ----------------- ADSP2_CLK_SEL_MASK, val); + +++++++++++++++++ if (dsp->dvfs) { + +++++++++++++++++ ret = regmap_read(dsp->regmap, + +++++++++++++++++ dsp->base + ADSP2_CLOCKING, &val); if (ret != 0) { - ----------------- adsp_err(dsp, "Failed to set clock rate: %d\n", - ----------------- ret); - ----------------- return ret; + +++++++++++++++++ dev_err(dsp->dev, "Failed to read clocking: %d\n", ret); + +++++++++++++++++ return; } - ----------------- if (dsp->dvfs) { - ----------------- ret = regmap_read(dsp->regmap, - ----------------- dsp->base + ADSP2_CLOCKING, &val); + +++++++++++++++++ if ((val & ADSP2_CLK_SEL_MASK) >= 3) { + +++++++++++++++++ ret = regulator_enable(dsp->dvfs); if (ret != 0) { dev_err(dsp->dev, - ----------------- "Failed to read clocking: %d\n", ret); - ----------------- return ret; + +++++++++++++++++ "Failed to enable supply: %d\n", + +++++++++++++++++ ret); + +++++++++++++++++ return; } - ----------------- if ((val & ADSP2_CLK_SEL_MASK) >= 3) { - ----------------- ret = regulator_enable(dsp->dvfs); - ----------------- if (ret != 0) { - ----------------- dev_err(dsp->dev, - ----------------- "Failed to enable supply: %d\n", - ----------------- ret); - ----------------- return ret; - ----------------- } - ----------------- - ----------------- ret = regulator_set_voltage(dsp->dvfs, - ----------------- 1800000, - ----------------- 1800000); - ----------------- if (ret != 0) { - ----------------- dev_err(dsp->dev, - ----------------- "Failed to raise supply: %d\n", - ----------------- ret); - ----------------- return ret; - ----------------- } + +++++++++++++++++ ret = regulator_set_voltage(dsp->dvfs, + +++++++++++++++++ 1800000, + +++++++++++++++++ 1800000); + +++++++++++++++++ if (ret != 0) { + +++++++++++++++++ dev_err(dsp->dev, + +++++++++++++++++ "Failed to raise supply: %d\n", + +++++++++++++++++ ret); + +++++++++++++++++ return; } } + +++++++++++++++++ } - ----------------- ret = wm_adsp2_ena(dsp); - ----------------- if (ret != 0) - ----------------- return ret; + +++++++++++++++++ ret = wm_adsp2_ena(dsp); + +++++++++++++++++ if (ret != 0) + +++++++++++++++++ return; - ----------------- ret = wm_adsp_load(dsp); - ----------------- if (ret != 0) - ----------------- goto err; + +++++++++++++++++ ret = wm_adsp_load(dsp); + +++++++++++++++++ if (ret != 0) + +++++++++++++++++ goto err; - ----------------- ret = wm_adsp_setup_algs(dsp); - ----------------- if (ret != 0) - ----------------- goto err; + +++++++++++++++++ ret = wm_adsp_setup_algs(dsp); + +++++++++++++++++ if (ret != 0) + +++++++++++++++++ goto err; - ----------------- ret = wm_adsp_load_coeff(dsp); - ----------------- if (ret != 0) - ----------------- goto err; + +++++++++++++++++ ret = wm_adsp_load_coeff(dsp); + +++++++++++++++++ if (ret != 0) + +++++++++++++++++ goto err; - ----------------- /* Initialize caches for enabled and unset controls */ - ----------------- ret = wm_coeff_init_control_caches(dsp); - ----------------- if (ret != 0) - ----------------- goto err; + +++++++++++++++++ /* Initialize caches for enabled and unset controls */ + +++++++++++++++++ ret = wm_coeff_init_control_caches(dsp); + +++++++++++++++++ if (ret != 0) + +++++++++++++++++ goto err; - ----------------- /* Sync set controls */ - ----------------- ret = wm_coeff_sync_controls(dsp); - ----------------- if (ret != 0) - ----------------- goto err; + +++++++++++++++++ /* Sync set controls */ + +++++++++++++++++ ret = wm_coeff_sync_controls(dsp); + +++++++++++++++++ if (ret != 0) + +++++++++++++++++ goto err; + +++++++++++++++++ + +++++++++++++++++ ret = regmap_update_bits_async(dsp->regmap, + +++++++++++++++++ dsp->base + ADSP2_CONTROL, + +++++++++++++++++ ADSP2_CORE_ENA, + +++++++++++++++++ ADSP2_CORE_ENA); + +++++++++++++++++ if (ret != 0) + +++++++++++++++++ goto err; + +++++++++++++++++ + +++++++++++++++++ dsp->running = true; + +++++++++++++++++ + +++++++++++++++++ return; + +++++++++++++++++ + +++++++++++++++++err: + +++++++++++++++++ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, + +++++++++++++++++ ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); + +++++++++++++++++} + +++++++++++++++++ + +++++++++++++++++int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, + +++++++++++++++++ struct snd_kcontrol *kcontrol, int event) + +++++++++++++++++{ + +++++++++++++++++ struct snd_soc_codec *codec = w->codec; + +++++++++++++++++ struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); + +++++++++++++++++ struct wm_adsp *dsp = &dsps[w->shift]; + +++++++++++++++++ + +++++++++++++++++ dsp->card = codec->card; + +++++++++++++++++ + +++++++++++++++++ switch (event) { + +++++++++++++++++ case SND_SOC_DAPM_PRE_PMU: + +++++++++++++++++ queue_work(system_unbound_wq, &dsp->boot_work); + +++++++++++++++++ break; + +++++++++++++++++ default: + +++++++++++++++++ break; + +++++++++++++++++ }; + +++++++++++++++++ + +++++++++++++++++ return 0; + +++++++++++++++++} + +++++++++++++++++EXPORT_SYMBOL_GPL(wm_adsp2_early_event); + +++++++++++++++++ + +++++++++++++++++int wm_adsp2_event(struct snd_soc_dapm_widget *w, + +++++++++++++++++ struct snd_kcontrol *kcontrol, int event) + +++++++++++++++++{ + +++++++++++++++++ struct snd_soc_codec *codec = w->codec; + +++++++++++++++++ struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); + +++++++++++++++++ struct wm_adsp *dsp = &dsps[w->shift]; + +++++++++++++++++ struct wm_adsp_alg_region *alg_region; + +++++++++++++++++ struct wm_coeff_ctl *ctl; + +++++++++++++++++ int ret; + +++++++++++++++++ + +++++++++++++++++ switch (event) { + +++++++++++++++++ case SND_SOC_DAPM_POST_PMU: + +++++++++++++++++ flush_work(&dsp->boot_work); + +++++++++++++++++ + +++++++++++++++++ if (!dsp->running) + +++++++++++++++++ return -EIO; - ret = regmap_update_bits_async(dsp->regmap, - dsp->base + ADSP2_CONTROL, - ADSP2_CORE_ENA | ADSP2_START, - ADSP2_CORE_ENA | ADSP2_START); + ret = regmap_update_bits(dsp->regmap, + dsp->base + ADSP2_CONTROL, ----------------- ADSP2_CORE_ENA | ADSP2_START, ----------------- ADSP2_CORE_ENA | ADSP2_START); + +++++++++++++++++ ADSP2_START, + +++++++++++++++++ ADSP2_START); if (ret != 0) goto err; - ----------------- - ----------------- dsp->running = true; break; case SND_SOC_DAPM_PRE_PMD: diff --cc sound/soc/fsl/fsl_ssi.c index 76e56b3,35e2773,35e2773,35e2773,35e2773,7864ec5,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773,35e2773..f9090b1 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@@@@@@@@@@@@@@@@@@@ -130,19 -132,17 -132,17 -132,17 -132,17 -153,21 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 -132,17 +152,21 @@@@@@@@@@@@@@@@@@@@ struct fsl_ssi_private struct ccsr_ssi __iomem *ssi; dma_addr_t ssi_phys; unsigned int irq; ---- ------------- struct snd_pcm_substream *first_stream; ---- ------------- struct snd_pcm_substream *second_stream; unsigned int fifo_depth; struct snd_soc_dai_driver cpu_dai_drv; ----- ------------- struct device_attribute dev_attr; struct platform_device *pdev; +++++ +++++++++++++ enum fsl_ssi_type hw_type; bool new_binding; bool ssi_on_imx; bool imx_ac97; bool use_dma; ++++ +++++++++++++ bool baudclk_locked; +++++ +++++++++++++ bool irq_stats; +++++ +++++++++++++ bool offline_config; ++++ +++++++++++++ u8 i2s_mode; ++++ +++++++++++++ spinlock_t baudclk_lock; ++++ +++++++++++++ struct clk *baudclk; struct clk *clk; struct snd_dmaengine_dai_dma_data dma_params_tx; struct snd_dmaengine_dai_dma_data dma_params_rx; @@@@@@@@@@@@@@@@@@@@ -321,46 -321,17 -321,17 -321,17 -321,17 -373,287 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 -321,17 +372,287 @@@@@@@@@@@@@@@@@@@@ static irqreturn_t fsl_ssi_isr(int irq return ret; } +++++ +++++++++++++#if IS_ENABLED(CONFIG_DEBUG_FS) +++++ +++++++++++++/* Show the statistics of a flag only if its interrupt is enabled. The +++++ +++++++++++++ * compiler will optimze this code to a no-op if the interrupt is not +++++ +++++++++++++ * enabled. +++++ +++++++++++++ */ +++++ +++++++++++++#define SIER_SHOW(flag, name) \ +++++ +++++++++++++ do { \ +++++ +++++++++++++ if (FSLSSI_SISR_MASK & CCSR_SSI_SIER_##flag) \ +++++ +++++++++++++ seq_printf(s, #name "=%u\n", ssi_private->stats.name); \ +++++ +++++++++++++ } while (0) +++++ +++++++++++++ +++++ +++++++++++++ +++++ +++++++++++++/** +++++ +++++++++++++ * fsl_sysfs_ssi_show: display SSI statistics +++++ +++++++++++++ * +++++ +++++++++++++ * Display the statistics for the current SSI device. To avoid confusion, +++++ +++++++++++++ * we only show those counts that are enabled. +++++ +++++++++++++ */ +++++ +++++++++++++static int fsl_ssi_stats_show(struct seq_file *s, void *unused) +++++ +++++++++++++{ +++++ +++++++++++++ struct fsl_ssi_private *ssi_private = s->private; +++++ +++++++++++++ +++++ +++++++++++++ SIER_SHOW(RFRC_EN, rfrc); +++++ +++++++++++++ SIER_SHOW(TFRC_EN, tfrc); +++++ +++++++++++++ SIER_SHOW(CMDAU_EN, cmdau); +++++ +++++++++++++ SIER_SHOW(CMDDU_EN, cmddu); +++++ +++++++++++++ SIER_SHOW(RXT_EN, rxt); +++++ +++++++++++++ SIER_SHOW(RDR1_EN, rdr1); +++++ +++++++++++++ SIER_SHOW(RDR0_EN, rdr0); +++++ +++++++++++++ SIER_SHOW(TDE1_EN, tde1); +++++ +++++++++++++ SIER_SHOW(TDE0_EN, tde0); +++++ +++++++++++++ SIER_SHOW(ROE1_EN, roe1); +++++ +++++++++++++ SIER_SHOW(ROE0_EN, roe0); +++++ +++++++++++++ SIER_SHOW(TUE1_EN, tue1); +++++ +++++++++++++ SIER_SHOW(TUE0_EN, tue0); +++++ +++++++++++++ SIER_SHOW(TFS_EN, tfs); +++++ +++++++++++++ SIER_SHOW(RFS_EN, rfs); +++++ +++++++++++++ SIER_SHOW(TLS_EN, tls); +++++ +++++++++++++ SIER_SHOW(RLS_EN, rls); +++++ +++++++++++++ SIER_SHOW(RFF1_EN, rff1); +++++ +++++++++++++ SIER_SHOW(RFF0_EN, rff0); +++++ +++++++++++++ SIER_SHOW(TFE1_EN, tfe1); +++++ +++++++++++++ SIER_SHOW(TFE0_EN, tfe0); +++++ +++++++++++++ +++++ +++++++++++++ return 0; +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++static int fsl_ssi_stats_open(struct inode *inode, struct file *file) +++++ +++++++++++++{ +++++ +++++++++++++ return single_open(file, fsl_ssi_stats_show, inode->i_private); +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++static const struct file_operations fsl_ssi_stats_ops = { +++++ +++++++++++++ .open = fsl_ssi_stats_open, +++++ +++++++++++++ .read = seq_read, +++++ +++++++++++++ .llseek = seq_lseek, +++++ +++++++++++++ .release = single_release, +++++ +++++++++++++}; +++++ +++++++++++++ +++++ +++++++++++++static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private, +++++ +++++++++++++ struct device *dev) +++++ +++++++++++++{ +++++ +++++++++++++ ssi_private->dbg_dir = debugfs_create_dir(dev_name(dev), NULL); +++++ +++++++++++++ if (!ssi_private->dbg_dir) +++++ +++++++++++++ return -ENOMEM; +++++ +++++++++++++ +++++ +++++++++++++ ssi_private->dbg_stats = debugfs_create_file("stats", S_IRUGO, +++++ +++++++++++++ ssi_private->dbg_dir, ssi_private, &fsl_ssi_stats_ops); +++++ +++++++++++++ if (!ssi_private->dbg_stats) { +++++ +++++++++++++ debugfs_remove(ssi_private->dbg_dir); +++++ +++++++++++++ return -ENOMEM; +++++ +++++++++++++ } +++++ +++++++++++++ +++++ +++++++++++++ return 0; +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private) +++++ +++++++++++++{ +++++ +++++++++++++ debugfs_remove(ssi_private->dbg_stats); +++++ +++++++++++++ debugfs_remove(ssi_private->dbg_dir); +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++#else +++++ +++++++++++++ +++++ +++++++++++++static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private, +++++ +++++++++++++ struct device *dev) +++++ +++++++++++++{ +++++ +++++++++++++ return 0; +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private) +++++ +++++++++++++{ +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */ +++++ +++++++++++++ +++++ +++++++++++++/* +++++ +++++++++++++ * Enable/Disable all rx/tx config flags at once. +++++ +++++++++++++ */ +++++ +++++++++++++static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private, +++++ +++++++++++++ bool enable) +++++ +++++++++++++{ +++++ +++++++++++++ struct ccsr_ssi __iomem *ssi = ssi_private->ssi; +++++ +++++++++++++ struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val; +++++ +++++++++++++ +++++ +++++++++++++ if (enable) { +++++ +++++++++++++ write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier); +++++ +++++++++++++ write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr); +++++ +++++++++++++ write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr); +++++ +++++++++++++ } else { +++++ +++++++++++++ write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0); +++++ +++++++++++++ write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0); +++++ +++++++++++++ write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0); +++++ +++++++++++++ } +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++/* +++++ +++++++++++++ * Enable/Disable a ssi configuration. You have to pass either +++++ +++++++++++++ * ssi_private->rxtx_reg_val.rx or tx as vals parameter. +++++ +++++++++++++ */ +++++ +++++++++++++static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable, +++++ +++++++++++++ struct fsl_ssi_reg_val *vals) +++++ +++++++++++++{ +++++ +++++++++++++ struct ccsr_ssi __iomem *ssi = ssi_private->ssi; +++++ +++++++++++++ struct fsl_ssi_reg_val *avals; +++++ +++++++++++++ u32 scr_val = read_ssi(&ssi->scr); +++++ +++++++++++++ int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) + +++++ +++++++++++++ !!(scr_val & CCSR_SSI_SCR_RE); +++++ +++++++++++++ +++++ +++++++++++++ /* Find the other direction values rx or tx which we do not want to +++++ +++++++++++++ * modify */ +++++ +++++++++++++ if (&ssi_private->rxtx_reg_val.rx == vals) +++++ +++++++++++++ avals = &ssi_private->rxtx_reg_val.tx; +++++ +++++++++++++ else +++++ +++++++++++++ avals = &ssi_private->rxtx_reg_val.rx; +++++ +++++++++++++ +++++ +++++++++++++ /* If vals should be disabled, start with disabling the unit */ +++++ +++++++++++++ if (!enable) { +++++ +++++++++++++ u32 scr = vals->scr & (vals->scr ^ avals->scr); +++++ +++++++++++++ write_ssi_mask(&ssi->scr, scr, 0); +++++ +++++++++++++ } +++++ +++++++++++++ +++++ +++++++++++++ /* +++++ +++++++++++++ * We are running on a SoC which does not support online SSI +++++ +++++++++++++ * reconfiguration, so we have to enable all necessary flags at once +++++ +++++++++++++ * even if we do not use them later (capture and playback configuration) +++++ +++++++++++++ */ +++++ +++++++++++++ if (ssi_private->offline_config) { +++++ +++++++++++++ if ((enable && !nr_active_streams) || +++++ +++++++++++++ (!enable && nr_active_streams == 1)) +++++ +++++++++++++ fsl_ssi_rxtx_config(ssi_private, enable); +++++ +++++++++++++ +++++ +++++++++++++ goto config_done; +++++ +++++++++++++ } +++++ +++++++++++++ +++++ +++++++++++++ /* +++++ +++++++++++++ * Configure single direction units while the SSI unit is running +++++ +++++++++++++ * (online configuration) +++++ +++++++++++++ */ +++++ +++++++++++++ if (enable) { +++++ +++++++++++++ write_ssi_mask(&ssi->sier, 0, vals->sier); +++++ +++++++++++++ write_ssi_mask(&ssi->srcr, 0, vals->srcr); +++++ +++++++++++++ write_ssi_mask(&ssi->stcr, 0, vals->stcr); +++++ +++++++++++++ } else { +++++ +++++++++++++ u32 sier; +++++ +++++++++++++ u32 srcr; +++++ +++++++++++++ u32 stcr; +++++ +++++++++++++ +++++ +++++++++++++ /* +++++ +++++++++++++ * Disabling the necessary flags for one of rx/tx while the +++++ +++++++++++++ * other stream is active is a little bit more difficult. We +++++ +++++++++++++ * have to disable only those flags that differ between both +++++ +++++++++++++ * streams (rx XOR tx) and that are set in the stream that is +++++ +++++++++++++ * disabled now. Otherwise we could alter flags of the other +++++ +++++++++++++ * stream +++++ +++++++++++++ */ +++++ +++++++++++++ +++++ +++++++++++++ /* These assignments are simply vals without bits set in avals*/ +++++ +++++++++++++ sier = vals->sier & (vals->sier ^ avals->sier); +++++ +++++++++++++ srcr = vals->srcr & (vals->srcr ^ avals->srcr); +++++ +++++++++++++ stcr = vals->stcr & (vals->stcr ^ avals->stcr); +++++ +++++++++++++ +++++ +++++++++++++ write_ssi_mask(&ssi->srcr, srcr, 0); +++++ +++++++++++++ write_ssi_mask(&ssi->stcr, stcr, 0); +++++ +++++++++++++ write_ssi_mask(&ssi->sier, sier, 0); +++++ +++++++++++++ } +++++ +++++++++++++ +++++ +++++++++++++config_done: +++++ +++++++++++++ /* Enabling of subunits is done after configuration */ +++++ +++++++++++++ if (enable) +++++ +++++++++++++ write_ssi_mask(&ssi->scr, 0, vals->scr); +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++ +++++ +++++++++++++static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable) +++++ +++++++++++++{ +++++ +++++++++++++ fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx); +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable) +++++ +++++++++++++{ +++++ +++++++++++++ fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx); +++++ +++++++++++++} +++++ +++++++++++++ +++++ +++++++++++++/* +++++ +++++++++++++ * Setup rx/tx register values used to enable/disable the streams. These will +++++ +++++++++++++ * be used later in fsl_ssi_config to setup the streams without the need to +++++ +++++++++++++ * check for all different SSI modes. +++++ +++++++++++++ */ +++++ +++++++++++++static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private) +++++ +++++++++++++{ +++++ +++++++++++++ struct fsl_ssi_rxtx_reg_val *reg = &ssi_private->rxtx_reg_val; +++++ +++++++++++++ +++++ +++++++++++++ reg->rx.sier = CCSR_SSI_SIER_RFF0_EN; +++++ +++++++++++++ reg->rx.srcr = CCSR_SSI_SRCR_RFEN0; +++++ +++++++++++++ reg->rx.scr = 0; +++++ +++++++++++++ reg->tx.sier = CCSR_SSI_SIER_TFE0_EN; +++++ +++++++++++++ reg->tx.stcr = CCSR_SSI_STCR_TFEN0; +++++ +++++++++++++ reg->tx.scr = 0; +++++ +++++++++++++ +++++ +++++++++++++ if (!ssi_private->imx_ac97) { +++++ +++++++++++++ reg->rx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE; +++++ +++++++++++++ reg->rx.sier |= CCSR_SSI_SIER_RFF0_EN; +++++ +++++++++++++ reg->tx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE; +++++ +++++++++++++ reg->tx.sier |= CCSR_SSI_SIER_TFE0_EN; +++++ +++++++++++++ } +++++ +++++++++++++ +++++ +++++++++++++ if (ssi_private->use_dma) { +++++ +++++++++++++ reg->rx.sier |= CCSR_SSI_SIER_RDMAE; +++++ +++++++++++++ reg->tx.sier |= CCSR_SSI_SIER_TDMAE; +++++ +++++++++++++ } else { +++++ +++++++++++++ reg->rx.sier |= CCSR_SSI_SIER_RIE; +++++ +++++++++++++ reg->tx.sier |= CCSR_SSI_SIER_TIE; +++++ +++++++++++++ } +++++ +++++++++++++ +++++ +++++++++++++ reg->rx.sier |= FSLSSI_SIER_DBG_RX_FLAGS; +++++ +++++++++++++ reg->tx.sier |= FSLSSI_SIER_DBG_TX_FLAGS; +++++ +++++++++++++} +++++ +++++++++++++ ++++ +++++++++++++static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private) ++++ +++++++++++++{ ++++ +++++++++++++ struct ccsr_ssi __iomem *ssi = ssi_private->ssi; ++++ +++++++++++++ ++++ +++++++++++++ /* ++++ +++++++++++++ * Setup the clock control register ++++ +++++++++++++ */ ++++ +++++++++++++ write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), ++++ +++++++++++++ &ssi->stccr); ++++ +++++++++++++ write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), ++++ +++++++++++++ &ssi->srccr); ++++ +++++++++++++ ++++ +++++++++++++ /* ++++ +++++++++++++ * Enable AC97 mode and startup the SSI ++++ +++++++++++++ */ ++++ +++++++++++++ write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, ++++ +++++++++++++ &ssi->sacnt); ++++ +++++++++++++ write_ssi(0xff, &ssi->saccdis); ++++ +++++++++++++ write_ssi(0x300, &ssi->saccen); ++++ +++++++++++++ ++++ +++++++++++++ /* ++++ +++++++++++++ * Enable SSI, Transmit and Receive. AC97 has to communicate with the ++++ +++++++++++++ * codec before a stream is started. ++++ +++++++++++++ */ ++++ +++++++++++++ write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN | ++++ +++++++++++++ CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); ++++ +++++++++++++ ++++ +++++++++++++ write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); ++++ +++++++++++++} ++++ +++++++++++++ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; u8 wm; int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; +++++ +++++++++++++ fsl_ssi_setup_reg_vals(ssi_private); +++++ +++++++++++++ if (ssi_private->imx_ac97) ---- ------------- i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; ++++ +++++++++++++ ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; else ---- ------------- i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; ++++ +++++++++++++ ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; /* * Section 16.5 of the MPC8610 reference manual says that the SSI needs @@@@@@@@@@@@@@@@@@@@ -377,16 -348,16 -348,16 -348,16 -348,16 -670,15 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 -348,16 +669,15 @@@@@@@@@@@@@@@@@@@@ write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, CCSR_SSI_SCR_TFR_CLK_DIS | ---- ------------- i2s_mode | ++++ +++++++++++++ ssi_private->i2s_mode | (synchronous ? CCSR_SSI_SCR_SYN : 0)); ----- ------------- write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | ----- ------------- CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | ----- ------------- CCSR_SSI_STCR_TSCKP, &ssi->stcr); +++++ +++++++++++++ write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFSI | +++++ +++++++++++++ CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr); +++++ +++++++++++++ +++++ +++++++++++++ write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFSI | +++++ +++++++++++++ CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); ----- ------------- write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | ----- ------------- CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | ----- ------------- CCSR_SSI_SRCR_RSCKP, &ssi->srcr); /* * The DC and PM bits are only used if the SSI is the clock master. */ @@@@@@@@@@@@@@@@@@@@ -416,9 -387,32 -387,32 -387,32 -387,32 -708,20 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 -387,32 +707,20 @@@@@@@@@@@@@@@@@@@@ * because it is also running without an active substream. Normally SSI * is only enabled when there is a substream. */ ---- ------------- if (ssi_private->imx_ac97) { ---- ------------- /* ---- ------------- * Setup the clock control register ---- ------------- */ ---- ------------- write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), ---- ------------- &ssi->stccr); ---- ------------- write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13), ---- ------------- &ssi->srccr); ---- ------------- ---- ------------- /* ---- ------------- * Enable AC97 mode and startup the SSI ---- ------------- */ ---- ------------- write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV, ---- ------------- &ssi->sacnt); ---- ------------- write_ssi(0xff, &ssi->saccdis); ---- ------------- write_ssi(0x300, &ssi->saccen); ---- ------------- ---- ------------- /* ---- ------------- * Enable SSI, Transmit and Receive ---- ------------- */ ---- ------------- write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN | ---- ------------- CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE); ++++ +++++++++++++ if (ssi_private->imx_ac97) ++++ +++++++++++++ fsl_ssi_setup_ac97(ssi_private); ---- ------------- write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); +++++ +++++++++++++ /* +++++ +++++++++++++ * Set a default slot number so that there is no need for those common +++++ +++++++++++++ * cases like I2S mode to call the extra set_tdm_slot() any more. +++++ +++++++++++++ */ +++++ +++++++++++++ if (!ssi_private->imx_ac97) { +++++ +++++++++++++ write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK, +++++ +++++++++++++ CCSR_SSI_SxCCR_DC(2)); +++++ +++++++++++++ write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK, +++++ +++++++++++++ CCSR_SSI_SxCCR_DC(2)); + } + return 0; } @@@@@@@@@@@@@@@@@@@@ -761,29 -548,28 -548,28 -548,28 -548,28 -1064,8 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 -548,28 +1063,8 @@@@@@@@@@@@@@@@@@@@ static int fsl_ssi_trigger(struct snd_p struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct ccsr_ssi __iomem *ssi = ssi_private->ssi; ----- ------------- unsigned int sier_bits; ---- ------------- ---- ------------- /* ---- ------------- * Enable only the interrupts and DMA requests ---- ------------- * that are needed for the channel. As the fiq ---- ------------- * is polling for this bits, we have to ensure ---- ------------- * that this are aligned with the preallocated ---- ------------- * buffers ---- ------------- */ ---- ------------- ---- ------------- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ---- ------------- if (ssi_private->use_dma) ---- ------------- sier_bits = SIER_FLAGS; ---- ------------- else ---- ------------- sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN; ---- ------------- } else { ---- ------------- if (ssi_private->use_dma) ---- ------------- sier_bits = SIER_FLAGS; ---- ------------- else ---- ------------- sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN; ---- ------------- } ++++ +++++++++++++ unsigned long flags; - /* - * Enable only the interrupts and DMA requests - * that are needed for the channel. As the fiq - * is polling for this bits, we have to ensure - * that this are aligned with the preallocated - * buffers - */ - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (ssi_private->use_dma) - sier_bits = SIER_FLAGS; - else - sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN; - } else { - if (ssi_private->use_dma) - sier_bits = SIER_FLAGS; - else - sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN; - } - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@@@@@@@@@@@@@@@@@@@ -798,17 -584,13 -584,13 -584,13 -584,13 -1078,16 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 -584,13 +1077,16 @@@@@@@@@@@@@@@@@@@@ case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ----- ------------- write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); +++++ +++++++++++++ fsl_ssi_tx_config(ssi_private, false); else ----- ------------- write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); +++++ +++++++++++++ fsl_ssi_rx_config(ssi_private, false); if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) & ---- ------------- (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) ---- ------------- write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); ++++ +++++++++++++ (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) { - write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); ++++ +++++++++++++ spin_lock_irqsave(&ssi_private->baudclk_lock, flags); ++++ +++++++++++++ ssi_private->baudclk_locked = false; ++++ +++++++++++++ spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); ++++ +++++++++++++ } break; default: @@@@@@@@@@@@@@@@@@@@ -863,58 -661,59 -661,59 -661,59 -661,59 -1147,6 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 -661,59 +1146,6 @@@@@@@@@@@@@@@@@@@@ static const struct snd_soc_component_d .name = "fsl-ssi", }; ----- -------------/** ----- ------------- * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit. ----- ------------- * ----- ------------- * This function is called by ALSA to start, stop, pause, and resume the ----- ------------- * transfer of data. ----- ------------- */ ----- -------------static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, ----- ------------- struct snd_soc_dai *dai) ----- -------------{ ----- ------------- struct snd_soc_pcm_runtime *rtd = substream->private_data; ----- ------------- struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata( ----- ------------- rtd->cpu_dai); ----- ------------- struct ccsr_ssi __iomem *ssi = ssi_private->ssi; ----- ------------- ----- ------------- switch (cmd) { ----- ------------- case SNDRV_PCM_TRIGGER_START: ----- ------------- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ----- ------------- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ----- ------------- write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE | ----- ------------- CCSR_SSI_SIER_TFE0_EN); ----- ------------- else ----- ------------- write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE | ----- ------------- CCSR_SSI_SIER_RFF0_EN); ----- ------------- break; ----- ------------- ----- ------------- case SNDRV_PCM_TRIGGER_STOP: ----- ------------- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ----- ------------- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ----- ------------- write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE | ----- ------------- CCSR_SSI_SIER_TFE0_EN, 0); ----- ------------- else ----- ------------- write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE | ----- ------------- CCSR_SSI_SIER_RFF0_EN, 0); ----- ------------- break; ----- ------------- ----- ------------- default: ----- ------------- return -EINVAL; ----- ------------- } ----- ------------- ----- ------------- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ----- ------------- write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor); ----- ------------- else ----- ------------- write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor); ----- ------------- ----- ------------- return 0; ----- -------------} ----- ------------- ----- -------------static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { ----- ------------- .startup = fsl_ssi_startup, ---- ------------- .shutdown = fsl_ssi_shutdown, ----- ------------- .trigger = fsl_ssi_ac97_trigger, ----- -------------}; ----- ------------- static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { .ac97_control = 1, .playback = { @@@@@@@@@@@@@@@@@@@@ -1150,10 -946,7 -946,7 -946,7 -946,7 -1340,37 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 -946,7 +1339,37 @@@@@@@@@@@@@@@@@@@@ static int fsl_ssi_probe(struct platfor /* Older 8610 DTs didn't have the fifo-depth property */ ssi_private->fifo_depth = 8; ---- ------------- if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { ++++ +++++++++++++ ssi_private->baudclk_locked = false; ++++ +++++++++++++ spin_lock_init(&ssi_private->baudclk_lock); ++++ +++++++++++++ - if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { +++++ +++++++++++++ /* +++++ +++++++++++++ * imx51 and later SoCs have a slightly different IP that allows the +++++ +++++++++++++ * SSI configuration while the SSI unit is running. +++++ +++++++++++++ * +++++ +++++++++++++ * More important, it is necessary on those SoCs to configure the +++++ +++++++++++++ * sperate TX/RX DMA bits just before starting the stream +++++ +++++++++++++ * (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi +++++ +++++++++++++ * sends any DMA requests to the SDMA unit, otherwise it is not defined +++++ +++++++++++++ * how the SDMA unit handles the DMA request. +++++ +++++++++++++ * +++++ +++++++++++++ * SDMA units are present on devices starting at imx35 but the imx35 +++++ +++++++++++++ * reference manual states that the DMA bits should not be changed +++++ +++++++++++++ * while the SSI unit is running (SSIEN). So we support the necessary +++++ +++++++++++++ * online configuration of fsl-ssi starting at imx51. +++++ +++++++++++++ */ +++++ +++++++++++++ switch (hw_type) { +++++ +++++++++++++ case FSL_SSI_MCP8610: +++++ +++++++++++++ case FSL_SSI_MX21: +++++ +++++++++++++ case FSL_SSI_MX35: +++++ +++++++++++++ ssi_private->offline_config = true; +++++ +++++++++++++ break; +++++ +++++++++++++ case FSL_SSI_MX51: +++++ +++++++++++++ ssi_private->offline_config = false; +++++ +++++++++++++ break; +++++ +++++++++++++ } +++++ +++++++++++++ +++++ +++++++++++++ if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 || +++++ +++++++++++++ hw_type == FSL_SSI_MX35) { u32 dma_events[2]; ssi_private->ssi_on_imx = true; @@@@@@@@@@@@@@@@@@@@ -1170,15 -963,6 -963,6 -963,6 -963,6 -1387,16 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 -963,6 +1386,16 @@@@@@@@@@@@@@@@@@@@ goto error_irqmap; } ++++ +++++++++++++ /* For those SLAVE implementations, we ingore non-baudclk cases ++++ +++++++++++++ * and, instead, abandon MASTER mode that needs baud clock. ++++ +++++++++++++ */ ++++ +++++++++++++ ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud"); ++++ +++++++++++++ if (IS_ERR(ssi_private->baudclk)) - dev_warn(&pdev->dev, "could not get baud clock: %d\n", ret); +++++ +++++++++++++ dev_warn(&pdev->dev, "could not get baud clock: %ld\n", +++++ +++++++++++++ PTR_ERR(ssi_private->baudclk)); ++++ +++++++++++++ else ++++ +++++++++++++ clk_prepare_enable(ssi_private->baudclk); ++++ +++++++++++++ /* * We have burstsize be "fifo_depth - 2" to match the SSI * watermark setting in fsl_ssi_startup(). @@@@@@@@@@@@@@@@@@@@ -1318,20 -1102,19 -1102,19 -1102,19 -1102,19 -1533,28 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 -1102,19 +1532,28 @@@@@@@@@@@@@@@@@@@@ done return 0; error_dai: ---- ------------- if (ssi_private->ssi_on_imx) ---- ------------- imx_pcm_dma_exit(pdev); +++++ +++++++++++++ if (ssi_private->ssi_on_imx && !ssi_private->use_dma) +++++ +++++++++++++ imx_pcm_fiq_exit(pdev); +++++ +++++++++++++ +++++ +++++++++++++error_pcm: +++++ +++++++++++++ fsl_ssi_debugfs_remove(ssi_private); +++++ +++++++++++++ +++++ +++++++++++++error_dbgfs: snd_soc_unregister_component(&pdev->dev); error_dev: device_remove_file(&pdev->dev, dev_attr); error_clk: ---- ------------- if (ssi_private->ssi_on_imx) ++++ +++++++++++++ if (ssi_private->ssi_on_imx) { ++++ +++++++++++++ if (!IS_ERR(ssi_private->baudclk)) ++++ +++++++++++++ clk_disable_unprepare(ssi_private->baudclk); clk_disable_unprepare(ssi_private->clk); ++++ +++++++++++++ } error_irqmap: ----- ------------- irq_dispose_mapping(ssi_private->irq); +++++ +++++++++++++ if (ssi_private->irq_stats) +++++ +++++++++++++ irq_dispose_mapping(ssi_private->irq); return ret; } @@@@@@@@@@@@@@@@@@@@ -1340,16 -1123,15 -1123,15 -1123,15 -1123,15 -1563,18 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 -1123,15 +1562,18 @@@@@@@@@@@@@@@@@@@@ static int fsl_ssi_remove(struct platfo { struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev); +++++ +++++++++++++ fsl_ssi_debugfs_remove(ssi_private); +++++ +++++++++++++ if (!ssi_private->new_binding) platform_device_unregister(ssi_private->pdev); ---- ------------- if (ssi_private->ssi_on_imx) ---- ------------- imx_pcm_dma_exit(pdev); snd_soc_unregister_component(&pdev->dev); ----- ------------- device_remove_file(&pdev->dev, &ssi_private->dev_attr); ---- ------------- if (ssi_private->ssi_on_imx) ++++ +++++++++++++ if (ssi_private->ssi_on_imx) { ++++ +++++++++++++ if (!IS_ERR(ssi_private->baudclk)) ++++ +++++++++++++ clk_disable_unprepare(ssi_private->baudclk); clk_disable_unprepare(ssi_private->clk); ---- ------------- irq_dispose_mapping(ssi_private->irq); ++++ +++++++++++++ } - irq_dispose_mapping(ssi_private->irq); +++++ +++++++++++++ if (ssi_private->irq_stats) +++++ +++++++++++++ irq_dispose_mapping(ssi_private->irq); return 0; } diff --cc sound/soc/generic/simple-card.c index c0d92813,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,53395f5,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70,b2fbb70..2a1b1b5 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@@@@@@@@@@@@@@@@@@@ -8,15 -8,14 -8,14 -8,14 -8,14 -8,14 -8,13 -8,14 -8,14 -8,14 -8,14 -8,14 -8,14 -8,14 -8,14 -8,14 -8,14 -8,14 -8,14 +8,13 @@@@@@@@@@@@@@@@@@@@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ ----- ------------ ----- ------------#include +++++ ++++++++++++#include + #include +++++ ++++++++++++#include +++++ ++++++++++++#include - #include ++++++ ++++++++++++#include #include ------ ------------#define asoc_simple_get_card_info(p) \ ------ ------------ container_of(p->dai_link, struct asoc_simple_card_info, snd_link) ------ ------------ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, struct asoc_simple_dai *set, unsigned int daifmt) @@@@@@@@@@@@@@@@@@@@ -58,173 -57,14 -57,14 -57,14 -57,14 -57,14 -57,171 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 -57,14 +57,174 @@@@@@@@@@@@@@@@@@@@ static int asoc_simple_card_dai_init(st return 0; } +++++ ++++++++++++static int +++++ ++++++++++++asoc_simple_card_sub_parse_of(struct device_node *np, +++++ ++++++++++++ struct asoc_simple_dai *dai, +++++ ++++++++++++ struct device_node **node) +++++ ++++++++++++{ +++++ ++++++++++++ struct clk *clk; +++++ ++++++++++++ int ret; +++++ ++++++++++++ +++++ ++++++++++++ /* +++++ ++++++++++++ * get node via "sound-dai = <&phandle port>" +++++ ++++++++++++ * it will be used as xxx_of_node on soc_bind_dai_link() +++++ ++++++++++++ */ +++++ ++++++++++++ *node = of_parse_phandle(np, "sound-dai", 0); +++++ ++++++++++++ if (!*node) +++++ ++++++++++++ return -ENODEV; +++++ ++++++++++++ +++++ ++++++++++++ /* get dai->name */ +++++ ++++++++++++ ret = snd_soc_of_get_dai_name(np, &dai->name); +++++ ++++++++++++ if (ret < 0) +++++ ++++++++++++ goto parse_error; +++++ ++++++++++++ +++++ ++++++++++++ /* +++++ ++++++++++++ * bitclock-inversion, frame-inversion +++++ ++++++++++++ * bitclock-master, frame-master +++++ ++++++++++++ * and specific "format" if it has +++++ ++++++++++++ */ +++++ ++++++++++++ dai->fmt = snd_soc_of_parse_daifmt(np, NULL); +++++ ++++++++++++ +++++ ++++++++++++ /* +++++ ++++++++++++ * dai->sysclk come from +++++ ++++++++++++ * "clocks = <&xxx>" (if system has common clock) +++++ ++++++++++++ * or "system-clock-frequency = " +++++ ++++++++++++ * or device's module clock. +++++ ++++++++++++ */ +++++ ++++++++++++ if (of_property_read_bool(np, "clocks")) { +++++ ++++++++++++ clk = of_clk_get(np, 0); +++++ ++++++++++++ if (IS_ERR(clk)) { +++++ ++++++++++++ ret = PTR_ERR(clk); +++++ ++++++++++++ goto parse_error; +++++ ++++++++++++ } +++++ ++++++++++++ +++++ ++++++++++++ dai->sysclk = clk_get_rate(clk); +++++ ++++++++++++ } else if (of_property_read_bool(np, "system-clock-frequency")) { +++++ ++++++++++++ of_property_read_u32(np, +++++ ++++++++++++ "system-clock-frequency", +++++ ++++++++++++ &dai->sysclk); +++++ ++++++++++++ } else { +++++ ++++++++++++ clk = of_clk_get(*node, 0); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - goto parse_error; - } - - dai->sysclk = clk_get_rate(clk); ++++++ ++++++++++++ if (!IS_ERR(clk)) ++++++ ++++++++++++ dai->sysclk = clk_get_rate(clk); +++++ ++++++++++++ } +++++ ++++++++++++ +++++ ++++++++++++ ret = 0; +++++ ++++++++++++ +++++ ++++++++++++parse_error: +++++ ++++++++++++ of_node_put(*node); +++++ ++++++++++++ +++++ ++++++++++++ return ret; +++++ ++++++++++++} +++++ ++++++++++++ +++++ ++++++++++++static int asoc_simple_card_parse_of(struct device_node *node, +++++ ++++++++++++ struct asoc_simple_card_info *info, +++++ ++++++++++++ struct device *dev, +++++ ++++++++++++ struct device_node **of_cpu, +++++ ++++++++++++ struct device_node **of_codec, +++++ ++++++++++++ struct device_node **of_platform) +++++ ++++++++++++{ +++++ ++++++++++++ struct device_node *np; +++++ ++++++++++++ char *name; +++++ ++++++++++++ int ret; +++++ ++++++++++++ +++++ ++++++++++++ /* get CPU/CODEC common format via simple-audio-card,format */ +++++ ++++++++++++ info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & +++++ ++++++++++++ (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); +++++ ++++++++++++ +++++ ++++++++++++ /* DAPM routes */ - ret = snd_soc_of_parse_audio_routing(&info->snd_card, - "simple-audio-routing"); - if (ret) - return ret; ++++++ ++++++++++++ if (of_property_read_bool(node, "simple-audio-card,routing")) { ++++++ ++++++++++++ ret = snd_soc_of_parse_audio_routing(&info->snd_card, ++++++ ++++++++++++ "simple-audio-card,routing"); ++++++ ++++++++++++ if (ret) ++++++ ++++++++++++ return ret; ++++++ ++++++++++++ } +++++ ++++++++++++ +++++ ++++++++++++ /* CPU sub-node */ +++++ ++++++++++++ ret = -EINVAL; +++++ ++++++++++++ np = of_get_child_by_name(node, "simple-audio-card,cpu"); +++++ ++++++++++++ if (np) +++++ ++++++++++++ ret = asoc_simple_card_sub_parse_of(np, +++++ ++++++++++++ &info->cpu_dai, +++++ ++++++++++++ of_cpu); +++++ ++++++++++++ if (ret < 0) +++++ ++++++++++++ return ret; +++++ ++++++++++++ +++++ ++++++++++++ /* CODEC sub-node */ +++++ ++++++++++++ ret = -EINVAL; +++++ ++++++++++++ np = of_get_child_by_name(node, "simple-audio-card,codec"); +++++ ++++++++++++ if (np) +++++ ++++++++++++ ret = asoc_simple_card_sub_parse_of(np, +++++ ++++++++++++ &info->codec_dai, +++++ ++++++++++++ of_codec); +++++ ++++++++++++ if (ret < 0) +++++ ++++++++++++ return ret; +++++ ++++++++++++ ++++++++++++++++++ if (!info->cpu_dai.name || !info->codec_dai.name) ++++++++++++++++++ return -EINVAL; ++++++++++++++++++ +++++ ++++++++++++ /* card name is created from CPU/CODEC dai name */ +++++ ++++++++++++ name = devm_kzalloc(dev, +++++ ++++++++++++ strlen(info->cpu_dai.name) + +++++ ++++++++++++ strlen(info->codec_dai.name) + 2, +++++ ++++++++++++ GFP_KERNEL); +++++ ++++++++++++ sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); +++++ ++++++++++++ info->name = info->card = name; +++++ ++++++++++++ +++++ ++++++++++++ /* simple-card assumes platform == cpu */ +++++ ++++++++++++ *of_platform = *of_cpu; +++++ ++++++++++++ +++++ ++++++++++++ dev_dbg(dev, "card-name : %s\n", info->card); +++++ ++++++++++++ dev_dbg(dev, "platform : %04x\n", info->daifmt); +++++ ++++++++++++ dev_dbg(dev, "cpu : %s / %04x / %d\n", +++++ ++++++++++++ info->cpu_dai.name, +++++ ++++++++++++ info->cpu_dai.fmt, +++++ ++++++++++++ info->cpu_dai.sysclk); +++++ ++++++++++++ dev_dbg(dev, "codec : %s / %04x / %d\n", +++++ ++++++++++++ info->codec_dai.name, +++++ ++++++++++++ info->codec_dai.fmt, +++++ ++++++++++++ info->codec_dai.sysclk); +++++ ++++++++++++ +++++ ++++++++++++ return 0; +++++ ++++++++++++} +++++ ++++++++++++ static int asoc_simple_card_probe(struct platform_device *pdev) { ----- ------------ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; +++++ ++++++++++++ struct asoc_simple_card_info *cinfo; +++++ ++++++++++++ struct device_node *np = pdev->dev.of_node; +++++ ++++++++++++ struct device_node *of_cpu, *of_codec, *of_platform; struct device *dev = &pdev->dev; ++++++ ++++++++++++ int ret; ----- ------------ if (!cinfo) { ----- ------------ dev_err(dev, "no info for asoc-simple-card\n"); ----- ------------ return -EINVAL; +++++ ++++++++++++ cinfo = NULL; +++++ ++++++++++++ of_cpu = NULL; +++++ ++++++++++++ of_codec = NULL; +++++ ++++++++++++ of_platform = NULL; ++++++ ++++++++++++ ++++++ ++++++++++++ cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); ++++++ ++++++++++++ if (!cinfo) ++++++ ++++++++++++ return -ENOMEM; ++++++ ++++++++++++ +++++ ++++++++++++ if (np && of_device_is_available(np)) { - cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); - if (cinfo) { - int ret; - cinfo->snd_card.dev = &pdev->dev; - ret = asoc_simple_card_parse_of(np, cinfo, dev, - &of_cpu, - &of_codec, - &of_platform); - if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "parse error %d\n", ret); - return ret; - } ++++++ ++++++++++++ cinfo->snd_card.dev = dev; ++++++ ++++++++++++ ++++++ ++++++++++++ ret = asoc_simple_card_parse_of(np, cinfo, dev, ++++++ ++++++++++++ &of_cpu, ++++++ ++++++++++++ &of_codec, ++++++ ++++++++++++ &of_platform); ++++++ ++++++++++++ if (ret < 0) { ++++++ ++++++++++++ if (ret != -EPROBE_DEFER) ++++++ ++++++++++++ dev_err(dev, "parse error %d\n", ret); ++++++ ++++++++++++ return ret; +++++ ++++++++++++ } +++++ ++++++++++++ } else { - cinfo->snd_card.dev = &pdev->dev; - cinfo = pdev->dev.platform_data; - } ++++++ ++++++++++++ if (!dev->platform_data) { ++++++ ++++++++++++ dev_err(dev, "no info for asoc-simple-card\n"); ++++++ ++++++++++++ return -EINVAL; ++++++ ++++++++++++ } +++++ ++++++++++++ - if (!cinfo) { - dev_err(dev, "no info for asoc-simple-card\n"); - return -EINVAL; ++++++ ++++++++++++ memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); ++++++ ++++++++++++ cinfo->snd_card.dev = dev; } if (!cinfo->name || @@@@@@@@@@@@@@@@@@@@ -258,16 -95,18 -95,18 -95,18 -95,18 -95,18 -255,18 -95,18 -95,18 -95,18 -95,18 -95,18 -95,18 -95,18 -95,18 -95,18 -95,18 -95,18 -95,18 +258,18 @@@@@@@@@@@@@@@@@@@@ cinfo->snd_card.owner = THIS_MODULE; cinfo->snd_card.dai_link = &cinfo->snd_link; cinfo->snd_card.num_links = 1; ----- ------------ cinfo->snd_card.dev = &pdev->dev; ----- ------------ return snd_soc_register_card(&cinfo->snd_card); ----- ------------} ++++++ ++++++++++++ snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); + ----- ------------static int asoc_simple_card_remove(struct platform_device *pdev) ----- ------------{ ----- ------------ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; ----- ------------ ----- ------------ return snd_soc_unregister_card(&cinfo->snd_card); +++++ ++++++++++++ return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); } +++++ ++++++++++++static const struct of_device_id asoc_simple_of_match[] = { +++++ ++++++++++++ { .compatible = "simple-audio-card", }, +++++ ++++++++++++ {}, +++++ ++++++++++++}; +++++ ++++++++++++MODULE_DEVICE_TABLE(of, asoc_simple_of_match); +++++ ++++++++++++ static struct platform_driver asoc_simple_card = { .driver = { .name = "asoc-simple-card",