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 31 struct tegra_max98090 { 32 struct tegra_asoc_utils_data util_data; 33 int gpio_hp_det; 34 int gpio_mic_det; 35 }; 36 37 static 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 85 static const struct snd_soc_ops tegra_max98090_ops = { 86 .hw_params = tegra_max98090_asoc_hw_params, 87 }; 88 89 static struct snd_soc_jack tegra_max98090_hp_jack; 90 91 static struct snd_soc_jack_pin tegra_max98090_hp_jack_pins[] = { 92 { 93 .pin = "Headphones", 94 .mask = SND_JACK_HEADPHONE, 95 }, 96 }; 97 98 static 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 105 static struct snd_soc_jack tegra_max98090_mic_jack; 106 107 static struct snd_soc_jack_pin tegra_max98090_mic_jack_pins[] = { 108 { 109 .pin = "Mic Jack", 110 .mask = SND_JACK_MICROPHONE, 111 }, 112 }; 113 114 static 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 121 static 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 128 static 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 135 static 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 168 SND_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 173 static 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 183 static 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 196 static 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 return dev_err_probe(&pdev->dev, ret, 253 "snd_soc_register_card failed\n"); 254 255 return 0; 256 } 257 258 static const struct of_device_id tegra_max98090_of_match[] = { 259 { .compatible = "nvidia,tegra-audio-max98090", }, 260 {}, 261 }; 262 263 static struct platform_driver tegra_max98090_driver = { 264 .driver = { 265 .name = DRV_NAME, 266 .pm = &snd_soc_pm_ops, 267 .of_match_table = tegra_max98090_of_match, 268 }, 269 .probe = tegra_max98090_probe, 270 }; 271 module_platform_driver(tegra_max98090_driver); 272 273 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 274 MODULE_DESCRIPTION("Tegra max98090 machine ASoC driver"); 275 MODULE_LICENSE("GPL v2"); 276 MODULE_ALIAS("platform:" DRV_NAME); 277 MODULE_DEVICE_TABLE(of, tegra_max98090_of_match); 278
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.