Linux-libre 5.4.49-gnu
[librecmc/linux-libre.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                 return ret;
352
353         img_i2s_out_disable(i2s);
354
355         reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
356         reg = (reg & ~control_mask) | control_set;
357         img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
358
359         for (i = 0; i < i2s->active_channels; i++)
360                 img_i2s_out_ch_disable(i2s, i);
361
362         for (i = 0; i < i2s->max_i2s_chan; i++) {
363                 reg = img_i2s_out_ch_readl(i2s, i, IMG_I2S_OUT_CH_CTL);
364                 reg = (reg & ~chan_control_mask) | chan_control_set;
365                 img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
366         }
367
368         for (i = 0; i < i2s->active_channels; i++)
369                 img_i2s_out_ch_enable(i2s, i);
370
371         img_i2s_out_enable(i2s);
372         pm_runtime_put(i2s->dev);
373
374         i2s->force_clk_active = force_clk_active;
375
376         return 0;
377 }
378
379 static const struct snd_soc_dai_ops img_i2s_out_dai_ops = {
380         .trigger = img_i2s_out_trigger,
381         .hw_params = img_i2s_out_hw_params,
382         .set_fmt = img_i2s_out_set_fmt
383 };
384
385 static int img_i2s_out_dai_probe(struct snd_soc_dai *dai)
386 {
387         struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
388
389         snd_soc_dai_init_dma_data(dai, &i2s->dma_data, NULL);
390
391         return 0;
392 }
393
394 static const struct snd_soc_component_driver img_i2s_out_component = {
395         .name = "img-i2s-out"
396 };
397
398 static int img_i2s_out_dma_prepare_slave_config(struct snd_pcm_substream *st,
399         struct snd_pcm_hw_params *params, struct dma_slave_config *sc)
400 {
401         unsigned int i2s_channels = params_channels(params) / 2;
402         struct snd_soc_pcm_runtime *rtd = st->private_data;
403         struct snd_dmaengine_dai_dma_data *dma_data;
404         int ret;
405
406         dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, st);
407
408         ret = snd_hwparams_to_dma_slave_config(st, params, sc);
409         if (ret)
410                 return ret;
411
412         sc->dst_addr = dma_data->addr;
413         sc->dst_addr_width = dma_data->addr_width;
414         sc->dst_maxburst = 4 * i2s_channels;
415
416         return 0;
417 }
418
419 static const struct snd_dmaengine_pcm_config img_i2s_out_dma_config = {
420         .prepare_slave_config = img_i2s_out_dma_prepare_slave_config
421 };
422
423 static int img_i2s_out_probe(struct platform_device *pdev)
424 {
425         struct img_i2s_out *i2s;
426         struct resource *res;
427         void __iomem *base;
428         int i, ret;
429         unsigned int max_i2s_chan_pow_2;
430         u32 reg;
431         struct device *dev = &pdev->dev;
432
433         i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
434         if (!i2s)
435                 return -ENOMEM;
436
437         platform_set_drvdata(pdev, i2s);
438
439         i2s->dev = &pdev->dev;
440
441         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
442         base = devm_ioremap_resource(&pdev->dev, res);
443         if (IS_ERR(base))
444                 return PTR_ERR(base);
445
446         i2s->base = base;
447
448         if (of_property_read_u32(pdev->dev.of_node, "img,i2s-channels",
449                         &i2s->max_i2s_chan)) {
450                 dev_err(&pdev->dev, "No img,i2s-channels property\n");
451                 return -EINVAL;
452         }
453
454         max_i2s_chan_pow_2 = 1 << get_count_order(i2s->max_i2s_chan);
455
456         i2s->channel_base = base + (max_i2s_chan_pow_2 * 0x20);
457
458         i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, "rst");
459         if (IS_ERR(i2s->rst)) {
460                 if (PTR_ERR(i2s->rst) != -EPROBE_DEFER)
461                         dev_err(&pdev->dev, "No top level reset found\n");
462                 return PTR_ERR(i2s->rst);
463         }
464
465         i2s->clk_sys = devm_clk_get(&pdev->dev, "sys");
466         if (IS_ERR(i2s->clk_sys)) {
467                 if (PTR_ERR(i2s->clk_sys) != -EPROBE_DEFER)
468                         dev_err(dev, "Failed to acquire clock 'sys'\n");
469                 return PTR_ERR(i2s->clk_sys);
470         }
471
472         i2s->clk_ref = devm_clk_get(&pdev->dev, "ref");
473         if (IS_ERR(i2s->clk_ref)) {
474                 if (PTR_ERR(i2s->clk_ref) != -EPROBE_DEFER)
475                         dev_err(dev, "Failed to acquire clock 'ref'\n");
476                 return PTR_ERR(i2s->clk_ref);
477         }
478
479         i2s->suspend_ch_ctl = devm_kcalloc(dev,
480                 i2s->max_i2s_chan, sizeof(*i2s->suspend_ch_ctl), GFP_KERNEL);
481         if (!i2s->suspend_ch_ctl)
482                 return -ENOMEM;
483
484         pm_runtime_enable(&pdev->dev);
485         if (!pm_runtime_enabled(&pdev->dev)) {
486                 ret = img_i2s_out_runtime_resume(&pdev->dev);
487                 if (ret)
488                         goto err_pm_disable;
489         }
490         ret = pm_runtime_get_sync(&pdev->dev);
491         if (ret < 0)
492                 goto err_suspend;
493
494         reg = IMG_I2S_OUT_CTL_FRM_SIZE_MASK;
495         img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
496
497         reg = IMG_I2S_OUT_CHAN_CTL_JUST_MASK |
498                 IMG_I2S_OUT_CHAN_CTL_LT_MASK |
499                 IMG_I2S_OUT_CHAN_CTL_CH_MASK |
500                 (8 << IMG_I2S_OUT_CHAN_CTL_FMT_SHIFT);
501
502         for (i = 0; i < i2s->max_i2s_chan; i++)
503                 img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
504
505         img_i2s_out_reset(i2s);
506         pm_runtime_put(&pdev->dev);
507
508         i2s->active_channels = 1;
509         i2s->dma_data.addr = res->start + IMG_I2S_OUT_TX_FIFO;
510         i2s->dma_data.addr_width = 4;
511         i2s->dma_data.maxburst = 4;
512
513         i2s->dai_driver.probe = img_i2s_out_dai_probe;
514         i2s->dai_driver.playback.channels_min = 2;
515         i2s->dai_driver.playback.channels_max = i2s->max_i2s_chan * 2;
516         i2s->dai_driver.playback.rates = SNDRV_PCM_RATE_8000_192000;
517         i2s->dai_driver.playback.formats = SNDRV_PCM_FMTBIT_S32_LE;
518         i2s->dai_driver.ops = &img_i2s_out_dai_ops;
519
520         ret = devm_snd_soc_register_component(&pdev->dev,
521                         &img_i2s_out_component, &i2s->dai_driver, 1);
522         if (ret)
523                 goto err_suspend;
524
525         ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
526                         &img_i2s_out_dma_config, 0);
527         if (ret)
528                 goto err_suspend;
529
530         return 0;
531
532 err_suspend:
533         if (!pm_runtime_status_suspended(&pdev->dev))
534                 img_i2s_out_runtime_suspend(&pdev->dev);
535 err_pm_disable:
536         pm_runtime_disable(&pdev->dev);
537
538         return ret;
539 }
540
541 static int img_i2s_out_dev_remove(struct platform_device *pdev)
542 {
543         pm_runtime_disable(&pdev->dev);
544         if (!pm_runtime_status_suspended(&pdev->dev))
545                 img_i2s_out_runtime_suspend(&pdev->dev);
546
547         return 0;
548 }
549
550 #ifdef CONFIG_PM_SLEEP
551 static int img_i2s_out_suspend(struct device *dev)
552 {
553         struct img_i2s_out *i2s = dev_get_drvdata(dev);
554         int i, ret;
555         u32 reg;
556
557         if (pm_runtime_status_suspended(dev)) {
558                 ret = img_i2s_out_runtime_resume(dev);
559                 if (ret)
560                         return ret;
561         }
562
563         for (i = 0; i < i2s->max_i2s_chan; i++) {
564                 reg = img_i2s_out_ch_readl(i2s, i, IMG_I2S_OUT_CH_CTL);
565                 i2s->suspend_ch_ctl[i] = reg;
566         }
567
568         i2s->suspend_ctl = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
569
570         img_i2s_out_runtime_suspend(dev);
571
572         return 0;
573 }
574
575 static int img_i2s_out_resume(struct device *dev)
576 {
577         struct img_i2s_out *i2s = dev_get_drvdata(dev);
578         int i, ret;
579         u32 reg;
580
581         ret = img_i2s_out_runtime_resume(dev);
582         if (ret)
583                 return ret;
584
585         for (i = 0; i < i2s->max_i2s_chan; i++) {
586                 reg = i2s->suspend_ch_ctl[i];
587                 img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
588         }
589
590         img_i2s_out_writel(i2s, i2s->suspend_ctl, IMG_I2S_OUT_CTL);
591
592         if (pm_runtime_status_suspended(dev))
593                 img_i2s_out_runtime_suspend(dev);
594
595         return 0;
596 }
597 #endif
598
599 static const struct of_device_id img_i2s_out_of_match[] = {
600         { .compatible = "img,i2s-out" },
601         {}
602 };
603 MODULE_DEVICE_TABLE(of, img_i2s_out_of_match);
604
605 static const struct dev_pm_ops img_i2s_out_pm_ops = {
606         SET_RUNTIME_PM_OPS(img_i2s_out_runtime_suspend,
607                            img_i2s_out_runtime_resume, NULL)
608         SET_SYSTEM_SLEEP_PM_OPS(img_i2s_out_suspend, img_i2s_out_resume)
609 };
610
611 static struct platform_driver img_i2s_out_driver = {
612         .driver = {
613                 .name = "img-i2s-out",
614                 .of_match_table = img_i2s_out_of_match,
615                 .pm = &img_i2s_out_pm_ops
616         },
617         .probe = img_i2s_out_probe,
618         .remove = img_i2s_out_dev_remove
619 };
620 module_platform_driver(img_i2s_out_driver);
621
622 MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
623 MODULE_DESCRIPTION("IMG I2S Output Driver");
624 MODULE_LICENSE("GPL v2");