|
14 | 14 | //
|
15 | 15 |
|
16 | 16 | #include <linux/crc8.h>
|
| 17 | +#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C |
| 18 | +#include <linux/debugfs.h> |
| 19 | +#endif |
17 | 20 | #include <linux/firmware.h>
|
18 | 21 | #include <linux/gpio/consumer.h>
|
19 | 22 | #include <linux/i2c.h>
|
@@ -1422,10 +1425,150 @@ static int tasdevice_create_cali_ctrls(struct tasdevice_priv *priv)
|
1422 | 1425 | nctrls < i ? nctrls : i);
|
1423 | 1426 | }
|
1424 | 1427 |
|
| 1428 | +#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C |
| 1429 | +/* |
| 1430 | + * This debugfs node is a bridge to the acoustic tuning application |
| 1431 | + * tool which can tune the chips' acoustic effect. |
| 1432 | + * |
| 1433 | + * package structure for PPC3 communications: |
| 1434 | + * Pkg len (1 byte) |
| 1435 | + * Pkg id (1 byte, 'r' or 'w') |
| 1436 | + * Dev id (1 byte, i2c address) |
| 1437 | + * Book id (1 byte) |
| 1438 | + * Page id (1 byte) |
| 1439 | + * Reg id (1 byte) |
| 1440 | + * switch (pkg id) { |
| 1441 | + * case 'w': |
| 1442 | + * 1 byte, length of data to read |
| 1443 | + * case 'r': |
| 1444 | + * data payload (1~128 bytes) |
| 1445 | + * } |
| 1446 | + */ |
| 1447 | +static ssize_t acoustic_ctl_read(struct file *file, char __user *to, |
| 1448 | + size_t count, loff_t *ppos) |
| 1449 | +{ |
| 1450 | + struct snd_soc_component *comp = file->private_data; |
| 1451 | + struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp); |
| 1452 | + struct acoustic_data *p = &tas_priv->acou_data; |
| 1453 | + int ret = -1; |
| 1454 | + |
| 1455 | + if (p->id == 'r' && p->len == count && count <= sizeof(*p)) |
| 1456 | + ret = simple_read_from_buffer(to, count, ppos, p, p->len); |
| 1457 | + else |
| 1458 | + dev_err(tas_priv->dev, "Not ready for get.\n"); |
| 1459 | + return ret; |
| 1460 | +} |
| 1461 | + |
| 1462 | +static ssize_t acoustic_ctl_write(struct file *file, |
| 1463 | + const char __user *from, size_t count, loff_t *ppos) |
| 1464 | +{ |
| 1465 | + struct snd_soc_component *comp = file->private_data; |
| 1466 | + struct tasdevice_priv *priv = snd_soc_component_get_drvdata(comp); |
| 1467 | + struct acoustic_data *p = &priv->acou_data; |
| 1468 | + unsigned int max_pkg_len = sizeof(*p); |
| 1469 | + unsigned char *src; |
| 1470 | + int j, len, reg, val; |
| 1471 | + unsigned short chn; |
| 1472 | + int ret = -1; |
| 1473 | + |
| 1474 | + if (count > sizeof(*p)) { |
| 1475 | + dev_err(priv->dev, "count(%u) is larger than max(%u).\n", |
| 1476 | + (unsigned int)count, max_pkg_len); |
| 1477 | + return ret; |
| 1478 | + } |
| 1479 | + |
| 1480 | + src = memdup_user(from, count); |
| 1481 | + if (IS_ERR(src)) |
| 1482 | + return PTR_ERR(src); |
| 1483 | + |
| 1484 | + if (src[0] > max_pkg_len && src[0] != count) { |
| 1485 | + dev_err(priv->dev, "pkg(%u), max(%u), count(%u) dismatch.\n", |
| 1486 | + src[0], max_pkg_len, (unsigned int)count); |
| 1487 | + ret = 0; |
| 1488 | + goto exit; |
| 1489 | + } |
| 1490 | + |
| 1491 | + switch (src[1]) { |
| 1492 | + case 'r': |
| 1493 | + /* length of data to read */ |
| 1494 | + len = src[6]; |
| 1495 | + break; |
| 1496 | + case 'w': |
| 1497 | + /* Skip 6 bytes for package type and register address */ |
| 1498 | + len = src[0] - 6; |
| 1499 | + break; |
| 1500 | + default: |
| 1501 | + dev_err(priv->dev, "%s Wrong code %02x.\n", __func__, src[1]); |
| 1502 | + ret = 0; |
| 1503 | + goto exit; |
| 1504 | + } |
| 1505 | + |
| 1506 | + if (len < 1) { |
| 1507 | + dev_err(priv->dev, "pkg fmt invalid %02x.\n", len); |
| 1508 | + ret = 0; |
| 1509 | + goto exit; |
| 1510 | + } |
| 1511 | + |
| 1512 | + for (j = 0; j < priv->ndev; j++) |
| 1513 | + if (src[2] == priv->tasdevice[j].dev_addr) { |
| 1514 | + chn = j; |
| 1515 | + break; |
| 1516 | + } |
| 1517 | + if (j >= priv->ndev) { |
| 1518 | + dev_err(priv->dev, "no such device 0x%02x.\n", src[2]); |
| 1519 | + ret = 0; |
| 1520 | + goto exit; |
| 1521 | + } |
| 1522 | + |
| 1523 | + reg = TASDEVICE_REG(src[3], src[4], src[5]); |
| 1524 | + |
| 1525 | + guard(mutex)(&priv->codec_lock); |
| 1526 | + |
| 1527 | + if (src[1] == 'w') { |
| 1528 | + if (len > 1) |
| 1529 | + ret = tasdevice_dev_bulk_write(priv, chn, reg, |
| 1530 | + &src[6], len); |
| 1531 | + else |
| 1532 | + ret = tasdevice_dev_write(priv, chn, reg, src[6]); |
| 1533 | + } else { |
| 1534 | + struct acoustic_data *p = &priv->acou_data; |
| 1535 | + |
| 1536 | + memcpy(p, src, 6); |
| 1537 | + if (len > 1) { |
| 1538 | + ret = tasdevice_dev_bulk_read(priv, chn, reg, |
| 1539 | + p->data, len); |
| 1540 | + } else { |
| 1541 | + ret = tasdevice_dev_read(priv, chn, reg, &val); |
| 1542 | + p->data[0] = val; |
| 1543 | + } |
| 1544 | + p->len = len + 6; |
| 1545 | + } |
| 1546 | + |
| 1547 | + if (ret) |
| 1548 | + dev_err(priv->dev, "i2c communication error.\n"); |
| 1549 | + else |
| 1550 | + ret = count; |
| 1551 | +exit: |
| 1552 | + kfree(src); |
| 1553 | + return ret; |
| 1554 | +} |
| 1555 | + |
| 1556 | +static const struct file_operations acoustic_ctl_fops = { |
| 1557 | + .open = simple_open, |
| 1558 | + .read = acoustic_ctl_read, |
| 1559 | + .write = acoustic_ctl_write, |
| 1560 | +}; |
| 1561 | +#endif |
| 1562 | + |
1425 | 1563 | static void tasdevice_fw_ready(const struct firmware *fmw,
|
1426 | 1564 | void *context)
|
1427 | 1565 | {
|
1428 | 1566 | struct tasdevice_priv *tas_priv = context;
|
| 1567 | +#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C |
| 1568 | + struct snd_soc_component *comp = tas_priv->codec; |
| 1569 | + struct dentry *debugfs_root = comp->debugfs_root; |
| 1570 | + char *acoustic_debugfs_node; |
| 1571 | +#endif |
1429 | 1572 | int ret = 0;
|
1430 | 1573 | int i;
|
1431 | 1574 |
|
@@ -1499,6 +1642,17 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
|
1499 | 1642 |
|
1500 | 1643 | tasdevice_prmg_load(tas_priv, 0);
|
1501 | 1644 | tas_priv->cur_prog = 0;
|
| 1645 | + |
| 1646 | +#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C |
| 1647 | + if (tas_priv->name_prefix) |
| 1648 | + acoustic_debugfs_node = devm_kasprintf(tas_priv->dev, |
| 1649 | + GFP_KERNEL, "%s_acoustic_ctl", tas_priv->name_prefix); |
| 1650 | + else |
| 1651 | + acoustic_debugfs_node = devm_kstrdup(tas_priv->dev, |
| 1652 | + "acoustic_ctl", GFP_KERNEL); |
| 1653 | + debugfs_create_file(acoustic_debugfs_node, 0644, debugfs_root, |
| 1654 | + comp, &acoustic_ctl_fops); |
| 1655 | +#endif |
1502 | 1656 | out:
|
1503 | 1657 | if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) {
|
1504 | 1658 | /* If DSP FW fail, DSP kcontrol won't be created. */
|
|
0 commit comments