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>
15faa312daSEric Miao #include <linux/fb.h>
161da177e4SLinus Torvalds
1728ee086dSRichard Purdie /* Notes on locking:
1828ee086dSRichard Purdie *
19599a52d1SRichard Purdie * lcd_device->ops_lock is an internal backlight lock protecting the ops
2028ee086dSRichard Purdie * field and no code outside the core should need to touch it.
2128ee086dSRichard Purdie *
2228ee086dSRichard Purdie * Access to set_power() is serialised by the update_lock mutex since
2328ee086dSRichard Purdie * most drivers seem to need this and historically get it wrong.
2428ee086dSRichard Purdie *
2528ee086dSRichard Purdie * Most drivers don't need locking on their get_power() method.
2628ee086dSRichard Purdie * If yours does, you need to implement it in the driver. You can use the
2728ee086dSRichard Purdie * update_lock mutex if appropriate.
2828ee086dSRichard Purdie *
2928ee086dSRichard Purdie * Any other use of the locks below is probably wrong.
3028ee086dSRichard Purdie */
3128ee086dSRichard Purdie
321da177e4SLinus Torvalds struct lcd_device;
331da177e4SLinus Torvalds struct fb_info;
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds struct lcd_properties {
36599a52d1SRichard Purdie /* The maximum value for contrast (read-only) */
37599a52d1SRichard Purdie int max_contrast;
38599a52d1SRichard Purdie };
39599a52d1SRichard Purdie
40599a52d1SRichard Purdie struct lcd_ops {
411da177e4SLinus Torvalds /* Get the LCD panel power status (0: full on, 1..3: controller
421da177e4SLinus Torvalds power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
431da177e4SLinus Torvalds int (*get_power)(struct lcd_device *);
441da177e4SLinus Torvalds /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
451da177e4SLinus Torvalds int (*set_power)(struct lcd_device *, int power);
461da177e4SLinus Torvalds /* Get the current contrast setting (0-max_contrast) */
471da177e4SLinus Torvalds int (*get_contrast)(struct lcd_device *);
481da177e4SLinus Torvalds /* Set LCD panel contrast */
491da177e4SLinus Torvalds int (*set_contrast)(struct lcd_device *, int contrast);
50faa312daSEric Miao /* Set LCD panel mode (resolutions ...) */
51faa312daSEric Miao int (*set_mode)(struct lcd_device *, struct fb_videomode *);
521da177e4SLinus Torvalds /* Check if given framebuffer device is the one LCD is bound to;
531da177e4SLinus Torvalds return 0 if not, !=0 if it is. If NULL, lcd always matches the fb. */
540c531360SBen Dooks int (*check_fb)(struct lcd_device *, struct fb_info *);
551da177e4SLinus Torvalds };
561da177e4SLinus Torvalds
571da177e4SLinus Torvalds struct lcd_device {
58599a52d1SRichard Purdie struct lcd_properties props;
59599a52d1SRichard Purdie /* This protects the 'ops' field. If 'ops' is NULL, the driver that
601da177e4SLinus Torvalds registered this device has been unloaded, and if class_get_devdata()
611da177e4SLinus Torvalds points to something in the body of that driver, it is also invalid. */
62599a52d1SRichard Purdie struct mutex ops_lock;
631da177e4SLinus Torvalds /* If this is NULL, the backing module is unloaded */
64599a52d1SRichard Purdie struct lcd_ops *ops;
6528ee086dSRichard Purdie /* Serialise access to set_power method */
6628ee086dSRichard Purdie struct mutex update_lock;
671da177e4SLinus Torvalds /* The framebuffer notifier block */
681da177e4SLinus Torvalds struct notifier_block fb_notif;
69655bfd7aSRichard Purdie
70655bfd7aSRichard Purdie struct device dev;
711da177e4SLinus Torvalds };
721da177e4SLinus Torvalds
73ee378a5cSInKi Dae struct lcd_platform_data {
74ee378a5cSInKi Dae /* reset lcd panel device. */
75ee378a5cSInKi Dae int (*reset)(struct lcd_device *ld);
76ee378a5cSInKi Dae /* on or off to lcd panel. if 'enable' is 0 then
77ee378a5cSInKi Dae lcd power off and 1, lcd power on. */
78ee378a5cSInKi Dae int (*power_on)(struct lcd_device *ld, int enable);
79ee378a5cSInKi Dae
80ee378a5cSInKi Dae /* it indicates whether lcd panel was enabled
81ee378a5cSInKi Dae from bootloader or not. */
82ee378a5cSInKi Dae int lcd_enabled;
83ee378a5cSInKi Dae /* it means delay for stable time when it becomes low to high
84ee378a5cSInKi Dae or high to low that is dependent on whether reset gpio is
85ee378a5cSInKi Dae low active or high active. */
86ee378a5cSInKi Dae unsigned int reset_delay;
87ee378a5cSInKi Dae /* stable time needing to become lcd power on. */
88ee378a5cSInKi Dae unsigned int power_on_delay;
89ee378a5cSInKi Dae /* stable time needing to become lcd power off. */
90ee378a5cSInKi Dae unsigned int power_off_delay;
91ee378a5cSInKi Dae
92ee378a5cSInKi Dae /* it could be used for any purpose. */
93ee378a5cSInKi Dae void *pdata;
94ee378a5cSInKi Dae };
95ee378a5cSInKi Dae
lcd_set_power(struct lcd_device * ld,int power)9628ee086dSRichard Purdie static inline void lcd_set_power(struct lcd_device *ld, int power)
9728ee086dSRichard Purdie {
9828ee086dSRichard Purdie mutex_lock(&ld->update_lock);
99599a52d1SRichard Purdie if (ld->ops && ld->ops->set_power)
100599a52d1SRichard Purdie ld->ops->set_power(ld, power);
10128ee086dSRichard Purdie mutex_unlock(&ld->update_lock);
10228ee086dSRichard Purdie }
10328ee086dSRichard Purdie
1041da177e4SLinus Torvalds extern struct lcd_device *lcd_device_register(const char *name,
105655bfd7aSRichard Purdie struct device *parent, void *devdata, struct lcd_ops *ops);
1061d0c48e6SJingoo Han extern struct lcd_device *devm_lcd_device_register(struct device *dev,
1071d0c48e6SJingoo Han const char *name, struct device *parent,
1081d0c48e6SJingoo Han void *devdata, struct lcd_ops *ops);
1091da177e4SLinus Torvalds extern void lcd_device_unregister(struct lcd_device *ld);
1101d0c48e6SJingoo Han extern void devm_lcd_device_unregister(struct device *dev,
1111d0c48e6SJingoo Han struct lcd_device *ld);
1121da177e4SLinus Torvalds
113655bfd7aSRichard Purdie #define to_lcd_device(obj) container_of(obj, struct lcd_device, dev)
114655bfd7aSRichard Purdie
lcd_get_data(struct lcd_device * ld_dev)115655bfd7aSRichard Purdie static inline void * lcd_get_data(struct lcd_device *ld_dev)
116655bfd7aSRichard Purdie {
117655bfd7aSRichard Purdie return dev_get_drvdata(&ld_dev->dev);
118655bfd7aSRichard Purdie }
119655bfd7aSRichard Purdie
1201da177e4SLinus Torvalds
1211da177e4SLinus Torvalds #endif
122