^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // TSE-850 audio - ASoC driver for the Axentia TSE-850 with a PCM5142 codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (C) 2016 Axentia Technologies AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // Author: Peter Rosin <peda@axentia.se>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // loop1 relays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // IN1 +---o +------------+ o---+ OUT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // \ /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) // + +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) // | / |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) // +--o +--. |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) // | add | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) // | V |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) // | .---. |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) // DAC +----------->|Sum|---+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) // | '---' |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) // | |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) // + +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) // IN2 +---o--+------------+--o---+ OUT2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) // loop2 relays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) // The 'loop1' gpio pin controlls two relays, which are either in loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) // position, meaning that input and output are directly connected, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) // they are in mixer position, meaning that the signal is passed through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) // the 'Sum' mixer. Similarly for 'loop2'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) // In the above, the 'loop1' relays are inactive, thus feeding IN1 to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) // mixer (if 'add' is active) and feeding the mixer output to OUT1. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) // 'loop2' relays are active, short-cutting the TSE-850 from channel 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) // IN1, IN2, OUT1 and OUT2 are TSE-850 connectors and DAC is the PCB name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) // of the (filtered) output from the PCM5142 codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct tse850_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct gpio_desc *add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct gpio_desc *loop1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct gpio_desc *loop2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct regulator *ana;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int add_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int loop1_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int loop2_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int tse850_get_mux1(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ucontrol->value.enumerated.item[0] = tse850->loop1_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int tse850_put_mux1(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned int val = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (val >= e->items)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) gpiod_set_value_cansleep(tse850->loop1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) tse850->loop1_cache = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int tse850_get_mux2(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ucontrol->value.enumerated.item[0] = tse850->loop2_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int tse850_put_mux2(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned int val = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (val >= e->items)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) gpiod_set_value_cansleep(tse850->loop2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) tse850->loop2_cache = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int tse850_get_mix(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ucontrol->value.enumerated.item[0] = tse850->add_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int tse850_put_mix(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int connect = !!ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (tse850->add_cache == connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * Hmmm, this gpiod_set_value_cansleep call should probably happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * inside snd_soc_dapm_mixer_update_power in the loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) gpiod_set_value_cansleep(tse850->add, connect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) tse850->add_cache = connect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) snd_soc_dapm_mixer_update_power(dapm, kctrl, connect, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int tse850_get_ana(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = regulator_get_voltage(tse850->ana);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * Map regulator output values like so:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * -11.5V to "Low" (enum 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * 11.5V-12.5V to "12V" (enum 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * 12.5V-13.5V to "13V" (enum 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * 18.5V-19.5V to "19V" (enum 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * 19.5V- to "20V" (enum 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (ret < 11000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ret = 11000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) else if (ret > 20000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = 20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ret -= 11000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret = (ret + 500000) / 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ucontrol->value.enumerated.item[0] = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int tse850_put_ana(struct snd_kcontrol *kctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned int uV = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (uV >= e->items)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * Map enum zero (Low) to 2 volts on the regulator, do this since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * the ana regulator is supplied by the system 12V voltage and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * requesting anything below the system voltage causes the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * voltage to be passed through the regulator. Also, the ana
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * regulator induces noise when requesting voltages near the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * system voltage. So, by mapping Low to 2V, that noise is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * eliminated when all that is needed is 12V (the system voltage).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (uV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) uV = 11000000 + (1000000 * uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) uV = 2000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret = regulator_set_voltage(tse850->ana, uV, uV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static const char * const mux_text[] = { "Mixer", "Loop" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static const struct soc_enum mux_enum =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(mux_text), mux_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static const struct snd_kcontrol_new mux1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) SOC_DAPM_ENUM_EXT("MUX1", mux_enum, tse850_get_mux1, tse850_put_mux1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static const struct snd_kcontrol_new mux2 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) SOC_DAPM_ENUM_EXT("MUX2", mux_enum, tse850_get_mux2, tse850_put_mux2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) #define TSE850_DAPM_SINGLE_EXT(xname, reg, shift, max, invert, xget, xput) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .info = snd_soc_info_volsw, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .get = xget, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .put = xput, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static const struct snd_kcontrol_new mix[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) TSE850_DAPM_SINGLE_EXT("IN Switch", SND_SOC_NOPM, 0, 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) tse850_get_mix, tse850_put_mix),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static const char * const ana_text[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) "Low", "12V", "13V", "14V", "15V", "16V", "17V", "18V", "19V", "20V"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static const struct soc_enum ana_enum =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(ana_text), ana_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static const struct snd_kcontrol_new out =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) SOC_DAPM_ENUM_EXT("ANA", ana_enum, tse850_get_ana, tse850_put_ana);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static const struct snd_soc_dapm_widget tse850_dapm_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) SND_SOC_DAPM_LINE("OUT1", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) SND_SOC_DAPM_LINE("OUT2", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) SND_SOC_DAPM_LINE("IN1", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) SND_SOC_DAPM_LINE("IN2", NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) SND_SOC_DAPM_INPUT("DAC"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) SOC_MIXER_ARRAY("MIX", SND_SOC_NOPM, 0, 0, mix),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) SND_SOC_DAPM_MUX("MUX1", SND_SOC_NOPM, 0, 0, &mux1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) SND_SOC_DAPM_MUX("MUX2", SND_SOC_NOPM, 0, 0, &mux2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) SND_SOC_DAPM_OUT_DRV("OUT", SND_SOC_NOPM, 0, 0, &out, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * These connections are not entirely correct, since both IN1 and IN2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * are always fed to MIX (if the "IN switch" is set so), i.e. without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * regard to the loop1 and loop2 relays that according to this only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * control MUX1 and MUX2 but in fact also control how the input signals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * are routed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * But, 1) I don't know how to do it right, and 2) it doesn't seem to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * matter in practice since nothing is powered in those sections anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static const struct snd_soc_dapm_route tse850_intercon[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) { "OUT1", NULL, "MUX1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) { "OUT2", NULL, "MUX2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { "MUX1", "Loop", "IN1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { "MUX1", "Mixer", "OUT" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) { "MUX2", "Loop", "IN2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) { "MUX2", "Mixer", "OUT" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { "OUT", NULL, "MIX" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { "MIX", NULL, "DAC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { "MIX", "IN Switch", "IN1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { "MIX", "IN Switch", "IN2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* connect board input to the codec left channel output pin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) { "DAC", NULL, "OUTL" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) SND_SOC_DAILINK_DEFS(pcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) DAILINK_COMP_ARRAY(COMP_EMPTY()),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi")),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) DAILINK_COMP_ARRAY(COMP_EMPTY()));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static struct snd_soc_dai_link tse850_dailink = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .name = "TSE-850",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .stream_name = "TSE-850-PCM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .dai_fmt = SND_SOC_DAIFMT_I2S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) | SND_SOC_DAIFMT_NB_NF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) | SND_SOC_DAIFMT_CBM_CFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) SND_SOC_DAILINK_REG(pcm),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static struct snd_soc_card tse850_card = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .name = "TSE-850-ASoC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .dai_link = &tse850_dailink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) .num_links = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .dapm_widgets = tse850_dapm_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .num_dapm_widgets = ARRAY_SIZE(tse850_dapm_widgets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .dapm_routes = tse850_intercon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .num_dapm_routes = ARRAY_SIZE(tse850_intercon),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .fully_routed = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static int tse850_dt_init(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct device_node *codec_np, *cpu_np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct snd_soc_dai_link *dailink = &tse850_dailink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) dev_err(&pdev->dev, "only device tree supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) cpu_np = of_parse_phandle(np, "axentia,cpu-dai", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!cpu_np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) dev_err(&pdev->dev, "failed to get cpu dai\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) dailink->cpus->of_node = cpu_np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) dailink->platforms->of_node = cpu_np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) of_node_put(cpu_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) codec_np = of_parse_phandle(np, "axentia,audio-codec", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!codec_np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dev_err(&pdev->dev, "failed to get codec info\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dailink->codecs->of_node = codec_np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) of_node_put(codec_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int tse850_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct snd_soc_card *card = &tse850_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct device *dev = card->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct tse850_priv *tse850;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) tse850 = devm_kzalloc(dev, sizeof(*tse850), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!tse850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) snd_soc_card_set_drvdata(card, tse850);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ret = tse850_dt_init(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dev_err(dev, "failed to init dt info\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) tse850->add = devm_gpiod_get(dev, "axentia,add", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (IS_ERR(tse850->add)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (PTR_ERR(tse850->add) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) dev_err(dev, "failed to get 'add' gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return PTR_ERR(tse850->add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) tse850->add_cache = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) tse850->loop1 = devm_gpiod_get(dev, "axentia,loop1", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (IS_ERR(tse850->loop1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (PTR_ERR(tse850->loop1) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) dev_err(dev, "failed to get 'loop1' gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return PTR_ERR(tse850->loop1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) tse850->loop1_cache = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) tse850->loop2 = devm_gpiod_get(dev, "axentia,loop2", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (IS_ERR(tse850->loop2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (PTR_ERR(tse850->loop2) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) dev_err(dev, "failed to get 'loop2' gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return PTR_ERR(tse850->loop2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) tse850->loop2_cache = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tse850->ana = devm_regulator_get(dev, "axentia,ana");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (IS_ERR(tse850->ana)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (PTR_ERR(tse850->ana) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) dev_err(dev, "failed to get 'ana' regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return PTR_ERR(tse850->ana);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ret = regulator_enable(tse850->ana);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) dev_err(dev, "failed to enable the 'ana' regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ret = snd_soc_register_card(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) dev_err(dev, "snd_soc_register_card failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) goto err_disable_ana;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) err_disable_ana:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) regulator_disable(tse850->ana);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int tse850_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct snd_soc_card *card = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) snd_soc_unregister_card(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) regulator_disable(tse850->ana);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static const struct of_device_id tse850_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) { .compatible = "axentia,tse850-pcm5142", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) MODULE_DEVICE_TABLE(of, tse850_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static struct platform_driver tse850_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .name = "axentia-tse850-pcm5142",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .of_match_table = of_match_ptr(tse850_dt_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .probe = tse850_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .remove = tse850_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) module_platform_driver(tse850_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* Module information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) MODULE_DESCRIPTION("ALSA SoC driver for TSE-850 with PCM5142 codec");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) MODULE_LICENSE("GPL v2");