Loading sound/soc/codecs/max98925.c +13 −10 Original line number Diff line number Diff line Loading @@ -579,7 +579,7 @@ static int max98925_i2c_probe(struct i2c_client *i2c, ret = PTR_ERR(max98925->regmap); dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); goto err_out; return ret; } if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) { Loading @@ -596,16 +596,20 @@ static int max98925_i2c_probe(struct i2c_client *i2c, } max98925->i_slot = value; } ret = regmap_read(max98925->regmap, MAX98925_REV_VERSION, ®); if ((ret < 0) || ((reg != MAX98925_VERSION) && (reg != MAX98925_VERSION1))) { dev_err(&i2c->dev, "device initialization error (%d 0x%02X)\n", ret = regmap_read(max98925->regmap, MAX98925_REV_VERSION, ®); if (ret < 0) { dev_err(&i2c->dev, "Read revision failed\n"); return ret; } if ((reg != MAX98925_VERSION) && (reg != MAX98925_VERSION1)) { ret = -ENODEV; dev_err(&i2c->dev, "Invalid revision (%d 0x%02X)\n", ret, reg); goto err_out; return ret; } dev_info(&i2c->dev, "device version 0x%02X\n", reg); ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98925, Loading @@ -613,7 +617,6 @@ static int max98925_i2c_probe(struct i2c_client *i2c, if (ret < 0) dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); err_out: return ret; } Loading sound/soc/codecs/max98927.c +124 −31 Original line number Diff line number Diff line /* * max98927.c -- MAX98927 ALSA Soc Audio driver * * Copyright (C) 2016 Maxim Integrated Products * Copyright (C) 2016-2017 Maxim Integrated Products * Author: Ryan Lee <ryans.lee@maximintegrated.com> * * This program is free software; you can redistribute it and/or modify it Loading Loading @@ -146,6 +146,7 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int mode = 0; unsigned int format = 0; bool use_pdm = false; unsigned int invert = 0; dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); Loading Loading @@ -187,22 +188,27 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: max98927->iface |= SND_SOC_DAIFMT_I2S; format = MAX98927_PCM_FORMAT_I2S; break; case SND_SOC_DAIFMT_LEFT_J: max98927->iface |= SND_SOC_DAIFMT_LEFT_J; format = MAX98927_PCM_FORMAT_LJ; break; case SND_SOC_DAIFMT_DSP_A: format = MAX98927_PCM_FORMAT_TDM_MODE1; break; case SND_SOC_DAIFMT_DSP_B: format = MAX98927_PCM_FORMAT_TDM_MODE0; break; case SND_SOC_DAIFMT_PDM: max98927->iface |= SND_SOC_DAIFMT_PDM; use_pdm = true; break; default: return -EINVAL; } max98927->iface = fmt & SND_SOC_DAIFMT_FORMAT_MASK; if (!use_pdm) { /* pcm channel configuration */ if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) { regmap_update_bits(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, Loading @@ -217,13 +223,11 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) MAX98927_R003B_SPK_SRC_SEL, MAX98927_SPK_SRC_MASK, 0); } else regmap_update_bits(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0); MAX98927_R0035_PDM_RX_CTRL, MAX98927_PDM_RX_EN_MASK, 0); } else { /* pdm channel configuration */ if (max98927->iface & SND_SOC_DAIFMT_PDM) { regmap_update_bits(max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, MAX98927_PDM_RX_EN_MASK, 1); Loading @@ -231,10 +235,11 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) regmap_update_bits(max98927->regmap, MAX98927_R003B_SPK_SRC_SEL, MAX98927_SPK_SRC_MASK, 3); } else regmap_update_bits(max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, MAX98927_PDM_RX_EN_MASK, 0); MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0); } return 0; } Loading @@ -245,6 +250,21 @@ static const int rate_table[] = { 13000000, 19200000, }; /* BCLKs per LRCLK */ static const int bclk_sel_table[] = { 32, 48, 64, 96, 128, 192, 256, 384, 512, }; static int max98927_get_bclk_sel(int bclk) { int i; /* match BCLKs per LRCLK */ for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { if (bclk_sel_table[i] == bclk) return i + 2; } return 0; } static int max98927_set_clock(struct max98927_priv *max98927, struct snd_pcm_hw_params *params) { Loading @@ -270,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927, i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); } switch (blr_clk_ratio) { case 32: value = 2; break; case 48: value = 3; break; case 64: value = 4; break; default: if (!max98927->tdm_mode) { /* BCLK configuration */ value = max98927_get_bclk_sel(blr_clk_ratio); if (!value) { dev_err(codec->dev, "format unsupported %d\n", params_format(params)); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, MAX98927_PCM_CLK_SETUP_BSEL_MASK, value); } return 0; } Loading Loading @@ -386,6 +403,78 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } static int max98927_dai_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { struct snd_soc_codec *codec = dai->codec; struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); int bsel = 0; unsigned int chan_sz = 0; max98927->tdm_mode = true; /* BCLK configuration */ bsel = max98927_get_bclk_sel(slots * slot_width); if (bsel == 0) { dev_err(codec->dev, "BCLK %d not supported\n", slots * slot_width); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, MAX98927_PCM_CLK_SETUP_BSEL_MASK, bsel); /* Channel size configuration */ switch (slot_width) { case 16: chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; break; case 24: chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; break; case 32: chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; break; default: dev_err(codec->dev, "format unsupported %d\n", slot_width); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); /* Rx slot configuration */ regmap_write(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, rx_mask & 0xFF); regmap_write(max98927->regmap, MAX98927_R0019_PCM_RX_EN_B, (rx_mask & 0xFF00) >> 8); /* Tx slot configuration */ regmap_write(max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, tx_mask & 0xFF); regmap_write(max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, (tx_mask & 0xFF00) >> 8); /* Tx slot Hi-Z configuration */ regmap_write(max98927->regmap, MAX98927_R001C_PCM_TX_HIZ_CTRL_A, ~tx_mask & 0xFF); regmap_write(max98927->regmap, MAX98927_R001D_PCM_TX_HIZ_CTRL_B, (~tx_mask & 0xFF00) >> 8); return 0; } #define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 #define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ Loading @@ -405,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = { .set_sysclk = max98927_dai_set_sysclk, .set_fmt = max98927_dai_set_fmt, .hw_params = max98927_dai_hw_params, .set_tdm_slot = max98927_dai_tdm_slot, }; static int max98927_dac_event(struct snd_soc_dapm_widget *w, Loading @@ -414,6 +504,9 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w, struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: max98927->tdm_mode = 0; break; case SND_SOC_DAPM_POST_PMU: regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, Loading sound/soc/codecs/max98927.h +5 −2 Original line number Diff line number Diff line /* * max98927.h -- MAX98927 ALSA Soc Audio driver * * Copyright 2013-15 Maxim Integrated Products * Copyright (C) 2016-2017 Maxim Integrated Products * Author: Ryan Lee <ryans.lee@maximintegrated.com> * * This program is free software; you can redistribute it and/or modify it Loading Loading @@ -161,7 +161,9 @@ #define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3) #define MAX98927_PCM_FORMAT_I2S (0x0 << 0) #define MAX98927_PCM_FORMAT_LJ (0x1 << 0) #define MAX98927_PCM_FORMAT_TDM_MODE0 (0x3 << 0) #define MAX98927_PCM_FORMAT_TDM_MODE1 (0x4 << 0) #define MAX98927_PCM_FORMAT_TDM_MODE2 (0x5 << 0) #define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6) #define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6) #define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6) Loading Loading @@ -268,5 +270,6 @@ struct max98927_priv { unsigned int iface; unsigned int master; unsigned int digital_gain; bool tdm_mode; }; #endif sound/soc/codecs/msm8916-wcd-analog.c +59 −53 Original line number Diff line number Diff line Loading @@ -285,7 +285,7 @@ struct pm8916_wcd_analog_priv { u16 codec_version; bool mbhc_btn_enabled; /* special event to detect accessory type */ bool mbhc_btn0_pressed; int mbhc_btn0_released; bool detect_accessory_type; struct clk *mclk; struct snd_soc_codec *codec; Loading Loading @@ -444,50 +444,6 @@ static int pm8916_wcd_analog_enable_micbias_int1(struct wcd->micbias1_cap_mode); } static void pm8916_wcd_setup_mbhc(struct pm8916_wcd_analog_priv *wcd) { struct snd_soc_codec *codec = wcd->codec; u32 plug_type = 0; u32 int_en_mask; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_1, CDC_A_MBHC_DET_CTL_L_DET_EN | CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_INSERTION | CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_AUTO | CDC_A_MBHC_DET_CTL_MBHC_BIAS_EN); if (wcd->hphl_jack_type_normally_open) plug_type |= CDC_A_HPHL_PLUG_TYPE_NO; if (wcd->gnd_jack_type_normally_open) plug_type |= CDC_A_GND_PLUG_TYPE_NO; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_2, CDC_A_MBHC_DET_CTL_HS_L_DET_PULL_UP_CTRL_I_3P0 | CDC_A_MBHC_DET_CTL_HS_L_DET_COMPA_CTRL_V0P9_VDD | plug_type | CDC_A_MBHC_DET_CTL_HPHL_100K_TO_GND_EN); snd_soc_write(codec, CDC_A_MBHC_DBNC_TIMER, CDC_A_MBHC_DBNC_TIMER_INSREM_DBNC_T_256_MS | CDC_A_MBHC_DBNC_TIMER_BTN_DBNC_T_16MS); /* enable MBHC clock */ snd_soc_update_bits(codec, CDC_D_CDC_DIG_CLK_CTL, DIG_CLK_CTL_D_MBHC_CLK_EN_MASK, DIG_CLK_CTL_D_MBHC_CLK_EN); int_en_mask = MBHC_SWITCH_INT; if (wcd->mbhc_btn_enabled) int_en_mask |= MBHC_BUTTON_PRESS_DET | MBHC_BUTTON_RELEASE_DET; snd_soc_update_bits(codec, CDC_D_INT_EN_CLR, int_en_mask, 0); snd_soc_update_bits(codec, CDC_D_INT_EN_SET, int_en_mask, int_en_mask); wcd->mbhc_btn0_pressed = false; wcd->detect_accessory_type = true; } static int pm8916_mbhc_configure_bias(struct pm8916_wcd_analog_priv *priv, bool micbias2_enabled) { Loading Loading @@ -535,6 +491,56 @@ static int pm8916_mbhc_configure_bias(struct pm8916_wcd_analog_priv *priv, return 0; } static void pm8916_wcd_setup_mbhc(struct pm8916_wcd_analog_priv *wcd) { struct snd_soc_codec *codec = wcd->codec; bool micbias_enabled = false; u32 plug_type = 0; u32 int_en_mask; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_1, CDC_A_MBHC_DET_CTL_L_DET_EN | CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_INSERTION | CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_AUTO | CDC_A_MBHC_DET_CTL_MBHC_BIAS_EN); if (wcd->hphl_jack_type_normally_open) plug_type |= CDC_A_HPHL_PLUG_TYPE_NO; if (wcd->gnd_jack_type_normally_open) plug_type |= CDC_A_GND_PLUG_TYPE_NO; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_2, CDC_A_MBHC_DET_CTL_HS_L_DET_PULL_UP_CTRL_I_3P0 | CDC_A_MBHC_DET_CTL_HS_L_DET_COMPA_CTRL_V0P9_VDD | plug_type | CDC_A_MBHC_DET_CTL_HPHL_100K_TO_GND_EN); snd_soc_write(codec, CDC_A_MBHC_DBNC_TIMER, CDC_A_MBHC_DBNC_TIMER_INSREM_DBNC_T_256_MS | CDC_A_MBHC_DBNC_TIMER_BTN_DBNC_T_16MS); /* enable MBHC clock */ snd_soc_update_bits(codec, CDC_D_CDC_DIG_CLK_CTL, DIG_CLK_CTL_D_MBHC_CLK_EN_MASK, DIG_CLK_CTL_D_MBHC_CLK_EN); if (snd_soc_read(codec, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) micbias_enabled = true; pm8916_mbhc_configure_bias(wcd, micbias_enabled); int_en_mask = MBHC_SWITCH_INT; if (wcd->mbhc_btn_enabled) int_en_mask |= MBHC_BUTTON_PRESS_DET | MBHC_BUTTON_RELEASE_DET; snd_soc_update_bits(codec, CDC_D_INT_EN_CLR, int_en_mask, 0); snd_soc_update_bits(codec, CDC_D_INT_EN_SET, int_en_mask, int_en_mask); wcd->mbhc_btn0_released = false; wcd->detect_accessory_type = true; } static int pm8916_wcd_analog_enable_micbias_int2(struct snd_soc_dapm_widget *w, struct snd_kcontrol Loading Loading @@ -952,7 +958,7 @@ static irqreturn_t mbhc_btn_release_irq_handler(int irq, void *arg) /* check if its BTN0 thats released */ if ((val != -1) && !(val & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK)) priv->mbhc_btn0_pressed = false; priv->mbhc_btn0_released = true; } else { snd_soc_jack_report(priv->jack, 0, btn_mask); Loading Loading @@ -985,9 +991,7 @@ static irqreturn_t mbhc_btn_press_irq_handler(int irq, void *arg) break; case 0x0: /* handle BTN_0 specially for type detection */ if (priv->detect_accessory_type) priv->mbhc_btn0_pressed = true; else if (!priv->detect_accessory_type) snd_soc_jack_report(priv->jack, SND_JACK_BTN_0, btn_mask); break; Loading Loading @@ -1031,19 +1035,19 @@ static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg) * both press and release event received then its * a headset. */ if (priv->mbhc_btn0_pressed) if (priv->mbhc_btn0_released) snd_soc_jack_report(priv->jack, SND_JACK_HEADPHONE, hs_jack_mask); SND_JACK_HEADSET, hs_jack_mask); else snd_soc_jack_report(priv->jack, SND_JACK_HEADSET, hs_jack_mask); SND_JACK_HEADPHONE, hs_jack_mask); priv->detect_accessory_type = false; } else { /* removal */ snd_soc_jack_report(priv->jack, 0, hs_jack_mask); priv->detect_accessory_type = true; priv->mbhc_btn0_pressed = false; priv->mbhc_btn0_released = false; } return IRQ_HANDLED; Loading Loading @@ -1243,6 +1247,8 @@ static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { { } }; MODULE_DEVICE_TABLE(of, pm8916_wcd_analog_spmi_match_table); static struct platform_driver pm8916_wcd_analog_spmi_driver = { .driver = { .name = "qcom,pm8916-wcd-spmi-codec", Loading sound/soc/omap/omap-hdmi-audio.c +3 −0 Original line number Diff line number Diff line Loading @@ -362,6 +362,9 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) card->name = devm_kasprintf(dev, GFP_KERNEL, "HDMI %s", dev_name(ad->dssdev)); if (!card->name) return -ENOMEM; card->owner = THIS_MODULE; card->dai_link = devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL); Loading Loading
sound/soc/codecs/max98925.c +13 −10 Original line number Diff line number Diff line Loading @@ -579,7 +579,7 @@ static int max98925_i2c_probe(struct i2c_client *i2c, ret = PTR_ERR(max98925->regmap); dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); goto err_out; return ret; } if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) { Loading @@ -596,16 +596,20 @@ static int max98925_i2c_probe(struct i2c_client *i2c, } max98925->i_slot = value; } ret = regmap_read(max98925->regmap, MAX98925_REV_VERSION, ®); if ((ret < 0) || ((reg != MAX98925_VERSION) && (reg != MAX98925_VERSION1))) { dev_err(&i2c->dev, "device initialization error (%d 0x%02X)\n", ret = regmap_read(max98925->regmap, MAX98925_REV_VERSION, ®); if (ret < 0) { dev_err(&i2c->dev, "Read revision failed\n"); return ret; } if ((reg != MAX98925_VERSION) && (reg != MAX98925_VERSION1)) { ret = -ENODEV; dev_err(&i2c->dev, "Invalid revision (%d 0x%02X)\n", ret, reg); goto err_out; return ret; } dev_info(&i2c->dev, "device version 0x%02X\n", reg); ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98925, Loading @@ -613,7 +617,6 @@ static int max98925_i2c_probe(struct i2c_client *i2c, if (ret < 0) dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); err_out: return ret; } Loading
sound/soc/codecs/max98927.c +124 −31 Original line number Diff line number Diff line /* * max98927.c -- MAX98927 ALSA Soc Audio driver * * Copyright (C) 2016 Maxim Integrated Products * Copyright (C) 2016-2017 Maxim Integrated Products * Author: Ryan Lee <ryans.lee@maximintegrated.com> * * This program is free software; you can redistribute it and/or modify it Loading Loading @@ -146,6 +146,7 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int mode = 0; unsigned int format = 0; bool use_pdm = false; unsigned int invert = 0; dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); Loading Loading @@ -187,22 +188,27 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: max98927->iface |= SND_SOC_DAIFMT_I2S; format = MAX98927_PCM_FORMAT_I2S; break; case SND_SOC_DAIFMT_LEFT_J: max98927->iface |= SND_SOC_DAIFMT_LEFT_J; format = MAX98927_PCM_FORMAT_LJ; break; case SND_SOC_DAIFMT_DSP_A: format = MAX98927_PCM_FORMAT_TDM_MODE1; break; case SND_SOC_DAIFMT_DSP_B: format = MAX98927_PCM_FORMAT_TDM_MODE0; break; case SND_SOC_DAIFMT_PDM: max98927->iface |= SND_SOC_DAIFMT_PDM; use_pdm = true; break; default: return -EINVAL; } max98927->iface = fmt & SND_SOC_DAIFMT_FORMAT_MASK; if (!use_pdm) { /* pcm channel configuration */ if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) { regmap_update_bits(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, Loading @@ -217,13 +223,11 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) MAX98927_R003B_SPK_SRC_SEL, MAX98927_SPK_SRC_MASK, 0); } else regmap_update_bits(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0); MAX98927_R0035_PDM_RX_CTRL, MAX98927_PDM_RX_EN_MASK, 0); } else { /* pdm channel configuration */ if (max98927->iface & SND_SOC_DAIFMT_PDM) { regmap_update_bits(max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, MAX98927_PDM_RX_EN_MASK, 1); Loading @@ -231,10 +235,11 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) regmap_update_bits(max98927->regmap, MAX98927_R003B_SPK_SRC_SEL, MAX98927_SPK_SRC_MASK, 3); } else regmap_update_bits(max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, MAX98927_PDM_RX_EN_MASK, 0); MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0); } return 0; } Loading @@ -245,6 +250,21 @@ static const int rate_table[] = { 13000000, 19200000, }; /* BCLKs per LRCLK */ static const int bclk_sel_table[] = { 32, 48, 64, 96, 128, 192, 256, 384, 512, }; static int max98927_get_bclk_sel(int bclk) { int i; /* match BCLKs per LRCLK */ for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { if (bclk_sel_table[i] == bclk) return i + 2; } return 0; } static int max98927_set_clock(struct max98927_priv *max98927, struct snd_pcm_hw_params *params) { Loading @@ -270,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927, i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); } switch (blr_clk_ratio) { case 32: value = 2; break; case 48: value = 3; break; case 64: value = 4; break; default: if (!max98927->tdm_mode) { /* BCLK configuration */ value = max98927_get_bclk_sel(blr_clk_ratio); if (!value) { dev_err(codec->dev, "format unsupported %d\n", params_format(params)); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, MAX98927_PCM_CLK_SETUP_BSEL_MASK, value); } return 0; } Loading Loading @@ -386,6 +403,78 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } static int max98927_dai_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { struct snd_soc_codec *codec = dai->codec; struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); int bsel = 0; unsigned int chan_sz = 0; max98927->tdm_mode = true; /* BCLK configuration */ bsel = max98927_get_bclk_sel(slots * slot_width); if (bsel == 0) { dev_err(codec->dev, "BCLK %d not supported\n", slots * slot_width); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, MAX98927_PCM_CLK_SETUP_BSEL_MASK, bsel); /* Channel size configuration */ switch (slot_width) { case 16: chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; break; case 24: chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; break; case 32: chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; break; default: dev_err(codec->dev, "format unsupported %d\n", slot_width); return -EINVAL; } regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); /* Rx slot configuration */ regmap_write(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, rx_mask & 0xFF); regmap_write(max98927->regmap, MAX98927_R0019_PCM_RX_EN_B, (rx_mask & 0xFF00) >> 8); /* Tx slot configuration */ regmap_write(max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, tx_mask & 0xFF); regmap_write(max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, (tx_mask & 0xFF00) >> 8); /* Tx slot Hi-Z configuration */ regmap_write(max98927->regmap, MAX98927_R001C_PCM_TX_HIZ_CTRL_A, ~tx_mask & 0xFF); regmap_write(max98927->regmap, MAX98927_R001D_PCM_TX_HIZ_CTRL_B, (~tx_mask & 0xFF00) >> 8); return 0; } #define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 #define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ Loading @@ -405,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = { .set_sysclk = max98927_dai_set_sysclk, .set_fmt = max98927_dai_set_fmt, .hw_params = max98927_dai_hw_params, .set_tdm_slot = max98927_dai_tdm_slot, }; static int max98927_dac_event(struct snd_soc_dapm_widget *w, Loading @@ -414,6 +504,9 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w, struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: max98927->tdm_mode = 0; break; case SND_SOC_DAPM_POST_PMU: regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, Loading
sound/soc/codecs/max98927.h +5 −2 Original line number Diff line number Diff line /* * max98927.h -- MAX98927 ALSA Soc Audio driver * * Copyright 2013-15 Maxim Integrated Products * Copyright (C) 2016-2017 Maxim Integrated Products * Author: Ryan Lee <ryans.lee@maximintegrated.com> * * This program is free software; you can redistribute it and/or modify it Loading Loading @@ -161,7 +161,9 @@ #define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3) #define MAX98927_PCM_FORMAT_I2S (0x0 << 0) #define MAX98927_PCM_FORMAT_LJ (0x1 << 0) #define MAX98927_PCM_FORMAT_TDM_MODE0 (0x3 << 0) #define MAX98927_PCM_FORMAT_TDM_MODE1 (0x4 << 0) #define MAX98927_PCM_FORMAT_TDM_MODE2 (0x5 << 0) #define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6) #define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6) #define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6) Loading Loading @@ -268,5 +270,6 @@ struct max98927_priv { unsigned int iface; unsigned int master; unsigned int digital_gain; bool tdm_mode; }; #endif
sound/soc/codecs/msm8916-wcd-analog.c +59 −53 Original line number Diff line number Diff line Loading @@ -285,7 +285,7 @@ struct pm8916_wcd_analog_priv { u16 codec_version; bool mbhc_btn_enabled; /* special event to detect accessory type */ bool mbhc_btn0_pressed; int mbhc_btn0_released; bool detect_accessory_type; struct clk *mclk; struct snd_soc_codec *codec; Loading Loading @@ -444,50 +444,6 @@ static int pm8916_wcd_analog_enable_micbias_int1(struct wcd->micbias1_cap_mode); } static void pm8916_wcd_setup_mbhc(struct pm8916_wcd_analog_priv *wcd) { struct snd_soc_codec *codec = wcd->codec; u32 plug_type = 0; u32 int_en_mask; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_1, CDC_A_MBHC_DET_CTL_L_DET_EN | CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_INSERTION | CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_AUTO | CDC_A_MBHC_DET_CTL_MBHC_BIAS_EN); if (wcd->hphl_jack_type_normally_open) plug_type |= CDC_A_HPHL_PLUG_TYPE_NO; if (wcd->gnd_jack_type_normally_open) plug_type |= CDC_A_GND_PLUG_TYPE_NO; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_2, CDC_A_MBHC_DET_CTL_HS_L_DET_PULL_UP_CTRL_I_3P0 | CDC_A_MBHC_DET_CTL_HS_L_DET_COMPA_CTRL_V0P9_VDD | plug_type | CDC_A_MBHC_DET_CTL_HPHL_100K_TO_GND_EN); snd_soc_write(codec, CDC_A_MBHC_DBNC_TIMER, CDC_A_MBHC_DBNC_TIMER_INSREM_DBNC_T_256_MS | CDC_A_MBHC_DBNC_TIMER_BTN_DBNC_T_16MS); /* enable MBHC clock */ snd_soc_update_bits(codec, CDC_D_CDC_DIG_CLK_CTL, DIG_CLK_CTL_D_MBHC_CLK_EN_MASK, DIG_CLK_CTL_D_MBHC_CLK_EN); int_en_mask = MBHC_SWITCH_INT; if (wcd->mbhc_btn_enabled) int_en_mask |= MBHC_BUTTON_PRESS_DET | MBHC_BUTTON_RELEASE_DET; snd_soc_update_bits(codec, CDC_D_INT_EN_CLR, int_en_mask, 0); snd_soc_update_bits(codec, CDC_D_INT_EN_SET, int_en_mask, int_en_mask); wcd->mbhc_btn0_pressed = false; wcd->detect_accessory_type = true; } static int pm8916_mbhc_configure_bias(struct pm8916_wcd_analog_priv *priv, bool micbias2_enabled) { Loading Loading @@ -535,6 +491,56 @@ static int pm8916_mbhc_configure_bias(struct pm8916_wcd_analog_priv *priv, return 0; } static void pm8916_wcd_setup_mbhc(struct pm8916_wcd_analog_priv *wcd) { struct snd_soc_codec *codec = wcd->codec; bool micbias_enabled = false; u32 plug_type = 0; u32 int_en_mask; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_1, CDC_A_MBHC_DET_CTL_L_DET_EN | CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_INSERTION | CDC_A_MBHC_DET_CTL_MIC_CLAMP_CTL_AUTO | CDC_A_MBHC_DET_CTL_MBHC_BIAS_EN); if (wcd->hphl_jack_type_normally_open) plug_type |= CDC_A_HPHL_PLUG_TYPE_NO; if (wcd->gnd_jack_type_normally_open) plug_type |= CDC_A_GND_PLUG_TYPE_NO; snd_soc_write(codec, CDC_A_MBHC_DET_CTL_2, CDC_A_MBHC_DET_CTL_HS_L_DET_PULL_UP_CTRL_I_3P0 | CDC_A_MBHC_DET_CTL_HS_L_DET_COMPA_CTRL_V0P9_VDD | plug_type | CDC_A_MBHC_DET_CTL_HPHL_100K_TO_GND_EN); snd_soc_write(codec, CDC_A_MBHC_DBNC_TIMER, CDC_A_MBHC_DBNC_TIMER_INSREM_DBNC_T_256_MS | CDC_A_MBHC_DBNC_TIMER_BTN_DBNC_T_16MS); /* enable MBHC clock */ snd_soc_update_bits(codec, CDC_D_CDC_DIG_CLK_CTL, DIG_CLK_CTL_D_MBHC_CLK_EN_MASK, DIG_CLK_CTL_D_MBHC_CLK_EN); if (snd_soc_read(codec, CDC_A_MICB_2_EN) & CDC_A_MICB_2_EN_ENABLE) micbias_enabled = true; pm8916_mbhc_configure_bias(wcd, micbias_enabled); int_en_mask = MBHC_SWITCH_INT; if (wcd->mbhc_btn_enabled) int_en_mask |= MBHC_BUTTON_PRESS_DET | MBHC_BUTTON_RELEASE_DET; snd_soc_update_bits(codec, CDC_D_INT_EN_CLR, int_en_mask, 0); snd_soc_update_bits(codec, CDC_D_INT_EN_SET, int_en_mask, int_en_mask); wcd->mbhc_btn0_released = false; wcd->detect_accessory_type = true; } static int pm8916_wcd_analog_enable_micbias_int2(struct snd_soc_dapm_widget *w, struct snd_kcontrol Loading Loading @@ -952,7 +958,7 @@ static irqreturn_t mbhc_btn_release_irq_handler(int irq, void *arg) /* check if its BTN0 thats released */ if ((val != -1) && !(val & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK)) priv->mbhc_btn0_pressed = false; priv->mbhc_btn0_released = true; } else { snd_soc_jack_report(priv->jack, 0, btn_mask); Loading Loading @@ -985,9 +991,7 @@ static irqreturn_t mbhc_btn_press_irq_handler(int irq, void *arg) break; case 0x0: /* handle BTN_0 specially for type detection */ if (priv->detect_accessory_type) priv->mbhc_btn0_pressed = true; else if (!priv->detect_accessory_type) snd_soc_jack_report(priv->jack, SND_JACK_BTN_0, btn_mask); break; Loading Loading @@ -1031,19 +1035,19 @@ static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg) * both press and release event received then its * a headset. */ if (priv->mbhc_btn0_pressed) if (priv->mbhc_btn0_released) snd_soc_jack_report(priv->jack, SND_JACK_HEADPHONE, hs_jack_mask); SND_JACK_HEADSET, hs_jack_mask); else snd_soc_jack_report(priv->jack, SND_JACK_HEADSET, hs_jack_mask); SND_JACK_HEADPHONE, hs_jack_mask); priv->detect_accessory_type = false; } else { /* removal */ snd_soc_jack_report(priv->jack, 0, hs_jack_mask); priv->detect_accessory_type = true; priv->mbhc_btn0_pressed = false; priv->mbhc_btn0_released = false; } return IRQ_HANDLED; Loading Loading @@ -1243,6 +1247,8 @@ static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { { } }; MODULE_DEVICE_TABLE(of, pm8916_wcd_analog_spmi_match_table); static struct platform_driver pm8916_wcd_analog_spmi_driver = { .driver = { .name = "qcom,pm8916-wcd-spmi-codec", Loading
sound/soc/omap/omap-hdmi-audio.c +3 −0 Original line number Diff line number Diff line Loading @@ -362,6 +362,9 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) card->name = devm_kasprintf(dev, GFP_KERNEL, "HDMI %s", dev_name(ad->dssdev)); if (!card->name) return -ENOMEM; card->owner = THIS_MODULE; card->dai_link = devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL); Loading