summaryrefslogtreecommitdiff
path: root/sound/soc/amlogic/auge/tdm_hw.c (plain)
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 */
33void 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
58void 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
64void 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
91void 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
115void 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
144int 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
168void 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
191static 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
217static 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
231static 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
244static 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
257void 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
439void 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
450void 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
461void 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
485void 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)
503if (index == 0) /*TODO: ptm, tdma dsp_a lb*/
504 aml_audiobus_update_bits(actrl, reg,
505 0xf<<20|0x1f, 13<<20|(slot_width-1));
506else if (index == 1) /*TODO: ptm, tdmb i2s lb*/
507 aml_audiobus_update_bits(actrl, reg,
508 0xf<<20|0x1f, 14<<20|(slot_width-1));
509else
510#endif
511 aml_audiobus_update_bits(actrl, reg,
512 0xf << 20 | 0x1f, in_src << 20 | (slot_width-1));
513}
514
515void 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
528void 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
541void 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
558void 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
584void 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
597void 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
613void 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
624void 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
640void 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
650void 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
695void 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
707void 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
727void 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