diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/simple-card.txt | 3 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/simple-scu-card.txt | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/sun4i-i2s.txt | 2 | ||||
-rw-r--r-- | include/sound/simple_card_utils.h | 1 | ||||
-rw-r--r-- | sound/soc/codecs/sta32x.c | 3 | ||||
-rw-r--r-- | sound/soc/generic/audio-graph-card.c | 1 | ||||
-rw-r--r-- | sound/soc/generic/audio-graph-scu-card.c | 1 | ||||
-rw-r--r-- | sound/soc/generic/simple-card-utils.c | 9 | ||||
-rw-r--r-- | sound/soc/generic/simple-scu-card.c | 5 | ||||
-rw-r--r-- | sound/soc/spear/spdif_in.c | 12 | ||||
-rw-r--r-- | sound/soc/spear/spdif_out.c | 4 | ||||
-rw-r--r-- | sound/soc/stm/stm32_i2s.c | 2 | ||||
-rw-r--r-- | sound/soc/stm/stm32_sai.c | 2 | ||||
-rw-r--r-- | sound/soc/stm/stm32_spdifrx.c | 2 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-codec.c | 15 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-i2s.c | 455 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-spdif.c | 14 | ||||
-rw-r--r-- | sound/soc/sunxi/sun8i-codec.c | 4 |
18 files changed, 442 insertions, 94 deletions
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index c7a93931fad2..166f2290233b 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt | |||
@@ -86,6 +86,9 @@ Optional CPU/CODEC subnodes properties: | |||
86 | in dai startup() and disabled with | 86 | in dai startup() and disabled with |
87 | clk_disable_unprepare() in dai | 87 | clk_disable_unprepare() in dai |
88 | shutdown(). | 88 | shutdown(). |
89 | - system-clock-direction-out : specifies clock direction as 'out' on | ||
90 | initialization. It is useful for some aCPUs with | ||
91 | fixed clocks. | ||
89 | 92 | ||
90 | Example 1 - single DAI link: | 93 | Example 1 - single DAI link: |
91 | 94 | ||
diff --git a/Documentation/devicetree/bindings/sound/simple-scu-card.txt b/Documentation/devicetree/bindings/sound/simple-scu-card.txt index 327d229a51b2..32f8dbce5241 100644 --- a/Documentation/devicetree/bindings/sound/simple-scu-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-scu-card.txt | |||
@@ -24,6 +24,7 @@ Optional subnode properties: | |||
24 | - simple-audio-card,convert-rate : platform specified sampling rate convert | 24 | - simple-audio-card,convert-rate : platform specified sampling rate convert |
25 | - simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) | 25 | - simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) |
26 | - simple-audio-card,prefix : see routing | 26 | - simple-audio-card,prefix : see routing |
27 | - simple-audio-card,widgets : Please refer to widgets.txt. | ||
27 | - simple-audio-card,routing : A list of the connections between audio components. | 28 | - simple-audio-card,routing : A list of the connections between audio components. |
28 | Each entry is a pair of strings, the first being the connection's sink, | 29 | Each entry is a pair of strings, the first being the connection's sink, |
29 | the second being the connection's source. Valid names for sources. | 30 | the second being the connection's source. Valid names for sources. |
diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt index ee21da865771..fc5da6080759 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-h3-i2s" | ||
11 | - reg: physical base address of the controller and length of memory mapped | 12 | - reg: physical base address of the controller and length of memory mapped |
12 | region. | 13 | region. |
13 | - interrupts: should contain the I2S interrupt. | 14 | - interrupts: should contain the I2S interrupt. |
@@ -22,6 +23,7 @@ Required properties: | |||
22 | 23 | ||
23 | Required properties for the following compatibles: | 24 | Required properties for the following compatibles: |
24 | - "allwinner,sun6i-a31-i2s" | 25 | - "allwinner,sun6i-a31-i2s" |
26 | - "allwinner,sun8i-h3-i2s" | ||
25 | - resets: phandle to the reset line for this codec | 27 | - resets: phandle to the reset line for this codec |
26 | 28 | ||
27 | Example: | 29 | Example: |
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 42c6a6ac3ce6..7e25afce6566 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h | |||
@@ -15,6 +15,7 @@ | |||
15 | struct asoc_simple_dai { | 15 | struct asoc_simple_dai { |
16 | const char *name; | 16 | const char *name; |
17 | unsigned int sysclk; | 17 | unsigned int sysclk; |
18 | int clk_direction; | ||
18 | int slots; | 19 | int slots; |
19 | int slot_width; | 20 | int slot_width; |
20 | unsigned int tx_slot_mask; | 21 | unsigned int tx_slot_mask; |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 0790ae8530d9..5b888476d9ff 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -847,8 +847,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec, | |||
847 | msleep(300); | 847 | msleep(300); |
848 | sta32x_watchdog_stop(sta32x); | 848 | sta32x_watchdog_stop(sta32x); |
849 | 849 | ||
850 | if (sta32x->gpiod_nreset) | 850 | gpiod_set_value(sta32x->gpiod_nreset, 0); |
851 | gpiod_set_value(sta32x->gpiod_nreset, 0); | ||
852 | 851 | ||
853 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), | 852 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), |
854 | sta32x->supplies); | 853 | sta32x->supplies); |
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 2f7c8cf6f123..488c52f9405f 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c | |||
@@ -325,6 +325,7 @@ MODULE_DEVICE_TABLE(of, asoc_graph_of_match); | |||
325 | static struct platform_driver asoc_graph_card = { | 325 | static struct platform_driver asoc_graph_card = { |
326 | .driver = { | 326 | .driver = { |
327 | .name = "asoc-audio-graph-card", | 327 | .name = "asoc-audio-graph-card", |
328 | .pm = &snd_soc_pm_ops, | ||
328 | .of_match_table = asoc_graph_of_match, | 329 | .of_match_table = asoc_graph_of_match, |
329 | }, | 330 | }, |
330 | .probe = asoc_graph_card_probe, | 331 | .probe = asoc_graph_card_probe, |
diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c index 06b6fcf0513e..a967aa143d51 100644 --- a/sound/soc/generic/audio-graph-scu-card.c +++ b/sound/soc/generic/audio-graph-scu-card.c | |||
@@ -401,6 +401,7 @@ MODULE_DEVICE_TABLE(of, asoc_graph_of_match); | |||
401 | static struct platform_driver asoc_graph_card = { | 401 | static struct platform_driver asoc_graph_card = { |
402 | .driver = { | 402 | .driver = { |
403 | .name = "asoc-audio-graph-scu-card", | 403 | .name = "asoc-audio-graph-scu-card", |
404 | .pm = &snd_soc_pm_ops, | ||
404 | .of_match_table = asoc_graph_of_match, | 405 | .of_match_table = asoc_graph_of_match, |
405 | }, | 406 | }, |
406 | .probe = asoc_graph_card_probe, | 407 | .probe = asoc_graph_card_probe, |
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index d72f7d58102f..3751a07de6aa 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c | |||
@@ -196,7 +196,11 @@ int asoc_simple_card_parse_clk(struct device *dev, | |||
196 | simple_dai->sysclk = clk_get_rate(clk); | 196 | simple_dai->sysclk = clk_get_rate(clk); |
197 | } | 197 | } |
198 | 198 | ||
199 | dev_dbg(dev, "%s : sysclk = %d\n", name, simple_dai->sysclk); | 199 | if (of_property_read_bool(node, "system-clock-direction-out")) |
200 | simple_dai->clk_direction = SND_SOC_CLOCK_OUT; | ||
201 | |||
202 | dev_dbg(dev, "%s : sysclk = %d, direction %d\n", name, | ||
203 | simple_dai->sysclk, simple_dai->clk_direction); | ||
200 | 204 | ||
201 | return 0; | 205 | return 0; |
202 | } | 206 | } |
@@ -308,7 +312,8 @@ int asoc_simple_card_init_dai(struct snd_soc_dai *dai, | |||
308 | int ret; | 312 | int ret; |
309 | 313 | ||
310 | if (simple_dai->sysclk) { | 314 | if (simple_dai->sysclk) { |
311 | ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0); | 315 | ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, |
316 | simple_dai->clk_direction); | ||
312 | if (ret && ret != -ENOTSUPP) { | 317 | if (ret && ret != -ENOTSUPP) { |
313 | dev_err(dai->dev, "simple-card: set_sysclk error\n"); | 318 | dev_err(dai->dev, "simple-card: set_sysclk error\n"); |
314 | return ret; | 319 | return ret; |
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index a75b385455c4..48606c63562a 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c | |||
@@ -191,6 +191,10 @@ static int asoc_simple_card_parse_of(struct simple_card_data *priv) | |||
191 | if (!node) | 191 | if (!node) |
192 | return -EINVAL; | 192 | return -EINVAL; |
193 | 193 | ||
194 | ret = asoc_simple_card_of_parse_widgets(card, PREFIX); | ||
195 | if (ret < 0) | ||
196 | return ret; | ||
197 | |||
194 | ret = asoc_simple_card_of_parse_routing(card, PREFIX, 0); | 198 | ret = asoc_simple_card_of_parse_routing(card, PREFIX, 0); |
195 | if (ret < 0) | 199 | if (ret < 0) |
196 | return ret; | 200 | return ret; |
@@ -296,6 +300,7 @@ MODULE_DEVICE_TABLE(of, asoc_simple_of_match); | |||
296 | static struct platform_driver asoc_simple_card = { | 300 | static struct platform_driver asoc_simple_card = { |
297 | .driver = { | 301 | .driver = { |
298 | .name = "simple-scu-audio-card", | 302 | .name = "simple-scu-audio-card", |
303 | .pm = &snd_soc_pm_ops, | ||
299 | .of_match_table = asoc_simple_of_match, | 304 | .of_match_table = asoc_simple_of_match, |
300 | }, | 305 | }, |
301 | .probe = asoc_simple_card_probe, | 306 | .probe = asoc_simple_card_probe, |
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c index 977a078eb92f..78a6a360b4a6 100644 --- a/sound/soc/spear/spdif_in.c +++ b/sound/soc/spear/spdif_in.c | |||
@@ -151,7 +151,7 @@ static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd, | |||
151 | return ret; | 151 | return ret; |
152 | } | 152 | } |
153 | 153 | ||
154 | static struct snd_soc_dai_ops spdif_in_dai_ops = { | 154 | static const struct snd_soc_dai_ops spdif_in_dai_ops = { |
155 | .shutdown = spdif_in_shutdown, | 155 | .shutdown = spdif_in_shutdown, |
156 | .trigger = spdif_in_trigger, | 156 | .trigger = spdif_in_trigger, |
157 | .hw_params = spdif_in_hw_params, | 157 | .hw_params = spdif_in_hw_params, |
@@ -216,15 +216,15 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
216 | return -EINVAL; | 216 | return -EINVAL; |
217 | 217 | ||
218 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | 218 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); |
219 | if (!host) { | 219 | if (!host) |
220 | dev_warn(&pdev->dev, "kzalloc fail\n"); | ||
221 | return -ENOMEM; | 220 | return -ENOMEM; |
222 | } | ||
223 | 221 | ||
224 | host->io_base = io_base; | 222 | host->io_base = io_base; |
225 | host->irq = platform_get_irq(pdev, 0); | 223 | host->irq = platform_get_irq(pdev, 0); |
226 | if (host->irq < 0) | 224 | if (host->irq < 0) { |
227 | return -EINVAL; | 225 | dev_warn(&pdev->dev, "failed to get IRQ: %d\n", host->irq); |
226 | return host->irq; | ||
227 | } | ||
228 | 228 | ||
229 | host->clk = devm_clk_get(&pdev->dev, NULL); | 229 | host->clk = devm_clk_get(&pdev->dev, NULL); |
230 | if (IS_ERR(host->clk)) | 230 | if (IS_ERR(host->clk)) |
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index 0a72d52d533e..58d5843811f9 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c | |||
@@ -282,10 +282,8 @@ static int spdif_out_probe(struct platform_device *pdev) | |||
282 | int ret; | 282 | int ret; |
283 | 283 | ||
284 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | 284 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); |
285 | if (!host) { | 285 | if (!host) |
286 | dev_warn(&pdev->dev, "kzalloc fail\n"); | ||
287 | return -ENOMEM; | 286 | return -ENOMEM; |
288 | } | ||
289 | 287 | ||
290 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 288 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
291 | host->io_base = devm_ioremap_resource(&pdev->dev, res); | 289 | host->io_base = devm_ioremap_resource(&pdev->dev, res); |
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 8052629a89df..6d0bf78d114d 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c | |||
@@ -840,7 +840,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, | |||
840 | } | 840 | } |
841 | 841 | ||
842 | /* Reset */ | 842 | /* Reset */ |
843 | rst = devm_reset_control_get(&pdev->dev, NULL); | 843 | rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
844 | if (!IS_ERR(rst)) { | 844 | if (!IS_ERR(rst)) { |
845 | reset_control_assert(rst); | 845 | reset_control_assert(rst); |
846 | udelay(2); | 846 | udelay(2); |
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index f7713314913b..1258bef4dcb3 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c | |||
@@ -85,7 +85,7 @@ static int stm32_sai_probe(struct platform_device *pdev) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /* reset */ | 87 | /* reset */ |
88 | rst = reset_control_get(&pdev->dev, NULL); | 88 | rst = reset_control_get_exclusive(&pdev->dev, NULL); |
89 | if (!IS_ERR(rst)) { | 89 | if (!IS_ERR(rst)) { |
90 | reset_control_assert(rst); | 90 | reset_control_assert(rst); |
91 | udelay(2); | 91 | udelay(2); |
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index 4e4250bdb75a..84cc5678beba 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c | |||
@@ -930,7 +930,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) | |||
930 | return ret; | 930 | return ret; |
931 | } | 931 | } |
932 | 932 | ||
933 | rst = devm_reset_control_get(&pdev->dev, NULL); | 933 | rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
934 | if (!IS_ERR(rst)) { | 934 | if (!IS_ERR(rst)) { |
935 | reset_control_assert(rst); | 935 | reset_control_assert(rst); |
936 | udelay(2); | 936 | udelay(2); |
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 150069987c0c..baa9007464ed 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c | |||
@@ -762,7 +762,7 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = { | |||
762 | { "Mic1", NULL, "VMIC" }, | 762 | { "Mic1", NULL, "VMIC" }, |
763 | }; | 763 | }; |
764 | 764 | ||
765 | static struct snd_soc_codec_driver sun4i_codec_codec = { | 765 | static const struct snd_soc_codec_driver sun4i_codec_codec = { |
766 | .component_driver = { | 766 | .component_driver = { |
767 | .controls = sun4i_codec_controls, | 767 | .controls = sun4i_codec_controls, |
768 | .num_controls = ARRAY_SIZE(sun4i_codec_controls), | 768 | .num_controls = ARRAY_SIZE(sun4i_codec_controls), |
@@ -1068,7 +1068,7 @@ static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = { | |||
1068 | { "Right ADC", NULL, "Right ADC Mixer" }, | 1068 | { "Right ADC", NULL, "Right ADC Mixer" }, |
1069 | }; | 1069 | }; |
1070 | 1070 | ||
1071 | static struct snd_soc_codec_driver sun6i_codec_codec = { | 1071 | static const struct snd_soc_codec_driver sun6i_codec_codec = { |
1072 | .component_driver = { | 1072 | .component_driver = { |
1073 | .controls = sun6i_codec_codec_widgets, | 1073 | .controls = sun6i_codec_codec_widgets, |
1074 | .num_controls = ARRAY_SIZE(sun6i_codec_codec_widgets), | 1074 | .num_controls = ARRAY_SIZE(sun6i_codec_codec_widgets), |
@@ -1096,7 +1096,7 @@ static const struct snd_soc_dapm_widget sun8i_a23_codec_codec_widgets[] = { | |||
1096 | 1096 | ||
1097 | }; | 1097 | }; |
1098 | 1098 | ||
1099 | static struct snd_soc_codec_driver sun8i_a23_codec_codec = { | 1099 | static const struct snd_soc_codec_driver sun8i_a23_codec_codec = { |
1100 | .component_driver = { | 1100 | .component_driver = { |
1101 | .controls = sun8i_a23_codec_codec_controls, | 1101 | .controls = sun8i_a23_codec_codec_controls, |
1102 | .num_controls = ARRAY_SIZE(sun8i_a23_codec_codec_controls), | 1102 | .num_controls = ARRAY_SIZE(sun8i_a23_codec_codec_controls), |
@@ -1171,9 +1171,8 @@ static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w, | |||
1171 | { | 1171 | { |
1172 | struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card); | 1172 | struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card); |
1173 | 1173 | ||
1174 | if (scodec->gpio_pa) | 1174 | gpiod_set_value_cansleep(scodec->gpio_pa, |
1175 | gpiod_set_value_cansleep(scodec->gpio_pa, | 1175 | !!SND_SOC_DAPM_EVENT_ON(event)); |
1176 | !!SND_SOC_DAPM_EVENT_ON(event)); | ||
1177 | 1176 | ||
1178 | return 0; | 1177 | return 0; |
1179 | } | 1178 | } |
@@ -1574,7 +1573,8 @@ static int sun4i_codec_probe(struct platform_device *pdev) | |||
1574 | } | 1573 | } |
1575 | 1574 | ||
1576 | if (quirks->has_reset) { | 1575 | if (quirks->has_reset) { |
1577 | scodec->rst = devm_reset_control_get(&pdev->dev, NULL); | 1576 | scodec->rst = devm_reset_control_get_exclusive(&pdev->dev, |
1577 | NULL); | ||
1578 | if (IS_ERR(scodec->rst)) { | 1578 | if (IS_ERR(scodec->rst)) { |
1579 | dev_err(&pdev->dev, "Failed to get reset control\n"); | 1579 | dev_err(&pdev->dev, "Failed to get reset control\n"); |
1580 | return PTR_ERR(scodec->rst); | 1580 | return PTR_ERR(scodec->rst); |
@@ -1655,7 +1655,6 @@ static int sun4i_codec_probe(struct platform_device *pdev) | |||
1655 | goto err_unregister_codec; | 1655 | goto err_unregister_codec; |
1656 | } | 1656 | } |
1657 | 1657 | ||
1658 | platform_set_drvdata(pdev, card); | ||
1659 | snd_soc_card_set_drvdata(card, scodec); | 1658 | snd_soc_card_set_drvdata(card, scodec); |
1660 | 1659 | ||
1661 | ret = snd_soc_register_card(card); | 1660 | ret = snd_soc_register_card(card); |
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 3635bbc72cbc..04f92583a969 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c | |||
@@ -50,6 +50,8 @@ | |||
50 | #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0) | 50 | #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0) |
51 | #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0) | 51 | #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0) |
52 | #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0) | 52 | #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0) |
53 | #define SUN4I_I2S_FMT0_POLARITY_INVERTED (1) | ||
54 | #define SUN4I_I2S_FMT0_POLARITY_NORMAL (0) | ||
53 | 55 | ||
54 | #define SUN4I_I2S_FMT1_REG 0x08 | 56 | #define SUN4I_I2S_FMT1_REG 0x08 |
55 | #define SUN4I_I2S_FIFO_TX_REG 0x0c | 57 | #define SUN4I_I2S_FIFO_TX_REG 0x0c |
@@ -82,7 +84,7 @@ | |||
82 | #define SUN4I_I2S_TX_CNT_REG 0x2c | 84 | #define SUN4I_I2S_TX_CNT_REG 0x2c |
83 | 85 | ||
84 | #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30 | 86 | #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30 |
85 | #define SUN4I_I2S_TX_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) | 87 | #define SUN4I_I2S_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) |
86 | 88 | ||
87 | #define SUN4I_I2S_TX_CHAN_MAP_REG 0x34 | 89 | #define SUN4I_I2S_TX_CHAN_MAP_REG 0x34 |
88 | #define SUN4I_I2S_TX_CHAN_MAP(chan, sample) ((sample) << (chan << 2)) | 90 | #define SUN4I_I2S_TX_CHAN_MAP(chan, sample) ((sample) << (chan << 2)) |
@@ -90,6 +92,83 @@ | |||
90 | #define SUN4I_I2S_RX_CHAN_SEL_REG 0x38 | 92 | #define SUN4I_I2S_RX_CHAN_SEL_REG 0x38 |
91 | #define SUN4I_I2S_RX_CHAN_MAP_REG 0x3c | 93 | #define SUN4I_I2S_RX_CHAN_MAP_REG 0x3c |
92 | 94 | ||
95 | /* Defines required for sun8i-h3 support */ | ||
96 | #define SUN8I_I2S_CTRL_BCLK_OUT BIT(18) | ||
97 | #define SUN8I_I2S_CTRL_LRCK_OUT BIT(17) | ||
98 | |||
99 | #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8) | ||
100 | #define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8) | ||
101 | |||
102 | #define SUN8I_I2S_INT_STA_REG 0x0c | ||
103 | #define SUN8I_I2S_FIFO_TX_REG 0x20 | ||
104 | |||
105 | #define SUN8I_I2S_CHAN_CFG_REG 0x30 | ||
106 | #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4) | ||
107 | #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) (chan - 1) | ||
108 | #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) | ||
109 | #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1) | ||
110 | |||
111 | #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 | ||
112 | #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 | ||
113 | #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 11) | ||
114 | #define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) | ||
115 | #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) | ||
116 | #define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) | ||
117 | |||
118 | #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 | ||
119 | #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 | ||
120 | |||
121 | /** | ||
122 | * struct sun4i_i2s_quirks - Differences between SoC variants. | ||
123 | * | ||
124 | * @has_reset: SoC needs reset deasserted. | ||
125 | * @has_slave_select_bit: SoC has a bit to enable slave mode. | ||
126 | * @has_fmt_set_lrck_period: SoC requires lrclk period to be set. | ||
127 | * @has_chcfg: tx and rx slot number need to be set. | ||
128 | * @has_chsel_tx_chen: SoC requires that the tx channels are enabled. | ||
129 | * @has_chsel_offset: SoC uses offset for selecting dai operational mode. | ||
130 | * @reg_offset_txdata: offset of the tx fifo. | ||
131 | * @sun4i_i2s_regmap: regmap config to use. | ||
132 | * @mclk_offset: Value by which mclkdiv needs to be adjusted. | ||
133 | * @bclk_offset: Value by which bclkdiv needs to be adjusted. | ||
134 | * @fmt_offset: Value by which wss and sr needs to be adjusted. | ||
135 | * @field_clkdiv_mclk_en: regmap field to enable mclk output. | ||
136 | * @field_fmt_wss: regmap field to set word select size. | ||
137 | * @field_fmt_sr: regmap field to set sample resolution. | ||
138 | * @field_fmt_bclk: regmap field to set clk polarity. | ||
139 | * @field_fmt_lrclk: regmap field to set frame polarity. | ||
140 | * @field_fmt_mode: regmap field to set the operational mode. | ||
141 | * @field_txchanmap: location of the tx channel mapping register. | ||
142 | * @field_rxchanmap: location of the rx channel mapping register. | ||
143 | * @field_txchansel: location of the tx channel select bit fields. | ||
144 | * @field_rxchansel: location of the rx channel select bit fields. | ||
145 | */ | ||
146 | struct sun4i_i2s_quirks { | ||
147 | bool has_reset; | ||
148 | bool has_slave_select_bit; | ||
149 | bool has_fmt_set_lrck_period; | ||
150 | bool has_chcfg; | ||
151 | bool has_chsel_tx_chen; | ||
152 | bool has_chsel_offset; | ||
153 | unsigned int reg_offset_txdata; /* TX FIFO */ | ||
154 | const struct regmap_config *sun4i_i2s_regmap; | ||
155 | unsigned int mclk_offset; | ||
156 | unsigned int bclk_offset; | ||
157 | unsigned int fmt_offset; | ||
158 | |||
159 | /* Register fields for i2s */ | ||
160 | struct reg_field field_clkdiv_mclk_en; | ||
161 | struct reg_field field_fmt_wss; | ||
162 | struct reg_field field_fmt_sr; | ||
163 | struct reg_field field_fmt_bclk; | ||
164 | struct reg_field field_fmt_lrclk; | ||
165 | struct reg_field field_fmt_mode; | ||
166 | struct reg_field field_txchanmap; | ||
167 | struct reg_field field_rxchanmap; | ||
168 | struct reg_field field_txchansel; | ||
169 | struct reg_field field_rxchansel; | ||
170 | }; | ||
171 | |||
93 | struct sun4i_i2s { | 172 | struct sun4i_i2s { |
94 | struct clk *bus_clk; | 173 | struct clk *bus_clk; |
95 | struct clk *mod_clk; | 174 | struct clk *mod_clk; |
@@ -100,6 +179,20 @@ struct sun4i_i2s { | |||
100 | 179 | ||
101 | struct snd_dmaengine_dai_dma_data capture_dma_data; | 180 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
102 | struct snd_dmaengine_dai_dma_data playback_dma_data; | 181 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
182 | |||
183 | /* Register fields for i2s */ | ||
184 | struct regmap_field *field_clkdiv_mclk_en; | ||
185 | struct regmap_field *field_fmt_wss; | ||
186 | struct regmap_field *field_fmt_sr; | ||
187 | struct regmap_field *field_fmt_bclk; | ||
188 | struct regmap_field *field_fmt_lrclk; | ||
189 | struct regmap_field *field_fmt_mode; | ||
190 | struct regmap_field *field_txchanmap; | ||
191 | struct regmap_field *field_rxchanmap; | ||
192 | struct regmap_field *field_txchansel; | ||
193 | struct regmap_field *field_rxchansel; | ||
194 | |||
195 | const struct sun4i_i2s_quirks *variant; | ||
103 | }; | 196 | }; |
104 | 197 | ||
105 | struct sun4i_i2s_clk_div { | 198 | struct sun4i_i2s_clk_div { |
@@ -114,6 +207,7 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_bclk_div[] = { | |||
114 | { .div = 8, .val = 3 }, | 207 | { .div = 8, .val = 3 }, |
115 | { .div = 12, .val = 4 }, | 208 | { .div = 12, .val = 4 }, |
116 | { .div = 16, .val = 5 }, | 209 | { .div = 16, .val = 5 }, |
210 | /* TODO - extend divide ratio supported by newer SoCs */ | ||
117 | }; | 211 | }; |
118 | 212 | ||
119 | static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = { | 213 | static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = { |
@@ -125,6 +219,7 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = { | |||
125 | { .div = 12, .val = 5 }, | 219 | { .div = 12, .val = 5 }, |
126 | { .div = 16, .val = 6 }, | 220 | { .div = 16, .val = 6 }, |
127 | { .div = 24, .val = 7 }, | 221 | { .div = 24, .val = 7 }, |
222 | /* TODO - extend divide ratio supported by newer SoCs */ | ||
128 | }; | 223 | }; |
129 | 224 | ||
130 | static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, | 225 | static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, |
@@ -226,10 +321,21 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s, | |||
226 | if (mclk_div < 0) | 321 | if (mclk_div < 0) |
227 | return -EINVAL; | 322 | return -EINVAL; |
228 | 323 | ||
324 | /* Adjust the clock division values if needed */ | ||
325 | bclk_div += i2s->variant->bclk_offset; | ||
326 | mclk_div += i2s->variant->mclk_offset; | ||
327 | |||
229 | regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG, | 328 | regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG, |
230 | SUN4I_I2S_CLK_DIV_BCLK(bclk_div) | | 329 | SUN4I_I2S_CLK_DIV_BCLK(bclk_div) | |
231 | SUN4I_I2S_CLK_DIV_MCLK(mclk_div) | | 330 | SUN4I_I2S_CLK_DIV_MCLK(mclk_div)); |
232 | SUN4I_I2S_CLK_DIV_MCLK_EN); | 331 | |
332 | regmap_field_write(i2s->field_clkdiv_mclk_en, 1); | ||
333 | |||
334 | /* Set sync period */ | ||
335 | if (i2s->variant->has_fmt_set_lrck_period) | ||
336 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, | ||
337 | SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, | ||
338 | SUN8I_I2S_FMT0_LRCK_PERIOD(32)); | ||
233 | 339 | ||
234 | return 0; | 340 | return 0; |
235 | } | 341 | } |
@@ -239,12 +345,38 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
239 | struct snd_soc_dai *dai) | 345 | struct snd_soc_dai *dai) |
240 | { | 346 | { |
241 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 347 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
242 | int sr, wss; | 348 | int sr, wss, channels; |
243 | u32 width; | 349 | u32 width; |
244 | 350 | ||
245 | if (params_channels(params) != 2) | 351 | channels = params_channels(params); |
352 | if (channels != 2) | ||
246 | return -EINVAL; | 353 | return -EINVAL; |
247 | 354 | ||
355 | if (i2s->variant->has_chcfg) { | ||
356 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, | ||
357 | SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, | ||
358 | SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); | ||
359 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, | ||
360 | SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, | ||
361 | SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); | ||
362 | } | ||
363 | |||
364 | /* Map the channels for playback and capture */ | ||
365 | regmap_field_write(i2s->field_txchanmap, 0x76543210); | ||
366 | regmap_field_write(i2s->field_rxchanmap, 0x00003210); | ||
367 | |||
368 | /* Configure the channels */ | ||
369 | regmap_field_write(i2s->field_txchansel, | ||
370 | SUN4I_I2S_CHAN_SEL(params_channels(params))); | ||
371 | |||
372 | regmap_field_write(i2s->field_rxchansel, | ||
373 | SUN4I_I2S_CHAN_SEL(params_channels(params))); | ||
374 | |||
375 | if (i2s->variant->has_chsel_tx_chen) | ||
376 | regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, | ||
377 | SUN8I_I2S_TX_CHAN_EN_MASK, | ||
378 | SUN8I_I2S_TX_CHAN_EN(channels)); | ||
379 | |||
248 | switch (params_physical_width(params)) { | 380 | switch (params_physical_width(params)) { |
249 | case 16: | 381 | case 16: |
250 | width = DMA_SLAVE_BUSWIDTH_2_BYTES; | 382 | width = DMA_SLAVE_BUSWIDTH_2_BYTES; |
@@ -264,9 +396,10 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
264 | return -EINVAL; | 396 | return -EINVAL; |
265 | } | 397 | } |
266 | 398 | ||
267 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, | 399 | regmap_field_write(i2s->field_fmt_wss, |
268 | SUN4I_I2S_FMT0_WSS_MASK | SUN4I_I2S_FMT0_SR_MASK, | 400 | wss + i2s->variant->fmt_offset); |
269 | SUN4I_I2S_FMT0_WSS(wss) | SUN4I_I2S_FMT0_SR(sr)); | 401 | regmap_field_write(i2s->field_fmt_sr, |
402 | sr + i2s->variant->fmt_offset); | ||
270 | 403 | ||
271 | return sun4i_i2s_set_clk_rate(i2s, params_rate(params), | 404 | return sun4i_i2s_set_clk_rate(i2s, params_rate(params), |
272 | params_width(params)); | 405 | params_width(params)); |
@@ -276,11 +409,15 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
276 | { | 409 | { |
277 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 410 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
278 | u32 val; | 411 | u32 val; |
412 | u32 offset = 0; | ||
413 | u32 bclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL; | ||
414 | u32 lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL; | ||
279 | 415 | ||
280 | /* DAI Mode */ | 416 | /* DAI Mode */ |
281 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 417 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
282 | case SND_SOC_DAIFMT_I2S: | 418 | case SND_SOC_DAIFMT_I2S: |
283 | val = SUN4I_I2S_FMT0_FMT_I2S; | 419 | val = SUN4I_I2S_FMT0_FMT_I2S; |
420 | offset = 1; | ||
284 | break; | 421 | break; |
285 | case SND_SOC_DAIFMT_LEFT_J: | 422 | case SND_SOC_DAIFMT_LEFT_J: |
286 | val = SUN4I_I2S_FMT0_FMT_LEFT_J; | 423 | val = SUN4I_I2S_FMT0_FMT_LEFT_J; |
@@ -292,59 +429,89 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
292 | return -EINVAL; | 429 | return -EINVAL; |
293 | } | 430 | } |
294 | 431 | ||
295 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, | 432 | if (i2s->variant->has_chsel_offset) { |
296 | SUN4I_I2S_FMT0_FMT_MASK, | 433 | /* |
297 | val); | 434 | * offset being set indicates that we're connected to an i2s |
435 | * device, however offset is only used on the sun8i block and | ||
436 | * i2s shares the same setting with the LJ format. Increment | ||
437 | * val so that the bit to value to write is correct. | ||
438 | */ | ||
439 | if (offset > 0) | ||
440 | val++; | ||
441 | /* blck offset determines whether i2s or LJ */ | ||
442 | regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, | ||
443 | SUN8I_I2S_TX_CHAN_OFFSET_MASK, | ||
444 | SUN8I_I2S_TX_CHAN_OFFSET(offset)); | ||
445 | } | ||
446 | |||
447 | regmap_field_write(i2s->field_fmt_mode, val); | ||
298 | 448 | ||
299 | /* DAI clock polarity */ | 449 | /* DAI clock polarity */ |
300 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 450 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
301 | case SND_SOC_DAIFMT_IB_IF: | 451 | case SND_SOC_DAIFMT_IB_IF: |
302 | /* Invert both clocks */ | 452 | /* Invert both clocks */ |
303 | val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED | | 453 | bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; |
304 | SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED; | 454 | lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; |
305 | break; | 455 | break; |
306 | case SND_SOC_DAIFMT_IB_NF: | 456 | case SND_SOC_DAIFMT_IB_NF: |
307 | /* Invert bit clock */ | 457 | /* Invert bit clock */ |
308 | val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED | | 458 | bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; |
309 | SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL; | ||
310 | break; | 459 | break; |
311 | case SND_SOC_DAIFMT_NB_IF: | 460 | case SND_SOC_DAIFMT_NB_IF: |
312 | /* Invert frame clock */ | 461 | /* Invert frame clock */ |
313 | val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED | | 462 | lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; |
314 | SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL; | ||
315 | break; | 463 | break; |
316 | case SND_SOC_DAIFMT_NB_NF: | 464 | case SND_SOC_DAIFMT_NB_NF: |
317 | /* Nothing to do for both normal cases */ | ||
318 | val = SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL | | ||
319 | SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL; | ||
320 | break; | 465 | break; |
321 | default: | 466 | default: |
322 | return -EINVAL; | 467 | return -EINVAL; |
323 | } | 468 | } |
324 | 469 | ||
325 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, | 470 | regmap_field_write(i2s->field_fmt_bclk, bclk_polarity); |
326 | SUN4I_I2S_FMT0_BCLK_POLARITY_MASK | | 471 | regmap_field_write(i2s->field_fmt_lrclk, lrclk_polarity); |
327 | SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK, | 472 | |
328 | val); | 473 | if (i2s->variant->has_slave_select_bit) { |
329 | 474 | /* DAI clock master masks */ | |
330 | /* DAI clock master masks */ | 475 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
331 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 476 | case SND_SOC_DAIFMT_CBS_CFS: |
332 | case SND_SOC_DAIFMT_CBS_CFS: | 477 | /* BCLK and LRCLK master */ |
333 | /* BCLK and LRCLK master */ | 478 | val = SUN4I_I2S_CTRL_MODE_MASTER; |
334 | val = SUN4I_I2S_CTRL_MODE_MASTER; | 479 | break; |
335 | break; | 480 | case SND_SOC_DAIFMT_CBM_CFM: |
336 | case SND_SOC_DAIFMT_CBM_CFM: | 481 | /* BCLK and LRCLK slave */ |
337 | /* BCLK and LRCLK slave */ | 482 | val = SUN4I_I2S_CTRL_MODE_SLAVE; |
338 | val = SUN4I_I2S_CTRL_MODE_SLAVE; | 483 | break; |
339 | break; | 484 | default: |
340 | default: | 485 | return -EINVAL; |
341 | return -EINVAL; | 486 | } |
487 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
488 | SUN4I_I2S_CTRL_MODE_MASK, | ||
489 | val); | ||
490 | } else { | ||
491 | /* | ||
492 | * The newer i2s block does not have a slave select bit, | ||
493 | * instead the clk pins are configured as inputs. | ||
494 | */ | ||
495 | /* DAI clock master masks */ | ||
496 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
497 | case SND_SOC_DAIFMT_CBS_CFS: | ||
498 | /* BCLK and LRCLK master */ | ||
499 | val = SUN8I_I2S_CTRL_BCLK_OUT | | ||
500 | SUN8I_I2S_CTRL_LRCK_OUT; | ||
501 | break; | ||
502 | case SND_SOC_DAIFMT_CBM_CFM: | ||
503 | /* BCLK and LRCLK slave */ | ||
504 | val = 0; | ||
505 | break; | ||
506 | default: | ||
507 | return -EINVAL; | ||
508 | } | ||
509 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
510 | SUN8I_I2S_CTRL_BCLK_OUT | | ||
511 | SUN8I_I2S_CTRL_LRCK_OUT, | ||
512 | val); | ||
342 | } | 513 | } |
343 | 514 | ||
344 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
345 | SUN4I_I2S_CTRL_MODE_MASK, | ||
346 | val); | ||
347 | |||
348 | /* Set significant bits in our FIFOs */ | 515 | /* Set significant bits in our FIFOs */ |
349 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, | 516 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, |
350 | SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK | | 517 | SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK | |
@@ -459,21 +626,14 @@ static int sun4i_i2s_startup(struct snd_pcm_substream *substream, | |||
459 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 626 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
460 | 627 | ||
461 | /* Enable the whole hardware block */ | 628 | /* Enable the whole hardware block */ |
462 | regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG, | 629 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, |
463 | SUN4I_I2S_CTRL_GL_EN); | 630 | SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN); |
464 | 631 | ||
465 | /* Enable the first output line */ | 632 | /* Enable the first output line */ |
466 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | 633 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, |
467 | SUN4I_I2S_CTRL_SDO_EN_MASK, | 634 | SUN4I_I2S_CTRL_SDO_EN_MASK, |
468 | SUN4I_I2S_CTRL_SDO_EN(0)); | 635 | SUN4I_I2S_CTRL_SDO_EN(0)); |
469 | 636 | ||
470 | /* Enable the first two channels */ | ||
471 | regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG, | ||
472 | SUN4I_I2S_TX_CHAN_SEL(2)); | ||
473 | |||
474 | /* Map them to the two first samples coming in */ | ||
475 | regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, | ||
476 | SUN4I_I2S_TX_CHAN_MAP(0, 0) | SUN4I_I2S_TX_CHAN_MAP(1, 1)); | ||
477 | 637 | ||
478 | return clk_prepare_enable(i2s->mod_clk); | 638 | return clk_prepare_enable(i2s->mod_clk); |
479 | } | 639 | } |
@@ -490,7 +650,8 @@ static void sun4i_i2s_shutdown(struct snd_pcm_substream *substream, | |||
490 | SUN4I_I2S_CTRL_SDO_EN_MASK, 0); | 650 | SUN4I_I2S_CTRL_SDO_EN_MASK, 0); |
491 | 651 | ||
492 | /* Disable the whole hardware block */ | 652 | /* Disable the whole hardware block */ |
493 | regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG, 0); | 653 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, |
654 | SUN4I_I2S_CTRL_GL_EN, 0); | ||
494 | } | 655 | } |
495 | 656 | ||
496 | static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 657 | static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
@@ -589,6 +750,27 @@ static bool sun4i_i2s_volatile_reg(struct device *dev, unsigned int reg) | |||
589 | } | 750 | } |
590 | } | 751 | } |
591 | 752 | ||
753 | static bool sun8i_i2s_rd_reg(struct device *dev, unsigned int reg) | ||
754 | { | ||
755 | switch (reg) { | ||
756 | case SUN8I_I2S_FIFO_TX_REG: | ||
757 | return false; | ||
758 | |||
759 | default: | ||
760 | return true; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | static bool sun8i_i2s_volatile_reg(struct device *dev, unsigned int reg) | ||
765 | { | ||
766 | if (reg == SUN8I_I2S_INT_STA_REG) | ||
767 | return true; | ||
768 | if (reg == SUN8I_I2S_FIFO_TX_REG) | ||
769 | return false; | ||
770 | |||
771 | return sun4i_i2s_volatile_reg(dev, reg); | ||
772 | } | ||
773 | |||
592 | static const struct reg_default sun4i_i2s_reg_defaults[] = { | 774 | static const struct reg_default sun4i_i2s_reg_defaults[] = { |
593 | { SUN4I_I2S_CTRL_REG, 0x00000000 }, | 775 | { SUN4I_I2S_CTRL_REG, 0x00000000 }, |
594 | { SUN4I_I2S_FMT0_REG, 0x0000000c }, | 776 | { SUN4I_I2S_FMT0_REG, 0x0000000c }, |
@@ -602,6 +784,20 @@ static const struct reg_default sun4i_i2s_reg_defaults[] = { | |||
602 | { SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210 }, | 784 | { SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210 }, |
603 | }; | 785 | }; |
604 | 786 | ||
787 | static const struct reg_default sun8i_i2s_reg_defaults[] = { | ||
788 | { SUN4I_I2S_CTRL_REG, 0x00060000 }, | ||
789 | { SUN4I_I2S_FMT0_REG, 0x00000033 }, | ||
790 | { SUN4I_I2S_FMT1_REG, 0x00000030 }, | ||
791 | { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 }, | ||
792 | { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, | ||
793 | { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, | ||
794 | { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, | ||
795 | { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, | ||
796 | { SUN8I_I2S_TX_CHAN_MAP_REG, 0x00000000 }, | ||
797 | { SUN8I_I2S_RX_CHAN_SEL_REG, 0x00000000 }, | ||
798 | { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 }, | ||
799 | }; | ||
800 | |||
605 | static const struct regmap_config sun4i_i2s_regmap_config = { | 801 | static const struct regmap_config sun4i_i2s_regmap_config = { |
606 | .reg_bits = 32, | 802 | .reg_bits = 32, |
607 | .reg_stride = 4, | 803 | .reg_stride = 4, |
@@ -616,6 +812,19 @@ static const struct regmap_config sun4i_i2s_regmap_config = { | |||
616 | .volatile_reg = sun4i_i2s_volatile_reg, | 812 | .volatile_reg = sun4i_i2s_volatile_reg, |
617 | }; | 813 | }; |
618 | 814 | ||
815 | static const struct regmap_config sun8i_i2s_regmap_config = { | ||
816 | .reg_bits = 32, | ||
817 | .reg_stride = 4, | ||
818 | .val_bits = 32, | ||
819 | .max_register = SUN8I_I2S_RX_CHAN_MAP_REG, | ||
820 | .cache_type = REGCACHE_FLAT, | ||
821 | .reg_defaults = sun8i_i2s_reg_defaults, | ||
822 | .num_reg_defaults = ARRAY_SIZE(sun8i_i2s_reg_defaults), | ||
823 | .writeable_reg = sun4i_i2s_wr_reg, | ||
824 | .readable_reg = sun8i_i2s_rd_reg, | ||
825 | .volatile_reg = sun8i_i2s_volatile_reg, | ||
826 | }; | ||
827 | |||
619 | static int sun4i_i2s_runtime_resume(struct device *dev) | 828 | static int sun4i_i2s_runtime_resume(struct device *dev) |
620 | { | 829 | { |
621 | struct sun4i_i2s *i2s = dev_get_drvdata(dev); | 830 | struct sun4i_i2s *i2s = dev_get_drvdata(dev); |
@@ -654,22 +863,129 @@ static int sun4i_i2s_runtime_suspend(struct device *dev) | |||
654 | return 0; | 863 | return 0; |
655 | } | 864 | } |
656 | 865 | ||
657 | struct sun4i_i2s_quirks { | ||
658 | bool has_reset; | ||
659 | }; | ||
660 | |||
661 | static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { | 866 | static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { |
662 | .has_reset = false, | 867 | .has_reset = false, |
868 | .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, | ||
869 | .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, | ||
870 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | ||
871 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | ||
872 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | ||
873 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | ||
874 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | ||
875 | .has_slave_select_bit = true, | ||
876 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | ||
877 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | ||
878 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | ||
879 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
880 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
663 | }; | 881 | }; |
664 | 882 | ||
665 | static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { | 883 | static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { |
666 | .has_reset = true, | 884 | .has_reset = true, |
885 | .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, | ||
886 | .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, | ||
887 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | ||
888 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | ||
889 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | ||
890 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | ||
891 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | ||
892 | .has_slave_select_bit = true, | ||
893 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | ||
894 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | ||
895 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | ||
896 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
897 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
898 | }; | ||
899 | |||
900 | static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { | ||
901 | .has_reset = true, | ||
902 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, | ||
903 | .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, | ||
904 | .mclk_offset = 1, | ||
905 | .bclk_offset = 2, | ||
906 | .fmt_offset = 3, | ||
907 | .has_fmt_set_lrck_period = true, | ||
908 | .has_chcfg = true, | ||
909 | .has_chsel_tx_chen = true, | ||
910 | .has_chsel_offset = true, | ||
911 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), | ||
912 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), | ||
913 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), | ||
914 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | ||
915 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19), | ||
916 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_CTRL_REG, 4, 5), | ||
917 | .field_txchanmap = REG_FIELD(SUN8I_I2S_TX_CHAN_MAP_REG, 0, 31), | ||
918 | .field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31), | ||
919 | .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
920 | .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
667 | }; | 921 | }; |
668 | 922 | ||
923 | static int sun4i_i2s_init_regmap_fields(struct device *dev, | ||
924 | struct sun4i_i2s *i2s) | ||
925 | { | ||
926 | i2s->field_clkdiv_mclk_en = | ||
927 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
928 | i2s->variant->field_clkdiv_mclk_en); | ||
929 | if (IS_ERR(i2s->field_clkdiv_mclk_en)) | ||
930 | return PTR_ERR(i2s->field_clkdiv_mclk_en); | ||
931 | |||
932 | i2s->field_fmt_wss = | ||
933 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
934 | i2s->variant->field_fmt_wss); | ||
935 | if (IS_ERR(i2s->field_fmt_wss)) | ||
936 | return PTR_ERR(i2s->field_fmt_wss); | ||
937 | |||
938 | i2s->field_fmt_sr = | ||
939 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
940 | i2s->variant->field_fmt_sr); | ||
941 | if (IS_ERR(i2s->field_fmt_sr)) | ||
942 | return PTR_ERR(i2s->field_fmt_sr); | ||
943 | |||
944 | i2s->field_fmt_bclk = | ||
945 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
946 | i2s->variant->field_fmt_bclk); | ||
947 | if (IS_ERR(i2s->field_fmt_bclk)) | ||
948 | return PTR_ERR(i2s->field_fmt_bclk); | ||
949 | |||
950 | i2s->field_fmt_lrclk = | ||
951 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
952 | i2s->variant->field_fmt_lrclk); | ||
953 | if (IS_ERR(i2s->field_fmt_lrclk)) | ||
954 | return PTR_ERR(i2s->field_fmt_lrclk); | ||
955 | |||
956 | i2s->field_fmt_mode = | ||
957 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
958 | i2s->variant->field_fmt_mode); | ||
959 | if (IS_ERR(i2s->field_fmt_mode)) | ||
960 | return PTR_ERR(i2s->field_fmt_mode); | ||
961 | |||
962 | i2s->field_txchanmap = | ||
963 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
964 | i2s->variant->field_txchanmap); | ||
965 | if (IS_ERR(i2s->field_txchanmap)) | ||
966 | return PTR_ERR(i2s->field_txchanmap); | ||
967 | |||
968 | i2s->field_rxchanmap = | ||
969 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
970 | i2s->variant->field_rxchanmap); | ||
971 | if (IS_ERR(i2s->field_rxchanmap)) | ||
972 | return PTR_ERR(i2s->field_rxchanmap); | ||
973 | |||
974 | i2s->field_txchansel = | ||
975 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
976 | i2s->variant->field_txchansel); | ||
977 | if (IS_ERR(i2s->field_txchansel)) | ||
978 | return PTR_ERR(i2s->field_txchansel); | ||
979 | |||
980 | i2s->field_rxchansel = | ||
981 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
982 | i2s->variant->field_rxchansel); | ||
983 | return PTR_ERR_OR_ZERO(i2s->field_rxchansel); | ||
984 | } | ||
985 | |||
669 | static int sun4i_i2s_probe(struct platform_device *pdev) | 986 | static int sun4i_i2s_probe(struct platform_device *pdev) |
670 | { | 987 | { |
671 | struct sun4i_i2s *i2s; | 988 | struct sun4i_i2s *i2s; |
672 | const struct sun4i_i2s_quirks *quirks; | ||
673 | struct resource *res; | 989 | struct resource *res; |
674 | void __iomem *regs; | 990 | void __iomem *regs; |
675 | int irq, ret; | 991 | int irq, ret; |
@@ -690,8 +1006,8 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
690 | return irq; | 1006 | return irq; |
691 | } | 1007 | } |
692 | 1008 | ||
693 | quirks = of_device_get_match_data(&pdev->dev); | 1009 | i2s->variant = of_device_get_match_data(&pdev->dev); |
694 | if (!quirks) { | 1010 | if (!i2s->variant) { |
695 | dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); | 1011 | dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); |
696 | return -ENODEV; | 1012 | return -ENODEV; |
697 | } | 1013 | } |
@@ -703,7 +1019,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
703 | } | 1019 | } |
704 | 1020 | ||
705 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, | 1021 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, |
706 | &sun4i_i2s_regmap_config); | 1022 | i2s->variant->sun4i_i2s_regmap); |
707 | if (IS_ERR(i2s->regmap)) { | 1023 | if (IS_ERR(i2s->regmap)) { |
708 | dev_err(&pdev->dev, "Regmap initialisation failed\n"); | 1024 | dev_err(&pdev->dev, "Regmap initialisation failed\n"); |
709 | return PTR_ERR(i2s->regmap); | 1025 | return PTR_ERR(i2s->regmap); |
@@ -715,8 +1031,8 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
715 | return PTR_ERR(i2s->mod_clk); | 1031 | return PTR_ERR(i2s->mod_clk); |
716 | } | 1032 | } |
717 | 1033 | ||
718 | if (quirks->has_reset) { | 1034 | if (i2s->variant->has_reset) { |
719 | i2s->rst = devm_reset_control_get(&pdev->dev, NULL); | 1035 | i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
720 | if (IS_ERR(i2s->rst)) { | 1036 | if (IS_ERR(i2s->rst)) { |
721 | dev_err(&pdev->dev, "Failed to get reset control\n"); | 1037 | dev_err(&pdev->dev, "Failed to get reset control\n"); |
722 | return PTR_ERR(i2s->rst); | 1038 | return PTR_ERR(i2s->rst); |
@@ -732,7 +1048,8 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
732 | } | 1048 | } |
733 | } | 1049 | } |
734 | 1050 | ||
735 | i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG; | 1051 | i2s->playback_dma_data.addr = res->start + |
1052 | i2s->variant->reg_offset_txdata; | ||
736 | i2s->playback_dma_data.maxburst = 8; | 1053 | i2s->playback_dma_data.maxburst = 8; |
737 | 1054 | ||
738 | i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; | 1055 | i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; |
@@ -759,6 +1076,12 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
759 | goto err_suspend; | 1076 | goto err_suspend; |
760 | } | 1077 | } |
761 | 1078 | ||
1079 | ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s); | ||
1080 | if (ret) { | ||
1081 | dev_err(&pdev->dev, "Could not initialise regmap fields\n"); | ||
1082 | goto err_suspend; | ||
1083 | } | ||
1084 | |||
762 | return 0; | 1085 | return 0; |
763 | 1086 | ||
764 | err_suspend: | 1087 | err_suspend: |
@@ -797,6 +1120,10 @@ static const struct of_device_id sun4i_i2s_match[] = { | |||
797 | .compatible = "allwinner,sun6i-a31-i2s", | 1120 | .compatible = "allwinner,sun6i-a31-i2s", |
798 | .data = &sun6i_a31_i2s_quirks, | 1121 | .data = &sun6i_a31_i2s_quirks, |
799 | }, | 1122 | }, |
1123 | { | ||
1124 | .compatible = "allwinner,sun8i-h3-i2s", | ||
1125 | .data = &sun8i_h3_i2s_quirks, | ||
1126 | }, | ||
800 | {} | 1127 | {} |
801 | }; | 1128 | }; |
802 | MODULE_DEVICE_TABLE(of, sun4i_i2s_match); | 1129 | MODULE_DEVICE_TABLE(of, sun4i_i2s_match); |
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index eaefd07a5ed0..b4af4aabead1 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c | |||
@@ -458,11 +458,16 @@ static int sun4i_spdif_runtime_suspend(struct device *dev) | |||
458 | static int sun4i_spdif_runtime_resume(struct device *dev) | 458 | static int sun4i_spdif_runtime_resume(struct device *dev) |
459 | { | 459 | { |
460 | struct sun4i_spdif_dev *host = dev_get_drvdata(dev); | 460 | struct sun4i_spdif_dev *host = dev_get_drvdata(dev); |
461 | int ret; | ||
461 | 462 | ||
462 | clk_prepare_enable(host->spdif_clk); | 463 | ret = clk_prepare_enable(host->spdif_clk); |
463 | clk_prepare_enable(host->apb_clk); | 464 | if (ret) |
465 | return ret; | ||
466 | ret = clk_prepare_enable(host->apb_clk); | ||
467 | if (ret) | ||
468 | clk_disable_unprepare(host->spdif_clk); | ||
464 | 469 | ||
465 | return 0; | 470 | return ret; |
466 | } | 471 | } |
467 | 472 | ||
468 | static int sun4i_spdif_probe(struct platform_device *pdev) | 473 | static int sun4i_spdif_probe(struct platform_device *pdev) |
@@ -520,7 +525,8 @@ static int sun4i_spdif_probe(struct platform_device *pdev) | |||
520 | platform_set_drvdata(pdev, host); | 525 | platform_set_drvdata(pdev, host); |
521 | 526 | ||
522 | if (quirks->has_reset) { | 527 | if (quirks->has_reset) { |
523 | host->rst = devm_reset_control_get_optional(&pdev->dev, NULL); | 528 | host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, |
529 | NULL); | ||
524 | if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) { | 530 | if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) { |
525 | ret = -EPROBE_DEFER; | 531 | ret = -EPROBE_DEFER; |
526 | dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); | 532 | dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); |
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 5723c3404f6b..abfb710df7cb 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c | |||
@@ -341,7 +341,7 @@ static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = { | |||
341 | "AIF1 Slot 0 Right"}, | 341 | "AIF1 Slot 0 Right"}, |
342 | }; | 342 | }; |
343 | 343 | ||
344 | static struct snd_soc_dai_ops sun8i_codec_dai_ops = { | 344 | static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { |
345 | .hw_params = sun8i_codec_hw_params, | 345 | .hw_params = sun8i_codec_hw_params, |
346 | .set_fmt = sun8i_set_fmt, | 346 | .set_fmt = sun8i_set_fmt, |
347 | }; | 347 | }; |
@@ -360,7 +360,7 @@ static struct snd_soc_dai_driver sun8i_codec_dai = { | |||
360 | .ops = &sun8i_codec_dai_ops, | 360 | .ops = &sun8i_codec_dai_ops, |
361 | }; | 361 | }; |
362 | 362 | ||
363 | static struct snd_soc_codec_driver sun8i_soc_codec = { | 363 | static const struct snd_soc_codec_driver sun8i_soc_codec = { |
364 | .component_driver = { | 364 | .component_driver = { |
365 | .dapm_widgets = sun8i_codec_dapm_widgets, | 365 | .dapm_widgets = sun8i_codec_dapm_widgets, |
366 | .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), | 366 | .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), |