linux/sound/soc/omap/rx51.c
<<
>>
Prefs
   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@ti.com>
   7 *          Eduardo Valentin <eduardo.valentin@nokia.com>
   8 *          Jarkko Nikula <jarkko.nikula@bitmer.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 <linux/gpio/consumer.h>
  30#include <linux/module.h>
  31#include <sound/core.h>
  32#include <sound/jack.h>
  33#include <sound/pcm.h>
  34#include <sound/soc.h>
  35#include <linux/platform_data/asoc-ti-mcbsp.h>
  36#include "../codecs/tpa6130a2.h"
  37
  38#include <asm/mach-types.h>
  39
  40#include "omap-mcbsp.h"
  41
  42enum {
  43        RX51_JACK_DISABLED,
  44        RX51_JACK_TVOUT,                /* tv-out with stereo output */
  45        RX51_JACK_HP,                   /* headphone: stereo output, no mic */
  46        RX51_JACK_HS,                   /* headset: stereo output with mic */
  47};
  48
  49struct rx51_audio_pdata {
  50        struct gpio_desc *tvout_selection_gpio;
  51        struct gpio_desc *jack_detection_gpio;
  52        struct gpio_desc *eci_sw_gpio;
  53        struct gpio_desc *speaker_amp_gpio;
  54};
  55
  56static int rx51_spk_func;
  57static int rx51_dmic_func;
  58static int rx51_jack_func;
  59
  60static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
  61{
  62        struct snd_soc_card *card = dapm->card;
  63        struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
  64        int hp = 0, hs = 0, tvout = 0;
  65
  66        switch (rx51_jack_func) {
  67        case RX51_JACK_TVOUT:
  68                tvout = 1;
  69                hp = 1;
  70                break;
  71        case RX51_JACK_HS:
  72                hs = 1;
  73        case RX51_JACK_HP:
  74                hp = 1;
  75                break;
  76        }
  77
  78        snd_soc_dapm_mutex_lock(dapm);
  79
  80        if (rx51_spk_func)
  81                snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
  82        else
  83                snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
  84        if (rx51_dmic_func)
  85                snd_soc_dapm_enable_pin_unlocked(dapm, "DMic");
  86        else
  87                snd_soc_dapm_disable_pin_unlocked(dapm, "DMic");
  88        if (hp)
  89                snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
  90        else
  91                snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
  92        if (hs)
  93                snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic");
  94        else
  95                snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic");
  96
  97        gpiod_set_value(pdata->tvout_selection_gpio, tvout);
  98
  99        snd_soc_dapm_sync_unlocked(dapm);
 100
 101        snd_soc_dapm_mutex_unlock(dapm);
 102}
 103
 104static int rx51_startup(struct snd_pcm_substream *substream)
 105{
 106        struct snd_pcm_runtime *runtime = substream->runtime;
 107        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 108        struct snd_soc_card *card = rtd->card;
 109
 110        snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
 111        rx51_ext_control(&card->dapm);
 112
 113        return 0;
 114}
 115
 116static int rx51_hw_params(struct snd_pcm_substream *substream,
 117        struct snd_pcm_hw_params *params)
 118{
 119        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 120        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 121
 122        /* Set the codec system clock for DAC and ADC */
 123        return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
 124                                      SND_SOC_CLOCK_IN);
 125}
 126
 127static struct snd_soc_ops rx51_ops = {
 128        .startup = rx51_startup,
 129        .hw_params = rx51_hw_params,
 130};
 131
 132static int rx51_get_spk(struct snd_kcontrol *kcontrol,
 133                        struct snd_ctl_elem_value *ucontrol)
 134{
 135        ucontrol->value.enumerated.item[0] = rx51_spk_func;
 136
 137        return 0;
 138}
 139
 140static int rx51_set_spk(struct snd_kcontrol *kcontrol,
 141                        struct snd_ctl_elem_value *ucontrol)
 142{
 143        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 144
 145        if (rx51_spk_func == ucontrol->value.enumerated.item[0])
 146                return 0;
 147
 148        rx51_spk_func = ucontrol->value.enumerated.item[0];
 149        rx51_ext_control(&card->dapm);
 150
 151        return 1;
 152}
 153
 154static int rx51_spk_event(struct snd_soc_dapm_widget *w,
 155                          struct snd_kcontrol *k, int event)
 156{
 157        struct snd_soc_dapm_context *dapm = w->dapm;
 158        struct snd_soc_card *card = dapm->card;
 159        struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
 160
 161        gpiod_set_raw_value_cansleep(pdata->speaker_amp_gpio,
 162                                     !!SND_SOC_DAPM_EVENT_ON(event));
 163
 164        return 0;
 165}
 166
 167static int rx51_hp_event(struct snd_soc_dapm_widget *w,
 168                         struct snd_kcontrol *k, int event)
 169{
 170        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 171
 172        if (SND_SOC_DAPM_EVENT_ON(event))
 173                tpa6130a2_stereo_enable(codec, 1);
 174        else
 175                tpa6130a2_stereo_enable(codec, 0);
 176
 177        return 0;
 178}
 179
 180static int rx51_get_input(struct snd_kcontrol *kcontrol,
 181                          struct snd_ctl_elem_value *ucontrol)
 182{
 183        ucontrol->value.enumerated.item[0] = rx51_dmic_func;
 184
 185        return 0;
 186}
 187
 188static int rx51_set_input(struct snd_kcontrol *kcontrol,
 189                          struct snd_ctl_elem_value *ucontrol)
 190{
 191        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 192
 193        if (rx51_dmic_func == ucontrol->value.enumerated.item[0])
 194                return 0;
 195
 196        rx51_dmic_func = ucontrol->value.enumerated.item[0];
 197        rx51_ext_control(&card->dapm);
 198
 199        return 1;
 200}
 201
 202static int rx51_get_jack(struct snd_kcontrol *kcontrol,
 203                         struct snd_ctl_elem_value *ucontrol)
 204{
 205        ucontrol->value.enumerated.item[0] = rx51_jack_func;
 206
 207        return 0;
 208}
 209
 210static int rx51_set_jack(struct snd_kcontrol *kcontrol,
 211                         struct snd_ctl_elem_value *ucontrol)
 212{
 213        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 214
 215        if (rx51_jack_func == ucontrol->value.enumerated.item[0])
 216                return 0;
 217
 218        rx51_jack_func = ucontrol->value.enumerated.item[0];
 219        rx51_ext_control(&card->dapm);
 220
 221        return 1;
 222}
 223
 224static struct snd_soc_jack rx51_av_jack;
 225
 226static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
 227        {
 228                .name = "avdet-gpio",
 229                .report = SND_JACK_HEADSET,
 230                .invert = 1,
 231                .debounce_time = 200,
 232        },
 233};
 234
 235static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
 236        SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
 237        SND_SOC_DAPM_MIC("DMic", NULL),
 238        SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event),
 239        SND_SOC_DAPM_MIC("HS Mic", NULL),
 240        SND_SOC_DAPM_LINE("FM Transmitter", NULL),
 241        SND_SOC_DAPM_SPK("Earphone", NULL),
 242};
 243
 244static const struct snd_soc_dapm_route audio_map[] = {
 245        {"Ext Spk", NULL, "HPLOUT"},
 246        {"Ext Spk", NULL, "HPROUT"},
 247        {"Ext Spk", NULL, "HPLCOM"},
 248        {"Ext Spk", NULL, "HPRCOM"},
 249        {"Headphone Jack", NULL, "LLOUT"},
 250        {"Headphone Jack", NULL, "RLOUT"},
 251        {"FM Transmitter", NULL, "LLOUT"},
 252        {"FM Transmitter", NULL, "RLOUT"},
 253
 254        {"DMic Rate 64", NULL, "DMic"},
 255        {"DMic", NULL, "Mic Bias"},
 256
 257        {"b LINE2R", NULL, "MONO_LOUT"},
 258        {"Earphone", NULL, "b HPLOUT"},
 259
 260        {"LINE1L", NULL, "HS Mic"},
 261        {"HS Mic", NULL, "b Mic Bias"},
 262};
 263
 264static const char * const spk_function[] = {"Off", "On"};
 265static const char * const input_function[] = {"ADC", "Digital Mic"};
 266static const char * const jack_function[] = {
 267        "Off", "TV-OUT", "Headphone", "Headset"
 268};
 269
 270static const struct soc_enum rx51_enum[] = {
 271        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
 272        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
 273        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
 274};
 275
 276static const struct snd_kcontrol_new aic34_rx51_controls[] = {
 277        SOC_ENUM_EXT("Speaker Function", rx51_enum[0],
 278                     rx51_get_spk, rx51_set_spk),
 279        SOC_ENUM_EXT("Input Select",  rx51_enum[1],
 280                     rx51_get_input, rx51_set_input),
 281        SOC_ENUM_EXT("Jack Function", rx51_enum[2],
 282                     rx51_get_jack, rx51_set_jack),
 283        SOC_DAPM_PIN_SWITCH("FM Transmitter"),
 284        SOC_DAPM_PIN_SWITCH("Earphone"),
 285};
 286
 287static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 288{
 289        struct snd_soc_codec *codec = rtd->codec;
 290        struct snd_soc_card *card = rtd->card;
 291        struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
 292        int err;
 293
 294        err = tpa6130a2_add_controls(codec);
 295        if (err < 0) {
 296                dev_err(card->dev, "Failed to add TPA6130A2 controls\n");
 297                return err;
 298        }
 299        snd_soc_limit_volume(card, "TPA6130A2 Headphone Playback Volume", 42);
 300
 301        err = omap_mcbsp_st_add_controls(rtd, 2);
 302        if (err < 0) {
 303                dev_err(card->dev, "Failed to add MCBSP controls\n");
 304                return err;
 305        }
 306
 307        /* AV jack detection */
 308        err = snd_soc_card_jack_new(rtd->card, "AV Jack",
 309                                    SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
 310                                    &rx51_av_jack, NULL, 0);
 311        if (err) {
 312                dev_err(card->dev, "Failed to add AV Jack\n");
 313                return err;
 314        }
 315
 316        /* prepare gpio for snd_soc_jack_add_gpios */
 317        rx51_av_jack_gpios[0].gpio = desc_to_gpio(pdata->jack_detection_gpio);
 318        devm_gpiod_put(card->dev, pdata->jack_detection_gpio);
 319
 320        err = snd_soc_jack_add_gpios(&rx51_av_jack,
 321                                     ARRAY_SIZE(rx51_av_jack_gpios),
 322                                     rx51_av_jack_gpios);
 323        if (err) {
 324                dev_err(card->dev, "Failed to add GPIOs\n");
 325                return err;
 326        }
 327
 328        return err;
 329}
 330
 331static int rx51_card_remove(struct snd_soc_card *card)
 332{
 333        snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios),
 334                                rx51_av_jack_gpios);
 335
 336        return 0;
 337}
 338
 339/* Digital audio interface glue - connects codec <--> CPU */
 340static struct snd_soc_dai_link rx51_dai[] = {
 341        {
 342                .name = "TLV320AIC34",
 343                .stream_name = "AIC34",
 344                .cpu_dai_name = "omap-mcbsp.2",
 345                .codec_dai_name = "tlv320aic3x-hifi",
 346                .platform_name = "omap-mcbsp.2",
 347                .codec_name = "tlv320aic3x-codec.2-0018",
 348                .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
 349                           SND_SOC_DAIFMT_CBM_CFM,
 350                .init = rx51_aic34_init,
 351                .ops = &rx51_ops,
 352        },
 353};
 354
 355static struct snd_soc_aux_dev rx51_aux_dev[] = {
 356        {
 357                .name = "TLV320AIC34b",
 358                .codec_name = "tlv320aic3x-codec.2-0019",
 359        },
 360};
 361
 362static struct snd_soc_codec_conf rx51_codec_conf[] = {
 363        {
 364                .dev_name = "tlv320aic3x-codec.2-0019",
 365                .name_prefix = "b",
 366        },
 367};
 368
 369/* Audio card */
 370static struct snd_soc_card rx51_sound_card = {
 371        .name = "RX-51",
 372        .owner = THIS_MODULE,
 373        .remove = rx51_card_remove,
 374        .dai_link = rx51_dai,
 375        .num_links = ARRAY_SIZE(rx51_dai),
 376        .aux_dev = rx51_aux_dev,
 377        .num_aux_devs = ARRAY_SIZE(rx51_aux_dev),
 378        .codec_conf = rx51_codec_conf,
 379        .num_configs = ARRAY_SIZE(rx51_codec_conf),
 380        .fully_routed = true,
 381
 382        .controls = aic34_rx51_controls,
 383        .num_controls = ARRAY_SIZE(aic34_rx51_controls),
 384        .dapm_widgets = aic34_dapm_widgets,
 385        .num_dapm_widgets = ARRAY_SIZE(aic34_dapm_widgets),
 386        .dapm_routes = audio_map,
 387        .num_dapm_routes = ARRAY_SIZE(audio_map),
 388};
 389
 390static int rx51_soc_probe(struct platform_device *pdev)
 391{
 392        struct rx51_audio_pdata *pdata;
 393        struct device_node *np = pdev->dev.of_node;
 394        struct snd_soc_card *card = &rx51_sound_card;
 395        int err;
 396
 397        if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900"))
 398                return -ENODEV;
 399
 400        card->dev = &pdev->dev;
 401
 402        if (np) {
 403                struct device_node *dai_node;
 404
 405                dai_node = of_parse_phandle(np, "nokia,cpu-dai", 0);
 406                if (!dai_node) {
 407                        dev_err(&pdev->dev, "McBSP node is not provided\n");
 408                        return -EINVAL;
 409                }
 410                rx51_dai[0].cpu_dai_name = NULL;
 411                rx51_dai[0].platform_name = NULL;
 412                rx51_dai[0].cpu_of_node = dai_node;
 413                rx51_dai[0].platform_of_node = dai_node;
 414
 415                dai_node = of_parse_phandle(np, "nokia,audio-codec", 0);
 416                if (!dai_node) {
 417                        dev_err(&pdev->dev, "Codec node is not provided\n");
 418                        return -EINVAL;
 419                }
 420                rx51_dai[0].codec_name = NULL;
 421                rx51_dai[0].codec_of_node = dai_node;
 422
 423                dai_node = of_parse_phandle(np, "nokia,audio-codec", 1);
 424                if (!dai_node) {
 425                        dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n");
 426                        return -EINVAL;
 427                }
 428                rx51_aux_dev[0].codec_name = NULL;
 429                rx51_aux_dev[0].codec_of_node = dai_node;
 430                rx51_codec_conf[0].dev_name = NULL;
 431                rx51_codec_conf[0].of_node = dai_node;
 432
 433                dai_node = of_parse_phandle(np, "nokia,headphone-amplifier", 0);
 434                if (!dai_node) {
 435                        dev_err(&pdev->dev, "Headphone amplifier node is not provided\n");
 436                        return -EINVAL;
 437                }
 438
 439                /* TODO: tpa6130a2a driver supports only a single instance, so
 440                 * this driver ignores the headphone-amplifier node for now.
 441                 * It's already mandatory in the DT binding to be future proof.
 442                 */
 443        }
 444
 445        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 446        if (pdata == NULL) {
 447                dev_err(card->dev, "failed to create private data\n");
 448                return -ENOMEM;
 449        }
 450        snd_soc_card_set_drvdata(card, pdata);
 451
 452        pdata->tvout_selection_gpio = devm_gpiod_get(card->dev,
 453                                                     "tvout-selection",
 454                                                     GPIOD_OUT_LOW);
 455        if (IS_ERR(pdata->tvout_selection_gpio)) {
 456                dev_err(card->dev, "could not get tvout selection gpio\n");
 457                return PTR_ERR(pdata->tvout_selection_gpio);
 458        }
 459
 460        pdata->jack_detection_gpio = devm_gpiod_get(card->dev,
 461                                                    "jack-detection",
 462                                                    GPIOD_ASIS);
 463        if (IS_ERR(pdata->jack_detection_gpio)) {
 464                dev_err(card->dev, "could not get jack detection gpio\n");
 465                return PTR_ERR(pdata->jack_detection_gpio);
 466        }
 467
 468        pdata->eci_sw_gpio = devm_gpiod_get(card->dev, "eci-switch",
 469                                            GPIOD_OUT_HIGH);
 470        if (IS_ERR(pdata->eci_sw_gpio)) {
 471                dev_err(card->dev, "could not get eci switch gpio\n");
 472                return PTR_ERR(pdata->eci_sw_gpio);
 473        }
 474
 475        pdata->speaker_amp_gpio = devm_gpiod_get(card->dev,
 476                                                 "speaker-amplifier",
 477                                                 GPIOD_OUT_LOW);
 478        if (IS_ERR(pdata->speaker_amp_gpio)) {
 479                dev_err(card->dev, "could not get speaker enable gpio\n");
 480                return PTR_ERR(pdata->speaker_amp_gpio);
 481        }
 482
 483        err = devm_snd_soc_register_card(card->dev, card);
 484        if (err) {
 485                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err);
 486                return err;
 487        }
 488
 489        return 0;
 490}
 491
 492#if defined(CONFIG_OF)
 493static const struct of_device_id rx51_audio_of_match[] = {
 494        { .compatible = "nokia,n900-audio", },
 495        {},
 496};
 497MODULE_DEVICE_TABLE(of, rx51_audio_of_match);
 498#endif
 499
 500static struct platform_driver rx51_soc_driver = {
 501        .driver = {
 502                .name = "rx51-audio",
 503                .of_match_table = of_match_ptr(rx51_audio_of_match),
 504        },
 505        .probe = rx51_soc_probe,
 506};
 507
 508module_platform_driver(rx51_soc_driver);
 509
 510MODULE_AUTHOR("Nokia Corporation");
 511MODULE_DESCRIPTION("ALSA SoC Nokia RX-51");
 512MODULE_LICENSE("GPL");
 513MODULE_ALIAS("platform:rx51-audio");
 514
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.