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 27struct sirf_audio_codec { 28 struct clk *clk; 29 struct regmap *regmap; 30 u32 reg_ctrl0, reg_ctrl1; 31}; 32 33static const char * const input_mode_mux[] = {"Single-ended", 34 "Differential"}; 35 36static const struct soc_enum input_mode_mux_enum = 37 SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux); 38 39static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control = 40 SOC_DAPM_ENUM("Route", input_mode_mux_enum); 41 42static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0); 43static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0); 44static 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 49static 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 56static 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 63static 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 68static 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 73static 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 76static 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 79static 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 82static 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 85static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control = 86 SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0); 87 88static 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 */ 92static 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 106static 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 117static 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 140static 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 163static 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 172static 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 181static 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 186static 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 191static 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 241static 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 281static 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 295static 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 302static 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 324static 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 331static 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 372static const struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { 373 .trigger = sirf_audio_codec_trigger, 374}; 375 376static 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 395static 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 425static void sirf_audio_codec_remove(struct snd_soc_component *component) 426{ 427 pm_runtime_disable(component->dev); 428} 429 430static 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 442static const struct of_device_id sirf_audio_codec_of_match[] = { 443 { .compatible = "sirf,prima2-audio-codec" }, 444 { .compatible = "sirf,atlas6-audio-codec" }, 445 {} 446}; 447MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match); 448 449static 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 457static 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 511err_clk_put: 512 clk_disable_unprepare(sirf_audio_codec->clk); 513 return ret; 514} 515 516static 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 526static 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 539static 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 557static 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 561static 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 571module_platform_driver(sirf_audio_codec_driver); 572 573MODULE_DESCRIPTION("SiRF audio codec driver"); 574MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>"); 575MODULE_LICENSE("GPL v2"); 576