diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-05-27 04:24:18 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-06-01 06:55:07 -0400 |
commit | fcdbadef378bc9cc64cb8cbfd96c23fc15812923 (patch) | |
tree | 8653171ca7facc25a719939a3392dfb4c8f21bf5 /sound/soc/fsl | |
parent | b20e53a826a7adc3bfd2772bd49a83b6f21b4cce (diff) |
ASoC: fsl-ssi: introduce SoC specific data
Introduce a SoC data struct which contains the differences between
the different SoCs this driver supports. This makes it easy to support
more differences without having to introduce a new switch/case each
time.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Tested-By: Michael Grzeschik <mgr@pengutronix.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 125 |
1 files changed, 57 insertions, 68 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index ef504257e105..fa650112925a 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -132,6 +132,12 @@ struct fsl_ssi_rxtx_reg_val { | |||
132 | struct fsl_ssi_reg_val tx; | 132 | struct fsl_ssi_reg_val tx; |
133 | }; | 133 | }; |
134 | 134 | ||
135 | struct fsl_ssi_soc_data { | ||
136 | bool imx; | ||
137 | bool offline_config; | ||
138 | u32 sisr_write_mask; | ||
139 | }; | ||
140 | |||
135 | /** | 141 | /** |
136 | * fsl_ssi_private: per-SSI private data | 142 | * fsl_ssi_private: per-SSI private data |
137 | * | 143 | * |
@@ -153,7 +159,6 @@ struct fsl_ssi_private { | |||
153 | struct platform_device *pdev; | 159 | struct platform_device *pdev; |
154 | unsigned int dai_fmt; | 160 | unsigned int dai_fmt; |
155 | 161 | ||
156 | enum fsl_ssi_type hw_type; | ||
157 | bool use_dma; | 162 | bool use_dma; |
158 | bool baudclk_locked; | 163 | bool baudclk_locked; |
159 | bool use_dual_fifo; | 164 | bool use_dual_fifo; |
@@ -168,35 +173,9 @@ struct fsl_ssi_private { | |||
168 | struct fsl_ssi_rxtx_reg_val rxtx_reg_val; | 173 | struct fsl_ssi_rxtx_reg_val rxtx_reg_val; |
169 | 174 | ||
170 | struct fsl_ssi_dbg dbg_stats; | 175 | struct fsl_ssi_dbg dbg_stats; |
171 | }; | ||
172 | 176 | ||
173 | static const struct of_device_id fsl_ssi_ids[] = { | 177 | const struct fsl_ssi_soc_data *soc; |
174 | { .compatible = "fsl,mpc8610-ssi", .data = (void *) FSL_SSI_MCP8610}, | ||
175 | { .compatible = "fsl,imx51-ssi", .data = (void *) FSL_SSI_MX51}, | ||
176 | { .compatible = "fsl,imx35-ssi", .data = (void *) FSL_SSI_MX35}, | ||
177 | { .compatible = "fsl,imx21-ssi", .data = (void *) FSL_SSI_MX21}, | ||
178 | {} | ||
179 | }; | 178 | }; |
180 | MODULE_DEVICE_TABLE(of, fsl_ssi_ids); | ||
181 | |||
182 | static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private) | ||
183 | { | ||
184 | return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97); | ||
185 | } | ||
186 | |||
187 | static bool fsl_ssi_on_imx(struct fsl_ssi_private *ssi_private) | ||
188 | { | ||
189 | switch (ssi_private->hw_type) { | ||
190 | case FSL_SSI_MX21: | ||
191 | case FSL_SSI_MX35: | ||
192 | case FSL_SSI_MX51: | ||
193 | return true; | ||
194 | case FSL_SSI_MCP8610: | ||
195 | return false; | ||
196 | } | ||
197 | |||
198 | return false; | ||
199 | } | ||
200 | 179 | ||
201 | /* | 180 | /* |
202 | * imx51 and later SoCs have a slightly different IP that allows the | 181 | * imx51 and later SoCs have a slightly different IP that allows the |
@@ -213,18 +192,48 @@ static bool fsl_ssi_on_imx(struct fsl_ssi_private *ssi_private) | |||
213 | * while the SSI unit is running (SSIEN). So we support the necessary | 192 | * while the SSI unit is running (SSIEN). So we support the necessary |
214 | * online configuration of fsl-ssi starting at imx51. | 193 | * online configuration of fsl-ssi starting at imx51. |
215 | */ | 194 | */ |
216 | static bool fsl_ssi_offline_config(struct fsl_ssi_private *ssi_private) | ||
217 | { | ||
218 | switch (ssi_private->hw_type) { | ||
219 | case FSL_SSI_MCP8610: | ||
220 | case FSL_SSI_MX21: | ||
221 | case FSL_SSI_MX35: | ||
222 | return true; | ||
223 | case FSL_SSI_MX51: | ||
224 | return false; | ||
225 | } | ||
226 | 195 | ||
227 | return true; | 196 | static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = { |
197 | .imx = false, | ||
198 | .offline_config = true, | ||
199 | .sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC | | ||
200 | CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 | | ||
201 | CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1, | ||
202 | }; | ||
203 | |||
204 | static struct fsl_ssi_soc_data fsl_ssi_imx21 = { | ||
205 | .imx = true, | ||
206 | .offline_config = true, | ||
207 | .sisr_write_mask = 0, | ||
208 | }; | ||
209 | |||
210 | static struct fsl_ssi_soc_data fsl_ssi_imx35 = { | ||
211 | .imx = true, | ||
212 | .offline_config = true, | ||
213 | .sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC | | ||
214 | CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 | | ||
215 | CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1, | ||
216 | }; | ||
217 | |||
218 | static struct fsl_ssi_soc_data fsl_ssi_imx51 = { | ||
219 | .imx = true, | ||
220 | .offline_config = false, | ||
221 | .sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 | | ||
222 | CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1, | ||
223 | }; | ||
224 | |||
225 | static const struct of_device_id fsl_ssi_ids[] = { | ||
226 | { .compatible = "fsl,mpc8610-ssi", .data = &fsl_ssi_mpc8610 }, | ||
227 | { .compatible = "fsl,imx51-ssi", .data = &fsl_ssi_imx51 }, | ||
228 | { .compatible = "fsl,imx35-ssi", .data = &fsl_ssi_imx35 }, | ||
229 | { .compatible = "fsl,imx21-ssi", .data = &fsl_ssi_imx21 }, | ||
230 | {} | ||
231 | }; | ||
232 | MODULE_DEVICE_TABLE(of, fsl_ssi_ids); | ||
233 | |||
234 | static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private) | ||
235 | { | ||
236 | return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97); | ||
228 | } | 237 | } |
229 | 238 | ||
230 | /** | 239 | /** |
@@ -245,25 +254,6 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
245 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 254 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
246 | __be32 sisr; | 255 | __be32 sisr; |
247 | __be32 sisr2; | 256 | __be32 sisr2; |
248 | __be32 sisr_write_mask = 0; | ||
249 | |||
250 | switch (ssi_private->hw_type) { | ||
251 | case FSL_SSI_MX21: | ||
252 | sisr_write_mask = 0; | ||
253 | break; | ||
254 | |||
255 | case FSL_SSI_MCP8610: | ||
256 | case FSL_SSI_MX35: | ||
257 | sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC | | ||
258 | CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 | | ||
259 | CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1; | ||
260 | break; | ||
261 | |||
262 | case FSL_SSI_MX51: | ||
263 | sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 | | ||
264 | CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1; | ||
265 | break; | ||
266 | } | ||
267 | 257 | ||
268 | /* We got an interrupt, so read the status register to see what we | 258 | /* We got an interrupt, so read the status register to see what we |
269 | were interrupted for. We mask it with the Interrupt Enable register | 259 | were interrupted for. We mask it with the Interrupt Enable register |
@@ -271,7 +261,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
271 | */ | 261 | */ |
272 | sisr = read_ssi(&ssi->sisr); | 262 | sisr = read_ssi(&ssi->sisr); |
273 | 263 | ||
274 | sisr2 = sisr & sisr_write_mask; | 264 | sisr2 = sisr & ssi_private->soc->sisr_write_mask; |
275 | /* Clear the bits that we set */ | 265 | /* Clear the bits that we set */ |
276 | if (sisr2) | 266 | if (sisr2) |
277 | write_ssi(sisr2, &ssi->sisr); | 267 | write_ssi(sisr2, &ssi->sisr); |
@@ -359,7 +349,7 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable, | |||
359 | * reconfiguration, so we have to enable all necessary flags at once | 349 | * reconfiguration, so we have to enable all necessary flags at once |
360 | * even if we do not use them later (capture and playback configuration) | 350 | * even if we do not use them later (capture and playback configuration) |
361 | */ | 351 | */ |
362 | if (fsl_ssi_offline_config(ssi_private)) { | 352 | if (ssi_private->soc->offline_config) { |
363 | if ((enable && !nr_active_streams) || | 353 | if ((enable && !nr_active_streams) || |
364 | (!enable && !keep_active)) | 354 | (!enable && !keep_active)) |
365 | fsl_ssi_rxtx_config(ssi_private, enable); | 355 | fsl_ssi_rxtx_config(ssi_private, enable); |
@@ -915,7 +905,7 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | |||
915 | { | 905 | { |
916 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); | 906 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); |
917 | 907 | ||
918 | if (fsl_ssi_on_imx(ssi_private) && ssi_private->use_dma) { | 908 | if (ssi_private->soc->imx && ssi_private->use_dma) { |
919 | dai->playback_dma_data = &ssi_private->dma_params_tx; | 909 | dai->playback_dma_data = &ssi_private->dma_params_tx; |
920 | dai->capture_dma_data = &ssi_private->dma_params_rx; | 910 | dai->capture_dma_data = &ssi_private->dma_params_rx; |
921 | } | 911 | } |
@@ -1141,7 +1131,6 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1141 | int ret = 0; | 1131 | int ret = 0; |
1142 | struct device_node *np = pdev->dev.of_node; | 1132 | struct device_node *np = pdev->dev.of_node; |
1143 | const struct of_device_id *of_id; | 1133 | const struct of_device_id *of_id; |
1144 | enum fsl_ssi_type hw_type; | ||
1145 | const char *p, *sprop; | 1134 | const char *p, *sprop; |
1146 | const uint32_t *iprop; | 1135 | const uint32_t *iprop; |
1147 | struct resource res; | 1136 | struct resource res; |
@@ -1156,9 +1145,8 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1156 | return -ENODEV; | 1145 | return -ENODEV; |
1157 | 1146 | ||
1158 | of_id = of_match_device(fsl_ssi_ids, &pdev->dev); | 1147 | of_id = of_match_device(fsl_ssi_ids, &pdev->dev); |
1159 | if (!of_id) | 1148 | if (!of_id || !of_id->data) |
1160 | return -EINVAL; | 1149 | return -EINVAL; |
1161 | hw_type = (enum fsl_ssi_type) of_id->data; | ||
1162 | 1150 | ||
1163 | sprop = of_get_property(np, "fsl,mode", NULL); | 1151 | sprop = of_get_property(np, "fsl,mode", NULL); |
1164 | if (!sprop) { | 1152 | if (!sprop) { |
@@ -1175,9 +1163,10 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1175 | return -ENOMEM; | 1163 | return -ENOMEM; |
1176 | } | 1164 | } |
1177 | 1165 | ||
1166 | ssi_private->soc = of_id->data; | ||
1167 | |||
1178 | ssi_private->use_dma = !of_property_read_bool(np, | 1168 | ssi_private->use_dma = !of_property_read_bool(np, |
1179 | "fsl,fiq-stream-filter"); | 1169 | "fsl,fiq-stream-filter"); |
1180 | ssi_private->hw_type = hw_type; | ||
1181 | 1170 | ||
1182 | if (ac97) { | 1171 | if (ac97) { |
1183 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, | 1172 | memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai, |
@@ -1232,7 +1221,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1232 | 1221 | ||
1233 | dev_set_drvdata(&pdev->dev, ssi_private); | 1222 | dev_set_drvdata(&pdev->dev, ssi_private); |
1234 | 1223 | ||
1235 | if (fsl_ssi_on_imx(ssi_private)) { | 1224 | if (ssi_private->soc->imx) { |
1236 | ret = fsl_ssi_imx_probe(pdev, ssi_private, ssi_private->ssi); | 1225 | ret = fsl_ssi_imx_probe(pdev, ssi_private, ssi_private->ssi); |
1237 | if (ret) | 1226 | if (ret) |
1238 | goto error_irqmap; | 1227 | goto error_irqmap; |
@@ -1299,7 +1288,7 @@ error_irq: | |||
1299 | snd_soc_unregister_component(&pdev->dev); | 1288 | snd_soc_unregister_component(&pdev->dev); |
1300 | 1289 | ||
1301 | error_asoc_register: | 1290 | error_asoc_register: |
1302 | if (fsl_ssi_on_imx(ssi_private)) | 1291 | if (ssi_private->soc->imx) |
1303 | fsl_ssi_imx_clean(pdev, ssi_private); | 1292 | fsl_ssi_imx_clean(pdev, ssi_private); |
1304 | 1293 | ||
1305 | error_irqmap: | 1294 | error_irqmap: |
@@ -1319,7 +1308,7 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
1319 | platform_device_unregister(ssi_private->pdev); | 1308 | platform_device_unregister(ssi_private->pdev); |
1320 | snd_soc_unregister_component(&pdev->dev); | 1309 | snd_soc_unregister_component(&pdev->dev); |
1321 | 1310 | ||
1322 | if (fsl_ssi_on_imx(ssi_private)) | 1311 | if (ssi_private->soc->imx) |
1323 | fsl_ssi_imx_clean(pdev, ssi_private); | 1312 | fsl_ssi_imx_clean(pdev, ssi_private); |
1324 | 1313 | ||
1325 | if (ssi_private->use_dma) | 1314 | if (ssi_private->use_dma) |