Add copyright message to gles_video
[gpsp.git] / gp2x / pollux_dpc_set.c
CommitLineData
e8f5db5d 1/*
2 * quick tool to set LCD timings for Wiz
3 * (c) notaz, 2009
4 * code dedicated to public domain.
5 *
6 * HTOTAL: X VTOTAL: 341
7 * HSWIDTH: 1 VSWIDTH: 0
8 * HASTART: 37 VASTART: 17
9 * HAEND: 277 VAEND: 337
10 *
11 * 120Hz
12 * pcd 8, 447: + 594us
13 * pcd 9, 397: + 36us
14 * pcd 10, 357: - 523us
15 * pcd 11, 325: +1153us
16 *
17 * 'lcd_timings=397,1,37,277,341,0,17,337;clkdiv0=9'
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include "pollux_dpc_set.h"
24
25/*
26 * set LCD timings based on preformated string (see usage() below for params).
27 * returns 0 on success.
28 */
29int pollux_dpc_set(volatile unsigned short *memregs, const char *str)
30{
31 int timings[8], have_timings = 0;
32 int pcd = 0, have_pcd = 0;
33 const char *p;
34 int i, ret;
35
36 if (str == NULL)
37 return -1;
38
39 p = str;
40 while (1)
41 {
42 if (strncmp(p, "lcd_timings=", 12) == 0)
43 {
44 int c;
45 p += 12;
46 ret = sscanf(p, "%d,%d,%d,%d,%d,%d,%d,%d",
47 &timings[0], &timings[1], &timings[2], &timings[3],
48 &timings[4], &timings[5], &timings[6], &timings[7]);
49 if (ret != 8)
50 break;
51 /* skip seven commas */
52 for (c = 0; c < 7 && *p != 0; p++)
53 if (*p == ',')
54 c++;
55 if (c != 7)
56 break;
57 /* skip last number */
58 while ('0' <= *p && *p <= '9')
59 p++;
60 have_timings = 1;
61 }
62 else if (strncmp(p, "clkdiv0=", 8) == 0)
63 {
64 char *ep;
65 p += 8;
66 pcd = strtoul(p, &ep, 10);
67 if (p == ep)
68 break;
69 p = ep;
70 have_pcd = 1;
71 }
72 else
73 break;
74
75 while (*p == ';' || *p == ' ')
76 p++;
77 if (*p == 0)
78 goto parse_done;
79 }
80
81 fprintf(stderr, "dpc_set parser: error at '%s'\n", p);
82 return -1;
83
84parse_done:
85 /* some validation */
86 if (have_timings)
87 {
88 for (i = 0; i < 8; i++)
89 if (timings[i] & ~0xffff) {
90 fprintf(stderr, "dpc_set: invalid timing %d: %d\n", i, timings[i]);
91 return -1;
92 }
93 }
94
95 if (have_pcd)
96 {
97 if ((pcd - 1) & ~0x3f) {
98 fprintf(stderr, "dpc_set: invalid clkdiv0: %d\n", pcd);
99 return -1;
100 }
101 }
102
103 /* write */
104 if (have_timings)
105 {
106 for (i = 0; i < 8; i++)
107 memregs[(0x307c>>1) + i] = timings[i];
108 }
109
110 if (have_pcd)
111 {
112 int tmp;
113 pcd = (pcd - 1) & 0x3f;
114 tmp = memregs[0x31c4>>1];
115 memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4);
116 }
117
118 return 0;
119}
120
121#ifdef BINARY
122#include <sys/types.h>
123#include <sys/stat.h>
124#include <fcntl.h>
125#include <sys/mman.h>
126#include <unistd.h>
127
128static void usage(const char *binary)
129{
130 printf("usage:\n%s <set_str[;set_str[;...]]>\n"
131 "set_str:\n"
132 " lcd_timings=<htotal,hswidth,hastart,haend,vtotal,vswidth,vastart,vaend>\n"
133 " clkdiv0=<divider>\n", binary);
134}
135
136int main(int argc, char *argv[])
137{
138 volatile unsigned short *memregs;
139 int ret, memdev;
140
141 if (argc != 2) {
142 usage(argv[0]);
143 return 1;
144 }
145
146 memdev = open("/dev/mem", O_RDWR);
147 if (memdev == -1)
148 {
149 perror("open(/dev/mem) failed");
150 return 1;
151 }
152
153 memregs = mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
154 if (memregs == MAP_FAILED)
155 {
156 perror("mmap(memregs) failed");
157 close(memdev);
158 return 1;
159 }
160
161 ret = pollux_dpc_set(memregs, argv[1]);
162
163 munmap((void *)memregs, 0x10000);
164 close(memdev);
165
166 return ret;
167}
168#endif