| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 1 | /* | 
 | 2 |  * CS4270 ALSA SoC (ASoC) codec driver | 
 | 3 |  * | 
 | 4 |  * Author: Timur Tabi <timur@freescale.com> | 
 | 5 |  * | 
 | 6 |  * Copyright 2007 Freescale Semiconductor, Inc.  This file is licensed under | 
 | 7 |  * the terms of the GNU General Public License version 2.  This program | 
 | 8 |  * is licensed "as is" without any warranty of any kind, whether express | 
 | 9 |  * or implied. | 
 | 10 |  * | 
 | 11 |  * This is an ASoC device driver for the Cirrus Logic CS4270 codec. | 
 | 12 |  * | 
 | 13 |  * Current features/limitations: | 
 | 14 |  * | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 15 |  * 1) Software mode is supported.  Stand-alone mode is automatically | 
 | 16 |  *    selected if I2C is disabled or if a CS4270 is not found on the I2C | 
 | 17 |  *    bus.  However, stand-alone mode is only partially implemented because | 
 | 18 |  *    there is no mechanism yet for this driver and the machine driver to | 
 | 19 |  *    communicate the values of the M0, M1, MCLK1, and MCLK2 pins. | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 20 |  * 2) Only I2C is supported, not SPI | 
 | 21 |  * 3) Only Master mode is supported, not Slave. | 
 | 22 |  * 4) The machine driver's 'startup' function must call | 
 | 23 |  *    cs4270_set_dai_sysclk() with the value of MCLK. | 
 | 24 |  * 5) Only I2S and left-justified modes are supported | 
 | 25 |  * 6) Power management is not supported | 
 | 26 |  * 7) The only supported control is volume and hardware mute (if enabled) | 
 | 27 |  */ | 
 | 28 |  | 
 | 29 | #include <linux/module.h> | 
 | 30 | #include <linux/platform_device.h> | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 31 | #include <sound/core.h> | 
 | 32 | #include <sound/soc.h> | 
 | 33 | #include <sound/initval.h> | 
 | 34 | #include <linux/i2c.h> | 
 | 35 |  | 
 | 36 | #include "cs4270.h" | 
 | 37 |  | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 38 | /* If I2C is defined, then we support software mode.  However, if we're | 
 | 39 |    not compiled as module but I2C is, then we can't use I2C calls. */ | 
 | 40 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | 
 | 41 | #define USE_I2C | 
 | 42 | #endif | 
 | 43 |  | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 44 | /* Private data for the CS4270 */ | 
 | 45 | struct cs4270_private { | 
 | 46 | 	unsigned int mclk; /* Input frequency of the MCLK pin */ | 
 | 47 | 	unsigned int mode; /* The mode (I2S or left-justified) */ | 
 | 48 | }; | 
 | 49 |  | 
 | 50 | /* | 
 | 51 |  * The codec isn't really big-endian or little-endian, since the I2S | 
 | 52 |  * interface requires data to be sent serially with the MSbit first. | 
 | 53 |  * However, to support BE and LE I2S devices, we specify both here.  That | 
 | 54 |  * way, ALSA will always match the bit patterns. | 
 | 55 |  */ | 
 | 56 | #define CS4270_FORMATS (SNDRV_PCM_FMTBIT_S8      | \ | 
 | 57 | 			SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S16_BE  | \ | 
 | 58 | 			SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | 
 | 59 | 			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | 
 | 60 | 			SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | 
 | 61 | 			SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE) | 
 | 62 |  | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 63 | #ifdef USE_I2C | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 64 |  | 
 | 65 | /* CS4270 registers addresses */ | 
 | 66 | #define CS4270_CHIPID	0x01	/* Chip ID */ | 
 | 67 | #define CS4270_PWRCTL	0x02	/* Power Control */ | 
 | 68 | #define CS4270_MODE	0x03	/* Mode Control */ | 
 | 69 | #define CS4270_FORMAT	0x04	/* Serial Format, ADC/DAC Control */ | 
 | 70 | #define CS4270_TRANS	0x05	/* Transition Control */ | 
 | 71 | #define CS4270_MUTE	0x06	/* Mute Control */ | 
 | 72 | #define CS4270_VOLA	0x07	/* DAC Channel A Volume Control */ | 
 | 73 | #define CS4270_VOLB	0x08	/* DAC Channel B Volume Control */ | 
 | 74 |  | 
 | 75 | #define CS4270_FIRSTREG	0x01 | 
 | 76 | #define CS4270_LASTREG	0x08 | 
 | 77 | #define CS4270_NUMREGS	(CS4270_LASTREG - CS4270_FIRSTREG + 1) | 
 | 78 |  | 
 | 79 | /* Bit masks for the CS4270 registers */ | 
 | 80 | #define CS4270_CHIPID_ID	0xF0 | 
 | 81 | #define CS4270_CHIPID_REV	0x0F | 
 | 82 | #define CS4270_PWRCTL_FREEZE	0x80 | 
 | 83 | #define CS4270_PWRCTL_PDN_ADC	0x20 | 
 | 84 | #define CS4270_PWRCTL_PDN_DAC	0x02 | 
 | 85 | #define CS4270_PWRCTL_PDN	0x01 | 
 | 86 | #define CS4270_MODE_SPEED_MASK	0x30 | 
 | 87 | #define CS4270_MODE_1X		0x00 | 
 | 88 | #define CS4270_MODE_2X		0x10 | 
 | 89 | #define CS4270_MODE_4X		0x20 | 
 | 90 | #define CS4270_MODE_SLAVE	0x30 | 
 | 91 | #define CS4270_MODE_DIV_MASK	0x0E | 
 | 92 | #define CS4270_MODE_DIV1	0x00 | 
 | 93 | #define CS4270_MODE_DIV15	0x02 | 
 | 94 | #define CS4270_MODE_DIV2	0x04 | 
 | 95 | #define CS4270_MODE_DIV3	0x06 | 
 | 96 | #define CS4270_MODE_DIV4	0x08 | 
 | 97 | #define CS4270_MODE_POPGUARD	0x01 | 
 | 98 | #define CS4270_FORMAT_FREEZE_A	0x80 | 
 | 99 | #define CS4270_FORMAT_FREEZE_B	0x40 | 
 | 100 | #define CS4270_FORMAT_LOOPBACK	0x20 | 
 | 101 | #define CS4270_FORMAT_DAC_MASK	0x18 | 
 | 102 | #define CS4270_FORMAT_DAC_LJ	0x00 | 
 | 103 | #define CS4270_FORMAT_DAC_I2S	0x08 | 
 | 104 | #define CS4270_FORMAT_DAC_RJ16	0x18 | 
 | 105 | #define CS4270_FORMAT_DAC_RJ24	0x10 | 
 | 106 | #define CS4270_FORMAT_ADC_MASK	0x01 | 
 | 107 | #define CS4270_FORMAT_ADC_LJ	0x00 | 
 | 108 | #define CS4270_FORMAT_ADC_I2S	0x01 | 
 | 109 | #define CS4270_TRANS_ONE_VOL	0x80 | 
 | 110 | #define CS4270_TRANS_SOFT	0x40 | 
 | 111 | #define CS4270_TRANS_ZERO	0x20 | 
 | 112 | #define CS4270_TRANS_INV_ADC_A	0x08 | 
 | 113 | #define CS4270_TRANS_INV_ADC_B	0x10 | 
 | 114 | #define CS4270_TRANS_INV_DAC_A	0x02 | 
 | 115 | #define CS4270_TRANS_INV_DAC_B	0x04 | 
 | 116 | #define CS4270_TRANS_DEEMPH	0x01 | 
 | 117 | #define CS4270_MUTE_AUTO	0x20 | 
 | 118 | #define CS4270_MUTE_ADC_A	0x08 | 
 | 119 | #define CS4270_MUTE_ADC_B	0x10 | 
 | 120 | #define CS4270_MUTE_POLARITY	0x04 | 
 | 121 | #define CS4270_MUTE_DAC_A	0x01 | 
 | 122 | #define CS4270_MUTE_DAC_B	0x02 | 
 | 123 |  | 
 | 124 | /* | 
| Timur Tabi | 8432395 | 2007-12-18 15:42:53 +0100 | [diff] [blame] | 125 |  * Clock Ratio Selection for Master Mode with I2C enabled | 
 | 126 |  * | 
 | 127 |  * The data for this chart is taken from Table 5 of the CS4270 reference | 
 | 128 |  * manual. | 
 | 129 |  * | 
 | 130 |  * This table is used to determine how to program the Mode Control register. | 
 | 131 |  * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling | 
 | 132 |  * rates the CS4270 currently supports. | 
 | 133 |  * | 
 | 134 |  * Each element in this array corresponds to the ratios in mclk_ratios[]. | 
 | 135 |  * These two arrays need to be in sync. | 
 | 136 |  * | 
 | 137 |  * 'speed_mode' is the corresponding bit pattern to be written to the | 
 | 138 |  * MODE bits of the Mode Control Register | 
 | 139 |  * | 
 | 140 |  * 'mclk' is the corresponding bit pattern to be wirten to the MCLK bits of | 
 | 141 |  * the Mode Control Register. | 
 | 142 |  * | 
 | 143 |  * In situations where a single ratio is represented by multiple speed | 
 | 144 |  * modes, we favor the slowest speed.  E.g, for a ratio of 128, we pick | 
 | 145 |  * double-speed instead of quad-speed.  However, the CS4270 errata states | 
 | 146 |  * that Divide-By-1.5 can cause failures, so we avoid that mode where | 
 | 147 |  * possible. | 
 | 148 |  * | 
 | 149 |  * ERRATA: There is an errata for the CS4270 where divide-by-1.5 does not | 
 | 150 |  * work if VD = 3.3V.  If this effects you, select the | 
 | 151 |  * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will | 
 | 152 |  * never select any sample rates that require divide-by-1.5. | 
 | 153 |  */ | 
 | 154 | static struct { | 
 | 155 | 	unsigned int ratio; | 
 | 156 | 	u8 speed_mode; | 
 | 157 | 	u8 mclk; | 
 | 158 | } cs4270_mode_ratios[] = { | 
 | 159 | 	{64, CS4270_MODE_4X, CS4270_MODE_DIV1}, | 
 | 160 | #ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA | 
 | 161 | 	{96, CS4270_MODE_4X, CS4270_MODE_DIV15}, | 
 | 162 | #endif | 
 | 163 | 	{128, CS4270_MODE_2X, CS4270_MODE_DIV1}, | 
 | 164 | 	{192, CS4270_MODE_4X, CS4270_MODE_DIV3}, | 
 | 165 | 	{256, CS4270_MODE_1X, CS4270_MODE_DIV1}, | 
 | 166 | 	{384, CS4270_MODE_2X, CS4270_MODE_DIV3}, | 
 | 167 | 	{512, CS4270_MODE_1X, CS4270_MODE_DIV2}, | 
 | 168 | 	{768, CS4270_MODE_1X, CS4270_MODE_DIV3}, | 
 | 169 | 	{1024, CS4270_MODE_1X, CS4270_MODE_DIV4} | 
 | 170 | }; | 
 | 171 |  | 
 | 172 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | 
 | 173 | #define NUM_MCLK_RATIOS		ARRAY_SIZE(cs4270_mode_ratios) | 
 | 174 |  | 
 | 175 | /* | 
 | 176 |  * Determine the CS4270 samples rates. | 
 | 177 |  * | 
 | 178 |  * 'freq' is the input frequency to MCLK.  The other parameters are ignored. | 
 | 179 |  * | 
 | 180 |  * The value of MCLK is used to determine which sample rates are supported | 
 | 181 |  * by the CS4270.  The ratio of MCLK / Fs must be equal to one of nine | 
 | 182 |  * support values: 64, 96, 128, 192, 256, 384, 512, 768, and 1024. | 
 | 183 |  * | 
 | 184 |  * This function calculates the nine ratios and determines which ones match | 
 | 185 |  * a standard sample rate.  If there's a match, then it is added to the list | 
 | 186 |  * of support sample rates. | 
 | 187 |  * | 
 | 188 |  * This function must be called by the machine driver's 'startup' function, | 
 | 189 |  * otherwise the list of supported sample rates will not be available in | 
 | 190 |  * time for ALSA. | 
 | 191 |  * | 
 | 192 |  * Note that in stand-alone mode, the sample rate is determined by input | 
 | 193 |  * pins M0, M1, MDIV1, and MDIV2.  Also in stand-alone mode, divide-by-3 | 
 | 194 |  * is not a programmable option.  However, divide-by-3 is not an available | 
 | 195 |  * option in stand-alone mode.  This cases two problems: a ratio of 768 is | 
 | 196 |  * not available (it requires divide-by-3) and B) ratios 192 and 384 can | 
 | 197 |  * only be selected with divide-by-1.5, but there is an errate that make | 
 | 198 |  * this selection difficult. | 
 | 199 |  * | 
 | 200 |  * In addition, there is no mechanism for communicating with the machine | 
 | 201 |  * driver what the input settings can be.  This would need to be implemented | 
 | 202 |  * for stand-alone mode to work. | 
 | 203 |  */ | 
