diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/st,stm32-sai.txt | 12 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/sun4i-i2s.txt | 2 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/tas5720.txt | 4 | ||||
-rw-r--r-- | include/sound/soc-dai.h | 3 | ||||
-rw-r--r-- | sound/soc/codecs/tas5720.c | 61 | ||||
-rw-r--r-- | sound/soc/codecs/tas5720.h | 31 | ||||
-rw-r--r-- | sound/soc/codecs/wm2200.c | 9 | ||||
-rw-r--r-- | sound/soc/stm/stm32_sai.c | 114 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-codec.c | 29 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-i2s.c | 57 |
10 files changed, 195 insertions, 127 deletions
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt index 1f9cd7095337..b1acc1a256ba 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt +++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt | |||
@@ -20,11 +20,6 @@ Required properties: | |||
20 | 20 | ||
21 | Optional properties: | 21 | Optional properties: |
22 | - resets: Reference to a reset controller asserting the SAI | 22 | - resets: Reference to a reset controller asserting the SAI |
23 | - st,sync: specify synchronization mode. | ||
24 | By default SAI sub-block is in asynchronous mode. | ||
25 | This property sets SAI sub-block as slave of another SAI sub-block. | ||
26 | Must contain the phandle and index of the sai sub-block providing | ||
27 | the synchronization. | ||
28 | 23 | ||
29 | SAI subnodes: | 24 | SAI subnodes: |
30 | Two subnodes corresponding to SAI sub-block instances A et B can be defined. | 25 | Two subnodes corresponding to SAI sub-block instances A et B can be defined. |
@@ -44,6 +39,13 @@ SAI subnodes required properties: | |||
44 | - pinctrl-names: should contain only value "default" | 39 | - pinctrl-names: should contain only value "default" |
45 | - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt | 40 | - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt |
46 | 41 | ||
42 | SAI subnodes Optional properties: | ||
43 | - st,sync: specify synchronization mode. | ||
44 | By default SAI sub-block is in asynchronous mode. | ||
45 | This property sets SAI sub-block as slave of another SAI sub-block. | ||
46 | Must contain the phandle and index of the sai sub-block providing | ||
47 | the synchronization. | ||
48 | |||
47 | The device node should contain one 'port' child node with one child 'endpoint' | 49 | The device node should contain one 'port' child node with one child 'endpoint' |
48 | node, according to the bindings defined in Documentation/devicetree/bindings/ | 50 | node, according to the bindings defined in Documentation/devicetree/bindings/ |
49 | graph.txt. | 51 | graph.txt. |
diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt index 05d7135a8d2f..b9d50d6cdef3 100644 --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt +++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt | |||
@@ -8,6 +8,7 @@ Required properties: | |||
8 | - compatible: should be one of the following: | 8 | - compatible: should be one of the following: |
9 | - "allwinner,sun4i-a10-i2s" | 9 | - "allwinner,sun4i-a10-i2s" |
10 | - "allwinner,sun6i-a31-i2s" | 10 | - "allwinner,sun6i-a31-i2s" |
11 | - "allwinner,sun8i-a83t-i2s" | ||
11 | - "allwinner,sun8i-h3-i2s" | 12 | - "allwinner,sun8i-h3-i2s" |
12 | - reg: physical base address of the controller and length of memory mapped | 13 | - reg: physical base address of the controller and length of memory mapped |
13 | region. | 14 | region. |
@@ -23,6 +24,7 @@ Required properties: | |||
23 | 24 | ||
24 | Required properties for the following compatibles: | 25 | Required properties for the following compatibles: |
25 | - "allwinner,sun6i-a31-i2s" | 26 | - "allwinner,sun6i-a31-i2s" |
27 | - "allwinner,sun8i-a83t-i2s" | ||
26 | - "allwinner,sun8i-h3-i2s" | 28 | - "allwinner,sun8i-h3-i2s" |
27 | - resets: phandle to the reset line for this codec | 29 | - resets: phandle to the reset line for this codec |
28 | 30 | ||
diff --git a/Documentation/devicetree/bindings/sound/tas5720.txt b/Documentation/devicetree/bindings/sound/tas5720.txt index 40d94f82beb3..7481653fe8e3 100644 --- a/Documentation/devicetree/bindings/sound/tas5720.txt +++ b/Documentation/devicetree/bindings/sound/tas5720.txt | |||
@@ -6,10 +6,12 @@ audio playback. For more product information please see the links below: | |||
6 | 6 | ||
7 | http://www.ti.com/product/TAS5720L | 7 | http://www.ti.com/product/TAS5720L |
8 | http://www.ti.com/product/TAS5720M | 8 | http://www.ti.com/product/TAS5720M |
9 | http://www.ti.com/product/TAS5722L | ||
9 | 10 | ||
10 | Required properties: | 11 | Required properties: |
11 | 12 | ||
12 | - compatible : "ti,tas5720" | 13 | - compatible : "ti,tas5720", |
14 | "ti,tas5722" | ||
13 | - reg : I2C slave address | 15 | - reg : I2C slave address |
14 | - dvdd-supply : phandle to a 3.3-V supply for the digital circuitry | 16 | - dvdd-supply : phandle to a 3.3-V supply for the digital circuitry |
15 | - pvdd-supply : phandle to a supply used for the Class-D amp and the analog | 17 | - pvdd-supply : phandle to a supply used for the Class-D amp and the analog |
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index d970879944fc..8ad11669e4d8 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
@@ -296,9 +296,6 @@ struct snd_soc_dai { | |||
296 | /* DAI runtime info */ | 296 | /* DAI runtime info */ |
297 | unsigned int capture_active:1; /* stream is in use */ | 297 | unsigned int capture_active:1; /* stream is in use */ |
298 | unsigned int playback_active:1; /* stream is in use */ | 298 | unsigned int playback_active:1; /* stream is in use */ |
299 | unsigned int symmetric_rates:1; | ||
300 | unsigned int symmetric_channels:1; | ||
301 | unsigned int symmetric_samplebits:1; | ||
302 | unsigned int probed:1; | 299 | unsigned int probed:1; |
303 | 300 | ||
304 | unsigned int active; | 301 | unsigned int active; |
diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index a736a2a6976c..f3006f301fe8 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c | |||
@@ -36,6 +36,11 @@ | |||
36 | /* Define how often to check (and clear) the fault status register (in ms) */ | 36 | /* Define how often to check (and clear) the fault status register (in ms) */ |
37 | #define TAS5720_FAULT_CHECK_INTERVAL 200 | 37 | #define TAS5720_FAULT_CHECK_INTERVAL 200 |
38 | 38 | ||
39 | enum tas572x_type { | ||
40 | TAS5720, | ||
41 | TAS5722, | ||
42 | }; | ||
43 | |||
39 | static const char * const tas5720_supply_names[] = { | 44 | static const char * const tas5720_supply_names[] = { |
40 | "dvdd", /* Digital power supply. Connect to 3.3-V supply. */ | 45 | "dvdd", /* Digital power supply. Connect to 3.3-V supply. */ |
41 | "pvdd", /* Class-D amp and analog power supply (connected). */ | 46 | "pvdd", /* Class-D amp and analog power supply (connected). */ |
@@ -47,6 +52,7 @@ struct tas5720_data { | |||
47 | struct snd_soc_codec *codec; | 52 | struct snd_soc_codec *codec; |
48 | struct regmap *regmap; | 53 | struct regmap *regmap; |
49 | struct i2c_client *tas5720_client; | 54 | struct i2c_client *tas5720_client; |
55 | enum tas572x_type devtype; | ||
50 | struct regulator_bulk_data supplies[TAS5720_NUM_SUPPLIES]; | 56 | struct regulator_bulk_data supplies[TAS5720_NUM_SUPPLIES]; |
51 | struct delayed_work fault_check_work; | 57 | struct delayed_work fault_check_work; |
52 | unsigned int last_fault; | 58 | unsigned int last_fault; |
@@ -264,7 +270,7 @@ out: | |||
264 | static int tas5720_codec_probe(struct snd_soc_codec *codec) | 270 | static int tas5720_codec_probe(struct snd_soc_codec *codec) |
265 | { | 271 | { |
266 | struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); | 272 | struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); |
267 | unsigned int device_id; | 273 | unsigned int device_id, expected_device_id; |
268 | int ret; | 274 | int ret; |
269 | 275 | ||
270 | tas5720->codec = codec; | 276 | tas5720->codec = codec; |
@@ -276,6 +282,11 @@ static int tas5720_codec_probe(struct snd_soc_codec *codec) | |||
276 | return ret; | 282 | return ret; |
277 | } | 283 | } |
278 | 284 | ||
285 | /* | ||
286 | * Take a liberal approach to checking the device ID to allow the | ||
287 | * driver to be used even if the device ID does not match, however | ||
288 | * issue a warning if there is a mismatch. | ||
289 | */ | ||
279 | ret = regmap_read(tas5720->regmap, TAS5720_DEVICE_ID_REG, &device_id); | 290 | ret = regmap_read(tas5720->regmap, TAS5720_DEVICE_ID_REG, &device_id); |
280 | if (ret < 0) { | 291 | if (ret < 0) { |
281 | dev_err(codec->dev, "failed to read device ID register: %d\n", | 292 | dev_err(codec->dev, "failed to read device ID register: %d\n", |
@@ -283,13 +294,22 @@ static int tas5720_codec_probe(struct snd_soc_codec *codec) | |||
283 | goto probe_fail; | 294 | goto probe_fail; |
284 | } | 295 | } |
285 | 296 | ||
286 | if (device_id != TAS5720_DEVICE_ID) { | 297 | switch (tas5720->devtype) { |
287 | dev_err(codec->dev, "wrong device ID. expected: %u read: %u\n", | 298 | case TAS5720: |
288 | TAS5720_DEVICE_ID, device_id); | 299 | expected_device_id = TAS5720_DEVICE_ID; |
289 | ret = -ENODEV; | 300 | break; |
290 | goto probe_fail; | 301 | case TAS5722: |
302 | expected_device_id = TAS5722_DEVICE_ID; | ||
303 | break; | ||
304 | default: | ||
305 | dev_err(codec->dev, "unexpected private driver data\n"); | ||
306 | return -EINVAL; | ||
291 | } | 307 | } |
292 | 308 | ||
309 | if (device_id != expected_device_id) | ||
310 | dev_warn(codec->dev, "wrong device ID. expected: %u read: %u\n", | ||
311 | expected_device_id, device_id); | ||
312 | |||
293 | /* Set device to mute */ | 313 | /* Set device to mute */ |
294 | ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, | 314 | ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, |
295 | TAS5720_MUTE, TAS5720_MUTE); | 315 | TAS5720_MUTE, TAS5720_MUTE); |
@@ -446,6 +466,15 @@ static const struct regmap_config tas5720_regmap_config = { | |||
446 | .volatile_reg = tas5720_is_volatile_reg, | 466 | .volatile_reg = tas5720_is_volatile_reg, |
447 | }; | 467 | }; |
448 | 468 | ||
469 | static const struct regmap_config tas5722_regmap_config = { | ||
470 | .reg_bits = 8, | ||
471 | .val_bits = 8, | ||
472 | |||
473 | .max_register = TAS5722_MAX_REG, | ||
474 | .cache_type = REGCACHE_RBTREE, | ||
475 | .volatile_reg = tas5720_is_volatile_reg, | ||
476 | }; | ||
477 | |||
449 | /* | 478 | /* |
450 | * DAC analog gain. There are four discrete values to select from, ranging | 479 | * DAC analog gain. There are four discrete values to select from, ranging |
451 | * from 19.2 dB to 26.3dB. | 480 | * from 19.2 dB to 26.3dB. |
@@ -544,6 +573,7 @@ static int tas5720_probe(struct i2c_client *client, | |||
544 | { | 573 | { |
545 | struct device *dev = &client->dev; | 574 | struct device *dev = &client->dev; |
546 | struct tas5720_data *data; | 575 | struct tas5720_data *data; |
576 | const struct regmap_config *regmap_config; | ||
547 | int ret; | 577 | int ret; |
548 | int i; | 578 | int i; |
549 | 579 | ||
@@ -552,7 +582,20 @@ static int tas5720_probe(struct i2c_client *client, | |||
552 | return -ENOMEM; | 582 | return -ENOMEM; |
553 | 583 | ||
554 | data->tas5720_client = client; | 584 | data->tas5720_client = client; |
555 | data->regmap = devm_regmap_init_i2c(client, &tas5720_regmap_config); | 585 | data->devtype = id->driver_data; |
586 | |||
587 | switch (id->driver_data) { | ||
588 | case TAS5720: | ||
589 | regmap_config = &tas5720_regmap_config; | ||
590 | break; | ||
591 | case TAS5722: | ||
592 | regmap_config = &tas5722_regmap_config; | ||
593 | break; | ||
594 | default: | ||
595 | dev_err(dev, "unexpected private driver data\n"); | ||
596 | return -EINVAL; | ||
597 | } | ||
598 | data->regmap = devm_regmap_init_i2c(client, regmap_config); | ||
556 | if (IS_ERR(data->regmap)) { | 599 | if (IS_ERR(data->regmap)) { |
557 | ret = PTR_ERR(data->regmap); | 600 | ret = PTR_ERR(data->regmap); |
558 | dev_err(dev, "failed to allocate register map: %d\n", ret); | 601 | dev_err(dev, "failed to allocate register map: %d\n", ret); |
@@ -592,7 +635,8 @@ static int tas5720_remove(struct i2c_client *client) | |||
592 | } | 635 | } |
593 | 636 | ||
594 | static const struct i2c_device_id tas5720_id[] = { | 637 | static const struct i2c_device_id tas5720_id[] = { |
595 | { "tas5720", 0 }, | 638 | { "tas5720", TAS5720 }, |
639 | { "tas5722", TAS5722 }, | ||
596 | { } | 640 | { } |
597 | }; | 641 | }; |
598 | MODULE_DEVICE_TABLE(i2c, tas5720_id); | 642 | MODULE_DEVICE_TABLE(i2c, tas5720_id); |
@@ -600,6 +644,7 @@ MODULE_DEVICE_TABLE(i2c, tas5720_id); | |||
600 | #if IS_ENABLED(CONFIG_OF) | 644 | #if IS_ENABLED(CONFIG_OF) |
601 | static const struct of_device_id tas5720_of_match[] = { | 645 | static const struct of_device_id tas5720_of_match[] = { |
602 | { .compatible = "ti,tas5720", }, | 646 | { .compatible = "ti,tas5720", }, |
647 | { .compatible = "ti,tas5722", }, | ||
603 | { }, | 648 | { }, |
604 | }; | 649 | }; |
605 | MODULE_DEVICE_TABLE(of, tas5720_of_match); | 650 | MODULE_DEVICE_TABLE(of, tas5720_of_match); |
diff --git a/sound/soc/codecs/tas5720.h b/sound/soc/codecs/tas5720.h index 3d077c779b12..1dda3095961d 100644 --- a/sound/soc/codecs/tas5720.h +++ b/sound/soc/codecs/tas5720.h | |||
@@ -30,8 +30,14 @@ | |||
30 | #define TAS5720_DIGITAL_CLIP1_REG 0x11 | 30 | #define TAS5720_DIGITAL_CLIP1_REG 0x11 |
31 | #define TAS5720_MAX_REG TAS5720_DIGITAL_CLIP1_REG | 31 | #define TAS5720_MAX_REG TAS5720_DIGITAL_CLIP1_REG |
32 | 32 | ||
33 | /* Additional TAS5722-specific Registers */ | ||
34 | #define TAS5722_DIGITAL_CTRL2_REG 0x13 | ||
35 | #define TAS5722_ANALOG_CTRL2_REG 0x14 | ||
36 | #define TAS5722_MAX_REG TAS5722_ANALOG_CTRL2_REG | ||
37 | |||
33 | /* TAS5720_DEVICE_ID_REG */ | 38 | /* TAS5720_DEVICE_ID_REG */ |
34 | #define TAS5720_DEVICE_ID 0x01 | 39 | #define TAS5720_DEVICE_ID 0x01 |
40 | #define TAS5722_DEVICE_ID 0x12 | ||
35 | 41 | ||
36 | /* TAS5720_POWER_CTRL_REG */ | 42 | /* TAS5720_POWER_CTRL_REG */ |
37 | #define TAS5720_DIG_CLIP_MASK GENMASK(7, 2) | 43 | #define TAS5720_DIG_CLIP_MASK GENMASK(7, 2) |
@@ -51,6 +57,7 @@ | |||
51 | #define TAS5720_SAIF_FORMAT_MASK GENMASK(2, 0) | 57 | #define TAS5720_SAIF_FORMAT_MASK GENMASK(2, 0) |
52 | 58 | ||
53 | /* TAS5720_DIGITAL_CTRL2_REG */ | 59 | /* TAS5720_DIGITAL_CTRL2_REG */ |
60 | #define TAS5722_VOL_RAMP_RATE BIT(6) | ||
54 | #define TAS5720_MUTE BIT(4) | 61 | #define TAS5720_MUTE BIT(4) |
55 | #define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0) | 62 | #define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0) |
56 | 63 | ||
@@ -87,4 +94,28 @@ | |||
87 | #define TAS5720_CLIP1_MASK GENMASK(7, 2) | 94 | #define TAS5720_CLIP1_MASK GENMASK(7, 2) |
88 | #define TAS5720_CLIP1_SHIFT (0x2) | 95 | #define TAS5720_CLIP1_SHIFT (0x2) |
89 | 96 | ||
97 | /* TAS5722_DIGITAL_CTRL2_REG */ | ||
98 | #define TAS5722_HPF_3_7HZ (0x0 << 5) | ||
99 | #define TAS5722_HPF_7_4HZ (0x1 << 5) | ||
100 | #define TAS5722_HPF_14_9HZ (0x2 << 5) | ||
101 | #define TAS5722_HPF_29_7HZ (0x3 << 5) | ||
102 | #define TAS5722_HPF_59_4HZ (0x4 << 5) | ||
103 | #define TAS5722_HPF_118_4HZ (0x5 << 5) | ||
104 | #define TAS5722_HPF_235_0HZ (0x6 << 5) | ||
105 | #define TAS5722_HPF_463_2HZ (0x7 << 5) | ||
106 | #define TAS5722_HPF_MASK GENMASK(7, 5) | ||
107 | #define TAS5722_AUTO_SLEEP_OFF (0x0 << 3) | ||
108 | #define TAS5722_AUTO_SLEEP_1024LR (0x1 << 3) | ||
109 | #define TAS5722_AUTO_SLEEP_65536LR (0x2 << 3) | ||
110 | #define TAS5722_AUTO_SLEEP_262144LR (0x3 << 3) | ||
111 | #define TAS5722_AUTO_SLEEP_MASK GENMASK(4, 3) | ||
112 | #define TAS5722_TDM_SLOT_16B BIT(2) | ||
113 | #define TAS5722_MCLK_PIN_CFG BIT(1) | ||
114 | #define TAS5722_VOL_CONTROL_LSB BIT(0) | ||
115 | |||
116 | /* TAS5722_ANALOG_CTRL2_REG */ | ||
117 | #define TAS5722_FAULTZ_PU BIT(3) | ||
118 | #define TAS5722_VREG_LVL BIT(2) | ||
119 | #define TAS5722_PWR_TUNE BIT(0) | ||
120 | |||
90 | #endif /* __TAS5720_H__ */ | 121 | #endif /* __TAS5720_H__ */ |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index d83dab57a1d1..5c2f5727244d 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -98,6 +98,8 @@ struct wm2200_priv { | |||
98 | 98 | ||
99 | int rev; | 99 | int rev; |
100 | int sysclk; | 100 | int sysclk; |
101 | |||
102 | unsigned int symmetric_rates:1; | ||
101 | }; | 103 | }; |
102 | 104 | ||
103 | #define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1) | 105 | #define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1) |
@@ -1550,7 +1552,7 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = { | |||
1550 | 1552 | ||
1551 | static int wm2200_probe(struct snd_soc_codec *codec) | 1553 | static int wm2200_probe(struct snd_soc_codec *codec) |
1552 | { | 1554 | { |
1553 | struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev); | 1555 | struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); |
1554 | int ret; | 1556 | int ret; |
1555 | 1557 | ||
1556 | wm2200->codec = codec; | 1558 | wm2200->codec = codec; |
@@ -1758,7 +1760,7 @@ static int wm2200_hw_params(struct snd_pcm_substream *substream, | |||
1758 | lrclk = bclk_rates[bclk] / params_rate(params); | 1760 | lrclk = bclk_rates[bclk] / params_rate(params); |
1759 | dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); | 1761 | dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); |
1760 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || | 1762 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || |
1761 | dai->symmetric_rates) | 1763 | wm2200->symmetric_rates) |
1762 | snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7, | 1764 | snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7, |
1763 | WM2200_AIF1RX_BCPF_MASK, lrclk); | 1765 | WM2200_AIF1RX_BCPF_MASK, lrclk); |
1764 | else | 1766 | else |
@@ -2059,13 +2061,14 @@ static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2059 | static int wm2200_dai_probe(struct snd_soc_dai *dai) | 2061 | static int wm2200_dai_probe(struct snd_soc_dai *dai) |
2060 | { | 2062 | { |
2061 | struct snd_soc_codec *codec = dai->codec; | 2063 | struct snd_soc_codec *codec = dai->codec; |
2064 | struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); | ||
2062 | unsigned int val = 0; | 2065 | unsigned int val = 0; |
2063 | int ret; | 2066 | int ret; |
2064 | 2067 | ||
2065 | ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1); | 2068 | ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1); |
2066 | if (ret >= 0) { | 2069 | if (ret >= 0) { |
2067 | if ((ret & WM2200_GP1_FN_MASK) != 0) { | 2070 | if ((ret & WM2200_GP1_FN_MASK) != 0) { |
2068 | dai->symmetric_rates = true; | 2071 | wm2200->symmetric_rates = true; |
2069 | val = WM2200_AIF1TX_LRCLK_SRC; | 2072 | val = WM2200_AIF1TX_LRCLK_SRC; |
2070 | } | 2073 | } |
2071 | } else { | 2074 | } else { |
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index d6f71a3406e9..d743b7dd52fb 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c | |||
@@ -28,16 +28,6 @@ | |||
28 | 28 | ||
29 | #include "stm32_sai.h" | 29 | #include "stm32_sai.h" |
30 | 30 | ||
31 | static LIST_HEAD(sync_providers); | ||
32 | static DEFINE_MUTEX(sync_mutex); | ||
33 | |||
34 | struct sync_provider { | ||
35 | struct list_head link; | ||
36 | struct device_node *node; | ||
37 | int (*sync_conf)(void *data, int synco); | ||
38 | void *data; | ||
39 | }; | ||
40 | |||
41 | static const struct stm32_sai_conf stm32_sai_conf_f4 = { | 31 | static const struct stm32_sai_conf stm32_sai_conf_f4 = { |
42 | .version = SAI_STM32F4, | 32 | .version = SAI_STM32F4, |
43 | }; | 33 | }; |
@@ -70,9 +60,8 @@ static int stm32_sai_sync_conf_client(struct stm32_sai_data *sai, int synci) | |||
70 | return 0; | 60 | return 0; |
71 | } | 61 | } |
72 | 62 | ||
73 | static int stm32_sai_sync_conf_provider(void *data, int synco) | 63 | static int stm32_sai_sync_conf_provider(struct stm32_sai_data *sai, int synco) |
74 | { | 64 | { |
75 | struct stm32_sai_data *sai = (struct stm32_sai_data *)data; | ||
76 | u32 prev_synco; | 65 | u32 prev_synco; |
77 | int ret; | 66 | int ret; |
78 | 67 | ||
@@ -103,83 +92,42 @@ static int stm32_sai_sync_conf_provider(void *data, int synco) | |||
103 | return 0; | 92 | return 0; |
104 | } | 93 | } |
105 | 94 | ||
106 | static int stm32_sai_set_sync_provider(struct device_node *np, int synco) | 95 | static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, |
96 | struct device_node *np_provider, | ||
97 | int synco, int synci) | ||
107 | { | 98 | { |
108 | struct sync_provider *provider; | 99 | struct platform_device *pdev = of_find_device_by_node(np_provider); |
100 | struct stm32_sai_data *sai_provider; | ||
109 | int ret; | 101 | int ret; |
110 | 102 | ||
111 | mutex_lock(&sync_mutex); | 103 | if (!pdev) { |
112 | list_for_each_entry(provider, &sync_providers, link) { | 104 | dev_err(&sai_client->pdev->dev, |
113 | if (provider->node == np) { | 105 | "Device not found for node %s\n", np_provider->name); |
114 | ret = provider->sync_conf(provider->data, synco); | 106 | return -ENODEV; |
115 | mutex_unlock(&sync_mutex); | ||
116 | return ret; | ||
117 | } | ||
118 | } | 107 | } |
119 | mutex_unlock(&sync_mutex); | ||
120 | 108 | ||
121 | /* SAI sync provider not found */ | 109 | sai_provider = platform_get_drvdata(pdev); |
122 | return -ENODEV; | 110 | if (!sai_provider) { |
123 | } | 111 | dev_err(&sai_client->pdev->dev, |
124 | 112 | "SAI sync provider data not found\n"); | |
125 | static int stm32_sai_set_sync(struct stm32_sai_data *sai, | 113 | return -EINVAL; |
126 | struct device_node *np_provider, | 114 | } |
127 | int synco, int synci) | ||
128 | { | ||
129 | int ret; | ||
130 | 115 | ||
131 | /* Configure sync client */ | 116 | /* Configure sync client */ |
132 | stm32_sai_sync_conf_client(sai, synci); | 117 | ret = stm32_sai_sync_conf_client(sai_client, synci); |
118 | if (ret < 0) | ||
119 | return ret; | ||
133 | 120 | ||
134 | /* Configure sync provider */ | 121 | /* Configure sync provider */ |
135 | ret = stm32_sai_set_sync_provider(np_provider, synco); | 122 | return stm32_sai_sync_conf_provider(sai_provider, synco); |
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | static int stm32_sai_sync_add_provider(struct platform_device *pdev, | ||
141 | void *data) | ||
142 | { | ||
143 | struct sync_provider *sp; | ||
144 | |||
145 | sp = devm_kzalloc(&pdev->dev, sizeof(*sp), GFP_KERNEL); | ||
146 | if (!sp) | ||
147 | return -ENOMEM; | ||
148 | |||
149 | sp->node = of_node_get(pdev->dev.of_node); | ||
150 | sp->data = data; | ||
151 | sp->sync_conf = &stm32_sai_sync_conf_provider; | ||
152 | |||
153 | mutex_lock(&sync_mutex); | ||
154 | list_add(&sp->link, &sync_providers); | ||
155 | mutex_unlock(&sync_mutex); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void stm32_sai_sync_del_provider(struct device_node *np) | ||
161 | { | ||
162 | struct sync_provider *sp; | ||
163 | |||
164 | mutex_lock(&sync_mutex); | ||
165 | list_for_each_entry(sp, &sync_providers, link) { | ||
166 | if (sp->node == np) { | ||
167 | list_del(&sp->link); | ||
168 | of_node_put(sp->node); | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | mutex_unlock(&sync_mutex); | ||
173 | } | 123 | } |
174 | 124 | ||
175 | static int stm32_sai_probe(struct platform_device *pdev) | 125 | static int stm32_sai_probe(struct platform_device *pdev) |
176 | { | 126 | { |
177 | struct device_node *np = pdev->dev.of_node; | ||
178 | struct stm32_sai_data *sai; | 127 | struct stm32_sai_data *sai; |
179 | struct reset_control *rst; | 128 | struct reset_control *rst; |
180 | struct resource *res; | 129 | struct resource *res; |
181 | const struct of_device_id *of_id; | 130 | const struct of_device_id *of_id; |
182 | int ret; | ||
183 | 131 | ||
184 | sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); | 132 | sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); |
185 | if (!sai) | 133 | if (!sai) |
@@ -231,28 +179,11 @@ static int stm32_sai_probe(struct platform_device *pdev) | |||
231 | reset_control_deassert(rst); | 179 | reset_control_deassert(rst); |
232 | } | 180 | } |
233 | 181 | ||
234 | ret = stm32_sai_sync_add_provider(pdev, sai); | ||
235 | if (ret < 0) | ||
236 | return ret; | ||
237 | sai->set_sync = &stm32_sai_set_sync; | ||
238 | |||
239 | sai->pdev = pdev; | 182 | sai->pdev = pdev; |
183 | sai->set_sync = &stm32_sai_set_sync; | ||
240 | platform_set_drvdata(pdev, sai); | 184 | platform_set_drvdata(pdev, sai); |
241 | 185 | ||
242 | ret = of_platform_populate(np, NULL, NULL, &pdev->dev); | 186 | return devm_of_platform_populate(&pdev->dev); |
243 | if (ret < 0) | ||
244 | stm32_sai_sync_del_provider(np); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int stm32_sai_remove(struct platform_device *pdev) | ||
250 | { | ||
251 | of_platform_depopulate(&pdev->dev); | ||
252 | |||
253 | stm32_sai_sync_del_provider(pdev->dev.of_node); | ||
254 | |||
255 | return 0; | ||
256 | } | 187 | } |
257 | 188 | ||
258 | MODULE_DEVICE_TABLE(of, stm32_sai_ids); | 189 | MODULE_DEVICE_TABLE(of, stm32_sai_ids); |
@@ -263,7 +194,6 @@ static struct platform_driver stm32_sai_driver = { | |||
263 | .of_match_table = stm32_sai_ids, | 194 | .of_match_table = stm32_sai_ids, |
264 | }, | 195 | }, |
265 | .probe = stm32_sai_probe, | 196 | .probe = stm32_sai_probe, |
266 | .remove = stm32_sai_remove, | ||
267 | }; | 197 | }; |
268 | 198 | ||
269 | module_platform_driver(stm32_sai_driver); | 199 | module_platform_driver(stm32_sai_driver); |
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 5da4efe7a550..886281673972 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c | |||
@@ -590,12 +590,28 @@ static int sun4i_codec_hw_params(struct snd_pcm_substream *substream, | |||
590 | hwrate); | 590 | hwrate); |
591 | } | 591 | } |
592 | 592 | ||
593 | |||
594 | static unsigned int sun4i_codec_src_rates[] = { | ||
595 | 8000, 11025, 12000, 16000, 22050, 24000, 32000, | ||
596 | 44100, 48000, 96000, 192000 | ||
597 | }; | ||
598 | |||
599 | |||
600 | static struct snd_pcm_hw_constraint_list sun4i_codec_constraints = { | ||
601 | .count = ARRAY_SIZE(sun4i_codec_src_rates), | ||
602 | .list = sun4i_codec_src_rates, | ||
603 | }; | ||
604 | |||
605 | |||
593 | static int sun4i_codec_startup(struct snd_pcm_substream *substream, | 606 | static int sun4i_codec_startup(struct snd_pcm_substream *substream, |
594 | struct snd_soc_dai *dai) | 607 | struct snd_soc_dai *dai) |
595 | { | 608 | { |
596 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 609 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
597 | struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); | 610 | struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card); |
598 | 611 | ||
612 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
613 | SNDRV_PCM_HW_PARAM_RATE, &sun4i_codec_constraints); | ||
614 | |||
599 | /* | 615 | /* |
600 | * Stop issuing DRQ when we have room for less than 16 samples | 616 | * Stop issuing DRQ when we have room for less than 16 samples |
601 | * in our TX FIFO | 617 | * in our TX FIFO |
@@ -633,9 +649,7 @@ static struct snd_soc_dai_driver sun4i_codec_dai = { | |||
633 | .channels_max = 2, | 649 | .channels_max = 2, |
634 | .rate_min = 8000, | 650 | .rate_min = 8000, |
635 | .rate_max = 192000, | 651 | .rate_max = 192000, |
636 | .rates = SNDRV_PCM_RATE_8000_48000 | | 652 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
637 | SNDRV_PCM_RATE_96000 | | ||
638 | SNDRV_PCM_RATE_192000, | ||
639 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 653 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
640 | SNDRV_PCM_FMTBIT_S32_LE, | 654 | SNDRV_PCM_FMTBIT_S32_LE, |
641 | .sig_bits = 24, | 655 | .sig_bits = 24, |
@@ -645,11 +659,8 @@ static struct snd_soc_dai_driver sun4i_codec_dai = { | |||
645 | .channels_min = 1, | 659 | .channels_min = 1, |
646 | .channels_max = 2, | 660 | .channels_max = 2, |
647 | .rate_min = 8000, | 661 | .rate_min = 8000, |
648 | .rate_max = 192000, | 662 | .rate_max = 48000, |
649 | .rates = SNDRV_PCM_RATE_8000_48000 | | 663 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
650 | SNDRV_PCM_RATE_96000 | | ||
651 | SNDRV_PCM_RATE_192000 | | ||
652 | SNDRV_PCM_RATE_KNOT, | ||
653 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 664 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
654 | SNDRV_PCM_FMTBIT_S32_LE, | 665 | SNDRV_PCM_FMTBIT_S32_LE, |
655 | .sig_bits = 24, | 666 | .sig_bits = 24, |
@@ -1128,7 +1139,7 @@ static const struct snd_soc_component_driver sun4i_codec_component = { | |||
1128 | .name = "sun4i-codec", | 1139 | .name = "sun4i-codec", |
1129 | }; | 1140 | }; |
1130 | 1141 | ||
1131 | #define SUN4I_CODEC_RATES SNDRV_PCM_RATE_8000_192000 | 1142 | #define SUN4I_CODEC_RATES SNDRV_PCM_RATE_CONTINUOUS |
1132 | #define SUN4I_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 1143 | #define SUN4I_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
1133 | SNDRV_PCM_FMTBIT_S32_LE) | 1144 | SNDRV_PCM_FMTBIT_S32_LE) |
1134 | 1145 | ||
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 04f92583a969..dca1143c1150 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c | |||
@@ -269,10 +269,11 @@ static bool sun4i_i2s_oversample_is_valid(unsigned int oversample) | |||
269 | return false; | 269 | return false; |
270 | } | 270 | } |
271 | 271 | ||
272 | static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s, | 272 | static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, |
273 | unsigned int rate, | 273 | unsigned int rate, |
274 | unsigned int word_size) | 274 | unsigned int word_size) |
275 | { | 275 | { |
276 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
276 | unsigned int oversample_rate, clk_rate; | 277 | unsigned int oversample_rate, clk_rate; |
277 | int bclk_div, mclk_div; | 278 | int bclk_div, mclk_div; |
278 | int ret; | 279 | int ret; |
@@ -300,6 +301,7 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s, | |||
300 | break; | 301 | break; |
301 | 302 | ||
302 | default: | 303 | default: |
304 | dev_err(dai->dev, "Unsupported sample rate: %u\n", rate); | ||
303 | return -EINVAL; | 305 | return -EINVAL; |
304 | } | 306 | } |
305 | 307 | ||
@@ -308,18 +310,25 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s, | |||
308 | return ret; | 310 | return ret; |
309 | 311 | ||
310 | oversample_rate = i2s->mclk_freq / rate; | 312 | oversample_rate = i2s->mclk_freq / rate; |
311 | if (!sun4i_i2s_oversample_is_valid(oversample_rate)) | 313 | if (!sun4i_i2s_oversample_is_valid(oversample_rate)) { |
314 | dev_err(dai->dev, "Unsupported oversample rate: %d\n", | ||
315 | oversample_rate); | ||
312 | return -EINVAL; | 316 | return -EINVAL; |
317 | } | ||
313 | 318 | ||
314 | bclk_div = sun4i_i2s_get_bclk_div(i2s, oversample_rate, | 319 | bclk_div = sun4i_i2s_get_bclk_div(i2s, oversample_rate, |
315 | word_size); | 320 | word_size); |
316 | if (bclk_div < 0) | 321 | if (bclk_div < 0) { |
322 | dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); | ||
317 | return -EINVAL; | 323 | return -EINVAL; |
324 | } | ||
318 | 325 | ||
319 | mclk_div = sun4i_i2s_get_mclk_div(i2s, oversample_rate, | 326 | mclk_div = sun4i_i2s_get_mclk_div(i2s, oversample_rate, |
320 | clk_rate, rate); | 327 | clk_rate, rate); |
321 | if (mclk_div < 0) | 328 | if (mclk_div < 0) { |
329 | dev_err(dai->dev, "Unsupported MCLK divider: %d\n", mclk_div); | ||
322 | return -EINVAL; | 330 | return -EINVAL; |
331 | } | ||
323 | 332 | ||
324 | /* Adjust the clock division values if needed */ | 333 | /* Adjust the clock division values if needed */ |
325 | bclk_div += i2s->variant->bclk_offset; | 334 | bclk_div += i2s->variant->bclk_offset; |
@@ -349,8 +358,11 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
349 | u32 width; | 358 | u32 width; |
350 | 359 | ||
351 | channels = params_channels(params); | 360 | channels = params_channels(params); |
352 | if (channels != 2) | 361 | if (channels != 2) { |
362 | dev_err(dai->dev, "Unsupported number of channels: %d\n", | ||
363 | channels); | ||
353 | return -EINVAL; | 364 | return -EINVAL; |
365 | } | ||
354 | 366 | ||
355 | if (i2s->variant->has_chcfg) { | 367 | if (i2s->variant->has_chcfg) { |
356 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, | 368 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, |
@@ -382,6 +394,8 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
382 | width = DMA_SLAVE_BUSWIDTH_2_BYTES; | 394 | width = DMA_SLAVE_BUSWIDTH_2_BYTES; |
383 | break; | 395 | break; |
384 | default: | 396 | default: |
397 | dev_err(dai->dev, "Unsupported physical sample width: %d\n", | ||
398 | params_physical_width(params)); | ||
385 | return -EINVAL; | 399 | return -EINVAL; |
386 | } | 400 | } |
387 | i2s->playback_dma_data.addr_width = width; | 401 | i2s->playback_dma_data.addr_width = width; |
@@ -393,6 +407,8 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
393 | break; | 407 | break; |
394 | 408 | ||
395 | default: | 409 | default: |
410 | dev_err(dai->dev, "Unsupported sample width: %d\n", | ||
411 | params_width(params)); | ||
396 | return -EINVAL; | 412 | return -EINVAL; |
397 | } | 413 | } |
398 | 414 | ||
@@ -401,7 +417,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
401 | regmap_field_write(i2s->field_fmt_sr, | 417 | regmap_field_write(i2s->field_fmt_sr, |
402 | sr + i2s->variant->fmt_offset); | 418 | sr + i2s->variant->fmt_offset); |
403 | 419 | ||
404 | return sun4i_i2s_set_clk_rate(i2s, params_rate(params), | 420 | return sun4i_i2s_set_clk_rate(dai, params_rate(params), |
405 | params_width(params)); | 421 | params_width(params)); |
406 | } | 422 | } |
407 | 423 | ||
@@ -426,6 +442,8 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
426 | val = SUN4I_I2S_FMT0_FMT_RIGHT_J; | 442 | val = SUN4I_I2S_FMT0_FMT_RIGHT_J; |
427 | break; | 443 | break; |
428 | default: | 444 | default: |
445 | dev_err(dai->dev, "Unsupported format: %d\n", | ||
446 | fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
429 | return -EINVAL; | 447 | return -EINVAL; |
430 | } | 448 | } |
431 | 449 | ||
@@ -464,6 +482,8 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
464 | case SND_SOC_DAIFMT_NB_NF: | 482 | case SND_SOC_DAIFMT_NB_NF: |
465 | break; | 483 | break; |
466 | default: | 484 | default: |
485 | dev_err(dai->dev, "Unsupported clock polarity: %d\n", | ||
486 | fmt & SND_SOC_DAIFMT_INV_MASK); | ||
467 | return -EINVAL; | 487 | return -EINVAL; |
468 | } | 488 | } |
469 | 489 | ||
@@ -482,6 +502,8 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
482 | val = SUN4I_I2S_CTRL_MODE_SLAVE; | 502 | val = SUN4I_I2S_CTRL_MODE_SLAVE; |
483 | break; | 503 | break; |
484 | default: | 504 | default: |
505 | dev_err(dai->dev, "Unsupported slave setting: %d\n", | ||
506 | fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
485 | return -EINVAL; | 507 | return -EINVAL; |
486 | } | 508 | } |
487 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | 509 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, |
@@ -504,6 +526,8 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
504 | val = 0; | 526 | val = 0; |
505 | break; | 527 | break; |
506 | default: | 528 | default: |
529 | dev_err(dai->dev, "Unsupported slave setting: %d\n", | ||
530 | fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
507 | return -EINVAL; | 531 | return -EINVAL; |
508 | } | 532 | } |
509 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | 533 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, |
@@ -897,6 +921,23 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { | |||
897 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | 921 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), |
898 | }; | 922 | }; |
899 | 923 | ||
924 | static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { | ||
925 | .has_reset = true, | ||
926 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, | ||
927 | .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, | ||
928 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | ||
929 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | ||
930 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | ||
931 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | ||
932 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | ||
933 | .has_slave_select_bit = true, | ||
934 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | ||
935 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | ||
936 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | ||
937 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
938 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
939 | }; | ||
940 | |||
900 | static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { | 941 | static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { |
901 | .has_reset = true, | 942 | .has_reset = true, |
902 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, | 943 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, |
@@ -1121,6 +1162,10 @@ static const struct of_device_id sun4i_i2s_match[] = { | |||
1121 | .data = &sun6i_a31_i2s_quirks, | 1162 | .data = &sun6i_a31_i2s_quirks, |
1122 | }, | 1163 | }, |
1123 | { | 1164 | { |
1165 | .compatible = "allwinner,sun8i-a83t-i2s", | ||
1166 | .data = &sun8i_a83t_i2s_quirks, | ||
1167 | }, | ||
1168 | { | ||
1124 | .compatible = "allwinner,sun8i-h3-i2s", | 1169 | .compatible = "allwinner,sun8i-h3-i2s", |
1125 | .data = &sun8i_h3_i2s_quirks, | 1170 | .data = &sun8i_h3_i2s_quirks, |
1126 | }, | 1171 | }, |