diff options
Diffstat (limited to 'drivers/video')
48 files changed, 6069 insertions, 473 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e4e1765b82f..80cbd21b483 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -364,7 +364,7 @@ config FB_SA1100 Y here. config FB_IMX - tristate "Freescale i.MX LCD support" + tristate "Freescale i.MX1/21/25/27 LCD support" depends on FB && IMX_HAVE_PLATFORM_IMX_FB select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -2025,7 +2025,8 @@ config FB_TMIO_ACCELL config FB_S3C tristate "Samsung S3C framebuffer support" - depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0) + depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \ + ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -2183,6 +2184,15 @@ config FB_XILINX framebuffer. ML300 carries a 640*480 LCD display on the board, ML403 uses a standard DB15 VGA connector. +config FB_GOLDFISH + tristate "Goldfish Framebuffer" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for Goldfish Virtual Platform + config FB_COBALT tristate "Cobalt server LCD frame buffer support" depends on FB && (MIPS_COBALT || MIPS_SEAD3) @@ -2422,6 +2432,7 @@ config FB_PUV3_UNIGFX source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" source "drivers/video/exynos/Kconfig" +source "drivers/video/mmp/Kconfig" source "drivers/video/backlight/Kconfig" if VT diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 768a137a1ba..0577f834fdc 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o +obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o obj-$(CONFIG_FB_68328) += 68328fb.o obj-$(CONFIG_FB_GBE) += gbefb.o obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o @@ -105,6 +106,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o obj-$(CONFIG_FB_PXA168) += pxa168fb.o obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o +obj-$(CONFIG_MMP_DISP) += mmp/ obj-$(CONFIG_FB_W100) += w100fb.o obj-$(CONFIG_FB_TMIO) += tmiofb.o obj-$(CONFIG_FB_AU1100) += au1100fb.o diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index c072ed9aea3..2cd63507ed7 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -165,8 +165,10 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, struct pm860x_backlight_data *data, char *name) { - struct device_node *nproot = pdev->dev.parent->of_node, *np; + struct device_node *nproot, *np; int iset = 0; + + nproot = of_node_get(pdev->dev.parent->of_node); if (!nproot) return -ENODEV; nproot = of_find_node_by_name(nproot, "backlights"); @@ -184,6 +186,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, break; } } + of_node_put(nproot); return 0; } #else diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 765a945f8ea..be27b551473 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -126,6 +126,21 @@ config LCD_AMS369FG06 If you have an AMS369FG06 AMOLED Panel, say Y to enable its LCD control driver. +config LCD_LMS501KF03 + tristate "LMS501KF03 LCD Driver" + depends on SPI + default n + help + If you have an LMS501KF03 LCD Panel, say Y to enable its + LCD control driver. + +config LCD_HX8357 + tristate "Himax HX-8357 LCD Driver" + depends on SPI + help + If you have a HX-8357 LCD panel, say Y to enable its LCD control + driver. + endif # LCD_CLASS_DEVICE # @@ -366,7 +381,7 @@ config BACKLIGHT_LP855X tristate "Backlight driver for TI LP855X" depends on BACKLIGHT_CLASS_DEVICE && I2C help - This supports TI LP8550, LP8551, LP8552, LP8553 and LP8556 + This supports TI LP8550, LP8551, LP8552, LP8553, LP8556 and LP8557 backlight driver. config BACKLIGHT_OT200 @@ -390,6 +405,13 @@ config BACKLIGHT_TPS65217 If you have a Texas Instruments TPS65217 say Y to enable the backlight driver. +config BACKLIGHT_AS3711 + tristate "AS3711 Backlight" + depends on BACKLIGHT_CLASS_DEVICE && MFD_AS3711 + help + If you have an Austrian Microsystems AS3711 say Y to enable the + backlight driver. + endif # BACKLIGHT_CLASS_DEVICE endif # BACKLIGHT_LCD_SUPPORT diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index e7ce7291635..4606c218e8e 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -1,47 +1,50 @@ # Backlight & LCD drivers -obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o -obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o -obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o -obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o -obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o -obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o -obj-$(CONFIG_LCD_ILI9320) += ili9320.o -obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o -obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o -obj-$(CONFIG_LCD_TDO24M) += tdo24m.o -obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o -obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o -obj-$(CONFIG_LCD_LD9040) += ld9040.o -obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o +obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o +obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o +obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o +obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o +obj-$(CONFIG_LCD_HX8357) += hx8357.o +obj-$(CONFIG_LCD_ILI9320) += ili9320.o +obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o +obj-$(CONFIG_LCD_LD9040) += ld9040.o +obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o +obj-$(CONFIG_LCD_LMS501KF03) += lms501kf03.o +obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o +obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o +obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o +obj-$(CONFIG_LCD_TDO24M) += tdo24m.o +obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o +obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o -obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o -obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o -obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o -obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o -obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o -obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o -obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o -obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o -obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o -obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o -obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o -obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o -obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o -obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o -obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o -obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o -obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o -obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o -obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o -obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o -obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o -obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o -obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o -obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o -obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o -obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o +obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o +obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o +obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o +obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o +obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o +obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o +obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o +obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o +obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o +obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o +obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o +obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o +obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o +obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o +obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o +obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o +obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o +obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o +obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o +obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o +obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o +obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o +obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o +obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o +obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o -obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o -obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o -obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o +obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o +obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o +obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o +obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o +obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c index 7ff752288b9..c6fc668d623 100644 --- a/drivers/video/backlight/aat2870_bl.c +++ b/drivers/video/backlight/aat2870_bl.c @@ -74,7 +74,7 @@ static int aat2870_bl_get_brightness(struct backlight_device *bd) static int aat2870_bl_update_status(struct backlight_device *bd) { - struct aat2870_bl_driver_data *aat2870_bl = dev_get_drvdata(&bd->dev); + struct aat2870_bl_driver_data *aat2870_bl = bl_get_data(bd); struct aat2870_data *aat2870 = dev_get_drvdata(aat2870_bl->pdev->dev.parent); int brightness = bd->props.brightness; diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 6bb72c0cb80..a77c9cad332 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -783,7 +783,7 @@ static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) static int adp8860_i2c_resume(struct i2c_client *client) { - adp8860_set_bits(client, ADP8860_MDCR, NSTBY); + adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN); return 0; } diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 63c882b8177..712c25a0d8f 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -957,7 +957,7 @@ static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) static int adp8870_i2c_resume(struct i2c_client *client) { - adp8870_set_bits(client, ADP8870_MDCR, NSTBY); + adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); return 0; } diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index f57e1905236..d29e49443f2 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c @@ -10,25 +10,16 @@ * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * 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., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <linux/wait.h> -#include <linux/module.h> -#include <linux/fb.h> +#include <linux/backlight.h> #include <linux/delay.h> +#include <linux/fb.h> #include <linux/gpio.h> -#include <linux/spi/spi.h> #include <linux/lcd.h> -#include <linux/backlight.h> +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/wait.h> #define SLEEPMSEC 0x1000 #define ENDDEF 0x2000 @@ -210,8 +201,9 @@ static int ams369fg06_panel_send_sequence(struct ams369fg06 *lcd, ret = ams369fg06_spi_write(lcd, wbuf[i], wbuf[i+1]); if (ret) break; - } else - mdelay(wbuf[i+1]); + } else { + msleep(wbuf[i+1]); + } i += 2; } @@ -313,41 +305,32 @@ static int ams369fg06_ldi_disable(struct ams369fg06 *lcd) static int ams369fg06_power_is_on(int power) { - return ((power) <= FB_BLANK_NORMAL); + return power <= FB_BLANK_NORMAL; } static int ams369fg06_power_on(struct ams369fg06 *lcd) { int ret = 0; - struct lcd_platform_data *pd = NULL; - struct backlight_device *bd = NULL; + struct lcd_platform_data *pd; + struct backlight_device *bd; pd = lcd->lcd_pd; - if (!pd) { - dev_err(lcd->dev, "platform data is NULL.\n"); - return -EFAULT; - } - bd = lcd->bd; - if (!bd) { - dev_err(lcd->dev, "backlight device is NULL.\n"); - return -EFAULT; - } if (!pd->power_on) { dev_err(lcd->dev, "power_on is NULL.\n"); - return -EFAULT; + return -EINVAL; } else { pd->power_on(lcd->ld, 1); - mdelay(pd->power_on_delay); + msleep(pd->power_on_delay); } if (!pd->reset) { dev_err(lcd->dev, "reset is NULL.\n"); - return -EFAULT; + return -EINVAL; } else { pd->reset(lcd->ld); - mdelay(pd->reset_delay); + msleep(pd->reset_delay); } ret = ams369fg06_ldi_init(lcd); @@ -374,14 +357,10 @@ static int ams369fg06_power_on(struct ams369fg06 *lcd) static int ams369fg06_power_off(struct ams369fg06 *lcd) { - int ret = 0; - struct lcd_platform_data *pd = NULL; + int ret; + struct lcd_platform_data *pd; pd = lcd->lcd_pd; - if (!pd) { - dev_err(lcd->dev, "platform data is NULL\n"); - return -EFAULT; - } ret = ams369fg06_ldi_disable(lcd); if (ret) { @@ -389,13 +368,9 @@ static int ams369fg06_power_off(struct ams369fg06 *lcd) return -EIO; } - mdelay(pd->power_off_delay); + msleep(pd->power_off_delay); - if (!pd->power_on) { - dev_err(lcd->dev, "power_on is NULL.\n"); - return -EFAULT; - } else - pd->power_on(lcd->ld, 0); + pd->power_on(lcd->ld, 0); return 0; } @@ -446,7 +421,7 @@ static int ams369fg06_set_brightness(struct backlight_device *bd) { int ret = 0; int brightness = bd->props.brightness; - struct ams369fg06 *lcd = dev_get_drvdata(&bd->dev); + struct ams369fg06 *lcd = bl_get_data(bd); if (brightness < MIN_BRIGHTNESS || brightness > bd->props.max_brightness) { @@ -501,7 +476,7 @@ static int ams369fg06_probe(struct spi_device *spi) lcd->lcd_pd = spi->dev.platform_data; if (!lcd->lcd_pd) { dev_err(&spi->dev, "platform data is NULL\n"); - return -EFAULT; + return -EINVAL; } ld = lcd_device_register("ams369fg06", &spi->dev, lcd, @@ -534,10 +509,11 @@ static int ams369fg06_probe(struct spi_device *spi) lcd->power = FB_BLANK_POWERDOWN; ams369fg06_power(lcd, FB_BLANK_UNBLANK); - } else + } else { lcd->power = FB_BLANK_UNBLANK; + } - dev_set_drvdata(&spi->dev, lcd); + spi_set_drvdata(spi, lcd); dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n"); @@ -550,7 +526,7 @@ out_lcd_unregister: static int ams369fg06_remove(struct spi_device *spi) { - struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); + struct ams369fg06 *lcd = spi_get_drvdata(spi); ams369fg06_power(lcd, FB_BLANK_POWERDOWN); backlight_device_unregister(lcd->bd); @@ -560,44 +536,26 @@ static int ams369fg06_remove(struct spi_device *spi) } #if defined(CONFIG_PM) -static unsigned int before_power; - static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) { - int ret = 0; - struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); + struct ams369fg06 *lcd = spi_get_drvdata(spi); dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); - before_power = lcd->power; - /* * when lcd panel is suspend, lcd panel becomes off * regardless of status. */ - ret = ams369fg06_power(lcd, FB_BLANK_POWERDOWN); - - return ret; + return ams369fg06_power(lcd, FB_BLANK_POWERDOWN); } static int ams369fg06_resume(struct spi_device *spi) { - int ret = 0; - struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); + struct ams369fg06 *lcd = spi_get_drvdata(spi); - /* - * after suspended, if lcd panel status is FB_BLANK_UNBLANK - * (at that time, before_power is FB_BLANK_UNBLANK) then - * it changes that status to FB_BLANK_POWERDOWN to get lcd on. - */ - if (before_power == FB_BLANK_UNBLANK) - lcd->power = FB_BLANK_POWERDOWN; - - dev_dbg(&spi->dev, "before_power = %d\n", before_power); + lcd->power = FB_BLANK_POWERDOWN; - ret = ams369fg06_power(lcd, before_power); - - return ret; + return ams369fg06_power(lcd, FB_BLANK_UNBLANK); } #else #define ams369fg06_suspend NULL @@ -606,7 +564,7 @@ static int ams369fg06_resume(struct spi_device *spi) static void ams369fg06_shutdown(struct spi_device *spi) { - struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); + struct ams369fg06 *lcd = spi_get_drvdata(spi); ams369fg06_power(lcd, FB_BLANK_POWERDOWN); } diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c new file mode 100644 index 00000000000..41d52fe5254 --- /dev/null +++ b/drivers/video/backlight/as3711_bl.c @@ -0,0 +1,380 @@ +/* + * AS3711 PMIC backlight driver, using DCDC Step Up Converters + * + * Copyright (C) 2012 Renesas Electronics Corporation + * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License as + * published by the Free Software Foundation + */ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/fb.h> +#include <linux/kernel.h> +#include <linux/mfd/as3711.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +enum as3711_bl_type { + AS3711_BL_SU1, + AS3711_BL_SU2, +}; + +struct as3711_bl_data { + bool powered; + const char *fb_name; + struct device *fb_dev; + enum as3711_bl_type type; + int brightness; + struct backlight_device *bl; +}; + +struct as3711_bl_supply { + struct as3711_bl_data su1; + struct as3711_bl_data su2; + const struct as3711_bl_pdata *pdata; + struct as3711 *as3711; +}; + +static struct as3711_bl_supply *to_supply(struct as3711_bl_data *su) +{ + switch (su->type) { + case AS3711_BL_SU1: + return container_of(su, struct as3711_bl_supply, su1); + case AS3711_BL_SU2: + return container_of(su, struct as3711_bl_supply, su2); + } + return NULL; +} + +static int as3711_set_brightness_auto_i(struct as3711_bl_data *data, + unsigned int brightness) +{ + struct as3711_bl_supply *supply = to_supply(data); + struct as3711 *as3711 = supply->as3711; + const struct as3711_bl_pdata *pdata = supply->pdata; + int ret = 0; + + /* Only all equal current values are supported */ + if (pdata->su2_auto_curr1) + ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE, + brightness); + if (!ret && pdata->su2_auto_curr2) + ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE, + brightness); + if (!ret && pdata->su2_auto_curr3) + ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE, + brightness); + + return ret; +} + +static int as3711_set_brightness_v(struct as3711 *as3711, + unsigned int brightness, + unsigned int reg) +{ + if (brightness > 31) + return -EINVAL; + + return regmap_update_bits(as3711->regmap, reg, 0xf0, + brightness << 4); +} + +static int as3711_bl_su2_reset(struct as3711_bl_supply *supply) +{ + struct as3711 *as3711 = supply->as3711; + int ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_5, + 3, supply->pdata->su2_fbprot); + if (!ret) + ret = regmap_update_bits(as3711->regmap, + AS3711_STEPUP_CONTROL_2, 1, 0); + if (!ret) + ret = regmap_update_bits(as3711->regmap, + AS3711_STEPUP_CONTROL_2, 1, 1); + return ret; +} + +/* + * Someone with less fragile or less expensive hardware could try to simplify + * the brightness adjustment procedure. + */ +static int as3711_bl_update_status(struct backlight_device *bl) +{ + struct as3711_bl_data *data = bl_get_data(bl); + struct as3711_bl_supply *supply = to_supply(data); + struct as3711 *as3711 = supply->as3711; + int brightness = bl->props.brightness; + int ret = 0; + + dev_dbg(&bl->dev, "%s(): brightness %u, pwr %x, blank %x, state %x\n", + __func__, bl->props.brightness, bl->props.power, + bl->props.fb_blank, bl->props.state); + + if (bl->props.power != FB_BLANK_UNBLANK || + bl->props.fb_blank != FB_BLANK_UNBLANK || + bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) + brightness = 0; + + if (data->type == AS3711_BL_SU1) { + ret = as3711_set_brightness_v(as3711, brightness, + AS3711_STEPUP_CONTROL_1); + } else { + const struct as3711_bl_pdata *pdata = supply->pdata; + + switch (pdata->su2_feedback) { + case AS3711_SU2_VOLTAGE: + ret = as3711_set_brightness_v(as3711, brightness, + AS3711_STEPUP_CONTROL_2); + break; + case AS3711_SU2_CURR_AUTO: + ret = as3711_set_brightness_auto_i(data, brightness / 4); + if (ret < 0) + return ret; + if (brightness) { + ret = as3711_bl_su2_reset(supply); + if (ret < 0) + return ret; + udelay(500); + ret = as3711_set_brightness_auto_i(data, brightness); + } else { + ret = regmap_update_bits(as3711->regmap, + AS3711_STEPUP_CONTROL_2, 1, 0); + } + break; + /* Manual one current feedback pin below */ + case AS3711_SU2_CURR1: + ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE, + brightness); + break; + case AS3711_SU2_CURR2: + ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE, + brightness); + break; + case AS3711_SU2_CURR3: + ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE, + brightness); + break; + default: + ret = -EINVAL; + } + } + if (!ret) + data->brightness = brightness; + + return ret; +} + +static int as3711_bl_get_brightness(struct backlight_device *bl) +{ + struct as3711_bl_data *data = bl_get_data(bl); + + return data->brightness; +} + +static const struct backlight_ops as3711_bl_ops = { + .update_status = as3711_bl_update_status, + .get_brightness = as3711_bl_get_brightness, +}; + +static int as3711_bl_init_su2(struct as3711_bl_supply *supply) +{ + struct as3711 *as3711 = supply->as3711; + const struct as3711_bl_pdata *pdata = supply->pdata; + u8 ctl = 0; + int ret; + + dev_dbg(as3711->dev, "%s(): use %u\n", __func__, pdata->su2_feedback); |