Discussion:
[lcd4linux] [PATCH] drv_HD44780: add 8bit i2c mode for HD44780
Michael Grzeschik
2015-06-18 16:00:36 UTC
Permalink
From: Michael Grzeschik <***@pengutronix.de>

This patch adds support for dual i2c io-expander
based 8bit support for HD44780. It multiplexes the
switch between the data and databits.

Signed-off-by: Michael Grzeschik <***@pengutronix.de>
---
drv_HD44780.c | 82 ++++++++++++++++++++++++++++++++++++++-----------------
drv_generic_i2c.c | 65 +++++++++++++++++++++++++++++++++----------
drv_generic_i2c.h | 2 +-
3 files changed, 109 insertions(+), 40 deletions(-)

diff --git a/drv_HD44780.c b/drv_HD44780.c
index 26f0bc9..7f4a56a 100644
--- a/drv_HD44780.c
+++ b/drv_HD44780.c
@@ -706,10 +706,10 @@ static void drv_HD_PP_stop(void)

*/

-static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble)
+static void drv_HD_I2C(unsigned char controller, unsigned char byte, int rs, int rw)
{
unsigned char enable;
- unsigned char command; /* this is actually the first data byte on the PCF8574 */
+ unsigned char command = 0; /* this is actually the first data byte on the PCF8574 */
unsigned char data_block[2];
/* enable signal: 'controller' is a bitmask */
/* bit n .. send to controller #n */
@@ -738,28 +738,51 @@ static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble)
The main advantage we see is that we do 2 less IOCTL's from our driver.
*/

- command = nibble;
- data_block[0] = nibble | enable;
- data_block[1] = nibble;
+ if (Bits == 4) {
+ if (rw)
+ byte |= SIGNAL_RW;
+ if (rs)
+ byte |= SIGNAL_RS;
+ command = byte;
+ data_block[0] = byte | enable;
+ data_block[1] = byte;
+
+ } else if (Bits == 8) {
+ if (rw)
+ command |= SIGNAL_RW;
+ if (rs)
+ command |= SIGNAL_RS;
+
+ data_block[0] = byte;
+ data_block[1] = enable;
+ }

- drv_generic_i2c_command(command, data_block, 2);
+ drv_generic_i2c_command(command, data_block, 2, Bits);
}


static void drv_HD_I2C_byte(const unsigned char controller, const unsigned char data)
{
/* send data with RS enabled */
- drv_HD_I2C_nibble(controller, ((data >> 4) & 0x0f) | SIGNAL_RS);
- drv_HD_I2C_nibble(controller, (data & 0x0f) | SIGNAL_RS);
+ if (Bits == 4) {
+ drv_HD_I2C(controller, ((data >> 4) & 0x0f), 1, 0);
+ drv_HD_I2C(controller, (data & 0x0f), 1, 0);
+ } else if (Bits == 8) {
+ drv_HD_I2C(controller, data, 1, 0);
+ }
}


static void drv_HD_I2C_command(const unsigned char controller, const unsigned char cmd, __attribute__ ((unused))
const unsigned long delay)
{
- /* send data with RS disabled */
- drv_HD_I2C_nibble(controller, ((cmd >> 4) & 0x0f));
- drv_HD_I2C_nibble(controller, ((cmd) & 0x0f));
+ /* send command data with RS disabled */
+ if (Bits == 4) {
+ drv_HD_I2C(controller, ((cmd >> 4) & 0x0f), 0, 0);
+ drv_HD_I2C(controller, ((cmd) & 0x0f), 0, 0);
+ } else if (Bits == 8) {
+ drv_HD_I2C(controller, cmd, 0, 0);
+ }
}

