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