1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * LCD Lowlevel Control Abstraction
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 2003,2004 Hewlett-Packard Company
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds #ifndef _LINUX_LCD_H
101da177e4SLinus Torvalds #define _LINUX_LCD_H
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds #include <linux/device.h>
1328ee086dSRichard Purdie #include <linux/mutex.h>
141da177e4SLinus Torvalds #include <linux/notifier.h>
151da177e4SLinus Torvalds
1648ffe207SThomas Zimmermann #define LCD_POWER_ON (0)
1748ffe207SThomas Zimmermann #define LCD_POWER_REDUCED (1) // deprecated; don't use in new code
1848ffe207SThomas Zimmermann #define LCD_POWER_REDUCED_VSYNC_SUSPEND (2) // deprecated; don't use in new code
1948ffe207SThomas Zimmermann #define LCD_POWER_OFF (4)
2048ffe207SThomas Zimmermann
2128ee086dSRichard Purdie /* Notes on locking:
2228ee086dSRichard Purdie *
23599a52d1SRichard Purdie * lcd_device->ops_lock is an internal backlight lock protecting the ops
2428ee086dSRichard Purdie * field and no code outside the core should need to touch it.
2528ee086dSRichard Purdie *
2628ee086dSRichard Purdie * Access to set_power() is serialised by the update_lock mutex since
2728ee086dSRichard Purdie * most drivers seem to need this and historically get it wrong.
2828ee086dSRichard Purdie *
2928ee086dSRichard Purdie * Most drivers don't need locking on their get_power() method.
3028ee086dSRichard Purdie * If yours does, you need to implement it in the driver. You can use the
3128ee086dSRichard Purdie * update_lock mutex if appropriate.
3228ee086dSRichard Purdie *
3328ee086dSRichard Purdie * Any other use of the locks below is probably wrong.
3428ee086dSRichard Purdie */
3528ee086dSRichard Purdie
361da177e4SLinus Torvalds struct lcd_device;
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds struct lcd_properties {
39599a52d1SRichard Purdie /* The maximum value for contrast (read-only) */
40599a52d1SRichard Purdie int max_contrast;
41599a52d1SRichard Purdie };
42599a52d1SRichard Purdie
43599a52d1SRichard Purdie struct lcd_ops {
441da177e4SLinus Torvalds /* Get the LCD panel power status (0: full on, 1..3: controller
451da177e4SLinus Torvalds power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
461da177e4SLinus Torvalds int (*get_power)(struct lcd_device *);
471da177e4SLinus Torvalds /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
481da177e4SLinus Torvalds int (*set_power)(struct lcd_device *, int power);
491da177e4SLinus Torvalds /* Get the current contrast setting (0-max_contrast) */
501da177e4SLinus Torvalds int (*get_contrast)(struct lcd_device *);
511da177e4SLinus Torvalds /* Set LCD panel contrast */
521da177e4SLinus Torvalds int (*set_contrast)(struct lcd_device *, int contrast);
53*02e224d0SThomas Zimmermann
54*02e224d0SThomas Zimmermann /*
55*02e224d0SThomas Zimmermann * Set LCD panel mode (resolutions ...)
56*02e224d0SThomas Zimmermann */
57*02e224d0SThomas Zimmermann int (*set_mode)(struct lcd_device *lcd, u32 xres, u32 yres);
5843e1120dSThomas Zimmermann
5943e1120dSThomas Zimmermann /*
6043e1120dSThomas Zimmermann * Check if the LCD controls the given display device. This
6143e1120dSThomas Zimmermann * operation is optional and if not implemented it is assumed that
6243e1120dSThomas Zimmermann * the display is always the one controlled by the LCD.
6343e1120dSThomas Zimmermann *
6443e1120dSThomas Zimmermann * RETURNS:
6543e1120dSThomas Zimmermann *
6643e1120dSThomas Zimmermann * If display_dev is NULL or display_dev matches the device controlled by
6743e1120dSThomas Zimmermann * the LCD, return true. Otherwise return false.
6843e1120dSThomas Zimmermann */
6943e1120dSThomas Zimmermann bool (*controls_device)(struct lcd_device *lcd, struct device *display_device);
701da177e4SLinus Torvalds };
711da177e4SLinus Torvalds
721da177e4SLinus Torvalds struct lcd_device {
73599a52d1SRichard Purdie struct lcd_properties props;
74599a52d1SRichard Purdie /* This protects the 'ops' field. If 'ops' is NULL, the driver that
751da177e4SLinus Torvalds registered this device has been unloaded, and if class_get_devdata()
761da177e4SLinus Torvalds points to something in the body of that driver, it is also invalid. */
77599a52d1SRichard Purdie struct mutex ops_lock;
781da177e4SLinus Torvalds /* If this is NULL, the backing module is unloaded */
79a2e25c81SKrzysztof Kozlowski const struct lcd_ops *ops;
8028ee086dSRichard Purdie /* Serialise access to set_power method */
8128ee086dSRichard Purdie struct mutex update_lock;
821da177e4SLinus Torvalds /* The framebuffer notifier block */
831da177e4SLinus Torvalds struct notifier_block fb_notif;
84655bfd7aSRichard Purdie
85655bfd7aSRichard Purdie struct device dev;
861da177e4SLinus Torvalds };
871da177e4SLinus Torvalds
88ee378a5cSInKi Dae struct lcd_platform_data {
89ee378a5cSInKi Dae /* reset lcd panel device. */
90ee378a5cSInKi Dae int (*reset)(struct lcd_device *ld);
91ee378a5cSInKi Dae /* on or off to lcd panel. if 'enable' is 0 then
92ee378a5cSInKi Dae lcd power off and 1, lcd power on. */
93ee378a5cSInKi Dae int (*power_on)(struct lcd_device *ld, int enable);
94ee378a5cSInKi Dae
95ee378a5cSInKi Dae /* it indicates whether lcd panel was enabled
96ee378a5cSInKi Dae from bootloader or not. */
97ee378a5cSInKi Dae int lcd_enabled;
98ee378a5cSInKi Dae /* it means delay for stable time when it becomes low to high
99ee378a5cSInKi Dae or high to low that is dependent on whether reset gpio is
100ee378a5cSInKi Dae low active or high active. */
101ee378a5cSInKi Dae unsigned int reset_delay;
102ee378a5cSInKi Dae /* stable time needing to become lcd power on. */
103ee378a5cSInKi Dae unsigned int power_on_delay;
104ee378a5cSInKi Dae /* stable time needing to become lcd power off. */
105ee378a5cSInKi Dae unsigned int power_off_delay;
106ee378a5cSInKi Dae
107ee378a5cSInKi Dae /* it could be used for any purpose. */
108ee378a5cSInKi Dae void *pdata;
109ee378a5cSInKi Dae };
110ee378a5cSInKi Dae
lcd_set_power(struct lcd_device * ld,int power)11128ee086dSRichard Purdie static inline void lcd_set_power(struct lcd_device *ld, int power)
11228ee086dSRichard Purdie {
11328ee086dSRichard Purdie mutex_lock(&ld->update_lock);
114599a52d1SRichard Purdie if (ld->ops && ld->ops->set_power)
115599a52d1SRichard Purdie ld->ops->set_power(ld, power);
11628ee086dSRichard Purdie mutex_unlock(&ld->update_lock);
11728ee086dSRichard Purdie }
11828ee086dSRichard Purdie
1191da177e4SLinus Torvalds extern struct lcd_device *lcd_device_register(const char *name,
120a2e25c81SKrzysztof Kozlowski struct device *parent, void *devdata, const struct lcd_ops *ops);
1211d0c48e6SJingoo Han extern struct lcd_device *devm_lcd_device_register(struct device *dev,
1221d0c48e6SJingoo Han const char *name, struct device *parent,
123a2e25c81SKrzysztof Kozlowski void *devdata, const struct lcd_ops *ops);
1241da177e4SLinus Torvalds extern void lcd_device_unregister(struct lcd_device *ld);
1251d0c48e6SJingoo Han extern void devm_lcd_device_unregister(struct device *dev,
1261d0c48e6SJingoo Han struct lcd_device *ld);
1271da177e4SLinus Torvalds
128655bfd7aSRichard Purdie #define to_lcd_device(obj) container_of(obj, struct lcd_device, dev)
129655bfd7aSRichard Purdie
lcd_get_data(struct lcd_device * ld_dev)130655bfd7aSRichard Purdie static inline void * lcd_get_data(struct lcd_device *ld_dev)
131655bfd7aSRichard Purdie {
132655bfd7aSRichard Purdie return dev_get_drvdata(&ld_dev->dev);
133655bfd7aSRichard Purdie }
134655bfd7aSRichard Purdie
1351da177e4SLinus Torvalds
1361da177e4SLinus Torvalds #endif
137