0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/regmap.h>
0009 #include <linux/delay.h>
0010 #include "mt8183-afe-common.h"
0011 #include "mt8183-interconnection.h"
0012 #include "mt8183-reg.h"
0013
0014 enum {
0015 AUDIO_SDM_LEVEL_MUTE = 0,
0016 AUDIO_SDM_LEVEL_NORMAL = 0x1d,
0017
0018
0019 };
0020
0021 enum {
0022 DELAY_DATA_MISO1 = 0,
0023 DELAY_DATA_MISO2,
0024 };
0025
0026 enum {
0027 MTK_AFE_ADDA_DL_RATE_8K = 0,
0028 MTK_AFE_ADDA_DL_RATE_11K = 1,
0029 MTK_AFE_ADDA_DL_RATE_12K = 2,
0030 MTK_AFE_ADDA_DL_RATE_16K = 3,
0031 MTK_AFE_ADDA_DL_RATE_22K = 4,
0032 MTK_AFE_ADDA_DL_RATE_24K = 5,
0033 MTK_AFE_ADDA_DL_RATE_32K = 6,
0034 MTK_AFE_ADDA_DL_RATE_44K = 7,
0035 MTK_AFE_ADDA_DL_RATE_48K = 8,
0036 MTK_AFE_ADDA_DL_RATE_96K = 9,
0037 MTK_AFE_ADDA_DL_RATE_192K = 10,
0038 };
0039
0040 enum {
0041 MTK_AFE_ADDA_UL_RATE_8K = 0,
0042 MTK_AFE_ADDA_UL_RATE_16K = 1,
0043 MTK_AFE_ADDA_UL_RATE_32K = 2,
0044 MTK_AFE_ADDA_UL_RATE_48K = 3,
0045 MTK_AFE_ADDA_UL_RATE_96K = 4,
0046 MTK_AFE_ADDA_UL_RATE_192K = 5,
0047 MTK_AFE_ADDA_UL_RATE_48K_HD = 6,
0048 };
0049
0050 static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe,
0051 unsigned int rate)
0052 {
0053 switch (rate) {
0054 case 8000:
0055 return MTK_AFE_ADDA_DL_RATE_8K;
0056 case 11025:
0057 return MTK_AFE_ADDA_DL_RATE_11K;
0058 case 12000:
0059 return MTK_AFE_ADDA_DL_RATE_12K;
0060 case 16000:
0061 return MTK_AFE_ADDA_DL_RATE_16K;
0062 case 22050:
0063 return MTK_AFE_ADDA_DL_RATE_22K;
0064 case 24000:
0065 return MTK_AFE_ADDA_DL_RATE_24K;
0066 case 32000:
0067 return MTK_AFE_ADDA_DL_RATE_32K;
0068 case 44100:
0069 return MTK_AFE_ADDA_DL_RATE_44K;
0070 case 48000:
0071 return MTK_AFE_ADDA_DL_RATE_48K;
0072 case 96000:
0073 return MTK_AFE_ADDA_DL_RATE_96K;
0074 case 192000:
0075 return MTK_AFE_ADDA_DL_RATE_192K;
0076 default:
0077 dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
0078 __func__, rate);
0079 return MTK_AFE_ADDA_DL_RATE_48K;
0080 }
0081 }
0082
0083 static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe,
0084 unsigned int rate)
0085 {
0086 switch (rate) {
0087 case 8000:
0088 return MTK_AFE_ADDA_UL_RATE_8K;
0089 case 16000:
0090 return MTK_AFE_ADDA_UL_RATE_16K;
0091 case 32000:
0092 return MTK_AFE_ADDA_UL_RATE_32K;
0093 case 48000:
0094 return MTK_AFE_ADDA_UL_RATE_48K;
0095 case 96000:
0096 return MTK_AFE_ADDA_UL_RATE_96K;
0097 case 192000:
0098 return MTK_AFE_ADDA_UL_RATE_192K;
0099 default:
0100 dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
0101 __func__, rate);
0102 return MTK_AFE_ADDA_UL_RATE_48K;
0103 }
0104 }
0105
0106
0107 static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {
0108 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3, I_DL1_CH1, 1, 0),
0109 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN3, I_DL2_CH1, 1, 0),
0110 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN3, I_DL3_CH1, 1, 0),
0111 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN3,
0112 I_ADDA_UL_CH2, 1, 0),
0113 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN3,
0114 I_ADDA_UL_CH1, 1, 0),
0115 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN3,
0116 I_PCM_1_CAP_CH1, 1, 0),
0117 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN3,
0118 I_PCM_2_CAP_CH1, 1, 0),
0119 };
0120
0121 static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {
0122 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN4, I_DL1_CH1, 1, 0),
0123 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN4, I_DL1_CH2, 1, 0),
0124 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN4, I_DL2_CH1, 1, 0),
0125 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN4, I_DL2_CH2, 1, 0),
0126 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN4, I_DL3_CH1, 1, 0),
0127 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN4, I_DL3_CH2, 1, 0),
0128 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN4,
0129 I_ADDA_UL_CH2, 1, 0),
0130 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN4,
0131 I_ADDA_UL_CH1, 1, 0),
0132 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN4,
0133 I_PCM_1_CAP_CH1, 1, 0),
0134 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN4,
0135 I_PCM_2_CAP_CH1, 1, 0),
0136 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN4,
0137 I_PCM_1_CAP_CH2, 1, 0),
0138 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN4,
0139 I_PCM_2_CAP_CH2, 1, 0),
0140 };
0141
0142 static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
0143 struct snd_kcontrol *kcontrol,
0144 int event)
0145 {
0146 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
0147 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0148 struct mt8183_afe_private *afe_priv = afe->platform_priv;
0149
0150 dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
0151 __func__, w->name, event);
0152
0153 switch (event) {
0154 case SND_SOC_DAPM_PRE_PMU:
0155
0156 if (afe_priv->mtkaif_dmic) {
0157
0158 regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,
0159 0x1, 0x1);
0160
0161
0162 regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,
0163 0x0, 0xf << 20);
0164 regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
0165 0x0, 0x1 << 5);
0166 regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
0167 0x0, 0x3 << 14);
0168
0169
0170 regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
0171 0x1 << 1, 0x1 << 1);
0172 regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
0173 0x3 << 21, 0x3 << 21);
0174 }
0175 break;
0176 case SND_SOC_DAPM_POST_PMD:
0177
0178 usleep_range(125, 135);
0179 break;
0180 default:
0181 break;
0182 }
0183
0184 return 0;
0185 }
0186
0187
0188 static const char * const mt8183_adda_off_on_str[] = {
0189 "Off", "On"
0190 };
0191
0192 static const struct soc_enum mt8183_adda_enum[] = {
0193 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8183_adda_off_on_str),
0194 mt8183_adda_off_on_str),
0195 };
0196
0197 static int mt8183_adda_dmic_get(struct snd_kcontrol *kcontrol,
0198 struct snd_ctl_elem_value *ucontrol)
0199 {
0200 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0201 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0202 struct mt8183_afe_private *afe_priv = afe->platform_priv;
0203
0204 ucontrol->value.integer.value[0] = afe_priv->mtkaif_dmic;
0205
0206 return 0;
0207 }
0208
0209 static int mt8183_adda_dmic_set(struct snd_kcontrol *kcontrol,
0210 struct snd_ctl_elem_value *ucontrol)
0211 {
0212 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0213 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0214 struct mt8183_afe_private *afe_priv = afe->platform_priv;
0215 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
0216
0217 if (ucontrol->value.enumerated.item[0] >= e->items)
0218 return -EINVAL;
0219
0220 afe_priv->mtkaif_dmic = ucontrol->value.integer.value[0];
0221
0222 dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_dmic %d\n",
0223 __func__, kcontrol->id.name, afe_priv->mtkaif_dmic);
0224
0225 return 0;
0226 }
0227
0228 static const struct snd_kcontrol_new mtk_adda_controls[] = {
0229 SOC_ENUM_EXT("MTKAIF_DMIC", mt8183_adda_enum[0],
0230 mt8183_adda_dmic_get, mt8183_adda_dmic_set),
0231 };
0232
0233 enum {
0234 SUPPLY_SEQ_ADDA_AFE_ON,
0235 SUPPLY_SEQ_ADDA_DL_ON,
0236 SUPPLY_SEQ_ADDA_UL_ON,
0237 };
0238
0239 static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
0240
0241 SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,
0242 mtk_adda_dl_ch1_mix,
0243 ARRAY_SIZE(mtk_adda_dl_ch1_mix)),
0244 SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,
0245 mtk_adda_dl_ch2_mix,
0246 ARRAY_SIZE(mtk_adda_dl_ch2_mix)),
0247
0248 SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
0249 AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0,
0250 NULL, 0),
0251
0252 SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,
0253 AFE_ADDA_DL_SRC2_CON0,
0254 DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0,
0255 NULL, 0),
0256
0257 SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
0258 AFE_ADDA_UL_SRC_CON0,
0259 UL_SRC_ON_TMP_CTL_SFT, 0,
0260 mtk_adda_ul_event,
0261 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0262
0263 SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_clk"),
0264 SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_predis_clk"),
0265 SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_clk"),
0266 SND_SOC_DAPM_CLOCK_SUPPLY("mtkaif_26m_clk"),
0267 };
0268
0269 static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
0270
0271 {"ADDA_DL_CH1", "DL1_CH1", "DL1"},
0272 {"ADDA_DL_CH2", "DL1_CH1", "DL1"},
0273 {"ADDA_DL_CH2", "DL1_CH2", "DL1"},
0274
0275 {"ADDA_DL_CH1", "DL2_CH1", "DL2"},
0276 {"ADDA_DL_CH2", "DL2_CH1", "DL2"},
0277 {"ADDA_DL_CH2", "DL2_CH2", "DL2"},
0278
0279 {"ADDA_DL_CH1", "DL3_CH1", "DL3"},
0280 {"ADDA_DL_CH2", "DL3_CH1", "DL3"},
0281 {"ADDA_DL_CH2", "DL3_CH2", "DL3"},
0282
0283 {"ADDA Playback", NULL, "ADDA_DL_CH1"},
0284 {"ADDA Playback", NULL, "ADDA_DL_CH2"},
0285
0286
0287 {"ADDA Playback", NULL, "ADDA Enable"},
0288 {"ADDA Playback", NULL, "ADDA Playback Enable"},
0289 {"ADDA Capture", NULL, "ADDA Enable"},
0290 {"ADDA Capture", NULL, "ADDA Capture Enable"},
0291
0292
0293 {"ADDA Playback", NULL, "mtkaif_26m_clk"},
0294 {"ADDA Playback", NULL, "aud_dac_clk"},
0295 {"ADDA Playback", NULL, "aud_dac_predis_clk"},
0296
0297 {"ADDA Capture", NULL, "mtkaif_26m_clk"},
0298 {"ADDA Capture", NULL, "aud_adc_clk"},
0299 };
0300
0301 static int set_mtkaif_rx(struct mtk_base_afe *afe)
0302 {
0303 struct mt8183_afe_private *afe_priv = afe->platform_priv;
0304 int delay_data;
0305 int delay_cycle;
0306
0307 switch (afe_priv->mtkaif_protocol) {
0308 case MT8183_MTKAIF_PROTOCOL_2_CLK_P2:
0309 regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x38);
0310 regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x39);
0311
0312 regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
0313 0x80010000);
0314
0315 if (afe_priv->mtkaif_phase_cycle[0] >=
0316 afe_priv->mtkaif_phase_cycle[1]) {
0317 delay_data = DELAY_DATA_MISO1;
0318 delay_cycle = afe_priv->mtkaif_phase_cycle[0] -
0319 afe_priv->mtkaif_phase_cycle[1];
0320 } else {
0321 delay_data = DELAY_DATA_MISO2;
0322 delay_cycle = afe_priv->mtkaif_phase_cycle[1] -
0323 afe_priv->mtkaif_phase_cycle[0];
0324 }
0325
0326 regmap_update_bits(afe->regmap,
0327 AFE_ADDA_MTKAIF_RX_CFG2,
0328 MTKAIF_RXIF_DELAY_DATA_MASK_SFT,
0329 delay_data << MTKAIF_RXIF_DELAY_DATA_SFT);
0330
0331 regmap_update_bits(afe->regmap,
0332 AFE_ADDA_MTKAIF_RX_CFG2,
0333 MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT,
0334 delay_cycle << MTKAIF_RXIF_DELAY_CYCLE_SFT);
0335 break;
0336 case MT8183_MTKAIF_PROTOCOL_2:
0337 regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31);
0338 regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,
0339 0x00010000);
0340 break;
0341 case MT8183_MTKAIF_PROTOCOL_1:
0342 regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31);
0343 regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x0);
0344 break;
0345 default:
0346 break;
0347 }
0348
0349 return 0;
0350 }
0351
0352
0353 static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
0354 struct snd_pcm_hw_params *params,
0355 struct snd_soc_dai *dai)
0356 {
0357 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
0358 unsigned int rate = params_rate(params);
0359
0360 dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
0361 __func__, dai->id, substream->stream, rate);
0362
0363 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0364 unsigned int dl_src2_con0 = 0;
0365 unsigned int dl_src2_con1 = 0;
0366
0367
0368 regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0);
0369 regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0);
0370
0371
0372 dl_src2_con0 = adda_dl_rate_transform(afe, rate) << 28;
0373
0374
0375 switch (rate) {
0376 case 192000:
0377 dl_src2_con0 |= (0x1 << 24);
0378 dl_src2_con0 |= 1 << 14;
0379 break;
0380 case 96000:
0381 dl_src2_con0 |= (0x2 << 24);
0382 dl_src2_con0 |= 1 << 14;
0383 break;
0384 default:
0385 dl_src2_con0 |= (0x3 << 24);
0386 break;
0387 }
0388
0389
0390 dl_src2_con0 |= (0x03 << 11);
0391
0392
0393 if (rate == 8000 || rate == 16000)
0394 dl_src2_con0 |= 0x01 << 5;
0395
0396
0397 dl_src2_con1 = 0xf74f0000;
0398
0399
0400 dl_src2_con0 = dl_src2_con0 | (0x01 << 1);
0401
0402 regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON0, dl_src2_con0);
0403 regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON1, dl_src2_con1);
0404
0405
0406 regmap_update_bits(afe->regmap,
0407 AFE_ADDA_DL_SDM_DCCOMP_CON,
0408 ATTGAIN_CTL_MASK_SFT,
0409 AUDIO_SDM_LEVEL_NORMAL << ATTGAIN_CTL_SFT);
0410 } else {
0411 unsigned int voice_mode = 0;
0412 unsigned int ul_src_con0 = 0;
0413
0414
0415 set_mtkaif_rx(afe);
0416
0417
0418 regmap_update_bits(afe->regmap,
0419 AFE_ADDA_TOP_CON0,
0420 0x1 << 0,
0421 0x0 << 0);
0422
0423 voice_mode = adda_ul_rate_transform(afe, rate);
0424
0425 ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
0426
0427
0428 ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
0429 UL_IIR_ON_TMP_CTL_MASK_SFT;
0430
0431
0432 regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_02_01, 0x00000000);
0433 regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_04_03, 0x00003FB8);
0434 regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_06_05, 0x3FB80000);
0435 regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_08_07, 0x3FB80000);
0436 regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_10_09, 0x0000C048);
0437
0438 regmap_write(afe->regmap, AFE_ADDA_UL_SRC_CON0, ul_src_con0);
0439
0440
0441 regmap_update_bits(afe->regmap,
0442 AFE_ADDA_MTKAIF_RX_CFG0,
0443 0x1 << 0,
0444 0x0 << 0);
0445 }
0446
0447 return 0;
0448 }
0449
0450 static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
0451 .hw_params = mtk_dai_adda_hw_params,
0452 };
0453
0454
0455 #define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
0456 SNDRV_PCM_RATE_96000 |\
0457 SNDRV_PCM_RATE_192000)
0458
0459 #define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
0460 SNDRV_PCM_RATE_16000 |\
0461 SNDRV_PCM_RATE_32000 |\
0462 SNDRV_PCM_RATE_48000)
0463
0464 #define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
0465 SNDRV_PCM_FMTBIT_S24_LE |\
0466 SNDRV_PCM_FMTBIT_S32_LE)
0467
0468 static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
0469 {
0470 .name = "ADDA",
0471 .id = MT8183_DAI_ADDA,
0472 .playback = {
0473 .stream_name = "ADDA Playback",
0474 .channels_min = 1,
0475 .channels_max = 2,
0476 .rates = MTK_ADDA_PLAYBACK_RATES,
0477 .formats = MTK_ADDA_FORMATS,
0478 },
0479 .capture = {
0480 .stream_name = "ADDA Capture",
0481 .channels_min = 1,
0482 .channels_max = 2,
0483 .rates = MTK_ADDA_CAPTURE_RATES,
0484 .formats = MTK_ADDA_FORMATS,
0485 },
0486 .ops = &mtk_dai_adda_ops,
0487 },
0488 };
0489
0490 int mt8183_dai_adda_register(struct mtk_base_afe *afe)
0491 {
0492 struct mtk_base_afe_dai *dai;
0493
0494 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
0495 if (!dai)
0496 return -ENOMEM;
0497
0498 list_add(&dai->list, &afe->sub_dais);
0499
0500 dai->dai_drivers = mtk_dai_adda_driver;
0501 dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
0502
0503 dai->controls = mtk_adda_controls;
0504 dai->num_controls = ARRAY_SIZE(mtk_adda_controls);
0505 dai->dapm_widgets = mtk_dai_adda_widgets;
0506 dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
0507 dai->dapm_routes = mtk_dai_adda_routes;
0508 dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
0509 return 0;
0510 }