1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2012 Samsung Electronics 4 * R. Chandrasekar <rcsekar@samsung.com> 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <i2s.h> 10 #include <sound.h> 11 #include <asm/arch/clk.h> 12 #include <asm/arch/pinmux.h> 13 #include <asm/arch/i2s-regs.h> 14 #include <asm/io.h> 15 16 #define FIC_TX2COUNT(x) (((x) >> 24) & 0xf) 17 #define FIC_TX1COUNT(x) (((x) >> 16) & 0xf) 18 #define FIC_TXCOUNT(x) (((x) >> 8) & 0xf) 19 #define FIC_RXCOUNT(x) (((x) >> 0) & 0xf) 20 #define FICS_TXCOUNT(x) (((x) >> 8) & 0x7f) 21 22 #define TIMEOUT_I2S_TX 100 /* i2s transfer timeout */ 23 24 /* 25 * Sets the frame size for I2S LR clock 26 * 27 * @param i2s_reg i2s register address 28 * @param rfs Frame Size 29 */ 30 static void i2s_set_lr_framesize(struct i2s_reg *i2s_reg, unsigned int rfs) 31 { 32 unsigned int mod = readl(&i2s_reg->mod); 33 34 mod &= ~MOD_RCLK_MASK; 35 36 switch (rfs) { 37 case 768: 38 mod |= MOD_RCLK_768FS; 39 break; 40 case 512: 41 mod |= MOD_RCLK_512FS; 42 break; 43 case 384: 44 mod |= MOD_RCLK_384FS; 45 break; 46 default: 47 mod |= MOD_RCLK_256FS; 48 break; 49 } 50 51 writel(mod, &i2s_reg->mod); 52 } 53 54 /* 55 * Sets the i2s transfer control 56 * 57 * @param i2s_reg i2s register address 58 * @param on 1 enable tx , 0 disable tx transfer 59 */ 60 static void i2s_txctrl(struct i2s_reg *i2s_reg, int on) 61 { 62 unsigned int con = readl(&i2s_reg->con); 63 unsigned int mod = readl(&i2s_reg->mod) & ~MOD_MASK; 64 65 if (on) { 66 con |= CON_ACTIVE; 67 con &= ~CON_TXCH_PAUSE; 68 } else { 69 con |= CON_TXCH_PAUSE; 70 con &= ~CON_ACTIVE; 71 } 72 73 writel(mod, &i2s_reg->mod); 74 writel(con, &i2s_reg->con); 75 } 76 77 /* 78 * set the bit clock frame size (in multiples of LRCLK) 79 * 80 * @param i2s_reg i2s register address 81 * @param bfs bit Frame Size 82 */ 83 static void i2s_set_bitclk_framesize(struct i2s_reg *i2s_reg, unsigned bfs) 84 { 85 unsigned int mod = readl(&i2s_reg->mod); 86 87 mod &= ~MOD_BCLK_MASK; 88 89 switch (bfs) { 90 case 48: 91 mod |= MOD_BCLK_48FS; 92 break; 93 case 32: 94 mod |= MOD_BCLK_32FS; 95 break; 96 case 24: 97 mod |= MOD_BCLK_24FS; 98 break; 99 case 16: 100 mod |= MOD_BCLK_16FS; 101 break; 102 default: 103 return; 104 } 105 writel(mod, &i2s_reg->mod); 106 } 107 108 /* 109 * flushes the i2stx fifo 110 * 111 * @param i2s_reg i2s register address 112 * @param flush Tx fifo flush command (0x00 - do not flush 113 * 0x80 - flush tx fifo) 114 */ 115 static void i2s_fifo(struct i2s_reg *i2s_reg, unsigned int flush) 116 { 117 /* Flush the FIFO */ 118 setbits_le32(&i2s_reg->fic, flush); 119 clrbits_le32(&i2s_reg->fic, flush); 120 } 121 122 /* 123 * Set System Clock direction 124 * 125 * @param i2s_reg i2s register address 126 * @param dir Clock direction 127 * 128 * @return int value 0 for success, -1 in case of error 129 */ 130 static int i2s_set_sysclk_dir(struct i2s_reg *i2s_reg, int dir) 131 { 132 unsigned int mod = readl(&i2s_reg->mod); 133 134 if (dir == SND_SOC_CLOCK_IN) 135 mod |= MOD_CDCLKCON; 136 else 137 mod &= ~MOD_CDCLKCON; 138 139 writel(mod, &i2s_reg->mod); 140 141 return 0; 142 } 143 144 /* 145 * Sets I2S Clcok format 146 * 147 * @param fmt i2s clock properties 148 * @param i2s_reg i2s register address 149 * 150 * @return int value 0 for success, -1 in case of error 151 */ 152 static int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt) 153 { 154 unsigned int mod = readl(&i2s_reg->mod); 155 unsigned int tmp = 0; 156 unsigned int ret = 0; 157 158 /* Format is priority */ 159 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 160 case SND_SOC_DAIFMT_RIGHT_J: 161 tmp |= MOD_LR_RLOW; 162 tmp |= MOD_SDF_MSB; 163 break; 164 case SND_SOC_DAIFMT_LEFT_J: 165 tmp |= MOD_LR_RLOW; 166 tmp |= MOD_SDF_LSB; 167 break; 168 case SND_SOC_DAIFMT_I2S: 169 tmp |= MOD_SDF_IIS; 170 break; 171 default: 172 debug("%s: Invalid format priority [0x%x]\n", __func__, 173 (fmt & SND_SOC_DAIFMT_FORMAT_MASK)); 174 return -ERANGE; 175 } 176 177 /* 178 * INV flag is relative to the FORMAT flag - if set it simply 179 * flips the polarity specified by the Standard 180 */ 181 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 182 case SND_SOC_DAIFMT_NB_NF: 183 break; 184 case SND_SOC_DAIFMT_NB_IF: 185 if (tmp & MOD_LR_RLOW) 186 tmp &= ~MOD_LR_RLOW; 187 else 188 tmp |= MOD_LR_RLOW; 189 break; 190 default: 191 debug("%s: Invalid clock ploarity input [0x%x]\n", __func__, 192 (fmt & SND_SOC_DAIFMT_INV_MASK)); 193 return -ERANGE; 194 } 195 196 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 197 case SND_SOC_DAIFMT_CBS_CFS: 198 tmp |= MOD_SLAVE; 199 break; 200 case SND_SOC_DAIFMT_CBM_CFM: 201 /* Set default source clock in Master mode */ 202 ret = i2s_set_sysclk_dir(i2s_reg, SND_SOC_CLOCK_OUT); 203 if (ret != 0) { 204 debug("%s:set i2s clock direction failed\n", __func__); 205 return ret; 206 } 207 break; 208 default: 209 debug("%s: Invalid master selection [0x%x]\n", __func__, 210 (fmt & SND_SOC_DAIFMT_MASTER_MASK)); 211 return -ERANGE; 212 } 213 214 mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE); 215 mod |= tmp; 216 writel(mod, &i2s_reg->mod); 217 218 return 0; 219 } 220 221 /* 222 * Sets the sample width in bits 223 * 224 * @param blc samplewidth (size of sample in bits) 225 * @param i2s_reg i2s register address 226 * 227 * @return int value 0 for success, -1 in case of error 228 */ 229 static int i2s_set_samplesize(struct i2s_reg *i2s_reg, unsigned int blc) 230 { 231 unsigned int mod = readl(&i2s_reg->mod); 232 233 mod &= ~MOD_BLCP_MASK; 234 mod &= ~MOD_BLC_MASK; 235 236 switch (blc) { 237 case 8: 238 mod |= MOD_BLCP_8BIT; 239 mod |= MOD_BLC_8BIT; 240 break; 241 case 16: 242 mod |= MOD_BLCP_16BIT; 243 mod |= MOD_BLC_16BIT; 244 break; 245 case 24: 246 mod |= MOD_BLCP_24BIT; 247 mod |= MOD_BLC_24BIT; 248 break; 249 default: 250 debug("%s: Invalid sample size input [0x%x]\n", 251 __func__, blc); 252 return -ERANGE; 253 } 254 writel(mod, &i2s_reg->mod); 255 256 return 0; 257 } 258 259 int i2s_transfer_tx_data(struct i2s_uc_priv *pi2s_tx, void *data, 260 uint data_size) 261 { 262 struct i2s_reg *i2s_reg = (struct i2s_reg *)pi2s_tx->base_address; 263 u32 *ptr; 264 int i; 265 int start; 266 267 if (data_size < FIFO_LENGTH) { 268 debug("%s : Invalid data size\n", __func__); 269 return -ENODATA; /* invalid pcm data size */ 270 } 271 272 /* fill the tx buffer before stating the tx transmit */ 273 for (i = 0, ptr = data; i < FIFO_LENGTH; i++) 274 writel(*ptr++, &i2s_reg->txd); 275 276 data_size -= sizeof(*ptr) * FIFO_LENGTH; 277 i2s_txctrl(i2s_reg, I2S_TX_ON); 278 279 while (data_size > 0) { 280 start = get_timer(0); 281 if (!(CON_TXFIFO_FULL & (readl(&i2s_reg->con)))) { 282 writel(*ptr++, &i2s_reg->txd); 283 data_size -= sizeof(*ptr); 284 } else { 285 if (get_timer(start) > TIMEOUT_I2S_TX) { 286 i2s_txctrl(i2s_reg, I2S_TX_OFF); 287 debug("%s: I2S Transfer Timeout\n", __func__); 288 return -ETIMEDOUT; 289 } 290 } 291 } 292 i2s_txctrl(i2s_reg, I2S_TX_OFF); 293 294 return 0; 295 } 296 297 static int i2s_tx_init(struct i2s_uc_priv *pi2s_tx) 298 { 299 int ret; 300 struct i2s_reg *i2s_reg = (struct i2s_reg *)pi2s_tx->base_address; 301 302 if (pi2s_tx->id == 0) { 303 /* Initialize GPIO for I2S-0 */ 304 exynos_pinmux_config(PERIPH_ID_I2S0, 0); 305 306 /* Set EPLL Clock */ 307 ret = set_epll_clk(pi2s_tx->samplingrate * pi2s_tx->rfs * 4); 308 } else if (pi2s_tx->id == 1) { 309 /* Initialize GPIO for I2S-1 */ 310 exynos_pinmux_config(PERIPH_ID_I2S1, 0); 311 312 /* Set EPLL Clock */ 313 ret = set_epll_clk(pi2s_tx->audio_pll_clk); 314 } else { 315 debug("%s: unsupported i2s-%d bus\n", __func__, pi2s_tx->id); 316 return -ERANGE; 317 } 318 319 if (ret) { 320 debug("%s: epll clock set rate failed\n", __func__); 321 return ret; 322 } 323 324 /* Select Clk Source for Audio 0 or 1 */ 325 ret = set_i2s_clk_source(pi2s_tx->id); 326 if (ret) { 327 debug("%s: unsupported clock for i2s-%d\n", __func__, 328 pi2s_tx->id); 329 return ret; 330 } 331 332 if (pi2s_tx->id == 0) { 333 /*Reset the i2s module */ 334 writel(CON_RESET, &i2s_reg->con); 335 336 writel(MOD_OP_CLK | MOD_RCLKSRC, &i2s_reg->mod); 337 /* set i2s prescaler */ 338 writel(PSREN | PSVAL, &i2s_reg->psr); 339 } else { 340 /* Set Prescaler to get MCLK */ 341 ret = set_i2s_clk_prescaler(pi2s_tx->audio_pll_clk, 342 (pi2s_tx->samplingrate * (pi2s_tx->rfs)), 343 pi2s_tx->id); 344 } 345 if (ret) { 346 debug("%s: unsupported prescalar for i2s-%d\n", __func__, 347 pi2s_tx->id); 348 return ret; 349 } 350 351 /* Configure I2s format */ 352 ret = i2s_set_fmt(i2s_reg, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 353 SND_SOC_DAIFMT_CBM_CFM); 354 if (ret == 0) { 355 i2s_set_lr_framesize(i2s_reg, pi2s_tx->rfs); 356 ret = i2s_set_samplesize(i2s_reg, pi2s_tx->bitspersample); 357 if (ret != 0) { 358 debug("%s:set sample rate failed\n", __func__); 359 return ret; 360 } 361 362 i2s_set_bitclk_framesize(i2s_reg, pi2s_tx->bfs); 363 /* disable i2s transfer flag and flush the fifo */ 364 i2s_txctrl(i2s_reg, I2S_TX_OFF); 365 i2s_fifo(i2s_reg, FIC_TXFLUSH); 366 } else { 367 debug("%s: failed\n", __func__); 368 } 369 370 return ret; 371 } 372 373 static int samsung_i2s_tx_data(struct udevice *dev, void *data, uint data_size) 374 { 375 struct i2s_uc_priv *priv = dev_get_uclass_priv(dev); 376 377 return i2s_transfer_tx_data(priv, data, data_size); 378 } 379 380 static int samsung_i2s_probe(struct udevice *dev) 381 { 382 struct i2s_uc_priv *priv = dev_get_uclass_priv(dev); 383 384 return i2s_tx_init(priv); 385 } 386 387 static int samsung_i2s_ofdata_to_platdata(struct udevice *dev) 388 { 389 struct i2s_uc_priv *priv = dev_get_uclass_priv(dev); 390 ulong base; 391 392 /* 393 * Get the pre-defined sound specific values from FDT. 394 * All of these are expected to be correct otherwise 395 * wrong register values in i2s setup parameters 396 * may result in no sound play. 397 */ 398 base = dev_read_addr(dev); 399 if (base == FDT_ADDR_T_NONE) { 400 debug("%s: Missing i2s base\n", __func__); 401 return -EINVAL; 402 } 403 priv->base_address = base; 404 405 if (dev_read_u32u(dev, "samsung,i2s-epll-clock-frequency", 406 &priv->audio_pll_clk)) 407 goto err; 408 debug("audio_pll_clk = %d\n", priv->audio_pll_clk); 409 if (dev_read_u32u(dev, "samsung,i2s-sampling-rate", 410 &priv->samplingrate)) 411 goto err; 412 debug("samplingrate = %d\n", priv->samplingrate); 413 if (dev_read_u32u(dev, "samsung,i2s-bits-per-sample", 414 &priv->bitspersample)) 415 goto err; 416 debug("bitspersample = %d\n", priv->bitspersample); 417 if (dev_read_u32u(dev, "samsung,i2s-channels", &priv->channels)) 418 goto err; 419 debug("channels = %d\n", priv->channels); 420 if (dev_read_u32u(dev, "samsung,i2s-lr-clk-framesize", &priv->rfs)) 421 goto err; 422 debug("rfs = %d\n", priv->rfs); 423 if (dev_read_u32u(dev, "samsung,i2s-bit-clk-framesize", &priv->bfs)) 424 goto err; 425 debug("bfs = %d\n", priv->bfs); 426 427 if (dev_read_u32u(dev, "samsung,i2s-id", &priv->id)) 428 goto err; 429 debug("id = %d\n", priv->id); 430 431 return 0; 432 433 err: 434 debug("fail to get sound i2s node properties\n"); 435 436 return -EINVAL; 437 } 438 439 static const struct i2s_ops samsung_i2s_ops = { 440 .tx_data = samsung_i2s_tx_data, 441 }; 442 443 static const struct udevice_id samsung_i2s_ids[] = { 444 { .compatible = "samsung,s5pv210-i2s" }, 445 { } 446 }; 447 448 U_BOOT_DRIVER(samsung_i2s) = { 449 .name = "samsung_i2s", 450 .id = UCLASS_I2S, 451 .of_match = samsung_i2s_ids, 452 .probe = samsung_i2s_probe, 453 .ofdata_to_platdata = samsung_i2s_ofdata_to_platdata, 454 .ops = &samsung_i2s_ops, 455 }; 456