2 * Copyright (c) 2010, GraÅžvydas Ignotas
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the organization nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/types.h>
38 #include <sys/ioctl.h>
40 #include <linux/input.h>
41 #include <linux/matroxfb.h>
46 #define DO_RGB(type,d,after,r,g,b) { \
47 int i, u, c, l, div = (w << 8) / SPLIT; \
48 char lines[8][dotsz * w]; \
50 for (dest = (void *)lines[0], i = 0; i < w; i++) { \
51 d = (i * (1 << r) / w) << (g+b); \
54 for (dest = (void *)lines[1], i = 0; i < w; i++) { \
55 d = (i * (1 << g) / w) << b; \
58 for (dest = (void *)lines[2], i = 0; i < w; i++) { \
59 d = (i * (1 << b) / w); \
62 for (dest = (void *)lines[3], i = 0; i < w; i++) { \
63 d = ((i * (1 << r) / w) << (g+b)) | \
64 ((i * (1 << g) / w) << b) | \
69 for (dest = (void *)lines[4], i = 0; i < w; i++) { \
70 c = (((i << 8) / div + 1) * div) >> 8; \
71 d = ((c * (1 << r) / w) << (g+b)) | \
72 ((c * (1 << g) / w) << b) | \
76 for (dest = (void *)lines[5], i = 0; i < w; i++) { \
77 c = (((i << 8) / div + 1) * div) >> 8; \
78 d = (c * (1 << b) / w); \
81 for (dest = (void *)lines[6], i = 0; i < w; i++) { \
82 c = (((i << 8) / div + 1) * div) >> 8; \
83 d = (c * (1 << g) / w) << b; \
86 for (dest = (void *)lines[7], i = 0; i < w; i++) { \
87 c = (((i << 8) / div + 1) * div) >> 8; \
88 d = (c * (1 << r) / w) << (g+b); \
92 for (u = 0; u < h; u++) { \
94 memcpy((char *)ptr + u * dotsz * w, lines[l], dotsz * w); \
100 static void text_out(void *fbi, int x, int y, int dotsz, int stride, const char *text)
105 fb = (char *)fbi + x * dotsz + y * stride;
107 for (i = 0; i < strlen(text); i++)
111 #define pix(fdmask,add) \
112 if (fontdata8x8[((text[i])*8)+l]&fdmask) \
113 memcpy(fb + l*stride + add*dotsz, &v, dotsz)
128 static void get_config(char *buff, size_t size, int just_dir)
132 home = getenv("HOME");
136 snprintf(buff, size, "%s/.config", home);
138 snprintf(buff, size, "%s/.config/op_gammatool", home);
141 static int do_load(int *gamma)
147 get_config(buff, sizeof(buff), 0);
148 f = fopen(buff, "r");
151 ret = fscanf(f, "%d %d %d %d %d %d %d %d %d %d %d %d\n",
152 &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
153 &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
156 return (ret == 12) ? 0 : -1;
159 static int do_save(const int *gamma)
161 const int *g = gamma;
166 get_config(buff, sizeof(buff), 1);
168 get_config(buff, sizeof(buff), 0);
169 f = fopen(buff, "w");
172 ret = fprintf(f, "%d %d %d %d %d %d %d %d %d %d %d %d\n",
173 g[0], g[1], g[2], g[3], g[4], g[5],
174 g[6], g[7], g[8], g[9], g[10], g[11]);
177 return (ret > 0) ? 0 : -1;
180 int main(int argc, char *argv[])
182 const char *msg_once = "Start - exit, Y - change bpp, A/B - save/load, "
183 "hold R for faster tuning";
184 int pressed_up = 0, pressed_down = 0, pressed_r = 0;
185 struct fb_var_screeninfo fbvar;
186 int fbdev, ifd, ret, sel = 0;
187 int i, w, h, dotsz = 0, stride;
188 int gamma[12] = { 0, };
193 fbdev = open("/dev/fb0", O_RDWR);
195 perror("open(\"/dev/fb0\") failed");
199 ret = ioctl(fbdev, FBIOGET_VSCREENINFO, &fbvar);
201 perror("ioctl(FBIOGET_FSCREENINFO) failed");
205 if (argv[1] != NULL) {
206 fbvar.bits_per_pixel = atoi(argv[1]);
207 ret = ioctl(fbdev, FBIOPUT_VSCREENINFO, &fbvar);
210 perror("ioctl FBIOPUT_VSCREENINFO");
214 printf("visible resolution: %i %i\n", fbvar.xres, fbvar.yres);
215 printf("virtual resolution: %i %i\n", fbvar.xres_virtual, fbvar.yres_virtual);
216 printf("offset from virtual to visible: %i %i\n", fbvar.xoffset, fbvar.yoffset);
217 printf("bits_per_pixel: %i\n", fbvar.bits_per_pixel);
219 ptr = mmap(0, fbvar.xres * fbvar.yres * 4,
220 PROT_WRITE|PROT_READ, MAP_SHARED, fbdev, 0);
221 if (ptr == MAP_FAILED)
222 ptr = mmap(0, fbvar.xres * fbvar.yres * fbvar.bits_per_pixel / 8,
223 PROT_WRITE|PROT_READ, MAP_SHARED, fbdev, 0);
224 if (ptr == MAP_FAILED)
226 perror("mmap(fbptr) failed");
233 // search for gpio keys
234 for (ifd = -1, i = 0; ; i++) {
235 snprintf(buff, sizeof(buff), "/dev/input/event%i", i);
236 ifd = open(buff, O_RDONLY | O_NONBLOCK);
240 ioctl(ifd, EVIOCGNAME(sizeof(buff)), buff);
242 if (strcasestr(buff, "gpio") != NULL)
248 f = fopen("/sys/devices/platform/omap2_mcspi.1/spi1.1/gamma", "r+");
252 ret = fscanf(f, "%d %d %d %d %d %d %d %d %d %d %d %d\n",
253 &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
254 &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
258 fprintf(stderr, "gamma file missing or bad\n");
267 fscanf(f, "%d %d %d %d %d %d %d %d %d %d %d %d\n",
268 &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
269 &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
272 //ioctl(fbdev, FBIO_WAITFORVSYNC, &ret);
273 if (fbvar.bits_per_pixel == 16)
276 DO_RGB(unsigned short, dest[i],, 5, 6, 5);
278 else if (fbvar.bits_per_pixel == 24)
284 DO_RGB(unsigned char, d, p = &dest[i*3]; p[0] = d; p[1] = d >> 8; p[2] = d >> 16, 8, 8, 8);
286 else if (fbvar.bits_per_pixel == 32)
289 DO_RGB(unsigned int, dest[i],, 8, 8, 8);
293 fprintf(stderr, "unhandled bpp: %d\n", fbvar.bits_per_pixel);
298 snprintf(buff, sizeof(buff), "%dbpp", fbvar.bits_per_pixel);
299 text_out(ptr, 8, 10, dotsz, stride, buff);
300 if (msg_once != NULL) {
301 text_out(ptr, 80, 10, dotsz, stride, msg_once);
304 for (i = 0; i < 12; i++) {
305 int x = i * w / 12 + 8;
307 text_out(ptr, x, h - 18, dotsz, stride, "____");
308 snprintf(buff, sizeof(buff), "%d", gamma[i]);
309 text_out(ptr, x, h - 20, dotsz, stride, buff);
318 struct input_event ev;
319 ret = read(ifd, &ev, sizeof(ev));
320 if (ret < (int) sizeof(ev)) {
321 if (errno == EAGAIN || errno == EWOULDBLOCK)
322 goto input_no_change;
324 perror("evtest: read error");
328 if (ev.type != EV_KEY)
345 pressed_up = ev.value;
348 pressed_down = ev.value;
352 pressed_r = ev.value;
357 fbvar.bits_per_pixel += 8;
358 if (fbvar.bits_per_pixel > 32)
359 fbvar.bits_per_pixel = 16;
360 ret = ioctl(fbdev, FBIOPUT_VSCREENINFO, &fbvar);
362 perror("ioctl FBIOPUT_VSCREENINFO");
369 if (do_load(gamma) == 0)
372 msg_once = "load failed";
373 goto input_done_gamma;
378 if (do_save(gamma) == 0)
381 msg_once = "save failed";
394 if (gamma[sel] >= 1023)
398 goto input_done_gamma;
406 goto input_done_gamma;
416 fprintf(f, "%d %d %d %d %d %d %d %d %d %d %d %d\n",
417 g[0], g[1], g[2], g[3], g[4], g[5],
418 g[6], g[7], g[8], g[9], g[10], g[11]);
424 munmap(ptr, fbvar.xres * fbvar.yres * fbvar.bits_per_pixel / 8);