Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89a88dd3 authored by Mark Brown's avatar Mark Brown
Browse files

Merge tag 'asoc-v4.1' into asoc-next

ASoC: Changes for v4.1

A selection of changes for v4.1 so far.  The main things are:

 - Move of jack registration to the card where it belongs.
 - Support for DAPM routes specified by both the machine driver and DT.

# gpg: Signature made Thu 05 Mar 2015 01:10:27 GMT using RSA key ID 5D5487D0
# gpg: WARNING: digest algorithm MD5 is deprecated
# gpg: please see https://gnupg.org/faq/weak-digest-algos.html for more information
# gpg: Oops: keyid_from_fingerprint: no pubkey
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg:                 aka "Mark Brown <broonie@debian.org>"
# gpg:                 aka "Mark Brown <broonie@kernel.org>"
# gpg:                 aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg:                 aka "Mark Brown <broonie@linaro.org>"
# gpg:                 aka "Mark Brown <Mark.Brown@linaro.org>"
parents 3eaecb4b d7e3281b
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ Required properties:
  * Headphones
  * Headphones
  * Speakers
  * Speakers
  * Mic Jack
  * Mic Jack
  * Int Mic


- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
  connected to the CODEC.
  connected to the CODEC.
+7 −0
Original line number Original line Diff line number Diff line
@@ -366,4 +366,11 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p)
	return snd_pcm_format_physical_width(params_format(p));
	return snd_pcm_format_physical_width(params_format(p));
}
}


static inline void
params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
{
	snd_mask_set(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT),
		(__force int)fmt);
}

#endif /* __SOUND_PCM_PARAMS_H */
#endif /* __SOUND_PCM_PARAMS_H */
+13 −3
Original line number Original line Diff line number Diff line
@@ -450,8 +450,10 @@ int soc_dai_hw_params(struct snd_pcm_substream *substream,
		      struct snd_soc_dai *dai);
		      struct snd_soc_dai *dai);


/* Jack reporting */
/* Jack reporting */
int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
		     struct snd_soc_jack *jack);
	struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins,
	unsigned int num_pins);

void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
			  struct snd_soc_jack_pin *pins);
			  struct snd_soc_jack_pin *pins);
