0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/mfd/syscon.h>
0012 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
0013 #include <linux/of_device.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/of.h>
0016 #include <linux/pm.h>
0017 #include <linux/slab.h>
0018 #include <sound/soc.h>
0019 #include <sound/pcm.h>
0020 #include <sound/initval.h>
0021
0022 #define REG_MQS_CTRL 0x00
0023
0024 #define MQS_EN_MASK (0x1 << 28)
0025 #define MQS_EN_SHIFT (28)
0026 #define MQS_SW_RST_MASK (0x1 << 24)
0027 #define MQS_SW_RST_SHIFT (24)
0028 #define MQS_OVERSAMPLE_MASK (0x1 << 20)
0029 #define MQS_OVERSAMPLE_SHIFT (20)
0030 #define MQS_CLK_DIV_MASK (0xFF << 0)
0031 #define MQS_CLK_DIV_SHIFT (0)
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 struct fsl_mqs_soc_data {
0048 bool use_gpr;
0049 int ctrl_off;
0050 int en_mask;
0051 int en_shift;
0052 int rst_mask;
0053 int rst_shift;
0054 int osr_mask;
0055 int osr_shift;
0056 int div_mask;
0057 int div_shift;
0058 };
0059
0060
0061 struct fsl_mqs {
0062 struct regmap *regmap;
0063 struct clk *mclk;
0064 struct clk *ipg;
0065 const struct fsl_mqs_soc_data *soc;
0066
0067 unsigned int reg_mqs_ctrl;
0068 };
0069
0070 #define FSL_MQS_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
0071 #define FSL_MQS_FORMATS SNDRV_PCM_FMTBIT_S16_LE
0072
0073 static int fsl_mqs_hw_params(struct snd_pcm_substream *substream,
0074 struct snd_pcm_hw_params *params,
0075 struct snd_soc_dai *dai)
0076 {
0077 struct snd_soc_component *component = dai->component;
0078 struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component);
0079 unsigned long mclk_rate;
0080 int div, res;
0081 int lrclk;
0082
0083 mclk_rate = clk_get_rate(mqs_priv->mclk);
0084 lrclk = params_rate(params);
0085
0086
0087
0088
0089
0090
0091 div = mclk_rate / (32 * lrclk * 2 * 8);
0092 res = mclk_rate % (32 * lrclk * 2 * 8);
0093
0094 if (res == 0 && div > 0 && div <= 256) {
0095 regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off,
0096 mqs_priv->soc->div_mask,
0097 (div - 1) << mqs_priv->soc->div_shift);
0098 regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off,
0099 mqs_priv->soc->osr_mask, 0);
0100 } else {
0101 dev_err(component->dev, "can't get proper divider\n");
0102 }
0103
0104 return 0;
0105 }
0106
0107 static int fsl_mqs_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0108 {
0109
0110 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0111 case SND_SOC_DAIFMT_LEFT_J:
0112 break;
0113 default:
0114 return -EINVAL;
0115 }
0116
0117 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0118 case SND_SOC_DAIFMT_NB_NF:
0119 break;
0120 default:
0121 return -EINVAL;
0122 }
0123
0124 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
0125 case SND_SOC_DAIFMT_CBC_CFC:
0126 break;
0127 default:
0128 return -EINVAL;
0129 }
0130
0131 return 0;
0132 }
0133
0134 static int fsl_mqs_startup(struct snd_pcm_substream *substream,
0135 struct snd_soc_dai *dai)
0136 {
0137 struct snd_soc_component *component = dai->component;
0138 struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component);
0139
0140 regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off,
0141 mqs_priv->soc->en_mask,
0142 1 << mqs_priv->soc->en_shift);
0143 return 0;
0144 }
0145
0146 static void fsl_mqs_shutdown(struct snd_pcm_substream *substream,
0147 struct snd_soc_dai *dai)
0148 {
0149 struct snd_soc_component *component = dai->component;
0150 struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component);
0151
0152 regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off,
0153 mqs_priv->soc->en_mask, 0);
0154 }
0155
0156 static const struct snd_soc_component_driver soc_codec_fsl_mqs = {
0157 .idle_bias_on = 1,
0158 };
0159
0160 static const struct snd_soc_dai_ops fsl_mqs_dai_ops = {
0161 .startup = fsl_mqs_startup,
0162 .shutdown = fsl_mqs_shutdown,
0163 .hw_params = fsl_mqs_hw_params,
0164 .set_fmt = fsl_mqs_set_dai_fmt,
0165 };
0166
0167 static struct snd_soc_dai_driver fsl_mqs_dai = {
0168 .name = "fsl-mqs-dai",
0169 .playback = {
0170 .stream_name = "Playback",
0171 .channels_min = 2,
0172 .channels_max = 2,
0173 .rates = FSL_MQS_RATES,
0174 .formats = FSL_MQS_FORMATS,
0175 },
0176 .ops = &fsl_mqs_dai_ops,
0177 };
0178
0179 static const struct regmap_config fsl_mqs_regmap_config = {
0180 .reg_bits = 32,
0181 .reg_stride = 4,
0182 .val_bits = 32,
0183 .max_register = REG_MQS_CTRL,
0184 .cache_type = REGCACHE_NONE,
0185 };
0186
0187 static int fsl_mqs_probe(struct platform_device *pdev)
0188 {
0189 struct device_node *np = pdev->dev.of_node;
0190 struct device_node *gpr_np = NULL;
0191 struct fsl_mqs *mqs_priv;
0192 void __iomem *regs;
0193 int ret;
0194
0195 mqs_priv = devm_kzalloc(&pdev->dev, sizeof(*mqs_priv), GFP_KERNEL);
0196 if (!mqs_priv)
0197 return -ENOMEM;
0198
0199
0200
0201
0202
0203 mqs_priv->soc = of_device_get_match_data(&pdev->dev);
0204
0205 if (mqs_priv->soc->use_gpr) {
0206 gpr_np = of_parse_phandle(np, "gpr", 0);
0207 if (!gpr_np) {
0208 dev_err(&pdev->dev, "failed to get gpr node by phandle\n");
0209 return -EINVAL;
0210 }
0211
0212 mqs_priv->regmap = syscon_node_to_regmap(gpr_np);
0213 if (IS_ERR(mqs_priv->regmap)) {
0214 dev_err(&pdev->dev, "failed to get gpr regmap\n");
0215 ret = PTR_ERR(mqs_priv->regmap);
0216 goto err_free_gpr_np;
0217 }
0218 } else {
0219 regs = devm_platform_ioremap_resource(pdev, 0);
0220 if (IS_ERR(regs))
0221 return PTR_ERR(regs);
0222
0223 mqs_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
0224 "core",
0225 regs,
0226 &fsl_mqs_regmap_config);
0227 if (IS_ERR(mqs_priv->regmap)) {
0228 dev_err(&pdev->dev, "failed to init regmap: %ld\n",
0229 PTR_ERR(mqs_priv->regmap));
0230 return PTR_ERR(mqs_priv->regmap);
0231 }
0232
0233 mqs_priv->ipg = devm_clk_get(&pdev->dev, "core");
0234 if (IS_ERR(mqs_priv->ipg)) {
0235 dev_err(&pdev->dev, "failed to get the clock: %ld\n",
0236 PTR_ERR(mqs_priv->ipg));
0237 return PTR_ERR(mqs_priv->ipg);
0238 }
0239 }
0240
0241 mqs_priv->mclk = devm_clk_get(&pdev->dev, "mclk");
0242 if (IS_ERR(mqs_priv->mclk)) {
0243 dev_err(&pdev->dev, "failed to get the clock: %ld\n",
0244 PTR_ERR(mqs_priv->mclk));
0245 ret = PTR_ERR(mqs_priv->mclk);
0246 goto err_free_gpr_np;
0247 }
0248
0249 dev_set_drvdata(&pdev->dev, mqs_priv);
0250 pm_runtime_enable(&pdev->dev);
0251
0252 ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_fsl_mqs,
0253 &fsl_mqs_dai, 1);
0254 if (ret)
0255 goto err_free_gpr_np;
0256 return 0;
0257
0258 err_free_gpr_np:
0259 of_node_put(gpr_np);
0260
0261 return ret;
0262 }
0263
0264 static int fsl_mqs_remove(struct platform_device *pdev)
0265 {
0266 pm_runtime_disable(&pdev->dev);
0267 return 0;
0268 }
0269
0270 #ifdef CONFIG_PM
0271 static int fsl_mqs_runtime_resume(struct device *dev)
0272 {
0273 struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
0274 int ret;
0275
0276 ret = clk_prepare_enable(mqs_priv->ipg);
0277 if (ret) {
0278 dev_err(dev, "failed to enable ipg clock\n");
0279 return ret;
0280 }
0281
0282 ret = clk_prepare_enable(mqs_priv->mclk);
0283 if (ret) {
0284 dev_err(dev, "failed to enable mclk clock\n");
0285 clk_disable_unprepare(mqs_priv->ipg);
0286 return ret;
0287 }
0288
0289 regmap_write(mqs_priv->regmap, mqs_priv->soc->ctrl_off, mqs_priv->reg_mqs_ctrl);
0290 return 0;
0291 }
0292
0293 static int fsl_mqs_runtime_suspend(struct device *dev)
0294 {
0295 struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
0296
0297 regmap_read(mqs_priv->regmap, mqs_priv->soc->ctrl_off, &mqs_priv->reg_mqs_ctrl);
0298
0299 clk_disable_unprepare(mqs_priv->mclk);
0300 clk_disable_unprepare(mqs_priv->ipg);
0301
0302 return 0;
0303 }
0304 #endif
0305
0306 static const struct dev_pm_ops fsl_mqs_pm_ops = {
0307 SET_RUNTIME_PM_OPS(fsl_mqs_runtime_suspend,
0308 fsl_mqs_runtime_resume,
0309 NULL)
0310 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0311 pm_runtime_force_resume)
0312 };
0313
0314 static const struct fsl_mqs_soc_data fsl_mqs_imx8qm_data = {
0315 .use_gpr = false,
0316 .ctrl_off = REG_MQS_CTRL,
0317 .en_mask = MQS_EN_MASK,
0318 .en_shift = MQS_EN_SHIFT,
0319 .rst_mask = MQS_SW_RST_MASK,
0320 .rst_shift = MQS_SW_RST_SHIFT,
0321 .osr_mask = MQS_OVERSAMPLE_MASK,
0322 .osr_shift = MQS_OVERSAMPLE_SHIFT,
0323 .div_mask = MQS_CLK_DIV_MASK,
0324 .div_shift = MQS_CLK_DIV_SHIFT,
0325 };
0326
0327 static const struct fsl_mqs_soc_data fsl_mqs_imx6sx_data = {
0328 .use_gpr = true,
0329 .ctrl_off = IOMUXC_GPR2,
0330 .en_mask = IMX6SX_GPR2_MQS_EN_MASK,
0331 .en_shift = IMX6SX_GPR2_MQS_EN_SHIFT,
0332 .rst_mask = IMX6SX_GPR2_MQS_SW_RST_MASK,
0333 .rst_shift = IMX6SX_GPR2_MQS_SW_RST_SHIFT,
0334 .osr_mask = IMX6SX_GPR2_MQS_OVERSAMPLE_MASK,
0335 .osr_shift = IMX6SX_GPR2_MQS_OVERSAMPLE_SHIFT,
0336 .div_mask = IMX6SX_GPR2_MQS_CLK_DIV_MASK,
0337 .div_shift = IMX6SX_GPR2_MQS_CLK_DIV_SHIFT,
0338 };
0339
0340 static const struct fsl_mqs_soc_data fsl_mqs_imx93_data = {
0341 .use_gpr = true,
0342 .ctrl_off = 0x20,
0343 .en_mask = BIT(1),
0344 .en_shift = 1,
0345 .rst_mask = BIT(2),
0346 .rst_shift = 2,
0347 .osr_mask = BIT(3),
0348 .osr_shift = 3,
0349 .div_mask = GENMASK(15, 8),
0350 .div_shift = 8,
0351 };
0352
0353 static const struct of_device_id fsl_mqs_dt_ids[] = {
0354 { .compatible = "fsl,imx8qm-mqs", .data = &fsl_mqs_imx8qm_data },
0355 { .compatible = "fsl,imx6sx-mqs", .data = &fsl_mqs_imx6sx_data },
0356 { .compatible = "fsl,imx93-mqs", .data = &fsl_mqs_imx93_data },
0357 {}
0358 };
0359 MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids);
0360
0361 static struct platform_driver fsl_mqs_driver = {
0362 .probe = fsl_mqs_probe,
0363 .remove = fsl_mqs_remove,
0364 .driver = {
0365 .name = "fsl-mqs",
0366 .of_match_table = fsl_mqs_dt_ids,
0367 .pm = &fsl_mqs_pm_ops,
0368 },
0369 };
0370
0371 module_platform_driver(fsl_mqs_driver);
0372
0373 MODULE_AUTHOR("Shengjiu Wang <Shengjiu.Wang@nxp.com>");
0374 MODULE_DESCRIPTION("MQS codec driver");
0375 MODULE_LICENSE("GPL v2");
0376 MODULE_ALIAS("platform:fsl-mqs");