1/* 2 * rx51.c -- SoC audio for Nokia RX-51 3 * 4 * Copyright (C) 2008 - 2009 Nokia Corporation 5 * 6 * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com> 7 * Eduardo Valentin <eduardo.valentin@nokia.com> 8 * Jarkko Nikula <jhnikula@gmail.com> 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * version 2 as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 * 02110-1301 USA 23 * 24 */ 25 26#include <linux/delay.h> 27#include <linux/gpio.h> 28#include <linux/platform_device.h> 29#include <sound/core.h> 30#include <sound/jack.h> 31#include <sound/pcm.h> 32#include <sound/soc.h> 33#include <sound/soc-dapm.h> 34 35#include <asm/mach-types.h> 36 37#include "omap-mcbsp.h" 38#include "omap-pcm.h" 39#include "../codecs/tlv320aic3x.h" 40 41#define RX51_TVOUT_SEL_GPIO 40 42#define RX51_JACK_DETECT_GPIO 177 43/* 44 * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This 45 * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c 46 */ 47#define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7) 48 49enum { 50 RX51_JACK_DISABLED, 51 RX51_JACK_TVOUT, /* tv-out */ 52}; 53 54static int rx51_spk_func; 55static int rx51_dmic_func; 56static int rx51_jack_func; 57 58static void rx51_ext_control(struct snd_soc_codec *codec) 59{ 60 if (rx51_spk_func) 61 snd_soc_dapm_enable_pin(codec, "Ext Spk"); 62 else 63 snd_soc_dapm_disable_pin(codec, "Ext Spk"); 64 if (rx51_dmic_func) 65 snd_soc_dapm_enable_pin(codec, "DMic"); 66 else 67 snd_soc_dapm_disable_pin(codec, "DMic"); 68 69 gpio_set_value(RX51_TVOUT_SEL_GPIO, 70 rx51_jack_func == RX51_JACK_TVOUT); 71 72 snd_soc_dapm_sync(codec); 73} 74 75static int rx51_startup(struct snd_pcm_substream *substream) 76{ 77 struct snd_pcm_runtime *runtime = substream->runtime; 78 struct snd_soc_pcm_runtime *rtd = substream->private_data; 79 struct snd_soc_codec *codec = rtd->socdev->card->codec; 80 81 snd_pcm_hw_constraint_minmax(runtime, 82 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); 83 rx51_ext_control(codec); 84 85 return 0; 86} 87 88static int rx51_hw_params(struct snd_pcm_substream *substream, 89 struct snd_pcm_hw_params *params) 90{ 91 struct snd_soc_pcm_runtime *rtd = substream->private_data; 92 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 93 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 94 int err; 95 96 /* Set codec DAI configuration */ 97 err = snd_soc_dai_set_fmt(codec_dai, 98 SND_SOC_DAIFMT_DSP_A | 99 SND_SOC_DAIFMT_IB_NF | 100 SND_SOC_DAIFMT_CBM_CFM); 101 if (err < 0) 102 return err; 103 104 /* Set cpu DAI configuration */ 105 err = snd_soc_dai_set_fmt(cpu_dai, 106 SND_SOC_DAIFMT_DSP_A | 107 SND_SOC_DAIFMT_IB_NF | 108 SND_SOC_DAIFMT_CBM_CFM); 109 if (err < 0) 110 return err; 111 112 /* Set the codec system clock for DAC and ADC */ 113 return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000, 114 SND_SOC_CLOCK_IN); 115} 116 117static struct snd_soc_ops rx51_ops = { 118 .startup = rx51_startup, 119 .hw_params = rx51_hw_params, 120}; 121 122static int rx51_get_spk(struct snd_kcontrol *kcontrol, 123 struct snd_ctl_elem_value *ucontrol) 124{ 125 ucontrol->value.integer.value[0] = rx51_spk_func; 126 127 return 0; 128} 129 130static int rx51_set_spk(struct snd_kcontrol *kcontrol, 131 struct snd_ctl_elem_value *ucontrol) 132{ 133 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 134 135 if (rx51_spk_func == ucontrol->value.integer.value[0]) 136 return 0; 137 138 rx51_spk_func = ucontrol->value.integer.value[0]; 139 rx51_ext_control(codec); 140 141 return 1; 142} 143 144static int rx51_spk_event(struct snd_soc_dapm_widget *w, 145 struct snd_kcontrol *k, int event) 146{ 147 if (SND_SOC_DAPM_EVENT_ON(event)) 148 gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1); 149 else 150 gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0); 151 152 return 0; 153} 154 155static int rx51_get_input(struct snd_kcontrol *kcontrol, 156 struct snd_ctl_elem_value *ucontrol) 157{ 158 ucontrol->value.integer.value[0] = rx51_dmic_func; 159 160 return 0; 161} 162 163static int rx51_set_input(struct snd_kcontrol *kcontrol, 164 struct snd_ctl_elem_value *ucontrol) 165{ 166 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 167 168 if (rx51_dmic_func == ucontrol->value.integer.value[0]) 169 return 0; 170 171 rx51_dmic_func = ucontrol->value.integer.value[0]; 172 rx51_ext_control(codec); 173 174 return 1; 175} 176 177static int rx51_get_jack(struct snd_kcontrol *kcontrol, 178 struct snd_ctl_elem_value *ucontrol) 179{ 180 ucontrol->value.integer.value[0] = rx51_jack_func; 181 182 return 0; 183} 184 185static int rx51_set_jack(struct snd_kcontrol *kcontrol, 186 struct snd_ctl_elem_value *ucontrol) 187{ 188 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 189 190 if (rx51_jack_func == ucontrol->value.integer.value[0]) 191 return 0; 192 193 rx51_jack_func = ucontrol->value.integer.value[0]; 194 rx51_ext_control(codec); 195 196 return 1; 197} 198 199static struct snd_soc_jack rx51_av_jack; 200 201static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { 202 { 203 .gpio = RX51_JACK_DETECT_GPIO, 204 .name = "avdet-gpio", 205 .report = SND_JACK_VIDEOOUT, 206 .invert = 1, 207 .debounce_time = 200, 208 }, 209}; 210 211static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { 212 SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), 213 SND_SOC_DAPM_MIC("DMic", NULL), 214}; 215 216static const struct snd_soc_dapm_route audio_map[] = { 217 {"Ext Spk", NULL, "HPLOUT"}, 218 {"Ext Spk", NULL, "HPROUT"}, 219 220 {"DMic Rate 64", NULL, "Mic Bias 2V"}, 221 {"Mic Bias 2V", NULL, "DMic"}, 222}; 223 224static const char *spk_function[] = {"Off", "On"}; 225static const char *input_function[] = {"ADC", "Digital Mic"}; 226static const char *jack_function[] = {"Off", "TV-OUT"}; 227 228static const struct soc_enum rx51_enum[] = { 229 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), 230 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function), 231 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function), 232}; 233 234static const struct snd_kcontrol_new aic34_rx51_controls[] = { 235 SOC_ENUM_EXT("Speaker Function", rx51_enum[0], 236 rx51_get_spk, rx51_set_spk), 237 SOC_ENUM_EXT("Input Select", rx51_enum[1], 238 rx51_get_input, rx51_set_input), 239 SOC_ENUM_EXT("Jack Function", rx51_enum[2], 240 rx51_get_jack, rx51_set_jack), 241}; 242 243static int rx51_aic34_init(struct snd_soc_codec *codec) 244{ 245 struct snd_soc_card *card = codec->socdev->card; 246 int err; 247 248 /* Set up NC codec pins */ 249 snd_soc_dapm_nc_pin(codec, "MIC3L"); 250 snd_soc_dapm_nc_pin(codec, "MIC3R"); 251 snd_soc_dapm_nc_pin(codec, "LINE1R"); 252 253 /* Add RX-51 specific controls */ 254 err = snd_soc_add_controls(codec, aic34_rx51_controls, 255 ARRAY_SIZE(aic34_rx51_controls)); 256 if (err < 0) 257 return err; 258 259 /* Add RX-51 specific widgets */ 260 snd_soc_dapm_new_controls(codec, aic34_dapm_widgets, 261 ARRAY_SIZE(aic34_dapm_widgets)); 262 263 /* Set up RX-51 specific audio path audio_map */ 264 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 265 266 snd_soc_dapm_sync(codec); 267 268 /* AV jack detection */ 269 err = snd_soc_jack_new(card, "AV Jack", 270 SND_JACK_VIDEOOUT, &rx51_av_jack); 271 if (err) 272 return err; 273 err = snd_soc_jack_add_gpios(&rx51_av_jack, 274 ARRAY_SIZE(rx51_av_jack_gpios), 275 rx51_av_jack_gpios); 276 277 return err; 278} 279 280/* Digital audio interface glue - connects codec <--> CPU */ 281static struct snd_soc_dai_link rx51_dai[] = { 282 { 283 .name = "TLV320AIC34", 284 .stream_name = "AIC34", 285 .cpu_dai = &omap_mcbsp_dai[0], 286 .codec_dai = &aic3x_dai, 287 .init = rx51_aic34_init, 288 .ops = &rx51_ops, 289 }, 290}; 291 292/* Audio private data */ 293static struct aic3x_setup_data rx51_aic34_setup = { 294 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, 295 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, 296}; 297 298/* Audio card */ 299static struct snd_soc_card rx51_sound_card = { 300 .name = "RX-51", 301 .dai_link = rx51_dai, 302 .num_links = ARRAY_SIZE(rx51_dai), 303 .platform = &omap_soc_platform, 304}; 305 306/* Audio subsystem */ 307static struct snd_soc_device rx51_snd_devdata = { 308 .card = &rx51_sound_card, 309 .codec_dev = &soc_codec_dev_aic3x, 310 .codec_data = &rx51_aic34_setup, 311}; 312 313static struct platform_device *rx51_snd_device; 314 315static int __init rx51_soc_init(void) 316{ 317 int err; 318 319 if (!machine_is_nokia_rx51()) 320 return -ENODEV; 321 322 err = gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel"); 323 if (err) 324 goto err_gpio_tvout_sel; 325 gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0); 326 327 rx51_snd_device = platform_device_alloc("soc-audio", -1); 328 if (!rx51_snd_device) { 329 err = -ENOMEM; 330 goto err1; 331 } 332 333 platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata); 334 rx51_snd_devdata.dev = &rx51_snd_device->dev; 335 *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ 336 337 err = platform_device_add(rx51_snd_device); 338 if (err) 339 goto err2; 340 341 return 0; 342err2: 343 platform_device_put(rx51_snd_device); 344err1: 345 gpio_free(RX51_TVOUT_SEL_GPIO); 346err_gpio_tvout_sel: 347 348 return err; 349} 350 351static void __exit rx51_soc_exit(void) 352{ 353 snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios), 354 rx51_av_jack_gpios); 355 356 platform_device_unregister(rx51_snd_device); 357 gpio_free(RX51_TVOUT_SEL_GPIO); 358} 359 360module_init(rx51_soc_init); 361module_exit(rx51_soc_exit); 362 363MODULE_AUTHOR("Nokia Corporation"); 364MODULE_DESCRIPTION("ALSA SoC Nokia RX-51"); 365MODULE_LICENSE("GPL"); 366