diff options
Diffstat (limited to 'sound/soc/davinci/davinci-mcasp.c')
| -rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 169 |
1 files changed, 117 insertions, 52 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 32ddb7fe5034..71e14bb3a8cd 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
| @@ -1001,18 +1001,40 @@ static const struct snd_soc_component_driver davinci_mcasp_component = { | |||
| 1001 | .name = "davinci-mcasp", | 1001 | .name = "davinci-mcasp", |
| 1002 | }; | 1002 | }; |
| 1003 | 1003 | ||
| 1004 | /* Some HW specific values and defaults. The rest is filled in from DT. */ | ||
| 1005 | static struct snd_platform_data dm646x_mcasp_pdata = { | ||
| 1006 | .tx_dma_offset = 0x400, | ||
| 1007 | .rx_dma_offset = 0x400, | ||
| 1008 | .asp_chan_q = EVENTQ_0, | ||
| 1009 | .version = MCASP_VERSION_1, | ||
| 1010 | }; | ||
| 1011 | |||
| 1012 | static struct snd_platform_data da830_mcasp_pdata = { | ||
| 1013 | .tx_dma_offset = 0x2000, | ||
| 1014 | .rx_dma_offset = 0x2000, | ||
| 1015 | .asp_chan_q = EVENTQ_0, | ||
| 1016 | .version = MCASP_VERSION_2, | ||
| 1017 | }; | ||
| 1018 | |||
| 1019 | static struct snd_platform_data omap2_mcasp_pdata = { | ||
| 1020 | .tx_dma_offset = 0, | ||
| 1021 | .rx_dma_offset = 0, | ||
| 1022 | .asp_chan_q = EVENTQ_0, | ||
| 1023 | .version = MCASP_VERSION_3, | ||
| 1024 | }; | ||
| 1025 | |||
| 1004 | static const struct of_device_id mcasp_dt_ids[] = { | 1026 | static const struct of_device_id mcasp_dt_ids[] = { |
| 1005 | { | 1027 | { |
| 1006 | .compatible = "ti,dm646x-mcasp-audio", | 1028 | .compatible = "ti,dm646x-mcasp-audio", |
| 1007 | .data = (void *)MCASP_VERSION_1, | 1029 | .data = &dm646x_mcasp_pdata, |
| 1008 | }, | 1030 | }, |
| 1009 | { | 1031 | { |
| 1010 | .compatible = "ti,da830-mcasp-audio", | 1032 | .compatible = "ti,da830-mcasp-audio", |
| 1011 | .data = (void *)MCASP_VERSION_2, | 1033 | .data = &da830_mcasp_pdata, |
| 1012 | }, | 1034 | }, |
| 1013 | { | 1035 | { |
| 1014 | .compatible = "ti,omap2-mcasp-audio", | 1036 | .compatible = "ti,am33xx-mcasp-audio", |
| 1015 | .data = (void *)MCASP_VERSION_3, | 1037 | .data = &omap2_mcasp_pdata, |
| 1016 | }, | 1038 | }, |
| 1017 | { /* sentinel */ } | 1039 | { /* sentinel */ } |
| 1018 | }; | 1040 | }; |
| @@ -1025,9 +1047,9 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
| 1025 | struct snd_platform_data *pdata = NULL; | 1047 | struct snd_platform_data *pdata = NULL; |
| 1026 | const struct of_device_id *match = | 1048 | const struct of_device_id *match = |
| 1027 | of_match_device(mcasp_dt_ids, &pdev->dev); | 1049 | of_match_device(mcasp_dt_ids, &pdev->dev); |
| 1050 | struct of_phandle_args dma_spec; | ||
| 1028 | 1051 | ||
| 1029 | const u32 *of_serial_dir32; | 1052 | const u32 *of_serial_dir32; |
| 1030 | u8 *of_serial_dir; | ||
| 1031 | u32 val; | 1053 | u32 val; |
| 1032 | int i, ret = 0; | 1054 | int i, ret = 0; |
| 1033 | 1055 | ||
| @@ -1035,20 +1057,13 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
| 1035 | pdata = pdev->dev.platform_data; | 1057 | pdata = pdev->dev.platform_data; |
| 1036 | return pdata; | 1058 | return pdata; |
| 1037 | } else if (match) { | 1059 | } else if (match) { |
| 1038 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 1060 | pdata = (struct snd_platform_data *) match->data; |
| 1039 | if (!pdata) { | ||
| 1040 | ret = -ENOMEM; | ||
| 1041 | goto nodata; | ||
| 1042 | } | ||
| 1043 | } else { | 1061 | } else { |
| 1044 | /* control shouldn't reach here. something is wrong */ | 1062 | /* control shouldn't reach here. something is wrong */ |
| 1045 | ret = -EINVAL; | 1063 | ret = -EINVAL; |
| 1046 | goto nodata; | 1064 | goto nodata; |
| 1047 | } | 1065 | } |
| 1048 | 1066 | ||
| 1049 | if (match->data) | ||
| 1050 | pdata->version = (u8)((int)match->data); | ||
| 1051 | |||
| 1052 | ret = of_property_read_u32(np, "op-mode", &val); | 1067 | ret = of_property_read_u32(np, "op-mode", &val); |
| 1053 | if (ret >= 0) | 1068 | if (ret >= 0) |
| 1054 | pdata->op_mode = val; | 1069 | pdata->op_mode = val; |
| @@ -1065,35 +1080,46 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
| 1065 | pdata->tdm_slots = val; | 1080 | pdata->tdm_slots = val; |
| 1066 | } | 1081 | } |
| 1067 | 1082 | ||
| 1068 | ret = of_property_read_u32(np, "num-serializer", &val); | ||
| 1069 | if (ret >= 0) | ||
| 1070 | pdata->num_serializer = val; | ||
| 1071 | |||
| 1072 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); | 1083 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); |
| 1073 | val /= sizeof(u32); | 1084 | val /= sizeof(u32); |
| 1074 | if (val != pdata->num_serializer) { | ||
| 1075 | dev_err(&pdev->dev, | ||
| 1076 | "num-serializer(%d) != serial-dir size(%d)\n", | ||
| 1077 | pdata->num_serializer, val); | ||
| 1078 | ret = -EINVAL; | ||
| 1079 | goto nodata; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | if (of_serial_dir32) { | 1085 | if (of_serial_dir32) { |
| 1083 | of_serial_dir = devm_kzalloc(&pdev->dev, | 1086 | u8 *of_serial_dir = devm_kzalloc(&pdev->dev, |
| 1084 | (sizeof(*of_serial_dir) * val), | 1087 | (sizeof(*of_serial_dir) * val), |
| 1085 | GFP_KERNEL); | 1088 | GFP_KERNEL); |
| 1086 | if (!of_serial_dir) { | 1089 | if (!of_serial_dir) { |
| 1087 | ret = -ENOMEM; | 1090 | ret = -ENOMEM; |
| 1088 | goto nodata; | 1091 | goto nodata; |
| 1089 | } | 1092 | } |
| 1090 | 1093 | ||
| 1091 | for (i = 0; i < pdata->num_serializer; i++) | 1094 | for (i = 0; i < val; i++) |
| 1092 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); | 1095 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); |
| 1093 | 1096 | ||
| 1097 | pdata->num_serializer = val; | ||
| 1094 | pdata->serial_dir = of_serial_dir; | 1098 | pdata->serial_dir = of_serial_dir; |
| 1095 | } | 1099 | } |
| 1096 | 1100 | ||
| 1101 | ret = of_property_match_string(np, "dma-names", "tx"); | ||
| 1102 | if (ret < 0) | ||
| 1103 | goto nodata; | ||
| 1104 | |||
| 1105 | ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, | ||
| 1106 | &dma_spec); | ||
| 1107 | if (ret < 0) | ||
| 1108 | goto nodata; | ||
| 1109 | |||
| 1110 | pdata->tx_dma_channel = dma_spec.args[0]; | ||
| 1111 | |||
| 1112 | ret = of_property_match_string(np, "dma-names", "rx"); | ||
| 1113 | if (ret < 0) | ||
| 1114 | goto nodata; | ||
| 1115 | |||
| 1116 | ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, | ||
| 1117 | &dma_spec); | ||
| 1118 | if (ret < 0) | ||
| 1119 | goto nodata; | ||
| 1120 | |||
| 1121 | pdata->rx_dma_channel = dma_spec.args[0]; | ||
| 1122 | |||
| 1097 | ret = of_property_read_u32(np, "tx-num-evt", &val); | 1123 | ret = of_property_read_u32(np, "tx-num-evt", &val); |
| 1098 | if (ret >= 0) | 1124 | if (ret >= 0) |
| 1099 | pdata->txnumevt = val; | 1125 | pdata->txnumevt = val; |
| @@ -1124,7 +1150,7 @@ nodata: | |||
| 1124 | static int davinci_mcasp_probe(struct platform_device *pdev) | 1150 | static int davinci_mcasp_probe(struct platform_device *pdev) |
| 1125 | { | 1151 | { |
| 1126 | struct davinci_pcm_dma_params *dma_data; | 1152 | struct davinci_pcm_dma_params *dma_data; |
| 1127 | struct resource *mem, *ioarea, *res; | 1153 | struct resource *mem, *ioarea, *res, *dat; |
| 1128 | struct snd_platform_data *pdata; | 1154 | struct snd_platform_data *pdata; |
| 1129 | struct davinci_audio_dev *dev; | 1155 | struct davinci_audio_dev *dev; |
| 1130 | int ret; | 1156 | int ret; |
| @@ -1145,10 +1171,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 1145 | return -EINVAL; | 1171 | return -EINVAL; |
| 1146 | } | 1172 | } |
| 1147 | 1173 | ||
| 1148 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1174 | mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
| 1149 | if (!mem) { | 1175 | if (!mem) { |
| 1150 | dev_err(&pdev->dev, "no mem resource?\n"); | 1176 | dev_warn(dev->dev, |
| 1151 | return -ENODEV; | 1177 | "\"mpu\" mem resource not found, using index 0\n"); |
| 1178 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1179 | if (!mem) { | ||
| 1180 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
| 1181 | return -ENODEV; | ||
| 1182 | } | ||
| 1152 | } | 1183 | } |
| 1153 | 1184 | ||
| 1154 | ioarea = devm_request_mem_region(&pdev->dev, mem->start, | 1185 | ioarea = devm_request_mem_region(&pdev->dev, mem->start, |
| @@ -1182,40 +1213,36 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 1182 | dev->rxnumevt = pdata->rxnumevt; | 1213 | dev->rxnumevt = pdata->rxnumevt; |
| 1183 | dev->dev = &pdev->dev; | 1214 | dev->dev = &pdev->dev; |
| 1184 | 1215 | ||
| 1216 | dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); | ||
| 1217 | if (!dat) | ||
| 1218 | dat = mem; | ||
| 1219 | |||
| 1185 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 1220 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
| 1186 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1221 | dma_data->asp_chan_q = pdata->asp_chan_q; |
| 1187 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1222 | dma_data->ram_chan_q = pdata->ram_chan_q; |
| 1188 | dma_data->sram_pool = pdata->sram_pool; | 1223 | dma_data->sram_pool = pdata->sram_pool; |
| 1189 | dma_data->sram_size = pdata->sram_size_playback; | 1224 | dma_data->sram_size = pdata->sram_size_playback; |
| 1190 | dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + | 1225 | dma_data->dma_addr = dat->start + pdata->tx_dma_offset; |
| 1191 | mem->start); | ||
| 1192 | 1226 | ||
| 1193 | /* first TX, then RX */ | ||
| 1194 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1227 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
| 1195 | if (!res) { | 1228 | if (res) |
| 1196 | dev_err(&pdev->dev, "no DMA resource\n"); | 1229 | dma_data->channel = res->start; |
| 1197 | ret = -ENODEV; | 1230 | else |
| 1198 | goto err_release_clk; | 1231 | dma_data->channel = pdata->tx_dma_channel; |
| 1199 | } | ||
| 1200 | |||
| 1201 | dma_data->channel = res->start; | ||
| 1202 | 1232 | ||
| 1203 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; | 1233 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; |
| 1204 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1234 | dma_data->asp_chan_q = pdata->asp_chan_q; |
| 1205 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1235 | dma_data->ram_chan_q = pdata->ram_chan_q; |
| 1206 | dma_data->sram_pool = pdata->sram_pool; | 1236 | dma_data->sram_pool = pdata->sram_pool; |
| 1207 | dma_data->sram_size = pdata->sram_size_capture; | 1237 | dma_data->sram_size = pdata->sram_size_capture; |
| 1208 | dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + | 1238 | dma_data->dma_addr = dat->start + pdata->rx_dma_offset; |
| 1209 | mem->start); | ||
| 1210 | 1239 | ||
| 1211 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 1240 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
| 1212 | if (!res) { | 1241 | if (res) |
| 1213 | dev_err(&pdev->dev, "no DMA resource\n"); | 1242 | dma_data->channel = res->start; |
| 1214 | ret = -ENODEV; | 1243 | else |
| 1215 | goto err_release_clk; | 1244 | dma_data->channel = pdata->rx_dma_channel; |
| 1216 | } | ||
| 1217 | 1245 | ||
| 1218 | dma_data->channel = res->start; | ||
| 1219 | dev_set_drvdata(&pdev->dev, dev); | 1246 | dev_set_drvdata(&pdev->dev, dev); |
| 1220 | ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, | 1247 | ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, |
| 1221 | &davinci_mcasp_dai[pdata->op_mode], 1); | 1248 | &davinci_mcasp_dai[pdata->op_mode], 1); |
| @@ -1251,12 +1278,51 @@ static int davinci_mcasp_remove(struct platform_device *pdev) | |||
| 1251 | return 0; | 1278 | return 0; |
| 1252 | } | 1279 | } |
| 1253 | 1280 | ||
| 1281 | #ifdef CONFIG_PM_SLEEP | ||
| 1282 | static int davinci_mcasp_suspend(struct device *dev) | ||
| 1283 | { | ||
| 1284 | struct davinci_audio_dev *a = dev_get_drvdata(dev); | ||
| 1285 | void __iomem *base = a->base; | ||
| 1286 | |||
| 1287 | a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG); | ||
| 1288 | a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG); | ||
| 1289 | a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG); | ||
| 1290 | a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG); | ||
| 1291 | a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG); | ||
| 1292 | a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG); | ||
| 1293 | a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG); | ||
| 1294 | |||
| 1295 | return 0; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | static int davinci_mcasp_resume(struct device *dev) | ||
| 1299 | { | ||
| 1300 | struct davinci_audio_dev *a = dev_get_drvdata(dev); | ||
| 1301 | void __iomem *base = a->base; | ||
| 1302 | |||
| 1303 | mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl); | ||
| 1304 | mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl); | ||
| 1305 | mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt); | ||
| 1306 | mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt); | ||
| 1307 | mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl); | ||
| 1308 | mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl); | ||
| 1309 | mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir); | ||
| 1310 | |||
| 1311 | return 0; | ||
| 1312 | } | ||
| 1313 | #endif | ||
| 1314 | |||
| 1315 | SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops, | ||
| 1316 | davinci_mcasp_suspend, | ||
| 1317 | davinci_mcasp_resume); | ||
| 1318 | |||
| 1254 | static struct platform_driver davinci_mcasp_driver = { | 1319 | static struct platform_driver davinci_mcasp_driver = { |
| 1255 | .probe = davinci_mcasp_probe, | 1320 | .probe = davinci_mcasp_probe, |
| 1256 | .remove = davinci_mcasp_remove, | 1321 | .remove = davinci_mcasp_remove, |
| 1257 | .driver = { | 1322 | .driver = { |
| 1258 | .name = "davinci-mcasp", | 1323 | .name = "davinci-mcasp", |
| 1259 | .owner = THIS_MODULE, | 1324 | .owner = THIS_MODULE, |
| 1325 | .pm = &davinci_mcasp_pm_ops, | ||
| 1260 | .of_match_table = mcasp_dt_ids, | 1326 | .of_match_table = mcasp_dt_ids, |
| 1261 | }, | 1327 | }, |
| 1262 | }; | 1328 | }; |
| @@ -1266,4 +1332,3 @@ module_platform_driver(davinci_mcasp_driver); | |||
| 1266 | MODULE_AUTHOR("Steve Chen"); | 1332 | MODULE_AUTHOR("Steve Chen"); |
| 1267 | MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); | 1333 | MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); |
| 1268 | MODULE_LICENSE("GPL"); | 1334 | MODULE_LICENSE("GPL"); |
| 1269 | |||