| Liam Girdwood | e550e17 | 2008-07-07 16:07:52 +0100 | [diff] [blame] | 204 | static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 
| Timur Tabi | 8432395 | 2007-12-18 15:42:53 +0100 | [diff] [blame] | 205 | 				 int clk_id, unsigned int freq, int dir) | 
 | 206 | { | 
 | 207 | 	struct snd_soc_codec *codec = codec_dai->codec; | 
 | 208 | 	struct cs4270_private *cs4270 = codec->private_data; | 
 | 209 | 	unsigned int rates = 0; | 
 | 210 | 	unsigned int rate_min = -1; | 
 | 211 | 	unsigned int rate_max = 0; | 
 | 212 | 	unsigned int i; | 
 | 213 |  | 
 | 214 | 	cs4270->mclk = freq; | 
 | 215 |  | 
 | 216 | 	for (i = 0; i < NUM_MCLK_RATIOS; i++) { | 
 | 217 | 		unsigned int rate = freq / cs4270_mode_ratios[i].ratio; | 
 | 218 | 		rates |= snd_pcm_rate_to_rate_bit(rate); | 
 | 219 | 		if (rate < rate_min) | 
 | 220 | 			rate_min = rate; | 
 | 221 | 		if (rate > rate_max) | 
 | 222 | 			rate_max = rate; | 
 | 223 | 	} | 
 | 224 | 	/* FIXME: soc should support a rate list */ | 
 | 225 | 	rates &= ~SNDRV_PCM_RATE_KNOT; | 
 | 226 |  | 
 | 227 | 	if (!rates) { | 
 | 228 | 		printk(KERN_ERR "cs4270: could not find a valid sample rate\n"); | 
 | 229 | 		return -EINVAL; | 
 | 230 | 	} | 
 | 231 |  | 
 | 232 | 	codec_dai->playback.rates = rates; | 
 | 233 | 	codec_dai->playback.rate_min = rate_min; | 
 | 234 | 	codec_dai->playback.rate_max = rate_max; | 
 | 235 |  | 
 | 236 | 	codec_dai->capture.rates = rates; | 
 | 237 | 	codec_dai->capture.rate_min = rate_min; | 
 | 238 | 	codec_dai->capture.rate_max = rate_max; | 
 | 239 |  | 
 | 240 | 	return 0; | 
 | 241 | } | 
 | 242 |  | 
 | 243 | /* | 
 | 244 |  * Configure the codec for the selected audio format | 
 | 245 |  * | 
 | 246 |  * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the | 
 | 247 |  * codec accordingly. | 
 | 248 |  * | 
 | 249 |  * Currently, this function only supports SND_SOC_DAIFMT_I2S and | 
 | 250 |  * SND_SOC_DAIFMT_LEFT_J.  The CS4270 codec also supports right-justified | 
 | 251 |  * data for playback only, but ASoC currently does not support different | 
 | 252 |  * formats for playback vs. record. | 
 | 253 |  */ | 
