Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/sound/soc/mediatek/mt8183/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 16 kB image not shown  

Quelle  mt8183-afe-clk.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
//
// mt8183-afe-clk.c  --  Mediatek 8183 afe clock ctrl
//
// Copyright (c) 2018 MediaTek Inc.
// Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>

#include <linux/clk.h>

#include "mt8183-afe-common.h"
#include "mt8183-afe-clk.h"
#include "mt8183-reg.h"

enum {
 CLK_AFE = 0,
 CLK_TML,
 CLK_APLL22M,
 CLK_APLL24M,
 CLK_APLL1_TUNER,
 CLK_APLL2_TUNER,
 CLK_I2S1_BCLK_SW,
 CLK_I2S2_BCLK_SW,
 CLK_I2S3_BCLK_SW,
 CLK_I2S4_BCLK_SW,
 CLK_INFRA_SYS_AUDIO,
 CLK_MUX_AUDIO,
 CLK_MUX_AUDIOINTBUS,
 CLK_TOP_SYSPLL_D2_D4,
 /* apll related mux */
 CLK_TOP_MUX_AUD_1,
 CLK_TOP_APLL1_CK,
 CLK_TOP_MUX_AUD_2,
 CLK_TOP_APLL2_CK,
 CLK_TOP_MUX_AUD_ENG1,
 CLK_TOP_APLL1_D8,
 CLK_TOP_MUX_AUD_ENG2,
 CLK_TOP_APLL2_D8,
 CLK_TOP_I2S0_M_SEL,
 CLK_TOP_I2S1_M_SEL,
 CLK_TOP_I2S2_M_SEL,
 CLK_TOP_I2S3_M_SEL,
 CLK_TOP_I2S4_M_SEL,
 CLK_TOP_I2S5_M_SEL,
 CLK_TOP_APLL12_DIV0,
 CLK_TOP_APLL12_DIV1,
 CLK_TOP_APLL12_DIV2,
 CLK_TOP_APLL12_DIV3,
 CLK_TOP_APLL12_DIV4,
 CLK_TOP_APLL12_DIVB,
 CLK_CLK26M,
 CLK_NUM
};

static const char *aud_clks[CLK_NUM] = {
 [CLK_AFE] = "aud_afe_clk",
 [CLK_TML] = "aud_tml_clk",
 [CLK_APLL22M] = "aud_apll22m_clk",
 [CLK_APLL24M] = "aud_apll24m_clk",
 [CLK_APLL1_TUNER] = "aud_apll1_tuner_clk",
 [CLK_APLL2_TUNER] = "aud_apll2_tuner_clk",
 [CLK_I2S1_BCLK_SW] = "aud_i2s1_bclk_sw",
 [CLK_I2S2_BCLK_SW] = "aud_i2s2_bclk_sw",
 [CLK_I2S3_BCLK_SW] = "aud_i2s3_bclk_sw",
 [CLK_I2S4_BCLK_SW] = "aud_i2s4_bclk_sw",
 [CLK_INFRA_SYS_AUDIO] = "aud_infra_clk",
 [CLK_MUX_AUDIO] = "top_mux_audio",
 [CLK_MUX_AUDIOINTBUS] = "top_mux_aud_intbus",
 [CLK_TOP_SYSPLL_D2_D4] = "top_syspll_d2_d4",
 [CLK_TOP_MUX_AUD_1] = "top_mux_aud_1",
 [CLK_TOP_APLL1_CK] = "top_apll1_ck",
 [CLK_TOP_MUX_AUD_2] = "top_mux_aud_2",
 [CLK_TOP_APLL2_CK] = "top_apll2_ck",
 [CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1",
 [CLK_TOP_APLL1_D8] = "top_apll1_d8",
 [CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2",
 [CLK_TOP_APLL2_D8] = "top_apll2_d8",
 [CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel",
 [CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel",
 [CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel",
 [CLK_TOP_I2S3_M_SEL] = "top_i2s3_m_sel",
 [CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel",
 [CLK_TOP_I2S5_M_SEL] = "top_i2s5_m_sel",
 [CLK_TOP_APLL12_DIV0] = "top_apll12_div0",
 [CLK_TOP_APLL12_DIV1] = "top_apll12_div1",
 [CLK_TOP_APLL12_DIV2] = "top_apll12_div2",
 [CLK_TOP_APLL12_DIV3] = "top_apll12_div3",
 [CLK_TOP_APLL12_DIV4] = "top_apll12_div4",
 [CLK_TOP_APLL12_DIVB] = "top_apll12_divb",
 [CLK_CLK26M] = "top_clk26m_clk",
};

int mt8183_init_clock(struct mtk_base_afe *afe)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int i;

 afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
         GFP_KERNEL);
 if (!afe_priv->clk)
  return -ENOMEM;

 for (i = 0; i < CLK_NUM; i++) {
  afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
  if (IS_ERR(afe_priv->clk[i])) {
   dev_err(afe->dev, "%s(), devm_clk_get %s fail, ret %ld\n",
    __func__, aud_clks[i],
    PTR_ERR(afe_priv->clk[i]));
   return PTR_ERR(afe_priv->clk[i]);
  }
 }

 return 0;
}

int mt8183_afe_enable_clock(struct mtk_base_afe *afe)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int ret;

 ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
 if (ret) {
  dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret);
  goto CLK_INFRA_SYS_AUDIO_ERR;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]);
 if (ret) {
  dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_MUX_AUDIO], ret);
  goto CLK_MUX_AUDIO_ERR;
 }

 ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO],
        afe_priv->clk[CLK_CLK26M]);
 if (ret) {
  dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
   __func__, aud_clks[CLK_MUX_AUDIO],
   aud_clks[CLK_CLK26M], ret);
  goto CLK_MUX_AUDIO_ERR;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
 if (ret) {
  dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret);
  goto CLK_MUX_AUDIO_INTBUS_ERR;
 }

 ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS],
        afe_priv->clk[CLK_TOP_SYSPLL_D2_D4]);
 if (ret) {
  dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
   __func__, aud_clks[CLK_MUX_AUDIOINTBUS],
   aud_clks[CLK_TOP_SYSPLL_D2_D4], ret);
  goto CLK_MUX_AUDIO_INTBUS_ERR;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_AFE], ret);
  goto CLK_AFE_ERR;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_I2S1_BCLK_SW]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_I2S1_BCLK_SW], ret);
  goto CLK_I2S1_BCLK_SW_ERR;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_I2S2_BCLK_SW]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_I2S2_BCLK_SW], ret);
  goto CLK_I2S2_BCLK_SW_ERR;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_I2S3_BCLK_SW]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_I2S3_BCLK_SW], ret);
  goto CLK_I2S3_BCLK_SW_ERR;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_I2S4_BCLK_SW]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_I2S4_BCLK_SW], ret);
  goto CLK_I2S4_BCLK_SW_ERR;
 }

 return 0;

