Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Based on drivers/video/omap/lcd_inn1510.c
0004  *
0005  * LCD panel support for the Amstrad E3 (Delta) videophone.
0006  *
0007  * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
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 /* LCD class device section */
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 /* omapfb panel section */
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 /* platform driver section */
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");