diff options
Diffstat (limited to 'arch/arm/plat-s3c24xx')
-rw-r--r-- | arch/arm/plat-s3c24xx/neo1973_pm_bt.c | 115 |
1 files changed, 57 insertions, 58 deletions
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c index 894651afc12..217fcf05953 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c @@ -36,6 +36,8 @@ struct gta01_pm_bt_data { struct regulator *regulator; + struct rfkill *rfkill; + int pre_resume_state; }; static ssize_t bt_read(struct device *dev, struct device_attribute *attr, @@ -72,11 +74,35 @@ static ssize_t bt_read(struct device *dev, struct device_attribute *attr, } } +static void __gta02_pm_bt_toggle_radio(struct device *dev, unsigned int on) +{ + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev); + + dev_info(dev, "__gta02_pm_bt_toggle_radio %d\n", on); + + if (machine_is_neo1973_gta02()) { + + bt_data = dev_get_drvdata(dev); + + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on); + + if (on) { + if (!regulator_is_enabled(bt_data->regulator)) + regulator_enable(bt_data->regulator); + } else { + if (regulator_is_enabled(bt_data->regulator)) + regulator_disable(bt_data->regulator); + } + + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on); + } +} + + static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state) { struct device *dev = data; unsigned long on = (state == RFKILL_STATE_ON); - struct gta01_pm_bt_data *bt_data; if (machine_is_neo1973_gta01()) { /* if we are powering up, assert reset, then power, @@ -90,25 +116,8 @@ static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state) pcf50606_onoff_set(pcf50606_global, PCF50606_REGULATOR_D1REG, on); neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on); - } else if (machine_is_neo1973_gta02()) { - if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == on) - return 0; - - bt_data = dev_get_drvdata(dev); - BUG_ON(!bt_data || !bt_data->regulator); - - neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on); - - if (on) { - if (!regulator_is_enabled(bt_data->regulator)) - regulator_enable(bt_data->regulator); - } else { - if (regulator_is_enabled(bt_data->regulator)) - regulator_disable(bt_data->regulator); - } - - neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on); - } + } else if (machine_is_neo1973_gta02()) + __gta02_pm_bt_toggle_radio(dev, on); return 0; } @@ -117,15 +126,12 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long on = simple_strtoul(buf, NULL, 10); - unsigned int vol; - struct gta01_pm_bt_data *bt_data; - struct regulator *regulator; + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev); if (!strcmp(attr->attr.name, "power_on")) { - struct rfkill *rfkill = dev_get_drvdata(dev); enum rfkill_state state = on ? RFKILL_STATE_ON : RFKILL_STATE_OFF; bt_rfkill_toggle_radio(dev, state); - rfkill->state = state; + bt_data->rfkill->state = state; if (machine_is_neo1973_gta01()) { /* if we are powering up, assert reset, then power, @@ -139,29 +145,9 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr, pcf50606_onoff_set(pcf50606_global, PCF50606_REGULATOR_D1REG, on); neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on); - } else if (machine_is_neo1973_gta02()) { - if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == on) - return count; - - bt_data = dev_get_drvdata(dev); - BUG_ON(!bt_data || !bt_data->regulator); - regulator = bt_data->regulator; - - neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on); - - if (on) { - if (!regulator_is_enabled(regulator)) - regulator_enable(regulator); - } else { - if (regulator_is_enabled(regulator)) - regulator_disable(regulator); - } - - vol = regulator_get_voltage(regulator); + } else if (machine_is_neo1973_gta02()) + __gta02_pm_bt_toggle_radio(dev, on); - dev_info(dev, "GTA02 Set PCF50633 LDO4 = %d\n", vol); - neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on); - } } else if (!strcmp(attr->attr.name, "reset")) { /* reset is low-active, so we need to invert */ if (machine_is_neo1973_gta01()) { @@ -180,18 +166,29 @@ static DEVICE_ATTR(reset, 0644, bt_read, bt_write); #ifdef CONFIG_PM static int gta01_bt_suspend(struct platform_device *pdev, pm_message_t state) { + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); + dev_dbg(&pdev->dev, DRVMSG ": suspending\n"); - /* FIXME: The PMU should save the PMU status, and the GPIO code should - * preserve the GPIO level, so there shouldn't be anything left to do - * for us, should there? */ + + if (machine_is_neo1973_gta02()) { + bt_data->pre_resume_state = + s3c2410_gpio_getpin(GTA02_GPIO_BT_EN); + __gta02_pm_bt_toggle_radio(&pdev->dev, 0); + } return 0; } static int gta01_bt_resume(struct platform_device *pdev) { + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); dev_dbg(&pdev->dev, DRVMSG ": resuming\n"); + if (machine_is_neo1973_gta02()) { + __gta02_pm_bt_toggle_radio(&pdev->dev, + bt_data->pre_resume_state); + } + return 0; } #else @@ -219,6 +216,8 @@ static int __init gta01_bt_probe(struct platform_device *pdev) dev_info(&pdev->dev, DRVMSG ": starting\n"); + bt_data = kzalloc(sizeof(*bt_data), GFP_KERNEL); + if (machine_is_neo1973_gta01()) { /* we make sure that the voltage is off */ pcf50606_onoff_set(pcf50606_global, @@ -231,7 +230,6 @@ static int __init gta01_bt_probe(struct platform_device *pdev) if (IS_ERR(regulator)) return -ENODEV; - bt_data = kmalloc(sizeof(*bt_data), GFP_KERNEL); bt_data->regulator = regulator; dev_set_drvdata(&pdev->dev, bt_data); @@ -264,24 +262,23 @@ static int __init gta01_bt_probe(struct platform_device *pdev) return ret; } - platform_set_drvdata(pdev, rfkill); + bt_data->rfkill = rfkill; return sysfs_create_group(&pdev->dev.kobj, >a01_bt_attr_group); } static int gta01_bt_remove(struct platform_device *pdev) { - struct rfkill *rfkill = platform_get_drvdata(pdev); - - struct gta01_pm_bt_data *bt_data; + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); struct regulator *regulator; sysfs_remove_group(&pdev->dev.kobj, >a01_bt_attr_group); - rfkill_unregister(rfkill); - rfkill_free(rfkill); + if (bt_data->rfkill) { + rfkill_unregister(bt_data->rfkill); + rfkill_free(bt_data->rfkill); + } - bt_data = dev_get_drvdata(&pdev->dev); if (!bt_data || !bt_data->regulator) return 0; @@ -292,6 +289,8 @@ static int gta01_bt_remove(struct platform_device *pdev) regulator_disable(regulator); regulator_put(regulator); + + kfree(bt_data); return 0; } |