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

Commit 9dbd627b authored by Timur Tabi's avatar Timur Tabi Committed by Jaroslav Kysela
Browse files

[ALSA] CS4270 driver does not compile with I2C disabled



Fix compilation errors with the CS4270 when I2C is not enabled.  Updated
some comments to indicate that that stand-alone mode is not fully implemented,
because there is no mechanism for the CS4270 driver and the machine driver to
communicate the values of various input pins.

Signed-off-by: default avatarTimur Tabi <timur@freescale.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent b0c813ce
Loading
Loading
Loading
Loading
+172 −147
Original line number Diff line number Diff line
@@ -12,9 +12,11 @@
 *
 * Current features/limitations:
 *
 * 1) Stand-alone and software mode is supported.  Stand-alone is
 *    automatically selected if I2C is disabled or if a CS4270 is not found
 *    on the I2C bus.
 * 1) Software mode is supported.  Stand-alone mode is automatically
 *    selected if I2C is disabled or if a CS4270 is not found on the I2C
 *    bus.  However, stand-alone mode is only partially implemented because
 *    there is no mechanism yet for this driver and the machine driver to
 *    communicate the values of the M0, M1, MCLK1, and MCLK2 pins.
 * 2) Only I2C is supported, not SPI
 * 3) Only Master mode is supported, not Slave.
 * 4) The machine driver's 'startup' function must call
@@ -34,12 +36,157 @@

#include "cs4270.h"

/* If I2C is defined, then we support software mode.  However, if we're
   not compiled as module but I2C is, then we can't use I2C calls. */
#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
#define USE_I2C
#endif

/* Private data for the CS4270 */
struct cs4270_private {
	unsigned int mclk; /* Input frequency of the MCLK pin */
	unsigned int mode; /* The mode (I2S or left-justified) */
};

/* The number of MCLK/LRCK ratios supported by the CS4270 */
#define NUM_MCLK_RATIOS		9

/* The actual MCLK/LRCK ratios, in increasing numerical order */
static unsigned int mclk_ratios[NUM_MCLK_RATIOS] =
	{64, 96, 128, 192, 256, 384, 512, 768, 1024};

/*
 * Sampling rate <-> bit patter mapping
 *
 * This array maps sampling rates to their SNDRV_PCM_RATE_x equivalent.
 *
 * This is really something that ALSA should provide.
 *
 * This table is used by cs4270_set_dai_sysclk() to tell ALSA which sampling
 * rates the CS4270 currently supports.
 */
static struct {
	unsigned int rate;
	unsigned int bit;
} rate_map[] = {
	{5512, SNDRV_PCM_RATE_5512},
	{8000, SNDRV_PCM_RATE_8000},
	{11025, SNDRV_PCM_RATE_11025},
	{16000, SNDRV_PCM_RATE_16000},
	{22050, SNDRV_PCM_RATE_22050},
	{32000, SNDRV_PCM_RATE_32000},
	{44100, SNDRV_PCM_RATE_44100},
	{48000, SNDRV_PCM_RATE_48000},
	{64000, SNDRV_PCM_RATE_64000},
	{88200, SNDRV_PCM_RATE_88200},
	{96000, SNDRV_PCM_RATE_96000},
	{176400, SNDRV_PCM_RATE_176400},
	{192000, SNDRV_PCM_RATE_192000}
};

/*
 * Determine the CS4270 samples rates.
 *
 * 'freq' is the input frequency to MCLK.  The other parameters are ignored.
 *
 * The value of MCLK is used to determine which sample rates are supported
 * by the CS4270.  The ratio of MCLK / Fs must be equal to one of nine
 * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024.
 *
 * This function calculates the nine ratios and determines which ones match
 * a standard sample rate.  If there's a match, then it is added to the list
 * of support sample rates.
 *
 * This function must be called by the machine driver's 'startup' function,
 * otherwise the list of supported sample rates will not be available in
 * time for ALSA.
 *
 * Note that in stand-alone mode, the sample rate is determined by input
 * pins M0, M1, MDIV1, and MDIV2.  Also in stand-alone mode, divide-by-3
 * is not a programmable option.  However, divide-by-3 is not an available
 * option in stand-alone mode.  This cases two problems: a ratio of 768 is
 * not available (it requires divide-by-3) and B) ratios 192 and 384 can
 * only be selected with divide-by-1.5, but there is an errate that make
 * this selection difficult.
 *
 * In addition, there is no mechanism for communicating with the machine
 * driver what the input settings can be.  This would need to be implemented
 * for stand-alone mode to work.
 */
static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
				 int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct cs4270_private *cs4270 = codec->private_data;
	unsigned int rates = 0;
	unsigned int rate_min = -1;
	unsigned int rate_max = 0;
	unsigned int i;

	cs4270->mclk = freq;

	for (i = 0; i < NUM_MCLK_RATIOS; i++) {
		unsigned int rate;
		unsigned int j;
		rate = freq / mclk_ratios[i];
		for (j = 0; j < ARRAY_SIZE(rate_map); j++) {
			if (rate == rate_map[j].rate) {
				rates |= rate_map[j].bit;
				if (rate < rate_min)
					rate_min = rate;
				if (rate > rate_max)
					rate_max = rate;
			}
		}
	}

	if (!rates) {
		printk(KERN_ERR "cs4270: could not find a valid sample rate\n");
		return -EINVAL;
	}

	codec_dai->playback.rates = rates;
	codec_dai->playback.rate_min = rate_min;
	codec_dai->playback.rate_max = rate_max;

	codec_dai->capture.rates = rates;
	codec_dai->capture.rate_min = rate_min;
	codec_dai->capture.rate_max = rate_max;

	return 0;
}

