^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * tegra_rt5677.c - Tegra machine ASoC driver for boards using RT5677 codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014, The Chromium OS Authors. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on code copyright/by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2010-2012 - NVIDIA, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright 2007 Wolfson Microelectronics PLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/jack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "../codecs/rt5677.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "tegra_asoc_utils.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DRV_NAME "tegra-snd-rt5677"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct tegra_rt5677 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct tegra_asoc_utils_data util_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int gpio_hp_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int gpio_hp_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int gpio_mic_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int gpio_dmic_clk_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int tegra_rt5677_asoc_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct snd_soc_card *card = rtd->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int srate, mclk, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) srate = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) mclk = 256 * srate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) dev_err(card->dev, "Can't configure clocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) err = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_MCLK, mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) SND_SOC_CLOCK_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dev_err(card->dev, "codec_dai clock not set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int tegra_rt5677_event_hp(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct snd_kcontrol *k, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct snd_soc_dapm_context *dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (!gpio_is_valid(machine->gpio_hp_en))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) gpio_set_value_cansleep(machine->gpio_hp_en,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) SND_SOC_DAPM_EVENT_ON(event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static const struct snd_soc_ops tegra_rt5677_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .hw_params = tegra_rt5677_asoc_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct snd_soc_jack tegra_rt5677_hp_jack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static struct snd_soc_jack_pin tegra_rt5677_hp_jack_pins = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .pin = "Headphone",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .mask = SND_JACK_HEADPHONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static struct snd_soc_jack_gpio tegra_rt5677_hp_jack_gpio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .name = "Headphone detection",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .report = SND_JACK_HEADPHONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .debounce_time = 150,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static struct snd_soc_jack tegra_rt5677_mic_jack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static struct snd_soc_jack_pin tegra_rt5677_mic_jack_pins = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .pin = "Headset Mic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .mask = SND_JACK_MICROPHONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static struct snd_soc_jack_gpio tegra_rt5677_mic_jack_gpio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .name = "Headset Mic detection",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .report = SND_JACK_MICROPHONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .debounce_time = 150,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .invert = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static const struct snd_soc_dapm_widget tegra_rt5677_dapm_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) SND_SOC_DAPM_SPK("Speaker", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) SND_SOC_DAPM_HP("Headphone", tegra_rt5677_event_hp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) SND_SOC_DAPM_MIC("Headset Mic", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) SND_SOC_DAPM_MIC("Internal Mic 1", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) SND_SOC_DAPM_MIC("Internal Mic 2", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static const struct snd_kcontrol_new tegra_rt5677_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) SOC_DAPM_PIN_SWITCH("Speaker"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) SOC_DAPM_PIN_SWITCH("Headphone"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) SOC_DAPM_PIN_SWITCH("Headset Mic"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) SOC_DAPM_PIN_SWITCH("Internal Mic 1"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) SOC_DAPM_PIN_SWITCH("Internal Mic 2"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) &tegra_rt5677_hp_jack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) &tegra_rt5677_hp_jack_pins, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (gpio_is_valid(machine->gpio_hp_det)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) tegra_rt5677_hp_jack_gpio.gpio = machine->gpio_hp_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) snd_soc_jack_add_gpios(&tegra_rt5677_hp_jack, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) &tegra_rt5677_hp_jack_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) snd_soc_card_jack_new(rtd->card, "Mic Jack", SND_JACK_MICROPHONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) &tegra_rt5677_mic_jack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) &tegra_rt5677_mic_jack_pins, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (gpio_is_valid(machine->gpio_mic_present)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) tegra_rt5677_mic_jack_gpio.gpio = machine->gpio_mic_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) snd_soc_jack_add_gpios(&tegra_rt5677_mic_jack, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) &tegra_rt5677_mic_jack_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) snd_soc_dapm_force_enable_pin(&rtd->card->dapm, "MICBIAS1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) SND_SOC_DAILINK_DEFS(pcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) DAILINK_COMP_ARRAY(COMP_EMPTY()),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5677-aif1")),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) DAILINK_COMP_ARRAY(COMP_EMPTY()));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static struct snd_soc_dai_link tegra_rt5677_dai = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .name = "RT5677",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .stream_name = "RT5677 PCM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .init = tegra_rt5677_asoc_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .ops = &tegra_rt5677_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) SND_SOC_DAIFMT_CBS_CFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) SND_SOC_DAILINK_REG(pcm),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct snd_soc_card snd_soc_tegra_rt5677 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .name = "tegra-rt5677",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .driver_name = "tegra",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .dai_link = &tegra_rt5677_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .num_links = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .controls = tegra_rt5677_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .num_controls = ARRAY_SIZE(tegra_rt5677_controls),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .dapm_widgets = tegra_rt5677_dapm_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .num_dapm_widgets = ARRAY_SIZE(tegra_rt5677_dapm_widgets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .fully_routed = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int tegra_rt5677_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct snd_soc_card *card = &snd_soc_tegra_rt5677;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct tegra_rt5677 *machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) machine = devm_kzalloc(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) sizeof(struct tegra_rt5677), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) card->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) snd_soc_card_set_drvdata(card, machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (machine->gpio_hp_det == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) machine->gpio_mic_present = of_get_named_gpio(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) "nvidia,mic-present-gpios", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (machine->gpio_mic_present == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) machine->gpio_hp_en = of_get_named_gpio(np, "nvidia,hp-en-gpios", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (machine->gpio_hp_en == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (gpio_is_valid(machine->gpio_hp_en)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ret = devm_gpio_request_one(&pdev->dev, machine->gpio_hp_en,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) GPIOF_OUT_INIT_LOW, "hp_en");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dev_err(card->dev, "cannot get hp_en gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) machine->gpio_dmic_clk_en = of_get_named_gpio(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "nvidia,dmic-clk-en-gpios", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (machine->gpio_dmic_clk_en == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (gpio_is_valid(machine->gpio_dmic_clk_en)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = devm_gpio_request_one(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) machine->gpio_dmic_clk_en,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) GPIOF_OUT_INIT_HIGH, "dmic_clk_en");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dev_err(card->dev, "cannot get dmic_clk_en gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = snd_soc_of_parse_card_name(card, "nvidia,model");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) tegra_rt5677_dai.codecs->of_node = of_parse_phandle(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) "nvidia,audio-codec", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!tegra_rt5677_dai.codecs->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) "Property 'nvidia,audio-codec' missing or invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) tegra_rt5677_dai.cpus->of_node = of_parse_phandle(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) "nvidia,i2s-controller", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!tegra_rt5677_dai.cpus->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) "Property 'nvidia,i2s-controller' missing or invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) goto err_put_codec_of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) tegra_rt5677_dai.platforms->of_node = tegra_rt5677_dai.cpus->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto err_put_cpu_of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = snd_soc_register_card(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) goto err_put_cpu_of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) err_put_cpu_of_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) of_node_put(tegra_rt5677_dai.cpus->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tegra_rt5677_dai.cpus->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) tegra_rt5677_dai.platforms->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) err_put_codec_of_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) of_node_put(tegra_rt5677_dai.codecs->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) tegra_rt5677_dai.codecs->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static int tegra_rt5677_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct snd_soc_card *card = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) snd_soc_unregister_card(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) tegra_rt5677_dai.platforms->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) of_node_put(tegra_rt5677_dai.codecs->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) tegra_rt5677_dai.codecs->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) of_node_put(tegra_rt5677_dai.cpus->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) tegra_rt5677_dai.cpus->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static const struct of_device_id tegra_rt5677_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { .compatible = "nvidia,tegra-audio-rt5677", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static struct platform_driver tegra_rt5677_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .pm = &snd_soc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .of_match_table = tegra_rt5677_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .probe = tegra_rt5677_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .remove = tegra_rt5677_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) module_platform_driver(tegra_rt5677_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) MODULE_AUTHOR("Anatol Pomozov <anatol@google.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) MODULE_DESCRIPTION("Tegra+RT5677 machine ASoC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) MODULE_ALIAS("platform:" DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) MODULE_DEVICE_TABLE(of, tegra_rt5677_of_match);