Add video in support included with version 4.1 of the radeon driver.
Feel free to relocate if I have guessed the wrong destination for this stuff. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8407 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -6,6 +6,7 @@ SubDir OBOS_TOP src add-ons media media-add-ons ;
|
||||
SubInclude OBOS_TOP src add-ons media media-add-ons legacy ;
|
||||
SubInclude OBOS_TOP src add-ons media media-add-ons mixer ;
|
||||
SubInclude OBOS_TOP src add-ons media media-add-ons multi_audio ;
|
||||
SubInclude OBOS_TOP src add-ons media media-add-ons radeon ;
|
||||
SubInclude OBOS_TOP src add-ons media media-add-ons tone_producer_demo ;
|
||||
SubInclude OBOS_TOP src add-ons media media-add-ons video_producer_demo ;
|
||||
|
||||
|
||||
@@ -0,0 +1,828 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: CC.cpp
|
||||
/
|
||||
/ Description: Closed caption module.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Debug.h>
|
||||
#include "CC.h"
|
||||
|
||||
CCaption::CCaption(CCapture & capture)
|
||||
: fCapture(capture),
|
||||
fChannel(C_RADEON_CC1),
|
||||
fRow(0),
|
||||
fColumn(0),
|
||||
fColor(0),
|
||||
fLastControlCode(0)
|
||||
{
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++) {
|
||||
fText[row][column] = fDisplayText[row][column] = 0x0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCaption::~CCaption()
|
||||
{
|
||||
}
|
||||
|
||||
status_t CCaption::InitCheck() const
|
||||
{
|
||||
return fCapture.InitCheck();
|
||||
}
|
||||
|
||||
void CCaption::SetMode(cc_mode mode)
|
||||
{
|
||||
fChannel = mode;
|
||||
fLastControlCode = 0;
|
||||
}
|
||||
|
||||
bool CCaption::DecodeBits(const unsigned char * buffer, int & data)
|
||||
{
|
||||
// assume the buffer is long enough (at least VBI line width bytes)
|
||||
if (buffer == NULL)
|
||||
return false;
|
||||
|
||||
// compute low/high levels
|
||||
int low = 0xff, high = 0x00;
|
||||
for (int offset = C_RADEON_CC_BLANK_START; offset < C_RADEON_CC_BLANK_START + 4 * C_RADEON_CC_BIT_DURATION; offset++) {
|
||||
if (low > buffer[offset])
|
||||
low = buffer[offset];
|
||||
if (high < buffer[offset])
|
||||
high = buffer[offset];
|
||||
}
|
||||
if (low + C_RADEON_CC_LEVEL_THRESHOLD >= high)
|
||||
return false;
|
||||
|
||||
const int middle = (low + high) >> 1;
|
||||
|
||||
// find position of the first pulse
|
||||
int start = C_RADEON_CC_BLANK_START + C_RADEON_CC_BIT_DURATION;
|
||||
while (start <= C_RADEON_CC_BLANK_START + 4 * C_RADEON_CC_BIT_DURATION) {
|
||||
if (buffer[start + 0] < middle && buffer[start + 1] < middle &&
|
||||
buffer[start + 3] > middle && buffer[start + 4] > middle)
|
||||
break;
|
||||
start++;
|
||||
}
|
||||
if (start >= C_RADEON_CC_BLANK_START + 4 * C_RADEON_CC_BIT_DURATION)
|
||||
return false;
|
||||
|
||||
// compute position of the last pulse
|
||||
int end = start + 17 * C_RADEON_CC_BIT_DURATION;
|
||||
|
||||
// start in middle of first pulse
|
||||
int bit = 0;
|
||||
bool one = true;
|
||||
for (int offset = start + C_RADEON_CC_BIT_DURATION / 2; offset < end; offset++) {
|
||||
int width = 1;
|
||||
|
||||
// search the next pulse front
|
||||
while (offset < end) {
|
||||
if (one) {
|
||||
if (buffer[offset + 0] > middle && buffer[offset + 1] > middle &&
|
||||
buffer[offset + 3] < middle && buffer[offset + 4] < middle)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (buffer[offset + 0] < middle && buffer[offset + 1] < middle &&
|
||||
buffer[offset + 3] > middle && buffer[offset + 4] > middle)
|
||||
break;
|
||||
}
|
||||
offset++;
|
||||
width++;
|
||||
}
|
||||
|
||||
// compute pulse width in bits
|
||||
const int nbits = (width + (bit == 0 ? 0 : bit == 15 ? C_RADEON_CC_BIT_DURATION :
|
||||
C_RADEON_CC_BIT_DURATION / 2)) / C_RADEON_CC_BIT_DURATION;
|
||||
data >>= nbits;
|
||||
if (one)
|
||||
data |= (0xffff << (16 - nbits)) & 0xffff;
|
||||
|
||||
if ((bit += nbits) >= C_RADEON_CC_BITS_PER_FIELD)
|
||||
break;
|
||||
|
||||
one = !one;
|
||||
}
|
||||
|
||||
if (bit != C_RADEON_CC_BITS_PER_FIELD)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCaption::Decode(const unsigned char * buffer0,
|
||||
const unsigned char * buffer1)
|
||||
{
|
||||
enum caption_code {
|
||||
/* channel */
|
||||
C_CC1 = 0x0000,
|
||||
C_CC2 = 0x0800,
|
||||
|
||||
/* address */
|
||||
C_ROW_1 = 0x0100,
|
||||
C_ROW_2 = 0x0120,
|
||||
C_ROW_3 = 0x0200,
|
||||
C_ROW_4 = 0x0220,
|
||||
C_ROW_5 = 0x0500,
|
||||
C_ROW_6 = 0x0520,
|
||||
C_ROW_7 = 0x0600,
|
||||
C_ROW_8 = 0x0620,
|
||||
C_ROW_9 = 0x0700,
|
||||
C_ROW_10 = 0x0720,
|
||||
C_ROW_11 = 0x0000,
|
||||
C_ROW_12 = 0x0300,
|
||||
C_ROW_13 = 0x0320,
|
||||
C_ROW_14 = 0x0400,
|
||||
C_ROW_15 = 0x0420,
|
||||
|
||||
/* color */
|
||||
C_WHITE = 0x0000,
|
||||
C_GREEN = 0x0002,
|
||||
C_BLUE = 0x0004,
|
||||
C_CYAN = 0x0006,
|
||||
C_RED = 0x0008,
|
||||
C_YELLOW = 0x000a,
|
||||
C_MAGENTA = 0x000c,
|
||||
C_ITALICS = 0x000e,
|
||||
|
||||
/* underline */
|
||||
C_NORMAL = 0x0000,
|
||||
C_UNDERLINE = 0x0001,
|
||||
|
||||
/* control */
|
||||
C_RCL = 0x0000, // resume caption loading
|
||||
C_BS = 0x0001, // backspace
|
||||
C_AOF = 0x0002, // alarm off
|
||||
C_AON = 0x0003, // alarm on
|
||||
C_DER = 0x0004, // delete to end of row
|
||||
C_RU2 = 0x0005, // roll-up captions (2 rows)
|
||||
C_RU3 = 0x0006, // roll-up captions (3 rows)
|
||||
C_RU4 = 0x0007, // roll-up captions (4 rows)
|
||||
C_FON = 0x0008, // flash on
|
||||
C_RDC = 0x0009, // resume direct captioning
|
||||
C_TR = 0x000a, // text restart
|
||||
C_RTD = 0x000b, // resume text display
|
||||
C_EDM = 0x000c, // erase displayed memory
|
||||
C_CR = 0x000d, // carriage return
|
||||
C_ENM = 0x000e, // erase non-displayed memory
|
||||
C_EOC = 0x000f, // end of caption
|
||||
|
||||
/* special character */
|
||||
C_reg = 0x0000, // registered
|
||||
C_deg = 0x0001, // degree
|
||||
C_frac12 = 0x0002, // fraction 1/2
|
||||
C_iquest = 0x0003, // invert question
|
||||
C_trademark = 0x0004, // trademark
|
||||
C_cent = 0x0005, // cent
|
||||
C_pound = 0x0006, // pound
|
||||
C_music = 0x0007, // music note
|
||||
C_agrave = 0x0008, // agrave
|
||||
C_tspace = 0x0009, // transparent space
|
||||
C_egrave = 0x000a, // egrave
|
||||
C_acirc = 0x000b, // a circ
|
||||
C_ecirc = 0x000c, // e circ
|
||||
C_icirc = 0x000d, // i circ
|
||||
C_ocirc = 0x000e, // o circ
|
||||
C_ucirc = 0x000f, // u circ
|
||||
|
||||
/* standard character (ASCII) */
|
||||
C_aacute = 0x002a, // a acute accent
|
||||
C_eacute = 0x005c, // e acute accent
|
||||
C_iacute = 0x005e, // i acute accent
|
||||
C_oacute = 0x005f, // o acute accent
|
||||
C_uacute = 0x0060, // u acute accent
|
||||
C_ccedil = 0x007b, // c cedilla
|
||||
C_division = 0x007c, // division sign
|
||||
C_Ntilde = 0x007d, // N tilde
|
||||
C_ntilde = 0x007e, // n tilde
|
||||
C_block = 0x007f // solid block
|
||||
};
|
||||
|
||||
int code, channel, character;
|
||||
|
||||
/* decode next pair of bytes from the odd or even field buffer */
|
||||
if (!DecodeBits(fChannel == C_RADEON_CC1 || fChannel == C_RADEON_CC2 ? buffer0 : buffer1, code))
|
||||
return false;
|
||||
|
||||
/* swap decoded bytes */
|
||||
code = ((code << 8) & 0xff00) | ((code >> 8) & 0x00ff);
|
||||
|
||||
/* check parity */
|
||||
for (int bit = 0; bit < 7; bit++) {
|
||||
if ((code & (0x0001 << bit)) != 0)
|
||||
code ^= 0x0080;
|
||||
if ((code & (0x0100 << bit)) != 0)
|
||||
code ^= 0x8000;
|
||||
}
|
||||
if ((code & 0x8080) != 0x8080) {
|
||||
PRINT(("CCaption::Decode() - parity error (%04X)\n", code));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check channel number */
|
||||
channel = (code & 0x0800) >> 12;
|
||||
if (channel == 0) {
|
||||
if (fChannel != C_RADEON_CC1 && fChannel != C_RADEON_CC3) {
|
||||
PRINT(("CCaption::Decode() - ignore channel (%02X)\n", code & 0x7f7f));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fChannel != C_RADEON_CC2 && fChannel != C_RADEON_CC4) {
|
||||
PRINT(("CCaption::Decode() - ignore channel (%02X)\n", code & 0x7f7f));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((code & 0x7000) == 0x0000) {
|
||||
/* one-byte standard character (0?XX) */
|
||||
character = code & 0x007f;
|
||||
|
||||
if (character >= 0x20) {
|
||||
|
||||
PRINT(("%c", character));
|
||||
|
||||
fText[fRow][fColumn] = (fColor << 8) + character;
|
||||
if (fColumn < C_RADEON_CC_COLUMNS - 1)
|
||||
fColumn++;
|
||||
}
|
||||
else if (character != 0x00) {
|
||||
PRINT(("<%04X>", code & 0x7f7f));
|
||||
}
|
||||
}
|
||||
else if ((code & 0x7770) == 0x1120) {
|
||||
/* middle row code (112X) */
|
||||
fColor = code & 0x000f;
|
||||
|
||||
fText[fRow][fColumn] = (fColor << 8) + ' ';
|
||||
if (fColumn < C_RADEON_CC_COLUMNS - 1)
|
||||
fColumn++;
|
||||
|
||||
switch (fColor & 0x000e) {
|
||||
case C_WHITE:
|
||||
PRINT(("<white"));
|
||||
break;
|
||||
case C_GREEN:
|
||||
PRINT(("<green"));
|
||||
break;
|
||||
case C_BLUE:
|
||||
PRINT(("<blue"));
|
||||
break;
|
||||
case C_CYAN:
|
||||
PRINT(("<cyan"));
|
||||
break;
|
||||
case C_RED:
|
||||
PRINT(("<red"));
|
||||
break;
|
||||
case C_YELLOW:
|
||||
PRINT(("<yellow"));
|
||||
break;
|
||||
case C_MAGENTA:
|
||||
PRINT(("<magenta"));
|
||||
break;
|
||||
case C_ITALICS:
|
||||
PRINT(("<italics"));
|
||||
break;
|
||||
}
|
||||
if ((fColor & 0x0001) != 0)
|
||||
PRINT((",underline>"));
|
||||
else
|
||||
PRINT((">"));
|
||||
}
|
||||
else if ((code & 0x7770) == 0x1130) {
|
||||
/* two-byte special character (113X) */
|
||||
character = (code & 0x000f);
|
||||
|
||||
fText[fRow][fColumn] = (fColor << 8) + character + 0x0080;
|
||||
if (fColumn < C_RADEON_CC_COLUMNS - 1)
|
||||
fColumn++;
|
||||
|
||||
switch (character) {
|
||||
case C_reg:
|
||||
PRINT(("®"));
|
||||
break;
|
||||
case C_deg:
|
||||
PRINT(("°"));
|
||||
break;
|
||||
case C_frac12:
|
||||
PRINT(("½"));
|
||||
break;
|
||||
case C_iquest:
|
||||
PRINT(("¿"));
|
||||
break;
|
||||
case C_trademark:
|
||||
PRINT(("&trademark;"));
|
||||
break;
|
||||
case C_cent:
|
||||
PRINT(("¢"));
|
||||
break;
|
||||
case C_pound:
|
||||
PRINT(("£"));
|
||||
break;
|
||||
case C_music:
|
||||
PRINT(("&music;"));
|
||||
break;
|
||||
case C_agrave:
|
||||
PRINT(("à"));
|
||||
break;
|
||||
case C_tspace:
|
||||
PRINT(("&tspace;"));
|
||||
break;
|
||||
case C_egrave:
|
||||
PRINT(("è"));
|
||||
break;
|
||||
case C_acirc:
|
||||
PRINT(("â"));
|
||||
break;
|
||||
case C_ecirc:
|
||||
PRINT(("ê"));
|
||||
break;
|
||||
case C_icirc:
|
||||
PRINT(("î"));
|
||||
break;
|
||||
case C_ocirc:
|
||||
PRINT(("ô"));
|
||||
break;
|
||||
case C_ucirc:
|
||||
PRINT(("û"));
|
||||
break;
|
||||
default:
|
||||
PRINT(("<special=%04X>", code & 0x7f7f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((code & 0x7770) == 0x1420) {
|
||||
|
||||
if (code == fLastControlCode)
|
||||
return false;
|
||||
fLastControlCode = code;
|
||||
|
||||
/* miscellaneous control code (142X) */
|
||||
switch (code & 0x000f) {
|
||||
case C_RCL:
|
||||
// resume caption loading
|
||||
PRINT(("<rcl>"));
|
||||
break;
|
||||
|
||||
case C_BS:
|
||||
// backspace
|
||||
PRINT(("<bs>"));
|
||||
if (fColumn > 0)
|
||||
fText[fRow][--fColumn] = 0x0000;
|
||||
break;
|
||||
|
||||
case C_AOF:
|
||||
// alarm off
|
||||
PRINT(("<aof>"));
|
||||
break;
|
||||
|
||||
case C_AON:
|
||||
// alarm on
|
||||
PRINT(("<aon>"));
|
||||
break;
|
||||
|
||||
case C_DER:
|
||||
// delete to end of row
|
||||
PRINT(("<der>"));
|
||||
for (int column = fColumn; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[fRow][column] = 0x0000;
|
||||
break;
|
||||
|
||||
case C_RU2:
|
||||
// rollup captions (2 rows)
|
||||
PRINT(("<ru2>"));
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS - 2; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[row][column] = fText[row + 2][column];
|
||||
}
|
||||
for (int row = C_RADEON_CC_ROWS - 2; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[row][column] = 0x0000;
|
||||
}
|
||||
break;
|
||||
|
||||
case C_RU3:
|
||||
// rollup captions (3 rows)
|
||||
PRINT(("<ru3>"));
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS - 3; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[row][column] = fText[row + 2][column];
|
||||
}
|
||||
for (int row = C_RADEON_CC_ROWS - 3; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[row][column] = 0x0000;
|
||||
}
|
||||
break;
|
||||
|
||||
case C_RU4:
|
||||
// rollup captions (4 rows)
|
||||
PRINT(("<ru4>"));
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS - 4; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[row][column] = fText[row + 2][column];
|
||||
}
|
||||
for (int row = C_RADEON_CC_ROWS - 4; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[row][column] = 0x0000;
|
||||
}
|
||||
break;
|
||||
|
||||
case C_FON:
|
||||
// flash on
|
||||
PRINT(("<fon>"));
|
||||
break;
|
||||
|
||||
case C_RDC:
|
||||
// resume direct captioning
|
||||
PRINT(("<rdc>"));
|
||||
break;
|
||||
|
||||
case C_TR:
|
||||
// text restart
|
||||
PRINT(("<tr>"));
|
||||
|
||||
fRow = fColumn = 0;
|
||||
break;
|
||||
|
||||
case C_RTD:
|
||||
// resume text display
|
||||
PRINT(("<rtd>"));
|
||||
|
||||
fRow = fColumn = 0;
|
||||
break;
|
||||
|
||||
case C_EDM:
|
||||
// erase displayed memory
|
||||
PRINT(("<edm>\n"));
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fDisplayText[row][column] = 0x0000;
|
||||
}
|
||||
DisplayCaptions();
|
||||
break;
|
||||
|
||||
case C_CR:
|
||||
// carriage return
|
||||
PRINT(("<cr>"));
|
||||
|
||||
/* has no effect in caption loading mode */
|
||||
break;
|
||||
|
||||
case C_ENM:
|
||||
// erase non-displayed memory
|
||||
PRINT(("<enm>"));
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++)
|
||||
fText[row][column] = 0x0000;
|
||||
}
|
||||
break;
|
||||
|
||||
case C_EOC:
|
||||
// end of caption
|
||||
PRINT(("<eoc>\n"));
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++) {
|
||||
const int code = fText[row][column];
|
||||
fText[row][column] = fDisplayText[row][column];
|
||||
fDisplayText[row][column] = code;
|
||||
}
|
||||
}
|
||||
|
||||
DisplayCaptions();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((code & 0x7770) == 0x1720) {
|
||||
/* tab offset (172X) */
|
||||
const int offset = code & 0x000f;
|
||||
|
||||
if (offset >= 1 && offset <= 3) {
|
||||
PRINT(("<tab%d>", offset));
|
||||
|
||||
if ((fColumn += offset) >= C_RADEON_CC_COLUMNS - 1)
|
||||
fColumn = C_RADEON_CC_COLUMNS - 1;
|
||||
}
|
||||
else {
|
||||
PRINT(("<tab=%04X>", code & 0x7f7f));
|
||||
}
|
||||
}
|
||||
else if ((code & 0x7040) == 0x1040) {
|
||||
/* preamble address code (1Y4X, 1Y6X) */
|
||||
|
||||
switch (code & 0x0720) {
|
||||
case C_ROW_1:
|
||||
PRINT(("\n<row1"));
|
||||
fRow = 0;
|
||||
break;
|
||||
case C_ROW_2:
|
||||
PRINT(("\n<row2"));
|
||||
fRow = 1;
|
||||
break;
|
||||
case C_ROW_3:
|
||||
PRINT(("\n<row3"));
|
||||
fRow = 2;
|
||||
break;
|
||||
case C_ROW_4:
|
||||
PRINT(("\n<row4"));
|
||||
fRow = 3;
|
||||
break;
|
||||
case C_ROW_5:
|
||||
PRINT(("\n<row5"));
|
||||
fRow = 4;
|
||||
break;
|
||||
case C_ROW_6:
|
||||
PRINT(("\n<row6"));
|
||||
fRow = 5;
|
||||
break;
|
||||
case C_ROW_7:
|
||||
PRINT(("\n<row7"));
|
||||
fRow = 6;
|
||||
break;
|
||||
case C_ROW_8:
|
||||
PRINT(("\n<row8"));
|
||||
fRow = 7;
|
||||
break;
|
||||
case C_ROW_9:
|
||||
PRINT(("\n<row9"));
|
||||
fRow = 8;
|
||||
break;
|
||||
case C_ROW_10:
|
||||
PRINT(("\n<row10"));
|
||||
fRow = 9;
|
||||
break;
|
||||
case C_ROW_11:
|
||||
PRINT(("\n<row11"));
|
||||
fRow = 10;
|
||||
break;
|
||||
case C_ROW_12:
|
||||
PRINT(("\n<row12"));
|
||||
fRow = 11;
|
||||
break;
|
||||
case C_ROW_13:
|
||||
PRINT(("\n<row13"));
|
||||
fRow = 12;
|
||||
break;
|
||||
case C_ROW_14:
|
||||
PRINT(("\n<row14"));
|
||||
fRow = 13;
|
||||
break;
|
||||
case C_ROW_15:
|
||||
PRINT(("\n<row15"));
|
||||
fRow = 14;
|
||||
break;
|
||||
default:
|
||||
PRINT(("\n<pac=%04X>", code & 0x7f7f));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((code & 0x0010) == 0x0000) {
|
||||
/* change color */
|
||||
fColor = (code & 0x000f);
|
||||
fColumn = 0;
|
||||
|
||||
switch (fColor & 0x000e) {
|
||||
case C_WHITE:
|
||||
PRINT((",white"));
|
||||
break;
|
||||
case C_GREEN:
|
||||
PRINT((",green"));
|
||||
break;
|
||||
case C_BLUE:
|
||||
PRINT((",blue"));
|
||||
break;
|
||||
case C_CYAN:
|
||||
PRINT((",cyan"));
|
||||
break;
|
||||
case C_RED:
|
||||
PRINT((",red"));
|
||||
break;
|
||||
case C_YELLOW:
|
||||
PRINT((",yellow"));
|
||||
break;
|
||||
case C_MAGENTA:
|
||||
PRINT((",magenta"));
|
||||
break;
|
||||
case C_ITALICS:
|
||||
PRINT((",italics"));
|
||||
break;
|
||||
}
|
||||
if ((fColor & 0x0001) != 0)
|
||||
PRINT((",underline>"));
|
||||
else
|
||||
PRINT((">"));
|
||||
|
||||
}
|
||||
else {
|
||||
/* indent, white */
|
||||
fColor = C_WHITE | (code & 0x0001);
|
||||
fColumn = (code & 0x000e) << 1;
|
||||
PRINT((",col%d>", fColumn));
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* two one-byte standard characters */
|
||||
character = (code >> 8) & 0x7f;
|
||||
if (character >= 0x20) {
|
||||
|
||||
PRINT(("%c", character));
|
||||
|
||||
fText[fRow][fColumn] = (fColor << 8) + character;
|
||||
if (fColumn < C_RADEON_CC_COLUMNS - 1)
|
||||
fColumn++;
|
||||
}
|
||||
else if (character != 0x00) {
|
||||
PRINT(("<%02X>", character));
|
||||
}
|
||||
|
||||
character = (code >> 0) & 0x7f;
|
||||
if (character >= 0x20) {
|
||||
|
||||
PRINT(("%c", character));
|
||||
|
||||
fText[fRow][fColumn] = (fColor << 8) + character;
|
||||
if (fColumn < C_RADEON_CC_COLUMNS - 1)
|
||||
fColumn++;
|
||||
}
|
||||
else if (character != 0x00) {
|
||||
PRINT(("<%02X>", character));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCaption::DisplayCaptions() const
|
||||
{
|
||||
printf("\x1b[H\x1b[J");
|
||||
|
||||
for (int row = 0; row < C_RADEON_CC_ROWS; row++) {
|
||||
for (int column = 0; column < C_RADEON_CC_COLUMNS; column++) {
|
||||
if (fDisplayText[row][column] == 0x0000) {
|
||||
printf("\x1b[0;47;37m ");
|
||||
continue;
|
||||
}
|
||||
|
||||
const int code = (fDisplayText[row][column] >> 0) & 0xff;
|
||||
const int color = (fDisplayText[row][column] >> 8) & 0xff;
|
||||
|
||||
switch (color & 0x000e) {
|
||||
case 0x0000: // WHITE
|
||||
printf("\x1b[0;%d;40;37m", (color & 1) << 2);
|
||||
break;
|
||||
case 0x0002: // GREEN
|
||||
printf("\x1b[0;%d;40;32m", (color & 1) << 2);
|
||||
break;
|
||||
case 0x0004: // BLUE
|
||||
printf("\x1b[0;%d;40;34m", (color & 1) << 2);
|
||||
break;
|
||||
case 0x0006: // CYAN
|
||||
printf("\x1b[0;%d;40;35m", (color & 1) << 2);
|
||||
break;
|
||||
case 0x0008: // RED
|
||||
printf("\x1b[0;%d;40;31m", (color & 1) << 2);
|
||||
break;
|
||||
case 0x000a: // YELLOW
|
||||
printf("\x1b[0;%d;40;33m", (color & 1) << 2);
|
||||
break;
|
||||
case 0x000c: // MAGENTA
|
||||
printf("\x1b[0;%d;40;36m", (color & 1) << 2);
|
||||
break;
|
||||
case 0x000e: // WHITE ITALICS
|
||||
if ((color & 1) == 0)
|
||||
printf("\x1b[1;40;37m");
|
||||
else
|
||||
printf("\x1b[1;4;40;37m");
|
||||
break;
|
||||
}
|
||||
|
||||
if (code >= 0x20 && code <= 0x7f) {
|
||||
switch (code) {
|
||||
case 0x002a:
|
||||
// aacute
|
||||
printf("\xc3\xa1");
|
||||
break;
|
||||
case 0x005c:
|
||||
// eacute
|
||||
printf("\xc3\xa9");
|
||||
break;
|
||||
case 0x005e:
|
||||
// iacute
|
||||
printf("\xc3\xad");
|
||||
break;
|
||||
case 0x005f:
|
||||
// oacute
|
||||
printf("\xc3\xb3");
|
||||
break;
|
||||
case 0x0060:
|
||||
// uacute
|
||||
printf("\xc3\xba");
|
||||
break;
|
||||
case 0x007b:
|
||||
// ccedil
|
||||
printf("\xc3\xa7");
|
||||
break;
|
||||
case 0x007c:
|
||||
// division
|
||||
printf("\xc3\xb7");
|
||||
break;
|
||||
case 0x007d:
|
||||
// Ntilde
|
||||
printf("\xc3\x91");
|
||||
break;
|
||||
case 0x007e:
|
||||
// ntilde
|
||||
printf("\xc3\xb1");
|
||||
break;
|
||||
case 0x007f:
|
||||
// block
|
||||
printf("\xc1\xbf");
|
||||
break;
|
||||
default:
|
||||
// ASCII character
|
||||
printf("%c", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (code) {
|
||||
case 0x0080:
|
||||
// reg
|
||||
printf("\xc2\xae");
|
||||
break;
|
||||
case 0x0081:
|
||||
// deg
|
||||
printf("\xc2\xb0");
|
||||
break;
|
||||
case 0x0082:
|
||||
// frac12
|
||||
printf("\xc2\xbd");
|
||||
break;
|
||||
case 0x0083:
|
||||
// iquest
|
||||
printf("\xc2\xbf");
|
||||
break;
|
||||
case 0x0084:
|
||||
// trademark
|
||||
printf("\xe2\x84");
|
||||
break;
|
||||
case 0x0085:
|
||||
// cent
|
||||
printf("\xc2\xa2");
|
||||
break;
|
||||
case 0x0086:
|
||||
// pound
|
||||
printf("\xc2\xa3");
|
||||
break;
|
||||
case 0x0087:
|
||||
// music
|
||||
printf("\xc2\xa7");
|
||||
break;
|
||||
case 0x0088:
|
||||
// agrave
|
||||
printf("\xc3\xa0");
|
||||
break;
|
||||
case 0x0089:
|
||||
// tspace
|
||||
printf("\x1b[0;47;37m ");
|
||||
break;
|
||||
case 0x008a:
|
||||
// egrave
|
||||
printf("\xc3\xa8");
|
||||
break;
|
||||
case 0x008b:
|
||||
// acirc
|
||||
printf("\xc3\xa2");
|
||||
break;
|
||||
case 0x008c:
|
||||
// ecirc
|
||||
printf("\xc3\xaa");
|
||||
break;
|
||||
case 0x008d:
|
||||
// icirc
|
||||
printf("\xc3\xae");
|
||||
break;
|
||||
case 0x008e:
|
||||
// ocirc
|
||||
printf("\xc3\xb4");
|
||||
break;
|
||||
case 0x008f:
|
||||
// ucirc
|
||||
printf("\xc3\xbb");
|
||||
break;
|
||||
default:
|
||||
// buggy code
|
||||
printf("<%02X>", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\x1b[0;30;47m");
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: CC.h
|
||||
/
|
||||
/ Description: Closed caption module.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __CC_H__
|
||||
#define __CC_H__
|
||||
|
||||
#include "Capture.h"
|
||||
|
||||
enum cc_mode {
|
||||
C_RADEON_CC1 = 0,
|
||||
C_RADEON_CC2 = 1,
|
||||
C_RADEON_CC3 = 2,
|
||||
C_RADEON_CC4 = 3
|
||||
};
|
||||
|
||||
enum cc_window {
|
||||
C_RADEON_CC_VBI_LINE_WIDTH = 2048,
|
||||
C_RADEON_CC_BLANK_START = 4*112,
|
||||
C_RADEON_CC_VBI_LINE_NUMBER = 19,
|
||||
C_RADEON_CC_BIT_DURATION = 56,
|
||||
C_RADEON_CC_BITS_PER_FIELD = 16,
|
||||
C_RADEON_CC_LEVEL_THRESHOLD = 32,
|
||||
|
||||
C_RADEON_CC_LINE = 21,
|
||||
|
||||
C_RADEON_CC_CHANNELS = 4,
|
||||
C_RADEON_CC_ROWS = 15,
|
||||
C_RADEON_CC_COLUMNS = 32
|
||||
};
|
||||
|
||||
class CCaption {
|
||||
public:
|
||||
CCaption(CCapture & capture);
|
||||
|
||||
~CCaption();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
void SetMode(cc_mode mode);
|
||||
|
||||
bool Decode(const unsigned char * buffer0,
|
||||
const unsigned char * buffer1);
|
||||
|
||||
private:
|
||||
bool DecodeBits(const unsigned char * buffer, int & data);
|
||||
|
||||
void DisplayCaptions() const;
|
||||
|
||||
private:
|
||||
CCapture & fCapture;
|
||||
cc_mode fChannel;
|
||||
int fRow;
|
||||
int fColumn;
|
||||
int fColor;
|
||||
int fLastControlCode;
|
||||
short fText[C_RADEON_CC_ROWS][C_RADEON_CC_COLUMNS];
|
||||
short fDisplayText[C_RADEON_CC_ROWS][C_RADEON_CC_COLUMNS];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,346 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: Capture.cpp
|
||||
/
|
||||
/ Description: ATI Radeon Capture Unit interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
/ TK: something about synchronization: I removed all the FIFO wait
|
||||
/ functions as they aren't thread-safe and AFAIK not needed as
|
||||
/ only 2D/3D register accesses are buffered
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#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));
|
||||
|
||||
// initially the capture unit is disabled
|
||||
//fRadeon.WaitForFifo(2);
|
||||
SetRegister(C_RADEON_CAP0_TRIG_CNTL, C_RADEON_CAP0_TRIGGER_W_NO_ACTION);
|
||||
|
||||
// select buffer offset and pitch
|
||||
//fRadeon.WaitForFifo(5);
|
||||
|
||||
switch (fMode) {
|
||||
case C_RADEON_CAPTURE_FIELD_SINGLE:
|
||||
/* capture single field, single buffer */
|
||||
SetRegister(C_RADEON_CAP0_BUF0_OFFSET, fOffset0);
|
||||
SetRegister(C_RADEON_CAP0_BUF_PITCH, fPitch << 1);
|
||||
break;
|
||||
|
||||
case C_RADEON_CAPTURE_FIELD_DOUBLE:
|
||||
/* capture single field, double buffer */
|
||||
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:
|
||||
/* capture interlaced frame, single buffer */
|
||||
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:
|
||||
/* capture interlaced frame, double buffer */
|
||||
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:
|
||||
/* capture deinterlaced frame, single buffer */
|
||||
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:
|
||||
/* capture deinterlaced frame, double buffer */
|
||||
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;
|
||||
}
|
||||
|
||||
// select VBI buffer offset
|
||||
//fRadeon.WaitForFifo(4);
|
||||
|
||||
// FIXME: change according to the buffering mode?
|
||||
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);
|
||||
|
||||
// select capture clipping window
|
||||
//fRadeon.WaitForFifo(2);
|
||||
|
||||
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));
|
||||
|
||||
// select VBI clipping window
|
||||
//fRadeon.WaitForFifo(2);
|
||||
|
||||
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));
|
||||
|
||||
// select buffer type, input mode, video format and buffering mode
|
||||
//fRadeon.WaitForFifo(10);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
// select stream format and port mode
|
||||
//fRadeon.WaitForFifo(4);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// set capture mirror mode, field sense, downscaler/decimator, enable 3:4 pull down
|
||||
//fRadeon.WaitForFifo(16);
|
||||
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);
|
||||
|
||||
// prepare to enable capture
|
||||
//fRadeon.WaitForFifo(14);
|
||||
|
||||
// disable test and debug modes
|
||||
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);
|
||||
|
||||
// connect capture engine to AMC connector
|
||||
SetRegister(C_RADEON_VIDEOMUX_CNTL, 1, 1);
|
||||
|
||||
// select capture engine clock source to PCLK
|
||||
SetRegister(C_RADEON_FCP_CNTL, C_RADEON_FCP0_SRC_PCLK);
|
||||
|
||||
// enable capture unit
|
||||
SetRegister(C_RADEON_CAP0_TRIG_CNTL,
|
||||
C_RADEON_CAP0_TRIGGER_W_CAPTURE | C_RADEON_CAP0_EN);
|
||||
|
||||
// enable VBI capture
|
||||
SetRegister(C_RADEON_CAP0_CONFIG, C_RADEON_CAP0_VBI_EN,
|
||||
(vbi ? C_RADEON_CAP0_VBI_EN : 0));
|
||||
}
|
||||
|
||||
void CCapture::Stop()
|
||||
{
|
||||
PRINT(("CCapture::Stop()\n"));
|
||||
|
||||
// disable capture unit
|
||||
//fRadeon.WaitForFifo(4);
|
||||
|
||||
// disable capture unit
|
||||
SetRegister(C_RADEON_CAP0_TRIG_CNTL, C_RADEON_CAP0_TRIGGER_W_NO_ACTION);
|
||||
|
||||
// disable the capture engine clock (set to ground)
|
||||
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));
|
||||
|
||||
// clear any stick interrupt
|
||||
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) {
|
||||
/*
|
||||
int mask = fRadeon.Register(C_RADEON_CAP_INT_STATUS);
|
||||
|
||||
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);
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: Capture.h
|
||||
/
|
||||
/ Description: ATI Radeon Capture Unit interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __CAPTURE_H__
|
||||
#define __CAPTURE_H__
|
||||
|
||||
#include "Radeon.h"
|
||||
|
||||
enum capture_buffer_mode {
|
||||
C_RADEON_CAPTURE_FIELD_SINGLE = 0,
|
||||
C_RADEON_CAPTURE_FIELD_DOUBLE = 1,
|
||||
C_RADEON_CAPTURE_BOB_SINGLE = 2,
|
||||
C_RADEON_CAPTURE_BOB_DOUBLE = 3,
|
||||
C_RADEON_CAPTURE_WEAVE_SINGLE = 4,
|
||||
C_RADEON_CAPTURE_WEAVE_DOUBLE = 5
|
||||
};
|
||||
|
||||
enum capture_stream_format {
|
||||
C_RADEON_CAPTURE_BROOKTREE = 0,
|
||||
C_RADEON_CAPTURE_CCIR656 = 1,
|
||||
C_RADEON_CAPTURE_ZOOMVIDEO = 2,
|
||||
C_RADEON_CAPTURE_VIP = 3
|
||||
};
|
||||
|
||||
enum capture_interrupt_mask {
|
||||
C_RADEON_CAPTURE_BUF0_INT = 1 << 0,
|
||||
C_RADEON_CAPTURE_BUF0_EVEN_INT = 1 << 1,
|
||||
C_RADEON_CAPTURE_BUF1_INT = 1 << 2,
|
||||
C_RADEON_CAPTURE_BUF1_EVEN_INT = 1 << 3,
|
||||
C_RADEON_CAPTURE_VBI0_INT = 1 << 4,
|
||||
C_RADEON_CAPTURE_VBI1_INT = 1 << 5
|
||||
};
|
||||
|
||||
class CCapture {
|
||||
public:
|
||||
CCapture(CRadeon & radeon);
|
||||
|
||||
~CCapture();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
void SetBuffer(capture_stream_format format, capture_buffer_mode mode,
|
||||
int offset0, int offset1, int size, int pitch);
|
||||
|
||||
void SetClip(int left, int top, int right, int bottom);
|
||||
|
||||
void SetVBIBuffer(int offset0, int offset1, int size);
|
||||
|
||||
void SetVBIClip(int left, int top, int right, int bottom);
|
||||
|
||||
void Start(bool vbi = false);
|
||||
|
||||
void Stop();
|
||||
|
||||
public:
|
||||
void SetInterrupts(bool enable);
|
||||
|
||||
int WaitInterrupts(int * sequence, bigtime_t * when, bigtime_t timeout);
|
||||
|
||||
private:
|
||||
int Register(radeon_register index, int mask);
|
||||
|
||||
void SetRegister(radeon_register index, int value);
|
||||
|
||||
void SetRegister(radeon_register index, int mask, int value);
|
||||
|
||||
private:
|
||||
CRadeon & fRadeon;
|
||||
capture_buffer_mode fMode;
|
||||
capture_stream_format fFormat;
|
||||
int fOffset0;
|
||||
int fOffset1;
|
||||
int fVBIOffset0;
|
||||
int fVBIOffset1;
|
||||
int fSize;
|
||||
int fVBISize;
|
||||
int fPitch;
|
||||
CRadeonRect fClip;
|
||||
CRadeonRect fVBIClip;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,234 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: I2C.cpp
|
||||
/
|
||||
/ Description: ATI Radeon I2C Serial Bus interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <Debug.h>
|
||||
#include "I2CPort.h"
|
||||
|
||||
CI2CPort::CI2CPort(CRadeon & radeon, int rate)
|
||||
: fRadeon(radeon),
|
||||
fNfactor(0),
|
||||
fMfactor(0),
|
||||
fTimeLimit(0)
|
||||
{
|
||||
PRINT(("CI2CPort::CI2CPort()\n"));
|
||||
|
||||
if( fRadeon.InitCheck() == B_OK ) {
|
||||
int refFreq, refDiv, minFreq, maxFreq, xclock;
|
||||
fRadeon.GetPLLParameters(refFreq, refDiv, minFreq, maxFreq, xclock);
|
||||
|
||||
double n = (xclock * 10000.0) / (4.0 * rate);
|
||||
for (fNfactor = 1; fNfactor < 255; fNfactor++) {
|
||||
if (fNfactor * (fNfactor - 1) > n)
|
||||
break;
|
||||
}
|
||||
fMfactor = fNfactor - 1;
|
||||
fTimeLimit = 2 * fNfactor;
|
||||
|
||||
// enable I2C bus
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_1, 0x00ff0000,
|
||||
C_RADEON_I2C_SEL | C_RADEON_I2C_EN);
|
||||
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_0, 0x000000ff,
|
||||
C_RADEON_I2C_DONE | C_RADEON_I2C_NACK |
|
||||
C_RADEON_I2C_HALT | C_RADEON_I2C_SOFT_RST |
|
||||
C_RADEON_I2C_DRIVE_EN | C_RADEON_I2C_DRIVE_SEL);
|
||||
|
||||
#if DEBUG
|
||||
PRINT(("CI2CPort::CI2CPort() - I2C devices found at ports: "));
|
||||
for (int address = 0x80; address <= 0xff; address += 0x02) {
|
||||
if (Probe(address))
|
||||
PRINT(("0x%02x ", address));
|
||||
}
|
||||
PRINT(("\n"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CI2CPort::~CI2CPort()
|
||||
{
|
||||
PRINT(("CI2CPort::~CI2CPort()\n"));
|
||||
if( fRadeon.InitCheck() == B_OK ) {
|
||||
// disable I2C bus
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
status_t CI2CPort::InitCheck() const
|
||||
{
|
||||
return fRadeon.InitCheck();
|
||||
}
|
||||
|
||||
CRadeon & CI2CPort::Radeon() const
|
||||
{
|
||||
return fRadeon;
|
||||
}
|
||||
|
||||
bool CI2CPort::Probe(int address)
|
||||
{
|
||||
char buffer[1];
|
||||
|
||||
return Read(address, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
bool CI2CPort::Write(int address, const char * buffer, int length)
|
||||
{
|
||||
if (Send(address, buffer, length, true, true) == length)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CI2CPort::Read(int address, char * buffer, int length)
|
||||
{
|
||||
if (Receive(address, buffer, length, true, true) == length)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CI2CPort::Write(int address, const char * buffer, int length, char * result, int reslen)
|
||||
{
|
||||
if (Send(address, buffer, length, true, false) == length)
|
||||
if (Receive(address, result, reslen, true, true) == reslen)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int CI2CPort::Register(int address, int index)
|
||||
{
|
||||
char value = index;
|
||||
|
||||
if (Send(address, &value, sizeof(value), true, false) == sizeof(value)) {
|
||||
if (Receive(address, &value, sizeof(value), true, true) == sizeof(value))
|
||||
return value & 0xff;
|
||||
}
|
||||
PRINT(("CI2CPort::Register() - error\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CI2CPort::SetRegister(int address, int index, int value)
|
||||
{
|
||||
char buffer[2];
|
||||
|
||||
buffer[0] = index;
|
||||
buffer[1] = value;
|
||||
|
||||
if (Send(address, buffer, sizeof(buffer), true, true) != sizeof(buffer))
|
||||
PRINT(("CI2CPort::SetRegister() - error\n"));
|
||||
}
|
||||
|
||||
int CI2CPort::Send(int address, const char * buffer, int length, bool start, bool stop)
|
||||
{
|
||||
//fRadeon.WaitForFifo(4 + length);
|
||||
|
||||
// clear status bit
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,
|
||||
C_RADEON_I2C_DONE | C_RADEON_I2C_NACK |
|
||||
C_RADEON_I2C_HALT | C_RADEON_I2C_SOFT_RST);
|
||||
|
||||
// write address
|
||||
fRadeon.SetRegister(C_RADEON_I2C_DATA, address & 0xfffffffe);
|
||||
|
||||
// write data
|
||||
for (int offset = 0; offset < length; offset++)
|
||||
fRadeon.SetRegister(C_RADEON_I2C_DATA, buffer[offset]);
|
||||
|
||||
//
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_1,
|
||||
(fTimeLimit << 24) | length |
|
||||
C_RADEON_I2C_EN | C_RADEON_I2C_SEL | 0x100);
|
||||
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,
|
||||
(fNfactor << 24) | (fMfactor << 16) |
|
||||
C_RADEON_I2C_GO | C_RADEON_I2C_DRIVE_EN |
|
||||
(start ? C_RADEON_I2C_START : 0) | (stop ? C_RADEON_I2C_STOP : 0));
|
||||
|
||||
for (int wait = 0; wait < 100; wait++) {
|
||||
if ((fRadeon.Register(C_RADEON_I2C_CNTL_0) & C_RADEON_I2C_GO) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (WaitAck() != C_RADEON_I2C_DONE) {
|
||||
Stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int CI2CPort::Receive(int address, char * buffer, int length, bool start, bool stop)
|
||||
{
|
||||
//fRadeon.WaitForFifo(length + 4);
|
||||
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,
|
||||
C_RADEON_I2C_DONE | C_RADEON_I2C_NACK |
|
||||
C_RADEON_I2C_HALT | C_RADEON_I2C_SOFT_RST);
|
||||
|
||||
fRadeon.SetRegister(C_RADEON_I2C_DATA, address | 0x00000001);
|
||||
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_1,
|
||||
(fTimeLimit << 24) | C_RADEON_I2C_EN | //C_RADEON_I2C_SEL |
|
||||
length | 0x100);
|
||||
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,
|
||||
(fNfactor << 24) | (fMfactor << 16) | C_RADEON_I2C_GO |
|
||||
(start ? C_RADEON_I2C_START : 0) | (stop ? C_RADEON_I2C_STOP : 0) |
|
||||
C_RADEON_I2C_DRIVE_EN | C_RADEON_I2C_RECEIVE);
|
||||
|
||||
|
||||
for (int wait = 0; wait < 100; wait++) {
|
||||
if ((fRadeon.Register(C_RADEON_I2C_CNTL_0) & C_RADEON_I2C_GO) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (WaitAck() != C_RADEON_I2C_DONE)
|
||||
return 0;
|
||||
|
||||
snooze(1000);
|
||||
|
||||
for (int offset = 0; offset < length; offset++) {
|
||||
//fRadeon.WaitForFifo(1);
|
||||
buffer[offset] = fRadeon.Register(C_RADEON_I2C_DATA) & 0xff;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int CI2CPort::WaitAck()
|
||||
{
|
||||
for (int wait = 0; wait < 100; wait++) {
|
||||
int control = fRadeon.Register(C_RADEON_I2C_CNTL_0);
|
||||
if ((control & C_RADEON_I2C_HALT) != 0)
|
||||
return C_RADEON_I2C_HALT;
|
||||
if ((control & C_RADEON_I2C_NACK) != 0)
|
||||
return C_RADEON_I2C_NACK;
|
||||
if ((control & C_RADEON_I2C_DONE) != 0)
|
||||
return C_RADEON_I2C_DONE;
|
||||
snooze(1000);
|
||||
}
|
||||
PRINT(("CI2CPort::WaitAck() - Time out!\n"));
|
||||
return C_RADEON_I2C_HALT;
|
||||
}
|
||||
|
||||
void CI2CPort::Stop()
|
||||
{
|
||||
// reset status flags
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,
|
||||
C_RADEON_I2C_DONE | C_RADEON_I2C_NACK | C_RADEON_I2C_HALT, 0);
|
||||
|
||||
// issue abort call
|
||||
fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,
|
||||
C_RADEON_I2C_ABORT | C_RADEON_I2C_GO, C_RADEON_I2C_ABORT | C_RADEON_I2C_GO);
|
||||
|
||||
// wait GO bit to go low
|
||||
for (int wait = 0; wait < 100; wait++) {
|
||||
if ((fRadeon.Register(C_RADEON_I2C_CNTL_0) & C_RADEON_I2C_GO) == 0)
|
||||
snooze(1000);
|
||||
}
|
||||
PRINT(("CI2CPort::Stop() - Time out!\n"));
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: I2C.h
|
||||
/
|
||||
/ Description: ATI Radeon I2C Serial Bus interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __I2C_PORT_H__
|
||||
#define __I2C_PORT_H__
|
||||
|
||||
#include "Radeon.h"
|
||||
|
||||
enum i2c_port_clock_rate {
|
||||
C_RADEON_I2C_MIN_CLOCK_RATE = 7500,
|
||||
C_RADEON_I2C_MAX_CLOCK_RATE = 100000,
|
||||
C_RADEON_I2C_DEFAULT_CLOCK_RATE = 80000
|
||||
};
|
||||
|
||||
class CI2CPort {
|
||||
public:
|
||||
CI2CPort(CRadeon & radeon, int rate = C_RADEON_I2C_DEFAULT_CLOCK_RATE);
|
||||
|
||||
~CI2CPort();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
CRadeon & Radeon() const;
|
||||
|
||||
bool Probe(int address);
|
||||
|
||||
public:
|
||||
bool Write(int address, const char * buffer, int length);
|
||||
|
||||
bool Read(int address, char * buffer, int length);
|
||||
|
||||
bool Write(int address, const char * buffer, int length, char * output, int outlen);
|
||||
|
||||
public:
|
||||
int Register(int address, int index);
|
||||
|
||||
void SetRegister(int address, int index, int value);
|
||||
|
||||
private:
|
||||
int Send(int address, const char * buffer, int length, bool start, bool stop);
|
||||
|
||||
int Receive(int address, char * buffer, int length, bool start, bool stop);
|
||||
|
||||
int WaitAck();
|
||||
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
CRadeon & fRadeon;
|
||||
int fNfactor;
|
||||
int fMfactor;
|
||||
int fTimeLimit;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,878 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: MSP3430.cpp
|
||||
/
|
||||
/ Description: Micronas Multistandard Sound Processor (MSP) interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <Debug.h>
|
||||
#include "MSP3430.h"
|
||||
|
||||
enum MSP3430_register {
|
||||
MSP3430_CONTROL = 0x00, // R/W control register
|
||||
MSP3430_WR_DEM = 0x10, // Write demodulator register
|
||||
MSP3430_RD_DEM = 0x11, // Read demodulator register
|
||||
MSP3430_WR_DSP = 0x12, // Read DSP register
|
||||
MSP3430_RD_DSP = 0x13 // Write DSP register
|
||||
};
|
||||
|
||||
enum MSP3430_control_register {
|
||||
MSP3430_CONTROL_NORMAL = 0x0000, // normal operation mode
|
||||
MSP3430_CONTROL_RESET = 0x8000 // reset mode
|
||||
};
|
||||
|
||||
enum MSP3430_wr_dem_register {
|
||||
MSP3430_DEM_STANDARD_SEL = 0x0020, // standard selection
|
||||
MSP3430_DEM_MODUS = 0x0030, // demodulator options
|
||||
MSP3430_DEM_I2S_CONFIG = 0x0040 // I2S configuration
|
||||
};
|
||||
|
||||
enum MSP3430_rd_dem_register {
|
||||
MSP3430_DEM_STANDARD_RES = 0x007e, // standard detection result
|
||||
MSP3430_DEM_STATUS = 0x0200 // status register
|
||||
};
|
||||
|
||||
enum MSP3430_wr_dsp_register {
|
||||
// preprocessing
|
||||
MSP3430_DSP_FM_PRESCALE = 0x000e, // FM/AM analog signal prescale
|
||||
MSP3430_DSP_PRE_FM = BITS(15:8),
|
||||
MSP3430_DSP_FM_MATRIX = BITS(7:0),
|
||||
MSP3430_DSP_NICAM_PRESCALE = 0x0010, // NICAM digital signal prescale
|
||||
MSP34300_DSP_PRE_NICAM = BITS(15:8),
|
||||
MSP3430_DSP_PRE_I2S2 = 0x0012, // I2S digital signal prescale
|
||||
MSP3430_DSP_PRE_I2S1 = 0x0016,
|
||||
MSP3430_DSP_PRE_SCART = 0x000d, // SCART prescale
|
||||
|
||||
// source select and output channel matrix
|
||||
MSP3430_DSP_SRC_MAT_MAIN = 0x0008, // loudspeaker source and matrix
|
||||
MSP3430_DSP_SRC_MAIN = BITS(15:8),
|
||||
MSP3430_DSP_MAT_MAIN = BITS(7:0),
|
||||
MSP3430_DSP_SRC_MAT_AUX = 0x0009, // headphone source and matrix
|
||||
MSP3430_DSP_SRC_AUX = BITS(15:8),
|
||||
MSP3430_DSP_MAT_AUX = BITS(7:0),
|
||||
MSP3430_DSP_SRC_MAT_SCART1 = 0x000a, // SCART1 source and matrix
|
||||
MSP3430_DSP_SRC_SCART1 = BITS(15:8),
|
||||
MSP3430_DSP_MAT_SCART1 = BITS(7:0),
|
||||
MSP3430_DSP_SRC_MAT_SCART2 = 0x0041, // SCART2 source and matrix
|
||||
MSP3430_DSP_SRC_SCART2 = BITS(15:8),
|
||||
MSP3430_DSP_MAT_SCART2 = BITS(7:0),
|
||||
MSP3430_DSP_SRC_MAT_I2S = 0x000b, // I2S source and matrix
|
||||
MSP3430_DSP_SRC_I2S = BITS(15:8),
|
||||
MSP3430_DSP_MAT_I2S = BITS(7:0),
|
||||
MSP3430_DSP_SRC_MAT_QPEAK = 0x000c, // QuasiPeak detector source and matrix
|
||||
MSP3430_DSP_SRC_QPEAK = BITS(15:8),
|
||||
MSP3430_DSP_MAT_QPEAK = BITS(7:0),
|
||||
|
||||
// loudspeaker and headphone processing
|
||||
MSP3430_DSP_VOL_MAIN = 0x0000, // loudspeaker volume
|
||||
MSP3430_DSP_VOL_AUX = 0x0006, // headphone volume
|
||||
MSP3430_DSP_AVC = 0x0029, // automatic volume correction
|
||||
MSP3430_DSP_BAL_MAIN = 0x0001, // loudspeaker balance
|
||||
MSP3430_DSP_BAL_AUX = 0x0030, // headphone balance
|
||||
MSP3430_DSP_TONE_MODE = 0x0020, // select bass/treble or equalizer
|
||||
MSP3430_DSP_BASS_MAIN = 0x0002, // loudspeaker bass
|
||||
MSP3430_DSP_BASS_AUX = 0x0031, // headphone bass
|
||||
MSP3430_DSP_TREB_MAIN = 0x0003, // loudspeaker treble
|
||||
MSP3430_DSP_TREB_AUX = 0x0032, // headphone treble
|
||||
MSP3430_DSP_EQUAL_BAND1 = 0x0021, // equalizer coefficients
|
||||
MSP3430_DSP_EQUAL_BAND2 = 0x0022,
|
||||
MSP3430_DSP_EQUAL_BAND3 = 0x0023,
|
||||
MSP3430_DSP_EQUAL_BAND4 = 0x0024,
|
||||
MSP3430_DSP_EQUAL_BAND5 = 0x0025,
|
||||
MSP3430_DSP_LOUD_MAIN = 0x0004, // loudspeaker loudness
|
||||
MSP3430_DSP_LOUD_AUX = 0x0033, // headphone loudness
|
||||
MSP3430_DSP_SPAT_MAIN = 0x0005, // spatial effects
|
||||
|
||||
// subwoofer output channel
|
||||
MSP3430_DSP_SUBW_LEVEL = 0x002c, // subwoofer level
|
||||
MSP3430_DSP_SUBW_FREQ = 0x002d, // subwoofer frequency
|
||||
|
||||
// micronas dynamic bass
|
||||
MSP3430_DSP_MDB_STR = 0x0068, // MDB strength
|
||||
MSP3430_DSP_MDB_LIM = 0x0069, // MDB limit
|
||||
MSP3430_DSP_MDB_HMC = 0x006a, // MDB harmonic content
|
||||
MSP3430_DSP_MDB_LP = 0x006b, // MDB low frequency
|
||||
MSP3430_DSP_MDB_HP = 0x006c, // MDB high frequency
|
||||
|
||||
// SCART output channel
|
||||
MSP3430_DSP_VOL_SCART1 = 0x0007, // SCART1 volume
|
||||
MSP3430_DSP_VOL_SCART2 = 0x0040, // SCART2 volume
|
||||
|
||||
// SCART switches and digital I/O pins
|
||||
MSP3430_DSP_ACB_REG = 0x0013, // SCART switches
|
||||
MSP3430_DSP_BEEPER = 0x0014 // Beeper volume and frequency
|
||||
};
|
||||
|
||||
enum MSP3430_rd_dsp_register {
|
||||
// quasi-peak detector readout
|
||||
MSP3430_DSP_QPEAK_L = 0x0019, // Quasipeak detector left and right
|
||||
MSP3430_DSP_QPEAK_R = 0x001a,
|
||||
|
||||
// MSP 34x0G version readout
|
||||
MSP3430_DSP_MSP_HARD_REVISION = 0x001e, // MSP hardware and revision
|
||||
MSP3430_DSP_MSP_HARD = BITS(15:8),
|
||||
MSP3430_DSP_MSP_REVISION = BITS(7:0),
|
||||
MSP3430_DSP_MSP_PRODUCT_ROM = 0x001f, // MSP product and ROM version
|
||||
MSP3430_DSP_MSP_PRODUCT = BITS(15:8),
|
||||
MSP3430_DSP_MSP_ROM = BITS(7:0)
|
||||
};
|
||||
|
||||
enum MSP3430_sound_standard {
|
||||
C_MSP3430_AUTOMATIC = 0x0001, // Automatic Detection (*)
|
||||
C_MSP3430_M_FM_STEREO = 0x0002, // NTSC M/N (*)
|
||||
C_MSP3430_BG_FM_STEREO = 0x0003, // PAL B/G (*)
|
||||
C_MSP3430_DK1_FM_STEREO = 0x0004, // (*)
|
||||
C_MSP3430_DK2_FM_STEREO = 0x0005, //
|
||||
C_MSP3430_DK_FM_MONO = 0x0006, //
|
||||
C_MSP3430_DK3_FM_STEREO = 0x0007, //
|
||||
C_MSP3430_BG_NICAM_FM = 0x0008, // PAL B/G (*)
|
||||
C_MSP3430_L_NICAM_AM = 0x0009, // (*)
|
||||
C_MSP3430_I_NICAM_FM = 0x000A, // PAL I (*)
|
||||
C_MSP3430_DK_NICAM_FM = 0x000B, // (*)
|
||||
C_MSP3430_DK_NICAM_FM_HDEV2 = 0x000C,
|
||||
C_MSP3430_DK_NICAM_FM_HDEV3 = 0x000D,
|
||||
C_MSP3430_BTSC_STEREO = 0x0020, // BTSC Stereo (*)
|
||||
C_MSP3430_BTSC_MONO_SAP = 0x0021,
|
||||
C_MSP3430_M_JAPAN_STEREO = 0x0030, // NTSC Japan (*)
|
||||
C_MSP3430_FM_RADIO = 0x0040, // FM Radio (*)
|
||||
C_MSP3430_SAT_MONO = 0x0050, // Satellite Mono
|
||||
C_MSP3430_SAT_STEREO = 0x0051, // Satellite Stereo
|
||||
C_MSP3430_SAT_ASTRA_RADIO = 0x0060 // Astra Digital Radio
|
||||
};
|
||||
|
||||
enum MSP3430_channel_source {
|
||||
C_MSP3430_SOURCE_FM = 0x00, // FM/AM Mono
|
||||
C_MSP3430_SOURCE_STEREO = 0x01, // Stereo or A/B (NICAM)
|
||||
C_MSP3430_SOURCE_SCART = 0x02, // SCART Input
|
||||
C_MSP3430_SOURCE_LANG_A = 0x03, // Stereo/Language A
|
||||
C_MSP3430_SOURCE_LANG_B = 0x04, // Stereo/Language B
|
||||
C_MSP3430_SOURCE_I2S1 = 0x05, // I2S1 Input
|
||||
C_MSP3430_SOURCE_I2S2 = 0x06 // I2S2 Input
|
||||
};
|
||||
|
||||
enum MSP3430_channel_matrix {
|
||||
C_MSP3430_MATRIX_SOUND_A = 0x00, // Sound A Mono
|
||||
C_MSP3430_MATRIX_SOUND_B = 0x10, // Sound B Mono
|
||||
C_MSP3430_MATRIX_STEREO = 0x20, // Stereo
|
||||
C_MSP3430_MATRIX_MONO = 0x30 // Mono
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
-------------------------------------------------------------------
|
||||
System Sound Sound Color
|
||||
Carrier (MHz) Modulation System
|
||||
-------------------------------------------------------------------
|
||||
Satellite 6.5/5.85 FM-Mono/NICAM PAL
|
||||
6.5 FM-Mono
|
||||
7.02/7.2 FM-Stereo PAL
|
||||
7.38/7.56 ASTRA Digital Radio
|
||||
etc.
|
||||
4.5/4.724212 FM-Stereo (A2) NTSC
|
||||
-------------------------------------------------------------------
|
||||
NTSC M/N 4.5 FM-FM (EIA-J) NTSC
|
||||
-------------------------------------------------------------------
|
||||
4.5 BTSC Stereo + SAP NTSC, PAL
|
||||
FM-Radio 10.7 FM-Stereo Radio .
|
||||
-------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
CMSP3430::CMSP3430(CI2CPort & port)
|
||||
: fPort(port),
|
||||
fAddress(0)
|
||||
{
|
||||
PRINT(("CMSP3430::CMSP3430()\n"));
|
||||
|
||||
if( fPort.InitCheck() == B_OK ) {
|
||||
for (fAddress = 0x80; fAddress <= 0x80; fAddress += 0x02) {
|
||||
if (fPort.Probe(fAddress)) {
|
||||
PRINT(("CMSP3430::CMSP3430() - Sound Processor found at I2C port 0x%02x\n", fAddress));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( InitCheck() != B_OK )
|
||||
PRINT(("CMSP3430::CMSP3430() - Sound processor not found!\n"));
|
||||
}
|
||||
|
||||
CMSP3430::~CMSP3430()
|
||||
{
|
||||
PRINT(("CMSP3430::~CMSP3430()\n"));
|
||||
}
|
||||
|
||||
status_t CMSP3430::InitCheck() const
|
||||
{
|
||||
status_t res;
|
||||
|
||||
res = fPort.InitCheck();
|
||||
if( res != B_OK )
|
||||
return res;
|
||||
|
||||
return (fAddress >= 0x80 && fAddress <= 0x80) ? B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
void CMSP3430::SetEnable(bool enable)
|
||||
{
|
||||
PRINT(("CMSP3430::SetEnable(%d)\n", enable));
|
||||
|
||||
SetControlRegister(MSP3430_CONTROL_RESET);
|
||||
SetControlRegister(MSP3430_CONTROL_NORMAL);
|
||||
|
||||
if (enable) {
|
||||
SetRegister(MSP3430_WR_DEM, MSP3430_DEM_MODUS, 0x2003);
|
||||
SetRegister(MSP3430_WR_DEM, MSP3430_DEM_STANDARD_SEL, C_MSP3430_BTSC_STEREO); // 0x20
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_FM_PRESCALE, 0x2403);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_MAIN, 0x0320);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_VOL_MAIN, 0x7300);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_MAIN, 0x0320);
|
||||
}
|
||||
else {
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_VOL_MAIN, 0x0000);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
|
||||
void CMSP3430::SetI2S(bool fast)
|
||||
{
|
||||
// select 2 x 16 bit (1024 MHz) or 2 x 32 bit (2048) frequency
|
||||
SetRegister(MSP3430_WR_DEM, I2S_CONFIG, fast ? 0x0001 : 0x0000);
|
||||
}
|
||||
|
||||
bool CMSP3430::IsSAP()
|
||||
{
|
||||
// bilingual sound mode or SAP present?
|
||||
if ((Register(MSP3430_RD_DEM, STATUS) & 0x0100) != 0x0000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMSP3430::IsMonoNICAM()
|
||||
{
|
||||
// independent mono sound (only NICAM)?
|
||||
if ((Register(MSP3430_RD_DEM, STATUS) & 0x0080) != 0x0000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMSP3430::IsStereo()
|
||||
{
|
||||
// mono/stereo indication
|
||||
if ((Register(MSP3430_RD_DEM, STATUS) & 0x0040) != 0x0000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMSP3430::IsFM()
|
||||
{
|
||||
// is analog sound standard (FM or AM) active?
|
||||
if ((Register(MSP3430_RD_DEM, STATUS) & 0x0120) == 0x0000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMSP3430::IsNICAM()
|
||||
{
|
||||
// digital sound (NICAM) available?
|
||||
if ((Register(MSP3430_RD_DEM, STATUS) & 0x0100) == 0x0100)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMSP3430::HasSecondaryCarrier()
|
||||
{
|
||||
// detected secondary carrier (2nd A2 or SAP sub-carrier)
|
||||
if ((Register(MSP3430_RD_DEM, STATUS) & 0x0004) != 0x0000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMSP3430::HasPrimaryCarrier()
|
||||
{
|
||||
// detected primary carrier (Mono or MPX carrier)
|
||||
if ((Register(MSP3430_RD_DEM, STATUS) & 0x0002) != 0x0000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CMSP3430::SetStandard(MSP3430_standard standard)
|
||||
{
|
||||
fStandard = standard;
|
||||
|
||||
// set sound mode, FM/AM matrix, source channels
|
||||
switch (standard) {
|
||||
C_MSP3430_STANDARD_BG_FM:
|
||||
C_MSP3430_STANDARD_DK_FM:
|
||||
// Sound Mode FM Matrix FM/AM Source Stereo A/B Source
|
||||
// ---------------------------------------------------------------
|
||||
// Mono Sound A Mono Mono Mono
|
||||
C_MSP3430_STANDARD_M_KOREA:
|
||||
C_MSP3430_STANDARD_M_JAPAN:
|
||||
// Stereo Korean Stereo Stereo Stereo
|
||||
// Stereo German Stereo Stereo Stereo
|
||||
// Lang A & B No Matrix Left=A, Right=B Left=A, Right=B
|
||||
|
||||
C_MSP3430_STANDARD_BG_NICAM:
|
||||
|
||||
|
||||
}
|
||||
|
||||
SetDemodulator();
|
||||
}
|
||||
|
||||
void CMSP3430::SetFMPrescale(int gain, MSP3430_fm_matrix matrix, bool mute)
|
||||
{
|
||||
// set FM/AM prescale and FM matrix mode
|
||||
fFMPrescale = (mute ? 0x00 : Clamp(gain, 0x00, 0x7f)) << 8;
|
||||
/// see table 6--17, Appendix B.
|
||||
switch (matrix) {
|
||||
case C_MSP3430_MATRIX_NONE:
|
||||
fFMPrescale |= 0x0000;
|
||||
break;
|
||||
case C_MSP3430_MATRIX_GERMAN_STEREO_BG:
|
||||
fFMPrescale |= 0x0001;
|
||||
break;
|
||||
case C_MSP3430_MATRIX_KOREAN_STEREO:
|
||||
fFMPrescale |= 0x0002;
|
||||
break;
|
||||
case C_MSP3430_MATRIX_SOUND_A_MONO:
|
||||
fFMPrescale |= 0x0003;
|
||||
break;
|
||||
case C_MSP3430_MATROX_SOUND_B_MONO:
|
||||
fFMPrescale |= 0x0004;
|
||||
break;
|
||||
}
|
||||
|
||||
SetDemodulator();
|
||||
}
|
||||
|
||||
void CMSP3430::SetNICAMPrescale(int gain, bool mute)
|
||||
{
|
||||
// set NICAM prescale to 0..12 dB
|
||||
fNICAMPrescale = (mute ? 0x00 : Clamp(0x20 + (0x5f * gain) / 12, 0x20, 0x7f)) << 8;
|
||||
|
||||
SetDemodulator();
|
||||
}
|
||||
|
||||
void CMSP3430::SetI2SPrescale(int gain, bool mute)
|
||||
{
|
||||
// set digital I2S input prescale 0..18 dB
|
||||
fI2SPrescale = (mute ? 0x00 : Clamp(0x10 + (0x7f * gain) / 18, 0x10, 0x7f) << 8;
|
||||
SetSCARTInput();
|
||||
}
|
||||
|
||||
void CMSP3430::SetSCARTPrescale(int gain, bool mute)
|
||||
{
|
||||
// set SCART input signal prescale 0..14 dB
|
||||
fSCARTPrescale = (mute ? 0x00 : Clamp(0x19 + (0x66 * gain) / 14, 0x19, 0x7f) << 8;
|
||||
SetSCARTInput();
|
||||
}
|
||||
|
||||
void CMSP3430::SetSource(MSP3430_source_channel speaker,
|
||||
MSP3430_source_channel headphone,
|
||||
MSP3430_source_channel scart1,
|
||||
MSP3430_source_channel scart2,
|
||||
MSP3430_source_channel i2s,
|
||||
MSP3430_source_channel qpeak)
|
||||
{
|
||||
// set source and matrix..
|
||||
// select FM/AM, Stereo A/B, Stereo A, Stereo B, SCART, I2S1 or I2S2 source channels
|
||||
// and select Sound A Mono, Sound B Mono, Stereo or Mono mode
|
||||
fSrcMain = loudspeaker;
|
||||
fSrcAux = headphone;
|
||||
fSrcSCART1 = scart1;
|
||||
fSrcSCART2 = scart2;
|
||||
fSrcI2S = i2s;
|
||||
fSrcQPeak = qpeak;
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
|
||||
void CMSP3430::SetVolume(int level, bool mute, MSP3430_clipping_mode mode,
|
||||
MSP3430_automatic_volume automatic)
|
||||
{
|
||||
// set volume between -114 dB and 12 dB with 1 dB step size
|
||||
fVolume = (mute ? 0x00 : Clamp(level + 0x73, 0x01, 0x7f)) << 8;
|
||||
switch (mode) {
|
||||
case C_MSP3430_CLIP_REDUCE_VOLUME:
|
||||
fVolume |= 0x00;
|
||||
break;
|
||||
case C_MSP3430_CLIP_REDUCE_TONE:
|
||||
fVolume |= 0x01;
|
||||
break;
|
||||
case C_MSP3430_CLIP_COMPROMISE:
|
||||
fVolume |= 0x02;
|
||||
break;
|
||||
case C_MSP3430_CLIP_DYNAMIC:
|
||||
fVolume |= 0x03;
|
||||
break;
|
||||
}
|
||||
|
||||
// enable/disable automatic volume correction
|
||||
switch (automatic) {
|
||||
case C_MSP3430_AUTOMATIC_VOLUME_OFF:
|
||||
fAVC = 0x0000;
|
||||
break;
|
||||
case C_MSP3430_AUTOMATIC_VOLUME_20_MS:
|
||||
fAVC = 0x8100;
|
||||
break;
|
||||
case C_MSP3430_AUTOMATIC_VOLUME_2_SEC:
|
||||
fAVC = 0x8200;
|
||||
break;
|
||||
case C_MSP3430_AUTOMATIC_VOLUME_4_SEC:
|
||||
fAVC = 0x8400;
|
||||
break;
|
||||
case C_MSP3430_AUTOMATIC_VOLUME_8_SEC:
|
||||
fAVC = 0x8800;
|
||||
break;
|
||||
}
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetBalance(int balance, MSP3430_balance_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case C_MSP3430_BALANCE_LINEAR:
|
||||
// set balance between -100% (right) and 100% (left)
|
||||
fBalance = (((0x7f * Clamp(balance, -100, 100)) / 100) << 8) + 0x0000;
|
||||
break;
|
||||
|
||||
case C_MSP3430_BALANCE_LOGARITHMIC:
|
||||
// set balance between -128 dB (right) and 127 dB (left)
|
||||
fBalance = (((0x7f * Clamp(balance, -128, 127)) / 127) << 8) + 0x0001;
|
||||
break;
|
||||
}
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
|
||||
void CMSP3430::SetEqualizer(int bass, int treble)
|
||||
{
|
||||
// set bass to -12..12 dB or 14..20 dB
|
||||
if (bass <= 12)
|
||||
fBass = Clamp(0x00 + 8 * bass, -0x60, 0x60) << 8;
|
||||
else
|
||||
fBass = Clamp(0x68 + 4 * (bass - 14), 0x68, 0x7f) << 8;
|
||||
|
||||
// set treble to -12..15 dB
|
||||
fTreble = Clamp(0x00 + 8 * treble, -0x60, 0x78) << 8;
|
||||
|
||||
// enable bass/treble and disable equalizer
|
||||
fToneControl = 0x00;
|
||||
fEqualizer[0] = fEqualizer[1] = fEqualizer[2] =
|
||||
fEqualizer[3] = fEqualizer[4] = fEqualizer[5] = 0x00;
|
||||
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetEqualizer(int gain[5])
|
||||
{
|
||||
// set five band equalizer (120 Hz, 500 Hz, 1500 Hz, 5000 Hz, 10000 Hz)
|
||||
for (int index = 0; index < 5; index++)
|
||||
fEqualizer[index] = Clamp(0x00 + 8 * gain[index], -0x60, 0x60) << 8;
|
||||
|
||||
// disable bass/treble and enable equalizer
|
||||
fToneControl = 0xff;
|
||||
fBass = fTreble = 0x00;
|
||||
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetLoudness(int loudness, MSP3430_loudness_mode mode)
|
||||
{
|
||||
// set loudness gain between 0 dB and 17 dB
|
||||
fLoudness = Clamp(0x00 + 4 * loudness, 0x00, 0x44) << 8;
|
||||
switch (mode) {
|
||||
case C_MSP3430_LOUDNESS_NORMAL:
|
||||
fLoudness |= 0x0000;
|
||||
break;
|
||||
case C_MSP3430_LOUDNESS_SUPER_BASS:
|
||||
fLoudness |= 0x0004;
|
||||
break;
|
||||
}
|
||||
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetSpatial(int strength, MSP3430_spatial_mode mode, MSP3430_spatial_highpass pass)
|
||||
{
|
||||
// enlarge or reduce spatial effects -100% to +100%
|
||||
fSpatial = Clamp(0x00 + (0x7f * strength) / 100, -0x80, 0x7f) << 8;
|
||||
switch (mode) {
|
||||
case C_MSP3430_SPATIAL_MODE_A:
|
||||
fSpatial |= 0x0000;
|
||||
break;
|
||||
case C_MSP3430_SPATIAL_MODE_B:
|
||||
fSpatial |= 0x0020;
|
||||
break;
|
||||
}
|
||||
switch (pass) {
|
||||
case C_MSP3430_SPATIAL_MAX_HIGH_PASS:
|
||||
fSpatial |= 0x0000;
|
||||
break;
|
||||
case C_MSP3430_SPATIAL_2_3_HIGH_PASS:
|
||||
fSpatial |= 0x0002;
|
||||
break;
|
||||
case C_MSP3430_SPATIAL_1_3_HIGH_PASS:
|
||||
fSpatial |= 0x0004;
|
||||
break;
|
||||
case C_MSP3430_SPATIAL_MIN_HIGH_PASS:
|
||||
fSpatial |= 0x0006;
|
||||
break;
|
||||
case C_MSP3430_SPATIAL_AUTO_HIGH_PASS:
|
||||
fSpatial |= 0x0008;
|
||||
break;
|
||||
}
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetSubwoofer(int level, int frequency, bool mute, MSP3430_subwoofer_mode mode)
|
||||
{
|
||||
// set subwoofer level between -128 dB and 12 dB
|
||||
fSubwooferLevel = (mute ? 0x80 : Clamp(0x00 + level, -128, 12)) << 8;
|
||||
|
||||
// set subwoofer corner frequency between 50..400 Hz
|
||||
fSubwooferFrequency = Clamp(frequency / 10, 5, 40) << 8;
|
||||
switch (mode) {
|
||||
case C_MSP3430_SUBWOOFER_UNFILTERED:
|
||||
fSubwooferFrequency |= 0x0000;
|
||||
break;
|
||||
case C_MSP3430_SUBWOOFER_HIGH_PASS:
|
||||
fSubwooferFrequency |= 0x0001;
|
||||
break;
|
||||
case C_MSP3430_SUBWOOFER_MDB_MAIN:
|
||||
fSubwooferFrequency |= 0x0002;
|
||||
break;
|
||||
}
|
||||
|
||||
// disable MDB?
|
||||
fMDBStrength = 0x0000;
|
||||
fMDBLimit = 0x0000;
|
||||
fMDBHarmonic = 0x0000;
|
||||
fMDBHighPass = 0x0a00;
|
||||
fMDBLowPass = 0x0a00;
|
||||
|
||||
SetSubwooferAndMDBOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetMDB(int strength, int limit, int harmonic,
|
||||
int minfrequency, int maxfrequency, bool mute)
|
||||
{
|
||||
// set MDB effect strength 0..127
|
||||
fMDBStrength = (mute ? 0x00 : Clamp(strength, 0x00, 0x7f)) << 7;
|
||||
|
||||
// set MDB amplitude limit between -32..0 dBFS
|
||||
fMDBLimit = Clamp(limit, -32, 0) << 8;
|
||||
|
||||
// set MDB harmonic content 0..100%
|
||||
fMDBHarmonic = Clamp((0x7f * harmonic) / 100, 0x00, 0x7f) << 8;
|
||||
|
||||
// set MDB low pass corner frequency 50..300 Hz
|
||||
fMDBLowPass = Clamp(minFrequency / 10, 5, 30) << 8;
|
||||
|
||||
// set MDB high pass corner frequency 20..300 Hz
|
||||
fMDBHighPass = Clamp(maxFrequency / 10, 2, 30) << 8;
|
||||
|
||||
// disable subwoofer level adjustments
|
||||
fSubwooferLevel = 0x0000;
|
||||
fSubwooferFrequency = 0x0002;
|
||||
|
||||
// for MDB, use dynamic clipping mode
|
||||
fVolume = (fVolume & ~0x000f) | 0x0003;
|
||||
|
||||
SetSubwooferAndMDBOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetSCART(int level1, int level2, bool mute,
|
||||
MSP3430_scart_input input,
|
||||
MSP3430_scart_output output1,
|
||||
MSP3430_scart_output output2)
|
||||
{
|
||||
// set volume SCART1/2 output channel -114..12 dB
|
||||
fSCART1Volume = (mute ? 0x00 : Clamp(0x73 + (0x7f * level1) / 12, 0x00, 0x7f)) << 8;
|
||||
fSCART2Volume = (mute ? 0x00 : Clamp(0x73 + (0x7f * level2) / 12, 0x00, 0x7f)) << 8;
|
||||
|
||||
fSCART1Volume |= 0x0001;
|
||||
fSCART2Volume |= 0x0001;
|
||||
|
||||
// SCART DSP input select
|
||||
fACB = 0x0000;
|
||||
switch (input) {
|
||||
case C_MSP3430_SCART_INPUT_SCART1:
|
||||
fACB = 0x0000;
|
||||
break;
|
||||
case C_MSP3430_SCART_INPUT_MONO:
|
||||
fACB = 0x0100;
|
||||
break;
|
||||
case C_MSP3430_SCART_INPUT_SCART2:
|
||||
fACB = 0x0200;
|
||||
break;
|
||||
case C_MSP3430_SCART_INPUT_SCART3:
|
||||
fACB = 0x0300;
|
||||
break;
|
||||
case C_MSP3430_SCART_INPUT_SCART4:
|
||||
fACB = 0x0020;
|
||||
break;
|
||||
case C_MSP3430_SCART_INPUT_MUTE:
|
||||
fACB = 0x0320;
|
||||
break;
|
||||
}
|
||||
|
||||
// SCART1 output select
|
||||
switch (output1) {
|
||||
case C_MSP3430_SCART_OUTPUT_SCART3:
|
||||
fACB |= 0x0000;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART2:
|
||||
fACB |= 0x0400;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_MONO:
|
||||
fACB |= 0x0800;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART1_DA:
|
||||
fACB |= 0x0c00;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART2_DA:
|
||||
fACB |= 0x0080;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART1_INPUT:
|
||||
fACB |= 0x0480;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART4_INPUT:
|
||||
fACB |= 0x0880;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_MUTE:
|
||||
fACB |= 0x0c80;
|
||||
break;
|
||||
}
|
||||
|
||||
// SCART2 output select
|
||||
switch (output2) {
|
||||
case C_MSP3430_SCART_OUTPUT_SCART3:
|
||||
fACB |= 0x0000;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART2:
|
||||
fACB |= 0x1000;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_MONO:
|
||||
fACB |= 0x2000;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART1_DA:
|
||||
fACB |= 0x3000;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART2_DA:
|
||||
fACB |= 0x0200;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART1_INPUT:
|
||||
fACB |= 0x1200;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_SCART4_INPUT:
|
||||
fACB |= 0x2200;
|
||||
break;
|
||||
case C_MSP3430_SCART_OUTPUT_MUTE:
|
||||
fACB |= 0x3200;
|
||||
break;
|
||||
}
|
||||
|
||||
SetSCARTSignalPath();
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::SetBeeper(int volume, MSP3430_beeper_frequency frequency, bool mute)
|
||||
{
|
||||
// set beeper volume 0..127
|
||||
int beeper = (mute ? 0x00 : Clamp(volume, 0x00, 0x7f)) << 8;
|
||||
|
||||
// set beeper frequency 16, 1000 or 4000 Hz
|
||||
switch (frequency) {
|
||||
case C_MSP3430_BEEPER_16_HZ:
|
||||
beeper |= 0x0001;
|
||||
break;
|
||||
case C_MSP3430_BEEPER_1_KHZ:
|
||||
beeper |= 0x0040;
|
||||
break;
|
||||
case C_MSP3430_BEEPER_4_KHZ:
|
||||
beeper |= 0x00ff;
|
||||
break;
|
||||
}
|
||||
SetRegister(MSP3430_WR_DSP, BEEPER, beeper);
|
||||
}
|
||||
|
||||
void CMSP3430::SetQuasiPeak(int left, int right)
|
||||
{
|
||||
// set quasipeak detector readout -32768..32767
|
||||
fQPeakLeft = left;
|
||||
fQPeakRight = right;
|
||||
|
||||
SetOutputChannels();
|
||||
}
|
||||
|
||||
void CMSP3430::GetVersion(char * version)
|
||||
{
|
||||
int revision = Register(MSP3430_RD_DSP, MSP_HARD_REVISION);
|
||||
int product = Register(MSP3430_RD_DSP, MSP_PRODUCT_ROM);
|
||||
|
||||
sprintf(version, "MSP34%02d%c-%c%d",
|
||||
((product & MSP_PRODUCT) >> 8),
|
||||
((revision & MSP_REVISION) >> 0) + 0x40,
|
||||
((revision & MSP_HARD) >> 8) + 0x40,
|
||||
((product & MSP_ROM) >> 0));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
void CMSP3430::Reset()
|
||||
{
|
||||
// software reset
|
||||
SetControlRegister(MSP3430_CONTROL_RESET);
|
||||
SetControlRegister(MSP3430_CONTROL_NORMAL);
|
||||
}
|
||||
|
||||
void CMSP3430::SetSCARTSignalPath()
|
||||
{
|
||||
// select SCART DSP input and output
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_ACB_REG,fACB);
|
||||
}
|
||||
|
||||
void CMSP3430::SetDemodulator()
|
||||
{
|
||||
// set preferred mode and sound IF input
|
||||
// (automatic, enable STATUS change, detect 4.5 MHz carrier as BTSC)
|
||||
SetRegister(MSP3430_WR_DEM, MODUS, 0x2003);
|
||||
|
||||
// set preferred prescale (FM and NICAM)
|
||||
SetRegister(MSP3430_WR_DSP, PRE_FM, fFMPrescale);
|
||||
SetRegister(MSP3430_WR_DSP, PRE_NICAM, fNICAMPrescale);
|
||||
|
||||
// automatic sound standard selection
|
||||
SetRegister(MSP3430_WR_DEM, MSP3430_DEM_STANDARD_SEL, 0x0001);
|
||||
|
||||
// readback the detected TV sound or FM-radio standard
|
||||
while ((fStandard = Register(MSP3430_RD_DEM, STANDARD_RES)) >= 0x0800)
|
||||
snooze(100000);
|
||||
}
|
||||
|
||||
void CMSP3430::SetSCARTInput()
|
||||
{
|
||||
// select preferred prescale for SCART and I2C
|
||||
SetRegister(MSP3430_WR_DSP, PRE_SCART, fSCARTPrescale);
|
||||
SetRegister(MSP3430_WR_DSP, PRE_I2S1, fI2SPrescale);
|
||||
SetRegister(MSP3430_WR_DSP, PRE_I2S2, fI2SPrescale);
|
||||
}
|
||||
|
||||
void CMSP3430::SetOutputChannels()
|
||||
{
|
||||
// select source channel and matrix for each output
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_MAIN, fMainMatrix);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_AUX, fAuxMatrix);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_SCART1, fSCART1Matrix);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_SCART2, fSCART2Matrix);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_I2S, fI2SMatrix);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SRC_MAT_QPEAK, fQPeakMatrix);
|
||||
|
||||
// set audio baseband processing
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_TONE_MODE, fToneControl);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_BASS_MAIN, fBass);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_BASS_AUX, fBass);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_TREB_MAIN, fTreble);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_TREB_AUX, fTreble);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_EQUAL_BAND1, fEqualizer[0]);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_EQUAL_BAND2, fEqualizer[1]);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_EQUAL_BAND3, fEqualizer[2]);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_EQUAL_BAND4, fEqualizer[3]);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_EQUAL_BAND5, fEqualizer[4]);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_LOUD_MAIN, fLoudness);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_LOUD_AUX, fLoudness);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_SPAT_MAIN, fSpatial);
|
||||
|
||||
// select volume for each output channel
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_VOL_MAIN, fVolume);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_VOL_AUX, fVolume);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_AVC, fAVC);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_BAL_MAIN, fBalance);
|
||||
SetRegister(MSP3430_WR_DSP, MSP3430_DSP_BAL_AUX, fBalance);
|
||||
|
||||
SetRegister(MSP3430_WR_DSP, VOL_SCART1, fSCART1Volume);
|
||||
SetRegister(MSP3430_WR_DSP, VOL_SCART2, fSCART2Volume);
|
||||
|
||||
// set quasipeak detector readout
|
||||
SetRegister(MSP3430_WR_DSP, QPEAK_L, fQPeakLeft);
|
||||
SetRegister(MSP3430_WR_DSP, QPEAK_R, fQPeakRight);
|
||||
}
|
||||
|
||||
void CMSP3430::SetSubwooferAndMDBOutputChannels()
|
||||
{
|
||||
// set subwoofer output channel
|
||||
SetRegister(MSP3430_WR_DSP, SUBW_LEVEL, fSubwooferLevel);
|
||||
SetRegister(MSP3430_WR_DSP, SUBW_FREQ, fSubwooferFrequency);
|
||||
|
||||
// set MDB control
|
||||
SetRegister(MSP3430_WR_DSP, MDB_STR, fMDBStrength);
|
||||
SetRegister(MSP3430_WR_DSP, MDB_LIM, fMDBLimit);
|
||||
SetRegister(MSP3430_WR_DSP, MDB_HMC, fMDBHarmonic);
|
||||
SetRegister(MSP3430_WR_DSP, MDB_LP, fMDBLowPass);
|
||||
SetRegister(MSP3430_WR_DSP, MDB_HP, fMDBHighPass);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
int CMSP3430::ControlRegister()
|
||||
{
|
||||
char message[1], result[2];
|
||||
|
||||
message[0] = MSP3430_CONTROL;
|
||||
if (fPort.Write(fAddress, message, sizeof(message), result, sizeof(result)))
|
||||
return ((result[0] << 8) & 0xff00) + ((result[1] << 0) & 0x00ff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CMSP3430::SetControlRegister(int value)
|
||||
{
|
||||
char message[3];
|
||||
|
||||
message[0] = MSP3430_CONTROL;
|
||||
message[1] = value >> 8;
|
||||
message[2] = value >> 0;
|
||||
|
||||
if (!fPort.Write(fAddress, message, sizeof(message)))
|
||||
PRINT(("CMSP3430::SetControl() - error\n"));
|
||||
}
|
||||
|
||||
int CMSP3430::Register(int address, int subaddress)
|
||||
{
|
||||
char message[3], response[2];
|
||||
|
||||
message[0] = address;
|
||||
message[1] = subaddress >> 8;
|
||||
message[2] = subaddress >> 0;
|
||||
|
||||
if (fPort.Write(fAddress, message, sizeof(message), response, sizeof(response)))
|
||||
return ((response[0] << 8) & 0xff00) + ((response[1] << 0) & 0x00ff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CMSP3430::SetRegister(int address, int subaddress, int value)
|
||||
{
|
||||
char message[5];
|
||||
|
||||
message[0] = address;
|
||||
message[1] = subaddress >> 8;
|
||||
message[2] = subaddress >> 0;
|
||||
message[3] = value >> 8;
|
||||
message[4] = value >> 0;
|
||||
|
||||
if (!fPort.Write(fAddress, message, sizeof(message)))
|
||||
PRINT(("CMSP3430::SetRegister() - error\n"));
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: MSP3430.h
|
||||
/
|
||||
/ Description: Micronas Multistandard Sound Processor (MSP) interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __MSP3430_H__
|
||||
#define __MSP3430_H__
|
||||
|
||||
#include "I2CPort.h"
|
||||
|
||||
class CMSP3430 {
|
||||
public:
|
||||
CMSP3430(CI2CPort & port);
|
||||
|
||||
~CMSP3430();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
void SetEnable(bool enable);
|
||||
|
||||
private:
|
||||
int ControlRegister();
|
||||
|
||||
void SetControlRegister(int value);
|
||||
|
||||
int Register(int address, int subaddress);
|
||||
|
||||
void SetRegister(int address, int subaddress, int value);
|
||||
|
||||
private:
|
||||
CI2CPort & fPort;
|
||||
int fAddress;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,899 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: Radeon.cpp
|
||||
/
|
||||
/ Description: ATI Radeon Graphics Chip interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <Debug.h>
|
||||
#include <string.h>
|
||||
//#include "Driver.h"
|
||||
#include "Radeon.h"
|
||||
|
||||
static const char * const C_RADEON_REGISTER_AREA_NAME = "RadeonRegisters";
|
||||
static const char * const C_RADEON_MEMORY_AREA_NAME = "RadeonMemory";
|
||||
static const char * const C_RADEON_ROM_AREA_NAME = "RadeonROM";
|
||||
|
||||
// CRadeonRect
|
||||
CRadeonRect::CRadeonRect()
|
||||
: fLeft(0),
|
||||
fTop(0),
|
||||
fRight(0),
|
||||
fBottom(0)
|
||||
{
|
||||
}
|
||||
|
||||
CRadeonRect::CRadeonRect(int left, int top, int right, int bottom)
|
||||
: fLeft(left),
|
||||
fTop(top),
|
||||
fRight(right),
|
||||
fBottom(bottom)
|
||||
{
|
||||
}
|
||||
|
||||
int CRadeonRect::Left() const
|
||||
{
|
||||
return fLeft;
|
||||
}
|
||||
|
||||
int CRadeonRect::Top() const
|
||||
{
|
||||
return fTop;
|
||||
}
|
||||
|
||||
int CRadeonRect::Right() const
|
||||
{
|
||||
return fRight;
|
||||
}
|
||||
|
||||
int CRadeonRect::Bottom() const
|
||||
{
|
||||
return fBottom;
|
||||
}
|
||||
|
||||
int CRadeonRect::Width() const
|
||||
{
|
||||
return fRight - fLeft + 1;
|
||||
}
|
||||
|
||||
int CRadeonRect::Height() const
|
||||
{
|
||||
return fBottom - fTop + 1;
|
||||
}
|
||||
|
||||
void CRadeonRect::SetLeft(int value)
|
||||
{
|
||||
fLeft = value;
|
||||
}
|
||||
|
||||
void CRadeonRect::SetTop(int value)
|
||||
{
|
||||
fTop = value;
|
||||
}
|
||||
|
||||
void CRadeonRect::SetRight(int value)
|
||||
{
|
||||
fRight = value;
|
||||
}
|
||||
|
||||
void CRadeonRect::SetBottom(int value)
|
||||
{
|
||||
fBottom = value;
|
||||
}
|
||||
|
||||
void CRadeonRect::SetTo(int left, int top, int right, int bottom)
|
||||
{
|
||||
fLeft = left;
|
||||
fTop = top;
|
||||
fRight = right;
|
||||
fBottom = bottom;
|
||||
}
|
||||
|
||||
void CRadeonRect::MoveTo(int left, int top)
|
||||
{
|
||||
fRight += left - fLeft;
|
||||
fBottom += top - fTop;
|
||||
fLeft += left - fLeft;
|
||||
fTop += top - fTop;
|
||||
}
|
||||
|
||||
void CRadeonRect::ResizeTo(int width, int height)
|
||||
{
|
||||
fRight = fLeft + width - 1;
|
||||
fBottom = fTop + height - 1;
|
||||
}
|
||||
|
||||
|
||||
// CRadeon
|
||||
CRadeon::CRadeon( const char *dev_name )
|
||||
: fHandle(0),
|
||||
fRegister(NULL),
|
||||
fROM(NULL),
|
||||
fVirtualCard(NULL),
|
||||
fSharedInfo(NULL),
|
||||
fRegisterArea(0),
|
||||
fROMArea(0),
|
||||
fVirtualCardArea(0),
|
||||
fSharedInfoArea(0)
|
||||
{
|
||||
PRINT(("CRadeon::CRadeon()\n"));
|
||||
|
||||
if ((fHandle = open(dev_name, O_RDWR | O_CLOEXEC)) < 0) {
|
||||
PRINT(("CRadeon::CRadeon() - Can't open kernel driver\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
radeon_get_private_data gpd;
|
||||
|
||||
if (GetDeviceInformation(gpd) < B_OK) {
|
||||
PRINT(("CRadeon::CRadeon() - Can't get device information\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
CloneArea(
|
||||
"Radeon virtual card", gpd.virtual_card_area,
|
||||
&fVirtualCardArea, (void **)&fVirtualCard );
|
||||
CloneArea(
|
||||
"Radeon shared info", gpd.shared_info_area,
|
||||
&fSharedInfoArea, (void **)&fSharedInfo );
|
||||
|
||||
if( fSharedInfo != NULL ) {
|
||||
CloneArea(
|
||||
"Radeon regs", fSharedInfo->regs_area,
|
||||
&fRegisterArea, (void **)&fRegister );
|
||||
CloneArea(
|
||||
"Radeon ROM", fSharedInfo->ROM_area,
|
||||
&fROMArea, (void **)&fROM );
|
||||
}
|
||||
|
||||
if (fVirtualCard == NULL || fSharedInfo == NULL ||
|
||||
fROM == NULL || fRegister == NULL)
|
||||
{
|
||||
PRINT(("CRadeon::CRadeon() - Can't map memory apertures\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
PRINT(("CRadeon::CRadeon() - ATI Radeon found\n"));
|
||||
}
|
||||
|
||||
CRadeon::~CRadeon()
|
||||
{
|
||||
PRINT(("CRadeon::~CRadeon()\n"));
|
||||
|
||||
if( fVirtualCard != NULL )
|
||||
delete_area( fVirtualCardArea );
|
||||
|
||||
if( fSharedInfo != NULL )
|
||||
delete_area( fSharedInfoArea );
|
||||
|
||||
if (fRegister != NULL)
|
||||
delete_area( fRegisterArea );
|
||||
|
||||
if (fROM != NULL)
|
||||
delete_area( fROMArea );
|
||||
|
||||
if (fHandle >= 0)
|
||||
close(fHandle);
|
||||
}
|
||||
|
||||
status_t CRadeon::InitCheck() const
|
||||
{
|
||||
return
|
||||
(fHandle >= 0 &&
|
||||
fRegister != NULL && fROM != NULL &&
|
||||
fVirtualCard != NULL && fSharedInfo != NULL) ? B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
uint32 CRadeon::VirtualMemoryBase() const
|
||||
{
|
||||
return fSharedInfo->memory[mt_local].virtual_addr_start;
|
||||
}
|
||||
|
||||
int CRadeon::Register(radeon_register index) const
|
||||
{
|
||||
return fRegister[index >> 2];
|
||||
}
|
||||
|
||||
void CRadeon::SetRegister(radeon_register index, int value)
|
||||
{
|
||||
fRegister[index >> 2] = value;
|
||||
}
|
||||
|
||||
int CRadeon::Register(radeon_register index, int mask) const
|
||||
{
|
||||
return fRegister[index >> 2] & mask;
|
||||
}
|
||||
|
||||
void CRadeon::SetRegister(radeon_register index, int mask, int value)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if ((value & ~mask) != 0)
|
||||
PRINT(("CRadeon::SetRegister(0x%04x, 0x%08x, 0x%08x)\n", index, mask, value));
|
||||
#endif
|
||||
|
||||
fRegister[index >> 2] = (fRegister[index >> 2] & ~mask) | (value & mask);
|
||||
}
|
||||
|
||||
int CRadeon::VIPRegister(int device, int address)
|
||||
{
|
||||
radeon_vip_read vr;
|
||||
status_t res;
|
||||
|
||||
vr.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
vr.channel = device;
|
||||
vr.address = address;
|
||||
|
||||
res = ioctl( fHandle, RADEON_VIPREAD, &vr, sizeof( vr ));
|
||||
|
||||
if( res == B_OK )
|
||||
return vr.data;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CRadeon::SetVIPRegister(int device, int address, int value)
|
||||
{
|
||||
radeon_vip_write vw;
|
||||
|
||||
vw.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
vw.channel = device;
|
||||
vw.address = address;
|
||||
vw.data = value;
|
||||
|
||||
ioctl( fHandle, RADEON_VIPWRITE, &vw, sizeof( vw ));
|
||||
}
|
||||
|
||||
int CRadeon::FindVIPDevice( uint32 device_id )
|
||||
{
|
||||
radeon_find_vip_device fvd;
|
||||
status_t res;
|
||||
|
||||
fvd.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
fvd.device_id = device_id;
|
||||
|
||||
res = ioctl( fHandle, RADEON_FINDVIPDEVICE, &fvd, sizeof( fvd ));
|
||||
|
||||
if( res == B_OK )
|
||||
return fvd.channel;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CRadeon::GetPLLParameters(int & refFreq, int & refDiv, int & minFreq, int & maxFreq, int & xclock)
|
||||
{
|
||||
refFreq = fSharedInfo->pll.ref_freq;
|
||||
refDiv = fSharedInfo->pll.ref_div;
|
||||
minFreq = fSharedInfo->pll.min_pll_freq;
|
||||
maxFreq = fSharedInfo->pll.max_pll_freq;
|
||||
xclock = fSharedInfo->pll.xclk;
|
||||
}
|
||||
|
||||
void CRadeon::GetMMParameters(radeon_video_tuner & tuner,
|
||||
radeon_video_decoder & video,
|
||||
radeon_video_clock & clock,
|
||||
int & tunerPort,
|
||||
int & compositePort,
|
||||
int & svideoPort)
|
||||
{
|
||||
unsigned char *fVideoBIOS = fROM + fROM[0x48] + (fROM[0x49] << 8);
|
||||
unsigned char * fMMTable = fROM + fVideoBIOS[0x38] + (fVideoBIOS[0x39] << 8);
|
||||
|
||||
switch (fMMTable[0] & 0x1f) {
|
||||
case 0x00:
|
||||
tuner = C_RADEON_NO_TUNER;
|
||||
break;
|
||||
case 0x01:
|
||||
tuner = C_RADEON_FI1236_MK1_NTSC;
|
||||
break;
|
||||
case 0x02:
|
||||
tuner = C_RADEON_FI1236_MK2_NTSC_JAPAN;
|
||||
break;
|
||||
case 0x03:
|
||||
tuner = C_RADEON_FI1216_MK2_PAL_BG;
|
||||
break;
|
||||
case 0x04:
|
||||
tuner = C_RADEON_FI1246_MK2_PAL_I;
|
||||
break;
|
||||
case 0x05:
|
||||
tuner = C_RADEON_FI1216_MF_MK2_PAL_BG_SECAM_L;
|
||||
break;
|
||||
case 0x06:
|
||||
tuner = C_RADEON_FI1236_MK2_NTSC;
|
||||
break;
|
||||
case 0x07:
|
||||
tuner = C_RADEON_FI1256_MK2_SECAM_DK;
|
||||
break;
|
||||
case 0x08:
|
||||
tuner = C_RADEON_FI1236_MK2_NTSC;
|
||||
break;
|
||||
case 0x09:
|
||||
tuner = C_RADEON_FI1216_MK2_PAL_BG;
|
||||
break;
|
||||
case 0x0a:
|
||||
tuner = C_RADEON_FI1246_MK2_PAL_I;
|
||||
break;
|
||||
case 0x0b:
|
||||
tuner = C_RADEON_FI1216_MK2_PAL_BG_SECAM_L;
|
||||
break;
|
||||
case 0x0c:
|
||||
tuner = C_RADEON_FI1236_MK2_NTSC;
|
||||
break;
|
||||
case 0x0d:
|
||||
tuner = C_RADEON_TEMIC_FN5AL_PAL_IBGDK_SECAM_DK;
|
||||
break;
|
||||
default:
|
||||
tuner = C_RADEON_NO_TUNER;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (fMMTable[5] & 0x0f) {
|
||||
case 0x00:
|
||||
video = C_RADEON_NO_VIDEO;
|
||||
break;
|
||||
case 0x01:
|
||||
video = C_RADEON_BT819;
|
||||
break;
|
||||
case 0x02:
|
||||
video = C_RADEON_BT829;
|
||||
break;
|
||||
case 0x03:
|
||||
video = C_RADEON_BT829A;
|
||||
break;
|
||||
case 0x04:
|
||||
video = C_RADEON_SA7111;
|
||||
break;
|
||||
case 0x05:
|
||||
video = C_RADEON_SA7112;
|
||||
break;
|
||||
case 0x06:
|
||||
video = C_RADEON_RAGE_THEATER;
|
||||
break;
|
||||
default:
|
||||
video = C_RADEON_NO_VIDEO;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (fMMTable[5] & 0xf0) {
|
||||
case 0x00:
|
||||
case 0x10:
|
||||
case 0x20:
|
||||
case 0x30:
|
||||
clock = C_RADEON_NO_VIDEO_CLOCK;
|
||||
break;
|
||||
case 0x40:
|
||||
clock = C_RADEON_VIDEO_CLOCK_28_63636_MHZ;
|
||||
break;
|
||||
case 0x50:
|
||||
clock = C_RADEON_VIDEO_CLOCK_29_49892_MHZ;
|
||||
break;
|
||||
case 0x60:
|
||||
clock = C_RADEON_VIDEO_CLOCK_27_00000_MHZ;
|
||||
break;
|
||||
case 0x70:
|
||||
clock = C_RADEON_VIDEO_CLOCK_14_31818_MHZ;
|
||||
break;
|
||||
default:
|
||||
clock = C_RADEON_NO_VIDEO_CLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int port = 0; port < 4; port++) {
|
||||
switch (fMMTable[7 + port] & 0x03) {
|
||||
case 0x00:
|
||||
// Unused or Invalid
|
||||
break;
|
||||
case 0x01:
|
||||
// Tuner Input
|
||||
tunerPort = 0;
|
||||
break;
|
||||
case 0x02:
|
||||
// Front/Rear Composite Input
|
||||
compositePort = (fMMTable[7 + port] & 0x04 ? 2 : 1);
|
||||
break;
|
||||
case 0x03:
|
||||
// Front/Rear SVideo Input
|
||||
svideoPort = (fMMTable[7 + port] & 0x04 ? 6 : 5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status_t CRadeon::AllocateGraphicsMemory(
|
||||
memory_type_e memory_type, int32 size,
|
||||
int32 *offset, int32 *handle )
|
||||
{
|
||||
radeon_alloc_mem am;
|
||||
status_t res;
|
||||
|
||||
am.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
am.size = size;
|
||||
am.memory_type = mt_local;
|
||||
am.global = false;
|
||||
|
||||
res = ioctl( fHandle, RADEON_ALLOC_MEM, &am );
|
||||
|
||||
if( res != B_OK )
|
||||
return res;
|
||||
|
||||
*handle = am.handle;
|
||||
*offset = am.offset;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void CRadeon::FreeGraphicsMemory(
|
||||
memory_type_e memory_type, int32 handle )
|
||||
{
|
||||
radeon_free_mem fm;
|
||||
|
||||
fm.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
fm.memory_type = memory_type;
|
||||
fm.global = false;
|
||||
fm.handle = handle;
|
||||
|
||||
ioctl( fHandle, RADEON_FREE_MEM, &fm );
|
||||
}
|
||||
|
||||
status_t CRadeon::DMACopy(
|
||||
uint32 src, void *target, size_t size, bool lock_mem, bool contiguous )
|
||||
{
|
||||
radeon_dma_copy dc;
|
||||
|
||||
dc.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
dc.src = src;
|
||||
dc.target = target;
|
||||
dc.size = size;
|
||||
dc.lock_mem = lock_mem;
|
||||
dc.contiguous = contiguous;
|
||||
|
||||
return ioctl( fHandle, RADEON_DMACOPY, &dc );
|
||||
}
|
||||
|
||||
status_t CRadeon::GetDeviceInformation(radeon_get_private_data & info)
|
||||
{
|
||||
info.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
|
||||
return ioctl( fHandle, RADEON_GET_PRIVATE_DATA, &info, sizeof( info ));
|
||||
}
|
||||
|
||||
status_t CRadeon::CloneArea(const char * name, area_id src_area,
|
||||
area_id *cloned_area, void ** map)
|
||||
{
|
||||
int res = clone_area( name, map, B_ANY_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA, src_area );
|
||||
|
||||
if( res < 0 ) {
|
||||
return res;
|
||||
} else {
|
||||
*cloned_area = res;
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
status_t CRadeon::WaitInterrupt(int * mask, int * sequence, bigtime_t * time, bigtime_t timeout)
|
||||
{
|
||||
radeon_wait_for_cap_irq wvc;
|
||||
status_t status;
|
||||
|
||||
wvc.magic = RADEON_PRIVATE_DATA_MAGIC;
|
||||
wvc.timeout = timeout;
|
||||
|
||||
status = ioctl( fHandle, RADEON_WAIT_FOR_CAP_IRQ, &wvc );
|
||||
|
||||
if( status == B_OK ) {
|
||||
*mask = wvc.int_status;
|
||||
*sequence = wvc.counter;
|
||||
*time = wvc.timestamp;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void CRadeon::PrintToStream()
|
||||
{
|
||||
// ATI ROM Signature
|
||||
if (ROM(0) == 0x55 && ROM(1) == 0xAA) {
|
||||
for (int offset = 0; offset < 128 - 9; offset++) {
|
||||
if (ROM(offset + 0) == '7' &&
|
||||
ROM(offset + 1) == '6' &&
|
||||
ROM(offset + 2) == '1' &&
|
||||
ROM(offset + 3) == '2' &&
|
||||
ROM(offset + 4) == '9' &&
|
||||
ROM(offset + 5) == '5' &&
|
||||
ROM(offset + 6) == '5' &&
|
||||
ROM(offset + 7) == '2' &&
|
||||
ROM(offset + 8) == '0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Video BIOS
|
||||
unsigned char *fVideoBIOS = fROM + fROM[0x48] + (fROM[0x49] << 8);
|
||||
|
||||
PRINT((
|
||||
"----------------------------------------------------------------------\n"
|
||||
"ATI RADEON VIDEO BIOS\n"
|
||||
"\n"
|
||||
"BIOS Revision: %03d.%03d.%03d%03d.%s\n"
|
||||
"PCI Bus/Device/Function Code: 0x%04x\n"
|
||||
"BIOS Runtime Segment Address: 0x%04x\n"
|
||||
"I/O Base Address: 0x%04x\n"
|
||||
"Subsystem Vendor ID: 0x%04x\n"
|
||||
"Subsystem ID: 0x%04x\n"
|
||||
"Post Vendor ID: 0x%04x\n"
|
||||
"\n",
|
||||
|
||||
// OEM Revision (ID1.ID2.REVISION.CONFIG_FILE)
|
||||
fVideoBIOS[2], fVideoBIOS[3],
|
||||
fVideoBIOS[4], fVideoBIOS[5],
|
||||
fROM + fVideoBIOS[0x10] + (fVideoBIOS[0x11] << 8),
|
||||
|
||||
// PCI bus, device, function code
|
||||
fVideoBIOS[0x16] + (fVideoBIOS[0x17] << 8),
|
||||
|
||||
// ROM BIOS segment
|
||||
fVideoBIOS[0x18] + (fVideoBIOS[0x19] << 8),
|
||||
|
||||
// I/O base address
|
||||
fVideoBIOS[0x1a] + (fVideoBIOS[0x1b] << 8),
|
||||
|
||||
// Subsystem Vendor ID, Subsystem ID, Post Vendor ID
|
||||
fVideoBIOS[0x1c] + (fVideoBIOS[0x1d] << 8),
|
||||
fVideoBIOS[0x1e] + (fVideoBIOS[0x1f] << 8),
|
||||
fVideoBIOS[0x20] + (fVideoBIOS[0x21] << 8)
|
||||
));
|
||||
|
||||
|
||||
// PLL Information
|
||||
unsigned char *fPLL = fROM + fVideoBIOS[0x30] + (fVideoBIOS[0x31] << 8);
|
||||
|
||||
PRINT((
|
||||
"----------------------------------------------------------------------\n"
|
||||
"ATI RADEON PLL INFORMATION TABLE\n"
|
||||
"\n"
|
||||
"External Clock: %g MHz\n"
|
||||
"Reference Frequency: %g MHz\n"
|
||||
"Reference Divisor: %d\n"
|
||||
"Min PLL Frequency: %g MHz\n"
|
||||
"Max PLL Frequency: %g MHz\n"
|
||||
"\n",
|
||||
(fPLL[0x08] + (fPLL[0x09] << 8)) / 1000.0,
|
||||
(fPLL[0x0e] + (fPLL[0x0f] << 8)) / 100.0,
|
||||
fPLL[0x10] + (fPLL[0x11] << 8),
|
||||
(fPLL[0x12] + (fPLL[0x13] << 8) + (fPLL[0x14] << 16) + (fPLL[0x15] << 24)) / 1000.0,
|
||||
(fPLL[0x12] + (fPLL[0x16] << 8) + (fPLL[0x17] << 16) + (fPLL[0x18] << 24)) / 1000.0));
|
||||
|
||||
|
||||
// TV Table
|
||||
unsigned char * fTVTable = fROM + fVideoBIOS[0x32] + (fVideoBIOS[0x33] << 8);
|
||||
|
||||
PRINT((
|
||||
"----------------------------------------------------------------------\n"
|
||||
"ATI RADEON TV INFORMATION TABLE\n"
|
||||
"\n"
|
||||
"Table Signature: %c%c%c\n"
|
||||
"Table Version: %d\n"
|
||||
"Table Size: %d bytes\n"
|
||||
"\n"
|
||||
"TVOut Support: %s\n"
|
||||
"BIOS built-in TV standard: %s\n"
|
||||
"TVOut information: %s, %s MHz\n"
|
||||
"\n"
|
||||
"Run time supported TV standard:%s%s%s%s%s%s\n"
|
||||
"Initialization time supported TV standard:%s%s%s%s%s%s\n"
|
||||
"\n",
|
||||
|
||||
// Table signature, version and size
|
||||
fTVTable[0x00],fTVTable[0x01], fTVTable[0x02],
|
||||
fTVTable[0x03],
|
||||
fTVTable[0x04] + ((int) fTVTable[0x05] << 8),
|
||||
|
||||
// TVOut support
|
||||
fTVTable[0x06] == 'N' ? "TVOut chip not found" : "TVOut chip on board",
|
||||
|
||||
// BIOS built-in initialization TV standard
|
||||
(fTVTable[0x07] & 0x0f) == 0x01 ? "NTSC" :
|
||||
(fTVTable[0x07] & 0x0f) == 0x02 ? "PAL" :
|
||||
(fTVTable[0x07] & 0x0f) == 0x03 ? "PAL-M" :
|
||||
(fTVTable[0x07] & 0x0f) == 0x04 ? "PAL-60" :
|
||||
(fTVTable[0x07] & 0x0f) == 0x05 ? "NTSC-J" :
|
||||
(fTVTable[0x07] & 0x0f) == 0x06 ? "SCART-PAL" : "Reserved",
|
||||
|
||||
// TV Out information
|
||||
(fTVTable[0x09] & 0x03) == 0x00 ? "Invalid" :
|
||||
(fTVTable[0x09] & 0x03) == 0x01 ? "TV off, CRT on" :
|
||||
(fTVTable[0x09] & 0x03) == 0x02 ? "TV on, CRT off" : "TV on, CRT on",
|
||||
|
||||
(fTVTable[0x09] & 0x0c) == 0x00 ? "29.498928713" :
|
||||
(fTVTable[0x09] & 0x0c) == 0x04 ? "28.63636" :
|
||||
(fTVTable[0x09] & 0x0c) == 0x08 ? "14.31818" : "27.0",
|
||||
|
||||
// Runtime supported TV standard
|
||||
(fTVTable[0x0a] & 0x01) != 0 ? " NTSC" : "",
|
||||
(fTVTable[0x0a] & 0x02) != 0 ? " PAL" : "",
|
||||
(fTVTable[0x0a] & 0x04) != 0 ? " PAL-M" : "",
|
||||
(fTVTable[0x0a] & 0x08) != 0 ? " PAL-60" : "",
|
||||
(fTVTable[0x0a] & 0x10) != 0 ? " NTSC-J" : "",
|
||||
(fTVTable[0x0a] & 0x20) != 0 ? " SCART-PAL" : "",
|
||||
|
||||
// Initialization time supported TV standard
|
||||
(fTVTable[0x0b] & 0x01) != 0 ? " NTSC" : "",
|
||||
(fTVTable[0x0b] & 0x02) != 0 ? " PAL" : "",
|
||||
(fTVTable[0x0b] & 0x04) != 0 ? " PAL-M" : "",
|
||||
(fTVTable[0x0b] & 0x08) != 0 ? " PAL-60" : "",
|
||||
(fTVTable[0x0b] & 0x10) != 0 ? " NTSC-J" : "",
|
||||
(fTVTable[0x0b] & 0x20) != 0 ? " SCART-PAL" : ""
|
||||
));
|
||||
|
||||
// Hardware Configuration Table
|
||||
unsigned char * fHWTable = fROM + fVideoBIOS[0x36] + (fVideoBIOS[0x37] << 8);
|
||||
|
||||
PRINT((
|
||||
"----------------------------------------------------------------------\n"
|
||||
"ATI RADEON HARDWARE CONFIGURATION TABLE\n"
|
||||
"\n"
|
||||
"Table Signature: %c%c%c%c\n"
|
||||
"Table Revision: %d\n"
|
||||
"Table Size: %d\n"
|
||||
"\n"
|
||||
"I2C Type: %s\n"
|
||||
"TVOut Support: %s\n"
|
||||
"Video Out Crystal: %s\n"
|
||||
"ImpactTV Data Port: %s\n"
|
||||
"\n"
|
||||
"Video Port Capability:\n"
|
||||
" AMC/DVS0 Video Port: %s\n"
|
||||
" Zoom Video Port: %s\n"
|
||||
" AMC/DVS1 Video Port: %s\n"
|
||||
" VIP 16-bit Video Port: %s\n"
|
||||
"\n"
|
||||
"Host Port Configuration: %s\n"
|
||||
"\n",
|
||||
|
||||
// Table Signature, Revision, Size
|
||||
fHWTable[0x00], fHWTable[0x01], fHWTable[0x02], fHWTable[0x03],
|
||||
fHWTable[0x04], fHWTable[0x05],
|
||||
|
||||
// I2C type
|
||||
(fHWTable[0x06] & 0x0f) == 0x00 ? "Normal GP I/O (data=GP_IO2, clock=GP_IO1)" :
|
||||
(fHWTable[0x06] & 0x0f) == 0x01 ? "ImpacTV GP I/O" :
|
||||
(fHWTable[0x06] & 0x0f) == 0x02 ? "Dedicated I2C Pin" :
|
||||
(fHWTable[0x06] & 0x0f) == 0x03 ? "GP I/O (data=GP_IO12, clock=GP_IO13)" :
|
||||
(fHWTable[0x06] & 0x0f) == 0x04 ? "GP I/O (data=GPIO12, clock=GPIO10)" :
|
||||
(fHWTable[0x06] & 0x0f) == 0x05 ? "RAGE THEATER I2C Master" :
|
||||
(fHWTable[0x06] & 0x0f) == 0x06 ? "Rage128 MPP2 Pin" :
|
||||
(fHWTable[0x06] & 0x0f) == 0x0f ? "No I2C Configuration" : "Reserved",
|
||||
|
||||
// TVOut support
|
||||
(fHWTable[0x07] & 0x0f) == 0x00 ? "No TVOut supported" :
|
||||
(fHWTable[0x07] & 0x0f) == 0x01 ? "ImpactTV1 supported" :
|
||||
(fHWTable[0x07] & 0x0f) == 0x02 ? "ImpactTV2 supported" :
|
||||
(fHWTable[0x07] & 0x0f) == 0x03 ? "Improved ImpactTV2 supported" :
|
||||
(fHWTable[0x07] & 0x0f) == 0x04 ? "RAGE THEATER supported" : "Reserved",
|
||||
|
||||
// Video Out Crystal
|
||||
(fHWTable[0x07] & 0x70) == 0x00 ? "TVOut not installed" :
|
||||
(fHWTable[0x07] & 0x70) == 0x10 ? "28.63636 MHz" :
|
||||
(fHWTable[0x07] & 0x70) == 0x20 ? "29.49892713 MHz" :
|
||||
(fHWTable[0x07] & 0x70) == 0x30 ? "27.0 MHz" :
|
||||
(fHWTable[0x07] & 0x70) == 0x40 ? "14.31818 MHz" : "Reserved",
|
||||
|
||||
// ImpactTV data port
|
||||
(fHWTable[0x07] & 0x80) == 0x00 ? "MPP1" : "MPP2",
|
||||
|
||||
// Video Port Capability
|
||||
(fHWTable[0x08] & 0x01) == 0x00 ? "Not Supported" : "Supported",
|
||||
(fHWTable[0x08] & 0x02) == 0x00 ? "Not Supported" : "Supported",
|
||||
(fHWTable[0x08] & 0x04) == 0x00 ? "Not Supported" : "Supported",
|
||||
(fHWTable[0x08] & 0x08) == 0x00 ? "Not Supported" : "Supported",
|
||||
|
||||
// Host Port Configuration
|
||||
(fHWTable[0x09] & 0x0f) == 0x00 ? "No Host Port" :
|
||||
(fHWTable[0x09] & 0x0f) == 0x01 ? "MPP Host Port" :
|
||||
(fHWTable[0x09] & 0x0f) == 0x02 ? "2 bit VIP Host Port" :
|
||||
(fHWTable[0x09] & 0x0f) == 0x03 ? "4 bit VIP Host Port" :
|
||||
(fHWTable[0x09] & 0x0f) == 0x04 ? "8 bit VIP Host Port" : "Reserved"
|
||||
));
|
||||
|
||||
// Multimedia Table
|
||||
unsigned char * fMMTable = fROM + fVideoBIOS[0x38] + (fVideoBIOS[0x39] << 8);
|
||||
|
||||
PRINT((
|
||||
"----------------------------------------------------------------------\n"
|
||||
"ATI RADEON MULTIMEDIA TABLE\n"
|
||||
"\n"
|
||||
"Table Revision: %d\n"
|
||||
"Table Size: %d bytes\n"
|
||||
"\n"
|
||||
"Tuner Chip: %s\n"
|
||||
"Tuner Input: %s\n"
|
||||
"Tuner Voltage Regulator: %s\n"
|
||||
"\n"
|
||||
"Audio Chip: %s\n"
|
||||
"FM Audio Decoder: %s\n"
|
||||
"Audio Scrambling: %s\n"
|
||||
"\n"
|
||||
"Product Type: %s, Revision %d\n"
|
||||
"Product ID: %s\n"
|
||||
"\n"
|
||||
"I2S Input Configuration: %s\n"
|
||||
"I2S Output Configuration: %s\n"
|
||||
"I2S Audio Chip: %s\n"
|
||||
"S/PDIF Output Configuration: %s\n"
|
||||
"\n"
|
||||
"Video Decoder: %s\n"
|
||||
"Video Standard/Crystal: %s\n"
|
||||
"Video Decoder Host Config: %s\n"
|
||||
"Hardware Teletext: %s\n"
|
||||
"\n"
|
||||
"Video Input:\n"
|
||||
" 0: %s, %s (ID %d)\n"
|
||||
" 1: %s, %s (ID %d)\n"
|
||||
" 2: %s, %s (ID %d)\n"
|
||||
" 3: %s, %s (ID %d)\n"
|
||||
" 4: %s, %s (ID %d)\n"
|
||||
"\n",
|
||||
|
||||
/* Hardware Table */
|
||||
fMMTable[-2], fMMTable[-1],
|
||||
|
||||
/* Tuner Type */
|
||||
(fMMTable[0] & 0x1f) == 0x00 ? "No Tuner" :
|
||||
(fMMTable[0] & 0x1f) == 0x01 ? "Philips FI1236 MK1 NTSC M/N North America" :
|
||||
(fMMTable[0] & 0x1f) == 0x02 ? "Philips FI1236 MK2 NTSC M/N Japan" :
|
||||
|
||||
(fMMTable[0] & 0x1f) == 0x03 ? "Philips FI1216 MK2 PAL B/G" :
|
||||
(fMMTable[0] & 0x1f) == 0x04 ? "Philips FI1246 MK2 PAL I" :
|
||||
(fMMTable[0] & 0x1f) == 0x05 ? "Philips FI1216 MF MK2 PAL B/G, SECAM L/L'" :
|
||||
(fMMTable[0] & 0x1f) == 0x06 ? "Philips FI1236 MK2 NTSC M/N North America" :
|
||||
(fMMTable[0] & 0x1f) == 0x07 ? "Philips FI1256 MK2 SECAM D/K" :
|
||||
(fMMTable[0] & 0x1f) == 0x08 ? "Philips FM1236 MK2 NTSC M/N North America" :
|
||||
|
||||
(fMMTable[0] & 0x1f) == 0x09 ? "Philips FI1216 MK2 PAL B/G - External Tuner POD" :
|
||||
(fMMTable[0] & 0x1f) == 0x0a ? "Philips FI1246 MK2 PAL I - External Tuner POD" :
|
||||
(fMMTable[0] & 0x1f) == 0x0b ? "Philips FI1216 MF MK2 PAL B/G, SECAM L/L' - External Tuner POD" :
|
||||
(fMMTable[0] & 0x1f) == 0x0c ? "Philips FI1236 MK2 NTSC M/N North America - External Tuner POD" :
|
||||
|
||||
(fMMTable[0] & 0x1f) == 0x0d ? "Temic FN5AL RF3X7595 PAL I/B/G/DK & SECAM DK" :
|
||||
(fMMTable[0] & 0x1f) == 0x10 ? "Alps TSBH5 NTSC M/N North America" :
|
||||
(fMMTable[0] & 0x1f) == 0x11 ? "Alps TSC?? NTSC M/N North America" :
|
||||
(fMMTable[0] & 0x1f) == 0x12 ? "Alps TSCH5 NTSC M/N North America" :
|
||||
|
||||
(fMMTable[0] & 0x1f) == 0x1f ? "Unknown Tuner Type" : "Reserved",
|
||||
|
||||
/* Video Input for Tuner */
|
||||
(fMMTable[0] & 0xe0) == 0x00 ? "Video Input 0" :
|
||||
(fMMTable[0] & 0xe0) == 0x20 ? "Video Input 1" :
|
||||
(fMMTable[0] & 0xe0) == 0x40 ? "Video Input 2" :
|
||||
(fMMTable[0] & 0xe0) == 0x60 ? "Video Input 3" :
|
||||
(fMMTable[0] & 0xe0) == 0x80 ? "Video Input 4" : "Reserved",
|
||||
|
||||
/* Tuner Voltage */
|
||||
(fMMTable[3] & 0x03) == 0x00 ? "No Tuner Power down feature" :
|
||||
(fMMTable[3] & 0x03) == 0x01 ? "Tuner Power down feature" : "Reserved",
|
||||
|
||||
/* Audio Chip Type */
|
||||
(fMMTable[1] & 0x0f) == 0x00 ? "Philips TEA5582 NTSC Stereo, no dbx, no volume" :
|
||||
(fMMTable[1] & 0x0f) == 0x01 ? "Mono with audio mux" :
|
||||
(fMMTable[1] & 0x0f) == 0x02 ? "Philips TDA9850 NTSC N.A. Stereo, dbx, mux, no volume" :
|
||||
(fMMTable[1] & 0x0f) == 0x03 ? "Sony CXA2020S Japan NTSC Stereo, mux, no volume" :
|
||||
(fMMTable[1] & 0x0f) == 0x04 ? "ITT MSP3410D Europe Stereo, volume, internal mux" :
|
||||
(fMMTable[1] & 0x0f) == 0x05 ? "Crystal CS4236B" :
|
||||
(fMMTable[1] & 0x0f) == 0x06 ? "Philips TDA9851 NTSC Stereo, volume, no dbx, no mux" :
|
||||
(fMMTable[1] & 0x0f) == 0x07 ? "ITT MSP3415 (Europe)" :
|
||||
(fMMTable[1] & 0x0f) == 0x08 ? "ITT MSP3430 (N.A.)" :
|
||||
(fMMTable[1] & 0x0f) == 0x0f ? "No Audio Chip Installed" : "Reserved",
|
||||
|
||||
/* FM Audio Decoder */
|
||||
(fMMTable[3] & 0x30) == 0x00 ? "No FM Audio Decoder" :
|
||||
(fMMTable[3] & 0x30) == 0x10 ? "FM Audio Decoder (Rohm BA1332F)" : "Reserved",
|
||||
|
||||
/* Audio Scrambling */
|
||||
(fMMTable[3] & 0x80) == 0x00 ? "Not Supported" : "Supported",
|
||||
|
||||
/* Product Type */
|
||||
(fMMTable[1] & 0x10) == 0x00 ? "OEM Product" : "ATI Product",
|
||||
|
||||
/* OEM Revision */
|
||||
(fMMTable[1] & 0xe0) >> 5,
|
||||
|
||||
/* Product ID */
|
||||
(fMMTable[1] & 0x10) == 0x00 ? "<OEM ID>" :
|
||||
(
|
||||
fMMTable[2] == 0x00 ? "ATI Prototype Board" :
|
||||
fMMTable[2] == 0x01 ? "ATI All in Wonder" :
|
||||
fMMTable[2] == 0x02 ? "ATI All in Wonder Pro, no MPEG/DVD decoder" :
|
||||
fMMTable[2] == 0x03 ? "ATI All in Wonder Pro, CD11 or similar MPEG/DVD decoder on MPP" :
|
||||
fMMTable[2] == 0x04 ? "ATI All in Wonder Plus" :
|
||||
fMMTable[2] == 0x05 ? "ATI Kitchener Board" :
|
||||
fMMTable[2] == 0x06 ? "ATI Toronto Board (analog audio)" :
|
||||
fMMTable[2] == 0x07 ? "ATI TV-Wonder" :
|
||||
fMMTable[2] == 0x08 ? "ATI Victoria Board (Rage XL plus RAGE THEATER)" : "Reserved"
|
||||
),
|
||||
|
||||
/* I2S Input/Output Configuration */
|
||||
(fMMTable[4] & 0x01) == 0x00 ? "Not Supported" : "Supported",
|
||||
(fMMTable[4] & 0x02) == 0x00 ? "Not Supported" : "Supported",
|
||||
|
||||
/* I2S Audio Chip */
|
||||
(fMMTable[4] & 0x1c) == 0x00 ? "TDA1309_32Strap" :
|
||||
(fMMTable[4] & 0x1c) == 0x04 ? "TDA1309_64Strap" :
|
||||
(fMMTable[4] & 0x1c) == 0x08 ? "ITT MSP3430" :
|
||||
(fMMTable[4] & 0x1c) == 0x0c ? "ITT MSP3415" : "Reserved",
|
||||
|
||||
/* S/PDIF Output Config */
|
||||
(fMMTable[4] & 0x20) == 0x00 ? "Not Supported" : "Supported",
|
||||
|
||||
/* Video Decoder Type */
|
||||
(fMMTable[5] & 0x0f) == 0x00 ? "No Video Decoder" :
|
||||
(fMMTable[5] & 0x0f) == 0x01 ? "Bt819" :
|
||||
(fMMTable[5] & 0x0f) == 0x02 ? "Bt829" :
|
||||
(fMMTable[5] & 0x0f) == 0x03 ? "Bt829A" :
|
||||
(fMMTable[5] & 0x0f) == 0x04 ? "Philips SA7111" :
|
||||
(fMMTable[5] & 0x0f) == 0x05 ? "Philips SA7112 or SA7112A" :
|
||||
(fMMTable[5] & 0x0f) == 0x06 ? "RAGE THEATER" : "Reserved",
|
||||
|
||||
/* Video-In Standard/Crystal */
|
||||
(fMMTable[5] & 0xf0) == 0x00 ? "NTSC and PAL Crystals installed" :
|
||||
(fMMTable[5] & 0xf0) == 0x10 ? "NTSC Crystal only" :
|
||||
(fMMTable[5] & 0xf0) == 0x20 ? "PAL Crystal only" :
|
||||
(fMMTable[5] & 0xf0) == 0x30 ? "NTSC, PAL, SECAM Ssingle crystal for Bt829 and Bt879" :
|
||||
(fMMTable[5] & 0xf0) == 0x40 ? "28.63636 MHz Crystal" :
|
||||
(fMMTable[5] & 0xf0) == 0x50 ? "29.49892713 MHz Crystal" :
|
||||
(fMMTable[5] & 0xf0) == 0x60 ? "27.0 MHz Crystal" :
|
||||
(fMMTable[5] & 0xf0) == 0x70 ? "14.31818 MHz Crystal" : "Reserved",
|
||||
|
||||
/* Video Decoder Host Config */
|
||||
(fMMTable[6] & 0x07) == 0x00 ? "I2C Device" :
|
||||
(fMMTable[6] & 0x07) == 0x01 ? "MPP Device" :
|
||||
(fMMTable[6] & 0x07) == 0x02 ? "2 bits VIP Device" :
|
||||
(fMMTable[6] & 0x07) == 0x03 ? "4 bits VIP Device" :
|
||||
(fMMTable[6] & 0x07) == 0x04 ? "8 bits VIP Device" :
|
||||
(fMMTable[6] & 0x07) == 0x07 ? "PCI Device" : "Reserved",
|
||||
|
||||
/* Hardware Teletext */
|
||||
(fMMTable[3] & 0x0c) == 0x00 ? "No Hardware Teletext" :
|
||||
(fMMTable[3] & 0x0c) == 0x04 ? "Philips SAA5281" : "Reserved",
|
||||
|
||||
/* Video Input 0 */
|
||||
(fMMTable[7] & 0x03) == 0x00 ? "Unused/Invalid" :
|
||||
(fMMTable[7] & 0x03) == 0x01 ? "Tuner Input" :
|
||||
(fMMTable[7] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
|
||||
(fMMTable[7] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
|
||||
(fMMTable[7] & 0x38) >> 3,
|
||||
|
||||
/* Video Input 1 */
|
||||
(fMMTable[8] & 0x03) == 0x00 ? "Unused/Invalid" :
|
||||
(fMMTable[8] & 0x03) == 0x01 ? "Tuner Input" :
|
||||
(fMMTable[8] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
|
||||
(fMMTable[8] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
|
||||
(fMMTable[8] & 0x38) >> 3,
|
||||
|
||||
/* Video Input 2 */
|
||||
(fMMTable[9] & 0x03) == 0x00 ? "Unused/Invalid" :
|
||||
(fMMTable[9] & 0x03) == 0x01 ? "Tuner Input" :
|
||||
(fMMTable[9] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
|
||||
(fMMTable[9] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
|
||||
(fMMTable[9] & 0x38) >> 3,
|
||||
|
||||
/* Video Input 3 */
|
||||
(fMMTable[10] & 0x03) == 0x00 ? "Unused/Invalid" :
|
||||
(fMMTable[10] & 0x03) == 0x01 ? "Tuner Input" :
|
||||
(fMMTable[10] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
|
||||
(fMMTable[10] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
|
||||
(fMMTable[10] & 0x38) >> 3,
|
||||
|
||||
/* Video Input 4 */
|
||||
(fMMTable[11] & 0x03) == 0x00 ? "Unused/Invalid" :
|
||||
(fMMTable[11] & 0x03) == 0x01 ? "Tuner Input" :
|
||||
(fMMTable[11] & 0x03) == 0x02 ? "Composite Input" : "S-Video Input",
|
||||
(fMMTable[11] & 0x04) == 0x00 ? "Front Connector" : "Rear Connector",
|
||||
(fMMTable[11] & 0x38) >> 3
|
||||
));
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,405 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: Radeon.h
|
||||
/
|
||||
/ Description: ATI Radeon Graphics Chip interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __RADEON_H__
|
||||
#define __RADEON_H__
|
||||
|
||||
#include "radeon_interface.h"
|
||||
|
||||
#define BITS(a) int((0xffffffffU>>(31-(1?a)))&(0xffffffffU<<(0?a)))
|
||||
|
||||
enum radeon_video_tuner {
|
||||
C_RADEON_NO_TUNER = 0,
|
||||
C_RADEON_FI1236_MK1_NTSC = 1,
|
||||
C_RADEON_FI1236_MK2_NTSC_JAPAN = 2,
|
||||
C_RADEON_FI1216_MK2_PAL_BG = 3,
|
||||
C_RADEON_FI1246_MK2_PAL_I = 4,
|
||||
C_RADEON_FI1216_MF_MK2_PAL_BG_SECAM_L = 5,
|
||||
C_RADEON_FI1236_MK2_NTSC = 6,
|
||||
C_RADEON_FI1256_MK2_SECAM_DK = 7,
|
||||
C_RADEON_FI1216_MK2_PAL_BG_SECAM_L = 8,
|
||||
C_RADEON_TEMIC_FN5AL_PAL_IBGDK_SECAM_DK = 9
|
||||
};
|
||||
|
||||
enum radeon_video_clock {
|
||||
C_RADEON_NO_VIDEO_CLOCK = 0,
|
||||
C_RADEON_VIDEO_CLOCK_28_63636_MHZ = 1,
|
||||
C_RADEON_VIDEO_CLOCK_29_49892_MHZ = 2,
|
||||
C_RADEON_VIDEO_CLOCK_27_00000_MHZ = 3,
|
||||
C_RADEON_VIDEO_CLOCK_14_31818_MHZ = 4
|
||||
};
|
||||
|
||||
enum radeon_video_decoder {
|
||||
C_RADEON_NO_VIDEO = 0,
|
||||
C_RADEON_BT819 = 1,
|
||||
C_RADEON_BT829 = 2,
|
||||
C_RADEON_BT829A = 3,
|
||||
C_RADEON_SA7111 = 4,
|
||||
C_RADEON_SA7112 = 5,
|
||||
C_RADEON_RAGE_THEATER = 6
|
||||
};
|
||||
|
||||
|
||||
enum radeon_register {
|
||||
C_RADEON_VIDEOMUX_CNTL = 0x0190,
|
||||
C_RADEON_VIPH_INT_SEL = BITS(0:0),
|
||||
C_RADEON_ROM_CLK_DIVIDE = BITS(20:16),
|
||||
C_RADEON_STR_ROMCLK = BITS(21:21),
|
||||
C_RADEON_VIP_INTERNAL_DEBUG_SEL = BITS(24:22),
|
||||
|
||||
// I2C
|
||||
C_RADEON_I2C_CNTL_0 = 0x0090,
|
||||
C_RADEON_I2C_DONE = BITS(0:0),
|
||||
C_RADEON_I2C_NACK = BITS(1:1),
|
||||
C_RADEON_I2C_HALT = BITS(2:2),
|
||||
C_RADEON_I2C_SOFT_RST = BITS(5:5),
|
||||
C_RADEON_I2C_DRIVE_EN = BITS(6:6),
|
||||
C_RADEON_I2C_DRIVE_SEL = BITS(7:7),
|
||||
C_RADEON_I2C_DRIVE_SEL_10_MCLKS = 0 << 7,
|
||||
C_RADEON_I2C_DRIVE_SEL_20_MCLKS = 1 << 7,
|
||||
C_RADEON_I2C_START = BITS(8:8),
|
||||
C_RADEON_I2C_STOP = BITS(9:9),
|
||||
C_RADEON_I2C_RECEIVE = BITS(10:10),
|
||||
C_RADEON_I2C_ABORT = BITS(11:11),
|
||||
C_RADEON_I2C_GO = BITS(12:12),
|
||||
C_RADEON_I2C_PRESCALE = BITS(31:16),
|
||||
|
||||
C_RADEON_I2C_CNTL_1 = 0x0094,
|
||||
C_RADEON_I2C_DATA_COUNT = BITS(3:0),
|
||||
C_RADEON_I2C_ADDR_COUNT = BITS(10:8),
|
||||
C_RADEON_I2C_SEL = BITS(16:16),
|
||||
C_RADEON_I2C_EN = BITS(17:17),
|
||||
C_RADEON_I2C_TIME_LIMIT = BITS(31:24),
|
||||
|
||||
C_RADEON_I2C_DATA = 0x0098,
|
||||
C_RADEON_I2C_DATA_MASK = BITS(7:0),
|
||||
|
||||
// Capture
|
||||
C_RADEON_CAP_INT_CNTL = 0x0908,
|
||||
C_RADEON_CAP0_BUF0_INT_EN = BITS(0:0),
|
||||
C_RADEON_CAP0_BUF0_EVEN_INT_EN = BITS(1:1),
|
||||
C_RADEON_CAP0_BUF1_INT_EN = BITS(2:2),
|
||||
C_RADEON_CAP0_BUF1_EVEN_INT_EN = BITS(3:3),
|
||||
C_RADEON_CAP0_VBI0_INT_EN = BITS(4:4),
|
||||
C_RADEON_CAP0_VBI1_INT_EN = BITS(5:5),
|
||||
C_RADEON_CAP0_ONESHOT_INT_EN = BITS(6:6),
|
||||
C_RADEON_CAP0_ANC0_INT_EN = BITS(7:7),
|
||||
C_RADEON_CAP0_ANC1_INT_EN = BITS(8:8),
|
||||
C_RADEON_CAP0_VBI2_INT_EN = BITS(9:9),
|
||||
C_RADEON_CAP0_VBI3_INT_EN = BITS(10:10),
|
||||
C_RADEON_CAP0_ANC2_INT_EN = BITS(11:11),
|
||||
C_RADEON_CAP0_ANC3_INT_EN = BITS(12:12),
|
||||
|
||||
C_RADEON_CAP_INT_STATUS = 0x090C,
|
||||
C_RADEON_CAP0_BUF0_INT = BITS(0:0),
|
||||
C_RADEON_CAP0_BUF0_INT_AK = BITS(0:0),
|
||||
C_RADEON_CAP0_BUF0_EVEN_INT = BITS(1:1),
|
||||
C_RADEON_CAP0_BUF0_EVEN_INT_AK = BITS(1:1),
|
||||
C_RADEON_CAP0_BUF1_INT = BITS(2:2),
|
||||
C_RADEON_CAP0_BUF1_INT_AK = BITS(2:2),
|
||||
C_RADEON_CAP0_BUF1_EVEN_INT = BITS(3:3),
|
||||
C_RADEON_CAP0_BUF1_EVEN_INT_AK = BITS(3:3),
|
||||
C_RADEON_CAP0_VBI0_INT = BITS(4:4),
|
||||
C_RADEON_CAP0_VBI0_INT_AK = BITS(4:4),
|
||||
C_RADEON_CAP0_VBI1_INT = BITS(5:5),
|
||||
C_RADEON_CAP0_VBI1_INT_AK = BITS(5:5),
|
||||
C_RADEON_CAP0_ONESHOT_INT = BITS(6:6),
|
||||
C_RADEON_CAP0_ONESHOT_INT_AK = BITS(6:6),
|
||||
C_RADEON_CAP0_ANC0_INT = BITS(7:7),
|
||||
C_RADEON_CAP0_ANC0_INT_AK = BITS(7:7),
|
||||
C_RADEON_CAP0_ANC1_INT = BITS(8:8),
|
||||
C_RADEON_CAP0_ANC1_INT_AK = BITS(8:8),
|
||||
C_RADEON_CAP0_VBI2_INT = BITS(9:9),
|
||||
C_RADEON_CAP0_VBI2_INT_AK = BITS(9:9),
|
||||
C_RADEON_CAP0_VBI3_INT = BITS(10:10),
|
||||
C_RADEON_CAP0_VBI3_INT_AK = BITS(10:10),
|
||||
C_RADEON_CAP0_ANC2_INT = BITS(11:11),
|
||||
C_RADEON_CAP0_ANC2_INT_AK = BITS(11:11),
|
||||
C_RADEON_CAP0_ANC3_INT = BITS(12:12),
|
||||
C_RADEON_CAP0_ANC3_INT_AK = BITS(12:12),
|
||||
|
||||
C_RADEON_FCP_CNTL = 0x0910,
|
||||
C_RADEON_FCP0_SRC_SEL = BITS(2:0),
|
||||
C_RADEON_FCP0_SRC_PCICLK = 0 << 0,
|
||||
C_RADEON_FCP0_SRC_PCLK = 1 << 0,
|
||||
C_RADEON_FCP0_SRC_PCLKb = 2 << 0,
|
||||
C_RADEON_FCP0_SRC_HREF = 3 << 0,
|
||||
C_RADEON_FCP0_SRC_GND = 4 << 0,
|
||||
C_RADEON_FCP0_SRC_HREFb = 5 << 0,
|
||||
|
||||
C_RADEON_CAP0_BUF0_OFFSET = 0x0920,
|
||||
C_RADEON_CAP0_BUF1_OFFSET = 0x0924,
|
||||
C_RADEON_CAP0_BUF0_EVEN_OFFSET = 0x0928,
|
||||
C_RADEON_CAP0_BUF1_EVEN_OFFSET = 0x092C,
|
||||
|
||||
C_RADEON_CAP0_BUF_PITCH = 0x0930,
|
||||
C_RADEON_CAP0_BUF_PITCH_MASK = BITS(11:0),
|
||||
|
||||
C_RADEON_CAP0_V_WINDOW = 0x0934,
|
||||
C_RADEON_CAP0_V_START = BITS(11:0),
|
||||
C_RADEON_CAP0_V_END = BITS(27:16),
|
||||
|
||||
C_RADEON_CAP0_H_WINDOW = 0x0938,
|
||||
C_RADEON_CAP0_H_START = BITS(11:0),
|
||||
C_RADEON_CAP0_H_WIDTH = BITS(27:16),
|
||||
|
||||
C_RADEON_CAP0_VBI0_OFFSET = 0x093C,
|
||||
C_RADEON_CAP0_VBI1_OFFSET = 0x0940,
|
||||
|
||||
C_RADEON_CAP0_VBI_V_WINDOW = 0x0944,
|
||||
C_RADEON_CAP0_VBI_V_START = BITS(11:0),
|
||||
C_RADEON_CAP0_VBI_V_END = BITS(27:16),
|
||||
|
||||
C_RADEON_CAP0_VBI_H_WINDOW = 0x0948,
|
||||
C_RADEON_CAP0_VBI_H_START = BITS(11:0),
|
||||
C_RADEON_CAP0_VBI_H_WIDTH = BITS(27:16),
|
||||
|
||||
C_RADEON_CAP0_PORT_MODE_CNTL = 0x094C,
|
||||
C_RADEON_CAP0_PORT_WIDTH = BITS(1:1),
|
||||
C_RADEON_CAP0_PORT_WIDTH_8_BITS = 0 << 1,
|
||||
C_RADEON_CAP0_PORT_WIDTH_16_BITS = 1 << 1,
|
||||
C_RADEON_CAP0_PORT_BYTE_USED = BITS(2:2),
|
||||
C_RADEON_CAP0_PORT_LOWER_BYTE_USED = 0 << 2,
|
||||
C_RADEON_CAP0_PORT_UPPER_BYTE_USED = 1 << 2,
|
||||
|
||||
C_RADEON_CAP0_TRIG_CNTL = 0x0950,
|
||||
C_RADEON_CAP0_TRIGGER_R = BITS(1:0),
|
||||
C_RADEON_CAP0_TRIGGER_R_COMPLETE = 0 << 0,
|
||||
C_RADEON_CAP0_TRIGGER_R_PENDING = 1 << 0,
|
||||
C_RADEON_CAP0_TRIGGER_R_IN_PROGRESS = 2 << 0,
|
||||
C_RADEON_CAP0_TRIGGER_W = BITS(0:0),
|
||||
C_RADEON_CAP0_TRIGGER_W_NO_ACTION = 0 << 0,
|
||||
C_RADEON_CAP0_TRIGGER_W_CAPTURE = 1 << 0,
|
||||
C_RADEON_CAP0_EN = BITS(4:4),
|
||||
C_RADEON_CAP0_VSYNC_CNT_R = BITS(15:8),
|
||||
C_RADEON_CAP0_VSYNC_CLR = BITS(16:16),
|
||||
|
||||
C_RADEON_CAP0_DEBUG = 0x0954,
|
||||
C_RADEON_CAP0_H_STATUS = BITS(11:0),
|
||||
C_RADEON_CAP0_V_STATUS = BITS(27:16),
|
||||
C_RADEON_CAP0_V_SYNC = BITS(28:28),
|
||||
|
||||
C_RADEON_CAP0_CONFIG = 0x0958,
|
||||
C_RADEON_CAP0_INPUT_MODE = BITS(0:0),
|
||||
C_RADEON_CAP0_INPUT_MODE_ONESHOT = 0 << 0,
|
||||
C_RADEON_CAP0_INPUT_MODE_CONTINUOUS = 1 << 0,
|
||||
C_RADEON_CAP0_START_FIELD = BITS(1:1),
|
||||
C_RADEON_CAP0_START_ODD_FIELD = 0 << 1,
|
||||
C_RADEON_CAP0_START_EVEN_FIELD = 1 << 1,
|
||||
C_RADEON_CAP0_START_BUF_R = BITS(2:2),
|
||||
C_RADEON_CAP0_START_BUF_W = BITS(3:3),
|
||||
C_RADEON_CAP0_BUF_TYPE = BITS(5:4),
|
||||
C_RADEON_CAP0_BUF_TYPE_FIELD = 0 << 4,
|
||||
C_RADEON_CAP0_BUF_TYPE_ALTERNATING = 1 << 4,
|
||||
C_RADEON_CAP0_BUF_TYPE_FRAME = 2 << 4,
|
||||
C_RADEON_CAP0_ONESHOT_MODE = BITS(6:6),
|
||||
C_RADEON_CAP0_ONESHOT_MODE_FIELD = 0 << 6,
|
||||
C_RADEON_CAP0_ONESHOT_MODE_FRAME = 1 << 6,
|
||||
C_RADEON_CAP0_BUF_MODE = BITS(8:7),
|
||||
C_RADEON_CAP0_BUF_MODE_SINGLE = 0 << 7,
|
||||
C_RADEON_CAP0_BUF_MODE_DOUBLE = 1 << 7,
|
||||
C_RADEON_CAP0_BUF_MODE_TRIPLE = 2 << 7,
|
||||
C_RADEON_CAP0_MIRROR_EN = BITS(9:9),
|
||||
C_RADEON_CAP0_ONESHOT_MIRROR_EN = BITS(10:10),
|
||||
C_RADEON_CAP0_VIDEO_SIGNED_UV = BITS(11:11),
|
||||
C_RADEON_CAP0_ANC_DECODE_EN = BITS(12:12),
|
||||
C_RADEON_CAP0_VBI_EN = BITS(13:13),
|
||||
C_RADEON_CAP0_SOFT_PULL_DOWN_EN = BITS(14:14),
|
||||
C_RADEON_CAP0_VIP_EXTEND_FLAG_EN = BITS(15:15),
|
||||
C_RADEON_CAP0_FAKE_FIELD_EN = BITS(16:16),
|
||||
C_RADEON_CAP0_FIELD_START_LINE_DIFF = BITS(18:17),
|
||||
C_RADEON_CAP0_HORZ_DOWN = BITS(20:19),
|
||||
C_RADEON_CAP0_HORZ_DOWN_1X = 0 << 19,
|
||||
C_RADEON_CAP0_HORZ_DOWN_2X = 1 << 19,
|
||||
C_RADEON_CAP0_HORZ_DOWN_3X = 2 << 19,
|
||||
C_RADEON_CAP0_VERT_DOWN = BITS(22:21),
|
||||
C_RADEON_CAP0_VERT_DOWN_1X = 0 << 21,
|
||||
C_RADEON_CAP0_VERT_DOWN_2X = 1 << 21,
|
||||
C_RADEON_CAP0_VERT_DOWN_3X = 2 << 21,
|
||||
C_RADEON_CAP0_STREAM_FORMAT = BITS(25:23),
|
||||
C_RADEON_CAP0_STREAM_BROOKTREE = 0 << 23,
|
||||
C_RADEON_CAP0_STREAM_CCIR656 = 1 << 23,
|
||||
C_RADEON_CAP0_STREAM_ZV = 2 << 23,
|
||||
C_RADEON_CAP0_STREAM_VIP = 3 << 23,
|
||||
C_RADEON_CAP0_STREAM_TRANSPORT = 4 << 23,
|
||||
C_RADEON_CAP0_HDWNS_DEC = BITS(26:26),
|
||||
C_RADEON_CAP0_DOWNSCALER = 0 << 26,
|
||||
C_RADEON_CAP0_DECIMATOR = 1 << 26,
|
||||
C_RADEON_CAP0_VIDEO_IN_FORMAT = BITS(29:29),
|
||||
C_RADEON_CAP0_VIDEO_IN_YVYU422 = 0 << 29,
|
||||
C_RADEON_CAP0_VIDEO_IN_VYUY422 = 1 << 29,
|
||||
C_RADEON_CAP0_VBI_HORZ_DOWN = BITS(31:30),
|
||||
C_RADEON_CAP0_VBI_HORZ_DOWN_1X = 0 << 30,
|
||||
C_RADEON_CAP0_VBI_HORZ_DOWN_2X = 1 << 30,
|
||||
C_RADEON_CAP0_VBI_HORZ_DOWN_4X = 2 << 30,
|
||||
|
||||
C_RADEON_CAP0_ANC0_OFFSET = 0x095C,
|
||||
C_RADEON_CAP0_ANC1_OFFSET = 0x0960,
|
||||
|
||||
C_RADEON_CAP0_ANC_H_WINDOW = 0x0964,
|
||||
C_RADEON_CAP0_ANC_WIDTH = BITS(11:0),
|
||||
|
||||
C_RADEON_CAP0_VIDEO_SYNC_TEST = 0x0968,
|
||||
C_RADEON_CAP0_TEST_VID_SOF = BITS(0:0),
|
||||
C_RADEON_CAP0_TEST_VID_EOF = BITS(1:1),
|
||||
C_RADEON_CAP0_TEST_VID_EOL = BITS(2:2),
|
||||
C_RADEON_CAP0_TEST_VID_FIELD = BITS(3:3),
|
||||
C_RADEON_CAP0_TEST_SYNC_EN = BITS(5:5),
|
||||
|
||||
C_RADEON_CAP0_ONESHOT_BUF_OFFSET = 0x096C,
|
||||
|
||||
C_RADEON_CAP0_BUF_STATUS = 0x0970,
|
||||
C_RADEON_CAP0_PRE_VID_BUF = BITS(1:0),
|
||||
C_RADEON_CAP0_CUR_VID_BUF = BITS(3:2),
|
||||
C_RADEON_CAP0_PRE_FIELD = BITS(4:4),
|
||||
C_RADEON_CAP0_CUR_FIELD = BITS(5:5),
|
||||
C_RADEON_CAP0_PRE_VBI_BUF = BITS(7:6),
|
||||
C_RADEON_CAP0_CUR_VBI_BUF = BITS(9:8),
|
||||
C_RADEON_CAP0_VBI_BUF_STATUS = BITS(10:10),
|
||||
C_RADEON_CAP0_PRE_ANC_BUF = BITS(12:11),
|
||||
C_RADEON_CAP0_CUR_ANC_BUF = BITS(14:13),
|
||||
C_RADEON_CAP0_ANC_BUF_STATUS = BITS(16:16),
|
||||
C_RADEON_CAP0_ANC_PRE_BUF_CNT = BITS(27:16),
|
||||
C_RADEON_CAP0_VIP_INC = BITS(28:28),
|
||||
C_RADEON_CAP0_VIP_PRE_REPEAT_FIELD = BITS(29:29),
|
||||
C_RADEON_CAP0_CAP_BUF_STATUS = BITS(30:30),
|
||||
|
||||
C_RADEON_CAP0_VBI2_OFFSET = 0x0980,
|
||||
C_RADEON_CAP0_VBI3_OFFSET = 0x0984,
|
||||
C_RADEON_CAP0_ANC2_OFFSET = 0x0988,
|
||||
C_RADEON_CAP0_ANC3_OFFSET = 0x098C,
|
||||
|
||||
C_RADEON_VBI_BUFFER_CONTROL = 0x0900,
|
||||
C_RADEON_CAP0_BUFFER_WATER_MARK = BITS(4:0),
|
||||
C_RADEON_FULL_BUFFER_EN = BITS(16:16),
|
||||
C_RADEON_CAP0_ANC_VBI_QUAD_BUF = BITS(17:17),
|
||||
C_RADEON_VID_BUFFER_RESET = BITS(20:20),
|
||||
C_RADEON_CAP_SWAP = BITS(22:21),
|
||||
C_RADEON_CAP0_BUFFER_EMPTY_R = BITS(24:24),
|
||||
|
||||
// Test and Debug control
|
||||
C_RADEON_TEST_DEBUG_CNTL = 0x0120,
|
||||
C_RADEON_TEST_DEBUG_OUT_EN = 0x00000001
|
||||
};
|
||||
|
||||
|
||||
class CRadeonRect {
|
||||
public:
|
||||
CRadeonRect();
|
||||
|
||||
CRadeonRect(int left, int top, int right, int bottom);
|
||||
|
||||
int Left() const;
|
||||
|
||||
int Top() const;
|
||||
|
||||
int Right() const;
|
||||
|
||||
int Bottom() const;
|
||||
|
||||
int Width() const;
|
||||
|
||||
int Height() const;
|
||||
|
||||
void SetLeft(int value);
|
||||
|
||||
void SetTop(int value);
|
||||
|
||||
void SetRight(int value);
|
||||
|
||||
void SetBottom(int value);
|
||||
|
||||
void SetTo(int left, int top, int right, int bottom);
|
||||
|
||||
void MoveTo(int left, int top);
|
||||
|
||||
void ResizeTo(int width, int height);
|
||||
|
||||
private:
|
||||
int fLeft;
|
||||
int fTop;
|
||||
int fRight;
|
||||
int fBottom;
|
||||
};
|
||||
|
||||
class CRadeon {
|
||||
public:
|
||||
CRadeon( const char *dev_name );
|
||||
|
||||
~CRadeon();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
uint32 VirtualMemoryBase() const;
|
||||
|
||||
public:
|
||||
int Register(radeon_register index) const;
|
||||
|
||||
void SetRegister(radeon_register index, int value);
|
||||
|
||||
int Register(radeon_register index, int mask) const;
|
||||
|
||||
void SetRegister(radeon_register index, int mask, int value);
|
||||
|
||||
int VIPRegister(int device, int address);
|
||||
|
||||
void SetVIPRegister(int device, int address, int value);
|
||||
|
||||
int FindVIPDevice( uint32 device_id );
|
||||
|
||||
public:
|
||||
void GetPLLParameters(int & refFreq, int & refDiv, int & minFreq, int & maxFreq, int & xclock);
|
||||
|
||||
void GetMMParameters(radeon_video_tuner & tuner,
|
||||
radeon_video_decoder & video,
|
||||
radeon_video_clock & clock,
|
||||
int & tunerPort,
|
||||
int & compositePort,
|
||||
int & svideoPort);
|
||||
|
||||
public:
|
||||
status_t AllocateGraphicsMemory(
|
||||
memory_type_e memory_type, int32 size,
|
||||
int32 *offset, int32 *handle );
|
||||
|
||||
void FreeGraphicsMemory(
|
||||
memory_type_e memory_type, int32 handle );
|
||||
|
||||
status_t DMACopy(
|
||||
uint32 src, void *target, size_t size, bool lock_mem, bool contiguous );
|
||||
|
||||
public:
|
||||
status_t GetDeviceInformation(radeon_get_private_data & info);
|
||||
|
||||
status_t WaitInterrupt(int * mask, int * sequence, bigtime_t * time, bigtime_t timeout);
|
||||
|
||||
status_t CloneArea(const char * name, area_id src_area,
|
||||
area_id *cloned_area, void ** map);
|
||||
|
||||
private:
|
||||
int fHandle;
|
||||
unsigned int * fRegister;
|
||||
unsigned char * fROM;
|
||||
virtual_card *fVirtualCard;
|
||||
shared_info *fSharedInfo;
|
||||
|
||||
area_id fRegisterArea;
|
||||
area_id fROMArea;
|
||||
area_id fVirtualCardArea;
|
||||
area_id fSharedInfoArea;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T Clamp(T value, T min, T max)
|
||||
{
|
||||
return (value < min ? min : value > max ? max : value);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,432 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: RadeonAddOn.cpp
|
||||
/
|
||||
/ Description: ATI Radeon Video Capture Media AddOn for BeOS.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <support/Autolock.h>
|
||||
#include <media/MediaFormats.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Debug.h>
|
||||
#include <File.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <storage/FindDirectory.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "RadeonAddOn.h"
|
||||
#include "RadeonProducer.h"
|
||||
|
||||
#define DPRINT(args) { PRINT(("\x1b[0;30;35m")); PRINT(args); PRINT(("\x1b[0;30;47m")); }
|
||||
|
||||
CRadeonPlug::CRadeonPlug( CRadeonAddOn *aaddon, const BPath &adev_path, int aid )
|
||||
: addon( aaddon ), dev_path( adev_path ), id( aid ), node( NULL )
|
||||
{
|
||||
fFlavorInfo.name = const_cast<char *>("Radeon In");
|
||||
fFlavorInfo.info = const_cast<char *>("Radeon Video In Media Node");
|
||||
fFlavorInfo.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT;
|
||||
fFlavorInfo.flavor_flags = 0;
|
||||
fFlavorInfo.internal_id = aid;
|
||||
fFlavorInfo.possible_count = 1;
|
||||
|
||||
fFlavorInfo.in_format_count = 0;
|
||||
fFlavorInfo.in_format_flags = 0;
|
||||
fFlavorInfo.in_formats = NULL;
|
||||
|
||||
fFlavorInfo.out_format_count = 4;
|
||||
//fFlavorInfo.out_format_count = 1;
|
||||
fFlavorInfo.out_format_flags = 0;
|
||||
|
||||
fMediaFormat[0].type = B_MEDIA_RAW_VIDEO;
|
||||
fMediaFormat[0].u.raw_video = media_raw_video_format::wildcard;
|
||||
fMediaFormat[0].u.raw_video.interlace = 1;
|
||||
fMediaFormat[0].u.raw_video.display.format = B_RGB32;
|
||||
|
||||
fMediaFormat[1].type = B_MEDIA_RAW_VIDEO;
|
||||
fMediaFormat[1].u.raw_video = media_raw_video_format::wildcard;
|
||||
fMediaFormat[1].u.raw_video.interlace = 1;
|
||||
fMediaFormat[1].u.raw_video.display.format = B_RGB16;
|
||||
|
||||
fMediaFormat[2].type = B_MEDIA_RAW_VIDEO;
|
||||
fMediaFormat[2].u.raw_video = media_raw_video_format::wildcard;
|
||||
fMediaFormat[2].u.raw_video.interlace = 1;
|
||||
fMediaFormat[2].u.raw_video.display.format = B_RGB15;
|
||||
|
||||
fMediaFormat[3].type = B_MEDIA_RAW_VIDEO;
|
||||
fMediaFormat[3].u.raw_video = media_raw_video_format::wildcard;
|
||||
fMediaFormat[3].u.raw_video.interlace = 1;
|
||||
fMediaFormat[3].u.raw_video.display.format = B_YCbCr422;
|
||||
|
||||
/*fMediaFormat[0].type = B_MEDIA_RAW_VIDEO;
|
||||
fMediaFormat[0].u.raw_video = media_raw_video_format::wildcard;
|
||||
fMediaFormat[0].u.raw_video.interlace = 1;
|
||||
fMediaFormat[0].u.raw_video.display.format = B_YCbCr422;*/
|
||||
|
||||
fFlavorInfo.out_formats = fMediaFormat;
|
||||
|
||||
readSettings();
|
||||
}
|
||||
|
||||
BPath
|
||||
CRadeonPlug::getSettingsPath()
|
||||
{
|
||||
BPath path;
|
||||
|
||||
if( find_directory( B_USER_CONFIG_DIRECTORY, &path ) != B_OK )
|
||||
return BPath();
|
||||
|
||||
path.Append( "settings/Media/RadeonIn" );
|
||||
|
||||
create_directory( path.Path(), 755 );
|
||||
|
||||
BString id_string;
|
||||
|
||||
id_string << "settings" << id;
|
||||
|
||||
path.Append( id_string.String() );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void
|
||||
CRadeonPlug::writeSettings( BMessage *new_settings )
|
||||
{
|
||||
BMessage cur_settings;
|
||||
|
||||
// if new_settings are provided, use them; else, ask node for settings
|
||||
// (needed during shutdown where node cannot reply anymore)
|
||||
if( new_settings != NULL ) {
|
||||
cur_settings = *new_settings;
|
||||
|
||||
} else {
|
||||
if( node == NULL )
|
||||
return;
|
||||
|
||||
if( addon->GetConfigurationFor( node, &cur_settings ) != B_OK )
|
||||
return;
|
||||
}
|
||||
|
||||
BMallocIO old_settings_flat, new_settings_flat;
|
||||
|
||||
settings.Flatten( &old_settings_flat );
|
||||
cur_settings.Flatten( &new_settings_flat );
|
||||
|
||||
if( old_settings_flat.BufferLength() == new_settings_flat.BufferLength() &&
|
||||
memcmp( old_settings_flat.Buffer(), new_settings_flat.Buffer(), old_settings_flat.BufferLength() ) == 0 )
|
||||
return;
|
||||
|
||||
settings = cur_settings;
|
||||
|
||||
BPath settings_path = getSettingsPath();
|
||||
|
||||
BFile file( settings_path.Path(), B_WRITE_ONLY | B_CREATE_FILE );
|
||||
|
||||
settings.Flatten( &file );
|
||||
}
|
||||
|
||||
void
|
||||
CRadeonPlug::readSettings()
|
||||
{
|
||||
BPath settings_path = getSettingsPath();
|
||||
|
||||
BFile file( settings_path.Path(), B_READ_ONLY );
|
||||
|
||||
settings.Unflatten( &file );
|
||||
}
|
||||
|
||||
|
||||
CRadeonAddOn::CRadeonAddOn(image_id imid)
|
||||
: BMediaAddOn(imid),
|
||||
settings_thread( -1 ), settings_thread_sem( -1 )
|
||||
{
|
||||
DPRINT(("CRadeonAddOn::CRadeonAddOn()\n"));
|
||||
|
||||
fInitStatus = B_NO_INIT;
|
||||
|
||||
if( RecursiveScan( "/dev/video/radeon" ) != B_OK )
|
||||
return;
|
||||
|
||||
if( (settings_thread_sem = create_sem( 0, "Radeon In settings" )) < 0 )
|
||||
return;
|
||||
|
||||
if( INIT_BEN( plug_lock, "Radeon device list" ) < 0 )
|
||||
return;
|
||||
|
||||
if( (settings_thread = spawn_thread(
|
||||
settings_writer, "Radeon In settings", B_LOW_PRIORITY, this )) < 0 )
|
||||
return;
|
||||
|
||||
resume_thread( settings_thread );
|
||||
|
||||
fInitStatus = B_OK;
|
||||
}
|
||||
|
||||
CRadeonAddOn::~CRadeonAddOn()
|
||||
{
|
||||
status_t dummy;
|
||||
|
||||
DPRINT(("CRadeonAddOn::~CRadeonAddOn()\n"));
|
||||
|
||||
release_sem( settings_thread_sem );
|
||||
wait_for_thread( settings_thread, &dummy );
|
||||
|
||||
delete_sem( settings_thread_sem );
|
||||
|
||||
for( int32 i = 0; i < fDevices.CountItems(); ++i ) {
|
||||
CRadeonPlug *plug = (CRadeonPlug *)fDevices.ItemAt(i);
|
||||
|
||||
delete plug;
|
||||
}
|
||||
|
||||
DELETE_BEN( plug_lock );
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CRadeonAddOn::InitCheck(const char **out_failure_text)
|
||||
{
|
||||
DPRINT(("CRadeonAddOn::InitCheck()\n"));
|
||||
|
||||
if (fInitStatus < B_OK) {
|
||||
*out_failure_text = "Unknown error";
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
int32
|
||||
CRadeonAddOn::settings_writer( void *param )
|
||||
{
|
||||
((CRadeonAddOn *)param)->settingsWriter();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void
|
||||
CRadeonAddOn::writeSettings()
|
||||
{
|
||||
ACQUIRE_BEN( plug_lock );
|
||||
|
||||
for( int32 i = 0; i < fDevices.CountItems(); ++i ) {
|
||||
CRadeonPlug *plug = (CRadeonPlug *)fDevices.ItemAt(i);
|
||||
|
||||
plug->writeSettings( NULL );
|
||||
}
|
||||
|
||||
RELEASE_BEN( plug_lock );
|
||||
}
|
||||
|
||||
void
|
||||
CRadeonAddOn::settingsWriter()
|
||||
{
|
||||
while( acquire_sem_etc( settings_thread_sem, 1, B_RELATIVE_TIMEOUT, 10000000 ) == B_TIMED_OUT ) {
|
||||
writeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CRadeonAddOn::UnregisterNode( BMediaNode *node, BMessage *settings )
|
||||
{
|
||||
ACQUIRE_BEN( plug_lock );
|
||||
|
||||
for( int32 i = 0; i < fDevices.CountItems(); ++i ) {
|
||||
CRadeonPlug *plug = (CRadeonPlug *)fDevices.ItemAt(i);
|
||||
|
||||
if( plug->getNode() == node ) {
|
||||
// write last settings, so they don't get lost
|
||||
plug->writeSettings( settings );
|
||||
plug->setNode( NULL );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RELEASE_BEN( plug_lock );
|
||||
}
|
||||
|
||||
int32
|
||||
CRadeonAddOn::CountFlavors()
|
||||
{
|
||||
DPRINT(("CRadeonAddOn::CountFlavors()\n"));
|
||||
|
||||
if (fInitStatus < B_OK)
|
||||
return fInitStatus;
|
||||
|
||||
return fDevices.CountItems();
|
||||
}
|
||||
|
||||
/*
|
||||
* The pointer to the flavor received only needs to be valid between
|
||||
* successive calls to BCRadeonAddOn::GetFlavorAt().
|
||||
*/
|
||||
status_t
|
||||
CRadeonAddOn::GetFlavorAt(int32 n, const flavor_info **out_info)
|
||||
{
|
||||
DPRINT(("CRadeonAddOn::GetFlavorAt()\n"));
|
||||
|
||||
if (fInitStatus < B_OK)
|
||||
return fInitStatus;
|
||||
|
||||
if (n < 0 || n >= fDevices.CountItems() )
|
||||
return B_BAD_INDEX;
|
||||
|
||||
/* Return the flavor defined in the constructor */
|
||||
*out_info = ((CRadeonPlug *)fDevices.ItemAt(n))->getFlavorInfo();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
BMediaNode *
|
||||
CRadeonAddOn::InstantiateNodeFor(
|
||||
const flavor_info *info, BMessage *config, status_t *out_error)
|
||||
{
|
||||
DPRINT(("CRadeonAddOn::InstantiateNodeFor()\n"));
|
||||
|
||||
CRadeonProducer *node;
|
||||
|
||||
if (fInitStatus < B_OK)
|
||||
return NULL;
|
||||
|
||||
if (info->internal_id < 0 || info->internal_id >= fDevices.CountItems())
|
||||
return NULL;
|
||||
|
||||
CRadeonPlug *plug = (CRadeonPlug *)fDevices.ItemAt( info->internal_id );
|
||||
|
||||
ACQUIRE_BEN( plug_lock );
|
||||
|
||||
if( plug->getNode() != NULL ) {
|
||||
*out_error = B_BUSY;
|
||||
node = NULL;
|
||||
|
||||
} else {
|
||||
BMessage single_settings;
|
||||
|
||||
// under R5, configuration is always an empty message, so we need to
|
||||
// get our own configuration
|
||||
if( config == NULL || 1 )
|
||||
config = plug->getSettings();
|
||||
|
||||
node = new CRadeonProducer( this, plug->getName(),
|
||||
plug->getDeviceName(), info->internal_id, config );
|
||||
|
||||
if (node && (node->InitCheck() < B_OK)) {
|
||||
*out_error = node->InitCheck();
|
||||
delete node;
|
||||
node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
plug->setNode( node );
|
||||
|
||||
RELEASE_BEN( plug_lock );
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
status_t CRadeonAddOn::GetConfigurationFor(
|
||||
BMediaNode *your_node,
|
||||
BMessage *into_message )
|
||||
{
|
||||
port_id reply_port;
|
||||
CRadeonProducer::configuration_msg msg;
|
||||
status_t res;
|
||||
|
||||
reply_port = create_port( 1, "GetConfiguration Reply" );
|
||||
if( reply_port < 0 )
|
||||
return reply_port;
|
||||
|
||||
msg.reply_port = reply_port;
|
||||
|
||||
res = write_port_etc( your_node->ControlPort(), CRadeonProducer::C_GET_CONFIGURATION,
|
||||
&msg, sizeof( msg ), B_TIMEOUT, 10000000 );
|
||||
if( res == B_OK ) {
|
||||
ssize_t reply_size;
|
||||
CRadeonProducer::configuration_msg_reply *reply;
|
||||
int32 code;
|
||||
|
||||
reply_size = port_buffer_size_etc( reply_port, B_TIMEOUT, 10000000 );
|
||||
if( reply_size < 0 )
|
||||
res = reply_size;
|
||||
else {
|
||||
reply = (CRadeonProducer::configuration_msg_reply *)malloc( reply_size );
|
||||
|
||||
res = read_port( reply_port, &code, reply, reply_size );
|
||||
if( res == reply_size ) {
|
||||
if( code != CRadeonProducer::C_GET_CONFIGURATION_REPLY )
|
||||
res = B_ERROR;
|
||||
else {
|
||||
res = reply->res;
|
||||
|
||||
if( res == B_OK )
|
||||
res = into_message->Unflatten( &reply->config );
|
||||
}
|
||||
}
|
||||
|
||||
free( reply );
|
||||
}
|
||||
}
|
||||
|
||||
delete_port( reply_port );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
status_t
|
||||
CRadeonAddOn::RecursiveScan(const char* rootPath, BEntry *rootEntry = NULL)
|
||||
{
|
||||
BDirectory root;
|
||||
|
||||
if( rootEntry != NULL )
|
||||
root.SetTo( rootEntry );
|
||||
else if( rootPath != NULL ) {
|
||||
root.SetTo( rootPath );
|
||||
} else {
|
||||
PRINT(("Error in MultiAudioAddOn::RecursiveScan null params\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
BEntry entry;
|
||||
int cur_id = 0;
|
||||
|
||||
while( root.GetNextEntry( &entry ) > B_ERROR ) {
|
||||
if(entry.IsDirectory()) {
|
||||
RecursiveScan( rootPath, &entry );
|
||||
|
||||
} else {
|
||||
BPath path;
|
||||
|
||||
entry.GetPath(&path);
|
||||
|
||||
CRadeon device( path.Path() );
|
||||
|
||||
if( device.InitCheck() != B_OK)
|
||||
continue;
|
||||
|
||||
CVIPPort vip_port( device );
|
||||
|
||||
// if there is a Rage Theatre, then there should be Video-In
|
||||
if( vip_port.InitCheck() == B_OK &&
|
||||
vip_port.FindVIPDevice(
|
||||
(C_THEATER_VIP_VENDOR_ID << 0) |
|
||||
(C_THEATER_VIP_DEVICE_ID << 16)) >= 0 )
|
||||
{
|
||||
fDevices.AddItem( new CRadeonPlug( this, path, cur_id++ ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BMediaAddOn *
|
||||
make_media_addon(image_id imid)
|
||||
{
|
||||
return new CRadeonAddOn(imid);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: RadeonAddOn.h
|
||||
/
|
||||
/ Description: ATI Radeon Video Capture Media AddOn for BeOS.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __RADEON_ADDON_H__
|
||||
#define __RADEON_ADDON_H__
|
||||
|
||||
#include <media/MediaAddOn.h>
|
||||
#include <Path.h>
|
||||
#include "benaphore.h"
|
||||
|
||||
#define TOUCH(x) ((void)(x))
|
||||
|
||||
extern "C" _EXPORT BMediaAddOn *make_media_addon(image_id you);
|
||||
|
||||
class CRadeonAddOn;
|
||||
|
||||
// descriptor of a possible Radeon node
|
||||
class CRadeonPlug {
|
||||
public:
|
||||
CRadeonPlug( CRadeonAddOn *addon, const BPath &dev_path, int id );
|
||||
~CRadeonPlug() {}
|
||||
|
||||
const char *getName() { return fFlavorInfo.name; }
|
||||
const char *getDeviceName() { return dev_path.Path(); }
|
||||
const char *getDeviceShortName() { return dev_path.Leaf(); }
|
||||
flavor_info *getFlavorInfo() { return &fFlavorInfo; }
|
||||
BMediaNode *getNode() { return node; }
|
||||
void setNode( BMediaNode *anode ) { node = anode; }
|
||||
BMessage *getSettings() { return &settings; }
|
||||
|
||||
void writeSettings( BMessage *new_settings );
|
||||
|
||||
private:
|
||||
CRadeonAddOn *addon; // (global) addon (only needed for GetConfiguration())
|
||||
BPath dev_path; // path of device driver
|
||||
int id; // id of plug
|
||||
flavor_info fFlavorInfo; // flavor of plug (contains unique id)
|
||||
BMediaNode *node; // active node (or NULL)
|
||||
BMessage settings; // settings for this node
|
||||
media_format fMediaFormat[4];
|
||||
|
||||
void readSettings();
|
||||
BPath getSettingsPath();
|
||||
};
|
||||
|
||||
class CRadeonAddOn : public BMediaAddOn
|
||||
{
|
||||
public:
|
||||
CRadeonAddOn(image_id imid);
|
||||
virtual ~CRadeonAddOn();
|
||||
|
||||
virtual status_t InitCheck(const char **out_failure_text);
|
||||
|
||||
virtual int32 CountFlavors();
|
||||
virtual status_t GetFlavorAt(int32 n, const flavor_info ** out_info);
|
||||
virtual BMediaNode *InstantiateNodeFor(
|
||||
const flavor_info * info,
|
||||
BMessage * config,
|
||||
status_t * out_error);
|
||||
|
||||
virtual status_t SaveConfigInfo(BMediaNode *node, BMessage *message)
|
||||
{ TOUCH(node); TOUCH(message); return B_OK; }
|
||||
|
||||
virtual bool WantsAutoStart() { return false; }
|
||||
virtual status_t AutoStart(int in_count, BMediaNode **out_node,
|
||||
int32 *out_internal_id, bool *out_has_more)
|
||||
{ TOUCH(in_count); TOUCH(out_node);
|
||||
TOUCH(out_internal_id); TOUCH(out_has_more);
|
||||
return B_ERROR; }
|
||||
|
||||
virtual status_t GetConfigurationFor(
|
||||
BMediaNode *your_node,
|
||||
BMessage *into_message );
|
||||
|
||||
// private methods
|
||||
void UnregisterNode( BMediaNode *node, BMessage *settings );
|
||||
|
||||
private:
|
||||
status_t fInitStatus;
|
||||
BList fDevices; // list of BPath of found devices
|
||||
thread_id settings_thread;
|
||||
sem_id settings_thread_sem;
|
||||
benaphore plug_lock;
|
||||
BMessage settings;
|
||||
|
||||
status_t RecursiveScan( const char* rootPath, BEntry *rootEntry = NULL );
|
||||
static int32 settings_writer( void *param );
|
||||
void settingsWriter();
|
||||
void writeSettings();
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,241 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: RadeonProducer.h
|
||||
/
|
||||
/ Description: ATI Radeon Video Producer media node.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __RADEON_PRODUCER_H__
|
||||
#define __RADEON_PRODUCER_H__
|
||||
|
||||
#include <kernel/OS.h>
|
||||
#include <media/BufferProducer.h>
|
||||
#include <media/Controllable.h>
|
||||
#include <media/MediaDefs.h>
|
||||
#include <media/MediaEventLooper.h>
|
||||
#include <media/MediaNode.h>
|
||||
#include <support/Locker.h>
|
||||
#include "VideoIn.h"
|
||||
|
||||
class CRadeonAddOn;
|
||||
|
||||
class CRadeonProducer :
|
||||
public virtual BMediaEventLooper,
|
||||
public virtual BBufferProducer,
|
||||
public virtual BControllable
|
||||
{
|
||||
public:
|
||||
CRadeonProducer(
|
||||
CRadeonAddOn *addon, const char *name, const char *device_name,
|
||||
int32 internal_id, BMessage *config );
|
||||
virtual ~CRadeonProducer();
|
||||
|
||||
void setupWeb();
|
||||
virtual status_t InitCheck() const { return fInitStatus; }
|
||||
|
||||
/* BMediaNode */
|
||||
public:
|
||||
virtual port_id ControlPort() const;
|
||||
virtual BMediaAddOn *AddOn(int32 * internal_id) const;
|
||||
virtual status_t HandleMessage(int32 message, const void *data,
|
||||
size_t size);
|
||||
protected:
|
||||
virtual void Preroll();
|
||||
virtual void SetTimeSource(BTimeSource * time_source);
|
||||
virtual status_t RequestCompleted(const media_request_info & info);
|
||||
|
||||
/* BMediaEventLooper */
|
||||
protected:
|
||||
virtual void NodeRegistered();
|
||||
virtual void Start(bigtime_t performance_time);
|
||||
virtual void Stop(bigtime_t performance_time, bool immediate);
|
||||
virtual void Seek(bigtime_t media_time, bigtime_t performance_time);
|
||||
virtual void TimeWarp(bigtime_t at_real_time,
|
||||
bigtime_t to_performance_time);
|
||||
virtual status_t AddTimer(bigtime_t at_performance_time, int32 cookie);
|
||||
virtual void SetRunMode(run_mode mode);
|
||||
virtual void HandleEvent(const media_timed_event *event,
|
||||
bigtime_t lateness, bool realTimeEvent = false);
|
||||
virtual void CleanUpEvent(const media_timed_event *event);
|
||||
virtual bigtime_t OfflineTime();
|
||||
virtual void ControlLoop();
|
||||
virtual status_t DeleteHook(BMediaNode * node);
|
||||
|
||||
/* BBufferProducer */
|
||||
protected:
|
||||
virtual status_t FormatSuggestionRequested(media_type type, int32 quality,
|
||||
media_format * format);
|
||||
virtual status_t FormatProposal(const media_source &output,
|
||||
media_format *format);
|
||||
virtual status_t FormatChangeRequested(const media_source &source,
|
||||
const media_destination &destination,
|
||||
media_format *io_format, int32 *_deprecated_);
|
||||
virtual status_t GetNextOutput(int32 * cookie, media_output * out_output);
|
||||
virtual status_t DisposeOutputCookie(int32 cookie);
|
||||
virtual status_t SetBufferGroup(const media_source &for_source,
|
||||
BBufferGroup * group);
|
||||
virtual status_t VideoClippingChanged(const media_source &for_source,
|
||||
int16 num_shorts, int16 *clip_data,
|
||||
const media_video_display_info &display,
|
||||
int32 * _deprecated_);
|
||||
virtual status_t GetLatency(bigtime_t * out_latency);
|
||||
virtual status_t PrepareToConnect(const media_source &what,
|
||||
const media_destination &where,
|
||||
media_format *format,
|
||||
media_source *out_source, char *out_name);
|
||||
virtual void Connect(status_t error, const media_source &source,
|
||||
const media_destination &destination,
|
||||
const media_format & format, char *io_name);
|
||||
virtual void Disconnect(const media_source & what,
|
||||
const media_destination & where);
|
||||
virtual void LateNoticeReceived(const media_source & what,
|
||||
bigtime_t how_much, bigtime_t performance_time);
|
||||
virtual void EnableOutput(const media_source & what, bool enabled,
|
||||
int32 * _deprecated_);
|
||||
virtual status_t SetPlayRate(int32 numer,int32 denom);
|
||||
virtual void AdditionalBufferRequested(const media_source & source,
|
||||
media_buffer_id prev_buffer, bigtime_t prev_time,
|
||||
const media_seek_tag * prev_tag);
|
||||
virtual void LatencyChanged(const media_source & source,
|
||||
const media_destination & destination,
|
||||
bigtime_t new_latency, uint32 flags);
|
||||
|
||||
/* BControllable */
|
||||
protected:
|
||||
virtual status_t GetParameterValue(int32 id, bigtime_t *last_change,
|
||||
void *value, size_t *size);
|
||||
virtual void SetParameterValue(int32 id, bigtime_t when,
|
||||
const void *value, size_t size);
|
||||
virtual status_t StartControlPanel(BMessenger *out_messenger);
|
||||
|
||||
public:
|
||||
enum {
|
||||
C_GET_CONFIGURATION = BTimedEventQueue::B_USER_EVENT,
|
||||
C_GET_CONFIGURATION_REPLY
|
||||
};
|
||||
|
||||
struct configuration_msg {
|
||||
port_id reply_port;
|
||||
};
|
||||
|
||||
struct configuration_msg_reply {
|
||||
status_t res;
|
||||
size_t config_size;
|
||||
char config;
|
||||
};
|
||||
|
||||
/* state */
|
||||
private:
|
||||
void HandleStart(bigtime_t performance_time);
|
||||
void HandleStop();
|
||||
void HandleTimeWarp(bigtime_t performance_time);
|
||||
void HandleSeek(bigtime_t performance_time);
|
||||
void HandleHardware();
|
||||
|
||||
// home-brewed extension
|
||||
status_t GetConfiguration( BMessage *out );
|
||||
|
||||
CVideoIn fVideoIn;
|
||||
|
||||
status_t fInitStatus;
|
||||
|
||||
int32 fInternalID;
|
||||
CRadeonAddOn *fAddOn;
|
||||
|
||||
BBufferGroup *fBufferGroup;
|
||||
//BBufferGroup *fUsedBufferGroup;
|
||||
|
||||
static int32 _frame_generator_(void *data);
|
||||
int32 FrameGenerator();
|
||||
|
||||
/* The remaining variables should be declared volatile, but they
|
||||
* are not here to improve the legibility of the sample code. */
|
||||
//uint32 fFrame;
|
||||
uint32 fFieldSequenceBase;
|
||||
//bigtime_t fPerformanceTimeBase;
|
||||
bigtime_t fProcessingLatency;
|
||||
media_output fOutput;
|
||||
//media_raw_video_format fConnectedFormat;
|
||||
//bool fConnected;
|
||||
bool fEnabled;
|
||||
|
||||
// use fixed names as they are used in settings file
|
||||
enum EOptions {
|
||||
P_SOURCE = 'VSRC',
|
||||
P_AUDIO_SOURCE = 'ASRC',
|
||||
P_AUDIO_FORMAT = 'AFMT',
|
||||
P_VOLUME = 'VOL ',
|
||||
P_STANDARD = 'TVST',
|
||||
P_MODE = 'CMOD',
|
||||
P_FORMAT = 'VFMT',
|
||||
P_RESOLUTION = 'RES ',
|
||||
P_TUNER = 'TUNR',
|
||||
P_BRIGHTNESS = 'BRGT',
|
||||
P_CONTRAST = 'CONT',
|
||||
P_SATURATION = 'SATU',
|
||||
P_HUE = 'HUE ',
|
||||
P_SHARPNESS = 'SHRP'
|
||||
};
|
||||
|
||||
enum { C_RESOLUTION_MAX = 6 };
|
||||
enum { C_CHANNEL_MAX = 125 };
|
||||
|
||||
int32 fSource;
|
||||
int32 fStandard;
|
||||
int32 fMode;
|
||||
int32 fCurMode; // mode, overwritten by application
|
||||
int32 fFormat;
|
||||
int32 fResolution;
|
||||
int32 fTuner;
|
||||
int32 fBrightness;
|
||||
int32 fContrast;
|
||||
int32 fSaturation;
|
||||
int32 fHue;
|
||||
int32 fSharpness;
|
||||
bigtime_t fSourceLastChange;
|
||||
bigtime_t fStandardLastChange;
|
||||
bigtime_t fModeLastChange;
|
||||
bigtime_t fFormatLastChange;
|
||||
bigtime_t fResolutionLastChange;
|
||||
bigtime_t fTunerLastChange;
|
||||
bigtime_t fBrightnessLastChange;
|
||||
bigtime_t fContrastLastChange;
|
||||
bigtime_t fSaturationLastChange;
|
||||
bigtime_t fHueLastChange;
|
||||
bigtime_t fSharpnessLastChange;
|
||||
|
||||
status_t AddInt32(
|
||||
BMessage *msg, EOptions option, int32 value );
|
||||
|
||||
status_t FindInt32(
|
||||
BMessage *config, EOptions option, int32 min_value, int32 max_value,
|
||||
int32 default_value, int32 *value );
|
||||
|
||||
// format negotiation helpers
|
||||
status_t verifySetMode( media_format *format );
|
||||
int32 extractCaptureMode( const media_format *format );
|
||||
status_t verifySetPixelAspect( media_format *format );
|
||||
status_t verifyActiveRange( media_format *format );
|
||||
void setActiveRange( media_format *format );
|
||||
status_t verifyOrientation( media_format *format );
|
||||
void setOrientation( media_format *format );
|
||||
status_t verifyPixelFormat( media_format *format );
|
||||
void setPixelFormat( media_format *format );
|
||||
status_t verifySetSize( media_format *format, int32 mode, bool set_bytes_per_row );
|
||||
status_t verifyFormatOffsets( media_format *format );
|
||||
void setFormatOffsets( media_format *format );
|
||||
status_t verifyFormatFlags( media_format *format );
|
||||
void setFormatFlags( media_format *format );
|
||||
|
||||
status_t finalizeFormat( media_format *format );
|
||||
|
||||
void startCapturing();
|
||||
void captureField( bigtime_t *capture_time );
|
||||
void setDefaultBufferGroup();
|
||||
void instantFormatChange( media_format *new_format );
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,135 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: Theater.h
|
||||
/
|
||||
/ Description: ATI Rage Theater Video Decoder interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __THEATER_H__
|
||||
#define __THEATER_H__
|
||||
|
||||
#include "Radeon.h"
|
||||
#include "VIPPort.h"
|
||||
|
||||
enum theater_identifier {
|
||||
C_THEATER_VIP_VENDOR_ID = 0x1002,
|
||||
C_THEATER_VIP_DEVICE_ID = 0x4d54
|
||||
};
|
||||
|
||||
|
||||
enum theater_standard {
|
||||
// TK: rearranged to match spec order
|
||||
C_THEATER_NTSC = 0,
|
||||
C_THEATER_NTSC_JAPAN = 1,
|
||||
C_THEATER_NTSC_443 = 2,
|
||||
C_THEATER_PAL_M = 3,
|
||||
C_THEATER_PAL_N = 4,
|
||||
C_THEATER_PAL_NC = 5,
|
||||
C_THEATER_PAL_BDGHI = 6,
|
||||
C_THEATER_PAL_60 = 7,
|
||||
C_THEATER_SECAM = 8
|
||||
};
|
||||
|
||||
enum theater_source {
|
||||
C_THEATER_TUNER = 0,
|
||||
C_THEATER_COMPOSITE = 1,
|
||||
C_THEATER_SVIDEO = 2
|
||||
};
|
||||
|
||||
|
||||
class CTheater {
|
||||
public:
|
||||
CTheater(CRadeon & radeon);
|
||||
|
||||
~CTheater();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetEnable(bool enable, bool vbi);
|
||||
|
||||
void SetStandard(theater_standard standard, theater_source source);
|
||||
|
||||
void SetSize(int hactive, int vactive);
|
||||
|
||||
void SetDeinterlace(bool deinterlace);
|
||||
|
||||
void SetSharpness(int sharpness);
|
||||
|
||||
void SetBrightness(int brightness);
|
||||
|
||||
void SetContrast(int contrast);
|
||||
|
||||
void SetSaturation(int saturation);
|
||||
|
||||
void SetHue(int hue);
|
||||
|
||||
int CurrentLine();
|
||||
|
||||
void getActiveRange( theater_standard standard, CRadeonRect &rect );
|
||||
|
||||
void getVBIRange( theater_standard standard, CRadeonRect &rect );
|
||||
|
||||
void PrintToStream();
|
||||
|
||||
private:
|
||||
void SetClock(theater_standard standard, radeon_video_clock clock);
|
||||
|
||||
void SetADC(theater_standard standard, theater_source source);
|
||||
|
||||
void SetHSYNC(theater_standard standard);
|
||||
|
||||
void WaitHSYNC();
|
||||
|
||||
void SetVSYNC(theater_standard standard);
|
||||
|
||||
void WaitVSYNC();
|
||||
|
||||
void SetSyncGenerator(theater_standard standard);
|
||||
|
||||
void SetCombFilter(theater_standard standard, theater_source source);
|
||||
|
||||
void SetLuminanceProcessor(theater_standard standard);
|
||||
|
||||
void SetLuminanceLevels(theater_standard standard, int brightness, int contrast);
|
||||
|
||||
void SetChromaProcessor(theater_standard standard);
|
||||
|
||||
void SetChromaLevels(theater_standard standard, int saturation, int hue);
|
||||
|
||||
void SetClipWindow(theater_standard standard, bool vbi);
|
||||
|
||||
void SetScaler(theater_standard standard, int hactive, int vactive, bool deinterlace);
|
||||
|
||||
public:
|
||||
int Register(int index);
|
||||
|
||||
int Register(int index, int mask);
|
||||
|
||||
void SetRegister(int index, int value);
|
||||
|
||||
void SetRegister(int index, int mask, int value);
|
||||
|
||||
private:
|
||||
CVIPPort fPort;
|
||||
int fDevice;
|
||||
radeon_video_clock fClock;
|
||||
int fTunerPort;
|
||||
int fCompositePort;
|
||||
int fSVideoPort;
|
||||
theater_standard fStandard;
|
||||
theater_source fSource;
|
||||
int fBrightness;
|
||||
int fContrast;
|
||||
int fSaturation;
|
||||
int fHue;
|
||||
int fHActive;
|
||||
int fVActive;
|
||||
bool fDeinterlace;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,323 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: Tuner.cpp
|
||||
/
|
||||
/ Description: Philips Desktop TV Tuners interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <Debug.h>
|
||||
#include "Tuner.h"
|
||||
|
||||
enum tuner_control_bits {
|
||||
CHANGE_PUMP = 0x40, /* change pump settings */
|
||||
CHANGE_PUMP_FAST = 0x00, /* for fast tuning */
|
||||
CHANGE_PUMP_SLOW = 0x40, /* for moderate speed tuning */
|
||||
|
||||
TEST_MODE = 0x38, /* test mode settings */
|
||||
TEST_MODE_NORMAL = 0x08, /* for normal operation */
|
||||
|
||||
RATIO_SELECT = 0x06, /* ratio select */
|
||||
RATIO_SELECT_FAST = 0x00, /* fast picture search */
|
||||
RATIO_SELECT_SLOW = 0x02, /* slow picture search */
|
||||
RATIO_SELECT_NORMAL = 0x06, /* normal picture search */
|
||||
|
||||
OS_MODE = 0x01, /* PLL disabling */
|
||||
OS_MODE_NORMAL = 0x00, /* for normal operation */
|
||||
OS_MODE_SWITCH = 0x01 /* change pump to high impedance */
|
||||
};
|
||||
|
||||
enum tuner_status_bits {
|
||||
STB_POR = 0x80, /* power on reset */
|
||||
STB_FL = 0x40, /* in-lock flag */
|
||||
STB_INF = 0x38, /* digital information */
|
||||
STB_ADC = 0x07 /* A/D converter */
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
/
|
||||
/ Tuner Parameters and Frequencies for TV Antenna and Cable Channels
|
||||
/
|
||||
******************************************************************************/
|
||||
|
||||
static const int kBandsPerTuner = 5;
|
||||
|
||||
static const struct {
|
||||
tuner_type brand;
|
||||
const char* name;
|
||||
struct {
|
||||
int pll;
|
||||
float minFrequency, maxFrequency;
|
||||
} bands[kBandsPerTuner];
|
||||
} kTunerTable[] = {
|
||||
/* Philips FI1236 NTSC M/N */
|
||||
{ C_TUNER_FI1236, "FI1236 NTSC",
|
||||
{ { 0xa2, 54.00, 157.25 },
|
||||
{ 0x94, 162.00, 451.25 },
|
||||
{ 0x34, 451.25, 463.25 },
|
||||
{ 0x31, 463.25, 801.25 },
|
||||
{ 0x00, 0.00, 0.00 } } },
|
||||
|
||||
/* Philips FI1236J NTSC Japan */
|
||||
{ C_TUNER_FI1236J, "FI1236J NTSC Japan",
|
||||
{ { 0xa2, 54.00, 157.25 },
|
||||
{ 0x94, 162.00, 451.25 },
|
||||
{ 0x34, 451.25, 463.25 },
|
||||
{ 0x31, 463.25, 801.25 },
|
||||
{ 0x00, 0.00, 0.00 } } },
|
||||
|
||||
/* Philips FI1236MK2 NTSC M/N */
|
||||
{ C_TUNER_FI1236MK2, "FI1236MK2 NTSC",
|
||||
{ { 0xa0, 55.25, 160.00 },
|
||||
{ 0x90, 160.00, 454.00 },
|
||||
{ 0x30, 454.00, 855.25 },
|
||||
{ 0x00, 0.00, 0.00 },
|
||||
{ 0x00, 0.00, 0.00 } } },
|
||||
|
||||
/* Philips FI1216 PAL B/G */
|
||||
{ C_TUNER_FI1216, "FI1216 PAL",
|
||||
{ { 0xa2, 45.00, 140.25 },
|
||||
{ 0xa4, 140.25, 168.25 },
|
||||
{ 0x94, 168.25, 447.25 },
|
||||
{ 0x34, 447.25, 463.25 },
|
||||
{ 0x31, 463.25, 855.25 } } },
|
||||
|
||||
/* Philips FI1216MK2 PAL B/G */
|
||||
{ C_TUNER_FI1216MK2, "FI1216MK2 PAL",
|
||||
{ { 0xa0, 48.25, 170.00 },
|
||||
{ 0x90, 170.00, 450.00 },
|
||||
{ 0x30, 450.00, 855.25 },
|
||||
{ 0x00, 0.00, 0.00 },
|
||||
{ 0x00, 0.00, 0.00 } } },
|
||||
|
||||
/* Philips FI1216MF PAL B/G, SECAM L/L' */
|
||||
{ C_TUNER_FI1216MF, "FI1216MF PAL/SECAM",
|
||||
{ { 0xa1, 45.00, 168.25 },
|
||||
{ 0x91, 168.25, 447.25 },
|
||||
{ 0x31, 447.25, 855.25 },
|
||||
{ 0x00, 0.00, 0.00 },
|
||||
{ 0x00, 0.00, 0.00 } } },
|
||||
|
||||
/* Philips FI1246 PAL I */
|
||||
{ C_TUNER_FI1246, "FI1246 PAL I",
|
||||
{ { 0xa2, 45.00, 140.25 },
|
||||
{ 0xa4, 140.25, 168.25 },
|
||||
{ 0x94, 168.25, 447.25 },
|
||||
{ 0x34, 447.25, 463.25 },
|
||||
{ 0x31, 463.25, 855.25 } } },
|
||||
|
||||
/* Philips FI1256 SECAM D/K */
|
||||
{ C_TUNER_FI1256, "FI1256 SECAM",
|
||||
{ { 0xa0, 48.25, 168.25 },
|
||||
{ 0x90, 175.25, 455.25 },
|
||||
{ 0x30, 463.25, 863.25 },
|
||||
{ 0x00, 0.00, 0.00 },
|
||||
{ 0x00, 0.00, 0.00 } } },
|
||||
|
||||
/* Temic FN5AL PAL I/B/G/DK, SECAM DK */
|
||||
{ C_TUNER_TEMIC_FN5AL_PAL, "Temic FN5AL PAL",
|
||||
{ { 0xa2, 45.00, 140.25 },
|
||||
{ 0xa4, 140.25, 168.25 },
|
||||
{ 0x94, 168.25, 447.25 },
|
||||
{ 0x31, 447.25, 855.25 },
|
||||
{ 0x00, 0.00, 0.00 } } },
|
||||
|
||||
/* Temic FN5AL PAL I/B/G/DK, SECAM DK */
|
||||
{ C_TUNER_TEMIC_FN5AL_SECAM, "Temic FN5AL SECAM",
|
||||
{ { 0xa0, 48.25, 168.25 },
|
||||
{ 0x90, 175.25, 455.25 },
|
||||
{ 0x30, 463.25, 863.25 },
|
||||
{ 0x00, 0.00, 0.00 },
|
||||
{ 0x00, 0.00, 0.00 } } } };
|
||||
|
||||
static const int kNumTuners = sizeof(kTunerTable) / sizeof(kTunerTable[0]);
|
||||
|
||||
|
||||
CTuner::CTuner(CI2CPort & port)
|
||||
: fPort(port),
|
||||
fType(C_TUNER_NONE),
|
||||
fAddress(0xC6),
|
||||
fDivider(0)
|
||||
{
|
||||
PRINT(("CTuner::CTuner()\n"));
|
||||
|
||||
if( fPort.InitCheck() == B_OK ) {
|
||||
radeon_video_tuner tuner;
|
||||
radeon_video_decoder video;
|
||||
radeon_video_clock clock;
|
||||
int dummy;
|
||||
|
||||
fPort.Radeon().GetMMParameters(tuner, video, clock, dummy, dummy, dummy);
|
||||
switch (tuner) {
|
||||
case C_RADEON_NO_TUNER:
|
||||
fType = C_TUNER_NONE;
|
||||
break;
|
||||
case C_RADEON_FI1236_MK1_NTSC:
|
||||
fType = C_TUNER_FI1236;
|
||||
break;
|
||||
case C_RADEON_FI1236_MK2_NTSC_JAPAN:
|
||||
fType = C_TUNER_FI1236J;
|
||||
break;
|
||||
case C_RADEON_FI1216_MK2_PAL_BG:
|
||||
fType = C_TUNER_FI1216;
|
||||
break;
|
||||
case C_RADEON_FI1246_MK2_PAL_I:
|
||||
fType = C_TUNER_FI1246;
|
||||
break;
|
||||
case C_RADEON_FI1216_MF_MK2_PAL_BG_SECAM_L:
|
||||
fType = C_TUNER_FI1216MF;
|
||||
break;
|
||||
case C_RADEON_FI1236_MK2_NTSC:
|
||||
fType = C_TUNER_FI1236MK2;
|
||||
break;
|
||||
case C_RADEON_FI1256_MK2_SECAM_DK:
|
||||
fType = C_TUNER_FI1256;
|
||||
break;
|
||||
case C_RADEON_FI1216_MK2_PAL_BG_SECAM_L:
|
||||
fType = C_TUNER_FI1216MK2;
|
||||
break;
|
||||
case C_RADEON_TEMIC_FN5AL_PAL_IBGDK_SECAM_DK:
|
||||
fType = C_TUNER_TEMIC_FN5AL_PAL;
|
||||
break;
|
||||
default:
|
||||
fType = C_TUNER_FI1236;
|
||||
break;
|
||||
}
|
||||
|
||||
for (fAddress = 0xc0; fAddress <= 0xc6; fAddress += 0x02) {
|
||||
if (fPort.Probe(fAddress)) {
|
||||
PRINT(("CTuner::CTuner() - TV Tuner found at I2C port 0x%02x\n", fAddress));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( InitCheck() != B_OK )
|
||||
PRINT(("CTuner::CTuner() - TV Tuner not found!\n"));
|
||||
}
|
||||
|
||||
CTuner::~CTuner()
|
||||
{
|
||||
PRINT(("CTuner::~CTuner()\n"));
|
||||
}
|
||||
|
||||
status_t CTuner::InitCheck() const
|
||||
{
|
||||
return (fType != C_TUNER_NONE && fAddress >= 0xc0 && fAddress <= 0xc6) ?
|
||||
B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
bool CTuner::SetFrequency(float frequency, float picture)
|
||||
{
|
||||
//PRINT(("CTuner::SetFrequency(%g, %g)\n", frequency, picture));
|
||||
|
||||
for (int index = 0; index < kNumTuners; index++) {
|
||||
if (kTunerTable[index].brand == fType) {
|
||||
for (int band = 0; band < kBandsPerTuner; band++) {
|
||||
if (frequency >= kTunerTable[index].bands[band].minFrequency &&
|
||||
frequency <= kTunerTable[index].bands[band].maxFrequency) {
|
||||
SetParameters(
|
||||
(int) (16.0 * (frequency + picture)),
|
||||
CHANGE_PUMP_FAST | RATIO_SELECT_NORMAL |
|
||||
TEST_MODE_NORMAL | OS_MODE_NORMAL,
|
||||
kTunerTable[index].bands[band].pll |
|
||||
((Status() & STB_INF) >> 3));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTuner::SweepFrequency(float frequency, float picture)
|
||||
{
|
||||
PRINT(("CTuner::SweepFrequency(%g, %g)\n", frequency, picture));
|
||||
|
||||
float centerFrequency = frequency;
|
||||
|
||||
/* sweeping down */
|
||||
do {
|
||||
SetFrequency(frequency, picture);
|
||||
for (int timeout = 0; timeout < 10; timeout++) {
|
||||
snooze(20000);
|
||||
if (IsLocked())
|
||||
break;
|
||||
}
|
||||
} while (ADC() == 0 &&
|
||||
(frequency -= 0.5000) > centerFrequency - 3.000);
|
||||
|
||||
/* sweeping up */
|
||||
do {
|
||||
SetFrequency(frequency, picture);
|
||||
for (int timeout = 0; timeout < 10; timeout++) {
|
||||
snooze(20000);
|
||||
if (IsLocked())
|
||||
break;
|
||||
}
|
||||
} while (ADC() != 0 &&
|
||||
(frequency += 0.0625) < centerFrequency + 0.500);
|
||||
|
||||
return (ADC() == 0);
|
||||
}
|
||||
|
||||
const char * CTuner::Name() const
|
||||
{
|
||||
for (int index = 0; index < kNumTuners; index++) {
|
||||
if (kTunerTable[index].brand == fType)
|
||||
return kTunerTable[index].name;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
tuner_type CTuner::Type() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
bool CTuner::HasSignal(void)
|
||||
{
|
||||
return (IsLocked() && ADC() <= 2);
|
||||
}
|
||||
|
||||
int CTuner::Status(void)
|
||||
{
|
||||
char buffer[1];
|
||||
fPort.Read(fAddress, buffer, sizeof(buffer));
|
||||
return buffer[0] & 0xff;
|
||||
}
|
||||
|
||||
int CTuner::ADC(void)
|
||||
{
|
||||
return Status() & STB_ADC;
|
||||
}
|
||||
|
||||
bool CTuner::IsLocked(void)
|
||||
{
|
||||
return (Status() & STB_FL) != 0;
|
||||
}
|
||||
|
||||
void CTuner::SetParameters(int divider, int control, int band)
|
||||
{
|
||||
char buffer[4];
|
||||
|
||||
if (divider > fDivider) {
|
||||
buffer[0] = (divider >> 8) & 0x7f;
|
||||
buffer[1] = (divider >> 0) & 0xff;
|
||||
|
||||
buffer[2] = (control | 0x80);
|
||||
buffer[3] = (band & 0xff);
|
||||
}
|
||||
else {
|
||||
buffer[0] = (control | 0x80);
|
||||
buffer[1] = (band & 0xff);
|
||||
|
||||
buffer[2] = (divider >> 8) & 0x7f;
|
||||
buffer[3] = (divider >> 0) & 0xff;
|
||||
}
|
||||
|
||||
fDivider = divider;
|
||||
|
||||
fPort.Write(fAddress, buffer, sizeof(buffer));
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: Tuner.h
|
||||
/
|
||||
/ Description: Philips Desktop TV Tuners interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __TUNER_H__
|
||||
#define __TUNER_H__
|
||||
|
||||
#include "I2CPort.h"
|
||||
|
||||
enum tuner_type {
|
||||
C_TUNER_NONE = 0x1400, /* Unknown */
|
||||
C_TUNER_FI1236 = 0x1401, /* NTSC M/N */
|
||||
C_TUNER_FI1236J = 0x1402, /* NTSC Japan */
|
||||
C_TUNER_FI1236MK2 = 0x1403, /* NTSC M/N */
|
||||
C_TUNER_FI1216 = 0x1404, /* PAL B/G */
|
||||
C_TUNER_FI1216MK2 = 0x1405, /* PAL B/G */
|
||||
C_TUNER_FI1216MF = 0x1406, /* PAL B/G, SECAM L/L' */
|
||||
C_TUNER_FI1246 = 0x1407, /* PAL I */
|
||||
C_TUNER_FI1256 = 0x1408, /* SECAM D/K */
|
||||
C_TUNER_TEMIC_FN5AL_PAL = 0x1409, /* PAL I/B/G/DK */
|
||||
C_TUNER_TEMIC_FN5AL_SECAM = 0x140a /* SECAM DK */
|
||||
};
|
||||
|
||||
enum tuner_picture_carrier {
|
||||
C_TUNER_NTSC_PICTURE_CARRIER = 4575,
|
||||
C_TUNER_PAL_PICTURE_CARRIER = 3890,
|
||||
C_TUNER_SECAM_PICTURE_CARRIER = 3890
|
||||
};
|
||||
|
||||
class CTuner {
|
||||
public:
|
||||
CTuner(CI2CPort & port);
|
||||
|
||||
~CTuner();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
const char * Name() const;
|
||||
|
||||
tuner_type Type() const;
|
||||
|
||||
bool SetFrequency(float frequency, float picture);
|
||||
|
||||
bool SweepFrequency(float frequency, float picture);
|
||||
|
||||
bool HasSignal(void);
|
||||
|
||||
int Status();
|
||||
|
||||
bool IsLocked();
|
||||
|
||||
int ADC();
|
||||
|
||||
private:
|
||||
void SetParameters(int divider, int control, int band);
|
||||
|
||||
private:
|
||||
CI2CPort & fPort;
|
||||
tuner_type fType;
|
||||
int fAddress;
|
||||
int fDivider;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: VIP.cpp
|
||||
/
|
||||
/ Description: ATI Radeon Video Input Port (VIP) interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <Debug.h>
|
||||
#include "VIPPort.h"
|
||||
|
||||
CVIPPort::CVIPPort(CRadeon & radeon)
|
||||
: fRadeon(radeon)
|
||||
{
|
||||
PRINT(("CVIPPort::CVIPPort()\n"));
|
||||
}
|
||||
|
||||
CVIPPort::~CVIPPort()
|
||||
{
|
||||
PRINT(("CVIPPort::~CVIPPort()\n"));
|
||||
}
|
||||
|
||||
status_t CVIPPort::InitCheck() const
|
||||
{
|
||||
return fRadeon.InitCheck();
|
||||
}
|
||||
|
||||
CRadeon & CVIPPort::Radeon()
|
||||
{
|
||||
return fRadeon;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: VIP.h
|
||||
/
|
||||
/ Description: ATI Radeon Video Input Port (VIP) interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __VIP_PORT_H__
|
||||
#define __VIP_PORT_H__
|
||||
|
||||
#include "Radeon.h"
|
||||
|
||||
enum vip_port_device {
|
||||
C_VIP_PORT_DEVICE_0 = 0,
|
||||
C_VIP_PORT_DEVICE_1 = 1,
|
||||
C_VIP_PORT_DEVICE_2 = 2,
|
||||
C_VIP_PORT_DEVICE_3 = 3
|
||||
};
|
||||
|
||||
enum vip_port_register {
|
||||
C_VIP_VENDOR_DEVICE_ID = 0x0000,
|
||||
C_VIP_VENDOR_ID = BITS(15:0),
|
||||
C_VIP_DEVICE_ID = BITS(31:16),
|
||||
|
||||
C_VIP_SUB_VENDOR_DEVICE_ID = 0x0004,
|
||||
C_VIP_SUB_VENDOR_ID = BITS(15:0),
|
||||
C_VIP_SUB_DEVICE_ID = BITS(31:16),
|
||||
|
||||
C_VIP_COMMAND_STATUS = 0x0008,
|
||||
C_VIP_POWER_ST = BITS(1:0),
|
||||
C_VIP_XHOST_ON = BITS(2:2),
|
||||
C_VIP_P1_SUPPORT = BITS(16:16),
|
||||
C_VIP_P2_SUPPORT = BITS(17:17),
|
||||
C_VIP_HOST_CAP = BITS(19:18),
|
||||
|
||||
C_VIP_REVISION_ID = 0x000c,
|
||||
C_VIP_REVISION_ID_MASK = BITS(15:0)
|
||||
};
|
||||
|
||||
class CVIPPort {
|
||||
public:
|
||||
CVIPPort(CRadeon & radeon);
|
||||
|
||||
~CVIPPort();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
CRadeon & Radeon();
|
||||
|
||||
int Register(int device, int address) {
|
||||
return fRadeon.VIPRegister( device, address );
|
||||
}
|
||||
|
||||
void SetRegister(int device, int address, int value) {
|
||||
fRadeon.SetVIPRegister( device, address, value );
|
||||
}
|
||||
|
||||
int FindVIPDevice( uint32 device_id ) {
|
||||
return fRadeon.FindVIPDevice( device_id );
|
||||
}
|
||||
|
||||
private:
|
||||
CRadeon & fRadeon;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,453 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: VideoIn.cpp
|
||||
/
|
||||
/ Description: High-Level ATI Radeon Video Capture Interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <Debug.h>
|
||||
#include "VideoIn.h"
|
||||
#include <memory.h>
|
||||
|
||||
static const theater_standard kStandard[] = {
|
||||
C_THEATER_NTSC,
|
||||
C_THEATER_NTSC_JAPAN,
|
||||
C_THEATER_NTSC_443,
|
||||
C_THEATER_PAL_M,
|
||||
C_THEATER_PAL_BDGHI,
|
||||
C_THEATER_PAL_N,
|
||||
C_THEATER_PAL_60,
|
||||
C_THEATER_PAL_NC,
|
||||
C_THEATER_SECAM,
|
||||
// C_THEATER_NTSC_RAW
|
||||
};
|
||||
|
||||
static const theater_source kSource[] = {
|
||||
C_THEATER_TUNER,
|
||||
C_THEATER_COMPOSITE,
|
||||
C_THEATER_SVIDEO
|
||||
};
|
||||
|
||||
static const capture_buffer_mode kMode[] = {
|
||||
C_RADEON_CAPTURE_FIELD_DOUBLE,
|
||||
C_RADEON_CAPTURE_BOB_DOUBLE,
|
||||
C_RADEON_CAPTURE_WEAVE_DOUBLE
|
||||
};
|
||||
|
||||
static const struct {
|
||||
struct {
|
||||
int width, height;
|
||||
} total;
|
||||
struct {
|
||||
int left, top;
|
||||
int width, height;
|
||||
} active;
|
||||
struct {
|
||||
int left, top;
|
||||
int width, height;
|
||||
} vbi;
|
||||
} kTiming[] = {
|
||||
{ { 910, 525 }, { 112, 37, 755, 480 }, { 73, 13, 798, 20 } }, // NTSC-M
|
||||
{ { 910, 525 }, { 112, 37, 755, 480 }, { 73, 13, 798, 24 } }, // NTSC-Japan
|
||||
{ { 1042, 525 }, { 126, 37, 940, 480 }, { 73, 13, 798, 24 } }, // NTSC-443
|
||||
{ { 910, 525 }, { 103, 37, 764, 480 }, { 73, 13, 798, 24 } }, // PAL-M
|
||||
|
||||
{ { 1135, 625 }, { 154, 35, 928, 576 }, { 132, 11, 924, 24 } }, // PAL-BDGHI
|
||||
{ { 1135, 625 }, { 154, 35, 928, 576 }, { 132, 11, 924, 24 } }, // PAL-N
|
||||
{ { 1125, 625 }, { 132, 37, 736, 480 }, { 100, 13, 770, 26 } }, // PAL-60
|
||||
{ { 910, 625 }, { 125, 35, 957, 576 }, { 132, 11, 924, 24 } }, // PAL-NC
|
||||
{ { 1135, 625 }, { 149, 35, 933, 576 }, { 132, 11, 924, 24 } }, // SECAM
|
||||
|
||||
{ { 910, 525 }, { 112, 37, 755, 480 }, { 73, 13, 798, 22 } } // NTSC-Raw
|
||||
};
|
||||
|
||||
|
||||
|
||||
CVideoIn::CVideoIn( const char *dev_name )
|
||||
: fRadeon( dev_name ),
|
||||
fCapture(fRadeon),
|
||||
fI2CPort(fRadeon),
|
||||
fTheater(fRadeon),
|
||||
fTuner(fI2CPort),
|
||||
fSound(fI2CPort),
|
||||
fBuffer0(0),
|
||||
fBuffer1(0),
|
||||
fBuffer0Handle(0),
|
||||
fBuffer1Handle(0),
|
||||
convert_buffer( NULL ),
|
||||
fBufferLength(0),
|
||||
fBufferBytesPerRow(0),
|
||||
fBufferSequence(0),
|
||||
fBufferPeriod(0),
|
||||
started( false )
|
||||
{
|
||||
Trace("CVideoIn::CVideoIn()");
|
||||
}
|
||||
|
||||
CVideoIn::~CVideoIn()
|
||||
{
|
||||
Trace("CVideoIn::~CVideoIn()");
|
||||
|
||||
FreeBuffers();
|
||||
}
|
||||
|
||||
status_t CVideoIn::InitCheck() const
|
||||
{
|
||||
status_t res;
|
||||
|
||||
Trace("CVideoIn::InitCheck()");
|
||||
|
||||
if( (res = fRadeon.InitCheck()) != B_OK )
|
||||
return res;
|
||||
|
||||
if( (res = fCapture.InitCheck()) != B_OK )
|
||||
return res;
|
||||
|
||||
if( (res = fI2CPort.InitCheck()) != B_OK )
|
||||
return res;
|
||||
|
||||
return fTheater.InitCheck();
|
||||
}
|
||||
|
||||
int CVideoIn::Capabilities() const
|
||||
{
|
||||
return (fTuner.InitCheck() == B_OK ? C_VIDEO_IN_HAS_TUNER + C_VIDEO_IN_HAS_COMPOSITE + C_VIDEO_IN_HAS_SVIDEO : 0) +
|
||||
(fSound.InitCheck() == B_OK ? C_VIDEO_IN_HAS_SOUND : 0);
|
||||
}
|
||||
|
||||
void CVideoIn::Start(video_in_source source, video_in_standard standard,
|
||||
video_in_capture_mode mode, int width, int height)
|
||||
{
|
||||
char buffer[256];
|
||||
sprintf(buffer, "CVideoIn::Start(%s, %d, %d)",
|
||||
mode == C_VIDEO_IN_FIELD ? "C_VIDEO_IN_FIELD" :
|
||||
mode == C_VIDEO_IN_BOB ? "C_VIDEO_IN_BOB" : "C_VIDEO_IN_WEAVE", width, height);
|
||||
Trace(buffer);
|
||||
|
||||
if( started )
|
||||
Stop();
|
||||
|
||||
switch (mode) {
|
||||
case C_VIDEO_IN_FIELD:
|
||||
case C_VIDEO_IN_BOB:
|
||||
width = Clamp(width, 0, kTiming[standard].active.width);
|
||||
height = Clamp(height, 0, kTiming[standard].active.height / 2);
|
||||
break;
|
||||
case C_VIDEO_IN_WEAVE:
|
||||
width = Clamp(width, 0, kTiming[standard].active.width);
|
||||
height = Clamp(height, 0, kTiming[standard].active.height);
|
||||
break;
|
||||
}
|
||||
|
||||
fBufferBytesPerRow = (2 * width + 15) & ~15;
|
||||
fBufferLength = (fBufferBytesPerRow * height + 15) & ~15;
|
||||
|
||||
FreeBuffers();
|
||||
|
||||
// TBD:
|
||||
// no error handling !!!!
|
||||
fRadeon.AllocateGraphicsMemory(
|
||||
mt_local,
|
||||
mode == C_VIDEO_IN_BOB ? 4 * fBufferLength : 2 * fBufferLength,
|
||||
&fBuffer0, &fBuffer0Handle );
|
||||
|
||||
fRadeon.AllocateGraphicsMemory(
|
||||
mt_local,
|
||||
mode == C_VIDEO_IN_BOB ? 2 * fBufferLength : 1 * fBufferLength,
|
||||
&fBuffer1, &fBuffer1Handle );
|
||||
|
||||
convert_buffer = malloc( mode == C_VIDEO_IN_BOB ? 4 * fBufferLength : 2 * fBufferLength );
|
||||
|
||||
fBufferPeriod = 1000000000LL / getFrameRate( standard );
|
||||
|
||||
if( mode == C_VIDEO_IN_BOB )
|
||||
fBufferPeriod >>= 1;
|
||||
|
||||
fTheater.SetStandard(kStandard[standard], kSource[source]);
|
||||
fTheater.SetSize(width, (mode != C_VIDEO_IN_WEAVE ? 2 * height : height));
|
||||
|
||||
fCapture.SetBuffer(C_RADEON_CAPTURE_CCIR656, kMode[mode], fBuffer0, fBuffer1, fBufferLength, fBufferBytesPerRow >> 1);
|
||||
fCapture.SetClip(0, kTiming[standard].vbi.height, width - 1, kTiming[standard].vbi.height + (mode != C_VIDEO_IN_WEAVE ? height : height >> 1) - 1);
|
||||
|
||||
fTheater.SetEnable(true, false);
|
||||
if( fSound.InitCheck() == B_OK )
|
||||
fSound.SetEnable(true);
|
||||
fCapture.SetInterrupts(true);
|
||||
fCapture.Start();
|
||||
}
|
||||
|
||||
void CVideoIn::Stop()
|
||||
{
|
||||
Trace("CVideoIn::Stop()");
|
||||
|
||||
if( !started )
|
||||
return;
|
||||
|
||||
fCapture.Stop();
|
||||
fCapture.SetInterrupts(false);
|
||||
if( fSound.InitCheck() == B_OK )
|
||||
fSound.SetEnable(false);
|
||||
fTheater.SetEnable(false, false);
|
||||
|
||||
FreeBuffers();
|
||||
}
|
||||
|
||||
void CVideoIn::FreeBuffers()
|
||||
{
|
||||
if( fBuffer0Handle > 0 ) {
|
||||
fRadeon.FreeGraphicsMemory( mt_local, fBuffer0Handle );
|
||||
fBuffer0Handle = 0;
|
||||
}
|
||||
|
||||
if( fBuffer1Handle > 0 ) {
|
||||
fRadeon.FreeGraphicsMemory( mt_local, fBuffer1Handle );
|
||||
fBuffer1Handle = 0;
|
||||
}
|
||||
|
||||
if( convert_buffer != NULL ) {
|
||||
free( convert_buffer );
|
||||
convert_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CVideoIn::SetBrightness(int brightness)
|
||||
{
|
||||
Trace("CVideoIn::SetBrightness()");
|
||||
|
||||
fTheater.SetBrightness(brightness);
|
||||
}
|
||||
|
||||
void CVideoIn::SetContrast(int contrast)
|
||||
{
|
||||
Trace("CVideoIn::SetContrast()");
|
||||
|
||||
fTheater.SetContrast(contrast);
|
||||
}
|
||||
|
||||
void CVideoIn::SetSaturation(int saturation)
|
||||
{
|
||||
Trace("CVideoIn::SetSaturation()");
|
||||
|
||||
fTheater.SetSaturation(saturation);
|
||||
}
|
||||
|
||||
void CVideoIn::SetHue(int hue)
|
||||
{
|
||||
Trace("CVideoIn::SetHue()");
|
||||
|
||||
fTheater.SetHue(hue);
|
||||
}
|
||||
|
||||
void CVideoIn::SetSharpness(int sharpness)
|
||||
{
|
||||
Trace("CVideoIn::SetSharpness()");
|
||||
|
||||
fTheater.SetSharpness(sharpness);
|
||||
}
|
||||
|
||||
void CVideoIn::SetFrequency(float frequency, float picture)
|
||||
{
|
||||
Trace("CVideoIn::SetFrequency()");
|
||||
|
||||
if (fTuner.Type() != C_TUNER_NONE)
|
||||
fTuner.SweepFrequency(frequency, picture);
|
||||
}
|
||||
|
||||
float CVideoIn::FrequencyForChannel(int channel, video_in_standard standard)
|
||||
{
|
||||
float frequency = 0;
|
||||
|
||||
Trace("CVideoIn::FrequencyForChannel()");
|
||||
|
||||
if (fTuner.Type() != C_TUNER_NONE) {
|
||||
switch (standard) {
|
||||
case C_VIDEO_IN_NTSC:
|
||||
case C_VIDEO_IN_NTSC_RAW:
|
||||
// NTSC Cable
|
||||
if (channel >= 2 && channel <= 6) {
|
||||
frequency = 55.25 + 6.00 * (channel - 2);
|
||||
}
|
||||
else if (channel >= 7 && channel <= 13) {
|
||||
frequency = 175.25 + 6.00 * (channel - 7);
|
||||
}
|
||||
else if (channel >= 14 && channel <= 22) {
|
||||
frequency = 121.25 + 6.00 * (channel - 14);
|
||||
}
|
||||
else if (channel >= 23 && channel <= 36) {
|
||||
frequency = 217.25 + 6.00 * (channel - 23);
|
||||
}
|
||||
else if (channel >= 37 && channel <= 62) {
|
||||
frequency = 301.25 + 6.00 * (channel - 37);
|
||||
}
|
||||
else if (channel >= 63 && channel <= 94) {
|
||||
frequency = 457.25 + 6.00 * (channel - 63);
|
||||
}
|
||||
else if (channel >= 95 && channel <= 99) {
|
||||
frequency = 91.25 + 6.00 * (channel - 95);
|
||||
}
|
||||
else if (channel >= 100 && channel <= 125) {
|
||||
frequency = 649.25 + 6.00 * (channel - 100);
|
||||
}
|
||||
else {
|
||||
frequency = 0;
|
||||
}
|
||||
break;
|
||||
case C_VIDEO_IN_NTSC_JAPAN:
|
||||
case C_VIDEO_IN_NTSC_443:
|
||||
case C_VIDEO_IN_PAL_M:
|
||||
case C_VIDEO_IN_PAL_BDGHI:
|
||||
case C_VIDEO_IN_PAL_N:
|
||||
case C_VIDEO_IN_PAL_60:
|
||||
case C_VIDEO_IN_PAL_NC:
|
||||
case C_VIDEO_IN_SECAM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return frequency;
|
||||
}
|
||||
|
||||
bool CVideoIn::SetChannel(int channel, video_in_standard standard)
|
||||
{
|
||||
Trace("CVideoIn::SetChannel()");
|
||||
|
||||
if (fTuner.Type() == C_TUNER_NONE)
|
||||
return true;
|
||||
|
||||
const float frequency = FrequencyForChannel(channel, standard);
|
||||
|
||||
switch (standard) {
|
||||
case C_VIDEO_IN_NTSC:
|
||||
case C_VIDEO_IN_NTSC_RAW:
|
||||
return fTuner.SweepFrequency(frequency, C_TUNER_NTSC_PICTURE_CARRIER / 100.0f);
|
||||
break;
|
||||
case C_VIDEO_IN_NTSC_JAPAN:
|
||||
case C_VIDEO_IN_NTSC_443:
|
||||
case C_VIDEO_IN_PAL_M:
|
||||
case C_VIDEO_IN_PAL_BDGHI:
|
||||
case C_VIDEO_IN_PAL_N:
|
||||
case C_VIDEO_IN_PAL_60:
|
||||
case C_VIDEO_IN_PAL_NC:
|
||||
case C_VIDEO_IN_SECAM:
|
||||
return fTuner.SweepFrequency(frequency, C_TUNER_PAL_PICTURE_CARRIER / 100.0f);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int CVideoIn::Capture(color_space colorSpace, void * bits, int bitsLength,
|
||||
int bytesPerRow, int * sequence, short * number, bigtime_t * when)
|
||||
{
|
||||
// Trace("CVideoIn::Capture()");
|
||||
|
||||
int mask, counter;
|
||||
|
||||
if ((mask = fCapture.WaitInterrupts(sequence, when, fBufferPeriod)) == 0)
|
||||
return 0;
|
||||
|
||||
*number = ((mask & (C_RADEON_CAPTURE_BUF0_INT | C_RADEON_CAPTURE_BUF1_INT)) != 0 ? 0 : 1);
|
||||
|
||||
int32 captured_buffer =
|
||||
((mask & C_RADEON_CAPTURE_BUF0_INT) != 0 ? fBuffer0 :
|
||||
(mask & C_RADEON_CAPTURE_BUF1_INT) != 0 ? fBuffer1 :
|
||||
(mask & C_RADEON_CAPTURE_BUF0_EVEN_INT) != 0 ? fBuffer0 + fBufferLength :
|
||||
(mask & C_RADEON_CAPTURE_BUF1_EVEN_INT) != 0 ? fBuffer1 + fBufferLength : 0);
|
||||
|
||||
/*PRINT(("colorSpace:%x, bitsLength: %d, fBufferLength: %d, bytesPerRow: %d, fBufferBytesPerRow: %d\n",
|
||||
colorSpace, bitsLength, fBufferLength, bytesPerRow, fBufferBytesPerRow ));*/
|
||||
|
||||
// always copy into main memory first, even if it must be converted by CPU -
|
||||
// reading from graphics mem is incredibly slow
|
||||
if (colorSpace == B_YCbCr422 && bitsLength <= fBufferLength && bytesPerRow == fBufferBytesPerRow) {
|
||||
PRINT(("%d, %p\n", captured_buffer, bits));
|
||||
|
||||
fRadeon.DMACopy( captured_buffer, bits, bitsLength, true, false );
|
||||
}
|
||||
else if (colorSpace == B_RGB32 && bitsLength <= 2 * fBufferLength && bytesPerRow == 2 * fBufferBytesPerRow) {
|
||||
|
||||
fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );
|
||||
|
||||
#define RGB32
|
||||
#include "yuv_converter.h"
|
||||
#undef RGB32
|
||||
|
||||
}
|
||||
else if (colorSpace == B_RGB16 && bitsLength <= fBufferLength && bytesPerRow == fBufferBytesPerRow) {
|
||||
fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );
|
||||
|
||||
#define RGB16
|
||||
#include "yuv_converter.h"
|
||||
#undef RGB16
|
||||
|
||||
}
|
||||
else if (colorSpace == B_RGB15 && bitsLength <= fBufferLength && bytesPerRow == fBufferBytesPerRow) {
|
||||
fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );
|
||||
|
||||
#define RGB15
|
||||
#include "yuv_converter.h"
|
||||
#undef RGB15
|
||||
|
||||
}
|
||||
else if (colorSpace == B_GRAY8 && 2 * bitsLength <= fBufferLength && 2 * bytesPerRow == fBufferBytesPerRow) {
|
||||
fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );
|
||||
|
||||
static const unsigned short mask[] = {
|
||||
0x00ff, 0x00ff, 0x00ff, 0x00ff };
|
||||
|
||||
asm volatile(
|
||||
"1:\n"
|
||||
"movq 0x00(%0),%%mm0\n" // mm0 = Cr2' Y3 Cb2' Y2 Cr0' Y1 Cb0' Y0
|
||||
"movq 0x08(%0),%%mm1\n" // mm1 = Cr6' Y7 Cb6' Y6 Cr4' Y5 Cb4' Y4
|
||||
"pand %3,%%mm0\n" // mm0 = 00 Y3 00 Y2 00 Y1 00 Y0
|
||||
"pand %3,%%mm1\n" // mm1 = 00 Y7 00 Y6 00 Y5 00 Y4
|
||||
"packuswb %%mm1,%%mm0\n" // mm0 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
|
||||
"movq %%mm0,(%1)\n" // destination[0] = mm0
|
||||
"addl $0x10,%0\n" // source += 16
|
||||
"addl $0x08,%1\n" // destination += 8
|
||||
"subl $0x08,%2\n"
|
||||
"jg 1b\n"
|
||||
"emms\n"
|
||||
:
|
||||
: "r" (convert_buffer), "r" (bits), "r" (bitsLength), "m" (mask));
|
||||
}
|
||||
else if( colorSpace == B_NO_COLOR_SPACE ) {
|
||||
// special case: only wait for image but don't copy it
|
||||
;
|
||||
}
|
||||
else {
|
||||
PRINT(("CVideoIn::Capture() - Bad buffer format\n"));
|
||||
}
|
||||
|
||||
counter = *sequence - fBufferSequence;
|
||||
fBufferSequence = *sequence;
|
||||
return counter;
|
||||
}
|
||||
|
||||
void CVideoIn::Trace(const char * message) const
|
||||
{
|
||||
PRINT(("\x1b[0;30;34m%s\x1b[0;30;47m\n", message));
|
||||
}
|
||||
|
||||
int32 CVideoIn::getFrameRate( video_in_standard standard )
|
||||
{
|
||||
// TODO: I'm not really sure about these values
|
||||
static const int32 frame_rate[] = {
|
||||
29976, 29976, 29976, 25000, 25000, 25000, 29976, 25000, 25000, 29976
|
||||
};
|
||||
|
||||
return frame_rate[standard];
|
||||
}
|
||||
|
||||
void CVideoIn::getActiveRange( video_in_standard standard, CRadeonRect &rect )
|
||||
{
|
||||
// in theory, we would ask fTheatre;
|
||||
// in practice, values retrieved from there don't work;
|
||||
// e.g. for PAL, according to Theatre, VBI height is 38, but you must set up the
|
||||
// clipping unit to height 24! I have no clue what goes wrong there
|
||||
rect.SetTo(
|
||||
kTiming[standard].active.left,
|
||||
kTiming[standard].active.top,
|
||||
kTiming[standard].active.left + kTiming[standard].active.width - 1,
|
||||
kTiming[standard].active.top + kTiming[standard].active.height - 1 );
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: VideoIn.h
|
||||
/
|
||||
/ Description: High-Level ATI Radeon Video Capture Interface.
|
||||
/
|
||||
/ Copyright 2001, Carlos Hasan
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __VIDEO_IN_H__
|
||||
#define __VIDEO_IN_H__
|
||||
|
||||
#include "Radeon.h"
|
||||
#include "Capture.h"
|
||||
//#include "Overlay.h"
|
||||
#include "I2CPort.h"
|
||||
#include "VIPPort.h"
|
||||
#include "Tuner.h"
|
||||
#include "MSP3430.h"
|
||||
#include "Theater.h"
|
||||
|
||||
enum video_in_source {
|
||||
C_VIDEO_IN_TUNER,
|
||||
C_VIDEO_IN_COMPOSITE,
|
||||
C_VIDEO_IN_SVIDEO,
|
||||
};
|
||||
|
||||
enum { C_VIDEO_IN_SOURCE_MAX = 2 };
|
||||
|
||||
enum video_in_standard {
|
||||
C_VIDEO_IN_NTSC,
|
||||
C_VIDEO_IN_NTSC_JAPAN,
|
||||
C_VIDEO_IN_NTSC_443,
|
||||
C_VIDEO_IN_PAL_M,
|
||||
C_VIDEO_IN_PAL_BDGHI,
|
||||
C_VIDEO_IN_PAL_N,
|
||||
C_VIDEO_IN_PAL_60,
|
||||
C_VIDEO_IN_PAL_NC,
|
||||
C_VIDEO_IN_SECAM,
|
||||
C_VIDEO_IN_NTSC_RAW
|
||||
};
|
||||
|
||||
enum { C_VIDEO_IN_STANDARD_MAX = 8 };
|
||||
|
||||
enum video_in_capture_mode {
|
||||
C_VIDEO_IN_FIELD,
|
||||
C_VIDEO_IN_BOB,
|
||||
C_VIDEO_IN_WEAVE
|
||||
};
|
||||
|
||||
enum { C_VIDEO_IN_CAPTURE_MODE_MAX = 2 };
|
||||
|
||||
enum video_in_resolution {
|
||||
C_VIDEO_IN_NTSC_SQ_WIDTH = 640,
|
||||
C_VIDEO_IN_NTSC_SQ_HEIGHT = 480,
|
||||
|
||||
C_VIDEO_IN_NTSC_CCIR_WIDTH = 720,
|
||||
C_VIDEO_IN_NTSC_CCIR_HEIGHT = 480,
|
||||
|
||||
C_VIDEO_IN_PAL_SQ_WIDTH = 768,
|
||||
C_VIDEO_IN_PAL_SQ_HEIGHT = 576,
|
||||
|
||||
C_VIDEO_IN_PAL_CCIR_WIDTH = 720,
|
||||
C_VIDEO_IN_PAL_CCIR_HEIGHT = 576
|
||||
};
|
||||
|
||||
/*enum video_in_frame_rate {
|
||||
C_VIDEO_IN_NTSC_FRAME_RATE = 29976,
|
||||
C_VIDEO_IN_PAL_FRAME_RATE = 25000
|
||||
};*/
|
||||
|
||||
enum video_in_capabilities {
|
||||
C_VIDEO_IN_HAS_SOUND = 1 << 0,
|
||||
C_VIDEO_IN_HAS_TUNER = 1 << 1,
|
||||
C_VIDEO_IN_HAS_COMPOSITE = 1 << 2,
|
||||
C_VIDEO_IN_HAS_SVIDEO = 1 << 3
|
||||
};
|
||||
|
||||
class CVideoIn {
|
||||
public:
|
||||
CVideoIn( const char *dev_name );
|
||||
|
||||
~CVideoIn();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
int Capabilities() const;
|
||||
|
||||
public:
|
||||
void Start(video_in_source source, video_in_standard standard,
|
||||
video_in_capture_mode mode, int width, int height);
|
||||
|
||||
void Stop();
|
||||
|
||||
int Capture(color_space colorSpace, void * bits, int bitsLength,
|
||||
int bytesPerRow, int * sequence, short * number, bigtime_t * when);
|
||||
|
||||
public:
|
||||
void SetBrightness(int brightness);
|
||||
|
||||
void SetContrast(int contrast);
|
||||
|
||||
void SetSaturation(int saturation);
|
||||
|
||||
void SetHue(int hue);
|
||||
|
||||
void SetSharpness(int sharpness);
|
||||
|
||||
void SetFrequency(float frequency, float picture);
|
||||
|
||||
float FrequencyForChannel(int channel, video_in_standard standard);
|
||||
|
||||
bool SetChannel(int channel, video_in_standard standard);
|
||||
|
||||
int32 getFrameRate( video_in_standard standard );
|
||||
|
||||
void getActiveRange( video_in_standard standard, CRadeonRect &rect );
|
||||
|
||||
private:
|
||||
void FreeBuffers();
|
||||
|
||||
void Trace(const char * message) const;
|
||||
|
||||
private:
|
||||
CRadeon fRadeon;
|
||||
CCapture fCapture;
|
||||
CI2CPort fI2CPort;
|
||||
CTheater fTheater;
|
||||
CTuner fTuner;
|
||||
CMSP3430 fSound;
|
||||
int32 fBuffer0;
|
||||
int32 fBuffer1;
|
||||
int32 fBuffer0Handle;
|
||||
int32 fBuffer1Handle;
|
||||
void *convert_buffer;
|
||||
int fBufferLength;
|
||||
int fBufferBytesPerRow;
|
||||
int fBufferSequence;
|
||||
bigtime_t fBufferPeriod;
|
||||
bool started;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Copyright (c) 2004, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon In add-on
|
||||
|
||||
YUV converter
|
||||
|
||||
The Rage Theatre always provides YUV422 data and starting with Radeon, ATI
|
||||
moved colour converter from 2D to 3D unit, so if you need another format you
|
||||
must convert it manually, unless you get 3D working (which is, starting with r300,
|
||||
hopeless anyway as there is no spec).
|
||||
|
||||
Colour temperature is according to BT.601; for YCbCr format see also GraphicsDefs.h
|
||||
|
||||
This header is included from VideoIn.cpp, with various defines to convert to
|
||||
the wished format (RGB15, RGB16 or RGB32).
|
||||
|
||||
Things to improve:
|
||||
- colour components should be interpolated for odd pixels
|
||||
*/
|
||||
|
||||
static const int8 c_offs[8] =
|
||||
{ 128, 128, 128, 128, 128, 128, 128, 128 };
|
||||
|
||||
static const int16 y_offs[4] =
|
||||
{ 16*128, 16*128, 16*128, 16*128 };
|
||||
|
||||
static const uint16 masks[2][4] = {
|
||||
// high byte mask
|
||||
{ 0xff00, 0xff00, 0xff00, 0xff00 },
|
||||
// low byte mask
|
||||
{ 0x00ff, 0x00ff, 0x00ff, 0x00ff },
|
||||
};
|
||||
|
||||
static const int16 scale[5][4] = {
|
||||
// Y pre-scale
|
||||
{ (int16)(1.1678 * 512), (int16)(1.1678 * 512), (int16)(1.1678 * 512), (int16)(1.1678 * 512) },
|
||||
// CbG CrG CbG CrG
|
||||
{ (int16)(-0.3929 * 256), (int16)(-0.8154 * 256), (int16)(-0.3929 * 256), (int16)(-0.8154 * 256) },
|
||||
// CbB CrR CbB CrR
|
||||
{ (int16)(2.0232 * 256), (int16)(1.6007 * 256), (int16)(2.0232 * 256), (int16)(1.6007 * 256) },
|
||||
};
|
||||
|
||||
static const int8 masks_8bit[2][8] = {
|
||||
// r/b 16 bit mask and r/g/b 15 bit mask
|
||||
{ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8 },
|
||||
// g 16 bit mask
|
||||
{ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc },
|
||||
};
|
||||
|
||||
asm volatile(
|
||||
"2:\n"
|
||||
"pxor %%mm7,%%mm7\n"
|
||||
|
||||
"1:\n"
|
||||
"movq (%0),%%mm0\n" // mm0 = Cr2'Y3' Cb2'Y2' Cr0'Y1' Cb0'Y0'
|
||||
"movq %%mm0,%%mm1\n" // mm1 = Cr2'Y3' Cb2'Y2' Cr0'Y1' Cb0'Y0'
|
||||
|
||||
// Y is in 16..235
|
||||
// we need to substract 16 and scale to full range
|
||||
// as standard MMX has a _signed_ integer multiply only, the highest bit must
|
||||
// be zero before scaling, i.e. we use signed format 9.7
|
||||
"pand 8+%4,%%mm0\n" // mm2 = Y3' Y2' Y1' Y0'
|
||||
"psllw $7,%%mm0\n"
|
||||
"psubusw %3,%%mm0\n"
|
||||
"pmulhw %5,%%mm0\n" // mm0 = Y3 Y2 Y1 Y0
|
||||
|
||||
// Cb and Cr is biased; compensate that
|
||||
"psubb %2,%%mm1\n" // mm1 = Cr2 xxx Cb2 xxx Cr0 xxx Cb0 xxx
|
||||
"pand %4,%%mm1\n" // mm1 = Cr2 Cb2 Cr0 Cb0
|
||||
|
||||
// transform Cb and Cr to green component
|
||||
"movq %%mm1,%%mm2\n"
|
||||
"pmaddwd 8+%5,%%mm1\n" // mm1 = CbCrG2 xxxxxxx CbCrG0 xxxxxxx
|
||||
"psrad $16,%%mm1\n" // mm1 = CbCrG2 CbCrG0
|
||||
"packssdw %%mm1,%%mm1\n" // mm1 = CbCrG2 CbCrG0 CbCrG2 CbCrG0
|
||||
"punpcklwd %%mm1,%%mm1\n" // mm1 = CbCrG2 CbCrG2 CbCrG0 CbCrG0
|
||||
|
||||
// transform Cb to blue and Cr to red component
|
||||
"pmulhw 16+%5,%%mm2\n" // mm2 = CrR2 CbB2 CrR0 CbB0
|
||||
|
||||
// nasty shuffling to separate and duplicate components
|
||||
"movq %%mm2,%%mm3\n"
|
||||
"punpcklwd %%mm3,%%mm3\n" // mm3 = CrR0 CrR0 CbB0 CbB0
|
||||
"punpckhwd %%mm2,%%mm2\n" // mm2 = CrR2 CrR2 CbB2 CbB2
|
||||
|
||||
"movq %%mm3,%%mm4\n"
|
||||
"punpckldq %%mm2,%%mm3\n" // mm3 = CbB2 CbB2 CbB0 CbB0
|
||||
"punpckhdq %%mm2,%%mm4\n" // mm4 = CrR2 CrR2 CrR0 CrR0
|
||||
|
||||
// add Y to get final RGB
|
||||
"paddsw %%mm0,%%mm1\n" // mm1 = G3 G2 G1 G0
|
||||
"paddsw %%mm0,%%mm3\n" // mm3 = B3 B2 B1 B0
|
||||
"paddsw %%mm0,%%mm4\n" // mm4 = R3 R2 R1 R0
|
||||
|
||||
// now, RBG can be converted to 8 bits each
|
||||
"packuswb %%mm0,%%mm1\n" // mm1 = Y3 Y2 Y1 Y0 G3 G2 G1 G0
|
||||
"packuswb %%mm4,%%mm3\n" // mm3 = R3 R2 R1 R0 B3 B2 B1 B0
|
||||
|
||||
#ifdef RGB32
|
||||
// convertion to RGB32
|
||||
"movq %%mm3,%%mm2\n"
|
||||
"punpckhbw %%mm1,%%mm3\n" // mm3 = Y3 R3 Y2 R2 Y1 R1 Y0 R0
|
||||
"punpcklbw %%mm1,%%mm2\n" // mm2 = G3 B3 G2 B2 G1 B1 G0 B0
|
||||
|
||||
"movq %%mm2,%%mm1\n"
|
||||
"punpcklwd %%mm3,%%mm2\n"
|
||||
"movq %%mm2,0x00(%1)\n" // dst = Y1 R1 G1 B1 Y0 R0 G0 B0
|
||||
|
||||
"punpckhwd %%mm3,%%mm1\n"
|
||||
"movq %%mm1,0x08(%1)\n" // dst = Y3 R3 G3 B3 Y2 R2 G2 B2
|
||||
|
||||
"addl $0x08,%0\n" // source += 8
|
||||
"addl $0x10,%1\n" // destination += 16
|
||||
"subl $0x10,%7\n" // next pixels
|
||||
#endif
|
||||
|
||||
#ifdef RGB16
|
||||
// convertion to RGB16
|
||||
// things would be much easier if Intel had added a RGB32->RGB16 instruction
|
||||
"pand %6,%%mm3\n" // mm3 - R3 R2 R1 R0 B3 B2 B1 B0 (masked)
|
||||
"pand 8+%6,%%mm1\n" // mm1 - Y3 Y2 Y1 Y0 G3 G2 G1 G0 (masked)
|
||||
|
||||
"punpcklbw %%mm7,%%mm1\n" // mm1 - G3 G2 G1 G0
|
||||
"movq %%mm7,%%mm2\n"
|
||||
"punpckhbw %%mm3,%%mm2\n" // mm2 - R3 R2 R1 R0
|
||||
"punpcklbw %%mm7,%%mm3\n" // mm3 - B3 B2 B1 B0
|
||||
|
||||
"psllw $3,%%mm1\n" // mm1 - G3 G2 G1 G0
|
||||
"psrlw $3,%%mm3\n" // mm3 - B3 B2 B1 B0
|
||||
|
||||
"por %%mm2,%%mm1\n"
|
||||
"por %%mm3,%%mm1\n"
|
||||
"movq %%mm1,(%1)\n"
|
||||
|
||||
"addl $0x08,%0\n" // source += 8
|
||||
"addl $0x08,%1\n" // destination += 8
|
||||
"subl $0x08,%7\n" // next pixels
|
||||
#endif
|
||||
|
||||
#ifdef RGB15
|
||||
// convertion to RGB15
|
||||
// same problem as before
|
||||
"pand %6,%%mm3\n" // mm3 - R3 R2 R1 R0 B3 B2 B1 B0 (masked)
|
||||
"pand %6,%%mm1\n" // mm1 - Y3 Y2 Y1 Y0 G3 G2 G1 G0 (masked)
|
||||
|
||||
"punpcklbw %%mm7,%%mm1\n" // mm1 - G3 G2 G1 G0
|
||||
"movq %%mm7,%%mm2\n"
|
||||
"punpckhbw %%mm3,%%mm2\n" // mm2 - R3 R2 R1 R0
|
||||
"punpcklbw %%mm7,%%mm3\n" // mm3 - B3 B2 B1 B0
|
||||
|
||||
"psllw $2,%%mm1\n" // mm1 - G3 G2 G1 G0
|
||||
"psrlw $1,%%mm2\n" // mm2 - R3 R2 R1 R0
|
||||
"psrlw $3,%%mm3\n" // mm3 - B3 B2 B1 B0
|
||||
|
||||
"por %%mm2,%%mm1\n"
|
||||
"por %%mm3,%%mm1\n"
|
||||
"movq %%mm1,(%1)\n"
|
||||
|
||||
"addl $0x08,%0\n" // source += 8
|
||||
"addl $0x08,%1\n" // destination += 8
|
||||
"subl $0x08,%7\n" // next pixels
|
||||
#endif
|
||||
|
||||
// next
|
||||
"jg 1b\n"
|
||||
|
||||
"movl %9,%7\n"
|
||||
"subl %7,%8\n"
|
||||
|
||||
"jg 2b\n"
|
||||
"emms\n"
|
||||
:
|
||||
: "r" (convert_buffer), "r" (bits), "m" (c_offs), "m" (y_offs),
|
||||
"m" (masks), "m" (scale), "m" (masks_8bit),
|
||||
"r" (bytesPerRow), "m" (bitsLength), "m" (bytesPerRow));
|
||||
Reference in New Issue
Block a user