1/* 2 * SoC audio for HTC Magician 3 * 4 * Copyright (c) 2006 Philipp Zabel <philipp.zabel@gmail.com> 5 * 6 * based on spitz.c, 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk> 8 * Richard Purdie <richard@openedhand.com> 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 * 15 */ 16 17#include <linux/module.h> 18#include <linux/timer.h> 19#include <linux/interrupt.h> 20#include <linux/platform_device.h> 21#include <linux/delay.h> 22#include <linux/gpio.h> 23#include <linux/i2c.h> 24 25#include <sound/core.h> 26#include <sound/pcm.h> 27#include <sound/pcm_params.h> 28#include <sound/soc.h> 29#include <sound/uda1380.h> 30 31#include <mach/magician.h> 32#include <asm/mach-types.h> 33#include "../codecs/uda1380.h" 34#include "pxa2xx-i2s.h" 35#include "pxa-ssp.h" 36 37#define MAGICIAN_MIC 0 38#define MAGICIAN_MIC_EXT 1 39 40static int magician_hp_switch; 41static int magician_spk_switch = 1; 42static int magician_in_sel = MAGICIAN_MIC; 43 44static void magician_ext_control(struct snd_soc_dapm_context *dapm) 45{ 46 47 snd_soc_dapm_mutex_lock(dapm); 48 49 if (magician_spk_switch) 50 snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); 51 else 52 snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); 53 if (magician_hp_switch) 54 snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); 55 else 56 snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); 57 58 switch (magician_in_sel) { 59 case MAGICIAN_MIC: 60 snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Mic"); 61 snd_soc_dapm_enable_pin_unlocked(dapm, "Call Mic"); 62 break; 63 case MAGICIAN_MIC_EXT: 64 snd_soc_dapm_disable_pin_unlocked(dapm, "Call Mic"); 65 snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Mic"); 66 break; 67 } 68 69 snd_soc_dapm_sync_unlocked(dapm); 70 71 snd_soc_dapm_mutex_unlock(dapm); 72} 73 74static int magician_startup(struct snd_pcm_substream *substream) 75{ 76 struct snd_soc_pcm_runtime *rtd = substream->private_data; 77 78 /* check the jack status at stream startup */ 79 magician_ext_control(&rtd->card->dapm); 80 81 return 0; 82} 83 84/* 85 * Magician uses SSP port for playback. 86 */ 87static int magician_playback_hw_params(struct snd_pcm_substream *substream, 88 struct snd_pcm_hw_params *params) 89{ 90 struct snd_soc_pcm_runtime *rtd = substream->private_data; 91 struct snd_soc_dai *codec_dai = rtd->codec_dai; 92 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 93 unsigned int acps, acds, width; 94 unsigned int div4 = PXA_SSP_CLK_SCDB_4; 95 int ret = 0; 96 97 width = snd_pcm_format_physical_width(params_format(params)); 98 99 /* 100 * rate = SSPSCLK / (2 * width(16 or 32)) 101 * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1) 102 */ 103 switch (params_rate(params)) { 104 case 8000: 105 /* off by a factor of 2: bug in the PXA27x audio clock? */ 106 acps = 32842000; 107 switch (width) { 108 case 16: 109 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */ 110 acds = PXA_SSP_CLK_AUDIO_DIV_16; 111 break; 112 default: /* 32 */ 113 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */ 114 acds = PXA_SSP_CLK_AUDIO_DIV_8; 115 } 116 break; 117 case 11025: 118 acps = 5622000; 119 switch (width) { 120 case 16: 121 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */ 122 acds = PXA_SSP_CLK_AUDIO_DIV_4; 123 break; 124 default: /* 32 */ 125 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */ 126 acds = PXA_SSP_CLK_AUDIO_DIV_2; 127 } 128 break; 129 case 22050: 130 acps = 5622000; 131 switch (width) { 132 case 16: 133 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */ 134 acds = PXA_SSP_CLK_AUDIO_DIV_2; 135 break; 136 default: /* 32 */ 137 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */ 138 acds = PXA_SSP_CLK_AUDIO_DIV_1; 139 } 140 break; 141 case 44100: 142 acps = 5622000; 143 switch (width) { 144 case 16: 145 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */ 146 acds = PXA_SSP_CLK_AUDIO_DIV_2; 147 break; 148 default: /* 32 */ 149 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */ 150 acds = PXA_SSP_CLK_AUDIO_DIV_1; 151 } 152 break; 153 case 48000: 154 acps = 12235000; 155 switch (width) { 156 case 16: 157 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */ 158 acds = PXA_SSP_CLK_AUDIO_DIV_2; 159 break; 160 default: /* 32 */ 161 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */ 162 acds = PXA_SSP_CLK_AUDIO_DIV_1; 163 } 164 break; 165 case 96000: 166 default: 167 acps = 12235000; 168 switch (width) { 169 case 16: 170 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */ 171 acds = PXA_SSP_CLK_AUDIO_DIV_1; 172 break; 173 default: /* 32 */ 174 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */ 175 acds = PXA_SSP_CLK_AUDIO_DIV_2; 176 div4 = PXA_SSP_CLK_SCDB_1; 177 break; 178 } 179 break; 180 } 181 182 /* set codec DAI configuration */ 183 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_MSB | 184 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 185 if (ret < 0) 186 return ret; 187 188 /* set cpu DAI configuration */ 189 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 190 SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS); 191 if (ret < 0) 192 return ret; 193 194 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 0, 1, width); 195 if (ret < 0) 196 return ret; 197 198 /* set audio clock as clock source */ 199 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 200 SND_SOC_CLOCK_OUT); 201 if (ret < 0) 202 return ret; 203 204 /* set the SSP audio system clock ACDS divider */ 205 ret = snd_soc_dai_set_clkdiv(cpu_dai, 206 PXA_SSP_AUDIO_DIV_ACDS, acds); 207 if (ret < 0) 208 return ret; 209 210 /* set the SSP audio system clock SCDB divider4 */ 211 ret = snd_soc_dai_set_clkdiv(cpu_dai, 212 PXA_SSP_AUDIO_DIV_SCDB, div4); 213 if (ret < 0) 214 return ret; 215 216 /* set SSP audio pll clock */ 217 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, acps); 218 if (ret < 0) 219 return ret; 220 221 return 0; 222} 223 224/* 225 * Magician uses I2S for capture. 226 */ 227static int magician_capture_hw_params(struct snd_pcm_substream *substream, 228 struct snd_pcm_hw_params *params) 229{ 230 struct snd_soc_pcm_runtime *rtd = substream->private_data; 231 struct snd_soc_dai *codec_dai = rtd->codec_dai; 232 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 233 int ret = 0; 234 235 /* set codec DAI configuration */ 236 ret = snd_soc_dai_set_fmt(codec_dai, 237 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | 238 SND_SOC_DAIFMT_CBS_CFS); 239 if (ret < 0) 240 return ret; 241 242 /* set cpu DAI configuration */ 243 ret = snd_soc_dai_set_fmt(cpu_dai, 244 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | 245 SND_SOC_DAIFMT_CBS_CFS); 246 if (ret < 0) 247 return ret; 248 249 /* set the I2S system clock as output */ 250 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, 251 SND_SOC_CLOCK_OUT); 252 if (ret < 0) 253 return ret; 254 255 return 0; 256} 257 258static struct snd_soc_ops magician_capture_ops = { 259 .startup = magician_startup, 260 .hw_params = magician_capture_hw_params, 261}; 262 263static struct snd_soc_ops magician_playback_ops = { 264 .startup = magician_startup, 265 .hw_params = magician_playback_hw_params, 266}; 267 268static int magician_get_hp(struct snd_kcontrol *kcontrol, 269 struct snd_ctl_elem_value *ucontrol) 270{ 271 ucontrol->value.integer.value[0] = magician_hp_switch; 272 return 0; 273} 274 275static int magician_set_hp(struct snd_kcontrol *kcontrol, 276 struct snd_ctl_elem_value *ucontrol) 277{ 278 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 279 280 if (magician_hp_switch == ucontrol->value.integer.value[0]) 281 return 0; 282 283 magician_hp_switch = ucontrol->value.integer.value[0]; 284 magician_ext_control(&card->dapm); 285 return 1; 286} 287 288static int magician_get_spk(struct snd_kcontrol *kcontrol, 289 struct snd_ctl_elem_value *ucontrol) 290{ 291 ucontrol->value.integer.value[0] = magician_spk_switch; 292 return 0; 293} 294 295static int magician_set_spk(struct snd_kcontrol *kcontrol, 296 struct snd_ctl_elem_value *ucontrol) 297{ 298 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 299 300 if (magician_spk_switch == ucontrol->value.integer.value[0]) 301 return 0; 302 303 magician_spk_switch = ucontrol->value.integer.value[0]; 304 magician_ext_control(&card->dapm); 305 return 1; 306} 307 308static int magician_get_input(struct snd_kcontrol *kcontrol, 309 struct snd_ctl_elem_value *ucontrol) 310{ 311 ucontrol->value.integer.value[0] = magician_in_sel; 312 return 0; 313} 314 315static int magician_set_input(struct snd_kcontrol *kcontrol, 316 struct snd_ctl_elem_value *ucontrol) 317{ 318 if (magician_in_sel == ucontrol->value.integer.value[0]) 319 return 0; 320 321 magician_in_sel = ucontrol->value.integer.value[0]; 322 323 switch (magician_in_sel) { 324 case MAGICIAN_MIC: 325 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 1); 326 break; 327 case MAGICIAN_MIC_EXT: 328 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 0); 329 } 330 331 return 1; 332} 333 334static int magician_spk_power(struct snd_soc_dapm_widget *w, 335 struct snd_kcontrol *k, int event) 336{ 337 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, SND_SOC_DAPM_EVENT_ON(event)); 338 return 0; 339} 340 341static int magician_hp_power(struct snd_soc_dapm_widget *w, 342 struct snd_kcontrol *k, int event) 343{ 344 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, SND_SOC_DAPM_EVENT_ON(event)); 345 return 0; 346} 347 348static int magician_mic_bias(struct snd_soc_dapm_widget *w, 349 struct snd_kcontrol *k, int event) 350{ 351 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, SND_SOC_DAPM_EVENT_ON(event)); 352 return 0; 353} 354 355/* magician machine dapm widgets */ 356static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { 357 SND_SOC_DAPM_HP("Headphone Jack", magician_hp_power), 358 SND_SOC_DAPM_SPK("Speaker", magician_spk_power), 359 SND_SOC_DAPM_MIC("Call Mic", magician_mic_bias), 360 SND_SOC_DAPM_MIC("Headset Mic", magician_mic_bias), 361}; 362 363/* magician machine audio_map */ 364static const struct snd_soc_dapm_route audio_map[] = { 365 366 /* Headphone connected to VOUTL, VOUTR */ 367 {"Headphone Jack", NULL, "VOUTL"}, 368 {"Headphone Jack", NULL, "VOUTR"}, 369 370 /* Speaker connected to VOUTL, VOUTR */ 371 {"Speaker", NULL, "VOUTL"}, 372 {"Speaker", NULL, "VOUTR"}, 373 374 /* Mics are connected to VINM */ 375 {"VINM", NULL, "Headset Mic"}, 376 {"VINM", NULL, "Call Mic"}, 377}; 378 379static const char *input_select[] = {"Call Mic", "Headset Mic"}; 380static const struct soc_enum magician_in_sel_enum = 381 SOC_ENUM_SINGLE_EXT(2, input_select); 382 383static const struct snd_kcontrol_new uda1380_magician_controls[] = { 384 SOC_SINGLE_BOOL_EXT("Headphone Switch", 385 (unsigned long)&magician_hp_switch, 386 magician_get_hp, magician_set_hp), 387 SOC_SINGLE_BOOL_EXT("Speaker Switch", 388 (unsigned long)&magician_spk_switch, 389 magician_get_spk, magician_set_spk), 390 SOC_ENUM_EXT("Input Select", magician_in_sel_enum, 391 magician_get_input, magician_set_input), 392}; 393 394/* magician digital audio interface glue - connects codec <--> CPU */ 395static struct snd_soc_dai_link magician_dai[] = { 396{ 397 .name = "uda1380", 398 .stream_name = "UDA1380 Playback", 399 .cpu_dai_name = "pxa-ssp-dai.0", 400 .codec_dai_name = "uda1380-hifi-playback", 401 .platform_name = "pxa-pcm-audio", 402 .codec_name = "uda1380-codec.0-0018", 403 .ops = &magician_playback_ops, 404}, 405{ 406 .name = "uda1380", 407 .stream_name = "UDA1380 Capture", 408 .cpu_dai_name = "pxa2xx-i2s", 409 .codec_dai_name = "uda1380-hifi-capture", 410 .platform_name = "pxa-pcm-audio", 411 .codec_name = "uda1380-codec.0-0018", 412 .ops = &magician_capture_ops, 413} 414}; 415 416/* magician audio machine driver */ 417static struct snd_soc_card snd_soc_card_magician = { 418 .name = "Magician", 419 .owner = THIS_MODULE, 420 .dai_link = magician_dai, 421 .num_links = ARRAY_SIZE(magician_dai), 422 423 .controls = uda1380_magician_controls, 424 .num_controls = ARRAY_SIZE(uda1380_magician_controls), 425 .dapm_widgets = uda1380_dapm_widgets, 426 .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), 427 .dapm_routes = audio_map, 428 .num_dapm_routes = ARRAY_SIZE(audio_map), 429 .fully_routed = true, 430}; 431 432static struct platform_device *magician_snd_device; 433 434/* 435 * FIXME: move into magician board file once merged into the pxa tree 436 */ 437static struct uda1380_platform_data uda1380_info = { 438 .gpio_power = EGPIO_MAGICIAN_CODEC_POWER, 439 .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET, 440 .dac_clk = UDA1380_DAC_CLK_WSPLL, 441}; 442 443static struct i2c_board_info i2c_board_info[] = { 444 { 445 I2C_BOARD_INFO("uda1380", 0x18), 446 .platform_data = &uda1380_info, 447 }, 448}; 449 450static int __init magician_init(void) 451{ 452 int ret; 453 struct i2c_adapter *adapter; 454 struct i2c_client *client; 455 456 if (!machine_is_magician()) 457 return -ENODEV; 458 459 adapter = i2c_get_adapter(0); 460 if (!adapter) 461 return -ENODEV; 462 client = i2c_new_device(adapter, i2c_board_info); 463 i2c_put_adapter(adapter); 464 if (!client) 465 return -ENODEV; 466 467 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER"); 468 if (ret) 469 goto err_request_spk; 470 ret = gpio_request(EGPIO_MAGICIAN_EP_POWER, "EP_POWER"); 471 if (ret) 472 goto err_request_ep; 473 ret = gpio_request(EGPIO_MAGICIAN_MIC_POWER, "MIC_POWER"); 474 if (ret) 475 goto err_request_mic; 476 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL0, "IN_SEL0"); 477 if (ret) 478 goto err_request_in_sel0; 479 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL1, "IN_SEL1"); 480 if (ret) 481 goto err_request_in_sel1; 482 483 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0); 484 485 magician_snd_device = platform_device_alloc("soc-audio", -1); 486 if (!magician_snd_device) { 487 ret = -ENOMEM; 488 goto err_pdev; 489 } 490 491 platform_set_drvdata(magician_snd_device, &snd_soc_card_magician); 492 ret = platform_device_add(magician_snd_device); 493 if (ret) { 494 platform_device_put(magician_snd_device); 495 goto err_pdev; 496 } 497 498 return 0; 499 500err_pdev: 501 gpio_free(EGPIO_MAGICIAN_IN_SEL1); 502err_request_in_sel1: 503 gpio_free(EGPIO_MAGICIAN_IN_SEL0); 504err_request_in_sel0: 505 gpio_free(EGPIO_MAGICIAN_MIC_POWER); 506err_request_mic: 507 gpio_free(EGPIO_MAGICIAN_EP_POWER); 508err_request_ep: 509 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 510err_request_spk: 511 return ret; 512} 513 514static void __exit magician_exit(void) 515{ 516 platform_device_unregister(magician_snd_device); 517 518 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0); 519 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0); 520 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0); 521 522 gpio_free(EGPIO_MAGICIAN_IN_SEL1); 523 gpio_free(EGPIO_MAGICIAN_IN_SEL0); 524 gpio_free(EGPIO_MAGICIAN_MIC_POWER); 525 gpio_free(EGPIO_MAGICIAN_EP_POWER); 526 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 527} 528 529module_init(magician_init); 530module_exit(magician_exit); 531 532MODULE_AUTHOR("Philipp Zabel"); 533MODULE_DESCRIPTION("ALSA SoC Magician"); 534MODULE_LICENSE("GPL"); 535