powerpc: Fix circular dependency between percpu.h and mmu.h
[linux-2.6-microblaze.git] / sound / soc / img / img-i2s-out.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * IMG I2S output controller driver
4  *
5  * Copyright (C) 2015 Imagination Technologies Ltd.
6  *
7  * Author: Damien Horsley <Damien.Horsley@imgtec.com>
8  */
9
10 #include <linux/clk.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/reset.h>
18
19 #include <sound/core.h>
20 #include <sound/dmaengine_pcm.h>
21 #include <sound/initval.h>
22 #include <sound/pcm.h>
23 #include <sound/pcm_params.h>
24 #include <sound/soc.h>
25
26 #define IMG_I2S_OUT_TX_FIFO                     0x0
27
28 #define IMG_I2S_OUT_CTL                         0x4
29 #define IMG_I2S_OUT_CTL_DATA_EN_MASK            BIT(24)
30 #define IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK        0xffe000
31 #define IMG_I2S_OUT_CTL_ACTIVE_CHAN_SHIFT       13
32 #define IMG_I2S_OUT_CTL_FRM_SIZE_MASK           BIT(8)
33 #define IMG_I2S_OUT_CTL_MASTER_MASK             BIT(6)
34 #define IMG_I2S_OUT_CTL_CLK_MASK                BIT(5)
35 #define IMG_I2S_OUT_CTL_CLK_EN_MASK             BIT(4)
36 #define IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK        BIT(3)
37 #define IMG_I2S_OUT_CTL_BCLK_POL_MASK           BIT(2)
38 #define IMG_I2S_OUT_CTL_ME_MASK                 BIT(0)
39
40 #define IMG_I2S_OUT_CH_CTL                      0x4
41 #define IMG_I2S_OUT_CHAN_CTL_CH_MASK            BIT(11)
42 #define IMG_I2S_OUT_CHAN_CTL_LT_MASK            BIT(10)
43 #define IMG_I2S_OUT_CHAN_CTL_FMT_MASK           0xf0
44 #define IMG_I2S_OUT_CHAN_CTL_FMT_SHIFT          4
45 #define IMG_I2S_OUT_CHAN_CTL_JUST_MASK          BIT(3)
46 #define IMG_I2S_OUT_CHAN_CTL_CLKT_MASK          BIT(1)
47 #define IMG_I2S_OUT_CHAN_CTL_ME_MASK            BIT(0)
48
49 #define IMG_I2S_OUT_CH_STRIDE                   0x20
50
51 struct img_i2s_out {
52         void __iomem *base;
53         struct clk *clk_sys;
54         struct clk *clk_ref;
55         struct snd_dmaengine_dai_dma_data dma_data;
56         struct device *dev;
57         unsigned int max_i2s_chan;
58         void __iomem *channel_base;
59         bool force_clk_active;
60         unsigned int active_channels;
61         struct reset_control *rst;
62         struct snd_soc_dai_driver dai_driver;
63         u32 suspend_ctl;
64         u32 *suspend_ch_ctl;
65 };
66
67 static int img_i2s_out_runtime_suspend(struct device *dev)
68 {
69         struct img_i2s_out *i2s = dev_get_drvdata(dev);
70
71         clk_disable_unprepare(i2s->clk_ref);
72         clk_disable_unprepare(i2s->clk_sys);
73
74         return 0;
75 }
76
77 static int img_i2s_out_runtime_resume(struct device *dev)
78 {
79         struct img_i2s_out *i2s = dev_get_drvdata(dev);
80         int ret;
81
82         ret = clk_prepare_enable(i2s->clk_sys);
83         if (ret) {
84                 dev_err(dev, "clk_enable failed: %d\n", ret);
85                 return ret;
86         }
87
88         ret = clk_prepare_enable(i2s->clk_ref);
89         if (ret) {
90                 dev_err(dev, "clk_enable failed: %d\n", ret);
91                 clk_disable_unprepare(i2s->clk_sys);
92                 return ret;
93         }
94
95         return 0;
96 }
97
98 static inline void img_i2s_out_writel(struct img_i2s_out *i2s, u32 val,
99                                         u32 reg)
100 {
101         writel(val, i2s->base + reg);
102 }
103
104 static inline u32 img_i2s_out_readl(struct img_i2s_out *i2s, u32 reg)
105 {
106         return readl(i2s->base + reg);
107 }
108
109 static inline void img_i2s_out_ch_writel(struct img_i2s_out *i2s,
110                                         u32 chan, u32 val, u32 reg)
111 {
112         writel(val, i2s->channel_base + (chan * IMG_I2S_OUT_CH_STRIDE) + reg);
113 }
114
115 static inline u32 img_i2s_out_ch_readl(struct img_i2s_out *i2s, u32 chan,
116                                         u32 reg)
117 {
118         return readl(i2s->channel_base + (chan * IMG_I2S_OUT_CH_STRIDE) + reg);
119 }
120
121 static inline void img_i2s_out_ch_disable(struct img_i2s_out *i2s, u32 chan)
122 {
123         u32 reg;
124
125         reg = img_i2s_out_ch_readl(i2s, chan, IMG_I2S_OUT_CH_CTL);
126         reg &= ~IMG_I2S_OUT_CHAN_CTL_ME_MASK;
127         img_i2s_out_ch_writel(i2s, chan, reg, IMG_I2S_OUT_CH_CTL);
128 }
129
130 static inline void img_i2s_out_ch_enable(struct img_i2s_out *i2s, u32 chan)
131 {
132         u32 reg;
133
134         reg = img_i2s_out_ch_readl(i2s, chan, IMG_I2S_OUT_CH_CTL);
135         reg |= IMG_I2S_OUT_CHAN_CTL_ME_MASK;
136         img_i2s_out_ch_writel(i2s, chan, reg, IMG_I2S_OUT_CH_CTL);
137 }
138
139 static inline void img_i2s_out_disable(struct img_i2s_out *i2s)
140 {
141         u32 reg;
142
143         reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
144         reg &= ~IMG_I2S_OUT_CTL_ME_MASK;
145         img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
146 }
147
148 static inline void img_i2s_out_enable(struct img_i2s_out *i2s)
149 {
150         u32 reg;
151
152         reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
153         reg |= IMG_I2S_OUT_CTL_ME_MASK;
154         img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
155 }
156
157 static void img_i2s_out_reset(struct img_i2s_out *i2s)
158 {
159         int i;
160         u32 core_ctl, chan_ctl;
161
162         core_ctl = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL) &
163                         ~IMG_I2S_OUT_CTL_ME_MASK &
164                         ~IMG_I2S_OUT_CTL_DATA_EN_MASK;
165
166         if (!i2s->force_clk_active)
167                 core_ctl &= ~IMG_I2S_OUT_CTL_CLK_EN_MASK;
168
169         chan_ctl = img_i2s_out_ch_readl(i2s, 0, IMG_I2S_OUT_CH_CTL) &
170                         ~IMG_I2S_OUT_CHAN_CTL_ME_MASK;
171
172         reset_control_assert(i2s->rst);
173         reset_control_deassert(i2s->rst);
174
175         for (i = 0; i < i2s->max_i2s_chan; i++)
176                 img_i2s_out_ch_writel(i2s, i, chan_ctl, IMG_I2S_OUT_CH_CTL);
177
178         for (i = 0; i < i2s->active_channels; i++)
179                 img_i2s_out_ch_enable(i2s, i);
180
181         img_i2s_out_writel(i2s, core_ctl, IMG_I2S_OUT_CTL);
182         img_i2s_out_enable(i2s);
183 }
184
185 static int img_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd,
186         struct snd_soc_dai *dai)
187 {
188         struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
189         u32 reg;
190
191         switch (cmd) {
192         case SNDRV_PCM_TRIGGER_START:
193         case SNDRV_PCM_TRIGGER_RESUME:
194         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
195                 reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
196                 if (!i2s->force_clk_active)
197                         reg |= IMG_I2S_OUT_CTL_CLK_EN_MASK;
198                 reg |= IMG_I2S_OUT_CTL_DATA_EN_MASK;
199                 img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
200                 break;
201         case SNDRV_PCM_TRIGGER_STOP:
202         case SNDRV_PCM_TRIGGER_SUSPEND:
203         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
204                 img_i2s_out_reset(i2s);
205                 break;
206         default:
207                 return -EINVAL;
208         }
209
210         return 0;
211 }
212
213 static int img_i2s_out_hw_params(struct snd_pcm_substream *substream,
214         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
215 {
216         struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
217         unsigned int channels, i2s_channels;
218         long pre_div_a, pre_div_b, diff_a, diff_b, rate, clk_rate;
219         int i;
220         u32 reg, control_mask, control_set = 0;
221         snd_pcm_format_t format;
222
223         rate = params_rate(params);
224         format = params_format(params);
225         channels = params_channels(params);
226         i2s_channels = channels / 2;
227
228         if (format != SNDRV_PCM_FORMAT_S32_LE)
229                 return -EINVAL;
230
231         if ((channels < 2) ||
232             (channels > (i2s->max_i2s_chan * 2)) ||
233             (channels % 2))
234                 return -EINVAL;
235
236         pre_div_a = clk_round_rate(i2s->clk_ref, rate * 256);
237         if (pre_div_a < 0)
238                 return pre_div_a;
239         pre_div_b = clk_round_rate(i2s->clk_ref, rate * 384);
240         if (pre_div_b < 0)
241                 return pre_div_b;
242
243         diff_a = abs((pre_div_a / 256) - rate);
244         diff_b = abs((pre_div_b / 384) - rate);
245
246         /* If diffs are equal, use lower clock rate */
247         if (diff_a > diff_b)
248                 clk_set_rate(i2s->clk_ref, pre_div_b);
249         else
250                 clk_set_rate(i2s->clk_ref, pre_div_a);
251
252         /*
253          * Another driver (eg alsa machine driver) may have rejected the above
254          * change. Get the current rate and set the register bit according to
255          * the new minimum diff
256          */
257         clk_rate = clk_get_rate(i2s->clk_ref);
258
259         diff_a = abs((clk_rate / 256) - rate);
260         diff_b = abs((clk_rate / 384) - rate);
261
262         if (diff_a > diff_b)
263                 control_set |= IMG_I2S_OUT_CTL_CLK_MASK;
264
265         control_set |= ((i2s_channels - 1) <<
266                        IMG_I2S_OUT_CTL_ACTIVE_CHAN_SHIFT) &
267                        IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK;
268
269         control_mask = IMG_I2S_OUT_CTL_CLK_MASK |
270                        IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK;
271
272         img_i2s_out_disable(i2s);
273
274         reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
275         reg = (reg & ~control_mask) | control_set;
276         img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
277
278         for (i = 0; i < i2s_channels; i++)
279                 img_i2s_out_ch_enable(i2s, i);
280
281         for (; i < i2s->max_i2s_chan; i++)
282                 img_i2s_out_ch_disable(i2s, i);
283
284         img_i2s_out_enable(i2s);
285
286         i2s->active_channels = i2s_channels;
287
288         return 0;
289 }
290
291 static int img_i2s_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
292 {
293         struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
294         int i, ret;
295         bool force_clk_active;
296         u32 chan_control_mask, control_mask, chan_control_set = 0;
297         u32 reg, control_set = 0;
298
299         force_clk_active = ((fmt & SND_SOC_DAIFMT_CLOCK_MASK) ==
300                         SND_SOC_DAIFMT_CONT);
301
302         if (force_clk_active)
303                 control_set |= IMG_I2S_OUT_CTL_CLK_EN_MASK;
304
305         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
306         case SND_SOC_DAIFMT_CBM_CFM:
307                 break;
308         case SND_SOC_DAIFMT_CBS_CFS:
309                 control_set |= IMG_I2S_OUT_CTL_MASTER_MASK;
310                 break;
311         default:
312                 return -EINVAL;
313         }
314
315         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
316         case SND_SOC_DAIFMT_NB_NF:
317                 control_set |= IMG_I2S_OUT_CTL_BCLK_POL_MASK;
318                 break;
319         case SND_SOC_DAIFMT_NB_IF:
320                 control_set |= IMG_I2S_OUT_CTL_BCLK_POL_MASK;
321                 control_set |= IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK;
322                 break;
323         case SND_SOC_DAIFMT_IB_NF:
324                 break;
325         case SND_SOC_DAIFMT_IB_IF:
326                 control_set |= IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK;
327                 break;
328         default:
329                 return -EINVAL;
330         }
331
332         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
333         case SND_SOC_DAIFMT_I2S:
334                 chan_control_set |= IMG_I2S_OUT_CHAN_CTL_CLKT_MASK;
335                 break;
336         case SND_SOC_DAIFMT_LEFT_J:
337                 break;
338         default:
339                 return -EINVAL;
340         }
341
342         control_mask = IMG_I2S_OUT_CTL_CLK_EN_MASK |
343                        IMG_I2S_OUT_CTL_MASTER_MASK |
344                        IMG_I2S_OUT_CTL_BCLK_POL_MASK |
345                        IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK;
346
347         chan_control_mask = IMG_I2S_OUT_CHAN_CTL_CLKT_MASK;
348
349         ret = pm_runtime_get_sync(i2s->dev);
350         if (ret < 0) {
351                 pm_runtime_put_noidle(i2s->dev);
352                 return ret;
353         }
354
355         img_i2s_out_disable(i2s);
356
357         reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
358         reg = (reg & ~control_mask) | control_set;
359         img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
360
361         for (i = 0; i < i2s->active_channels; i++)
362                 img_i2s_out_ch_disable(i2s, i);
363
364         for (i = 0; i < i2s->max_i2s_chan; i++) {
365                 reg = img_i2s_out_ch_readl(i2s, i, IMG_I2S_OUT_CH_CTL);
366                 reg = (reg & ~chan_control_mask) | chan_control_set;
367                 img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
368         }
369
370         for (i = 0; i < i2s->active_channels; i++)
371                 img_i2s_out_ch_enable(i2s, i);
372
373         img_i2s_out_enable(i2s);
374         pm_runtime_put(i2s->dev);
375
376         i2s->force_clk_active = force_clk_active;
377
378         return 0;
379 }
380
381 static const struct snd_soc_dai_ops img_i2s_out_dai_ops = {
382         .trigger = img_i2s_out_trigger,
383         .hw_params = img_i2s_out_hw_params,
384         .set_fmt = img_i2s_out_set_fmt
385 };
386
387 static int img_i2s_out_dai_probe(struct snd_soc_dai *dai)
388 {
389         struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
390
391         snd_soc_dai_init_dma_data(dai, &i2s->dma_data, NULL);
392
393         return 0;
394 }
395
396 static const struct snd_soc_component_driver img_i2s_out_component = {
397         .name = "img-i2s-out"
398 };
399
400 static int img_i2s_out_dma_prepare_slave_config(struct snd_pcm_substream *st,
401         struct snd_pcm_hw_params *params, struct dma_slave_config *sc)
402 {
403         unsigned int i2s_channels = params_channels(params) / 2;
404         struct snd_soc_pcm_runtime *rtd = st->private_data;
405         struct snd_dmaengine_dai_dma_data *dma_data;
406         int ret;
407
408         dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), st);
409
410         ret = snd_hwparams_to_dma_slave_config(st, params, sc);
411         if (ret)
412                 return ret;
413
414         sc->dst_addr = dma_data->addr;
415         sc->dst_addr_width = dma_data->addr_width;
416         sc->dst_maxburst = 4 * i2s_channels;
417
418         return 0;
419 }
420
421 static const struct snd_dmaengine_pcm_config img_i2s_out_dma_config = {
422         .prepare_slave_config = img_i2s_out_dma_prepare_slave_config
423 };
424
425 static int img_i2s_out_probe(struct platform_device *pdev)
426 {
427         struct img_i2s_out *i2s;
428         struct resource *res;
429         void __iomem *base;
430         int i, ret;
431         unsigned int max_i2s_chan_pow_2;
432         u32 reg;
433         struct device *dev = &pdev->dev;
434
435         i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
436         if (!i2s)
437                 return -ENOMEM;
438
439         platform_set_drvdata(pdev, i2s);
440
441         i2s->dev = &pdev->dev;
442
443         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
444         base = devm_ioremap_resource(&pdev->dev, res);
445         if (IS_ERR(base))
446                 return PTR_ERR(base);
447
448         i2s->base = base;
449
450         if (of_property_read_u32(pdev->dev.of_node, "img,i2s-channels",
451                         &i2s->max_i2s_chan)) {
452                 dev_err(&pdev->dev, "No img,i2s-channels property\n");
453                 return -EINVAL;
454         }
455
456         max_i2s_chan_pow_2 = 1 << get_count_order(i2s->max_i2s_chan);
457
458         i2s->channel_base = base + (max_i2s_chan_pow_2 * 0x20);
459
460         i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, "rst");
461         if (IS_ERR(i2s->rst)) {
462                 if (PTR_ERR(i2s->rst) != -EPROBE_DEFER)
463                         dev_err(&pdev->dev, "No top level reset found\n");
464                 return PTR_ERR(i2s->rst);
465         }
466
467         i2s->clk_sys = devm_clk_get(&pdev->dev, "sys");
468         if (IS_ERR(i2s->clk_sys)) {
469                 if (PTR_ERR(i2s->clk_sys) != -EPROBE_DEFER)
470                         dev_err(dev, "Failed to acquire clock 'sys'\n");
471                 return PTR_ERR(i2s->clk_sys);
472         }
473
474         i2s->clk_ref = devm_clk_get(&pdev->dev, "ref");
475         if (IS_ERR(i2s->clk_ref)) {
476                 if (PTR_ERR(i2s->clk_ref) != -EPROBE_DEFER)
477                         dev_err(dev, "Failed to acquire clock 'ref'\n");
478                 return PTR_ERR(i2s->clk_ref);
479         }
480
481         i2s->suspend_ch_ctl = devm_kcalloc(dev,
482                 i2s->max_i2s_chan, sizeof(*i2s->suspend_ch_ctl), GFP_KERNEL);
483         if (!i2s->suspend_ch_ctl)
484                 return -ENOMEM;
485
486         pm_runtime_enable(&pdev->dev);
487         if (!pm_runtime_enabled(&pdev->dev)) {
488                 ret = img_i2s_out_runtime_resume(&pdev->dev);
489                 if (ret)
490                         goto err_pm_disable;
491         }
492         ret = pm_runtime_get_sync(&pdev->dev);
493         if (ret < 0) {
494                 pm_runtime_put_noidle(&pdev->dev);
495                 goto err_suspend;
496         }
497
498         reg = IMG_I2S_OUT_CTL_FRM_SIZE_MASK;
499         img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
500
501         reg = IMG_I2S_OUT_CHAN_CTL_JUST_MASK |
502                 IMG_I2S_OUT_CHAN_CTL_LT_MASK |
503                 IMG_I2S_OUT_CHAN_CTL_CH_MASK |
504                 (8 << IMG_I2S_OUT_CHAN_CTL_FMT_SHIFT);
505
506         for (i = 0; i < i2s->max_i2s_chan; i++)
507                 img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
508
509         img_i2s_out_reset(i2s);
510         pm_runtime_put(&pdev->dev);
511
512         i2s->active_channels = 1;
513         i2s->dma_data.addr = res->start + IMG_I2S_OUT_TX_FIFO;
514         i2s->dma_data.addr_width = 4;
515         i2s->dma_data.maxburst = 4;
516
517         i2s->dai_driver.probe = img_i2s_out_dai_probe;
518         i2s->dai_driver.playback.channels_min = 2;
519         i2s->dai_driver.playback.channels_max = i2s->max_i2s_chan * 2;
520         i2s->dai_driver.playback.rates = SNDRV_PCM_RATE_8000_192000;
521         i2s->dai_driver.playback.formats = SNDRV_PCM_FMTBIT_S32_LE;
522         i2s->dai_driver.ops = &img_i2s_out_dai_ops;
523
524         ret = devm_snd_soc_register_component(&pdev->dev,
525                         &img_i2s_out_component, &i2s->dai_driver, 1);
526         if (ret)
527                 goto err_suspend;
528
529         ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
530                         &img_i2s_out_dma_config, 0);
531         if (ret)
532                 goto err_suspend;
533
534         return 0;
535
536 err_suspend:
537         if (!pm_runtime_status_suspended(&pdev->dev))
538                 img_i2s_out_runtime_suspend(&pdev->dev);
539 err_pm_disable:
540         pm_runtime_disable(&pdev->dev);
541
542         return ret;
543 }
544
545 static int img_i2s_out_dev_remove(struct platform_device *pdev)
546 {
547         pm_runtime_disable(&pdev->dev);
548         if (!pm_runtime_status_suspended(&pdev->dev))
549                 img_i2s_out_runtime_suspend(&pdev->dev);
550
551         return 0;
552 }
553
554 #ifdef CONFIG_PM_SLEEP
555 static int img_i2s_out_suspend(struct device *dev)
556 {
557         struct img_i2s_out *i2s = dev_get_drvdata(dev);
558         int i, ret;
559         u32 reg;
560
561         if (pm_runtime_status_suspended(dev)) {
562                 ret = img_i2s_out_runtime_resume(dev);
563                 if (ret)
564                         return ret;
565         }
566
567         for (i = 0; i < i2s->max_i2s_chan; i++) {
568                 reg = img_i2s_out_ch_readl(i2s, i, IMG_I2S_OUT_CH_CTL);
569                 i2s->suspend_ch_ctl[i] = reg;
570         }
571
572         i2s->suspend_ctl = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
573
574         img_i2s_out_runtime_suspend(dev);
575
576         return 0;
577 }
578
579 static int img_i2s_out_resume(struct device *dev)
580 {
581         struct img_i2s_out *i2s = dev_get_drvdata(dev);
582         int i, ret;
583         u32 reg;
584
585         ret = img_i2s_out_runtime_resume(dev);
586         if (ret)
587                 return ret;
588
589         for (i = 0; i < i2s->max_i2s_chan; i++) {
590                 reg = i2s->suspend_ch_ctl[i];
591                 img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
592         }
593
594         img_i2s_out_writel(i2s, i2s->suspend_ctl, IMG_I2S_OUT_CTL);
595
596         if (pm_runtime_status_suspended(dev))
597                 img_i2s_out_runtime_suspend(dev);
598
599         return 0;
600 }
601 #endif
602
603 static const struct of_device_id img_i2s_out_of_match[] = {
604         { .compatible = "img,i2s-out" },
605         {}
606 };
607 MODULE_DEVICE_TABLE(of, img_i2s_out_of_match);
608
609 static const struct dev_pm_ops img_i2s_out_pm_ops = {
610         SET_RUNTIME_PM_OPS(img_i2s_out_runtime_suspend,
611                            img_i2s_out_runtime_resume, NULL)
612         SET_SYSTEM_SLEEP_PM_OPS(img_i2s_out_suspend, img_i2s_out_resume)
613 };
614
615 static struct platform_driver img_i2s_out_driver = {
616         .driver = {
617                 .name = "img-i2s-out",
618                 .of_match_table = img_i2s_out_of_match,
619                 .pm = &img_i2s_out_pm_ops
620         },
621         .probe = img_i2s_out_probe,
622         .remove = img_i2s_out_dev_remove
623 };
624 module_platform_driver(img_i2s_out_driver);
625
626 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
627 MODULE_DESCRIPTION("IMG I2S Output Driver");
628 MODULE_LICENSE("GPL v2");