0001
0002
0003
0004
0005
0006 #include <linux/bitfield.h>
0007 #include <linux/clk.h>
0008 #include <sound/pcm_params.h>
0009 #include <sound/soc.h>
0010 #include <sound/soc-dai.h>
0011
0012 #include "aiu.h"
0013
0014 #define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0)
0015 #define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5)
0016 #define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9)
0017 #define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11)
0018 #define AIU_RST_SOFT_I2S_FAST BIT(0)
0019
0020 #define AIU_I2S_DAC_CFG_MSB_FIRST BIT(2)
0021 #define AIU_CLK_CTRL_I2S_DIV_EN BIT(0)
0022 #define AIU_CLK_CTRL_I2S_DIV GENMASK(3, 2)
0023 #define AIU_CLK_CTRL_AOCLK_INVERT BIT(6)
0024 #define AIU_CLK_CTRL_LRCLK_INVERT BIT(7)
0025 #define AIU_CLK_CTRL_LRCLK_SKEW GENMASK(9, 8)
0026 #define AIU_CLK_CTRL_MORE_HDMI_AMCLK BIT(6)
0027 #define AIU_CLK_CTRL_MORE_I2S_DIV GENMASK(5, 0)
0028 #define AIU_CODEC_DAC_LRCLK_CTRL_DIV GENMASK(11, 0)
0029
0030 static void aiu_encoder_i2s_divider_enable(struct snd_soc_component *component,
0031 bool enable)
0032 {
0033 snd_soc_component_update_bits(component, AIU_CLK_CTRL,
0034 AIU_CLK_CTRL_I2S_DIV_EN,
0035 enable ? AIU_CLK_CTRL_I2S_DIV_EN : 0);
0036 }
0037
0038 static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component,
0039 struct snd_pcm_hw_params *params)
0040 {
0041
0042 unsigned int desc = AIU_I2S_SOURCE_DESC_MODE_SPLIT;
0043
0044
0045 snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST);
0046 snd_soc_component_read(component, AIU_I2S_SYNC);
0047
0048 switch (params_physical_width(params)) {
0049 case 16:
0050 break;
0051
0052 case 32:
0053 desc |= (AIU_I2S_SOURCE_DESC_MODE_24BIT |
0054 AIU_I2S_SOURCE_DESC_MODE_32BIT);
0055 break;
0056
0057 default:
0058 return -EINVAL;
0059 }
0060
0061 switch (params_channels(params)) {
0062 case 2:
0063 break;
0064 case 8:
0065 desc |= AIU_I2S_SOURCE_DESC_MODE_8CH;
0066 break;
0067 default:
0068 return -EINVAL;
0069 }
0070
0071 snd_soc_component_update_bits(component, AIU_I2S_SOURCE_DESC,
0072 AIU_I2S_SOURCE_DESC_MODE_8CH |
0073 AIU_I2S_SOURCE_DESC_MODE_24BIT |
0074 AIU_I2S_SOURCE_DESC_MODE_32BIT |
0075 AIU_I2S_SOURCE_DESC_MODE_SPLIT,
0076 desc);
0077
0078 return 0;
0079 }
0080
0081 static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *component,
0082 struct snd_pcm_hw_params *params,
0083 unsigned int bs)
0084 {
0085 switch (bs) {
0086 case 1:
0087 case 2:
0088 case 4:
0089 case 8:
0090
0091 break;
0092
0093 default:
0094 dev_err(component->dev, "Unsupported i2s divider: %u\n", bs);
0095 return -EINVAL;
0096 }
0097
0098 snd_soc_component_update_bits(component, AIU_CLK_CTRL,
0099 AIU_CLK_CTRL_I2S_DIV,
0100 FIELD_PREP(AIU_CLK_CTRL_I2S_DIV,
0101 __ffs(bs)));
0102
0103 snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE,
0104 AIU_CLK_CTRL_MORE_I2S_DIV,
0105 FIELD_PREP(AIU_CLK_CTRL_MORE_I2S_DIV,
0106 0));
0107
0108 return 0;
0109 }
0110
0111 static int aiu_encoder_i2s_set_more_div(struct snd_soc_component *component,
0112 struct snd_pcm_hw_params *params,
0113 unsigned int bs)
0114 {
0115
0116
0117
0118
0119
0120
0121
0122 if (params_width(params) == 16 && params_channels(params) == 8) {
0123 if (bs % 2) {
0124 dev_err(component->dev,
0125 "Cannot increase i2s divider by 50%%\n");
0126 return -EINVAL;
0127 }
0128 bs += bs / 2;
0129 }
0130
0131
0132 snd_soc_component_update_bits(component, AIU_CLK_CTRL,
0133 AIU_CLK_CTRL_I2S_DIV,
0134 FIELD_PREP(AIU_CLK_CTRL_I2S_DIV, 0));
0135
0136 snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE,
0137 AIU_CLK_CTRL_MORE_I2S_DIV,
0138 FIELD_PREP(AIU_CLK_CTRL_MORE_I2S_DIV,
0139 bs - 1));
0140
0141 return 0;
0142 }
0143
0144 static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component,
0145 struct snd_pcm_hw_params *params)
0146 {
0147 struct aiu *aiu = snd_soc_component_get_drvdata(component);
0148 unsigned int srate = params_rate(params);
0149 unsigned int fs, bs;
0150 int ret;
0151
0152
0153 fs = DIV_ROUND_CLOSEST(clk_get_rate(aiu->i2s.clks[MCLK].clk), srate);
0154
0155 if (fs % 64)
0156 return -EINVAL;
0157
0158
0159 snd_soc_component_update_bits(component, AIU_I2S_DAC_CFG,
0160 AIU_I2S_DAC_CFG_MSB_FIRST,
0161 AIU_I2S_DAC_CFG_MSB_FIRST);
0162
0163
0164 snd_soc_component_update_bits(component, AIU_CODEC_DAC_LRCLK_CTRL,
0165 AIU_CODEC_DAC_LRCLK_CTRL_DIV,
0166 FIELD_PREP(AIU_CODEC_DAC_LRCLK_CTRL_DIV,
0167 64 - 1));
0168
0169 bs = fs / 64;
0170
0171 if (aiu->platform->has_clk_ctrl_more_i2s_div)
0172 ret = aiu_encoder_i2s_set_more_div(component, params, bs);
0173 else
0174 ret = aiu_encoder_i2s_set_legacy_div(component, params, bs);
0175
0176 if (ret)
0177 return ret;
0178
0179
0180 snd_soc_component_update_bits(component, AIU_CLK_CTRL_MORE,
0181 AIU_CLK_CTRL_MORE_HDMI_AMCLK,
0182 AIU_CLK_CTRL_MORE_HDMI_AMCLK);
0183
0184 return 0;
0185 }
0186
0187 static int aiu_encoder_i2s_hw_params(struct snd_pcm_substream *substream,
0188 struct snd_pcm_hw_params *params,
0189 struct snd_soc_dai *dai)
0190 {
0191 struct snd_soc_component *component = dai->component;
0192 int ret;
0193
0194
0195 aiu_encoder_i2s_divider_enable(component, false);
0196
0197 ret = aiu_encoder_i2s_setup_desc(component, params);
0198 if (ret) {
0199 dev_err(dai->dev, "setting i2s desc failed\n");
0200 return ret;
0201 }
0202
0203 ret = aiu_encoder_i2s_set_clocks(component, params);
0204 if (ret) {
0205 dev_err(dai->dev, "setting i2s clocks failed\n");
0206 return ret;
0207 }
0208
0209 aiu_encoder_i2s_divider_enable(component, true);
0210
0211 return 0;
0212 }
0213
0214 static int aiu_encoder_i2s_hw_free(struct snd_pcm_substream *substream,
0215 struct snd_soc_dai *dai)
0216 {
0217 struct snd_soc_component *component = dai->component;
0218
0219 aiu_encoder_i2s_divider_enable(component, false);
0220
0221 return 0;
0222 }
0223
0224 static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0225 {
0226 struct snd_soc_component *component = dai->component;
0227 unsigned int inv = fmt & SND_SOC_DAIFMT_INV_MASK;
0228 unsigned int val = 0;
0229 unsigned int skew;
0230
0231
0232 if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP)
0233 return -EINVAL;
0234
0235 if (inv == SND_SOC_DAIFMT_NB_IF ||
0236 inv == SND_SOC_DAIFMT_IB_IF)
0237 val |= AIU_CLK_CTRL_LRCLK_INVERT;
0238
0239 if (inv == SND_SOC_DAIFMT_IB_NF ||
0240 inv == SND_SOC_DAIFMT_IB_IF)
0241 val |= AIU_CLK_CTRL_AOCLK_INVERT;
0242
0243
0244 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0245 case SND_SOC_DAIFMT_I2S:
0246
0247 val ^= AIU_CLK_CTRL_LRCLK_INVERT;
0248 skew = 1;
0249 break;
0250 case SND_SOC_DAIFMT_LEFT_J:
0251 skew = 0;
0252 break;
0253 default:
0254 return -EINVAL;
0255 }
0256
0257 val |= FIELD_PREP(AIU_CLK_CTRL_LRCLK_SKEW, skew);
0258 snd_soc_component_update_bits(component, AIU_CLK_CTRL,
0259 AIU_CLK_CTRL_LRCLK_INVERT |
0260 AIU_CLK_CTRL_AOCLK_INVERT |
0261 AIU_CLK_CTRL_LRCLK_SKEW,
0262 val);
0263
0264 return 0;
0265 }
0266
0267 static int aiu_encoder_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
0268 unsigned int freq, int dir)
0269 {
0270 struct aiu *aiu = snd_soc_component_get_drvdata(dai->component);
0271 int ret;
0272
0273 if (WARN_ON(clk_id != 0))
0274 return -EINVAL;
0275
0276 if (dir == SND_SOC_CLOCK_IN)
0277 return 0;
0278
0279 ret = clk_set_rate(aiu->i2s.clks[MCLK].clk, freq);
0280 if (ret)
0281 dev_err(dai->dev, "Failed to set sysclk to %uHz", freq);
0282
0283 return ret;
0284 }
0285
0286 static const unsigned int hw_channels[] = {2, 8};
0287 static const struct snd_pcm_hw_constraint_list hw_channel_constraints = {
0288 .list = hw_channels,
0289 .count = ARRAY_SIZE(hw_channels),
0290 .mask = 0,
0291 };
0292
0293 static int aiu_encoder_i2s_startup(struct snd_pcm_substream *substream,
0294 struct snd_soc_dai *dai)
0295 {
0296 struct aiu *aiu = snd_soc_component_get_drvdata(dai->component);
0297 int ret;
0298
0299
0300 ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
0301 SNDRV_PCM_HW_PARAM_CHANNELS,
0302 &hw_channel_constraints);
0303 if (ret) {
0304 dev_err(dai->dev, "adding channels constraints failed\n");
0305 return ret;
0306 }
0307
0308 ret = clk_bulk_prepare_enable(aiu->i2s.clk_num, aiu->i2s.clks);
0309 if (ret)
0310 dev_err(dai->dev, "failed to enable i2s clocks\n");
0311
0312 return ret;
0313 }
0314
0315 static void aiu_encoder_i2s_shutdown(struct snd_pcm_substream *substream,
0316 struct snd_soc_dai *dai)
0317 {
0318 struct aiu *aiu = snd_soc_component_get_drvdata(dai->component);
0319
0320 clk_bulk_disable_unprepare(aiu->i2s.clk_num, aiu->i2s.clks);
0321 }
0322
0323 const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = {
0324 .hw_params = aiu_encoder_i2s_hw_params,
0325 .hw_free = aiu_encoder_i2s_hw_free,
0326 .set_fmt = aiu_encoder_i2s_set_fmt,
0327 .set_sysclk = aiu_encoder_i2s_set_sysclk,
0328 .startup = aiu_encoder_i2s_startup,
0329 .shutdown = aiu_encoder_i2s_shutdown,
0330 };
0331