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_OUTPUT("Speaker"), 55af5adf12SKenneth Westfield }; 56af5adf12SKenneth Westfield 57af5adf12SKenneth Westfield static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { 58508e6195SAnatol Pomozov {"Speaker", NULL, "HiFi Playback"}, 59af5adf12SKenneth Westfield }; 60af5adf12SKenneth Westfield 61af5adf12SKenneth Westfield static int max98357a_codec_probe(struct snd_soc_codec *codec) 62af5adf12SKenneth Westfield { 63af5adf12SKenneth Westfield struct gpio_desc *sdmode; 64af5adf12SKenneth Westfield 655119222fSAnatol Pomozov sdmode = devm_gpiod_get_optional(codec->dev, "sdmode", GPIOD_OUT_LOW); 66af5adf12SKenneth Westfield if (IS_ERR(sdmode)) { 67af5adf12SKenneth Westfield dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n", 68af5adf12SKenneth Westfield __func__, PTR_ERR(sdmode)); 69af5adf12SKenneth Westfield return PTR_ERR(sdmode); 70af5adf12SKenneth Westfield } 71af5adf12SKenneth Westfield snd_soc_codec_set_drvdata(codec, sdmode); 72af5adf12SKenneth Westfield 73af5adf12SKenneth Westfield return 0; 74af5adf12SKenneth Westfield } 75af5adf12SKenneth Westfield 76af5adf12SKenneth Westfield static struct snd_soc_codec_driver max98357a_codec_driver = { 77af5adf12SKenneth Westfield .probe = max98357a_codec_probe, 78af5adf12SKenneth Westfield .dapm_widgets = max98357a_dapm_widgets, 79af5adf12SKenneth Westfield .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), 80af5adf12SKenneth Westfield .dapm_routes = max98357a_dapm_routes, 81af5adf12SKenneth Westfield .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), 82af5adf12SKenneth Westfield }; 83af5adf12SKenneth Westfield 84af5adf12SKenneth Westfield static struct snd_soc_dai_ops max98357a_dai_ops = { 85af5adf12SKenneth Westfield .trigger = max98357a_daiops_trigger, 86af5adf12SKenneth Westfield }; 87af5adf12SKenneth Westfield 88af5adf12SKenneth Westfield static struct snd_soc_dai_driver max98357a_dai_driver = { 8992b2ad2cSKenneth Westfield .name = "HiFi", 90af5adf12SKenneth Westfield .playback = { 9192b2ad2cSKenneth Westfield .stream_name = "HiFi Playback", 92af5adf12SKenneth Westfield .formats = SNDRV_PCM_FMTBIT_S16 | 93af5adf12SKenneth Westfield SNDRV_PCM_FMTBIT_S24 | 94af5adf12SKenneth Westfield SNDRV_PCM_FMTBIT_S32, 95af5adf12SKenneth Westfield .rates = SNDRV_PCM_RATE_8000 | 96af5adf12SKenneth Westfield SNDRV_PCM_RATE_16000 | 97af5adf12SKenneth Westfield SNDRV_PCM_RATE_48000 | 98af5adf12SKenneth Westfield SNDRV_PCM_RATE_96000, 99af5adf12SKenneth Westfield .rate_min = 8000, 100af5adf12SKenneth Westfield .rate_max = 96000, 101af5adf12SKenneth Westfield .channels_min = 1, 102af5adf12SKenneth Westfield .channels_max = 2, 103af5adf12SKenneth Westfield }, 104af5adf12SKenneth Westfield .ops = &max98357a_dai_ops, 105af5adf12SKenneth Westfield }; 106af5adf12SKenneth Westfield 107af5adf12SKenneth Westfield static int max98357a_platform_probe(struct platform_device *pdev) 108af5adf12SKenneth Westfield { 109af5adf12SKenneth Westfield int ret; 110af5adf12SKenneth Westfield 111af5adf12SKenneth Westfield ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver, 112af5adf12SKenneth Westfield &max98357a_dai_driver, 1); 113af5adf12SKenneth Westfield if (ret) 114af5adf12SKenneth Westfield dev_err(&pdev->dev, "%s() error registering codec driver: %d\n", 115af5adf12SKenneth Westfield __func__, ret); 116af5adf12SKenneth Westfield 117af5adf12SKenneth Westfield return ret; 118af5adf12SKenneth Westfield } 119af5adf12SKenneth Westfield 120af5adf12SKenneth Westfield static int max98357a_platform_remove(struct platform_device *pdev) 121af5adf12SKenneth Westfield { 122af5adf12SKenneth Westfield snd_soc_unregister_codec(&pdev->dev); 123af5adf12SKenneth Westfield 124af5adf12SKenneth Westfield return 0; 125af5adf12SKenneth Westfield } 126af5adf12SKenneth Westfield 127af5adf12SKenneth Westfield #ifdef CONFIG_OF 128af5adf12SKenneth Westfield static const struct of_device_id max98357a_device_id[] = { 1297ff5eabcSKenneth Westfield { .compatible = "maxim,max98357a" }, 130af5adf12SKenneth Westfield {} 131af5adf12SKenneth Westfield }; 1323efa130dSMark Brown MODULE_DEVICE_TABLE(of, max98357a_device_id); 133af5adf12SKenneth Westfield #endif 134af5adf12SKenneth Westfield 135af5adf12SKenneth Westfield static struct platform_driver max98357a_platform_driver = { 136af5adf12SKenneth Westfield .driver = { 1377ff5eabcSKenneth Westfield .name = "max98357a", 138af5adf12SKenneth Westfield .of_match_table = of_match_ptr(max98357a_device_id), 139af5adf12SKenneth Westfield }, 140af5adf12SKenneth Westfield .probe = max98357a_platform_probe, 141af5adf12SKenneth Westfield .remove = max98357a_platform_remove, 142af5adf12SKenneth Westfield }; 143af5adf12SKenneth Westfield module_platform_driver(max98357a_platform_driver); 144af5adf12SKenneth Westfield 145af5adf12SKenneth Westfield MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver"); 146af5adf12SKenneth Westfield MODULE_LICENSE("GPL v2"); 147