diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 19:05:59 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 19:05:59 -0400 |
| commit | 900bca34940ca1db8dd04a2e9b240ffac32da6f6 (patch) | |
| tree | 9f23e69f1ee3500dd51b2a26a741943b38b81ed1 | |
| parent | 2fca5ccf97d2c28bcfce44f5b07d85e74e3cd18e (diff) | |
| parent | d03ebb12981e80de99e9b482639ec3b5795741f3 (diff) | |
Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-backlight
* 'for-linus' of git://git.o-hand.com/linux-rpurdie-backlight:
backlight: Add driver for Tabletkiosk Sahara TouchIT-213 Tablet PC
backlight: da903x: Add backlight driver for DA9030/DA9034
tosa: add support for bl/lcd driver
backlight: add support for Sharp SL-6000 LCD and backlight drivers
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/tosa.h | 3 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/tosa.c | 21 | ||||
| -rw-r--r-- | drivers/video/backlight/Kconfig | 32 | ||||
| -rw-r--r-- | drivers/video/backlight/Makefile | 4 | ||||
| -rw-r--r-- | drivers/video/backlight/da903x.c | 201 | ||||
| -rw-r--r-- | drivers/video/backlight/kb3886_bl.c | 204 | ||||
| -rw-r--r-- | drivers/video/backlight/tosa_bl.c | 198 | ||||
| -rw-r--r-- | drivers/video/backlight/tosa_lcd.c | 280 |
8 files changed, 942 insertions, 1 deletions
diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h index 8bce6d8615b9..4df2d38507dc 100644 --- a/arch/arm/mach-pxa/include/mach/tosa.h +++ b/arch/arm/mach-pxa/include/mach/tosa.h | |||
| @@ -193,4 +193,7 @@ | |||
| 193 | #define TOSA_KEY_MAIL KEY_MAIL | 193 | #define TOSA_KEY_MAIL KEY_MAIL |
| 194 | #endif | 194 | #endif |
| 195 | 195 | ||
| 196 | struct spi_device; | ||
| 197 | extern int tosa_bl_enable(struct spi_device *spi, int enable); | ||
| 198 | |||
| 196 | #endif /* _ASM_ARCH_TOSA_H_ */ | 199 | #endif /* _ASM_ARCH_TOSA_H_ */ |
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index a6c4694359ca..224897a67d15 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
| 32 | #include <linux/pda_power.h> | 32 | #include <linux/pda_power.h> |
| 33 | #include <linux/rfkill.h> | 33 | #include <linux/rfkill.h> |
| 34 | #include <linux/spi/spi.h> | ||
| 34 | 35 | ||
| 35 | #include <asm/setup.h> | 36 | #include <asm/setup.h> |
| 36 | #include <asm/mach-types.h> | 37 | #include <asm/mach-types.h> |
| @@ -42,6 +43,7 @@ | |||
| 42 | #include <mach/mmc.h> | 43 | #include <mach/mmc.h> |
| 43 | #include <mach/udc.h> | 44 | #include <mach/udc.h> |
| 44 | #include <mach/tosa_bt.h> | 45 | #include <mach/tosa_bt.h> |
| 46 | #include <mach/pxa2xx_spi.h> | ||
| 45 | 47 | ||
| 46 | #include <asm/mach/arch.h> | 48 | #include <asm/mach/arch.h> |
| 47 | #include <mach/tosa.h> | 49 | #include <mach/tosa.h> |
| @@ -612,7 +614,7 @@ static int tosa_tc6393xb_enable(struct platform_device *dev) | |||
| 612 | rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend"); | 614 | rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend"); |
| 613 | if (rc) | 615 | if (rc) |
| 614 | goto err_req_suspend; | 616 | goto err_req_suspend; |
| 615 | rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v"); | 617 | rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "tc6393xb l3v"); |
| 616 | if (rc) | 618 | if (rc) |
| 617 | goto err_req_l3v; | 619 | goto err_req_l3v; |
| 618 | rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0); | 620 | rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0); |
| @@ -772,6 +774,20 @@ static struct platform_device tosa_bt_device = { | |||
| 772 | .dev.platform_data = &tosa_bt_data, | 774 | .dev.platform_data = &tosa_bt_data, |
| 773 | }; | 775 | }; |
| 774 | 776 | ||
| 777 | static struct pxa2xx_spi_master pxa_ssp_master_info = { | ||
| 778 | .num_chipselect = 1, | ||
| 779 | }; | ||
| 780 | |||
| 781 | static struct spi_board_info spi_board_info[] __initdata = { | ||
| 782 | { | ||
| 783 | .modalias = "tosa-lcd", | ||
| 784 | // .platform_data | ||
| 785 | .max_speed_hz = 28750, | ||
| 786 | .bus_num = 2, | ||
| 787 | .chip_select = 0, | ||
| 788 | .mode = SPI_MODE_0, | ||
| 789 | }, | ||
| 790 | }; | ||
| 775 | 791 | ||
| 776 | static struct platform_device *devices[] __initdata = { | 792 | static struct platform_device *devices[] __initdata = { |
| 777 | &tosascoop_device, | 793 | &tosascoop_device, |
| @@ -826,6 +842,9 @@ static void __init tosa_init(void) | |||
| 826 | pxa_set_i2c_info(NULL); | 842 | pxa_set_i2c_info(NULL); |
| 827 | platform_scoop_config = &tosa_pcmcia_config; | 843 | platform_scoop_config = &tosa_pcmcia_config; |
| 828 | 844 | ||
| 845 | pxa2xx_set_spi_info(2, &pxa_ssp_master_info); | ||
| 846 | spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); | ||
| 847 | |||
| 829 | clk_add_alias("CLK_CK3P6MI", &tc6393xb_device.dev, "GPIO11_CLK", NULL); | 848 | clk_add_alias("CLK_CK3P6MI", &tc6393xb_device.dev, "GPIO11_CLK", NULL); |
| 830 | 849 | ||
| 831 | platform_add_devices(devices, ARRAY_SIZE(devices)); | 850 | platform_add_devices(devices, ARRAY_SIZE(devices)); |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index c72a13562954..51c94a5971b4 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
| @@ -75,6 +75,15 @@ config LCD_PLATFORM | |||
| 75 | This driver provides a platform-device registered LCD power | 75 | This driver provides a platform-device registered LCD power |
| 76 | control interface. | 76 | control interface. |
| 77 | 77 | ||
| 78 | config LCD_TOSA | ||
| 79 | tristate "Sharp SL-6000 LCD Driver" | ||
| 80 | depends on LCD_CLASS_DEVICE && SPI | ||
| 81 | depends on MACH_TOSA | ||
| 82 | default n | ||
| 83 | help | ||
| 84 | If you have an Sharp SL-6000 Zaurus say Y to enable a driver | ||
| 85 | for its LCD. | ||
| 86 | |||
| 78 | # | 87 | # |
| 79 | # Backlight | 88 | # Backlight |
| 80 | # | 89 | # |
| @@ -171,6 +180,13 @@ config BACKLIGHT_PWM | |||
| 171 | If you have a LCD backlight adjustable by PWM, say Y to enable | 180 | If you have a LCD backlight adjustable by PWM, say Y to enable |
| 172 | this driver. | 181 | this driver. |
| 173 | 182 | ||
| 183 | config BACKLIGHT_DA903X | ||
| 184 | tristate "Backlight Driver for DA9030/DA9034 using WLED" | ||
| 185 | depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X | ||
| 186 | help | ||
| 187 | If you have a LCD backlight connected to the WLED output of DA9030 | ||
| 188 | or DA9034 WLED output, say Y here to enable this driver. | ||
| 189 | |||
| 174 | config BACKLIGHT_MBP_NVIDIA | 190 | config BACKLIGHT_MBP_NVIDIA |
| 175 | tristate "MacBook Pro Nvidia Backlight Driver" | 191 | tristate "MacBook Pro Nvidia Backlight Driver" |
| 176 | depends on BACKLIGHT_CLASS_DEVICE && X86 | 192 | depends on BACKLIGHT_CLASS_DEVICE && X86 |
| @@ -179,3 +195,19 @@ config BACKLIGHT_MBP_NVIDIA | |||
| 179 | If you have an Apple Macbook Pro with Nvidia graphics hardware say Y | 195 | If you have an Apple Macbook Pro with Nvidia graphics hardware say Y |
| 180 | to enable a driver for its backlight | 196 | to enable a driver for its backlight |
| 181 | 197 | ||
| 198 | config BACKLIGHT_TOSA | ||
| 199 | tristate "Sharp SL-6000 Backlight Driver" | ||
| 200 | depends on BACKLIGHT_CLASS_DEVICE && I2C | ||
| 201 | depends on MACH_TOSA && LCD_TOSA | ||
| 202 | default n | ||
| 203 | help | ||
| 204 | If you have an Sharp SL-6000 Zaurus say Y to enable a driver | ||
| 205 | for its backlight | ||
| 206 | |||
| 207 | config BACKLIGHT_SAHARA | ||
| 208 | tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" | ||
| 209 | depends on BACKLIGHT_CLASS_DEVICE && X86 | ||
| 210 | default n | ||
| 211 | help | ||
| 212 | If you have a Tabletkiosk Sahara Touch-iT, say y to enable the | ||
| 213 | backlight driver. | ||
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 3ec551eb472c..103427de6703 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
| @@ -7,6 +7,7 @@ obj-$(CONFIG_LCD_ILI9320) += ili9320.o | |||
| 7 | obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o | 7 | obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o |
| 8 | obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o | 8 | obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o |
| 9 | obj-$(CONFIG_LCD_TDO24M) += tdo24m.o | 9 | obj-$(CONFIG_LCD_TDO24M) += tdo24m.o |
| 10 | obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o | ||
| 10 | 11 | ||
| 11 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o | 12 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o |
| 12 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o | 13 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o |
| @@ -17,5 +18,8 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o | |||
| 17 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o | 18 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o |
| 18 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o | 19 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o |
| 19 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o | 20 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o |
| 21 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x.o | ||
| 20 | obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o | 22 | obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o |
| 23 | obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o | ||
| 24 | obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o | ||
| 21 | 25 | ||
diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c new file mode 100644 index 000000000000..242c38250166 --- /dev/null +++ b/drivers/video/backlight/da903x.c | |||
| @@ -0,0 +1,201 @@ | |||
| 1 | /* | ||
| 2 | * Backlight driver for Dialog Semiconductor DA9030/DA9034 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Compulab, Ltd. | ||
| 5 | * Mike Rapoport <mike@compulab.co.il> | ||
| 6 | * | ||
| 7 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
| 8 | * Eric Miao <eric.miao@marvell.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/fb.h> | ||
| 19 | #include <linux/backlight.h> | ||
| 20 | #include <linux/mfd/da903x.h> | ||
| 21 | |||
| 22 | #define DA9030_WLED_CONTROL 0x25 | ||
| 23 | #define DA9030_WLED_CP_EN (1 << 6) | ||
| 24 | #define DA9030_WLED_TRIM(x) ((x) & 0x7) | ||
| 25 | |||
| 26 | #define DA9034_WLED_CONTROL1 0x3C | ||
| 27 | #define DA9034_WLED_CONTROL2 0x3D | ||
| 28 | |||
| 29 | #define DA9034_WLED_BOOST_EN (1 << 5) | ||
| 30 | |||
| 31 | #define DA9030_MAX_BRIGHTNESS 7 | ||
| 32 | #define DA9034_MAX_BRIGHTNESS 0x7f | ||
| 33 | |||
| 34 | struct da903x_backlight_data { | ||
| 35 | struct device *da903x_dev; | ||
| 36 | int id; | ||
| 37 | int current_brightness; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int da903x_backlight_set(struct backlight_device *bl, int brightness) | ||
| 41 | { | ||
| 42 | struct da903x_backlight_data *data = bl_get_data(bl); | ||
| 43 | struct device *dev = data->da903x_dev; | ||
| 44 | uint8_t val; | ||
| 45 | int ret = 0; | ||
| 46 | |||
| 47 | switch (data->id) { | ||
| 48 | case DA9034_ID_WLED: | ||
| 49 | ret = da903x_update(dev, DA9034_WLED_CONTROL1, | ||
| 50 | brightness, 0x7f); | ||
| 51 | if (ret) | ||
| 52 | return ret; | ||
| 53 | |||
| 54 | if (data->current_brightness && brightness == 0) | ||
| 55 | ret = da903x_clr_bits(dev, | ||
| 56 | DA9034_WLED_CONTROL2, | ||
| 57 | DA9034_WLED_BOOST_EN); | ||
| 58 | |||
| 59 | if (data->current_brightness == 0 && brightness) | ||
| 60 | ret = da903x_set_bits(dev, | ||
| 61 | DA9034_WLED_CONTROL2, | ||
| 62 | DA9034_WLED_BOOST_EN); | ||
| 63 | break; | ||
| 64 | case DA9030_ID_WLED: | ||
| 65 | val = DA9030_WLED_TRIM(brightness); | ||
| 66 | val |= brightness ? DA9030_WLED_CP_EN : 0; | ||
| 67 | ret = da903x_write(dev, DA9030_WLED_CONTROL, val); | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | |||
| 71 | if (ret) | ||
| 72 | return ret; | ||
| 73 | |||
| 74 | data->current_brightness = brightness; | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static int da903x_backlight_update_status(struct backlight_device *bl) | ||
| 79 | { | ||
| 80 | int brightness = bl->props.brightness; | ||
| 81 | |||
| 82 | if (bl->props.power != FB_BLANK_UNBLANK) | ||
| 83 | brightness = 0; | ||
| 84 | |||
| 85 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | ||
| 86 | brightness = 0; | ||
| 87 | |||
| 88 | return da903x_backlight_set(bl, brightness); | ||
| 89 | } | ||
| 90 | |||
| 91 | static int da903x_backlight_get_brightness(struct backlight_device *bl) | ||
| 92 | { | ||
| 93 | struct da903x_backlight_data *data = bl_get_data(bl); | ||
| 94 | return data->current_brightness; | ||
| 95 | } | ||
| 96 | |||
| 97 | static struct backlight_ops da903x_backlight_ops = { | ||
| 98 | .update_status = da903x_backlight_update_status, | ||
| 99 | .get_brightness = da903x_backlight_get_brightness, | ||
| 100 | }; | ||
| 101 | |||
| 102 | static int da903x_backlight_probe(struct platform_device *pdev) | ||
| 103 | { | ||
| 104 | struct da903x_backlight_data *data; | ||
| 105 | struct backlight_device *bl; | ||
| 106 | int max_brightness; | ||
| 107 | |||
| 108 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 109 | if (data == NULL) | ||
| 110 | return -ENOMEM; | ||
| 111 | |||
| 112 | switch (pdev->id) { | ||
| 113 | case DA9030_ID_WLED: | ||
| 114 | max_brightness = DA9030_MAX_BRIGHTNESS; | ||
| 115 | break; | ||
| 116 | case DA9034_ID_WLED: | ||
| 117 | max_brightness = DA9034_MAX_BRIGHTNESS; | ||
| 118 | break; | ||
| 119 | default: | ||
| 120 | dev_err(&pdev->dev, "invalid backlight device ID(%d)\n", | ||
| 121 | pdev->id); | ||
| 122 | return -EINVAL; | ||
| 123 | } | ||
| 124 | |||
| 125 | data->id = pdev->id; | ||
| 126 | data->da903x_dev = pdev->dev.parent; | ||
| 127 | data->current_brightness = 0; | ||
| 128 | |||
| 129 | bl = backlight_device_register(pdev->name, data->da903x_dev, | ||
| 130 | data, &da903x_backlight_ops); | ||
| 131 | if (IS_ERR(bl)) { | ||
| 132 | dev_err(&pdev->dev, "failed to register backlight\n"); | ||
| 133 | return PTR_ERR(bl); | ||
| 134 | } | ||
| 135 | |||
| 136 | bl->props.max_brightness = max_brightness; | ||
| 137 | bl->props.brightness = max_brightness; | ||
| 138 | |||
| 139 | platform_set_drvdata(pdev, bl); | ||
| 140 | backlight_update_status(bl); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int da903x_backlight_remove(struct platform_device *pdev) | ||
| 145 | { | ||
| 146 | struct backlight_device *bl = platform_get_drvdata(pdev); | ||
| 147 | struct da903x_backlight_data *data = bl_get_data(bl); | ||
| 148 | |||
| 149 | backlight_device_unregister(bl); | ||
| 150 | kfree(data); | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | #ifdef CONFIG_PM | ||
| 155 | static int da903x_backlight_suspend(struct platform_device *pdev, | ||
| 156 | pm_message_t state) | ||
| 157 | { | ||
| 158 | struct backlight_device *bl = platform_get_drvdata(pdev); | ||
| 159 | return da903x_backlight_set(bl, 0); | ||
| 160 | } | ||
| 161 | |||
| 162 | static int da903x_backlight_resume(struct platform_device *pdev) | ||
| 163 | { | ||
| 164 | struct backlight_device *bl = platform_get_drvdata(pdev); | ||
| 165 | |||
| 166 | backlight_update_status(bl); | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | #else | ||
| 170 | #define da903x_backlight_suspend NULL | ||
| 171 | #define da903x_backlight_resume NULL | ||
| 172 | #endif | ||
| 173 | |||
| 174 | static struct platform_driver da903x_backlight_driver = { | ||
| 175 | .driver = { | ||
| 176 | .name = "da903x-backlight", | ||
| 177 | .owner = THIS_MODULE, | ||
| 178 | }, | ||
| 179 | .probe = da903x_backlight_probe, | ||
| 180 | .remove = da903x_backlight_remove, | ||
| 181 | .suspend = da903x_backlight_suspend, | ||
| 182 | .resume = da903x_backlight_resume, | ||
| 183 | }; | ||
| 184 | |||
| 185 | static int __init da903x_backlight_init(void) | ||
| 186 | { | ||
| 187 | return platform_driver_register(&da903x_backlight_driver); | ||
| 188 | } | ||
| 189 | module_init(da903x_backlight_init); | ||
| 190 | |||
| 191 | static void __exit da903x_backlight_exit(void) | ||
| 192 | { | ||
| 193 | platform_driver_unregister(&da903x_backlight_driver); | ||
| 194 | } | ||
| 195 | module_exit(da903x_backlight_exit); | ||
| 196 | |||
| 197 | MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); | ||
| 198 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" | ||
| 199 | "Mike Rapoport <mike@compulab.co.il>"); | ||
| 200 | MODULE_LICENSE("GPL"); | ||
| 201 | MODULE_ALIAS("platform:da903x-backlight"); | ||
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c new file mode 100644 index 000000000000..a38fda1742dd --- /dev/null +++ b/drivers/video/backlight/kb3886_bl.c | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | * Backlight Driver for the KB3886 Backlight | ||
| 3 | * | ||
| 4 | * Copyright (c) 2007-2008 Claudio Nieder | ||
| 5 | * | ||
| 6 | * Based on corgi_bl.c by Richard Purdie and kb3886 driver by Robert Woerle | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/fb.h> | ||
| 20 | #include <linux/backlight.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/dmi.h> | ||
| 23 | |||
| 24 | #define KB3886_PARENT 0x64 | ||
| 25 | #define KB3886_IO 0x60 | ||
| 26 | #define KB3886_ADC_DAC_PWM 0xC4 | ||
| 27 | #define KB3886_PWM0_WRITE 0x81 | ||
| 28 | #define KB3886_PWM0_READ 0x41 | ||
| 29 | |||
| 30 | static DEFINE_MUTEX(bl_mutex); | ||
| 31 | |||
| 32 | static void kb3886_bl_set_intensity(int intensity) | ||
| 33 | { | ||
| 34 | mutex_lock(&bl_mutex); | ||
| 35 | intensity = intensity&0xff; | ||
| 36 | outb(KB3886_ADC_DAC_PWM, KB3886_PARENT); | ||
| 37 | msleep(10); | ||
| 38 | outb(KB3886_PWM0_WRITE, KB3886_IO); | ||
| 39 | msleep(10); | ||
| 40 | outb(intensity, KB3886_IO); | ||
| 41 | mutex_unlock(&bl_mutex); | ||
| 42 | } | ||
| 43 | |||
| 44 | struct kb3886bl_machinfo { | ||
| 45 | int max_intensity; | ||
| 46 | int default_intensity; | ||
| 47 | int limit_mask; | ||
| 48 | void (*set_bl_intensity)(int intensity); | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct kb3886bl_machinfo kb3886_bl_machinfo = { | ||
| 52 | .max_intensity = 0xff, | ||
| 53 | .default_intensity = 0xa0, | ||
| 54 | .limit_mask = 0x7f, | ||
| 55 | .set_bl_intensity = kb3886_bl_set_intensity, | ||
| 56 | }; | ||
| 57 | |||
| 58 | static struct platform_device kb3886bl_device = { | ||
| 59 | .name = "kb3886-bl", | ||
| 60 | .dev = { | ||
| 61 | .platform_data = &kb3886_bl_machinfo, | ||
| 62 | }, | ||
| 63 | .id = -1, | ||
| 64 | }; | ||
| 65 | |||
| 66 | static struct platform_device *devices[] __initdata = { | ||
| 67 | &kb3886bl_device, | ||
| 68 | }; | ||
| 69 | |||
| 70 | /* | ||
| 71 | * Back to driver | ||
| 72 | */ | ||
| 73 | |||
| 74 | static int kb3886bl_intensity; | ||
| 75 | static struct backlight_device *kb3886_backlight_device; | ||
| 76 | static struct kb3886bl_machinfo *bl_machinfo; | ||
| 77 | |||
| 78 | static unsigned long kb3886bl_flags; | ||
| 79 | #define KB3886BL_SUSPENDED 0x01 | ||
| 80 | |||
| 81 | static struct dmi_system_id __initdata kb3886bl_device_table[] = { | ||
| 82 | { | ||
| 83 | .ident = "Sahara Touch-iT", | ||
| 84 | .matches = { | ||
| 85 | DMI_MATCH(DMI_SYS_VENDOR, "SDV"), | ||
| 86 | DMI_MATCH(DMI_PRODUCT_NAME, "iTouch T201"), | ||
| 87 | }, | ||
| 88 | }, | ||
| 89 | { } | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int kb3886bl_send_intensity(struct backlight_device *bd) | ||
| 93 | { | ||
| 94 | int intensity = bd->props.brightness; | ||
| 95 | |||
| 96 | if (bd->props.power != FB_BLANK_UNBLANK) | ||
| 97 | intensity = 0; | ||
| 98 | if (bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
| 99 | intensity = 0; | ||
| 100 | if (kb3886bl_flags & KB3886BL_SUSPENDED) | ||
| 101 | intensity = 0; | ||
| 102 | |||
| 103 | bl_machinfo->set_bl_intensity(intensity); | ||
| 104 | |||
| 105 | kb3886bl_intensity = intensity; | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | #ifdef CONFIG_PM | ||
| 110 | static int kb3886bl_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 111 | { | ||
| 112 | struct backlight_device *bd = platform_get_drvdata(pdev); | ||
| 113 | |||
| 114 | kb3886bl_flags |= KB3886BL_SUSPENDED; | ||
| 115 | backlight_update_status(bd); | ||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int kb3886bl_resume(struct platform_device *pdev) | ||
| 120 | { | ||
| 121 | struct backlight_device *bd = platform_get_drvdata(pdev); | ||
| 122 | |||
| 123 | kb3886bl_flags &= ~KB3886BL_SUSPENDED; | ||
| 124 | backlight_update_status(bd); | ||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | #else | ||
| 128 | #define kb3886bl_suspend NULL | ||
| 129 | #define kb3886bl_resume NULL | ||
| 130 | #endif | ||
| 131 | |||
| 132 | static int kb3886bl_get_intensity(struct backlight_device *bd) | ||
| 133 | { | ||
| 134 | return kb3886bl_intensity; | ||
| 135 | } | ||
| 136 | |||
| 137 | static struct backlight_ops kb3886bl_ops = { | ||
| 138 | .get_brightness = kb3886bl_get_intensity, | ||
| 139 | .update_status = kb3886bl_send_intensity, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int kb3886bl_probe(struct platform_device *pdev) | ||
| 143 | { | ||
| 144 | struct kb3886bl_machinfo *machinfo = pdev->dev.platform_data; | ||
| 145 | |||
| 146 | bl_machinfo = machinfo; | ||
| 147 | if (!machinfo->limit_mask) | ||
| 148 | machinfo->limit_mask = -1; | ||
| 149 | |||
| 150 | kb3886_backlight_device = backlight_device_register("kb3886-bl", | ||
| 151 | &pdev->dev, NULL, &kb3886bl_ops); | ||
| 152 | if (IS_ERR(kb3886_backlight_device)) | ||
| 153 | return PTR_ERR(kb3886_backlight_device); | ||
| 154 | |||
| 155 | platform_set_drvdata(pdev, kb3886_backlight_device); | ||
| 156 | |||
| 157 | kb3886_backlight_device->props.max_brightness = machinfo->max_intensity; | ||
| 158 | kb3886_backlight_device->props.power = FB_BLANK_UNBLANK; | ||
| 159 | kb3886_backlight_device->props.brightness = machinfo->default_intensity; | ||
| 160 | backlight_update_status(kb3886_backlight_device); | ||
| 161 | |||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int kb3886bl_remove(struct platform_device *pdev) | ||
| 166 | { | ||
| 167 | struct backlight_device *bd = platform_get_drvdata(pdev); | ||
| 168 | |||
| 169 | backlight_device_unregister(bd); | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static struct platform_driver kb3886bl_driver = { | ||
| 175 | .probe = kb3886bl_probe, | ||
| 176 | .remove = kb3886bl_remove, | ||
| 177 | .suspend = kb3886bl_suspend, | ||
| 178 | .resume = kb3886bl_resume, | ||
| 179 | .driver = { | ||
| 180 | .name = "kb3886-bl", | ||
| 181 | }, | ||
| 182 | }; | ||
| 183 | |||
| 184 | static int __init kb3886_init(void) | ||
| 185 | { | ||
| 186 | if (!dmi_check_system(kb3886bl_device_table)) | ||
| 187 | return -ENODEV; | ||
| 188 | |||
| 189 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
| 190 | return platform_driver_register(&kb3886bl_driver); | ||
| 191 | } | ||
| 192 | |||
| 193 | static void __exit kb3886_exit(void) | ||
| 194 | { | ||
| 195 | platform_driver_unregister(&kb3886bl_driver); | ||
| 196 | } | ||
| 197 | |||
| 198 | module_init(kb3886_init); | ||
| 199 | module_exit(kb3886_exit); | ||
| 200 | |||
| 201 | MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>"); | ||
| 202 | MODULE_DESCRIPTION("Tabletkiosk Sahara Touch-iT Backlight Driver"); | ||
| 203 | MODULE_LICENSE("GPL"); | ||
| 204 | MODULE_ALIAS("dmi:*:svnSDV:pniTouchT201:*"); | ||
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c new file mode 100644 index 000000000000..43edbada12d1 --- /dev/null +++ b/drivers/video/backlight/tosa_bl.c | |||
| @@ -0,0 +1,198 @@ | |||
| 1 | /* | ||
| 2 | * LCD / Backlight control code for Sharp SL-6000x (tosa) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Dirk Opfer | ||
| 5 | * Copyright (c) 2007,2008 Dmitry Baryshkov | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/device.h> | ||
| 16 | #include <linux/spi/spi.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/gpio.h> | ||
| 19 | #include <linux/fb.h> | ||
| 20 | #include <linux/backlight.h> | ||
| 21 | |||
| 22 | #include <asm/mach/sharpsl_param.h> | ||
| 23 | |||
| 24 | #include <mach/tosa.h> | ||
| 25 | |||
| 26 | #define COMADJ_DEFAULT 97 | ||
| 27 | |||
| 28 | #define DAC_CH1 0 | ||
| 29 | #define DAC_CH2 1 | ||
| 30 | |||
| 31 | struct tosa_bl_data { | ||
| 32 | struct i2c_client *i2c; | ||
| 33 | struct backlight_device *bl; | ||
| 34 | |||
| 35 | int comadj; | ||
| 36 | }; | ||
| 37 | |||
| 38 | static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness) | ||
| 39 | { | ||
| 40 | struct spi_device *spi = data->i2c->dev.platform_data; | ||
| 41 | |||
| 42 | i2c_smbus_write_byte_data(data->i2c, DAC_CH1, data->comadj); | ||
| 43 | |||
| 44 | /* SetBacklightDuty */ | ||
| 45 | i2c_smbus_write_byte_data(data->i2c, DAC_CH2, (u8)(brightness & 0xff)); | ||
| 46 | |||
| 47 | /* SetBacklightVR */ | ||
| 48 | gpio_set_value(TOSA_GPIO_BL_C20MA, brightness & 0x100); | ||
| 49 | |||
| 50 | tosa_bl_enable(spi, brightness); | ||
| 51 | } | ||
| 52 | |||
| 53 | static int tosa_bl_update_status(struct backlight_device *dev) | ||
| 54 | { | ||
| 55 | struct backlight_properties *props = &dev->props; | ||
| 56 | struct tosa_bl_data *data = dev_get_drvdata(&dev->dev); | ||
| 57 | int power = max(props->power, props->fb_blank); | ||
| 58 | int brightness = props->brightness; | ||
| 59 | |||
| 60 | if (power) | ||
| 61 | brightness = 0; | ||
| 62 | |||
| 63 | tosa_bl_set_backlight(data, brightness); | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static int tosa_bl_get_brightness(struct backlight_device *dev) | ||
| 69 | { | ||
| 70 | struct backlight_properties *props = &dev->props; | ||
| 71 | |||
| 72 | return props->brightness; | ||
| 73 | } | ||
| 74 | |||
| 75 | static struct backlight_ops bl_ops = { | ||
| 76 | .get_brightness = tosa_bl_get_brightness, | ||
| 77 | .update_status = tosa_bl_update_status, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static int __devinit tosa_bl_probe(struct i2c_client *client, | ||
| 81 | const struct i2c_device_id *id) | ||
| 82 | { | ||
| 83 | struct tosa_bl_data *data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL); | ||
| 84 | int ret = 0; | ||
| 85 | if (!data) | ||
| 86 | return -ENOMEM; | ||
| 87 | |||
| 88 | data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; | ||
| 89 | |||
| 90 | ret = gpio_request(TOSA_GPIO_BL_C20MA, "backlight"); | ||
| 91 | if (ret) { | ||
| 92 | dev_dbg(&data->bl->dev, "Unable to request gpio!\n"); | ||
| 93 | goto err_gpio_bl; | ||
| 94 | } | ||
| 95 | ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0); | ||
| 96 | if (ret) | ||
| 97 | goto err_gpio_dir; | ||
| 98 | |||
| 99 | i2c_set_clientdata(client, data); | ||
| 100 | data->i2c = client; | ||
| 101 | |||
| 102 | data->bl = backlight_device_register("tosa-bl", &client->dev, | ||
| 103 | data, &bl_ops); | ||
| 104 | if (IS_ERR(data->bl)) { | ||
| 105 | ret = PTR_ERR(data->bl); | ||
| 106 | goto err_reg; | ||
| 107 | } | ||
| 108 | |||
| 109 | data->bl->props.brightness = 69; | ||
| 110 | data->bl->props.max_brightness = 512 - 1; | ||
| 111 | data->bl->props.power = FB_BLANK_UNBLANK; | ||
| 112 | |||
| 113 | backlight_update_status(data->bl); | ||
| 114 | |||
| 115 | return 0; | ||
| 116 | |||
| 117 | err_reg: | ||
| 118 | data->bl = NULL; | ||
| 119 | i2c_set_clientdata(client, NULL); | ||
| 120 | err_gpio_dir: | ||
| 121 | gpio_free(TOSA_GPIO_BL_C20MA); | ||
| 122 | err_gpio_bl: | ||
| 123 | kfree(data); | ||
| 124 | return ret; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int __devexit tosa_bl_remove(struct i2c_client *client) | ||
| 128 | { | ||
| 129 | struct tosa_bl_data *data = i2c_get_clientdata(client); | ||
| 130 | |||
| 131 | backlight_device_unregister(data->bl); | ||
| 132 | data->bl = NULL; | ||
| 133 | i2c_set_clientdata(client, NULL); | ||
| 134 | |||
| 135 | gpio_free(TOSA_GPIO_BL_C20MA); | ||
| 136 | |||
| 137 | kfree(data); | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | #ifdef CONFIG_PM | ||
| 143 | static int tosa_bl_suspend(struct i2c_client *client, pm_message_t pm) | ||
| 144 | { | ||
| 145 | struct tosa_bl_data *data = i2c_get_clientdata(client); | ||
| 146 | |||
| 147 | tosa_bl_set_backlight(data, 0); | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int tosa_bl_resume(struct i2c_client *client) | ||
| 153 | { | ||
| 154 | struct tosa_bl_data *data = i2c_get_clientdata(client); | ||
| 155 | |||
| 156 | backlight_update_status(data->bl); | ||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | #else | ||
| 160 | #define tosa_bl_suspend NULL | ||
| 161 | #define tosa_bl_resume NULL | ||
| 162 | #endif | ||
| 163 | |||
| 164 | static const struct i2c_device_id tosa_bl_id[] = { | ||
| 165 | { "tosa-bl", 0 }, | ||
| 166 | { }, | ||
| 167 | }; | ||
| 168 | |||
| 169 | |||
| 170 | static struct i2c_driver tosa_bl_driver = { | ||
| 171 | .driver = { | ||
| 172 | .name = "tosa-bl", | ||
| 173 | .owner = THIS_MODULE, | ||
| 174 | }, | ||
| 175 | .probe = tosa_bl_probe, | ||
| 176 | .remove = __devexit_p(tosa_bl_remove), | ||
| 177 | .suspend = tosa_bl_suspend, | ||
| 178 | .resume = tosa_bl_resume, | ||
| 179 | .id_table = tosa_bl_id, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static int __init tosa_bl_init(void) | ||
| 183 | { | ||
| 184 | return i2c_add_driver(&tosa_bl_driver); | ||
| 185 | } | ||
| 186 | |||
| 187 | static void __exit tosa_bl_exit(void) | ||
| 188 | { | ||
| 189 | i2c_del_driver(&tosa_bl_driver); | ||
| 190 | } | ||
| 191 | |||
| 192 | module_init(tosa_bl_init); | ||
| 193 | module_exit(tosa_bl_exit); | ||
| 194 | |||
| 195 | MODULE_AUTHOR("Dmitry Baryshkov"); | ||
| 196 | MODULE_LICENSE("GPL v2"); | ||
| 197 | MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA"); | ||
| 198 | |||
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c new file mode 100644 index 000000000000..57a26649f1a5 --- /dev/null +++ b/drivers/video/backlight/tosa_lcd.c | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* | ||
| 2 | * LCD / Backlight control code for Sharp SL-6000x (tosa) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Dirk Opfer | ||
| 5 | * Copyright (c) 2007,2008 Dmitry Baryshkov | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/device.h> | ||
| 16 | #include <linux/spi/spi.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/gpio.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/lcd.h> | ||
| 21 | #include <linux/fb.h> | ||
| 22 | |||
| 23 | #include <asm/mach/sharpsl_param.h> | ||
| 24 | |||
| 25 | #include <mach/tosa.h> | ||
| 26 | |||
| 27 | #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) | ||
| 28 | |||
| 29 | #define TG_REG0_VQV 0x0001 | ||
| 30 | #define TG_REG0_COLOR 0x0002 | ||
| 31 | #define TG_REG0_UD 0x0004 | ||
| 32 | #define TG_REG0_LR 0x0008 | ||
| 33 | |||
| 34 | #define DAC_BASE 0x4e | ||
| 35 | |||
| 36 | struct tosa_lcd_data { | ||
| 37 | struct spi_device *spi; | ||
| 38 | struct lcd_device *lcd; | ||
| 39 | struct i2c_client *i2c; | ||
| 40 | |||
| 41 | int lcd_power; | ||
| 42 | }; | ||
| 43 | |||
| 44 | static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data) | ||
| 45 | { | ||
| 46 | u8 buf[1]; | ||
| 47 | struct spi_message msg; | ||
| 48 | struct spi_transfer xfer = { | ||
| 49 | .len = 1, | ||
| 50 | .cs_change = 1, | ||
| 51 | .tx_buf = buf, | ||
| 52 | }; | ||
| 53 | |||
| 54 | buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f); | ||
| 55 | spi_message_init(&msg); | ||
| 56 | spi_message_add_tail(&xfer, &msg); | ||
| 57 | |||
| 58 | return spi_sync(spi, &msg); | ||
| 59 | } | ||
| 60 | |||
| 61 | int tosa_bl_enable(struct spi_device *spi, int enable) | ||
| 62 | { | ||
| 63 | /* bl_enable GP04=1 otherwise GP04=0*/ | ||
| 64 | return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00); | ||
| 65 | } | ||
| 66 | EXPORT_SYMBOL(tosa_bl_enable); | ||
| 67 | |||
| 68 | static void tosa_lcd_tg_init(struct tosa_lcd_data *data) | ||
| 69 | { | ||
| 70 | /* TG on */ | ||
| 71 | gpio_set_value(TOSA_GPIO_TG_ON, 0); | ||
| 72 | |||
| 73 | mdelay(60); | ||
| 74 | |||
| 75 | /* delayed 0clk TCTL signal for VGA */ | ||
| 76 | tosa_tg_send(data->spi, TG_TPOSCTL, 0x00); | ||
| 77 | /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */ | ||
| 78 | tosa_tg_send(data->spi, TG_GPOSR, 0x02); | ||
| 79 | } | ||
| 80 | |||
| 81 | static void tosa_lcd_tg_on(struct tosa_lcd_data *data) | ||
| 82 | { | ||
| 83 | struct spi_device *spi = data->spi; | ||
| 84 | const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR; | ||
| 85 | tosa_tg_send(spi, TG_PNLCTL, value | TG_REG0_VQV); /* this depends on mode */ | ||
| 86 | |||
| 87 | /* TG LCD pannel power up */ | ||
| 88 | tosa_tg_send(spi, TG_PINICTL,0x4); | ||
| 89 | mdelay(50); | ||
| 90 | |||
| 91 | /* TG LCD GVSS */ | ||
| 92 | tosa_tg_send(spi, TG_PINICTL,0x0); | ||
| 93 | |||
| 94 | if (!data->i2c) { | ||
| 95 | /* after the pannel is powered up the first time, we can access the i2c bus */ | ||
| 96 | /* so probe for the DAC */ | ||
| 97 | struct i2c_adapter *adap = i2c_get_adapter(0); | ||
| 98 | struct i2c_board_info info = { | ||
| 99 | .type = "tosa-bl", | ||
| 100 | .addr = DAC_BASE, | ||
| 101 | .platform_data = data->spi, | ||
| 102 | }; | ||
| 103 | data->i2c = i2c_new_device(adap, &info); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | static void tosa_lcd_tg_off(struct tosa_lcd_data *data) | ||
| 108 | { | ||
| 109 | struct spi_device *spi = data->spi; | ||
| 110 | |||
| 111 | /* TG LCD VHSA off */ | ||
| 112 | tosa_tg_send(spi, TG_PINICTL,0x4); | ||
| 113 | mdelay(50); | ||
| 114 | |||
| 115 | /* TG LCD signal off */ | ||
| 116 | tosa_tg_send(spi, TG_PINICTL,0x6); | ||
| 117 | mdelay(50); | ||
| 118 | |||
| 119 | /* TG Off */ | ||
| 120 | gpio_set_value(TOSA_GPIO_TG_ON, 1); | ||
| 121 | mdelay(100); | ||
| 122 | } | ||
| 123 | |||
| 124 | int tosa_lcd_set_power(struct lcd_device *lcd, int power) | ||
| 125 | { | ||
| 126 | struct tosa_lcd_data *data = lcd_get_data(lcd); | ||
| 127 | |||
| 128 | if (POWER_IS_ON(power) && !POWER_IS_ON(data->lcd_power)) | ||
| 129 | tosa_lcd_tg_on(data); | ||
| 130 | |||
| 131 | if (!POWER_IS_ON(power) && POWER_IS_ON(data->lcd_power)) | ||
| 132 | tosa_lcd_tg_off(data); | ||
| 133 | |||
| 134 | data->lcd_power = power; | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int tosa_lcd_get_power(struct lcd_device *lcd) | ||
| 139 | { | ||
| 140 | struct tosa_lcd_data *data = lcd_get_data(lcd); | ||
| 141 | |||
| 142 | return data->lcd_power; | ||
| 143 | } | ||
| 144 | |||
| 145 | static struct lcd_ops tosa_lcd_ops = { | ||
| 146 | .set_power = tosa_lcd_set_power, | ||
| 147 | .get_power = tosa_lcd_get_power, | ||
| 148 | }; | ||
| 149 | |||
| 150 | static int __devinit tosa_lcd_probe(struct spi_device *spi) | ||
| 151 | { | ||
| 152 | int ret; | ||
| 153 | struct tosa_lcd_data *data; | ||
| 154 | |||
| 155 | data = kzalloc(sizeof(struct tosa_lcd_data), GFP_KERNEL); | ||
| 156 | if (!data) | ||
| 157 | return -ENOMEM; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * bits_per_word cannot be configured in platform data | ||
| 161 | */ | ||
| 162 | spi->bits_per_word = 8; | ||
| 163 | |||
| 164 | ret = spi_setup(spi); | ||
| 165 | if (ret < 0) | ||
| 166 | goto err_spi; | ||
| 167 | |||
| 168 | data->spi = spi; | ||
| 169 | dev_set_drvdata(&spi->dev, data); | ||
| 170 | |||
| 171 | ret = gpio_request(TOSA_GPIO_TG_ON, "tg #pwr"); | ||
| 172 | if (ret < 0) | ||
| 173 | goto err_gpio_tg; | ||
| 174 | |||
| 175 | mdelay(60); | ||
| 176 | |||
| 177 | ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0); | ||
| 178 | if (ret < 0) | ||
| 179 | goto err_gpio_dir; | ||
| 180 | |||
| 181 | mdelay(60); | ||
| 182 | tosa_lcd_tg_init(data); | ||
| 183 | |||
| 184 | tosa_lcd_tg_on(data); | ||
| 185 | |||
| 186 | data->lcd = lcd_device_register("tosa-lcd", &spi->dev, data, | ||
| 187 | &tosa_lcd_ops); | ||
| 188 | |||
| 189 | if (IS_ERR(data->lcd)) { | ||
| 190 | ret = PTR_ERR(data->lcd); | ||
| 191 | data->lcd = NULL; | ||
| 192 | goto err_register; | ||
| 193 | } | ||
| 194 | |||
| 195 | return 0; | ||
| 196 | |||
| 197 | err_register: | ||
| 198 | tosa_lcd_tg_off(data); | ||
| 199 | err_gpio_dir: | ||
| 200 | gpio_free(TOSA_GPIO_TG_ON); | ||
| 201 | err_gpio_tg: | ||
| 202 | dev_set_drvdata(&spi->dev, NULL); | ||
| 203 | err_spi: | ||
| 204 | kfree(data); | ||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int __devexit tosa_lcd_remove(struct spi_device *spi) | ||
| 209 | { | ||
| 210 | struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev); | ||
| 211 | |||
| 212 | lcd_device_unregister(data->lcd); | ||
| 213 | |||
| 214 | if (data->i2c) | ||
| 215 | i2c_unregister_device(data->i2c); | ||
| 216 | |||
| 217 | tosa_lcd_tg_off(data); | ||
| 218 | |||
| 219 | gpio_free(TOSA_GPIO_TG_ON); | ||
| 220 | dev_set_drvdata(&spi->dev, NULL); | ||
| 221 | kfree(data); | ||
| 222 | |||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | #ifdef CONFIG_PM | ||
| 227 | static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state) | ||
| 228 | { | ||
| 229 | struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev); | ||
| 230 | |||
| 231 | tosa_lcd_tg_off(data); | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int tosa_lcd_resume(struct spi_device *spi) | ||
| 237 | { | ||
| 238 | struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev); | ||
| 239 | |||
| 240 | tosa_lcd_tg_init(data); | ||
| 241 | if (POWER_IS_ON(data->lcd_power)) | ||
| 242 | tosa_lcd_tg_on(data); | ||
| 243 | else | ||
| 244 | tosa_lcd_tg_off(data); | ||
| 245 | |||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | #else | ||
| 249 | #define tosa_lcd_suspend NULL | ||
| 250 | #define tosa_lcd_reume NULL | ||
| 251 | #endif | ||
| 252 | |||
| 253 | static struct spi_driver tosa_lcd_driver = { | ||
| 254 | .driver = { | ||
| 255 | .name = "tosa-lcd", | ||
| 256 | .owner = THIS_MODULE, | ||
| 257 | }, | ||
| 258 | .probe = tosa_lcd_probe, | ||
| 259 | .remove = __devexit_p(tosa_lcd_remove), | ||
| 260 | .suspend = tosa_lcd_suspend, | ||
| 261 | .resume = tosa_lcd_resume, | ||
| 262 | }; | ||
| 263 | |||
| 264 | static int __init tosa_lcd_init(void) | ||
| 265 | { | ||
| 266 | return spi_register_driver(&tosa_lcd_driver); | ||
| 267 | } | ||
| 268 | |||
| 269 | static void __exit tosa_lcd_exit(void) | ||
| 270 | { | ||
| 271 | spi_unregister_driver(&tosa_lcd_driver); | ||
| 272 | } | ||
| 273 | |||
| 274 | module_init(tosa_lcd_init); | ||
| 275 | module_exit(tosa_lcd_exit); | ||
| 276 | |||
| 277 | MODULE_AUTHOR("Dmitry Baryshkov"); | ||
| 278 | MODULE_LICENSE("GPL v2"); | ||
| 279 | MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA"); | ||
| 280 | |||
