1af5adf12SKenneth Westfield /* Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. 2af5adf12SKenneth Westfield * 3af5adf12SKenneth Westfield * This program is free software; you can redistribute it and/or modify 4af5adf12SKenneth Westfield * it under the terms of the GNU General Public License version 2 and 5af5adf12SKenneth Westfield * only version 2 as published by the Free Software Foundation. 6af5adf12SKenneth Westfield * 7af5adf12SKenneth Westfield * This program is distributed in the hope that it will be useful, 8af5adf12SKenneth Westfield * but WITHOUT ANY WARRANTY; without even the implied warranty of 9af5adf12SKenneth Westfield * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10af5adf12SKenneth Westfield * GNU General Public License for more details. 11af5adf12SKenneth Westfield * 12af5adf12SKenneth Westfield * max98357a.c -- MAX98357A ALSA SoC Codec driver 13af5adf12SKenneth Westfield */ 14af5adf12SKenneth Westfield 1508d0a55cSKenneth Westfield #include <linux/device.h> 1608d0a55cSKenneth Westfield #include <linux/err.h> 17af5adf12SKenneth Westfield #include <linux/gpio.h> 185c8be987SVincent Stehlé #include <linux/gpio/consumer.h> 1908d0a55cSKenneth Westfield #include <linux/kernel.h> 2008d0a55cSKenneth Westfield #include <linux/mod_devicetable.h> 2108d0a55cSKenneth Westfield #include <linux/module.h> 2208d0a55cSKenneth Westfield #include <linux/of.h> 2308d0a55cSKenneth Westfield #include <linux/platform_device.h> 2408d0a55cSKenneth Westfield #include <sound/pcm.h> 25af5adf12SKenneth Westfield #include <sound/soc.h> 2608d0a55cSKenneth Westfield #include <sound/soc-dai.h> 2708d0a55cSKenneth Westfield #include <sound/soc-dapm.h> 28af5adf12SKenneth Westfield 29af5adf12SKenneth Westfield static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, 30af5adf12SKenneth Westfield int cmd, struct snd_soc_dai *dai) 31af5adf12SKenneth Westfield { 32af5adf12SKenneth Westfield struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai); 33af5adf12SKenneth Westfield 345119222fSAnatol Pomozov if (!sdmode) 355119222fSAnatol Pomozov return 0; 365119222fSAnatol Pomozov 37af5adf12SKenneth Westfield switch (cmd) { 38af5adf12SKenneth Westfield case SNDRV_PCM_TRIGGER_START: 39af5adf12SKenneth Westfield case SNDRV_PCM_TRIGGER_RESUME: 40af5adf12SKenneth Westfield case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 41af5adf12SKenneth Westfield gpiod_set_value(sdmode, 1); 42af5adf12SKenneth Westfield break; 43af5adf12SKenneth Westfield case SNDRV_PCM_TRIGGER_STOP: 44af5adf12SKenneth Westfield case SNDRV_PCM_TRIGGER_SUSPEND: 45af5adf12SKenneth Westfield case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 46af5adf12SKenneth Westfield gpiod_set_value(sdmode, 0); 47af5adf12SKenneth Westfield break; 48af5adf12SKenneth Westfield } 49af5adf12SKenneth Westfield 50af5adf12SKenneth Westfield return 0; 51af5adf12SKenneth Westfield } 52af5adf12SKenneth Westfield 53af5adf12SKenneth Westfield static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { 54af5adf12SKenneth Westfield SND_SOC_DAPM_DAC("SDMode", NULL, SND_SOC_NOPM, 0, 0), 55af5adf12SKenneth Westfield SND_SOC_DAPM_OUTPUT("Speaker"), 56af5adf12SKenneth Westfield }; 57af5adf12SKenneth Westfield 58af5adf12SKenneth Westfield static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { 59af5adf12SKenneth Westfield {"Speaker", NULL, "SDMode"}, 60af5adf12SKenneth Westfield }; 61af5adf12SKenneth Westfield 62af5adf12SKenneth Westfield static int max98357a_codec_probe(struct snd_soc_codec *codec) 63af5adf12SKenneth Westfield { 64af5adf12SKenneth Westfield struct gpio_desc *sdmode; 65af5adf12SKenneth Westfield 665119222fSAnatol Pomozov sdmode = devm_gpiod_get_optional(codec->dev, "sdmode", GPIOD_OUT_LOW); 67af5adf12SKenneth Westfield if (IS_ERR(sdmode)) { 68af5adf12SKenneth Westfield dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n", 69af5adf12SKenneth Westfield __func__, PTR_ERR(sdmode)); 70af5adf12SKenneth Westfield return PTR_ERR(sdmode); 71af5adf12SKenneth Westfield } 72af5adf12SKenneth Westfield snd_soc_codec_set_drvdata(codec, sdmode); 73af5adf12SKenneth Westfield 74af5adf12SKenneth Westfield return 0; 75af5adf12SKenneth Westfield } 76af5adf12SKenneth Westfield 77af5adf12SKenneth Westfield static struct snd_soc_codec_driver max98357a_codec_driver = { 78af5adf12SKenneth Westfield .probe = max98357a_codec_probe, 79af5adf12SKenneth Westfield .dapm_widgets = max98357a_dapm_widgets, 80af5adf12SKenneth Westfield .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), 81af5adf12SKenneth Westfield .dapm_routes = max98357a_dapm_routes, 82af5adf12SKenneth Westfield .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), 83af5adf12SKenneth Westfield }; 84af5adf12SKenneth Westfield 85af5adf12SKenneth Westfield static struct snd_soc_dai_ops max98357a_dai_ops = { 86af5adf12SKenneth Westfield .trigger = max98357a_daiops_trigger, 87af5adf12SKenneth Westfield }; 88af5adf12SKenneth Westfield 89af5adf12SKenneth Westfield static struct snd_soc_dai_driver max98357a_dai_driver = { 9092b2ad2cSKenneth Westfield .name = "HiFi", 91af5adf12SKenneth Westfield .playback = { 9292b2ad2cSKenneth Westfield .stream_name = "HiFi Playback", 93af5adf12SKenneth Westfield .formats = SNDRV_PCM_FMTBIT_S16 | 94af5adf12SKenneth Westfield SNDRV_PCM_FMTBIT_S24 | 95af5adf12SKenneth Westfield SNDRV_PCM_FMTBIT_S32, 96af5adf12SKenneth Westfield .rates = SNDRV_PCM_RATE_8000 | 97af5adf12SKenneth Westfield SNDRV_PCM_RATE_16000 | 98af5adf12SKenneth Westfield SNDRV_PCM_RATE_48000 | 99af5adf12SKenneth Westfield SNDRV_PCM_RATE_96000, 100af5adf12SKenneth Westfield .rate_min = 8000, 101af5adf12SKenneth Westfield .rate_max = 96000, 102af5adf12SKenneth Westfield .channels_min = 1, 103af5adf12SKenneth Westfield .channels_max = 2, 104af5adf12SKenneth Westfield }, 105af5adf12SKenneth Westfield .ops = &max98357a_dai_ops, 106af5adf12SKenneth Westfield }; 107af5adf12SKenneth Westfield 108af5adf12SKenneth Westfield static int max98357a_platform_probe(struct platform_device *pdev) 109af5adf12SKenneth Westfield { 110af5adf12SKenneth Westfield int ret; 111af5adf12SKenneth Westfield 112af5adf12SKenneth Westfield ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver, 113af5adf12SKenneth Westfield &max98357a_dai_driver, 1); 114af5adf12SKenneth Westfield if (ret) 115af5adf12SKenneth Westfield dev_err(&pdev->dev, "%s() error registering codec driver: %d\n", 116af5adf12SKenneth Westfield __func__, ret); 117af5adf12SKenneth Westfield 118af5adf12SKenneth Westfield return ret; 119af5adf12SKenneth Westfield } 120af5adf12SKenneth Westfield 121af5adf12SKenneth Westfield static int max98357a_platform_remove(struct platform_device *pdev) 122af5adf12SKenneth Westfield { 123af5adf12SKenneth Westfield snd_soc_unregister_codec(&pdev->dev); 124af5adf12SKenneth Westfield 125af5adf12SKenneth Westfield return 0; 126af5adf12SKenneth Westfield } 127af5adf12SKenneth Westfield 128af5adf12SKenneth Westfield #ifdef CONFIG_OF 129af5adf12SKenneth Westfield static const struct of_device_id max98357a_device_id[] = { 1307ff5eabcSKenneth Westfield { .compatible = "maxim,max98357a" }, 131af5adf12SKenneth Westfield {} 132af5adf12SKenneth Westfield }; 1333efa130dSMark Brown MODULE_DEVICE_TABLE(of, max98357a_device_id); 134af5adf12SKenneth Westfield #endif 135af5adf12SKenneth Westfield 136af5adf12SKenneth Westfield static struct platform_driver max98357a_platform_driver = { 137af5adf12SKenneth Westfield .driver = { 1387ff5eabcSKenneth Westfield .name = "max98357a", 139af5adf12SKenneth Westfield .of_match_table = of_match_ptr(max98357a_device_id), 140af5adf12SKenneth Westfield }, 141af5adf12SKenneth Westfield .probe = max98357a_platform_probe, 142af5adf12SKenneth Westfield .remove = max98357a_platform_remove, 143af5adf12SKenneth Westfield }; 144af5adf12SKenneth Westfield module_platform_driver(max98357a_platform_driver); 145af5adf12SKenneth Westfield 146af5adf12SKenneth Westfield MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver"); 147af5adf12SKenneth Westfield MODULE_LICENSE("GPL v2"); 148