| Liam Girdwood | e550e17 | 2008-07-07 16:07:52 +0100 | [diff] [blame] | 254 | static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, | 
| Timur Tabi | 8432395 | 2007-12-18 15:42:53 +0100 | [diff] [blame] | 255 | 			      unsigned int format) | 
 | 256 | { | 
 | 257 | 	struct snd_soc_codec *codec = codec_dai->codec; | 
 | 258 | 	struct cs4270_private *cs4270 = codec->private_data; | 
 | 259 | 	int ret = 0; | 
 | 260 |  | 
 | 261 | 	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | 
 | 262 | 	case SND_SOC_DAIFMT_I2S: | 
 | 263 | 	case SND_SOC_DAIFMT_LEFT_J: | 
 | 264 | 		cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK; | 
 | 265 | 		break; | 
 | 266 | 	default: | 
 | 267 | 		printk(KERN_ERR "cs4270: invalid DAI format\n"); | 
 | 268 | 		ret = -EINVAL; | 
 | 269 | 	} | 
 | 270 |  | 
 | 271 | 	return ret; | 
 | 272 | } | 
 | 273 |  | 
 | 274 | /* | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 275 |  * A list of addresses on which this CS4270 could use.  I2C addresses are | 
 | 276 |  * 7 bits.  For the CS4270, the upper four bits are always 1001, and the | 
 | 277 |  * lower three bits are determined via the AD2, AD1, and AD0 pins | 
 | 278 |  * (respectively). | 
 | 279 |  */ | 
