Home | History | Annotate | Download | only in sound
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2012 Samsung Electronics
      4  * R. Chandrasekar <rcsekar (at) 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