diff options
Diffstat (limited to 'sound/soc/sunxi')
| -rw-r--r-- | sound/soc/sunxi/Kconfig | 2 | ||||
| -rw-r--r-- | sound/soc/sunxi/sun4i-codec.c | 469 | ||||
| -rw-r--r-- | sound/soc/sunxi/sun4i-spdif.c | 75 | ||||
| -rw-r--r-- | sound/soc/sunxi/sun50i-codec-analog.c | 2 | ||||
| -rw-r--r-- | sound/soc/sunxi/sun50i-dmic.c | 9 | ||||
| -rw-r--r-- | sound/soc/sunxi/sun8i-codec-analog.c | 14 | ||||
| -rw-r--r-- | sound/soc/sunxi/sun8i-codec.c | 23 |
7 files changed, 510 insertions, 84 deletions
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index 1f18f016acbb..205f422d9ded 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -menu "Allwinner SoC Audio support" +menu "Allwinner" depends on ARCH_SUNXI || COMPILE_TEST config SND_SUN4I_CODEC diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 933a0913237c..f4e22af594fa 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -5,6 +5,7 @@ * Copyright 2015 Maxime Ripard <maxime.ripard@free-electrons.com> * Copyright 2015 Adam Sampson <ats@offog.org> * Copyright 2016 Chen-Yu Tsai <wens@csie.org> + * Copyright 2018 Mesih Kilinc <mesihkilinc@gmail.com> * * Based on the Allwinner SDK driver, released under the GPL. */ @@ -21,6 +22,7 @@ #include <linux/gpio/consumer.h> #include <sound/core.h> +#include <sound/jack.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> @@ -265,6 +267,64 @@ /* TODO H3 DAP (Digital Audio Processing) bits */ +#define SUN4I_DMA_MAX_BURST (8) + +/* suniv specific registers */ + +#define SUNIV_DMA_MAX_BURST (4) + +/* Codec DAC digital controls and FIFO registers */ +#define SUNIV_CODEC_ADC_FIFOC (0x10) +#define SUNIV_CODEC_ADC_FIFOC_EN_AD (28) +#define SUNIV_CODEC_ADC_FIFOS (0x14) +#define SUNIV_CODEC_ADC_RXDATA (0x18) + +/* Output mixer and gain controls */ +#define SUNIV_CODEC_OM_DACA_CTRL (0x20) +#define SUNIV_CODEC_OM_DACA_CTRL_DACAREN (31) +#define SUNIV_CODEC_OM_DACA_CTRL_DACALEN (30) +#define SUNIV_CODEC_OM_DACA_CTRL_RMIXEN (29) +#define SUNIV_CODEC_OM_DACA_CTRL_LMIXEN (28) +#define SUNIV_CODEC_OM_DACA_CTRL_RHPPAMUTE (27) +#define SUNIV_CODEC_OM_DACA_CTRL_LHPPAMUTE (26) +#define SUNIV_CODEC_OM_DACA_CTRL_RHPIS (25) +#define SUNIV_CODEC_OM_DACA_CTRL_LHPIS (24) +#define SUNIV_CODEC_OM_DACA_CTRL_HPCOM_CTL (22) +#define SUNIV_CODEC_OM_DACA_CTRL_COMPTEN (21) +#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_MICIN (20) +#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LINEIN (19) +#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_FMIN (18) +#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_RDAC (17) +#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LDAC (16) +#define SUNIV_CODEC_OM_DACA_CTRL_HPPAEN (15) +#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_MICIN (12) +#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LINEIN (11) +#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_FMIN (10) +#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LDAC (9) +#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_RDAC (8) +#define SUNIV_CODEC_OM_DACA_CTRL_LTLNMUTE (7) +#define SUNIV_CODEC_OM_DACA_CTRL_RTLNMUTE (6) +#define SUNIV_CODEC_OM_DACA_CTRL_HPVOL (0) + +/* Analog Input Mixer controls */ +#define SUNIV_CODEC_ADC_ACTL (0x24) +#define SUNIV_CODEC_ADC_ADCEN (31) +#define SUNIV_CODEC_ADC_MICG (24) +#define SUNIV_CODEC_ADC_LINEINVOL (21) +#define SUNIV_CODEC_ADC_ADCG (16) +#define SUNIV_CODEC_ADC_ADCMIX_MIC (13) +#define SUNIV_CODEC_ADC_ADCMIX_FMINL (12) +#define SUNIV_CODEC_ADC_ADCMIX_FMINR (11) +#define SUNIV_CODEC_ADC_ADCMIX_LINEIN (10) +#define SUNIV_CODEC_ADC_ADCMIX_LOUT (9) +#define SUNIV_CODEC_ADC_ADCMIX_ROUT (8) +#define SUNIV_CODEC_ADC_PASPEEDSELECT (7) +#define SUNIV_CODEC_ADC_FMINVOL (4) +#define SUNIV_CODEC_ADC_MICAMPEN (3) +#define SUNIV_CODEC_ADC_MICBOOST (0) + +#define SUNIV_CODEC_ADC_DBG (0x4c) + struct sun4i_codec { struct device *dev; struct regmap *regmap; @@ -272,6 +332,7 @@ struct sun4i_codec { struct clk *clk_module; struct reset_control *rst; struct gpio_desc *gpio_pa; + struct gpio_desc *gpio_hp; /* ADC_FIFOC register is at different offset on different SoCs */ struct regmap_field *reg_adc_fifoc; @@ -1255,6 +1316,228 @@ static const struct snd_soc_component_driver sun8i_a23_codec_codec = { .endianness = 1, }; +/*suniv F1C100s codec */ + +/* headphone controls */ +static const char * const suniv_codec_hp_src_enum_text[] = { + "DAC", "Mixer", +}; + +static SOC_ENUM_DOUBLE_DECL(suniv_codec_hp_src_enum, + SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LHPIS, + SUNIV_CODEC_OM_DACA_CTRL_RHPIS, + suniv_codec_hp_src_enum_text); + +static const struct snd_kcontrol_new suniv_codec_hp_src[] = { + SOC_DAPM_ENUM("Headphone Source Playback Route", + suniv_codec_hp_src_enum), +}; + +/* mixer controls */ +static const struct snd_kcontrol_new suniv_codec_adc_mixer_controls[] = { + SOC_DAPM_SINGLE("Right Out Capture Switch", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_ADCMIX_ROUT, 1, 0), + SOC_DAPM_SINGLE("Left Out Capture Switch", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_ADCMIX_LOUT, 1, 0), + SOC_DAPM_SINGLE("Line In Capture Switch", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_ADCMIX_LINEIN, 1, 0), + SOC_DAPM_SINGLE("Right FM In Capture Switch", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_ADCMIX_FMINR, 1, 0), + SOC_DAPM_SINGLE("Left FM In Capture Switch", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_ADCMIX_FMINL, 1, 0), + SOC_DAPM_SINGLE("Mic Capture Switch", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_ADCMIX_MIC, 1, 0), +}; + +static const struct snd_kcontrol_new suniv_codec_dac_lmixer_controls[] = { + SOC_DAPM_SINGLE("Right DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_RDAC, 1, 0), + SOC_DAPM_SINGLE("Left DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LDAC, 1, 0), + SOC_DAPM_SINGLE("FM In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_FMIN, 1, 0), + SOC_DAPM_SINGLE("Line In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LINEIN, 1, 0), + SOC_DAPM_SINGLE("Mic In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_MICIN, 1, 0), +}; + +static const struct snd_kcontrol_new suniv_codec_dac_rmixer_controls[] = { + SOC_DAPM_SINGLE("Left DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LDAC, 1, 0), + SOC_DAPM_SINGLE("Right DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_RDAC, 1, 0), + SOC_DAPM_SINGLE("FM In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_FMIN, 1, 0), + SOC_DAPM_SINGLE("Line In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LINEIN, 1, 0), + SOC_DAPM_SINGLE("Mic In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_MICIN, 1, 0), +}; + +static const DECLARE_TLV_DB_SCALE(suniv_codec_dvol_scale, -7308, 116, 0); +static const DECLARE_TLV_DB_SCALE(suniv_codec_hp_vol_scale, -6300, 100, 1); +static const DECLARE_TLV_DB_SCALE(suniv_codec_out_mixer_pregain_scale, + -450, 150, 0); + +static const DECLARE_TLV_DB_RANGE(suniv_codec_mic_gain_scale, + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0), +); + +static const struct snd_kcontrol_new suniv_codec_codec_widgets[] = { + SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC, + SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1, + suniv_codec_dvol_scale), + SOC_SINGLE_TLV("Headphone Playback Volume", + SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_HPVOL, 0x3f, 0, + suniv_codec_hp_vol_scale), + SOC_DOUBLE("Headphone Playback Switch", + SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LHPPAMUTE, + SUNIV_CODEC_OM_DACA_CTRL_RHPPAMUTE, 1, 0), + SOC_SINGLE_TLV("Line In Playback Volume", + SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_LINEINVOL, + 0x7, 0, suniv_codec_out_mixer_pregain_scale), + SOC_SINGLE_TLV("FM In Playback Volume", + SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_FMINVOL, + 0x7, 0, suniv_codec_out_mixer_pregain_scale), + SOC_SINGLE_TLV("Mic In Playback Volume", + SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_MICG, + 0x7, 0, suniv_codec_out_mixer_pregain_scale), + + /* Microphone Amp boost gains */ + SOC_SINGLE_TLV("Mic Boost Volume", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_MICBOOST, 0x7, 0, + suniv_codec_mic_gain_scale), + SOC_SINGLE_TLV("ADC Capture Volume", + SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_ADCG, + 0x7, 0, suniv_codec_out_mixer_pregain_scale), +}; + +static const struct snd_soc_dapm_widget suniv_codec_codec_dapm_widgets[] = { + /* Microphone inputs */ + SND_SOC_DAPM_INPUT("MIC"), + + /* Microphone Bias */ + /* deleted: HBIAS, MBIAS */ + + /* Mic input path */ + SND_SOC_DAPM_PGA("Mic Amplifier", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_MICAMPEN, 0, NULL, 0), + + /* Line In */ + SND_SOC_DAPM_INPUT("LINEIN"), + + /* FM In */ + SND_SOC_DAPM_INPUT("FMINR"), + SND_SOC_DAPM_INPUT("FMINL"), + + /* Digital parts of the ADCs */ + SND_SOC_DAPM_SUPPLY("ADC Enable", SUNIV_CODEC_ADC_FIFOC, + SUNIV_CODEC_ADC_FIFOC_EN_AD, 0, + NULL, 0), + + /* Analog parts of the ADCs */ + SND_SOC_DAPM_ADC("ADC", "Codec Capture", SUNIV_CODEC_ADC_ACTL, + SUNIV_CODEC_ADC_ADCEN, 0), + + /* ADC Mixers */ + SOC_MIXER_ARRAY("ADC Mixer", SUNIV_CODEC_ADC_ACTL, + SND_SOC_NOPM, 0, + suniv_codec_adc_mixer_controls), + + /* Digital parts of the DACs */ + SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC, + SUN4I_CODEC_DAC_DPC_EN_DA, 0, + NULL, 0), + + /* Analog parts of the DACs */ + SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", + SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_DACALEN, 0), + SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", + SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_DACAREN, 0), + + /* Mixers */ + SOC_MIXER_ARRAY("Left Mixer", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_LMIXEN, 0, + suniv_codec_dac_lmixer_controls), + SOC_MIXER_ARRAY("Right Mixer", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_RMIXEN, 0, + suniv_codec_dac_rmixer_controls), + + /* Headphone output path */ + SND_SOC_DAPM_MUX("Headphone Source Playback Route", + SND_SOC_NOPM, 0, 0, suniv_codec_hp_src), + SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_HPPAEN, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_COMPTEN, 0, NULL, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUNIV_CODEC_OM_DACA_CTRL, + SUNIV_CODEC_OM_DACA_CTRL_HPCOM_CTL, 0x3, 0x3, 0), + SND_SOC_DAPM_OUTPUT("HP"), +}; + +static const struct snd_soc_dapm_route suniv_codec_codec_dapm_routes[] = { + /* DAC Routes */ + { "Left DAC", NULL, "DAC Enable" }, + { "Right DAC", NULL, "DAC Enable" }, + + /* Microphone Routes */ + { "Mic Amplifier", NULL, "MIC"}, + + /* Left Mixer Routes */ + { "Left Mixer", "Right DAC Playback Switch", "Right DAC" }, + { "Left Mixer", "Left DAC Playback Switch", "Left DAC" }, + { "Left Mixer", "FM In Playback Switch", "FMINL" }, + { "Left Mixer", "Line In Playback Switch", "LINEIN" }, + { "Left Mixer", "Mic In Playback Switch", "Mic Amplifier" }, + + /* Right Mixer Routes */ + { "Right Mixer", "Left DAC Playback Switch", "Left DAC" }, + { "Right Mixer", "Right DAC Playback Switch", "Right DAC" }, + { "Right Mixer", "FM In Playback Switch", "FMINR" }, + { "Right Mixer", "Line In Playback Switch", "LINEIN" }, + { "Right Mixer", "Mic In Playback Switch", "Mic Amplifier" }, + + /* ADC Mixer Routes */ + { "ADC Mixer", "Right Out Capture Switch", "Right Mixer" }, + { "ADC Mixer", "Left Out Capture Switch", "Left Mixer" }, + { "ADC Mixer", "Line In Capture Switch", "LINEIN" }, + { "ADC Mixer", "Right FM In Capture Switch", "FMINR" }, + { "ADC Mixer", "Left FM In Capture Switch", "FMINL" }, + { "ADC Mixer", "Mic Capture Switch", "Mic Amplifier" }, + + /* Headphone Routes */ + { "Headphone Source Playback Route", "DAC", "Left DAC" }, + { "Headphone Source Playback Route", "DAC", "Right DAC" }, + { "Headphone Source Playback Route", "Mixer", "Left Mixer" }, + { "Headphone Source Playback Route", "Mixer", "Right Mixer" }, + { "Headphone Amp", NULL, "Headphone Source Playback Route" }, + { "HP", NULL, "Headphone Amp" }, + { "HPCOM", NULL, "HPCOM Protection" }, + + /* ADC Routes */ + { "ADC", NULL, "ADC Mixer" }, + { "ADC", NULL, "ADC Enable" }, +}; + +static const struct snd_soc_component_driver suniv_codec_codec = { + .controls = suniv_codec_codec_widgets, + .num_controls = ARRAY_SIZE(suniv_codec_codec_widgets), + .dapm_widgets = suniv_codec_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(suniv_codec_codec_dapm_widgets), + .dapm_routes = suniv_codec_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(suniv_codec_codec_dapm_routes), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + static const struct snd_soc_component_driver sun4i_codec_component = { .name = "sun4i-codec", .legacy_dai_naming = 1, @@ -1302,6 +1585,49 @@ static struct snd_soc_dai_driver dummy_cpu_dai = { .ops = &dummy_dai_ops, }; +static struct snd_soc_jack sun4i_headphone_jack; + +static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = { + { .pin = "Headphone", .mask = SND_JACK_HEADPHONE }, +}; + +static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = { + .name = "hp-det", + .report = SND_JACK_HEADPHONE, + .debounce_time = 150, +}; + +static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); + int ret; + + if (scodec->gpio_hp) { + ret = snd_soc_card_jack_new_pins(card, "Headphone Jack", + SND_JACK_HEADPHONE, + &sun4i_headphone_jack, + sun4i_headphone_jack_pins, + ARRAY_SIZE(sun4i_headphone_jack_pins)); + if (ret) { + dev_err(rtd->dev, + "Headphone jack creation failed: %d\n", ret); + return ret; + } + + sun4i_headphone_jack_gpio.desc = scodec->gpio_hp; + ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1, + &sun4i_headphone_jack_gpio); + + if (ret) { + dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret); + return ret; + } + } + + return 0; +} + static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, int *num_links) { @@ -1327,6 +1653,7 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, link->codecs->name = dev_name(dev); link->platforms->name = dev_name(dev); link->dai_fmt = SND_SOC_DAIFMT_I2S; + link->init = sun4i_codec_machine_init; *num_links = 1; @@ -1336,7 +1663,8 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card); + struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm); + struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); gpiod_set_value_cansleep(scodec->gpio_pa, !!SND_SOC_DAPM_EVENT_ON(event)); @@ -1635,10 +1963,11 @@ static const struct snd_soc_component_driver sun50i_h616_codec_codec = { }; static const struct snd_kcontrol_new sun50i_h616_card_controls[] = { - SOC_DAPM_PIN_SWITCH("LINEOUT"), + SOC_DAPM_PIN_SWITCH("Speaker"), }; static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event), }; @@ -1685,6 +2014,7 @@ static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev) card->dev = dev; card->owner = THIS_MODULE; card->name = "H616 Audio Codec"; + card->long_name = "h616-audio-codec"; card->driver_name = "sun4i-codec"; card->controls = sun50i_h616_card_controls; card->num_controls = ARRAY_SIZE(sun50i_h616_card_controls); @@ -1701,6 +2031,56 @@ static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev) return card; }; +static const struct snd_soc_dapm_widget suniv_codec_card_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_LINE("Line In", NULL), + SND_SOC_DAPM_LINE("Right FM In", NULL), + SND_SOC_DAPM_LINE("Left FM In", NULL), + SND_SOC_DAPM_MIC("Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event), +}; + +/* Connect digital side enables to analog side widgets */ +static const struct snd_soc_dapm_route suniv_codec_card_routes[] = { + /* ADC Routes */ + { "ADC", NULL, "ADC Enable" }, + { "Codec Capture", NULL, "ADC" }, + + /* DAC Routes */ + { "Left DAC", NULL, "DAC Enable" }, + { "Right DAC", NULL, "DAC Enable" }, + { "Left DAC", NULL, "Codec Playback" }, + { "Right DAC", NULL, "Codec Playback" }, +}; + +static struct snd_soc_card *suniv_codec_create_card(struct device *dev) +{ + struct snd_soc_card *card; + int ret; + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return ERR_PTR(-ENOMEM); + + card->dai_link = sun4i_codec_create_link(dev, &card->num_links); + if (!card->dai_link) + return ERR_PTR(-ENOMEM); + + card->dev = dev; + card->name = "F1C100s Audio Codec"; + card->dapm_widgets = suniv_codec_card_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(suniv_codec_card_dapm_widgets); + card->dapm_routes = suniv_codec_card_routes; + card->num_dapm_routes = ARRAY_SIZE(suniv_codec_card_routes); + card->fully_routed = true; + + ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing"); + if (ret) + dev_warn(dev, "failed to parse audio-routing: %d\n", ret); + + return card; +}; + static const struct regmap_config sun4i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -1751,6 +2131,13 @@ static const struct regmap_config sun50i_h616_codec_regmap_config = { .cache_type = REGCACHE_NONE, }; +static const struct regmap_config suniv_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = SUNIV_CODEC_ADC_DBG, +}; + struct sun4i_codec_quirks { const struct regmap_config *regmap_config; const struct snd_soc_component_driver *codec; @@ -1761,6 +2148,7 @@ struct sun4i_codec_quirks { unsigned int reg_adc_rxdata; /* RX FIFO offset for DMA config */ bool has_reset; bool playback_only; + u32 dma_max_burst; }; static const struct sun4i_codec_quirks sun4i_codec_quirks = { @@ -1771,6 +2159,7 @@ static const struct sun4i_codec_quirks sun4i_codec_quirks = { .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA, + .dma_max_burst = SUN4I_DMA_MAX_BURST, }; static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = { @@ -1782,6 +2171,7 @@ static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = { .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, + .dma_max_burst = SUN4I_DMA_MAX_BURST, }; static const struct sun4i_codec_quirks sun7i_codec_quirks = { @@ -1792,6 +2182,7 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = { .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA, + .dma_max_burst = SUN4I_DMA_MAX_BURST, }; static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = { @@ -1803,6 +2194,7 @@ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = { .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, + .dma_max_burst = SUN4I_DMA_MAX_BURST, }; static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = { @@ -1819,6 +2211,7 @@ static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = { .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, + .dma_max_burst = SUN4I_DMA_MAX_BURST, }; static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = { @@ -1834,6 +2227,7 @@ static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = { .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, .has_reset = true, + .dma_max_burst = SUN4I_DMA_MAX_BURST, }; static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = { @@ -1843,6 +2237,19 @@ static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = { .reg_dac_fifoc = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, .has_reset = true, + .dma_max_burst = SUN4I_DMA_MAX_BURST, +}; + +static const struct sun4i_codec_quirks suniv_f1c100s_codec_quirks = { + .regmap_config = &suniv_codec_regmap_config, + .codec = &suniv_codec_codec, + .create_card = suniv_codec_create_card, + .reg_adc_fifoc = REG_FIELD(SUNIV_CODEC_ADC_FIFOC, 0, 31), + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31), + .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA, + .reg_adc_rxdata = SUNIV_CODEC_ADC_RXDATA, + .has_reset = true, + .dma_max_burst = SUNIV_DMA_MAX_BURST, }; static const struct of_device_id sun4i_codec_of_match[] = { @@ -1874,6 +2281,10 @@ static const struct of_device_id sun4i_codec_of_match[] = { .compatible = "allwinner,sun50i-h616-codec", .data = &sun50i_h616_codec_quirks, }, + { + .compatible = "allwinner,suniv-f1c100s-codec", + .data = &suniv_f1c100s_codec_quirks, + }, {} }; MODULE_DEVICE_TABLE(of, sun4i_codec_of_match); @@ -1911,7 +2322,7 @@ static int sun4i_codec_probe(struct platform_device *pdev) } /* Get the clocks from the DT */ - scodec->clk_apb = devm_clk_get(&pdev->dev, "apb"); + scodec->clk_apb = devm_clk_get_enabled(&pdev->dev, "apb"); if (IS_ERR(scodec->clk_apb)) { dev_err(&pdev->dev, "Failed to get the APB clock\n"); return PTR_ERR(scodec->clk_apb); @@ -1924,8 +2335,7 @@ static int sun4i_codec_probe(struct platform_device *pdev) } if (quirks->has_reset) { - scodec->rst = devm_reset_control_get_exclusive(&pdev->dev, - NULL); + scodec->rst = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL); if (IS_ERR(scodec->rst)) { dev_err(&pdev->dev, "Failed to get reset control\n"); return PTR_ERR(scodec->rst); @@ -1940,6 +2350,13 @@ static int sun4i_codec_probe(struct platform_device *pdev) return ret; } + scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN); + if (IS_ERR(scodec->gpio_hp)) { + ret = PTR_ERR(scodec->gpio_hp); + dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n"); + return ret; + } + /* reg_field setup */ scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev, scodec->regmap, @@ -1961,32 +2378,16 @@ static int sun4i_codec_probe(struct platform_device *pdev) return ret; } - /* Enable the bus clock */ - if (clk_prepare_enable(scodec->clk_apb)) { - dev_err(&pdev->dev, "Failed to enable the APB clock\n"); - return -EINVAL; - } - - /* Deassert the reset control */ - if (scodec->rst) { - ret = reset_control_deassert(scodec->rst); - if (ret) { - dev_err(&pdev->dev, - "Failed to deassert the reset control\n"); - goto err_clk_disable; - } - } - /* DMA configuration for TX FIFO */ scodec->playback_dma_data.addr = res->start + quirks->reg_dac_txdata; - scodec->playback_dma_data.maxburst = 8; + scodec->playback_dma_data.maxburst = quirks->dma_max_burst; scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; if (!quirks->playback_only) { /* DMA configuration for RX FIFO */ scodec->capture_dma_data.addr = res->start + quirks->reg_adc_rxdata; - scodec->capture_dma_data.maxburst = 8; + scodec->capture_dma_data.maxburst = quirks->dma_max_burst; scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; } @@ -1994,7 +2395,7 @@ static int sun4i_codec_probe(struct platform_device *pdev) &sun4i_codec_dai, 1); if (ret) { dev_err(&pdev->dev, "Failed to register our codec\n"); - goto err_assert_reset; + return ret; } ret = devm_snd_soc_register_component(&pdev->dev, @@ -2002,20 +2403,20 @@ static int sun4i_codec_probe(struct platform_device *pdev) &dummy_cpu_dai, 1); if (ret) { dev_err(&pdev->dev, "Failed to register our DAI\n"); - goto err_assert_reset; + return ret; } ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); if (ret) { dev_err(&pdev->dev, "Failed to register against DMAEngine\n"); - goto err_assert_reset; + return ret; } card = quirks->create_card(&pdev->dev); if (IS_ERR(card)) { ret = PTR_ERR(card); dev_err(&pdev->dev, "Failed to create our card\n"); - goto err_assert_reset; + return ret; } snd_soc_card_set_drvdata(card, scodec); @@ -2023,28 +2424,17 @@ static int sun4i_codec_probe(struct platform_device *pdev) ret = snd_soc_register_card(card); if (ret) { dev_err_probe(&pdev->dev, ret, "Failed to register our card\n"); - goto err_assert_reset; + return ret; } return 0; - -err_assert_reset: - if (scodec->rst) - reset_control_assert(scodec->rst); -err_clk_disable: - clk_disable_unprepare(scodec->clk_apb); - return ret; } static void sun4i_codec_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); snd_soc_unregister_card(card); - if (scodec->rst) - reset_control_assert(scodec->rst); - clk_disable_unprepare(scodec->clk_apb); } static struct platform_driver sun4i_codec_driver = { @@ -2063,4 +2453,5 @@ MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); MODULE_AUTHOR("Ryan Walklin <ryan@testtoast.com"); +MODULE_AUTHOR("Mesih Kilinc <mesikilinc@gmail.com>"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 0aa416423246..c2ec19437cd7 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -171,11 +171,15 @@ * @reg_dac_txdata: TX FIFO offset for DMA config. * @has_reset: SoC needs reset deasserted. * @val_fctl_ftx: TX FIFO flush bitmask. + * @mclk_multiplier: ratio of internal MCLK divider + * @tx_clk_name: name of TX module clock if split clock design */ struct sun4i_spdif_quirks { unsigned int reg_dac_txdata; bool has_reset; unsigned int val_fctl_ftx; + unsigned int mclk_multiplier; + const char *tx_clk_name; }; struct sun4i_spdif_dev { @@ -201,6 +205,10 @@ static void sun4i_spdif_configure(struct sun4i_spdif_dev *host) regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, quirks->val_fctl_ftx, quirks->val_fctl_ftx); + /* Valid data at the MSB of TXFIFO Register */ + regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, + SUN4I_SPDIF_FCTL_TXIM, 0); + /* clear TX counter */ regmap_write(host->regmap, SUN4I_SPDIF_TXCNT, 0); } @@ -282,14 +290,17 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: fmt |= SUN4I_SPDIF_TXCFG_FMT16BIT; + host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case SNDRV_PCM_FORMAT_S20_3LE: fmt |= SUN4I_SPDIF_TXCFG_FMT20BIT; break; case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S32_LE: fmt |= SUN4I_SPDIF_TXCFG_FMT24BIT; break; default: @@ -313,6 +324,7 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream, default: return -EINVAL; } + mclk *= host->quirks->mclk_multiplier; ret = clk_set_rate(host->spdif_clk, mclk); if (ret < 0) { @@ -321,9 +333,6 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream, return ret; } - regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, - SUN4I_SPDIF_FCTL_TXIM, SUN4I_SPDIF_FCTL_TXIM); - switch (rate) { case 22050: case 24000: @@ -347,6 +356,7 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream, default: return -EINVAL; } + mclk_div *= host->quirks->mclk_multiplier; reg_val = 0; reg_val |= SUN4I_SPDIF_TXCFG_ASS; @@ -522,9 +532,10 @@ static const struct regmap_config sun4i_spdif_regmap_config = { #define SUN4I_RATES SNDRV_PCM_RATE_8000_192000 -#define SUN4I_FORMATS (SNDRV_PCM_FORMAT_S16_LE | \ - SNDRV_PCM_FORMAT_S20_3LE | \ - SNDRV_PCM_FORMAT_S24_LE) +#define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) static struct snd_soc_dai_driver sun4i_spdif_dai = { .playback = { @@ -540,24 +551,36 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = { static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = { .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, + .mclk_multiplier = 1, }; static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = { .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, + .mclk_multiplier = 1, }; static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = { .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, + .mclk_multiplier = 4, }; static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = { .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX, .has_reset = true, + .mclk_multiplier = 1, +}; + +static const struct sun4i_spdif_quirks sun55i_a523_spdif_quirks = { + .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX, + .has_reset = true, + .mclk_multiplier = 1, + .tx_clk_name = "tx", }; static const struct of_device_id sun4i_spdif_of_match[] = { @@ -582,6 +605,15 @@ static const struct of_device_id sun4i_spdif_of_match[] = { /* Essentially the same as the H6, but without RX */ .data = &sun50i_h6_spdif_quirks, }, + { + .compatible = "allwinner,sun55i-a523-spdif", + /* + * Almost the same as H6, but has split the TX and RX clocks, + * has a separate reset bit for the RX side, and has some + * expanded features for the RX side. + */ + .data = &sun55i_a523_spdif_quirks, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); @@ -623,6 +655,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev) const struct sun4i_spdif_quirks *quirks; int ret; void __iomem *base; + const char *tx_clk_name = "spdif"; dev_dbg(&pdev->dev, "Entered %s\n", __func__); @@ -651,6 +684,10 @@ static int sun4i_spdif_probe(struct platform_device *pdev) host->regmap = devm_regmap_init_mmio(&pdev->dev, base, &sun4i_spdif_regmap_config); + if (IS_ERR(host->regmap)) { + dev_err(&pdev->dev, "failed to initialise regmap.\n"); + return PTR_ERR(host->regmap); + } /* Clocks */ host->apb_clk = devm_clk_get(&pdev->dev, "apb"); @@ -659,9 +696,12 @@ static int sun4i_spdif_probe(struct platform_device *pdev) return PTR_ERR(host->apb_clk); } - host->spdif_clk = devm_clk_get(&pdev->dev, "spdif"); + if (quirks->tx_clk_name) + tx_clk_name = quirks->tx_clk_name; + host->spdif_clk = devm_clk_get(&pdev->dev, tx_clk_name); if (IS_ERR(host->spdif_clk)) { - dev_err(&pdev->dev, "failed to get a spdif clock.\n"); + dev_err(&pdev->dev, "failed to get the \"%s\" clock.\n", + tx_clk_name); return PTR_ERR(host->spdif_clk); } @@ -672,15 +712,10 @@ static int sun4i_spdif_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); if (quirks->has_reset) { - host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, - NULL); - if (PTR_ERR(host->rst) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; - dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); - return ret; - } - if (!IS_ERR(host->rst)) - reset_control_deassert(host->rst); + host->rst = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL); + if (IS_ERR(host->rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(host->rst), + "Failed to get reset\n"); } ret = devm_snd_soc_register_component(&pdev->dev, @@ -715,15 +750,15 @@ static void sun4i_spdif_remove(struct platform_device *pdev) } static const struct dev_pm_ops sun4i_spdif_pm = { - SET_RUNTIME_PM_OPS(sun4i_spdif_runtime_suspend, - sun4i_spdif_runtime_resume, NULL) + RUNTIME_PM_OPS(sun4i_spdif_runtime_suspend, + sun4i_spdif_runtime_resume, NULL) }; static struct platform_driver sun4i_spdif_driver = { .driver = { .name = "sun4i-spdif", .of_match_table = sun4i_spdif_of_match, - .pm = &sun4i_spdif_pm, + .pm = pm_ptr(&sun4i_spdif_pm), }, .probe = sun4i_spdif_probe, .remove = sun4i_spdif_remove, diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index 2dcdf113b66e..a19f8aaaf1c4 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -495,7 +495,7 @@ static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { static int sun50i_a64_codec_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); int hbias; switch (level) { diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c index 3e751b5694fe..eddfebe16616 100644 --- a/sound/soc/sunxi/sun50i-dmic.c +++ b/sound/soc/sunxi/sun50i-dmic.c @@ -358,6 +358,9 @@ static int sun50i_dmic_probe(struct platform_device *pdev) host->regmap = devm_regmap_init_mmio(&pdev->dev, base, &sun50i_dmic_regmap_config); + if (IS_ERR(host->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(host->regmap), + "failed to initialise regmap\n"); /* Clocks */ host->bus_clk = devm_clk_get(&pdev->dev, "bus"); @@ -415,15 +418,15 @@ static void sun50i_dmic_remove(struct platform_device *pdev) } static const struct dev_pm_ops sun50i_dmic_pm = { - SET_RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend, - sun50i_dmic_runtime_resume, NULL) + RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend, + sun50i_dmic_runtime_resume, NULL) }; static struct platform_driver sun50i_dmic_driver = { .driver = { .name = "sun50i-dmic", .of_match_table = sun50i_dmic_of_match, - .pm = &sun50i_dmic_pm, + .pm = pm_ptr(&sun50i_dmic_pm), }, .probe = sun50i_dmic_probe, .remove = sun50i_dmic_remove, diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index 445b34141896..2024e2b2553e 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c @@ -390,7 +390,7 @@ static const struct snd_soc_dapm_route sun8i_codec_headphone_routes[] = { static int sun8i_codec_add_headphone(struct snd_soc_component *cmpnt) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(cmpnt); struct device *dev = cmpnt->dev; int ret; @@ -428,7 +428,7 @@ static const struct snd_soc_dapm_widget sun8i_codec_mbias_widgets[] = { static int sun8i_codec_add_mbias(struct snd_soc_component *cmpnt) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(cmpnt); struct device *dev = cmpnt->dev; int ret; @@ -449,7 +449,7 @@ static const struct snd_soc_dapm_widget sun8i_codec_hmic_widgets[] = { static int sun8i_codec_add_hmic(struct snd_soc_component *cmpnt) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(cmpnt); struct device *dev = cmpnt->dev; int ret; @@ -486,7 +486,7 @@ static const struct snd_soc_dapm_route sun8i_codec_linein_routes[] = { static int sun8i_codec_add_linein(struct snd_soc_component *cmpnt) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(cmpnt); struct device *dev = cmpnt->dev; int ret; @@ -567,7 +567,7 @@ static const struct snd_soc_dapm_route sun8i_codec_lineout_routes[] = { static int sun8i_codec_add_lineout(struct snd_soc_component *cmpnt) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(cmpnt); struct device *dev = cmpnt->dev; int ret; @@ -632,7 +632,7 @@ static const struct snd_soc_dapm_route sun8i_codec_mic2_routes[] = { static int sun8i_codec_add_mic2(struct snd_soc_component *cmpnt) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(cmpnt); struct device *dev = cmpnt->dev; int ret; @@ -688,7 +688,7 @@ static const struct sun8i_codec_analog_quirks sun8i_h3_quirks = { static int sun8i_codec_analog_add_mixer(struct snd_soc_component *cmpnt, const struct sun8i_codec_analog_quirks *quirks) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(cmpnt); struct device *dev = cmpnt->dev; int ret; diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 8c645e04d571..6bd42da57ac0 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -248,12 +248,10 @@ static int sun8i_codec_runtime_resume(struct device *dev) struct sun8i_codec *scodec = dev_get_drvdata(dev); int ret; - if (scodec->clk_bus) { - ret = clk_prepare_enable(scodec->clk_bus); - if (ret) { - dev_err(dev, "Failed to enable the bus clock\n"); - return ret; - } + ret = clk_prepare_enable(scodec->clk_bus); + if (ret) { + dev_err(dev, "Failed to enable the bus clock\n"); + return ret; } regcache_cache_only(scodec->regmap, false); @@ -274,8 +272,7 @@ static int sun8i_codec_runtime_suspend(struct device *dev) regcache_cache_only(scodec->regmap, true); regcache_mark_dirty(scodec->regmap); - if (scodec->clk_bus) - clk_disable_unprepare(scodec->clk_bus); + clk_disable_unprepare(scodec->clk_bus); return 0; } @@ -1290,7 +1287,7 @@ static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = { static int sun8i_codec_component_probe(struct snd_soc_component *component) { - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); int ret; @@ -1334,7 +1331,7 @@ static int sun8i_codec_component_probe(struct snd_soc_component *component) static void sun8i_codec_set_hmic_bias(struct sun8i_codec *scodec, bool enable) { - struct snd_soc_dapm_context *dapm = &scodec->component->card->dapm; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(scodec->component->card); int irq_mask = BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN); if (enable) @@ -1702,15 +1699,15 @@ static const struct of_device_id sun8i_codec_of_match[] = { MODULE_DEVICE_TABLE(of, sun8i_codec_of_match); static const struct dev_pm_ops sun8i_codec_pm_ops = { - SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend, - sun8i_codec_runtime_resume, NULL) + RUNTIME_PM_OPS(sun8i_codec_runtime_suspend, + sun8i_codec_runtime_resume, NULL) }; static struct platform_driver sun8i_codec_driver = { .driver = { .name = "sun8i-codec", .of_match_table = sun8i_codec_of_match, - .pm = &sun8i_codec_pm_ops, + .pm = pm_ptr(&sun8i_codec_pm_ops), }, .probe = sun8i_codec_probe, .remove = sun8i_codec_remove, |