| Jean Delvare | 2cdddeb | 2008-01-27 18:14:47 +0100 | [diff] [blame] | 280 | static const unsigned short normal_i2c[] = { | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 281 | 	0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END | 
 | 282 | }; | 
 | 283 | I2C_CLIENT_INSMOD; | 
 | 284 |  | 
 | 285 | /* | 
 | 286 |  * Pre-fill the CS4270 register cache. | 
 | 287 |  * | 
 | 288 |  * We use the auto-increment feature of the CS4270 to read all registers in | 
 | 289 |  * one shot. | 
 | 290 |  */ | 
 | 291 | static int cs4270_fill_cache(struct snd_soc_codec *codec) | 
 | 292 | { | 
 | 293 | 	u8 *cache = codec->reg_cache; | 
 | 294 | 	struct i2c_client *i2c_client = codec->control_data; | 
 | 295 | 	s32 length; | 
 | 296 |  | 
 | 297 | 	length = i2c_smbus_read_i2c_block_data(i2c_client, | 
 | 298 | 		CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache); | 
 | 299 |  | 
 | 300 | 	if (length != CS4270_NUMREGS) { | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 301 | 		printk(KERN_ERR "cs4270: I2C read failure, addr=0x%x\n", | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 302 | 		       i2c_client->addr); | 
 | 303 | 		return -EIO; | 
 | 304 | 	} | 
 | 305 |  | 
 | 306 | 	return 0; | 
 | 307 | } | 
 | 308 |  | 
 | 309 | /* | 
 | 310 |  * Read from the CS4270 register cache. | 
 | 311 |  * | 
 | 312 |  * This CS4270 registers are cached to avoid excessive I2C I/O operations. | 
 | 313 |  * After the initial read to pre-fill the cache, the CS4270 never updates | 
 | 314 |  * the register values, so we won't have a cache coherncy problem. | 
 | 315 |  */ | 
 | 316 | static unsigned int cs4270_read_reg_cache(struct snd_soc_codec *codec, | 
 | 317 | 	unsigned int reg) | 
 | 318 | { | 
 | 319 | 	u8 *cache = codec->reg_cache; | 
 | 320 |  | 
 | 321 | 	if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) | 
 | 322 | 		return -EIO; | 
 | 323 |  | 
 | 324 | 	return cache[reg - CS4270_FIRSTREG]; | 
 | 325 | } | 
 | 326 |  | 
 | 327 | /* | 
 | 328 |  * Write to a CS4270 register via the I2C bus. | 
 | 329 |  * | 
 | 330 |  * This function writes the given value to the given CS4270 register, and | 
 | 331 |  * also updates the register cache. | 
 | 332 |  * | 
 | 333 |  * Note that we don't use the hw_write function pointer of snd_soc_codec. | 
 | 334 |  * That's because it's too clunky: the hw_write_t prototype does not match | 
 | 335 |  * i2c_smbus_write_byte_data(), and it's just another layer of overhead. | 
 | 336 |  */ | 
 | 337 | static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, | 
 | 338 | 			    unsigned int value) | 
 | 339 | { | 
| Timur Tabi | bfc4e86 | 2007-09-11 00:45:50 +0200 | [diff] [blame] | 340 | 	u8 *cache = codec->reg_cache; | 
 | 341 |  | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 342 | 	if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) | 
 | 343 | 		return -EIO; | 
 | 344 |  | 
| Timur Tabi | bfc4e86 | 2007-09-11 00:45:50 +0200 | [diff] [blame] | 345 | 	/* Only perform an I2C operation if the new value is different */ | 
 | 346 | 	if (cache[reg - CS4270_FIRSTREG] != value) { | 
 | 347 | 		struct i2c_client *client = codec->control_data; | 
 | 348 | 		if (i2c_smbus_write_byte_data(client, reg, value)) { | 
 | 349 | 			printk(KERN_ERR "cs4270: I2C write failed\n"); | 
 | 350 | 			return -EIO; | 
 | 351 | 		} | 
 | 352 |  | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 353 | 		/* We've written to the hardware, so update the cache */ | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 354 | 		cache[reg - CS4270_FIRSTREG] = value; | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 355 | 	} | 
