root/sound/soc/codecs/max9759.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pga_event
  2. speaker_gain_control_get
  3. speaker_gain_control_put
  4. speaker_mute_get
  5. speaker_mute_put
  6. max9759_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * MAX9759 Amplifier Driver
   4  *
   5  * Copyright (c) 2017 BayLibre, SAS.
   6  * Author: Neil Armstrong <narmstrong@baylibre.com>
   7  */
   8 
   9 #include <linux/gpio/consumer.h>
  10 #include <linux/module.h>
  11 #include <sound/soc.h>
  12 #include <sound/soc-dapm.h>
  13 #include <sound/tlv.h>
  14 
  15 #define DRV_NAME "max9759"
  16 
  17 struct max9759 {
  18         struct gpio_desc *gpiod_shutdown;
  19         struct gpio_desc *gpiod_mute;
  20         struct gpio_descs *gpiod_gain;
  21         bool is_mute;
  22         unsigned int gain;
  23 };
  24 
  25 static int pga_event(struct snd_soc_dapm_widget *w,
  26                      struct snd_kcontrol *control, int event)
  27 {
  28         struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
  29         struct max9759 *priv = snd_soc_component_get_drvdata(c);
  30 
  31         if (SND_SOC_DAPM_EVENT_ON(event))
  32                 gpiod_set_value_cansleep(priv->gpiod_shutdown, 0);
  33         else
  34                 gpiod_set_value_cansleep(priv->gpiod_shutdown, 1);
  35 
  36         return 0;
  37 }
  38 
  39 /* From 6dB to 24dB in steps of 6dB */
  40 static const DECLARE_TLV_DB_SCALE(speaker_gain_tlv, 600, 600, 0);
  41 
  42 static int speaker_gain_control_get(struct snd_kcontrol *kcontrol,
  43                                     struct snd_ctl_elem_value *ucontrol)
  44 {
  45         struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
  46         struct max9759 *priv = snd_soc_component_get_drvdata(c);
  47 
  48         ucontrol->value.integer.value[0] = priv->gain;
  49 
  50         return 0;
  51 }
  52 
  53 static const bool speaker_gain_table[4][2] = {
  54         /* G1, G2 */
  55         {true, true},   /* +6dB */
  56         {false, true},  /* +12dB */
  57         {true, false},  /* +18dB */
  58         {false, false}, /* +24dB */
  59 };
  60 
  61 static int speaker_gain_control_put(struct snd_kcontrol *kcontrol,
  62                                     struct snd_ctl_elem_value *ucontrol)
  63 {
  64         struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
  65         struct max9759 *priv = snd_soc_component_get_drvdata(c);
  66 
  67         if (ucontrol->value.integer.value[0] > 3)
  68                 return -EINVAL;
  69 
  70         priv->gain = ucontrol->value.integer.value[0];
  71 
  72         /* G1 */
  73         gpiod_set_value_cansleep(priv->gpiod_gain->desc[0],
  74                                  speaker_gain_table[priv->gain][0]);
  75         /* G2 */
  76         gpiod_set_value_cansleep(priv->gpiod_gain->desc[1],
  77                                  speaker_gain_table[priv->gain][1]);
  78 
  79         return 1;
  80 }
  81 
  82 static int speaker_mute_get(struct snd_kcontrol *kcontrol,
  83                             struct snd_ctl_elem_value *ucontrol)
  84 {
  85         struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
  86         struct max9759 *priv = snd_soc_component_get_drvdata(c);
  87 
  88         ucontrol->value.integer.value[0] = !priv->is_mute;
  89 
  90         return 0;
  91 }
  92 
  93 static int speaker_mute_put(struct snd_kcontrol *kcontrol,
  94                             struct snd_ctl_elem_value *ucontrol)
  95 {
  96         struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
  97         struct max9759 *priv = snd_soc_component_get_drvdata(c);
  98 
  99         priv->is_mute = !ucontrol->value.integer.value[0];
 100 
 101         gpiod_set_value_cansleep(priv->gpiod_mute, priv->is_mute);
 102 
 103         return 1;
 104 }
 105 
 106 static const struct snd_kcontrol_new max9759_dapm_controls[] = {
 107         SOC_SINGLE_EXT_TLV("Speaker Gain Volume", 0, 0, 3, 0,
 108                            speaker_gain_control_get, speaker_gain_control_put,
 109                            speaker_gain_tlv),
 110         SOC_SINGLE_BOOL_EXT("Playback Switch", 0,
 111                             speaker_mute_get, speaker_mute_put),
 112 };
 113 
 114 static const struct snd_soc_dapm_widget max9759_dapm_widgets[] = {
 115         SND_SOC_DAPM_INPUT("INL"),
 116         SND_SOC_DAPM_INPUT("INR"),
 117         SND_SOC_DAPM_PGA_E("PGA", SND_SOC_NOPM, 0, 0, NULL, 0, pga_event,
 118                            (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)),
 119         SND_SOC_DAPM_OUTPUT("OUTL"),
 120         SND_SOC_DAPM_OUTPUT("OUTR"),
 121 };
 122 
 123 static const struct snd_soc_dapm_route max9759_dapm_routes[] = {
 124         { "PGA", NULL, "INL" },
 125         { "PGA", NULL, "INR" },
 126         { "OUTL", NULL, "PGA" },
 127         { "OUTR", NULL, "PGA" },
 128 };
 129 
 130 static const struct snd_soc_component_driver max9759_component_driver = {
 131         .controls               = max9759_dapm_controls,
 132         .num_controls           = ARRAY_SIZE(max9759_dapm_controls),
 133         .dapm_widgets           = max9759_dapm_widgets,
 134         .num_dapm_widgets       = ARRAY_SIZE(max9759_dapm_widgets),
 135         .dapm_routes            = max9759_dapm_routes,
 136         .num_dapm_routes        = ARRAY_SIZE(max9759_dapm_routes),
 137 };
 138 
 139 static int max9759_probe(struct platform_device *pdev)
 140 {
 141         struct device *dev = &pdev->dev;
 142         struct max9759 *priv;
 143         int err;
 144 
 145         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 146         if (!priv)
 147                 return -ENOMEM;
 148 
 149         platform_set_drvdata(pdev, priv);
 150 
 151         priv->gpiod_shutdown = devm_gpiod_get(dev, "shutdown", GPIOD_OUT_HIGH);
 152         if (IS_ERR(priv->gpiod_shutdown)) {
 153                 err = PTR_ERR(priv->gpiod_shutdown);
 154                 if (err != -EPROBE_DEFER)
 155                         dev_err(dev, "Failed to get 'shutdown' gpio: %d", err);
 156                 return err;
 157         }
 158 
 159         priv->gpiod_mute = devm_gpiod_get(dev, "mute", GPIOD_OUT_HIGH);
 160         if (IS_ERR(priv->gpiod_mute)) {
 161                 err = PTR_ERR(priv->gpiod_mute);
 162                 if (err != -EPROBE_DEFER)
 163                         dev_err(dev, "Failed to get 'mute' gpio: %d", err);
 164                 return err;
 165         }
 166         priv->is_mute = true;
 167 
 168         priv->gpiod_gain = devm_gpiod_get_array(dev, "gain", GPIOD_OUT_HIGH);
 169         if (IS_ERR(priv->gpiod_gain)) {
 170                 err = PTR_ERR(priv->gpiod_gain);
 171                 if (err != -EPROBE_DEFER)
 172                         dev_err(dev, "Failed to get 'gain' gpios: %d", err);
 173                 return err;
 174         }
 175         priv->gain = 0;
 176 
 177         if (priv->gpiod_gain->ndescs != 2) {
 178                 dev_err(dev, "Invalid 'gain' gpios count: %d",
 179                         priv->gpiod_gain->ndescs);
 180                 return -EINVAL;
 181         }
 182 
 183         return devm_snd_soc_register_component(dev, &max9759_component_driver,
 184                                                NULL, 0);
 185 }
 186 
 187 #ifdef CONFIG_OF
 188 static const struct of_device_id max9759_ids[] = {
 189         { .compatible = "maxim,max9759", },
 190         { }
 191 };
 192 MODULE_DEVICE_TABLE(of, max9759_ids);
 193 #endif
 194 
 195 static struct platform_driver max9759_driver = {
 196         .driver = {
 197                 .name = DRV_NAME,
 198                 .of_match_table = of_match_ptr(max9759_ids),
 199         },
 200         .probe = max9759_probe,
 201 };
 202 
 203 module_platform_driver(max9759_driver);
 204 
 205 MODULE_DESCRIPTION("ASoC MAX9759 amplifier driver");
 206 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
 207 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */