xref: /openbmc/linux/sound/soc/codecs/cs42l51.c (revision a1253ef6)
172ed5a8cSapatard@mandriva.com /*
272ed5a8cSapatard@mandriva.com  * cs42l51.c
372ed5a8cSapatard@mandriva.com  *
472ed5a8cSapatard@mandriva.com  * ASoC Driver for Cirrus Logic CS42L51 codecs
572ed5a8cSapatard@mandriva.com  *
672ed5a8cSapatard@mandriva.com  * Copyright (c) 2010 Arnaud Patard <apatard@mandriva.com>
772ed5a8cSapatard@mandriva.com  *
872ed5a8cSapatard@mandriva.com  * Based on cs4270.c - Copyright (c) Freescale Semiconductor
972ed5a8cSapatard@mandriva.com  *
1072ed5a8cSapatard@mandriva.com  * This program is free software; you can redistribute it and/or modify
1172ed5a8cSapatard@mandriva.com  * it under the terms of the GNU General Public License version 2 as
1272ed5a8cSapatard@mandriva.com  * published by the Free Software Foundation.
1372ed5a8cSapatard@mandriva.com  *
1472ed5a8cSapatard@mandriva.com  * This program is distributed in the hope that it will be useful,
1572ed5a8cSapatard@mandriva.com  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1672ed5a8cSapatard@mandriva.com  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1772ed5a8cSapatard@mandriva.com  * GNU General Public License for more details.
1872ed5a8cSapatard@mandriva.com  *
1972ed5a8cSapatard@mandriva.com  * For now:
2072ed5a8cSapatard@mandriva.com  *  - Only I2C is support. Not SPI
2172ed5a8cSapatard@mandriva.com  *  - master mode *NOT* supported
2272ed5a8cSapatard@mandriva.com  */
2372ed5a8cSapatard@mandriva.com 
2472ed5a8cSapatard@mandriva.com #include <linux/module.h>
2572ed5a8cSapatard@mandriva.com #include <linux/slab.h>
2672ed5a8cSapatard@mandriva.com #include <sound/core.h>
2772ed5a8cSapatard@mandriva.com #include <sound/soc.h>
2872ed5a8cSapatard@mandriva.com #include <sound/tlv.h>
2972ed5a8cSapatard@mandriva.com #include <sound/initval.h>
3072ed5a8cSapatard@mandriva.com #include <sound/pcm_params.h>
3172ed5a8cSapatard@mandriva.com #include <sound/pcm.h>
32da071489SMark Brown #include <linux/regmap.h>
3372ed5a8cSapatard@mandriva.com 
3472ed5a8cSapatard@mandriva.com #include "cs42l51.h"
3572ed5a8cSapatard@mandriva.com 
3672ed5a8cSapatard@mandriva.com enum master_slave_mode {
3772ed5a8cSapatard@mandriva.com 	MODE_SLAVE,
3872ed5a8cSapatard@mandriva.com 	MODE_SLAVE_AUTO,
3972ed5a8cSapatard@mandriva.com 	MODE_MASTER,
4072ed5a8cSapatard@mandriva.com };
4172ed5a8cSapatard@mandriva.com 
4272ed5a8cSapatard@mandriva.com struct cs42l51_private {
4372ed5a8cSapatard@mandriva.com 	unsigned int mclk;
4472ed5a8cSapatard@mandriva.com 	unsigned int audio_mode;	/* The mode (I2S or left-justified) */
4572ed5a8cSapatard@mandriva.com 	enum master_slave_mode func;
4672ed5a8cSapatard@mandriva.com };
4772ed5a8cSapatard@mandriva.com 
4872ed5a8cSapatard@mandriva.com #define CS42L51_FORMATS ( \
4972ed5a8cSapatard@mandriva.com 		SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S16_BE  | \
5072ed5a8cSapatard@mandriva.com 		SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
5172ed5a8cSapatard@mandriva.com 		SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
5272ed5a8cSapatard@mandriva.com 		SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE)
5372ed5a8cSapatard@mandriva.com 
5472ed5a8cSapatard@mandriva.com static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
5572ed5a8cSapatard@mandriva.com 			struct snd_ctl_elem_value *ucontrol)
5672ed5a8cSapatard@mandriva.com {
5772ed5a8cSapatard@mandriva.com 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
5872ed5a8cSapatard@mandriva.com 	unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3;
5972ed5a8cSapatard@mandriva.com 
6072ed5a8cSapatard@mandriva.com 	switch (value) {
6172ed5a8cSapatard@mandriva.com 	default:
6272ed5a8cSapatard@mandriva.com 	case 0:
6372ed5a8cSapatard@mandriva.com 		ucontrol->value.integer.value[0] = 0;
6472ed5a8cSapatard@mandriva.com 		break;
6572ed5a8cSapatard@mandriva.com 	/* same value : (L+R)/2 and (R+L)/2 */
6672ed5a8cSapatard@mandriva.com 	case 1:
6772ed5a8cSapatard@mandriva.com 	case 2:
6872ed5a8cSapatard@mandriva.com 		ucontrol->value.integer.value[0] = 1;
6972ed5a8cSapatard@mandriva.com 		break;
7072ed5a8cSapatard@mandriva.com 	case 3:
7172ed5a8cSapatard@mandriva.com 		ucontrol->value.integer.value[0] = 2;
7272ed5a8cSapatard@mandriva.com 		break;
7372ed5a8cSapatard@mandriva.com 	}
7472ed5a8cSapatard@mandriva.com 
7572ed5a8cSapatard@mandriva.com 	return 0;
7672ed5a8cSapatard@mandriva.com }
7772ed5a8cSapatard@mandriva.com 
7872ed5a8cSapatard@mandriva.com #define CHAN_MIX_NORMAL	0x00
7972ed5a8cSapatard@mandriva.com #define CHAN_MIX_BOTH	0x55
8072ed5a8cSapatard@mandriva.com #define CHAN_MIX_SWAP	0xFF
8172ed5a8cSapatard@mandriva.com 
8272ed5a8cSapatard@mandriva.com static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
8372ed5a8cSapatard@mandriva.com 			struct snd_ctl_elem_value *ucontrol)
8472ed5a8cSapatard@mandriva.com {
8572ed5a8cSapatard@mandriva.com 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
8672ed5a8cSapatard@mandriva.com 	unsigned char val;
8772ed5a8cSapatard@mandriva.com 
8872ed5a8cSapatard@mandriva.com 	switch (ucontrol->value.integer.value[0]) {
8972ed5a8cSapatard@mandriva.com 	default:
9072ed5a8cSapatard@mandriva.com 	case 0:
9172ed5a8cSapatard@mandriva.com 		val = CHAN_MIX_NORMAL;
9272ed5a8cSapatard@mandriva.com 		break;
9372ed5a8cSapatard@mandriva.com 	case 1:
9472ed5a8cSapatard@mandriva.com 		val = CHAN_MIX_BOTH;
9572ed5a8cSapatard@mandriva.com 		break;
9672ed5a8cSapatard@mandriva.com 	case 2:
9772ed5a8cSapatard@mandriva.com 		val = CHAN_MIX_SWAP;
9872ed5a8cSapatard@mandriva.com 		break;
9972ed5a8cSapatard@mandriva.com 	}
10072ed5a8cSapatard@mandriva.com 
10172ed5a8cSapatard@mandriva.com 	snd_soc_write(codec, CS42L51_PCM_MIXER, val);
10272ed5a8cSapatard@mandriva.com 
10372ed5a8cSapatard@mandriva.com 	return 1;
10472ed5a8cSapatard@mandriva.com }
10572ed5a8cSapatard@mandriva.com 
10672ed5a8cSapatard@mandriva.com static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0);
10772ed5a8cSapatard@mandriva.com static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
1087272e051SBrian Austin 
1097272e051SBrian Austin static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0);
11072ed5a8cSapatard@mandriva.com 
11172ed5a8cSapatard@mandriva.com static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0);
11272ed5a8cSapatard@mandriva.com static const char *chan_mix[] = {
11372ed5a8cSapatard@mandriva.com 	"L R",
11472ed5a8cSapatard@mandriva.com 	"L+R",
11572ed5a8cSapatard@mandriva.com 	"R L",
11672ed5a8cSapatard@mandriva.com };
11772ed5a8cSapatard@mandriva.com 
1186109ab2bSTakashi Iwai static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix);
11972ed5a8cSapatard@mandriva.com 
12072ed5a8cSapatard@mandriva.com static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
12172ed5a8cSapatard@mandriva.com 	SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
12272ed5a8cSapatard@mandriva.com 			CS42L51_PCMA_VOL, CS42L51_PCMB_VOL,
1237272e051SBrian Austin 			0, 0x19, 0x7F, adc_pcm_tlv),
12472ed5a8cSapatard@mandriva.com 	SOC_DOUBLE_R("PCM Playback Switch",
12572ed5a8cSapatard@mandriva.com 			CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1),
12672ed5a8cSapatard@mandriva.com 	SOC_DOUBLE_R_SX_TLV("Analog Playback Volume",
12772ed5a8cSapatard@mandriva.com 			CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL,
1281d99f243SBrian Austin 			0, 0x34, 0xE4, aout_tlv),
12972ed5a8cSapatard@mandriva.com 	SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
13072ed5a8cSapatard@mandriva.com 			CS42L51_ADCA_VOL, CS42L51_ADCB_VOL,
1317272e051SBrian Austin 			0, 0x19, 0x7F, adc_pcm_tlv),
13272ed5a8cSapatard@mandriva.com 	SOC_DOUBLE_R("ADC Mixer Switch",
13372ed5a8cSapatard@mandriva.com 			CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1),
13472ed5a8cSapatard@mandriva.com 	SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0),
13572ed5a8cSapatard@mandriva.com 	SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0),
13672ed5a8cSapatard@mandriva.com 	SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0),
13772ed5a8cSapatard@mandriva.com 	SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0),
13872ed5a8cSapatard@mandriva.com 	SOC_DOUBLE_TLV("Mic Boost Volume",
13972ed5a8cSapatard@mandriva.com 			CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv),
14072ed5a8cSapatard@mandriva.com 	SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv),
14172ed5a8cSapatard@mandriva.com 	SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv),
14272ed5a8cSapatard@mandriva.com 	SOC_ENUM_EXT("PCM channel mixer",
14372ed5a8cSapatard@mandriva.com 			cs42l51_chan_mix,
14472ed5a8cSapatard@mandriva.com 			cs42l51_get_chan_mix, cs42l51_set_chan_mix),
14572ed5a8cSapatard@mandriva.com };
14672ed5a8cSapatard@mandriva.com 
14772ed5a8cSapatard@mandriva.com /*
14872ed5a8cSapatard@mandriva.com  * to power down, one must:
14972ed5a8cSapatard@mandriva.com  * 1.) Enable the PDN bit
15072ed5a8cSapatard@mandriva.com  * 2.) enable power-down for the select channels
15172ed5a8cSapatard@mandriva.com  * 3.) disable the PDN bit.
15272ed5a8cSapatard@mandriva.com  */
15372ed5a8cSapatard@mandriva.com static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
15472ed5a8cSapatard@mandriva.com 		struct snd_kcontrol *kcontrol, int event)
15572ed5a8cSapatard@mandriva.com {
15672ed5a8cSapatard@mandriva.com 	switch (event) {
15772ed5a8cSapatard@mandriva.com 	case SND_SOC_DAPM_PRE_PMD:
158e94de1e8SAxel Lin 		snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
159e94de1e8SAxel Lin 				    CS42L51_POWER_CTL1_PDN,
160e94de1e8SAxel Lin 				    CS42L51_POWER_CTL1_PDN);
16172ed5a8cSapatard@mandriva.com 		break;
16272ed5a8cSapatard@mandriva.com 	default:
16372ed5a8cSapatard@mandriva.com 	case SND_SOC_DAPM_POST_PMD:
164e94de1e8SAxel Lin 		snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
165e94de1e8SAxel Lin 				    CS42L51_POWER_CTL1_PDN, 0);
16672ed5a8cSapatard@mandriva.com 		break;
16772ed5a8cSapatard@mandriva.com 	}
16872ed5a8cSapatard@mandriva.com 
16972ed5a8cSapatard@mandriva.com 	return 0;
17072ed5a8cSapatard@mandriva.com }
17172ed5a8cSapatard@mandriva.com 
17272ed5a8cSapatard@mandriva.com static const char *cs42l51_dac_names[] = {"Direct PCM",
17372ed5a8cSapatard@mandriva.com 	"DSP PCM", "ADC"};
1746109ab2bSTakashi Iwai static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum,
1756109ab2bSTakashi Iwai 			    CS42L51_DAC_CTL, 6, cs42l51_dac_names);
17672ed5a8cSapatard@mandriva.com static const struct snd_kcontrol_new cs42l51_dac_mux_controls =
17772ed5a8cSapatard@mandriva.com 	SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum);
17872ed5a8cSapatard@mandriva.com 
17972ed5a8cSapatard@mandriva.com static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left",
18072ed5a8cSapatard@mandriva.com 	"MIC Left", "MIC+preamp Left"};
1816109ab2bSTakashi Iwai static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum,
1826109ab2bSTakashi Iwai 			    CS42L51_ADC_INPUT, 4, cs42l51_adcl_names);
18372ed5a8cSapatard@mandriva.com static const struct snd_kcontrol_new cs42l51_adcl_mux_controls =
18472ed5a8cSapatard@mandriva.com 	SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum);
18572ed5a8cSapatard@mandriva.com 
18672ed5a8cSapatard@mandriva.com static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right",
18772ed5a8cSapatard@mandriva.com 	"MIC Right", "MIC+preamp Right"};
1886109ab2bSTakashi Iwai static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum,
1896109ab2bSTakashi Iwai 			    CS42L51_ADC_INPUT, 6, cs42l51_adcr_names);
19072ed5a8cSapatard@mandriva.com static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
19172ed5a8cSapatard@mandriva.com 	SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
19272ed5a8cSapatard@mandriva.com 
19372ed5a8cSapatard@mandriva.com static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
19472ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_MICBIAS("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1),
19572ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0,
19672ed5a8cSapatard@mandriva.com 		cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
19772ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0,
19872ed5a8cSapatard@mandriva.com 		cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
19972ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_ADC_E("Left ADC", "Left HiFi Capture",
20072ed5a8cSapatard@mandriva.com 		CS42L51_POWER_CTL1, 1, 1,
20172ed5a8cSapatard@mandriva.com 		cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
20272ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture",
20372ed5a8cSapatard@mandriva.com 		CS42L51_POWER_CTL1, 2, 1,
20472ed5a8cSapatard@mandriva.com 		cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
20572ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback",
20672ed5a8cSapatard@mandriva.com 		CS42L51_POWER_CTL1, 5, 1,
20772ed5a8cSapatard@mandriva.com 		cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
20872ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback",
20972ed5a8cSapatard@mandriva.com 		CS42L51_POWER_CTL1, 6, 1,
21072ed5a8cSapatard@mandriva.com 		cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
21172ed5a8cSapatard@mandriva.com 
21272ed5a8cSapatard@mandriva.com 	/* analog/mic */
21372ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_INPUT("AIN1L"),
21472ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_INPUT("AIN1R"),
21572ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_INPUT("AIN2L"),
21672ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_INPUT("AIN2R"),
21772ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_INPUT("MICL"),
21872ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_INPUT("MICR"),
21972ed5a8cSapatard@mandriva.com 
22072ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_MIXER("Mic Preamp Left",
22172ed5a8cSapatard@mandriva.com 		CS42L51_MIC_POWER_CTL, 2, 1, NULL, 0),
22272ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_MIXER("Mic Preamp Right",
22372ed5a8cSapatard@mandriva.com 		CS42L51_MIC_POWER_CTL, 3, 1, NULL, 0),
22472ed5a8cSapatard@mandriva.com 
22572ed5a8cSapatard@mandriva.com 	/* HP */
22672ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_OUTPUT("HPL"),
22772ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_OUTPUT("HPR"),
22872ed5a8cSapatard@mandriva.com 
22972ed5a8cSapatard@mandriva.com 	/* mux */
23072ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0,
23172ed5a8cSapatard@mandriva.com 		&cs42l51_dac_mux_controls),
23272ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_MUX("PGA-ADC Mux Left", SND_SOC_NOPM, 0, 0,
23372ed5a8cSapatard@mandriva.com 		&cs42l51_adcl_mux_controls),
23472ed5a8cSapatard@mandriva.com 	SND_SOC_DAPM_MUX("PGA-ADC Mux Right", SND_SOC_NOPM, 0, 0,
23572ed5a8cSapatard@mandriva.com 		&cs42l51_adcr_mux_controls),
23672ed5a8cSapatard@mandriva.com };
23772ed5a8cSapatard@mandriva.com 
23872ed5a8cSapatard@mandriva.com static const struct snd_soc_dapm_route cs42l51_routes[] = {
23972ed5a8cSapatard@mandriva.com 	{"HPL", NULL, "Left DAC"},
24072ed5a8cSapatard@mandriva.com 	{"HPR", NULL, "Right DAC"},
24172ed5a8cSapatard@mandriva.com 
24272ed5a8cSapatard@mandriva.com 	{"Left ADC", NULL, "Left PGA"},
24372ed5a8cSapatard@mandriva.com 	{"Right ADC", NULL, "Right PGA"},
24472ed5a8cSapatard@mandriva.com 
24572ed5a8cSapatard@mandriva.com 	{"Mic Preamp Left",  NULL,  "MICL"},
24672ed5a8cSapatard@mandriva.com 	{"Mic Preamp Right", NULL,  "MICR"},
24772ed5a8cSapatard@mandriva.com 
24872ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Left",  "AIN1 Left",        "AIN1L" },
24972ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Left",  "AIN2 Left",        "AIN2L" },
25072ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Left",  "MIC Left",         "MICL"  },
25172ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Left",  "MIC+preamp Left",  "Mic Preamp Left" },
25272ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Right", "AIN1 Right",       "AIN1R" },
25372ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Right", "AIN2 Right",       "AIN2R" },
25472ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Right", "MIC Right",        "MICR" },
25572ed5a8cSapatard@mandriva.com 	{"PGA-ADC Mux Right", "MIC+preamp Right", "Mic Preamp Right" },
25672ed5a8cSapatard@mandriva.com 
25772ed5a8cSapatard@mandriva.com 	{"Left PGA", NULL, "PGA-ADC Mux Left"},
25872ed5a8cSapatard@mandriva.com 	{"Right PGA", NULL, "PGA-ADC Mux Right"},
25972ed5a8cSapatard@mandriva.com };
26072ed5a8cSapatard@mandriva.com 
26172ed5a8cSapatard@mandriva.com static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
26272ed5a8cSapatard@mandriva.com 		unsigned int format)
26372ed5a8cSapatard@mandriva.com {
26472ed5a8cSapatard@mandriva.com 	struct snd_soc_codec *codec = codec_dai->codec;
26572ed5a8cSapatard@mandriva.com 	struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
26672ed5a8cSapatard@mandriva.com 
26772ed5a8cSapatard@mandriva.com 	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
26872ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_I2S:
26972ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_LEFT_J:
27072ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_RIGHT_J:
27172ed5a8cSapatard@mandriva.com 		cs42l51->audio_mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
27272ed5a8cSapatard@mandriva.com 		break;
27372ed5a8cSapatard@mandriva.com 	default:
27472ed5a8cSapatard@mandriva.com 		dev_err(codec->dev, "invalid DAI format\n");
275ac60155fSAxel Lin 		return -EINVAL;
27672ed5a8cSapatard@mandriva.com 	}
27772ed5a8cSapatard@mandriva.com 
27872ed5a8cSapatard@mandriva.com 	switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
27972ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_CBM_CFM:
28072ed5a8cSapatard@mandriva.com 		cs42l51->func = MODE_MASTER;
28172ed5a8cSapatard@mandriva.com 		break;
28272ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_CBS_CFS:
28372ed5a8cSapatard@mandriva.com 		cs42l51->func = MODE_SLAVE_AUTO;
28472ed5a8cSapatard@mandriva.com 		break;
28572ed5a8cSapatard@mandriva.com 	default:
286ac60155fSAxel Lin 		dev_err(codec->dev, "Unknown master/slave configuration\n");
287ac60155fSAxel Lin 		return -EINVAL;
28872ed5a8cSapatard@mandriva.com 	}
28972ed5a8cSapatard@mandriva.com 
290ac60155fSAxel Lin 	return 0;
29172ed5a8cSapatard@mandriva.com }
29272ed5a8cSapatard@mandriva.com 
29372ed5a8cSapatard@mandriva.com struct cs42l51_ratios {
29472ed5a8cSapatard@mandriva.com 	unsigned int ratio;
29572ed5a8cSapatard@mandriva.com 	unsigned char speed_mode;
29672ed5a8cSapatard@mandriva.com 	unsigned char mclk;
29772ed5a8cSapatard@mandriva.com };
29872ed5a8cSapatard@mandriva.com 
29972ed5a8cSapatard@mandriva.com static struct cs42l51_ratios slave_ratios[] = {
30072ed5a8cSapatard@mandriva.com 	{  512, CS42L51_QSM_MODE, 0 }, {  768, CS42L51_QSM_MODE, 0 },
30172ed5a8cSapatard@mandriva.com 	{ 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
30272ed5a8cSapatard@mandriva.com 	{ 2048, CS42L51_QSM_MODE, 0 }, { 3072, CS42L51_QSM_MODE, 0 },
30372ed5a8cSapatard@mandriva.com 	{  256, CS42L51_HSM_MODE, 0 }, {  384, CS42L51_HSM_MODE, 0 },
30472ed5a8cSapatard@mandriva.com 	{  512, CS42L51_HSM_MODE, 0 }, {  768, CS42L51_HSM_MODE, 0 },
30572ed5a8cSapatard@mandriva.com 	{ 1024, CS42L51_HSM_MODE, 0 }, { 1536, CS42L51_HSM_MODE, 0 },
30672ed5a8cSapatard@mandriva.com 	{  128, CS42L51_SSM_MODE, 0 }, {  192, CS42L51_SSM_MODE, 0 },
30772ed5a8cSapatard@mandriva.com 	{  256, CS42L51_SSM_MODE, 0 }, {  384, CS42L51_SSM_MODE, 0 },
30872ed5a8cSapatard@mandriva.com 	{  512, CS42L51_SSM_MODE, 0 }, {  768, CS42L51_SSM_MODE, 0 },
30972ed5a8cSapatard@mandriva.com 	{  128, CS42L51_DSM_MODE, 0 }, {  192, CS42L51_DSM_MODE, 0 },
31072ed5a8cSapatard@mandriva.com 	{  256, CS42L51_DSM_MODE, 0 }, {  384, CS42L51_DSM_MODE, 0 },
31172ed5a8cSapatard@mandriva.com };
31272ed5a8cSapatard@mandriva.com 
31372ed5a8cSapatard@mandriva.com static struct cs42l51_ratios slave_auto_ratios[] = {
31472ed5a8cSapatard@mandriva.com 	{ 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
31572ed5a8cSapatard@mandriva.com 	{ 2048, CS42L51_QSM_MODE, 1 }, { 3072, CS42L51_QSM_MODE, 1 },
31672ed5a8cSapatard@mandriva.com 	{  512, CS42L51_HSM_MODE, 0 }, {  768, CS42L51_HSM_MODE, 0 },
31772ed5a8cSapatard@mandriva.com 	{ 1024, CS42L51_HSM_MODE, 1 }, { 1536, CS42L51_HSM_MODE, 1 },
31872ed5a8cSapatard@mandriva.com 	{  256, CS42L51_SSM_MODE, 0 }, {  384, CS42L51_SSM_MODE, 0 },
31972ed5a8cSapatard@mandriva.com 	{  512, CS42L51_SSM_MODE, 1 }, {  768, CS42L51_SSM_MODE, 1 },
32072ed5a8cSapatard@mandriva.com 	{  128, CS42L51_DSM_MODE, 0 }, {  192, CS42L51_DSM_MODE, 0 },
32172ed5a8cSapatard@mandriva.com 	{  256, CS42L51_DSM_MODE, 1 }, {  384, CS42L51_DSM_MODE, 1 },
32272ed5a8cSapatard@mandriva.com };
32372ed5a8cSapatard@mandriva.com 
32472ed5a8cSapatard@mandriva.com static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
32572ed5a8cSapatard@mandriva.com 		int clk_id, unsigned int freq, int dir)
32672ed5a8cSapatard@mandriva.com {
32772ed5a8cSapatard@mandriva.com 	struct snd_soc_codec *codec = codec_dai->codec;
32872ed5a8cSapatard@mandriva.com 	struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
32972ed5a8cSapatard@mandriva.com 
33072ed5a8cSapatard@mandriva.com 	cs42l51->mclk = freq;
33172ed5a8cSapatard@mandriva.com 	return 0;
33272ed5a8cSapatard@mandriva.com }
33372ed5a8cSapatard@mandriva.com 
33472ed5a8cSapatard@mandriva.com static int cs42l51_hw_params(struct snd_pcm_substream *substream,
33572ed5a8cSapatard@mandriva.com 		struct snd_pcm_hw_params *params,
33672ed5a8cSapatard@mandriva.com 		struct snd_soc_dai *dai)
33772ed5a8cSapatard@mandriva.com {
338e6968a17SMark Brown 	struct snd_soc_codec *codec = dai->codec;
33972ed5a8cSapatard@mandriva.com 	struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
34072ed5a8cSapatard@mandriva.com 	int ret;
34172ed5a8cSapatard@mandriva.com 	unsigned int i;
34272ed5a8cSapatard@mandriva.com 	unsigned int rate;
34372ed5a8cSapatard@mandriva.com 	unsigned int ratio;
34472ed5a8cSapatard@mandriva.com 	struct cs42l51_ratios *ratios = NULL;
34572ed5a8cSapatard@mandriva.com 	int nr_ratios = 0;
34672ed5a8cSapatard@mandriva.com 	int intf_ctl, power_ctl, fmt;
34772ed5a8cSapatard@mandriva.com 
34872ed5a8cSapatard@mandriva.com 	switch (cs42l51->func) {
34972ed5a8cSapatard@mandriva.com 	case MODE_MASTER:
35072ed5a8cSapatard@mandriva.com 		return -EINVAL;
35172ed5a8cSapatard@mandriva.com 	case MODE_SLAVE:
35272ed5a8cSapatard@mandriva.com 		ratios = slave_ratios;
35372ed5a8cSapatard@mandriva.com 		nr_ratios = ARRAY_SIZE(slave_ratios);
35472ed5a8cSapatard@mandriva.com 		break;
35572ed5a8cSapatard@mandriva.com 	case MODE_SLAVE_AUTO:
35672ed5a8cSapatard@mandriva.com 		ratios = slave_auto_ratios;
35772ed5a8cSapatard@mandriva.com 		nr_ratios = ARRAY_SIZE(slave_auto_ratios);
35872ed5a8cSapatard@mandriva.com 		break;
35972ed5a8cSapatard@mandriva.com 	}
36072ed5a8cSapatard@mandriva.com 
36172ed5a8cSapatard@mandriva.com 	/* Figure out which MCLK/LRCK ratio to use */
36272ed5a8cSapatard@mandriva.com 	rate = params_rate(params);     /* Sampling rate, in Hz */
36372ed5a8cSapatard@mandriva.com 	ratio = cs42l51->mclk / rate;    /* MCLK/LRCK ratio */
36472ed5a8cSapatard@mandriva.com 	for (i = 0; i < nr_ratios; i++) {
36572ed5a8cSapatard@mandriva.com 		if (ratios[i].ratio == ratio)
36672ed5a8cSapatard@mandriva.com 			break;
36772ed5a8cSapatard@mandriva.com 	}
36872ed5a8cSapatard@mandriva.com 
36972ed5a8cSapatard@mandriva.com 	if (i == nr_ratios) {
37072ed5a8cSapatard@mandriva.com 		/* We did not find a matching ratio */
37172ed5a8cSapatard@mandriva.com 		dev_err(codec->dev, "could not find matching ratio\n");
37272ed5a8cSapatard@mandriva.com 		return -EINVAL;
37372ed5a8cSapatard@mandriva.com 	}
37472ed5a8cSapatard@mandriva.com 
37572ed5a8cSapatard@mandriva.com 	intf_ctl = snd_soc_read(codec, CS42L51_INTF_CTL);
37672ed5a8cSapatard@mandriva.com 	power_ctl = snd_soc_read(codec, CS42L51_MIC_POWER_CTL);
37772ed5a8cSapatard@mandriva.com 
37872ed5a8cSapatard@mandriva.com 	intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S
37972ed5a8cSapatard@mandriva.com 			| CS42L51_INTF_CTL_DAC_FORMAT(7));
38072ed5a8cSapatard@mandriva.com 	power_ctl &= ~(CS42L51_MIC_POWER_CTL_SPEED(3)
38172ed5a8cSapatard@mandriva.com 			| CS42L51_MIC_POWER_CTL_MCLK_DIV2);
38272ed5a8cSapatard@mandriva.com 
38372ed5a8cSapatard@mandriva.com 	switch (cs42l51->func) {
38472ed5a8cSapatard@mandriva.com 	case MODE_MASTER:
38572ed5a8cSapatard@mandriva.com 		intf_ctl |= CS42L51_INTF_CTL_MASTER;
38672ed5a8cSapatard@mandriva.com 		power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
38772ed5a8cSapatard@mandriva.com 		break;
38872ed5a8cSapatard@mandriva.com 	case MODE_SLAVE:
38972ed5a8cSapatard@mandriva.com 		power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
39072ed5a8cSapatard@mandriva.com 		break;
39172ed5a8cSapatard@mandriva.com 	case MODE_SLAVE_AUTO:
39272ed5a8cSapatard@mandriva.com 		power_ctl |= CS42L51_MIC_POWER_CTL_AUTO;
39372ed5a8cSapatard@mandriva.com 		break;
39472ed5a8cSapatard@mandriva.com 	}
39572ed5a8cSapatard@mandriva.com 
39672ed5a8cSapatard@mandriva.com 	switch (cs42l51->audio_mode) {
39772ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_I2S:
39872ed5a8cSapatard@mandriva.com 		intf_ctl |= CS42L51_INTF_CTL_ADC_I2S;
39972ed5a8cSapatard@mandriva.com 		intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_I2S);
40072ed5a8cSapatard@mandriva.com 		break;
40172ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_LEFT_J:
40272ed5a8cSapatard@mandriva.com 		intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24);
40372ed5a8cSapatard@mandriva.com 		break;
40472ed5a8cSapatard@mandriva.com 	case SND_SOC_DAIFMT_RIGHT_J:
4051b6b0dfaSMark Brown 		switch (params_width(params)) {
4061b6b0dfaSMark Brown 		case 16:
40772ed5a8cSapatard@mandriva.com 			fmt = CS42L51_DAC_DIF_RJ16;
40872ed5a8cSapatard@mandriva.com 			break;
4091b6b0dfaSMark Brown 		case 18:
41072ed5a8cSapatard@mandriva.com 			fmt = CS42L51_DAC_DIF_RJ18;
41172ed5a8cSapatard@mandriva.com 			break;
4121b6b0dfaSMark Brown 		case 20:
41372ed5a8cSapatard@mandriva.com 			fmt = CS42L51_DAC_DIF_RJ20;
41472ed5a8cSapatard@mandriva.com 			break;
4151b6b0dfaSMark Brown 		case 24:
41672ed5a8cSapatard@mandriva.com 			fmt = CS42L51_DAC_DIF_RJ24;
41772ed5a8cSapatard@mandriva.com 			break;
41872ed5a8cSapatard@mandriva.com 		default:
41972ed5a8cSapatard@mandriva.com 			dev_err(codec->dev, "unknown format\n");
42072ed5a8cSapatard@mandriva.com 			return -EINVAL;
42172ed5a8cSapatard@mandriva.com 		}
42272ed5a8cSapatard@mandriva.com 		intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(fmt);
42372ed5a8cSapatard@mandriva.com 		break;
42472ed5a8cSapatard@mandriva.com 	default:
42572ed5a8cSapatard@mandriva.com 		dev_err(codec->dev, "unknown format\n");
42672ed5a8cSapatard@mandriva.com 		return -EINVAL;
42772ed5a8cSapatard@mandriva.com 	}
42872ed5a8cSapatard@mandriva.com 
42972ed5a8cSapatard@mandriva.com 	if (ratios[i].mclk)
43072ed5a8cSapatard@mandriva.com 		power_ctl |= CS42L51_MIC_POWER_CTL_MCLK_DIV2;
43172ed5a8cSapatard@mandriva.com 
43272ed5a8cSapatard@mandriva.com 	ret = snd_soc_write(codec, CS42L51_INTF_CTL, intf_ctl);
43372ed5a8cSapatard@mandriva.com 	if (ret < 0)
43472ed5a8cSapatard@mandriva.com 		return ret;
43572ed5a8cSapatard@mandriva.com 
43672ed5a8cSapatard@mandriva.com 	ret = snd_soc_write(codec, CS42L51_MIC_POWER_CTL, power_ctl);
43772ed5a8cSapatard@mandriva.com 	if (ret < 0)
43872ed5a8cSapatard@mandriva.com 		return ret;
43972ed5a8cSapatard@mandriva.com 
44072ed5a8cSapatard@mandriva.com 	return 0;
44172ed5a8cSapatard@mandriva.com }
44272ed5a8cSapatard@mandriva.com 
44372ed5a8cSapatard@mandriva.com static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute)
44472ed5a8cSapatard@mandriva.com {
44572ed5a8cSapatard@mandriva.com 	struct snd_soc_codec *codec = dai->codec;
44672ed5a8cSapatard@mandriva.com 	int reg;
44772ed5a8cSapatard@mandriva.com 	int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE;
44872ed5a8cSapatard@mandriva.com 
44972ed5a8cSapatard@mandriva.com 	reg = snd_soc_read(codec, CS42L51_DAC_OUT_CTL);
45072ed5a8cSapatard@mandriva.com 
45172ed5a8cSapatard@mandriva.com 	if (mute)
45272ed5a8cSapatard@mandriva.com 		reg |= mask;
45372ed5a8cSapatard@mandriva.com 	else
45472ed5a8cSapatard@mandriva.com 		reg &= ~mask;
45572ed5a8cSapatard@mandriva.com 
45672ed5a8cSapatard@mandriva.com 	return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg);
45772ed5a8cSapatard@mandriva.com }
45872ed5a8cSapatard@mandriva.com 
45985e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops cs42l51_dai_ops = {
46072ed5a8cSapatard@mandriva.com 	.hw_params      = cs42l51_hw_params,
46172ed5a8cSapatard@mandriva.com 	.set_sysclk     = cs42l51_set_dai_sysclk,
46272ed5a8cSapatard@mandriva.com 	.set_fmt        = cs42l51_set_dai_fmt,
46372ed5a8cSapatard@mandriva.com 	.digital_mute   = cs42l51_dai_mute,
46472ed5a8cSapatard@mandriva.com };
46572ed5a8cSapatard@mandriva.com 
466f0fba2adSLiam Girdwood static struct snd_soc_dai_driver cs42l51_dai = {
467f0fba2adSLiam Girdwood 	.name = "cs42l51-hifi",
46872ed5a8cSapatard@mandriva.com 	.playback = {
46972ed5a8cSapatard@mandriva.com 		.stream_name = "Playback",
47072ed5a8cSapatard@mandriva.com 		.channels_min = 1,
47172ed5a8cSapatard@mandriva.com 		.channels_max = 2,
47272ed5a8cSapatard@mandriva.com 		.rates = SNDRV_PCM_RATE_8000_96000,
47372ed5a8cSapatard@mandriva.com 		.formats = CS42L51_FORMATS,
47472ed5a8cSapatard@mandriva.com 	},
47572ed5a8cSapatard@mandriva.com 	.capture = {
47672ed5a8cSapatard@mandriva.com 		.stream_name = "Capture",
47772ed5a8cSapatard@mandriva.com 		.channels_min = 1,
47872ed5a8cSapatard@mandriva.com 		.channels_max = 2,
47972ed5a8cSapatard@mandriva.com 		.rates = SNDRV_PCM_RATE_8000_96000,
48072ed5a8cSapatard@mandriva.com 		.formats = CS42L51_FORMATS,
48172ed5a8cSapatard@mandriva.com 	},
48272ed5a8cSapatard@mandriva.com 	.ops = &cs42l51_dai_ops,
48372ed5a8cSapatard@mandriva.com };
48472ed5a8cSapatard@mandriva.com 
485a1253ef6SBrian Austin static int cs42l51_codec_probe(struct snd_soc_codec *codec)
48672ed5a8cSapatard@mandriva.com {
487f0fba2adSLiam Girdwood 	int ret, reg;
48872ed5a8cSapatard@mandriva.com 
489f0fba2adSLiam Girdwood 	/*
490f0fba2adSLiam Girdwood 	 * DAC configuration
491f0fba2adSLiam Girdwood 	 * - Use signal processor
492f0fba2adSLiam Girdwood 	 * - auto mute
493f0fba2adSLiam Girdwood 	 * - vol changes immediate
494f0fba2adSLiam Girdwood 	 * - no de-emphasize
495f0fba2adSLiam Girdwood 	 */
496f0fba2adSLiam Girdwood 	reg = CS42L51_DAC_CTL_DATA_SEL(1)
497f0fba2adSLiam Girdwood 		| CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
498f0fba2adSLiam Girdwood 	ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
499f0fba2adSLiam Girdwood 	if (ret < 0)
500f0fba2adSLiam Girdwood 		return ret;
501f0fba2adSLiam Girdwood 
50272ed5a8cSapatard@mandriva.com 	return 0;
50372ed5a8cSapatard@mandriva.com }
50472ed5a8cSapatard@mandriva.com 
505f0fba2adSLiam Girdwood static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
506a1253ef6SBrian Austin 	.probe = cs42l51_codec_probe,
5073f7cec04SAxel Lin 
5083f7cec04SAxel Lin 	.controls = cs42l51_snd_controls,
5093f7cec04SAxel Lin 	.num_controls = ARRAY_SIZE(cs42l51_snd_controls),
5103f7cec04SAxel Lin 	.dapm_widgets = cs42l51_dapm_widgets,
5113f7cec04SAxel Lin 	.num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets),
5123f7cec04SAxel Lin 	.dapm_routes = cs42l51_routes,
5133f7cec04SAxel Lin 	.num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
514f0fba2adSLiam Girdwood };
51572ed5a8cSapatard@mandriva.com 
516a1253ef6SBrian Austin const struct regmap_config cs42l51_regmap = {
517da071489SMark Brown 	.max_register = CS42L51_CHARGE_FREQ,
518da071489SMark Brown 	.cache_type = REGCACHE_RBTREE,
519da071489SMark Brown };
520a1253ef6SBrian Austin EXPORT_SYMBOL_GPL(cs42l51_regmap);
521da071489SMark Brown 
522a1253ef6SBrian Austin int cs42l51_probe(struct device *dev, struct regmap *regmap)
52372ed5a8cSapatard@mandriva.com {
524f0fba2adSLiam Girdwood 	struct cs42l51_private *cs42l51;
525da071489SMark Brown 	unsigned int val;
526f0fba2adSLiam Girdwood 	int ret;
52772ed5a8cSapatard@mandriva.com 
528a1253ef6SBrian Austin 	if (IS_ERR(regmap))
529a1253ef6SBrian Austin 		return PTR_ERR(regmap);
530a1253ef6SBrian Austin 
531a1253ef6SBrian Austin 	cs42l51 = devm_kzalloc(dev, sizeof(struct cs42l51_private),
532a1253ef6SBrian Austin 			       GFP_KERNEL);
533a1253ef6SBrian Austin 	if (!cs42l51)
534a1253ef6SBrian Austin 		return -ENOMEM;
535a1253ef6SBrian Austin 
536a1253ef6SBrian Austin 	dev_set_drvdata(dev, cs42l51);
537da071489SMark Brown 
538f0fba2adSLiam Girdwood 	/* Verify that we have a CS42L51 */
539da071489SMark Brown 	ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val);
540f0fba2adSLiam Girdwood 	if (ret < 0) {
541a1253ef6SBrian Austin 		dev_err(dev, "failed to read I2C\n");
542f0fba2adSLiam Girdwood 		goto error;
543f0fba2adSLiam Girdwood 	}
54472ed5a8cSapatard@mandriva.com 
545da071489SMark Brown 	if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
546da071489SMark Brown 	    (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
547a1253ef6SBrian Austin 		dev_err(dev, "Invalid chip id: %x\n", val);
548f0fba2adSLiam Girdwood 		ret = -ENODEV;
549f0fba2adSLiam Girdwood 		goto error;
550f0fba2adSLiam Girdwood 	}
551a1253ef6SBrian Austin 	dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n", val & 0xFF);
552f0fba2adSLiam Girdwood 
553a1253ef6SBrian Austin 	ret =  snd_soc_register_codec(dev,
554f0fba2adSLiam Girdwood 			&soc_codec_device_cs42l51, &cs42l51_dai, 1);
555f0fba2adSLiam Girdwood error:
556f0fba2adSLiam Girdwood 	return ret;
557f0fba2adSLiam Girdwood }
558a1253ef6SBrian Austin EXPORT_SYMBOL_GPL(cs42l51_probe);
559f0fba2adSLiam Girdwood 
560dfd72a68SThomas Petazzoni static const struct of_device_id cs42l51_of_match[] = {
561dfd72a68SThomas Petazzoni 	{ .compatible = "cirrus,cs42l51", },
562dfd72a68SThomas Petazzoni 	{ }
563dfd72a68SThomas Petazzoni };
564dfd72a68SThomas Petazzoni MODULE_DEVICE_TABLE(of, cs42l51_of_match);
56569737897SArnaud Patard (Rtp) MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
56672ed5a8cSapatard@mandriva.com MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
56772ed5a8cSapatard@mandriva.com MODULE_LICENSE("GPL");
568