| Timur Tabi | bfc4e86 | 2007-09-11 00:45:50 +0200 | [diff] [blame] | 356 |  | 
 | 357 | 	return 0; | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 358 | } | 
 | 359 |  | 
 | 360 | /* | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 361 |  * Program the CS4270 with the given hardware parameters. | 
 | 362 |  * | 
 | 363 |  * The .dai_ops functions are used to provide board-specific data, like | 
 | 364 |  * input frequencies, to this driver.  This function takes that information, | 
 | 365 |  * combines it with the hardware parameters provided, and programs the | 
 | 366 |  * hardware accordingly. | 
 | 367 |  */ | 
 | 368 | static int cs4270_hw_params(struct snd_pcm_substream *substream, | 
 | 369 | 			    struct snd_pcm_hw_params *params) | 
 | 370 | { | 
 | 371 | 	struct snd_soc_pcm_runtime *rtd = substream->private_data; | 
 | 372 | 	struct snd_soc_device *socdev = rtd->socdev; | 
 | 373 | 	struct snd_soc_codec *codec = socdev->codec; | 
 | 374 | 	struct cs4270_private *cs4270 = codec->private_data; | 
| Roel Kluin | e34ba21 | 2008-04-17 18:58:34 +0200 | [diff] [blame] | 375 | 	int ret; | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 376 | 	unsigned int i; | 
 | 377 | 	unsigned int rate; | 
 | 378 | 	unsigned int ratio; | 
 | 379 | 	int reg; | 
 | 380 |  | 
 | 381 | 	/* Figure out which MCLK/LRCK ratio to use */ | 
 | 382 |  | 
 | 383 | 	rate = params_rate(params);	/* Sampling rate, in Hz */ | 
 | 384 | 	ratio = cs4270->mclk / rate;	/* MCLK/LRCK ratio */ | 
 | 385 |  | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 386 | 	for (i = 0; i < NUM_MCLK_RATIOS; i++) { | 
| Timur Tabi | 8432395 | 2007-12-18 15:42:53 +0100 | [diff] [blame] | 387 | 		if (cs4270_mode_ratios[i].ratio == ratio) | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 388 | 			break; | 
 | 389 | 	} | 
 | 390 |  | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 391 | 	if (i == NUM_MCLK_RATIOS) { | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 392 | 		/* We did not find a matching ratio */ | 
 | 393 | 		printk(KERN_ERR "cs4270: could not find matching ratio\n"); | 
 | 394 | 		return -EINVAL; | 
 | 395 | 	} | 
 | 396 |  | 
 | 397 | 	/* Freeze and power-down the codec */ | 
 | 398 |  | 
 | 399 | 	ret = snd_soc_write(codec, CS4270_PWRCTL, CS4270_PWRCTL_FREEZE | | 
 | 400 | 			    CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | | 
 | 401 | 			    CS4270_PWRCTL_PDN); | 
 | 402 | 	if (ret < 0) { | 
 | 403 | 		printk(KERN_ERR "cs4270: I2C write failed\n"); | 
 | 404 | 		return ret; | 
 | 405 | 	} | 
 | 406 |  | 
 | 407 | 	/* Program the mode control register */ | 
 | 408 |  | 
 | 409 | 	reg = snd_soc_read(codec, CS4270_MODE); | 
 | 410 | 	reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); | 
 | 411 | 	reg |= cs4270_mode_ratios[i].speed_mode | cs4270_mode_ratios[i].mclk; | 
 | 412 |  | 
 | 413 | 	ret = snd_soc_write(codec, CS4270_MODE, reg); | 
 | 414 | 	if (ret < 0) { | 
 | 415 | 		printk(KERN_ERR "cs4270: I2C write failed\n"); | 
 | 416 | 		return ret; | 
 | 417 | 	} | 
 | 418 |  | 
 | 419 | 	/* Program the format register */ | 
 | 420 |  | 
 | 421 | 	reg = snd_soc_read(codec, CS4270_FORMAT); | 
 | 422 | 	reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); | 
 | 423 |  | 
 | 424 | 	switch (cs4270->mode) { | 
 | 425 | 	case SND_SOC_DAIFMT_I2S: | 
 | 426 | 		reg |= CS4270_FORMAT_DAC_I2S | CS4270_FORMAT_ADC_I2S; | 
 | 427 | 		break; | 
 | 428 | 	case SND_SOC_DAIFMT_LEFT_J: | 
 | 429 | 		reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ; | 
 | 430 | 		break; | 
 | 431 | 	default: | 
 | 432 | 		printk(KERN_ERR "cs4270: unknown format\n"); | 
 | 433 | 		return -EINVAL; | 
 | 434 | 	} | 
 | 435 |  | 
 | 436 | 	ret = snd_soc_write(codec, CS4270_FORMAT, reg); | 
 | 437 | 	if (ret < 0) { | 
 | 438 | 		printk(KERN_ERR "cs4270: I2C write failed\n"); | 
 | 439 | 		return ret; | 
 | 440 | 	} | 
 | 441 |  | 
 | 442 | 	/* Disable auto-mute.  This feature appears to be buggy, because in | 
 | 443 | 	   some situations, auto-mute will not deactivate when it should. */ | 
 | 444 |  | 
 | 445 | 	reg = snd_soc_read(codec, CS4270_MUTE); | 
 | 446 | 	reg &= ~CS4270_MUTE_AUTO; | 
 | 447 | 	ret = snd_soc_write(codec, CS4270_MUTE, reg); | 
 | 448 | 	if (ret < 0) { | 
 | 449 | 		printk(KERN_ERR "cs4270: I2C write failed\n"); | 
 | 450 | 		return ret; | 
 | 451 | 	} | 
 | 452 |  | 
 | 453 | 	/* Thaw and power-up the codec */ | 
 | 454 |  | 
 | 455 | 	ret = snd_soc_write(codec, CS4270_PWRCTL, 0); | 
 | 456 | 	if (ret < 0) { | 
 | 457 | 		printk(KERN_ERR "cs4270: I2C write failed\n"); | 
 | 458 | 		return ret; | 
 | 459 | 	} | 
 | 460 |  | 
 | 461 | 	return ret; | 
 | 462 | } | 
 | 463 |  | 
 | 464 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | 
 | 465 |  | 
 | 466 | /* | 
 | 467 |  * Set the CS4270 external mute | 
 | 468 |  * | 
 | 469 |  * This function toggles the mute bits in the MUTE register.  The CS4270's | 
 | 470 |  * mute capability is intended for external muting circuitry, so if the | 
 | 471 |  * board does not have the MUTEA or MUTEB pins connected to such circuitry, | 
 | 472 |  * then this function will do nothing. | 
 | 473 |  */ | 
