1 /* 2 * Copyright (C) ST-Ericsson SA 2012 3 * 4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>, 5 * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com> 6 * for ST-Ericsson. 7 * 8 * License terms: 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as published 12 * by the Free Software Foundation. 13 */ 14 15 #include <linux/module.h> 16 #include <linux/device.h> 17 #include <linux/io.h> 18 #include <linux/clk.h> 19 20 #include <sound/soc.h> 21 #include <sound/soc-dapm.h> 22 #include <sound/pcm.h> 23 #include <sound/pcm_params.h> 24 25 #include "ux500_pcm.h" 26 #include "ux500_msp_dai.h" 27 #include "../codecs/ab8500-codec.h" 28 29 #define TX_SLOT_MONO 0x0008 30 #define TX_SLOT_STEREO 0x000a 31 #define RX_SLOT_MONO 0x0001 32 #define RX_SLOT_STEREO 0x0003 33 #define TX_SLOT_8CH 0x00FF 34 #define RX_SLOT_8CH 0x00FF 35 36 #define DEF_TX_SLOTS TX_SLOT_STEREO 37 #define DEF_RX_SLOTS RX_SLOT_MONO 38 39 #define DRIVERMODE_NORMAL 0 40 #define DRIVERMODE_CODEC_ONLY 1 41 42 /* Slot configuration */ 43 static unsigned int tx_slots = DEF_TX_SLOTS; 44 static unsigned int rx_slots = DEF_RX_SLOTS; 45 46 /* Clocks */ 47 static const char * const enum_mclk[] = { 48 "SYSCLK", 49 "ULPCLK" 50 }; 51 enum mclk { 52 MCLK_SYSCLK, 53 MCLK_ULPCLK, 54 }; 55 56 static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_mclk, enum_mclk); 57 58 /* Private data for machine-part MOP500<->AB8500 */ 59 struct mop500_ab8500_drvdata { 60 /* Clocks */ 61 enum mclk mclk_sel; 62 struct clk *clk_ptr_intclk; 63 struct clk *clk_ptr_sysclk; 64 struct clk *clk_ptr_ulpclk; 65 }; 66 67 static inline const char *get_mclk_str(enum mclk mclk_sel) 68 { 69 switch (mclk_sel) { 70 case MCLK_SYSCLK: 71 return "SYSCLK"; 72 case MCLK_ULPCLK: 73 return "ULPCLK"; 74 default: 75 return "Unknown"; 76 } 77 } 78 79 static int mop500_ab8500_set_mclk(struct device *dev, 80 struct mop500_ab8500_drvdata *drvdata) 81 { 82 int status; 83 struct clk *clk_ptr; 84 85 if (IS_ERR(drvdata->clk_ptr_intclk)) { 86 dev_err(dev, 87 "%s: ERROR: intclk not initialized!\n", __func__); 88 return -EIO; 89 } 90 91 switch (drvdata->mclk_sel) { 92 case MCLK_SYSCLK: 93 clk_ptr = drvdata->clk_ptr_sysclk; 94 break; 95 case MCLK_ULPCLK: 96 clk_ptr = drvdata->clk_ptr_ulpclk; 97 break; 98 default: 99 return -EINVAL; 100 } 101 102 if (IS_ERR(clk_ptr)) { 103 dev_err(dev, "%s: ERROR: %s not initialized!\n", __func__, 104 get_mclk_str(drvdata->mclk_sel)); 105 return -EIO; 106 } 107 108 status = clk_set_parent(drvdata->clk_ptr_intclk, clk_ptr); 109 if (status) 110 dev_err(dev, 111 "%s: ERROR: Setting intclk parent to %s failed (ret = %d)!", 112 __func__, get_mclk_str(drvdata->mclk_sel), status); 113 else 114 dev_dbg(dev, 115 "%s: intclk parent changed to %s.\n", 116 __func__, get_mclk_str(drvdata->mclk_sel)); 117 118 return status; 119 } 120 121 /* 122 * Control-events 123 */ 124 125 static int mclk_input_control_get(struct snd_kcontrol *kcontrol, 126 struct snd_ctl_elem_value *ucontrol) 127 { 128 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 129 struct mop500_ab8500_drvdata *drvdata = 130 snd_soc_card_get_drvdata(codec->card); 131 132 ucontrol->value.enumerated.item[0] = drvdata->mclk_sel; 133 134 return 0; 135 } 136 137 static int mclk_input_control_put(struct snd_kcontrol *kcontrol, 138 struct snd_ctl_elem_value *ucontrol) 139 { 140 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 141 struct mop500_ab8500_drvdata *drvdata = 142 snd_soc_card_get_drvdata(codec->card); 143 unsigned int val = ucontrol->value.enumerated.item[0]; 144 145 if (val > (unsigned int)MCLK_ULPCLK) 146 return -EINVAL; 147 if (drvdata->mclk_sel == val) 148 return 0; 149 150 drvdata->mclk_sel = val; 151 152 return 1; 153 } 154 155 /* 156 * Controls 157 */ 158 159 static struct snd_kcontrol_new mop500_ab8500_ctrls[] = { 160 SOC_ENUM_EXT("Master Clock Select", 161 soc_enum_mclk, 162 mclk_input_control_get, mclk_input_control_put), 163 /* Digital interface - Clocks */ 164 SOC_SINGLE("Digital Interface Master Generator Switch", 165 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENMASTGEN, 166 1, 0), 167 SOC_SINGLE("Digital Interface 0 Bit-clock Switch", 168 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK0, 169 1, 0), 170 SOC_SINGLE("Digital Interface 1 Bit-clock Switch", 171 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK1, 172 1, 0), 173 SOC_DAPM_PIN_SWITCH("Headset Left"), 174 SOC_DAPM_PIN_SWITCH("Headset Right"), 175 SOC_DAPM_PIN_SWITCH("Earpiece"), 176 SOC_DAPM_PIN_SWITCH("Speaker Left"), 177 SOC_DAPM_PIN_SWITCH("Speaker Right"), 178 SOC_DAPM_PIN_SWITCH("LineOut Left"), 179 SOC_DAPM_PIN_SWITCH("LineOut Right"), 180 SOC_DAPM_PIN_SWITCH("Vibra 1"), 181 SOC_DAPM_PIN_SWITCH("Vibra 2"), 182 SOC_DAPM_PIN_SWITCH("Mic 1"), 183 SOC_DAPM_PIN_SWITCH("Mic 2"), 184 SOC_DAPM_PIN_SWITCH("LineIn Left"), 185 SOC_DAPM_PIN_SWITCH("LineIn Right"), 186 SOC_DAPM_PIN_SWITCH("DMic 1"), 187 SOC_DAPM_PIN_SWITCH("DMic 2"), 188 SOC_DAPM_PIN_SWITCH("DMic 3"), 189 SOC_DAPM_PIN_SWITCH("DMic 4"), 190 SOC_DAPM_PIN_SWITCH("DMic 5"), 191 SOC_DAPM_PIN_SWITCH("DMic 6"), 192 }; 193 194 /* ASoC */ 195 196 int mop500_ab8500_startup(struct snd_pcm_substream *substream) 197 { 198 struct snd_soc_pcm_runtime *rtd = substream->private_data; 199 200 /* Set audio-clock source */ 201 return mop500_ab8500_set_mclk(rtd->card->dev, 202 snd_soc_card_get_drvdata(rtd->card)); 203 } 204 205 void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) 206 { 207 struct snd_soc_pcm_runtime *rtd = substream->private_data; 208 struct device *dev = rtd->card->dev; 209 210 dev_dbg(dev, "%s: Enter\n", __func__); 211 212 /* Reset slots configuration to default(s) */ 213 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 214 tx_slots = DEF_TX_SLOTS; 215 else 216 rx_slots = DEF_RX_SLOTS; 217 } 218 219 int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, 220 struct snd_pcm_hw_params *params) 221 { 222 struct snd_soc_pcm_runtime *rtd = substream->private_data; 223 struct snd_soc_dai *codec_dai = rtd->codec_dai; 224 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 225 struct device *dev = rtd->card->dev; 226 unsigned int fmt; 227 int channels, ret = 0, driver_mode, slots; 228 unsigned int sw_codec, sw_cpu; 229 bool is_playback; 230 231 dev_dbg(dev, "%s: Enter\n", __func__); 232 233 dev_dbg(dev, "%s: substream->pcm->name = %s\n" 234 "substream->pcm->id = %s.\n" 235 "substream->name = %s.\n" 236 "substream->number = %d.\n", 237 __func__, 238 substream->pcm->name, 239 substream->pcm->id, 240 substream->name, 241 substream->number); 242 243 channels = params_channels(params); 244 245 switch (params_format(params)) { 246 case SNDRV_PCM_FORMAT_S32_LE: 247 sw_cpu = 32; 248 break; 249 250 case SNDRV_PCM_FORMAT_S16_LE: 251 sw_cpu = 16; 252 break; 253 254 default: 255 return -EINVAL; 256 } 257 258 /* Setup codec depending on driver-mode */ 259 if (channels == 8) 260 driver_mode = DRIVERMODE_CODEC_ONLY; 261 else 262 driver_mode = DRIVERMODE_NORMAL; 263 dev_dbg(dev, "%s: Driver-mode: %s.\n", __func__, 264 (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY"); 265 266 /* Setup format */ 267 268 if (driver_mode == DRIVERMODE_NORMAL) { 269 fmt = SND_SOC_DAIFMT_DSP_A | 270 SND_SOC_DAIFMT_CBM_CFM | 271 SND_SOC_DAIFMT_NB_NF | 272 SND_SOC_DAIFMT_CONT; 273 } else { 274 fmt = SND_SOC_DAIFMT_DSP_A | 275 SND_SOC_DAIFMT_CBM_CFM | 276 SND_SOC_DAIFMT_NB_NF | 277 SND_SOC_DAIFMT_GATED; 278 } 279 280 ret = snd_soc_dai_set_fmt(codec_dai, fmt); 281 if (ret < 0) { 282 dev_err(dev, 283 "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", 284 __func__, ret); 285 return ret; 286 } 287 288 ret = snd_soc_dai_set_fmt(cpu_dai, fmt); 289 if (ret < 0) { 290 dev_err(dev, 291 "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n", 292 __func__, ret); 293 return ret; 294 } 295 296 /* Setup TDM-slots */ 297 298 is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 299 switch (channels) { 300 case 1: 301 slots = 16; 302 tx_slots = (is_playback) ? TX_SLOT_MONO : 0; 303 rx_slots = (is_playback) ? 0 : RX_SLOT_MONO; 304 break; 305 case 2: 306 slots = 16; 307 tx_slots = (is_playback) ? TX_SLOT_STEREO : 0; 308 rx_slots = (is_playback) ? 0 : RX_SLOT_STEREO; 309 break; 310 case 8: 311 slots = 16; 312 tx_slots = (is_playback) ? TX_SLOT_8CH : 0; 313 rx_slots = (is_playback) ? 0 : RX_SLOT_8CH; 314 break; 315 default: 316 return -EINVAL; 317 } 318 319 if (driver_mode == DRIVERMODE_NORMAL) 320 sw_codec = sw_cpu; 321 else 322 sw_codec = 20; 323 324 dev_dbg(dev, "%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, 325 tx_slots, rx_slots); 326 ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots, 327 sw_cpu); 328 if (ret) 329 return ret; 330 331 dev_dbg(dev, "%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, 332 tx_slots, rx_slots); 333 ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots, 334 sw_codec); 335 if (ret) 336 return ret; 337 338 return 0; 339 } 340 341 struct snd_soc_ops mop500_ab8500_ops[] = { 342 { 343 .hw_params = mop500_ab8500_hw_params, 344 .startup = mop500_ab8500_startup, 345 .shutdown = mop500_ab8500_shutdown, 346 } 347 }; 348 349 int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) 350 { 351 struct snd_soc_codec *codec = rtd->codec; 352 struct device *dev = rtd->card->dev; 353 struct mop500_ab8500_drvdata *drvdata; 354 int ret; 355 356 dev_dbg(dev, "%s Enter.\n", __func__); 357 358 /* Create driver private-data struct */ 359 drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata), 360 GFP_KERNEL); 361 snd_soc_card_set_drvdata(rtd->card, drvdata); 362 363 /* Setup clocks */ 364 365 drvdata->clk_ptr_sysclk = clk_get(dev, "sysclk"); 366 if (IS_ERR(drvdata->clk_ptr_sysclk)) 367 dev_warn(dev, "%s: WARNING: clk_get failed for 'sysclk'!\n", 368 __func__); 369 drvdata->clk_ptr_ulpclk = clk_get(dev, "ulpclk"); 370 if (IS_ERR(drvdata->clk_ptr_ulpclk)) 371 dev_warn(dev, "%s: WARNING: clk_get failed for 'ulpclk'!\n", 372 __func__); 373 drvdata->clk_ptr_intclk = clk_get(dev, "intclk"); 374 if (IS_ERR(drvdata->clk_ptr_intclk)) 375 dev_warn(dev, "%s: WARNING: clk_get failed for 'intclk'!\n", 376 __func__); 377 378 /* Set intclk default parent to ulpclk */ 379 drvdata->mclk_sel = MCLK_ULPCLK; 380 ret = mop500_ab8500_set_mclk(dev, drvdata); 381 if (ret < 0) 382 dev_warn(dev, "%s: WARNING: mop500_ab8500_set_mclk!\n", 383 __func__); 384 385 drvdata->mclk_sel = MCLK_ULPCLK; 386 387 /* Add controls */ 388 ret = snd_soc_add_codec_controls(codec, mop500_ab8500_ctrls, 389 ARRAY_SIZE(mop500_ab8500_ctrls)); 390 if (ret < 0) { 391 pr_err("%s: Failed to add machine-controls (%d)!\n", 392 __func__, ret); 393 return ret; 394 } 395 396 ret = snd_soc_dapm_disable_pin(&codec->dapm, "Earpiece"); 397 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Left"); 398 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Right"); 399 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Left"); 400 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Right"); 401 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 1"); 402 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 2"); 403 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 1"); 404 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 2"); 405 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Left"); 406 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Right"); 407 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 1"); 408 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 2"); 409 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 3"); 410 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 4"); 411 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 5"); 412 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 6"); 413 414 return ret; 415 } 416 417 void mop500_ab8500_remove(struct snd_soc_card *card) 418 { 419 struct mop500_ab8500_drvdata *drvdata = snd_soc_card_get_drvdata(card); 420 421 if (drvdata->clk_ptr_sysclk != NULL) 422 clk_put(drvdata->clk_ptr_sysclk); 423 if (drvdata->clk_ptr_ulpclk != NULL) 424 clk_put(drvdata->clk_ptr_ulpclk); 425 if (drvdata->clk_ptr_intclk != NULL) 426 clk_put(drvdata->clk_ptr_intclk); 427 428 snd_soc_card_set_drvdata(card, drvdata); 429 } 430