static void drv_HD_I2C_data(const unsigned char controller, const char *string, const int len, __attribute__ ((unused))
@@ -781,13 +804,14 @@ static int drv_HD_I2C_load(const char *section)
{
if (cfg_number(section, "Bits", 8, 4, 8, &Bits) < 0)
return -1;
- if (Bits != 4) {
- error("%s: bad %s.Bits '%d' from %s, should be '4'", Name, section, Bits, cfg_source());
- return -1;
- }

info("%s: using %d bit mode", Name, Bits);

+ if (Bits != 4 && Bits != 8) {
+ error("%s: bad %s.Bits '%d' from %s, should be '4' or '8'", Name, section, Bits, cfg_source());
+ return -1;
+ }
+
if (drv_generic_i2c_open(section, Name) != 0) {
error("%s: could not initialize i2c attached device!", Name);
return -1;
@@ -804,16 +828,24 @@ static int drv_HD_I2C_load(const char *section)
if ((SIGNAL_GPO = drv_generic_i2c_wire("GPO", "GND")) == 0xff)
return -1;

- /* initialize display */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
- drv_HD_I2C_nibble(allControllers, 0x02);
- udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
- drv_HD_I2C_command(allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
+ if (Bits == 4) {
+ /* initialize display */
+ drv_HD_I2C(allControllers, 0x02, 0, 0);
+ udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x03, 0, 0);
+ udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_I2C(allControllers, 0x03, 0, 0);
+ udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x02, 0, 0);
+ udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_I2C_command(allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
+ } else if (Bits == 8) {
+ drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 4.1 ms */
+ udelay(T_INIT1); /* 8 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 100 us */
+ udelay(T_INIT2); /* 8 Bit mode, wait 4.1 ms */
+ drv_HD_I2C_command(allControllers, 0x38, T_EXEC); /* 8 Bit mode, 1/16 duty cycle, 5x8 font */
+ }

info("%s: I2C initialization done", Name);

diff --git a/drv_generic_i2c.c b/drv_generic_i2c.c
index 2170b0c..1bee16f 100644
--- a/drv_generic_i2c.c
+++ b/drv_generic_i2c.c
@@ -62,7 +62,8 @@
static char *Driver = "";
static char *Section = "";
static int i2c_device;
-
+static int ctrldev;
+static int datadev;

static void my_i2c_smbus_write_byte_data(const int device, const unsigned char val)
{
@@ -91,34 +92,49 @@ static void my_i2c_smbus_read_byte_data(const int device, const unsigned char da
}
#endif

+int drv_generic_i2c_pre_write(int dev) {
+
+ info("%s: selecting slave device 0x%x", Driver, dev);
+ if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
+ error("%s: error selecting slave device 0x%x\n", Driver, dev);
+ return -EPIPE;
+ }
+
+ info("%s: initializing I2C slave device 0x%x for output", Driver, dev);
+ if (i2c_smbus_write_byte_data(i2c_device, 3, 0) < 0) {
+ error("%s: error initializing device 0x%x\n", Driver, dev);
+ close(i2c_device);
+ }
+
+ return 0;
+}

int drv_generic_i2c_open(const char *section, const char *driver)
{
- int dev;
char *bus, *device;
udelay_init();
Section = (char *) section;
Driver = (char *) driver;
bus = cfg_get(Section, "Port", NULL);
device = cfg_get(Section, "Device", NULL);
- dev = atoi(device);
+ ctrldev = atoi(device);
+ device = cfg_get(Section, "DDevice", NULL);
+ datadev = atoi(device);
+
info("%s: initializing I2C bus %s", Driver, bus);
if ((i2c_device = open(bus, O_WRONLY)) < 0) {
error("%s: I2C bus %s open failed !\n", Driver, bus);
goto exit_error;
}
- info("%s: selecting slave device 0x%x", Driver, dev);
- if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
- error("%s: error selecting slave device 0x%x\n", Driver, dev);
- goto exit_error;
- }

- info("%s: initializing I2C slave device 0x%x", Driver, dev);
- if (i2c_smbus_write_quick(i2c_device, I2C_SMBUS_WRITE) < 0) {
- error("%s: error initializing device 0x%x\n", Driver, dev);
- close(i2c_device);
+ if (datadev) {
+ if (drv_generic_i2c_pre_write(datadev) < 0)
+ goto exit_error;
}

+ if (drv_generic_i2c_pre_write(ctrldev) < 0)
+ goto exit_error;
+
return 0;

exit_error:
@@ -172,8 +188,29 @@ void drv_generic_i2c_data(const unsigned char data)
my_i2c_smbus_write_byte_data(i2c_device, data);
}

+static void i2c_out(int dev, unsigned char val)
+{
+ info("%s: initializing I2C slave device 0x%x", Driver, dev);
+ if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
+ error("%s: error selecting slave device 0x%x\n", Driver, dev);
+ return;
+ }
+
+ i2c_smbus_write_byte_data(i2c_device, 1, val);
+}

-void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length)
+void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, int bits)
{
- i2c_smbus_write_block_data(i2c_device, command, length, data);
+ if (bits == 4) {
+ i2c_smbus_write_block_data(i2c_device, command, length, data);
+ } else if (bits == 8 && datadev) {
+ /* set data on pins */
+ info("cmd: %08x, data0: %08x, data1: %08x\n", command, data[0], data[1]);
+ i2c_out(datadev, data[0]);
+ /* set enable pin including optional rs and rw */
+ i2c_out(ctrldev, command | data[1]);
+ /* unset enable pin including optional rs and rw */
+ i2c_out(ctrldev, command);
+ }
+
}
diff --git a/drv_generic_i2c.h b/drv_generic_i2c.h
index 2cc6a02..bd68e44 100644
--- a/drv_generic_i2c.h
+++ b/drv_generic_i2c.h
@@ -57,6 +57,6 @@ int drv_generic_i2c_close(void);
unsigned char drv_generic_i2c_wire(const char *name, const char *deflt);
void drv_generic_i2c_byte(const unsigned char data);
void drv_generic_i2c_data(const unsigned char data);
-void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length);
+void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, int bits);

