Commit 36633237be60c0ec88b11e00d5fa22a305563d03

Authored by Vinod Koul
Committed by Mark Brown
1 parent 42aee9b43e

ASoC: sn95031: Add support for reading mic bias

This patch adds support to read the mic bias voltage
when a jack is inserted. It uses ADC to measure.

Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Harsha Priya <priya.harsha@intel.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 2 changed files with 147 additions and 4 deletions Side-by-side Diff

sound/soc/codecs/sn95031.c
... ... @@ -40,13 +40,130 @@
40 40 #define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
41 41 #define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
42 42  
  43 +/* adc helper functions */
  44 +
  45 +/* enables mic bias voltage */
  46 +static void sn95031_enable_mic_bias(struct snd_soc_codec *codec)
  47 +{
  48 + snd_soc_write(codec, SN95031_VAUD, BIT(2)|BIT(1)|BIT(0));
  49 + snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(2), BIT(2));
  50 +}
  51 +
  52 +/* Enable/Disable the ADC depending on the argument */
  53 +static void configure_adc(struct snd_soc_codec *sn95031_codec, int val)
  54 +{
  55 + int value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
  56 +
  57 + if (val) {
  58 + /* Enable and start the ADC */
  59 + value |= (SN95031_ADC_ENBL | SN95031_ADC_START);
  60 + value &= (~SN95031_ADC_NO_LOOP);
  61 + } else {
  62 + /* Just stop the ADC */
  63 + value &= (~SN95031_ADC_START);
  64 + }
  65 + snd_soc_write(sn95031_codec, SN95031_ADC1CNTL1, value);
  66 +}
  67 +
