Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: cyapa - add gen5 trackpad read baseline support

Add read baseline function support for gen5 trackpad device, it can be used
through sysfs baseline interface.

Signed-off-by: Dudley Du <dudl@cypress.com>
Tested-by: Jeremiah Mahler <jmmahler@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Dudley Du and committed by
Dmitry Torokhov
6499d390 5812d306

+642
+2
drivers/input/mouse/cyapa.h
··· 263 263 u8 y_origin; /* Y Axis Origin: 0 = top; 1 = bottom. */ 264 264 int electrodes_x; /* Number of electrodes on the X Axis*/ 265 265 int electrodes_y; /* Number of electrodes on the Y Axis*/ 266 + int electrodes_rx; /* Number of Rx electrodes */ 267 + int aligned_electrodes_rx; /* 4 aligned */ 266 268 int max_z; 267 269 268 270 /*
+640
drivers/input/mouse/cyapa_gen5.c
··· 363 363 u8 parameter_id; 364 364 } __packed; 365 365 366 + struct gen5_retrieve_panel_scan_data { 367 + __le16 read_offset; 368 + __le16 read_elements; 369 + u8 data_id; 370 + } __packed; 371 + 366 372 /* Variables to record latest gen5 trackpad power states. */ 367 373 #define GEN5_DEV_SET_PWR_STATE(cyapa, s) ((cyapa)->dev_pwr_mode = (s)) 368 374 #define GEN5_DEV_GET_PWR_STATE(cyapa) ((cyapa)->dev_pwr_mode) ··· 1667 1661 return 0; 1668 1662 } 1669 1663 1664 + static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) 1665 + { 1666 + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; 1667 + u8 resp_data[6]; 1668 + int resp_len; 1669 + int error; 1670 + 1671 + /* Try to dump all buffered data before doing command. */ 1672 + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1673 + 1674 + resp_len = sizeof(resp_data); 1675 + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 1676 + cmd, sizeof(cmd), 1677 + resp_data, &resp_len, 1678 + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); 1679 + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04)) 1680 + return -EINVAL; 1681 + 1682 + /* Try to dump all buffered data when resuming scanning. */ 1683 + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1684 + 1685 + return 0; 1686 + } 1687 + 1688 + static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) 1689 + { 1690 + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; 1691 + u8 resp_data[6]; 1692 + int resp_len; 1693 + int error; 1694 + 1695 + /* Try to dump all buffered data before doing command. */ 1696 + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1697 + 1698 + resp_len = sizeof(resp_data); 1699 + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 1700 + cmd, sizeof(cmd), 1701 + resp_data, &resp_len, 1702 + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); 1703 + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03)) 1704 + return -EINVAL; 1705 + 1706 + /* Try to dump all buffered data when suspending scanning. */ 1707 + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1708 + 1709 + return 0; 1710 + } 1711 + 1712 + static s32 twos_complement_to_s32(s32 value, int num_bits) 1713 + { 1714 + if (value >> (num_bits - 1)) 1715 + value |= -1 << num_bits; 1716 + return value; 1717 + } 1718 + 1719 + static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len) 1720 + { 1721 + int data_size; 1722 + bool big_endian; 1723 + bool unsigned_type; 1724 + s32 value; 1725 + 1726 + data_size = (data_format & 0x07); 1727 + big_endian = ((data_format & 0x10) == 0x00); 1728 + unsigned_type = ((data_format & 0x20) == 0x00); 1729 + 1730 + if (buf_len < data_size) 1731 + return 0; 1732 + 1733 + switch (data_size) { 1734 + case 1: 1735 + value = buf[0]; 1736 + break; 1737 + case 2: 1738 + if (big_endian) 1739 + value = get_unaligned_be16(buf); 1740 + else 1741 + value = get_unaligned_le16(buf); 1742 + break; 1743 + case 4: 1744 + if (big_endian) 1745 + value = get_unaligned_be32(buf); 1746 + else 1747 + value = get_unaligned_le32(buf); 1748 + break; 1749 + default: 1750 + /* Should not happen, just as default case here. */ 1751 + value = 0; 1752 + break; 1753 + } 1754 + 1755 + if (!unsigned_type) 1756 + value = twos_complement_to_s32(value, data_size * 8); 1757 + 1758 + return value; 1759 + } 1760 + 1761 + static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa, 1762 + int *electrodes_rx, int *electrodes_tx) 1763 + { 1764 + if (cyapa->electrodes_rx != 0) { 1765 + *electrodes_rx = cyapa->electrodes_rx; 1766 + *electrodes_tx = (cyapa->electrodes_x == *electrodes_rx) ? 1767 + cyapa->electrodes_y : cyapa->electrodes_x; 1768 + } else { 1769 + *electrodes_tx = min(cyapa->electrodes_x, cyapa->electrodes_y); 1770 + *electrodes_rx = max(cyapa->electrodes_x, cyapa->electrodes_y); 1771 + } 1772 + } 1773 + 1774 + /* 1775 + * Read all the global mutual or self idac data or mutual or self local PWC 1776 + * data based on the @idac_data_type. 1777 + * If the input value of @data_size is 0, then means read global mutual or 1778 + * self idac data. For read global mutual idac data, @idac_max, @idac_min and 1779 + * @idac_ave are in order used to return the max value of global mutual idac 1780 + * data, the min value of global mutual idac and the average value of the 1781 + * global mutual idac data. For read global self idac data, @idac_max is used 1782 + * to return the global self cap idac data in Rx direction, @idac_min is used 1783 + * to return the global self cap idac data in Tx direction. @idac_ave is not 1784 + * used. 1785 + * If the input value of @data_size is not 0, than means read the mutual or 1786 + * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to 1787 + * return the max, min and average value of the mutual or self local PWC data. 1788 + * Note, in order to raed mutual local PWC data, must read invoke this function 1789 + * to read the mutual global idac data firstly to set the correct Rx number 1790 + * value, otherwise, the read mutual idac and PWC data may not correct. 1791 + */ 1792 + static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, 1793 + u8 cmd_code, u8 idac_data_type, int *data_size, 1794 + int *idac_max, int *idac_min, int *idac_ave) 1795 + { 1796 + struct gen5_app_cmd_head *cmd_head; 1797 + u8 cmd[12]; 1798 + u8 resp_data[256]; 1799 + int resp_len; 1800 + int read_len; 1801 + int value; 1802 + u16 offset; 1803 + int read_elements; 1804 + bool read_global_idac; 1805 + int sum, count, max_element_cnt; 1806 + int tmp_max, tmp_min, tmp_ave, tmp_sum, tmp_count; 1807 + int electrodes_rx, electrodes_tx; 1808 + int i; 1809 + int error; 1810 + 1811 + if (cmd_code != GEN5_CMD_RETRIEVE_DATA_STRUCTURE || 1812 + (idac_data_type != GEN5_RETRIEVE_MUTUAL_PWC_DATA && 1813 + idac_data_type != GEN5_RETRIEVE_SELF_CAP_PWC_DATA) || 1814 + !data_size || !idac_max || !idac_min || !idac_ave) 1815 + return -EINVAL; 1816 + 1817 + *idac_max = INT_MIN; 1818 + *idac_min = INT_MAX; 1819 + sum = count = tmp_count = 0; 1820 + electrodes_rx = electrodes_tx = 0; 1821 + if (*data_size == 0) { 1822 + /* 1823 + * Read global idac values firstly. 1824 + * Currently, no idac data exceed 4 bytes. 1825 + */ 1826 + read_global_idac = true; 1827 + offset = 0; 1828 + *data_size = 4; 1829 + tmp_max = INT_MIN; 1830 + tmp_min = INT_MAX; 1831 + tmp_ave = tmp_sum = tmp_count = 0; 1832 + 1833 + if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) { 1834 + if (cyapa->aligned_electrodes_rx == 0) { 1835 + cyapa_gen5_guess_electrodes(cyapa, 1836 + &electrodes_rx, &electrodes_tx); 1837 + cyapa->aligned_electrodes_rx = 1838 + (electrodes_rx + 3) & ~3u; 1839 + } 1840 + max_element_cnt = 1841 + (cyapa->aligned_electrodes_rx + 7) & ~7u; 1842 + } else { 1843 + max_element_cnt = 2; 1844 + } 1845 + } else { 1846 + read_global_idac = false; 1847 + if (*data_size > 4) 1848 + *data_size = 4; 1849 + /* Calculate the start offset in bytes of local PWC data. */ 1850 + if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) { 1851 + offset = cyapa->aligned_electrodes_rx * (*data_size); 1852 + if (cyapa->electrodes_rx == cyapa->electrodes_x) 1853 + electrodes_tx = cyapa->electrodes_y; 1854 + else 1855 + electrodes_tx = cyapa->electrodes_x; 1856 + max_element_cnt = ((cyapa->aligned_electrodes_rx + 7) & 1857 + ~7u) * electrodes_tx; 1858 + } else if (idac_data_type == GEN5_RETRIEVE_SELF_CAP_PWC_DATA) { 1859 + offset = 2; 1860 + max_element_cnt = cyapa->electrodes_x + 1861 + cyapa->electrodes_y; 1862 + max_element_cnt = (max_element_cnt + 3) & ~3u; 1863 + } 1864 + } 1865 + 1866 + memset(cmd, 0, sizeof(cmd)); 1867 + cmd_head = (struct gen5_app_cmd_head *)cmd; 1868 + put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &cmd_head->addr); 1869 + put_unaligned_le16(sizeof(cmd) - 2, &cmd_head->length); 1870 + cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; 1871 + cmd_head->cmd_code = cmd_code; 1872 + do { 1873 + read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / 1874 + (*data_size); 1875 + read_elements = min(read_elements, max_element_cnt - count); 1876 + read_len = read_elements * (*data_size); 1877 + 1878 + put_unaligned_le16(offset, &cmd_head->parameter_data[0]); 1879 + put_unaligned_le16(read_len, &cmd_head->parameter_data[2]); 1880 + cmd_head->parameter_data[4] = idac_data_type; 1881 + resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len; 1882 + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 1883 + cmd, sizeof(cmd), 1884 + resp_data, &resp_len, 1885 + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, 1886 + true); 1887 + if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET || 1888 + !VALID_CMD_RESP_HEADER(resp_data, cmd_code) || 1889 + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) || 1890 + resp_data[6] != idac_data_type) 1891 + return (error < 0) ? error : -EAGAIN; 1892 + read_len = get_unaligned_le16(&resp_data[7]); 1893 + if (read_len == 0) 1894 + break; 1895 + 1896 + *data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK); 1897 + if (read_len < *data_size) 1898 + return -EINVAL; 1899 + 1900 + if (read_global_idac && 1901 + idac_data_type == GEN5_RETRIEVE_SELF_CAP_PWC_DATA) { 1902 + /* Rx's self global idac data. */ 1903 + *idac_max = cyapa_parse_structure_data( 1904 + resp_data[9], 1905 + &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET], 1906 + *data_size); 1907 + /* Tx's self global idac data. */ 1908 + *idac_min = cyapa_parse_structure_data( 1909 + resp_data[9], 1910 + &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET + 1911 + *data_size], 1912 + *data_size); 1913 + break; 1914 + } 1915 + 1916 + /* Read mutual global idac or local mutual/self PWC data. */ 1917 + offset += read_len; 1918 + for (i = 10; i < (read_len + GEN5_RESP_DATA_STRUCTURE_OFFSET); 1919 + i += *data_size) { 1920 + value = cyapa_parse_structure_data(resp_data[9], 1921 + &resp_data[i], *data_size); 1922 + *idac_min = min(value, *idac_min); 1923 + *idac_max = max(value, *idac_max); 1924 + 1925 + if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA && 1926 + tmp_count < cyapa->aligned_electrodes_rx && 1927 + read_global_idac) { 1928 + /* 1929 + * The value gap betwen global and local mutual 1930 + * idac data must bigger than 50%. 1931 + * Normally, global value bigger than 50, 1932 + * local values less than 10. 1933 + */ 1934 + if (!tmp_ave || value > tmp_ave / 2) { 1935 + tmp_min = min(value, tmp_min); 1936 + tmp_max = max(value, tmp_max); 1937 + tmp_sum += value; 1938 + tmp_count++; 1939 + 1940 + tmp_ave = tmp_sum / tmp_count; 1941 + } 1942 + } 1943 + 1944 + sum += value; 1945 + count++; 1946 + 1947 + if (count >= max_element_cnt) 1948 + goto out; 1949 + } 1950 + } while (true); 1951 + 1952 + out: 1953 + *idac_ave = count ? (sum / count) : 0; 1954 + 1955 + if (read_global_idac && 1956 + idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) { 1957 + if (tmp_count == 0) 1958 + return 0; 1959 + 1960 + if (tmp_count == cyapa->aligned_electrodes_rx) { 1961 + cyapa->electrodes_rx = cyapa->electrodes_rx ? 1962 + cyapa->electrodes_rx : electrodes_rx; 1963 + } else if (tmp_count == electrodes_rx) { 1964 + cyapa->electrodes_rx = cyapa->electrodes_rx ? 1965 + cyapa->electrodes_rx : electrodes_rx; 1966 + cyapa->aligned_electrodes_rx = electrodes_rx; 1967 + } else { 1968 + cyapa->electrodes_rx = cyapa->electrodes_rx ? 1969 + cyapa->electrodes_rx : electrodes_tx; 1970 + cyapa->aligned_electrodes_rx = tmp_count; 1971 + } 1972 + 1973 + *idac_min = tmp_min; 1974 + *idac_max = tmp_max; 1975 + *idac_ave = tmp_ave; 1976 + } 1977 + 1978 + return 0; 1979 + } 1980 + 1981 + static int cyapa_gen5_read_mutual_idac_data(struct cyapa *cyapa, 1982 + int *gidac_mutual_max, int *gidac_mutual_min, int *gidac_mutual_ave, 1983 + int *lidac_mutual_max, int *lidac_mutual_min, int *lidac_mutual_ave) 1984 + { 1985 + int data_size; 1986 + int error; 1987 + 1988 + *gidac_mutual_max = *gidac_mutual_min = *gidac_mutual_ave = 0; 1989 + *lidac_mutual_max = *lidac_mutual_min = *lidac_mutual_ave = 0; 1990 + 1991 + data_size = 0; 1992 + error = cyapa_gen5_read_idac_data(cyapa, 1993 + GEN5_CMD_RETRIEVE_DATA_STRUCTURE, 1994 + GEN5_RETRIEVE_MUTUAL_PWC_DATA, 1995 + &data_size, 1996 + gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave); 1997 + if (error) 1998 + return error; 1999 + 2000 + error = cyapa_gen5_read_idac_data(cyapa, 2001 + GEN5_CMD_RETRIEVE_DATA_STRUCTURE, 2002 + GEN5_RETRIEVE_MUTUAL_PWC_DATA, 2003 + &data_size, 2004 + lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave); 2005 + return error; 2006 + } 2007 + 2008 + static int cyapa_gen5_read_self_idac_data(struct cyapa *cyapa, 2009 + int *gidac_self_rx, int *gidac_self_tx, 2010 + int *lidac_self_max, int *lidac_self_min, int *lidac_self_ave) 2011 + { 2012 + int data_size; 2013 + int error; 2014 + 2015 + *gidac_self_rx = *gidac_self_tx = 0; 2016 + *lidac_self_max = *lidac_self_min = *lidac_self_ave = 0; 2017 + 2018 + data_size = 0; 2019 + error = cyapa_gen5_read_idac_data(cyapa, 2020 + GEN5_CMD_RETRIEVE_DATA_STRUCTURE, 2021 + GEN5_RETRIEVE_SELF_CAP_PWC_DATA, 2022 + &data_size, 2023 + lidac_self_max, lidac_self_min, lidac_self_ave); 2024 + if (error) 2025 + return error; 2026 + *gidac_self_rx = *lidac_self_max; 2027 + *gidac_self_tx = *lidac_self_min; 2028 + 2029 + error = cyapa_gen5_read_idac_data(cyapa, 2030 + GEN5_CMD_RETRIEVE_DATA_STRUCTURE, 2031 + GEN5_RETRIEVE_SELF_CAP_PWC_DATA, 2032 + &data_size, 2033 + lidac_self_max, lidac_self_min, lidac_self_ave); 2034 + return error; 2035 + } 2036 + 2037 + static ssize_t cyapa_gen5_execute_panel_scan(struct cyapa *cyapa) 2038 + { 2039 + struct gen5_app_cmd_head *app_cmd_head; 2040 + u8 cmd[7]; 2041 + u8 resp_data[6]; 2042 + int resp_len; 2043 + int error; 2044 + 2045 + memset(cmd, 0, sizeof(cmd)); 2046 + app_cmd_head = (struct gen5_app_cmd_head *)cmd; 2047 + put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); 2048 + put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); 2049 + app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; 2050 + app_cmd_head->cmd_code = GEN5_CMD_EXECUTE_PANEL_SCAN; 2051 + resp_len = sizeof(resp_data); 2052 + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 2053 + cmd, sizeof(cmd), 2054 + resp_data, &resp_len, 2055 + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); 2056 + if (error || resp_len != sizeof(resp_data) || 2057 + !VALID_CMD_RESP_HEADER(resp_data, 2058 + GEN5_CMD_EXECUTE_PANEL_SCAN) || 2059 + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) 2060 + return error ? error : -EAGAIN; 2061 + 2062 + return 0; 2063 + } 2064 + 2065 + static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa *cyapa, 2066 + u8 cmd_code, u8 raw_data_type, int raw_data_max_num, 2067 + int *raw_data_max, int *raw_data_min, int *raw_data_ave, 2068 + u8 *buffer) 2069 + { 2070 + struct gen5_app_cmd_head *app_cmd_head; 2071 + struct gen5_retrieve_panel_scan_data *panel_sacn_data; 2072 + u8 cmd[12]; 2073 + u8 resp_data[256]; /* Max bytes can transfer one time. */ 2074 + int resp_len; 2075 + int read_elements; 2076 + int read_len; 2077 + u16 offset; 2078 + s32 value; 2079 + int sum, count; 2080 + int data_size; 2081 + s32 *intp; 2082 + int i; 2083 + int error; 2084 + 2085 + if (cmd_code != GEN5_CMD_RETRIEVE_PANEL_SCAN || 2086 + (raw_data_type > GEN5_PANEL_SCAN_SELF_DIFFCOUNT) || 2087 + !raw_data_max || !raw_data_min || !raw_data_ave) 2088 + return -EINVAL; 2089 + 2090 + intp = (s32 *)buffer; 2091 + *raw_data_max = INT_MIN; 2092 + *raw_data_min = INT_MAX; 2093 + sum = count = 0; 2094 + offset = 0; 2095 + /* Assume max element size is 4 currently. */ 2096 + read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / 4; 2097 + read_len = read_elements * 4; 2098 + app_cmd_head = (struct gen5_app_cmd_head *)cmd; 2099 + put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); 2100 + put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); 2101 + app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; 2102 + app_cmd_head->cmd_code = cmd_code; 2103 + panel_sacn_data = (struct gen5_retrieve_panel_scan_data *) 2104 + app_cmd_head->parameter_data; 2105 + do { 2106 + put_unaligned_le16(offset, &panel_sacn_data->read_offset); 2107 + put_unaligned_le16(read_elements, 2108 + &panel_sacn_data->read_elements); 2109 + panel_sacn_data->data_id = raw_data_type; 2110 + 2111 + resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len; 2112 + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 2113 + cmd, sizeof(cmd), 2114 + resp_data, &resp_len, 2115 + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); 2116 + if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET || 2117 + !VALID_CMD_RESP_HEADER(resp_data, cmd_code) || 2118 + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) || 2119 + resp_data[6] != raw_data_type) 2120 + return error ? error : -EAGAIN; 2121 + 2122 + read_elements = get_unaligned_le16(&resp_data[7]); 2123 + if (read_elements == 0) 2124 + break; 2125 + 2126 + data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK); 2127 + offset += read_elements; 2128 + if (read_elements) { 2129 + for (i = GEN5_RESP_DATA_STRUCTURE_OFFSET; 2130 + i < (read_elements * data_size + 2131 + GEN5_RESP_DATA_STRUCTURE_OFFSET); 2132 + i += data_size) { 2133 + value = cyapa_parse_structure_data(resp_data[9], 2134 + &resp_data[i], data_size); 2135 + *raw_data_min = min(value, *raw_data_min); 2136 + *raw_data_max = max(value, *raw_data_max); 2137 + 2138 + if (intp) 2139 + put_unaligned_le32(value, &intp[count]); 2140 + 2141 + sum += value; 2142 + count++; 2143 + 2144 + } 2145 + } 2146 + 2147 + if (count >= raw_data_max_num) 2148 + break; 2149 + 2150 + read_elements = (sizeof(resp_data) - 2151 + GEN5_RESP_DATA_STRUCTURE_OFFSET) / data_size; 2152 + read_len = read_elements * data_size; 2153 + } while (true); 2154 + 2155 + *raw_data_ave = count ? (sum / count) : 0; 2156 + 2157 + return 0; 2158 + } 2159 + 2160 + static ssize_t cyapa_gen5_show_baseline(struct device *dev, 2161 + struct device_attribute *attr, char *buf) 2162 + { 2163 + struct cyapa *cyapa = dev_get_drvdata(dev); 2164 + int gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave; 2165 + int lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave; 2166 + int gidac_self_rx, gidac_self_tx; 2167 + int lidac_self_max, lidac_self_min, lidac_self_ave; 2168 + int raw_cap_mutual_max, raw_cap_mutual_min, raw_cap_mutual_ave; 2169 + int raw_cap_self_max, raw_cap_self_min, raw_cap_self_ave; 2170 + int mutual_diffdata_max, mutual_diffdata_min, mutual_diffdata_ave; 2171 + int self_diffdata_max, self_diffdata_min, self_diffdata_ave; 2172 + int mutual_baseline_max, mutual_baseline_min, mutual_baseline_ave; 2173 + int self_baseline_max, self_baseline_min, self_baseline_ave; 2174 + int error, resume_error; 2175 + int size; 2176 + 2177 + if (cyapa->state != CYAPA_STATE_GEN5_APP) 2178 + return -EBUSY; 2179 + 2180 + /* 1. Suspend Scanning*/ 2181 + error = cyapa_gen5_suspend_scanning(cyapa); 2182 + if (error) 2183 + return error; 2184 + 2185 + /* 2. Read global and local mutual IDAC data. */ 2186 + gidac_self_rx = gidac_self_tx = 0; 2187 + error = cyapa_gen5_read_mutual_idac_data(cyapa, 2188 + &gidac_mutual_max, &gidac_mutual_min, 2189 + &gidac_mutual_ave, &lidac_mutual_max, 2190 + &lidac_mutual_min, &lidac_mutual_ave); 2191 + if (error) 2192 + goto resume_scanning; 2193 + 2194 + /* 3. Read global and local self IDAC data. */ 2195 + error = cyapa_gen5_read_self_idac_data(cyapa, 2196 + &gidac_self_rx, &gidac_self_tx, 2197 + &lidac_self_max, &lidac_self_min, 2198 + &lidac_self_ave); 2199 + if (error) 2200 + goto resume_scanning; 2201 + 2202 + /* 4. Execuate panel scan. It must be executed before read data. */ 2203 + error = cyapa_gen5_execute_panel_scan(cyapa); 2204 + if (error) 2205 + goto resume_scanning; 2206 + 2207 + /* 5. Retrieve panel scan, mutual cap raw data. */ 2208 + error = cyapa_gen5_read_panel_scan_raw_data(cyapa, 2209 + GEN5_CMD_RETRIEVE_PANEL_SCAN, 2210 + GEN5_PANEL_SCAN_MUTUAL_RAW_DATA, 2211 + cyapa->electrodes_x * cyapa->electrodes_y, 2212 + &raw_cap_mutual_max, &raw_cap_mutual_min, 2213 + &raw_cap_mutual_ave, 2214 + NULL); 2215 + if (error) 2216 + goto resume_scanning; 2217 + 2218 + /* 6. Retrieve panel scan, self cap raw data. */ 2219 + error = cyapa_gen5_read_panel_scan_raw_data(cyapa, 2220 + GEN5_CMD_RETRIEVE_PANEL_SCAN, 2221 + GEN5_PANEL_SCAN_SELF_RAW_DATA, 2222 + cyapa->electrodes_x + cyapa->electrodes_y, 2223 + &raw_cap_self_max, &raw_cap_self_min, 2224 + &raw_cap_self_ave, 2225 + NULL); 2226 + if (error) 2227 + goto resume_scanning; 2228 + 2229 + /* 7. Retrieve panel scan, mutual cap diffcount raw data. */ 2230 + error = cyapa_gen5_read_panel_scan_raw_data(cyapa, 2231 + GEN5_CMD_RETRIEVE_PANEL_SCAN, 2232 + GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT, 2233 + cyapa->electrodes_x * cyapa->electrodes_y, 2234 + &mutual_diffdata_max, &mutual_diffdata_min, 2235 + &mutual_diffdata_ave, 2236 + NULL); 2237 + if (error) 2238 + goto resume_scanning; 2239 + 2240 + /* 8. Retrieve panel scan, self cap diffcount raw data. */ 2241 + error = cyapa_gen5_read_panel_scan_raw_data(cyapa, 2242 + GEN5_CMD_RETRIEVE_PANEL_SCAN, 2243 + GEN5_PANEL_SCAN_SELF_DIFFCOUNT, 2244 + cyapa->electrodes_x + cyapa->electrodes_y, 2245 + &self_diffdata_max, &self_diffdata_min, 2246 + &self_diffdata_ave, 2247 + NULL); 2248 + if (error) 2249 + goto resume_scanning; 2250 + 2251 + /* 9. Retrieve panel scan, mutual cap baseline raw data. */ 2252 + error = cyapa_gen5_read_panel_scan_raw_data(cyapa, 2253 + GEN5_CMD_RETRIEVE_PANEL_SCAN, 2254 + GEN5_PANEL_SCAN_MUTUAL_BASELINE, 2255 + cyapa->electrodes_x * cyapa->electrodes_y, 2256 + &mutual_baseline_max, &mutual_baseline_min, 2257 + &mutual_baseline_ave, 2258 + NULL); 2259 + if (error) 2260 + goto resume_scanning; 2261 + 2262 + /* 10. Retrieve panel scan, self cap baseline raw data. */ 2263 + error = cyapa_gen5_read_panel_scan_raw_data(cyapa, 2264 + GEN5_CMD_RETRIEVE_PANEL_SCAN, 2265 + GEN5_PANEL_SCAN_SELF_BASELINE, 2266 + cyapa->electrodes_x + cyapa->electrodes_y, 2267 + &self_baseline_max, &self_baseline_min, 2268 + &self_baseline_ave, 2269 + NULL); 2270 + if (error) 2271 + goto resume_scanning; 2272 + 2273 + resume_scanning: 2274 + /* 11. Resume Scanning*/ 2275 + resume_error = cyapa_gen5_resume_scanning(cyapa); 2276 + if (resume_error || error) 2277 + return resume_error ? resume_error : error; 2278 + 2279 + /* 12. Output data strings */ 2280 + size = scnprintf(buf, PAGE_SIZE, "%d %d %d %d %d %d %d %d %d %d %d ", 2281 + gidac_mutual_min, gidac_mutual_max, gidac_mutual_ave, 2282 + lidac_mutual_min, lidac_mutual_max, lidac_mutual_ave, 2283 + gidac_self_rx, gidac_self_tx, 2284 + lidac_self_min, lidac_self_max, lidac_self_ave); 2285 + size += scnprintf(buf + size, PAGE_SIZE - size, 2286 + "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", 2287 + raw_cap_mutual_min, raw_cap_mutual_max, raw_cap_mutual_ave, 2288 + raw_cap_self_min, raw_cap_self_max, raw_cap_self_ave, 2289 + mutual_diffdata_min, mutual_diffdata_max, mutual_diffdata_ave, 2290 + self_diffdata_min, self_diffdata_max, self_diffdata_ave, 2291 + mutual_baseline_min, mutual_baseline_max, mutual_baseline_ave, 2292 + self_baseline_min, self_baseline_max, self_baseline_ave); 2293 + return size; 2294 + } 2295 + 1670 2296 static bool cyapa_gen5_sort_system_info_data(struct cyapa *cyapa, 1671 2297 u8 *buf, int len) 1672 2298 { ··· 2694 2056 .update_fw = cyapa_gen5_do_fw_update, 2695 2057 .bl_activate = cyapa_gen5_bl_activate, 2696 2058 .bl_deactivate = cyapa_gen5_bl_deactivate, 2059 + 2060 + .show_baseline = cyapa_gen5_show_baseline, 2697 2061 2698 2062 .initialize = cyapa_gen5_initialize, 2699 2063