#endif
--
2.1.4


------------------------------------------------------------------------------
Michael Grzeschik
2015-06-18 15:40:37 UTC
Permalink
This patch adds support for dual i2c io-expander
based 8bit mode for HD44780. It multiplexes the
switch between the data and databits on both chips.

Signed-off-by: Michael Grzeschik <***@pengutronix.de>
---
drv_HD44780.c | 82 ++++++++++++++++++++++++++++++++++++++-----------------
drv_generic_i2c.c | 65 +++++++++++++++++++++++++++++++++----------
drv_generic_i2c.h | 2 +-
3 files changed, 109 insertions(+), 40 deletions(-)

diff --git a/drv_HD44780.c b/drv_HD44780.c
index 26f0bc9..7f4a56a 100644
--- a/drv_HD44780.c
+++ b/drv_HD44780.c
@@ -706,10 +706,10 @@ static void drv_HD_PP_stop(void)

*/

-static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble)
+static void drv_HD_I2C(unsigned char controller, unsigned char byte, int rs, int rw)
{
unsigned char enable;
- unsigned char command; /* this is actually the first data byte on the PCF8574 */
+ unsigned char command = 0; /* this is actually the first data byte on the PCF8574 */
unsigned char data_block[2];
/* enable signal: 'controller' is a bitmask */
/* bit n .. send to controller #n */
@@ -738,28 +738,51 @@ static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble)
The main advantage we see is that we do 2 less IOCTL's from our driver.
*/

- command = nibble;
- data_block[0] = nibble | enable;
- data_block[1] = nibble;
+ if (Bits == 4) {
+ if (rw)
+ byte |= SIGNAL_RW;
+ if (rs)
+ byte |= SIGNAL_RS;
+ command = byte;
+ data_block[0] = byte | enable;
+ data_block[1] = byte;
+
+ } else if (Bits == 8) {
+ if (rw)
+ command |= SIGNAL_RW;
+ if (rs)
+ command |= SIGNAL_RS;
+
+ data_block[0] = byte;
+ data_block[1] = enable;
+ }

- drv_generic_i2c_command(command, data_block, 2);
+ drv_generic_i2c_command(command, data_block, 2, Bits);
}


static void drv_HD_I2C_byte(const unsigned char controller, const unsigned char data)
{
/* send data with RS enabled */
- drv_HD_I2C_nibble(controller, ((data >> 4) & 0x0f) | SIGNAL_RS);
- drv_HD_I2C_nibble(controller, (data & 0x0f) | SIGNAL_RS);
+ if (Bits == 4) {
+ drv_HD_I2C(controller, ((data >> 4) & 0x0f), 1, 0);
+ drv_HD_I2C(controller, (data & 0x0f), 1, 0);
+ } else if (Bits == 8) {
+ drv_HD_I2C(controller, data, 1, 0);
+ }
}


