11// 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.
33// All rights reserved.
44//
55// tegra210_amx.c - Tegra210 AMX driver
@@ -46,21 +46,35 @@ static const struct reg_default tegra210_amx_reg_defaults[] = {
4646 { TEGRA210_AMX_CFG_RAM_CTRL , 0x00004000 },
4747};
4848
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+
4961static void tegra210_amx_write_map_ram (struct tegra210_amx * amx )
5062{
5163 int i ;
5264
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 ,
5466 TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
5567 TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN |
5668 TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE );
5769
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 ,
6072 amx -> map [i ]);
6173
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 ]);
6478}
6579
6680static 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,
157171 cif_conf .audio_bits = audio_bits ;
158172 cif_conf .client_bits = audio_bits ;
159173
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 );
161178
162179 return 0 ;
163180}
@@ -170,9 +187,10 @@ static int tegra210_amx_in_hw_params(struct snd_pcm_substream *substream,
170187
171188 if (amx -> soc_data -> auto_disable ) {
172189 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 ),
174192 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 );
176194 }
177195
178196 return tegra210_amx_set_audio_cif (dai , params ,
@@ -194,14 +212,11 @@ static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
194212 struct soc_mixer_control * mc =
195213 (struct soc_mixer_control * )kcontrol -> private_value ;
196214 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 ;
198216 int reg = mc -> reg ;
199217 int enabled ;
200218
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 ));
205220
206221 /*
207222 * 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,
228243 (struct soc_mixer_control * )kcontrol -> private_value ;
229244 struct snd_soc_component * cmpnt = snd_soc_kcontrol_component (kcontrol );
230245 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 ;
232247 int reg = mc -> reg ;
233248 int value = ucontrol -> value .integer .value [0 ];
234249 unsigned int mask_val = amx -> byte_mask [reg / 32 ];
@@ -418,7 +433,90 @@ static struct snd_kcontrol_new tegra210_amx_controls[] = {
418433 TEGRA210_AMX_BYTE_MAP_CTRL (63 ),
419434};
420435
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+
421518static const struct snd_soc_component_driver tegra210_amx_cmpnt = {
519+ .probe = tegra210_amx_component_probe ,
422520 .dapm_widgets = tegra210_amx_widgets ,
423521 .num_dapm_widgets = ARRAY_SIZE (tegra210_amx_widgets ),
424522 .dapm_routes = tegra210_amx_routes ,
@@ -450,6 +548,22 @@ static bool tegra194_amx_wr_reg(struct device *dev, unsigned int reg)
450548 }
451549}
452550
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+
453567static bool tegra210_amx_rd_reg (struct device * dev , unsigned int reg )
454568{
455569 switch (reg ) {
@@ -470,6 +584,21 @@ static bool tegra194_amx_rd_reg(struct device *dev, unsigned int reg)
470584 }
471585}
472586
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+
473602static bool tegra210_amx_volatile_reg (struct device * dev , unsigned int reg )
474603{
475604 switch (reg ) {
@@ -492,6 +621,29 @@ static bool tegra210_amx_volatile_reg(struct device *dev, unsigned int reg)
492621 return false;
493622}
494623
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+
495647static const struct regmap_config tegra210_amx_regmap_config = {
496648 .reg_bits = 32 ,
497649 .reg_stride = 4 ,
@@ -518,18 +670,51 @@ static const struct regmap_config tegra194_amx_regmap_config = {
518670 .cache_type = REGCACHE_FLAT ,
519671};
520672
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+
521686static const struct tegra210_amx_soc_data soc_data_tegra210 = {
522687 .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 ,
523692};
524693
525694static const struct tegra210_amx_soc_data soc_data_tegra194 = {
526695 .regmap_conf = & tegra194_amx_regmap_config ,
527696 .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 ),
528712};
529713
530714static const struct of_device_id tegra210_amx_of_match [] = {
531715 { .compatible = "nvidia,tegra210-amx" , .data = & soc_data_tegra210 },
532716 { .compatible = "nvidia,tegra194-amx" , .data = & soc_data_tegra194 },
717+ { .compatible = "nvidia,tegra264-amx" , .data = & soc_data_tegra264 },
533718 {},
534719};
535720MODULE_DEVICE_TABLE (of , tegra210_amx_of_match );
@@ -562,6 +747,20 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev)
562747
563748 regcache_cache_only (amx -> regmap , true);
564749
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+
565764 err = devm_snd_soc_register_component (dev , & tegra210_amx_cmpnt ,
566765 tegra210_amx_dais ,
567766 ARRAY_SIZE (tegra210_amx_dais ));
0 commit comments