summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolin Chen <nicoleotsuka@gmail.com>2018-02-12 17:03:24 -0500
committerMark Brown <broonie@kernel.org>2018-02-21 07:30:59 -0500
commit76f3845110d7d40eb60c12bc64cdfe431a985947 (patch)
tree43801e0d8ac526de420d4b5e82467a08c41c3cdb
parentbadc9595bc15686be3b01e3554421647de348df0 (diff)
ASoC: fsl_ssi: Move DT related code to a separate probe()
This patch cleans up probe() function by moving all Device Tree related code into a separate function. It allows the probe() to be Device Tree independent. This will be very useful for future integration of imx-ssi driver which has similar functionalities while exists only because it supports non-DT cases. This patch also moves symmetric_channels of AC97 from the probe to the structure snd_soc_dai_driver for simplification. Additionally, since PowerPC and AC97 use the same pdev pointer to register a platform device, this patch also unifies related code. Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com> Tested-by: Caleb Crome <caleb@crome.org> Tested-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> Reviewed-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/fsl/fsl_ssi.c219
1 files changed, 124 insertions, 95 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index b58fabe77c6f..5bc67ad8000f 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -239,8 +239,12 @@ struct fsl_ssi_soc_data {
239 * 239 *
240 * @fiq_params: FIQ stream filtering parameters 240 * @fiq_params: FIQ stream filtering parameters
241 * 241 *
242 * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only) 242 * @card_pdev: Platform_device pointer to register a sound card for PowerPC or
243 * TODO: Should be replaced with simple-sound-card 243 * to register a CODEC platform device for AC97
244 * @card_name: Platform_device name to register a sound card for PowerPC or
245 * to register a CODEC platform device for AC97
246 * @card_idx: The index of SSI to register a sound card for PowerPC or
247 * to register a CODEC platform device for AC97
244 * 248 *
245 * @dbg_stats: Debugging statistics 249 * @dbg_stats: Debugging statistics
246 * 250 *
@@ -285,7 +289,9 @@ struct fsl_ssi {
285 289
286 struct imx_pcm_fiq_params fiq_params; 290 struct imx_pcm_fiq_params fiq_params;
287 291
288 struct platform_device *pdev; 292 struct platform_device *card_pdev;
293 char card_name[32];
294 u32 card_idx;
289 295
290 struct fsl_ssi_dbg dbg_stats; 296 struct fsl_ssi_dbg dbg_stats;
291 297
@@ -1134,6 +1140,7 @@ static const struct snd_soc_component_driver fsl_ssi_component = {
1134 1140
1135static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { 1141static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
1136 .bus_control = true, 1142 .bus_control = true,
1143 .symmetric_channels = 1,
1137 .probe = fsl_ssi_dai_probe, 1144 .probe = fsl_ssi_dai_probe,
1138 .playback = { 1145 .playback = {
1139 .stream_name = "AC97 Playback", 1146 .stream_name = "AC97 Playback",
@@ -1291,9 +1298,7 @@ static void make_lowercase(char *s)
1291static int fsl_ssi_imx_probe(struct platform_device *pdev, 1298static int fsl_ssi_imx_probe(struct platform_device *pdev,
1292 struct fsl_ssi *ssi, void __iomem *iomem) 1299 struct fsl_ssi *ssi, void __iomem *iomem)
1293{ 1300{
1294 struct device_node *np = pdev->dev.of_node;
1295 struct device *dev = &pdev->dev; 1301 struct device *dev = &pdev->dev;
1296 u32 dmas[4];
1297 int ret; 1302 int ret;
1298 1303
1299 /* Backward compatible for a DT without ipg clock name assigned */ 1304 /* Backward compatible for a DT without ipg clock name assigned */
@@ -1327,14 +1332,8 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
1327 ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0; 1332 ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
1328 ssi->dma_params_rx.addr = ssi->ssi_phys + REG_SSI_SRX0; 1333 ssi->dma_params_rx.addr = ssi->ssi_phys + REG_SSI_SRX0;
1329 1334
1330 /* Set to dual FIFO mode according to the SDMA sciprt */ 1335 /* Use even numbers to avoid channel swap due to SDMA script design */
1331 ret = of_property_read_u32_array(np, "dmas", dmas, 4); 1336 if (ssi->use_dual_fifo) {
1332 if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
1333 ssi->use_dual_fifo = true;
1334 /*
1335 * Use even numbers to avoid channel swap due to SDMA
1336 * script design
1337 */
1338 ssi->dma_params_tx.maxburst &= ~0x1; 1337 ssi->dma_params_tx.maxburst &= ~0x1;
1339 ssi->dma_params_rx.maxburst &= ~0x1; 1338 ssi->dma_params_rx.maxburst &= ~0x1;
1340 } 1339 }
@@ -1375,41 +1374,109 @@ static void fsl_ssi_imx_clean(struct platform_device *pdev, struct fsl_ssi *ssi)
1375 clk_disable_unprepare(ssi->clk); 1374 clk_disable_unprepare(ssi->clk);
1376} 1375}
1377 1376
1378static int fsl_ssi_probe(struct platform_device *pdev) 1377static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
1379{ 1378{
1380 struct fsl_ssi *ssi; 1379 struct device *dev = ssi->dev;
1381 int ret = 0; 1380 struct device_node *np = dev->of_node;
1382 struct device_node *np = pdev->dev.of_node;
1383 struct device *dev = &pdev->dev;
1384 const struct of_device_id *of_id; 1381 const struct of_device_id *of_id;
1385 const char *p, *sprop; 1382 const char *p, *sprop;
1386 const __be32 *iprop; 1383 const __be32 *iprop;
1387 struct resource *res; 1384 u32 dmas[4];
1388 void __iomem *iomem; 1385 int ret;
1389 char name[64];
1390 struct regmap_config regconfig = fsl_ssi_regconfig;
1391 1386
1392 of_id = of_match_device(fsl_ssi_ids, dev); 1387 of_id = of_match_device(fsl_ssi_ids, dev);
1393 if (!of_id || !of_id->data) 1388 if (!of_id || !of_id->data)
1394 return -EINVAL; 1389 return -EINVAL;
1395 1390
1396 ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL);
1397 if (!ssi)
1398 return -ENOMEM;
1399
1400 ssi->soc = of_id->data; 1391 ssi->soc = of_id->data;
1401 ssi->dev = dev; 1392
1393 ret = of_property_match_string(np, "clock-names", "ipg");
1394 /* Get error code if not found */
1395 ssi->has_ipg_clk_name = ret >= 0;
1402 1396
1403 /* Check if being used in AC97 mode */ 1397 /* Check if being used in AC97 mode */
1404 sprop = of_get_property(np, "fsl,mode", NULL); 1398 sprop = of_get_property(np, "fsl,mode", NULL);
1405 if (sprop) { 1399 if (sprop && !strcmp(sprop, "ac97-slave")) {
1406 if (!strcmp(sprop, "ac97-slave")) 1400 ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
1407 ssi->dai_fmt = FSLSSI_AC97_DAIFMT; 1401
1402 ret = of_property_read_u32(np, "cell-index", &ssi->card_idx);
1403 if (ret) {
1404 dev_err(dev, "failed to get SSI index property\n");
1405 return -EINVAL;
1406 }
1407 strcpy(ssi->card_name, "ac97-codec");
1408 } else if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) {
1409 /*
1410 * In synchronous mode, STCK and STFS ports are used by RX
1411 * as well. So the software should limit the sample rates,
1412 * sample bits and channels to be symmetric.
1413 *
1414 * This is exclusive with FSLSSI_AC97_FORMATS as AC97 runs
1415 * in the SSI synchronous mode however it does not have to
1416 * limit symmetric sample rates and sample bits.
1417 */
1418 ssi->synchronous = true;
1408 } 1419 }
1409 1420
1410 /* Select DMA or FIQ */ 1421 /* Select DMA or FIQ */
1411 ssi->use_dma = !of_property_read_bool(np, "fsl,fiq-stream-filter"); 1422 ssi->use_dma = !of_property_read_bool(np, "fsl,fiq-stream-filter");
1412 1423
1424 /* Fetch FIFO depth; Set to 8 for older DT without this property */
1425 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
1426 if (iprop)
1427 ssi->fifo_depth = be32_to_cpup(iprop);
1428 else
1429 ssi->fifo_depth = 8;
1430
1431 /* Use dual FIFO mode depending on the support from SDMA script */
1432 ret = of_property_read_u32_array(np, "dmas", dmas, 4);
1433 if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL)
1434 ssi->use_dual_fifo = true;
1435
1436 /*
1437 * Backward compatible for older bindings by manually triggering the
1438 * machine driver's probe(). Use /compatible property, including the
1439 * address of CPU DAI driver structure, as the name of machine driver
1440 *
1441 * If card_name is set by AC97 earlier, bypass here since it uses a
1442 * different name to register the device.
1443 */
1444 if (!ssi->card_name[0] && of_get_property(np, "codec-handle", NULL)) {
1445 sprop = of_get_property(of_find_node_by_path("/"),
1446 "compatible", NULL);
1447 /* Strip "fsl," in the compatible name if applicable */
1448 p = strrchr(sprop, ',');
1449 if (p)
1450 sprop = p + 1;
1451 snprintf(ssi->card_name, sizeof(ssi->card_name),
1452 "snd-soc-%s", sprop);
1453 make_lowercase(ssi->card_name);
1454 ssi->card_idx = 0;
1455 }
1456
1457 return 0;
1458}
1459
1460static int fsl_ssi_probe(struct platform_device *pdev)
1461{
1462 struct regmap_config regconfig = fsl_ssi_regconfig;
1463 struct device *dev = &pdev->dev;
1464 struct fsl_ssi *ssi;
1465 struct resource *res;
1466 void __iomem *iomem;
1467 int ret = 0;
1468
1469 ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL);
1470 if (!ssi)
1471 return -ENOMEM;
1472
1473 ssi->dev = dev;
1474
1475 /* Probe from DT */
1476 ret = fsl_ssi_probe_from_dt(ssi);
1477 if (ret)
1478 return ret;
1479
1413 if (fsl_ssi_is_ac97(ssi)) { 1480 if (fsl_ssi_is_ac97(ssi)) {
1414 memcpy(&ssi->cpu_dai_drv, &fsl_ssi_ac97_dai, 1481 memcpy(&ssi->cpu_dai_drv, &fsl_ssi_ac97_dai,
1415 sizeof(fsl_ssi_ac97_dai)); 1482 sizeof(fsl_ssi_ac97_dai));
@@ -1433,15 +1500,11 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1433 REG_SSI_SRMSK / sizeof(uint32_t) + 1; 1500 REG_SSI_SRMSK / sizeof(uint32_t) + 1;
1434 } 1501 }
1435 1502
1436 ret = of_property_match_string(np, "clock-names", "ipg"); 1503 if (ssi->has_ipg_clk_name)
1437 if (ret < 0) {
1438 ssi->has_ipg_clk_name = false;
1439 ssi->regs = devm_regmap_init_mmio(dev, iomem, &regconfig);
1440 } else {
1441 ssi->has_ipg_clk_name = true;
1442 ssi->regs = devm_regmap_init_mmio_clk(dev, "ipg", iomem, 1504 ssi->regs = devm_regmap_init_mmio_clk(dev, "ipg", iomem,
1443 &regconfig); 1505 &regconfig);
1444 } 1506 else
1507 ssi->regs = devm_regmap_init_mmio(dev, iomem, &regconfig);
1445 if (IS_ERR(ssi->regs)) { 1508 if (IS_ERR(ssi->regs)) {
1446 dev_err(dev, "failed to init register map\n"); 1509 dev_err(dev, "failed to init register map\n");
1447 return PTR_ERR(ssi->regs); 1510 return PTR_ERR(ssi->regs);
@@ -1453,24 +1516,13 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1453 return ssi->irq; 1516 return ssi->irq;
1454 } 1517 }
1455 1518
1456 /* Set software limitations for synchronous mode */ 1519 /* Set software limitations for synchronous mode except AC97 */
1457 if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { 1520 if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) {
1458 if (!fsl_ssi_is_ac97(ssi)) { 1521 ssi->cpu_dai_drv.symmetric_rates = 1;
1459 ssi->cpu_dai_drv.symmetric_rates = 1;
1460 ssi->cpu_dai_drv.symmetric_samplebits = 1;
1461 ssi->synchronous = true;
1462 }
1463
1464 ssi->cpu_dai_drv.symmetric_channels = 1; 1522 ssi->cpu_dai_drv.symmetric_channels = 1;
1523 ssi->cpu_dai_drv.symmetric_samplebits = 1;
1465 } 1524 }
1466 1525
1467 /* Fetch FIFO depth; Set to 8 for older DT without this property */
1468 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
1469 if (iprop)
1470 ssi->fifo_depth = be32_to_cpup(iprop);
1471 else
1472 ssi->fifo_depth = 8;
1473
1474 /* 1526 /*
1475 * Configure TX and RX DMA watermarks -- when to send a DMA request 1527 * Configure TX and RX DMA watermarks -- when to send a DMA request
1476 * 1528 *
@@ -1535,50 +1587,27 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1535 if (ret) 1587 if (ret)
1536 goto error_asoc_register; 1588 goto error_asoc_register;
1537 1589
1538 /* Bypass it if using newer DT bindings of ASoC machine drivers */
1539 if (!of_get_property(np, "codec-handle", NULL))
1540 goto done;
1541
1542 /*
1543 * Backward compatible for older bindings by manually triggering the
1544 * machine driver's probe(). Use /compatible property, including the
1545 * address of CPU DAI driver structure, as the name of machine driver.
1546 */
1547 sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
1548 /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
1549 p = strrchr(sprop, ',');
1550 if (p)
1551 sprop = p + 1;
1552 snprintf(name, sizeof(name), "snd-soc-%s", sprop);
1553 make_lowercase(name);
1554
1555 ssi->pdev = platform_device_register_data(dev, name, 0, NULL, 0);
1556 if (IS_ERR(ssi->pdev)) {
1557 ret = PTR_ERR(ssi->pdev);
1558 dev_err(dev, "failed to register platform: %d\n", ret);
1559 goto error_sound_card;
1560 }
1561
1562done:
1563 /* Initially configures SSI registers */ 1590 /* Initially configures SSI registers */
1564 fsl_ssi_hw_init(ssi); 1591 fsl_ssi_hw_init(ssi);
1565 1592
1566 if (fsl_ssi_is_ac97(ssi)) { 1593 /* Register a platform device for older bindings or AC97 */
1567 u32 ssi_idx; 1594 if (ssi->card_name[0]) {
1568 1595 struct device *parent = dev;
1569 ret = of_property_read_u32(np, "cell-index", &ssi_idx); 1596 /*
1570 if (ret) { 1597 * Do not set SSI dev as the parent of AC97 CODEC device since
1571 dev_err(dev, "failed to get SSI index property\n"); 1598 * it does not have a DT node. Otherwise ASoC core will assume
1572 goto error_sound_card; 1599 * CODEC has the same DT node as the SSI, so it may bypass the
1573 } 1600 * dai_probe() of SSI and then cause NULL DMA data pointers.
1574 1601 */
1575 ssi->pdev = platform_device_register_data(NULL, "ac97-codec", 1602 if (fsl_ssi_is_ac97(ssi))
1576 ssi_idx, NULL, 0); 1603 parent = NULL;
1577 if (IS_ERR(ssi->pdev)) { 1604
1578 ret = PTR_ERR(ssi->pdev); 1605 ssi->card_pdev = platform_device_register_data(parent,
1579 dev_err(dev, 1606 ssi->card_name, ssi->card_idx, NULL, 0);
1580 "failed to register AC97 codec platform: %d\n", 1607 if (IS_ERR(ssi->card_pdev)) {
1581 ret); 1608 ret = PTR_ERR(ssi->card_pdev);
1609 dev_err(dev, "failed to register %s: %d\n",
1610 ssi->card_name, ret);
1582 goto error_sound_card; 1611 goto error_sound_card;
1583 } 1612 }
1584 } 1613 }
@@ -1606,8 +1635,8 @@ static int fsl_ssi_remove(struct platform_device *pdev)
1606 1635
1607 fsl_ssi_debugfs_remove(&ssi->dbg_stats); 1636 fsl_ssi_debugfs_remove(&ssi->dbg_stats);
1608 1637
1609 if (ssi->pdev) 1638 if (ssi->card_pdev)
1610 platform_device_unregister(ssi->pdev); 1639 platform_device_unregister(ssi->card_pdev);
1611 1640
1612 /* Clean up SSI registers */ 1641 /* Clean up SSI registers */
1613 fsl_ssi_hw_clean(ssi); 1642 fsl_ssi_hw_clean(ssi);