/*
 * Configure the codec for the selected audio format
 *
 * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
 * codec accordingly.
 *
 * Currently, this function only supports SND_SOC_DAIFMT_I2S and
 * SND_SOC_DAIFMT_LEFT_J.  The CS4270 codec also supports right-justified
 * data for playback only, but ASoC currently does not support different
 * formats for playback vs. record.
 */
static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
			      unsigned int format)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct cs4270_private *cs4270 = codec->private_data;
	int ret = 0;

	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
	case SND_SOC_DAIFMT_LEFT_J:
		cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
		break;
	default:
		printk(KERN_ERR "cs4270: invalid DAI format\n");
		ret = -EINVAL;
	}

	return ret;
}

/*
 * The codec isn't really big-endian or little-endian, since the I2S
 * interface requires data to be sent serially with the MSbit first.
@@ -53,7 +200,7 @@ struct cs4270_private {
			SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
			SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE)

#ifdef CONFIG_I2C
#ifdef USE_I2C

/* CS4270 registers addresses */
#define CS4270_CHIPID	0x01	/* Chip ID */
@@ -141,7 +288,7 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec)
		CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache);

	if (length != CS4270_NUMREGS) {
		printk(KERN_ERR "cs4270: I2C read failure, addr=%u\n",
		printk(KERN_ERR "cs4270: I2C read failure, addr=0x%x\n",
		       i2c_client->addr);
		return -EIO;
	}
@@ -189,13 +336,14 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
		cache[reg - CS4270_FIRSTREG] = value;
		return 0;
	} else {
		printk(KERN_ERR "cs4270: I2C write failed\n");
		printk(KERN_ERR "cs4270: I2C write of register %u failed\n",
			reg);
		return -EIO;
	}
}

/*
 * Clock Ratio Selection for Master Mode.
 * Clock Ratio Selection for Master Mode with I2C enabled
 *
 * The data for this chart is taken from Table 5 of the CS4270 reference
 * manual.
@@ -204,10 +352,8 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
 * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling
 * rates the CS4270 currently supports.
 *
 * 'ratio' is the MCLK/LRCK ratio.  MCLK is usually a fixed input frequency,
 * and LRCK is equal to the sampling rate. The CS4270 only supports sampling
 * rates where this ratio is one of: 64, 96, 128, 192, 256, 384, 512, 768 or
 * 1024.
 * Each element in this array corresponds to the ratios in mclk_ratios[].
 * These two arrays need to be in sync.
 *
 * 'speed_mode' is the corresponding bit pattern to be written to the
 * MODE bits of the Mode Control Register
@@ -227,21 +373,20 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
 * never select any sample rates that require divide-by-1.5.
 */
static struct {
	unsigned int ratio;
	u8 speed_mode;
	u8 mclk;
} cs4270_mode_ratios[] = {
	{64, CS4270_MODE_4X, CS4270_MODE_DIV1},
} cs4270_mode_ratios[NUM_MCLK_RATIOS] = {
	{CS4270_MODE_4X, CS4270_MODE_DIV1},	/* 64 */
#ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA
	{96, CS4270_MODE_4X, CS4270_MODE_DIV15},
	{CS4270_MODE_4X, CS4270_MODE_DIV15},    /* 96 */
#endif
	{128, CS4270_MODE_2X, CS4270_MODE_DIV1},
	{192, CS4270_MODE_4X, CS4270_MODE_DIV3},
	{256, CS4270_MODE_1X, CS4270_MODE_DIV1},
	{384, CS4270_MODE_2X, CS4270_MODE_DIV3},
	{512, CS4270_MODE_1X, CS4270_MODE_DIV2},
	{768, CS4270_MODE_1X, CS4270_MODE_DIV3},
	{1024, CS4270_MODE_1X, CS4270_MODE_DIV4}
	{CS4270_MODE_2X, CS4270_MODE_DIV1},     /* 128 */
	{CS4270_MODE_4X, CS4270_MODE_DIV3},     /* 192 */
	{CS4270_MODE_1X, CS4270_MODE_DIV1},     /* 256 */
	{CS4270_MODE_2X, CS4270_MODE_DIV3},     /* 384 */
	{CS4270_MODE_1X, CS4270_MODE_DIV2},     /* 512 */
	{CS4270_MODE_1X, CS4270_MODE_DIV3},     /* 768 */
	{CS4270_MODE_1X, CS4270_MODE_DIV4}      /* 1024 */
};