CLK_I2S4_BCLK_SW_ERR:
 clk_disable_unprepare(afe_priv->clk[CLK_I2S3_BCLK_SW]);
CLK_I2S3_BCLK_SW_ERR:
 clk_disable_unprepare(afe_priv->clk[CLK_I2S2_BCLK_SW]);
CLK_I2S2_BCLK_SW_ERR:
 clk_disable_unprepare(afe_priv->clk[CLK_I2S1_BCLK_SW]);
CLK_I2S1_BCLK_SW_ERR:
 clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
CLK_AFE_ERR:
 clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
CLK_MUX_AUDIO_INTBUS_ERR:
 clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
CLK_MUX_AUDIO_ERR:
 clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);
CLK_INFRA_SYS_AUDIO_ERR:
 return ret;
}

int mt8183_afe_disable_clock(struct mtk_base_afe *afe)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;

 clk_disable_unprepare(afe_priv->clk[CLK_I2S4_BCLK_SW]);
 clk_disable_unprepare(afe_priv->clk[CLK_I2S3_BCLK_SW]);
 clk_disable_unprepare(afe_priv->clk[CLK_I2S2_BCLK_SW]);
 clk_disable_unprepare(afe_priv->clk[CLK_I2S1_BCLK_SW]);
 clk_disable_unprepare(afe_priv->clk[CLK_AFE]);
 clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]);
 clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]);
 clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]);

 return 0;
}

/* apll */
static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int ret;

 if (enable) {
  ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
  if (ret) {
   dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_1], ret);
   goto ERR_ENABLE_CLK_TOP_MUX_AUD_1;
  }
  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
         afe_priv->clk[CLK_TOP_APLL1_CK]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_1],
    aud_clks[CLK_TOP_APLL1_CK], ret);
   goto ERR_SELECT_CLK_TOP_MUX_AUD_1;
  }

  /* 180.6336 / 8 = 22.5792MHz */
  ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
  if (ret) {
   dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], ret);
   goto ERR_ENABLE_CLK_TOP_MUX_AUD_ENG1;
  }
  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
         afe_priv->clk[CLK_TOP_APLL1_D8]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
    aud_clks[CLK_TOP_APLL1_D8], ret);
   goto ERR_SELECT_CLK_TOP_MUX_AUD_ENG1;
  }
 } else {
  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
         afe_priv->clk[CLK_CLK26M]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1],
    aud_clks[CLK_CLK26M], ret);
   goto EXIT;
  }
  clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);

  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
         afe_priv->clk[CLK_CLK26M]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_1],
    aud_clks[CLK_CLK26M], ret);
   goto EXIT;
  }
  clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
 }

 return 0;

