#include <Debug.h>
#include "Capture.h"
CCapture::CCapture(CRadeon & radeon)
: fRadeon(radeon),
fMode(C_RADEON_CAPTURE_FIELD_SINGLE),
fFormat(C_RADEON_CAPTURE_CCIR656),
fOffset0(0),
fOffset1(0),
fVBIOffset0(0),
fVBIOffset1(0),
fSize(0),
fVBISize(0),
fPitch(0),
fClip(),
fVBIClip()
{
PRINT(("CCapture::CCapture()\n"));
}
CCapture::~CCapture()
{
PRINT(("CCapture::~CCapture()\n"));
}
status_t CCapture::InitCheck() const
{
return fRadeon.InitCheck();
}
void CCapture::SetBuffer(capture_stream_format format, capture_buffer_mode mode,
int offset0, int offset1, int size, int pitch)
{
PRINT(("CCapture::SetBuffer(%s, %s, 0x%08x, 0x%08x, 0x%08x, %d)\n",
"BROOKTREE\0CCIR656\0\0\0ZVIDEO\0\0\0\0VIP"+10*format,
"FIELD-SINGLE\0FIELD-DOUBLE\0BOB-SINGLE\0\0\0"
"BOB-DOUBLE\0\0\0WEAVE-SINGLE\0WEAVE-DOUBLE"+13*mode,
offset0, offset1, size, pitch));
fMode = mode;
fFormat = format;
fOffset0 = offset0 + fRadeon.VirtualMemoryBase();
fOffset1 = offset1 + fRadeon.VirtualMemoryBase();
fSize = size;
fPitch = pitch;
}
void CCapture::SetClip(int left, int top, int right, int bottom)
{
PRINT(("CCapture::SetClip(%d, %d, %d, %d)\n",
left, top, right, bottom));
fClip.SetTo(left, top, right, bottom);
}
void CCapture::SetVBIBuffer(int offset0, int offset1, int size)
{
PRINT(("CCapture::SetVBIBuffer(0x%08x, 0x%08x, %d)\n", offset0, offset1, size));
fVBIOffset0 = offset0 + fRadeon.VirtualMemoryBase();
fVBIOffset1 = offset1 + fRadeon.VirtualMemoryBase();
fVBISize = size;
}
void CCapture::SetVBIClip(int left, int top, int right, int bottom)
{
PRINT(("CCapture::SetVBIClip(%d, %d, %d, %d)\n",
left, top, right, bottom));
fVBIClip.SetTo(left, top, right, bottom);
}
void CCapture::Start(bool vbi)
{
PRINT(("CCapture::Start(%d)\n", vbi));
SetRegister(C_RADEON_CAP0_TRIG_CNTL, C_RADEON_CAP0_TRIGGER_W_NO_ACTION);
switch (fMode) {
case C_RADEON_CAPTURE_FIELD_SINGLE:
SetRegister(C_RADEON_CAP0_BUF0_OFFSET, fOffset0);
SetRegister(C_RADEON_CAP0_BUF_PITCH, fPitch << 1);
break;
case C_RADEON_CAPTURE_FIELD_DOUBLE:
SetRegister(C_RADEON_CAP0_BUF0_OFFSET, fOffset0);
SetRegister(C_RADEON_CAP0_BUF1_OFFSET, fOffset1);
SetRegister(C_RADEON_CAP0_BUF_PITCH, fPitch << 1);
break;
case C_RADEON_CAPTURE_BOB_SINGLE:
SetRegister(C_RADEON_CAP0_BUF0_OFFSET, fOffset0);
SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET, fOffset0 + fSize);
SetRegister(C_RADEON_CAP0_BUF_PITCH, fPitch << 1);
break;
case C_RADEON_CAPTURE_BOB_DOUBLE:
SetRegister(C_RADEON_CAP0_BUF0_OFFSET, fOffset0);
SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET, fOffset0 + fSize);
SetRegister(C_RADEON_CAP0_BUF1_OFFSET, fOffset1);
SetRegister(C_RADEON_CAP0_BUF1_EVEN_OFFSET, fOffset1 + fSize);
SetRegister(C_RADEON_CAP0_BUF_PITCH, fPitch << 1);
break;
case C_RADEON_CAPTURE_WEAVE_SINGLE:
SetRegister(C_RADEON_CAP0_BUF0_OFFSET, fOffset0);
SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET, fOffset0 + (fPitch << 1));
SetRegister(C_RADEON_CAP0_BUF_PITCH, fPitch << 2);
break;
case C_RADEON_CAPTURE_WEAVE_DOUBLE:
SetRegister(C_RADEON_CAP0_BUF0_OFFSET, fOffset0);
SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET, fOffset0 + (fPitch << 1));
SetRegister(C_RADEON_CAP0_BUF1_OFFSET, fOffset1);
SetRegister(C_RADEON_CAP0_BUF1_EVEN_OFFSET, fOffset1 + (fPitch << 1));
SetRegister(C_RADEON_CAP0_BUF_PITCH, fPitch << 2);
break;
}
SetRegister(C_RADEON_CAP0_VBI0_OFFSET, fVBIOffset0);
SetRegister(C_RADEON_CAP0_VBI1_OFFSET, fVBIOffset0 + fVBISize);
SetRegister(C_RADEON_CAP0_VBI2_OFFSET, fVBIOffset1);
SetRegister(C_RADEON_CAP0_VBI3_OFFSET, fVBIOffset1 + fVBISize);
SetRegister(C_RADEON_CAP0_H_WINDOW,
((fClip.Left() << 1) & C_RADEON_CAP0_H_START) |
((fClip.Width() << 17) & C_RADEON_CAP0_H_WIDTH));
SetRegister(C_RADEON_CAP0_V_WINDOW,
((fClip.Top() << 0) & C_RADEON_CAP0_V_START) |
((fClip.Bottom() << 16) & C_RADEON_CAP0_V_END));
SetRegister(C_RADEON_CAP0_VBI_H_WINDOW,
((fVBIClip.Left() << 0) & C_RADEON_CAP0_VBI_H_START) |
((fVBIClip.Width() << 16) & C_RADEON_CAP0_VBI_H_WIDTH));
SetRegister(C_RADEON_CAP0_VBI_V_WINDOW,
((fVBIClip.Top() << 0) & C_RADEON_CAP0_VBI_V_START) |
((fVBIClip.Bottom() << 16) & C_RADEON_CAP0_VBI_V_END));
switch (fMode) {
case C_RADEON_CAPTURE_FIELD_SINGLE:
case C_RADEON_CAPTURE_FIELD_DOUBLE:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_BUF_TYPE, C_RADEON_CAP0_BUF_TYPE_FIELD);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_ONESHOT_MODE, C_RADEON_CAP0_ONESHOT_MODE_FIELD);
break;
case C_RADEON_CAPTURE_BOB_SINGLE:
case C_RADEON_CAPTURE_BOB_DOUBLE:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_BUF_TYPE, C_RADEON_CAP0_BUF_TYPE_ALTERNATING);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_ONESHOT_MODE, C_RADEON_CAP0_ONESHOT_MODE_FIELD);
break;
case C_RADEON_CAPTURE_WEAVE_SINGLE:
case C_RADEON_CAPTURE_WEAVE_DOUBLE:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_BUF_TYPE, C_RADEON_CAP0_BUF_TYPE_FRAME);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_ONESHOT_MODE, C_RADEON_CAP0_ONESHOT_MODE_FRAME);
break;
}
switch (fMode) {
case C_RADEON_CAPTURE_FIELD_SINGLE:
case C_RADEON_CAPTURE_BOB_SINGLE:
case C_RADEON_CAPTURE_WEAVE_SINGLE:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_BUF_MODE, C_RADEON_CAP0_BUF_MODE_SINGLE);
break;
case C_RADEON_CAPTURE_FIELD_DOUBLE:
case C_RADEON_CAPTURE_BOB_DOUBLE:
case C_RADEON_CAPTURE_WEAVE_DOUBLE:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_BUF_MODE, C_RADEON_CAP0_BUF_MODE_DOUBLE);
break;
}
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_INPUT_MODE, C_RADEON_CAP0_INPUT_MODE_CONTINUOUS);
SetRegister(C_RADEON_CAP0_CONFIG,
C_RADEON_CAP0_VIDEO_IN_FORMAT | C_RADEON_CAP0_VIDEO_SIGNED_UV, C_RADEON_CAP0_VIDEO_IN_VYUY422);
switch (fFormat) {
case C_RADEON_CAPTURE_BROOKTREE:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_STREAM_FORMAT, C_RADEON_CAP0_STREAM_BROOKTREE);
SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL, C_RADEON_CAP0_PORT_WIDTH_8_BITS | C_RADEON_CAP0_PORT_LOWER_BYTE_USED);
break;
case C_RADEON_CAPTURE_CCIR656:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_STREAM_FORMAT, C_RADEON_CAP0_STREAM_CCIR656);
SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL, C_RADEON_CAP0_PORT_WIDTH_8_BITS | C_RADEON_CAP0_PORT_LOWER_BYTE_USED);
break;
case C_RADEON_CAPTURE_ZOOMVIDEO:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_STREAM_FORMAT, C_RADEON_CAP0_STREAM_ZV);
SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL, C_RADEON_CAP0_PORT_WIDTH_16_BITS | C_RADEON_CAP0_PORT_LOWER_BYTE_USED);
break;
case C_RADEON_CAPTURE_VIP:
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_STREAM_FORMAT, C_RADEON_CAP0_STREAM_VIP);
SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL, C_RADEON_CAP0_PORT_WIDTH_16_BITS | C_RADEON_CAP0_PORT_LOWER_BYTE_USED);
break;
}
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_MIRROR_EN, 0);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_ONESHOT_MIRROR_EN, 0);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_START_FIELD, C_RADEON_CAP0_START_ODD_FIELD);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_HORZ_DOWN, C_RADEON_CAP0_HORZ_DOWN_1X);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_VERT_DOWN, C_RADEON_CAP0_VERT_DOWN_1X);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_VBI_HORZ_DOWN, C_RADEON_CAP0_VBI_HORZ_DOWN_1X);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_HDWNS_DEC, C_RADEON_CAP0_DECIMATOR);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_SOFT_PULL_DOWN_EN, C_RADEON_CAP0_SOFT_PULL_DOWN_EN);
SetRegister(C_RADEON_TEST_DEBUG_CNTL, 0);
SetRegister(C_RADEON_CAP0_VIDEO_SYNC_TEST, 0);
SetRegister(C_RADEON_CAP0_DEBUG, C_RADEON_CAP0_V_SYNC);
SetRegister(C_RADEON_VIDEOMUX_CNTL, 1, 1);
SetRegister(C_RADEON_FCP_CNTL, C_RADEON_FCP0_SRC_PCLK);
SetRegister(C_RADEON_CAP0_TRIG_CNTL,
C_RADEON_CAP0_TRIGGER_W_CAPTURE | C_RADEON_CAP0_EN);
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_VBI_EN,
(vbi ? C_RADEON_CAP0_VBI_EN : 0));
}
void CCapture::Stop()
{
PRINT(("CCapture::Stop()\n"));
SetRegister(C_RADEON_CAP0_TRIG_CNTL, C_RADEON_CAP0_TRIGGER_W_NO_ACTION);
fRadeon.SetRegister(C_RADEON_FCP_CNTL, C_RADEON_FCP0_SRC_GND);
}
void CCapture::SetInterrupts(bool enable)
{
PRINT(("CCapture::SetInterrupts(%d)\n", enable));
fRadeon.SetRegister(C_RADEON_CAP_INT_CNTL,
C_RADEON_CAP0_BUF0_INT_EN | C_RADEON_CAP0_BUF0_EVEN_INT_EN |
C_RADEON_CAP0_BUF1_INT_EN | C_RADEON_CAP0_BUF1_EVEN_INT_EN |
C_RADEON_CAP0_VBI0_INT_EN | C_RADEON_CAP0_VBI1_INT_EN,
(enable ? C_RADEON_CAP0_BUF0_INT_EN | C_RADEON_CAP0_BUF0_EVEN_INT_EN |
C_RADEON_CAP0_BUF1_INT_EN | C_RADEON_CAP0_BUF1_EVEN_INT_EN |
C_RADEON_CAP0_VBI0_INT_EN | C_RADEON_CAP0_VBI1_INT_EN : 0));
fRadeon.SetRegister(C_RADEON_CAP_INT_STATUS,
C_RADEON_CAP0_BUF0_INT_AK | C_RADEON_CAP0_BUF0_EVEN_INT_AK |
C_RADEON_CAP0_BUF1_INT_AK | C_RADEON_CAP0_BUF1_EVEN_INT_AK |
C_RADEON_CAP0_VBI0_INT_AK | C_RADEON_CAP0_VBI1_INT_AK);
}
int CCapture::WaitInterrupts(int * sequence, bigtime_t * when, bigtime_t timeout)
{
int mask;
if (fRadeon.WaitInterrupt(&mask, sequence, when, timeout) == B_OK) {
return
((mask & C_RADEON_CAP0_BUF0_INT) != 0 ? C_RADEON_CAPTURE_BUF0_INT : 0) |
((mask & C_RADEON_CAP0_BUF1_INT) != 0 ? C_RADEON_CAPTURE_BUF1_INT : 0) |
((mask & C_RADEON_CAP0_BUF0_EVEN_INT) != 0 ? C_RADEON_CAPTURE_BUF0_EVEN_INT : 0) |
((mask & C_RADEON_CAP0_BUF1_EVEN_INT) != 0 ? C_RADEON_CAPTURE_BUF1_EVEN_INT : 0) |
((mask & C_RADEON_CAP0_VBI0_INT) != 0 ? C_RADEON_CAPTURE_VBI0_INT : 0) |
((mask & C_RADEON_CAP0_VBI1_INT) != 0 ? C_RADEON_CAPTURE_VBI1_INT : 0);
}
return 0;
}
int CCapture::Register(radeon_register index, int mask)
{
return fRadeon.Register(index, mask);
}
void CCapture::SetRegister(radeon_register index, int value)
{
fRadeon.SetRegister(index, value);
}
void CCapture::SetRegister(radeon_register index, int mask, int value)
{
fRadeon.SetRegister(index, mask, value);
}