diff options
| author | Linus Torvalds <[email protected]> | 2019-07-09 09:59:43 -0700 |
|---|---|---|
| committer | Linus Torvalds <[email protected]> | 2019-07-09 09:59:43 -0700 |
| commit | 4cdd5f9186bbe80306e76f11da7ecb0b9720433c (patch) | |
| tree | 23c2f39933cd8253a65385eab00405beaf602f01 /sound/soc/sunxi/sun4i-i2s.c | |
| parent | 2d41ef5432b76ae90dc0db93026f1d981f874ec4 (diff) | |
| parent | 0dcb4efb1095d0a1f5f681c2b94e98b009cc5d77 (diff) | |
Merge tag 'sound-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"Many updates in this development cycle are found in ASoC where it got
a wide range of changes for the continued refactoring.
Some highlights are below.
ASoC:
- Continued refactoring work by Morimoto-san toward the full
componentization; the changes are seen allover the places
- Support for force disconnecting muxes in DAPM
- Continued development of ASoC Intel SOF stuff
- New drivers for Cirrus Logic CS47L35, CS47L85 and CS47L90, Conexant
CX2072X, Realtek RT1011 and RT1308
HD-audio:
- More fixes and adjustments for ASoC SOF HD-audio
- Fix for resume problem on some Realtek codecs
USB-audio:
- A few fixes for the issues reported by syzbot USB fuzzer
- Fix for UAC2 extension unit parser
- Quirks for Line6 Helix, Emgaic Unitor 8
FireWire:
- Lots of code refactoring and fixes in most of its components"
* tag 'sound-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (626 commits)
ALSA: firewire-lib: code refactoring for local variables
ALSA: firewire-lib: code refactoring for post operation to data block counter
ALSA: firewire-lib: code refactoring for error path of parser for CIP header
ALSA: firewire-lib: fix different data block counter between probed event and transferred isochronous packet
ALSA: firewire-lib: fix initial value of data block count for IR context without CIP_DBC_IS_END_EVENT
ALSA: firewire-lib/fireface: fix initial value of data block counter for IR context with CIP_NO_HEADER
ALSA: firewire-lib: fix invalid length of rx packet payload for tracepoint events
ALSA: usb-audio: fix Line6 Helix audio format rates
firewire-motu: fix wrong reference count for stream functionality at error path of rawmidi interface
ALSA: firewire-digi00x: fix wrong reference count for stream functionality at error path of rawmidi interface
ALSA: dice: fix wrong reference count for stream functionality at error path of rawmidi interface
ALSA: oxfw: fix wrong reference count for stream functionality at error path of rawmidi interface
ALSA: fireworks: fix wrong reference count for stream functionality at error path of rawmidi interface
ALSA: bebob: fix wrong reference count for stream functionality at error path of rawmidi interface
ASoC: SOF: Intel: implement runtime idle for CNL/APL
ASoC: SOF: add runtime idle callback
ASoC: hdac_hdmi: report codec link up/down status to bus
ASoC: SOF: debug: fix possible memory leak in sof_dfsentry_write()
ASoC: sunxi: sun50i-codec-analog: Add earpiece
ASoC: rt5665: remove redundant assignment to variable idx
...
Diffstat (limited to 'sound/soc/sunxi/sun4i-i2s.c')
| -rw-r--r-- | sound/soc/sunxi/sun4i-i2s.c | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index fd7c37596f21..9b2232908b65 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -114,6 +114,8 @@ #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 +struct sun4i_i2s; + /** * struct sun4i_i2s_quirks - Differences between SoC variants. * @@ -127,7 +129,6 @@ * @sun4i_i2s_regmap: regmap config to use. * @mclk_offset: Value by which mclkdiv needs to be adjusted. * @bclk_offset: Value by which bclkdiv needs to be adjusted. - * @fmt_offset: Value by which wss and sr needs to be adjusted. * @field_clkdiv_mclk_en: regmap field to enable mclk output. * @field_fmt_wss: regmap field to set word select size. * @field_fmt_sr: regmap field to set sample resolution. @@ -150,7 +151,6 @@ struct sun4i_i2s_quirks { const struct regmap_config *sun4i_i2s_regmap; unsigned int mclk_offset; unsigned int bclk_offset; - unsigned int fmt_offset; /* Register fields for i2s */ struct reg_field field_clkdiv_mclk_en; @@ -163,6 +163,9 @@ struct sun4i_i2s_quirks { struct reg_field field_rxchanmap; struct reg_field field_txchansel; struct reg_field field_rxchansel; + + s8 (*get_sr)(const struct sun4i_i2s *, int); + s8 (*get_wss)(const struct sun4i_i2s *, int); }; struct sun4i_i2s { @@ -345,6 +348,39 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, return 0; } +static s8 sun4i_i2s_get_sr(const struct sun4i_i2s *i2s, int width) +{ + if (width < 16 || width > 24) + return -EINVAL; + + if (width % 4) + return -EINVAL; + + return (width - 16) / 4; +} + +static s8 sun4i_i2s_get_wss(const struct sun4i_i2s *i2s, int width) +{ + if (width < 16 || width > 32) + return -EINVAL; + + if (width % 4) + return -EINVAL; + + return (width - 16) / 4; +} + +static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width) +{ + if (width % 4) + return -EINVAL; + + if (width < 8 || width > 32) + return -EINVAL; + + return (width - 8) / 4 + 1; +} + static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -396,22 +432,16 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, } i2s->playback_dma_data.addr_width = width; - switch (params_width(params)) { - case 16: - sr = 0; - wss = 0; - break; + sr = i2s->variant->get_sr(i2s, params_width(params)); + if (sr < 0) + return -EINVAL; - default: - dev_err(dai->dev, "Unsupported sample width: %d\n", - params_width(params)); + wss = i2s->variant->get_wss(i2s, params_width(params)); + if (wss < 0) return -EINVAL; - } - regmap_field_write(i2s->field_fmt_wss, - wss + i2s->variant->fmt_offset); - regmap_field_write(i2s->field_fmt_sr, - sr + i2s->variant->fmt_offset); + regmap_field_write(i2s->field_fmt_wss, wss); + regmap_field_write(i2s->field_fmt_sr, sr); return sun4i_i2s_set_clk_rate(dai, params_rate(params), params_width(params)); @@ -891,6 +921,8 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun4i_i2s_get_sr, + .get_wss = sun4i_i2s_get_wss, }; static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { @@ -908,6 +940,8 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun4i_i2s_get_sr, + .get_wss = sun4i_i2s_get_wss, }; static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { @@ -925,6 +959,8 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { @@ -933,7 +969,6 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, .mclk_offset = 1, .bclk_offset = 2, - .fmt_offset = 3, .has_fmt_set_lrck_period = true, .has_chcfg = true, .has_chsel_tx_chen = true, @@ -948,6 +983,8 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { @@ -965,6 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static int sun4i_i2s_init_regmap_fields(struct device *dev, |