| Liam Girdwood | e550e17 | 2008-07-07 16:07:52 +0100 | [diff] [blame] | 474 | static int cs4270_mute(struct snd_soc_dai *dai, int mute) | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 475 | { | 
 | 476 | 	struct snd_soc_codec *codec = dai->codec; | 
 | 477 | 	int reg6; | 
 | 478 |  | 
 | 479 | 	reg6 = snd_soc_read(codec, CS4270_MUTE); | 
 | 480 |  | 
 | 481 | 	if (mute) | 
 | 482 | 		reg6 |= CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | 
 | 483 | 			CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; | 
 | 484 | 	else | 
 | 485 | 		reg6 &= ~(CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | 
 | 486 | 			  CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); | 
 | 487 |  | 
 | 488 | 	return snd_soc_write(codec, CS4270_MUTE, reg6); | 
 | 489 | } | 
 | 490 |  | 
 | 491 | #endif | 
 | 492 |  | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 493 | static int cs4270_i2c_probe(struct i2c_adapter *adap, int addr, int kind); | 
 | 494 |  | 
 | 495 | /* | 
 | 496 |  * Notify the driver that a new I2C bus has been found. | 
 | 497 |  * | 
 | 498 |  * This function is called for each I2C bus in the system.  The function | 
 | 499 |  * then asks the I2C subsystem to probe that bus at the addresses on which | 
 | 500 |  * our device (the CS4270) could exist.  If a device is found at one of | 
 | 501 |  * those addresses, then our probe function (cs4270_i2c_probe) is called. | 
 | 502 |  */ | 
 | 503 | static int cs4270_i2c_attach(struct i2c_adapter *adapter) | 
 | 504 | { | 
 | 505 | 	return i2c_probe(adapter, &addr_data, cs4270_i2c_probe); | 
 | 506 | } | 
 | 507 |  | 
 | 508 | static int cs4270_i2c_detach(struct i2c_client *client) | 
 | 509 | { | 
 | 510 | 	struct snd_soc_codec *codec = i2c_get_clientdata(client); | 
 | 511 |  | 
 | 512 | 	i2c_detach_client(client); | 
 | 513 | 	codec->control_data = NULL; | 
 | 514 |  | 
 | 515 | 	kfree(codec->reg_cache); | 
 | 516 | 	codec->reg_cache = NULL; | 
 | 517 |  | 
 | 518 | 	kfree(client); | 
 | 519 | 	return 0; | 
 | 520 | } | 
 | 521 |  | 
 | 522 | /* A list of non-DAPM controls that the CS4270 supports */ | 
 | 523 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { | 
 | 524 | 	SOC_DOUBLE_R("Master Playback Volume", | 
| Timur Tabi | bfc4e86 | 2007-09-11 00:45:50 +0200 | [diff] [blame] | 525 | 		CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 526 | }; | 
 | 527 |  | 
 | 528 | static struct i2c_driver cs4270_i2c_driver = { | 
 | 529 | 	.driver = { | 
 | 530 | 		.name = "CS4270 I2C", | 
 | 531 | 		.owner = THIS_MODULE, | 
 | 532 | 	}, | 
 | 533 | 	.id =             I2C_DRIVERID_CS4270, | 
 | 534 | 	.attach_adapter = cs4270_i2c_attach, | 
 | 535 | 	.detach_client =  cs4270_i2c_detach, | 
 | 536 | }; | 
 | 537 |  | 
 | 538 | /* | 
 | 539 |  * Global variable to store socdev for i2c probe function. | 
 | 540 |  * | 
 | 541 |  * If struct i2c_driver had a private_data field, we wouldn't need to use | 
 | 542 |  * cs4270_socdec.  This is the only way to pass the socdev structure to | 
 | 543 |  * cs4270_i2c_probe(). | 
 | 544 |  * | 
 | 545 |  * The real solution to cs4270_socdev is to create a mechanism | 
 | 546 |  * that maps I2C addresses to snd_soc_device structures.  Perhaps the | 
 | 547 |  * creation of the snd_soc_device object should be moved out of | 
 | 548 |  * cs4270_probe() and into cs4270_i2c_probe(), but that would make this | 
 | 549 |  * driver dependent on I2C.  The CS4270 supports "stand-alone" mode, whereby | 
 | 550 |  * the chip is *not* connected to the I2C bus, but is instead configured via | 
 | 551 |  * input pins. | 
 | 552 |  */ | 
 | 553 | static struct snd_soc_device *cs4270_socdev; | 
 | 554 |  | 
 | 555 | /* | 
 | 556 |  * Initialize the I2C interface of the CS4270 | 
 | 557 |  * | 
 | 558 |  * This function is called for whenever the I2C subsystem finds a device | 
 | 559 |  * at a particular address. | 
 | 560 |  * | 
 | 561 |  * Note: snd_soc_new_pcms() must be called before this function can be called, | 
 | 562 |  * because of snd_ctl_add(). | 
 | 563 |  */ | 
 | 564 | static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) | 
 | 565 | { | 
 | 566 | 	struct snd_soc_device *socdev = cs4270_socdev; | 
 | 567 | 	struct snd_soc_codec *codec = socdev->codec; | 
 | 568 | 	struct i2c_client *i2c_client = NULL; | 
 | 569 | 	int i; | 
 | 570 | 	int ret = 0; | 
 | 571 |  | 
 | 572 | 	/* Probing all possible addresses has one drawback: if there are | 
 | 573 | 	   multiple CS4270s on the bus, then you cannot specify which | 
 | 574 | 	   socdev is matched with which CS4270.  For now, we just reject | 
 | 575 | 	   this I2C device if the socdev already has one attached. */ | 
 | 576 | 	if (codec->control_data) | 
 | 577 | 		return -ENODEV; | 
 | 578 |  | 
 | 579 | 	/* Note: codec_dai->codec is NULL here */ | 
 | 580 |  | 
 | 581 | 	i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 
 | 582 | 	if (!i2c_client) { | 
 | 583 | 		printk(KERN_ERR "cs4270: could not allocate I2C client\n"); | 
 | 584 | 		return -ENOMEM; | 
 | 585 | 	} | 
 | 586 |  | 
 | 587 | 	codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); | 
 | 588 | 	if (!codec->reg_cache) { | 
 | 589 | 		printk(KERN_ERR "cs4270: could not allocate register cache\n"); | 
 | 590 | 		ret = -ENOMEM; | 
 | 591 | 		goto error; | 
 | 592 | 	} | 
 | 593 |  | 
 | 594 | 	i2c_set_clientdata(i2c_client, codec); | 
 | 595 | 	strcpy(i2c_client->name, "CS4270"); | 
 | 596 |  | 
 | 597 | 	i2c_client->driver = &cs4270_i2c_driver; | 
 | 598 | 	i2c_client->adapter = adapter; | 
 | 599 | 	i2c_client->addr = addr; | 
 | 600 |  | 
 | 601 | 	/* Verify that we have a CS4270 */ | 
 | 602 |  | 
 | 603 | 	ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | 
 | 604 | 	if (ret < 0) { | 
 | 605 | 		printk(KERN_ERR "cs4270: failed to read I2C\n"); | 
 | 606 | 		goto error; | 
 | 607 | 	} | 
 | 608 | 	/* The top four bits of the chip ID should be 1100. */ | 
 | 609 | 	if ((ret & 0xF0) != 0xC0) { | 
 | 610 | 		/* The device at this address is not a CS4270 codec */ | 
 | 611 | 		ret = -ENODEV; | 
 | 612 | 		goto error; | 
 | 613 | 	} | 
 | 614 |  | 
 | 615 | 	printk(KERN_INFO "cs4270: found device at I2C address %X\n", addr); | 
 | 616 | 	printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); | 
 | 617 |  | 
 | 618 | 	/* Tell the I2C layer a new client has arrived */ | 
 | 619 |  | 
 | 620 | 	ret = i2c_attach_client(i2c_client); | 
 | 621 | 	if (ret) { | 
 | 622 | 		printk(KERN_ERR "cs4270: could not attach codec, " | 
 | 623 | 			"I2C address %x, error code %i\n", addr, ret); | 
 | 624 | 		goto error; | 
 | 625 | 	} | 
 | 626 |  | 
 | 627 | 	codec->control_data = i2c_client; | 
 | 628 | 	codec->read = cs4270_read_reg_cache; | 
 | 629 | 	codec->write = cs4270_i2c_write; | 
 | 630 | 	codec->reg_cache_size = CS4270_NUMREGS; | 
 | 631 |  | 
 | 632 | 	/* The I2C interface is set up, so pre-fill our register cache */ | 
 | 633 |  | 
 | 634 | 	ret = cs4270_fill_cache(codec); | 
 | 635 | 	if (ret < 0) { | 
 | 636 | 		printk(KERN_ERR "cs4270: failed to fill register cache\n"); | 
 | 637 | 		goto error; | 
 | 638 | 	} | 
 | 639 |  | 
 | 640 | 	/* Add the non-DAPM controls */ | 
 | 641 |  | 
 | 642 | 	for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { | 
 | 643 | 		struct snd_kcontrol *kctrl = | 
 | 644 | 		snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); | 
 | 645 |  | 
 | 646 | 		ret = snd_ctl_add(codec->card, kctrl); | 
 | 647 | 		if (ret < 0) | 
 | 648 | 			goto error; | 
 | 649 | 	} | 
 | 650 |  | 
 | 651 | 	return 0; | 
 | 652 |  | 
 | 653 | error: | 
 | 654 | 	if (codec->control_data) { | 
 | 655 | 		i2c_detach_client(i2c_client); | 
 | 656 | 		codec->control_data = NULL; | 
 | 657 | 	} | 
 | 658 |  | 
 | 659 | 	kfree(codec->reg_cache); | 
 | 660 | 	codec->reg_cache = NULL; | 
 | 661 | 	codec->reg_cache_size = 0; | 
 | 662 |  | 
 | 663 | 	kfree(i2c_client); | 
 | 664 |  | 
 | 665 | 	return ret; | 
 | 666 | } | 
 | 667 |  | 