static void drv_HD_I2C_command(const unsigned char controller, const unsigned char cmd, __attribute__ ((unused))
const unsigned long delay)
{
- /* send data with RS disabled */
- drv_HD_I2C_nibble(controller, ((cmd >> 4) & 0x0f));
- drv_HD_I2C_nibble(controller, ((cmd) & 0x0f));
+ /* send command data with RS disabled */
+ if (Bits == 4) {
+ drv_HD_I2C(controller, ((cmd >> 4) & 0x0f), 0, 0);
+ drv_HD_I2C(controller, ((cmd) & 0x0f), 0, 0);
+ } else if (Bits == 8) {
+ drv_HD_I2C(controller, cmd, 0, 0);
+ }
}

static void drv_HD_I2C_data(const unsigned char controller, const char *string, const int len, __attribute__ ((unused))
@@ -781,13 +804,14 @@ static int drv_HD_I2C_load(const char *section)
{
if (cfg_number(section, "Bits", 8, 4, 8, &Bits) < 0)
return -1;
- if (Bits != 4) {
- error("%s: bad %s.Bits '%d' from %s, should be '4'", Name, section, Bits, cfg_source());
- return -1;
- }

info("%s: using %d bit mode", Name, Bits);

+ if (Bits != 4 && Bits != 8) {
+ error("%s: bad %s.Bits '%d' from %s, should be '4' or '8'", Name, section, Bits, cfg_source());
+ return -1;
+ }
+
if (drv_generic_i2c_open(section, Name) != 0) {
error("%s: could not initialize i2c attached device!", Name);
return -1;
@@ -804,16 +828,24 @@ static int drv_HD_I2C_load(const char *section)
if ((SIGNAL_GPO = drv_generic_i2c_wire("GPO", "GND")) == 0xff)
return -1;

- /* initialize display */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
- drv_HD_I2C_nibble(allControllers, 0x02);
- udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
- drv_HD_I2C_command(allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
+ if (Bits == 4) {
+ /* initialize display */
+ drv_HD_I2C(allControllers, 0x02, 0, 0);
+ udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x03, 0, 0);
+ udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_I2C(allControllers, 0x03, 0, 0);
+ udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x02, 0, 0);
+ udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_I2C_command(allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
+ } else if (Bits == 8) {
+ drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 4.1 ms */
+ udelay(T_INIT1); /* 8 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 100 us */
+ udelay(T_INIT2); /* 8 Bit mode, wait 4.1 ms */
+ drv_HD_I2C_command(allControllers, 0x38, T_EXEC); /* 8 Bit mode, 1/16 duty cycle, 5x8 font */
+ }

info("%s: I2C initialization done", Name);

diff --git a/drv_generic_i2c.c b/drv_generic_i2c.c
index 2170b0c..1bee16f 100644
--- a/drv_generic_i2c.c
+++ b/drv_generic_i2c.c
@@ -62,7 +62,8 @@
static char *Driver = "";
static char *Section = "";
static int i2c_device;
-
+static int ctrldev;
+static int datadev;

static void my_i2c_smbus_write_byte_data(const int device, const unsigned char val)
{
@@ -91,34 +92,49 @@ static void my_i2c_smbus_read_byte_data(const int device, const unsigned char da
}
#endif

+int drv_generic_i2c_pre_write(int dev) {
+
+ info("%s: selecting slave device 0x%x", Driver, dev);
+ if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
+ error("%s: error selecting slave device 0x%x\n", Driver, dev);
+ return -EPIPE;
+ }
+
+ info("%s: initializing I2C slave device 0x%x for output", Driver, dev);
+ if (i2c_smbus_write_byte_data(i2c_device, 3, 0) < 0) {
+ error("%s: error initializing device 0x%x\n", Driver, dev);
+ close(i2c_device);
+ }
+
+ return 0;
+}

int drv_generic_i2c_open(const char *section, const char *driver)
{
- int dev;
char *bus, *device;
udelay_init();
Section = (char *) section;
Driver = (char *) driver;
bus = cfg_get(Section, "Port", NULL);
device = cfg_get(Section, "Device", NULL);
- dev = atoi(device);
+ ctrldev = atoi(device);
+ device = cfg_get(Section, "DDevice", NULL);
+ datadev = atoi(device);
+
info("%s: initializing I2C bus %s", Driver, bus);
if ((i2c_device = open(bus, O_WRONLY)) < 0) {
error("%s: I2C bus %s open failed !\n", Driver, bus);
goto exit_error;
}
- info("%s: selecting slave device 0x%x", Driver, dev);
- if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
- error("%s: error selecting slave device 0x%x\n", Driver, dev);
- goto exit_error;
- }

- info("%s: initializing I2C slave device 0x%x", Driver, dev);
- if (i2c_smbus_write_quick(i2c_device, I2C_SMBUS_WRITE) < 0) {
- error("%s: error initializing device 0x%x\n", Driver, dev);
- close(i2c_device);
+ if (datadev) {
+ if (drv_generic_i2c_pre_write(datadev) < 0)
+ goto exit_error;
}

+ if (drv_generic_i2c_pre_write(ctrldev) < 0)
+ goto exit_error;
+
return 0;

exit_error:
@@ -172,8 +188,29 @@ void drv_generic_i2c_data(const unsigned char data)
my_i2c_smbus_write_byte_data(i2c_device, data);
}

+static void i2c_out(int dev, unsigned char val)
+{
+ info("%s: initializing I2C slave device 0x%x", Driver, dev);
+ if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
+ error("%s: error selecting slave device 0x%x\n", Driver, dev);
+ return;
+ }
+
+ i2c_smbus_write_byte_data(i2c_device, 1, val);
+}

-void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length)
+void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, int bits)
{
- i2c_smbus_write_block_data(i2c_device, command, length, data);
+ if (bits == 4) {
+ i2c_smbus_write_block_data(i2c_device, command, length, data);
+ } else if (bits == 8 && datadev) {
+ /* set data on pins */
+ info("cmd: %08x, data0: %08x, data1: %08x\n", command, data[0], data[1]);
+ i2c_out(datadev, data[0]);
+ /* set enable pin including optional rs and rw */
+ i2c_out(ctrldev, command | data[1]);
+ /* unset enable pin including optional rs and rw */
+ i2c_out(ctrldev, command);
+ }
+
}
diff --git a/drv_generic_i2c.h b/drv_generic_i2c.h
index 2cc6a02..bd68e44 100644
--- a/drv_generic_i2c.h
+++ b/drv_generic_i2c.h
@@ -57,6 +57,6 @@ int drv_generic_i2c_close(void);
unsigned char drv_generic_i2c_wire(const char *name, const char *deflt);
void drv_generic_i2c_byte(const unsigned char data);
void drv_generic_i2c_data(const unsigned char data);
-void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length);
+void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, int bits);

