~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/sound/samsung-i2s.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        } 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 regiter 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 regiter address
 
112
 * @param flush         Tx fifo flush command (0x00 - do not flush
 
113
 *                              0x80 - flush tx fifo)
 
114
 */
 
115
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 regiter address
 
126
 * @param dir           Clock direction
 
127
 *
 
128
 * @return              int value 0 for success, -1 in case of error
 
129
 */
 
130
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 regiter address
 
149
 *
 
150
 * @return              int value 0 for success, -1 in case of error
 
151
 */
 
152
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 -1;
 
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 -1;
 
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 -1;
 
206
                }
 
207
                break;
 
208
        default:
 
209
                debug("%s: Invalid master selection [0x%x]\n", __func__,
 
210
                      (fmt & SND_SOC_DAIFMT_MASTER_MASK));
 
211
                return -1;
 
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 regiter address
 
226
 *
 
227
 * @return              int value 0 for success, -1 in case of error
 
228
 */
 
229
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 -1;
 
253
        }
 
254
        writel(mod, &i2s_reg->mod);
 
255
 
 
256
        return 0;
 
257
}
 
258
 
 
259
int i2s_transfer_tx_data(struct i2stx_info *pi2s_tx, unsigned int *data,
 
260
                                unsigned long data_size)
 
261
{
 
262
        int i;
 
263
        int start;
 
264
        struct i2s_reg *i2s_reg =
 
265
                                (struct i2s_reg *)pi2s_tx->base_address;
 
266
 
 
267
        if (data_size < FIFO_LENGTH) {
 
268
                debug("%s : Invalid data size\n", __func__);
 
269
                return -1; /* invalid pcm data size */
 
270
        }
 
271
 
 
272
        /* fill the tx buffer before stating the tx transmit */
 
273
        for (i = 0; i < FIFO_LENGTH; i++)
 
274
                writel(*data++, &i2s_reg->txd);
 
275
 
 
276
        data_size -= 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(*data++, &i2s_reg->txd);
 
283
                        data_size--;
 
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 -1;
 
289
                        }
 
290
                }
 
291
        }
 
292
        i2s_txctrl(i2s_reg, I2S_TX_OFF);
 
293
 
 
294
        return 0;
 
295
}
 
296
 
 
297
int i2s_tx_init(struct i2stx_info *pi2s_tx)
 
298
{
 
299
        int ret;
 
300
        struct i2s_reg *i2s_reg =
 
301
                                (struct i2s_reg *)pi2s_tx->base_address;
 
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 -1;
 
317
        }
 
318
 
 
319
        if (ret != 0) {
 
320
                debug("%s: epll clock set rate failed\n", __func__);
 
321
                return -1;
 
322
        }
 
323
 
 
324
        /* Select Clk Source for Audio 0 or 1 */
 
325
        ret = set_i2s_clk_source(pi2s_tx->id);
 
326
        if (ret == -1) {
 
327
                debug("%s: unsupported clock for i2s-%d\n", __func__,
 
328
                      pi2s_tx->id);
 
329
                return -1;
 
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 == -1) {
 
346
                debug("%s: unsupported prescalar for i2s-%d\n", __func__,
 
347
                      pi2s_tx->id);
 
348
                return -1;
 
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 -1;
 
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
}