Add support for enumerating video modes using the Milan API and the ST/TT XBIOS calls. Not really tested, ARAnyM doesn't emulate the Milan stuff, and the ST resolutions aren't exactly chunky anyway (will need patching the framebuffer kernel args to include the mode/4CC instead of just bit depth).

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42640 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2011-08-19 12:12:22 +00:00
parent e45efadaad
commit f62ad34221

View File

@ -25,7 +25,7 @@
#include <string.h>
//#define TRACE_VIDEO
#define TRACE_VIDEO
#ifdef TRACE_VIDEO
# define TRACE(x) dprintf x
#else
@ -204,6 +204,202 @@ ModeOps::MakeLabel(const struct video_mode *mode, char *label, size_t len)
}
// #pragma mark - ST/TT XBIOS API
class STModeOps : public ModeOps {
public:
STModeOps() : ModeOps("ST/TT") {};
~STModeOps() {};
virtual status_t Init();
virtual status_t Enumerate();
virtual status_t Decode(int16 id, struct video_mode *mode);
virtual status_t Get(struct video_mode *mode);
virtual status_t Set(const struct video_mode *mode);
virtual status_t Unset(const struct video_mode *mode);
virtual status_t SetPalette(const struct video_mode *mode,
const uint8 *palette);
virtual addr_t Framebuffer();
virtual void MakeLabel(const struct video_mode *mode,
char *label, size_t len);
private:
static int16 fPreviousMode;
static bool fIsTT;
};
int16 STModeOps::fPreviousMode = -1;
bool STModeOps::fIsTT = false;
status_t
STModeOps::Init()
{
const tos_cookie *c = tos_find_cookie('_VDO');
if (c == NULL)
return ENODEV;
if (c->ivalue >> 16 < 1)
return ENODEV;
if (c->ivalue >= 2)
fIsTT = true;
fInitStatus = B_OK;
return fInitStatus;
}
status_t
STModeOps::Enumerate()
{
if (fInitStatus < B_OK)
return fInitStatus;
static int16 modes[] = { 0, /*TT:*/ 4, 7 };
for (int i = 0; i < sizeof(modes) / sizeof(int16); i++) {
if (!fIsTT && i > 0)
break;
video_mode *videoMode = AllocMode();
if (videoMode == NULL)
continue;
if (Decode(modes[i], videoMode) != B_OK)
continue;
add_video_mode(videoMode);
}
return B_OK;
#if 0
// TODO: use TT video monitor detection and build possible mode list there...
return ENODEV;
#endif
}
status_t
STModeOps::Decode(int16 id, struct video_mode *mode)
{
mode->ops = this;
mode->mode = id;
switch (id) {
case 0:
mode->width = 320;
mode->height = 200;
mode->bits_per_pixel = 4;
break;
case 4:
mode->width = 640;
mode->height = 480;
mode->bits_per_pixel = 4;
break;
case 7:
mode->width = 320;
mode->height = 480;
mode->bits_per_pixel = 8;
break;
default:
mode->bits_per_pixel = 0;
break;
}
mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8;
return B_OK;
}
status_t
STModeOps::Get(struct video_mode *mode)
{
if (fInitStatus < B_OK)
return fInitStatus;
int16 m = Getrez();
return Decode(m, mode);
}
status_t
STModeOps::Set(const struct video_mode *mode)
{
if (fInitStatus < B_OK)
return fInitStatus;
if (mode == NULL)
return B_BAD_VALUE;
fPreviousMode = Getrez();
#warning M68K: FIXME: allocate framebuffer
dprintf("Switching to mode 0x%04x\n", mode->mode);
//VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode);
Setscreen(-1, -1, mode->mode, 0);
if (Getrez() != mode->mode) {
dprintf("failed to set mode %d. Current is %d\n", mode->mode, fPreviousMode);
fPreviousMode = -1;
}
return B_OK;
}
status_t
STModeOps::Unset(const struct video_mode *mode)
{
if (fInitStatus < B_OK)
return fInitStatus;
if (fPreviousMode != -1) {
dprintf("Reverting to mode 0x%04x\n", fPreviousMode);
Setscreen(-1, -1, fPreviousMode, 0);
fPreviousMode = -1;
}
return B_OK;
}
status_t
STModeOps::SetPalette(const struct video_mode *mode, const uint8 *palette)
{
switch (mode->bits_per_pixel) {
case 4:
//VsetRGB(0, 16, palette);
//XXX: Use ESet*
break;
case 8:
//VsetRGB(0, 256, palette);
//XXX: Use ESet*
break;
default:
break;
}
}
addr_t
STModeOps::Framebuffer()
{
addr_t fb = (addr_t)Physbase();
return fb;
}
void
STModeOps::MakeLabel(const struct video_mode *mode, char *label,
size_t len)
{
ModeOps::MakeLabel(mode, label, len);
label += strlen(label);
// XXX no len check
sprintf(label, " 0x%04x", mode->mode);
}
static STModeOps sSTModeOps;
// #pragma mark - Falcon XBIOS API
class FalconModeOps : public ModeOps {
@ -345,7 +541,9 @@ FalconModeOps::Set(const struct video_mode *mode)
#warning M68K: FIXME: allocate framebuffer
dprintf("Switching to mode 0x%04x\n", mode->mode);
VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode);
//VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode);
VsetScreen(((uint32)0x00c00000), ((uint32)0x00c00000), 3, mode->mode);
//VsetScreen(((uint32)-1), ((uint32)-1), 3, mode->mode);
return B_OK;
}
@ -412,6 +610,221 @@ FalconModeOps::MakeLabel(const struct video_mode *mode, char *label,
static FalconModeOps sFalconModeOps;
// #pragma mark - Milan XBIOS API
class MilanModeOps : public ModeOps {
public:
MilanModeOps() : ModeOps("Milan") {};
~MilanModeOps() {};
virtual status_t Init();
virtual status_t Enumerate();
virtual status_t Decode(int16 id, struct video_mode *mode);
virtual status_t Get(struct video_mode *mode);
virtual status_t Set(const struct video_mode *mode);
virtual status_t Unset(const struct video_mode *mode);
virtual status_t SetPalette(const struct video_mode *mode,
const uint8 *palette);
virtual addr_t Framebuffer();
virtual void MakeLabel(const struct video_mode *mode,
char *label, size_t len);
private:
static int16 fPreviousMode;
};
int16 MilanModeOps::fPreviousMode = -1;
status_t
MilanModeOps::Init()
{
const tos_cookie *c = tos_find_cookie('_MIL');
if (c == NULL)
return ENODEV;
fInitStatus = B_OK;
return fInitStatus;
}
status_t
MilanModeOps::Enumerate()
{
if (fInitStatus < B_OK)
return fInitStatus;
SCREENINFO info;
info.size = sizeof(info);
static int16 modes[] = {
0x001b, 0x001c, 0x002b, 0x002c,
0x003a, 0x003b, 0x003c, 0x000c,
0x0034, 0x0004
/*0x003a, 0x003b, 0x0003, 0x000c,
0x000b, 0x0033, 0x000c, 0x001c*/ };
for (int i = 0; i < sizeof(modes) / sizeof(int16); i++) {
video_mode *videoMode = AllocMode();
if (videoMode == NULL)
continue;
if (Decode(modes[i], videoMode) != B_OK)
continue;
add_video_mode(videoMode);
}
return B_OK;
#if 0
// TODO: use Milan video monitor detection and build possible mode list there...
int16 monitor;
bool vga = false;
bool tv = false;
monitor = VgetMonitor();
switch (monitor) {
case 0:
panic("Monochrome ?\n");
break;
case 2:
vga = true;
break;
case 3:
tv = true;
break;
//case 4 & 5: check for CT60
case 1:
default:
dprintf("monitor type %d\n", monitor);
break;
}
return ENODEV;
#endif
}
status_t
MilanModeOps::Decode(int16 id, struct video_mode *mode)
{
SCREENINFO info;
info.size = sizeof(info);
info.devID = mode->mode;
info.scrFlags = 0;
mode->ops = this;
mode->mode = id;
Setscreen(-1,&info,MI_MAGIC,CMD_GETINFO);
if (info.scrFlags & SCRINFO_OK == 0)
return B_ERROR;
// cf. F30.TXT
mode->width = info.scrWidth;
mode->height = info.scrHeight;
mode->bits_per_pixel = info.scrPlanes;
mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8;
return B_OK;
}
status_t
MilanModeOps::Get(struct video_mode *mode)
{
if (fInitStatus < B_OK)
return fInitStatus;
int16 m = -1;
Setscreen(-1,&m,MI_MAGIC,CMD_GETMODE);
if (m == -1)
return B_ERROR;
return Decode(m, mode);
}
status_t
MilanModeOps::Set(const struct video_mode *mode)
{
if (fInitStatus < B_OK)
return fInitStatus;
if (mode == NULL)
return B_BAD_VALUE;
Setscreen(-1,&fPreviousMode,MI_MAGIC,CMD_GETMODE);
#warning M68K: FIXME: allocate framebuffer
dprintf("Switching to mode 0x%04x\n", mode->mode);
//VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode);
//VsetScreen(((uint32)-1), ((uint32)-1), 3, mode->mode);
Setscreen(-1,mode->mode,MI_MAGIC,CMD_SETMODE);
return B_OK;
}
status_t
MilanModeOps::Unset(const struct video_mode *mode)
{
if (fInitStatus < B_OK)
return fInitStatus;
if (fPreviousMode != -1) {
dprintf("Reverting to mode 0x%04x\n", fPreviousMode);
Setscreen(-1,fPreviousMode,MI_MAGIC,CMD_SETMODE);
fPreviousMode = -1;
}
return B_OK;
}
status_t
MilanModeOps::SetPalette(const struct video_mode *mode, const uint8 *palette)
{
switch (mode->bits_per_pixel) {
case 4:
//VsetRGB(0, 16, palette);
break;
case 8:
//VsetRGB(0, 256, palette);
break;
default:
break;
}
}
addr_t
MilanModeOps::Framebuffer()
{
//XXX
addr_t fb = (addr_t)Physbase();
return fb;
}
void
MilanModeOps::MakeLabel(const struct video_mode *mode, char *label,
size_t len)
{
ModeOps::MakeLabel(mode, label, len);
label += strlen(label);
// XXX no len check
int16 m = mode->mode;
sprintf(label, " 0x%04x", mode->mode);
/*sprintf(label, "%s%s%s%s",
m & 0x0010 ? " vga" : " tv",
m & 0x0020 ? " pal" : "",
m & 0x0040 ? " oscan" : "",
//m & 0x0080 ? " tv" : "",
m & 0x0100 ? " ilace" : "");*/
}
static MilanModeOps sMilanModeOps;
// #pragma mark - ARAnyM NFVDI API
/* NatFeat VDI */
@ -723,7 +1136,7 @@ platform_switch_to_logo(void)
}
gKernelArgs.frame_buffer.enabled = true;
#if 0
#if 1
// If the new frame buffer is either larger than the old one or located at
// a different address, we need to remap it, so we first have to throw
// away its previous mapping
@ -777,7 +1190,11 @@ platform_init_video(void)
//sNFVDIModeOps.Init();
//sNFVDIModeOps.Enumerate();
if (sFalconModeOps.Init() == B_OK) {
if (sMilanModeOps.Init() == B_OK) {
sMilanModeOps.Enumerate();
} else if (sSTModeOps.Init() == B_OK) {
sSTModeOps.Enumerate();
} else if (sFalconModeOps.Init() == B_OK) {
sFalconModeOps.Enumerate();
} else {
dprintf("No usable video API found\n");