| Timur Tabi | 8432395 | 2007-12-18 15:42:53 +0100 | [diff] [blame] | 668 | #endif /* USE_I2C*/ | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 669 |  | 
| Liam Girdwood | e550e17 | 2008-07-07 16:07:52 +0100 | [diff] [blame] | 670 | struct snd_soc_dai cs4270_dai = { | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 671 | 	.name = "CS4270", | 
 | 672 | 	.playback = { | 
 | 673 | 		.stream_name = "Playback", | 
 | 674 | 		.channels_min = 1, | 
 | 675 | 		.channels_max = 2, | 
 | 676 | 		.rates = 0, | 
 | 677 | 		.formats = CS4270_FORMATS, | 
 | 678 | 	}, | 
 | 679 | 	.capture = { | 
 | 680 | 		.stream_name = "Capture", | 
 | 681 | 		.channels_min = 1, | 
 | 682 | 		.channels_max = 2, | 
 | 683 | 		.rates = 0, | 
 | 684 | 		.formats = CS4270_FORMATS, | 
 | 685 | 	}, | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 686 | }; | 
 | 687 | EXPORT_SYMBOL_GPL(cs4270_dai); | 
 | 688 |  | 
 | 689 | /* | 
 | 690 |  * ASoC probe function | 
 | 691 |  * | 
 | 692 |  * This function is called when the machine driver calls | 
 | 693 |  * platform_device_add(). | 
 | 694 |  */ | 
 | 695 | static int cs4270_probe(struct platform_device *pdev) | 
 | 696 | { | 
 | 697 | 	struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 
 | 698 | 	struct snd_soc_codec *codec; | 
 | 699 | 	int ret = 0; | 
 | 700 |  | 
 | 701 | 	printk(KERN_INFO "CS4270 ALSA SoC Codec\n"); | 
 | 702 |  | 
 | 703 | 	/* Allocate enough space for the snd_soc_codec structure | 
 | 704 | 	   and our private data together. */ | 
 | 705 | 	codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) + | 
 | 706 | 			sizeof(struct cs4270_private), GFP_KERNEL); | 
 | 707 | 	if (!codec) { | 
 | 708 | 		printk(KERN_ERR "cs4270: Could not allocate codec structure\n"); | 
 | 709 | 		return -ENOMEM; | 
 | 710 | 	} | 
 | 711 |  | 
 | 712 | 	mutex_init(&codec->mutex); | 
 | 713 | 	INIT_LIST_HEAD(&codec->dapm_widgets); | 
 | 714 | 	INIT_LIST_HEAD(&codec->dapm_paths); | 
 | 715 |  | 
 | 716 | 	codec->name = "CS4270"; | 
 | 717 | 	codec->owner = THIS_MODULE; | 
 | 718 | 	codec->dai = &cs4270_dai; | 
 | 719 | 	codec->num_dai = 1; | 
