Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
1
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
c2c0b67
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
ac97
aoa
arm
atmel
core
drivers
firewire
hda
i2c
isa
mips
oss
parisc
pci
pcmcia
ppc
sh
soc
adi
amd
apple
atmel
au1x
bcm
cirrus
codecs
aw88395
88pm860x-codec.c
88pm860x-codec.h
Kconfig
Makefile
ab8500-codec.c
ab8500-codec.h
ac97.c
ad1836.c
ad1836.h
ad193x-i2c.c
ad193x-spi.c
ad193x.c
ad193x.h
ad1980.c
ad73311.c
ad73311.h
adau-utils.c
adau-utils.h
adau1372-i2c.c
adau1372-spi.c
adau1372.c
adau1372.h
adau1373.c
adau1373.h
adau1701.c
adau1701.h
adau1761-i2c.c
adau1761-spi.c
adau1761.c
adau1761.h
adau1781-i2c.c
adau1781-spi.c
adau1781.c
adau1781.h
adau17x1.c
adau17x1.h
adau1977-i2c.c
adau1977-spi.c
adau1977.c
adau1977.h
adau7002.c
adau7118-hw.c
adau7118-i2c.c
adau7118.c
adau7118.h
adav801.c
adav803.c
adav80x.c
adav80x.h
ads117x.c
ak4104.c
ak4118.c
ak4375.c
ak4458.c
ak4458.h
ak4535.c
ak4535.h
ak4554.c
ak4613.c
ak4619.c
ak4641.c
ak4642.c
ak4671.c
ak4671.h
ak5386.c
ak5558.c
ak5558.h
alc5623.c
alc5623.h
alc5632.c
alc5632.h
arizona-jack.c
arizona.c
arizona.h
audio-iio-aux.c
aw8738.c
aw87390.c
aw87390.h
aw88261.c
aw88261.h
aw88399.c
aw88399.h
bd28623.c
bt-sco.c
chv3-codec.c
cirrus_legacy.h
cpcap.c
cq93vc.c
cros_ec_codec.c
cs-amp-lib-test.c
cs-amp-lib.c
cs35l32.c
cs35l32.h
cs35l33.c
cs35l33.h
cs35l34.c
cs35l34.h
cs35l35.c
cs35l35.h
cs35l36.c
cs35l36.h
cs35l41-i2c.c
cs35l41-lib.c
cs35l41-spi.c
cs35l41.c
cs35l41.h
cs35l45-i2c.c
cs35l45-spi.c
cs35l45-tables.c
cs35l45.c
cs35l45.h
cs35l56-i2c.c
cs35l56-sdw.c
cs35l56-shared.c
cs35l56-spi.c
cs35l56.c
cs35l56.h
cs40l50-codec.c
cs4234.c
cs4234.h
cs4265.c
cs4265.h
cs4270.c
cs4271-i2c.c
cs4271-spi.c
cs4271.c
cs4271.h
cs42l42-i2c.c
cs42l42-sdw.c
cs42l42.c
cs42l42.h
cs42l43-jack.c
cs42l43-sdw.c
cs42l43.c
cs42l43.h
cs42l51-i2c.c
cs42l51.c
cs42l51.h
cs42l52.c
cs42l52.h
cs42l56.c
cs42l56.h
cs42l73.c
cs42l73.h
cs42l83-i2c.c
cs42xx8-i2c.c
cs42xx8.c
cs42xx8.h
cs43130.c
cs43130.h
cs4341.c
cs4349.c
cs4349.h
cs47l15.c
cs47l24.c
cs47l24.h
cs47l35.c
cs47l85.c
cs47l90.c
cs47l92.c
cs530x-i2c.c
cs530x.c
cs530x.h
cs53l30.c
cs53l30.h
cx20442.c
cx20442.h
cx2072x.c
cx2072x.h
da7210.c
da7213.c
da7213.h
da7218.c
da7218.h
da7219-aad.c
da7219-aad.h
da7219.c
da7219.h
da732x.c
da732x.h
da732x_reg.h
da9055.c
dmic.c
es7134.c
es7241.c
es8311.c
es8311.h
es8316.c
es8316.h
es8326.c
es8326.h
es8328-i2c.c
es8328-spi.c
es8328.c
es8328.h
es83xx-dsm-common.c
es83xx-dsm-common.h
framer-codec.c
gtm601.c
hda-dai.c
hda.c
hda.h
hdac_hda.c
hdac_hda.h
hdac_hdmi.c
hdac_hdmi.h
hdmi-codec.c
ics43432.c
idt821034.c
inno_rk3036.c
inno_rk3036.h
isabelle.c
isabelle.h
jz4725b.c
jz4740.c
jz4760.c
jz4770.c
lm4857.c
lm49453.c
lm49453.h
lochnagar-sc.c
lpass-macro-common.c
lpass-macro-common.h
lpass-rx-macro.c
lpass-tx-macro.c
lpass-va-macro.c
lpass-wsa-macro.c
lpass-wsa-macro.h
madera.c
madera.h
max9759.c
max9768.c
max98088.c
max98088.h
max98090.c
max98090.h
max98095.c
max98095.h
max98357a.c
max98363.c
max98363.h
max98371.c
max98371.h
max98373-i2c.c
max98373-sdw.c
max98373-sdw.h
max98373.c
max98373.h
max98388.c
max98388.h
max98390.c
max98390.h
max98396.c
max98396.h
max9850.c
max9850.h
max98504.c
max98504.h
max98520.c
max98520.h
max9860.c
max9860.h
max9867.c
max9867.h
max9877.c
max9877.h
max98925.c
max98925.h
max98926.c
max98926.h
max98927.c
max98927.h
mc13783.c
mc13783.h
ml26124.c
ml26124.h
msm8916-wcd-analog.c
msm8916-wcd-digital.c
mt6351.c
mt6351.h
mt6358.c
mt6358.h
mt6359-accdet.c
mt6359-accdet.h
mt6359.c
mt6359.h
mt6660.c
mt6660.h
nau8315.c
nau8325.c
nau8325.h
nau8540.c
nau8540.h
nau8810.c
nau8810.h
nau8821.c
nau8821.h
nau8822.c
nau8822.h
nau8824.c
nau8824.h
nau8825.c
nau8825.h
pcm1681.c
pcm1789-i2c.c
pcm1789.c
pcm1789.h
pcm179x-i2c.c
pcm179x-spi.c
pcm179x.c
pcm179x.h
pcm186x-i2c.c
pcm186x-spi.c
pcm186x.c
pcm186x.h
pcm3008.c
pcm3008.h
pcm3060-i2c.c
pcm3060-spi.c
pcm3060.c
pcm3060.h
pcm3168a-i2c.c
pcm3168a-spi.c
pcm3168a.c
pcm3168a.h
pcm5102a.c
pcm512x-i2c.c
pcm512x-spi.c
pcm512x.c
pcm512x.h
pcm6240.c
pcm6240.h
peb2466.c
rk3308_codec.c
rk3308_codec.h
rk3328_codec.c
rk3328_codec.h
rk817_codec.c
rl6231.c
rl6231.h
rl6347a.c
rl6347a.h
rt1011.c
rt1011.h
rt1015.c
rt1015.h
rt1015p.c
rt1016.c
rt1016.h
rt1017-sdca-sdw.c
rt1017-sdca-sdw.h
rt1019.c
rt1019.h
rt1305.c
rt1305.h
rt1308-sdw.c
rt1308-sdw.h
rt1308.c
rt1308.h
rt1316-sdw.c
rt1316-sdw.h
rt1318-sdw.c
rt1318-sdw.h
rt1318.c
rt1318.h
rt1320-sdw.c
rt1320-sdw.h
rt274.c
rt274.h
rt286.c
rt286.h
rt298.c
rt298.h
rt5514-spi.c
rt5514-spi.h
rt5514.c
rt5514.h
rt5616.c
rt5616.h
rt5631.c
rt5631.h
rt5640.c
rt5640.h
rt5645.c
rt5645.h
rt5651.c
rt5651.h
rt5659.c
rt5659.h
rt5660.c
rt5660.h
rt5663.c
rt5663.h
rt5665.c
rt5665.h
rt5668.c
rt5668.h
rt5670-dsp.h
rt5670.c
rt5670.h
rt5677-spi.c
rt5677-spi.h
rt5677.c
rt5677.h
rt5682-i2c.c
rt5682-sdw.c
rt5682.c
rt5682.h
rt5682s.c
rt5682s.h
rt700-sdw.c
rt700-sdw.h
rt700.c
rt700.h
rt711-sdca-sdw.c
rt711-sdca-sdw.h
rt711-sdca.c
rt711-sdca.h
rt711-sdw.c
rt711-sdw.h
rt711.c
rt711.h
rt712-sdca-dmic.c
rt712-sdca-dmic.h
rt712-sdca-sdw.c
rt712-sdca-sdw.h
rt712-sdca.c
rt712-sdca.h
rt715-sdca-sdw.c
rt715-sdca-sdw.h
rt715-sdca.c
rt715-sdca.h
rt715-sdw.c
rt715-sdw.h
rt715.c
rt715.h
rt722-sdca-sdw.c
rt722-sdca-sdw.h
rt722-sdca.c
rt722-sdca.h
rt9120.c
rtq9128.c
sdw-mockup.c
sgtl5000.c
sgtl5000.h
si476x.c
sigmadsp-i2c.c
sigmadsp-regmap.c
sigmadsp.c
sigmadsp.h
simple-amplifier.c
simple-mux.c
sma1303.c
sma1303.h
spdif_receiver.c
spdif_transmitter.c
src4xxx-i2c.c
src4xxx.c
src4xxx.h
ssm2305.c
ssm2518.c
ssm2518.h
ssm2602-i2c.c
ssm2602-spi.c
ssm2602.c
ssm2602.h
ssm3515.c
ssm4567.c
sta32x.c
sta32x.h
sta350.c
sta350.h
sta529.c
stac9766.c
sti-sas.c
tas2552.c
tas2552.h
tas2562.c
tas2562.h
tas2764.c
tas2764.h
tas2770.c
tas2770.h
tas2780.c
tas2780.h
tas2781-comlib.c
tas2781-fmwlib.c
tas2781-i2c.c
tas5086.c
tas571x.c
tas571x.h
tas5720.c
tas5720.h
tas5805m.c
tas6424.c
tas6424.h
tda7419.c
tfa9879.c
tfa9879.h
tfa989x.c
tlv320adc3xxx.c
tlv320adcx140.c
tlv320adcx140.h
tlv320aic23-i2c.c
tlv320aic23-spi.c
tlv320aic23.c
tlv320aic23.h
tlv320aic26.c
tlv320aic26.h
tlv320aic31xx.c
tlv320aic31xx.h
tlv320aic32x4-clk.c
tlv320aic32x4-i2c.c
tlv320aic32x4-spi.c
tlv320aic32x4.c
tlv320aic32x4.h
tlv320aic3x-i2c.c
tlv320aic3x-spi.c
tlv320aic3x.c
tlv320aic3x.h
tlv320dac33.c
tlv320dac33.h
tpa6130a2.c
tpa6130a2.h
ts3a227e.c
ts3a227e.h
tscs42xx.c
tscs42xx.h
tscs454.c
tscs454.h
twl4030.c
twl6040.c
twl6040.h
uda1334.c
uda1380.c
uda1380.h
wcd-clsh-v2.c
wcd-clsh-v2.h
wcd-mbhc-v2.c
wcd-mbhc-v2.h
wcd9335.c
wcd9335.h
wcd934x.c
wcd937x-sdw.c
wcd937x.c
wcd937x.h
wcd938x-sdw.c
wcd938x.c
wcd938x.h
wcd939x-sdw.c
wcd939x.c
wcd939x.h
wl1273.c
wl1273.h
wm0010.c
wm1250-ev1.c
wm2000.c
wm2000.h
wm2200.c
wm2200.h
wm5100-tables.c
wm5100.c
wm5100.h
wm5102.c
wm5102.h
wm5110.c
wm5110.h
wm8350.c
wm8350.h
wm8400.c
wm8400.h
wm8510.c
wm8510.h
wm8523.c
wm8523.h
wm8524.c
wm8580.c
wm8580.h
wm8711.c
wm8711.h
wm8727.c
wm8728.c
wm8728.h
wm8731-i2c.c
wm8731-spi.c
wm8731.c
wm8731.h
wm8737.c
wm8737.h
wm8741.c
wm8741.h
wm8750.c
wm8750.h
wm8753.c
wm8753.h
wm8770.c
wm8770.h
wm8776.c
wm8776.h
wm8782.c
wm8804-i2c.c
wm8804-spi.c
wm8804.c
wm8804.h
wm8900.c
wm8900.h
wm8903.c
wm8903.h
wm8904.c
wm8904.h
wm8940.c
wm8940.h
wm8955.c
wm8955.h
wm8958-dsp2.c
wm8960.c
wm8960.h
wm8961.c
wm8961.h
wm8962.c
wm8962.h
wm8971.c
wm8971.h
wm8974.c
wm8974.h
wm8978.c
wm8978.h
wm8983.c
wm8983.h
wm8985.c
wm8985.h
wm8988.c
wm8988.h
wm8990.c
wm8990.h
wm8991.c
wm8991.h
wm8993.c
wm8993.h
wm8994.c
wm8994.h
wm8995.c
wm8995.h
wm8996.c
wm8996.h
wm8997.c
wm8997.h
wm8998.c
wm8998.h
wm9081.c
wm9081.h
wm9090.c
wm9090.h
wm9705.c
wm9712.c
wm9713.c
wm9713.h
wm_adsp.c
wm_adsp.h
wm_hubs.c
wm_hubs.h
wsa881x.c
wsa883x.c
wsa884x.c
zl38060.c
dwc
fsl
generic
google
hisilicon
img
intel
jz4740
kirkwood
loongson
mediatek
meson
mxs
pxa
qcom
rockchip
samsung
sdw_utils
sh
sof
spear
sprd
starfive
sti
stm
sunxi
tegra
ti
uniphier
ux500
xilinx
xtensa
Kconfig
Makefile
soc-ac97.c
soc-acpi.c
soc-card-test.c
soc-card.c
soc-component.c
soc-compress.c
soc-core.c
soc-dai.c
soc-dapm.c
soc-devres.c
soc-generic-dmaengine-pcm.c
soc-jack.c
soc-link.c
soc-ops.c
soc-pcm.c
soc-topology-test.c
soc-topology.c
soc-utils-test.c
soc-utils.c
sparc
spi
synth
usb
virtio
x86
xen
Kconfig
Makefile
ac97_bus.c
last.c
sound_core.c
tools
usr
virt
.clang-format
.cocciconfig
.editorconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
sound
/
soc
/
codecs
/
tas2781-comlib.c
Copy path
Blame
Blame
Latest commit
Linus Walleij
and
Mark Brown
ASoC: tas2781-i2c: Drop weird GPIO code
Aug 7, 2024
c2c0b67
·
Aug 7, 2024
History
History
550 lines (462 loc) · 12.5 KB
Breadcrumbs
linux
/
sound
/
soc
/
codecs
/
tas2781-comlib.c
Top
File metadata and controls
Code
Blame
550 lines (462 loc) · 12.5 KB
Raw
// SPDX-License-Identifier: GPL-2.0 // // TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers // // Copyright 2023 - 2024 Texas Instruments, Inc. // // Author: Shenghao Ding <shenghao-ding@ti.com> #include <linux/crc8.h> #include <linux/firmware.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/regmap.h> #include <linux/slab.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/tas2781.h> #define TASDEVICE_CRC8_POLYNOMIAL 0x4d static const struct regmap_range_cfg tasdevice_ranges[] = { { .range_min = 0, .range_max = 256 * 128, .selector_reg = TASDEVICE_PAGE_SELECT, .selector_mask = 0xff, .selector_shift = 0, .window_start = 0, .window_len = 128, }, }; static const struct regmap_config tasdevice_regmap = { .reg_bits = 8, .val_bits = 8, .cache_type = REGCACHE_NONE, .ranges = tasdevice_ranges, .num_ranges = ARRAY_SIZE(tasdevice_ranges), .max_register = 256 * 128, }; static int tasdevice_change_chn_book(struct tasdevice_priv *tas_priv, unsigned short chn, int book) { struct i2c_client *client = (struct i2c_client *)tas_priv->client; int ret = 0; if (chn < tas_priv->ndev) { struct tasdevice *tasdev = &tas_priv->tasdevice[chn]; struct regmap *map = tas_priv->regmap; if (client->addr != tasdev->dev_addr) { client->addr = tasdev->dev_addr; /* All tas2781s share the same regmap, clear the page * inside regmap once switching to another tas2781. * Register 0 at any pages and any books inside tas2781 * is the same one for page-switching. */ ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0); if (ret < 0) { dev_err(tas_priv->dev, "%s, E=%d channel:%d\n", __func__, ret, chn); goto out; } } if (tasdev->cur_book != book) { ret = regmap_write(map, TASDEVICE_BOOKCTL_REG, book); if (ret < 0) { dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); goto out; } tasdev->cur_book = book; } } else { ret = -EINVAL; dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); } out: return ret; } int tasdevice_dev_read(struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned int *val) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tasdevice_change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_read(map, TASDEVICE_PGRG(reg), val); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else { ret = -EINVAL; dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); } out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_read); int tasdevice_dev_write(struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned int value) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tasdevice_change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_write(map, TASDEVICE_PGRG(reg), value); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else { ret = -EINVAL; dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); } out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_write); int tasdevice_dev_bulk_write( struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned char *data, unsigned int len) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tasdevice_change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_bulk_write(map, TASDEVICE_PGRG(reg), data, len); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else { ret = -EINVAL; dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); } out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_write); int tasdevice_dev_bulk_read(struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned char *data, unsigned int len) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tasdevice_change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_bulk_read(map, TASDEVICE_PGRG(reg), data, len); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_read); int tasdevice_dev_update_bits( struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned int mask, unsigned int value) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tasdevice_change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_update_bits(map, TASDEVICE_PGRG(reg), mask, value); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else { dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); ret = -EINVAL; } out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_update_bits); struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c) { struct tasdevice_priv *tas_priv; tas_priv = devm_kzalloc(&i2c->dev, sizeof(*tas_priv), GFP_KERNEL); if (!tas_priv) return NULL; tas_priv->dev = &i2c->dev; tas_priv->client = (void *)i2c; return tas_priv; } EXPORT_SYMBOL_GPL(tasdevice_kzalloc); void tasdevice_reset(struct tasdevice_priv *tas_dev) { int ret, i; if (tas_dev->reset) { gpiod_set_value_cansleep(tas_dev->reset, 0); usleep_range(500, 1000); gpiod_set_value_cansleep(tas_dev->reset, 1); } else { for (i = 0; i < tas_dev->ndev; i++) { ret = tasdevice_dev_write(tas_dev, i, TASDEVICE_REG_SWRESET, TASDEVICE_REG_SWRESET_RESET); if (ret < 0) dev_err(tas_dev->dev, "dev %d swreset fail, %d\n", i, ret); } } usleep_range(1000, 1050); } EXPORT_SYMBOL_GPL(tasdevice_reset); int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, struct module *module, void (*cont)(const struct firmware *fw, void *context)) { int ret = 0; /* Codec Lock Hold to ensure that codec_probe and firmware parsing and * loading do not simultaneously execute. */ mutex_lock(&tas_priv->codec_lock); if (tas_priv->name_prefix) scnprintf(tas_priv->rca_binaryname, 64, "%s-%sRCA%d.bin", tas_priv->name_prefix, tas_priv->dev_name, tas_priv->ndev); else scnprintf(tas_priv->rca_binaryname, 64, "%sRCA%d.bin", tas_priv->dev_name, tas_priv->ndev); crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL); tas_priv->codec = codec; ret = request_firmware_nowait(module, FW_ACTION_UEVENT, tas_priv->rca_binaryname, tas_priv->dev, GFP_KERNEL, tas_priv, cont); if (ret) dev_err(tas_priv->dev, "request_firmware_nowait err:0x%08x\n", ret); /* Codec Lock Release*/ mutex_unlock(&tas_priv->codec_lock); return ret; } EXPORT_SYMBOL_GPL(tascodec_init); int tasdevice_init(struct tasdevice_priv *tas_priv) { int ret = 0; int i; tas_priv->regmap = devm_regmap_init_i2c(tas_priv->client, &tasdevice_regmap); if (IS_ERR(tas_priv->regmap)) { ret = PTR_ERR(tas_priv->regmap); dev_err(tas_priv->dev, "Failed to allocate register map: %d\n", ret); goto out; } tas_priv->cur_prog = -1; tas_priv->cur_conf = -1; for (i = 0; i < tas_priv->ndev; i++) { tas_priv->tasdevice[i].cur_book = -1; tas_priv->tasdevice[i].cur_prog = -1; tas_priv->tasdevice[i].cur_conf = -1; } mutex_init(&tas_priv->codec_lock); out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_init); static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog) { struct tasdevice_data *tas_dt; struct tasdev_blk *blk; unsigned int i; if (!prog) return; tas_dt = &(prog->dev_data); if (!tas_dt->dev_blks) return; for (i = 0; i < tas_dt->nr_blk; i++) { blk = &(tas_dt->dev_blks[i]); kfree(blk->data); } kfree(tas_dt->dev_blks); } static void tasdev_dsp_prog_remove(struct tasdevice_prog *prog, unsigned short nr) { int i; for (i = 0; i < nr; i++) tasdev_dsp_prog_blk_remove(&prog[i]); kfree(prog); } static void tasdev_dsp_cfg_blk_remove(struct tasdevice_config *cfg) { struct tasdevice_data *tas_dt; struct tasdev_blk *blk; unsigned int i; if (cfg) { tas_dt = &(cfg->dev_data); if (!tas_dt->dev_blks) return; for (i = 0; i < tas_dt->nr_blk; i++) { blk = &(tas_dt->dev_blks[i]); kfree(blk->data); } kfree(tas_dt->dev_blks); } } static void tasdev_dsp_cfg_remove(struct tasdevice_config *config, unsigned short nr) { int i; for (i = 0; i < nr; i++) tasdev_dsp_cfg_blk_remove(&config[i]); kfree(config); } void tasdevice_dsp_remove(void *context) { struct tasdevice_priv *tas_dev = (struct tasdevice_priv *) context; struct tasdevice_fw *tas_fmw = tas_dev->fmw; if (!tas_dev->fmw) return; if (tas_fmw->programs) tasdev_dsp_prog_remove(tas_fmw->programs, tas_fmw->nr_programs); if (tas_fmw->configs) tasdev_dsp_cfg_remove(tas_fmw->configs, tas_fmw->nr_configurations); kfree(tas_fmw); tas_dev->fmw = NULL; } EXPORT_SYMBOL_GPL(tasdevice_dsp_remove); void tasdevice_remove(struct tasdevice_priv *tas_priv) { mutex_destroy(&tas_priv->codec_lock); } EXPORT_SYMBOL_GPL(tasdevice_remove); int tasdevice_save_calibration(struct tasdevice_priv *tas_priv) { if (tas_priv->save_calibration) return tas_priv->save_calibration(tas_priv); return -EINVAL; } EXPORT_SYMBOL_GPL(tasdevice_save_calibration); void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv) { if (tas_priv->apply_calibration && tas_priv->cali_data.total_sz) tas_priv->apply_calibration(tas_priv); } EXPORT_SYMBOL_GPL(tasdevice_apply_calibration); static int tasdevice_clamp(int val, int max, unsigned int invert) { if (val > max) val = max; if (invert) val = max - val; if (val < 0) val = 0; return val; } int tasdevice_amp_putvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc) { unsigned int invert = mc->invert; unsigned char mask; int max = mc->max; int err_cnt = 0; int val, i, ret; mask = (1 << fls(max)) - 1; mask <<= mc->shift; val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert); for (i = 0; i < tas_priv->ndev; i++) { ret = tasdevice_dev_update_bits(tas_priv, i, mc->reg, mask, (unsigned int)(val << mc->shift)); if (!ret) continue; err_cnt++; dev_err(tas_priv->dev, "set AMP vol error in dev %d\n", i); } /* All the devices set error, return 0 */ return (err_cnt == tas_priv->ndev) ? 0 : 1; } EXPORT_SYMBOL_GPL(tasdevice_amp_putvol); int tasdevice_amp_getvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc) { unsigned int invert = mc->invert; unsigned char mask = 0; int max = mc->max; int ret = 0; int val; /* Read the primary device */ ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val); if (ret) { dev_err(tas_priv->dev, "%s, get AMP vol error\n", __func__); goto out; } mask = (1 << fls(max)) - 1; mask <<= mc->shift; val = (val & mask) >> mc->shift; val = tasdevice_clamp(val, max, invert); ucontrol->value.integer.value[0] = val; out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_amp_getvol); int tasdevice_digital_putvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc) { unsigned int invert = mc->invert; int max = mc->max; int err_cnt = 0; int ret; int val, i; val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert); for (i = 0; i < tas_priv->ndev; i++) { ret = tasdevice_dev_write(tas_priv, i, mc->reg, (unsigned int)val); if (!ret) continue; err_cnt++; dev_err(tas_priv->dev, "set digital vol err in dev %d\n", i); } /* All the devices set error, return 0 */ return (err_cnt == tas_priv->ndev) ? 0 : 1; } EXPORT_SYMBOL_GPL(tasdevice_digital_putvol); int tasdevice_digital_getvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc) { unsigned int invert = mc->invert; int max = mc->max; int ret, val; /* Read the primary device as the whole */ ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val); if (ret) { dev_err(tas_priv->dev, "%s, get digital vol error\n", __func__); goto out; } val = tasdevice_clamp(val, max, invert); ucontrol->value.integer.value[0] = val; out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_digital_getvol); MODULE_DESCRIPTION("TAS2781 common library"); MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>"); MODULE_LICENSE("GPL");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
You can’t perform that action at this time.