#define MODULE_BIT 0x00020000
#include "mga_std.h"
status_t g400_crtc2_set_timing(display_mode target)
{
uint32 temp;
LOG(4,("CRTC2: setting timing\n"));
if ((!(target.flags & TV_BITS)) || (si->ps.card_type <= G400MAX))
{
if ((target.timing.h_display & 0x07) | (target.timing.h_sync_start & 0x07) |
(target.timing.h_sync_end & 0x07) | (target.timing.h_total & 0x07))
{
LOG(8,("CRTC2: Horizontal timings are not multiples of 8 pixels\n"));
return B_ERROR;
}
CR2W(DATACTL, (CR2R(DATACTL) & ~0x00000010));
CR2W(CTL, (CR2R(CTL) & ~0x02001000));
CR2W(HPARAM, ((((target.timing.h_display - 8) & 0x0fff) << 16) |
((target.timing.h_total - 8) & 0x0fff)));
CR2W(HSYNC, ((((target.timing.h_sync_end - 8) & 0x0fff) << 16) |
((target.timing.h_sync_start - 8) & 0x0fff)));
CR2W(VPARAM, ((((target.timing.v_display - 1) & 0x0fff) << 16) |
((target.timing.v_total - 1) & 0x0fff)));
CR2W(VSYNC, ((((target.timing.v_sync_end - 1) & 0x0fff) << 16) |
((target.timing.v_sync_start - 1) & 0x0fff)));
CR2W(PRELOAD, ((((target.timing.v_sync_start - 1) & 0x0fff) << 16) |
((target.timing.h_sync_start - 8) & 0x0fff)));
temp = (0xfff << 16);
if (!(target.timing.flags & B_POSITIVE_HSYNC)) temp |= (0x01 << 8);
if (!(target.timing.flags & B_POSITIVE_VSYNC)) temp |= (0x01 << 9);
CR2W(MISC, temp);
if ((si->ps.secondary_head) && (!(target.flags & TV_BITS)))
gx00_maven_set_timing(target);
}
else
{
display_mode tv_mode = target;
uint8 frame;
unsigned int vcount, prev_vcount;
LOG(4,("CRTC2: setting up G450/G550 TVout mode\n"));
if ((tv_mode.timing.h_display & 0x07) | (tv_mode.timing.h_sync_start & 0x07) |
(tv_mode.timing.h_sync_end & 0x07))
{
LOG(8,("CRTC2: Horizontal timings are not multiples of 8 pixels\n"));
return B_ERROR;
}
CR2W(DATACTL, (CR2R(DATACTL) & ~0x00000010));
if (tv_mode.timing.h_total & 0x07)
{
LOG(4,("CRTC2: enabling clock killer circuitry\n"));
CR2W(DATACTL, (CR2R(DATACTL) | 0x00000010));
}
tv_mode.timing.h_total &= ~0x07;
tv_mode.timing.v_display >>= 1;
tv_mode.timing.v_sync_start >>= 1;
tv_mode.timing.v_sync_end >>= 1;
tv_mode.timing.v_total >>= 1;
CR2W(HPARAM, ((((tv_mode.timing.h_display - 8) & 0x0fff) << 16) |
((tv_mode.timing.h_total - 8) & 0x0fff)));
CR2W(HSYNC, ((((tv_mode.timing.h_sync_end - 8) & 0x0fff) << 16) |
((tv_mode.timing.h_sync_start - 8) & 0x0fff)));
CR2W(VPARAM, ((((tv_mode.timing.v_display - 1) & 0x0fff) << 16) |
((tv_mode.timing.v_total - 1) & 0x0fff)));
CR2W(VSYNC, ((((tv_mode.timing.v_sync_end - 1) & 0x0fff) << 16) |
((tv_mode.timing.v_sync_start - 1) & 0x0fff)));
CR2W(PRELOAD, ((((tv_mode.timing.v_sync_start - 1) & 0x0fff) << 16) |
((tv_mode.timing.h_sync_start - 8) & 0x0fff)));
CR2W(CTL, ((CR2R(CTL) & ~0x02000000) | 0x00001000));
prev_vcount = 0;
for (frame = 0; frame < 2; frame++)
{
for (;;)
{
vcount = (CR2R(VCOUNT) & 0x00000fff);
if (vcount >= prev_vcount)
prev_vcount = vcount;
else
break;
}
}
CR2W(CTL, (CR2R(CTL) | 0x02000000));
temp = (0xfff << 16);
if (!(tv_mode.timing.flags & B_POSITIVE_HSYNC)) temp |= (0x01 << 8);
if (!(tv_mode.timing.flags & B_POSITIVE_VSYNC)) temp |= (0x01 << 9);
CR2W(MISC, temp);
}
return B_OK;
}
status_t g400_crtc2_depth(int mode)
{
switch(mode)
{
case BPP16:case BPP32DIR:
CR2W(CTL,(CR2R(CTL)&0xFF10077F)|(mode<<21));
break;
case BPP8:case BPP15:case BPP24:case BPP32:default:
LOG(8,("CRTC2:Invalid bit depth\n"));
return B_ERROR;
break;
}
return B_OK;
}
status_t g400_crtc2_dpms(bool display, bool h, bool v)
{
char msg[100];
strlcpy(msg, "CRTC2: setting DPMS: ", sizeof(msg));
if (si->ps.card_type <= G400MAX)
{
if (display && h && v)
{
CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01));
strlcat(msg, "display on, hsync enabled, vsync enabled\n", sizeof(msg));
}
else
{
CR2W(CTL, (CR2R(CTL) & 0xFFF0177E));
strlcat(msg, "display off, hsync disabled, vsync disabled\n", sizeof(msg));
}
LOG(4, (msg));
if (si->ps.secondary_head) gx00_maven_dpms(display, h, v);
}
else
{
uint8 temp = 0x00;
if (display)
{
CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01));
strlcat(msg, "display on, ", sizeof(msg));
}
else
{
CR2W(CTL, (CR2R(CTL) & 0xFFF0177E));
strlcat(msg, "display off, ", sizeof(msg));
}
if (si->crossed_conns)
{
if (h)
{
temp &= ~0x01;
strlcat(msg, "hsync enabled, ", sizeof(msg));
}
else
{
temp |= 0x01;
strlcat(msg, "hsync disabled, ", sizeof(msg));
}
if (v)
{
temp &= ~0x02;
strlcat(msg, "vsync enabled\n", sizeof(msg));
}
else
{
temp |= 0x02;
strlcat(msg, "vsync disabled\n", sizeof(msg));
}
}
else
{
if (h)
{
temp &= ~0x10;
strlcat(msg, "hsync enabled, ", sizeof(msg));
}
else
{
temp |= 0x10;
strlcat(msg, "hsync disabled, ", sizeof(msg));
}
if (v)
{
temp &= ~0x20;
strlcat(msg, "vsync enabled\n", sizeof(msg));
}
else
{
temp |= 0x20;
strlcat(msg, "vsync disabled\n", sizeof(msg));
}
}
LOG(4, (msg));
DXIW(SYNCCTRL, temp);
}
return B_OK;
}
status_t g400_crtc2_set_display_pitch()
{
uint32 offset;
LOG(4,("CRTC2: setting card pitch (offset between lines)\n"));
offset = si->fbc.bytes_per_row;
if (si->interlaced_tv_mode)
{
LOG(4,("CRTC2: setting interlaced mode\n"));
offset *= 2;
}
else
LOG(4,("CRTC2: setting progressive scan mode\n"));
LOG(2,("CRTC2: offset set to %d bytes\n", offset));
CR2W(OFFSET,offset);
return B_OK;
}
status_t g400_crtc2_set_display_start(uint32 startadd,uint8 bpp)
{
LOG(4,("CRTC2: setting card RAM to be displayed for %d bits per pixel\n", bpp));
LOG(2,("CRTC2: startadd: $%x\n",startadd));
LOG(2,("CRTC2: frameRAM: $%x\n",si->framebuffer));
LOG(2,("CRTC2: framebuffer: $%x\n",si->fbc.frame_buffer));
if (si->interlaced_tv_mode)
{
LOG(4,("CRTC2: setting up fields for interlaced mode\n"));
CR2W(STARTADD0, (startadd + si->fbc.bytes_per_row));
CR2W(STARTADD1, startadd);
}
else
{
LOG(4,("CRTC2: setting up frames for progressive scan mode\n"));
CR2W(STARTADD0, startadd);
}
return B_OK;
}