@@ -659,7 +661,7 @@ struct snd_soc_jack_gpio {
struct snd_soc_jack {
struct snd_soc_jack {
	struct mutex mutex;
	struct mutex mutex;
	struct snd_jack *jack;
	struct snd_jack *jack;
	struct snd_soc_codec *codec;
	struct snd_soc_card *card;
	struct list_head pins;
	struct list_head pins;
	int status;
	int status;
	struct blocking_notifier_head notifier;
	struct blocking_notifier_head notifier;
@@ -954,6 +956,9 @@ struct snd_soc_dai_link {
	unsigned int symmetric_channels:1;
	unsigned int symmetric_channels:1;
	unsigned int symmetric_samplebits:1;
	unsigned int symmetric_samplebits:1;


	/* Mark this pcm with non atomic ops */
	bool nonatomic;

	/* Do not create a PCM for this DAI link (Backend link) */
	/* Do not create a PCM for this DAI link (Backend link) */
	unsigned int no_pcm:1;
	unsigned int no_pcm:1;


@@ -1071,11 +1076,16 @@ struct snd_soc_card {


	/*
	/*
	 * Card-specific routes and widgets.
	 * Card-specific routes and widgets.
	 * Note: of_dapm_xxx for Device Tree; Otherwise for driver build-in.
	 */
	 */
	const struct snd_soc_dapm_widget *dapm_widgets;
	const struct snd_soc_dapm_widget *dapm_widgets;
	int num_dapm_widgets;
	int num_dapm_widgets;
	const struct snd_soc_dapm_route *dapm_routes;
	const struct snd_soc_dapm_route *dapm_routes;
	int num_dapm_routes;
	int num_dapm_routes;
	const struct snd_soc_dapm_widget *of_dapm_widgets;
	int num_of_dapm_widgets;
	const struct snd_soc_dapm_route *of_dapm_routes;
	int num_of_dapm_routes;
	bool fully_routed;
	bool fully_routed;


	struct work_struct deferred_resume_work;
	struct work_struct deferred_resume_work;
+107 −4
Original line number Original line Diff line number Diff line
@@ -187,6 +187,94 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


/*
 * When the bit clock is input, limit the maximum rate according to the
 * Serial Clock Ratio Considerations section from the SSC documentation:
 *
 *   The Transmitter and the Receiver can be programmed to operate
 *   with the clock signals provided on either the TK or RK pins.
 *   This allows the SSC to support many slave-mode data transfers.
 *   In this case, the maximum clock speed allowed on the RK pin is:
 *   - Peripheral clock divided by 2 if Receiver Frame Synchro is input
 *   - Peripheral clock divided by 3 if Receiver Frame Synchro is output
 *   In addition, the maximum clock speed allowed on the TK pin is:
 *   - Peripheral clock divided by 6 if Transmit Frame Synchro is input
 *   - Peripheral clock divided by 2 if Transmit Frame Synchro is output
 *
 * When the bit clock is output, limit the rate according to the
 * SSC divider restrictions.
 */
static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
				  struct snd_pcm_hw_rule *rule)
{
	struct atmel_ssc_info *ssc_p = rule->private;
	struct ssc_device *ssc = ssc_p->ssc;
	struct snd_interval *i = hw_param_interval(params, rule->var);
	struct snd_interval t;
	struct snd_ratnum r = {
		.den_min = 1,
		.den_max = 4095,
		.den_step = 1,
	};
	unsigned int num = 0, den = 0;
	int frame_size;
	int mck_div = 2;
	int ret;

	frame_size = snd_soc_params_to_frame_size(params);
	if (frame_size < 0)
		return frame_size;

	switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBM_CFS:
		if ((ssc_p->dir_mask & SSC_DIR_MASK_CAPTURE)
		    && ssc->clk_from_rk_pin)
			/* Receiver Frame Synchro (i.e. capture)
			 * is output (format is _CFS) and the RK pin
			 * is used for input (format is _CBM_).
			 */
			mck_div = 3;
		break;

	case SND_SOC_DAIFMT_CBM_CFM:
		if ((ssc_p->dir_mask & SSC_DIR_MASK_PLAYBACK)
		    && !ssc->clk_from_rk_pin)
			/* Transmit Frame Synchro (i.e. playback)
			 * is input (format is _CFM) and the TK pin
			 * is used for input (format _CBM_ but not
			 * using the RK pin).
			 */
			mck_div = 6;
		break;
	}

	switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
		r.num = ssc_p->mck_rate / mck_div / frame_size;

		ret = snd_interval_ratnum(i, 1, &r, &num, &den);
		if (ret >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {
			params->rate_num = num;
			params->rate_den = den;
		}
		break;

	case SND_SOC_DAIFMT_CBM_CFS:
	case SND_SOC_DAIFMT_CBM_CFM:
		t.min = 8000;
		t.max = ssc_p->mck_rate / mck_div / frame_size;
		t.openmin = t.openmax = 0;
		t.integer = 0;
		ret = snd_interval_refine(i, &t);
		break;

	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}


/*-------------------------------------------------------------------------*\
/*-------------------------------------------------------------------------*\
 * DAI functions
 * DAI functions
@@ -200,6 +288,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
	struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
	struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
	struct atmel_pcm_dma_params *dma_params;
	struct atmel_pcm_dma_params *dma_params;
	int dir, dir_mask;
	int dir, dir_mask;
	int ret;


	pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
	pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
		ssc_readl(ssc_p->ssc->regs, SR));
		ssc_readl(ssc_p->ssc->regs, SR));
@@ -207,6 +296,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
	/* Enable PMC peripheral clock for this SSC */
	/* Enable PMC peripheral clock for this SSC */
	pr_debug("atmel_ssc_dai: Starting clock\n");
	pr_debug("atmel_ssc_dai: Starting clock\n");
	clk_enable(ssc_p->ssc->clk);
	clk_enable(ssc_p->ssc->clk);
	ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk);


	/* Reset the SSC to keep it at a clean status */
	/* Reset the SSC to keep it at a clean status */
	ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
	ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
@@ -219,6 +309,17 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
		dir_mask = SSC_DIR_MASK_CAPTURE;
		dir_mask = SSC_DIR_MASK_CAPTURE;
	}
	}


	ret = snd_pcm_hw_rule_add(substream->runtime, 0,
				  SNDRV_PCM_HW_PARAM_RATE,
				  atmel_ssc_hw_rule_rate,
				  ssc_p,
				  SNDRV_PCM_HW_PARAM_FRAME_BITS,
				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
	if (ret < 0) {
		dev_err(dai->dev, "Failed to specify rate rule: %d\n", ret);
		return ret;
	}

	dma_params = &ssc_dma_params[dai->id][dir];
	dma_params = &ssc_dma_params[dai->id][dir];
	dma_params->ssc = ssc_p->ssc;
	dma_params->ssc = ssc_p->ssc;
	dma_params->substream = substream;
	dma_params->substream = substream;
@@ -783,8 +884,6 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
#  define atmel_ssc_resume	NULL
#  define atmel_ssc_resume	NULL
#endif /* CONFIG_PM */
#endif /* CONFIG_PM */


#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)

#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_LE |\
#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_LE |\
			  SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
			  SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)


@@ -804,12 +903,16 @@ static struct snd_soc_dai_driver atmel_ssc_dai = {
		.playback = {
		.playback = {
			.channels_min = 1,
			.channels_min = 1,
			.channels_max = 2,
			.channels_max = 2,
			.rates = ATMEL_SSC_RATES,
			.rates = SNDRV_PCM_RATE_CONTINUOUS,
			.rate_min = 8000,
			.rate_max = 384000,
			.formats = ATMEL_SSC_FORMATS,},
			.formats = ATMEL_SSC_FORMATS,},
		.capture = {
		.capture = {
			.channels_min = 1,
			.channels_min = 1,
			.channels_max = 2,
			.channels_max = 2,
			.rates = ATMEL_SSC_RATES,
			.rates = SNDRV_PCM_RATE_CONTINUOUS,
			.rate_min = 8000,
			.rate_max = 384000,
			.formats = ATMEL_SSC_FORMATS,},
			.formats = ATMEL_SSC_FORMATS,},
		.ops = &atmel_ssc_dai_ops,
		.ops = &atmel_ssc_dai_ops,
};
};
+1 −0
Original line number Original line Diff line number Diff line
@@ -115,6 +115,7 @@ struct atmel_ssc_info {
	unsigned short rcmr_period;
	unsigned short rcmr_period;
	struct atmel_pcm_dma_params *dma_params[2];
	struct atmel_pcm_dma_params *dma_params[2];
	struct atmel_ssc_state ssc_state;
	struct atmel_ssc_state ssc_state;
	unsigned long mck_rate;
};
};


int atmel_ssc_set_audio(int ssc_id);
int atmel_ssc_set_audio(int ssc_id);
Loading