Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Pistachio internal dac driver
0004  *
0005  * Copyright (C) 2015 Imagination Technologies Ltd.
0006  *
0007  * Author: Damien Horsley <Damien.Horsley@imgtec.com>
0008  */
0009 
0010 #include <linux/clk.h>
0011 #include <linux/delay.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/module.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/regmap.h>
0016 #include <linux/regulator/consumer.h>
0017 
0018 #include <sound/pcm_params.h>
0019 #include <sound/soc.h>
0020 
0021 #define PISTACHIO_INTERNAL_DAC_CTRL         0x40
0022 #define PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK    0x2
0023 #define PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK      0x1
0024 
0025 #define PISTACHIO_INTERNAL_DAC_SRST         0x44
0026 #define PISTACHIO_INTERNAL_DAC_SRST_MASK        0x1
0027 
0028 #define PISTACHIO_INTERNAL_DAC_GTI_CTRL         0x48
0029 #define PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_SHIFT  0
0030 #define PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_MASK   0xFFF
0031 #define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK     0x1000
0032 #define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_SHIFT 13
0033 #define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_MASK  0x1FE000
0034 
0035 #define PISTACHIO_INTERNAL_DAC_PWR          0x1
0036 #define PISTACHIO_INTERNAL_DAC_PWR_MASK         0x1
0037 
0038 #define PISTACHIO_INTERNAL_DAC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE |  \
0039                     SNDRV_PCM_FMTBIT_S32_LE)
0040 
0041 /* codec private data */
0042 struct pistachio_internal_dac {
0043     struct regmap *regmap;
0044     struct regulator *supply;
0045     bool mute;
0046 };
0047 
0048 static const struct snd_kcontrol_new pistachio_internal_dac_snd_controls[] = {
0049     SOC_SINGLE("Playback Switch", PISTACHIO_INTERNAL_DAC_CTRL, 2, 1, 1)
0050 };
0051 
0052 static const struct snd_soc_dapm_widget pistachio_internal_dac_widgets[] = {
0053     SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
0054     SND_SOC_DAPM_OUTPUT("AOUTL"),
0055     SND_SOC_DAPM_OUTPUT("AOUTR"),
0056 };
0057 
0058 static const struct snd_soc_dapm_route pistachio_internal_dac_routes[] = {
0059     { "AOUTL", NULL, "DAC" },
0060     { "AOUTR", NULL, "DAC" },
0061 };
0062 
0063 static void pistachio_internal_dac_reg_writel(struct regmap *top_regs,
0064                         u32 val, u32 reg)
0065 {
0066     regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
0067             PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_MASK,
0068             reg << PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_SHIFT);
0069 
0070     regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
0071             PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_MASK,
0072             val << PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_SHIFT);
0073 
0074     regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
0075             PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK,
0076             PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK);
0077 
0078     regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
0079             PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK, 0);
0080 }
0081 
0082 static void pistachio_internal_dac_pwr_off(struct pistachio_internal_dac *dac)
0083 {
0084     regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
0085         PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK,
0086         PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK);
0087 
0088     pistachio_internal_dac_reg_writel(dac->regmap, 0,
0089                     PISTACHIO_INTERNAL_DAC_PWR);
0090 }
0091 
0092 static void pistachio_internal_dac_pwr_on(struct pistachio_internal_dac *dac)
0093 {
0094     regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_SRST,
0095             PISTACHIO_INTERNAL_DAC_SRST_MASK,
0096             PISTACHIO_INTERNAL_DAC_SRST_MASK);
0097 
0098     regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_SRST,
0099             PISTACHIO_INTERNAL_DAC_SRST_MASK, 0);
0100 
0101     pistachio_internal_dac_reg_writel(dac->regmap,
0102                     PISTACHIO_INTERNAL_DAC_PWR_MASK,
0103                     PISTACHIO_INTERNAL_DAC_PWR);
0104 
0105     regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
0106             PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK, 0);
0107 }
0108 
0109 static struct snd_soc_dai_driver pistachio_internal_dac_dais[] = {
0110     {
0111         .name = "pistachio_internal_dac",
0112         .playback = {
0113             .stream_name = "Playback",
0114             .channels_min = 2,
0115             .channels_max = 2,
0116             .rates = SNDRV_PCM_RATE_8000_48000,
0117             .formats = PISTACHIO_INTERNAL_DAC_FORMATS,
0118         }
0119     },
0120 };
0121 
0122 static int pistachio_internal_dac_codec_probe(struct snd_soc_component *component)
0123 {
0124     struct pistachio_internal_dac *dac = snd_soc_component_get_drvdata(component);
0125 
0126     snd_soc_component_init_regmap(component, dac->regmap);
0127 
0128     return 0;
0129 }
0130 
0131 static const struct snd_soc_component_driver pistachio_internal_dac_driver = {
0132     .probe          = pistachio_internal_dac_codec_probe,
0133     .controls       = pistachio_internal_dac_snd_controls,
0134     .num_controls       = ARRAY_SIZE(pistachio_internal_dac_snd_controls),
0135     .dapm_widgets       = pistachio_internal_dac_widgets,
0136     .num_dapm_widgets   = ARRAY_SIZE(pistachio_internal_dac_widgets),
0137     .dapm_routes        = pistachio_internal_dac_routes,
0138     .num_dapm_routes    = ARRAY_SIZE(pistachio_internal_dac_routes),
0139     .use_pmdown_time    = 1,
0140     .endianness     = 1,
0141 };
0142 
0143 static int pistachio_internal_dac_probe(struct platform_device *pdev)
0144 {
0145     struct pistachio_internal_dac *dac;
0146     int ret, voltage;
0147     struct device *dev = &pdev->dev;
0148     u32 reg;
0149 
0150     dac = devm_kzalloc(dev, sizeof(*dac), GFP_KERNEL);
0151 
0152     if (!dac)
0153         return -ENOMEM;
0154 
0155     platform_set_drvdata(pdev, dac);
0156 
0157     dac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
0158                                 "img,cr-top");
0159     if (IS_ERR(dac->regmap))
0160         return PTR_ERR(dac->regmap);
0161 
0162     dac->supply = devm_regulator_get(dev, "VDD");
0163     if (IS_ERR(dac->supply))
0164         return dev_err_probe(dev, PTR_ERR(dac->supply),
0165                      "failed to acquire supply 'VDD-supply'\n");
0166 
0167     ret = regulator_enable(dac->supply);
0168     if (ret) {
0169         dev_err(dev, "failed to enable supply: %d\n", ret);
0170         return ret;
0171     }
0172 
0173     voltage = regulator_get_voltage(dac->supply);
0174 
0175     switch (voltage) {
0176     case 1800000:
0177         reg = 0;
0178         break;
0179     case 3300000:
0180         reg = PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK;
0181         break;
0182     default:
0183         dev_err(dev, "invalid voltage: %d\n", voltage);
0184         ret = -EINVAL;
0185         goto err_regulator;
0186     }
0187 
0188     regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
0189             PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK, reg);
0190 
0191     pistachio_internal_dac_pwr_off(dac);
0192     pistachio_internal_dac_pwr_on(dac);
0193 
0194     pm_runtime_set_active(dev);
0195     pm_runtime_enable(dev);
0196     pm_runtime_idle(dev);
0197 
0198     ret = devm_snd_soc_register_component(dev,
0199             &pistachio_internal_dac_driver,
0200             pistachio_internal_dac_dais,
0201             ARRAY_SIZE(pistachio_internal_dac_dais));
0202     if (ret) {
0203         dev_err(dev, "failed to register component: %d\n", ret);
0204         goto err_pwr;
0205     }
0206 
0207     return 0;
0208 
0209 err_pwr:
0210     pm_runtime_disable(&pdev->dev);
0211     pistachio_internal_dac_pwr_off(dac);
0212 err_regulator:
0213     regulator_disable(dac->supply);
0214 
0215     return ret;
0216 }
0217 
0218 static int pistachio_internal_dac_remove(struct platform_device *pdev)
0219 {
0220     struct pistachio_internal_dac *dac = dev_get_drvdata(&pdev->dev);
0221 
0222     pm_runtime_disable(&pdev->dev);
0223     pistachio_internal_dac_pwr_off(dac);
0224     regulator_disable(dac->supply);
0225 
0226     return 0;
0227 }
0228 
0229 #ifdef CONFIG_PM
0230 static int pistachio_internal_dac_rt_resume(struct device *dev)
0231 {
0232     struct pistachio_internal_dac *dac = dev_get_drvdata(dev);
0233     int ret;
0234 
0235     ret = regulator_enable(dac->supply);
0236     if (ret) {
0237         dev_err(dev, "failed to enable supply: %d\n", ret);
0238         return ret;
0239     }
0240 
0241     pistachio_internal_dac_pwr_on(dac);
0242 
0243     return 0;
0244 }
0245 
0246 static int pistachio_internal_dac_rt_suspend(struct device *dev)
0247 {
0248     struct pistachio_internal_dac *dac = dev_get_drvdata(dev);
0249 
0250     pistachio_internal_dac_pwr_off(dac);
0251 
0252     regulator_disable(dac->supply);
0253 
0254     return 0;
0255 }
0256 #endif
0257 
0258 static const struct dev_pm_ops pistachio_internal_dac_pm_ops = {
0259     SET_RUNTIME_PM_OPS(pistachio_internal_dac_rt_suspend,
0260             pistachio_internal_dac_rt_resume, NULL)
0261 };
0262 
0263 static const struct of_device_id pistachio_internal_dac_of_match[] = {
0264     { .compatible = "img,pistachio-internal-dac" },
0265     {}
0266 };
0267 MODULE_DEVICE_TABLE(of, pistachio_internal_dac_of_match);
0268 
0269 static struct platform_driver pistachio_internal_dac_plat_driver = {
0270     .driver = {
0271         .name = "img-pistachio-internal-dac",
0272         .of_match_table = pistachio_internal_dac_of_match,
0273         .pm = &pistachio_internal_dac_pm_ops
0274     },
0275     .probe = pistachio_internal_dac_probe,
0276     .remove = pistachio_internal_dac_remove
0277 };
0278 module_platform_driver(pistachio_internal_dac_plat_driver);
0279 
0280 MODULE_DESCRIPTION("Pistachio Internal DAC driver");
0281 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
0282 MODULE_LICENSE("GPL v2");