diff options
author | Markus Pargmann <mpa@pengutronix.de> | 2014-04-28 06:54:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-05-20 18:02:34 -0400 |
commit | 49da09e26577702516e946ecd537f50b87533315 (patch) | |
tree | e49f74a4ff40bdd18e7a31c5584cb64948a2c339 /sound/soc/fsl | |
parent | 2a1d102de40a799072309d4d84fa6f214c5ee999 (diff) |
ASoC: fsl-ssi: Move imx-specific probe to seperate function
Move imx specific probe code to a seperate function. It reduces the
size of the probe() function and makes the code and error handling
easier to understand.
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 | 185 |
1 files changed, 103 insertions, 82 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 65d9da190d0c..418c64629ee7 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -992,6 +992,100 @@ static void make_lowercase(char *s) | |||
992 | } | 992 | } |
993 | } | 993 | } |
994 | 994 | ||
995 | static int fsl_ssi_imx_probe(struct platform_device *pdev, | ||
996 | struct fsl_ssi_private *ssi_private) | ||
997 | { | ||
998 | struct device_node *np = pdev->dev.of_node; | ||
999 | u32 dma_events[2], dmas[4]; | ||
1000 | bool shared; | ||
1001 | int ret; | ||
1002 | |||
1003 | ssi_private->clk = devm_clk_get(&pdev->dev, NULL); | ||
1004 | if (IS_ERR(ssi_private->clk)) { | ||
1005 | ret = PTR_ERR(ssi_private->clk); | ||
1006 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); | ||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | ret = clk_prepare_enable(ssi_private->clk); | ||
1011 | if (ret) { | ||
1012 | dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); | ||
1013 | return ret; | ||
1014 | } | ||
1015 | |||
1016 | /* For those SLAVE implementations, we ingore non-baudclk cases | ||
1017 | * and, instead, abandon MASTER mode that needs baud clock. | ||
1018 | */ | ||
1019 | ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud"); | ||
1020 | if (IS_ERR(ssi_private->baudclk)) | ||
1021 | dev_dbg(&pdev->dev, "could not get baud clock: %ld\n", | ||
1022 | PTR_ERR(ssi_private->baudclk)); | ||
1023 | else | ||
1024 | clk_prepare_enable(ssi_private->baudclk); | ||
1025 | |||
1026 | /* | ||
1027 | * We have burstsize be "fifo_depth - 2" to match the SSI | ||
1028 | * watermark setting in fsl_ssi_startup(). | ||
1029 | */ | ||
1030 | ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2; | ||
1031 | ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2; | ||
1032 | ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + | ||
1033 | offsetof(struct ccsr_ssi, stx0); | ||
1034 | ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + | ||
1035 | offsetof(struct ccsr_ssi, srx0); | ||
1036 | ssi_private->dma_params_tx.filter_data = &ssi_private->filter_data_tx; | ||
1037 | ssi_private->dma_params_rx.filter_data = &ssi_private->filter_data_rx; | ||
1038 | |||
1039 | if (!of_property_read_bool(pdev->dev.of_node, "dmas") && | ||
1040 | ssi_private->use_dma) { | ||
1041 | /* | ||
1042 | * FIXME: This is a temporary solution until all | ||
1043 | * necessary dma drivers support the generic dma | ||
1044 | * bindings. | ||
1045 | */ | ||
1046 | ret = of_property_read_u32_array(pdev->dev.of_node, | ||
1047 | "fsl,ssi-dma-events", dma_events, 2); | ||
1048 | if (ret && ssi_private->use_dma) { | ||
1049 | dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n"); | ||
1050 | goto error_dma_events; | ||
1051 | } | ||
1052 | } | ||
1053 | /* Should this be merge with the above? */ | ||
1054 | if (!of_property_read_u32_array(pdev->dev.of_node, "dmas", dmas, 4) | ||
1055 | && dmas[2] == IMX_DMATYPE_SSI_DUAL) { | ||
1056 | ssi_private->use_dual_fifo = true; | ||
1057 | /* When using dual fifo mode, we need to keep watermark | ||
1058 | * as even numbers due to dma script limitation. | ||
1059 | */ | ||
1060 | ssi_private->dma_params_tx.maxburst &= ~0x1; | ||
1061 | ssi_private->dma_params_rx.maxburst &= ~0x1; | ||
1062 | } | ||
1063 | |||
1064 | shared = of_device_is_compatible(of_get_parent(np), "fsl,spba-bus"); | ||
1065 | |||
1066 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, | ||
1067 | dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); | ||
1068 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, | ||
1069 | dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); | ||
1070 | |||
1071 | return 0; | ||
1072 | |||
1073 | error_dma_events: | ||
1074 | if (!IS_ERR(ssi_private->baudclk)) | ||
1075 | clk_disable_unprepare(ssi_private->baudclk); | ||
1076 | clk_disable_unprepare(ssi_private->clk); | ||
1077 | |||
1078 | return ret; | ||
1079 | } | ||
1080 | |||
1081 | static void fsl_ssi_imx_clean(struct platform_device *pdev, | ||
1082 | struct fsl_ssi_private *ssi_private) | ||
1083 | { | ||
1084 | if (!IS_ERR(ssi_private->baudclk)) | ||
1085 | clk_disable_unprepare(ssi_private->baudclk); | ||
1086 | clk_disable_unprepare(ssi_private->clk); | ||
1087 | } | ||
1088 | |||
995 | static int fsl_ssi_probe(struct platform_device *pdev) | 1089 | static int fsl_ssi_probe(struct platform_device *pdev) |
996 | { | 1090 | { |
997 | struct fsl_ssi_private *ssi_private; | 1091 | struct fsl_ssi_private *ssi_private; |
@@ -1004,7 +1098,6 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1004 | const uint32_t *iprop; | 1098 | const uint32_t *iprop; |
1005 | struct resource res; | 1099 | struct resource res; |
1006 | char name[64]; | 1100 | char name[64]; |
1007 | bool shared; | ||
1008 | bool ac97 = false; | 1101 | bool ac97 = false; |
1009 | 1102 | ||
1010 | /* SSIs that are not connected on the board should have a | 1103 | /* SSIs that are not connected on the board should have a |
@@ -1118,80 +1211,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1118 | 1211 | ||
1119 | if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 || | 1212 | if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 || |
1120 | hw_type == FSL_SSI_MX35) { | 1213 | hw_type == FSL_SSI_MX35) { |
1121 | u32 dma_events[2], dmas[4]; | ||
1122 | ssi_private->ssi_on_imx = true; | 1214 | ssi_private->ssi_on_imx = true; |
1123 | 1215 | ||
1124 | ssi_private->clk = devm_clk_get(&pdev->dev, NULL); | 1216 | ret = fsl_ssi_imx_probe(pdev, ssi_private); |
1125 | if (IS_ERR(ssi_private->clk)) { | 1217 | if (ret) |
1126 | ret = PTR_ERR(ssi_private->clk); | ||
1127 | dev_err(&pdev->dev, "could not get clock: %d\n", ret); | ||
1128 | goto error_irqmap; | 1218 | goto error_irqmap; |
1129 | } | ||
1130 | ret = clk_prepare_enable(ssi_private->clk); | ||
1131 | if (ret) { | ||
1132 | dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", | ||
1133 | ret); | ||
1134 | goto error_irqmap; | ||
1135 | } | ||
1136 | |||
1137 | /* For those SLAVE implementations, we ingore non-baudclk cases | ||
1138 | * and, instead, abandon MASTER mode that needs baud clock. | ||
1139 | */ | ||
1140 | ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud"); | ||
1141 | if (IS_ERR(ssi_private->baudclk)) | ||
1142 | dev_dbg(&pdev->dev, "could not get baud clock: %ld\n", | ||
1143 | PTR_ERR(ssi_private->baudclk)); | ||
1144 | else | ||
1145 | clk_prepare_enable(ssi_private->baudclk); | ||
1146 | |||
1147 | /* | ||
1148 | * We have burstsize be "fifo_depth - 2" to match the SSI | ||
1149 | * watermark setting in fsl_ssi_startup(). | ||
1150 | */ | ||
1151 | ssi_private->dma_params_tx.maxburst = | ||
1152 | ssi_private->fifo_depth - 2; | ||
1153 | ssi_private->dma_params_rx.maxburst = | ||
1154 | ssi_private->fifo_depth - 2; | ||
1155 | ssi_private->dma_params_tx.addr = | ||
1156 | ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0); | ||
1157 | ssi_private->dma_params_rx.addr = | ||
1158 | ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); | ||
1159 | ssi_private->dma_params_tx.filter_data = | ||
1160 | &ssi_private->filter_data_tx; | ||
1161 | ssi_private->dma_params_rx.filter_data = | ||
1162 | &ssi_private->filter_data_rx; | ||
1163 | if (!of_property_read_bool(pdev->dev.of_node, "dmas") && | ||
1164 | ssi_private->use_dma) { | ||
1165 | /* | ||
1166 | * FIXME: This is a temporary solution until all | ||
1167 | * necessary dma drivers support the generic dma | ||
1168 | * bindings. | ||
1169 | */ | ||
1170 | ret = of_property_read_u32_array(pdev->dev.of_node, | ||
1171 | "fsl,ssi-dma-events", dma_events, 2); | ||
1172 | if (ret && ssi_private->use_dma) { | ||
1173 | dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n"); | ||
1174 | goto error_clk; | ||
1175 | } | ||
1176 | } | ||
1177 | /* Should this be merge with the above? */ | ||
1178 | if (!of_property_read_u32_array(pdev->dev.of_node, "dmas", dmas, 4) | ||
1179 | && dmas[2] == IMX_DMATYPE_SSI_DUAL) { | ||
1180 | ssi_private->use_dual_fifo = true; | ||
1181 | /* When using dual fifo mode, we need to keep watermark | ||
1182 | * as even numbers due to dma script limitation. | ||
1183 | */ | ||
1184 | ssi_private->dma_params_tx.maxburst &= ~0x1; | ||
1185 | ssi_private->dma_params_rx.maxburst &= ~0x1; | ||
1186 | } | ||
1187 | |||
1188 | shared = of_device_is_compatible(of_get_parent(np), | ||
1189 | "fsl,spba-bus"); | ||
1190 | |||
1191 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, | ||
1192 | dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); | ||
1193 | imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, | ||
1194 | dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); | ||
1195 | } | 1219 | } |
1196 | 1220 | ||
1197 | /* | 1221 | /* |
@@ -1206,7 +1230,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1206 | if (ret < 0) { | 1230 | if (ret < 0) { |
1207 | dev_err(&pdev->dev, "could not claim irq %u\n", | 1231 | dev_err(&pdev->dev, "could not claim irq %u\n", |
1208 | ssi_private->irq); | 1232 | ssi_private->irq); |
1209 | goto error_clk; | 1233 | goto error_irq; |
1210 | } | 1234 | } |
1211 | } | 1235 | } |
1212 | 1236 | ||
@@ -1298,11 +1322,9 @@ error_dbgfs: | |||
1298 | error_dev: | 1322 | error_dev: |
1299 | device_remove_file(&pdev->dev, dev_attr); | 1323 | device_remove_file(&pdev->dev, dev_attr); |
1300 | 1324 | ||
1301 | error_clk: | 1325 | error_irq: |
1302 | if (ssi_private->ssi_on_imx) { | 1326 | if (ssi_private->ssi_on_imx) { |
1303 | if (!IS_ERR(ssi_private->baudclk)) | 1327 | fsl_ssi_imx_clean(pdev, ssi_private); |
1304 | clk_disable_unprepare(ssi_private->baudclk); | ||
1305 | clk_disable_unprepare(ssi_private->clk); | ||
1306 | } | 1328 | } |
1307 | 1329 | ||
1308 | error_irqmap: | 1330 | error_irqmap: |
@@ -1321,11 +1343,10 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
1321 | if (!ssi_private->new_binding) | 1343 | if (!ssi_private->new_binding) |
1322 | platform_device_unregister(ssi_private->pdev); | 1344 | platform_device_unregister(ssi_private->pdev); |
1323 | snd_soc_unregister_component(&pdev->dev); | 1345 | snd_soc_unregister_component(&pdev->dev); |
1324 | if (ssi_private->ssi_on_imx) { | 1346 | |
1325 | if (!IS_ERR(ssi_private->baudclk)) | 1347 | if (ssi_private->ssi_on_imx) |
1326 | clk_disable_unprepare(ssi_private->baudclk); | 1348 | fsl_ssi_imx_clean(pdev, ssi_private); |
1327 | clk_disable_unprepare(ssi_private->clk); | 1349 | |
1328 | } | ||
1329 | if (ssi_private->irq_stats) | 1350 | if (ssi_private->irq_stats) |
1330 | irq_dispose_mapping(ssi_private->irq); | 1351 | irq_dispose_mapping(ssi_private->irq); |
1331 | 1352 | ||