1010#include <linux/pm_qos.h>
1111#include <linux/proc_fs.h>
1212#include <linux/uaccess.h>
13+ #include <linux/fs.h>
1314
1415#define PROC_DIR "powersafe"
1516#define MAX_BUF_LEN 32
@@ -18,10 +19,87 @@ static struct pm_qos_request latency_req;
1819static struct proc_dir_entry * psafe_dir ;
1920
2021/* Track states */
21- static int latency_state = 0 ; // 0 = default, 1 = 100µs
22- static int prime_state = 0 ; // 0 = default, 1 = 2.84GHz
22+ static int latency_state = 0 ; // 0 = default, 1 = 100µs
23+ static int prime_state = 0 ; // 0 = default, 1 = 2.84GHz
2324static unsigned int io_weight_state = 0 ; // 0 = default, else custom
24- static int master_state = 0 ; // 0 = default, 1 = optimized
25+ static int master_state = 0 ; // 0 = default, 1 = optimized
26+ static int input_boost_state = 0 ; // 0 = off, 1 = on
27+
28+ /* ---------- Input boost helpers ---------- */
29+
30+ static void write_sysfs (const char * path , const char * val )
31+ {
32+ struct file * f ;
33+ loff_t pos = 0 ;
34+ mm_segment_t oldfs ;
35+
36+ oldfs = get_fs ();
37+ set_fs (KERNEL_DS );
38+
39+ f = filp_open (path , O_WRONLY , 0 );
40+ if (!IS_ERR (f )) {
41+ kernel_write (f , val , strlen (val ), & pos );
42+ filp_close (f , NULL );
43+ }
44+
45+ set_fs (oldfs );
46+ }
47+
48+ static void set_input_boost_enabled (bool enable )
49+ {
50+ struct file * f ;
51+ mm_segment_t oldfs ;
52+ char buf [2 ];
53+
54+ snprintf (buf , sizeof (buf ), "%d" , enable ? 1 : 0 );
55+
56+ oldfs = get_fs ();
57+ set_fs (KERNEL_DS );
58+
59+ f = filp_open ("/sys/module/cpu_input_boost/parameters/input_boost_enabled" , O_WRONLY , 0 );
60+ if (!IS_ERR (f )) {
61+ kernel_write (f , buf , strlen (buf ), & f -> f_pos );
62+ filp_close (f , NULL );
63+ }
64+
65+ set_fs (oldfs );
66+ }
67+
68+ static void set_input_boost_param_str (const char * name , const char * val )
69+ {
70+ char path [128 ];
71+ snprintf (path , sizeof (path ), "/sys/module/cpu_input_boost/parameters/%s" , name );
72+ write_sysfs (path , val );
73+ }
74+
75+ static void set_input_boost_param_int (const char * name , int val )
76+ {
77+ char buf [32 ];
78+ snprintf (buf , sizeof (buf ), "%d" , val );
79+ set_input_boost_param_str (name , buf );
80+ }
81+
82+ /* Convenience setters */
83+ static void configure_input_boost (int input_ms , int wake_ms ,
84+ int little_boost , int big_boost , int prime_boost ,
85+ int little_cap , int big_cap , int prime_cap ,
86+ int little_min , int big_min , int prime_min )
87+ {
88+ set_input_boost_param_int ("input_boost_ms" , input_ms );
89+ set_input_boost_param_int ("wake_boost_ms" , wake_ms );
90+
91+ set_input_boost_param_int ("l_cluster_boost_freq" , little_boost );
92+ set_input_boost_param_int ("b_cluster_boost_freq" , big_boost );
93+ set_input_boost_param_int ("p_cluster_boost_freq" , prime_boost );
94+
95+ set_input_boost_param_int ("l_cluster_max_boost_freq" , little_cap );
96+ set_input_boost_param_int ("b_cluster_max_boost_freq" , big_cap );
97+ set_input_boost_param_int ("p_cluster_max_boost_freq" , prime_cap );
98+
99+ set_input_boost_param_int ("little_default_min_freq" , little_min );
100+ set_input_boost_param_int ("big_default_min_freq" , big_min );
101+ set_input_boost_param_int ("prime_default_min_freq" , prime_min );
102+ }
25103
26104/* ---------- Latency toggle ---------- */
27105static ssize_t latency_toggle_write (struct file * file , const char __user * buf ,
@@ -131,52 +209,197 @@ static const struct file_operations io_weight_ops = {
131209 .read = io_weight_read ,
132210};
133211
212+ /* ---------- Input boost proc entries ---------- */
213+
214+ static ssize_t input_boost_state_read (struct file * file , char __user * buf ,
215+ size_t count , loff_t * ppos )
216+ {
217+ char kbuf [MAX_BUF_LEN ];
218+ int len ;
219+
220+ if (* ppos > 0 )
221+ return 0 ;
222+
223+ len = snprintf (kbuf , sizeof (kbuf ), "%d\n" , input_boost_state );
224+ if (copy_to_user (buf , kbuf , len ))
225+ return - EFAULT ;
226+
227+ * ppos = len ;
228+ return len ;
229+ }
230+
231+ static const struct file_operations input_boost_state_fops = {
232+ .owner = THIS_MODULE ,
233+ .read = input_boost_state_read ,
234+ .llseek = noop_llseek ,
235+ };
236+
237+ static ssize_t input_boost_write (struct file * file , const char __user * ubuf ,
238+ size_t count , loff_t * ppos )
239+ {
240+ char kbuf [MAX_BUF_LEN ];
241+ int val ;
242+
243+ if (count == 0 || count >= MAX_BUF_LEN )
244+ return - EINVAL ;
245+
246+ if (copy_from_user (kbuf , ubuf , count ))
247+ return - EFAULT ;
248+
249+ kbuf [count ] = '\0' ;
250+
251+ if (kstrtoint (kbuf , 10 , & val ))
252+ return - EINVAL ;
253+
254+ if (val == 0 || val == 1 ) {
255+ input_boost_state = val ;
256+ set_input_boost_enabled (val );
257+ pr_info ("powersafe: input boost manually %s\n" , val ? "enabled" : "disabled" );
258+ return count ;
259+ }
260+
261+ return - EINVAL ;
262+ }
263+
264+ static const struct file_operations input_boost_fops = {
265+ .owner = THIS_MODULE ,
266+ .write = input_boost_write ,
267+ .llseek = noop_llseek ,
268+ };
269+
134270/* ---------- Master toggle ---------- */
135- static ssize_t master_toggle_write (struct file * file , const char __user * buf ,
271+ static ssize_t master_toggle_write (struct file * file , const char __user * ubuf ,
136272 size_t count , loff_t * ppos )
137273{
138274 char kbuf [MAX_BUF_LEN ];
275+ int new_state ;
139276 struct cpufreq_policy * policy ;
140277
141- if (copy_from_user (kbuf , buf , count ))
278+ if (count == 0 || count >= MAX_BUF_LEN )
279+ return - EINVAL ;
280+
281+ if (copy_from_user (kbuf , ubuf , count ))
142282 return - EFAULT ;
143283
144- if (kbuf [0 ] == '1' ) {
145- /* Optimized profile */
146- pm_qos_update_request (& latency_req , 100 );
284+ kbuf [count ] = '\0' ;
285+
286+ if (kstrtoint (kbuf , 10 , & new_state ))
287+ return - EINVAL ;
288+
289+ switch (new_state ) {
290+ case 0 : /* Default */
291+ pm_qos_update_request (& latency_req , PM_QOS_DEFAULT_VALUE );
292+ latency_state = 0 ;
293+ io_weight_state = 0 ;
294+ prime_state = 0 ;
295+
296+ /* Restore prime max to default */
297+ policy = cpufreq_cpu_get (7 );
298+ if (policy ) {
299+ policy -> max = policy -> cpuinfo .max_freq ;
300+ cpufreq_update_policy (policy -> cpu );
301+ cpufreq_cpu_put (policy );
302+ }
303+
304+ /* Input boost off, baseline mins */
305+ input_boost_state = 0 ;
306+ set_input_boost_enabled (false);
307+ configure_input_boost (
308+ 0 , 0 ,
309+ 0 , 0 , 0 ,
310+ 0 , 0 , 0 ,
311+ 600000 , 825600 , 844800
312+ );
313+
314+ pr_info ("powersafe: state=0 (default)\n" );
315+ break ;
316+
317+ case 1 : /* Balanced */
318+ pm_qos_update_request (& latency_req , 200 );
147319 latency_state = 1 ;
320+ io_weight_state = 250 ;
321+ prime_state = 0 ;
148322
323+ /* Prime left at default */
149324 policy = cpufreq_cpu_get (7 );
150325 if (policy ) {
151- policy -> max = 2841600 ;
326+ policy -> max = policy -> cpuinfo . max_freq ;
152327 cpufreq_update_policy (policy -> cpu );
153328 cpufreq_cpu_put (policy );
154329 }
155- prime_state = 1 ;
156330
331+ /* Input boost moderate */
332+ input_boost_state = 1 ;
333+ set_input_boost_enabled (true);
334+ configure_input_boost (
335+ 58 , 0 ,
336+ 1708800 , 1056000 , 1401600 ,
337+ 1804800 , 2246400 , 2553600 ,
338+ 1171200 , 825600 , 844800
339+ );
340+
341+ pr_info ("powersafe: state=1 (balanced)\n" );
342+ break ;
343+
344+ case 2 : /* Performance + prime boost */
345+ pm_qos_update_request (& latency_req , 100 );
346+ latency_state = 1 ;
157347 io_weight_state = 500 ;
158- pr_info ( "powersafe-toggle: io.weight set to 500\n" ) ;
348+ prime_state = 1 ;
159349
160- master_state = 1 ;
161- } else {
162- /* Default profile: restore system defaults */
163- pm_qos_update_request (& latency_req , PM_QOS_DEFAULT_VALUE );
164- latency_state = 0 ;
350+ /* Prime boosted to 3.12 GHz */
351+ policy = cpufreq_cpu_get (7 );
352+ if (policy ) {
353+ policy -> max = 3120000 ;
354+ cpufreq_update_policy (policy -> cpu );
355+ cpufreq_cpu_put (policy );
356+ }
357+
358+ /* Input boost aggressive */
359+ input_boost_state = 1 ;
360+ set_input_boost_enabled (true);
361+ configure_input_boost (
362+ 100 , 1000 ,
363+ 1708800 , 2016000 , 2841600 ,
364+ 1804800 , 2246400 , 3120000 ,
365+ 1171200 , 1324800 , 1804800
366+ );
367+
368+ pr_info ("powersafe: state=2 (performance, prime boost)\n" );
369+ break ;
370+
371+ case 3 : /* Powersafe */
372+ pm_qos_update_request (& latency_req , 400 );
373+ latency_state = 1 ;
374+ io_weight_state = 100 ;
375+ prime_state = 0 ;
165376
377+ /* Prime back to default */
166378 policy = cpufreq_cpu_get (7 );
167379 if (policy ) {
168380 policy -> max = policy -> cpuinfo .max_freq ;
169381 cpufreq_update_policy (policy -> cpu );
170382 cpufreq_cpu_put (policy );
171383 }
172- prime_state = 0 ;
173384
174- io_weight_state = 0 ;
175- pr_info ("powersafe-toggle: io.weight reset to default\n" );
385+ /* Input boost disabled, conservative mins */
386+ input_boost_state = 0 ;
387+ set_input_boost_enabled (false);
388+ configure_input_boost (
389+ 0 , 0 ,
390+ 0 , 0 , 0 ,
391+ 0 , 0 , 0 ,
392+ 600000 , 825600 , 844800
393+ );
394+
395+ pr_info ("powersafe: state=3 (powersafe)\n" );
396+ break ;
176397
177- master_state = 0 ;
398+ default :
399+ return - EINVAL ;
178400 }
179401
402+ master_state = new_state ;
180403 return count ;
181404}
182405
@@ -201,24 +424,32 @@ static int __init powersafe_init(void)
201424 if (!psafe_dir )
202425 return - ENOMEM ;
203426
427+ /* Existing entries */
204428 proc_create ("latency_toggle" , 0666 , psafe_dir , & latency_toggle_ops );
205429 proc_create ("prime_freq_boost" , 0666 , psafe_dir , & prime_freq_boost_ops );
206430 proc_create ("io_weight" , 0666 , psafe_dir , & io_weight_ops );
207431 proc_create ("master_toggle" , 0666 , psafe_dir , & master_toggle_ops );
208432
433+ /* New input boost entries */
434+ proc_create ("input_boost_state" , 0444 , psafe_dir , & input_boost_state_fops );
435+ proc_create ("input_boost" , 0222 , psafe_dir , & input_boost_fops );
436+
209437 pm_qos_add_request (& latency_req , PM_QOS_CPU_DMA_LATENCY , PM_QOS_DEFAULT_VALUE );
210438
211- pr_info ("powersafe-toggle loaded\n" );
439+ pr_info ("powersafe-toggle loaded (with input boost) \n" );
212440 return 0 ;
213441}
214442
215443static void __exit powersafe_exit (void )
216444{
217445 pm_qos_remove_request (& latency_req );
446+
218447 remove_proc_entry ("latency_toggle" , psafe_dir );
219448 remove_proc_entry ("prime_freq_boost" , psafe_dir );
220449 remove_proc_entry ("io_weight" , psafe_dir );
221450 remove_proc_entry ("master_toggle" , psafe_dir );
451+ remove_proc_entry ("input_boost_state" , psafe_dir );
452+ remove_proc_entry ("input_boost" , psafe_dir );
222453 remove_proc_entry (PROC_DIR , NULL );
223454
224455 pr_info ("powersafe-toggle unloaded\n" );
@@ -227,5 +458,5 @@ static void __exit powersafe_exit(void)
227458module_init (powersafe_init );
228459module_exit (powersafe_exit );
229460MODULE_LICENSE ("GPL" );
230- MODULE_AUTHOR ("Manuel & Copilot" );
231- MODULE_DESCRIPTION ("Eff-CPU Runtime Toggle Module with Master Switch and Read Handlers" );
461+ MODULE_AUTHOR ("dtrail & Copilot" );
462+ MODULE_DESCRIPTION ("Powersafe Toggle Module with Master Switch, Input Boost, and Read Handlers" );
0 commit comments