| Timur Tabi | 4df2053 | 2007-11-14 12:07:58 +0100 | [diff] [blame] | 720 | 	codec->private_data = (void *) codec + | 
 | 721 | 		ALIGN(sizeof(struct snd_soc_codec), 4); | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 722 |  | 
 | 723 | 	socdev->codec = codec; | 
 | 724 |  | 
 | 725 | 	/* Register PCMs */ | 
 | 726 |  | 
 | 727 | 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 
 | 728 | 	if (ret < 0) { | 
 | 729 | 		printk(KERN_ERR "cs4270: failed to create PCMs\n"); | 
 | 730 | 		return ret; | 
 | 731 | 	} | 
 | 732 |  | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 733 | #ifdef USE_I2C | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 734 | 	cs4270_socdev = socdev; | 
 | 735 |  | 
 | 736 | 	ret = i2c_add_driver(&cs4270_i2c_driver); | 
 | 737 | 	if (ret) { | 
 | 738 | 		printk(KERN_ERR "cs4270: failed to attach driver"); | 
 | 739 | 		snd_soc_free_pcms(socdev); | 
 | 740 | 		return ret; | 
 | 741 | 	} | 
 | 742 |  | 
 | 743 | 	/* Did we find a CS4270 on the I2C bus? */ | 
 | 744 | 	if (codec->control_data) { | 
 | 745 | 		/* Initialize codec ops */ | 
 | 746 | 		cs4270_dai.ops.hw_params = cs4270_hw_params; | 
| Timur Tabi | 8432395 | 2007-12-18 15:42:53 +0100 | [diff] [blame] | 747 | 		cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk; | 
 | 748 | 		cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt; | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 749 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | 
 | 750 | 		cs4270_dai.dai_ops.digital_mute = cs4270_mute; | 
 | 751 | #endif | 
 | 752 | 	} else | 
 | 753 | 		printk(KERN_INFO "cs4270: no I2C device found, " | 
 | 754 | 			"using stand-alone mode\n"); | 
 | 755 | #else | 
 | 756 | 	printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); | 
 | 757 | #endif | 
 | 758 |  | 
 | 759 | 	ret = snd_soc_register_card(socdev); | 
 | 760 | 	if (ret < 0) { | 
 | 761 | 		printk(KERN_ERR "cs4270: failed to register card\n"); | 
 | 762 | 		snd_soc_free_pcms(socdev); | 
 | 763 | 		return ret; | 
 | 764 | 	} | 
 | 765 |  | 
 | 766 | 	return ret; | 
 | 767 | } | 
 | 768 |  | 
 | 769 | static int cs4270_remove(struct platform_device *pdev) | 
 | 770 | { | 
 | 771 | 	struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 
 | 772 |  | 
 | 773 | 	snd_soc_free_pcms(socdev); | 
 | 774 |  | 
| Timur Tabi | 9dbd627 | 2007-08-01 12:22:07 +0200 | [diff] [blame] | 775 | #ifdef USE_I2C | 
| Timur Tabi | b0c813c | 2007-07-31 18:18:44 +0200 | [diff] [blame] | 776 | 	if (socdev->codec->control_data) | 
 | 777 | 		i2c_del_driver(&cs4270_i2c_driver); | 
 | 778 | #endif | 
 | 779 |  | 
 | 780 | 	kfree(socdev->codec); | 
 | 781 | 	socdev->codec = NULL; | 
 | 782 |  | 
 | 783 | 	return 0; | 
 | 784 | } | 
 | 785 |  | 
 | 786 | /* | 
 | 787 |  * ASoC codec device structure | 
 | 788 |  * | 
 | 789 |  * Assign this variable to the codec_dev field of the machine driver's | 
 | 790 |  * snd_soc_device structure. | 
 | 791 |  */ | 
 | 792 | struct snd_soc_codec_device soc_codec_device_cs4270 = { | 
 | 793 | 	.probe = 	cs4270_probe, | 
 | 794 | 	.remove = 	cs4270_remove | 
 | 795 | }; | 
 | 796 | EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); | 
 | 797 |  | 
 | 798 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 
 | 799 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); | 
 | 800 | MODULE_LICENSE("GPL"); |