1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * TP suspend Control Abstraction
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) RK Company
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun #ifndef _RK_TP_SUSPEND_H
9*4882a593Smuzhiyun #define _RK_TP_SUSPEND_H
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/init.h>
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/err.h>
14*4882a593Smuzhiyun #include <linux/fb.h>
15*4882a593Smuzhiyun #include <linux/notifier.h>
16*4882a593Smuzhiyun #include "../../gpu/drm/rockchip/ebc-dev/ebc_dev.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun struct tp_device{
19*4882a593Smuzhiyun struct notifier_block fb_notif;
20*4882a593Smuzhiyun struct notifier_block ebc_notif;
21*4882a593Smuzhiyun int(*tp_suspend)(struct tp_device*);
22*4882a593Smuzhiyun int(*tp_resume)(struct tp_device*);
23*4882a593Smuzhiyun struct mutex ops_lock;
24*4882a593Smuzhiyun int status;
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun
fb_notifier_callback(struct notifier_block * self,unsigned long action,void * data)27*4882a593Smuzhiyun static inline int fb_notifier_callback(struct notifier_block *self,
28*4882a593Smuzhiyun unsigned long action, void *data)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun struct tp_device *tp;
31*4882a593Smuzhiyun struct fb_event *event = data;
32*4882a593Smuzhiyun int blank_mode;
33*4882a593Smuzhiyun int ret = 0;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun tp = container_of(self, struct tp_device, fb_notif);
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun if (action != FB_EVENT_BLANK)
38*4882a593Smuzhiyun return NOTIFY_DONE;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun mutex_lock(&tp->ops_lock);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun blank_mode = *((int *)event->data);
43*4882a593Smuzhiyun //printk("%s.....lin=%d tp->status=%x,blank_mode=%x\n",__func__,__LINE__,tp->status,blank_mode);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun switch (blank_mode) {
46*4882a593Smuzhiyun case FB_BLANK_UNBLANK:
47*4882a593Smuzhiyun if (tp->status != FB_BLANK_UNBLANK) {
48*4882a593Smuzhiyun tp->status = blank_mode;
49*4882a593Smuzhiyun tp->tp_resume(tp);
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun break;
52*4882a593Smuzhiyun default:
53*4882a593Smuzhiyun if (tp->status == FB_BLANK_UNBLANK) {
54*4882a593Smuzhiyun tp->status = blank_mode;
55*4882a593Smuzhiyun ret = tp->tp_suspend(tp);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun break;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun mutex_unlock(&tp->ops_lock);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (ret < 0)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun printk("TP_notifier_callback error action=%x,blank_mode=%x\n",(int)action,blank_mode);
65*4882a593Smuzhiyun return ret;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun return NOTIFY_OK;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
ebc_notifier_callback(struct notifier_block * self,unsigned long action,void * data)71*4882a593Smuzhiyun static int ebc_notifier_callback(struct notifier_block *self,
72*4882a593Smuzhiyun unsigned long action, void *data)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun struct tp_device *tp;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun tp = container_of(self, struct tp_device, ebc_notif);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun mutex_lock(&tp->ops_lock);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (action == EBC_FB_BLANK)
81*4882a593Smuzhiyun tp->tp_suspend(tp);
82*4882a593Smuzhiyun else if (action == EBC_FB_UNBLANK)
83*4882a593Smuzhiyun tp->tp_resume(tp);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun mutex_unlock(&tp->ops_lock);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun return NOTIFY_OK;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
tp_register_fb(struct tp_device * tp)90*4882a593Smuzhiyun static inline int tp_register_fb(struct tp_device *tp)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun memset(&tp->fb_notif, 0, sizeof(tp->fb_notif));
93*4882a593Smuzhiyun tp->fb_notif.notifier_call = fb_notifier_callback;
94*4882a593Smuzhiyun tp->ebc_notif.notifier_call = ebc_notifier_callback;
95*4882a593Smuzhiyun mutex_init(&tp->ops_lock);
96*4882a593Smuzhiyun tp->status = FB_BLANK_UNBLANK;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun ebc_register_notifier(&tp->ebc_notif);
99*4882a593Smuzhiyun fb_register_client(&tp->fb_notif);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun return 0;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
tp_unregister_fb(struct tp_device * tp)104*4882a593Smuzhiyun static inline void tp_unregister_fb(struct tp_device *tp)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun ebc_unregister_notifier(&tp->ebc_notif);
107*4882a593Smuzhiyun fb_unregister_client(&tp->fb_notif);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun #endif
110