From 4b070582ff1308b4a25a86f6fb54a74900d724ca Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 9 Apr 2015 10:54:17 +0200 Subject: [PATCH 1/9] ipv4: add option to drop unicast encapsulated in L2 multicast In order to solve a problem with 802.11, the so-called hole-196 attack, add an option (sysctl) called "drop_unicast_in_l2_multicast" which, if enabled, causes the stack to drop IPv4 unicast packets encapsulated in link-layer multi- or broadcast frames. Such frames can (as an attack) be created by any member of the same wireless network and transmitted as valid encrypted frames since the symmetric key for broadcast frames is shared between all stations. Additionally, enabling this option provides compliance with a SHOULD clause of RFC 1122. Signed-off-by: Johannes Berg (cherry picked from commit fbe66ad7c46e98a3edaf426422c9030d1a3c8072) Change-Id: I41b292ec33901b58b49859bc6b144f29257d5cc5 --- Documentation/networking/ip-sysctl.txt | 7 +++++++ include/linux/inetdevice.h | 1 + net/ipv4/devinet.c | 2 ++ net/ipv4/ip_input.c | 27 +++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 890fce9b3683..4fa77537450e 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -978,6 +978,13 @@ disable_xfrm - BOOLEAN Disable IPSEC encryption on this interface, whatever the policy +drop_unicast_in_l2_multicast - BOOLEAN + Drop any unicast IP packets that are received in link-layer + multicast (or broadcast) frames. + This behavior (for multicast) is actually a SHOULD in RFC + 1122, but is disabled by default for compatibility reasons. + Default: off (0) + tag - INTEGER Allows you to write a number, which can be used as required. diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 5f8146695b7f..7e1d0666019c 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -38,6 +38,7 @@ enum IPV4_DEVCONF_ACCEPT_LOCAL, IPV4_DEVCONF_SRC_VMARK, IPV4_DEVCONF_PROXY_ARP_PVLAN, + IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, __IPV4_DEVCONF_MAX }; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 085d63fbfd2a..23124b7f4072 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1631,6 +1631,8 @@ static struct devinet_sysctl_table { "force_igmp_version"), DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES, "promote_secondaries"), + DEVINET_SYSCTL_FLUSHING_ENTRY(DROP_UNICAST_IN_L2_MULTICAST, + "drop_unicast_in_l2_multicast"), }, }; diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index c8f48efc5fd3..0d3fdfc007a2 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -358,9 +358,34 @@ static int ip_rcv_finish(struct sk_buff *skb) if (rt->rt_type == RTN_MULTICAST) { IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INMCAST, skb->len); - } else if (rt->rt_type == RTN_BROADCAST) + } else if (rt->rt_type == RTN_BROADCAST) { IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INBCAST, skb->len); + } else { + struct in_device *in_dev = __in_dev_get_rcu(skb->dev); + + /* RFC 1122 3.3.6: + * + * When a host sends a datagram to a link-layer broadcast + * address, the IP destination address MUST be a legal IP + * broadcast or IP multicast address. + * + * A host SHOULD silently discard a datagram that is received + * via a link-layer broadcast (see Section 2.4) but does not + * specify an IP multicast or broadcast destination address. + * + * This doesn't explicitly say L2 *broadcast*, but broadcast is + * in a way a form of multicast and the most common use case for + * this is 802.11 protecting against cross-station spoofing (the + * so-called "hole-196" attack) so do it for both. + */ + if (in_dev && + IN_DEV_ORCONF(in_dev, DROP_UNICAST_IN_L2_MULTICAST) && + (skb->pkt_type == PACKET_BROADCAST || + skb->pkt_type == PACKET_MULTICAST)) + goto drop; + } + return dst_input(skb); -- GitLab From 073aec8feb07929797008e04fc08c82961ee3d52 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 9 Apr 2015 10:54:17 +0200 Subject: [PATCH 2/9] ipv6: add option to drop unicast encapsulated in L2 multicast In order to solve a problem with 802.11, the so-called hole-196 attack, add an option (sysctl) called "drop_unicast_in_l2_multicast" which, if enabled, causes the stack to drop IPv6 unicast packets encapsulated in link-layer multi- or broadcast frames. Such frames can (as an attack) be created by any member of the same wireless network and transmitted as valid encrypted frames since the symmetric key for broadcast frames is shared between all stations. Signed-off-by: Johannes Berg (cherry picked from commit 076252090c946f21e001e186da7f24b8bf4bff99) Change-Id: I445621aadc1954e53dd21131091cc915fea1a6d0 --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/ipv6.h | 2 ++ net/ipv6/addrconf.c | 8 ++++++++ net/ipv6/ip6_input.c | 10 ++++++++++ 4 files changed, 26 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 4fa77537450e..6ad46bf55635 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1271,6 +1271,12 @@ force_tllao - BOOLEAN race condition where the sender deletes the cached link-layer address prior to receiving a response to a previous solicitation." +drop_unicast_in_l2_multicast - BOOLEAN + Drop any unicast IPv6 packets that are received in link-layer + multicast (or broadcast) frames. + + By default this is turned off. + icmp/*: ratelimit - INTEGER Limit the maximal rates for sending ICMPv6 packets. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 84b1447481b5..f77a16ee40cb 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -170,6 +170,7 @@ struct ipv6_devconf { __s32 mc_forwarding; #endif __s32 disable_ipv6; + __s32 drop_unicast_in_l2_multicast; __s32 accept_dad; __s32 force_tllao; void *sysctl; @@ -213,6 +214,7 @@ enum { DEVCONF_DISABLE_IPV6, DEVCONF_ACCEPT_DAD, DEVCONF_FORCE_TLLAO, + DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, DEVCONF_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5574fc23b6b4..623a40d2dd36 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3883,6 +3883,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6; array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; + array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast; } static inline size_t inet6_ifla6_size(void) @@ -4551,6 +4552,13 @@ static struct addrconf_sysctl_table .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "drop_unicast_in_l2_multicast", + .data = &ipv6_devconf.drop_unicast_in_l2_multicast, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { /* sentinel */ } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index e2a08ae54ca9..bd734502192c 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -111,6 +111,16 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ipv6_addr_loopback(&hdr->daddr)) goto err; + /* If enabled, drop unicast packets that were encapsulated in link-layer + * multicast or broadcast to protected against the so-called "hole-196" + * attack in 802.11 wireless. + */ + if (!ipv6_addr_is_multicast(&hdr->daddr) && + (skb->pkt_type == PACKET_BROADCAST || + skb->pkt_type == PACKET_MULTICAST) && + idev->cnf.drop_unicast_in_l2_multicast) + goto err; + skb->transport_header = skb->network_header + sizeof(*hdr); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); -- GitLab From 9154f0fef517ac0f93a1d874c8b81ba193124c11 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 9 Apr 2015 11:25:13 +0200 Subject: [PATCH 3/9] ipv4: add option to drop gratuitous ARP packets In certain 802.11 wireless deployments, there will be ARP proxies that use knowledge of the network to correctly answer requests. To prevent gratuitous ARP frames on the shared medium from being a problem, on such deployments wireless needs to drop them. Enable this by providing an option called "drop_gratuitous_arp". Signed-off-by: Johannes Berg (cherry picked from commit f442f2becfa71bcd18b07d65f7726430c6b47ebf) Change-Id: I4a0776749cd2b26570c9024310349f0c75108666 --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/inetdevice.h | 1 + net/ipv4/arp.c | 8 ++++++++ net/ipv4/devinet.c | 2 ++ 4 files changed, 17 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 6ad46bf55635..adee6fab4a17 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -985,6 +985,12 @@ drop_unicast_in_l2_multicast - BOOLEAN 1122, but is disabled by default for compatibility reasons. Default: off (0) +drop_gratuitous_arp - BOOLEAN + Drop all gratuitous ARP frames, for example if there's a known + good ARP proxy on the network and such frames need not be used + (or in the case of 802.11, must not be used to prevent attacks.) + Default: off (0) + tag - INTEGER Allows you to write a number, which can be used as required. diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 7e1d0666019c..d83d62f26ff0 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -39,6 +39,7 @@ enum IPV4_DEVCONF_SRC_VMARK, IPV4_DEVCONF_PROXY_ARP_PVLAN, IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, + IPV4_DEVCONF_DROP_GRATUITOUS_ARP, __IPV4_DEVCONF_MAX }; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index d8f852dbf660..4bae334b2390 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -847,6 +847,14 @@ static int arp_process(struct sk_buff *skb) if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) goto out; + /* + * For some 802.11 wireless deployments (and possibly other networks), + * there will be an ARP proxy and gratuitous ARP frames are attacks + * and thus should not be accepted. + */ + if (IN_DEV_CONF_GET(in_dev, DROP_GRATUITOUS_ARP) && sip == tip) + goto out; + /* * Special case: We must set Frame Relay source Q.922 address */ diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 23124b7f4072..7f870c47d236 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1624,6 +1624,8 @@ static struct devinet_sysctl_table { DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"), DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"), DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP_PVLAN, "proxy_arp_pvlan"), + DEVINET_SYSCTL_RW_ENTRY(DROP_GRATUITOUS_ARP, + "drop_gratuitous_arp"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), -- GitLab From 4356fea91270b243e02c4e853b94279bd4bd8502 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 4 Feb 2016 13:31:20 +0100 Subject: [PATCH 4/9] ipv6: add option to drop unsolicited neighbor advertisements In certain 802.11 wireless deployments, there will be NA proxies that use knowledge of the network to correctly answer requests. To prevent unsolicitd advertisements on the shared medium from being a problem, on such deployments wireless needs to drop them. Enable this by providing an option called "drop_unsolicited_na". Change-Id: I2567a9973e72165a8e546f3638b509fbd1c95298 Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 7 +++++++ include/linux/ipv6.h | 2 ++ net/ipv6/addrconf.c | 8 ++++++++ net/ipv6/ndisc.c | 9 +++++++++ 4 files changed, 26 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index adee6fab4a17..1eeeb6dfe644 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1283,6 +1283,13 @@ drop_unicast_in_l2_multicast - BOOLEAN By default this is turned off. +drop_unsolicited_na - BOOLEAN + Drop all unsolicited neighbor advertisements, for example if there's + a known good NA proxy on the network and such frames need not be used + (or in the case of 802.11, must not be used to prevent attacks.) + + By default this is turned off. + icmp/*: ratelimit - INTEGER Limit the maximal rates for sending ICMPv6 packets. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index f77a16ee40cb..ab95c440c13b 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -173,6 +173,7 @@ struct ipv6_devconf { __s32 drop_unicast_in_l2_multicast; __s32 accept_dad; __s32 force_tllao; + __s32 drop_unsolicited_na; void *sysctl; }; @@ -215,6 +216,7 @@ enum { DEVCONF_ACCEPT_DAD, DEVCONF_FORCE_TLLAO, DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, + DEVCONF_DROP_UNSOLICITED_NA, DEVCONF_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 623a40d2dd36..1fb46ee45f2f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3884,6 +3884,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast; + array[DEVCONF_DROP_UNSOLICITED_NA] = cnf->drop_unsolicited_na; } static inline size_t inet6_ifla6_size(void) @@ -4559,6 +4560,13 @@ static struct addrconf_sysctl_table .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "drop_unsolicited_na", + .data = &ipv6_devconf.drop_unsolicited_na, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { /* sentinel */ } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index d8878ed36120..66c8e6d1e62b 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -932,6 +932,7 @@ static void ndisc_recv_na(struct sk_buff *skb) offsetof(struct nd_msg, opt)); struct ndisc_options ndopts; struct net_device *dev = skb->dev; + struct inet6_dev *idev = __in6_dev_get(dev); struct inet6_ifaddr *ifp; struct neighbour *neigh; @@ -954,6 +955,14 @@ static void ndisc_recv_na(struct sk_buff *skb) return; } + /* For some 802.11 wireless deployments (and possibly other networks), + * there will be a NA proxy and unsolicitd packets are attacks + * and thus should not be accepted. + */ + if (!msg->icmph.icmp6_solicited && idev && + idev->cnf.drop_unsolicited_na) + return; + if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) { ND_PRINTK2(KERN_WARNING "ICMPv6 NS: invalid ND option\n"); -- GitLab From 1335f9452beaf155984bb9260b521acfbc1f52b5 Mon Sep 17 00:00:00 2001 From: html6405 Date: Thu, 23 Sep 2021 13:27:49 +0200 Subject: [PATCH 5/9] wacom.i2c: Introduce double click and move back event there, so that we can configure the short press event in the system settings. --- .../input/touchscreen/wacom/wacom_i2c_func.c | 19 +++++++++++++------ include/linux/wacom_i2c.h | 3 +++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/wacom/wacom_i2c_func.c b/drivers/input/touchscreen/wacom/wacom_i2c_func.c index 347b4bcc88b6..a7244bc6d1a3 100644 --- a/drivers/input/touchscreen/wacom/wacom_i2c_func.c +++ b/drivers/input/touchscreen/wacom/wacom_i2c_func.c @@ -837,6 +837,7 @@ static void handle_gestures(int x, int y, ktime_t end, struct wacom_i2c *wac_i2c int dx = x - wac_i2c->gesture_start_x; int dy = y - wac_i2c->gesture_start_y; int dt = ktime_to_ms(ktime_sub(end, wac_i2c->gesture_start_time)); + int dtb = ktime_to_ms(ktime_sub(wac_i2c->gesture_start_time, wac_i2c->gesture_old_end_time)); if (abs(dy) > abs(dx)) { if (abs(dy) > MIN_GEST_DIST) { @@ -850,18 +851,20 @@ static void handle_gestures(int x, int y, ktime_t end, struct wacom_i2c *wac_i2c return; } } - //********************************************************************new gesture*********************************** - if ((dt >= SHORT_PRESS_TIME) && (dt < LONG_PRESS_TIME)) { - printk(KERN_DEBUG "[E-PEN] short pressed!\n"); + if ((dt >= SHORT_PRESS_TIME) && (dt < SHORT_PRESS_DOUBLED) && (dtb <= BREAK_TIME) && (dtb > 0)) { + printk(KERN_DEBUG "[E-PEN] double short pressed, send back event!\n"); input_report_key(wac_i2c->input_dev, KEY_BACK, 1); input_report_key(wac_i2c->input_dev, KEY_BACK, 0); input_sync(wac_i2c->input_dev); - wac_i2c->gesture_key = KEY_PEN_SP; return; } - + else if ((dt >= SHORT_PRESS_DOUBLED) && (dt < LONG_PRESS_TIME)) + { + printk(KERN_DEBUG "[E-PEN] short pressed!\n"); + wac_i2c->gesture_key = KEY_PEN_SP; + } else if (dt >= LONG_PRESS_TIME) { wac_i2c->gesture_key = KEY_PEN_LP; return; @@ -880,6 +883,8 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c) u8 gain = 0; u8 height = 0; int aveStrength = 2; + ktime_t time; + #ifdef WACOM_USE_SOFTKEY static s16 softkey, pressed, keycode; #endif @@ -1053,7 +1058,9 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c) wac_i2c->gesture_start_time = ktime_get(); } else if (!stylus && wac_i2c->side_pressed) { printk(KERN_DEBUG "[E-PEN] side off\n"); - handle_gestures(x, y, ktime_get(), wac_i2c); + time = ktime_get(); + handle_gestures(x, y, time, wac_i2c); + wac_i2c->gesture_old_end_time = time; if (wac_i2c->gesture_key > -1 && (wac_i2c->enabled_gestures & (1 << (wac_i2c->gesture_key - 0x2f1)))) { diff --git a/include/linux/wacom_i2c.h b/include/linux/wacom_i2c.h index d68616aa9cf3..9054ed0b72bc 100644 --- a/include/linux/wacom_i2c.h +++ b/include/linux/wacom_i2c.h @@ -392,6 +392,8 @@ struct wacom_g5_platform_data { }; #define SHORT_PRESS_TIME 0 +#define SHORT_PRESS_DOUBLED 200 +#define BREAK_TIME 200 #define LONG_PRESS_TIME 1000 #define MIN_GEST_DIST 3000 @@ -470,6 +472,7 @@ struct wacom_i2c { int gesture_start_x; int gesture_start_y; ktime_t gesture_start_time; + ktime_t gesture_old_end_time; }; #endif /* _LINUX_WACOM_I2C_H */ -- GitLab From 8e693925b77267b836e3c88b66278d51e2f5502f Mon Sep 17 00:00:00 2001 From: html6405 Date: Mon, 27 Sep 2021 12:51:21 +0200 Subject: [PATCH 6/9] video: samsung: replace earlysuspend with fb notifier callbacks --- drivers/video/samsung/gd2evf.c | 10 +-- drivers/video/samsung/hx8369b.c | 23 ++--- drivers/video/samsung/lcdfreq.c | 61 +++++++++++--- drivers/video/samsung/nt35560.c | 10 +-- drivers/video/samsung/s3cfb.h | 14 +++- drivers/video/samsung/s3cfb_ea8061.c | 24 +++--- drivers/video/samsung/s3cfb_lms501xx.c | 32 +++---- drivers/video/samsung/s3cfb_main.c | 102 +++++++++++++++-------- drivers/video/samsung/s3cfb_nt71391.c | 23 +++-- drivers/video/samsung/s3cfb_s6d7aa0.c | 20 +++-- drivers/video/samsung/s3cfb_s6e39a0.c | 29 ++++--- drivers/video/samsung/s3cfb_s6e63m0.c | 32 +++---- drivers/video/samsung/s3cfb_s6e8aa0.c | 34 +++++--- drivers/video/samsung/s3cfb_s6e8aa0a.c | 20 ++--- drivers/video/samsung/s3cfb_s6e8ab0.c | 17 ++-- drivers/video/samsung/s3cfb_s6evr01.c | 21 +++-- drivers/video/samsung/s3cfb_s6evr02.c | 24 +++--- drivers/video/samsung/s5p-dsim.c | 30 +++---- drivers/video/samsung/s6d6aa1.c | 31 +++---- drivers/video/samsung/s6d6aa1_gd2.c | 39 +++++---- drivers/video/samsung/s6d6aa1_sf2.c | 25 +++--- drivers/video/samsung/s6dr171.c | 24 +++--- drivers/video/samsung/s6e88a0_mipi_lcd.c | 18 ++-- drivers/video/samsung/s6e8aa1.c | 4 +- 24 files changed, 405 insertions(+), 262 deletions(-) diff --git a/drivers/video/samsung/gd2evf.c b/drivers/video/samsung/gd2evf.c index a171c1936a4f..ca4a770027ca 100644 --- a/drivers/video/samsung/gd2evf.c +++ b/drivers/video/samsung/gd2evf.c @@ -413,7 +413,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #if defined(CONFIG_PM) #ifdef CONFIG_HAS_EARLYSUSPEND -void gd2evf_early_suspend(struct early_suspend *h) +void gd2evf_fb_suspend(struct early_suspend *h) { struct lcd_info *lcd = container_of(h, struct lcd_info , early_suspend); @@ -424,7 +424,7 @@ void gd2evf_early_suspend(struct early_suspend *h) return ; } -void gd2evf_late_resume(struct early_suspend *h) +void gd2evf_fb_resume(struct early_suspend *h) { struct lcd_info *lcd = container_of(h, struct lcd_info , early_suspend); @@ -504,10 +504,10 @@ static int gd2evf_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, lcd); #ifdef CONFIG_HAS_EARLYSUSPEND - lcd->early_suspend.suspend = gd2evf_early_suspend; - lcd->early_suspend.resume = NULL; /* gd2evf_late_resume; */ + lcd->early_suspend.suspend = gd2evf_fb_suspend; + lcd->early_suspend.resume = NULL; /* gd2evf_fb_resume; */ lcd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; - register_early_suspend(&lcd->early_suspend); + register_fb_suspend(&lcd->early_suspend); #endif return 0; diff --git a/drivers/video/samsung/hx8369b.c b/drivers/video/samsung/hx8369b.c index 1265110868e7..ae66d26f1b4a 100644 --- a/drivers/video/samsung/hx8369b.c +++ b/drivers/video/samsung/hx8369b.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" @@ -48,7 +48,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned int irq; unsigned int connected; @@ -222,8 +223,8 @@ static const unsigned char SEQ_SLEEP_IN[] = { 0x00, 0x00 }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); static int _hx8369b_write(struct lcd_info *lcd, const unsigned char *seq, int len) { @@ -463,7 +464,7 @@ static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void hx8369b_early_suspend(void) +void hx8369b_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -478,7 +479,7 @@ void hx8369b_early_suspend(void) return ; } -void hx8369b_late_resume(void) +void hx8369b_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -490,6 +491,8 @@ void hx8369b_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -536,8 +539,8 @@ static int hx8369b_probe(struct device *dev) dev_info(&lcd->ld->dev, "hx8369b lcd panel driver has been probed.\n"); - lcd_early_suspend = hx8369b_early_suspend; - lcd_late_resume = hx8369b_late_resume; + lcd_fb_suspend = hx8369b_fb_suspend; + lcd_fb_resume = hx8369b_fb_resume; return 0; diff --git a/drivers/video/samsung/lcdfreq.c b/drivers/video/samsung/lcdfreq.c index 0379115692ef..8de08a365b1e 100644 --- a/drivers/video/samsung/lcdfreq.c +++ b/drivers/video/samsung/lcdfreq.c @@ -14,6 +14,10 @@ #include #include #include +#ifdef CONFIG_FB +#include +#include +#endif #include #include @@ -80,7 +84,10 @@ struct lcdfreq_info { int blank; - struct early_suspend early_suspend; +#ifdef CONFIG_FB + struct notifier_block fb_notif; + bool fb_suspended; +#endif }; static inline struct lcdfreq_info *dev_get_lcdfreq(struct device *dev) @@ -393,10 +400,11 @@ static struct attribute_group lcdfreq_attr_group = { .attrs = lcdfreq_attributes, }; -static void lcdfreq_early_suspend(struct early_suspend *h) +#ifdef CONFIG_FB +static void lcdfreq_fb_suspend(struct lcdfreq_info *lcdfreq) { - struct lcdfreq_info *lcdfreq = - container_of(h, struct lcdfreq_info, early_suspend); + if (lcdfreq->fb_suspended) + return; dev_info(lcdfreq->dev, "%s\n", __func__); @@ -406,13 +414,14 @@ static void lcdfreq_early_suspend(struct early_suspend *h) atomic_set(&lcdfreq->usage, 0); mutex_unlock(&lcdfreq->lock); + lcdfreq->fb_suspended = true; return; } -static void lcdfreq_late_resume(struct early_suspend *h) +static void lcdfreq_fb_resume(struct lcdfreq_info *lcdfreq) { - struct lcdfreq_info *lcdfreq = - container_of(h, struct lcdfreq_info, early_suspend); + if (!lcdfreq->fb_suspended) + return; dev_info(lcdfreq->dev, "%s\n", __func__); @@ -420,9 +429,38 @@ static void lcdfreq_late_resume(struct early_suspend *h) lcdfreq->enable = true; mutex_unlock(&lcdfreq->lock); + lcdfreq->fb_suspended = false; return; } +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct lcdfreq_info *info = container_of(self, struct lcdfreq_info, fb_notif); + + if (evdata && evdata->data && info) { + if (event == FB_EVENT_BLANK) { + blank = evdata->data; + switch (*blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + lcdfreq_fb_resume(info); + break; + default: + case FB_BLANK_POWERDOWN: + lcdfreq_fb_suspend(info); + break; + } + } + } + + return 0; +} +#endif #if 0 static int lcdfreq_pm_notifier_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -578,10 +616,11 @@ static int lcdfreq_probe(struct platform_device *pdev) info->reboot_noti.notifier_call = lcdfreq_reboot_notify; register_reboot_notifier(&info->reboot_noti); - info->early_suspend.suspend = lcdfreq_early_suspend; - info->early_suspend.resume = lcdfreq_late_resume; - info->early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING + 1; - register_early_suspend(&info->early_suspend); +#ifdef CONFIG_FB + info->fb_suspended = false; + info->fb_notif.notifier_call = fb_notifier_callback; + fb_register_client(&info->fb_notif); +#endif info->ielcd_reg = ioremap(IELCD_REG_BASE, IELCD_MAP_SIZE); info->enable = true; diff --git a/drivers/video/samsung/nt35560.c b/drivers/video/samsung/nt35560.c index 97e2f7caba4a..b24873bdf8d6 100644 --- a/drivers/video/samsung/nt35560.c +++ b/drivers/video/samsung/nt35560.c @@ -460,7 +460,7 @@ static DEVICE_ATTR(lcd_type, 0664, lcdtype_show, NULL); #if defined(CONFIG_PM) #ifdef CONFIG_HAS_EARLYSUSPEND -void nt35560_early_suspend(struct early_suspend *h) +void nt35560_fb_suspend(struct early_suspend *h) { struct lcd_info *lcd = container_of(h, struct lcd_info , early_suspend); @@ -471,7 +471,7 @@ void nt35560_early_suspend(struct early_suspend *h) return ; } -void nt35560_late_resume(struct early_suspend *h) +void nt35560_fb_resume(struct early_suspend *h) { struct lcd_info *lcd = container_of(h, struct lcd_info , early_suspend); @@ -567,10 +567,10 @@ static int nt35560_probe(struct spi_device *spi) dev_set_drvdata(&spi->dev, lcd); #ifdef CONFIG_HAS_EARLYSUSPEND - lcd->early_suspend.suspend = nt35560_early_suspend; - lcd->early_suspend.resume = nt35560_late_resume; + lcd->early_suspend.suspend = nt35560_fb_suspend; + lcd->early_suspend.resume = nt35560_fb_resume; lcd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; - register_early_suspend(&lcd->early_suspend); + register_fb_suspend(&lcd->early_suspend); #endif dev_info(&lcd->ld->dev, "nt35560 panel driver has been probed.\n"); diff --git a/drivers/video/samsung/s3cfb.h b/drivers/video/samsung/s3cfb.h index 820de723ab89..7a08ad260849 100644 --- a/drivers/video/samsung/s3cfb.h +++ b/drivers/video/samsung/s3cfb.h @@ -17,8 +17,11 @@ #include #include #ifdef CONFIG_HAS_WAKELOCK +#ifdef CONFIG_FB +#include +#include +#endif #include -#include #endif #include #endif @@ -238,7 +241,10 @@ struct s3cfb_global { int timeline_max; unsigned int support_fence; #ifdef CONFIG_HAS_WAKELOCK - struct early_suspend early_suspend; +#ifdef CONFIG_FB + struct notifier_block fb_notif; + bool fb_suspended; +#endif struct wake_lock idle_lock; #endif #ifdef FEATURE_BUSFREQ_LOCK @@ -491,8 +497,8 @@ extern void s3cfb_set_lcd_info(struct s3cfb_global *ctrl); #ifdef CONFIG_FB_S5P_MIPI_DSIM extern int s3cfb_vsync_status_check(void); -extern void s5p_dsim_early_suspend(void); -extern void s5p_dsim_late_resume(void); +extern void s5p_dsim_fb_suspend(void); +extern void s5p_dsim_fb_resume(void); extern void set_dsim_hs_clk_toggle_count(u8 count); extern void set_dsim_lcd_enabled(u8 enable); #endif diff --git a/drivers/video/samsung/s3cfb_ea8061.c b/drivers/video/samsung/s3cfb_ea8061.c index d92907400448..f52a81871a40 100644 --- a/drivers/video/samsung/s3cfb_ea8061.c +++ b/drivers/video/samsung/s3cfb_ea8061.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" #include "ea8061_param.h" @@ -73,7 +73,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned char id[LDI_ID_LEN]; unsigned char **gamma_table; unsigned char **elvss_table; @@ -112,8 +113,8 @@ static unsigned int aid_candela_table[GAMMA_MAX] = { }; #endif -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); #if defined(GPIO_ERR_FG) static void err_fg_detection_work(struct work_struct *work) @@ -1029,7 +1030,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND static struct lcd_info *g_lcd; -void ea8061_early_suspend(void) +void ea8061_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -1052,7 +1053,7 @@ void ea8061_early_suspend(void) return ; } -void ea8061_late_resume(void) +void ea8061_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -1069,6 +1070,8 @@ void ea8061_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -1146,6 +1149,7 @@ static int ea8061_probe(struct device *dev) lcd->ldi_enable = 1; lcd->connected = 1; lcd->auto_brightness = 0; + lcd->fb_suspended = false; ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); if (ret < 0) @@ -1221,8 +1225,8 @@ static int ea8061_probe(struct device *dev) } #endif - lcd_early_suspend = ea8061_early_suspend; - lcd_late_resume = ea8061_late_resume; + lcd_fb_suspend = ea8061_fb_suspend; + lcd_fb_resume = ea8061_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_lms501xx.c b/drivers/video/samsung/s3cfb_lms501xx.c index 8bbc8b787ddf..24a5343211e1 100644 --- a/drivers/video/samsung/s3cfb_lms501xx.c +++ b/drivers/video/samsung/s3cfb_lms501xx.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" #include "lms501xx.h" @@ -64,7 +64,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned char id[LDI_ID_LEN]; @@ -90,8 +91,8 @@ static const unsigned int candela_table[GAMMA_MAX-1] = { 230, 240, MAX_BRIGHTNESS, MAX_GAMMA }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); struct LCD_BRIGHTNESS { int off; int deflt; @@ -874,7 +875,7 @@ static DEVICE_ATTR(auto_brightness, 0644, #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void lms501xx_early_suspend(void) +void lms501xx_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -904,7 +905,7 @@ void lms501xx_early_suspend(void) return ; } -void lms501xx_late_resume(void) +void lms501xx_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -925,18 +926,20 @@ void lms501xx_late_resume(void) #endif + lcd->fb_suspended = false; + return ; } #ifdef DDI_STATUS_REG_PREVENTESD static void lms501xx_reinitialize_lcd(void) { - lms501xx_early_suspend(); - s5p_dsim_early_suspend(); + lms501xx_fb_suspend(); + s5p_dsim_fb_suspend(); msleep(20); - s5p_dsim_late_resume(); + s5p_dsim_fb_resume(); msleep(20); - lms501xx_late_resume(); + lms501xx_fb_resume(); printk(KERN_INFO "%s, re-initialize LCD - Done\n", __func__); } #endif @@ -1006,6 +1009,7 @@ static int lms501xx_probe(struct device *dev) lcd->ldi_enable = 1; lcd->connected = 1; lcd->auto_brightness = 0; + lcd->fb_suspended = false; ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); if (ret < 0) @@ -1058,8 +1062,8 @@ static int lms501xx_probe(struct device *dev) schedule_delayed_work(&lcd->check_ddi, msecs_to_jiffies(20000)); } #endif - lcd_early_suspend = lms501xx_early_suspend; - lcd_late_resume = lms501xx_late_resume; + lcd_fb_suspend = lms501xx_fb_suspend; + lcd_fb_resume = lms501xx_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_main.c b/drivers/video/samsung/s3cfb_main.c index 35dc1d5add49..d285878271a2 100644 --- a/drivers/video/samsung/s3cfb_main.c +++ b/drivers/video/samsung/s3cfb_main.c @@ -47,7 +47,10 @@ #endif #ifdef CONFIG_HAS_WAKELOCK #include -#include +#ifdef CONFIG_FB +#include +#include +#endif #include #endif @@ -546,13 +549,15 @@ void s3cfb_lcd0_pmu_off(void) } #ifdef CONFIG_PM -#ifdef CONFIG_HAS_EARLYSUSPEND -void (*lcd_early_suspend)(void); -void (*lcd_late_resume)(void); +#ifdef CONFIG_FB +void (*lcd_fb_suspend)(void); +void (*lcd_fb_resume)(void); -void s3cfb_early_suspend(struct early_suspend *h) +void s3cfb_fb_suspend(struct s3cfb_global *info) { - struct s3cfb_global *info = container_of(h, struct s3cfb_global, early_suspend); + if (info->fb_suspended) + return; + struct s3c_platform_fb *pdata = to_fb_plat(info->dev); struct platform_device *pdev = to_platform_device(info->dev); struct s3cfb_global *fbdev[2]; @@ -562,13 +567,13 @@ void s3cfb_early_suspend(struct early_suspend *h) #ifdef CONFIG_FB_S5P_GD2EVF info->suspend = 1; - if (lcd_early_suspend && current_mipi_lcd) - lcd_early_suspend(); + if (lcd_fb_suspend && current_mipi_lcd) + lcd_fb_suspend(); else gd2evf_power_ext(0); #elif defined(CONFIG_FB_S5P_MIPI_DSIM) - if (lcd_early_suspend) - lcd_early_suspend(); + if (lcd_fb_suspend) + lcd_fb_suspend(); #endif for (i = 0; i < FIMD_MAX; i++) { @@ -618,9 +623,9 @@ void s3cfb_early_suspend(struct early_suspend *h) } #ifdef CONFIG_FB_S5P_GD2EVF if (current_mipi_lcd) - s5p_dsim_early_suspend(); + s5p_dsim_fb_suspend(); #elif defined(CONFIG_FB_S5P_MIPI_DSIM) - s5p_dsim_early_suspend(); + s5p_dsim_fb_suspend(); #endif #ifdef CONFIG_EXYNOS_DEV_PD /* disable the power domain */ @@ -638,12 +643,15 @@ void s3cfb_early_suspend(struct early_suspend *h) dev_info(info->dev, "-%s\n", __func__); + info->fb_suspended = true; return; } -void s3cfb_late_resume(struct early_suspend *h) +void s3cfb_fb_resume(struct s3cfb_global *info) { - struct s3cfb_global *info = container_of(h, struct s3cfb_global, early_suspend); + if (!info->fb_suspended) + return; + struct s3c_platform_fb *pdata = to_fb_plat(info->dev); struct fb_info *fb; struct s3cfb_window *win; @@ -662,9 +670,9 @@ void s3cfb_late_resume(struct early_suspend *h) #ifdef CONFIG_FB_S5P_GD2EVF if (current_mipi_lcd) - s5p_dsim_late_resume(); + s5p_dsim_fb_resume(); #elif defined(CONFIG_FB_S5P_MIPI_DSIM) - s5p_dsim_late_resume(); + s5p_dsim_fb_resume(); #endif for (i = 0; i < FIMD_MAX; i++) { @@ -748,14 +756,14 @@ void s3cfb_late_resume(struct early_suspend *h) } #ifdef CONFIG_FB_S5P_GD2EVF - if (lcd_late_resume && current_mipi_lcd) - lcd_late_resume(); + if (lcd_fb_resume && current_mipi_lcd) + lcd_fb_resume(); else gd2evf_power_ext(1); info->suspend = 0; #elif defined(CONFIG_FB_S5P_MIPI_DSIM) - if (lcd_late_resume) - lcd_late_resume(); + if (lcd_fb_resume) + lcd_fb_resume(); #endif #ifdef CONFIG_FB_S5P_TRACE_UNDERRUN @@ -764,11 +772,41 @@ void s3cfb_late_resume(struct early_suspend *h) #endif dev_info(info->dev, "-%s\n", __func__); + info->fb_suspended = false; return; } -#else /* else !CONFIG_HAS_EARLYSUSPEND */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct s3cfb_global *info = container_of(self, struct s3cfb_global, fb_notif); + + if (evdata && evdata->data && info) { + if (event == FB_EVENT_BLANK) { + blank = evdata->data; + switch (*blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + s3cfb_fb_resume(info); + break; + default: + case FB_BLANK_POWERDOWN: + s3cfb_fb_suspend(info); + break; + } + } + } + + return 0; +} +#endif + +#ifndef CONFIG_HAS_EARLYSUSPEND int s3cfb_suspend(struct platform_device *pdev, pm_message_t state) { struct s3c_platform_fb *pdata = to_fb_plat(&pdev->dev); @@ -905,7 +943,7 @@ static int s3cfb_disable(struct s3cfb_global *fbdev) dev_info(fbdev->dev, "+%s\n", __func__); - if (lcd_early_suspend && current_mipi_lcd) + if (lcd_fb_suspend && current_mipi_lcd) s6d6aa1_power_ext(0); else gd2evf_power_ext(0); @@ -961,7 +999,7 @@ static int s3cfb_enable(struct s3cfb_global *fbdev) #endif if (current_mipi_lcd) - s5p_dsim_late_resume(); + s5p_dsim_fb_resume(); mutex_lock(&fbdev->output_lock); @@ -1017,11 +1055,11 @@ static int s3cfb_enable(struct s3cfb_global *fbdev) mutex_unlock(&fbdev->output_lock); - if (lcd_late_resume && current_mipi_lcd) + if (lcd_fb_resume && current_mipi_lcd) s6d6aa1_power_ext(1); else { gd2evf_power_ext(1); - s5p_dsim_early_suspend(); + s5p_dsim_fb_suspend(); } #ifdef CONFIG_FB_S5P_TRACE_UNDERRUN @@ -1265,12 +1303,10 @@ static int s3cfb_probe(struct platform_device *pdev) #endif #ifdef CONFIG_HAS_WAKELOCK -#ifdef CONFIG_HAS_EARLYSUSPEND - fbdev[i]->early_suspend.suspend = s3cfb_early_suspend; - fbdev[i]->early_suspend.resume = s3cfb_late_resume; - fbdev[i]->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; - - register_early_suspend(&fbdev[i]->early_suspend); +#ifdef CONFIG_FB + fbdev[i]->fb_suspended = false; + fbdev[i]->fb_notif.notifier_call = fb_notifier_callback; + fb_register_client(&fbdev[i]->fb_notif); #endif #endif #if defined(CONFIG_FB_S5P_VSYNC_THREAD) @@ -1375,8 +1411,8 @@ static int s3cfb_remove(struct platform_device *pdev) fbdev[i] = fbfimd->fbdev[i]; #ifdef CONFIG_HAS_WAKELOCK -#ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&fbdev[i]->early_suspend); +#ifdef CONFIG_FB + fb_unregister_client(&fbdev[i]->fb_notif); #endif #endif free_irq(fbdev[i]->irq, fbdev[i]); diff --git a/drivers/video/samsung/s3cfb_nt71391.c b/drivers/video/samsung/s3cfb_nt71391.c index 4e329c0b0a47..3ecebd8a693b 100644 --- a/drivers/video/samsung/s3cfb_nt71391.c +++ b/drivers/video/samsung/s3cfb_nt71391.c @@ -21,8 +21,9 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif #include "s3cfb.h" @@ -41,6 +42,10 @@ struct lcd_info { #if defined(CONFIG_MACH_KONA) unsigned int connected; struct mutex lock; +#endif +#ifdef CONFIG_FB + struct notifier_block fb_notif; + bool fb_suspended; #endif struct lcd_device *ld; struct lcd_platform_data *lcd_pd; @@ -285,12 +290,12 @@ static struct lcd_ops nt71391_lcd_ops = { }; #ifdef CONFIG_HAS_EARLYSUSPEND -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); struct lcd_info *g_lcd; -void nt71391_early_suspend(void) +void nt71391_fb_suspend(void) { struct lcd_info *lcd = g_lcd; int err = 0; @@ -306,7 +311,7 @@ void nt71391_early_suspend(void) return ; } -void nt71391_late_resume(void) +void nt71391_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -318,6 +323,8 @@ void nt71391_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -355,8 +362,8 @@ static int __init nt71391_probe(struct device *dev) dev_info(dev, "lcd panel driver has been probed.\n"); #ifdef CONFIG_HAS_EARLYSUSPEND - lcd_early_suspend = nt71391_early_suspend; - lcd_late_resume = nt71391_late_resume; + lcd_fb_suspend = nt71391_fb_suspend; + lcd_fb_resume = nt71391_fb_resume; #endif ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); if (ret < 0) diff --git a/drivers/video/samsung/s3cfb_s6d7aa0.c b/drivers/video/samsung/s3cfb_s6d7aa0.c index fae246189dc2..ce09abf69b0e 100644 --- a/drivers/video/samsung/s3cfb_s6d7aa0.c +++ b/drivers/video/samsung/s3cfb_s6d7aa0.c @@ -19,10 +19,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" #include "s6d7aa0_param.h" @@ -52,8 +52,8 @@ struct lcd_info { }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); static int s6d7aa0_power(struct lcd_info *lcd, int power); static int _s6d7aa0_write(struct lcd_info *lcd, const unsigned char *seq, int len) @@ -406,7 +406,7 @@ static DEVICE_ATTR(window_type, 0444, window_type_show, NULL); #ifdef CONFIG_HAS_EARLYSUSPEND static struct lcd_info *g_lcd; -void s6d7aa0_early_suspend(void) +void s6d7aa0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -420,7 +420,7 @@ void s6d7aa0_early_suspend(void) return ; } -void s6d7aa0_late_resume(void) +void s6d7aa0_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -431,6 +431,8 @@ void s6d7aa0_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -513,8 +515,8 @@ static int s6d7aa0_probe(struct device *dev) pr_err("failed to reqeust irq. %d\n", lcd->err_fg_irq); } - lcd_early_suspend = s6d7aa0_early_suspend; - lcd_late_resume = s6d7aa0_late_resume; + lcd_fb_suspend = s6d7aa0_fb_suspend; + lcd_fb_resume = s6d7aa0_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_s6e39a0.c b/drivers/video/samsung/s3cfb_s6e39a0.c index a07e45582e0d..7265fe07b625 100644 --- a/drivers/video/samsung/s3cfb_s6e39a0.c +++ b/drivers/video/samsung/s3cfb_s6e39a0.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" @@ -89,7 +89,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned int lcd_id; @@ -110,8 +111,8 @@ struct lcd_info { struct dsim_global *dsim; }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); static int s6e39a0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { @@ -869,7 +870,7 @@ static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, power_reduce_store); #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e39a0_early_suspend(void) +void s6e39a0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -880,7 +881,7 @@ void s6e39a0_early_suspend(void) return ; } -void s6e39a0_late_resume(void) +void s6e39a0_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -888,6 +889,8 @@ void s6e39a0_late_resume(void) s6e39a0_power(lcd, FB_BLANK_UNBLANK); dev_info(&lcd->ld->dev, "-%s\n", __func__); + lcd->fb_suspended = false; + return ; } #endif @@ -1003,10 +1006,10 @@ static int s6e39a0_probe(struct device *dev) #if 0 #ifdef CONFIG_HAS_EARLYSUSPEND - lcd->early_suspend.suspend = s6e39a0_early_suspend; - lcd->early_suspend.resume = s6e39a0_late_resume; + lcd->early_suspend.suspend = s6e39a0_fb_suspend; + lcd->early_suspend.resume = s6e39a0_fb_resume; lcd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2; - register_early_suspend(&lcd->early_suspend); + register_fb_suspend(&lcd->early_suspend); #endif #endif @@ -1037,8 +1040,8 @@ static int s6e39a0_probe(struct device *dev) s6e39a0_adb_brightness_update(lcd, lcd->bd->props.brightness, 1); #endif - lcd_early_suspend = s6e39a0_early_suspend; - lcd_late_resume = s6e39a0_late_resume; + lcd_fb_suspend = s6e39a0_fb_suspend; + lcd_fb_resume = s6e39a0_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_s6e63m0.c b/drivers/video/samsung/s3cfb_s6e63m0.c index 95b1501bd198..e6acbacc1c45 100644 --- a/drivers/video/samsung/s3cfb_s6e63m0.c +++ b/drivers/video/samsung/s3cfb_s6e63m0.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" #include "s6e63m0_gamma_l.h" @@ -98,7 +98,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned char id[LDI_ID_LEN]; @@ -127,8 +128,8 @@ static const unsigned int candela_table[GAMMA_MAX] = { 230, 240, 250, MAX_GAMMA }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); static int s6e63m0_power(struct lcd_info *lcd, int power); static int s6e63m0_read(struct lcd_info *lcd, const u8 addr, @@ -138,13 +139,13 @@ static int s6e63m0_read(struct lcd_info *lcd, const u8 addr, static void esd_reset_lcd(struct lcd_info *lcd) { dev_info(&lcd->ld->dev, "++%s\n", __func__); - if (lcd_early_suspend) - lcd_early_suspend(); + if (lcd_fb_suspend) + lcd_fb_suspend(); lcd->dsim->ops->suspend(); lcd->dsim->ops->resume(); - if (lcd_late_resume) - lcd_late_resume(); + if (lcd_fb_resume) + lcd_fb_resume(); dev_info(&lcd->ld->dev, "--%s\n", __func__); } @@ -825,7 +826,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e63m0_early_suspend(void) +void s6e63m0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; set_dsim_lcd_enabled(0); @@ -845,7 +846,7 @@ void s6e63m0_early_suspend(void) return ; } -void s6e63m0_late_resume(void) +void s6e63m0_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -862,6 +863,8 @@ void s6e63m0_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -989,6 +992,7 @@ static int s6e63m0_probe(struct device *dev) lcd->ldi_enable = 1; lcd->connected = 1; lcd->auto_brightness = 0; + lcd->fb_suspended = false; ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); if (ret < 0) @@ -1066,8 +1070,8 @@ static int s6e63m0_probe(struct device *dev) } #endif - lcd_early_suspend = s6e63m0_early_suspend; - lcd_late_resume = s6e63m0_late_resume; + lcd_fb_suspend = s6e63m0_fb_suspend; + lcd_fb_resume = s6e63m0_fb_resume; dev_info(&lcd->ld->dev, "s6e63m0 lcd panel driver has been probed.\n"); diff --git a/drivers/video/samsung/s3cfb_s6e8aa0.c b/drivers/video/samsung/s3cfb_s6e8aa0.c index 52deb818e685..5b930c511fa9 100644 --- a/drivers/video/samsung/s3cfb_s6e8aa0.c +++ b/drivers/video/samsung/s3cfb_s6e8aa0.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" #include "s6e8aa0_gamma_l.h" @@ -108,7 +108,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned char id[LDI_ID_LEN]; @@ -189,8 +190,8 @@ static unsigned int elvss_offset_table[ELVSS_STATUS_MAX] = { }; #endif -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); #if defined(GPIO_OLED_DET) static void oled_detection_work(struct work_struct *work) @@ -1280,14 +1281,17 @@ static ssize_t auto_brightness_store(struct device *dev, static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_store); -#ifdef CONFIG_HAS_EARLYSUSPEND +#ifdef CONFIG_FB struct lcd_info *g_lcd; -void s6e8ax0_early_suspend(void) +void s6e8ax0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; int err = 0; + if (lcd->fb_suspended) + return; + set_dsim_lcd_enabled(0); dev_info(&lcd->ld->dev, "+%s\n", __func__); @@ -1304,13 +1308,18 @@ void s6e8ax0_early_suspend(void) s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); dev_info(&lcd->ld->dev, "-%s\n", __func__); + lcd->fb_suspended = true; + return ; } -void s6e8ax0_late_resume(void) +void s6e8ax0_fb_resume(void) { struct lcd_info *lcd = g_lcd; + if (!lcd->fb_suspended) + return; + dev_info(&lcd->ld->dev, "+%s\n", __func__); s6e8ax0_power(lcd, FB_BLANK_UNBLANK); #if defined(GPIO_OLED_DET) @@ -1322,6 +1331,8 @@ void s6e8ax0_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -1452,6 +1463,7 @@ static int s6e8ax0_probe(struct device *dev) lcd->ldi_enable = 1; lcd->connected = 1; lcd->auto_brightness = 0; + lcd->fb_suspended = false; ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); if (ret < 0) @@ -1541,8 +1553,8 @@ static int s6e8ax0_probe(struct device *dev) } #endif - lcd_early_suspend = s6e8ax0_early_suspend; - lcd_late_resume = s6e8ax0_late_resume; + lcd_fb_suspend = s6e8ax0_fb_suspend; + lcd_fb_resume = s6e8ax0_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_s6e8aa0a.c b/drivers/video/samsung/s3cfb_s6e8aa0a.c index f07a74343c73..5318923bbfea 100644 --- a/drivers/video/samsung/s3cfb_s6e8aa0a.c +++ b/drivers/video/samsung/s3cfb_s6e8aa0a.c @@ -216,8 +216,8 @@ static unsigned int elvss_offset_table[ELVSS_STATUS_MAX] = { static void s3cfb_reinitialize_lcd(void); static int s6e8ax0_read_ddi_status_reg(struct lcd_info *lcd, u8 *buf); #endif -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); #ifdef DDI_STATUS_REG_PREVENTESD static void check_ddi_work(struct work_struct *work) { @@ -1405,7 +1405,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e8ax0_early_suspend(void) +void s6e8ax0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -1435,7 +1435,7 @@ void s6e8ax0_early_suspend(void) return ; } -void s6e8ax0_late_resume(void) +void s6e8ax0_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -1459,13 +1459,13 @@ void s6e8ax0_late_resume(void) #ifdef DDI_STATUS_REG_PREVENTESD static void s3cfb_reinitialize_lcd(void) { - s6e8ax0_early_suspend(); - s5p_dsim_early_suspend(); + s6e8ax0_fb_suspend(); + s5p_dsim_fb_suspend(); msleep(20); - s5p_dsim_late_resume(); + s5p_dsim_fb_resume(); msleep(20); - s6e8ax0_late_resume(); + s6e8ax0_fb_resume(); printk(KERN_INFO "%s, re-initialize LCD - Done\n", __func__); } #endif @@ -1693,8 +1693,8 @@ static int s6e8ax0_probe(struct device *dev) schedule_delayed_work(&lcd->check_ddi, msecs_to_jiffies(20000)); } #endif - lcd_early_suspend = s6e8ax0_early_suspend; - lcd_late_resume = s6e8ax0_late_resume; + lcd_fb_suspend = s6e8ax0_fb_suspend; + lcd_fb_resume = s6e8ax0_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_s6e8ab0.c b/drivers/video/samsung/s3cfb_s6e8ab0.c index 76a98d9035a9..2bb5cff83259 100644 --- a/drivers/video/samsung/s3cfb_s6e8ab0.c +++ b/drivers/video/samsung/s3cfb_s6e8ab0.c @@ -87,7 +87,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned char id[LDI_ID_LEN]; @@ -105,8 +106,8 @@ struct lcd_info { struct dsim_global *dsim; }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { @@ -653,7 +654,7 @@ static DEVICE_ATTR(gamma_table, 0444, gamma_table_show, NULL); #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e8ax0_early_suspend(void) +void s6e8ax0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -666,7 +667,7 @@ void s6e8ax0_early_suspend(void) return ; } -void s6e8ax0_late_resume(void) +void s6e8ax0_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -676,6 +677,8 @@ void s6e8ax0_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -830,8 +833,8 @@ static int s6e8ax0_probe(struct device *dev) update_brightness(lcd, 1); #endif - lcd_early_suspend = s6e8ax0_early_suspend; - lcd_late_resume = s6e8ax0_late_resume; + lcd_fb_suspend = s6e8ax0_fb_suspend; + lcd_fb_resume = s6e8ax0_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_s6evr01.c b/drivers/video/samsung/s3cfb_s6evr01.c index 7a59cf30913b..631b5d58fe86 100644 --- a/drivers/video/samsung/s3cfb_s6evr01.c +++ b/drivers/video/samsung/s3cfb_s6evr01.c @@ -29,10 +29,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" #include "s6evr01_param.h" @@ -118,8 +118,8 @@ static unsigned int aid_candela_table[GAMMA_MAX] = { }; #endif -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); #if defined(GPIO_ERR_FG) static void err_fg_detection_work(struct work_struct *work) @@ -1042,7 +1042,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND static struct lcd_info *g_lcd; -void s6evr01_early_suspend(void) +void s6evr01_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -1073,7 +1073,7 @@ void s6evr01_early_suspend(void) return ; } -void s6evr01_late_resume(void) +void s6evr01_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -1097,6 +1097,8 @@ void s6evr01_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -1172,6 +1174,7 @@ static int s6evr01_probe(struct device *dev) lcd->ldi_enable = 1; lcd->connected = 1; lcd->auto_brightness = 0; + lcd->fb_suspended = false; ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); if (ret < 0) @@ -1263,8 +1266,8 @@ static int s6evr01_probe(struct device *dev) } #endif - lcd_early_suspend = s6evr01_early_suspend; - lcd_late_resume = s6evr01_late_resume; + lcd_fb_suspend = s6evr01_fb_suspend; + lcd_fb_resume = s6evr01_fb_resume; return 0; diff --git a/drivers/video/samsung/s3cfb_s6evr02.c b/drivers/video/samsung/s3cfb_s6evr02.c index f0e911845a7e..423c0479437e 100644 --- a/drivers/video/samsung/s3cfb_s6evr02.c +++ b/drivers/video/samsung/s3cfb_s6evr02.c @@ -29,10 +29,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" #include "s6evr02_param.h" @@ -76,7 +76,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned char id[LDI_ID_LEN]; unsigned char **gamma_table; unsigned char **elvss_table; @@ -118,8 +119,8 @@ static unsigned int aid_candela_table[GAMMA_MAX] = { }; #endif -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); #if defined(GPIO_ERR_FG) static void err_fg_detection_work(struct work_struct *work) @@ -1068,7 +1069,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND static struct lcd_info *g_lcd; -void s6evr02_early_suspend(void) +void s6evr02_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -1099,7 +1100,7 @@ void s6evr02_early_suspend(void) return ; } -void s6evr02_late_resume(void) +void s6evr02_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -1123,6 +1124,8 @@ void s6evr02_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -1198,6 +1201,7 @@ static int s6evr02_probe(struct device *dev) lcd->ldi_enable = 1; lcd->connected = 1; lcd->auto_brightness = 0; + lcd->fb_suspended = false; ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); if (ret < 0) @@ -1289,8 +1293,8 @@ static int s6evr02_probe(struct device *dev) } #endif - lcd_early_suspend = s6evr02_early_suspend; - lcd_late_resume = s6evr02_late_resume; + lcd_fb_suspend = s6evr02_fb_suspend; + lcd_fb_resume = s6evr02_fb_resume; return 0; diff --git a/drivers/video/samsung/s5p-dsim.c b/drivers/video/samsung/s5p-dsim.c index 61cefab7206b..30f8c8165d29 100644 --- a/drivers/video/samsung/s5p-dsim.c +++ b/drivers/video/samsung/s5p-dsim.c @@ -45,9 +45,9 @@ #include "s5p_dsim_lowlevel.h" #include "s3cfb.h" -#ifdef CONFIG_HAS_WAKELOCK -#include -#include +#ifdef CONFIG_FB +#include +#include #include #endif @@ -793,7 +793,7 @@ static void s5p_dsim_set_clock(struct dsim_global *dsim, } } -static int s5p_dsim_late_resume_init_dsim(struct dsim_global *dsim) +static int s5p_dsim_fb_resume_init_dsim(struct dsim_global *dsim) { unsigned int dsim_base = dsim->reg_base; @@ -1180,8 +1180,8 @@ static int s5p_dsim_fifo_clear(struct dsim_global *dsim) } #endif -#ifdef CONFIG_HAS_EARLYSUSPEND -void s5p_dsim_early_suspend(void) +#ifdef CONFIG_FB +void s5p_dsim_fb_suspend(void) { u32 int_stat = 0; pm_message_t state; @@ -1234,7 +1234,7 @@ void s5p_dsim_early_suspend(void) return; } -void s5p_dsim_late_resume(void) +void s5p_dsim_fb_resume(void) { struct dsim_global *dsim = g_dsim; @@ -1251,7 +1251,7 @@ void s5p_dsim_late_resume(void) dsim->mipi_ddi_pd->lcd_power_on(dsim->dev, 1); usleep_range(25000, 25000); - s5p_dsim_late_resume_init_dsim(dsim); + s5p_dsim_fb_resume_init_dsim(dsim); s5p_dsim_init_link(dsim); usleep_range(10000, 10000); @@ -1424,8 +1424,8 @@ static struct dsim_ops s5p_dsim_ops = { .cmd_write = s5p_dsim_wr_data, .cmd_read = s5p_dsim_rd_data, .cmd_dcs_read = s5p_dsim_dcs_rd_data, - .suspend = s5p_dsim_early_suspend, - .resume = s5p_dsim_late_resume, + .suspend = s5p_dsim_fb_suspend, + .resume = s5p_dsim_fb_resume, }; static int s5p_dsim_probe(struct platform_device *pdev) @@ -1593,11 +1593,11 @@ static int s5p_dsim_probe(struct platform_device *pdev) #if 0 #ifdef CONFIG_HAS_WAKELOCK -#ifdef CONFIG_HAS_EARLYSUSPEND - dsim->early_suspend.suspend = s5p_dsim_early_suspend; - dsim->early_suspend.resume = s5p_dsim_late_resume; +#ifdef CONFIG_FB + dsim->early_suspend.suspend = s5p_dsim_fb_suspend; + dsim->early_suspend.resume = s5p_dsim_fb_resume; dsim->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; - register_early_suspend(&dsim->early_suspend); + register_fb_suspend(&dsim->early_suspend); #endif #endif #endif @@ -1626,7 +1626,7 @@ static int s5p_dsim_remove(struct platform_device *pdev) static struct platform_driver s5p_dsim_driver = { .probe = s5p_dsim_probe, .remove = s5p_dsim_remove, -#ifndef CONFIG_HAS_EARLYSUSPEND +#ifndef CONFIG_FB .suspend = s5p_dsim_suspend, .resume = s5p_dsim_resume, #endif diff --git a/drivers/video/samsung/s6d6aa1.c b/drivers/video/samsung/s6d6aa1.c index b2b8334b73ae..b981788c06da 100644 --- a/drivers/video/samsung/s6d6aa1.c +++ b/drivers/video/samsung/s6d6aa1.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" @@ -53,7 +53,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned int irq; unsigned int connected; @@ -215,20 +216,20 @@ static unsigned char TRANS_BRIGHTNESS[] = { 249, 250, 251, 252, 253, 254, 255, 255, }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); #if defined(GPIO_VGH_DET) static void esd_reset_lcd(struct lcd_info *lcd) { dev_info(&lcd->ld->dev, "++%s\n", __func__); - if (lcd_early_suspend) - lcd_early_suspend(); + if (lcd_fb_suspend) + lcd_fb_suspend(); lcd->dsim->ops->suspend(); lcd->dsim->ops->resume(); - if (lcd_late_resume) - lcd_late_resume(); + if (lcd_fb_resume) + lcd_fb_resume(); dev_info(&lcd->ld->dev, "--%s\n", __func__); } @@ -600,7 +601,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6d6aa1_early_suspend(void) +void s6d6aa1_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -623,7 +624,7 @@ void s6d6aa1_early_suspend(void) return ; } -void s6d6aa1_late_resume(void) +void s6d6aa1_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -639,6 +640,8 @@ void s6d6aa1_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -711,8 +714,8 @@ static int s6d6aa1_probe(struct device *dev) } #endif - lcd_early_suspend = s6d6aa1_early_suspend; - lcd_late_resume = s6d6aa1_late_resume; + lcd_fb_suspend = s6d6aa1_fb_suspend; + lcd_fb_resume = s6d6aa1_fb_resume; return 0; diff --git a/drivers/video/samsung/s6d6aa1_gd2.c b/drivers/video/samsung/s6d6aa1_gd2.c index 3db707262bea..c45e019cc0bd 100644 --- a/drivers/video/samsung/s6d6aa1_gd2.c +++ b/drivers/video/samsung/s6d6aa1_gd2.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" @@ -56,7 +56,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned int irq; unsigned int connected; @@ -197,23 +198,23 @@ static unsigned char TRANS_BRIGHTNESS[] = { struct lcd_info *g_lcd; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); -void s6d6aa1_early_suspend(void); -void s6d6aa1_late_resume(void); +void s6d6aa1_fb_suspend(void); +void s6d6aa1_fb_resume(void); #if defined(GPIO_VGH_DET) static void esd_reset_lcd(struct lcd_info *lcd) { dev_info(&lcd->ld->dev, "++%s\n", __func__); - if (lcd_early_suspend) - lcd_early_suspend(); + if (lcd_fb_suspend) + lcd_fb_suspend(); lcd->dsim->ops->suspend(); lcd->dsim->ops->resume(); - if (lcd_late_resume) - lcd_late_resume(); + if (lcd_fb_resume) + lcd_fb_resume(); dev_info(&lcd->ld->dev, "--%s\n", __func__); } @@ -475,9 +476,9 @@ int s6d6aa1_power_ext(int onoff) lcd->evf_switching = 1; if (onoff) - s6d6aa1_late_resume(); + s6d6aa1_fb_resume(); else - s6d6aa1_early_suspend(); + s6d6aa1_fb_suspend(); lcd->evf_switching = 0; @@ -635,7 +636,7 @@ static ssize_t outdoor_store(struct device *dev, static DEVICE_ATTR(outdoor, 0644, outdoor_show, outdoor_store); #ifdef CONFIG_HAS_EARLYSUSPEND -void s6d6aa1_early_suspend(void) +void s6d6aa1_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -658,7 +659,7 @@ void s6d6aa1_early_suspend(void) return ; } -void s6d6aa1_late_resume(void) +void s6d6aa1_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -674,6 +675,8 @@ void s6d6aa1_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -752,8 +755,8 @@ static int s6d6aa1_probe(struct device *dev) } #endif - lcd_early_suspend = s6d6aa1_early_suspend; - lcd_late_resume = s6d6aa1_late_resume; + lcd_fb_suspend = s6d6aa1_fb_suspend; + lcd_fb_resume = s6d6aa1_fb_resume; return 0; diff --git a/drivers/video/samsung/s6d6aa1_sf2.c b/drivers/video/samsung/s6d6aa1_sf2.c index 7fb5170473f7..0a0007cb0556 100644 --- a/drivers/video/samsung/s6d6aa1_sf2.c +++ b/drivers/video/samsung/s6d6aa1_sf2.c @@ -63,7 +63,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; #ifndef CONFIG_SAMSUNG_PRODUCT_SHIP unsigned char id[LDI_ID_LEN]; @@ -228,20 +229,20 @@ static unsigned char TRANS_BRIGHTNESS[] = { 249, 250, 251, 252, 253, 254, 255, 255, }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); #if defined(GPIO_OLED_DET) static void esd_reset_lcd(struct lcd_info *lcd) { dev_info(&lcd->ld->dev, "++%s\n", __func__); - if (lcd_early_suspend) - lcd_early_suspend(); + if (lcd_fb_suspend) + lcd_fb_suspend(); lcd->dsim->ops->suspend(); lcd->dsim->ops->resume(); - if (lcd_late_resume) - lcd_late_resume(); + if (lcd_fb_resume) + lcd_fb_resume(); dev_info(&lcd->ld->dev, "--%s\n", __func__); } @@ -648,7 +649,7 @@ static void s6d6aa1_read_id(struct lcd_info *lcd, u8 *buf) #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6d6aa1_early_suspend(void) +void s6d6aa1_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -671,7 +672,7 @@ void s6d6aa1_early_suspend(void) return ; } -void s6d6aa1_late_resume(void) +void s6d6aa1_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -694,6 +695,8 @@ Turning OFF/ON the LCD voltages as requested by H/W Team request for factory tes set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -770,8 +773,8 @@ static int s6d6aa1_probe(struct device *dev) } #endif - lcd_early_suspend = s6d6aa1_early_suspend; - lcd_late_resume = s6d6aa1_late_resume; + lcd_fb_suspend = s6d6aa1_fb_suspend; + lcd_fb_resume = s6d6aa1_fb_resume; return 0; diff --git a/drivers/video/samsung/s6dr171.c b/drivers/video/samsung/s6dr171.c index 868c006ab601..d17d9fa58bbd 100644 --- a/drivers/video/samsung/s6dr171.c +++ b/drivers/video/samsung/s6dr171.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" @@ -66,7 +66,8 @@ struct lcd_info { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; - struct early_suspend early_suspend; + struct notifier_block fb_notif; + bool fb_suspended; unsigned char id[LDI_ID_LEN]; @@ -79,8 +80,8 @@ struct lcd_info { struct dsim_global *dsim; }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); static int s6dr171_write(struct lcd_info *lcd, const unsigned char *seq, int len) { @@ -392,7 +393,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6dr171_early_suspend(void) +void s6dr171_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -405,7 +406,7 @@ void s6dr171_early_suspend(void) return ; } -void s6dr171_late_resume(void) +void s6dr171_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -415,6 +416,8 @@ void s6dr171_late_resume(void) set_dsim_lcd_enabled(1); + lcd->fb_suspended = false; + return ; } #endif @@ -483,6 +486,7 @@ static int s6dr171_probe(struct device *dev) lcd->ldi_enable = 1; lcd->connected = 1; lcd->auto_brightness = 0; + lcd->fb_suspended = false; ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); if (ret < 0) @@ -513,8 +517,8 @@ static int s6dr171_probe(struct device *dev) /*return -EPERM;*/ } - lcd_early_suspend = s6dr171_early_suspend; - lcd_late_resume = s6dr171_late_resume; + lcd_fb_suspend = s6dr171_fb_suspend; + lcd_fb_resume = s6dr171_fb_resume; return 0; diff --git a/drivers/video/samsung/s6e88a0_mipi_lcd.c b/drivers/video/samsung/s6e88a0_mipi_lcd.c index 76d7e6519ee5..573a1f715fb8 100644 --- a/drivers/video/samsung/s6e88a0_mipi_lcd.c +++ b/drivers/video/samsung/s6e88a0_mipi_lcd.c @@ -26,10 +26,10 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif - #include "s5p-dsim.h" #include "s3cfb.h" @@ -102,8 +102,8 @@ static const unsigned int candela_table[GAMMA_MAX] = { 220, 234, 249, 265, 282, 300, 400 }; -extern void (*lcd_early_suspend)(void); -extern void (*lcd_late_resume)(void); +extern void (*lcd_fb_suspend)(void); +extern void (*lcd_fb_resume)(void); static int _s6e88a0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { @@ -1237,7 +1237,7 @@ static DEVICE_ATTR(parameter, 0444, parameter_show, NULL); #ifdef CONFIG_HAS_EARLYSUSPEND static struct lcd_info *g_lcd; -void s6e88a0_early_suspend(void) +void s6e88a0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -1249,7 +1249,7 @@ void s6e88a0_early_suspend(void) return; } -void s6e88a0_late_resume(void) +void s6e88a0_fb_resume(void) { struct lcd_info *lcd = g_lcd; @@ -1376,8 +1376,8 @@ static int s6e88a0_probe(struct device *dev) update_brightness(lcd, 1); - lcd_early_suspend = s6e88a0_early_suspend; - lcd_late_resume = s6e88a0_late_resume; + lcd_fb_suspend = s6e88a0_fb_suspend; + lcd_fb_resume = s6e88a0_fb_resume; dev_info(&lcd->ld->dev, "%s lcd panel driver has been probed.\n", __FILE__); diff --git a/drivers/video/samsung/s6e8aa1.c b/drivers/video/samsung/s6e8aa1.c index d5cd9b8cc745..8445c7fb7ae9 100644 --- a/drivers/video/samsung/s6e8aa1.c +++ b/drivers/video/samsung/s6e8aa1.c @@ -391,7 +391,7 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e8ax0_early_suspend(void) +void s6e8ax0_fb_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -404,7 +404,7 @@ void s6e8ax0_early_suspend(void) return ; } -void s6e8ax0_late_resume(void) +void s6e8ax0_fb_resume(void) { struct lcd_info *lcd = g_lcd; -- GitLab From 80de7561bf64498a672a336983e2615c51fb2a32 Mon Sep 17 00:00:00 2001 From: Dominggoes Isakh Date: Fri, 14 Sep 2018 22:13:56 +0200 Subject: [PATCH 7/9] mdnie: replace earlysuspend with fb notifier callbacks Change-Id: Icc3b1acd520109aa2058825c54be8a84f987060b --- drivers/video/samsung/mdnie.c | 58 +++++++++++++++++++++++++++-------- drivers/video/samsung/mdnie.h | 10 +++--- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/drivers/video/samsung/mdnie.c b/drivers/video/samsung/mdnie.c index 2f424bdd0d37..9366f5b54652 100644 --- a/drivers/video/samsung/mdnie.c +++ b/drivers/video/samsung/mdnie.c @@ -1009,11 +1009,15 @@ static struct device_attribute mdnie_attributes[] = { }; #ifdef CONFIG_PM -#if defined(CONFIG_HAS_EARLYSUSPEND) +#if defined(CONFIG_FB) #if defined(CONFIG_FB_MDNIE_PWM) -static void mdnie_early_suspend(struct early_suspend *h) +static void mdnie_fb_suspend(struct mdnie_info *mdnie) { - struct mdnie_info *mdnie = container_of(h, struct mdnie_info, early_suspend); + if (mdnie->fb_suspended) + return; + + mdnie->fb_suspended = true; + struct lcd_platform_data *pd = mdnie->lcd_pd; dev_info(mdnie->dev, "+%s\n", __func__); @@ -1032,9 +1036,12 @@ static void mdnie_early_suspend(struct early_suspend *h) } #endif -static void mdnie_late_resume(struct early_suspend *h) +static void mdnie_fb_resume(struct mdnie_info *mdnie) { - struct mdnie_info *mdnie = container_of(h, struct mdnie_info, early_suspend); + if (!mdnie->fb_suspended) + return; + + mdnie->fb_suspended = false; #if defined(CONFIG_FB_MDNIE_PWM) struct lcd_platform_data *pd = mdnie->lcd_pd; #endif @@ -1063,6 +1070,34 @@ static void mdnie_late_resume(struct early_suspend *h) return; } #endif + +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct mdnie_info *mdnie = container_of(self, struct mdnie_info, fb_notif); + if (evdata && evdata->data && mdnie) { + if (event == FB_EVENT_BLANK) { + blank = evdata->data; + switch (*blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + mdnie_fb_resume(mdnie); + break; + default: + case FB_BLANK_POWERDOWN: +#if defined(CONFIG_FB_MDNIE_PWM) + mdnie_fb_suspend(mdnie); +#endif + break; + } + } + } + return 0; +} #endif static int mdnie_probe(struct platform_device *pdev) @@ -1140,13 +1175,10 @@ static int mdnie_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mdnie); dev_set_drvdata(mdnie->dev, mdnie); -#ifdef CONFIG_HAS_EARLYSUSPEND -#if defined(CONFIG_FB_MDNIE_PWM) - mdnie->early_suspend.suspend = mdnie_early_suspend; -#endif - mdnie->early_suspend.resume = mdnie_late_resume; - mdnie->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; - register_early_suspend(&mdnie->early_suspend); +#ifdef CONFIG_FB + mdnie->fb_suspended = false; + mdnie->fb_notif.notifier_call = fb_notifier_callback; + fb_register_client(&mdnie->fb_notif); #endif @@ -1228,7 +1260,7 @@ static struct platform_driver mdnie_driver = { }, .probe = mdnie_probe, .remove = mdnie_remove, -#ifndef CONFIG_HAS_EARLYSUSPEND +#ifndef CONFIG_FB .suspend = mdnie_suspend, .resume = mdnie_resume, #endif diff --git a/drivers/video/samsung/mdnie.h b/drivers/video/samsung/mdnie.h index 24f72c13a7ec..16636fc3723f 100644 --- a/drivers/video/samsung/mdnie.h +++ b/drivers/video/samsung/mdnie.h @@ -1,8 +1,9 @@ #ifndef __MDNIE_H__ #define __MDNIE_H__ -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif #define END_SEQ 0xffff @@ -111,8 +112,9 @@ struct mdnie_info { unsigned int accessibility; unsigned int color_correction; char path[50]; -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; +#ifdef CONFIG_FB + struct notifier_block fb_notif; + bool fb_suspended; #endif #ifdef CONFIG_FB_MDNIE_RGB_ADJUST u8 r_adj; -- GitLab From 45227fd3189f4c4698bcf8fa2735bbd9fef4fc33 Mon Sep 17 00:00:00 2001 From: Dominggoes Isakh Date: Sat, 2 Feb 2019 09:39:47 +0100 Subject: [PATCH 8/9] mdnie: Apply settings after resume Change-Id: I9fe22b4ffeda06fcd58c477e2f6d12a14f2040bd --- drivers/video/samsung/mdnie.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/video/samsung/mdnie.c b/drivers/video/samsung/mdnie.c index 9366f5b54652..d4bf0147336b 100644 --- a/drivers/video/samsung/mdnie.c +++ b/drivers/video/samsung/mdnie.c @@ -1010,7 +1010,6 @@ static struct device_attribute mdnie_attributes[] = { #ifdef CONFIG_PM #if defined(CONFIG_FB) -#if defined(CONFIG_FB_MDNIE_PWM) static void mdnie_fb_suspend(struct mdnie_info *mdnie) { if (mdnie->fb_suspended) @@ -1018,10 +1017,12 @@ static void mdnie_fb_suspend(struct mdnie_info *mdnie) mdnie->fb_suspended = true; - struct lcd_platform_data *pd = mdnie->lcd_pd; - dev_info(mdnie->dev, "+%s\n", __func__); + printk("%s: scenario:%d accessibility:%d", __func__, mdnie->scenario, mdnie->accessibility); +#if defined(CONFIG_FB_MDNIE_PWM) + struct lcd_platform_data *pd = mdnie->lcd_pd; + mdnie->bd_enable = FALSE; if (mdnie->enable) @@ -1030,11 +1031,11 @@ static void mdnie_fb_suspend(struct mdnie_info *mdnie) if (pd && pd->power_on) pd->power_on(NULL, 0); +#endif dev_info(mdnie->dev, "-%s\n", __func__); return; } -#endif static void mdnie_fb_resume(struct mdnie_info *mdnie) { @@ -1042,13 +1043,11 @@ static void mdnie_fb_resume(struct mdnie_info *mdnie) return; mdnie->fb_suspended = false; -#if defined(CONFIG_FB_MDNIE_PWM) - struct lcd_platform_data *pd = mdnie->lcd_pd; -#endif dev_info(mdnie->dev, "+%s\n", __func__); #if defined(CONFIG_FB_MDNIE_PWM) + struct lcd_platform_data *pd = mdnie->lcd_pd; if (mdnie->enable) mdnie_pwm_control(mdnie, 0); @@ -1062,7 +1061,6 @@ static void mdnie_fb_resume(struct mdnie_info *mdnie) mdnie->bd_enable = TRUE; #endif - mdnie_update(mdnie); dev_info(mdnie->dev, "-%s\n", __func__); @@ -1089,9 +1087,7 @@ static int fb_notifier_callback(struct notifier_block *self, break; default: case FB_BLANK_POWERDOWN: -#if defined(CONFIG_FB_MDNIE_PWM) mdnie_fb_suspend(mdnie); -#endif break; } } -- GitLab From 682320ec1e391c3797971a0d41ad0eba2f2f714c Mon Sep 17 00:00:00 2001 From: html6405 Date: Wed, 29 Sep 2021 17:34:01 +0200 Subject: [PATCH 9/9] lp855x_bl.c: switch from early suspend to fb notifier callbacks. --- drivers/video/backlight/lp855x_bl.c | 64 +++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index bbedab55e59e..f60bfca5da58 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -17,8 +17,9 @@ #include #include #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include +#ifdef CONFIG_FB +#include +#include #endif /* Registers */ @@ -47,8 +48,9 @@ struct lp855x { struct mutex xfer_lock; struct lp855x_platform_data *pdata; int enabled; -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; +#ifdef CONFIG_FB + struct notifier_block fb_notif; + bool fb_suspended; #endif }; @@ -321,27 +323,55 @@ static int lp855x_config(struct lp855x *lp) } #endif -#ifdef CONFIG_HAS_EARLYSUSPEND -static void lp855x_early_suspend(struct early_suspend *h) +#ifdef CONFIG_FB +static void lp855x_fb_suspend(struct lp855x *lp) { - struct lp855x *lp = - container_of(h, struct lp855x, early_suspend); + if (lp->fb_suspended) + return; lp855x_set_power(lp, 0); + lp->fb_suspended = true; } -static void lp855x_late_resume(struct early_suspend *h) +static void lp855x_fb_resume(struct lp855x *lp) { - struct lp855x *lp = - container_of(h, struct lp855x, early_suspend); + if (!lp->fb_suspended) + return; lp855x_set_power(lp, 1); backlight_update_status(lp->bl); #if defined(CONFIG_MACH_KONA) lp855x_config(lp); #endif + lp->fb_suspended = false; +} +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct lp855x *info = container_of(self, struct lp855x, fb_notif); + if (evdata && evdata->data && info) { + if (event == FB_EVENT_BLANK) { + blank = evdata->data; + switch (*blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + lp855x_fb_resume(info); + break; + default: + case FB_BLANK_POWERDOWN: + lp855x_fb_suspend(info); + break; + } + } + } + return 0; } + #endif static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) @@ -381,13 +411,11 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) } lp->enabled = 1; -#ifdef CONFIG_HAS_EARLYSUSPEND - if (lp->pdata->use_gpio_en) { - lp->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2; - lp->early_suspend.suspend = lp855x_early_suspend; - lp->early_suspend.resume = lp855x_late_resume; - register_early_suspend(&lp->early_suspend); - } + +#ifdef CONFIG_FB + lp->fb_suspended = false; + lp->fb_notif.notifier_call = fb_notifier_callback; + fb_register_client(&lp->fb_notif); #endif ret = lp855x_backlight_register(lp); -- GitLab