aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/video/fsl,imx-fb.txt1
-rw-r--r--arch/arm/mach-imx/mach-mx27ads.c55
-rw-r--r--drivers/video/imxfb.c71
-rw-r--r--include/linux/platform_data/video-imxfb.h1
4 files changed, 114 insertions, 14 deletions
diff --git a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
index 46da08db186a..e6b1ee9b8e2e 100644
--- a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
+++ b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
@@ -15,6 +15,7 @@ Required nodes:
15 - fsl,pcr: LCDC PCR value 15 - fsl,pcr: LCDC PCR value
16 16
17Optional properties: 17Optional properties:
18- lcd-supply: Regulator for LCD supply voltage.
18- fsl,dmacr: DMA Control Register value. This is optional. By default, the 19- fsl,dmacr: DMA Control Register value. This is optional. By default, the
19 register is not modified as recommended by the datasheet. 20 register is not modified as recommended by the datasheet.
20- fsl,lscr1: LCDC Sharp Configuration Register value. 21- fsl,lscr1: LCDC Sharp Configuration Register value.
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 9821b824dcaf..a7a4a9c67615 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -21,6 +21,10 @@
21#include <linux/mtd/physmap.h> 21#include <linux/mtd/physmap.h>
22#include <linux/i2c.h> 22#include <linux/i2c.h>
23#include <linux/irq.h> 23#include <linux/irq.h>
24
25#include <linux/regulator/fixed.h>
26#include <linux/regulator/machine.h>
27
24#include <asm/mach-types.h> 28#include <asm/mach-types.h>
25#include <asm/mach/arch.h> 29#include <asm/mach/arch.h>
26#include <asm/mach/time.h> 30#include <asm/mach/time.h>
@@ -195,14 +199,58 @@ static const struct imxi2c_platform_data mx27ads_i2c1_data __initconst = {
195static struct i2c_board_info mx27ads_i2c_devices[] = { 199static struct i2c_board_info mx27ads_i2c_devices[] = {
196}; 200};
197 201
198void lcd_power(int on) 202static void vgpio_set(struct gpio_chip *chip, unsigned offset, int value)
199{ 203{
200 if (on) 204 if (value)
201 __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG); 205 __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG);
202 else 206 else
203 __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG); 207 __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG);
204} 208}
205 209
210static int vgpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
211{
212 return 0;
213}
214
215#define MX27ADS_LCD_GPIO (6 * 32)
216
217static struct regulator_consumer_supply mx27ads_lcd_regulator_consumer =
218 REGULATOR_SUPPLY("lcd", "imx-fb.0");
219
220static struct regulator_init_data mx27ads_lcd_regulator_init_data = {
221 .constraints = {
222 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
223},
224 .consumer_supplies = &mx27ads_lcd_regulator_consumer,
225 .num_consumer_supplies = 1,
226};
227
228static struct fixed_voltage_config mx27ads_lcd_regulator_pdata = {
229 .supply_name = "LCD",
230 .microvolts = 3300000,
231 .gpio = MX27ADS_LCD_GPIO,
232 .init_data = &mx27ads_lcd_regulator_init_data,
233};
234
235static void __init mx27ads_regulator_init(void)
236{
237 struct gpio_chip *vchip;
238
239 vchip = kzalloc(sizeof(*vchip), GFP_KERNEL);
240 vchip->owner = THIS_MODULE;
241 vchip->label = "LCD";
242 vchip->base = MX27ADS_LCD_GPIO;
243 vchip->ngpio = 1;
244 vchip->direction_output = vgpio_dir_out;
245 vchip->set = vgpio_set;
246 gpiochip_add(vchip);
247
248 platform_device_register_data(&platform_bus, "reg-fixed-voltage",
249 PLATFORM_DEVID_AUTO,
250 &mx27ads_lcd_regulator_pdata,
251 sizeof(mx27ads_lcd_regulator_pdata));
252}
253
206static struct imx_fb_videomode mx27ads_modes[] = { 254static struct imx_fb_videomode mx27ads_modes[] = {
207 { 255 {
208 .mode = { 256 .mode = {
@@ -239,8 +287,6 @@ static const struct imx_fb_platform_data mx27ads_fb_data __initconst = {
239 .pwmr = 0x00A903FF, 287 .pwmr = 0x00A903FF,
240 .lscr1 = 0x00120300, 288 .lscr1 = 0x00120300,
241 .dmacr = 0x00020010, 289 .dmacr = 0x00020010,
242
243 .lcd_power = lcd_power,
244}; 290};
245 291
246static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq, 292static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
@@ -304,6 +350,7 @@ static void __init mx27ads_board_init(void)
304 i2c_register_board_info(1, mx27ads_i2c_devices, 350 i2c_register_board_info(1, mx27ads_i2c_devices,
305 ARRAY_SIZE(mx27ads_i2c_devices)); 351 ARRAY_SIZE(mx27ads_i2c_devices));
306 imx27_add_imx_i2c(1, &mx27ads_i2c1_data); 352 imx27_add_imx_i2c(1, &mx27ads_i2c1_data);
353 mx27ads_regulator_init();
307 imx27_add_imx_fb(&mx27ads_fb_data); 354 imx27_add_imx_fb(&mx27ads_fb_data);
308 imx27_add_mxc_mmc(0, &sdhc1_pdata); 355 imx27_add_mxc_mmc(0, &sdhc1_pdata);
309 imx27_add_mxc_mmc(1, &sdhc2_pdata); 356 imx27_add_mxc_mmc(1, &sdhc2_pdata);
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 44ee678481d5..e50b67fada51 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -30,10 +30,13 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/dma-mapping.h> 31#include <linux/dma-mapping.h>
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/lcd.h>
33#include <linux/math64.h> 34#include <linux/math64.h>
34#include <linux/of.h> 35#include <linux/of.h>
35#include <linux/of_device.h> 36#include <linux/of_device.h>
36 37
38#include <linux/regulator/consumer.h>
39
37#include <video/of_display_timing.h> 40#include <video/of_display_timing.h>
38#include <video/of_videomode.h> 41#include <video/of_videomode.h>
39#include <video/videomode.h> 42#include <video/videomode.h>
@@ -177,8 +180,9 @@ struct imxfb_info {
177 struct backlight_device *bl; 180 struct backlight_device *bl;
178#endif 181#endif
179 182
180 void (*lcd_power)(int);
181 void (*backlight_power)(int); 183 void (*backlight_power)(int);
184
185 struct regulator *lcd_pwr;
182}; 186};
183 187
184static struct platform_device_id imxfb_devtype[] = { 188static struct platform_device_id imxfb_devtype[] = {
@@ -591,8 +595,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
591 595
592 if (fbi->backlight_power) 596 if (fbi->backlight_power)
593 fbi->backlight_power(1); 597 fbi->backlight_power(1);
594 if (fbi->lcd_power)
595 fbi->lcd_power(1);
596} 598}
597 599
598static void imxfb_disable_controller(struct imxfb_info *fbi) 600static void imxfb_disable_controller(struct imxfb_info *fbi)
@@ -604,8 +606,6 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
604 606
605 if (fbi->backlight_power) 607 if (fbi->backlight_power)
606 fbi->backlight_power(0); 608 fbi->backlight_power(0);
607 if (fbi->lcd_power)
608 fbi->lcd_power(0);
609 609
610 clk_disable_unprepare(fbi->clk_per); 610 clk_disable_unprepare(fbi->clk_per);
611 clk_disable_unprepare(fbi->clk_ipg); 611 clk_disable_unprepare(fbi->clk_ipg);
@@ -796,7 +796,6 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
796 fbi->lscr1 = pdata->lscr1; 796 fbi->lscr1 = pdata->lscr1;
797 fbi->dmacr = pdata->dmacr; 797 fbi->dmacr = pdata->dmacr;
798 fbi->pwmr = pdata->pwmr; 798 fbi->pwmr = pdata->pwmr;
799 fbi->lcd_power = pdata->lcd_power;
800 fbi->backlight_power = pdata->backlight_power; 799 fbi->backlight_power = pdata->backlight_power;
801 } else { 800 } else {
802 np = pdev->dev.of_node; 801 np = pdev->dev.of_node;
@@ -810,9 +809,6 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
810 809
811 of_property_read_u32(np, "fsl,dmacr", &fbi->dmacr); 810 of_property_read_u32(np, "fsl,dmacr", &fbi->dmacr);
812 811
813 /* These two function pointers could be used by some specific
814 * platforms. */
815 fbi->lcd_power = NULL;
816 fbi->backlight_power = NULL; 812 fbi->backlight_power = NULL;
817 } 813 }
818 814
@@ -856,9 +852,50 @@ static int imxfb_of_read_mode(struct device *dev, struct device_node *np,
856 return 0; 852 return 0;
857} 853}
858 854
855static int imxfb_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi)
856{
857 struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
858
859 if (!fi || fi->par == fbi)
860 return 1;
861
862 return 0;
863}
864
865static int imxfb_lcd_get_power(struct lcd_device *lcddev)
866{
867 struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
868
869 if (!IS_ERR(fbi->lcd_pwr))
870 return regulator_is_enabled(fbi->lcd_pwr);
871
872 return 1;
873}
874
875static int imxfb_lcd_set_power(struct lcd_device *lcddev, int power)
876{
877 struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
878
879 if (!IS_ERR(fbi->lcd_pwr)) {
880 if (power)
881 return regulator_enable(fbi->lcd_pwr);
882 else
883 return regulator_disable(fbi->lcd_pwr);
884 }
885
886 return 0;
887}
888
889static struct lcd_ops imxfb_lcd_ops = {
890 .check_fb = imxfb_lcd_check_fb,
891 .get_power = imxfb_lcd_get_power,
892 .set_power = imxfb_lcd_set_power,
893};
894
859static int imxfb_probe(struct platform_device *pdev) 895static int imxfb_probe(struct platform_device *pdev)
860{ 896{
861 struct imxfb_info *fbi; 897 struct imxfb_info *fbi;
898 struct lcd_device *lcd;
862 struct fb_info *info; 899 struct fb_info *info;
863 struct imx_fb_platform_data *pdata; 900 struct imx_fb_platform_data *pdata;
864 struct resource *res; 901 struct resource *res;
@@ -1020,6 +1057,19 @@ static int imxfb_probe(struct platform_device *pdev)
1020 goto failed_register; 1057 goto failed_register;
1021 } 1058 }
1022 1059
1060 fbi->lcd_pwr = devm_regulator_get(&pdev->dev, "lcd");
1061 if (IS_ERR(fbi->lcd_pwr) && (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER)) {
1062 ret = -EPROBE_DEFER;
1063 goto failed_lcd;
1064 }
1065
1066 lcd = devm_lcd_device_register(&pdev->dev, "imxfb-lcd", &pdev->dev, fbi,
1067 &imxfb_lcd_ops);
1068 if (IS_ERR(lcd)) {
1069 ret = PTR_ERR(lcd);
1070 goto failed_lcd;
1071 }
1072
1023 imxfb_enable_controller(fbi); 1073 imxfb_enable_controller(fbi);
1024 fbi->pdev = pdev; 1074 fbi->pdev = pdev;
1025#ifdef PWMR_BACKLIGHT_AVAILABLE 1075#ifdef PWMR_BACKLIGHT_AVAILABLE
@@ -1028,6 +1078,9 @@ static int imxfb_probe(struct platform_device *pdev)
1028 1078
1029 return 0; 1079 return 0;
1030 1080
1081failed_lcd:
1082 unregister_framebuffer(info);
1083
1031failed_register: 1084failed_register:
1032 fb_dealloc_cmap(&info->cmap); 1085 fb_dealloc_cmap(&info->cmap);
1033failed_cmap: 1086failed_cmap:
diff --git a/include/linux/platform_data/video-imxfb.h b/include/linux/platform_data/video-imxfb.h
index 9de8f062ad5d..8902706fffa4 100644
--- a/include/linux/platform_data/video-imxfb.h
+++ b/include/linux/platform_data/video-imxfb.h
@@ -76,7 +76,6 @@ struct imx_fb_platform_data {
76 int (*init)(struct platform_device *); 76 int (*init)(struct platform_device *);
77 void (*exit)(struct platform_device *); 77 void (*exit)(struct platform_device *);
78 78
79 void (*lcd_power)(int);
80 void (*backlight_power)(int); 79 void (*backlight_power)(int);
81}; 80};
82 81