Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branches 'asoc/topic/simple', 'asoc/topic/spear', 'asoc/topic/sta32x', 'asoc/topic/stm32' and 'asoc/topic/sunxi' into asoc-next

+441 -93
+3
Documentation/devicetree/bindings/sound/simple-card.txt
··· 86 86 in dai startup() and disabled with 87 87 clk_disable_unprepare() in dai 88 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 93 Example 1 - single DAI link: 91 94
+1
Documentation/devicetree/bindings/sound/simple-scu-card.txt
··· 24 24 - simple-audio-card,convert-rate : platform specified sampling rate convert 25 25 - simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) 26 26 - simple-audio-card,prefix : see routing 27 + - simple-audio-card,widgets : Please refer to widgets.txt. 27 28 - simple-audio-card,routing : A list of the connections between audio components. 28 29 Each entry is a pair of strings, the first being the connection's sink, 29 30 the second being the connection's source. Valid names for sources.
+2
Documentation/devicetree/bindings/sound/sun4i-i2s.txt
··· 8 8 - compatible: should be one of the following: 9 9 - "allwinner,sun4i-a10-i2s" 10 10 - "allwinner,sun6i-a31-i2s" 11 + - "allwinner,sun8i-h3-i2s" 11 12 - reg: physical base address of the controller and length of memory mapped 12 13 region. 13 14 - interrupts: should contain the I2S interrupt. ··· 23 22 24 23 Required properties for the following compatibles: 25 24 - "allwinner,sun6i-a31-i2s" 25 + - "allwinner,sun8i-h3-i2s" 26 26 - resets: phandle to the reset line for this codec 27 27 28 28 Example:
+1
include/sound/simple_card_utils.h
··· 15 15 struct asoc_simple_dai { 16 16 const char *name; 17 17 unsigned int sysclk; 18 + int clk_direction; 18 19 int slots; 19 20 int slot_width; 20 21 unsigned int tx_slot_mask;
+1 -2
sound/soc/codecs/sta32x.c
··· 847 847 msleep(300); 848 848 sta32x_watchdog_stop(sta32x); 849 849 850 - if (sta32x->gpiod_nreset) 851 - gpiod_set_value(sta32x->gpiod_nreset, 0); 850 + gpiod_set_value(sta32x->gpiod_nreset, 0); 852 851 853 852 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), 854 853 sta32x->supplies);
+1
sound/soc/generic/audio-graph-card.c
··· 325 325 static struct platform_driver asoc_graph_card = { 326 326 .driver = { 327 327 .name = "asoc-audio-graph-card", 328 + .pm = &snd_soc_pm_ops, 328 329 .of_match_table = asoc_graph_of_match, 329 330 }, 330 331 .probe = asoc_graph_card_probe,
+1
sound/soc/generic/audio-graph-scu-card.c
··· 401 401 static struct platform_driver asoc_graph_card = { 402 402 .driver = { 403 403 .name = "asoc-audio-graph-scu-card", 404 + .pm = &snd_soc_pm_ops, 404 405 .of_match_table = asoc_graph_of_match, 405 406 }, 406 407 .probe = asoc_graph_card_probe,
+7 -2
sound/soc/generic/simple-card-utils.c
··· 196 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 205 return 0; 202 206 } ··· 312 308 int ret; 313 309 314 310 if (simple_dai->sysclk) { 315 - ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0); 311 + ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 312 + simple_dai->clk_direction); 316 313 if (ret && ret != -ENOTSUPP) { 317 314 dev_err(dai->dev, "simple-card: set_sysclk error\n"); 318 315 return ret;
+5
sound/soc/generic/simple-scu-card.c
··· 191 191 if (!node) 192 192 return -EINVAL; 193 193 194 + ret = asoc_simple_card_of_parse_widgets(card, PREFIX); 195 + if (ret < 0) 196 + return ret; 197 + 194 198 ret = asoc_simple_card_of_parse_routing(card, PREFIX, 0); 195 199 if (ret < 0) 196 200 return ret; ··· 300 296 static struct platform_driver asoc_simple_card = { 301 297 .driver = { 302 298 .name = "simple-scu-audio-card", 299 + .pm = &snd_soc_pm_ops, 303 300 .of_match_table = asoc_simple_of_match, 304 301 }, 305 302 .probe = asoc_simple_card_probe,
+6 -6
sound/soc/spear/spdif_in.c
··· 151 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 155 .shutdown = spdif_in_shutdown, 156 156 .trigger = spdif_in_trigger, 157 157 .hw_params = spdif_in_hw_params, ··· 216 216 return -EINVAL; 217 217 218 218 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); 219 - if (!host) { 220 - dev_warn(&pdev->dev, "kzalloc fail\n"); 219 + if (!host) 221 220 return -ENOMEM; 222 - } 223 221 224 222 host->io_base = io_base; 225 223 host->irq = platform_get_irq(pdev, 0); 226 - if (host->irq < 0) 227 - return -EINVAL; 224 + if (host->irq < 0) { 225 + dev_warn(&pdev->dev, "failed to get IRQ: %d\n", host->irq); 226 + return host->irq; 227 + } 228 228 229 229 host->clk = devm_clk_get(&pdev->dev, NULL); 230 230 if (IS_ERR(host->clk))
+1 -3
sound/soc/spear/spdif_out.c
··· 282 282 int ret; 283 283 284 284 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); 285 - if (!host) { 286 - dev_warn(&pdev->dev, "kzalloc fail\n"); 285 + if (!host) 287 286 return -ENOMEM; 288 - } 289 287 290 288 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 291 289 host->io_base = devm_ioremap_resource(&pdev->dev, res);
+1 -1
sound/soc/stm/stm32_i2s.c
··· 840 840 } 841 841 842 842 /* Reset */ 843 - rst = devm_reset_control_get(&pdev->dev, NULL); 843 + rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); 844 844 if (!IS_ERR(rst)) { 845 845 reset_control_assert(rst); 846 846 udelay(2);
+1 -1
sound/soc/stm/stm32_sai.c
··· 85 85 } 86 86 87 87 /* reset */ 88 - rst = reset_control_get(&pdev->dev, NULL); 88 + rst = reset_control_get_exclusive(&pdev->dev, NULL); 89 89 if (!IS_ERR(rst)) { 90 90 reset_control_assert(rst); 91 91 udelay(2);
+1 -1
sound/soc/stm/stm32_spdifrx.c
··· 930 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 934 if (!IS_ERR(rst)) { 935 935 reset_control_assert(rst); 936 936 udelay(2);
+7 -8
sound/soc/sunxi/sun4i-codec.c
··· 762 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 766 .component_driver = { 767 767 .controls = sun4i_codec_controls, 768 768 .num_controls = ARRAY_SIZE(sun4i_codec_controls), ··· 1068 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 1072 .component_driver = { 1073 1073 .controls = sun6i_codec_codec_widgets, 1074 1074 .num_controls = ARRAY_SIZE(sun6i_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 1100 .component_driver = { 1101 1101 .controls = sun8i_a23_codec_codec_controls, 1102 1102 .num_controls = ARRAY_SIZE(sun8i_a23_codec_codec_controls), ··· 1171 1171 { 1172 1172 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card); 1173 1173 1174 - if (scodec->gpio_pa) 1175 - gpiod_set_value_cansleep(scodec->gpio_pa, 1176 - !!SND_SOC_DAPM_EVENT_ON(event)); 1174 + gpiod_set_value_cansleep(scodec->gpio_pa, 1175 + !!SND_SOC_DAPM_EVENT_ON(event)); 1177 1176 1178 1177 return 0; 1179 1178 } ··· 1573 1574 } 1574 1575 1575 1576 if (quirks->has_reset) { 1576 - scodec->rst = devm_reset_control_get(&pdev->dev, NULL); 1577 + scodec->rst = devm_reset_control_get_exclusive(&pdev->dev, 1578 + NULL); 1577 1579 if (IS_ERR(scodec->rst)) { 1578 1580 dev_err(&pdev->dev, "Failed to get reset control\n"); 1579 1581 return PTR_ERR(scodec->rst); ··· 1655 1655 goto err_unregister_codec; 1656 1656 } 1657 1657 1658 - platform_set_drvdata(pdev, card); 1659 1658 snd_soc_card_set_drvdata(card, scodec); 1660 1659 1661 1660 ret = snd_soc_register_card(card);
+390 -63
sound/soc/sunxi/sun4i-i2s.c
··· 50 50 #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0) 51 51 #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0) 52 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 56 #define SUN4I_I2S_FMT1_REG 0x08 55 57 #define SUN4I_I2S_FIFO_TX_REG 0x0c ··· 84 82 #define SUN4I_I2S_TX_CNT_REG 0x2c 85 83 86 84 #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30 87 - #define SUN4I_I2S_TX_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) 85 + #define SUN4I_I2S_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) 88 86 89 87 #define SUN4I_I2S_TX_CHAN_MAP_REG 0x34 90 88 #define SUN4I_I2S_TX_CHAN_MAP(chan, sample) ((sample) << (chan << 2)) 91 89 92 90 #define SUN4I_I2S_RX_CHAN_SEL_REG 0x38 93 91 #define SUN4I_I2S_RX_CHAN_MAP_REG 0x3c 92 + 93 + /* Defines required for sun8i-h3 support */ 94 + #define SUN8I_I2S_CTRL_BCLK_OUT BIT(18) 95 + #define SUN8I_I2S_CTRL_LRCK_OUT BIT(17) 96 + 97 + #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8) 98 + #define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8) 99 + 100 + #define SUN8I_I2S_INT_STA_REG 0x0c 101 + #define SUN8I_I2S_FIFO_TX_REG 0x20 102 + 103 + #define SUN8I_I2S_CHAN_CFG_REG 0x30 104 + #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4) 105 + #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) (chan - 1) 106 + #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) 107 + #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1) 108 + 109 + #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 110 + #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 111 + #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 11) 112 + #define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) 113 + #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) 114 + #define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) 115 + 116 + #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 117 + #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 118 + 119 + /** 120 + * struct sun4i_i2s_quirks - Differences between SoC variants. 121 + * 122 + * @has_reset: SoC needs reset deasserted. 123 + * @has_slave_select_bit: SoC has a bit to enable slave mode. 124 + * @has_fmt_set_lrck_period: SoC requires lrclk period to be set. 125 + * @has_chcfg: tx and rx slot number need to be set. 126 + * @has_chsel_tx_chen: SoC requires that the tx channels are enabled. 127 + * @has_chsel_offset: SoC uses offset for selecting dai operational mode. 128 + * @reg_offset_txdata: offset of the tx fifo. 129 + * @sun4i_i2s_regmap: regmap config to use. 130 + * @mclk_offset: Value by which mclkdiv needs to be adjusted. 131 + * @bclk_offset: Value by which bclkdiv needs to be adjusted. 132 + * @fmt_offset: Value by which wss and sr needs to be adjusted. 133 + * @field_clkdiv_mclk_en: regmap field to enable mclk output. 134 + * @field_fmt_wss: regmap field to set word select size. 135 + * @field_fmt_sr: regmap field to set sample resolution. 136 + * @field_fmt_bclk: regmap field to set clk polarity. 137 + * @field_fmt_lrclk: regmap field to set frame polarity. 138 + * @field_fmt_mode: regmap field to set the operational mode. 139 + * @field_txchanmap: location of the tx channel mapping register. 140 + * @field_rxchanmap: location of the rx channel mapping register. 141 + * @field_txchansel: location of the tx channel select bit fields. 142 + * @field_rxchansel: location of the rx channel select bit fields. 143 + */ 144 + struct sun4i_i2s_quirks { 145 + bool has_reset; 146 + bool has_slave_select_bit; 147 + bool has_fmt_set_lrck_period; 148 + bool has_chcfg; 149 + bool has_chsel_tx_chen; 150 + bool has_chsel_offset; 151 + unsigned int reg_offset_txdata; /* TX FIFO */ 152 + const struct regmap_config *sun4i_i2s_regmap; 153 + unsigned int mclk_offset; 154 + unsigned int bclk_offset; 155 + unsigned int fmt_offset; 156 + 157 + /* Register fields for i2s */ 158 + struct reg_field field_clkdiv_mclk_en; 159 + struct reg_field field_fmt_wss; 160 + struct reg_field field_fmt_sr; 161 + struct reg_field field_fmt_bclk; 162 + struct reg_field field_fmt_lrclk; 163 + struct reg_field field_fmt_mode; 164 + struct reg_field field_txchanmap; 165 + struct reg_field field_rxchanmap; 166 + struct reg_field field_txchansel; 167 + struct reg_field field_rxchansel; 168 + }; 94 169 95 170 struct sun4i_i2s { 96 171 struct clk *bus_clk; ··· 179 100 180 101 struct snd_dmaengine_dai_dma_data capture_dma_data; 181 102 struct snd_dmaengine_dai_dma_data playback_dma_data; 103 + 104 + /* Register fields for i2s */ 105 + struct regmap_field *field_clkdiv_mclk_en; 106 + struct regmap_field *field_fmt_wss; 107 + struct regmap_field *field_fmt_sr; 108 + struct regmap_field *field_fmt_bclk; 109 + struct regmap_field *field_fmt_lrclk; 110 + struct regmap_field *field_fmt_mode; 111 + struct regmap_field *field_txchanmap; 112 + struct regmap_field *field_rxchanmap; 113 + struct regmap_field *field_txchansel; 114 + struct regmap_field *field_rxchansel; 115 + 116 + const struct sun4i_i2s_quirks *variant; 182 117 }; 183 118 184 119 struct sun4i_i2s_clk_div { ··· 207 114 { .div = 8, .val = 3 }, 208 115 { .div = 12, .val = 4 }, 209 116 { .div = 16, .val = 5 }, 117 + /* TODO - extend divide ratio supported by newer SoCs */ 210 118 }; 211 119 212 120 static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = { ··· 219 125 { .div = 12, .val = 5 }, 220 126 { .div = 16, .val = 6 }, 221 127 { .div = 24, .val = 7 }, 128 + /* TODO - extend divide ratio supported by newer SoCs */ 222 129 }; 223 130 224 131 static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, ··· 321 226 if (mclk_div < 0) 322 227 return -EINVAL; 323 228 229 + /* Adjust the clock division values if needed */ 230 + bclk_div += i2s->variant->bclk_offset; 231 + mclk_div += i2s->variant->mclk_offset; 232 + 324 233 regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG, 325 234 SUN4I_I2S_CLK_DIV_BCLK(bclk_div) | 326 - SUN4I_I2S_CLK_DIV_MCLK(mclk_div) | 327 - SUN4I_I2S_CLK_DIV_MCLK_EN); 235 + SUN4I_I2S_CLK_DIV_MCLK(mclk_div)); 236 + 237 + regmap_field_write(i2s->field_clkdiv_mclk_en, 1); 238 + 239 + /* Set sync period */ 240 + if (i2s->variant->has_fmt_set_lrck_period) 241 + regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 242 + SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, 243 + SUN8I_I2S_FMT0_LRCK_PERIOD(32)); 328 244 329 245 return 0; 330 246 } ··· 345 239 struct snd_soc_dai *dai) 346 240 { 347 241 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 348 - int sr, wss; 242 + int sr, wss, channels; 349 243 u32 width; 350 244 351 - if (params_channels(params) != 2) 245 + channels = params_channels(params); 246 + if (channels != 2) 352 247 return -EINVAL; 248 + 249 + if (i2s->variant->has_chcfg) { 250 + regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, 251 + SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, 252 + SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); 253 + regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, 254 + SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, 255 + SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); 256 + } 257 + 258 + /* Map the channels for playback and capture */ 259 + regmap_field_write(i2s->field_txchanmap, 0x76543210); 260 + regmap_field_write(i2s->field_rxchanmap, 0x00003210); 261 + 262 + /* Configure the channels */ 263 + regmap_field_write(i2s->field_txchansel, 264 + SUN4I_I2S_CHAN_SEL(params_channels(params))); 265 + 266 + regmap_field_write(i2s->field_rxchansel, 267 + SUN4I_I2S_CHAN_SEL(params_channels(params))); 268 + 269 + if (i2s->variant->has_chsel_tx_chen) 270 + regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 271 + SUN8I_I2S_TX_CHAN_EN_MASK, 272 + SUN8I_I2S_TX_CHAN_EN(channels)); 353 273 354 274 switch (params_physical_width(params)) { 355 275 case 16: ··· 396 264 return -EINVAL; 397 265 } 398 266 399 - regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 400 - SUN4I_I2S_FMT0_WSS_MASK | SUN4I_I2S_FMT0_SR_MASK, 401 - SUN4I_I2S_FMT0_WSS(wss) | SUN4I_I2S_FMT0_SR(sr)); 267 + regmap_field_write(i2s->field_fmt_wss, 268 + wss + i2s->variant->fmt_offset); 269 + regmap_field_write(i2s->field_fmt_sr, 270 + sr + i2s->variant->fmt_offset); 402 271 403 272 return sun4i_i2s_set_clk_rate(i2s, params_rate(params), 404 273 params_width(params)); ··· 409 276 { 410 277 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 411 278 u32 val; 279 + u32 offset = 0; 280 + u32 bclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL; 281 + u32 lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL; 412 282 413 283 /* DAI Mode */ 414 284 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 415 285 case SND_SOC_DAIFMT_I2S: 416 286 val = SUN4I_I2S_FMT0_FMT_I2S; 287 + offset = 1; 417 288 break; 418 289 case SND_SOC_DAIFMT_LEFT_J: 419 290 val = SUN4I_I2S_FMT0_FMT_LEFT_J; ··· 429 292 return -EINVAL; 430 293 } 431 294 432 - regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 433 - SUN4I_I2S_FMT0_FMT_MASK, 434 - val); 295 + if (i2s->variant->has_chsel_offset) { 296 + /* 297 + * offset being set indicates that we're connected to an i2s 298 + * device, however offset is only used on the sun8i block and 299 + * i2s shares the same setting with the LJ format. Increment 300 + * val so that the bit to value to write is correct. 301 + */ 302 + if (offset > 0) 303 + val++; 304 + /* blck offset determines whether i2s or LJ */ 305 + regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 306 + SUN8I_I2S_TX_CHAN_OFFSET_MASK, 307 + SUN8I_I2S_TX_CHAN_OFFSET(offset)); 308 + } 309 + 310 + regmap_field_write(i2s->field_fmt_mode, val); 435 311 436 312 /* DAI clock polarity */ 437 313 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 438 314 case SND_SOC_DAIFMT_IB_IF: 439 315 /* Invert both clocks */ 440 - val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED | 441 - SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED; 316 + bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; 317 + lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; 442 318 break; 443 319 case SND_SOC_DAIFMT_IB_NF: 444 320 /* Invert bit clock */ 445 - val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED | 446 - SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL; 321 + bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; 447 322 break; 448 323 case SND_SOC_DAIFMT_NB_IF: 449 324 /* Invert frame clock */ 450 - val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED | 451 - SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL; 325 + lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; 452 326 break; 453 327 case SND_SOC_DAIFMT_NB_NF: 454 - /* Nothing to do for both normal cases */ 455 - val = SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL | 456 - SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL; 457 328 break; 458 329 default: 459 330 return -EINVAL; 460 331 } 461 332 462 - regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 463 - SUN4I_I2S_FMT0_BCLK_POLARITY_MASK | 464 - SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK, 465 - val); 333 + regmap_field_write(i2s->field_fmt_bclk, bclk_polarity); 334 + regmap_field_write(i2s->field_fmt_lrclk, lrclk_polarity); 466 335 467 - /* DAI clock master masks */ 468 - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 469 - case SND_SOC_DAIFMT_CBS_CFS: 470 - /* BCLK and LRCLK master */ 471 - val = SUN4I_I2S_CTRL_MODE_MASTER; 472 - break; 473 - case SND_SOC_DAIFMT_CBM_CFM: 474 - /* BCLK and LRCLK slave */ 475 - val = SUN4I_I2S_CTRL_MODE_SLAVE; 476 - break; 477 - default: 478 - return -EINVAL; 336 + if (i2s->variant->has_slave_select_bit) { 337 + /* DAI clock master masks */ 338 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 339 + case SND_SOC_DAIFMT_CBS_CFS: 340 + /* BCLK and LRCLK master */ 341 + val = SUN4I_I2S_CTRL_MODE_MASTER; 342 + break; 343 + case SND_SOC_DAIFMT_CBM_CFM: 344 + /* BCLK and LRCLK slave */ 345 + val = SUN4I_I2S_CTRL_MODE_SLAVE; 346 + break; 347 + default: 348 + return -EINVAL; 349 + } 350 + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 351 + SUN4I_I2S_CTRL_MODE_MASK, 352 + val); 353 + } else { 354 + /* 355 + * The newer i2s block does not have a slave select bit, 356 + * instead the clk pins are configured as inputs. 357 + */ 358 + /* DAI clock master masks */ 359 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 360 + case SND_SOC_DAIFMT_CBS_CFS: 361 + /* BCLK and LRCLK master */ 362 + val = SUN8I_I2S_CTRL_BCLK_OUT | 363 + SUN8I_I2S_CTRL_LRCK_OUT; 364 + break; 365 + case SND_SOC_DAIFMT_CBM_CFM: 366 + /* BCLK and LRCLK slave */ 367 + val = 0; 368 + break; 369 + default: 370 + return -EINVAL; 371 + } 372 + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 373 + SUN8I_I2S_CTRL_BCLK_OUT | 374 + SUN8I_I2S_CTRL_LRCK_OUT, 375 + val); 479 376 } 480 - 481 - regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 482 - SUN4I_I2S_CTRL_MODE_MASK, 483 - val); 484 377 485 378 /* Set significant bits in our FIFOs */ 486 379 regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, ··· 626 459 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 627 460 628 461 /* Enable the whole hardware block */ 629 - regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG, 630 - SUN4I_I2S_CTRL_GL_EN); 462 + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 463 + SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN); 631 464 632 465 /* Enable the first output line */ 633 466 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 634 467 SUN4I_I2S_CTRL_SDO_EN_MASK, 635 468 SUN4I_I2S_CTRL_SDO_EN(0)); 636 469 637 - /* Enable the first two channels */ 638 - regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG, 639 - SUN4I_I2S_TX_CHAN_SEL(2)); 640 - 641 - /* Map them to the two first samples coming in */ 642 - regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 643 - SUN4I_I2S_TX_CHAN_MAP(0, 0) | SUN4I_I2S_TX_CHAN_MAP(1, 1)); 644 470 645 471 return clk_prepare_enable(i2s->mod_clk); 646 472 } ··· 650 490 SUN4I_I2S_CTRL_SDO_EN_MASK, 0); 651 491 652 492 /* Disable the whole hardware block */ 653 - regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG, 0); 493 + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 494 + SUN4I_I2S_CTRL_GL_EN, 0); 654 495 } 655 496 656 497 static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, ··· 750 589 } 751 590 } 752 591 592 + static bool sun8i_i2s_rd_reg(struct device *dev, unsigned int reg) 593 + { 594 + switch (reg) { 595 + case SUN8I_I2S_FIFO_TX_REG: 596 + return false; 597 + 598 + default: 599 + return true; 600 + } 601 + } 602 + 603 + static bool sun8i_i2s_volatile_reg(struct device *dev, unsigned int reg) 604 + { 605 + if (reg == SUN8I_I2S_INT_STA_REG) 606 + return true; 607 + if (reg == SUN8I_I2S_FIFO_TX_REG) 608 + return false; 609 + 610 + return sun4i_i2s_volatile_reg(dev, reg); 611 + } 612 + 753 613 static const struct reg_default sun4i_i2s_reg_defaults[] = { 754 614 { SUN4I_I2S_CTRL_REG, 0x00000000 }, 755 615 { SUN4I_I2S_FMT0_REG, 0x0000000c }, ··· 782 600 { SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210 }, 783 601 { SUN4I_I2S_RX_CHAN_SEL_REG, 0x00000001 }, 784 602 { SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210 }, 603 + }; 604 + 605 + static const struct reg_default sun8i_i2s_reg_defaults[] = { 606 + { SUN4I_I2S_CTRL_REG, 0x00060000 }, 607 + { SUN4I_I2S_FMT0_REG, 0x00000033 }, 608 + { SUN4I_I2S_FMT1_REG, 0x00000030 }, 609 + { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 }, 610 + { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, 611 + { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, 612 + { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, 613 + { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, 614 + { SUN8I_I2S_TX_CHAN_MAP_REG, 0x00000000 }, 615 + { SUN8I_I2S_RX_CHAN_SEL_REG, 0x00000000 }, 616 + { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 }, 785 617 }; 786 618 787 619 static const struct regmap_config sun4i_i2s_regmap_config = { ··· 810 614 .writeable_reg = sun4i_i2s_wr_reg, 811 615 .readable_reg = sun4i_i2s_rd_reg, 812 616 .volatile_reg = sun4i_i2s_volatile_reg, 617 + }; 618 + 619 + static const struct regmap_config sun8i_i2s_regmap_config = { 620 + .reg_bits = 32, 621 + .reg_stride = 4, 622 + .val_bits = 32, 623 + .max_register = SUN8I_I2S_RX_CHAN_MAP_REG, 624 + .cache_type = REGCACHE_FLAT, 625 + .reg_defaults = sun8i_i2s_reg_defaults, 626 + .num_reg_defaults = ARRAY_SIZE(sun8i_i2s_reg_defaults), 627 + .writeable_reg = sun4i_i2s_wr_reg, 628 + .readable_reg = sun8i_i2s_rd_reg, 629 + .volatile_reg = sun8i_i2s_volatile_reg, 813 630 }; 814 631 815 632 static int sun4i_i2s_runtime_resume(struct device *dev) ··· 863 654 return 0; 864 655 } 865 656 866 - struct sun4i_i2s_quirks { 867 - bool has_reset; 868 - }; 869 - 870 657 static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { 871 - .has_reset = false, 658 + .has_reset = false, 659 + .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, 660 + .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, 661 + .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), 662 + .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), 663 + .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 664 + .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), 665 + .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 666 + .has_slave_select_bit = true, 667 + .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), 668 + .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), 669 + .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), 670 + .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), 671 + .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), 872 672 }; 873 673 874 674 static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { 875 - .has_reset = true, 675 + .has_reset = true, 676 + .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, 677 + .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, 678 + .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), 679 + .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), 680 + .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 681 + .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), 682 + .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 683 + .has_slave_select_bit = true, 684 + .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), 685 + .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), 686 + .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), 687 + .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), 688 + .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), 876 689 }; 690 + 691 + static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { 692 + .has_reset = true, 693 + .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, 694 + .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, 695 + .mclk_offset = 1, 696 + .bclk_offset = 2, 697 + .fmt_offset = 3, 698 + .has_fmt_set_lrck_period = true, 699 + .has_chcfg = true, 700 + .has_chsel_tx_chen = true, 701 + .has_chsel_offset = true, 702 + .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), 703 + .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), 704 + .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), 705 + .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 706 + .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19), 707 + .field_fmt_mode = REG_FIELD(SUN4I_I2S_CTRL_REG, 4, 5), 708 + .field_txchanmap = REG_FIELD(SUN8I_I2S_TX_CHAN_MAP_REG, 0, 31), 709 + .field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31), 710 + .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2), 711 + .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), 712 + }; 713 + 714 + static int sun4i_i2s_init_regmap_fields(struct device *dev, 715 + struct sun4i_i2s *i2s) 716 + { 717 + i2s->field_clkdiv_mclk_en = 718 + devm_regmap_field_alloc(dev, i2s->regmap, 719 + i2s->variant->field_clkdiv_mclk_en); 720 + if (IS_ERR(i2s->field_clkdiv_mclk_en)) 721 + return PTR_ERR(i2s->field_clkdiv_mclk_en); 722 + 723 + i2s->field_fmt_wss = 724 + devm_regmap_field_alloc(dev, i2s->regmap, 725 + i2s->variant->field_fmt_wss); 726 + if (IS_ERR(i2s->field_fmt_wss)) 727 + return PTR_ERR(i2s->field_fmt_wss); 728 + 729 + i2s->field_fmt_sr = 730 + devm_regmap_field_alloc(dev, i2s->regmap, 731 + i2s->variant->field_fmt_sr); 732 + if (IS_ERR(i2s->field_fmt_sr)) 733 + return PTR_ERR(i2s->field_fmt_sr); 734 + 735 + i2s->field_fmt_bclk = 736 + devm_regmap_field_alloc(dev, i2s->regmap, 737 + i2s->variant->field_fmt_bclk); 738 + if (IS_ERR(i2s->field_fmt_bclk)) 739 + return PTR_ERR(i2s->field_fmt_bclk); 740 + 741 + i2s->field_fmt_lrclk = 742 + devm_regmap_field_alloc(dev, i2s->regmap, 743 + i2s->variant->field_fmt_lrclk); 744 + if (IS_ERR(i2s->field_fmt_lrclk)) 745 + return PTR_ERR(i2s->field_fmt_lrclk); 746 + 747 + i2s->field_fmt_mode = 748 + devm_regmap_field_alloc(dev, i2s->regmap, 749 + i2s->variant->field_fmt_mode); 750 + if (IS_ERR(i2s->field_fmt_mode)) 751 + return PTR_ERR(i2s->field_fmt_mode); 752 + 753 + i2s->field_txchanmap = 754 + devm_regmap_field_alloc(dev, i2s->regmap, 755 + i2s->variant->field_txchanmap); 756 + if (IS_ERR(i2s->field_txchanmap)) 757 + return PTR_ERR(i2s->field_txchanmap); 758 + 759 + i2s->field_rxchanmap = 760 + devm_regmap_field_alloc(dev, i2s->regmap, 761 + i2s->variant->field_rxchanmap); 762 + if (IS_ERR(i2s->field_rxchanmap)) 763 + return PTR_ERR(i2s->field_rxchanmap); 764 + 765 + i2s->field_txchansel = 766 + devm_regmap_field_alloc(dev, i2s->regmap, 767 + i2s->variant->field_txchansel); 768 + if (IS_ERR(i2s->field_txchansel)) 769 + return PTR_ERR(i2s->field_txchansel); 770 + 771 + i2s->field_rxchansel = 772 + devm_regmap_field_alloc(dev, i2s->regmap, 773 + i2s->variant->field_rxchansel); 774 + return PTR_ERR_OR_ZERO(i2s->field_rxchansel); 775 + } 877 776 878 777 static int sun4i_i2s_probe(struct platform_device *pdev) 879 778 { 880 779 struct sun4i_i2s *i2s; 881 - const struct sun4i_i2s_quirks *quirks; 882 780 struct resource *res; 883 781 void __iomem *regs; 884 782 int irq, ret; ··· 1006 690 return irq; 1007 691 } 1008 692 1009 - quirks = of_device_get_match_data(&pdev->dev); 1010 - if (!quirks) { 693 + i2s->variant = of_device_get_match_data(&pdev->dev); 694 + if (!i2s->variant) { 1011 695 dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); 1012 696 return -ENODEV; 1013 697 } ··· 1019 703 } 1020 704 1021 705 i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 1022 - &sun4i_i2s_regmap_config); 706 + i2s->variant->sun4i_i2s_regmap); 1023 707 if (IS_ERR(i2s->regmap)) { 1024 708 dev_err(&pdev->dev, "Regmap initialisation failed\n"); 1025 709 return PTR_ERR(i2s->regmap); ··· 1031 715 return PTR_ERR(i2s->mod_clk); 1032 716 } 1033 717 1034 - if (quirks->has_reset) { 1035 - i2s->rst = devm_reset_control_get(&pdev->dev, NULL); 718 + if (i2s->variant->has_reset) { 719 + i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); 1036 720 if (IS_ERR(i2s->rst)) { 1037 721 dev_err(&pdev->dev, "Failed to get reset control\n"); 1038 722 return PTR_ERR(i2s->rst); ··· 1048 732 } 1049 733 } 1050 734 1051 - i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG; 735 + i2s->playback_dma_data.addr = res->start + 736 + i2s->variant->reg_offset_txdata; 1052 737 i2s->playback_dma_data.maxburst = 8; 1053 738 1054 739 i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; ··· 1073 756 ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 1074 757 if (ret) { 1075 758 dev_err(&pdev->dev, "Could not register PCM\n"); 759 + goto err_suspend; 760 + } 761 + 762 + ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s); 763 + if (ret) { 764 + dev_err(&pdev->dev, "Could not initialise regmap fields\n"); 1076 765 goto err_suspend; 1077 766 } 1078 767 ··· 1119 796 { 1120 797 .compatible = "allwinner,sun6i-a31-i2s", 1121 798 .data = &sun6i_a31_i2s_quirks, 799 + }, 800 + { 801 + .compatible = "allwinner,sun8i-h3-i2s", 802 + .data = &sun8i_h3_i2s_quirks, 1122 803 }, 1123 804 {} 1124 805 };
+10 -4
sound/soc/sunxi/sun4i-spdif.c
··· 458 458 static int sun4i_spdif_runtime_resume(struct device *dev) 459 459 { 460 460 struct sun4i_spdif_dev *host = dev_get_drvdata(dev); 461 + int ret; 461 462 462 - clk_prepare_enable(host->spdif_clk); 463 - clk_prepare_enable(host->apb_clk); 463 + ret = clk_prepare_enable(host->spdif_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 473 static int sun4i_spdif_probe(struct platform_device *pdev) ··· 525 520 platform_set_drvdata(pdev, host); 526 521 527 522 if (quirks->has_reset) { 528 - host->rst = devm_reset_control_get_optional(&pdev->dev, NULL); 523 + host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, 524 + NULL); 529 525 if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) { 530 526 ret = -EPROBE_DEFER; 531 527 dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
+2 -2
sound/soc/sunxi/sun8i-codec.c
··· 341 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 345 .hw_params = sun8i_codec_hw_params, 346 346 .set_fmt = sun8i_set_fmt, 347 347 }; ··· 360 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 364 .component_driver = { 365 365 .dapm_widgets = sun8i_codec_dapm_widgets, 366 366 .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets),