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