GP2X updates
[libpicofe.git] / pandora / plat.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2011,2012
3  *
4  * This work is licensed under the terms of any of these licenses
5  * (at your option):
6  *  - GNU GPL, version 2 or later.
7  *  - GNU LGPL, version 2.1 or later.
8  *  - MAME license.
9  * See the COPYING file in the top-level directory.
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <dirent.h>
17 #include <linux/input.h>
18 #include <errno.h>
19
20 #include "../plat.h"
21 #include "../input.h"
22
23 static const char * const pandora_gpio_keys[KEY_MAX + 1] = {
24         [0 ... KEY_MAX] = NULL,
25         [KEY_UP]        = "Up",
26         [KEY_LEFT]      = "Left",
27         [KEY_RIGHT]     = "Right",
28         [KEY_DOWN]      = "Down",
29         [KEY_HOME]      = "(A)",
30         [KEY_PAGEDOWN]  = "(X)",
31         [KEY_END]       = "(B)",
32         [KEY_PAGEUP]    = "(Y)",
33         [KEY_RIGHTSHIFT]= "(L)",
34         [KEY_RIGHTCTRL] = "(R)",
35         [KEY_LEFTALT]   = "Start",
36         [KEY_LEFTCTRL]  = "Select",
37         [KEY_MENU]      = "Pandora",
38 };
39
40 static const char pnd_script_base[] = "sudo -n /usr/pandora/scripts";
41
42 static void scan_for_filters(void)
43 {
44         struct dirent *ent;
45         int i, count = 0;
46         const char **mfilters;
47         char buff[64];
48         DIR *dir;
49
50         dir = opendir("/etc/pandora/conf/dss_fir");
51         if (dir == NULL) {
52                 perror("filter opendir");
53                 return;
54         }
55
56         while (1) {
57                 errno = 0;
58                 ent = readdir(dir);
59                 if (ent == NULL) {
60                         if (errno != 0)
61                                 perror("readdir");
62                         break;
63                 }
64
65                 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
66                         continue;
67
68                 count++;
69         }
70
71         if (count == 0)
72                 return;
73
74         mfilters = calloc(count + 1, sizeof(mfilters[0]));
75         if (mfilters == NULL)
76                 return;
77
78         rewinddir(dir);
79         for (i = 0; (ent = readdir(dir)); ) {
80                 size_t len;
81
82                 if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
83                         continue;
84
85                 len = strlen(ent->d_name);
86
87                 // skip pre-HF5 extra files
88                 if (len >= 3 && strcmp(ent->d_name + len - 3, "_v3") == 0)
89                         continue;
90                 if (len >= 3 && strcmp(ent->d_name + len - 3, "_v5") == 0)
91                         continue;
92
93                 // have to cut "_up_h" for pre-HF5
94                 if (len > 5 && strcmp(ent->d_name + len - 5, "_up_h") == 0)
95                         len -= 5;
96
97                 if (len > sizeof(buff) - 1)
98                         continue;
99
100                 strncpy(buff, ent->d_name, len);
101                 buff[len] = 0;
102                 mfilters[i] = strdup(buff);
103                 if (mfilters[i] != NULL)
104                         i++;
105         }
106         closedir(dir);
107
108         plat_target.hwfilters = mfilters;
109 }
110
111 static int do_system(const char *cmd)
112 {
113         int ret;
114
115         ret = system(cmd);
116         if (ret >= 0)
117                 ret = 0;
118
119         return ret;
120 }
121
122 static int read_int_from_file(const char *fname)
123 {
124         int ret = -1;
125         FILE *f;
126
127         f = fopen(fname, "r");
128         if (f) {
129                 fscanf(f, "%d", &ret);
130                 fclose(f);
131         }
132         return ret;
133 }
134
135 static int lcdrate_set(int is_pal)
136 {
137         static int old_pal = -1;
138         char buf[128];
139
140         if (is_pal == old_pal)
141                 return 0;
142         old_pal = is_pal;
143
144         snprintf(buf, sizeof(buf), "%s/op_lcdrate.sh %d",
145                         pnd_script_base, is_pal ? 50 : 60);
146         return do_system(buf);
147 }
148
149 static int hwfilter_set(int which)
150 {
151         static int old_filter = -1;
152         char buf[128];
153         int i;
154
155         if (plat_target.hwfilters == NULL)
156                 return -1;
157
158         if (which == old_filter)
159                 return 0;
160
161         for (i = 0; i <= which; i++)
162                 if (plat_target.hwfilters[i] == NULL)
163                         return -1;
164
165         old_filter = which;
166
167         snprintf(buf, sizeof(buf), "%s/op_videofir.sh %s",
168                 pnd_script_base, plat_target.hwfilters[which]);
169         return do_system(buf);
170 }
171
172 static int cpu_clock_get(void)
173 {
174         return read_int_from_file("/proc/pandora/cpu_mhz_max");
175 }
176
177 static int cpu_clock_set(int cpu_clock)
178 {
179         char buf[128];
180
181         if (cpu_clock < 14)
182                 return -1;
183
184         if (cpu_clock == cpu_clock_get())
185                 return 0;
186
187         snprintf(buf, sizeof(buf),
188                  "unset DISPLAY; echo y | %s/op_cpuspeed.sh %d",
189                  pnd_script_base, cpu_clock);
190         return do_system(buf);
191 }
192
193 static int bat_capacity_get(void)
194 {
195         return read_int_from_file("/sys/class/power_supply/bq27500-0/capacity");
196 }
197
198 static int gamma_set(int val, int black_level)
199 {
200         char buf[128];
201
202         snprintf(buf, sizeof(buf), "%s/op_gamma.sh -b %d %.2f",
203                  pnd_script_base, black_level, (float)val / 100.0f);
204         return do_system(buf);
205 }
206
207 struct plat_target plat_target = {
208         cpu_clock_get,
209         cpu_clock_set,
210         bat_capacity_get,
211         hwfilter_set,
212         lcdrate_set,
213         gamma_set,
214 };
215
216 int plat_target_init(void)
217 {
218         scan_for_filters();
219
220         return 0;
221 }
222
223 /* to be called after in_probe */
224 void plat_target_setup_input(void)
225 {
226         int gpiokeys_id;
227
228         gpiokeys_id = in_name_to_id("evdev:gpio-keys");
229         in_set_config(gpiokeys_id, IN_CFG_KEY_NAMES,
230                       pandora_gpio_keys, sizeof(pandora_gpio_keys));
231         in_set_config(gpiokeys_id, IN_CFG_DEFAULT_DEV, NULL, 0);
232 }
233
234 void plat_target_finish(void)
235 {
236 }