ERR_SELECT_CLK_TOP_MUX_AUD_ENG1:
 clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1],
         afe_priv->clk[CLK_CLK26M]);
 clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]);
ERR_ENABLE_CLK_TOP_MUX_AUD_ENG1:
ERR_SELECT_CLK_TOP_MUX_AUD_1:
 clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1],
         afe_priv->clk[CLK_CLK26M]);
 clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_1]);
ERR_ENABLE_CLK_TOP_MUX_AUD_1:
EXIT:
 return ret;
}

static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int ret;

 if (enable) {
  ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
  if (ret) {
   dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_2], ret);
   goto ERR_ENABLE_CLK_TOP_MUX_AUD_2;
  }
  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
         afe_priv->clk[CLK_TOP_APLL2_CK]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_2],
    aud_clks[CLK_TOP_APLL2_CK], ret);
   goto ERR_SELECT_CLK_TOP_MUX_AUD_2;
  }

  /* 196.608 / 8 = 24.576MHz */
  ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
  if (ret) {
   dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], ret);
   goto ERR_ENABLE_CLK_TOP_MUX_AUD_ENG2;
  }
  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
         afe_priv->clk[CLK_TOP_APLL2_D8]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
    aud_clks[CLK_TOP_APLL2_D8], ret);
   goto ERR_SELECT_CLK_TOP_MUX_AUD_ENG2;
  }
 } else {
  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
         afe_priv->clk[CLK_CLK26M]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2],
    aud_clks[CLK_CLK26M], ret);
   goto EXIT;
  }
  clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);

  ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
         afe_priv->clk[CLK_CLK26M]);
  if (ret) {
   dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[CLK_TOP_MUX_AUD_2],
    aud_clks[CLK_CLK26M], ret);
   goto EXIT;
  }
  clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
 }

 return 0;

ERR_SELECT_CLK_TOP_MUX_AUD_ENG2:
 clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2],
         afe_priv->clk[CLK_CLK26M]);
 clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]);
ERR_ENABLE_CLK_TOP_MUX_AUD_ENG2:
ERR_SELECT_CLK_TOP_MUX_AUD_2:
 clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2],
         afe_priv->clk[CLK_CLK26M]);
 clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_2]);
ERR_ENABLE_CLK_TOP_MUX_AUD_2:
EXIT:
 return ret;
}

int mt8183_apll1_enable(struct mtk_base_afe *afe)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int ret;

 /* setting for APLL */
 apll1_mux_setting(afe, true);

 ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_APLL22M], ret);
  goto ERR_CLK_APLL22M;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_APLL1_TUNER], ret);
  goto ERR_CLK_APLL1_TUNER;
 }

 regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
      0x0000FFF7, 0x00000832);
 regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1);

 regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
      AFE_22M_ON_MASK_SFT,
      0x1 << AFE_22M_ON_SFT);

 return 0;

ERR_CLK_APLL1_TUNER:
 clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);
ERR_CLK_APLL22M:
 return ret;
}

void mt8183_apll1_disable(struct mtk_base_afe *afe)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;

 regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
      AFE_22M_ON_MASK_SFT,
      0x0 << AFE_22M_ON_SFT);

 regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x0);

 clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]);
 clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]);

 apll1_mux_setting(afe, false);
}

int mt8183_apll2_enable(struct mtk_base_afe *afe)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int ret;

 /* setting for APLL */
 apll2_mux_setting(afe, true);

 ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_APLL24M], ret);
  goto ERR_CLK_APLL24M;
 }

 ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]);
 if (ret) {
  dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[CLK_APLL2_TUNER], ret);
  goto ERR_CLK_APLL2_TUNER;
 }

 regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
      0x0000FFF7, 0x00000634);
 regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1);

 regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
      AFE_24M_ON_MASK_SFT,
      0x1 << AFE_24M_ON_SFT);

 return 0;

ERR_CLK_APLL2_TUNER:
 clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);
ERR_CLK_APLL24M:
 return ret;
}

