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