diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 11:07:44 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 11:07:44 -0700 |
commit | c48b75b7271db23c1b2d1204d6e8496d91f27711 (patch) | |
tree | 83c95f082e0605257b8af3ebd70b2c448262fd88 /sound/soc/codecs/rt1015.c | |
parent | 93b694d096cc10994c817730d4d50288f9ae3d66 (diff) | |
parent | ce1558c285f9ad04c03b46833a028230771cc0a7 (diff) |
Merge tag 'sound-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"The amount of changes is smaller at this round (what a surprise), but
lots of activity is seen. Most of changes are about ASoC driver
development, especially Intel platforms. Here are some highlights:
General:
- Replace all tasklet usages with other alternatives
- Cleanup of the ASoC error unwinding code
- Fixes for trivial issues caught by static checker
- Spell fixes allover the places
ALSA Core:
- Lockdep fix for control devices
- Fix for potential OSS sequencer mutex stalls
HD-audio and USB-audio:
- SoundBlaster AE-7 support
- Changes in quirk table for the rename handling
- Quirks for HP and ASUS machines, Pioneer DJ DJM-250MK2.
ASoC:
- Lots of updates for Intel SOF and SoundWire enablement
- Replacement of the DSP driver for some older x86 systems; the new
code was written from scratch, better maintenance expected
- Helpers for parsing auxiluary devices from the device tree
- New support for AllWinner A64, Cirrus Logic CS4234, Mediatek MT6359
Microchip S/PDIF TX and RX controllers, Realtek RT1015P, and Texas
Instruments J721E, TAS2110, TAS2564 and TAS2764"
* tag 'sound-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (498 commits)
ALSA: hda/hdmi: fix incorrect locking in hdmi_pcm_close
ALSA: hda: fix jack detection with Realtek codecs when in D3
ALSA: fireworks: use semicolons rather than commas to separate statements
ALSA: hda: use semicolons rather than commas to separate statements
ALSA: hda/i915 - fix list corruption with concurrent probes
ASoC: dmaengine: Document support for TX only or RX only streams
ASoC: mchp-spdiftx: remove 'TX' from playback stream name
ASoC: ti: davinci-mcasp: Use &pdev->dev for early dev_warn
ASoC: tas2764: Add the driver for the TAS2764
dt-bindings: tas2764: Add the TAS2764 binding doc
ASoC: Intel: catpt: Add explicit DMADEVICES kconfig dependency
ASoC: Intel: catpt: Fix compilation when CONFIG_MODULES is disabled
ASoC: stm32: dfsdm: add actual resolution trace
ASoC: stm32: dfsdm: change rate limits
ASoC: qcom: sc7180: Add support for audio over DP
Asoc: qcom: lpass-platform : Increase buffer size
ASoC: qcom: Add support for lpass hdmi driver
Asoc: qcom: lpass:Update lpaif_dmactl members order
Asoc:qcom:lpass-cpu:Update dts property read API
ASoC: dt-bindings: Add dt binding for lpass hdmi
...
Diffstat (limited to 'sound/soc/codecs/rt1015.c')
-rw-r--r-- | sound/soc/codecs/rt1015.c | 111 |
1 files changed, 90 insertions, 21 deletions
diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 548f68649064..25fe2ddedd54 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -484,6 +484,33 @@ static int rt1015_bypass_boost_get(struct snd_kcontrol *kcontrol, return 0; } +static void rt1015_calibrate(struct rt1015_priv *rt1015) +{ + struct snd_soc_component *component = rt1015->component; + struct regmap *regmap = rt1015->regmap; + + snd_soc_dapm_mutex_lock(&component->dapm); + regcache_cache_bypass(regmap, true); + + regmap_write(regmap, RT1015_PWR1, 0xd7df); + regmap_write(regmap, RT1015_PWR4, 0x00b2); + regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2008); + regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140); + regmap_write(regmap, RT1015_GAT_BOOST, 0x0efe); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000d); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000e); + regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5a00); + regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5a01); + regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5a05); + msleep(500); + regmap_write(regmap, RT1015_PWR1, 0x0); + + regcache_cache_bypass(regmap, false); + regcache_mark_dirty(regmap); + regcache_sync(regmap); + snd_soc_dapm_mutex_unlock(&component->dapm); +} + static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -494,20 +521,12 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, if (!rt1015->dac_is_used) { rt1015->bypass_boost = ucontrol->value.integer.value[0]; - if (rt1015->bypass_boost == RT1015_Bypass_Boost) { - snd_soc_component_write(component, - RT1015_PWR4, 0x00b2); - snd_soc_component_write(component, - RT1015_CLSD_INTERNAL8, 0x2008); - snd_soc_component_write(component, - RT1015_CLSD_INTERNAL9, 0x0140); - snd_soc_component_write(component, - RT1015_GAT_BOOST, 0x0efe); - snd_soc_component_write(component, - RT1015_PWR_STATE_CTRL, 0x000d); - msleep(500); - snd_soc_component_write(component, - RT1015_PWR_STATE_CTRL, 0x000e); + if (rt1015->bypass_boost == RT1015_Bypass_Boost && + !rt1015->cali_done) { + rt1015_calibrate(rt1015); + rt1015->cali_done = 1; + + regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010); } } else dev_err(component->dev, "DAC is being used!\n"); @@ -515,6 +534,32 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, return 0; } +static void rt1015_flush_work(struct work_struct *work) +{ + struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv, + flush_work.work); + struct snd_soc_component *component = rt1015->component; + unsigned int val, i = 0, count = 20; + + while (i < count) { + usleep_range(1000, 1500); + dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i); + regmap_read(rt1015->regmap, RT1015_CLK_DET, &val); + if (val & 0x800) + break; + i++; + } + + regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597); + regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7); + regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028); + + if (val & 0x800) + dev_dbg(component->dev, "Flush DAC completed.\n"); + else + dev_warn(component->dev, "Fail to flush DAC data.\n"); +} + static const struct snd_kcontrol_new rt1015_snd_controls[] = { SOC_SINGLE_TLV("DAC Playback Volume", RT1015_DAC1, RT1015_DAC_VOL_SFT, 127, 0, dac_vol_tlv), @@ -568,12 +613,7 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMU: - if (rt1015->bypass_boost == RT1015_Bypass_Boost) { - regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8); - regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597); - regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7); - regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028); - } + regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8); break; case SND_SOC_DAPM_POST_PMD: @@ -589,6 +629,8 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, RT1015_SYS_RST1, 0x05f5); } rt1015->dac_is_used = 0; + + cancel_delayed_work_sync(&rt1015->flush_work); break; default: @@ -597,6 +639,24 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, return 0; } +static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (rt1015->hw_config == RT1015_HW_28) + schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10)); + break; + default: + break; + } + return 0; +} + static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("LDO2", RT1015_PWR1, RT1015_PWR_LDO2_BIT, 0, NULL, 0), @@ -630,6 +690,8 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV_E("Amp Drv", SND_SOC_NOPM, 0, 0, NULL, 0, + rt1015_amp_drv_event, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_OUTPUT("SPO"), }; @@ -648,7 +710,8 @@ static const struct snd_soc_dapm_route rt1015_dapm_routes[] = { { "DAC", NULL, "MIXERV" }, { "DAC", NULL, "SUMV" }, { "DAC", NULL, "VREFLV" }, - { "SPO", NULL, "DAC" }, + { "Amp Drv", NULL, "DAC" }, + { "SPO", NULL, "Amp Drv" }, }; static int rt1015_hw_params(struct snd_pcm_substream *substream, @@ -888,8 +951,11 @@ static int rt1015_probe(struct snd_soc_component *component) rt1015->component = component; rt1015->bclk_ratio = 0; + rt1015->cali_done = 0; snd_soc_component_write(component, RT1015_BAT_RPO_STEP1, 0x061c); + INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work); + return 0; } @@ -897,6 +963,7 @@ static void rt1015_remove(struct snd_soc_component *component) { struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); + cancel_delayed_work_sync(&rt1015->flush_work); regmap_write(rt1015->regmap, RT1015_RESET, 0); } @@ -1022,6 +1089,8 @@ static int rt1015_i2c_probe(struct i2c_client *i2c, return ret; } + rt1015->hw_config = (i2c->addr == 0x29) ? RT1015_HW_29 : RT1015_HW_28; + regmap_read(rt1015->regmap, RT1015_DEVICE_ID, &val); if ((val != RT1015_DEVICE_ID_VAL) && (val != RT1015_DEVICE_ID_VAL2)) { dev_err(&i2c->dev, |