blob: a685e58c8b70ef344b92110822a8329a6fe09ec4
1 | /* |
2 | * sound/soc/amlogic/auge/tdm_hw.c |
3 | * |
4 | * Copyright (C) 2017 Amlogic, Inc. All rights reserved. |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, but WITHOUT |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
14 | * more details. |
15 | * |
16 | */ |
17 | #include <sound/soc.h> |
18 | |
19 | #include "tdm_hw.h" |
20 | #include "iomap.h" |
21 | |
22 | #define MST_CLK_INVERT_PH0_PAD_BCLK (1 << 0) |
23 | #define MST_CLK_INVERT_PH0_PAD_FCLK (1 << 1) |
24 | #define MST_CLK_INVERT_PH1_TDMIN_BCLK (1 << 2) |
25 | #define MST_CLK_INVERT_PH1_TDMIN_FCLK (1 << 3) |
26 | #define MST_CLK_INVERT_PH2_TDMOUT_BCLK (1 << 4) |
27 | #define MST_CLK_INVERT_PH2_TDMOUT_FCLK (1 << 5) |
28 | |
29 | /*#define G12A_PTM_LB_INTERNAL*/ |
30 | /*#define TL1_PTM_LB_INTERNAL*/ |
31 | |
32 | /* without audio handler, it should be improved */ |
33 | void aml_tdm_enable( |
34 | struct aml_audio_controller *actrl, |
35 | int stream, int index, |
36 | bool is_enable) |
37 | { |
38 | unsigned int offset, reg; |
39 | |
40 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
41 | pr_debug("tdm playback enable\n"); |
42 | |
43 | offset = EE_AUDIO_TDMOUT_B_CTRL0 |
44 | - EE_AUDIO_TDMOUT_A_CTRL0; |
45 | reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index; |
46 | aml_audiobus_update_bits(actrl, reg, 1<<31, is_enable<<31); |
47 | } else { |
48 | pr_debug("tdm capture enable\n"); |
49 | |
50 | offset = EE_AUDIO_TDMIN_B_CTRL |
51 | - EE_AUDIO_TDMIN_A_CTRL; |
52 | reg = EE_AUDIO_TDMIN_A_CTRL + offset * index; |
53 | aml_audiobus_update_bits(actrl, reg, 1<<31, is_enable<<31); |
54 | } |
55 | |
56 | } |
57 | |
58 | void aml_tdm_arb_config(struct aml_audio_controller *actrl) |
59 | { |
60 | /* config ddr arb */ |
61 | aml_audiobus_write(actrl, EE_AUDIO_ARB_CTRL, 1<<31|0xff<<0); |
62 | } |
63 | |
64 | void aml_tdm_fifo_reset( |
65 | struct aml_audio_controller *actrl, |
66 | int stream, int index) |
67 | { |
68 | unsigned int reg, offset; |
69 | |
70 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
71 | offset = EE_AUDIO_TDMOUT_B_CTRL0 |
72 | - EE_AUDIO_TDMOUT_A_CTRL0; |
73 | reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index; |
74 | /* reset afifo */ |
75 | aml_audiobus_update_bits(actrl, reg, 3<<28, 0); |
76 | aml_audiobus_update_bits(actrl, reg, 1<<29, 1<<29); |
77 | aml_audiobus_update_bits(actrl, reg, 1<<28, 1<<28); |
78 | } else { |
79 | offset = EE_AUDIO_TDMIN_B_CTRL |
80 | - EE_AUDIO_TDMIN_A_CTRL; |
81 | reg = EE_AUDIO_TDMIN_A_CTRL + offset * index; |
82 | /* reset afifo */ |
83 | aml_audiobus_update_bits(actrl, reg, 3<<28, 0); |
84 | aml_audiobus_update_bits(actrl, reg, 1<<29, 1<<29); |
85 | aml_audiobus_update_bits(actrl, reg, 1<<28, 1<<28); |
86 | } |
87 | |
88 | } |
89 | |
90 | |
91 | void tdm_enable(int tdm_index, int is_enable) |
92 | { |
93 | unsigned int offset, reg; |
94 | |
95 | if (tdm_index < 3) { |
96 | pr_info("tdmout is_enable:%d\n", is_enable); |
97 | |
98 | offset = EE_AUDIO_TDMOUT_B_CTRL0 |
99 | - EE_AUDIO_TDMOUT_A_CTRL0; |
100 | reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * tdm_index; |
101 | |
102 | audiobus_update_bits(reg, 1<<31, is_enable<<31); |
103 | } else if (tdm_index < 6) { |
104 | pr_info("tdmin is_enable:%d\n", is_enable); |
105 | |
106 | tdm_index -= 3; |
107 | offset = EE_AUDIO_TDMIN_B_CTRL |
108 | - EE_AUDIO_TDMIN_A_CTRL; |
109 | reg = EE_AUDIO_TDMIN_A_CTRL + offset * tdm_index; |
110 | |
111 | audiobus_update_bits(reg, 1<<31, is_enable<<31); |
112 | } |
113 | } |
114 | |
115 | void tdm_fifo_enable(int tdm_index, int is_enable) |
116 | { |
117 | unsigned int reg, offset; |
118 | |
119 | if (tdm_index < 3) { |
120 | offset = EE_AUDIO_TDMOUT_B_CTRL0 |
121 | - EE_AUDIO_TDMOUT_A_CTRL0; |
122 | reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * tdm_index; |
123 | |
124 | if (is_enable) { |
125 | audiobus_update_bits(reg, 1<<29, 1<<29); |
126 | audiobus_update_bits(reg, 1<<28, 1<<28); |
127 | } else |
128 | audiobus_update_bits(reg, 3<<28, 0); |
129 | |
130 | } else if (tdm_index < 6) { |
131 | tdm_index -= 3; |
132 | offset = EE_AUDIO_TDMIN_B_CTRL |
133 | - EE_AUDIO_TDMIN_A_CTRL; |
134 | reg = EE_AUDIO_TDMIN_A_CTRL + offset * tdm_index; |
135 | |
136 | if (is_enable) { |
137 | audiobus_update_bits(reg, 1<<29, 1<<29); |
138 | audiobus_update_bits(reg, 1<<28, 1<<28); |
139 | } else |
140 | audiobus_update_bits(reg, 3<<28, 0); |
141 | } |
142 | } |
143 | |
144 | int tdmout_get_frddr_type(int bitwidth) |
145 | { |
146 | unsigned int frddr_type = 0; |
147 | |
148 | switch (bitwidth) { |
149 | case 8: |
150 | frddr_type = 0; |
151 | break; |
152 | case 16: |
153 | frddr_type = 2; |
154 | break; |
155 | case 24: |
156 | case 32: |
157 | frddr_type = 4; |
158 | break; |
159 | default: |
160 | pr_err("invalid bit_depth: %d\n", |
161 | bitwidth); |
162 | break; |
163 | } |
164 | |
165 | return frddr_type; |
166 | } |
167 | |
168 | void aml_tdm_fifo_ctrl( |
169 | struct aml_audio_controller *actrl, |
170 | int bitwidth, int stream, |
171 | int index, unsigned int fifo_id) |
172 | { |
173 | unsigned int frddr_type = tdmout_get_frddr_type(bitwidth); |
174 | unsigned int reg, offset; |
175 | |
176 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
177 | pr_debug("tdm prepare----playback\n"); |
178 | // from ddr, 63bit split into 2 samples |
179 | offset = EE_AUDIO_TDMOUT_B_CTRL1 |
180 | - EE_AUDIO_TDMOUT_A_CTRL1; |
181 | reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * index; |
182 | aml_audiobus_update_bits(actrl, reg, |
183 | 0x3<<24|0x1f<<8|0x7<<4, |
184 | fifo_id<<24|(bitwidth-1)<<8|frddr_type<<4); |
185 | } else { |
186 | pr_debug("tdm prepare----capture\n"); |
187 | } |
188 | |
189 | } |
190 | |
191 | static void aml_clk_set_tdmout_by_id( |
192 | struct aml_audio_controller *actrl, |
193 | unsigned int tdm_index, |
194 | unsigned int sclk_sel, |
195 | unsigned int lrclk_sel, |
196 | bool sclk_ws_inv, |
197 | bool is_master, |
198 | bool binv) |
199 | { |
200 | unsigned int val_sclk_ws_inv = 0; |
201 | unsigned int reg = EE_AUDIO_CLK_TDMOUT_A_CTRL + tdm_index; |
202 | |
203 | /* This is just a copy from previous setting. WHY??? */ |
204 | val_sclk_ws_inv = sclk_ws_inv && is_master; |
205 | if (val_sclk_ws_inv) |
206 | aml_audiobus_update_bits(actrl, reg, |
207 | 0x3<<30|1<<28|0xf<<24|0xf<<20, |
208 | 0x3<<30|val_sclk_ws_inv<<28| |
209 | sclk_sel<<24|lrclk_sel<<20); |
210 | else |
211 | aml_audiobus_update_bits(actrl, reg, |
212 | 0x3<<30|1<<29|0xf<<24|0xf<<20, |
213 | 0x3<<30|binv<<29| |
214 | sclk_sel<<24|lrclk_sel<<20); |
215 | } |
216 | |
217 | static void aml_clk_set_tdmin_by_id( |
218 | struct aml_audio_controller *actrl, |
219 | unsigned int tdm_index, |
220 | unsigned int sclk_sel, |
221 | unsigned int lrclk_sel) |
222 | { |
223 | unsigned int reg = |
224 | EE_AUDIO_CLK_TDMIN_A_CTRL + tdm_index; |
225 | aml_audiobus_update_bits(actrl, |
226 | reg, |
227 | 0xff<<20, |
228 | sclk_sel<<24|lrclk_sel<<20); |
229 | } |
230 | |
231 | static void aml_tdmout_invert_lrclk( |
232 | struct aml_audio_controller *actrl, |
233 | unsigned int tdm_index, |
234 | bool finv) |
235 | { |
236 | unsigned int off_set = |
237 | EE_AUDIO_TDMOUT_B_CTRL1 - EE_AUDIO_TDMOUT_A_CTRL1; |
238 | unsigned int reg_out = |
239 | EE_AUDIO_TDMOUT_A_CTRL1 + off_set * tdm_index; |
240 | aml_audiobus_update_bits(actrl, |
241 | reg_out, 0x1<<28, finv<<28); |
242 | } |
243 | |
244 | static void aml_tdmout_bclk_skew( |
245 | struct aml_audio_controller *actrl, |
246 | unsigned int tdm_index, |
247 | unsigned int bclkout_skew) |
248 | { |
249 | unsigned int off_set = |
250 | EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0; |
251 | unsigned int reg_out = |
252 | EE_AUDIO_TDMOUT_A_CTRL0 + off_set * tdm_index; |
253 | aml_audiobus_update_bits(actrl, |
254 | reg_out, 0x1f<<15, bclkout_skew<<15); |
255 | } |
256 | |
257 | void aml_tdm_set_format( |
258 | struct aml_audio_controller *actrl, |
259 | struct pcm_setting *p_config, |
260 | unsigned int clk_sel, |
261 | unsigned int index, |
262 | unsigned int fmt, |
263 | unsigned int capture_active, |
264 | unsigned int playback_active) |
265 | { |
266 | unsigned int binv, finv, id; |
267 | unsigned int valb, valf; |
268 | unsigned int reg_in, reg_out, off_set; |
269 | int bclkin_skew, bclkout_skew; |
270 | int master_mode; |
271 | unsigned int clkctl = 0; |
272 | |
273 | id = index; |
274 | |
275 | binv = 0; |
276 | finv = 0; |
277 | |
278 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
279 | case SND_SOC_DAIFMT_CBM_CFM: |
280 | valb = SLAVE_A + id; |
281 | valf = SLAVE_A + id; |
282 | master_mode = 0; |
283 | break; |
284 | case SND_SOC_DAIFMT_CBS_CFS: |
285 | valb = MASTER_A + clk_sel; |
286 | valf = MASTER_A + clk_sel; |
287 | master_mode = 1; |
288 | break; |
289 | default: |
290 | return; |
291 | } |
292 | aml_clk_set_tdmin_by_id(actrl, id, valb, valf); |
293 | |
294 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
295 | case SND_SOC_DAIFMT_I2S: |
296 | if (p_config->sclk_ws_inv) { |
297 | if (master_mode) |
298 | bclkout_skew = 2; |
299 | else |
300 | bclkout_skew = 3; |
301 | } else |
302 | bclkout_skew = 1; |
303 | bclkin_skew = 3; |
304 | |
305 | clkctl |= MST_CLK_INVERT_PH0_PAD_FCLK |
306 | | MST_CLK_INVERT_PH2_TDMOUT_FCLK; |
307 | finv = 1; |
308 | |
309 | if (master_mode) { |
310 | clkctl |= MST_CLK_INVERT_PH0_PAD_BCLK; |
311 | if (capture_active) |
312 | binv |= 1; |
313 | } else { |
314 | if (playback_active) |
315 | binv |= 1; |
316 | } |
317 | |
318 | break; |
319 | case SND_SOC_DAIFMT_DSP_A: |
320 | /* |
321 | * Frame high, 1clk before data, one bit for frame sync, |
322 | * frame sync starts one serial clock cycle earlier, |
323 | * that is, together with the last bit of the previous |
324 | * data word. |
325 | */ |
326 | if (p_config->sclk_ws_inv) { |
327 | if (master_mode) |
328 | bclkout_skew = 2; |
329 | else |
330 | bclkout_skew = 3; |
331 | } else |
332 | bclkout_skew = 1; |
333 | bclkin_skew = 3; |
334 | |
335 | if (capture_active) |
336 | binv |= 1; |
337 | break; |
338 | case SND_SOC_DAIFMT_LEFT_J: |
339 | case SND_SOC_DAIFMT_DSP_B: |
340 | /* |
341 | * Frame high, one bit for frame sync, |
342 | * frame sync asserts with the first bit of the frame. |
343 | */ |
344 | if (p_config->sclk_ws_inv) { |
345 | if (master_mode) |
346 | bclkout_skew = 3; |
347 | else |
348 | bclkout_skew = 4; |
349 | } else |
350 | bclkout_skew = 2; |
351 | bclkin_skew = 2; |
352 | |
353 | if (capture_active) |
354 | binv |= 1; |
355 | break; |
356 | default: |
357 | return; |
358 | } |
359 | |
360 | p_config->pcm_mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
361 | |
362 | pr_debug("pad clk ctl value:%x\n", clkctl); |
363 | /* set lrclk/bclk invertion */ |
364 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
365 | case SND_SOC_DAIFMT_IB_IF: |
366 | /* Invert both clocks */ |
367 | if (!master_mode) |
368 | binv ^= 1; |
369 | |
370 | finv |= 1; |
371 | clkctl ^= MST_CLK_INVERT_PH0_PAD_BCLK; |
372 | clkctl ^= MST_CLK_INVERT_PH0_PAD_FCLK; |
373 | break; |
374 | case SND_SOC_DAIFMT_IB_NF: |
375 | /* Invert bit clock */ |
376 | if (!master_mode) |
377 | binv ^= 1; |
378 | clkctl ^= MST_CLK_INVERT_PH0_PAD_BCLK; |
379 | break; |
380 | case SND_SOC_DAIFMT_NB_IF: |
381 | /* Invert frame clock */ |
382 | finv ^= 1; |
383 | clkctl ^= MST_CLK_INVERT_PH0_PAD_FCLK; |
384 | break; |
385 | case SND_SOC_DAIFMT_NB_NF: |
386 | /* normal cases */ |
387 | break; |
388 | default: |
389 | return; |
390 | } |
391 | pr_debug("sclk_ph0 (pad) clk ctl set:%x\n", clkctl); |
392 | /* clk ctrl: delay line and invert clk */ |
393 | /*clkctl |= 0x88880000;*/ |
394 | |
395 | if (master_mode) { |
396 | off_set = EE_AUDIO_MST_B_SCLK_CTRL1 - EE_AUDIO_MST_A_SCLK_CTRL1; |
397 | reg_out = EE_AUDIO_MST_A_SCLK_CTRL1 + off_set * id; |
398 | |
399 | aml_audiobus_update_bits(actrl, reg_out, 0x3f, clkctl); |
400 | } |
401 | |
402 | pr_info("master_mode(%d), binv(%d), finv(%d) out_skew(%d), in_skew(%d)\n", |
403 | master_mode, binv, finv, bclkout_skew, bclkin_skew); |
404 | |
405 | /* TDM out */ |
406 | if (playback_active) { |
407 | aml_clk_set_tdmout_by_id(actrl, |
408 | id, valb, valf, |
409 | p_config->sclk_ws_inv, master_mode, binv); |
410 | aml_tdmout_invert_lrclk(actrl, id, finv); |
411 | aml_tdmout_bclk_skew(actrl, id, bclkout_skew); |
412 | } |
413 | |
414 | /* TDM in */ |
415 | if (capture_active) { |
416 | reg_in = EE_AUDIO_CLK_TDMIN_A_CTRL + id; |
417 | aml_audiobus_update_bits(actrl, reg_in, |
418 | 0x3<<30, 0x3<<30); |
419 | |
420 | if (master_mode) |
421 | aml_audiobus_update_bits(actrl, reg_in, |
422 | 0x1<<29, binv<<29); |
423 | |
424 | off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; |
425 | reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * id; |
426 | aml_audiobus_update_bits(actrl, reg_in, |
427 | 3<<26|0x7<<16, 3<<26|bclkin_skew<<16); |
428 | |
429 | aml_audiobus_update_bits(actrl, reg_in, |
430 | 0x1<<25, finv<<25); |
431 | |
432 | if (p_config->pcm_mode == SND_SOC_DAIFMT_I2S) |
433 | aml_audiobus_update_bits(actrl, reg_in, |
434 | 1<<30, |
435 | 1<<30); |
436 | } |
437 | } |
438 | |
439 | void aml_update_tdmin_skew(struct aml_audio_controller *actrl, |
440 | int idx, int skew) |
441 | { |
442 | unsigned int reg_in, off_set; |
443 | |
444 | off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; |
445 | reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * idx; |
446 | aml_audiobus_update_bits(actrl, reg_in, |
447 | 0x7 << 16, skew << 16); |
448 | } |
449 | |
450 | void aml_update_tdmin_rev_ws(struct aml_audio_controller *actrl, |
451 | int idx, int is_rev) |
452 | { |
453 | unsigned int reg_in, off_set; |
454 | |
455 | off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; |
456 | reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * idx; |
457 | aml_audiobus_update_bits(actrl, reg_in, |
458 | 0x1 << 25, is_rev << 25); |
459 | } |
460 | |
461 | void aml_tdm_set_slot_out( |
462 | struct aml_audio_controller *actrl, |
463 | int index, int slots, int slot_width, |
464 | int force_oe, int oe_val) |
465 | { |
466 | unsigned int reg, offset; |
467 | |
468 | offset = EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0; |
469 | reg = EE_AUDIO_TDMOUT_A_CTRL0 + offset * index; |
470 | aml_audiobus_update_bits(actrl, reg, |
471 | 0x3ff, ((slots - 1) << 5) | (slot_width - 1)); |
472 | |
473 | if (force_oe) { |
474 | aml_audiobus_update_bits(actrl, reg, 0xf << 24, force_oe << 24); |
475 | |
476 | /* force oe val, in or out */ |
477 | if (oe_val) { |
478 | reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * index; |
479 | aml_audiobus_update_bits(actrl, reg, |
480 | 0xf << 0, oe_val << 0); |
481 | } |
482 | } |
483 | } |
484 | |
485 | void aml_tdm_set_slot_in( |
486 | struct aml_audio_controller *actrl, |
487 | int index, int in_src, int slot_width) |
488 | { |
489 | unsigned int reg, offset; |
490 | |
491 | offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; |
492 | reg = EE_AUDIO_TDMIN_A_CTRL + offset * index; |
493 | |
494 | #if defined(G12A_PTM_LB_INTERNAL) |
495 | if (index == 0) /*TODO: ptm, tdma dsp_a lb*/ |
496 | aml_audiobus_update_bits(actrl, reg, |
497 | 0xf<<20|0x1f, 6<<20|(slot_width-1)); |
498 | if (index == 1) /*TODO: ptm, tdmb i2s lb*/ |
499 | aml_audiobus_update_bits(actrl, reg, |
500 | 0xf<<20|0x1f, 7<<20|(slot_width-1)); |
501 | else |
502 | #elif defined(TL1_PTM_LB_INTERNAL) |
503 | if (index == 0) /*TODO: ptm, tdma dsp_a lb*/ |
504 | aml_audiobus_update_bits(actrl, reg, |
505 | 0xf<<20|0x1f, 13<<20|(slot_width-1)); |
506 | else if (index == 1) /*TODO: ptm, tdmb i2s lb*/ |
507 | aml_audiobus_update_bits(actrl, reg, |
508 | 0xf<<20|0x1f, 14<<20|(slot_width-1)); |
509 | else |
510 | #endif |
511 | aml_audiobus_update_bits(actrl, reg, |
512 | 0xf << 20 | 0x1f, in_src << 20 | (slot_width-1)); |
513 | } |
514 | |
515 | void aml_update_tdmin_src( |
516 | struct aml_audio_controller *actrl, |
517 | int index, int in_src) |
518 | { |
519 | unsigned int reg, offset; |
520 | |
521 | offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; |
522 | reg = EE_AUDIO_TDMIN_A_CTRL + offset * index; |
523 | |
524 | aml_audiobus_update_bits(actrl, reg, |
525 | 0xf << 20, in_src << 20); |
526 | } |
527 | |
528 | void tdmin_set_chnum_en( |
529 | struct aml_audio_controller *actrl, |
530 | int index, bool enable) |
531 | { |
532 | unsigned int reg, offset; |
533 | |
534 | offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; |
535 | reg = EE_AUDIO_TDMIN_A_CTRL + offset * index; |
536 | |
537 | aml_audiobus_update_bits(actrl, reg, |
538 | 0x1 << 6, enable << 6); |
539 | } |
540 | |
541 | void aml_tdm_set_channel_mask( |
542 | struct aml_audio_controller *actrl, |
543 | int stream, int index, int lane, int mask) |
544 | { |
545 | unsigned int offset, reg; |
546 | |
547 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
548 | offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0; |
549 | reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; |
550 | } else { |
551 | offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0; |
552 | reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; |
553 | } |
554 | |
555 | aml_audiobus_write(actrl, reg + lane, mask); |
556 | } |
557 | |
558 | void aml_tdm_set_lane_channel_swap( |
559 | struct aml_audio_controller *actrl, |
560 | int stream, int index, int swap) |
561 | { |
562 | unsigned int offset, reg; |
563 | |
564 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
565 | // set lanes mask acordingly |
566 | offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0; |
567 | reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; |
568 | |
569 | pr_debug("\ttdmout swap val = %#x\n", swap); |
570 | offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP; |
571 | reg = EE_AUDIO_TDMOUT_A_SWAP + offset * index; |
572 | aml_audiobus_write(actrl, reg, swap); |
573 | } else { |
574 | offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0; |
575 | reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; |
576 | |
577 | pr_debug("\ttdmin swap val = %#x\n", swap); |
578 | offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP; |
579 | reg = EE_AUDIO_TDMIN_A_SWAP + offset * index; |
580 | aml_audiobus_write(actrl, reg, swap); |
581 | } |
582 | } |
583 | |
584 | void aml_tdm_set_bclk_ratio( |
585 | struct aml_audio_controller *actrl, |
586 | int clk_sel, int lrclk_hi, int bclk_ratio) |
587 | { |
588 | unsigned int reg, reg_step = 2; |
589 | |
590 | reg = EE_AUDIO_MST_A_SCLK_CTRL0 + reg_step * clk_sel; |
591 | |
592 | aml_audiobus_update_bits(actrl, reg, |
593 | (3 << 30)|0x3ff<<10|0x3ff, |
594 | (3 << 30)|lrclk_hi<<10|bclk_ratio); |
595 | } |
596 | |
597 | void aml_tdm_set_lrclkdiv( |
598 | struct aml_audio_controller *actrl, |
599 | int clk_sel, int ratio) |
600 | { |
601 | unsigned int reg, reg_step = 2; |
602 | |
603 | pr_debug("aml_dai_set_clkdiv, clksel(%d), ratio(%d)\n", |
604 | clk_sel, ratio); |
605 | |
606 | reg = EE_AUDIO_MST_A_SCLK_CTRL0 + reg_step * clk_sel; |
607 | |
608 | aml_audiobus_update_bits(actrl, reg, |
609 | (3 << 30)|(0x3ff << 20), |
610 | (3 << 30)|(ratio << 20)); |
611 | } |
612 | |
613 | void aml_tdmout_select_aed(bool enable, int tdmout_id) |
614 | { |
615 | unsigned int reg, offset; |
616 | |
617 | /* select eq_drc output */ |
618 | offset = EE_AUDIO_TDMOUT_B_CTRL1 |
619 | - EE_AUDIO_TDMOUT_A_CTRL1; |
620 | reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id; |
621 | audiobus_update_bits(reg, 0x1 << 31, enable << 31); |
622 | } |
623 | |
624 | void aml_tdmout_get_aed_info(int tdmout_id, |
625 | int *bitwidth, int *frddrtype) |
626 | { |
627 | unsigned int reg, offset, val; |
628 | |
629 | offset = EE_AUDIO_TDMOUT_B_CTRL1 |
630 | - EE_AUDIO_TDMOUT_A_CTRL1; |
631 | reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id; |
632 | |
633 | val = audiobus_read(reg); |
634 | if (bitwidth) |
635 | *bitwidth = (val >> 8) & 0x1f; |
636 | if (frddrtype) |
637 | *frddrtype = (val >> 4) & 0x7; |
638 | } |
639 | |
640 | void aml_tdmout_enable_gain(int tdmout_id, int en) |
641 | { |
642 | unsigned int reg, offset; |
643 | |
644 | offset = EE_AUDIO_TDMOUT_B_CTRL1 |
645 | - EE_AUDIO_TDMOUT_A_CTRL1; |
646 | reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id; |
647 | audiobus_update_bits(reg, 0x1 << 26, !!en << 26); |
648 | } |
649 | |
650 | void aml_tdm_clk_pad_select( |
651 | struct aml_audio_controller *actrl, |
652 | int mpad, int mclk_sel, |
653 | int tdm_index, int clk_sel) |
654 | { |
655 | unsigned int reg, mask_offset, val_offset; |
656 | |
657 | // TODO: fix mclk |
658 | if (mpad == 0) { |
659 | mask_offset = 0x7 << 0; |
660 | val_offset = mclk_sel << 0; |
661 | } else if (mpad == 1) { |
662 | mask_offset = 0x7 << 4; |
663 | val_offset = mclk_sel << 4; |
664 | } else { |
665 | pr_err("unknown tdm mpad:%d\n", mpad); |
666 | return; |
667 | } |
668 | reg = EE_AUDIO_MST_PAD_CTRL0(0); |
669 | aml_audiobus_update_bits(actrl, reg, |
670 | mask_offset, val_offset); |
671 | |
672 | reg = EE_AUDIO_MST_PAD_CTRL1(0); |
673 | switch (tdm_index) { |
674 | case 0: |
675 | mask_offset = 0x7 << 16 | 0x7 << 0; |
676 | val_offset = clk_sel << 16 | clk_sel << 0; |
677 | break; |
678 | case 1: |
679 | mask_offset = 0x7 << 20 | 0x7 << 4; |
680 | val_offset = clk_sel << 20 | clk_sel << 4; |
681 | break; |
682 | case 2: |
683 | mask_offset = 0x7 << 24 | 0x7 << 8; |
684 | val_offset = clk_sel << 24 | clk_sel << 8; |
685 | break; |
686 | default: |
687 | pr_err("unknown tdm index:%d\n", tdm_index); |
688 | return; |
689 | } |
690 | aml_audiobus_update_bits(actrl, reg, |
691 | mask_offset, val_offset); |
692 | |
693 | } |
694 | |
695 | void i2s_to_hdmitx_ctrl(int tdm_index) |
696 | { |
697 | audiobus_write(EE_AUDIO_TOHDMITX_CTRL0, |
698 | 1 << 31 |
699 | | tdm_index << 12 /* dat_sel */ |
700 | | tdm_index << 8 /* lrclk_sel */ |
701 | | 1 << 7 /* Bclk_cap_inv */ |
702 | | 0 << 6 /* Bclk_o_inv */ |
703 | | tdm_index << 4 /* Bclk_sel */ |
704 | ); |
705 | } |
706 | |
707 | void aml_tdm_mute_playback( |
708 | struct aml_audio_controller *actrl, |
709 | int tdm_index, |
710 | bool mute) |
711 | { |
712 | unsigned int offset, reg; |
713 | unsigned int mute_mask = 0xffffffff; |
714 | unsigned int mute_val = 0; |
715 | int i = 0, lanes = 4; |
716 | |
717 | if (mute) |
718 | mute_val = 0xffffffff; |
719 | |
720 | offset = EE_AUDIO_TDMOUT_B_MUTE0 |
721 | - EE_AUDIO_TDMOUT_A_MUTE0; |
722 | reg = EE_AUDIO_TDMOUT_A_MUTE0 + offset * tdm_index; |
723 | for (i = 0; i < lanes; i++) |
724 | aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); |
725 | } |
726 | |
727 | void aml_tdm_mute_capture( |
728 | struct aml_audio_controller *actrl, |
729 | int tdm_index, |
730 | bool mute) |
731 | { |
732 | unsigned int offset, reg; |
733 | unsigned int mute_mask = 0xffffffff; |
734 | unsigned int mute_val = 0; |
735 | int i = 0, lanes = 4; |
736 | |
737 | if (mute) |
738 | mute_val = 0xffffffff; |
739 | |
740 | offset = EE_AUDIO_TDMIN_B_MUTE0 |
741 | - EE_AUDIO_TDMIN_A_MUTE0; |
742 | reg = EE_AUDIO_TDMIN_A_MUTE0 + offset * tdm_index; |
743 | for (i = 0; i < lanes; i++) |
744 | aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); |
745 | } |
746 | |
747 |