void mt8183_apll2_disable(struct mtk_base_afe *afe)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;

 regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
      AFE_24M_ON_MASK_SFT,
      0x0 << AFE_24M_ON_SFT);

 regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x0);

 clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]);
 clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]);

 apll2_mux_setting(afe, false);
}

int mt8183_get_apll_rate(struct mtk_base_afe *afe, int apll)
{
 return (apll == MT8183_APLL1) ? 180633600 : 196608000;
}

int mt8183_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
{
 return ((rate % 8000) == 0) ? MT8183_APLL2 : MT8183_APLL1;
}

int mt8183_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
{
 if (strcmp(name, APLL1_W_NAME) == 0)
  return MT8183_APLL1;
 else
  return MT8183_APLL2;
}

/* mck */
struct mt8183_mck_div {
 int m_sel_id;
 int div_clk_id;
};

static const struct mt8183_mck_div mck_div[MT8183_MCK_NUM] = {
 [MT8183_I2S0_MCK] = {
  .m_sel_id = CLK_TOP_I2S0_M_SEL,
  .div_clk_id = CLK_TOP_APLL12_DIV0,
 },
 [MT8183_I2S1_MCK] = {
  .m_sel_id = CLK_TOP_I2S1_M_SEL,
  .div_clk_id = CLK_TOP_APLL12_DIV1,
 },
 [MT8183_I2S2_MCK] = {
  .m_sel_id = CLK_TOP_I2S2_M_SEL,
  .div_clk_id = CLK_TOP_APLL12_DIV2,
 },
 [MT8183_I2S3_MCK] = {
  .m_sel_id = CLK_TOP_I2S3_M_SEL,
  .div_clk_id = CLK_TOP_APLL12_DIV3,
 },
 [MT8183_I2S4_MCK] = {
  .m_sel_id = CLK_TOP_I2S4_M_SEL,
  .div_clk_id = CLK_TOP_APLL12_DIV4,
 },
 [MT8183_I2S4_BCK] = {
  .m_sel_id = -1,
  .div_clk_id = CLK_TOP_APLL12_DIVB,
 },
 [MT8183_I2S5_MCK] = {
  .m_sel_id = -1,
  .div_clk_id = -1,
 },
};

int mt8183_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int apll = mt8183_get_apll_by_rate(afe, rate);
 int apll_clk_id = apll == MT8183_APLL1 ?
     CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2;
 int m_sel_id = mck_div[mck_id].m_sel_id;
 int div_clk_id = mck_div[mck_id].div_clk_id;
 int ret;

 /* i2s5 mck not support */
 if (mck_id == MT8183_I2S5_MCK)
  return 0;

 /* select apll */
 if (m_sel_id >= 0) {
  ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
  if (ret) {
   dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
    __func__, aud_clks[m_sel_id], ret);
   goto ERR_ENABLE_MCLK;
  }
  ret = clk_set_parent(afe_priv->clk[m_sel_id],
         afe_priv->clk[apll_clk_id]);
  if (ret) {
   dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
    __func__, aud_clks[m_sel_id],
    aud_clks[apll_clk_id], ret);
   goto ERR_SELECT_MCLK;
  }
 }

 /* enable div, set rate */
 ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
 if (ret) {
  dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
   __func__, aud_clks[div_clk_id], ret);
  goto ERR_ENABLE_MCLK_DIV;
 }
 ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
 if (ret) {
  dev_err(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n",
   __func__, aud_clks[div_clk_id],
   rate, ret);
  goto ERR_SET_MCLK_RATE;
 }

 return 0;

ERR_SET_MCLK_RATE:
 clk_disable_unprepare(afe_priv->clk[div_clk_id]);
ERR_ENABLE_MCLK_DIV:
ERR_SELECT_MCLK:
 if (m_sel_id >= 0)
  clk_disable_unprepare(afe_priv->clk[m_sel_id]);
ERR_ENABLE_MCLK:
 return ret;
}

void mt8183_mck_disable(struct mtk_base_afe *afe, int mck_id)
{
 struct mt8183_afe_private *afe_priv = afe->platform_priv;
 int m_sel_id = mck_div[mck_id].m_sel_id;
 int div_clk_id = mck_div[mck_id].div_clk_id;

 /* i2s5 mck not support */
 if (mck_id == MT8183_I2S5_MCK)
  return;

 clk_disable_unprepare(afe_priv->clk[div_clk_id]);
 if (m_sel_id >= 0)
  clk_disable_unprepare(afe_priv->clk[m_sel_id]);
}

Messung V0.5
C=95 H=97 G=95

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.