1 /*
2 * omap35 display subsystem (dss) device interface to screen.c.
3 * implements #v/vgactl
4 */
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "ureg.h"
12 #include "../port/error.h"
13
14 #define Image IMAGE
15 #include <draw.h>
16 #include <memdraw.h>
17 #include <cursor.h>
18 #include "screen.h"
19 // #include "gamma.h"
20
21 enum {
22 Qdir,
23 Qdss,
24 };
25
26 extern OScreen oscreen;
27 extern Settings settings[];
28 extern Omap3fb *framebuf;
29
30 static QLock dsslck;
31 static Dirtab dsstab[] = {
32 ".", {Qdir, 0, QTDIR}, 0, 0555|DMDIR,
33 "vgactl", {Qdss, 0}, 0, 0666,
34 };
35
36 static Chan*
screenattach(char * spec)37 screenattach(char *spec)
38 {
39 return devattach('v', spec);
40 }
41
42 static Walkqid*
screenwalk(Chan * c,Chan * nc,char ** name,int nname)43 screenwalk(Chan *c, Chan *nc, char **name, int nname)
44 {
45 return devwalk(c, nc, name, nname, dsstab, nelem(dsstab), devgen);
46 }
47
48 static int
screenstat(Chan * c,uchar * dp,int n)49 screenstat(Chan *c, uchar *dp, int n)
50 {
51 return devstat(c, dp, n, dsstab, nelem(dsstab), devgen);
52 }
53
54 static Chan*
screenopen(Chan * c,int omode)55 screenopen(Chan *c, int omode)
56 {
57 if ((ulong)c->qid.path == Qdss) {
58 qlock(&dsslck);
59 oscreen.open = 1;
60 c->mode = openmode(omode);
61 c->flag |= COPEN;
62 c->offset = 0;
63 }
64 return c;
65 }
66
67 static void
screenclose(Chan * c)68 screenclose(Chan *c)
69 {
70 if ((c->qid.type & QTDIR) == 0 && c->flag & COPEN)
71 if (c->qid.path == Qdss) {
72 oscreen.open = 0;
73 qunlock(&dsslck);
74 }
75 }
76
77 static ulong
getchans(char * p)78 getchans(char *p)
79 {
80 if (strncmp("x24" , p, 3) == 0)
81 return RGB24; /* can't work yet, pixels are shorts */
82 else if (strncmp("x16", p, 3) == 0)
83 return RGB16;
84 else
85 return RGB16;
86 }
87
88 static long
settingswrite(OScreen * scr,char * p)89 settingswrite(OScreen *scr, char *p)
90 {
91 if (strncmp("800x600", p, 7) == 0) {
92 p += 7;
93 scr->settings = &settings[Res800x600];
94 } else if (strncmp("1024x768", p, 8) == 0) {
95 p += 8;
96 scr->settings = &settings[Res1024x768];
97 } else if (strncmp("1280x1024", p, 9) == 0) {
98 p += 9;
99 scr->settings = &settings[Res1280x1024];
100 } else
101 return -1;
102 scr->settings->chan = getchans(p);
103 return 1;
104 }
105
106 static long
screenread(Chan * c,void * a,long n,vlong off)107 screenread(Chan *c, void *a, long n, vlong off)
108 {
109 int len, depth;
110 char *p;
111 Settings *set;
112
113 switch ((ulong)c->qid.path) {
114 case Qdir:
115 return devdirread(c, a, n, dsstab, nelem(dsstab), devgen);
116 case Qdss:
117 set = oscreen.settings;
118 p = malloc(READSTR);
119 if(waserror()){
120 free(p);
121 nexterror();
122 }
123 if (set->chan == RGB16)
124 depth = 16;
125 else if (set->chan == RGB24)
126 depth = 24;
127 else
128 depth = 0;
129 len = snprint(p, READSTR, "size %dx%dx%d @ %d Hz\n"
130 "addr %#p size %ud\n", set->wid, set->ht, depth,
131 set->freq, framebuf, sizeof *framebuf);
132 USED(len);
133 n = readstr(off, a, n, p);
134 poperror();
135 free(p);
136 return n;
137 default:
138 error(Egreg);
139 }
140 return 0;
141 }
142
143 static long
screenwrite(Chan * c,void * a,long n,vlong off)144 screenwrite(Chan *c, void *a, long n, vlong off)
145 {
146 switch ((ulong)c->qid.path) {
147 case Qdss:
148 if(off)
149 error(Ebadarg);
150 n = settingswrite(&oscreen, a);
151 if (n < 0)
152 error(Ebadctl);
153 screeninit();
154 return n;
155 default:
156 error(Egreg);
157 }
158 return 0;
159 }
160
161 Dev dssdevtab = {
162 L'v',
163 "dss",
164
165 devreset,
166 devinit,
167 devshutdown, // TODO add a shutdown to stop dma to monitor
168 screenattach,
169 screenwalk,
170 screenstat,
171 screenopen,
172 devcreate,
173 screenclose,
174 screenread,
175 devbread,
176 screenwrite,
177 devbwrite,
178 devremove,
179 devwstat,
180 };
181