Merge commit 'v3.15' into next
[firefly-linux-kernel-4.4.55.git] / sound / soc / sirf / sirf-audio-port.c
1 /*
2  * SiRF Audio port driver
3  *
4  * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5  *
6  * Licensed under GPLv2 or later.
7  */
8 #include <linux/module.h>
9 #include <linux/io.h>
10 #include <linux/regmap.h>
11 #include <sound/soc.h>
12 #include <sound/dmaengine_pcm.h>
13
14 #include "sirf-audio-port.h"
15
16 struct sirf_audio_port {
17         struct regmap *regmap;
18         struct snd_dmaengine_dai_dma_data playback_dma_data;
19         struct snd_dmaengine_dai_dma_data capture_dma_data;
20 };
21
22 static void sirf_audio_port_tx_enable(struct sirf_audio_port *port)
23 {
24         regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP,
25                 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
26         regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0);
27         regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
28         regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP,
29                 AUDIO_FIFO_START, AUDIO_FIFO_START);
30         regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL,
31                 IC_TX_ENABLE, IC_TX_ENABLE);
32 }
33
34 static void sirf_audio_port_tx_disable(struct sirf_audio_port *port)
35 {
36         regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0);
37         regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL,
38                 IC_TX_ENABLE, ~IC_TX_ENABLE);
39 }
40
41 static void sirf_audio_port_rx_enable(struct sirf_audio_port *port,
42         int channels)
43 {
44         regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP,
45                 AUDIO_FIFO_RESET, AUDIO_FIFO_RESET);
46         regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0);
47         regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0);
48         regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP,
49                 AUDIO_FIFO_START, AUDIO_FIFO_START);
50         if (channels == 1)
51                 regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL,
52                         IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO);
53         else
54                 regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL,
55                         IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO);
56 }
57
58 static void sirf_audio_port_rx_disable(struct sirf_audio_port *port)
59 {
60         regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL,
61                         IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO);
62 }
63
64 static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai)
65 {
66         struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai);
67         snd_soc_dai_init_dma_data(dai, &port->playback_dma_data,
68                         &port->capture_dma_data);
69         return 0;
70 }
71
72 static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd,
73         struct snd_soc_dai *dai)
74 {
75         struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai);
76         int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
77
78         switch (cmd) {
79         case SNDRV_PCM_TRIGGER_STOP:
80         case SNDRV_PCM_TRIGGER_SUSPEND:
81         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
82                 if (playback)
83                         sirf_audio_port_tx_disable(port);
84                 else
85                         sirf_audio_port_rx_disable(port);
86                 break;
87         case SNDRV_PCM_TRIGGER_START:
88         case SNDRV_PCM_TRIGGER_RESUME:
89         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
90                 if (playback)
91                         sirf_audio_port_tx_enable(port);
92                 else
93                         sirf_audio_port_rx_enable(port,
94                                 substream->runtime->channels);
95                 break;
96         default:
97                 return -EINVAL;
98         }
99
100         return 0;
101 }
102
103 static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = {
104         .trigger = sirf_audio_port_trigger,
105 };
106
107 static struct snd_soc_dai_driver sirf_audio_port_dai = {
108         .probe = sirf_audio_port_dai_probe,
109         .name = "sirf-audio-port",
110         .id = 0,
111         .playback = {
112                 .channels_min = 2,
113                 .channels_max = 2,
114                 .rates = SNDRV_PCM_RATE_48000,
115                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
116         },
117         .capture = {
118                 .channels_min = 1,
119                 .channels_max = 2,
120                 .rates = SNDRV_PCM_RATE_48000,
121                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
122         },
123         .ops = &sirf_audio_port_dai_ops,
124 };
125
126 static const struct snd_soc_component_driver sirf_audio_port_component = {
127         .name       = "sirf-audio-port",
128 };
129
130 static const struct regmap_config sirf_audio_port_regmap_config = {
131         .reg_bits = 32,
132         .reg_stride = 4,
133         .val_bits = 32,
134         .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK,
135         .cache_type = REGCACHE_NONE,
136 };
137
138 static int sirf_audio_port_probe(struct platform_device *pdev)
139 {
140         int ret;
141         struct sirf_audio_port *port;
142         void __iomem *base;
143         struct resource *mem_res;
144
145         port = devm_kzalloc(&pdev->dev,
146                         sizeof(struct sirf_audio_port), GFP_KERNEL);
147         if (!port)
148                 return -ENOMEM;
149
150         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
151         if (!mem_res) {
152                 dev_err(&pdev->dev, "no mem resource?\n");
153                 return -ENODEV;
154         }
155
156         base = devm_ioremap(&pdev->dev, mem_res->start,
157                         resource_size(mem_res));
158         if (base == NULL)
159                 return -ENOMEM;
160
161         port->regmap = devm_regmap_init_mmio(&pdev->dev, base,
162                                             &sirf_audio_port_regmap_config);
163         if (IS_ERR(port->regmap))
164                 return PTR_ERR(port->regmap);
165
166         ret = devm_snd_soc_register_component(&pdev->dev,
167                         &sirf_audio_port_component, &sirf_audio_port_dai, 1);
168         if (ret)
169                 return ret;
170
171         platform_set_drvdata(pdev, port);
172         return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
173 }
174
175 static const struct of_device_id sirf_audio_port_of_match[] = {
176         { .compatible = "sirf,audio-port", },
177         {}
178 };
179 MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match);
180
181 static struct platform_driver sirf_audio_port_driver = {
182         .driver = {
183                 .name = "sirf-audio-port",
184                 .owner = THIS_MODULE,
185                 .of_match_table = sirf_audio_port_of_match,
186         },
187         .probe = sirf_audio_port_probe,
188 };
189
190 module_platform_driver(sirf_audio_port_driver);
191
192 MODULE_DESCRIPTION("SiRF Audio Port driver");
193 MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
194 MODULE_LICENSE("GPL v2");