diff options
| -rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 186 |
1 files changed, 110 insertions, 76 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 429b694405c7..fc149ea64be7 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -275,7 +275,8 @@ struct mxt_data { | |||
| 275 | char phys[64]; /* device physical location */ | 275 | char phys[64]; /* device physical location */ |
| 276 | const struct mxt_platform_data *pdata; | 276 | const struct mxt_platform_data *pdata; |
| 277 | struct mxt_object *object_table; | 277 | struct mxt_object *object_table; |
| 278 | struct mxt_info info; | 278 | struct mxt_info *info; |
| 279 | void *raw_info_block; | ||
| 279 | unsigned int irq; | 280 | unsigned int irq; |
| 280 | unsigned int max_x; | 281 | unsigned int max_x; |
| 281 | unsigned int max_y; | 282 | unsigned int max_y; |
| @@ -450,12 +451,13 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) | |||
| 450 | { | 451 | { |
| 451 | u8 appmode = data->client->addr; | 452 | u8 appmode = data->client->addr; |
| 452 | u8 bootloader; | 453 | u8 bootloader; |
| 454 | u8 family_id = data->info ? data->info->family_id : 0; | ||
| 453 | 455 | ||
| 454 | switch (appmode) { | 456 | switch (appmode) { |
| 455 | case 0x4a: | 457 | case 0x4a: |
| 456 | case 0x4b: | 458 | case 0x4b: |
| 457 | /* Chips after 1664S use different scheme */ | 459 | /* Chips after 1664S use different scheme */ |
| 458 | if (retry || data->info.family_id >= 0xa2) { | 460 | if (retry || family_id >= 0xa2) { |
| 459 | bootloader = appmode - 0x24; | 461 | bootloader = appmode - 0x24; |
| 460 | break; | 462 | break; |
| 461 | } | 463 | } |
| @@ -682,7 +684,7 @@ mxt_get_object(struct mxt_data *data, u8 type) | |||
| 682 | struct mxt_object *object; | 684 | struct mxt_object *object; |
| 683 | int i; | 685 | int i; |
| 684 | 686 | ||
| 685 | for (i = 0; i < data->info.object_num; i++) { | 687 | for (i = 0; i < data->info->object_num; i++) { |
| 686 | object = data->object_table + i; | 688 | object = data->object_table + i; |
| 687 | if (object->type == type) | 689 | if (object->type == type) |
| 688 | return object; | 690 | return object; |
| @@ -1453,12 +1455,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1453 | data_pos += offset; | 1455 | data_pos += offset; |
| 1454 | } | 1456 | } |
| 1455 | 1457 | ||
| 1456 | if (cfg_info.family_id != data->info.family_id) { | 1458 | if (cfg_info.family_id != data->info->family_id) { |
| 1457 | dev_err(dev, "Family ID mismatch!\n"); | 1459 | dev_err(dev, "Family ID mismatch!\n"); |
| 1458 | return -EINVAL; | 1460 | return -EINVAL; |
| 1459 | } | 1461 | } |
| 1460 | 1462 | ||
| 1461 | if (cfg_info.variant_id != data->info.variant_id) { | 1463 | if (cfg_info.variant_id != data->info->variant_id) { |
| 1462 | dev_err(dev, "Variant ID mismatch!\n"); | 1464 | dev_err(dev, "Variant ID mismatch!\n"); |
| 1463 | return -EINVAL; | 1465 | return -EINVAL; |
| 1464 | } | 1466 | } |
| @@ -1503,7 +1505,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1503 | 1505 | ||
| 1504 | /* Malloc memory to store configuration */ | 1506 | /* Malloc memory to store configuration */ |
| 1505 | cfg_start_ofs = MXT_OBJECT_START + | 1507 | cfg_start_ofs = MXT_OBJECT_START + |
| 1506 | data->info.object_num * sizeof(struct mxt_object) + | 1508 | data->info->object_num * sizeof(struct mxt_object) + |
| 1507 | MXT_INFO_CHECKSUM_SIZE; | 1509 | MXT_INFO_CHECKSUM_SIZE; |
| 1508 | config_mem_size = data->mem_size - cfg_start_ofs; | 1510 | config_mem_size = data->mem_size - cfg_start_ofs; |
| 1509 | config_mem = kzalloc(config_mem_size, GFP_KERNEL); | 1511 | config_mem = kzalloc(config_mem_size, GFP_KERNEL); |
| @@ -1554,20 +1556,6 @@ release_mem: | |||
| 1554 | return ret; | 1556 | return ret; |
| 1555 | } | 1557 | } |
| 1556 | 1558 | ||
| 1557 | static int mxt_get_info(struct mxt_data *data) | ||
| 1558 | { | ||
| 1559 | struct i2c_client *client = data->client; | ||
| 1560 | struct mxt_info *info = &data->info; | ||
| 1561 | int error; | ||
| 1562 | |||
| 1563 | /* Read 7-byte info block starting at address 0 */ | ||
| 1564 | error = __mxt_read_reg(client, 0, sizeof(*info), info); | ||
| 1565 | if (error) | ||
| 1566 | return error; | ||
| 1567 | |||
| 1568 | return 0; | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | static void mxt_free_input_device(struct mxt_data *data) | 1559 | static void mxt_free_input_device(struct mxt_data *data) |
| 1572 | { | 1560 | { |
| 1573 | if (data->input_dev) { | 1561 | if (data->input_dev) { |
| @@ -1582,9 +1570,10 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
| 1582 | video_unregister_device(&data->dbg.vdev); | 1570 | video_unregister_device(&data->dbg.vdev); |
| 1583 | v4l2_device_unregister(&data->dbg.v4l2); | 1571 | v4l2_device_unregister(&data->dbg.v4l2); |
| 1584 | #endif | 1572 | #endif |
| 1585 | |||
| 1586 | kfree(data->object_table); | ||
| 1587 | data->object_table = NULL; | 1573 | data->object_table = NULL; |
| 1574 | data->info = NULL; | ||
| 1575 | kfree(data->raw_info_block); | ||
| 1576 | data->raw_info_block = NULL; | ||
| 1588 | kfree(data->msg_buf); | 1577 | kfree(data->msg_buf); |
| 1589 | data->msg_buf = NULL; | 1578 | data->msg_buf = NULL; |
| 1590 | data->T5_address = 0; | 1579 | data->T5_address = 0; |
| @@ -1600,34 +1589,18 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
| 1600 | data->max_reportid = 0; | 1589 | data->max_reportid = 0; |
| 1601 | } | 1590 | } |
| 1602 | 1591 | ||
| 1603 | static int mxt_get_object_table(struct mxt_data *data) | 1592 | static int mxt_parse_object_table(struct mxt_data *data, |
| 1593 | struct mxt_object *object_table) | ||
| 1604 | { | 1594 | { |
| 1605 | struct i2c_client *client = data->client; | 1595 | struct i2c_client *client = data->client; |
| 1606 | size_t table_size; | ||
| 1607 | struct mxt_object *object_table; | ||
| 1608 | int error; | ||
| 1609 | int i; | 1596 | int i; |
| 1610 | u8 reportid; | 1597 | u8 reportid; |
| 1611 | u16 end_address; | 1598 | u16 end_address; |
| 1612 | 1599 | ||
| 1613 | table_size = data->info.object_num * sizeof(struct mxt_object); | ||
| 1614 | object_table = kzalloc(table_size, GFP_KERNEL); | ||
| 1615 | if (!object_table) { | ||
| 1616 | dev_err(&data->client->dev, "Failed to allocate memory\n"); | ||
| 1617 | return -ENOMEM; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | error = __mxt_read_reg(client, MXT_OBJECT_START, table_size, | ||
| 1621 | object_table); | ||
| 1622 | if (error) { | ||
| 1623 | kfree(object_table); | ||
| 1624 | return error; | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | /* Valid Report IDs start counting from 1 */ | 1600 | /* Valid Report IDs start counting from 1 */ |
| 1628 | reportid = 1; | 1601 | reportid = 1; |
| 1629 | data->mem_size = 0; | 1602 | data->mem_size = 0; |
| 1630 | for (i = 0; i < data->info.object_num; i++) { | 1603 | for (i = 0; i < data->info->object_num; i++) { |
| 1631 | struct mxt_object *object = object_table + i; | 1604 | struct mxt_object *object = object_table + i; |
| 1632 | u8 min_id, max_id; | 1605 | u8 min_id, max_id; |
| 1633 | 1606 | ||
| @@ -1651,8 +1624,8 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
| 1651 | 1624 | ||
| 1652 | switch (object->type) { | 1625 | switch (object->type) { |
| 1653 | case MXT_GEN_MESSAGE_T5: | 1626 | case MXT_GEN_MESSAGE_T5: |
| 1654 | if (data->info.family_id == 0x80 && | 1627 | if (data->info->family_id == 0x80 && |
| 1655 | data->info.version < 0x20) { | 1628 | data->info->version < 0x20) { |
| 1656 | /* | 1629 | /* |
| 1657 | * On mXT224 firmware versions prior to V2.0 | 1630 | * On mXT224 firmware versions prior to V2.0 |
| 1658 | * read and discard unused CRC byte otherwise | 1631 | * read and discard unused CRC byte otherwise |
| @@ -1707,24 +1680,102 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
| 1707 | /* If T44 exists, T5 position has to be directly after */ | 1680 | /* If T44 exists, T5 position has to be directly after */ |
| 1708 | if (data->T44_address && (data->T5_address != data->T44_address + 1)) { | 1681 | if (data->T44_address && (data->T5_address != data->T44_address + 1)) { |
| 1709 | dev_err(&client->dev, "Invalid T44 position\n"); | 1682 | dev_err(&client->dev, "Invalid T44 position\n"); |
| 1710 | error = -EINVAL; | 1683 | return -EINVAL; |
| 1711 | goto free_object_table; | ||
| 1712 | } | 1684 | } |
| 1713 | 1685 | ||
| 1714 | data->msg_buf = kcalloc(data->max_reportid, | 1686 | data->msg_buf = kcalloc(data->max_reportid, |
| 1715 | data->T5_msg_size, GFP_KERNEL); | 1687 | data->T5_msg_size, GFP_KERNEL); |
| 1716 | if (!data->msg_buf) { | 1688 | if (!data->msg_buf) |
| 1717 | dev_err(&client->dev, "Failed to allocate message buffer\n"); | 1689 | return -ENOMEM; |
| 1690 | |||
| 1691 | return 0; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | static int mxt_read_info_block(struct mxt_data *data) | ||
| 1695 | { | ||
| 1696 | struct i2c_client *client = data->client; | ||
| 1697 | int error; | ||
| 1698 | size_t size; | ||
| 1699 | void *id_buf, *buf; | ||
| 1700 | uint8_t num_objects; | ||
| 1701 | u32 calculated_crc; | ||
| 1702 | u8 *crc_ptr; | ||
| 1703 | |||
| 1704 | /* If info block already allocated, free it */ | ||
| 1705 | if (data->raw_info_block) | ||
| 1706 | mxt_free_object_table(data); | ||
| 1707 | |||
| 1708 | /* Read 7-byte ID information block starting at address 0 */ | ||
| 1709 | size = sizeof(struct mxt_info); | ||
| 1710 | id_buf = kzalloc(size, GFP_KERNEL); | ||
| 1711 | if (!id_buf) | ||
| 1712 | return -ENOMEM; | ||
| 1713 | |||
| 1714 | error = __mxt_read_reg(client, 0, size, id_buf); | ||
| 1715 | if (error) | ||
| 1716 | goto err_free_mem; | ||
| 1717 | |||
| 1718 | /* Resize buffer to give space for rest of info block */ | ||
| 1719 | num_objects = ((struct mxt_info *)id_buf)->object_num; | ||
| 1720 | size += (num_objects * sizeof(struct mxt_object)) | ||
| 1721 | + MXT_INFO_CHECKSUM_SIZE; | ||
| 1722 | |||
| 1723 | buf = krealloc(id_buf, size, GFP_KERNEL); | ||
| 1724 | if (!buf) { | ||
| 1718 | error = -ENOMEM; | 1725 | error = -ENOMEM; |
| 1719 | goto free_object_table; | 1726 | goto err_free_mem; |
| 1727 | } | ||
| 1728 | id_buf = buf; | ||
| 1729 | |||
| 1730 | /* Read rest of info block */ | ||
| 1731 | error = __mxt_read_reg(client, MXT_OBJECT_START, | ||
| 1732 | size - MXT_OBJECT_START, | ||
| 1733 | id_buf + MXT_OBJECT_START); | ||
| 1734 | if (error) | ||
| 1735 | goto err_free_mem; | ||
| 1736 | |||
| 1737 | /* Extract & calculate checksum */ | ||
| 1738 | crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE; | ||
| 1739 | data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16); | ||
| 1740 | |||
| 1741 | calculated_crc = mxt_calculate_crc(id_buf, 0, | ||
| 1742 | size - MXT_INFO_CHECKSUM_SIZE); | ||
| 1743 | |||
| 1744 | /* | ||
| 1745 | * CRC mismatch can be caused by data corruption due to I2C comms | ||
| 1746 | * issue or else device is not using Object Based Protocol (eg i2c-hid) | ||
| 1747 | */ | ||
| 1748 | if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) { | ||
| 1749 | dev_err(&client->dev, | ||
| 1750 | "Info Block CRC error calculated=0x%06X read=0x%06X\n", | ||
| 1751 | calculated_crc, data->info_crc); | ||
| 1752 | error = -EIO; | ||
| 1753 | goto err_free_mem; | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | data->raw_info_block = id_buf; | ||
| 1757 | data->info = (struct mxt_info *)id_buf; | ||
| 1758 | |||
| 1759 | dev_info(&client->dev, | ||
| 1760 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", | ||
| 1761 | data->info->family_id, data->info->variant_id, | ||
| 1762 | data->info->version >> 4, data->info->version & 0xf, | ||
| 1763 | data->info->build, data->info->object_num); | ||
| 1764 | |||
| 1765 | /* Parse object table information */ | ||
| 1766 | error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START); | ||
| 1767 | if (error) { | ||
| 1768 | dev_err(&client->dev, "Error %d parsing object table\n", error); | ||
| 1769 | mxt_free_object_table(data); | ||
| 1770 | goto err_free_mem; | ||
| 1720 | } | 1771 | } |
| 1721 | 1772 | ||
| 1722 | data->object_table = object_table; | 1773 | data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START); |
| 1723 | 1774 | ||
| 1724 | return 0; | 1775 | return 0; |
| 1725 | 1776 | ||
| 1726 | free_object_table: | 1777 | err_free_mem: |
| 1727 | mxt_free_object_table(data); | 1778 | kfree(id_buf); |
| 1728 | return error; | 1779 | return error; |
| 1729 | } | 1780 | } |
| 1730 | 1781 | ||
| @@ -2039,7 +2090,7 @@ static int mxt_initialize(struct mxt_data *data) | |||
| 2039 | int error; | 2090 | int error; |
| 2040 | 2091 | ||
| 2041 | while (1) { | 2092 | while (1) { |
| 2042 | error = mxt_get_info(data); | 2093 | error = mxt_read_info_block(data); |
| 2043 | if (!error) | 2094 | if (!error) |
| 2044 | break; | 2095 | break; |
| 2045 | 2096 | ||
| @@ -2070,16 +2121,9 @@ static int mxt_initialize(struct mxt_data *data) | |||
| 2070 | msleep(MXT_FW_RESET_TIME); | 2121 | msleep(MXT_FW_RESET_TIME); |
| 2071 | } | 2122 | } |
| 2072 | 2123 | ||
| 2073 | /* Get object table information */ | ||
| 2074 | error = mxt_get_object_table(data); | ||
| 2075 | if (error) { | ||
| 2076 | dev_err(&client->dev, "Error %d reading object table\n", error); | ||
| 2077 | return error; | ||
| 2078 | } | ||
| 2079 | |||
| 2080 | error = mxt_acquire_irq(data); | 2124 | error = mxt_acquire_irq(data); |
| 2081 | if (error) | 2125 | if (error) |
| 2082 | goto err_free_object_table; | 2126 | return error; |
| 2083 | 2127 | ||
| 2084 | error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, | 2128 | error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, |
| 2085 | &client->dev, GFP_KERNEL, data, | 2129 | &client->dev, GFP_KERNEL, data, |
| @@ -2087,14 +2131,10 @@ static int mxt_initialize(struct mxt_data *data) | |||
| 2087 | if (error) { | 2131 | if (error) { |
| 2088 | dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", | 2132 | dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", |
| 2089 | error); | 2133 | error); |
| 2090 | goto err_free_object_table; | 2134 | return error; |
| 2091 | } | 2135 | } |
| 2092 | 2136 | ||
| 2093 | return 0; | 2137 | return 0; |
| 2094 | |||
| 2095 | err_free_object_table: | ||
| 2096 | mxt_free_object_table(data); | ||
| 2097 | return error; | ||
| 2098 | } | 2138 | } |
| 2099 | 2139 | ||
| 2100 | static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) | 2140 | static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) |
| @@ -2155,7 +2195,7 @@ recheck: | |||
| 2155 | static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x, | 2195 | static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x, |
| 2156 | unsigned int y) | 2196 | unsigned int y) |
| 2157 | { | 2197 | { |
| 2158 | struct mxt_info *info = &data->info; | 2198 | struct mxt_info *info = data->info; |
| 2159 | struct mxt_dbg *dbg = &data->dbg; | 2199 | struct mxt_dbg *dbg = &data->dbg; |
| 2160 | unsigned int ofs, page; | 2200 | unsigned int ofs, page; |
| 2161 | unsigned int col = 0; | 2201 | unsigned int col = 0; |
| @@ -2483,7 +2523,7 @@ static const struct video_device mxt_video_device = { | |||
| 2483 | 2523 | ||
| 2484 | static void mxt_debug_init(struct mxt_data *data) | 2524 | static void mxt_debug_init(struct mxt_data *data) |
| 2485 | { | 2525 | { |
| 2486 | struct mxt_info *info = &data->info; | 2526 | struct mxt_info *info = data->info; |
| 2487 | struct mxt_dbg *dbg = &data->dbg; | 2527 | struct mxt_dbg *dbg = &data->dbg; |
| 2488 | struct mxt_object *object; | 2528 | struct mxt_object *object; |
| 2489 | int error; | 2529 | int error; |
| @@ -2569,7 +2609,6 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
| 2569 | const struct firmware *cfg) | 2609 | const struct firmware *cfg) |
| 2570 | { | 2610 | { |
| 2571 | struct device *dev = &data->client->dev; | 2611 | struct device *dev = &data->client->dev; |
| 2572 | struct mxt_info *info = &data->info; | ||
| 2573 | int error; | 2612 | int error; |
| 2574 | 2613 | ||
| 2575 | error = mxt_init_t7_power_cfg(data); | 2614 | error = mxt_init_t7_power_cfg(data); |
| @@ -2594,11 +2633,6 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
| 2594 | 2633 | ||
| 2595 | mxt_debug_init(data); | 2634 | mxt_debug_init(data); |
| 2596 | 2635 | ||
| 2597 | dev_info(dev, | ||
| 2598 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", | ||
| 2599 | info->family_id, info->variant_id, info->version >> 4, | ||
| 2600 | info->version & 0xf, info->build, info->object_num); | ||
| 2601 | |||
| 2602 | return 0; | 2636 | return 0; |
| 2603 | } | 2637 | } |
| 2604 | 2638 | ||
| @@ -2607,7 +2641,7 @@ static ssize_t mxt_fw_version_show(struct device *dev, | |||
| 2607 | struct device_attribute *attr, char *buf) | 2641 | struct device_attribute *attr, char *buf) |
| 2608 | { | 2642 | { |
| 2609 | struct mxt_data *data = dev_get_drvdata(dev); | 2643 | struct mxt_data *data = dev_get_drvdata(dev); |
| 2610 | struct mxt_info *info = &data->info; | 2644 | struct mxt_info *info = data->info; |
| 2611 | return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", | 2645 | return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", |
| 2612 | info->version >> 4, info->version & 0xf, info->build); | 2646 | info->version >> 4, info->version & 0xf, info->build); |
| 2613 | } | 2647 | } |
| @@ -2617,7 +2651,7 @@ static ssize_t mxt_hw_version_show(struct device *dev, | |||
| 2617 | struct device_attribute *attr, char *buf) | 2651 | struct device_attribute *attr, char *buf) |
| 2618 | { | 2652 | { |
| 2619 | struct mxt_data *data = dev_get_drvdata(dev); | 2653 | struct mxt_data *data = dev_get_drvdata(dev); |
| 2620 | struct mxt_info *info = &data->info; | 2654 | struct mxt_info *info = data->info; |
| 2621 | return scnprintf(buf, PAGE_SIZE, "%u.%u\n", | 2655 | return scnprintf(buf, PAGE_SIZE, "%u.%u\n", |
| 2622 | info->family_id, info->variant_id); | 2656 | info->family_id, info->variant_id); |
| 2623 | } | 2657 | } |
| @@ -2656,7 +2690,7 @@ static ssize_t mxt_object_show(struct device *dev, | |||
| 2656 | return -ENOMEM; | 2690 | return -ENOMEM; |
| 2657 | 2691 | ||
| 2658 | error = 0; | 2692 | error = 0; |
| 2659 | for (i = 0; i < data->info.object_num; i++) { | 2693 | for (i = 0; i < data->info->object_num; i++) { |
| 2660 | object = data->object_table + i; | 2694 | object = data->object_table + i; |
| 2661 | 2695 | ||
| 2662 | if (!mxt_object_readable(object->type)) | 2696 | if (!mxt_object_readable(object->type)) |
