1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Tegra machine ASoC driver for boards using a MAX90809 CODEC. 4 * 5 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. 6 * 7 * Based on code copyright/by: 8 * 9 * Copyright (C) 2010-2012 - NVIDIA, Inc. 10 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> 11 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. 12 * Copyright 2007 Wolfson Microelectronics PLC. 13 */ 14 15#include <linux/module.h> 16#include <linux/platform_device.h> 17#include <linux/slab.h> 18#include <linux/gpio.h> 19#include <linux/of_gpio.h> 20 21#include <sound/core.h> 22#include <sound/jack.h> 23#include <sound/pcm.h> 24#include <sound/pcm_params.h> 25#include <sound/soc.h> 26 27#include "tegra_asoc_utils.h" 28 29#define DRV_NAME "tegra-snd-max98090" 30 31struct tegra_max98090 { 32 struct tegra_asoc_utils_data util_data; 33 int gpio_hp_det; 34 int gpio_mic_det; 35}; 36 37static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream, 38 struct snd_pcm_hw_params *params) 39{ 40 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 41 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 42 struct snd_soc_card *card = rtd->card; 43 struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); 44 int srate, mclk; 45 int err; 46 47 srate = params_rate(params); 48 switch (srate) { 49 case 8000: 50 case 16000: 51 case 24000: 52 case 32000: 53 case 48000: 54 case 64000: 55 case 96000: 56 mclk = 12288000; 57 break; 58 case 11025: 59 case 22050: 60 case 44100: 61 case 88200: 62 mclk = 11289600; 63 break; 64 default: 65 mclk = 12000000; 66 break; 67 } 68 69 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); 70 if (err < 0) { 71 dev_err(card->dev, "Can't configure clocks\n"); 72 return err; 73 } 74 75 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, 76 SND_SOC_CLOCK_IN); 77 if (err < 0) { 78 dev_err(card->dev, "codec_dai clock not set\n"); 79 return err; 80 } 81 82 return 0; 83} 84 85static const struct snd_soc_ops tegra_max98090_ops = { 86 .hw_params = tegra_max98090_asoc_hw_params, 87}; 88 89static struct snd_soc_jack tegra_max98090_hp_jack; 90 91static struct snd_soc_jack_pin tegra_max98090_hp_jack_pins[] = { 92 { 93 .pin = "Headphones", 94 .mask = SND_JACK_HEADPHONE, 95 }, 96}; 97 98static struct snd_soc_jack_gpio tegra_max98090_hp_jack_gpio = { 99 .name = "Headphone detection", 100 .report = SND_JACK_HEADPHONE, 101 .debounce_time = 150, 102 .invert = 1, 103}; 104 105static struct snd_soc_jack tegra_max98090_mic_jack; 106 107static struct snd_soc_jack_pin tegra_max98090_mic_jack_pins[] = { 108 { 109 .pin = "Mic Jack", 110 .mask = SND_JACK_MICROPHONE, 111 }, 112}; 113 114static struct snd_soc_jack_gpio tegra_max98090_mic_jack_gpio = { 115 .name = "Mic detection", 116 .report = SND_JACK_MICROPHONE, 117 .debounce_time = 150, 118 .invert = 1, 119}; 120 121static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = { 122 SND_SOC_DAPM_HP("Headphones", NULL), 123 SND_SOC_DAPM_SPK("Speakers", NULL), 124 SND_SOC_DAPM_MIC("Mic Jack", NULL), 125 SND_SOC_DAPM_MIC("Int Mic", NULL), 126}; 127 128static const struct snd_kcontrol_new tegra_max98090_controls[] = { 129 SOC_DAPM_PIN_SWITCH("Headphones"), 130 SOC_DAPM_PIN_SWITCH("Speakers"), 131 SOC_DAPM_PIN_SWITCH("Mic Jack"), 132 SOC_DAPM_PIN_SWITCH("Int Mic"), 133}; 134 135static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd) 136{ 137 struct tegra_max98090 *machine = snd_soc_card_get_drvdata(rtd->card); 138 139 if (gpio_is_valid(machine->gpio_hp_det)) { 140 snd_soc_card_jack_new(rtd->card, "Headphones", 141 SND_JACK_HEADPHONE, 142 &tegra_max98090_hp_jack, 143 tegra_max98090_hp_jack_pins, 144 ARRAY_SIZE(tegra_max98090_hp_jack_pins)); 145 146 tegra_max98090_hp_jack_gpio.gpio = machine->gpio_hp_det; 147 snd_soc_jack_add_gpios(&tegra_max98090_hp_jack, 148 1, 149 &tegra_max98090_hp_jack_gpio); 150 } 151 152 if (gpio_is_valid(machine->gpio_mic_det)) { 153 snd_soc_card_jack_new(rtd->card, "Mic Jack", 154 SND_JACK_MICROPHONE, 155 &tegra_max98090_mic_jack, 156 tegra_max98090_mic_jack_pins, 157 ARRAY_SIZE(tegra_max98090_mic_jack_pins)); 158 159 tegra_max98090_mic_jack_gpio.gpio = machine->gpio_mic_det; 160 snd_soc_jack_add_gpios(&tegra_max98090_mic_jack, 161 1, 162 &tegra_max98090_mic_jack_gpio); 163 } 164 165 return 0; 166} 167 168SND_SOC_DAILINK_DEFS(pcm, 169 DAILINK_COMP_ARRAY(COMP_EMPTY()), 170 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")), 171 DAILINK_COMP_ARRAY(COMP_EMPTY())); 172 173static struct snd_soc_dai_link tegra_max98090_dai = { 174 .name = "max98090", 175 .stream_name = "max98090 PCM", 176 .init = tegra_max98090_asoc_init, 177 .ops = &tegra_max98090_ops, 178 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 179 SND_SOC_DAIFMT_CBS_CFS, 180 SND_SOC_DAILINK_REG(pcm), 181}; 182 183static struct snd_soc_card snd_soc_tegra_max98090 = { 184 .name = "tegra-max98090", 185 .driver_name = "tegra", 186 .owner = THIS_MODULE, 187 .dai_link = &tegra_max98090_dai, 188 .num_links = 1, 189 .controls = tegra_max98090_controls, 190 .num_controls = ARRAY_SIZE(tegra_max98090_controls), 191 .dapm_widgets = tegra_max98090_dapm_widgets, 192 .num_dapm_widgets = ARRAY_SIZE(tegra_max98090_dapm_widgets), 193 .fully_routed = true, 194}; 195 196static int tegra_max98090_probe(struct platform_device *pdev) 197{ 198 struct device_node *np = pdev->dev.of_node; 199 struct snd_soc_card *card = &snd_soc_tegra_max98090; 200 struct tegra_max98090 *machine; 201 int ret; 202 203 machine = devm_kzalloc(&pdev->dev, 204 sizeof(struct tegra_max98090), GFP_KERNEL); 205 if (!machine) 206 return -ENOMEM; 207 208 card->dev = &pdev->dev; 209 snd_soc_card_set_drvdata(card, machine); 210 211 machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); 212 if (machine->gpio_hp_det == -EPROBE_DEFER) 213 return -EPROBE_DEFER; 214 215 machine->gpio_mic_det = 216 of_get_named_gpio(np, "nvidia,mic-det-gpios", 0); 217 if (machine->gpio_mic_det == -EPROBE_DEFER) 218 return -EPROBE_DEFER; 219 220 ret = snd_soc_of_parse_card_name(card, "nvidia,model"); 221 if (ret) 222 return ret; 223 224 ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); 225 if (ret) 226 return ret; 227 228 tegra_max98090_dai.codecs->of_node = of_parse_phandle(np, 229 "nvidia,audio-codec", 0); 230 if (!tegra_max98090_dai.codecs->of_node) { 231 dev_err(&pdev->dev, 232 "Property 'nvidia,audio-codec' missing or invalid\n"); 233 return -EINVAL; 234 } 235 236 tegra_max98090_dai.cpus->of_node = of_parse_phandle(np, 237 "nvidia,i2s-controller", 0); 238 if (!tegra_max98090_dai.cpus->of_node) { 239 dev_err(&pdev->dev, 240 "Property 'nvidia,i2s-controller' missing or invalid\n"); 241 return -EINVAL; 242 } 243 244 tegra_max98090_dai.platforms->of_node = tegra_max98090_dai.cpus->of_node; 245 246 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); 247 if (ret) 248 return ret; 249 250 ret = devm_snd_soc_register_card(&pdev->dev, card); 251 if (ret) { 252 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", 253 ret); 254 return ret; 255 } 256 257 return 0; 258} 259 260static const struct of_device_id tegra_max98090_of_match[] = { 261 { .compatible = "nvidia,tegra-audio-max98090", }, 262 {}, 263}; 264 265static struct platform_driver tegra_max98090_driver = { 266 .driver = { 267 .name = DRV_NAME, 268 .pm = &snd_soc_pm_ops, 269 .of_match_table = tegra_max98090_of_match, 270 }, 271 .probe = tegra_max98090_probe, 272}; 273module_platform_driver(tegra_max98090_driver); 274 275MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 276MODULE_DESCRIPTION("Tegra max98090 machine ASoC driver"); 277MODULE_LICENSE("GPL v2"); 278MODULE_ALIAS("platform:" DRV_NAME); 279MODULE_DEVICE_TABLE(of, tegra_max98090_of_match); 280