1 /* aic20x-config.c -- setup individual TLV320AIC2x registers over I2C
3 * This file is provided as part of 0cpm Firmerware.
5 * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
7 * 0cpm Firmerware is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 3.
11 * 0cpm Firmerware is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with 0cpm Firmerware. If not, see <http://www.gnu.org/licenses/>.
22 * Note: If this program works (which it does), it proves that the
23 * subregisters may be addressed directly by way of the distinguishing
24 * top bits. This is not documented in the datasheet, but that is
25 * indeed not the best bit of technical work that TI has accomplished.
37 #include <sys/types.h>
39 #include <sys/ioctl.h>
41 #include <linux/i2c-dev.h>
44 #define INTERPOLL_WAIT_MS 5
47 const char * regname [14] = { "1", "2", "3A", "3B", "3C", "3D", "4A", "4B", "5A", "5B", "5C", "5D", "6A", "6B" };
48 const uint8_t regmask [14] = { 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80 };
49 const uint8_t regseln [14] = { 0x00, 0x00, 0x00, 0x40, 0x80, 0xc0, 0x00, 0x80, 0x00, 0x40, 0x80, 0xc0, 0x00, 0x80 };
51 uint8_t argval (char *strval) {
55 if (strncasecmp (strval, "0x", 2) == 0) {
58 } else if (*strval == '0') {
60 } else if (! *strval) {
61 strval = "(empty)"; // Cause error later
63 intval = strtol (strval, &postfix, base);
64 if ((*postfix) || (intval < 0) || (intval > 255)) {
65 fprintf (stderr, "Value error: Value %s should be an integer in the range 0x00 to 0xff\n", strval);
68 return (uint8_t) intval;
71 int main (int argc, char *argv []) {
76 fprintf (stderr, "Usage: %s /dev/i2c-N SLAVEADDR REGISTER=VALUE...\n"
77 "\tThe slave address is usually 0x40, 0x41, ... 0x4f\n"
78 "\tThe register may be a subregister, the value is a number\n"
79 "\tNumbers may be prefixed with 0 for octal, or 0x for hex\n"
80 "\tNote: All subregister indexes are assumed to be zero\n",
85 slave = argval (argv [2]);
86 printf ("Slave address 0x%02x, channel %d\n", slave, slave & 0x0f);
87 if ((slave < 0x40) || (slave > 0x4f)) {
88 fprintf (stderr, "Warning: The slave address usually falls in the range 0x40 to 0x4f\n");
92 int bus = open (argv [1], O_RDWR);
94 perror ("Failed to open I2C bus");
97 ioctl (bus, I2C_TIMEOUT, 1);
98 ioctl (bus, I2C_RETRIES, 2);
100 if (ioctl (bus, I2C_SLAVE, slave) == -1) {
101 perror ("Failed to set channel as address");
105 for (i=0; i < argc-3; i++) {
106 char *strval = argv [3+i];
108 if ((!*strval) || (!strval [1]) || (!strval [2])) {
109 fprintf (stderr, "Argument too short, specify REGISTER=VALUE for %s\n", strval);
112 if (strval [1] == '=') {
114 } else if (strval [2] == '=') {
117 fprintf (stderr, "Specify REGISTER=VALUE with REGISTER 1 or 2 characters long, not \n", strval);
120 uint8_t intval = argval (strval + reglen + 1);
123 for (j=0; j < 14; j++) {
124 if (reglen != strlen (regname [j])) {
127 if (strncasecmp (regname [j], strval, reglen) != 0) {
130 if ((intval & regmask [j]) != regseln [j]) {
131 fprintf (stderr, "Error: Register %s value %s should fall between 0x%02x and 0x%02x\n", regname [j], strval + reglen + 1, regseln [j], regseln [j] + 255 - regmask [j]);
135 buf [0] = *regname [j] - '0';
137 printf ("%-2s := 0x%02x\n", regname [j], intval);
138 usleep (INTERPOLL_WAIT_MS * 1000);
139 if (write (bus, buf, sizeof (buf)) != sizeof (buf)) {
140 perror ("Failed to write to registers");
145 fprintf (stderr, "Register for %s not found\n", strval);