diff options
-rw-r--r-- | Documentation/devicetree/bindings/video/fsl,imx-fb.txt | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-mx27ads.c | 55 | ||||
-rw-r--r-- | drivers/video/imxfb.c | 71 | ||||
-rw-r--r-- | include/linux/platform_data/video-imxfb.h | 1 |
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 | ||
17 | Optional properties: | 17 | Optional 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 = { | |||
195 | static struct i2c_board_info mx27ads_i2c_devices[] = { | 199 | static struct i2c_board_info mx27ads_i2c_devices[] = { |
196 | }; | 200 | }; |
197 | 201 | ||
198 | void lcd_power(int on) | 202 | static 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 | ||
210 | static 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 | |||
217 | static struct regulator_consumer_supply mx27ads_lcd_regulator_consumer = | ||
218 | REGULATOR_SUPPLY("lcd", "imx-fb.0"); | ||
219 | |||
220 | static 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 | |||
228 | static 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 | |||
235 | static 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 | |||
206 | static struct imx_fb_videomode mx27ads_modes[] = { | 254 | static 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 | ||
246 | static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq, | 292 | static 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 | ||
184 | static struct platform_device_id imxfb_devtype[] = { | 188 | static 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 | ||
598 | static void imxfb_disable_controller(struct imxfb_info *fbi) | 600 | static 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 | ||
855 | static 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 | |||
865 | static 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 | |||
875 | static 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 | |||
889 | static 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 | |||
859 | static int imxfb_probe(struct platform_device *pdev) | 895 | static 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 | ||
1081 | failed_lcd: | ||
1082 | unregister_framebuffer(info); | ||
1083 | |||
1031 | failed_register: | 1084 | failed_register: |
1032 | fb_dealloc_cmap(&info->cmap); | 1085 | fb_dealloc_cmap(&info->cmap); |
1033 | failed_cmap: | 1086 | failed_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 | ||