#endif
--
2.1.4


------------------------------------------------------------------------------
Michael Reinelt
2015-06-18 16:55:01 UTC
Permalink
Patch has been applied an checked in. Thanks a lot!
Post by Michael Grzeschik
This patch adds support for dual i2c io-expander
based 8bit support for HD44780. It multiplexes the
switch between the data and databits.
---
drv_HD44780.c | 82 ++++++++++++++++++++++++++++++++++++++-----------------
drv_generic_i2c.c | 65 +++++++++++++++++++++++++++++++++----------
drv_generic_i2c.h | 2 +-
3 files changed, 109 insertions(+), 40 deletions(-)
diff --git a/drv_HD44780.c b/drv_HD44780.c
index 26f0bc9..7f4a56a 100644
--- a/drv_HD44780.c
+++ b/drv_HD44780.c
@@ -706,10 +706,10 @@ static void drv_HD_PP_stop(void)
*/
-static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble)
+static void drv_HD_I2C(unsigned char controller, unsigned char byte, int rs, int rw)
{
unsigned char enable;
- unsigned char command; /* this is actually the first data byte on the PCF8574 */
+ unsigned char command = 0; /* this is actually the first data byte on the PCF8574 */
unsigned char data_block[2];
/* enable signal: 'controller' is a bitmask */
/* bit n .. send to controller #n */
@@ -738,28 +738,51 @@ static void drv_HD_I2C_nibble(unsigned char controller, unsigned char nibble)
The main advantage we see is that we do 2 less IOCTL's from our driver.
*/
- command = nibble;
- data_block[0] = nibble | enable;
- data_block[1] = nibble;
+ if (Bits == 4) {
+ if (rw)
+ byte |= SIGNAL_RW;
+ if (rs)
+ byte |= SIGNAL_RS;
+ command = byte;
+ data_block[0] = byte | enable;
+ data_block[1] = byte;
+
+ } else if (Bits == 8) {
+ if (rw)
+ command |= SIGNAL_RW;
+ if (rs)
+ command |= SIGNAL_RS;
+
+ data_block[0] = byte;
+ data_block[1] = enable;
+ }
- drv_generic_i2c_command(command, data_block, 2);
+ drv_generic_i2c_command(command, data_block, 2, Bits);
}
static void drv_HD_I2C_byte(const unsigned char controller, const unsigned char data)
{
/* send data with RS enabled */
- drv_HD_I2C_nibble(controller, ((data >> 4) & 0x0f) | SIGNAL_RS);
- drv_HD_I2C_nibble(controller, (data & 0x0f) | SIGNAL_RS);
+ if (Bits == 4) {
+ drv_HD_I2C(controller, ((data >> 4) & 0x0f), 1, 0);
+ drv_HD_I2C(controller, (data & 0x0f), 1, 0);
+ } else if (Bits == 8) {
+ drv_HD_I2C(controller, data, 1, 0);
+ }
}
static void drv_HD_I2C_command(const unsigned char controller, const unsigned char cmd, __attribute__ ((unused))
const unsigned long delay)
{
- /* send data with RS disabled */
- drv_HD_I2C_nibble(controller, ((cmd >> 4) & 0x0f));
- drv_HD_I2C_nibble(controller, ((cmd) & 0x0f));
+ /* send command data with RS disabled */
+ if (Bits == 4) {
+ drv_HD_I2C(controller, ((cmd >> 4) & 0x0f), 0, 0);
+ drv_HD_I2C(controller, ((cmd) & 0x0f), 0, 0);
+ } else if (Bits == 8) {
+ drv_HD_I2C(controller, cmd, 0, 0);
+ }
}
static void drv_HD_I2C_data(const unsigned char controller, const char *string, const int len, __attribute__ ((unused))
@@ -781,13 +804,14 @@ static int drv_HD_I2C_load(const char *section)
{
if (cfg_number(section, "Bits", 8, 4, 8, &Bits) < 0)
return -1;
- if (Bits != 4) {
- error("%s: bad %s.Bits '%d' from %s, should be '4'", Name, section, Bits, cfg_source());
- return -1;
- }
info("%s: using %d bit mode", Name, Bits);
+ if (Bits != 4 && Bits != 8) {
+ error("%s: bad %s.Bits '%d' from %s, should be '4' or '8'", Name, section, Bits, cfg_source());
+ return -1;
+ }
+
if (drv_generic_i2c_open(section, Name) != 0) {
error("%s: could not initialize i2c attached device!", Name);
return -1;
@@ -804,16 +828,24 @@ static int drv_HD_I2C_load(const char *section)
if ((SIGNAL_GPO = drv_generic_i2c_wire("GPO", "GND")) == 0xff)
return -1;
- /* initialize display */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
- drv_HD_I2C_nibble(allControllers, 0x03);
- udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
- drv_HD_I2C_nibble(allControllers, 0x02);
- udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
- drv_HD_I2C_command(allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
+ if (Bits == 4) {
+ /* initialize display */
+ drv_HD_I2C(allControllers, 0x02, 0, 0);
+ udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x03, 0, 0);
+ udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_I2C(allControllers, 0x03, 0, 0);
+ udelay(T_INIT1); /* 4 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x02, 0, 0);
+ udelay(T_INIT2); /* 4 Bit mode, wait 100 us */
+ drv_HD_I2C_command(allControllers, 0x28, T_EXEC); /* 4 Bit mode, 1/16 duty cycle, 5x8 font */
+ } else if (Bits == 8) {
+ drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 4.1 ms */
+ udelay(T_INIT1); /* 8 Bit mode, wait 4.1 ms */
+ drv_HD_I2C(allControllers, 0x30, 0, 0); /* 8 Bit mode, wait 100 us */
+ udelay(T_INIT2); /* 8 Bit mode, wait 4.1 ms */
+ drv_HD_I2C_command(allControllers, 0x38, T_EXEC); /* 8 Bit mode, 1/16 duty cycle, 5x8 font */
+ }
info("%s: I2C initialization done", Name);
diff --git a/drv_generic_i2c.c b/drv_generic_i2c.c
index 2170b0c..1bee16f 100644
--- a/drv_generic_i2c.c
+++ b/drv_generic_i2c.c
@@ -62,7 +62,8 @@
static char *Driver = "";
static char *Section = "";
static int i2c_device;
-
+static int ctrldev;
+static int datadev;
static void my_i2c_smbus_write_byte_data(const int device, const unsigned char val)
{
@@ -91,34 +92,49 @@ static void my_i2c_smbus_read_byte_data(const int device, const unsigned char da
}
#endif
+int drv_generic_i2c_pre_write(int dev) {
+
+ info("%s: selecting slave device 0x%x", Driver, dev);
+ if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
+ error("%s: error selecting slave device 0x%x\n", Driver, dev);
+ return -EPIPE;
+ }
+
+ info("%s: initializing I2C slave device 0x%x for output", Driver, dev);
+ if (i2c_smbus_write_byte_data(i2c_device, 3, 0) < 0) {
+ error("%s: error initializing device 0x%x\n", Driver, dev);
+ close(i2c_device);
+ }
+
+ return 0;
+}
int drv_generic_i2c_open(const char *section, const char *driver)
{
- int dev;
char *bus, *device;
udelay_init();
Section = (char *) section;
Driver = (char *) driver;
bus = cfg_get(Section, "Port", NULL);
device = cfg_get(Section, "Device", NULL);
- dev = atoi(device);
+ ctrldev = atoi(device);
+ device = cfg_get(Section, "DDevice", NULL);
+ datadev = atoi(device);
+
info("%s: initializing I2C bus %s", Driver, bus);
if ((i2c_device = open(bus, O_WRONLY)) < 0) {
error("%s: I2C bus %s open failed !\n", Driver, bus);
goto exit_error;
}
- info("%s: selecting slave device 0x%x", Driver, dev);
- if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
- error("%s: error selecting slave device 0x%x\n", Driver, dev);
- goto exit_error;
- }
- info("%s: initializing I2C slave device 0x%x", Driver, dev);
- if (i2c_smbus_write_quick(i2c_device, I2C_SMBUS_WRITE) < 0) {
- error("%s: error initializing device 0x%x\n", Driver, dev);
- close(i2c_device);
+ if (datadev) {
+ if (drv_generic_i2c_pre_write(datadev) < 0)
+ goto exit_error;
}
+ if (drv_generic_i2c_pre_write(ctrldev) < 0)
+ goto exit_error;
+
return 0;
@@ -172,8 +188,29 @@ void drv_generic_i2c_data(const unsigned char data)
my_i2c_smbus_write_byte_data(i2c_device, data);
}
+static void i2c_out(int dev, unsigned char val)
+{
+ info("%s: initializing I2C slave device 0x%x", Driver, dev);
+ if (ioctl(i2c_device, I2C_SLAVE, dev) < 0) {
+ error("%s: error selecting slave device 0x%x\n", Driver, dev);
+ return;
+ }
+
+ i2c_smbus_write_byte_data(i2c_device, 1, val);
+}
-void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length)
+void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, int bits)
{
- i2c_smbus_write_block_data(i2c_device, command, length, data);
+ if (bits == 4) {
+ i2c_smbus_write_block_data(i2c_device, command, length, data);
+ } else if (bits == 8 && datadev) {
+ /* set data on pins */
+ info("cmd: %08x, data0: %08x, data1: %08x\n", command, data[0], data[1]);
+ i2c_out(datadev, data[0]);
+ /* set enable pin including optional rs and rw */
+ i2c_out(ctrldev, command | data[1]);
+ /* unset enable pin including optional rs and rw */
+ i2c_out(ctrldev, command);
+ }
+
}
diff --git a/drv_generic_i2c.h b/drv_generic_i2c.h
index 2cc6a02..bd68e44 100644
--- a/drv_generic_i2c.h
+++ b/drv_generic_i2c.h
@@ -57,6 +57,6 @@ int drv_generic_i2c_close(void);
unsigned char drv_generic_i2c_wire(const char *name, const char *deflt);
void drv_generic_i2c_byte(const unsigned char data);
void drv_generic_i2c_data(const unsigned char data);
-void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length);
+void drv_generic_i2c_command(const unsigned char command, /*const */ unsigned char *data, const unsigned char length, int bits);
#endif
--
Michael Reinelt <***@reinelt.co.at>
http://home.pages.at/reinelt
GPG-Key 0xDF13BA50
ICQ #288386781

------------------------------------------------------------------------------
Loading...