/* * omap35 display subsystem (dss) device interface to screen.c. * implements #v/vgactl */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "../port/error.h" #define Image IMAGE#include <draw.h>#include <memdraw.h>#include <cursor.h>#include "screen.h"// #include "gamma.h" enum { Qdir, Qdss,}; extern OScreen oscreen;extern Settings settings[];extern Omap3fb *framebuf; static QLock dsslck;static Dirtab dsstab[] = { ".", {Qdir, 0, QTDIR}, 0, 0555|DMDIR, "vgactl", {Qdss, 0}, 0, 0666,}; static Chan*screenattach(char *spec){ return devattach('v', spec);} static Walkqid*screenwalk(Chan *c, Chan *nc, char **name, int nname){ return devwalk(c, nc, name, nname, dsstab, nelem(dsstab), devgen);} static intscreenstat(Chan *c, uchar *dp, int n){ return devstat(c, dp, n, dsstab, nelem(dsstab), devgen);} static Chan*screenopen(Chan *c, int omode){ if ((ulong)c->qid.path == Qdss) { qlock(&dsslck); oscreen.open = 1; c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; } return c;} static voidscreenclose(Chan *c){ if ((c->qid.type & QTDIR) == 0 && c->flag & COPEN) if (c->qid.path == Qdss) { oscreen.open = 0; qunlock(&dsslck); }} static ulonggetchans(char *p){ if (strncmp("x24" , p, 3) == 0) return RGB24; /* can't work yet, pixels are shorts */ else if (strncmp("x16", p, 3) == 0) return RGB16; else return RGB16;} static longsettingswrite(OScreen *scr, char *p){ if (strncmp("800x600", p, 7) == 0) { p += 7; scr->settings = &settings[Res800x600]; } else if (strncmp("1024x768", p, 8) == 0) { p += 8; scr->settings = &settings[Res1024x768]; } else if (strncmp("1280x1024", p, 9) == 0) { p += 9; scr->settings = &settings[Res1280x1024]; } else return -1; scr->settings->chan = getchans(p); return 1;} static longscreenread(Chan *c, void *a, long n, vlong off){ int len, depth; char *p; Settings *set; switch ((ulong)c->qid.path) { case Qdir: return devdirread(c, a, n, dsstab, nelem(dsstab), devgen); case Qdss: set = oscreen.settings; p = malloc(READSTR); if(waserror()){ free(p); nexterror(); } if (set->chan == RGB16) depth = 16; else if (set->chan == RGB24) depth = 24; else depth = 0; len = snprint(p, READSTR, "size %dx%dx%d @ %d Hz\n" "addr %#p size %ud\n", set->wid, set->ht, depth, set->freq, framebuf, sizeof *framebuf); USED(len); n = readstr(off, a, n, p); poperror(); free(p); return n; default: error(Egreg); } return 0;} static longscreenwrite(Chan *c, void *a, long n, vlong off){ switch ((ulong)c->qid.path) { case Qdss: if(off) error(Ebadarg); n = settingswrite(&oscreen, a); if (n < 0) error(Ebadctl); screeninit(); return n; default: error(Egreg); } return 0;} Dev dssdevtab = { L'v', "dss", devreset, devinit, devshutdown, // TODO add a shutdown to stop dma to monitor screenattach, screenwalk, screenstat, screenopen, devcreate, screenclose, screenread, devbread, screenwrite, devbwrite, devremove, devwstat,};
/*
* omap35 display subsystem (dss) device interface to screen.c.
* implements #v/vgactl
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
// #include "gamma.h"
enum {
Qdir,
Qdss,
};
extern OScreen oscreen;
extern Settings settings[];
extern Omap3fb *framebuf;
static QLock dsslck;
static Dirtab dsstab[] = {
".", {Qdir, 0, QTDIR}, 0, 0555|DMDIR,
"vgactl", {Qdss, 0}, 0, 0666,
};
static Chan*
screenattach(char *spec)
{
return devattach('v', spec);
}
static Walkqid*
screenwalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, dsstab, nelem(dsstab), devgen);
}
static int
screenstat(Chan *c, uchar *dp, int n)
{
return devstat(c, dp, n, dsstab, nelem(dsstab), devgen);
}
static Chan*
screenopen(Chan *c, int omode)
{
if ((ulong)c->qid.path == Qdss) {
qlock(&dsslck);
oscreen.open = 1;
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
}
return c;
}
static void
screenclose(Chan *c)
{
if ((c->qid.type & QTDIR) == 0 && c->flag & COPEN)
if (c->qid.path == Qdss) {
oscreen.open = 0;
qunlock(&dsslck);
}
}
static ulong
getchans(char *p)
{
if (strncmp("x24" , p, 3) == 0)
return RGB24; /* can't work yet, pixels are shorts */
else if (strncmp("x16", p, 3) == 0)
return RGB16;
else
return RGB16;
}
static long
settingswrite(OScreen *scr, char *p)
{
if (strncmp("800x600", p, 7) == 0) {
p += 7;
scr->settings = &settings[Res800x600];
} else if (strncmp("1024x768", p, 8) == 0) {
p += 8;
scr->settings = &settings[Res1024x768];
} else if (strncmp("1280x1024", p, 9) == 0) {
p += 9;
scr->settings = &settings[Res1280x1024];
} else
return -1;
scr->settings->chan = getchans(p);
return 1;
}
static long
screenread(Chan *c, void *a, long n, vlong off)
{
int len, depth;
char *p;
Settings *set;
switch ((ulong)c->qid.path) {
case Qdir:
return devdirread(c, a, n, dsstab, nelem(dsstab), devgen);
case Qdss:
set = oscreen.settings;
p = malloc(READSTR);
if(waserror()){
free(p);
nexterror();
}
if (set->chan == RGB16)
depth = 16;
else if (set->chan == RGB24)
depth = 24;
else
depth = 0;
len = snprint(p, READSTR, "size %dx%dx%d @ %d Hz\n"
"addr %#p size %ud\n", set->wid, set->ht, depth,
set->freq, framebuf, sizeof *framebuf);
USED(len);
n = readstr(off, a, n, p);
poperror();
free(p);
return n;
default:
error(Egreg);
}
return 0;
}
static long
screenwrite(Chan *c, void *a, long n, vlong off)
{
switch ((ulong)c->qid.path) {
case Qdss:
if(off)
error(Ebadarg);
n = settingswrite(&oscreen, a);
if (n < 0)
error(Ebadctl);
screeninit();
return n;
default:
error(Egreg);
}
return 0;
}
Dev dssdevtab = {
L'v',
"dss",
devreset,
devinit,
devshutdown, // TODO add a shutdown to stop dma to monitor
screenattach,
screenwalk,
screenstat,
screenopen,
devcreate,
screenclose,
screenread,
devbread,
screenwrite,
devbwrite,
devremove,
devwstat,
};