0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/io.h>
0013 #include <linux/delay.h>
0014 #include <linux/gpio/consumer.h>
0015 #include <linux/lcd.h>
0016
0017 #include <linux/soc/ti/omap1-io.h>
0018
0019 #include "omapfb.h"
0020
0021 #define AMS_DELTA_DEFAULT_CONTRAST 112
0022
0023 #define AMS_DELTA_MAX_CONTRAST 0x00FF
0024 #define AMS_DELTA_LCD_POWER 0x0100
0025
0026
0027
0028
0029 static int ams_delta_lcd;
0030 static struct gpio_desc *gpiod_vblen;
0031 static struct gpio_desc *gpiod_ndisp;
0032
0033 static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
0034 {
0035 if (power == FB_BLANK_UNBLANK) {
0036 if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) {
0037 omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST,
0038 OMAP_PWL_ENABLE);
0039 omap_writeb(1, OMAP_PWL_CLK_ENABLE);
0040 ams_delta_lcd |= AMS_DELTA_LCD_POWER;
0041 }
0042 } else {
0043 if (ams_delta_lcd & AMS_DELTA_LCD_POWER) {
0044 omap_writeb(0, OMAP_PWL_ENABLE);
0045 omap_writeb(0, OMAP_PWL_CLK_ENABLE);
0046 ams_delta_lcd &= ~AMS_DELTA_LCD_POWER;
0047 }
0048 }
0049 return 0;
0050 }
0051
0052 static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value)
0053 {
0054 if ((value >= 0) && (value <= AMS_DELTA_MAX_CONTRAST)) {
0055 omap_writeb(value, OMAP_PWL_ENABLE);
0056 ams_delta_lcd &= ~AMS_DELTA_MAX_CONTRAST;
0057 ams_delta_lcd |= value;
0058 }
0059 return 0;
0060 }
0061
0062 #ifdef CONFIG_LCD_CLASS_DEVICE
0063 static int ams_delta_lcd_get_power(struct lcd_device *dev)
0064 {
0065 if (ams_delta_lcd & AMS_DELTA_LCD_POWER)
0066 return FB_BLANK_UNBLANK;
0067 else
0068 return FB_BLANK_POWERDOWN;
0069 }
0070
0071 static int ams_delta_lcd_get_contrast(struct lcd_device *dev)
0072 {
0073 if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER))
0074 return 0;
0075
0076 return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST;
0077 }
0078
0079 static struct lcd_ops ams_delta_lcd_ops = {
0080 .get_power = ams_delta_lcd_get_power,
0081 .set_power = ams_delta_lcd_set_power,
0082 .get_contrast = ams_delta_lcd_get_contrast,
0083 .set_contrast = ams_delta_lcd_set_contrast,
0084 };
0085 #endif
0086
0087
0088
0089
0090 static int ams_delta_panel_enable(struct lcd_panel *panel)
0091 {
0092 gpiod_set_value(gpiod_ndisp, 1);
0093 gpiod_set_value(gpiod_vblen, 1);
0094 return 0;
0095 }
0096
0097 static void ams_delta_panel_disable(struct lcd_panel *panel)
0098 {
0099 gpiod_set_value(gpiod_vblen, 0);
0100 gpiod_set_value(gpiod_ndisp, 0);
0101 }
0102
0103 static struct lcd_panel ams_delta_panel = {
0104 .name = "ams-delta",
0105 .config = 0,
0106
0107 .bpp = 12,
0108 .data_lines = 16,
0109 .x_res = 480,
0110 .y_res = 320,
0111 .pixel_clock = 4687,
0112 .hsw = 3,
0113 .hfp = 1,
0114 .hbp = 1,
0115 .vsw = 1,
0116 .vfp = 0,
0117 .vbp = 0,
0118 .pcd = 0,
0119 .acb = 37,
0120
0121 .enable = ams_delta_panel_enable,
0122 .disable = ams_delta_panel_disable,
0123 };
0124
0125
0126
0127
0128 static int ams_delta_panel_probe(struct platform_device *pdev)
0129 {
0130 struct lcd_device *lcd_device = NULL;
0131
0132 gpiod_vblen = devm_gpiod_get(&pdev->dev, "vblen", GPIOD_OUT_LOW);
0133 if (IS_ERR(gpiod_vblen))
0134 return dev_err_probe(&pdev->dev, PTR_ERR(gpiod_vblen),
0135 "VBLEN GPIO request failed\n");
0136
0137 gpiod_ndisp = devm_gpiod_get(&pdev->dev, "ndisp", GPIOD_OUT_LOW);
0138 if (IS_ERR(gpiod_ndisp))
0139 return dev_err_probe(&pdev->dev, PTR_ERR(gpiod_ndisp),
0140 "NDISP GPIO request failed\n");
0141
0142 #ifdef CONFIG_LCD_CLASS_DEVICE
0143 lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
0144 &ams_delta_lcd_ops);
0145
0146 if (IS_ERR(lcd_device)) {
0147 int ret = PTR_ERR(lcd_device);
0148
0149 dev_err(&pdev->dev, "failed to register device\n");
0150 return ret;
0151 }
0152
0153 platform_set_drvdata(pdev, lcd_device);
0154 lcd_device->props.max_contrast = AMS_DELTA_MAX_CONTRAST;
0155 #endif
0156
0157 ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST);
0158 ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
0159
0160 omapfb_register_panel(&ams_delta_panel);
0161 return 0;
0162 }
0163
0164 static struct platform_driver ams_delta_panel_driver = {
0165 .probe = ams_delta_panel_probe,
0166 .driver = {
0167 .name = "lcd_ams_delta",
0168 },
0169 };
0170
0171 module_platform_driver(ams_delta_panel_driver);
0172
0173 MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
0174 MODULE_DESCRIPTION("LCD panel support for the Amstrad E3 (Delta) videophone");
0175 MODULE_LICENSE("GPL");