1 /******************************************************************************
5 / Description: ATI Radeon Capture Unit interface.
7 / Copyright 2001, Carlos Hasan
9 / TK: something about synchronization: I removed all the FIFO wait
10 / functions as they aren't thread-safe and AFAIK not needed as
11 / only 2D/3D register accesses are buffered
13 *******************************************************************************/
18 CCapture::CCapture(CRadeon
& radeon
)
20 fMode(C_RADEON_CAPTURE_FIELD_SINGLE
),
21 fFormat(C_RADEON_CAPTURE_CCIR656
),
32 PRINT(("CCapture::CCapture()\n"));
37 PRINT(("CCapture::~CCapture()\n"));
40 status_t
CCapture::InitCheck() const
42 return fRadeon
.InitCheck();
45 void CCapture::SetBuffer(capture_stream_format format
, capture_buffer_mode mode
,
46 int offset0
, int offset1
, int size
, int pitch
)
48 PRINT(("CCapture::SetBuffer(%s, %s, 0x%08x, 0x%08x, 0x%08x, %d)\n",
49 "BROOKTREE\0CCIR656\0\0\0ZVIDEO\0\0\0\0VIP"+10*format
,
50 "FIELD-SINGLE\0FIELD-DOUBLE\0BOB-SINGLE\0\0\0"
51 "BOB-DOUBLE\0\0\0WEAVE-SINGLE\0WEAVE-DOUBLE"+13*mode
,
52 offset0
, offset1
, size
, pitch
));
56 fOffset0
= offset0
+ fRadeon
.VirtualMemoryBase();
57 fOffset1
= offset1
+ fRadeon
.VirtualMemoryBase();
62 void CCapture::SetClip(int left
, int top
, int right
, int bottom
)
64 PRINT(("CCapture::SetClip(%d, %d, %d, %d)\n",
65 left
, top
, right
, bottom
));
67 fClip
.SetTo(left
, top
, right
, bottom
);
70 void CCapture::SetVBIBuffer(int offset0
, int offset1
, int size
)
72 PRINT(("CCapture::SetVBIBuffer(0x%08x, 0x%08x, %d)\n", offset0
, offset1
, size
));
74 fVBIOffset0
= offset0
+ fRadeon
.VirtualMemoryBase();
75 fVBIOffset1
= offset1
+ fRadeon
.VirtualMemoryBase();
79 void CCapture::SetVBIClip(int left
, int top
, int right
, int bottom
)
81 PRINT(("CCapture::SetVBIClip(%d, %d, %d, %d)\n",
82 left
, top
, right
, bottom
));
84 fVBIClip
.SetTo(left
, top
, right
, bottom
);
87 void CCapture::Start(bool vbi
)
89 PRINT(("CCapture::Start(%d)\n", vbi
));
91 // initially the capture unit is disabled
92 //fRadeon.WaitForFifo(2);
93 SetRegister(C_RADEON_CAP0_TRIG_CNTL
, C_RADEON_CAP0_TRIGGER_W_NO_ACTION
);
95 // select buffer offset and pitch
96 //fRadeon.WaitForFifo(5);
99 case C_RADEON_CAPTURE_FIELD_SINGLE
:
100 /* capture single field, single buffer */
101 SetRegister(C_RADEON_CAP0_BUF0_OFFSET
, fOffset0
);
102 SetRegister(C_RADEON_CAP0_BUF_PITCH
, fPitch
<< 1);
105 case C_RADEON_CAPTURE_FIELD_DOUBLE
:
106 /* capture single field, double buffer */
107 SetRegister(C_RADEON_CAP0_BUF0_OFFSET
, fOffset0
);
108 SetRegister(C_RADEON_CAP0_BUF1_OFFSET
, fOffset1
);
109 SetRegister(C_RADEON_CAP0_BUF_PITCH
, fPitch
<< 1);
112 case C_RADEON_CAPTURE_BOB_SINGLE
:
113 /* capture interlaced frame, single buffer */
114 SetRegister(C_RADEON_CAP0_BUF0_OFFSET
, fOffset0
);
115 SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET
, fOffset0
+ fSize
);
116 SetRegister(C_RADEON_CAP0_BUF_PITCH
, fPitch
<< 1);
119 case C_RADEON_CAPTURE_BOB_DOUBLE
:
120 /* capture interlaced frame, double buffer */
121 SetRegister(C_RADEON_CAP0_BUF0_OFFSET
, fOffset0
);
122 SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET
, fOffset0
+ fSize
);
123 SetRegister(C_RADEON_CAP0_BUF1_OFFSET
, fOffset1
);
124 SetRegister(C_RADEON_CAP0_BUF1_EVEN_OFFSET
, fOffset1
+ fSize
);
125 SetRegister(C_RADEON_CAP0_BUF_PITCH
, fPitch
<< 1);
128 case C_RADEON_CAPTURE_WEAVE_SINGLE
:
129 /* capture deinterlaced frame, single buffer */
130 SetRegister(C_RADEON_CAP0_BUF0_OFFSET
, fOffset0
);
131 SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET
, fOffset0
+ (fPitch
<< 1));
132 SetRegister(C_RADEON_CAP0_BUF_PITCH
, fPitch
<< 2);
135 case C_RADEON_CAPTURE_WEAVE_DOUBLE
:
136 /* capture deinterlaced frame, double buffer */
137 SetRegister(C_RADEON_CAP0_BUF0_OFFSET
, fOffset0
);
138 SetRegister(C_RADEON_CAP0_BUF0_EVEN_OFFSET
, fOffset0
+ (fPitch
<< 1));
139 SetRegister(C_RADEON_CAP0_BUF1_OFFSET
, fOffset1
);
140 SetRegister(C_RADEON_CAP0_BUF1_EVEN_OFFSET
, fOffset1
+ (fPitch
<< 1));
141 SetRegister(C_RADEON_CAP0_BUF_PITCH
, fPitch
<< 2);
145 // select VBI buffer offset
146 //fRadeon.WaitForFifo(4);
148 // FIXME: change according to the buffering mode?
149 SetRegister(C_RADEON_CAP0_VBI0_OFFSET
, fVBIOffset0
);
150 SetRegister(C_RADEON_CAP0_VBI1_OFFSET
, fVBIOffset0
+ fVBISize
);
152 SetRegister(C_RADEON_CAP0_VBI2_OFFSET
, fVBIOffset1
);
153 SetRegister(C_RADEON_CAP0_VBI3_OFFSET
, fVBIOffset1
+ fVBISize
);
155 // select capture clipping window
156 //fRadeon.WaitForFifo(2);
158 SetRegister(C_RADEON_CAP0_H_WINDOW
,
159 ((fClip
.Left() << 1) & C_RADEON_CAP0_H_START
) |
160 ((fClip
.Width() << 17) & C_RADEON_CAP0_H_WIDTH
));
162 SetRegister(C_RADEON_CAP0_V_WINDOW
,
163 ((fClip
.Top() << 0) & C_RADEON_CAP0_V_START
) |
164 ((fClip
.Bottom() << 16) & C_RADEON_CAP0_V_END
));
166 // select VBI clipping window
167 //fRadeon.WaitForFifo(2);
169 SetRegister(C_RADEON_CAP0_VBI_H_WINDOW
,
170 ((fVBIClip
.Left() << 0) & C_RADEON_CAP0_VBI_H_START
) |
171 ((fVBIClip
.Width() << 16) & C_RADEON_CAP0_VBI_H_WIDTH
));
173 SetRegister(C_RADEON_CAP0_VBI_V_WINDOW
,
174 ((fVBIClip
.Top() << 0) & C_RADEON_CAP0_VBI_V_START
) |
175 ((fVBIClip
.Bottom() << 16) & C_RADEON_CAP0_VBI_V_END
));
177 // select buffer type, input mode, video format and buffering mode
178 //fRadeon.WaitForFifo(10);
181 case C_RADEON_CAPTURE_FIELD_SINGLE
:
182 case C_RADEON_CAPTURE_FIELD_DOUBLE
:
183 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_BUF_TYPE
, C_RADEON_CAP0_BUF_TYPE_FIELD
);
184 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_ONESHOT_MODE
, C_RADEON_CAP0_ONESHOT_MODE_FIELD
);
187 case C_RADEON_CAPTURE_BOB_SINGLE
:
188 case C_RADEON_CAPTURE_BOB_DOUBLE
:
189 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_BUF_TYPE
, C_RADEON_CAP0_BUF_TYPE_ALTERNATING
);
190 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_ONESHOT_MODE
, C_RADEON_CAP0_ONESHOT_MODE_FIELD
);
193 case C_RADEON_CAPTURE_WEAVE_SINGLE
:
194 case C_RADEON_CAPTURE_WEAVE_DOUBLE
:
195 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_BUF_TYPE
, C_RADEON_CAP0_BUF_TYPE_FRAME
);
196 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_ONESHOT_MODE
, C_RADEON_CAP0_ONESHOT_MODE_FRAME
);
201 case C_RADEON_CAPTURE_FIELD_SINGLE
:
202 case C_RADEON_CAPTURE_BOB_SINGLE
:
203 case C_RADEON_CAPTURE_WEAVE_SINGLE
:
204 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_BUF_MODE
, C_RADEON_CAP0_BUF_MODE_SINGLE
);
207 case C_RADEON_CAPTURE_FIELD_DOUBLE
:
208 case C_RADEON_CAPTURE_BOB_DOUBLE
:
209 case C_RADEON_CAPTURE_WEAVE_DOUBLE
:
210 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_BUF_MODE
, C_RADEON_CAP0_BUF_MODE_DOUBLE
);
214 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_INPUT_MODE
, C_RADEON_CAP0_INPUT_MODE_CONTINUOUS
);
215 SetRegister(C_RADEON_CAP0_CONFIG
,
216 C_RADEON_CAP0_VIDEO_IN_FORMAT
| C_RADEON_CAP0_VIDEO_SIGNED_UV
, C_RADEON_CAP0_VIDEO_IN_VYUY422
);
219 // select stream format and port mode
220 //fRadeon.WaitForFifo(4);
223 case C_RADEON_CAPTURE_BROOKTREE
:
224 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_STREAM_FORMAT
, C_RADEON_CAP0_STREAM_BROOKTREE
);
225 SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL
, C_RADEON_CAP0_PORT_WIDTH_8_BITS
| C_RADEON_CAP0_PORT_LOWER_BYTE_USED
);
227 case C_RADEON_CAPTURE_CCIR656
:
228 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_STREAM_FORMAT
, C_RADEON_CAP0_STREAM_CCIR656
);
229 SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL
, C_RADEON_CAP0_PORT_WIDTH_8_BITS
| C_RADEON_CAP0_PORT_LOWER_BYTE_USED
);
231 case C_RADEON_CAPTURE_ZOOMVIDEO
:
232 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_STREAM_FORMAT
, C_RADEON_CAP0_STREAM_ZV
);
233 SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL
, C_RADEON_CAP0_PORT_WIDTH_16_BITS
| C_RADEON_CAP0_PORT_LOWER_BYTE_USED
);
235 case C_RADEON_CAPTURE_VIP
:
236 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_STREAM_FORMAT
, C_RADEON_CAP0_STREAM_VIP
);
237 SetRegister(C_RADEON_CAP0_PORT_MODE_CNTL
, C_RADEON_CAP0_PORT_WIDTH_16_BITS
| C_RADEON_CAP0_PORT_LOWER_BYTE_USED
);
241 // set capture mirror mode, field sense, downscaler/decimator, enable 3:4 pull down
242 //fRadeon.WaitForFifo(16);
243 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_MIRROR_EN
, 0);
244 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_ONESHOT_MIRROR_EN
, 0);
245 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_START_FIELD
, C_RADEON_CAP0_START_ODD_FIELD
);
246 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_HORZ_DOWN
, C_RADEON_CAP0_HORZ_DOWN_1X
);
247 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_VERT_DOWN
, C_RADEON_CAP0_VERT_DOWN_1X
);
248 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_VBI_HORZ_DOWN
, C_RADEON_CAP0_VBI_HORZ_DOWN_1X
);
249 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_HDWNS_DEC
, C_RADEON_CAP0_DECIMATOR
);
250 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_SOFT_PULL_DOWN_EN
, C_RADEON_CAP0_SOFT_PULL_DOWN_EN
);
252 // prepare to enable capture
253 //fRadeon.WaitForFifo(14);
255 // disable test and debug modes
256 SetRegister(C_RADEON_TEST_DEBUG_CNTL
, 0);
257 SetRegister(C_RADEON_CAP0_VIDEO_SYNC_TEST
, 0);
258 SetRegister(C_RADEON_CAP0_DEBUG
, C_RADEON_CAP0_V_SYNC
);
260 // connect capture engine to AMC connector
261 SetRegister(C_RADEON_VIDEOMUX_CNTL
, 1, 1);
263 // select capture engine clock source to PCLK
264 SetRegister(C_RADEON_FCP_CNTL
, C_RADEON_FCP0_SRC_PCLK
);
266 // enable capture unit
267 SetRegister(C_RADEON_CAP0_TRIG_CNTL
,
268 C_RADEON_CAP0_TRIGGER_W_CAPTURE
| C_RADEON_CAP0_EN
);
270 // enable VBI capture
271 SetRegister(C_RADEON_CAP0_CONFIG
, C_RADEON_CAP0_VBI_EN
,
272 (vbi
? C_RADEON_CAP0_VBI_EN
: 0));
275 void CCapture::Stop()
277 PRINT(("CCapture::Stop()\n"));
279 // disable capture unit
280 //fRadeon.WaitForFifo(4);
282 // disable capture unit
283 SetRegister(C_RADEON_CAP0_TRIG_CNTL
, C_RADEON_CAP0_TRIGGER_W_NO_ACTION
);
285 // disable the capture engine clock (set to ground)
286 fRadeon
.SetRegister(C_RADEON_FCP_CNTL
, C_RADEON_FCP0_SRC_GND
);
289 void CCapture::SetInterrupts(bool enable
)
291 PRINT(("CCapture::SetInterrupts(%d)\n", enable
));
293 fRadeon
.SetRegister(C_RADEON_CAP_INT_CNTL
,
294 C_RADEON_CAP0_BUF0_INT_EN
| C_RADEON_CAP0_BUF0_EVEN_INT_EN
|
295 C_RADEON_CAP0_BUF1_INT_EN
| C_RADEON_CAP0_BUF1_EVEN_INT_EN
|
296 C_RADEON_CAP0_VBI0_INT_EN
| C_RADEON_CAP0_VBI1_INT_EN
,
297 (enable
? C_RADEON_CAP0_BUF0_INT_EN
| C_RADEON_CAP0_BUF0_EVEN_INT_EN
|
298 C_RADEON_CAP0_BUF1_INT_EN
| C_RADEON_CAP0_BUF1_EVEN_INT_EN
|
299 C_RADEON_CAP0_VBI0_INT_EN
| C_RADEON_CAP0_VBI1_INT_EN
: 0));
301 // clear any stick interrupt
302 fRadeon
.SetRegister(C_RADEON_CAP_INT_STATUS
,
303 C_RADEON_CAP0_BUF0_INT_AK
| C_RADEON_CAP0_BUF0_EVEN_INT_AK
|
304 C_RADEON_CAP0_BUF1_INT_AK
| C_RADEON_CAP0_BUF1_EVEN_INT_AK
|
305 C_RADEON_CAP0_VBI0_INT_AK
| C_RADEON_CAP0_VBI1_INT_AK
);
308 int CCapture::WaitInterrupts(int * sequence
, bigtime_t
* when
, bigtime_t timeout
)
312 if (fRadeon
.WaitInterrupt(&mask
, sequence
, when
, timeout
) == B_OK
) {
314 int mask = fRadeon.Register(C_RADEON_CAP_INT_STATUS);
316 fRadeon.SetRegister(C_RADEON_CAP_INT_STATUS,
317 C_RADEON_CAP0_BUF0_INT_AK | C_RADEON_CAP0_BUF0_EVEN_INT_AK |
318 C_RADEON_CAP0_BUF1_INT_AK | C_RADEON_CAP0_BUF1_EVEN_INT_AK |
319 C_RADEON_CAP0_VBI0_INT_AK | C_RADEON_CAP0_VBI1_INT_AK);
323 ((mask
& C_RADEON_CAP0_BUF0_INT
) != 0 ? C_RADEON_CAPTURE_BUF0_INT
: 0) |
324 ((mask
& C_RADEON_CAP0_BUF1_INT
) != 0 ? C_RADEON_CAPTURE_BUF1_INT
: 0) |
325 ((mask
& C_RADEON_CAP0_BUF0_EVEN_INT
) != 0 ? C_RADEON_CAPTURE_BUF0_EVEN_INT
: 0) |
326 ((mask
& C_RADEON_CAP0_BUF1_EVEN_INT
) != 0 ? C_RADEON_CAPTURE_BUF1_EVEN_INT
: 0) |
327 ((mask
& C_RADEON_CAP0_VBI0_INT
) != 0 ? C_RADEON_CAPTURE_VBI0_INT
: 0) |
328 ((mask
& C_RADEON_CAP0_VBI1_INT
) != 0 ? C_RADEON_CAPTURE_VBI1_INT
: 0);
333 int CCapture::Register(radeon_register index
, int mask
)
335 return fRadeon
.Register(index
, mask
);
338 void CCapture::SetRegister(radeon_register index
, int value
)
340 fRadeon
.SetRegister(index
, value
);
343 void CCapture::SetRegister(radeon_register index
, int mask
, int value
)
345 fRadeon
.SetRegister(index
, mask
, value
);