xref: /haiku/src/add-ons/kernel/drivers/dvb/cx23882/cx23882.c (revision 083a11a3f4b17abb0e5c8d97bb9886af54626abf)
1*083a11a3SMarcus Overhagen /*
2*083a11a3SMarcus Overhagen  * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
3*083a11a3SMarcus Overhagen  *
4*083a11a3SMarcus Overhagen  * Permission is hereby granted, free of charge, to any person
5*083a11a3SMarcus Overhagen  * obtaining a copy of this software and associated documentation
6*083a11a3SMarcus Overhagen  * files (the "Software"), to deal in the Software without restriction,
7*083a11a3SMarcus Overhagen  * including without limitation the rights to use, copy, modify,
8*083a11a3SMarcus Overhagen  * merge, publish, distribute, sublicense, and/or sell copies of
9*083a11a3SMarcus Overhagen  * the Software, and to permit persons to whom the Software is
10*083a11a3SMarcus Overhagen  * furnished to do so, subject to the following conditions:
11*083a11a3SMarcus Overhagen  *
12*083a11a3SMarcus Overhagen  * The above copyright notice and this permission notice shall be
13*083a11a3SMarcus Overhagen  * included in all copies or substantial portions of the Software.
14*083a11a3SMarcus Overhagen  *
15*083a11a3SMarcus Overhagen  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*083a11a3SMarcus Overhagen  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17*083a11a3SMarcus Overhagen  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*083a11a3SMarcus Overhagen  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19*083a11a3SMarcus Overhagen  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20*083a11a3SMarcus Overhagen  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*083a11a3SMarcus Overhagen  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*083a11a3SMarcus Overhagen  * OTHER DEALINGS IN THE SOFTWARE.
23*083a11a3SMarcus Overhagen  */
24*083a11a3SMarcus Overhagen 
25*083a11a3SMarcus Overhagen #include "cx23882.h"
26*083a11a3SMarcus Overhagen #include "util.h"
27*083a11a3SMarcus Overhagen #include <KernelExport.h>
28*083a11a3SMarcus Overhagen #include <ByteOrder.h>
29*083a11a3SMarcus Overhagen #include <Drivers.h>
30*083a11a3SMarcus Overhagen 
31*083a11a3SMarcus Overhagen 
32*083a11a3SMarcus Overhagen #define TRACE_CX23882
33*083a11a3SMarcus Overhagen #ifdef TRACE_CX23882
34*083a11a3SMarcus Overhagen   #define TRACE dprintf
35*083a11a3SMarcus Overhagen #else
36*083a11a3SMarcus Overhagen   #define TRACE(a...)
37*083a11a3SMarcus Overhagen #endif
38*083a11a3SMarcus Overhagen 
39*083a11a3SMarcus Overhagen // settings for hardware stream sync
40*083a11a3SMarcus Overhagen #define MPEG2_SYNC_BYTE		0x47
41*083a11a3SMarcus Overhagen #define MPEG2_PACKET_SIZE	188
42*083a11a3SMarcus Overhagen #define SYNC_PACKET_COUNT	7		// 0 and 5 don't seem to work
43*083a11a3SMarcus Overhagen 
44*083a11a3SMarcus Overhagen // Line size is also used as FIFO size!
45*083a11a3SMarcus Overhagen // BYTES_PER_LINE must be a multiple of 8 and <= 4096 bytes
46*083a11a3SMarcus Overhagen #define PACKETS_PER_LINE	20
47*083a11a3SMarcus Overhagen #define BYTES_PER_LINE		(PACKETS_PER_LINE * MPEG2_PACKET_SIZE)
48*083a11a3SMarcus Overhagen 
49*083a11a3SMarcus Overhagen #define SRAM_START_ADDRESS	0x180000
50*083a11a3SMarcus Overhagen #define SRAM_BASE_CMDS_TS	0x200
51*083a11a3SMarcus Overhagen #define SRAM_BASE_RISC_PROG	0x400
52*083a11a3SMarcus Overhagen #define SRAM_BASE_RISC_QUEUE 0x800
53*083a11a3SMarcus Overhagen #define SRAM_BASE_CDT		0x900
54*083a11a3SMarcus Overhagen #define SRAM_BASE_FIFO_0	0x1000
55*083a11a3SMarcus Overhagen #define SRAM_BASE_FIFO_1	0x2000
56*083a11a3SMarcus Overhagen 
57*083a11a3SMarcus Overhagen // About 64 kByte DMA buffer size
58*083a11a3SMarcus Overhagen #define LINES_PER_BUFFER	16
59*083a11a3SMarcus Overhagen #define DMA_BUFFER_SIZE		(LINES_PER_BUFFER * BYTES_PER_LINE)
60*083a11a3SMarcus Overhagen 
61*083a11a3SMarcus Overhagen 
62*083a11a3SMarcus Overhagen static status_t	cx23882_buffers_alloc(cx23882_device *device);
63*083a11a3SMarcus Overhagen static void		cx23882_buffers_free(cx23882_device *device);
64*083a11a3SMarcus Overhagen static void		cx23882_risc_ram_setup(cx23882_device *device);
65*083a11a3SMarcus Overhagen static void		cx23882_sram_setup(cx23882_device *device);
66*083a11a3SMarcus Overhagen static void		cx23882_via_sis_fixup(cx23882_device *device);
67*083a11a3SMarcus Overhagen 
68*083a11a3SMarcus Overhagen 
69*083a11a3SMarcus Overhagen void
70*083a11a3SMarcus Overhagen cx23882_reset(cx23882_device *device)
71*083a11a3SMarcus Overhagen {
72*083a11a3SMarcus Overhagen 	// software reset (XXX Test)
73*083a11a3SMarcus Overhagen 	reg_write32(0x38c06c, 1);
74*083a11a3SMarcus Overhagen 	snooze(200000);
75*083a11a3SMarcus Overhagen 
76*083a11a3SMarcus Overhagen 	// disable RISC controller
77*083a11a3SMarcus Overhagen 	reg_write32(REG_DEV_CNTRL2, 0);
78*083a11a3SMarcus Overhagen 
79*083a11a3SMarcus Overhagen 	// disable TS interface DMA
80*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_DMA_CNTRL, 0x0);
81*083a11a3SMarcus Overhagen 
82*083a11a3SMarcus Overhagen 	// disable VIP interface up- & downstram DMA
83*083a11a3SMarcus Overhagen 	reg_write32(REG_VIP_STREAM_EN, 0x0);
84*083a11a3SMarcus Overhagen 
85*083a11a3SMarcus Overhagen 	// disable host interface up- & downstram DMA
86*083a11a3SMarcus Overhagen 	reg_write32(REG_HST_STREAM_EN, 0x0);
87*083a11a3SMarcus Overhagen 
88*083a11a3SMarcus Overhagen 	// stop all interrupts
89*083a11a3SMarcus Overhagen 	reg_write32(REG_PCI_INT_MSK, 0x0);
90*083a11a3SMarcus Overhagen 	reg_write32(REG_VID_INT_MSK, 0x0);
91*083a11a3SMarcus Overhagen 	reg_write32(REG_AUD_INT_MSK, 0x0);
92*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_INT_MSK,  0x0);
93*083a11a3SMarcus Overhagen 	reg_write32(REG_VIP_INT_MSK, 0x0);
94*083a11a3SMarcus Overhagen 	reg_write32(REG_HST_INT_MSK, 0x0);
95*083a11a3SMarcus Overhagen 	reg_write32(REG_DMA_RISC_INT_MSK, 0x0);
96*083a11a3SMarcus Overhagen 
97*083a11a3SMarcus Overhagen 	// clear all pending interrupts
98*083a11a3SMarcus Overhagen 	reg_write32(REG_PCI_INT_STAT, 0xffffffff);
99*083a11a3SMarcus Overhagen 	reg_write32(REG_VID_INT_STAT, 0xffffffff);
100*083a11a3SMarcus Overhagen 	reg_write32(REG_AUD_INT_STAT, 0xffffffff);
101*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_INT_STAT,  0xffffffff);
102*083a11a3SMarcus Overhagen 	reg_write32(REG_VIP_INT_STAT, 0xffffffff);
103*083a11a3SMarcus Overhagen 	reg_write32(REG_HST_INT_STAT, 0xffffffff);
104*083a11a3SMarcus Overhagen 	reg_write32(REG_DMA_RISC_INT_MSK, 0xffffffff);
105*083a11a3SMarcus Overhagen }
106*083a11a3SMarcus Overhagen 
107*083a11a3SMarcus Overhagen 
108*083a11a3SMarcus Overhagen status_t
109*083a11a3SMarcus Overhagen cx23882_init(cx23882_device *device)
110*083a11a3SMarcus Overhagen {
111*083a11a3SMarcus Overhagen 	// assumes that cx23882_reset() has already been called
112*083a11a3SMarcus Overhagen 
113*083a11a3SMarcus Overhagen 	status_t err;
114*083a11a3SMarcus Overhagen 
115*083a11a3SMarcus Overhagen 	if ((err = cx23882_buffers_alloc(device)) < B_OK) {
116*083a11a3SMarcus Overhagen 		dprintf("cx23882: Error, buffer alloc failed\n");
117*083a11a3SMarcus Overhagen 		return err;
118*083a11a3SMarcus Overhagen 	}
119*083a11a3SMarcus Overhagen 
120*083a11a3SMarcus Overhagen 	device->capture_size = DMA_BUFFER_SIZE;
121*083a11a3SMarcus Overhagen 
122*083a11a3SMarcus Overhagen 	cx23882_via_sis_fixup(device);
123*083a11a3SMarcus Overhagen 
124*083a11a3SMarcus Overhagen 	// Set FIFO thresholds, should be 0 < x <= 7
125*083a11a3SMarcus Overhagen 	reg_write32(REG_PDMA_STHRSH, PDMA_ISBTHRSH_6 | PDMA_PCITHRSH_6);
126*083a11a3SMarcus Overhagen 	reg_write32(REG_PDMA_DTHRSH, PDMA_ISBTHRSH_6 | PDMA_PCITHRSH_6);
127*083a11a3SMarcus Overhagen 
128*083a11a3SMarcus Overhagen 	// init risc programm
129*083a11a3SMarcus Overhagen 	cx23882_risc_ram_setup(device);
130*083a11a3SMarcus Overhagen 
131*083a11a3SMarcus Overhagen 	// init sram
132*083a11a3SMarcus Overhagen 	cx23882_sram_setup(device);
133*083a11a3SMarcus Overhagen 
134*083a11a3SMarcus Overhagen 	// Reset counter to 0
135*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_GP_CNT_CNTRL, 0x3);
136*083a11a3SMarcus Overhagen 
137*083a11a3SMarcus Overhagen 	// Line length for RISC DMA
138*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_LNGTH, BYTES_PER_LINE);
139*083a11a3SMarcus Overhagen 
140*083a11a3SMarcus Overhagen 	// Set serial interface mode
141*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_GEN_CONTROL, reg_read32(REG_TS_GEN_CONTROL) | TS_GEN_CONTROL_IPB_SMODE);
142*083a11a3SMarcus Overhagen 
143*083a11a3SMarcus Overhagen 	// Setup hardware MPEG2 fec interface
144*083a11a3SMarcus Overhagen 	reg_write32(REG_HW_SOP_CONTROL, (MPEG2_SYNC_BYTE << 16) | (MPEG2_PACKET_SIZE << 4) | SYNC_PACKET_COUNT);
145*083a11a3SMarcus Overhagen 
146*083a11a3SMarcus Overhagen 	// Setup TSSTOP status, active low, rising and falling edge, single bit width
147*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_SOP_STATUS, reg_read32(REG_TS_SOP_STATUS) |  0x18000);
148*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_SOP_STATUS, reg_read32(REG_TS_SOP_STATUS) & ~0x06000);
149*083a11a3SMarcus Overhagen 
150*083a11a3SMarcus Overhagen 	// Enable interrupts for MPEG TS and all errors
151*083a11a3SMarcus Overhagen 	reg_write32(REG_PCI_INT_MSK, reg_read32(REG_PCI_INT_MSK) | PCI_INT_STAT_TS_INT | 0x00fc00);
152*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_INT_MSK, reg_read32(REG_TS_INT_MSK) | TS_INT_STAT_TS_RISC1 | TS_INT_STAT_TS_RISC2 | 0x1f1100);
153*083a11a3SMarcus Overhagen 
154*083a11a3SMarcus Overhagen 	TRACE("cx23882_init done\n");
155*083a11a3SMarcus Overhagen 	return B_OK;
156*083a11a3SMarcus Overhagen }
157*083a11a3SMarcus Overhagen 
158*083a11a3SMarcus Overhagen 
159*083a11a3SMarcus Overhagen status_t
160*083a11a3SMarcus Overhagen cx23882_terminate(cx23882_device *device)
161*083a11a3SMarcus Overhagen {
162*083a11a3SMarcus Overhagen 	cx23882_reset(device);
163*083a11a3SMarcus Overhagen 
164*083a11a3SMarcus Overhagen 	cx23882_buffers_free(device);
165*083a11a3SMarcus Overhagen 	return B_OK;
166*083a11a3SMarcus Overhagen }
167*083a11a3SMarcus Overhagen 
168*083a11a3SMarcus Overhagen 
169*083a11a3SMarcus Overhagen status_t
170*083a11a3SMarcus Overhagen cx23882_start_capture(cx23882_device *device)
171*083a11a3SMarcus Overhagen {
172*083a11a3SMarcus Overhagen 	TRACE("cx23882_start_capture\n");
173*083a11a3SMarcus Overhagen 
174*083a11a3SMarcus Overhagen 	// start RISC processor and DMA
175*083a11a3SMarcus Overhagen 	reg_write32(REG_DEV_CNTRL2, reg_read32(REG_DEV_CNTRL2) | DEV_CNTRL2_RUN_RISC);
176*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_DMA_CNTRL, reg_read32(REG_TS_DMA_CNTRL) | TS_DMA_CNTRL_TS_FIFO_EN | TS_DMA_CNTRL_TS_RISC_EN);
177*083a11a3SMarcus Overhagen 	return B_OK;
178*083a11a3SMarcus Overhagen }
179*083a11a3SMarcus Overhagen 
180*083a11a3SMarcus Overhagen 
181*083a11a3SMarcus Overhagen status_t
182*083a11a3SMarcus Overhagen cx23882_stop_capture(cx23882_device *device)
183*083a11a3SMarcus Overhagen {
184*083a11a3SMarcus Overhagen 	TRACE("cx23882_stop_capture\n");
185*083a11a3SMarcus Overhagen 
186*083a11a3SMarcus Overhagen 	// stop RISC processor and DMA
187*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_DMA_CNTRL, reg_read32(REG_TS_DMA_CNTRL) & ~(TS_DMA_CNTRL_TS_FIFO_EN | TS_DMA_CNTRL_TS_RISC_EN));
188*083a11a3SMarcus Overhagen 	reg_write32(REG_DEV_CNTRL2, reg_read32(REG_DEV_CNTRL2) & ~DEV_CNTRL2_RUN_RISC);
189*083a11a3SMarcus Overhagen 	return B_OK;
190*083a11a3SMarcus Overhagen }
191*083a11a3SMarcus Overhagen 
192*083a11a3SMarcus Overhagen 
193*083a11a3SMarcus Overhagen static inline void
194*083a11a3SMarcus Overhagen cx23882_mpegts_int(cx23882_device *device)
195*083a11a3SMarcus Overhagen {
196*083a11a3SMarcus Overhagen 	uint32 mstat = reg_read32(REG_TS_INT_MSTAT);
197*083a11a3SMarcus Overhagen 	reg_write32(REG_TS_INT_STAT, mstat);
198*083a11a3SMarcus Overhagen 
199*083a11a3SMarcus Overhagen //	dprintf("cx23882_mpegts_int got 0x%08lx\n", mstat);
200*083a11a3SMarcus Overhagen 
201*083a11a3SMarcus Overhagen 	if (mstat & TS_INT_STAT_OPC_ERR) {
202*083a11a3SMarcus Overhagen 		dprintf("cx23882_mpegts_int RISC opcode error\n");
203*083a11a3SMarcus Overhagen 		reg_write32(REG_PCI_INT_MSK, 0);
204*083a11a3SMarcus Overhagen 		return;
205*083a11a3SMarcus Overhagen 	}
206*083a11a3SMarcus Overhagen 
207*083a11a3SMarcus Overhagen 	if ((mstat & (TS_INT_STAT_TS_RISC1 | TS_INT_STAT_TS_RISC2)) == (TS_INT_STAT_TS_RISC1 | TS_INT_STAT_TS_RISC2)) {
208*083a11a3SMarcus Overhagen 		dprintf("cx23882_mpegts_int both buffers ready\n");
209*083a11a3SMarcus Overhagen 		mstat = TS_INT_STAT_TS_RISC1;
210*083a11a3SMarcus Overhagen 	}
211*083a11a3SMarcus Overhagen 
212*083a11a3SMarcus Overhagen 	if (mstat & TS_INT_STAT_TS_RISC1) {
213*083a11a3SMarcus Overhagen 		int32 count;
214*083a11a3SMarcus Overhagen //		dprintf("cx23882_mpegts_int buffer 1 at %Ld\n", system_time());
215*083a11a3SMarcus Overhagen 		device->capture_data = device->dma_buf1_virt;
216*083a11a3SMarcus Overhagen 		device->capture_end_time = system_time();
217*083a11a3SMarcus Overhagen 		get_sem_count(device->capture_sem, &count);
218*083a11a3SMarcus Overhagen 		if (count <= 0)
219*083a11a3SMarcus Overhagen 			release_sem_etc(device->capture_sem, 1, B_DO_NOT_RESCHEDULE);
220*083a11a3SMarcus Overhagen 	}
221*083a11a3SMarcus Overhagen 
222*083a11a3SMarcus Overhagen 	if (mstat & TS_INT_STAT_TS_RISC2) {
223*083a11a3SMarcus Overhagen 		int32 count;
224*083a11a3SMarcus Overhagen //		dprintf("cx23882_mpegts_int buffer 2 at %Ld\n", system_time());
225*083a11a3SMarcus Overhagen 		device->capture_data = device->dma_buf2_virt;
226*083a11a3SMarcus Overhagen 		device->capture_end_time = system_time();
227*083a11a3SMarcus Overhagen 		get_sem_count(device->capture_sem, &count);
228*083a11a3SMarcus Overhagen 		if (count <= 0)
229*083a11a3SMarcus Overhagen 			release_sem_etc(device->capture_sem, 1, B_DO_NOT_RESCHEDULE);
230*083a11a3SMarcus Overhagen 	}
231*083a11a3SMarcus Overhagen }
232*083a11a3SMarcus Overhagen 
233*083a11a3SMarcus Overhagen 
234*083a11a3SMarcus Overhagen int32
235*083a11a3SMarcus Overhagen cx23882_int(void *data)
236*083a11a3SMarcus Overhagen {
237*083a11a3SMarcus Overhagen 	cx23882_device *device = data;
238*083a11a3SMarcus Overhagen 	uint32 mstat;
239*083a11a3SMarcus Overhagen 	uint32 wmstat;
240*083a11a3SMarcus Overhagen 
241*083a11a3SMarcus Overhagen 	mstat = reg_read32(REG_PCI_INT_MSTAT);
242*083a11a3SMarcus Overhagen 	if (!mstat)
243*083a11a3SMarcus Overhagen 		return B_UNHANDLED_INTERRUPT;
244*083a11a3SMarcus Overhagen 
245*083a11a3SMarcus Overhagen 	if (mstat & (PCI_INT_STAT_HST_INT | PCI_INT_STAT_VIP_INT | PCI_INT_STAT_AUD_INT | PCI_INT_STAT_VID_INT)) {
246*083a11a3SMarcus Overhagen 		// serious error, these bits should not be set
247*083a11a3SMarcus Overhagen 		dprintf("cx23882_int error: msk 0x%08lx, stat 0x%08lx, mstat 0x%08lx\n", reg_read32(REG_PCI_INT_MSK), reg_read32(REG_PCI_INT_STAT), mstat);
248*083a11a3SMarcus Overhagen 		reg_write32(REG_PCI_INT_MSK, 0);
249*083a11a3SMarcus Overhagen 		return B_HANDLED_INTERRUPT;
250*083a11a3SMarcus Overhagen 	}
251*083a11a3SMarcus Overhagen 
252*083a11a3SMarcus Overhagen 	wmstat = mstat & ~(PCI_INT_STAT_HST_INT | PCI_INT_STAT_VIP_INT | PCI_INT_STAT_TS_INT | PCI_INT_STAT_AUD_INT | PCI_INT_STAT_VID_INT);
253*083a11a3SMarcus Overhagen 	if (wmstat)
254*083a11a3SMarcus Overhagen 		reg_write32(REG_PCI_INT_STAT, wmstat);
255*083a11a3SMarcus Overhagen 
256*083a11a3SMarcus Overhagen 	if (wmstat)
257*083a11a3SMarcus Overhagen 		dprintf("cx23882_int got 0x%08lx\n", wmstat);
258*083a11a3SMarcus Overhagen 
259*083a11a3SMarcus Overhagen 	if (mstat & PCI_INT_STAT_TS_INT) {
260*083a11a3SMarcus Overhagen 		cx23882_mpegts_int(device);
261*083a11a3SMarcus Overhagen 		return B_INVOKE_SCHEDULER;
262*083a11a3SMarcus Overhagen 	} else {
263*083a11a3SMarcus Overhagen 		return B_HANDLED_INTERRUPT;
264*083a11a3SMarcus Overhagen 	}
265*083a11a3SMarcus Overhagen }
266*083a11a3SMarcus Overhagen 
267*083a11a3SMarcus Overhagen 
268*083a11a3SMarcus Overhagen static status_t
269*083a11a3SMarcus Overhagen cx23882_buffers_alloc(cx23882_device *device)
270*083a11a3SMarcus Overhagen {
271*083a11a3SMarcus Overhagen 	device->dma_buf1_area = alloc_mem(&device->dma_buf1_virt, &device->dma_buf1_phys, DMA_BUFFER_SIZE, B_READ_AREA, "cx23882 dma buf 1");
272*083a11a3SMarcus Overhagen 	device->dma_buf2_area = alloc_mem(&device->dma_buf2_virt, &device->dma_buf2_phys, DMA_BUFFER_SIZE, B_READ_AREA, "cx23882 dma buf 2");
273*083a11a3SMarcus Overhagen 	if (device->dma_buf1_area < B_OK || device->dma_buf2_area < B_OK) {
274*083a11a3SMarcus Overhagen 		cx23882_buffers_free(device);
275*083a11a3SMarcus Overhagen 		return B_NO_MEMORY;
276*083a11a3SMarcus Overhagen 	}
277*083a11a3SMarcus Overhagen 	return B_OK;
278*083a11a3SMarcus Overhagen }
279*083a11a3SMarcus Overhagen 
280*083a11a3SMarcus Overhagen 
281*083a11a3SMarcus Overhagen static void
282*083a11a3SMarcus Overhagen cx23882_buffers_free(cx23882_device *device)
283*083a11a3SMarcus Overhagen {
284*083a11a3SMarcus Overhagen 	if (device->dma_buf1_area >= 0)
285*083a11a3SMarcus Overhagen 		delete_area(device->dma_buf1_area);
286*083a11a3SMarcus Overhagen 	if (device->dma_buf2_area >= 0)
287*083a11a3SMarcus Overhagen 		delete_area(device->dma_buf2_area);
288*083a11a3SMarcus Overhagen 	device->dma_buf1_area = -1;
289*083a11a3SMarcus Overhagen 	device->dma_buf2_area = -1;
290*083a11a3SMarcus Overhagen }
291*083a11a3SMarcus Overhagen 
292*083a11a3SMarcus Overhagen 
293*083a11a3SMarcus Overhagen static void
294*083a11a3SMarcus Overhagen cx23882_sram_setup(cx23882_device *device)
295*083a11a3SMarcus Overhagen {
296*083a11a3SMarcus Overhagen 	dprintf("cx23882_sram_setup enter\n");
297*083a11a3SMarcus Overhagen 
298*083a11a3SMarcus Overhagen 	// setup CDT entries for both FIFOs
299*083a11a3SMarcus Overhagen 	reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CDT, SRAM_START_ADDRESS + SRAM_BASE_FIFO_0);
300*083a11a3SMarcus Overhagen 	reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CDT + 16, SRAM_START_ADDRESS + SRAM_BASE_FIFO_1);
301*083a11a3SMarcus Overhagen 
302*083a11a3SMarcus Overhagen 	// setup CDMS
303*083a11a3SMarcus Overhagen 	reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x00, SRAM_START_ADDRESS + SRAM_BASE_RISC_PROG);
304*083a11a3SMarcus Overhagen 	reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x04, SRAM_START_ADDRESS + SRAM_BASE_CDT);
305*083a11a3SMarcus Overhagen 	reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x08, (2 * 16) / 8); // FIFO count = 2
306*083a11a3SMarcus Overhagen 	reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x0c, SRAM_START_ADDRESS + SRAM_BASE_RISC_QUEUE);
307*083a11a3SMarcus Overhagen 	reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x10, 0x80000000 | (0x100 / 4));
308*083a11a3SMarcus Overhagen 
309*083a11a3SMarcus Overhagen 	// setup DMA registers
310*083a11a3SMarcus Overhagen 	reg_write32(REG_DMA28_PTR1, SRAM_START_ADDRESS + SRAM_BASE_FIFO_0);
311*083a11a3SMarcus Overhagen 	reg_write32(REG_DMA28_PTR2, SRAM_START_ADDRESS + SRAM_BASE_CDT);
312*083a11a3SMarcus Overhagen 	reg_write32(REG_DMA28_CNT1, BYTES_PER_LINE / 8);
313*083a11a3SMarcus Overhagen 	reg_write32(REG_DMA28_CNT2, (2 * 16) / 8); // FIFO count = 2
314*083a11a3SMarcus Overhagen 
315*083a11a3SMarcus Overhagen 	dprintf("cx23882_sram_setup leave\n");
316*083a11a3SMarcus Overhagen }
317*083a11a3SMarcus Overhagen 
318*083a11a3SMarcus Overhagen 
319*083a11a3SMarcus Overhagen static void
320*083a11a3SMarcus Overhagen cx23882_risc_ram_setup(cx23882_device *device)
321*083a11a3SMarcus Overhagen {
322*083a11a3SMarcus Overhagen 	char *start = (char *)(device->regs) + SRAM_START_ADDRESS + SRAM_BASE_RISC_PROG;
323*083a11a3SMarcus Overhagen 	volatile uint32 *rp = (volatile uint32 *)start;
324*083a11a3SMarcus Overhagen 	int i;
325*083a11a3SMarcus Overhagen 
326*083a11a3SMarcus Overhagen 	#define set_opcode(a) (*rp++) = B_HOST_TO_LENDIAN_INT32((a))
327*083a11a3SMarcus Overhagen 
328*083a11a3SMarcus Overhagen 	dprintf("cx23882_risc_ram_setup enter\n");
329*083a11a3SMarcus Overhagen 
330*083a11a3SMarcus Overhagen 	// sync
331*083a11a3SMarcus Overhagen 	set_opcode(RISC_RESYNC | 0);
332*083a11a3SMarcus Overhagen 
333*083a11a3SMarcus Overhagen 	// copy buffer 1
334*083a11a3SMarcus Overhagen 	for (i = 0; i < LINES_PER_BUFFER; i++) {
335*083a11a3SMarcus Overhagen 		set_opcode(RISC_WRITE | RISC_SOL | RISC_EOL | BYTES_PER_LINE);
336*083a11a3SMarcus Overhagen 		set_opcode((unsigned long)device->dma_buf1_phys + i * BYTES_PER_LINE);
337*083a11a3SMarcus Overhagen 	}
338*083a11a3SMarcus Overhagen 
339*083a11a3SMarcus Overhagen 	// execute IRQ 1
340*083a11a3SMarcus Overhagen 	set_opcode(RISC_SKIP | RISC_IRQ1 | RISC_SOL | 0);
341*083a11a3SMarcus Overhagen 
342*083a11a3SMarcus Overhagen 	// copy buffer 2
343*083a11a3SMarcus Overhagen 	for (i = 0; i < LINES_PER_BUFFER; i++) {
344*083a11a3SMarcus Overhagen 		set_opcode(RISC_WRITE | RISC_SOL | RISC_EOL | BYTES_PER_LINE);
345*083a11a3SMarcus Overhagen 		set_opcode((unsigned long)device->dma_buf2_phys + i * BYTES_PER_LINE);
346*083a11a3SMarcus Overhagen 	}
347*083a11a3SMarcus Overhagen 
348*083a11a3SMarcus Overhagen 	// execute IRQ 2
349*083a11a3SMarcus Overhagen 	set_opcode(RISC_SKIP | RISC_IRQ2 | RISC_SOL | 0);
350*083a11a3SMarcus Overhagen 
351*083a11a3SMarcus Overhagen 	// jmp to start, but skip sync instruction
352*083a11a3SMarcus Overhagen 	set_opcode(RISC_JUMP | RISC_SRP);
353*083a11a3SMarcus Overhagen 	set_opcode(SRAM_START_ADDRESS + SRAM_BASE_RISC_PROG + 4);
354*083a11a3SMarcus Overhagen 
355*083a11a3SMarcus Overhagen 	#undef set_opcode
356*083a11a3SMarcus Overhagen 
357*083a11a3SMarcus Overhagen 	dprintf("cx23882_risc_ram_setup leave\n");
358*083a11a3SMarcus Overhagen }
359*083a11a3SMarcus Overhagen 
360*083a11a3SMarcus Overhagen 
361*083a11a3SMarcus Overhagen static void
362*083a11a3SMarcus Overhagen cx23882_via_sis_fixup(cx23882_device *device)
363*083a11a3SMarcus Overhagen {
364*083a11a3SMarcus Overhagen 	uint16 host_vendor;
365*083a11a3SMarcus Overhagen 	uint32 dev_cntrl1;
366*083a11a3SMarcus Overhagen 
367*083a11a3SMarcus Overhagen 	host_vendor = gPci->read_pci_config(0, 0, 0, PCI_vendor_id, 2);
368*083a11a3SMarcus Overhagen 	dev_cntrl1 = reg_read32(REG_F2_DEV_CNTRL1);
369*083a11a3SMarcus Overhagen 
370*083a11a3SMarcus Overhagen 	if (host_vendor == PCI_VENDOR_VIA || host_vendor == PCI_VENDOR_SIS) {
371*083a11a3SMarcus Overhagen 		dprintf("cx23882: enabling VIA/SIS compatibility mode\n");
372*083a11a3SMarcus Overhagen 		reg_write32(REG_F2_DEV_CNTRL1, dev_cntrl1 | F2_DEV_CNTRL1_EN_VSFX);
373*083a11a3SMarcus Overhagen 	} else {
374*083a11a3SMarcus Overhagen 		dprintf("cx23882: disabling VIA/SIS compatibility mode\n");
375*083a11a3SMarcus Overhagen 		reg_write32(REG_F2_DEV_CNTRL1, dev_cntrl1 & ~F2_DEV_CNTRL1_EN_VSFX);
376*083a11a3SMarcus Overhagen 	}
377*083a11a3SMarcus Overhagen }
378