From 9764dbf8d7c32d95c198d587d59b8ed30e2c2c15 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 24 Oct 2009 18:48:17 +0200 Subject: MFD: pcf50633: Fix bitfield logic in interrupt handler As those constans are alread bitfields it's wrong Those constants are already bitfields. --- drivers/mfd/pcf50633-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 1d5e5212d81..45abed8784c 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -353,18 +353,18 @@ static void pcf50633_irq_worker(struct work_struct *work) if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) { chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); if (chgstat & (0x3 << 4)) - pcf_int[0] &= ~(1 << PCF50633_INT1_USBREM); + pcf_int[0] &= ~PCF50633_INT1_USBREM; else - pcf_int[0] &= ~(1 << PCF50633_INT1_USBINS); + pcf_int[0] &= ~PCF50633_INT1_USBINS; } /* Make sure only one of ADPINS or ADPREM is set */ if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) { chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); if (chgstat & (0x3 << 4)) - pcf_int[0] &= ~(1 << PCF50633_INT1_ADPREM); + pcf_int[0] &= ~PCF50633_INT1_ADPREM; else - pcf_int[0] &= ~(1 << PCF50633_INT1_ADPINS); + pcf_int[0] &= ~PCF50633_INT1_ADPINS; } dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x " -- cgit v1.2.3 From 9bc6c2e96286f0b27d73ec0c56eb12a0c214f648 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 2 Nov 2009 19:54:35 +0100 Subject: backlight/mfd: Add pcf50633 backlight driver This patch adds a backlight driver controling the pcf50633 led converter. Signed-off-by: Lars-Peter Clausen --- drivers/mfd/pcf50633-core.c | 3 + drivers/video/backlight/Kconfig | 7 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/pcf50633-backlight.c | 185 +++++++++++++++++++++++++++ include/linux/mfd/pcf50633/backlight.h | 44 +++++++ include/linux/mfd/pcf50633/core.h | 4 + 6 files changed, 244 insertions(+) create mode 100644 drivers/video/backlight/pcf50633-backlight.c create mode 100644 include/linux/mfd/pcf50633/backlight.h diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 45abed8784c..41ac3a52df1 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -619,6 +619,9 @@ static int __devinit pcf50633_probe(struct i2c_client *client, &pcf->mbc_pdev); pcf50633_client_dev_register(pcf, "pcf50633-adc", &pcf->adc_pdev); + pcf50633_client_dev_register(pcf, "pcf50633-backlight", + &pcf->bl_pdev); + for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { struct platform_device *pdev; diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index f9d19be0554..e7d7a306b5f 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -229,3 +229,10 @@ config BACKLIGHT_SAHARA help If you have a Tabletkiosk Sahara Touch-iT, say y to enable the backlight driver. + +config BACKLIGHT_PCF50633 + tristate "Backlight driver for NXP PCF50533 MFD" + depends on MFD_PCF50633 + help + If you have a backlight driven by a NXP PCF50633 MFD, say Y here to + enable its driver. diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 4eb178c1d68..57da456698e 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -24,4 +24,5 @@ obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o +obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c new file mode 100644 index 00000000000..10b9c31bc43 --- /dev/null +++ b/drivers/video/backlight/pcf50633-backlight.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * PCF50633 backlight device driver + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +struct pcf50633_bl { + struct pcf50633 *pcf; + struct backlight_device *bl; + + unsigned int brightness; + unsigned int brightness_limit; +}; + +/* + * pcf50633_bl_set_brightness_limit + * + * Update the brightness limit for the pc50633 backlight. The actuall brightness + * will not go above the limit. This is useful to limit power drain for example + * on low battery. + * + * @dev: Pointer to a pcf50633 device + * @limit: The brightness limit. Valid values are 0-63 + */ +int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit) +{ + struct pcf50633_bl *pcf_bl = platform_get_drvdata(pcf->bl_pdev); + + if (!pcf_bl) + return -ENODEV; + + pcf_bl->brightness_limit = limit & 0x3f; + backlight_update_status(pcf_bl->bl); + + return 0; +} + +static int pcf50633_bl_update_status(struct backlight_device *bl) +{ + struct pcf50633_bl *pcf_bl = bl_get_data(bl); + unsigned int new_brightness; + + + if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK) || + bl->props.power != FB_BLANK_UNBLANK) + new_brightness = 0; + else if (bl->props.brightness < pcf_bl->brightness_limit) + new_brightness = bl->props.brightness; + else + new_brightness = pcf_bl->brightness_limit; + + + if (pcf_bl->brightness == new_brightness) + return 0; + + if (new_brightness) { + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDOUT, + new_brightness); + if (!pcf_bl->brightness) + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 1); + } else { + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 0); + } + + pcf_bl->brightness = new_brightness; + + return 0; +} + +static int pcf50633_bl_get_brightness(struct backlight_device *bl) +{ + struct pcf50633_bl *pcf_bl = bl_get_data(bl); + return pcf_bl->brightness; +} + +static struct backlight_ops pcf50633_bl_ops = { + .get_brightness = pcf50633_bl_get_brightness, + .update_status = pcf50633_bl_update_status, + .options = BL_CORE_SUSPENDRESUME, +}; + +static int __devinit pcf50633_bl_probe(struct platform_device *pdev) +{ + int ret; + struct pcf50633_bl *pcf_bl; + struct pcf50633_platform_data *pcf50633_data = pdev->dev.parent->platform_data; + struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data; + + pcf_bl = kzalloc(sizeof(*pcf_bl), GFP_KERNEL); + if (!pcf_bl) + return -ENOMEM; + + pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent); + + pcf_bl->bl = backlight_device_register(pdev->name, &pdev->dev, pcf_bl, + &pcf50633_bl_ops); + + if (IS_ERR(pcf_bl->bl)) { + ret = PTR_ERR(pcf_bl->bl); + goto err_free; + } + + platform_set_drvdata(pdev, pcf_bl); + + pcf_bl->bl->props.max_brightness = 0x3f; + pcf_bl->bl->props.power = FB_BLANK_UNBLANK; + + if (pdata) { + pcf_bl->bl->props.brightness = pdata->default_brightness; + pcf_bl->brightness_limit = pdata->default_brightness_limit; + } else { + pcf_bl->bl->props.brightness = 0x3f; + pcf_bl->brightness_limit = 0x3f; + } + + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time); + + /* Should be different from props.brightness, so we don't + * update_status early the first time it's called */ + pcf_bl->brightness = pcf_bl->bl->props.brightness + 1; + + backlight_update_status(pcf_bl->bl); + + return 0; + +err_free: + kfree(pcf_bl); + + return ret; +} + +static int __devexit pcf50633_bl_remove(struct platform_device *pdev) +{ + struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev); + + backlight_device_unregister(pcf_bl->bl); + + platform_set_drvdata(pdev, NULL); + + kfree(pcf_bl); + + return 0; +} + +static struct platform_driver pcf50633_bl_driver = { + .probe = pcf50633_bl_probe, + .remove = __devexit_p(pcf50633_bl_remove), + .driver = { + .name = "pcf50633-backlight", + }, +}; + +static int __init pcf50633_bl_init(void) +{ + return platform_driver_register(&pcf50633_bl_driver); +} +module_init(pcf50633_bl_init); + +static void __exit pcf50633_bl_exit(void) +{ + platform_driver_unregister(&pcf50633_bl_driver); +} +module_exit(pcf50633_bl_exit); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("PCF50633 backlight driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pcf50633-backlight"); diff --git a/include/linux/mfd/pcf50633/backlight.h b/include/linux/mfd/pcf50633/backlight.h new file mode 100644 index 00000000000..9d3646af056 --- /dev/null +++ b/include/linux/mfd/pcf50633/backlight.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2009, Lars-Peter Clausen + * PCF50633 backlight device driver + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __LINUX_MFD_PCF50633_BACKLIGHT +#define __LINUX_MFD_PCF50633_BACKLIGHT + +/* +* @default_brightness: Brightness to be used after the driver has been + probed. Valid range 0-63. +* @default_brightness_limit: Brightness limit to be used after the driver has +* been probed. This is usfull when it is not known +* how much power is available for the backlight +* during probe. Valid range 0-63 +* @ramp_time: When changing the backlights brightness the change +* is not instant, instead it fades smooth from one +* state to another. This value specifies how long the +* fade should take. The lower the value the higher +* the fade time. Valid range 0-255 +*/ +struct pcf50633_bl_platform_data { + unsigned int default_brightness; + unsigned int default_brightness_limit; + uint8_t ramp_time; +}; + + +struct pcf50633; + +int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit); + +#endif + diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h index e304238dbc5..42f9af553ed 100644 --- a/include/linux/mfd/pcf50633/core.h +++ b/include/linux/mfd/pcf50633/core.h @@ -18,6 +18,7 @@ #include #include #include +#include struct pcf50633; @@ -38,6 +39,8 @@ struct pcf50633_platform_data { void (*force_shutdown)(struct pcf50633 *); u8 resumers[5]; + + struct pcf50633_bl_platform_data *backlight_data; }; struct pcf50633_irq { @@ -147,6 +150,7 @@ struct pcf50633 { struct platform_device *mbc_pdev; struct platform_device *adc_pdev; struct platform_device *input_pdev; + struct platform_device *bl_pdev; struct platform_device *regulator_pdev[PCF50633_NUM_REGULATORS]; }; -- cgit v1.2.3 From c55979ddeeb5667d7e5c173f1cf4712fb5a0b7b5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 2 Nov 2009 21:49:23 +0100 Subject: gta02: Replace platform backlight driver with pcf50633-backlight. --- arch/arm/mach-s3c2442/mach-gta02.c | 81 +++++--------------------------------- 1 file changed, 10 insertions(+), 71 deletions(-) diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index 9c5a515d69b..8c610265ff3 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -50,7 +50,6 @@ #include #include -#include #include #include @@ -58,6 +57,7 @@ #include #include #include +#include #include #include @@ -468,6 +468,12 @@ static struct regulator_consumer_supply ldo6_consumers[] = { }; #endif +static struct pcf50633_bl_platform_data gta02_backlight_data = { + .default_brightness = 0x3f, + .default_brightness_limit = 0, + .ramp_time = 3, +}; + struct pcf50633_platform_data gta02_pcf_pdata = { .resumers = { [0] = PCF50633_INT1_USBINS | @@ -485,6 +491,8 @@ struct pcf50633_platform_data gta02_pcf_pdata = { .chg_ref_current_ma = 1000, + .backlight_data = >a02_backlight_data, + .reg_init_data = { [PCF50633_REGULATOR_AUTO] = { .constraints = { @@ -746,67 +754,6 @@ const static struct s3c2410_ts_mach_info gta02_ts_cfg = { }; -static void gta02_bl_set_intensity(int intensity) -{ - struct pcf50633 *pcf = gta02_pcf; - int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT); - - /* We map 8-bit intensity to 6-bit intensity in hardware. */ - intensity >>= 2; - - /* - * This can happen during, eg, print of panic on blanked console, - * but we can't service i2c without interrupts active, so abort. - */ - if (in_atomic()) { - printk(KERN_ERR "gta02_bl_set_intensity called while atomic\n"); - return; - } - - old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT); - if (intensity == old_intensity) - return; - - /* We can't do this anywhere else. */ - pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5); - - if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3)) - old_intensity = 0; - - /* - * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60) - * if seen, you have to re-enable the LED unit. - */ - if (!intensity || !old_intensity) - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0); - - /* Illegal to set LEDOUT to 0. */ - if (!intensity) - pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 2); - else - pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, - intensity); - - if (intensity) - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2); - -} - -static struct generic_bl_info gta02_bl_info = { - .name = "gta02-bl", - .max_intensity = 0xff, - .default_intensity = 0xff, - .set_bl_intensity = gta02_bl_set_intensity, -}; - -static struct platform_device gta02_bl_dev = { - .name = "generic-bl", - .id = 1, - .dev = { - .platform_data = >a02_bl_info, - }, -}; - /* USB */ static struct s3c2410_hcd_info gta02_usb_info = { .port[0] = { @@ -880,15 +827,7 @@ static struct platform_device gta02_leds_device = { /* JBT6k74 display controller */ static void gta02_jbt6k74_probe_completed(struct device *dev) { - struct pcf50633 *pcf = gta02_pcf; - /* Switch on backlight. Qi does not do it for us */ - pcf50633_reg_write(pcf, PCF50633_REG_LEDOUT, 0x01); - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x00); - pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 0x01); - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x01); - - gta02_bl_dev.dev.parent = dev; - platform_device_register(>a02_bl_dev); + pcf50633_bl_set_brightness_limit(gta02_pcf, 0x3f); } const struct jbt6k74_platform_data jbt6k74_pdata = { -- cgit v1.2.3