43 68 /*
44   - * todo:
45   - * capture paths
46   - * jack detection
47   - * PM functions
  69 + * finds an empty channel for conversion
  70 + * If the ADC is not enabled then start using 0th channel
  71 + * itself. Otherwise find an empty channel by looking for a
  72 + * channel in which the stopbit is set to 1. returns the index
  73 + * of the first free channel if succeeds or an error code.
  74 + *
  75 + * Context: can sleep
  76 + *
48 77 */
  78 +static int find_free_channel(struct snd_soc_codec *sn95031_codec)
  79 +{
  80 + int ret = 0, i, value;
49 81  
  82 + /* check whether ADC is enabled */
  83 + value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
  84 +
  85 + if ((value & SN95031_ADC_ENBL) == 0)
  86 + return 0;
  87 +
  88 + /* ADC is already enabled; Looking for an empty channel */
  89 + for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) {
  90 + value = snd_soc_read(sn95031_codec,
  91 + SN95031_ADC_CHNL_START_ADDR + i);
  92 + if (value & SN95031_STOPBIT_MASK) {
  93 + ret = i;
  94 + break;
  95 + }
  96 + }
  97 + return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret;
  98 +}
  99 +
  100 +/* Initialize the ADC for reading micbias values. Can sleep. */
  101 +static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
  102 +{
  103 + int base_addr, chnl_addr;
  104 + int value;
  105 + static int channel_index;
  106 +
  107 + /* Index of the first channel in which the stop bit is set */
  108 + channel_index = find_free_channel(sn95031_codec);
  109 + if (channel_index < 0) {
  110 + pr_err("No free ADC channels");
  111 + return channel_index;
  112 + }
  113 +
  114 + base_addr = SN95031_ADC_CHNL_START_ADDR + channel_index;
  115 +
  116 + if (!(channel_index == 0 || channel_index == SN95031_ADC_LOOP_MAX)) {
  117 + /* Reset stop bit for channels other than 0 and 12 */
  118 + value = snd_soc_read(sn95031_codec, base_addr);
  119 + /* Set the stop bit to zero */
  120 + snd_soc_write(sn95031_codec, base_addr, value & 0xEF);
  121 + /* Index of the first free channel */
  122 + base_addr++;
  123 + channel_index++;
  124 + }
  125 +
  126 + /* Since this is the last channel, set the stop bit
  127 + to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
  128 + snd_soc_write(sn95031_codec, base_addr,
  129 + SN95031_AUDIO_DETECT_CODE | 0x10);
  130 +
  131 + chnl_addr = SN95031_ADC_DATA_START_ADDR + 2 * channel_index;
  132 + pr_debug("mid_initialize : %x", chnl_addr);
  133 + configure_adc(sn95031_codec, 1);
  134 + return chnl_addr;
  135 +}
  136 +
  137 +
  138 +/* reads the ADC registers and gets the mic bias value in mV. */
  139 +static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
  140 +{
  141 + u16 adc_adr = sn95031_initialize_adc(codec);
  142 + u16 adc_val1, adc_val2;
  143 + unsigned int mic_bias;
  144 +
  145 + sn95031_enable_mic_bias(codec);
  146 +
  147 + /* Enable the sound card for conversion before reading */
  148 + snd_soc_write(codec, SN95031_ADC1CNTL3, 0x05);
  149 + /* Re-toggle the RRDATARD bit */
  150 + snd_soc_write(codec, SN95031_ADC1CNTL3, 0x04);
  151 +
  152 + /* Read the higher bits of data */
  153 + msleep(1000);
  154 + adc_val1 = snd_soc_read(codec, adc_adr);
  155 + adc_adr++;
  156 + adc_val2 = snd_soc_read(codec, adc_adr);
  157 +
  158 + /* Adding lower two bits to the higher bits */
  159 + mic_bias = (adc_val1 << 2) + (adc_val2 & 3);
  160 + mic_bias = (mic_bias * SN95031_ADC_ONE_LSB_MULTIPLIER) / 1000;
  161 + pr_debug("mic bias = %dmV\n", mic_bias);
  162 + return mic_bias;
  163 +}
  164 +EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
  165 +/*end - adc helper functions */
  166 +
50 167 static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
51 168 unsigned int reg)
52 169 {
... ... @@ -663,6 +780,8 @@
663 780  
664 781 static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack)
665 782 {
  783 + int micbias = sn95031_get_mic_bias(mfld_jack->codec);
  784 +
666 785 /* Defaulting to HEADSET for now.
667 786 * will change after adding soc-jack detection apis */
668 787 int jack_type = SND_JACK_HEADSET;
sound/soc/codecs/sn95031.h
... ... @@ -96,7 +96,31 @@
96 96 #define SN95031_SSR5 0x384
97 97 #define SN95031_SSR6 0x385
98 98  
  99 +/* ADC registers */
  100 +
  101 +#define SN95031_ADC1CNTL1 0x1C0
  102 +#define SN95031_ADC_ENBL 0x10
  103 +#define SN95031_ADC_START 0x08
  104 +#define SN95031_ADC1CNTL3 0x1C2
  105 +#define SN95031_ADCTHERM_ENBL 0x04
  106 +#define SN95031_ADCRRDATA_ENBL 0x05
  107 +#define SN95031_STOPBIT_MASK 16
  108 +#define SN95031_ADCTHERM_MASK 4
  109 +#define SN95031_ADC_CHANLS_MAX 15 /* Number of ADC channels */
  110 +#define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1)
  111 +#define SN95031_ADC_NO_LOOP 0x07
99 112 #define SN95031_AUDIO_GPIO_CTRL 0x070
  113 +
  114 +/* ADC channel code values */
  115 +#define SN95031_AUDIO_DETECT_CODE 0x06
  116 +
  117 +/* ADC base addresses */
  118 +#define SN95031_ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
  119 +#define SN95031_ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */
  120 +/* multipier to convert to mV */
  121 +#define SN95031_ADC_ONE_LSB_MULTIPLIER 2346
  122 +
  123 +
100 124 struct mfld_jack_data {
101 125 int intr_id;
102 126 int micbias_vol;