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