root/sound/soc/codecs/sirf-audio-codec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adc_enable_delay_event
  2. enable_and_reset_codec
  3. atlas6_codec_enable_and_reset_event
  4. prima2_codec_enable_and_reset_event
  5. sirf_audio_codec_tx_enable
  6. sirf_audio_codec_tx_disable
  7. sirf_audio_codec_rx_enable
  8. sirf_audio_codec_rx_disable
  9. sirf_audio_codec_trigger
  10. sirf_audio_codec_probe
  11. sirf_audio_codec_remove
  12. sirf_audio_codec_driver_probe
  13. sirf_audio_codec_driver_remove
  14. sirf_audio_codec_suspend
  15. sirf_audio_codec_resume

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * SiRF audio codec driver
   4  *
   5  * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
   6  */
   7 
   8 #include <linux/module.h>
   9 #include <linux/platform_device.h>
  10 #include <linux/pm_runtime.h>
  11 #include <linux/of.h>
  12 #include <linux/of_device.h>
  13 #include <linux/clk.h>
  14 #include <linux/delay.h>
  15 #include <linux/io.h>
  16 #include <linux/regmap.h>
  17 #include <sound/core.h>
  18 #include <sound/pcm.h>
  19 #include <sound/pcm_params.h>
  20 #include <sound/initval.h>
  21 #include <sound/tlv.h>
  22 #include <sound/soc.h>
  23 #include <sound/dmaengine_pcm.h>
  24 
  25 #include "sirf-audio-codec.h"
  26 
  27 struct sirf_audio_codec {
  28         struct clk *clk;
  29         struct regmap *regmap;
  30         u32 reg_ctrl0, reg_ctrl1;
  31 };
  32 
  33 static const char * const input_mode_mux[] = {"Single-ended",
  34         "Differential"};
  35 
  36 static const struct soc_enum input_mode_mux_enum =
  37         SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux);
  38 
  39 static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control =
  40         SOC_DAPM_ENUM("Route", input_mode_mux_enum);
  41 
  42 static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0);
  43 static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0);
  44 static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6,
  45         0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0),
  46         0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0),
  47 );
  48 
  49 static struct snd_kcontrol_new volume_controls_atlas6[] = {
  50         SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
  51                         0x7F, 0, playback_vol_tlv),
  52         SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10,
  53                         0x3F, 0, capture_vol_tlv_atlas6),
  54 };
  55 
  56 static struct snd_kcontrol_new volume_controls_prima2[] = {
  57         SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14,
  58                         0x7F, 0, playback_vol_tlv),
  59         SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10,
  60                         0x1F, 0, capture_vol_tlv_prima2),
  61 };
  62 
  63 static struct snd_kcontrol_new left_input_path_controls[] = {
  64         SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0),
  65         SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0),
  66 };
  67 
  68 static struct snd_kcontrol_new right_input_path_controls[] = {
  69         SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0),
  70         SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0),
  71 };
  72 
  73 static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control =
  74         SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0);
  75 
  76 static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control =
  77         SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0);
  78 
  79 static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control =
  80         SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0);
  81 
  82 static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control =
  83         SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0);
  84 
  85 static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control =
  86         SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0);
  87 
  88 static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control =
  89         SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0);
  90 
  91 /* After enable adc, Delay 200ms to avoid pop noise */
  92 static int adc_enable_delay_event(struct snd_soc_dapm_widget *w,
  93                 struct snd_kcontrol *kcontrol, int event)
  94 {
  95         switch (event) {
  96         case SND_SOC_DAPM_POST_PMU:
  97                 msleep(200);
  98                 break;
  99         default:
 100                 break;
 101         }
 102 
 103         return 0;
 104 }
 105 
 106 static void enable_and_reset_codec(struct regmap *regmap,
 107                 u32 codec_enable_bits, u32 codec_reset_bits)
 108 {
 109         regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
 110                         codec_enable_bits | codec_reset_bits,
 111                         codec_enable_bits);
 112         msleep(20);
 113         regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1,
 114                         codec_reset_bits, codec_reset_bits);
 115 }
 116 
 117 static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
 118                 struct snd_kcontrol *kcontrol, int event)
 119 {
 120 #define ATLAS6_CODEC_ENABLE_BITS (1 << 29)
 121 #define ATLAS6_CODEC_RESET_BITS (1 << 28)
 122         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 123         struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
 124         switch (event) {
 125         case SND_SOC_DAPM_PRE_PMU:
 126                 enable_and_reset_codec(sirf_audio_codec->regmap,
 127                         ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS);
 128                 break;
 129         case SND_SOC_DAPM_POST_PMD:
 130                 regmap_update_bits(sirf_audio_codec->regmap,
 131                         AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, 0);
 132                 break;
 133         default:
 134                 break;
 135         }
 136 
 137         return 0;
 138 }
 139 
 140 static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w,
 141                 struct snd_kcontrol *kcontrol, int event)
 142 {
 143 #define PRIMA2_CODEC_ENABLE_BITS (1 << 27)
 144 #define PRIMA2_CODEC_RESET_BITS (1 << 26)
 145         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 146         struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
 147         switch (event) {
 148         case SND_SOC_DAPM_POST_PMU:
 149                 enable_and_reset_codec(sirf_audio_codec->regmap,
 150                         PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS);
 151                 break;
 152         case SND_SOC_DAPM_POST_PMD:
 153                 regmap_update_bits(sirf_audio_codec->regmap,
 154                         AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, 0);
 155                 break;
 156         default:
 157                 break;
 158         }
 159 
 160         return 0;
 161 }
 162 
 163 static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = {
 164         SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
 165                         25, 0, NULL, 0),
 166         SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
 167                         26, 0, NULL, 0),
 168         SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
 169                         27, 0, NULL, 0),
 170 };
 171 
 172 static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = {
 173         SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1,
 174                         23, 0, NULL, 0),
 175         SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1,
 176                         24, 0, NULL, 0),
 177         SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1,
 178                         25, 0, NULL, 0),
 179 };
 180 
 181 static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget =
 182         SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
 183                         atlas6_codec_enable_and_reset_event,
 184                         SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
 185 
 186 static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget =
 187         SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0,
 188                         prima2_codec_enable_and_reset_event,
 189                         SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD);
 190 
 191 static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = {
 192         SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0),
 193         SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0),
 194         SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0,
 195                         &left_dac_to_hp_left_amp_switch_control),
 196         SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0,
 197                         &left_dac_to_hp_right_amp_switch_control),
 198         SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0,
 199                         &right_dac_to_hp_left_amp_switch_control),
 200         SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0,
 201                         &right_dac_to_hp_right_amp_switch_control),
 202         SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
 203                         NULL, 0),
 204         SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0,
 205                         NULL, 0),
 206 
 207         SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0,
 208                         &left_dac_to_speaker_lineout_switch_control),
 209         SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0,
 210                         &right_dac_to_speaker_lineout_switch_control),
 211         SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0,
 212                         NULL, 0),
 213 
 214         SND_SOC_DAPM_OUTPUT("HPOUTL"),
 215         SND_SOC_DAPM_OUTPUT("HPOUTR"),
 216         SND_SOC_DAPM_OUTPUT("SPKOUT"),
 217 
 218         SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0,
 219                         adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
 220         SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0,
 221                         adc_enable_delay_event, SND_SOC_DAPM_POST_PMU),
 222         SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0,
 223                 &left_input_path_controls[0],
 224                 ARRAY_SIZE(left_input_path_controls)),
 225         SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0,
 226                 &right_input_path_controls[0],
 227                 ARRAY_SIZE(right_input_path_controls)),
 228 
 229         SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0,
 230                         &sirf_audio_codec_input_mode_control),
 231         SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0),
 232         SND_SOC_DAPM_INPUT("MICIN1"),
 233         SND_SOC_DAPM_INPUT("MICIN2"),
 234         SND_SOC_DAPM_INPUT("LINEIN1"),
 235         SND_SOC_DAPM_INPUT("LINEIN2"),
 236 
 237         SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0,
 238                         30, 0, NULL, 0),
 239 };
 240 
 241 static const struct snd_soc_dapm_route sirf_audio_codec_map[] = {
 242         {"SPKOUT", NULL, "Speaker Driver"},
 243         {"Speaker Driver", NULL, "Speaker amp driver"},
 244         {"Speaker amp driver", NULL, "Left dac to speaker lineout"},
 245         {"Speaker amp driver", NULL, "Right dac to speaker lineout"},
 246         {"Left dac to speaker lineout", "Switch", "DAC left"},
 247         {"Right dac to speaker lineout", "Switch", "DAC right"},
 248         {"HPOUTL", NULL, "HP Left Driver"},
 249         {"HPOUTR", NULL, "HP Right Driver"},
 250         {"HP Left Driver", NULL, "HP amp left driver"},
 251         {"HP Right Driver", NULL, "HP amp right driver"},
 252         {"HP amp left driver", NULL, "Right dac to hp left amp"},
 253         {"HP amp right driver", NULL , "Right dac to hp right amp"},
 254         {"HP amp left driver", NULL, "Left dac to hp left amp"},
 255         {"HP amp right driver", NULL , "Right dac to hp right amp"},
 256         {"Right dac to hp left amp", "Switch", "DAC left"},
 257         {"Right dac to hp right amp", "Switch", "DAC right"},
 258         {"Left dac to hp left amp", "Switch", "DAC left"},
 259         {"Left dac to hp right amp", "Switch", "DAC right"},
 260         {"DAC left", NULL, "codecclk"},
 261         {"DAC right", NULL, "codecclk"},
 262         {"DAC left", NULL, "Playback"},
 263         {"DAC right", NULL, "Playback"},
 264         {"DAC left", NULL, "HSL Phase Opposite"},
 265         {"DAC right", NULL, "HSL Phase Opposite"},
 266 
 267         {"Capture", NULL, "ADC left"},
 268         {"Capture", NULL, "ADC right"},
 269         {"ADC left", NULL, "codecclk"},
 270         {"ADC right", NULL, "codecclk"},
 271         {"ADC left", NULL, "Left PGA mixer"},
 272         {"ADC right", NULL, "Right PGA mixer"},
 273         {"Left PGA mixer", "Line Left Switch", "LINEIN2"},
 274         {"Right PGA mixer", "Line Right Switch", "LINEIN1"},
 275         {"Left PGA mixer", "Mic Left Switch", "MICIN2"},
 276         {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"},
 277         {"Mic input mode mux", "Single-ended", "MICIN1"},
 278         {"Mic input mode mux", "Differential", "MICIN1"},
 279 };
 280 
 281 static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec)
 282 {
 283         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
 284                 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
 285         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
 286                 AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
 287         regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
 288         regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
 289         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP,
 290                 AUDIO_FIFO_START, AUDIO_FIFO_START);
 291         regmap_update_bits(sirf_audio_codec->regmap,
 292                 AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE);
 293 }
 294 
 295 static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec)
 296 {
 297         regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
 298         regmap_update_bits(sirf_audio_codec->regmap,
 299                 AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE);
 300 }
 301 
 302 static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec,
 303         int channels)
 304 {
 305         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
 306                 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
 307         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
 308                 AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET);
 309         regmap_write(sirf_audio_codec->regmap,
 310                 AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
 311         regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
 312         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP,
 313                 AUDIO_FIFO_START, AUDIO_FIFO_START);
 314         if (channels == 1)
 315                 regmap_update_bits(sirf_audio_codec->regmap,
 316                         AUDIO_PORT_IC_CODEC_RX_CTRL,
 317                         IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
 318         else
 319                 regmap_update_bits(sirf_audio_codec->regmap,
 320                         AUDIO_PORT_IC_CODEC_RX_CTRL,
 321                         IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
 322 }
 323 
 324 static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec)
 325 {
 326         regmap_update_bits(sirf_audio_codec->regmap,
 327                         AUDIO_PORT_IC_CODEC_RX_CTRL,
 328                         IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
 329 }
 330 
 331 static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream,
 332                 int cmd,
 333                 struct snd_soc_dai *dai)
 334 {
 335         struct snd_soc_component *component = dai->component;
 336         struct sirf_audio_codec *sirf_audio_codec = snd_soc_component_get_drvdata(component);
 337         int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 338 
 339         /*
 340          * This is a workaround, When stop playback,
 341          * need disable HP amp, avoid the current noise.
 342          */
 343         switch (cmd) {
 344         case SNDRV_PCM_TRIGGER_STOP:
 345         case SNDRV_PCM_TRIGGER_SUSPEND:
 346         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 347                 if (playback) {
 348                         snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
 349                                 IC_HSLEN | IC_HSREN, 0);
 350                         sirf_audio_codec_tx_disable(sirf_audio_codec);
 351                 } else
 352                         sirf_audio_codec_rx_disable(sirf_audio_codec);
 353                 break;
 354         case SNDRV_PCM_TRIGGER_START:
 355         case SNDRV_PCM_TRIGGER_RESUME:
 356         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 357                 if (playback) {
 358                         sirf_audio_codec_tx_enable(sirf_audio_codec);
 359                         snd_soc_component_update_bits(component, AUDIO_IC_CODEC_CTRL0,
 360                                 IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN);
 361                 } else
 362                         sirf_audio_codec_rx_enable(sirf_audio_codec,
 363                                 substream->runtime->channels);
 364                 break;
 365         default:
 366                 return -EINVAL;
 367         }
 368 
 369         return 0;
 370 }
 371 
 372 static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = {
 373         .trigger = sirf_audio_codec_trigger,
 374 };
 375 
 376 static struct snd_soc_dai_driver sirf_audio_codec_dai = {
 377         .name = "sirf-audio-codec",
 378         .playback = {
 379                 .stream_name = "Playback",
 380                 .channels_min = 2,
 381                 .channels_max = 2,
 382                 .rates = SNDRV_PCM_RATE_48000,
 383                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
 384         },
 385         .capture = {
 386                 .stream_name = "Capture",
 387                 .channels_min = 1,
 388                 .channels_max = 2,
 389                 .rates = SNDRV_PCM_RATE_48000,
 390                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
 391         },
 392         .ops = &sirf_audio_codec_dai_ops,
 393 };
 394 
 395 static int sirf_audio_codec_probe(struct snd_soc_component *component)
 396 {
 397         struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
 398 
 399         pm_runtime_enable(component->dev);
 400 
 401         if (of_device_is_compatible(component->dev->of_node, "sirf,prima2-audio-codec")) {
 402                 snd_soc_dapm_new_controls(dapm,
 403                         prima2_output_driver_dapm_widgets,
 404                         ARRAY_SIZE(prima2_output_driver_dapm_widgets));
 405                 snd_soc_dapm_new_controls(dapm,
 406                         &prima2_codec_clock_dapm_widget, 1);
 407                 return snd_soc_add_component_controls(component,
 408                         volume_controls_prima2,
 409                         ARRAY_SIZE(volume_controls_prima2));
 410         }
 411         if (of_device_is_compatible(component->dev->of_node, "sirf,atlas6-audio-codec")) {
 412                 snd_soc_dapm_new_controls(dapm,
 413                         atlas6_output_driver_dapm_widgets,
 414                         ARRAY_SIZE(atlas6_output_driver_dapm_widgets));
 415                 snd_soc_dapm_new_controls(dapm,
 416                         &atlas6_codec_clock_dapm_widget, 1);
 417                 return snd_soc_add_component_controls(component,
 418                         volume_controls_atlas6,
 419                         ARRAY_SIZE(volume_controls_atlas6));
 420         }
 421 
 422         return -EINVAL;
 423 }
 424 
 425 static void sirf_audio_codec_remove(struct snd_soc_component *component)
 426 {
 427         pm_runtime_disable(component->dev);
 428 }
 429 
 430 static const struct snd_soc_component_driver soc_codec_device_sirf_audio_codec = {
 431         .probe                  = sirf_audio_codec_probe,
 432         .remove                 = sirf_audio_codec_remove,
 433         .dapm_widgets           = sirf_audio_codec_dapm_widgets,
 434         .num_dapm_widgets       = ARRAY_SIZE(sirf_audio_codec_dapm_widgets),
 435         .dapm_routes            = sirf_audio_codec_map,
 436         .num_dapm_routes        = ARRAY_SIZE(sirf_audio_codec_map),
 437         .use_pmdown_time        = 1,
 438         .endianness             = 1,
 439         .non_legacy_dai_naming  = 1,
 440 };
 441 
 442 static const struct of_device_id sirf_audio_codec_of_match[] = {
 443         { .compatible = "sirf,prima2-audio-codec" },
 444         { .compatible = "sirf,atlas6-audio-codec" },
 445         {}
 446 };
 447 MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match);
 448 
 449 static const struct regmap_config sirf_audio_codec_regmap_config = {
 450         .reg_bits = 32,
 451         .reg_stride = 4,
 452         .val_bits = 32,
 453         .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
 454         .cache_type = REGCACHE_NONE,
 455 };
 456 
 457 static int sirf_audio_codec_driver_probe(struct platform_device *pdev)
 458 {
 459         int ret;
 460         struct sirf_audio_codec *sirf_audio_codec;
 461         void __iomem *base;
 462 
 463         sirf_audio_codec = devm_kzalloc(&pdev->dev,
 464                 sizeof(struct sirf_audio_codec), GFP_KERNEL);
 465         if (!sirf_audio_codec)
 466                 return -ENOMEM;
 467 
 468         platform_set_drvdata(pdev, sirf_audio_codec);
 469 
 470         base = devm_platform_ioremap_resource(pdev, 0);
 471         if (IS_ERR(base))
 472                 return PTR_ERR(base);
 473 
 474         sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 475                                             &sirf_audio_codec_regmap_config);
 476         if (IS_ERR(sirf_audio_codec->regmap))
 477                 return PTR_ERR(sirf_audio_codec->regmap);
 478 
 479         sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL);
 480         if (IS_ERR(sirf_audio_codec->clk)) {
 481                 dev_err(&pdev->dev, "Get clock failed.\n");
 482                 return PTR_ERR(sirf_audio_codec->clk);
 483         }
 484 
 485         ret = clk_prepare_enable(sirf_audio_codec->clk);
 486         if (ret) {
 487                 dev_err(&pdev->dev, "Enable clock failed.\n");
 488                 return ret;
 489         }
 490 
 491         ret = devm_snd_soc_register_component(&(pdev->dev),
 492                         &soc_codec_device_sirf_audio_codec,
 493                         &sirf_audio_codec_dai, 1);
 494         if (ret) {
 495                 dev_err(&pdev->dev, "Register Audio Codec dai failed.\n");
 496                 goto err_clk_put;
 497         }
 498 
 499         /*
 500          * Always open charge pump, if not, when the charge pump closed the
 501          * adc will not stable
 502          */
 503         regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
 504                 IC_CPFREQ, IC_CPFREQ);
 505 
 506         if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec"))
 507                 regmap_update_bits(sirf_audio_codec->regmap,
 508                                 AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN);
 509         return 0;
 510 
 511 err_clk_put:
 512         clk_disable_unprepare(sirf_audio_codec->clk);
 513         return ret;
 514 }
 515 
 516 static int sirf_audio_codec_driver_remove(struct platform_device *pdev)
 517 {
 518         struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev);
 519 
 520         clk_disable_unprepare(sirf_audio_codec->clk);
 521 
 522         return 0;
 523 }
 524 
 525 #ifdef CONFIG_PM_SLEEP
 526 static int sirf_audio_codec_suspend(struct device *dev)
 527 {
 528         struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
 529 
 530         regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
 531                 &sirf_audio_codec->reg_ctrl0);
 532         regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
 533                 &sirf_audio_codec->reg_ctrl1);
 534         clk_disable_unprepare(sirf_audio_codec->clk);
 535 
 536         return 0;
 537 }
 538 
 539 static int sirf_audio_codec_resume(struct device *dev)
 540 {
 541         struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev);
 542         int ret;
 543 
 544         ret = clk_prepare_enable(sirf_audio_codec->clk);
 545         if (ret)
 546                 return ret;
 547 
 548         regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0,
 549                 sirf_audio_codec->reg_ctrl0);
 550         regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1,
 551                 sirf_audio_codec->reg_ctrl1);
 552 
 553         return 0;
 554 }
 555 #endif
 556 
 557 static const struct dev_pm_ops sirf_audio_codec_pm_ops = {
 558         SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume)
 559 };
 560 
 561 static struct platform_driver sirf_audio_codec_driver = {
 562         .driver = {
 563                 .name = "sirf-audio-codec",
 564                 .of_match_table = sirf_audio_codec_of_match,
 565                 .pm = &sirf_audio_codec_pm_ops,
 566         },
 567         .probe = sirf_audio_codec_driver_probe,
 568         .remove = sirf_audio_codec_driver_remove,
 569 };
 570 
 571 module_platform_driver(sirf_audio_codec_driver);
 572 
 573 MODULE_DESCRIPTION("SiRF audio codec driver");
 574 MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
 575 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */