1
1
// SPDX-License-Identifier: GPL-2.0-only
2
- // SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
2
+ // SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES.
3
3
// All rights reserved.
4
4
//
5
5
// tegra210_amx.c - Tegra210 AMX driver
@@ -46,21 +46,35 @@ static const struct reg_default tegra210_amx_reg_defaults[] = {
46
46
{ TEGRA210_AMX_CFG_RAM_CTRL , 0x00004000 },
47
47
};
48
48
49
+ static const struct reg_default tegra264_amx_reg_defaults [] = {
50
+ { TEGRA210_AMX_RX_INT_MASK , 0x0000000f },
51
+ { TEGRA210_AMX_RX1_CIF_CTRL , 0x00003800 },
52
+ { TEGRA210_AMX_RX2_CIF_CTRL , 0x00003800 },
53
+ { TEGRA210_AMX_RX3_CIF_CTRL , 0x00003800 },
54
+ { TEGRA210_AMX_RX4_CIF_CTRL , 0x00003800 },
55
+ { TEGRA210_AMX_TX_INT_MASK , 0x00000001 },
56
+ { TEGRA210_AMX_TX_CIF_CTRL , 0x00003800 },
57
+ { TEGRA210_AMX_CG , 0x1 },
58
+ { TEGRA264_AMX_CFG_RAM_CTRL , 0x00004000 },
59
+ };
60
+
49
61
static void tegra210_amx_write_map_ram (struct tegra210_amx * amx )
50
62
{
51
63
int i ;
52
64
53
- regmap_write (amx -> regmap , TEGRA210_AMX_CFG_RAM_CTRL ,
65
+ regmap_write (amx -> regmap , TEGRA210_AMX_CFG_RAM_CTRL + amx -> soc_data -> reg_offset ,
54
66
TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
55
67
TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN |
56
68
TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE );
57
69
58
- for (i = 0 ; i < TEGRA210_AMX_RAM_DEPTH ; i ++ )
59
- regmap_write (amx -> regmap , TEGRA210_AMX_CFG_RAM_DATA ,
70
+ for (i = 0 ; i < amx -> soc_data -> ram_depth ; i ++ )
71
+ regmap_write (amx -> regmap , TEGRA210_AMX_CFG_RAM_DATA + amx -> soc_data -> reg_offset ,
60
72
amx -> map [i ]);
61
73
62
- regmap_write (amx -> regmap , TEGRA210_AMX_OUT_BYTE_EN0 , amx -> byte_mask [0 ]);
63
- regmap_write (amx -> regmap , TEGRA210_AMX_OUT_BYTE_EN1 , amx -> byte_mask [1 ]);
74
+ for (i = 0 ; i < amx -> soc_data -> byte_mask_size ; i ++ )
75
+ regmap_write (amx -> regmap ,
76
+ TEGRA210_AMX_OUT_BYTE_EN0 + (i * TEGRA210_AMX_AUDIOCIF_CH_STRIDE ),
77
+ amx -> byte_mask [i ]);
64
78
}
65
79
66
80
static int tegra210_amx_startup (struct snd_pcm_substream * substream ,
@@ -157,7 +171,10 @@ static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai,
157
171
cif_conf .audio_bits = audio_bits ;
158
172
cif_conf .client_bits = audio_bits ;
159
173
160
- tegra_set_cif (amx -> regmap , reg , & cif_conf );
174
+ if (amx -> soc_data -> max_ch == TEGRA264_AMX_MAX_CHANNEL )
175
+ tegra264_set_cif (amx -> regmap , reg , & cif_conf );
176
+ else
177
+ tegra_set_cif (amx -> regmap , reg , & cif_conf );
161
178
162
179
return 0 ;
163
180
}
@@ -170,9 +187,10 @@ static int tegra210_amx_in_hw_params(struct snd_pcm_substream *substream,
170
187
171
188
if (amx -> soc_data -> auto_disable ) {
172
189
regmap_write (amx -> regmap ,
173
- AMX_CH_REG (dai -> id , TEGRA194_AMX_RX1_FRAME_PERIOD ),
190
+ AMX_CH_REG (dai -> id , TEGRA194_AMX_RX1_FRAME_PERIOD +
191
+ amx -> soc_data -> reg_offset ),
174
192
TEGRA194_MAX_FRAME_IDLE_COUNT );
175
- regmap_write (amx -> regmap , TEGRA210_AMX_CYA , 1 );
193
+ regmap_write (amx -> regmap , TEGRA210_AMX_CYA + amx -> soc_data -> reg_offset , 1 );
176
194
}
177
195
178
196
return tegra210_amx_set_audio_cif (dai , params ,
@@ -194,14 +212,11 @@ static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
194
212
struct soc_mixer_control * mc =
195
213
(struct soc_mixer_control * )kcontrol -> private_value ;
196
214
struct tegra210_amx * amx = snd_soc_component_get_drvdata (cmpnt );
197
- unsigned char * bytes_map = (unsigned char * )& amx -> map ;
215
+ unsigned char * bytes_map = (unsigned char * )amx -> map ;
198
216
int reg = mc -> reg ;
199
217
int enabled ;
200
218
201
- if (reg > 31 )
202
- enabled = amx -> byte_mask [1 ] & (1 << (reg - 32 ));
203
- else
204
- enabled = amx -> byte_mask [0 ] & (1 << reg );
219
+ enabled = amx -> byte_mask [reg / 32 ] & (1 << (reg % 32 ));
205
220
206
221
/*
207
222
* TODO: Simplify this logic to just return from bytes_map[]
@@ -228,7 +243,7 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
228
243
(struct soc_mixer_control * )kcontrol -> private_value ;
229
244
struct snd_soc_component * cmpnt = snd_soc_kcontrol_component (kcontrol );
230
245
struct tegra210_amx * amx = snd_soc_component_get_drvdata (cmpnt );
231
- unsigned char * bytes_map = (unsigned char * )& amx -> map ;
246
+ unsigned char * bytes_map = (unsigned char * )amx -> map ;
232
247
int reg = mc -> reg ;
233
248
int value = ucontrol -> value .integer .value [0 ];
234
249
unsigned int mask_val = amx -> byte_mask [reg / 32 ];
@@ -418,7 +433,90 @@ static struct snd_kcontrol_new tegra210_amx_controls[] = {
418
433
TEGRA210_AMX_BYTE_MAP_CTRL (63 ),
419
434
};
420
435
436
+ static struct snd_kcontrol_new tegra264_amx_controls [] = {
437
+ TEGRA210_AMX_BYTE_MAP_CTRL (64 ),
438
+ TEGRA210_AMX_BYTE_MAP_CTRL (65 ),
439
+ TEGRA210_AMX_BYTE_MAP_CTRL (66 ),
440
+ TEGRA210_AMX_BYTE_MAP_CTRL (67 ),
441
+ TEGRA210_AMX_BYTE_MAP_CTRL (68 ),
442
+ TEGRA210_AMX_BYTE_MAP_CTRL (69 ),
443
+ TEGRA210_AMX_BYTE_MAP_CTRL (70 ),
444
+ TEGRA210_AMX_BYTE_MAP_CTRL (71 ),
445
+ TEGRA210_AMX_BYTE_MAP_CTRL (72 ),
446
+ TEGRA210_AMX_BYTE_MAP_CTRL (73 ),
447
+ TEGRA210_AMX_BYTE_MAP_CTRL (74 ),
448
+ TEGRA210_AMX_BYTE_MAP_CTRL (75 ),
449
+ TEGRA210_AMX_BYTE_MAP_CTRL (76 ),
450
+ TEGRA210_AMX_BYTE_MAP_CTRL (77 ),
451
+ TEGRA210_AMX_BYTE_MAP_CTRL (78 ),
452
+ TEGRA210_AMX_BYTE_MAP_CTRL (79 ),
453
+ TEGRA210_AMX_BYTE_MAP_CTRL (80 ),
454
+ TEGRA210_AMX_BYTE_MAP_CTRL (81 ),
455
+ TEGRA210_AMX_BYTE_MAP_CTRL (82 ),
456
+ TEGRA210_AMX_BYTE_MAP_CTRL (83 ),
457
+ TEGRA210_AMX_BYTE_MAP_CTRL (84 ),
458
+ TEGRA210_AMX_BYTE_MAP_CTRL (85 ),
459
+ TEGRA210_AMX_BYTE_MAP_CTRL (86 ),
460
+ TEGRA210_AMX_BYTE_MAP_CTRL (87 ),
461
+ TEGRA210_AMX_BYTE_MAP_CTRL (88 ),
462
+ TEGRA210_AMX_BYTE_MAP_CTRL (89 ),
463
+ TEGRA210_AMX_BYTE_MAP_CTRL (90 ),
464
+ TEGRA210_AMX_BYTE_MAP_CTRL (91 ),
465
+ TEGRA210_AMX_BYTE_MAP_CTRL (92 ),
466
+ TEGRA210_AMX_BYTE_MAP_CTRL (93 ),
467
+ TEGRA210_AMX_BYTE_MAP_CTRL (94 ),
468
+ TEGRA210_AMX_BYTE_MAP_CTRL (95 ),
469
+ TEGRA210_AMX_BYTE_MAP_CTRL (96 ),
470
+ TEGRA210_AMX_BYTE_MAP_CTRL (97 ),
471
+ TEGRA210_AMX_BYTE_MAP_CTRL (98 ),
472
+ TEGRA210_AMX_BYTE_MAP_CTRL (99 ),
473
+ TEGRA210_AMX_BYTE_MAP_CTRL (100 ),
474
+ TEGRA210_AMX_BYTE_MAP_CTRL (101 ),
475
+ TEGRA210_AMX_BYTE_MAP_CTRL (102 ),
476
+ TEGRA210_AMX_BYTE_MAP_CTRL (103 ),
477
+ TEGRA210_AMX_BYTE_MAP_CTRL (104 ),
478
+ TEGRA210_AMX_BYTE_MAP_CTRL (105 ),
479
+ TEGRA210_AMX_BYTE_MAP_CTRL (106 ),
480
+ TEGRA210_AMX_BYTE_MAP_CTRL (107 ),
481
+ TEGRA210_AMX_BYTE_MAP_CTRL (108 ),
482
+ TEGRA210_AMX_BYTE_MAP_CTRL (109 ),
483
+ TEGRA210_AMX_BYTE_MAP_CTRL (110 ),
484
+ TEGRA210_AMX_BYTE_MAP_CTRL (111 ),
485
+ TEGRA210_AMX_BYTE_MAP_CTRL (112 ),
486
+ TEGRA210_AMX_BYTE_MAP_CTRL (113 ),
487
+ TEGRA210_AMX_BYTE_MAP_CTRL (114 ),
488
+ TEGRA210_AMX_BYTE_MAP_CTRL (115 ),
489
+ TEGRA210_AMX_BYTE_MAP_CTRL (116 ),
490
+ TEGRA210_AMX_BYTE_MAP_CTRL (117 ),
491
+ TEGRA210_AMX_BYTE_MAP_CTRL (118 ),
492
+ TEGRA210_AMX_BYTE_MAP_CTRL (119 ),
493
+ TEGRA210_AMX_BYTE_MAP_CTRL (120 ),
494
+ TEGRA210_AMX_BYTE_MAP_CTRL (121 ),
495
+ TEGRA210_AMX_BYTE_MAP_CTRL (122 ),
496
+ TEGRA210_AMX_BYTE_MAP_CTRL (123 ),
497
+ TEGRA210_AMX_BYTE_MAP_CTRL (124 ),
498
+ TEGRA210_AMX_BYTE_MAP_CTRL (125 ),
499
+ TEGRA210_AMX_BYTE_MAP_CTRL (126 ),
500
+ TEGRA210_AMX_BYTE_MAP_CTRL (127 ),
501
+ };
502
+
503
+ static int tegra210_amx_component_probe (struct snd_soc_component * component )
504
+ {
505
+ struct tegra210_amx * amx = snd_soc_component_get_drvdata (component );
506
+ int err = 0 ;
507
+
508
+ if (amx -> soc_data -> num_controls ) {
509
+ err = snd_soc_add_component_controls (component , amx -> soc_data -> controls ,
510
+ amx -> soc_data -> num_controls );
511
+ if (err )
512
+ dev_err (component -> dev , "can't add AMX controls, err: %d\n" , err );
513
+ }
514
+
515
+ return err ;
516
+ }
517
+
421
518
static const struct snd_soc_component_driver tegra210_amx_cmpnt = {
519
+ .probe = tegra210_amx_component_probe ,
422
520
.dapm_widgets = tegra210_amx_widgets ,
423
521
.num_dapm_widgets = ARRAY_SIZE (tegra210_amx_widgets ),
424
522
.dapm_routes = tegra210_amx_routes ,
@@ -450,6 +548,22 @@ static bool tegra194_amx_wr_reg(struct device *dev, unsigned int reg)
450
548
}
451
549
}
452
550
551
+ static bool tegra264_amx_wr_reg (struct device * dev ,
552
+ unsigned int reg )
553
+ {
554
+ switch (reg ) {
555
+ case TEGRA210_AMX_RX_INT_MASK ... TEGRA210_AMX_RX4_CIF_CTRL :
556
+ case TEGRA210_AMX_TX_INT_MASK ... TEGRA210_AMX_TX_CIF_CTRL :
557
+ case TEGRA210_AMX_ENABLE ... TEGRA210_AMX_CG :
558
+ case TEGRA210_AMX_CTRL ... TEGRA264_AMX_STREAMS_AUTO_DISABLE :
559
+ case TEGRA264_AMX_CFG_RAM_CTRL ... TEGRA264_AMX_CFG_RAM_DATA :
560
+ case TEGRA264_AMX_RX1_FRAME_PERIOD ... TEGRA264_AMX_RX4_FRAME_PERIOD :
561
+ return true;
562
+ default :
563
+ return false;
564
+ }
565
+ }
566
+
453
567
static bool tegra210_amx_rd_reg (struct device * dev , unsigned int reg )
454
568
{
455
569
switch (reg ) {
@@ -470,6 +584,21 @@ static bool tegra194_amx_rd_reg(struct device *dev, unsigned int reg)
470
584
}
471
585
}
472
586
587
+ static bool tegra264_amx_rd_reg (struct device * dev ,
588
+ unsigned int reg )
589
+ {
590
+ switch (reg ) {
591
+ case TEGRA210_AMX_RX_STATUS ... TEGRA210_AMX_RX4_CIF_CTRL :
592
+ case TEGRA210_AMX_TX_STATUS ... TEGRA210_AMX_TX_CIF_CTRL :
593
+ case TEGRA210_AMX_ENABLE ... TEGRA210_AMX_INT_STATUS :
594
+ case TEGRA210_AMX_CTRL ... TEGRA264_AMX_CFG_RAM_DATA :
595
+ case TEGRA264_AMX_RX1_FRAME_PERIOD ... TEGRA264_AMX_RX4_FRAME_PERIOD :
596
+ return true;
597
+ default :
598
+ return false;
599
+ }
600
+ }
601
+
473
602
static bool tegra210_amx_volatile_reg (struct device * dev , unsigned int reg )
474
603
{
475
604
switch (reg ) {
@@ -492,6 +621,29 @@ static bool tegra210_amx_volatile_reg(struct device *dev, unsigned int reg)
492
621
return false;
493
622
}
494
623
624
+ static bool tegra264_amx_volatile_reg (struct device * dev ,
625
+ unsigned int reg )
626
+ {
627
+ switch (reg ) {
628
+ case TEGRA210_AMX_RX_STATUS :
629
+ case TEGRA210_AMX_RX_INT_STATUS :
630
+ case TEGRA210_AMX_RX_INT_SET :
631
+ case TEGRA210_AMX_TX_STATUS :
632
+ case TEGRA210_AMX_TX_INT_STATUS :
633
+ case TEGRA210_AMX_TX_INT_SET :
634
+ case TEGRA210_AMX_SOFT_RESET :
635
+ case TEGRA210_AMX_STATUS :
636
+ case TEGRA210_AMX_INT_STATUS :
637
+ case TEGRA264_AMX_CFG_RAM_CTRL :
638
+ case TEGRA264_AMX_CFG_RAM_DATA :
639
+ return true;
640
+ default :
641
+ break ;
642
+ }
643
+
644
+ return false;
645
+ }
646
+
495
647
static const struct regmap_config tegra210_amx_regmap_config = {
496
648
.reg_bits = 32 ,
497
649
.reg_stride = 4 ,
@@ -518,18 +670,51 @@ static const struct regmap_config tegra194_amx_regmap_config = {
518
670
.cache_type = REGCACHE_FLAT ,
519
671
};
520
672
673
+ static const struct regmap_config tegra264_amx_regmap_config = {
674
+ .reg_bits = 32 ,
675
+ .reg_stride = 4 ,
676
+ .val_bits = 32 ,
677
+ .max_register = TEGRA264_AMX_RX4_LAST_FRAME_PERIOD ,
678
+ .writeable_reg = tegra264_amx_wr_reg ,
679
+ .readable_reg = tegra264_amx_rd_reg ,
680
+ .volatile_reg = tegra264_amx_volatile_reg ,
681
+ .reg_defaults = tegra264_amx_reg_defaults ,
682
+ .num_reg_defaults = ARRAY_SIZE (tegra264_amx_reg_defaults ),
683
+ .cache_type = REGCACHE_FLAT ,
684
+ };
685
+
521
686
static const struct tegra210_amx_soc_data soc_data_tegra210 = {
522
687
.regmap_conf = & tegra210_amx_regmap_config ,
688
+ .max_ch = TEGRA210_AMX_MAX_CHANNEL ,
689
+ .ram_depth = TEGRA210_AMX_RAM_DEPTH ,
690
+ .byte_mask_size = TEGRA210_AMX_BYTE_MASK_COUNT ,
691
+ .reg_offset = TEGRA210_AMX_AUTO_DISABLE_OFFSET ,
523
692
};
524
693
525
694
static const struct tegra210_amx_soc_data soc_data_tegra194 = {
526
695
.regmap_conf = & tegra194_amx_regmap_config ,
527
696
.auto_disable = true,
697
+ .max_ch = TEGRA210_AMX_MAX_CHANNEL ,
698
+ .ram_depth = TEGRA210_AMX_RAM_DEPTH ,
699
+ .byte_mask_size = TEGRA210_AMX_BYTE_MASK_COUNT ,
700
+ .reg_offset = TEGRA210_AMX_AUTO_DISABLE_OFFSET ,
701
+ };
702
+
703
+ static const struct tegra210_amx_soc_data soc_data_tegra264 = {
704
+ .regmap_conf = & tegra264_amx_regmap_config ,
705
+ .auto_disable = true,
706
+ .max_ch = TEGRA264_AMX_MAX_CHANNEL ,
707
+ .ram_depth = TEGRA264_AMX_RAM_DEPTH ,
708
+ .byte_mask_size = TEGRA264_AMX_BYTE_MASK_COUNT ,
709
+ .reg_offset = TEGRA264_AMX_AUTO_DISABLE_OFFSET ,
710
+ .controls = tegra264_amx_controls ,
711
+ .num_controls = ARRAY_SIZE (tegra264_amx_controls ),
528
712
};
529
713
530
714
static const struct of_device_id tegra210_amx_of_match [] = {
531
715
{ .compatible = "nvidia,tegra210-amx" , .data = & soc_data_tegra210 },
532
716
{ .compatible = "nvidia,tegra194-amx" , .data = & soc_data_tegra194 },
717
+ { .compatible = "nvidia,tegra264-amx" , .data = & soc_data_tegra264 },
533
718
{},
534
719
};
535
720
MODULE_DEVICE_TABLE (of , tegra210_amx_of_match );
@@ -562,6 +747,20 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev)
562
747
563
748
regcache_cache_only (amx -> regmap , true);
564
749
750
+ amx -> map = devm_kzalloc (dev , amx -> soc_data -> ram_depth * sizeof (* amx -> map ),
751
+ GFP_KERNEL );
752
+ if (!amx -> map )
753
+ return - ENOMEM ;
754
+
755
+ amx -> byte_mask = devm_kzalloc (dev ,
756
+ amx -> soc_data -> byte_mask_size * sizeof (* amx -> byte_mask ),
757
+ GFP_KERNEL );
758
+ if (!amx -> byte_mask )
759
+ return - ENOMEM ;
760
+
761
+ tegra210_amx_dais [TEGRA_AMX_OUT_DAI_ID ].capture .channels_max =
762
+ amx -> soc_data -> max_ch ;
763
+
565
764
err = devm_snd_soc_register_component (dev , & tegra210_amx_cmpnt ,
566
765
tegra210_amx_dais ,
567
766
ARRAY_SIZE (tegra210_amx_dais ));
0 commit comments