summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/omap3_h1.dts29
-rw-r--r--arch/arm/mach-omap2/board-omap3h1.c9
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/power/bq27x00_battery.c218
-rw-r--r--drivers/staging/triune/ts81001.c272
-rw-r--r--drivers/staging/triune/ts81001.h4
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/omap3h1_bt_sco.c74
-rw-r--r--sound/soc/omap/Kconfig1
-rw-r--r--sound/soc/omap/omap3h1.c197
11 files changed, 665 insertions, 147 deletions
diff --git a/arch/arm/boot/dts/omap3_h1.dts b/arch/arm/boot/dts/omap3_h1.dts
index 7b922bb66b0..46c6e2d97b1 100644
--- a/arch/arm/boot/dts/omap3_h1.dts
+++ b/arch/arm/boot/dts/omap3_h1.dts
@@ -68,7 +68,7 @@
* for a gpio IRQ (banks numbered 1 to 6)
* irq = 16 + 96 + (gpio_bank - 1) * 32 + GPIO no.
*/
- compatible = "ti,pad-wkup";
+ compatible = "ti,pad-wkup";
/* Map the pad offset (off) to an interrupt (IRQ). */
/* if handle is 1, an irq will be generated based on */
@@ -83,15 +83,16 @@
/* off IRQ handle */
ti,pad_irq = <0x150 88 1>, /* 72 + 16, uart1 - BT input */
- <0x9f6 143 1>, /* mpu6515 irq pin - is this offset correct? */
- <0x9ea 122 1>, /* bq27400 chg irq8 */
- <0x9f4 123 1>, /* BT host wake */
- <0x1b0 23 1>; /* sys_nirq */
+ <0x9f6 143 1>, /* mpu6515 irq pin - is this offset correct? */
+ /* <0x9ea 122 1>, */ /* bq27400 chg irq8 - needed here? */
+ <0x9f4 123 1>, /* BT host wake */
+ <0x1b0 23 1>; /* sys_nirq */
};
sound {
compatible = "olio,omap-soc-omap3h1";
- olio,mcbsp = <&mcbsp3>;
+ olio,mcbsp_bt = <&mcbsp2>;
+ olio,mcbsp_mic = <&mcbsp3>;
olio,mic_enable = <&gpio5 18 0>;
};
};
@@ -215,14 +216,14 @@
>;
};
- dev_pins: pinmux_pv_pins {
- pinctrl-single,pins = <
- 0x5b2 0x204 /* USB control, ETK_D3, MODE4 | OUTPUT */
- /* 0x1a2 0x104 */ /* ALS interrupt, input, GPIO */
- 0x086 0x004 /* DRV2605 vibrator, output, GPIO */
- /* 0x938 0x104 */ /* Battery state, input, GPIO */
- >;
- };
+dev_pins: pinmux_pv_pins {
+ pinctrl-single,pins = <
+ 0x5b2 0x204 /* USB control, ETK_D3, MODE4 | OUTPUT */
+ /* 0x1a2 0x104 */ /* ALS interrupt, input, GPIO */
+ 0x086 0x004 /* DRV2605 vibrator, output, GPIO */
+ /* 0x938 0x104 */ /* Battery state, input, GPIO */
+ >;
+ };
/*
i2c1_pins: pinmux_i2c1_pins {
diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c
index ad40bd6d90e..7915962e45b 100644
--- a/arch/arm/mach-omap2/board-omap3h1.c
+++ b/arch/arm/mach-omap2/board-omap3h1.c
@@ -254,6 +254,10 @@ static struct platform_device omap3h1_dmic_codec = {
.id = -1,
};
+static struct platform_device omap3h1_bt_codec = {
+ .name = "omap3h1_bt_sco",
+ .id = -1,
+};
/* --------------------------------------------------------------------------- */
/* USB settings
@@ -473,9 +477,10 @@ static int __init omap3_h1_i2c_init(void)
static struct platform_device *omap3h1_devices[] __initdata = {
- &bcm20702_bluetooth_device,
- &nop_phy_device,
+ &bcm20702_bluetooth_device,
+ &nop_phy_device,
&omap3h1_dmic_codec,
+ &omap3h1_bt_codec,
};
static void __init omap3_h1_init(void)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 0e15ad357aa..00fb5ac811c 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -690,7 +690,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
r = omap_i2c_wait_for_bb(dev);
/* If timeout, try to again check after attempting to clear the bus */
- if (WARN_ON(r == -ETIMEDOUT)) {
+ if (r == -ETIMEDOUT) { /* removed WARN_ON here, too much output from ts81001 */
r = omap_i2c_bus_clear(dev);
if (r < 0) {
dev_err(dev->dev, "Unable to recover i2c bus from bb\n");
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index c26859a2f84..8002531960e 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -47,18 +47,30 @@
#include <linux/power/bq27x00_battery.h>
#ifdef CONFIG_OLIO_TS81001
+
+/*
+ * OLIO Model One needs the fuel gauge to talk to the charger in some
+ * instances, such as deciding whether we're using the wireless
+ * charger or not. Hence this build flag.
+ *
+ * In hindsight, a lot of this can probably be moved to the charger
+ * manager.
+ */
+#include <linux/alarmtimer.h>
+#include "asm/io.h"
+#include "../../arch/arm/mach-omap2/mux.h"
+#include "../../arch/arm/mach-omap2/iomap.h"
#include "../staging/triune/ts81001.h"
#endif /* CONFIG_OLIO_TS81001 */
-
#ifdef OLIODEBUG
-#define do { olio_debug(format, ...) printk("OLIO %s: ", __FUNCTION__); \
+#define olio_debug(format, ...) do { \
+ printk("OLIO %s: ", __FUNCTION__); \
printk(format, ##__VA_ARGS__); } while(0)
#else
#define olio_debug(format, ...)
#endif
-
#define DRIVER_VERSION "1.2.0"
#define INVALID_REG_ADDR 0xFF
@@ -84,8 +96,14 @@ enum bq27xxx_reg_index {
NUM_REGS
};
+/* lock taken if we want the upper layers to run */
+
struct wake_lock chg_wake_lock;
+/* lock taken by interrupt to let work queue run*/
+
+struct wake_lock isr_wake_lock;
+
/* bq27500 registers */
static __initdata u8 bq27500_regs[NUM_REGS] = {
0x00, /* CONTROL */
@@ -226,7 +244,7 @@ static __initdata u8 bq276xx_regs[NUM_REGS] = {
#define BQ274XX_UNSEAL_KEY 0x80008000
#define BQ274XX_SOFT_RESET 0x43
-#define BQ274XX_FLAG_ITPOR 0x20
+#define BQ274XX_FLAG_ITPOR 0x20
#define BQ274XX_CTRL_STATUS_INITCOMP 0x80
#define BQ27XXX_FLAG_DSC BIT(0)
@@ -261,6 +279,8 @@ static __initdata u8 bq276xx_regs[NUM_REGS] = {
#define BQ276XX_OP_CFG_B_OFFSET 2
#define BQ276XX_OP_CFG_B_DEF_SEAL_BIT (1 << 5)
+#define BQ27X00_ALARM_TIMER_INTERVAL 300 /* 5 minutes */
+
struct bq27x00_device_info;
struct bq27x00_access_methods {
int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
@@ -306,6 +326,7 @@ struct bq27x00_device_info {
unsigned long last_update;
struct delayed_work work;
+ struct delayed_work interrupt_work;
struct power_supply bat;
@@ -318,6 +339,9 @@ struct bq27x00_device_info {
u8 regs[NUM_REGS];
struct dm_reg *dm_regs;
u16 dm_regs_count;
+
+ struct alarm poll_alarm;
+ ktime_t alarm_time;
};
static __initdata enum power_supply_property bq27x00_battery_props[] = {
@@ -410,6 +434,9 @@ static __initdata enum power_supply_property bq276xx_battery_props[] = {
* Ordering the parameters based on subclass and then offset will help in
* having fewer flash writes while updating.
* Customize these values and, if necessary, add more based on system needs.
+
+ To be added, maybe (for bq274xx):
+ {81, 9, 1, 3}, Quit Relax Time (3s)
*/
static struct dm_reg bq274xx_dm_regs[] = {
{36, 6, 1, 90}, /* FC Clear % */
@@ -438,6 +465,8 @@ module_param(poll_interval, uint, 0644);
MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
"0 disables polling");
+static volatile int mA_now;
+
/*
* Forward Declarations
*/
@@ -445,6 +474,14 @@ static int read_dm_block(struct bq27x00_device_info *di, u8 subclass,
u8 offset, u8 *data);
+#ifdef CONFIG_OLIO_TS81001
+static int bq27x00_charger_status(struct bq27x00_device_info *di,
+ union power_supply_propval *val);
+static int bq27x00_battery_status(struct bq27x00_device_info *di,
+ union power_supply_propval *val);
+#endif
+
+
/*
* Common code for BQ27x00 devices
*/
@@ -974,7 +1011,12 @@ static void bq27x00_update(struct bq27x00_device_info *di)
bool is_bq274xx = di->chip == BQ274XX;
bool is_bq276xx = di->chip == BQ276XX;
+ olio_debug ("entered\n");
+
cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, !is_bq27500);
+
+ olio_debug ("Cache flags read from bq is 0x%x\n", cache.flags);
+
if (cache.flags >= 0) {
if (is_bq27200 && (cache.flags & BQ27200_FLAG_CI)) {
dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
@@ -1060,10 +1102,11 @@ static bool rom_mode_gauge_dm_initialized(struct bq27x00_device_info *di)
dev_dbg(di->dev, "%s: flags - 0x%04x\n", __func__, flags);
- if (flags & BQ274XX_FLAG_ITPOR)
+ if (flags & BQ274XX_FLAG_ITPOR) {
return false;
- else
+ } else {
return true;
+ }
}
#define INITCOMP_TIMEOUT_MS 10000
@@ -1103,6 +1146,9 @@ static void rom_mode_gauge_dm_init(struct bq27x00_device_info *di)
subclass = dm_reg->subclass;
offset = dm_reg->offset;
+ olio_debug ("updating reg %d, offset %d\n",
+ subclass, offset);
+
/*
* Create a composite block number to see if the subsequent
* register also belongs to the same 32 btye block in the DM
@@ -1136,10 +1182,40 @@ static void rom_mode_gauge_dm_init(struct bq27x00_device_info *di)
exit_cfg_update_mode(di);
}
-static void bq27x00_battery_poll(struct work_struct *work)
+
+/***************************************************************************
+ * bq27x00_battery_interrupt - work to do from interrupt
+ *
+ * Decide whether we actually want to wake up, then take a wake lock if
+ * appropriate.
+ */
+
+static void bq27x00_battery_interrupt (struct work_struct *i_work)
{
+ int status;
+ union power_supply_propval val;
struct bq27x00_device_info *di =
- container_of(work, struct bq27x00_device_info, work.work);
+ container_of(i_work, struct bq27x00_device_info, interrupt_work.work);
+
+ olio_debug ("taking charge wake lock\n");
+
+ wake_lock_timeout(&chg_wake_lock, msecs_to_jiffies(500));
+ bq27x00_update (di);
+ status = bq27x00_battery_status(di, &val);
+
+ olio_debug ("battery status = %d\n", status);
+
+ /* release the low-level wake lock (taken in isr handler) */
+ wake_unlock (&isr_wake_lock);
+}
+
+
+static void bq27x00_battery_poll(struct work_struct *p_work)
+{
+ struct bq27x00_device_info *di =
+ container_of(p_work, struct bq27x00_device_info, work.work);
+
+ olio_debug ("entered\n");
if (((di->chip == BQ274XX) || (di->chip == BQ276XX)) &&
!rom_mode_gauge_dm_initialized(di)) {
@@ -1155,13 +1231,33 @@ static void bq27x00_battery_poll(struct work_struct *work)
}
}
+static enum alarmtimer_restart
+bq27x00_run_poll_alarm(struct alarm * p_alarm, ktime_t now)
+{
+ struct bq27x00_device_info *di =
+ container_of(p_alarm, struct bq27x00_device_info, poll_alarm);
+
+ olio_debug ("entered\n");
+
+ wake_lock_timeout(&chg_wake_lock, msecs_to_jiffies(500));
+
+ cancel_delayed_work(&di->work);
+ schedule_delayed_work(&di->work, 5);
+
+ /* reschedule manually, since restart doesn't seem to do what we want. */
+
+ alarm_start_relative (&di->poll_alarm, di->alarm_time);
+
+ return ALARMTIMER_NORESTART;
+}
+
/*
* Return the battery average current in µA
* Note that current can be negative signed as well
* Or 0 if something fails.
*/
static int bq27x00_battery_current(struct bq27x00_device_info *di,
- union power_supply_propval *val)
+ union power_supply_propval *val)
{
int curr;
int flags;
@@ -1190,7 +1286,36 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
#ifdef CONFIG_OLIO_TS81001
-static int bq27x00_charger_status(struct bq27x00_device_info *di) {
+/* These are unfortunately hardcoded to our (OLIO's) GPIO pins right now. */
+
+/* We need to turn off the wakeup capability of the pins when we don't
+ * want the interrupts, or all heck breaks loose.
+ */
+
+static void olio_interrupt_enabled (int irq) {
+ __raw_writew ((u16) (4 << 12 | 1 << 8 | 0 << 4 | 4),
+ (volatile void *)
+ OMAP2_L4_IO_ADDRESS(OMAP3_CONTROL_PADCONF_MUX_PBASE) +
+ OMAP3_CONTROL_PADCONF_SYS_CLKOUT1_OFFSET);
+ enable_irq (irq);
+ enable_irq_wake (irq);
+}
+
+
+static void olio_interrupt_disabled (int irq) {
+ disable_irq_wake (irq);
+ disable_irq (irq);
+ __raw_writew ((u16) (0 << 12 | 1 << 8 | 0 << 4 | 4),
+ (volatile void *)
+ OMAP2_L4_IO_ADDRESS(OMAP3_CONTROL_PADCONF_MUX_PBASE) +
+ OMAP3_CONTROL_PADCONF_SYS_CLKOUT1_OFFSET);
+}
+
+
+static volatile int irq_enabled = 1; /* enabled from start */
+
+static int bq27x00_charger_status (struct bq27x00_device_info *di,
+ union power_supply_propval *val) {
struct device * bq = di->dev;
struct bq27x00_platform_data * pdata = bq->platform_data;
struct ts81001 * ts81001;
@@ -1207,9 +1332,21 @@ static int bq27x00_charger_status(struct bq27x00_device_info *di) {
olio_debug("Got client data for dev %s\n", dev_name(ts81001->dev));
- if(di->cache.flags & BQ27XXX_FLAG_CHG) {
- ts81001->ops->request_charge(ts81001);
+#if 0
+ /* Test 1 */
+ if(di->cache.flags & BQ27XXX_FLAG_FC) {
+ ts81001->ops->request_charge(ts81001, 100);
+ } else {
+ ts81001->ops->request_charge(ts81001, 390);
+ }
+
+ /* Test 2 */
+ olio_debug ("mA_now == %d \n", mA_now);
+
+ if (mA_now < 0) {
+ ts81001->ops->request_charge(ts81001, 100);
}
+#endif
state = ts81001->ops->get_status(ts81001);
@@ -1219,11 +1356,27 @@ static int bq27x00_charger_status(struct bq27x00_device_info *di) {
{
case NOT_CHARGING:
olio_debug("exiting, DISCHARGING\n");
+ mutex_lock(&di->lock);
+ if (!irq_enabled) { /* set up for off charger behavior */
+ olio_debug ("off charger, enabling chg interrupts\n");
+ irq_enabled = 1;
+ olio_interrupt_enabled (di->irq);
+ alarm_cancel (&di->poll_alarm);
+ }
+ mutex_unlock(&di->lock);
return POWER_SUPPLY_STATUS_DISCHARGING;
case PRECHARGE:
case CHARGING_1C:
case TOPOFF:
olio_debug("exiting, CHARGING\n");
+ mutex_lock(&di->lock);
+ if (irq_enabled) { /* set up for on charger behavior */
+ olio_debug ("on charger, disabling chg interrupts\n");
+ irq_enabled = 0;
+ olio_interrupt_disabled (di->irq);
+ alarm_start_relative (&di->poll_alarm, di->alarm_time);
+ }
+ mutex_unlock(&di->lock);
return POWER_SUPPLY_STATUS_CHARGING;
default:
olio_debug("Couldn't read status from ts81001 charger.\n");
@@ -1231,7 +1384,6 @@ static int bq27x00_charger_status(struct bq27x00_device_info *di) {
return POWER_SUPPLY_STATUS_UNKNOWN;
}
}
-
#endif
static int bq27x00_battery_status(struct bq27x00_device_info *di,
@@ -1250,7 +1402,7 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
status = POWER_SUPPLY_STATUS_DISCHARGING;
} else {
#ifdef CONFIG_OLIO_TS81001
- status = bq27x00_charger_status (di);
+ status = bq27x00_charger_status (di, val);
if(status == POWER_SUPPLY_STATUS_CHARGING &&
di->cache.flags & BQ27XXX_FLAG_FC) {
@@ -1364,6 +1516,7 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
ret = bq27x00_battery_current(di, val);
+ mA_now = val->intval;
break;
case POWER_SUPPLY_PROP_CAPACITY:
ret = bq27x00_simple_value(di->cache.capacity, val);
@@ -1416,6 +1569,7 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
return ret;
}
+
static void bq27x00_external_power_changed(struct power_supply *psy)
{
struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
@@ -1424,14 +1578,17 @@ static void bq27x00_external_power_changed(struct power_supply *psy)
schedule_delayed_work(&di->work, 0);
}
-static irqreturn_t bq27x00_chg_isr(int irq, void *dev) {
+static irqreturn_t bq27x00_chg_isr(int irq, void *dev) {
struct power_supply *ps = (struct power_supply*) dev;
- wake_lock_timeout(&chg_wake_lock, msecs_to_jiffies(500));
- /* dev_dbg(ps->dev, "%s: Updating battery status\n", __func__); Don't
- do i/o in interrupt! */
+ struct bq27x00_device_info *di = to_bq27x00_device_info(ps);
+
+ olio_debug ("ISR triggered!\n");
- bq27x00_external_power_changed(ps);
+ wake_lock(&isr_wake_lock);
+
+ cancel_delayed_work(&di->interrupt_work);
+ schedule_delayed_work(&di->interrupt_work, 0);
return IRQ_HANDLED;
}
@@ -1476,6 +1633,18 @@ static int __init bq27x00_powersupply_init(struct bq27x00_device_info *di)
di->bat.external_power_changed = bq27x00_external_power_changed;
INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
+ INIT_DELAYED_WORK(&di->interrupt_work, bq27x00_battery_interrupt);
+
+#ifdef CONFIG_OLIO_TS81001
+ /* Set up alarm timer which wakes the device up if suspended. */
+
+ alarm_init (&di->poll_alarm, ALARM_BOOTTIME,
+ bq27x00_run_poll_alarm);
+
+ di->alarm_time = ktime_set(BQ27X00_ALARM_TIMER_INTERVAL,0);
+
+ alarm_start_relative (&di->poll_alarm, di->alarm_time);
+#endif
mutex_init(&di->lock);
ret = power_supply_register(di->dev, &di->bat);
@@ -1486,8 +1655,9 @@ static int __init bq27x00_powersupply_init(struct bq27x00_device_info *di)
/* This device is a wakeup source */
- device_init_wakeup(di->dev, 1);
+ /* device_init_wakeup(di->dev, 1); */
+ wake_lock_init(&isr_wake_lock, WAKE_LOCK_SUSPEND, "isr_wake_lock");
wake_lock_init(&chg_wake_lock, WAKE_LOCK_SUSPEND, "chg_wake_lock");
if(di->irq) {
@@ -1502,6 +1672,7 @@ static int __init bq27x00_powersupply_init(struct bq27x00_device_info *di)
}
ret = enable_irq_wake(di->irq);
+
if (ret) {
dev_err(di->dev, "failed to enable irq: %d, as wake\n", di->irq);
return ret;
@@ -1526,6 +1697,7 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
poll_interval = 0;
cancel_delayed_work_sync(&di->work);
+ cancel_delayed_work_sync(&di->interrupt_work);
power_supply_unregister(&di->bat);
@@ -1763,6 +1935,7 @@ static const struct attribute_group bq27x00_attr_group = {
#ifdef CONFIG_OLIO_TS81001
+
/***************************************************************************
* bq27x00_set_platform_data - act on basic platform data
*
@@ -1891,6 +2064,7 @@ static int __init bq27x00_battery_probe(struct i2c_client *client,
goto batt_failed_3;
/* Schedule a polling after about 1 min */
+
schedule_delayed_work(&di->work, 60 * HZ);
i2c_set_clientdata(client, di);
@@ -1944,8 +2118,8 @@ static struct i2c_driver bq27x00_battery_driver = {
.driver = {
.name = "bq27x00-battery",
},
- .probe = bq27x00_battery_probe,
- .remove = bq27x00_battery_remove,
+ .probe = bq27x00_battery_probe,
+ .remove = bq27x00_battery_remove,
.id_table = bq27x00_id,
};
diff --git a/drivers/staging/triune/ts81001.c b/drivers/staging/triune/ts81001.c
index 9ede65febc9..ed6f8abc78f 100644
--- a/drivers/staging/triune/ts81001.c
+++ b/drivers/staging/triune/ts81001.c
@@ -48,10 +48,20 @@
/* Globals */
-const int TS81001_ADDR=0x49;
-const u8 TS81001_STATUS_REG=0x10;
-const u8 TS81001_CURRENT_REG=0x20;
-const u16 TS81001_CHARGE_CURRENT=390;
+const int TS81001_ADDR = 0x49;
+const u8 TS81001_STATUS_REG = 0x10;
+const u8 TS81001_CURRENT_REG_LSB = 0x20;
+const u8 TS81001_CURRENT_REG_MSB = 0x21;
+
+/* Trying 400mA since we can't actually set 390mA. */
+
+const u16 TS81001_CHARGE_CURRENT = 400;
+const u8 TS81001_CHARGE_CURRENT_LSB = 0x90; /* 0x190 == 400 (0x186 == 390)*/
+const u8 TS81001_CHARGE_CURRENT_MSB = 0x01;
+
+const u8 TS81001_CHARGE_CURR_100_LSB = 0x64; /* 0x64 == 100 */
+const u8 TS81001_CHARGE_CURR_100_MSB = 0x00;
+
/***************************************************************************
@@ -66,7 +76,7 @@ static int ts81001_i2c_read (struct i2c_client * client,
int err = 0;
struct i2c_msg msg[2];
- olio_debug (" entered\n");
+ olio_debug ("entered\n");
msg[0].addr = client->addr;
msg[0].flags = client->flags;
@@ -83,36 +93,42 @@ static int ts81001_i2c_read (struct i2c_client * client,
else
err = i2c_transfer(client->adapter, msg, 2);
- olio_debug (" exiting\n");
+ olio_debug ("exiting\n");
return err;
}
-static int ts81001_write_i2c_blk(struct i2c_client * client, u8 reg,
- u8 *data, u8 sz)
+static int ts81001_write_i2c_blk(struct i2c_client * client, u8 reg_addr,
+ u8 * data, u16 sz)
{
struct i2c_msg msg;
int ret;
- u8 buf[33];
+ u8 buf[3];
+
+ olio_debug ("entered\n");
if (!client->adapter)
return -ENODEV;
- buf[0] = reg;
+ buf[0] = reg_addr;
memcpy(&buf[1], data, sz);
- msg.buf = buf;
+ olio_debug ("writing 0x%x,0x%x to 0x%x device 0x%x\n",
+ buf[1], buf[2], buf[0], client->addr);
+
msg.addr = client->addr;
- msg.flags = 0;
+ msg.flags = 0; //client->flags;
msg.len = sz + 1;
+ msg.buf = buf;
ret = i2c_transfer(client->adapter, &msg, 1);
- if (ret < 0)
- return ret;
+
+ olio_debug ("exiting, ret = %d\n", ret);
- return 0;
+ return ret;
}
+
/***************************************************************************
* ts81001_get_status - get current charger state.
*
@@ -132,10 +148,11 @@ static int ts81001_get_status (struct ts81001 * ts) {
olio_debug ("entered\n");
for (i = 0; i < retries; i++) {
- err = ts81001_i2c_read (ts->client, TS81001_STATUS_REG, len, &data, false);
-
+ err = ts81001_i2c_read (ts->client,
+ TS81001_STATUS_REG, len, &data, false);
if (err <= 0) {
- olio_debug ("Error reading status from ts81001, err = %d\n", err);
+ olio_debug ("Error reading status from ts81001, err = %d\n",
+ err);
state = err;
} else {
state = (ts81001_state_t) data;
@@ -148,32 +165,237 @@ static int ts81001_get_status (struct ts81001 * ts) {
return state;
}
-static int ts81001_request_charge (struct ts81001 * ts) {
+/***************************************************************************
+ * ts81001_request_charge - ask for current from charger
+ *
+ * This function allows us to set a new current for the charger. It depends
+ * on the firmware being recent enough, though. Returns the number of bytes
+ * written, or error (negative values) if needed.
+ */
+
+static int ts81001_request_charge (struct ts81001 * ts, u16 mA) {
int retries = 2;
int err = 0;
int i;
- u16 request_current = TS81001_CHARGE_CURRENT;
+ /* u16 request_current = TS81001_CHARGE_CURRENT; */
+ u8 data[2];
+
+ data[0] = mA & 0x00ff;
+ data[1] = (mA & 0xff00) >> 8;
+
+ printk ("OLIO %s entered, requested current = lb:0x%x, hb:0x%x\n",
+ __FUNCTION__, data[0], data[1]);
+
+ for (i = 0; i < retries; i++) {
+ err = ts81001_write_i2c_blk(ts->client,
+ TS81001_CURRENT_REG_LSB,
+ &data[0], 2);
+ if (err <= 0)
+ olio_debug ("error (%d) writing data to "
+ "register (try = %d)\n", err, i);
+ }
+
+ return err;
+}
+
+/***************************************************************************
+ * ts81001_charging_stop - send charge complete to power provider
+ *
+ * This function allows to stop charging - stopping and restarting charging
+ * is intended to simulate the device taken off the charger and put back on.
+ */
+
+#define TS81001_CHARGE_COMPLETE 0x01
+#define TS81001_STATE_REPORT_REG 0x12
+
+static int ts81001_charging_stop (struct ts81001 * ts) {
+ u8 data;
+ int len = 1;
+ int err = 0;
+ int i, retries = 2;
+
+ olio_debug ("entered\n");
+
+ data = TS81001_CHARGE_COMPLETE;
+
+ for (i = 0; i < retries; i++) {
+ err = ts81001_write_i2c_blk(ts->client, TS81001_STATE_REPORT_REG,
+ (u8*) &data, len);
+ }
+
+ if (err <= 0) {
+ olio_debug ("Error writing charging stop to ts81001, "
+ "err = %d\n", err);
+ }
+
+
+ olio_debug ("exiting\n");
+
+ return err;
+}
+
+
+/***************************************************************************
+ * ts81001_charging_stop - send charge complete to power provider
+ *
+ * This function allows to stop charging - stopping and restarting charging
+ * is intended to simulate the device taken off the charger and put back on.
+ */
+
+#define TS81001_CHARGE_RESTART 0xFF
+
+static int ts81001_charging_restart (struct ts81001 * ts) {
+ u8 data;
+ int len = 1;
+ int err = 0;
+ int i, retries = 2;
+
+ olio_debug ("entered\n");
+
+ data = TS81001_CHARGE_RESTART;
for (i = 0; i < retries; i++) {
- err = ts81001_write_i2c_blk(ts->client, TS81001_CURRENT_REG, (u8*) &request_current, 2);
+ err = ts81001_write_i2c_blk(ts->client,
+ TS81001_STATE_REPORT_REG,
+ (u8*) &data, len);
+
+ if (err <= 0) {
+ olio_debug ("Error writing state to ts81001, "
+ "err = %d\n", err);
+ }
}
+ olio_debug ("exiting\n");
+
return err;
}
+#if 0
+
+/* NOT FUNCTIONAL, NOT SURE HOW TO MAKE IT FUNCTIONAL! */
+
+/***************************************************************************
+ * ts81001_disconnect - stop talking to power TX
+ *
+ * If we send a 'signal strength' package, the TX unit should forget that
+ * we've reached full charge.
+ */
+
+static int ts81001_disconnect (struct ts81001 * ts) {
+ u8 data;
+ int len = 1;
+ int err = 0;
+ int i, retries = 2;
+
+ olio_debug ("entered\n");
+
+ data = TS81001_CHARGE_RESTART;
+
+ for (i = 0; i < retries; i++) {
+ err = ts81001_write_i2c_blk(ts->client,
+ TS81001_STATE_REPORT_REG,
+ (u8*) &data, len);
+
+ if (err <= 0) {
+ olio_debug ("Error writing state to ts81001, "
+ "err = %d\n", err);
+ }
+ }
+
+ olio_debug ("exiting\n");
+
+ return err;
+}
+#endif
static struct ts81001_ops ts_ops = {
- .get_status = ts81001_get_status,
+ .get_status = ts81001_get_status,
.request_charge = ts81001_request_charge,
+ .charge_stop = ts81001_charging_stop,
+ .charge_start = ts81001_charging_restart,
};
+
+
+/***************************************************************************
+ * sysfs operations
+ ***************************************************************************/
+
+/* sysfs entry for requesting power, mA's. */
+
+/***************************************************************************
+ * ts81001_sysfs_set_power_request - request power level from TX
+ *
+ * This entry allows us to request a certain power level from the TX unit.
+ * Mainly used for testing.
+ */
+
+static ssize_t ts81001_sysfs_set_power_request (
+ struct device * dev,
+ struct device_attribute * attr,
+ const char * buf,
+ size_t count)
+{
+ int mA_req;
+ int s;
+ u16 mA;
+ ssize_t retval = 0;
+
+ struct ts81001 * ts81001 =
+ i2c_get_clientdata (to_i2c_client (dev));
+
+ if ((s = sscanf (buf, "%d\n", &mA_req)) != 1) {
+ printk ("%s OLIO wrong number of args (%d, expected 1) "
+ "for power request.\n", __FUNCTION__, s);
+ retval = -EINVAL;
+ goto done;
+ } else {
+ printk ("%s OLIO read %d for new power level\n",
+ __FUNCTION__, mA_req);
+ }
+
+ if (mA_req > 0xffff) {
+ printk ("%s OLIO warning, max request is %d.\n",
+ __FUNCTION__, 0xffff);
+ mA_req = 0xffff;
+ }
+
+ mA = (u16) mA_req;
+
+ retval = ts81001_request_charge (ts81001, mA);
+
+done:
+ return count;
+}
+
+/***************************************************************************
+ * ts81001_sysfs_show_power_request - show the power level last requested
+ *
+ * This sysfs entry will read the value of the power request registers in
+ * the ts81001 and return it.
+ */
+
+static ssize_t ts81001_sysfs_show_power_request (struct device * dev,
+ struct device_attribute * attr,
+ char * buf) {
+
+ return 0;
+}
+
+static struct device_attribute ts81001_device_attr =
+ __ATTR(ts81001_power_request, S_IWUGO | S_IRUGO,
+ ts81001_sysfs_show_power_request,
+ ts81001_sysfs_set_power_request);
+
+
+
/***************************************************************************
* probe
*/
static int ts81001_i2c_probe(struct i2c_client * client,
- const struct i2c_device_id * id)
+ const struct i2c_device_id * id)
{
struct ts81001 *ts81001;
@@ -198,6 +420,8 @@ static int ts81001_i2c_probe(struct i2c_client * client,
i2c_set_clientdata(client, ts81001);
+ device_create_file (ts81001->dev, &ts81001_device_attr);
+
olio_debug ("exiting\n");
return ret;
@@ -230,6 +454,6 @@ static struct i2c_driver ts81001_i2c_driver = {
module_i2c_driver(ts81001_i2c_driver);
-MODULE_AUTHOR("Mattis Fjallstrom <mattis@oliodevice.com");
+MODULE_AUTHOR("Mattis Fjallstrom <mattis@oliodevices.com");
MODULE_DESCRIPTION("Basic driver for TS81001");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/triune/ts81001.h b/drivers/staging/triune/ts81001.h
index 8978ca2f0d1..aecf19780cc 100644
--- a/drivers/staging/triune/ts81001.h
+++ b/drivers/staging/triune/ts81001.h
@@ -52,7 +52,9 @@ struct ts81001 {
struct ts81001_ops {
int (*get_status) (struct ts81001 * ts);
- int (*request_charge) (struct ts81001 * ts);
+ int (*request_charge) (struct ts81001 * ts, u16 charge);
+ int (*charge_stop) (struct ts81001 * ts);
+ int (*charge_start) (struct ts81001 * ts);
};
#endif /* _CONFIG_TS81001_H */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 50ff7ca10a9..113ee1f928c 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -41,6 +41,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C
select SND_SOC_DFBMCS320
+ select SND_SOC_OMAP3H1_BT_SCO
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
@@ -266,6 +267,9 @@ config SND_SOC_DA9055
config SND_SOC_DFBMCS320
tristate
+config SND_SOC_OMAP3H1_BT_SCO
+ tristate
+
config SND_SOC_DMIC
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 39747d34c41..8e7bb4d4cbe 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -29,6 +29,7 @@ snd-soc-da7213-objs := da7213.o
snd-soc-da732x-objs := da732x.o
snd-soc-da9055-objs := da9055.o
snd-soc-dfbmcs320-objs := dfbmcs320.o
+snd-soc-omap3h1_bt_sco-objs := omap3h1_bt_sco.o
snd-soc-dmic-objs := dmic.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
@@ -157,6 +158,7 @@ obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o
+obj-$(CONFIG_SND_SOC_OMAP3H1_BT_SCO) += snd-soc-omap3h1_bt_sco.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
diff --git a/sound/soc/codecs/omap3h1_bt_sco.c b/sound/soc/codecs/omap3h1_bt_sco.c
new file mode 100644
index 00000000000..f72f004f64c
--- /dev/null
+++ b/sound/soc/codecs/omap3h1_bt_sco.c
@@ -0,0 +1,74 @@
+/*
+ * Driver for the DFBM-CS320 bluetooth module
+ * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <sound/soc.h>
+
+int omap3h1_bt_sco_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+ printk ("OMAP3H1:ASoc %s:%s starting\n", __FILE__, __FUNCTION__);
+ return 0;
+}
+
+void omap3h1_bt_sco_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+ printk ("OMAP3H1:ASoc %s:%s shutting down\n", __FILE__, __FUNCTION__);
+}
+
+static struct snd_soc_dai_ops omap3h1_bt_sco_dai_ops = {
+ .startup = omap3h1_bt_sco_dai_startup,
+ .shutdown = omap3h1_bt_sco_dai_shutdown,
+};
+
+static struct snd_soc_dai_driver omap3h1_bt_sco_dai = {
+ .name = "omap3h1_bt_sco-pcm",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &omap3h1_bt_sco_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_omap3h1_bt_sco;
+
+static int omap3h1_bt_sco_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_omap3h1_bt_sco,
+ &omap3h1_bt_sco_dai, 1);
+}
+
+static int omap3h1_bt_sco_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+
+ return 0;
+}
+
+
+static struct platform_driver omap3h1_bt_sco = {
+ .driver = {
+ .name = "omap3h1_bt_sco",
+ .owner = THIS_MODULE,
+ },
+ .probe = omap3h1_bt_sco_probe,
+ .remove = omap3h1_bt_sco_remove,
+};
+
+module_platform_driver(omap3h1_bt_sco);
+
+MODULE_AUTHOR("Evan Wilson <evan@oliodevices.com");
+MODULE_DESCRIPTION("OMAP3 H1 ALSA SoC codec driver");
+MODULE_LICENSE("GPL"); \ No newline at end of file
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 66d98e26a24..08c94b19bb9 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -31,6 +31,7 @@ config SND_OMAP_SOC_OMAP3_H1
depends on SND_OMAP_SOC && MACH_OMAP3_H1
select SND_OMAP_SOC_MCBSP
select SND_SOC_DMIC
+ select SND_SOC_OMAP3H1_BT_SCO
help
Say Y if you want to add support for SoC audio on the Olio H1 board.
diff --git a/sound/soc/omap/omap3h1.c b/sound/soc/omap/omap3h1.c
index f61949b295e..faad74810c3 100644
--- a/sound/soc/omap/omap3h1.c
+++ b/sound/soc/omap/omap3h1.c
@@ -22,7 +22,7 @@
*
*/
-#define DEBUG
+//#define DEBUG
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
@@ -42,19 +42,22 @@ static struct clk *per_96m_fck;
static unsigned long rate;
static int mic_gpio_enable;
-static int omap3h1_hw_params(struct snd_pcm_substream *substream,
+static int omap3h1_hw_in_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- //unsigned int fmt;
int ret = 0;
- unsigned int freq;
- //freq = 256 * params_rate(params);
- // We are triggering from the 96 MHz FSCK
+ pr_info("ASoc OMAP3H1: omap3h1_hw_in_params\n");
+ pr_info("ASoc OMAP3H1: in params channels=%d\n", params_channels(params));
+ pr_info("ASoc OMAP3H1: in params rate=%d\n", params_rate(params));
+ pr_info("ASoc OMAP3H1: in params params_period_size=%d\n", params_period_size(params));
+ pr_info("ASoc OMAP3H1: in params params_periods=%d\n", params_periods(params));
+ pr_info("ASoc OMAP3H1: in params params_buffer_size=%d\n", params_buffer_size(params));
+ pr_info("ASoc OMAP3H1: in params params_buffer_bytes=%d\n", params_buffer_bytes(params));
- // pr_info("ASoc OMAP3H1: setting system clock to: %d", freq);
+ /* Set McBSP clock to use PER_96M_FCLK */
ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
rate, SND_SOC_CLOCK_OUT);
if (ret < 0) {
@@ -62,68 +65,121 @@ static int omap3h1_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- // Set the divider so that our clock rate is ~3KHz, this is about
- // 48KHz sampling frequency on the mic (32-bit/channel, 2 channels, 48
- // Khz sampling)
+ /* The microphone becomes operational 2^18 clock cycles */
+ /* (85 ms with SCK at 3.072 MHz) */
ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 32);
if (ret < 0) {
- pr_err("ASoc OMAP3H1: can't set SRG clock divider\n");
+ pr_err("ASoc OMAP3H1: can't set MIC clock divider\n");
return ret;
}
return 0;
}
-static int omap3h1_startup(struct snd_pcm_substream *substream)
+static int omap3h1_hw_out_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+
+ pr_info("ASoc OMAP3H1: omap3h1_hw_out_params");
+ pr_info("ASoc OMAP3H1: out params channels=%u\n", params_channels(params));
+ pr_info("ASoc OMAP3H1: out params rate=%u\n", params_rate(params));
+ pr_info("ASoc OMAP3H1: out params params_period_size=%u\n", params_period_size(params));
+ pr_info("ASoc OMAP3H1: out params params_periods=%u\n", params_periods(params));
+ pr_info("ASoc OMAP3H1: out params params_buffer_size=%u\n", params_buffer_size(params));
+ pr_info("ASoc OMAP3H1: out params params_buffer_bytes=%u\n", params_buffer_bytes(params));
+
+ /* Set McBSP clock to use PER_96M_FCLK */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
+ rate, SND_SOC_CLOCK_OUT);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set DMIC cpu system clock\n");
+ return ret;
+ }
+
+ /* The BT operates on 512K freq */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, rate/512000);
+ if (ret < 0) {
+ pr_err("ASoc OMAP3H1: can't set BT clock divider\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int omap3h1_in_startup(struct snd_pcm_substream *substream)
{
+ pr_info("ASoc OMAP3H1: omap3h1_in_startup");
gpio_set_value(mic_gpio_enable, 1);
return clk_enable(per_96m_fck);
}
-static void omap3h1_shutdown(struct snd_pcm_substream *substream)
+static void omap3h1_in_shutdown(struct snd_pcm_substream *substream)
{
+ pr_info("ASoc OMAP3H1: omap3h1_in_shutdown");
gpio_set_value(mic_gpio_enable, 0);
clk_disable(per_96m_fck);
}
-static struct snd_soc_ops omap3h1_ops = {
- .hw_params = omap3h1_hw_params,
- .startup = omap3h1_startup,
- .shutdown = omap3h1_shutdown,
+static int omap3h1_out_startup(struct snd_pcm_substream *substream)
+{
+ pr_info("ASoc OMAP3H1: omap3h1_out_startup");
+ return clk_enable(per_96m_fck);
+}
+
+static void omap3h1_out_shutdown(struct snd_pcm_substream *substream)
+{
+ pr_info("ASoc OMAP3H1: omap3h1_out_shutdown");
+ clk_disable(per_96m_fck);
+}
+
+static struct snd_soc_ops omap3h1_in_ops = {
+ .hw_params = omap3h1_hw_in_params,
+ .startup = omap3h1_in_startup,
+ .shutdown = omap3h1_in_shutdown,
};
-//static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = {
-// SND_SOC_DAPM_MIC("Digital Mic", NULL),
-//};
-//
-//static const struct snd_soc_dapm_route dmic_audio_map[] = {
-// {"DMic", NULL, "Digital Mic"},
-//};
+static struct snd_soc_ops omap3h1_out_ops = {
+ .hw_params = omap3h1_hw_out_params,
+ .startup = omap3h1_out_startup,
+ .shutdown = omap3h1_out_shutdown,
+};
/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link omap3h1_dai = {
- .name = "DMIC",
- .stream_name = "DMIC Capture",
- .cpu_dai_name = "omap-mcbsp.3",
- .codec_dai_name = "dmic-hifi",
- .platform_name = "omap-pcm-audio",
- .codec_name = "dmic-codec",
- .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
- .ops = &omap3h1_ops,
+static struct snd_soc_dai_link omap3h1_dai[] = {
+ {
+ .name = "DMIC",
+ .stream_name = "DMIC Capture",
+ .cpu_dai_name = "omap-mcbsp.3",
+ .codec_dai_name = "dmic-hifi",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "dmic-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .ops = &omap3h1_in_ops,
+ },
+ {
+ .name = "BT",
+ .stream_name = "BT Playback",
+ .cpu_dai_name = "omap-mcbsp.2",
+ .codec_dai_name = "omap3h1_bt_sco-pcm",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "omap3h1_bt_sco",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .ops = &omap3h1_out_ops,
+ }
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_omap3h1 = {
.name = "omap3h1",
.owner = THIS_MODULE,
- .dai_link = &omap3h1_dai,
- .num_links = 1,
-
-// .dapm_widgets = dmic_dapm_widgets,
-// .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets),
-// .dapm_routes = dmic_audio_map,
-// .num_dapm_routes = ARRAY_SIZE(dmic_audio_map),
+ .dai_link = omap3h1_dai,
+ .num_links = ARRAY_SIZE(omap3h1_dai),
};
static int omap3h1_card_probe(struct platform_device *pdev)
@@ -135,15 +191,24 @@ static int omap3h1_card_probe(struct platform_device *pdev)
#ifdef CONFIG_OF
if (node) {
- struct device_node *dai_node;
+ struct device_node *dai_node1;
+ struct device_node *dai_node2;
+
+ dai_node1 = of_parse_phandle(node, "olio,mcbsp_mic", 0);
+ if (!dai_node1) {
+ dev_err(&pdev->dev, "mcbsp3 node is not provided\n");
+ return -EINVAL;
+ }
+ omap3h1_dai[0].cpu_dai_name = NULL;
+ omap3h1_dai[0].cpu_of_node = dai_node1;
- dai_node = of_parse_phandle(node, "olio,mcbsp", 0);
- if (!dai_node) {
- dev_err(&pdev->dev, "mcbsp node is not provided\n");
+ dai_node2 = of_parse_phandle(node, "olio,mcbsp_bt", 0);
+ if (!dai_node2) {
+ dev_err(&pdev->dev, "mcbsp2 node is not provided\n");
return -EINVAL;
}
- omap3h1_dai.cpu_dai_name = NULL;
- omap3h1_dai.cpu_of_node = dai_node;
+ omap3h1_dai[1].cpu_dai_name = NULL;
+ omap3h1_dai[1].cpu_of_node = dai_node2;
} else {
dev_err(&pdev->dev, "Missing node\n");
@@ -191,52 +256,18 @@ static int omap3h1_card_remove(struct platform_device *pdev)
return 0;
}
-/**
- * omap3h1_sound_suspend - suspend microphone
- *
- */
-
-static int omap3h1_sound_suspend(struct device *dev) {
- printk ("OLIO %s:%s Suspending\n", __FILE__, __FUNCTION__);
-
- snd_soc_suspend(dev);
-
- return 0;
-}
-
-
-/**
- * omap3h1_sound_resume - resume microphone
- *
- */
-
-static int omap3h1_sound_resume(struct device *dev) {
- printk ("OLIO %s:%s Resuming\n", __FILE__, __FUNCTION__);
-
- snd_soc_resume (dev);
-
- return 0;
-}
-
-
-/* ---------------------------------------------------------------------- */
-
-static const struct dev_pm_ops omap3h1_sound_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(omap3h1_sound_suspend, omap3h1_sound_resume)
-};
-
-
static const struct of_device_id omap_soc_h1_of_match[] = {
{.compatible = "olio,omap-soc-omap3h1", },
{ },
};
+
MODULE_DEVICE_TABLE(of, omap_soc_h1_of_match);
static struct platform_driver omap3h1_driver = {
.driver = {
.name = "omap-soc-omap3h1",
.of_match_table = of_match_ptr(omap_soc_h1_of_match),
- .pm = &snd_soc_pm_ops,
+ .pm = &snd_soc_pm_ops,
},
.probe = omap3h1_card_probe,
.remove = omap3h1_card_remove,