1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2015 Andrea Venturi 4 * Andrea Venturi <be17068@iperbole.bo.it> 5 * 6 * Copyright (C) 2016 Maxime Ripard 7 * Maxime Ripard <maxime.ripard@free-electrons.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/dmaengine.h> 12 #include <linux/module.h> 13 #include <linux/of_device.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/regmap.h> 17 #include <linux/reset.h> 18 19 #include <sound/dmaengine_pcm.h> 20 #include <sound/pcm_params.h> 21 #include <sound/soc.h> 22 #include <sound/soc-dai.h> 23 24 #define SUN4I_I2S_CTRL_REG 0x00 25 #define SUN4I_I2S_CTRL_SDO_EN_MASK GENMASK(11, 8) 26 #define SUN4I_I2S_CTRL_SDO_EN(sdo) BIT(8 + (sdo)) 27 #define SUN4I_I2S_CTRL_MODE_MASK BIT(5) 28 #define SUN4I_I2S_CTRL_MODE_SLAVE (1 << 5) 29 #define SUN4I_I2S_CTRL_MODE_MASTER (0 << 5) 30 #define SUN4I_I2S_CTRL_TX_EN BIT(2) 31 #define SUN4I_I2S_CTRL_RX_EN BIT(1) 32 #define SUN4I_I2S_CTRL_GL_EN BIT(0) 33 34 #define SUN4I_I2S_FMT0_REG 0x04 35 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(7) 36 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 7) 37 #define SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 7) 38 #define SUN4I_I2S_FMT0_BCLK_POLARITY_MASK BIT(6) 39 #define SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 6) 40 #define SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 6) 41 #define SUN4I_I2S_FMT0_SR_MASK GENMASK(5, 4) 42 #define SUN4I_I2S_FMT0_SR(sr) ((sr) << 4) 43 #define SUN4I_I2S_FMT0_WSS_MASK GENMASK(3, 2) 44 #define SUN4I_I2S_FMT0_WSS(wss) ((wss) << 2) 45 #define SUN4I_I2S_FMT0_FMT_MASK GENMASK(1, 0) 46 #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0) 47 #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0) 48 #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0) 49 50 #define SUN4I_I2S_FMT1_REG 0x08 51 #define SUN4I_I2S_FMT1_REG_SEXT_MASK BIT(8) 52 #define SUN4I_I2S_FMT1_REG_SEXT(sext) ((sext) << 8) 53 54 #define SUN4I_I2S_FIFO_TX_REG 0x0c 55 #define SUN4I_I2S_FIFO_RX_REG 0x10 56 57 #define SUN4I_I2S_FIFO_CTRL_REG 0x14 58 #define SUN4I_I2S_FIFO_CTRL_FLUSH_TX BIT(25) 59 #define SUN4I_I2S_FIFO_CTRL_FLUSH_RX BIT(24) 60 #define SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK BIT(2) 61 #define SUN4I_I2S_FIFO_CTRL_TX_MODE(mode) ((mode) << 2) 62 #define SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK GENMASK(1, 0) 63 #define SUN4I_I2S_FIFO_CTRL_RX_MODE(mode) (mode) 64 65 #define SUN4I_I2S_FIFO_STA_REG 0x18 66 67 #define SUN4I_I2S_DMA_INT_CTRL_REG 0x1c 68 #define SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN BIT(7) 69 #define SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN BIT(3) 70 71 #define SUN4I_I2S_INT_STA_REG 0x20 72 73 #define SUN4I_I2S_CLK_DIV_REG 0x24 74 #define SUN4I_I2S_CLK_DIV_MCLK_EN BIT(7) 75 #define SUN4I_I2S_CLK_DIV_BCLK_MASK GENMASK(6, 4) 76 #define SUN4I_I2S_CLK_DIV_BCLK(bclk) ((bclk) << 4) 77 #define SUN4I_I2S_CLK_DIV_MCLK_MASK GENMASK(3, 0) 78 #define SUN4I_I2S_CLK_DIV_MCLK(mclk) ((mclk) << 0) 79 80 #define SUN4I_I2S_TX_CNT_REG 0x28 81 #define SUN4I_I2S_RX_CNT_REG 0x2c 82 83 #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30 84 #define SUN4I_I2S_CHAN_SEL_MASK GENMASK(2, 0) 85 #define SUN4I_I2S_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) 86 87 #define SUN4I_I2S_TX_CHAN_MAP_REG 0x34 88 #define SUN4I_I2S_TX_CHAN_MAP(chan, sample) ((sample) << (chan << 2)) 89 90 #define SUN4I_I2S_RX_CHAN_SEL_REG 0x38 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_CTRL_MODE_MASK GENMASK(5, 4) 98 #define SUN8I_I2S_CTRL_MODE_RIGHT (2 << 4) 99 #define SUN8I_I2S_CTRL_MODE_LEFT (1 << 4) 100 #define SUN8I_I2S_CTRL_MODE_PCM (0 << 4) 101 102 #define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(19) 103 #define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19) 104 #define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19) 105 #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8) 106 #define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8) 107 #define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK BIT(7) 108 #define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 7) 109 #define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 7) 110 111 #define SUN8I_I2S_FMT1_REG_SEXT_MASK GENMASK(5, 4) 112 #define SUN8I_I2S_FMT1_REG_SEXT(sext) ((sext) << 4) 113 114 #define SUN8I_I2S_INT_STA_REG 0x0c 115 #define SUN8I_I2S_FIFO_TX_REG 0x20 116 117 #define SUN8I_I2S_CHAN_CFG_REG 0x30 118 #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4) 119 #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) ((chan - 1) << 4) 120 #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) 121 #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1) 122 123 #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 124 #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 125 #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12) 126 #define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) 127 #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) 128 #define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) 129 130 #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 131 #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 132 133 /* Defines required for sun50i-h6 support */ 134 #define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK GENMASK(21, 20) 135 #define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset) ((offset) << 20) 136 #define SUN50I_H6_I2S_TX_CHAN_SEL_MASK GENMASK(19, 16) 137 #define SUN50I_H6_I2S_TX_CHAN_SEL(chan) ((chan - 1) << 16) 138 #define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0) 139 #define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1)) 140 141 #define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44 142 #define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48 143 144 #define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64 145 #define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68 146 #define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6C 147 148 struct sun4i_i2s; 149 150 /** 151 * struct sun4i_i2s_quirks - Differences between SoC variants. 152 * @has_reset: SoC needs reset deasserted. 153 * @reg_offset_txdata: offset of the tx fifo. 154 * @sun4i_i2s_regmap: regmap config to use. 155 * @field_clkdiv_mclk_en: regmap field to enable mclk output. 156 * @field_fmt_wss: regmap field to set word select size. 157 * @field_fmt_sr: regmap field to set sample resolution. 158 * @bclk_dividers: bit clock dividers array 159 * @num_bclk_dividers: number of bit clock dividers 160 * @mclk_dividers: mclk dividers array 161 * @num_mclk_dividers: number of mclk dividers 162 * @get_bclk_parent_rate: callback to get bclk parent rate 163 * @get_sr: callback to get sample resolution 164 * @get_wss: callback to get word select size 165 * @set_chan_cfg: callback to set channel configuration 166 * @set_fmt: callback to set format 167 */ 168 struct sun4i_i2s_quirks { 169 bool has_reset; 170 unsigned int reg_offset_txdata; /* TX FIFO */ 171 const struct regmap_config *sun4i_i2s_regmap; 172 173 /* Register fields for i2s */ 174 struct reg_field field_clkdiv_mclk_en; 175 struct reg_field field_fmt_wss; 176 struct reg_field field_fmt_sr; 177 178 const struct sun4i_i2s_clk_div *bclk_dividers; 179 unsigned int num_bclk_dividers; 180 const struct sun4i_i2s_clk_div *mclk_dividers; 181 unsigned int num_mclk_dividers; 182 183 unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *i2s); 184 int (*get_sr)(unsigned int width); 185 int (*get_wss)(unsigned int width); 186 187 /* 188 * In the set_chan_cfg() function pointer: 189 * @slots: channels per frame + padding slots, regardless of format 190 * @slot_width: bits per sample + padding bits, regardless of format 191 */ 192 int (*set_chan_cfg)(const struct sun4i_i2s *i2s, 193 unsigned int channels, unsigned int slots, 194 unsigned int slot_width); 195 int (*set_fmt)(const struct sun4i_i2s *i2s, unsigned int fmt); 196 }; 197 198 struct sun4i_i2s { 199 struct clk *bus_clk; 200 struct clk *mod_clk; 201 struct regmap *regmap; 202 struct reset_control *rst; 203 204 unsigned int format; 205 unsigned int mclk_freq; 206 unsigned int slots; 207 unsigned int slot_width; 208 209 struct snd_dmaengine_dai_dma_data capture_dma_data; 210 struct snd_dmaengine_dai_dma_data playback_dma_data; 211 212 /* Register fields for i2s */ 213 struct regmap_field *field_clkdiv_mclk_en; 214 struct regmap_field *field_fmt_wss; 215 struct regmap_field *field_fmt_sr; 216 217 const struct sun4i_i2s_quirks *variant; 218 }; 219 220 struct sun4i_i2s_clk_div { 221 u8 div; 222 u8 val; 223 }; 224 225 static const struct sun4i_i2s_clk_div sun4i_i2s_bclk_div[] = { 226 { .div = 2, .val = 0 }, 227 { .div = 4, .val = 1 }, 228 { .div = 6, .val = 2 }, 229 { .div = 8, .val = 3 }, 230 { .div = 12, .val = 4 }, 231 { .div = 16, .val = 5 }, 232 /* TODO - extend divide ratio supported by newer SoCs */ 233 }; 234 235 static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = { 236 { .div = 1, .val = 0 }, 237 { .div = 2, .val = 1 }, 238 { .div = 4, .val = 2 }, 239 { .div = 6, .val = 3 }, 240 { .div = 8, .val = 4 }, 241 { .div = 12, .val = 5 }, 242 { .div = 16, .val = 6 }, 243 { .div = 24, .val = 7 }, 244 /* TODO - extend divide ratio supported by newer SoCs */ 245 }; 246 247 static const struct sun4i_i2s_clk_div sun8i_i2s_clk_div[] = { 248 { .div = 1, .val = 1 }, 249 { .div = 2, .val = 2 }, 250 { .div = 4, .val = 3 }, 251 { .div = 6, .val = 4 }, 252 { .div = 8, .val = 5 }, 253 { .div = 12, .val = 6 }, 254 { .div = 16, .val = 7 }, 255 { .div = 24, .val = 8 }, 256 { .div = 32, .val = 9 }, 257 { .div = 48, .val = 10 }, 258 { .div = 64, .val = 11 }, 259 { .div = 96, .val = 12 }, 260 { .div = 128, .val = 13 }, 261 { .div = 176, .val = 14 }, 262 { .div = 192, .val = 15 }, 263 }; 264 265 static unsigned long sun4i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s) 266 { 267 return i2s->mclk_freq; 268 } 269 270 static unsigned long sun8i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s) 271 { 272 return clk_get_rate(i2s->mod_clk); 273 } 274 275 static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, 276 unsigned long parent_rate, 277 unsigned int sampling_rate, 278 unsigned int channels, 279 unsigned int word_size) 280 { 281 const struct sun4i_i2s_clk_div *dividers = i2s->variant->bclk_dividers; 282 int div = parent_rate / sampling_rate / word_size / channels; 283 int i; 284 285 for (i = 0; i < i2s->variant->num_bclk_dividers; i++) { 286 const struct sun4i_i2s_clk_div *bdiv = ÷rs[i]; 287 288 if (bdiv->div == div) 289 return bdiv->val; 290 } 291 292 return -EINVAL; 293 } 294 295 static int sun4i_i2s_get_mclk_div(struct sun4i_i2s *i2s, 296 unsigned long parent_rate, 297 unsigned long mclk_rate) 298 { 299 const struct sun4i_i2s_clk_div *dividers = i2s->variant->mclk_dividers; 300 int div = parent_rate / mclk_rate; 301 int i; 302 303 for (i = 0; i < i2s->variant->num_mclk_dividers; i++) { 304 const struct sun4i_i2s_clk_div *mdiv = ÷rs[i]; 305 306 if (mdiv->div == div) 307 return mdiv->val; 308 } 309 310 return -EINVAL; 311 } 312 313 static int sun4i_i2s_oversample_rates[] = { 128, 192, 256, 384, 512, 768 }; 314 static bool sun4i_i2s_oversample_is_valid(unsigned int oversample) 315 { 316 int i; 317 318 for (i = 0; i < ARRAY_SIZE(sun4i_i2s_oversample_rates); i++) 319 if (sun4i_i2s_oversample_rates[i] == oversample) 320 return true; 321 322 return false; 323 } 324 325 static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, 326 unsigned int rate, 327 unsigned int slots, 328 unsigned int slot_width) 329 { 330 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 331 unsigned int oversample_rate, clk_rate, bclk_parent_rate; 332 int bclk_div, mclk_div; 333 int ret; 334 335 switch (rate) { 336 case 176400: 337 case 88200: 338 case 44100: 339 case 22050: 340 case 11025: 341 clk_rate = 22579200; 342 break; 343 344 case 192000: 345 case 128000: 346 case 96000: 347 case 64000: 348 case 48000: 349 case 32000: 350 case 24000: 351 case 16000: 352 case 12000: 353 case 8000: 354 clk_rate = 24576000; 355 break; 356 357 default: 358 dev_err(dai->dev, "Unsupported sample rate: %u\n", rate); 359 return -EINVAL; 360 } 361 362 ret = clk_set_rate(i2s->mod_clk, clk_rate); 363 if (ret) 364 return ret; 365 366 oversample_rate = i2s->mclk_freq / rate; 367 if (!sun4i_i2s_oversample_is_valid(oversample_rate)) { 368 dev_err(dai->dev, "Unsupported oversample rate: %d\n", 369 oversample_rate); 370 return -EINVAL; 371 } 372 373 bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s); 374 bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate, 375 rate, slots, slot_width); 376 if (bclk_div < 0) { 377 dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); 378 return -EINVAL; 379 } 380 381 mclk_div = sun4i_i2s_get_mclk_div(i2s, clk_rate, i2s->mclk_freq); 382 if (mclk_div < 0) { 383 dev_err(dai->dev, "Unsupported MCLK divider: %d\n", mclk_div); 384 return -EINVAL; 385 } 386 387 regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG, 388 SUN4I_I2S_CLK_DIV_BCLK(bclk_div) | 389 SUN4I_I2S_CLK_DIV_MCLK(mclk_div)); 390 391 regmap_field_write(i2s->field_clkdiv_mclk_en, 1); 392 393 return 0; 394 } 395 396 static int sun4i_i2s_get_sr(unsigned int width) 397 { 398 switch (width) { 399 case 16: 400 return 0; 401 case 20: 402 return 1; 403 case 24: 404 return 2; 405 } 406 407 return -EINVAL; 408 } 409 410 static int sun4i_i2s_get_wss(unsigned int width) 411 { 412 switch (width) { 413 case 16: 414 return 0; 415 case 20: 416 return 1; 417 case 24: 418 return 2; 419 case 32: 420 return 3; 421 } 422 423 return -EINVAL; 424 } 425 426 static int sun8i_i2s_get_sr_wss(unsigned int width) 427 { 428 switch (width) { 429 case 8: 430 return 1; 431 case 12: 432 return 2; 433 case 16: 434 return 3; 435 case 20: 436 return 4; 437 case 24: 438 return 5; 439 case 28: 440 return 6; 441 case 32: 442 return 7; 443 } 444 445 return -EINVAL; 446 } 447 448 static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, 449 unsigned int channels, unsigned int slots, 450 unsigned int slot_width) 451 { 452 /* Map the channels for playback and capture */ 453 regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210); 454 regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210); 455 456 /* Configure the channels */ 457 regmap_update_bits(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG, 458 SUN4I_I2S_CHAN_SEL_MASK, 459 SUN4I_I2S_CHAN_SEL(channels)); 460 regmap_update_bits(i2s->regmap, SUN4I_I2S_RX_CHAN_SEL_REG, 461 SUN4I_I2S_CHAN_SEL_MASK, 462 SUN4I_I2S_CHAN_SEL(channels)); 463 464 return 0; 465 } 466 467 static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, 468 unsigned int channels, unsigned int slots, 469 unsigned int slot_width) 470 { 471 unsigned int lrck_period; 472 473 /* Map the channels for playback and capture */ 474 regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210); 475 regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210); 476 477 /* Configure the channels */ 478 regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 479 SUN4I_I2S_CHAN_SEL_MASK, 480 SUN4I_I2S_CHAN_SEL(channels)); 481 regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, 482 SUN4I_I2S_CHAN_SEL_MASK, 483 SUN4I_I2S_CHAN_SEL(channels)); 484 485 regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, 486 SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, 487 SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); 488 regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, 489 SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, 490 SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); 491 492 switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { 493 case SND_SOC_DAIFMT_DSP_A: 494 case SND_SOC_DAIFMT_DSP_B: 495 lrck_period = slot_width * slots; 496 break; 497 498 case SND_SOC_DAIFMT_LEFT_J: 499 case SND_SOC_DAIFMT_RIGHT_J: 500 case SND_SOC_DAIFMT_I2S: 501 lrck_period = slot_width; 502 break; 503 504 default: 505 return -EINVAL; 506 } 507 508 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 509 SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, 510 SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); 511 512 regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 513 SUN8I_I2S_TX_CHAN_EN_MASK, 514 SUN8I_I2S_TX_CHAN_EN(channels)); 515 516 return 0; 517 } 518 519 static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, 520 unsigned int channels, unsigned int slots, 521 unsigned int slot_width) 522 { 523 unsigned int lrck_period; 524 525 /* Map the channels for playback and capture */ 526 regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98); 527 regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210); 528 regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); 529 regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); 530 531 /* Configure the channels */ 532 regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 533 SUN50I_H6_I2S_TX_CHAN_SEL_MASK, 534 SUN50I_H6_I2S_TX_CHAN_SEL(channels)); 535 regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, 536 SUN50I_H6_I2S_TX_CHAN_SEL_MASK, 537 SUN50I_H6_I2S_TX_CHAN_SEL(channels)); 538 539 regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, 540 SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, 541 SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); 542 regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, 543 SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, 544 SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); 545 546 switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { 547 case SND_SOC_DAIFMT_DSP_A: 548 case SND_SOC_DAIFMT_DSP_B: 549 lrck_period = slot_width * slots; 550 break; 551 552 case SND_SOC_DAIFMT_LEFT_J: 553 case SND_SOC_DAIFMT_RIGHT_J: 554 case SND_SOC_DAIFMT_I2S: 555 lrck_period = slot_width; 556 break; 557 558 default: 559 return -EINVAL; 560 } 561 562 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 563 SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, 564 SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); 565 566 regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 567 SUN50I_H6_I2S_TX_CHAN_EN_MASK, 568 SUN50I_H6_I2S_TX_CHAN_EN(channels)); 569 570 return 0; 571 } 572 573 static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, 574 struct snd_pcm_hw_params *params, 575 struct snd_soc_dai *dai) 576 { 577 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 578 unsigned int word_size = params_width(params); 579 unsigned int slot_width = params_physical_width(params); 580 unsigned int channels = params_channels(params); 581 582 unsigned int slots = channels; 583 584 int ret, sr, wss; 585 u32 width; 586 587 if (i2s->slots) 588 slots = i2s->slots; 589 590 if (i2s->slot_width) 591 slot_width = i2s->slot_width; 592 593 ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width); 594 if (ret < 0) { 595 dev_err(dai->dev, "Invalid channel configuration\n"); 596 return ret; 597 } 598 599 /* Set significant bits in our FIFOs */ 600 regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, 601 SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK | 602 SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK, 603 SUN4I_I2S_FIFO_CTRL_TX_MODE(1) | 604 SUN4I_I2S_FIFO_CTRL_RX_MODE(1)); 605 606 switch (params_physical_width(params)) { 607 case 16: 608 width = DMA_SLAVE_BUSWIDTH_2_BYTES; 609 break; 610 case 32: 611 width = DMA_SLAVE_BUSWIDTH_4_BYTES; 612 break; 613 default: 614 dev_err(dai->dev, "Unsupported physical sample width: %d\n", 615 params_physical_width(params)); 616 return -EINVAL; 617 } 618 i2s->playback_dma_data.addr_width = width; 619 620 sr = i2s->variant->get_sr(word_size); 621 if (sr < 0) 622 return -EINVAL; 623 624 wss = i2s->variant->get_wss(slot_width); 625 if (wss < 0) 626 return -EINVAL; 627 628 regmap_field_write(i2s->field_fmt_wss, wss); 629 regmap_field_write(i2s->field_fmt_sr, sr); 630 631 return sun4i_i2s_set_clk_rate(dai, params_rate(params), 632 slots, slot_width); 633 } 634 635 static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, 636 unsigned int fmt) 637 { 638 u32 val; 639 640 /* DAI clock polarity */ 641 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 642 case SND_SOC_DAIFMT_IB_IF: 643 /* Invert both clocks */ 644 val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED | 645 SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED; 646 break; 647 case SND_SOC_DAIFMT_IB_NF: 648 /* Invert bit clock */ 649 val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED; 650 break; 651 case SND_SOC_DAIFMT_NB_IF: 652 /* Invert frame clock */ 653 val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED; 654 break; 655 case SND_SOC_DAIFMT_NB_NF: 656 val = 0; 657 break; 658 default: 659 return -EINVAL; 660 } 661 662 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 663 SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK | 664 SUN4I_I2S_FMT0_BCLK_POLARITY_MASK, 665 val); 666 667 /* DAI Mode */ 668 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 669 case SND_SOC_DAIFMT_I2S: 670 val = SUN4I_I2S_FMT0_FMT_I2S; 671 break; 672 673 case SND_SOC_DAIFMT_LEFT_J: 674 val = SUN4I_I2S_FMT0_FMT_LEFT_J; 675 break; 676 677 case SND_SOC_DAIFMT_RIGHT_J: 678 val = SUN4I_I2S_FMT0_FMT_RIGHT_J; 679 break; 680 681 default: 682 return -EINVAL; 683 } 684 685 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 686 SUN4I_I2S_FMT0_FMT_MASK, val); 687 688 /* DAI clock master masks */ 689 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 690 case SND_SOC_DAIFMT_CBS_CFS: 691 /* BCLK and LRCLK master */ 692 val = SUN4I_I2S_CTRL_MODE_MASTER; 693 break; 694 695 case SND_SOC_DAIFMT_CBM_CFM: 696 /* BCLK and LRCLK slave */ 697 val = SUN4I_I2S_CTRL_MODE_SLAVE; 698 break; 699 700 default: 701 return -EINVAL; 702 } 703 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 704 SUN4I_I2S_CTRL_MODE_MASK, val); 705 706 return 0; 707 } 708 709 static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, 710 unsigned int fmt) 711 { 712 u32 mode, val; 713 u8 offset; 714 715 /* 716 * DAI clock polarity 717 * 718 * The setup for LRCK contradicts the datasheet, but under a 719 * scope it's clear that the LRCK polarity is reversed 720 * compared to the expected polarity on the bus. 721 */ 722 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 723 case SND_SOC_DAIFMT_IB_IF: 724 /* Invert both clocks */ 725 val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED; 726 break; 727 case SND_SOC_DAIFMT_IB_NF: 728 /* Invert bit clock */ 729 val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED | 730 SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; 731 break; 732 case SND_SOC_DAIFMT_NB_IF: 733 /* Invert frame clock */ 734 val = 0; 735 break; 736 case SND_SOC_DAIFMT_NB_NF: 737 val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; 738 break; 739 default: 740 return -EINVAL; 741 } 742 743 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 744 SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | 745 SUN8I_I2S_FMT0_BCLK_POLARITY_MASK, 746 val); 747 748 /* DAI Mode */ 749 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 750 case SND_SOC_DAIFMT_DSP_A: 751 mode = SUN8I_I2S_CTRL_MODE_PCM; 752 offset = 1; 753 break; 754 755 case SND_SOC_DAIFMT_DSP_B: 756 mode = SUN8I_I2S_CTRL_MODE_PCM; 757 offset = 0; 758 break; 759 760 case SND_SOC_DAIFMT_I2S: 761 mode = SUN8I_I2S_CTRL_MODE_LEFT; 762 offset = 1; 763 break; 764 765 case SND_SOC_DAIFMT_LEFT_J: 766 mode = SUN8I_I2S_CTRL_MODE_LEFT; 767 offset = 0; 768 break; 769 770 case SND_SOC_DAIFMT_RIGHT_J: 771 mode = SUN8I_I2S_CTRL_MODE_RIGHT; 772 offset = 0; 773 break; 774 775 default: 776 return -EINVAL; 777 } 778 779 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 780 SUN8I_I2S_CTRL_MODE_MASK, mode); 781 regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 782 SUN8I_I2S_TX_CHAN_OFFSET_MASK, 783 SUN8I_I2S_TX_CHAN_OFFSET(offset)); 784 regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, 785 SUN8I_I2S_TX_CHAN_OFFSET_MASK, 786 SUN8I_I2S_TX_CHAN_OFFSET(offset)); 787 788 /* DAI clock master masks */ 789 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 790 case SND_SOC_DAIFMT_CBS_CFS: 791 /* BCLK and LRCLK master */ 792 val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; 793 break; 794 795 case SND_SOC_DAIFMT_CBM_CFM: 796 /* BCLK and LRCLK slave */ 797 val = 0; 798 break; 799 800 default: 801 return -EINVAL; 802 } 803 804 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 805 SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT, 806 val); 807 808 /* Set sign extension to pad out LSB with 0 */ 809 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG, 810 SUN8I_I2S_FMT1_REG_SEXT_MASK, 811 SUN8I_I2S_FMT1_REG_SEXT(0)); 812 813 return 0; 814 } 815 816 static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, 817 unsigned int fmt) 818 { 819 u32 mode, val; 820 u8 offset; 821 822 /* 823 * DAI clock polarity 824 * 825 * The setup for LRCK contradicts the datasheet, but under a 826 * scope it's clear that the LRCK polarity is reversed 827 * compared to the expected polarity on the bus. 828 */ 829 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 830 case SND_SOC_DAIFMT_IB_IF: 831 /* Invert both clocks */ 832 val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED; 833 break; 834 case SND_SOC_DAIFMT_IB_NF: 835 /* Invert bit clock */ 836 val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED | 837 SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; 838 break; 839 case SND_SOC_DAIFMT_NB_IF: 840 /* Invert frame clock */ 841 val = 0; 842 break; 843 case SND_SOC_DAIFMT_NB_NF: 844 val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; 845 break; 846 default: 847 return -EINVAL; 848 } 849 850 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, 851 SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | 852 SUN8I_I2S_FMT0_BCLK_POLARITY_MASK, 853 val); 854 855 /* DAI Mode */ 856 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 857 case SND_SOC_DAIFMT_DSP_A: 858 mode = SUN8I_I2S_CTRL_MODE_PCM; 859 offset = 1; 860 break; 861 862 case SND_SOC_DAIFMT_DSP_B: 863 mode = SUN8I_I2S_CTRL_MODE_PCM; 864 offset = 0; 865 break; 866 867 case SND_SOC_DAIFMT_I2S: 868 mode = SUN8I_I2S_CTRL_MODE_LEFT; 869 offset = 1; 870 break; 871 872 case SND_SOC_DAIFMT_LEFT_J: 873 mode = SUN8I_I2S_CTRL_MODE_LEFT; 874 offset = 0; 875 break; 876 877 case SND_SOC_DAIFMT_RIGHT_J: 878 mode = SUN8I_I2S_CTRL_MODE_RIGHT; 879 offset = 0; 880 break; 881 882 default: 883 return -EINVAL; 884 } 885 886 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 887 SUN8I_I2S_CTRL_MODE_MASK, mode); 888 regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, 889 SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, 890 SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); 891 regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, 892 SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK, 893 SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); 894 895 /* DAI clock master masks */ 896 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 897 case SND_SOC_DAIFMT_CBS_CFS: 898 /* BCLK and LRCLK master */ 899 val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; 900 break; 901 902 case SND_SOC_DAIFMT_CBM_CFM: 903 /* BCLK and LRCLK slave */ 904 val = 0; 905 break; 906 907 default: 908 return -EINVAL; 909 } 910 911 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 912 SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT, 913 val); 914 915 /* Set sign extension to pad out LSB with 0 */ 916 regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG, 917 SUN8I_I2S_FMT1_REG_SEXT_MASK, 918 SUN8I_I2S_FMT1_REG_SEXT(0)); 919 920 return 0; 921 } 922 923 static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 924 { 925 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 926 int ret; 927 928 ret = i2s->variant->set_fmt(i2s, fmt); 929 if (ret) { 930 dev_err(dai->dev, "Unsupported format configuration\n"); 931 return ret; 932 } 933 934 i2s->format = fmt; 935 936 return 0; 937 } 938 939 static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s) 940 { 941 /* Flush RX FIFO */ 942 regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, 943 SUN4I_I2S_FIFO_CTRL_FLUSH_RX, 944 SUN4I_I2S_FIFO_CTRL_FLUSH_RX); 945 946 /* Clear RX counter */ 947 regmap_write(i2s->regmap, SUN4I_I2S_RX_CNT_REG, 0); 948 949 /* Enable RX Block */ 950 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 951 SUN4I_I2S_CTRL_RX_EN, 952 SUN4I_I2S_CTRL_RX_EN); 953 954 /* Enable RX DRQ */ 955 regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG, 956 SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN, 957 SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN); 958 } 959 960 static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s) 961 { 962 /* Flush TX FIFO */ 963 regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG, 964 SUN4I_I2S_FIFO_CTRL_FLUSH_TX, 965 SUN4I_I2S_FIFO_CTRL_FLUSH_TX); 966 967 /* Clear TX counter */ 968 regmap_write(i2s->regmap, SUN4I_I2S_TX_CNT_REG, 0); 969 970 /* Enable TX Block */ 971 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 972 SUN4I_I2S_CTRL_TX_EN, 973 SUN4I_I2S_CTRL_TX_EN); 974 975 /* Enable TX DRQ */ 976 regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG, 977 SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN, 978 SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN); 979 } 980 981 static void sun4i_i2s_stop_capture(struct sun4i_i2s *i2s) 982 { 983 /* Disable RX Block */ 984 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 985 SUN4I_I2S_CTRL_RX_EN, 986 0); 987 988 /* Disable RX DRQ */ 989 regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG, 990 SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN, 991 0); 992 } 993 994 static void sun4i_i2s_stop_playback(struct sun4i_i2s *i2s) 995 { 996 /* Disable TX Block */ 997 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 998 SUN4I_I2S_CTRL_TX_EN, 999 0); 1000 1001 /* Disable TX DRQ */ 1002 regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG, 1003 SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN, 1004 0); 1005 } 1006 1007 static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 1008 struct snd_soc_dai *dai) 1009 { 1010 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 1011 1012 switch (cmd) { 1013 case SNDRV_PCM_TRIGGER_START: 1014 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1015 case SNDRV_PCM_TRIGGER_RESUME: 1016 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1017 sun4i_i2s_start_playback(i2s); 1018 else 1019 sun4i_i2s_start_capture(i2s); 1020 break; 1021 1022 case SNDRV_PCM_TRIGGER_STOP: 1023 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1024 case SNDRV_PCM_TRIGGER_SUSPEND: 1025 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1026 sun4i_i2s_stop_playback(i2s); 1027 else 1028 sun4i_i2s_stop_capture(i2s); 1029 break; 1030 1031 default: 1032 return -EINVAL; 1033 } 1034 1035 return 0; 1036 } 1037 1038 static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, 1039 unsigned int freq, int dir) 1040 { 1041 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 1042 1043 if (clk_id != 0) 1044 return -EINVAL; 1045 1046 i2s->mclk_freq = freq; 1047 1048 return 0; 1049 } 1050 1051 static int sun4i_i2s_set_tdm_slot(struct snd_soc_dai *dai, 1052 unsigned int tx_mask, unsigned int rx_mask, 1053 int slots, int slot_width) 1054 { 1055 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 1056 1057 if (slots > 8) 1058 return -EINVAL; 1059 1060 i2s->slots = slots; 1061 i2s->slot_width = slot_width; 1062 1063 return 0; 1064 } 1065 1066 static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { 1067 .hw_params = sun4i_i2s_hw_params, 1068 .set_fmt = sun4i_i2s_set_fmt, 1069 .set_sysclk = sun4i_i2s_set_sysclk, 1070 .set_tdm_slot = sun4i_i2s_set_tdm_slot, 1071 .trigger = sun4i_i2s_trigger, 1072 }; 1073 1074 static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai) 1075 { 1076 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 1077 1078 snd_soc_dai_init_dma_data(dai, 1079 &i2s->playback_dma_data, 1080 &i2s->capture_dma_data); 1081 1082 return 0; 1083 } 1084 1085 #define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 1086 SNDRV_PCM_FMTBIT_S20_LE | \ 1087 SNDRV_PCM_FMTBIT_S24_LE) 1088 1089 static struct snd_soc_dai_driver sun4i_i2s_dai = { 1090 .probe = sun4i_i2s_dai_probe, 1091 .capture = { 1092 .stream_name = "Capture", 1093 .channels_min = 1, 1094 .channels_max = 8, 1095 .rates = SNDRV_PCM_RATE_8000_192000, 1096 .formats = SUN4I_FORMATS, 1097 }, 1098 .playback = { 1099 .stream_name = "Playback", 1100 .channels_min = 1, 1101 .channels_max = 8, 1102 .rates = SNDRV_PCM_RATE_8000_192000, 1103 .formats = SUN4I_FORMATS, 1104 }, 1105 .ops = &sun4i_i2s_dai_ops, 1106 .symmetric_rate = 1, 1107 }; 1108 1109 static const struct snd_soc_component_driver sun4i_i2s_component = { 1110 .name = "sun4i-dai", 1111 }; 1112 1113 static bool sun4i_i2s_rd_reg(struct device *dev, unsigned int reg) 1114 { 1115 switch (reg) { 1116 case SUN4I_I2S_FIFO_TX_REG: 1117 return false; 1118 1119 default: 1120 return true; 1121 } 1122 } 1123 1124 static bool sun4i_i2s_wr_reg(struct device *dev, unsigned int reg) 1125 { 1126 switch (reg) { 1127 case SUN4I_I2S_FIFO_RX_REG: 1128 case SUN4I_I2S_FIFO_STA_REG: 1129 return false; 1130 1131 default: 1132 return true; 1133 } 1134 } 1135 1136 static bool sun4i_i2s_volatile_reg(struct device *dev, unsigned int reg) 1137 { 1138 switch (reg) { 1139 case SUN4I_I2S_FIFO_RX_REG: 1140 case SUN4I_I2S_INT_STA_REG: 1141 case SUN4I_I2S_RX_CNT_REG: 1142 case SUN4I_I2S_TX_CNT_REG: 1143 return true; 1144 1145 default: 1146 return false; 1147 } 1148 } 1149 1150 static bool sun8i_i2s_rd_reg(struct device *dev, unsigned int reg) 1151 { 1152 switch (reg) { 1153 case SUN8I_I2S_FIFO_TX_REG: 1154 return false; 1155 1156 default: 1157 return true; 1158 } 1159 } 1160 1161 static bool sun8i_i2s_volatile_reg(struct device *dev, unsigned int reg) 1162 { 1163 switch (reg) { 1164 case SUN4I_I2S_FIFO_CTRL_REG: 1165 case SUN4I_I2S_FIFO_RX_REG: 1166 case SUN4I_I2S_FIFO_STA_REG: 1167 case SUN4I_I2S_RX_CNT_REG: 1168 case SUN4I_I2S_TX_CNT_REG: 1169 case SUN8I_I2S_FIFO_TX_REG: 1170 case SUN8I_I2S_INT_STA_REG: 1171 return true; 1172 1173 default: 1174 return false; 1175 } 1176 } 1177 1178 static const struct reg_default sun4i_i2s_reg_defaults[] = { 1179 { SUN4I_I2S_CTRL_REG, 0x00000000 }, 1180 { SUN4I_I2S_FMT0_REG, 0x0000000c }, 1181 { SUN4I_I2S_FMT1_REG, 0x00004020 }, 1182 { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 }, 1183 { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, 1184 { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, 1185 { SUN4I_I2S_TX_CHAN_SEL_REG, 0x00000001 }, 1186 { SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210 }, 1187 { SUN4I_I2S_RX_CHAN_SEL_REG, 0x00000001 }, 1188 { SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210 }, 1189 }; 1190 1191 static const struct reg_default sun8i_i2s_reg_defaults[] = { 1192 { SUN4I_I2S_CTRL_REG, 0x00060000 }, 1193 { SUN4I_I2S_FMT0_REG, 0x00000033 }, 1194 { SUN4I_I2S_FMT1_REG, 0x00000030 }, 1195 { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 }, 1196 { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, 1197 { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, 1198 { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, 1199 { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, 1200 { SUN8I_I2S_TX_CHAN_MAP_REG, 0x00000000 }, 1201 { SUN8I_I2S_RX_CHAN_SEL_REG, 0x00000000 }, 1202 { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 }, 1203 }; 1204 1205 static const struct reg_default sun50i_h6_i2s_reg_defaults[] = { 1206 { SUN4I_I2S_CTRL_REG, 0x00060000 }, 1207 { SUN4I_I2S_FMT0_REG, 0x00000033 }, 1208 { SUN4I_I2S_FMT1_REG, 0x00000030 }, 1209 { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 }, 1210 { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, 1211 { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, 1212 { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, 1213 { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, 1214 { SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0x00000000 }, 1215 { SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x00000000 }, 1216 { SUN50I_H6_I2S_RX_CHAN_SEL_REG, 0x00000000 }, 1217 { SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x00000000 }, 1218 { SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x00000000 }, 1219 }; 1220 1221 static const struct regmap_config sun4i_i2s_regmap_config = { 1222 .reg_bits = 32, 1223 .reg_stride = 4, 1224 .val_bits = 32, 1225 .max_register = SUN4I_I2S_RX_CHAN_MAP_REG, 1226 1227 .cache_type = REGCACHE_FLAT, 1228 .reg_defaults = sun4i_i2s_reg_defaults, 1229 .num_reg_defaults = ARRAY_SIZE(sun4i_i2s_reg_defaults), 1230 .writeable_reg = sun4i_i2s_wr_reg, 1231 .readable_reg = sun4i_i2s_rd_reg, 1232 .volatile_reg = sun4i_i2s_volatile_reg, 1233 }; 1234 1235 static const struct regmap_config sun8i_i2s_regmap_config = { 1236 .reg_bits = 32, 1237 .reg_stride = 4, 1238 .val_bits = 32, 1239 .max_register = SUN8I_I2S_RX_CHAN_MAP_REG, 1240 .cache_type = REGCACHE_FLAT, 1241 .reg_defaults = sun8i_i2s_reg_defaults, 1242 .num_reg_defaults = ARRAY_SIZE(sun8i_i2s_reg_defaults), 1243 .writeable_reg = sun4i_i2s_wr_reg, 1244 .readable_reg = sun8i_i2s_rd_reg, 1245 .volatile_reg = sun8i_i2s_volatile_reg, 1246 }; 1247 1248 static const struct regmap_config sun50i_h6_i2s_regmap_config = { 1249 .reg_bits = 32, 1250 .reg_stride = 4, 1251 .val_bits = 32, 1252 .max_register = SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 1253 .cache_type = REGCACHE_FLAT, 1254 .reg_defaults = sun50i_h6_i2s_reg_defaults, 1255 .num_reg_defaults = ARRAY_SIZE(sun50i_h6_i2s_reg_defaults), 1256 .writeable_reg = sun4i_i2s_wr_reg, 1257 .readable_reg = sun8i_i2s_rd_reg, 1258 .volatile_reg = sun8i_i2s_volatile_reg, 1259 }; 1260 1261 static int sun4i_i2s_runtime_resume(struct device *dev) 1262 { 1263 struct sun4i_i2s *i2s = dev_get_drvdata(dev); 1264 int ret; 1265 1266 ret = clk_prepare_enable(i2s->bus_clk); 1267 if (ret) { 1268 dev_err(dev, "Failed to enable bus clock\n"); 1269 return ret; 1270 } 1271 1272 regcache_cache_only(i2s->regmap, false); 1273 regcache_mark_dirty(i2s->regmap); 1274 1275 ret = regcache_sync(i2s->regmap); 1276 if (ret) { 1277 dev_err(dev, "Failed to sync regmap cache\n"); 1278 goto err_disable_clk; 1279 } 1280 1281 /* Enable the whole hardware block */ 1282 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 1283 SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN); 1284 1285 /* Enable the first output line */ 1286 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 1287 SUN4I_I2S_CTRL_SDO_EN_MASK, 1288 SUN4I_I2S_CTRL_SDO_EN(0)); 1289 1290 ret = clk_prepare_enable(i2s->mod_clk); 1291 if (ret) { 1292 dev_err(dev, "Failed to enable module clock\n"); 1293 goto err_disable_clk; 1294 } 1295 1296 return 0; 1297 1298 err_disable_clk: 1299 clk_disable_unprepare(i2s->bus_clk); 1300 return ret; 1301 } 1302 1303 static int sun4i_i2s_runtime_suspend(struct device *dev) 1304 { 1305 struct sun4i_i2s *i2s = dev_get_drvdata(dev); 1306 1307 clk_disable_unprepare(i2s->mod_clk); 1308 1309 /* Disable our output lines */ 1310 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 1311 SUN4I_I2S_CTRL_SDO_EN_MASK, 0); 1312 1313 /* Disable the whole hardware block */ 1314 regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, 1315 SUN4I_I2S_CTRL_GL_EN, 0); 1316 1317 regcache_cache_only(i2s->regmap, true); 1318 1319 clk_disable_unprepare(i2s->bus_clk); 1320 1321 return 0; 1322 } 1323 1324 static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { 1325 .has_reset = false, 1326 .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, 1327 .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, 1328 .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), 1329 .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), 1330 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 1331 .bclk_dividers = sun4i_i2s_bclk_div, 1332 .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), 1333 .mclk_dividers = sun4i_i2s_mclk_div, 1334 .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), 1335 .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, 1336 .get_sr = sun4i_i2s_get_sr, 1337 .get_wss = sun4i_i2s_get_wss, 1338 .set_chan_cfg = sun4i_i2s_set_chan_cfg, 1339 .set_fmt = sun4i_i2s_set_soc_fmt, 1340 }; 1341 1342 static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { 1343 .has_reset = true, 1344 .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, 1345 .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, 1346 .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), 1347 .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), 1348 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 1349 .bclk_dividers = sun4i_i2s_bclk_div, 1350 .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), 1351 .mclk_dividers = sun4i_i2s_mclk_div, 1352 .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), 1353 .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, 1354 .get_sr = sun4i_i2s_get_sr, 1355 .get_wss = sun4i_i2s_get_wss, 1356 .set_chan_cfg = sun4i_i2s_set_chan_cfg, 1357 .set_fmt = sun4i_i2s_set_soc_fmt, 1358 }; 1359 1360 /* 1361 * This doesn't describe the TDM controller documented in the A83t 1362 * datasheet, but the three undocumented I2S controller that use the 1363 * older design. 1364 */ 1365 static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { 1366 .has_reset = true, 1367 .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, 1368 .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, 1369 .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), 1370 .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), 1371 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 1372 .bclk_dividers = sun4i_i2s_bclk_div, 1373 .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), 1374 .mclk_dividers = sun4i_i2s_mclk_div, 1375 .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), 1376 .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, 1377 .get_sr = sun4i_i2s_get_sr, 1378 .get_wss = sun4i_i2s_get_wss, 1379 .set_chan_cfg = sun4i_i2s_set_chan_cfg, 1380 .set_fmt = sun4i_i2s_set_soc_fmt, 1381 }; 1382 1383 static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { 1384 .has_reset = true, 1385 .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, 1386 .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, 1387 .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), 1388 .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), 1389 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), 1390 .bclk_dividers = sun8i_i2s_clk_div, 1391 .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), 1392 .mclk_dividers = sun8i_i2s_clk_div, 1393 .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), 1394 .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate, 1395 .get_sr = sun8i_i2s_get_sr_wss, 1396 .get_wss = sun8i_i2s_get_sr_wss, 1397 .set_chan_cfg = sun8i_i2s_set_chan_cfg, 1398 .set_fmt = sun8i_i2s_set_soc_fmt, 1399 }; 1400 1401 static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { 1402 .has_reset = true, 1403 .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, 1404 .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, 1405 .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), 1406 .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), 1407 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 1408 .bclk_dividers = sun4i_i2s_bclk_div, 1409 .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), 1410 .mclk_dividers = sun4i_i2s_mclk_div, 1411 .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), 1412 .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, 1413 .get_sr = sun4i_i2s_get_sr, 1414 .get_wss = sun4i_i2s_get_wss, 1415 .set_chan_cfg = sun4i_i2s_set_chan_cfg, 1416 .set_fmt = sun4i_i2s_set_soc_fmt, 1417 }; 1418 1419 static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = { 1420 .has_reset = true, 1421 .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, 1422 .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config, 1423 .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), 1424 .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), 1425 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), 1426 .bclk_dividers = sun8i_i2s_clk_div, 1427 .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), 1428 .mclk_dividers = sun8i_i2s_clk_div, 1429 .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), 1430 .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate, 1431 .get_sr = sun8i_i2s_get_sr_wss, 1432 .get_wss = sun8i_i2s_get_sr_wss, 1433 .set_chan_cfg = sun50i_h6_i2s_set_chan_cfg, 1434 .set_fmt = sun50i_h6_i2s_set_soc_fmt, 1435 }; 1436 1437 static int sun4i_i2s_init_regmap_fields(struct device *dev, 1438 struct sun4i_i2s *i2s) 1439 { 1440 i2s->field_clkdiv_mclk_en = 1441 devm_regmap_field_alloc(dev, i2s->regmap, 1442 i2s->variant->field_clkdiv_mclk_en); 1443 if (IS_ERR(i2s->field_clkdiv_mclk_en)) 1444 return PTR_ERR(i2s->field_clkdiv_mclk_en); 1445 1446 i2s->field_fmt_wss = 1447 devm_regmap_field_alloc(dev, i2s->regmap, 1448 i2s->variant->field_fmt_wss); 1449 if (IS_ERR(i2s->field_fmt_wss)) 1450 return PTR_ERR(i2s->field_fmt_wss); 1451 1452 i2s->field_fmt_sr = 1453 devm_regmap_field_alloc(dev, i2s->regmap, 1454 i2s->variant->field_fmt_sr); 1455 if (IS_ERR(i2s->field_fmt_sr)) 1456 return PTR_ERR(i2s->field_fmt_sr); 1457 1458 return 0; 1459 } 1460 1461 static int sun4i_i2s_probe(struct platform_device *pdev) 1462 { 1463 struct sun4i_i2s *i2s; 1464 struct resource *res; 1465 void __iomem *regs; 1466 int irq, ret; 1467 1468 i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); 1469 if (!i2s) 1470 return -ENOMEM; 1471 platform_set_drvdata(pdev, i2s); 1472 1473 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1474 regs = devm_ioremap_resource(&pdev->dev, res); 1475 if (IS_ERR(regs)) 1476 return PTR_ERR(regs); 1477 1478 irq = platform_get_irq(pdev, 0); 1479 if (irq < 0) 1480 return irq; 1481 1482 i2s->variant = of_device_get_match_data(&pdev->dev); 1483 if (!i2s->variant) { 1484 dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); 1485 return -ENODEV; 1486 } 1487 1488 i2s->bus_clk = devm_clk_get(&pdev->dev, "apb"); 1489 if (IS_ERR(i2s->bus_clk)) { 1490 dev_err(&pdev->dev, "Can't get our bus clock\n"); 1491 return PTR_ERR(i2s->bus_clk); 1492 } 1493 1494 i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 1495 i2s->variant->sun4i_i2s_regmap); 1496 if (IS_ERR(i2s->regmap)) { 1497 dev_err(&pdev->dev, "Regmap initialisation failed\n"); 1498 return PTR_ERR(i2s->regmap); 1499 } 1500 1501 i2s->mod_clk = devm_clk_get(&pdev->dev, "mod"); 1502 if (IS_ERR(i2s->mod_clk)) { 1503 dev_err(&pdev->dev, "Can't get our mod clock\n"); 1504 return PTR_ERR(i2s->mod_clk); 1505 } 1506 1507 if (i2s->variant->has_reset) { 1508 i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); 1509 if (IS_ERR(i2s->rst)) { 1510 dev_err(&pdev->dev, "Failed to get reset control\n"); 1511 return PTR_ERR(i2s->rst); 1512 } 1513 } 1514 1515 if (!IS_ERR(i2s->rst)) { 1516 ret = reset_control_deassert(i2s->rst); 1517 if (ret) { 1518 dev_err(&pdev->dev, 1519 "Failed to deassert the reset control\n"); 1520 return -EINVAL; 1521 } 1522 } 1523 1524 i2s->playback_dma_data.addr = res->start + 1525 i2s->variant->reg_offset_txdata; 1526 i2s->playback_dma_data.maxburst = 8; 1527 1528 i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; 1529 i2s->capture_dma_data.maxburst = 8; 1530 1531 pm_runtime_enable(&pdev->dev); 1532 if (!pm_runtime_enabled(&pdev->dev)) { 1533 ret = sun4i_i2s_runtime_resume(&pdev->dev); 1534 if (ret) 1535 goto err_pm_disable; 1536 } 1537 1538 ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s); 1539 if (ret) { 1540 dev_err(&pdev->dev, "Could not initialise regmap fields\n"); 1541 goto err_suspend; 1542 } 1543 1544 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 1545 if (ret) { 1546 dev_err(&pdev->dev, "Could not register PCM\n"); 1547 goto err_suspend; 1548 } 1549 1550 ret = devm_snd_soc_register_component(&pdev->dev, 1551 &sun4i_i2s_component, 1552 &sun4i_i2s_dai, 1); 1553 if (ret) { 1554 dev_err(&pdev->dev, "Could not register DAI\n"); 1555 goto err_suspend; 1556 } 1557 1558 return 0; 1559 1560 err_suspend: 1561 if (!pm_runtime_status_suspended(&pdev->dev)) 1562 sun4i_i2s_runtime_suspend(&pdev->dev); 1563 err_pm_disable: 1564 pm_runtime_disable(&pdev->dev); 1565 if (!IS_ERR(i2s->rst)) 1566 reset_control_assert(i2s->rst); 1567 1568 return ret; 1569 } 1570 1571 static int sun4i_i2s_remove(struct platform_device *pdev) 1572 { 1573 struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev); 1574 1575 pm_runtime_disable(&pdev->dev); 1576 if (!pm_runtime_status_suspended(&pdev->dev)) 1577 sun4i_i2s_runtime_suspend(&pdev->dev); 1578 1579 if (!IS_ERR(i2s->rst)) 1580 reset_control_assert(i2s->rst); 1581 1582 return 0; 1583 } 1584 1585 static const struct of_device_id sun4i_i2s_match[] = { 1586 { 1587 .compatible = "allwinner,sun4i-a10-i2s", 1588 .data = &sun4i_a10_i2s_quirks, 1589 }, 1590 { 1591 .compatible = "allwinner,sun6i-a31-i2s", 1592 .data = &sun6i_a31_i2s_quirks, 1593 }, 1594 { 1595 .compatible = "allwinner,sun8i-a83t-i2s", 1596 .data = &sun8i_a83t_i2s_quirks, 1597 }, 1598 { 1599 .compatible = "allwinner,sun8i-h3-i2s", 1600 .data = &sun8i_h3_i2s_quirks, 1601 }, 1602 { 1603 .compatible = "allwinner,sun50i-a64-codec-i2s", 1604 .data = &sun50i_a64_codec_i2s_quirks, 1605 }, 1606 { 1607 .compatible = "allwinner,sun50i-h6-i2s", 1608 .data = &sun50i_h6_i2s_quirks, 1609 }, 1610 {} 1611 }; 1612 MODULE_DEVICE_TABLE(of, sun4i_i2s_match); 1613 1614 static const struct dev_pm_ops sun4i_i2s_pm_ops = { 1615 .runtime_resume = sun4i_i2s_runtime_resume, 1616 .runtime_suspend = sun4i_i2s_runtime_suspend, 1617 }; 1618 1619 static struct platform_driver sun4i_i2s_driver = { 1620 .probe = sun4i_i2s_probe, 1621 .remove = sun4i_i2s_remove, 1622 .driver = { 1623 .name = "sun4i-i2s", 1624 .of_match_table = sun4i_i2s_match, 1625 .pm = &sun4i_i2s_pm_ops, 1626 }, 1627 }; 1628 module_platform_driver(sun4i_i2s_driver); 1629 1630 MODULE_AUTHOR("Andrea Venturi <be17068@iperbole.bo.it>"); 1631 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 1632 MODULE_DESCRIPTION("Allwinner A10 I2S driver"); 1633 MODULE_LICENSE("GPL"); 1634