/*
@@ -270,12 +415,12 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
	rate = params_rate(params);	/* Sampling rate, in Hz */
	ratio = cs4270->mclk / rate;	/* MCLK/LRCK ratio */

	for (i = 0; i < ARRAY_SIZE(cs4270_mode_ratios); i++) {
		if (cs4270_mode_ratios[i].ratio == ratio)
	for (i = 0; i < NUM_MCLK_RATIOS; i++) {
		if (mclk_ratios[i] == ratio)
			break;
	}

	if (i == ARRAY_SIZE(cs4270_mode_ratios)) {
	if (i == NUM_MCLK_RATIOS) {
		/* We did not find a matching ratio */
		printk(KERN_ERR "cs4270: could not find matching ratio\n");
		return -EINVAL;
@@ -377,126 +522,6 @@ static int cs4270_mute(struct snd_soc_codec_dai *dai, int mute)

#endif

/*
 * Sampling rate <-> bit patter mapping
 *
 * This array maps sampling rates to their SNDRV_PCM_RATE_x equivalent.
 *
 * This is really something that ALSA should provide.
 *
 * This table is used by cs4270_set_dai_sysclk() to tell ALSA which sampling
 * rates the CS4270 currently supports.
 */
static struct {
	unsigned int rate;
	unsigned int bit;
} rate_map[] = {
	{5512, SNDRV_PCM_RATE_5512},
	{8000, SNDRV_PCM_RATE_8000},
	{11025, SNDRV_PCM_RATE_11025},
	{16000, SNDRV_PCM_RATE_16000},
	{22050, SNDRV_PCM_RATE_22050},
	{32000, SNDRV_PCM_RATE_32000},
	{44100, SNDRV_PCM_RATE_44100},
	{48000, SNDRV_PCM_RATE_48000},
	{64000, SNDRV_PCM_RATE_64000},
	{88200, SNDRV_PCM_RATE_88200},
	{96000, SNDRV_PCM_RATE_96000},
	{176400, SNDRV_PCM_RATE_176400},
	{192000, SNDRV_PCM_RATE_192000}
};

/*
 * Determine the CS4270 samples rates.
 *
 * 'freq' is the input frequency to MCLK.  The other parameters are ignored.
 *
 * The value of MCLK is used to determine which sample rates are supported
 * by the CS4270.  The ratio of MCLK / Fs must be equal to one of nine
 * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024.
 *
 * This function calculates the nine ratios and determines which ones match
 * a standard sample rate.  If there's a match, then it is added to the list
 * of support sample rates.
 *
 * This function must be called by the machine driver's 'startup' function,
 * otherwise the list of supported sample rates will not be available in
 * time for ALSA.
 */
static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
				 int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct cs4270_private *cs4270 = codec->private_data;
	unsigned int rates = 0;
	unsigned int rate_min = -1;
	unsigned int rate_max = 0;
	unsigned int i;

	cs4270->mclk = freq;

	for (i = 0; i < ARRAY_SIZE(cs4270_mode_ratios); i++) {
		unsigned int rate;
		unsigned int j;
		rate = freq / cs4270_mode_ratios[i].ratio;
		for (j = 0; j < ARRAY_SIZE(rate_map); j++) {
			if (rate == rate_map[j].rate) {
				rates |= rate_map[j].bit;
				if (rate < rate_min)
					rate_min = rate;
				if (rate > rate_max)
					rate_max = rate;
			}
		}
	}

	if (!rate_max) {
		printk(KERN_ERR "cs4270: could not find a valid rate\n");
		return -EINVAL;
	}

	codec_dai->playback.rates = rates;
	codec_dai->playback.rate_min = rate_min;
	codec_dai->playback.rate_max = rate_max;

	codec_dai->capture.rates = rates;
	codec_dai->capture.rate_min = rate_min;
	codec_dai->capture.rate_max = rate_max;

	return 0;
}

/*
 * Configure the codec for the selected audio format
 *
 * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
 * codec accordingly.
 *
 * Currently, this function only supports SND_SOC_DAIFMT_I2S and
 * SND_SOC_DAIFMT_LEFT_J.  The CS4270 codec also supports right-justified
 * data for playback only, but ASoC currently does not support different
 * formats for playback vs. record.
 */
static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
			      unsigned int format)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct cs4270_private *cs4270 = codec->private_data;
	int ret = 0;

	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
	case SND_SOC_DAIFMT_LEFT_J:
		cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
		break;
	default:
		printk(KERN_ERR "cs4270: invalid DAI format\n");
		ret = -EINVAL;
	}

	return ret;
}

static int cs4270_i2c_probe(struct i2c_adapter *adap, int addr, int kind);

/*
@@ -740,7 +765,7 @@ static int cs4270_probe(struct platform_device *pdev)
		return ret;
	}

#ifdef CONFIG_I2C
#ifdef USE_I2C
	cs4270_socdev = socdev;

	ret = i2c_add_driver(&cs4270_i2c_driver);
@@ -780,7 +805,7 @@ static int cs4270_remove(struct platform_device *pdev)

	snd_soc_free_pcms(socdev);

#ifdef CONFIG_I2C
#ifdef USE_I2C
	if (socdev->codec->control_data)
		i2c_del_driver(&cs4270_i2c_driver);
#endif