0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/clk.h>
0013 #include <linux/delay.h>
0014 #include <linux/device.h>
0015 #include <linux/kernel.h>
0016 #include <linux/init.h>
0017 #include <linux/io.h>
0018 #include <linux/ioport.h>
0019 #include <linux/module.h>
0020 #include <linux/platform_device.h>
0021 #include <sound/dmaengine_pcm.h>
0022 #include <sound/soc.h>
0023 #include <sound/spear_dma.h>
0024 #include <sound/spear_spdif.h>
0025 #include "spdif_out_regs.h"
0026 #include "spear_pcm.h"
0027
0028 struct spdif_out_params {
0029 u32 rate;
0030 u32 core_freq;
0031 u32 mute;
0032 };
0033
0034 struct spdif_out_dev {
0035 struct clk *clk;
0036 struct spear_dma_data dma_params;
0037 struct spdif_out_params saved_params;
0038 u32 running;
0039 void __iomem *io_base;
0040 struct snd_dmaengine_dai_dma_data dma_params_tx;
0041 struct snd_dmaengine_pcm_config config;
0042 };
0043
0044 static void spdif_out_configure(struct spdif_out_dev *host)
0045 {
0046 writel(SPDIF_OUT_RESET, host->io_base + SPDIF_OUT_SOFT_RST);
0047 mdelay(1);
0048 writel(readl(host->io_base + SPDIF_OUT_SOFT_RST) & ~SPDIF_OUT_RESET,
0049 host->io_base + SPDIF_OUT_SOFT_RST);
0050
0051 writel(SPDIF_OUT_FDMA_TRIG_16 | SPDIF_OUT_MEMFMT_16_16 |
0052 SPDIF_OUT_VALID_HW | SPDIF_OUT_USER_HW |
0053 SPDIF_OUT_CHNLSTA_HW | SPDIF_OUT_PARITY_HW,
0054 host->io_base + SPDIF_OUT_CFG);
0055
0056 writel(0x7F, host->io_base + SPDIF_OUT_INT_STA_CLR);
0057 writel(0x7F, host->io_base + SPDIF_OUT_INT_EN_CLR);
0058 }
0059
0060 static int spdif_out_startup(struct snd_pcm_substream *substream,
0061 struct snd_soc_dai *cpu_dai)
0062 {
0063 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
0064 int ret;
0065
0066 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
0067 return -EINVAL;
0068
0069 ret = clk_enable(host->clk);
0070 if (ret)
0071 return ret;
0072
0073 host->running = true;
0074 spdif_out_configure(host);
0075
0076 return 0;
0077 }
0078
0079 static void spdif_out_shutdown(struct snd_pcm_substream *substream,
0080 struct snd_soc_dai *dai)
0081 {
0082 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
0083
0084 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
0085 return;
0086
0087 clk_disable(host->clk);
0088 host->running = false;
0089 }
0090
0091 static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq,
0092 u32 rate)
0093 {
0094 u32 divider, ctrl;
0095
0096 clk_set_rate(host->clk, core_freq);
0097 divider = DIV_ROUND_CLOSEST(clk_get_rate(host->clk), (rate * 128));
0098
0099 ctrl = readl(host->io_base + SPDIF_OUT_CTRL);
0100 ctrl &= ~SPDIF_DIVIDER_MASK;
0101 ctrl |= (divider << SPDIF_DIVIDER_SHIFT) & SPDIF_DIVIDER_MASK;
0102 writel(ctrl, host->io_base + SPDIF_OUT_CTRL);
0103 }
0104
0105 static int spdif_out_hw_params(struct snd_pcm_substream *substream,
0106 struct snd_pcm_hw_params *params,
0107 struct snd_soc_dai *dai)
0108 {
0109 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
0110 u32 rate, core_freq;
0111
0112 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
0113 return -EINVAL;
0114
0115 rate = params_rate(params);
0116
0117 switch (rate) {
0118 case 8000:
0119 case 16000:
0120 case 32000:
0121 case 64000:
0122
0123
0124
0125
0126 core_freq = 64000 * 128 * 10;
0127 break;
0128 case 5512:
0129 case 11025:
0130 case 22050:
0131 case 44100:
0132 case 88200:
0133 case 176400:
0134 core_freq = 176400 * 128;
0135 break;
0136 case 48000:
0137 case 96000:
0138 case 192000:
0139 default:
0140 core_freq = 192000 * 128;
0141 break;
0142 }
0143
0144 spdif_out_clock(host, core_freq, rate);
0145 host->saved_params.core_freq = core_freq;
0146 host->saved_params.rate = rate;
0147
0148 return 0;
0149 }
0150
0151 static int spdif_out_trigger(struct snd_pcm_substream *substream, int cmd,
0152 struct snd_soc_dai *dai)
0153 {
0154 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
0155 u32 ctrl;
0156 int ret = 0;
0157
0158 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
0159 return -EINVAL;
0160
0161 switch (cmd) {
0162 case SNDRV_PCM_TRIGGER_START:
0163 case SNDRV_PCM_TRIGGER_RESUME:
0164 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0165 ctrl = readl(host->io_base + SPDIF_OUT_CTRL);
0166 ctrl &= ~SPDIF_OPMODE_MASK;
0167 if (!host->saved_params.mute)
0168 ctrl |= SPDIF_OPMODE_AUD_DATA |
0169 SPDIF_STATE_NORMAL;
0170 else
0171 ctrl |= SPDIF_OPMODE_MUTE_PCM;
0172 writel(ctrl, host->io_base + SPDIF_OUT_CTRL);
0173 break;
0174
0175 case SNDRV_PCM_TRIGGER_STOP:
0176 case SNDRV_PCM_TRIGGER_SUSPEND:
0177 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0178 ctrl = readl(host->io_base + SPDIF_OUT_CTRL);
0179 ctrl &= ~SPDIF_OPMODE_MASK;
0180 ctrl |= SPDIF_OPMODE_OFF;
0181 writel(ctrl, host->io_base + SPDIF_OUT_CTRL);
0182 break;
0183
0184 default:
0185 ret = -EINVAL;
0186 break;
0187 }
0188 return ret;
0189 }
0190
0191 static int spdif_mute(struct snd_soc_dai *dai, int mute, int direction)
0192 {
0193 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
0194 u32 val;
0195
0196 host->saved_params.mute = mute;
0197 val = readl(host->io_base + SPDIF_OUT_CTRL);
0198 val &= ~SPDIF_OPMODE_MASK;
0199
0200 if (mute)
0201 val |= SPDIF_OPMODE_MUTE_PCM;
0202 else {
0203 if (host->running)
0204 val |= SPDIF_OPMODE_AUD_DATA | SPDIF_STATE_NORMAL;
0205 else
0206 val |= SPDIF_OPMODE_OFF;
0207 }
0208
0209 writel(val, host->io_base + SPDIF_OUT_CTRL);
0210 return 0;
0211 }
0212
0213 static int spdif_mute_get(struct snd_kcontrol *kcontrol,
0214 struct snd_ctl_elem_value *ucontrol)
0215 {
0216 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
0217 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
0218
0219 ucontrol->value.integer.value[0] = host->saved_params.mute;
0220 return 0;
0221 }
0222
0223 static int spdif_mute_put(struct snd_kcontrol *kcontrol,
0224 struct snd_ctl_elem_value *ucontrol)
0225 {
0226 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
0227 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
0228
0229 if (host->saved_params.mute == ucontrol->value.integer.value[0])
0230 return 0;
0231
0232 spdif_mute(cpu_dai, ucontrol->value.integer.value[0],
0233 SNDRV_PCM_STREAM_PLAYBACK);
0234
0235 return 1;
0236 }
0237 static const struct snd_kcontrol_new spdif_out_controls[] = {
0238 SOC_SINGLE_BOOL_EXT("IEC958 Playback Switch", 0,
0239 spdif_mute_get, spdif_mute_put),
0240 };
0241
0242 static int spdif_soc_dai_probe(struct snd_soc_dai *dai)
0243 {
0244 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
0245
0246 host->dma_params_tx.filter_data = &host->dma_params;
0247 dai->playback_dma_data = &host->dma_params_tx;
0248
0249 return snd_soc_add_dai_controls(dai, spdif_out_controls,
0250 ARRAY_SIZE(spdif_out_controls));
0251 }
0252
0253 static const struct snd_soc_dai_ops spdif_out_dai_ops = {
0254 .mute_stream = spdif_mute,
0255 .startup = spdif_out_startup,
0256 .shutdown = spdif_out_shutdown,
0257 .trigger = spdif_out_trigger,
0258 .hw_params = spdif_out_hw_params,
0259 .no_capture_mute = 1,
0260 };
0261
0262 static struct snd_soc_dai_driver spdif_out_dai = {
0263 .playback = {
0264 .channels_min = 2,
0265 .channels_max = 2,
0266 .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
0267 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \
0268 SNDRV_PCM_RATE_192000),
0269 .formats = SNDRV_PCM_FMTBIT_S16_LE,
0270 },
0271 .probe = spdif_soc_dai_probe,
0272 .ops = &spdif_out_dai_ops,
0273 };
0274
0275 static const struct snd_soc_component_driver spdif_out_component = {
0276 .name = "spdif-out",
0277 .legacy_dai_naming = 1,
0278 };
0279
0280 static int spdif_out_probe(struct platform_device *pdev)
0281 {
0282 struct spdif_out_dev *host;
0283 struct spear_spdif_platform_data *pdata;
0284 struct resource *res;
0285 int ret;
0286
0287 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
0288 if (!host)
0289 return -ENOMEM;
0290
0291 host->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
0292 if (IS_ERR(host->io_base))
0293 return PTR_ERR(host->io_base);
0294
0295 host->clk = devm_clk_get(&pdev->dev, NULL);
0296 if (IS_ERR(host->clk))
0297 return PTR_ERR(host->clk);
0298
0299 pdata = dev_get_platdata(&pdev->dev);
0300
0301 host->dma_params.data = pdata->dma_params;
0302 host->dma_params.addr = res->start + SPDIF_OUT_FIFO_DATA;
0303 host->dma_params.max_burst = 16;
0304 host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0305
0306 dev_set_drvdata(&pdev->dev, host);
0307
0308 ret = devm_snd_soc_register_component(&pdev->dev, &spdif_out_component,
0309 &spdif_out_dai, 1);
0310 if (ret)
0311 return ret;
0312
0313 return devm_spear_pcm_platform_register(&pdev->dev, &host->config,
0314 pdata->filter);
0315 }
0316
0317 #ifdef CONFIG_PM
0318 static int spdif_out_suspend(struct device *dev)
0319 {
0320 struct platform_device *pdev = to_platform_device(dev);
0321 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
0322
0323 if (host->running)
0324 clk_disable(host->clk);
0325
0326 return 0;
0327 }
0328
0329 static int spdif_out_resume(struct device *dev)
0330 {
0331 struct platform_device *pdev = to_platform_device(dev);
0332 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
0333
0334 if (host->running) {
0335 clk_enable(host->clk);
0336 spdif_out_configure(host);
0337 spdif_out_clock(host, host->saved_params.core_freq,
0338 host->saved_params.rate);
0339 }
0340 return 0;
0341 }
0342
0343 static SIMPLE_DEV_PM_OPS(spdif_out_dev_pm_ops, spdif_out_suspend, \
0344 spdif_out_resume);
0345
0346 #define SPDIF_OUT_DEV_PM_OPS (&spdif_out_dev_pm_ops)
0347
0348 #else
0349 #define SPDIF_OUT_DEV_PM_OPS NULL
0350
0351 #endif
0352
0353 static struct platform_driver spdif_out_driver = {
0354 .probe = spdif_out_probe,
0355 .driver = {
0356 .name = "spdif-out",
0357 .pm = SPDIF_OUT_DEV_PM_OPS,
0358 },
0359 };
0360
0361 module_platform_driver(spdif_out_driver);
0362
0363 MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>");
0364 MODULE_DESCRIPTION("SPEAr SPDIF OUT SoC Interface");
0365 MODULE_LICENSE("GPL");
0366 MODULE_ALIAS("platform:spdif_out");