From 5d6f6259ee50bf24a75071c82c365937d74c5165 Mon Sep 17 00:00:00 2001 From: Marcoen Hirschberg Date: Mon, 21 Aug 2006 15:06:08 +0000 Subject: add driver for Semtech SC606 LED driver (for backlight and button LEDs) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10676 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c | 182 +++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c (limited to 'firmware/target/arm/gigabeat') diff --git a/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c new file mode 100644 index 0000000000..b4e55083e3 --- /dev/null +++ b/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c @@ -0,0 +1,182 @@ +#include "config.h" +#include "cpu.h" +#include +#include "kernel.h" +#include "system.h" +#include "hwcompat.h" +#include "logf.h" +#include "debug.h" +#include "string.h" + +#define SLAVE_ADDRESS 0xCC + +#define SDA_LO GPHDAT &= ~(1 << 9) +#define SDA_HI GPHDAT |= (1 << 9) +#define SDA_INPUT GPHCON &= ~(3 << 18) +#define SDA_OUTPUT GPHCON |= (1 << 18) +#define SDA GPHDAT & (1 << 9) + +#define SCL_LO GPHDAT &= ~(1 << 10) +#define SCL_HI GPHDAT |= (1 << 10) +#define SCL_INPUT GPHCON &= ~(3 << 20) +#define SCL_OUTPUT GPHCON |= (1 << 20) +#define SCL GPHDAT & (1 << 10) + +#define SCL_SDA_HI GPHDAT |= (3 << 9) + +/* arbitrary delay loop */ +#define DELAY do { int _x; for(_x=0;_x<2000;_x++);} while (0) + +void sc606_i2c_start(void) +{ + SCL_SDA_HI; + DELAY; + SDA_LO; + DELAY; + SCL_LO; +} + +void sc606_i2c_restart(void) +{ + SCL_SDA_HI; + DELAY; + SDA_LO; + DELAY; + SCL_LO; +} + +void sc606_i2c_stop(void) +{ + SDA_LO; + DELAY; + SCL_HI; + DELAY; + SDA_HI; + DELAY; +} + +void sc606_i2c_ack() +{ + + SDA_LO; + SCL_HI; + DELAY; + SCL_LO; +} + +int sc606_i2c_getack(void) +{ + int ret = 0; + + /* Don't need a delay since this follows a data bit with a delay on the end */ + SDA_INPUT; /* And set to input */ + SCL_HI; + DELAY; + + if (SDA) /* ack failed */ + ret = 1; + + DELAY; + SCL_LO; + DELAY; + SDA_OUTPUT; + return ret; +} + +int sc606_i2c_outb(unsigned char byte) +{ + int i; + + /* clock out each bit, MSB first */ + for (i = 0x80; i; i >>= 1) { + + if (i & byte) { + SDA_HI; + } else { + SDA_LO; + } + + DELAY; + SCL_HI; + DELAY; + SCL_LO; + DELAY; + } + + return sc606_i2c_getack(); +} + +unsigned char sc606_i2c_inb() +{ + int i; + unsigned char byte = 0; + + SDA_INPUT; /* And set to input */ + /* clock in each bit, MSB first */ + for (i = 0x80; i; i >>= 1) { + SCL_HI; + + if (SDA) + byte |= i; + + SCL_LO; + } + SDA_OUTPUT; + + sc606_i2c_ack(); + + return byte; +} + +int sc606_write(unsigned char reg, unsigned char data) +{ + int x = 0; + + sc606_i2c_start(); + x += sc606_i2c_outb(SLAVE_ADDRESS); + x += 0x10 * sc606_i2c_outb(reg); + sc606_i2c_start(); +/* sc606_i2c_restart(); */ + x += 0x100 * sc606_i2c_outb(SLAVE_ADDRESS); + x += 0x1000 *sc606_i2c_outb(data); + sc606_i2c_stop(); + + return x; +} + +int sc606_read(unsigned char reg, unsigned char* data) +{ + int x = 0; + + sc606_i2c_start(); + sc606_i2c_outb(SLAVE_ADDRESS); + sc606_i2c_outb(reg); + sc606_i2c_restart(); + sc606_i2c_outb(SLAVE_ADDRESS | 1); + *data = sc606_i2c_inb(); + sc606_i2c_stop(); + + return x; +} + +void sc606_init() +{ + /* Set GPB2 (EN) to 1 */ + GPBCON = (GPBCON & ~(3<<4)) | 1<<4; + + /* Turn enable line on */ + GPBDAT |= 1<<2; + /* OFF GPBDAT &= ~(1 << 2); */ + + /* About 400us - needs 350us */ + DELAY; + DELAY; + DELAY; + DELAY; + DELAY; + + /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ + GPHUP &= ~(3<<9); + GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18; +} + -- cgit v1.2.3