linux/sound/soc/samsung/midas_wm1811.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// Midas audio support
   4//
   5// Copyright (C) 2018 Simon Shields <simon@lineageos.org>
   6// Copyright (C) 2020 Samsung Electronics Co., Ltd.
   7
   8#include <linux/clk.h>
   9#include <linux/gpio/consumer.h>
  10#include <linux/iio/consumer.h>
  11#include <linux/mfd/wm8994/registers.h>
  12#include <linux/input-event-codes.h>
  13#include <linux/module.h>
  14#include <linux/of.h>
  15#include <sound/jack.h>
  16#include <sound/soc.h>
  17#include <sound/soc-dapm.h>
  18
  19#include "i2s.h"
  20#include "../codecs/wm8994.h"
  21
  22/*
  23 * The MCLK1 clock source is XCLKOUT with its mux set to the external fixed rate
  24 * oscillator (XXTI).
  25 */
  26#define MCLK1_RATE 24000000U
  27#define MCLK2_RATE 32768U
  28#define DEFAULT_FLL1_RATE 11289600U
  29
  30struct midas_priv {
  31        struct gpio_desc *gpio_fm_sel;
  32        struct gpio_desc *gpio_lineout_sel;
  33        struct gpio_desc *gpio_headset_detect;
  34        struct gpio_desc *gpio_headset_key;
  35        struct iio_channel *adc_headset_detect;
  36        unsigned int fll1_rate;
  37
  38        struct snd_soc_jack headset_jack;
  39};
  40
  41static struct snd_soc_jack_pin headset_jack_pins[] = {
  42        {
  43                .pin = "Headphone",
  44                .mask = SND_JACK_HEADPHONE,
  45        },
  46        {
  47                .pin = "Headset Mic",
  48                .mask = SND_JACK_MICROPHONE,
  49        },
  50};
  51
  52/*
  53 * min_mv/max_mv values in this struct are set up based on DT values.
  54 */
  55static struct snd_soc_jack_zone headset_jack_zones[] = {
  56        { .jack_type = SND_JACK_HEADPHONE, },
  57        { .jack_type = SND_JACK_HEADSET, },
  58        { .jack_type = SND_JACK_HEADPHONE, },
  59};
  60
  61/*
  62 * This is used for manual detection in headset_key_check, we reuse the
  63 * structure since it's convenient.
  64 *
  65 * min_mv/max_mv values in this struct are set up based on DT values.
  66 */
  67static struct snd_soc_jack_zone headset_key_zones[] = {
  68        { .jack_type = SND_JACK_BTN_0, },  /* Media */
  69        { .jack_type = SND_JACK_BTN_1, },  /* Volume Up */
  70        { .jack_type = SND_JACK_BTN_2, },  /* Volume Down */
  71};
  72
  73static int headset_jack_check(void *data)
  74{
  75        struct snd_soc_component *codec = data;
  76        struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
  77        struct midas_priv *priv = snd_soc_card_get_drvdata(codec->card);
  78        int adc, ret;
  79        int jack_type = 0;
  80
  81        if (!gpiod_get_value_cansleep(priv->gpio_headset_detect))
  82                return 0;
  83
  84        /* Enable headset mic bias regulator so that the ADC reading works */
  85        ret = snd_soc_dapm_force_enable_pin(dapm, "headset-mic-bias");
  86        if (ret < 0) {
  87                pr_err("%s: Failed to enable headset mic bias regulator (%d), assuming headphones\n",
  88                       __func__, ret);
  89                return SND_JACK_HEADPHONE;
  90        }
  91        snd_soc_dapm_sync(dapm);
  92
  93        /* Sleep for a small amount of time to get the value to stabilize */
  94        msleep(20);
  95
  96        ret = iio_read_channel_processed(priv->adc_headset_detect, &adc);
  97        if (ret) {
  98                pr_err("%s: Failed to read ADC (%d), assuming headphones\n",
  99                       __func__, ret);
 100                jack_type = SND_JACK_HEADPHONE;
 101                goto out;
 102        }
 103        pr_debug("%s: ADC value is %d\n", __func__, adc);
 104
 105        jack_type = snd_soc_jack_get_type(&priv->headset_jack, adc);
 106
 107out:
 108        ret = snd_soc_dapm_disable_pin(dapm, "headset-mic-bias");
 109        if (ret < 0)
 110                pr_err("%s: Failed to disable headset mic bias regulator (%d)\n",
 111                       __func__, ret);
 112        snd_soc_dapm_sync(dapm);
 113
 114        return jack_type;
 115}
 116
 117static int headset_key_check(void *data)
 118{
 119        struct snd_soc_component *codec = data;
 120        struct midas_priv *priv = snd_soc_card_get_drvdata(codec->card);
 121        int adc, i, ret;
 122
 123        if (!gpiod_get_value_cansleep(priv->gpio_headset_key))
 124                return 0;
 125
 126        /* Filter out keypresses when 4 pole jack not detected */
 127        if (!(priv->headset_jack.status & SND_JACK_MICROPHONE))
 128                return 0;
 129
 130        ret = iio_read_channel_processed(priv->adc_headset_detect, &adc);
 131        if (ret) {
 132                pr_err("%s: Failed to read ADC (%d), can't detect key type\n",
 133                       __func__, ret);
 134                return 0;
 135        }
 136        pr_debug("%s: ADC value is %d\n", __func__, adc);
 137
 138        for (i = 0; i < ARRAY_SIZE(headset_key_zones); i++) {
 139                if (adc >= headset_key_zones[i].min_mv &&
 140                    adc <= headset_key_zones[i].max_mv) {
 141                        return headset_key_zones[i].jack_type;
 142                }
 143        }
 144
 145        return 0;
 146}
 147
 148static struct snd_soc_jack_gpio headset_gpio[] = {
 149        {
 150                .name = "Headset Jack",
 151                .report = SND_JACK_HEADSET,
 152                .debounce_time = 150,
 153                .jack_status_check = headset_jack_check,
 154        },
 155        {
 156                .name = "Headset Key",
 157                .report = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
 158                .debounce_time = 30,
 159                .jack_status_check = headset_key_check,
 160        },
 161};
 162
 163static int midas_start_fll1(struct snd_soc_pcm_runtime *rtd, unsigned int rate)
 164{
 165        struct snd_soc_card *card = rtd->card;
 166        struct midas_priv *priv = snd_soc_card_get_drvdata(card);
 167        struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
 168        struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 169        int ret;
 170
 171        if (!rate)
 172                rate = priv->fll1_rate;
 173        /*
 174         * If no new rate is requested, set FLL1 to a sane default for jack
 175         * detection.
 176         */
 177        if (!rate)
 178                rate = DEFAULT_FLL1_RATE;
 179
 180        if (rate != priv->fll1_rate && priv->fll1_rate) {
 181                /* while reconfiguring, switch to MCLK2 for SYSCLK */
 182                ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
 183                                             MCLK2_RATE, SND_SOC_CLOCK_IN);
 184                if (ret < 0) {
 185                        dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
 186                        return ret;
 187                }
 188        }
 189
 190        ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
 191                                  MCLK1_RATE, rate);
 192        if (ret < 0) {
 193                dev_err(card->dev, "Failed to set FLL1 rate: %d\n", ret);
 194                return ret;
 195        }
 196        priv->fll1_rate = rate;
 197
 198        ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_FLL1,
 199                                     priv->fll1_rate, SND_SOC_CLOCK_IN);
 200        if (ret < 0) {
 201                dev_err(card->dev, "Failed to set SYSCLK source: %d\n", ret);
 202                return ret;
 203        }
 204
 205        ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, 0,
 206                                     SAMSUNG_I2S_OPCLK_PCLK);
 207        if (ret < 0) {
 208                dev_err(card->dev, "Failed to set OPCLK source: %d\n", ret);
 209                return ret;
 210        }
 211
 212        return 0;
 213}
 214
 215static int midas_stop_fll1(struct snd_soc_pcm_runtime *rtd)
 216{
 217        struct snd_soc_card *card = rtd->card;
 218        struct midas_priv *priv = snd_soc_card_get_drvdata(card);
 219        struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
 220        int ret;
 221
 222        ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
 223                                     MCLK2_RATE, SND_SOC_CLOCK_IN);
 224        if (ret < 0) {
 225                dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
 226                return ret;
 227        }
 228
 229        ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, 0, 0, 0);
 230        if (ret < 0) {
 231                dev_err(card->dev, "Unable to stop FLL1: %d\n", ret);
 232                return ret;
 233        }
 234
 235        priv->fll1_rate = 0;
 236
 237        return 0;
 238}
 239
 240static int midas_aif1_hw_params(struct snd_pcm_substream *substream,
 241                                struct snd_pcm_hw_params *params)
 242{
 243        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 244        unsigned int pll_out;
 245
 246        /* AIF1CLK should be at least 3MHz for "optimal performance" */
 247        if (params_rate(params) == 8000 || params_rate(params) == 11025)
 248                pll_out = params_rate(params) * 512;
 249        else
 250                pll_out = params_rate(params) * 256;
 251
 252        return midas_start_fll1(rtd, pll_out);
 253}
 254
 255static const struct snd_soc_ops midas_aif1_ops = {
 256        .hw_params = midas_aif1_hw_params,
 257};
 258
 259/*
 260 * We only have a single external speaker, so mix stereo data
 261 * to a single mono stream.
 262 */
 263static int midas_ext_spkmode(struct snd_soc_dapm_widget *w,
 264                             struct snd_kcontrol *kcontrol, int event)
 265{
 266        struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
 267        int ret = 0;
 268
 269        switch (event) {
 270        case SND_SOC_DAPM_PRE_PMU:
 271                ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
 272                                  WM8994_SPKMIXR_TO_SPKOUTL_MASK,
 273                                  WM8994_SPKMIXR_TO_SPKOUTL);
 274                break;
 275        case SND_SOC_DAPM_POST_PMD:
 276                ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
 277                                  WM8994_SPKMIXR_TO_SPKOUTL_MASK,
 278                                  0);
 279                break;
 280        }
 281
 282        return ret;
 283}
 284
 285static int midas_fm_set(struct snd_soc_dapm_widget *w,
 286                        struct snd_kcontrol *kcontrol, int event)
 287{
 288        struct snd_soc_card *card = w->dapm->card;
 289        struct midas_priv *priv = snd_soc_card_get_drvdata(card);
 290
 291        if (!priv->gpio_fm_sel)
 292                return 0;
 293
 294        switch (event) {
 295        case SND_SOC_DAPM_PRE_PMU:
 296                gpiod_set_value_cansleep(priv->gpio_fm_sel, 1);
 297                break;
 298        case SND_SOC_DAPM_POST_PMD:
 299                gpiod_set_value_cansleep(priv->gpio_fm_sel, 0);
 300                break;
 301        }
 302
 303        return 0;
 304}
 305
 306static int midas_line_set(struct snd_soc_dapm_widget *w,
 307                          struct snd_kcontrol *kcontrol, int event)
 308{
 309        struct snd_soc_card *card = w->dapm->card;
 310        struct midas_priv *priv = snd_soc_card_get_drvdata(card);
 311
 312        if (!priv->gpio_lineout_sel)
 313                return 0;
 314
 315        switch (event) {
 316        case SND_SOC_DAPM_PRE_PMU:
 317                gpiod_set_value_cansleep(priv->gpio_lineout_sel, 1);
 318                break;
 319        case SND_SOC_DAPM_POST_PMD:
 320                gpiod_set_value_cansleep(priv->gpio_lineout_sel, 0);
 321                break;
 322        }
 323
 324        return 0;
 325}
 326
 327static const struct snd_kcontrol_new midas_controls[] = {
 328        SOC_DAPM_PIN_SWITCH("HP"),
 329
 330        SOC_DAPM_PIN_SWITCH("SPK"),
 331        SOC_DAPM_PIN_SWITCH("RCV"),
 332
 333        SOC_DAPM_PIN_SWITCH("LINE"),
 334        SOC_DAPM_PIN_SWITCH("HDMI"),
 335
 336        SOC_DAPM_PIN_SWITCH("Main Mic"),
 337        SOC_DAPM_PIN_SWITCH("Sub Mic"),
 338        SOC_DAPM_PIN_SWITCH("Headset Mic"),
 339
 340        SOC_DAPM_PIN_SWITCH("FM In"),
 341};
 342
 343static const struct snd_soc_dapm_widget midas_dapm_widgets[] = {
 344        SND_SOC_DAPM_HP("HP", NULL),
 345
 346        SND_SOC_DAPM_SPK("SPK", midas_ext_spkmode),
 347        SND_SOC_DAPM_SPK("RCV", NULL),
 348
 349        /* FIXME: toggle MAX77693 on i9300/i9305 */
 350        SND_SOC_DAPM_LINE("LINE", midas_line_set),
 351        SND_SOC_DAPM_LINE("HDMI", NULL),
 352        SND_SOC_DAPM_LINE("FM In", midas_fm_set),
 353
 354        SND_SOC_DAPM_HP("Headphone", NULL),
 355        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 356        SND_SOC_DAPM_REGULATOR_SUPPLY("headset-mic-bias", 0, 0),
 357        SND_SOC_DAPM_MIC("Main Mic", NULL),
 358        SND_SOC_DAPM_REGULATOR_SUPPLY("mic-bias", 0, 0),
 359        SND_SOC_DAPM_MIC("Sub Mic", NULL),
 360        SND_SOC_DAPM_REGULATOR_SUPPLY("submic-bias", 0, 0),
 361};
 362
 363/* Default routing; supplemented by audio-routing DT property */
 364static const struct snd_soc_dapm_route midas_dapm_routes[] = {
 365        /* Bind microphones with their respective regulator supplies */
 366        {"Main Mic", NULL, "mic-bias"},
 367        {"Sub Mic", NULL, "submic-bias"},
 368        {"Headset Mic", NULL, "headset-mic-bias"},
 369};
 370
 371static int midas_set_bias_level(struct snd_soc_card *card,
 372                                struct snd_soc_dapm_context *dapm,
 373                                enum snd_soc_bias_level level)
 374{
 375        struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
 376                                                  &card->dai_link[0]);
 377        struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
 378
 379        if (dapm->dev != aif1_dai->dev)
 380                return 0;
 381
 382        switch (level) {
 383        case SND_SOC_BIAS_STANDBY:
 384                return midas_stop_fll1(rtd);
 385        case SND_SOC_BIAS_PREPARE:
 386                return midas_start_fll1(rtd, 0);
 387        default:
 388                break;
 389        }
 390
 391        return 0;
 392}
 393
 394static int midas_late_probe(struct snd_soc_card *card)
 395{
 396        struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
 397                                                        &card->dai_link[0]);
 398        struct snd_soc_dai *aif1_dai = snd_soc_rtd_to_codec(rtd, 0);
 399        struct midas_priv *priv = snd_soc_card_get_drvdata(card);
 400        int ret;
 401
 402        /* Use MCLK2 as SYSCLK for boot */
 403        ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, MCLK2_RATE,
 404                                     SND_SOC_CLOCK_IN);
 405        if (ret < 0) {
 406                dev_err(aif1_dai->dev, "Failed to switch to MCLK2: %d\n", ret);
 407                return ret;
 408        }
 409
 410        if (!priv->gpio_headset_detect) {
 411                ret = snd_soc_card_jack_new_pins(card, "Headset",
 412                                 SND_JACK_HEADSET | SND_JACK_MECHANICAL |
 413                                 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
 414                                 SND_JACK_BTN_2 | SND_JACK_BTN_3 |
 415                                 SND_JACK_BTN_4 | SND_JACK_BTN_5,
 416                                 &priv->headset_jack,
 417                                 headset_jack_pins,
 418                                 ARRAY_SIZE(headset_jack_pins));
 419                if (ret)
 420                        return ret;
 421
 422                wm8958_mic_detect(aif1_dai->component, &priv->headset_jack,
 423                                  NULL, NULL, NULL, NULL);
 424        } else {
 425                /* Some devices (n8000, t310) use a GPIO to detect the jack. */
 426                ret = snd_soc_card_jack_new_pins(card, "Headset",
 427                                SND_JACK_HEADSET | SND_JACK_BTN_0 |
 428                                SND_JACK_BTN_1 | SND_JACK_BTN_2,
 429                                &priv->headset_jack,
 430                                headset_jack_pins,
 431                                ARRAY_SIZE(headset_jack_pins));
 432                if (ret) {
 433                        dev_err(card->dev,
 434                                "Failed to set up headset pins: %d\n", ret);
 435                        return ret;
 436                }
 437
 438                ret = snd_soc_jack_add_zones(&priv->headset_jack,
 439                                ARRAY_SIZE(headset_jack_zones),
 440                                headset_jack_zones);
 441                if (ret) {
 442                        dev_err(card->dev,
 443                                "Failed to set up headset zones: %d\n", ret);
 444                        return ret;
 445                }
 446
 447                headset_gpio[0].data = aif1_dai->component;
 448                headset_gpio[0].desc = priv->gpio_headset_detect;
 449
 450                headset_gpio[1].data = aif1_dai->component;
 451                headset_gpio[1].desc = priv->gpio_headset_key;
 452
 453                snd_jack_set_key(priv->headset_jack.jack,
 454                                 SND_JACK_BTN_0, KEY_MEDIA);
 455                snd_jack_set_key(priv->headset_jack.jack,
 456                                 SND_JACK_BTN_1, KEY_VOLUMEUP);
 457                snd_jack_set_key(priv->headset_jack.jack,
 458                                 SND_JACK_BTN_2, KEY_VOLUMEDOWN);
 459
 460                ret = snd_soc_jack_add_gpios(&priv->headset_jack,
 461                                ARRAY_SIZE(headset_gpio),
 462                                headset_gpio);
 463                if (ret)
 464                        dev_err(card->dev,
 465                                "Failed to set up headset jack GPIOs: %d\n",
 466                                ret);
 467
 468                return ret;
 469        }
 470
 471        return 0;
 472}
 473
 474static struct snd_soc_dai_driver midas_ext_dai[] = {
 475        {
 476                .name = "Voice call",
 477                .playback = {
 478                        .channels_min = 1,
 479                        .channels_max = 2,
 480                        .rate_min = 8000,
 481                        .rate_max = 16000,
 482                        .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
 483                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
 484                },
 485                .capture = {
 486                        .channels_min = 1,
 487                        .channels_max = 2,
 488                        .rate_min = 8000,
 489                        .rate_max = 16000,
 490                        .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
 491                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
 492                },
 493        },
 494        {
 495                .name = "Bluetooth",
 496                .playback = {
 497                        .channels_min = 1,
 498                        .channels_max = 2,
 499                        .rate_min = 8000,
 500                        .rate_max = 16000,
 501                        .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
 502                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
 503                },
 504                .capture = {
 505                        .channels_min = 1,
 506                        .channels_max = 2,
 507                        .rate_min = 8000,
 508                        .rate_max = 16000,
 509                        .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
 510                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
 511                },
 512        },
 513};
 514
 515static const struct snd_soc_component_driver midas_component = {
 516        .name   = "midas-audio",
 517};
 518
 519SND_SOC_DAILINK_DEFS(wm1811_hifi,
 520        DAILINK_COMP_ARRAY(COMP_EMPTY()),
 521        DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
 522        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 523
 524SND_SOC_DAILINK_DEFS(wm1811_voice,
 525        DAILINK_COMP_ARRAY(COMP_EMPTY()),
 526        DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2")),
 527        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 528
 529SND_SOC_DAILINK_DEFS(wm1811_bt,
 530        DAILINK_COMP_ARRAY(COMP_EMPTY()),
 531        DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3")),
 532        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 533
 534static struct snd_soc_dai_link midas_dai[] = {
 535        {
 536                .name = "WM8994 AIF1",
 537                .stream_name = "HiFi Primary",
 538                .ops = &midas_aif1_ops,
 539                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 540                        SND_SOC_DAIFMT_CBP_CFP,
 541                SND_SOC_DAILINK_REG(wm1811_hifi),
 542        }, {
 543                .name = "WM1811 Voice",
 544                .stream_name = "Voice call",
 545                .ignore_suspend = 1,
 546                SND_SOC_DAILINK_REG(wm1811_voice),
 547        }, {
 548                .name = "WM1811 BT",
 549                .stream_name = "Bluetooth",
 550                .ignore_suspend = 1,
 551                SND_SOC_DAILINK_REG(wm1811_bt),
 552        },
 553};
 554
 555static struct snd_soc_card midas_card = {
 556        .name = "Midas WM1811",
 557        .owner = THIS_MODULE,
 558
 559        .dai_link = midas_dai,
 560        .num_links = ARRAY_SIZE(midas_dai),
 561        .controls = midas_controls,
 562        .num_controls = ARRAY_SIZE(midas_controls),
 563        .dapm_widgets = midas_dapm_widgets,
 564        .num_dapm_widgets = ARRAY_SIZE(midas_dapm_widgets),
 565        .dapm_routes = midas_dapm_routes,
 566        .num_dapm_routes = ARRAY_SIZE(midas_dapm_routes),
 567
 568        .set_bias_level = midas_set_bias_level,
 569        .late_probe = midas_late_probe,
 570};
 571
 572static int midas_probe(struct platform_device *pdev)
 573{
 574        struct device_node *cpu_dai_node = NULL, *codec_dai_node = NULL;
 575        struct device_node *cpu = NULL, *codec = NULL;
 576        struct snd_soc_card *card = &midas_card;
 577        struct device *dev = &pdev->dev;
 578        static struct snd_soc_dai_link *dai_link;
 579        enum iio_chan_type channel_type;
 580        u32 fourpole_threshold[2];
 581        u32 button_threshold[3];
 582        struct midas_priv *priv;
 583        int ret, i;
 584
 585        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 586        if (!priv)
 587                return -ENOMEM;
 588
 589        snd_soc_card_set_drvdata(card, priv);
 590        card->dev = dev;
 591
 592        priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH);
 593        if (IS_ERR(priv->gpio_fm_sel))
 594                return dev_err_probe(dev, PTR_ERR(priv->gpio_fm_sel),
 595                                     "Failed to get FM selection GPIO\n");
 596
 597        priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel",
 598                                                    GPIOD_OUT_HIGH);
 599        if (IS_ERR(priv->gpio_lineout_sel))
 600                return dev_err_probe(dev, PTR_ERR(priv->gpio_lineout_sel),
 601                                     "Failed to get line out selection GPIO\n");
 602
 603        priv->gpio_headset_detect = devm_gpiod_get_optional(dev,
 604                                "headset-detect", GPIOD_IN);
 605        if (IS_ERR(priv->gpio_headset_detect))
 606                return dev_err_probe(dev, PTR_ERR(priv->gpio_headset_detect),
 607                                     "Failed to get headset jack detect GPIO\n");
 608
 609        if (priv->gpio_headset_detect) {
 610                priv->adc_headset_detect = devm_iio_channel_get(dev,
 611                                                        "headset-detect");
 612                if (IS_ERR(priv->adc_headset_detect))
 613                        return dev_err_probe(dev,
 614                                             PTR_ERR(priv->adc_headset_detect),
 615                                             "Failed to get ADC channel\n");
 616
 617                ret = iio_get_channel_type(priv->adc_headset_detect,
 618                                           &channel_type);
 619                if (ret) {
 620                        dev_err(dev, "Failed to get ADC channel type\n");
 621                        return ret;
 622                }
 623
 624                if (channel_type != IIO_VOLTAGE) {
 625                        dev_err(dev, "ADC channel is not voltage\n");
 626                        return -EINVAL;
 627                }
 628
 629                priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key",
 630                                                        GPIOD_IN);
 631                if (IS_ERR(priv->gpio_headset_key))
 632                        return dev_err_probe(dev,
 633                                             PTR_ERR(priv->gpio_headset_key),
 634                                             "Failed to get headset key GPIO\n");
 635
 636                ret = of_property_read_u32_array(dev->of_node,
 637                                "samsung,headset-4pole-threshold-microvolt",
 638                                fourpole_threshold,
 639                                ARRAY_SIZE(fourpole_threshold));
 640                if (ret) {
 641                        dev_err(dev, "Failed to get 4-pole jack detection threshold\n");
 642                        return ret;
 643                }
 644
 645                if (fourpole_threshold[0] > fourpole_threshold[1]) {
 646                        dev_err(dev, "Invalid 4-pole jack detection threshold value\n");
 647                        return -EINVAL;
 648                }
 649
 650                headset_jack_zones[0].max_mv = (fourpole_threshold[0]);
 651                headset_jack_zones[1].min_mv = (fourpole_threshold[0] + 1);
 652
 653                headset_jack_zones[1].max_mv = (fourpole_threshold[1]);
 654                headset_jack_zones[2].min_mv = (fourpole_threshold[1] + 1);
 655
 656                ret = of_property_read_u32_array(dev->of_node,
 657                                "samsung,headset-button-threshold-microvolt",
 658                                button_threshold,
 659                                ARRAY_SIZE(button_threshold));
 660                if (ret) {
 661                        dev_err(dev, "Failed to get headset button detection threshold\n");
 662                        return ret;
 663                }
 664
 665                if (button_threshold[0] > button_threshold[1] ||
 666                    button_threshold[1] > button_threshold[2]) {
 667                        dev_err(dev, "Invalid headset button detection threshold value\n");
 668                        return -EINVAL;
 669                }
 670
 671                for (i = 0; i < 3; i++) {
 672                        if (i != 0 && button_threshold[i] <= 0) {
 673                                dev_err(dev, "Invalid headset button detection threshold value\n");
 674                                return -EINVAL;
 675                        }
 676
 677                        headset_key_zones[i].min_mv = button_threshold[i];
 678
 679                        if (i == 2)
 680                                headset_key_zones[i].max_mv = UINT_MAX;
 681                        else
 682                                headset_key_zones[i].max_mv = \
 683                                                (button_threshold[i+1] - 1);
 684                }
 685        }
 686
 687        ret = snd_soc_of_parse_card_name(card, "model");
 688        if (ret < 0) {
 689                dev_err(dev, "Card name is not specified\n");
 690                return ret;
 691        }
 692
 693        ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
 694        if (ret < 0) {
 695                /* Backwards compatible way */
 696                ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
 697                if (ret < 0) {
 698                        dev_err(dev, "Audio routing invalid/unspecified\n");
 699                        return ret;
 700                }
 701        }
 702
 703        cpu = of_get_child_by_name(dev->of_node, "cpu");
 704        if (!cpu)
 705                return -EINVAL;
 706
 707        codec = of_get_child_by_name(dev->of_node, "codec");
 708        if (!codec) {
 709                of_node_put(cpu);
 710                return -EINVAL;
 711        }
 712
 713        cpu_dai_node = of_parse_phandle(cpu, "sound-dai", 0);
 714        of_node_put(cpu);
 715        if (!cpu_dai_node) {
 716                dev_err(dev, "parsing cpu/sound-dai failed\n");
 717                of_node_put(codec);
 718                return -EINVAL;
 719        }
 720
 721        codec_dai_node = of_parse_phandle(codec, "sound-dai", 0);
 722        of_node_put(codec);
 723        if (!codec_dai_node) {
 724                dev_err(dev, "audio-codec property invalid/missing\n");
 725                ret = -EINVAL;
 726                goto put_cpu_dai_node;
 727        }
 728
 729        for_each_card_prelinks(card, i, dai_link) {
 730                dai_link->codecs->of_node = codec_dai_node;
 731                dai_link->cpus->of_node = cpu_dai_node;
 732                dai_link->platforms->of_node = cpu_dai_node;
 733        }
 734
 735        ret = devm_snd_soc_register_component(dev, &midas_component,
 736                        midas_ext_dai, ARRAY_SIZE(midas_ext_dai));
 737        if (ret < 0) {
 738                dev_err(dev, "Failed to register component: %d\n", ret);
 739                goto put_codec_dai_node;
 740        }
 741
 742        ret = devm_snd_soc_register_card(dev, card);
 743        if (ret < 0) {
 744                dev_err(dev, "Failed to register card: %d\n", ret);
 745                goto put_codec_dai_node;
 746        }
 747
 748        return 0;
 749
 750put_codec_dai_node:
 751        of_node_put(codec_dai_node);
 752put_cpu_dai_node:
 753        of_node_put(cpu_dai_node);
 754        return ret;
 755}
 756
 757static const struct of_device_id midas_of_match[] = {
 758        { .compatible = "samsung,midas-audio" },
 759        { },
 760};
 761MODULE_DEVICE_TABLE(of, midas_of_match);
 762
 763static struct platform_driver midas_driver = {
 764        .driver = {
 765                .name = "midas-audio",
 766                .of_match_table = midas_of_match,
 767                .pm = &snd_soc_pm_ops,
 768        },
 769        .probe = midas_probe,
 770};
 771module_platform_driver(midas_driver);
 772
 773MODULE_AUTHOR("Simon Shields <simon@lineageos.org>");
 774MODULE_DESCRIPTION("ASoC support for Midas");
 775MODULE_LICENSE("GPL v2");
 776