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 [13] = { "1", "2", "3A", "3B", "3C", "3D", "4", "5A", "5B", "5C", "5D", "6A", "6B" };
48 const uint8_t regmask [13] = { 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80 };
49 const uint8_t regseln [13] = { 0x00, 0x00, 0x00, 0x40, 0x80, 0xc0, 0x00, 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 []) {
77 fprintf (stderr, "Usage: %s /dev/i2c-N SLAVEADDR REGISTER=VALUE\n"
78 "\tThe slave address is usually 0x40, 0x41, ... 0x4f\n"
79 "\tThe register may be a subregister, the value is a number\n"
80 "\tNumbers may be prefixed with 0 for octal, or 0x for hex\n"
81 "\tNote: All subregister indexes are assumed to be zero\n",
86 slave = argval (argv [2]);
87 printf ("Slave address 0x%02x, channel %d\n", slave, slave & 0x0f);
88 if ((slave < 0x40) || (slave > 0x4f)) {
89 fprintf (stderr, "Warning: The slave address usually falls in the range 0x40 to 0x4f\n");
93 int bus = open (argv [1], O_RDWR);
95 perror ("Failed to open I2C bus");
98 ioctl (bus, I2C_TIMEOUT, 1);
99 ioctl (bus, I2C_RETRIES, 2);
101 if (ioctl (bus, I2C_SLAVE, slave) == -1) {
102 perror ("Failed to set channel as address");
106 for (i=0; i < argc-3; i++) {
107 char *strval = argv [3+i];
109 if ((!*strval) || (!strval [1]) || (!strval [2])) {
110 fprintf (stderr, "Argument too short, specify REGISTER=VALUE for %s\n", strval);
113 if (strval [1] == '=') {
115 } else if (strval [2] == '=') {
118 fprintf (stderr, "Specify REGISTER=VALUE with REGISTER 1 or 2 characters long, not \n", strval);
121 uint8_t intval = argval (strval + reglen + 1);
124 for (j=0; j < 13; j++) {
125 if (reglen != strlen (regname [j])) {
128 if (strncasecmp (regname [j], strval, reglen) != 0) {
131 if ((intval & regmask [j]) != regseln [j]) {
132 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]);
136 buf [0] = *regname [j] - '0';
138 printf ("%-2s := 0x%02x\n", regname [j], intval);
139 usleep (INTERPOLL_WAIT_MS * 1000);
140 if (write (bus, buf, sizeof (buf)) != sizeof (buf)) {
141 perror ("Failed to write to registers");
146 fprintf (stderr, "Register for %s not found\n", strval);