1083a11a3SMarcus Overhagen /* 2083a11a3SMarcus Overhagen * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de> 3083a11a3SMarcus Overhagen * 4083a11a3SMarcus Overhagen * Permission is hereby granted, free of charge, to any person 5083a11a3SMarcus Overhagen * obtaining a copy of this software and associated documentation 6083a11a3SMarcus Overhagen * files (the "Software"), to deal in the Software without restriction, 7083a11a3SMarcus Overhagen * including without limitation the rights to use, copy, modify, 8083a11a3SMarcus Overhagen * merge, publish, distribute, sublicense, and/or sell copies of 9083a11a3SMarcus Overhagen * the Software, and to permit persons to whom the Software is 10083a11a3SMarcus Overhagen * furnished to do so, subject to the following conditions: 11083a11a3SMarcus Overhagen * 12083a11a3SMarcus Overhagen * The above copyright notice and this permission notice shall be 13083a11a3SMarcus Overhagen * included in all copies or substantial portions of the Software. 14083a11a3SMarcus Overhagen * 15083a11a3SMarcus Overhagen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16083a11a3SMarcus Overhagen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17083a11a3SMarcus Overhagen * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18083a11a3SMarcus Overhagen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19083a11a3SMarcus Overhagen * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20083a11a3SMarcus Overhagen * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21083a11a3SMarcus Overhagen * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22083a11a3SMarcus Overhagen * OTHER DEALINGS IN THE SOFTWARE. 23083a11a3SMarcus Overhagen */ 24083a11a3SMarcus Overhagen 25083a11a3SMarcus Overhagen #include "cx23882.h" 26083a11a3SMarcus Overhagen #include "util.h" 27083a11a3SMarcus Overhagen #include <KernelExport.h> 28083a11a3SMarcus Overhagen #include <ByteOrder.h> 29083a11a3SMarcus Overhagen #include <Drivers.h> 30083a11a3SMarcus Overhagen 31083a11a3SMarcus Overhagen 32083a11a3SMarcus Overhagen #define TRACE_CX23882 33083a11a3SMarcus Overhagen #ifdef TRACE_CX23882 34083a11a3SMarcus Overhagen #define TRACE dprintf 35083a11a3SMarcus Overhagen #else 36083a11a3SMarcus Overhagen #define TRACE(a...) 37083a11a3SMarcus Overhagen #endif 38083a11a3SMarcus Overhagen 39083a11a3SMarcus Overhagen // settings for hardware stream sync 40083a11a3SMarcus Overhagen #define MPEG2_SYNC_BYTE 0x47 41083a11a3SMarcus Overhagen #define MPEG2_PACKET_SIZE 188 42083a11a3SMarcus Overhagen #define SYNC_PACKET_COUNT 7 // 0 and 5 don't seem to work 43083a11a3SMarcus Overhagen 44083a11a3SMarcus Overhagen // Line size is also used as FIFO size! 45083a11a3SMarcus Overhagen // BYTES_PER_LINE must be a multiple of 8 and <= 4096 bytes 46083a11a3SMarcus Overhagen #define PACKETS_PER_LINE 20 47083a11a3SMarcus Overhagen #define BYTES_PER_LINE (PACKETS_PER_LINE * MPEG2_PACKET_SIZE) 48083a11a3SMarcus Overhagen 49083a11a3SMarcus Overhagen #define SRAM_START_ADDRESS 0x180000 50083a11a3SMarcus Overhagen #define SRAM_BASE_CMDS_TS 0x200 51083a11a3SMarcus Overhagen #define SRAM_BASE_RISC_PROG 0x400 52083a11a3SMarcus Overhagen #define SRAM_BASE_RISC_QUEUE 0x800 53083a11a3SMarcus Overhagen #define SRAM_BASE_CDT 0x900 54083a11a3SMarcus Overhagen #define SRAM_BASE_FIFO_0 0x1000 55083a11a3SMarcus Overhagen #define SRAM_BASE_FIFO_1 0x2000 56083a11a3SMarcus Overhagen 57083a11a3SMarcus Overhagen // About 64 kByte DMA buffer size 58083a11a3SMarcus Overhagen #define LINES_PER_BUFFER 16 59083a11a3SMarcus Overhagen #define DMA_BUFFER_SIZE (LINES_PER_BUFFER * BYTES_PER_LINE) 60083a11a3SMarcus Overhagen 61083a11a3SMarcus Overhagen 62083a11a3SMarcus Overhagen static status_t cx23882_buffers_alloc(cx23882_device *device); 63083a11a3SMarcus Overhagen static void cx23882_buffers_free(cx23882_device *device); 64083a11a3SMarcus Overhagen static void cx23882_risc_ram_setup(cx23882_device *device); 65083a11a3SMarcus Overhagen static void cx23882_sram_setup(cx23882_device *device); 66083a11a3SMarcus Overhagen static void cx23882_via_sis_fixup(cx23882_device *device); 67083a11a3SMarcus Overhagen 68083a11a3SMarcus Overhagen 69083a11a3SMarcus Overhagen void 70083a11a3SMarcus Overhagen cx23882_reset(cx23882_device *device) 71083a11a3SMarcus Overhagen { 72083a11a3SMarcus Overhagen // software reset (XXX Test) 73083a11a3SMarcus Overhagen reg_write32(0x38c06c, 1); 74083a11a3SMarcus Overhagen snooze(200000); 75083a11a3SMarcus Overhagen 76083a11a3SMarcus Overhagen // disable RISC controller 77083a11a3SMarcus Overhagen reg_write32(REG_DEV_CNTRL2, 0); 78083a11a3SMarcus Overhagen 79083a11a3SMarcus Overhagen // disable TS interface DMA 80083a11a3SMarcus Overhagen reg_write32(REG_TS_DMA_CNTRL, 0x0); 81083a11a3SMarcus Overhagen 82083a11a3SMarcus Overhagen // disable VIP interface up- & downstram DMA 83083a11a3SMarcus Overhagen reg_write32(REG_VIP_STREAM_EN, 0x0); 84083a11a3SMarcus Overhagen 85083a11a3SMarcus Overhagen // disable host interface up- & downstram DMA 86083a11a3SMarcus Overhagen reg_write32(REG_HST_STREAM_EN, 0x0); 87083a11a3SMarcus Overhagen 88083a11a3SMarcus Overhagen // stop all interrupts 89083a11a3SMarcus Overhagen reg_write32(REG_PCI_INT_MSK, 0x0); 90083a11a3SMarcus Overhagen reg_write32(REG_VID_INT_MSK, 0x0); 91083a11a3SMarcus Overhagen reg_write32(REG_AUD_INT_MSK, 0x0); 92083a11a3SMarcus Overhagen reg_write32(REG_TS_INT_MSK, 0x0); 93083a11a3SMarcus Overhagen reg_write32(REG_VIP_INT_MSK, 0x0); 94083a11a3SMarcus Overhagen reg_write32(REG_HST_INT_MSK, 0x0); 95083a11a3SMarcus Overhagen reg_write32(REG_DMA_RISC_INT_MSK, 0x0); 96083a11a3SMarcus Overhagen 97083a11a3SMarcus Overhagen // clear all pending interrupts 98083a11a3SMarcus Overhagen reg_write32(REG_PCI_INT_STAT, 0xffffffff); 99083a11a3SMarcus Overhagen reg_write32(REG_VID_INT_STAT, 0xffffffff); 100083a11a3SMarcus Overhagen reg_write32(REG_AUD_INT_STAT, 0xffffffff); 101083a11a3SMarcus Overhagen reg_write32(REG_TS_INT_STAT, 0xffffffff); 102083a11a3SMarcus Overhagen reg_write32(REG_VIP_INT_STAT, 0xffffffff); 103083a11a3SMarcus Overhagen reg_write32(REG_HST_INT_STAT, 0xffffffff); 104083a11a3SMarcus Overhagen reg_write32(REG_DMA_RISC_INT_MSK, 0xffffffff); 105083a11a3SMarcus Overhagen } 106083a11a3SMarcus Overhagen 107083a11a3SMarcus Overhagen 108083a11a3SMarcus Overhagen status_t 109083a11a3SMarcus Overhagen cx23882_init(cx23882_device *device) 110083a11a3SMarcus Overhagen { 111083a11a3SMarcus Overhagen // assumes that cx23882_reset() has already been called 112083a11a3SMarcus Overhagen 113083a11a3SMarcus Overhagen status_t err; 114083a11a3SMarcus Overhagen 115083a11a3SMarcus Overhagen if ((err = cx23882_buffers_alloc(device)) < B_OK) { 116083a11a3SMarcus Overhagen dprintf("cx23882: Error, buffer alloc failed\n"); 117083a11a3SMarcus Overhagen return err; 118083a11a3SMarcus Overhagen } 119083a11a3SMarcus Overhagen 120083a11a3SMarcus Overhagen device->capture_size = DMA_BUFFER_SIZE; 121083a11a3SMarcus Overhagen 122083a11a3SMarcus Overhagen cx23882_via_sis_fixup(device); 123083a11a3SMarcus Overhagen 124083a11a3SMarcus Overhagen // Set FIFO thresholds, should be 0 < x <= 7 125083a11a3SMarcus Overhagen reg_write32(REG_PDMA_STHRSH, PDMA_ISBTHRSH_6 | PDMA_PCITHRSH_6); 126083a11a3SMarcus Overhagen reg_write32(REG_PDMA_DTHRSH, PDMA_ISBTHRSH_6 | PDMA_PCITHRSH_6); 127083a11a3SMarcus Overhagen 128083a11a3SMarcus Overhagen // init risc programm 129083a11a3SMarcus Overhagen cx23882_risc_ram_setup(device); 130083a11a3SMarcus Overhagen 131083a11a3SMarcus Overhagen // init sram 132083a11a3SMarcus Overhagen cx23882_sram_setup(device); 133083a11a3SMarcus Overhagen 134083a11a3SMarcus Overhagen // Reset counter to 0 135083a11a3SMarcus Overhagen reg_write32(REG_TS_GP_CNT_CNTRL, 0x3); 136083a11a3SMarcus Overhagen 137083a11a3SMarcus Overhagen // Line length for RISC DMA 138083a11a3SMarcus Overhagen reg_write32(REG_TS_LNGTH, BYTES_PER_LINE); 139083a11a3SMarcus Overhagen 140083a11a3SMarcus Overhagen // Set serial interface mode 141083a11a3SMarcus Overhagen reg_write32(REG_TS_GEN_CONTROL, reg_read32(REG_TS_GEN_CONTROL) | TS_GEN_CONTROL_IPB_SMODE); 142083a11a3SMarcus Overhagen 143083a11a3SMarcus Overhagen // Setup hardware MPEG2 fec interface 144083a11a3SMarcus Overhagen reg_write32(REG_HW_SOP_CONTROL, (MPEG2_SYNC_BYTE << 16) | (MPEG2_PACKET_SIZE << 4) | SYNC_PACKET_COUNT); 145083a11a3SMarcus Overhagen 146083a11a3SMarcus Overhagen // Setup TSSTOP status, active low, rising and falling edge, single bit width 147083a11a3SMarcus Overhagen reg_write32(REG_TS_SOP_STATUS, reg_read32(REG_TS_SOP_STATUS) | 0x18000); 148083a11a3SMarcus Overhagen reg_write32(REG_TS_SOP_STATUS, reg_read32(REG_TS_SOP_STATUS) & ~0x06000); 149083a11a3SMarcus Overhagen 150083a11a3SMarcus Overhagen // Enable interrupts for MPEG TS and all errors 151083a11a3SMarcus Overhagen reg_write32(REG_PCI_INT_MSK, reg_read32(REG_PCI_INT_MSK) | PCI_INT_STAT_TS_INT | 0x00fc00); 152083a11a3SMarcus Overhagen reg_write32(REG_TS_INT_MSK, reg_read32(REG_TS_INT_MSK) | TS_INT_STAT_TS_RISC1 | TS_INT_STAT_TS_RISC2 | 0x1f1100); 153083a11a3SMarcus Overhagen 154083a11a3SMarcus Overhagen TRACE("cx23882_init done\n"); 155083a11a3SMarcus Overhagen return B_OK; 156083a11a3SMarcus Overhagen } 157083a11a3SMarcus Overhagen 158083a11a3SMarcus Overhagen 159083a11a3SMarcus Overhagen status_t 160083a11a3SMarcus Overhagen cx23882_terminate(cx23882_device *device) 161083a11a3SMarcus Overhagen { 162083a11a3SMarcus Overhagen cx23882_reset(device); 163083a11a3SMarcus Overhagen 164083a11a3SMarcus Overhagen cx23882_buffers_free(device); 165083a11a3SMarcus Overhagen return B_OK; 166083a11a3SMarcus Overhagen } 167083a11a3SMarcus Overhagen 168083a11a3SMarcus Overhagen 169083a11a3SMarcus Overhagen status_t 170083a11a3SMarcus Overhagen cx23882_start_capture(cx23882_device *device) 171083a11a3SMarcus Overhagen { 172083a11a3SMarcus Overhagen TRACE("cx23882_start_capture\n"); 173083a11a3SMarcus Overhagen 174083a11a3SMarcus Overhagen // start RISC processor and DMA 175083a11a3SMarcus Overhagen reg_write32(REG_DEV_CNTRL2, reg_read32(REG_DEV_CNTRL2) | DEV_CNTRL2_RUN_RISC); 176083a11a3SMarcus 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); 177083a11a3SMarcus Overhagen return B_OK; 178083a11a3SMarcus Overhagen } 179083a11a3SMarcus Overhagen 180083a11a3SMarcus Overhagen 181083a11a3SMarcus Overhagen status_t 182083a11a3SMarcus Overhagen cx23882_stop_capture(cx23882_device *device) 183083a11a3SMarcus Overhagen { 184083a11a3SMarcus Overhagen TRACE("cx23882_stop_capture\n"); 185083a11a3SMarcus Overhagen 186083a11a3SMarcus Overhagen // stop RISC processor and DMA 187083a11a3SMarcus 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)); 188083a11a3SMarcus Overhagen reg_write32(REG_DEV_CNTRL2, reg_read32(REG_DEV_CNTRL2) & ~DEV_CNTRL2_RUN_RISC); 189083a11a3SMarcus Overhagen return B_OK; 190083a11a3SMarcus Overhagen } 191083a11a3SMarcus Overhagen 192083a11a3SMarcus Overhagen 193083a11a3SMarcus Overhagen static inline void 194083a11a3SMarcus Overhagen cx23882_mpegts_int(cx23882_device *device) 195083a11a3SMarcus Overhagen { 196083a11a3SMarcus Overhagen uint32 mstat = reg_read32(REG_TS_INT_MSTAT); 197083a11a3SMarcus Overhagen reg_write32(REG_TS_INT_STAT, mstat); 198083a11a3SMarcus Overhagen 199083a11a3SMarcus Overhagen // dprintf("cx23882_mpegts_int got 0x%08lx\n", mstat); 200083a11a3SMarcus Overhagen 201083a11a3SMarcus Overhagen if (mstat & TS_INT_STAT_OPC_ERR) { 202083a11a3SMarcus Overhagen dprintf("cx23882_mpegts_int RISC opcode error\n"); 203083a11a3SMarcus Overhagen reg_write32(REG_PCI_INT_MSK, 0); 204083a11a3SMarcus Overhagen return; 205083a11a3SMarcus Overhagen } 206083a11a3SMarcus Overhagen 207083a11a3SMarcus Overhagen if ((mstat & (TS_INT_STAT_TS_RISC1 | TS_INT_STAT_TS_RISC2)) == (TS_INT_STAT_TS_RISC1 | TS_INT_STAT_TS_RISC2)) { 208083a11a3SMarcus Overhagen dprintf("cx23882_mpegts_int both buffers ready\n"); 209083a11a3SMarcus Overhagen mstat = TS_INT_STAT_TS_RISC1; 210083a11a3SMarcus Overhagen } 211083a11a3SMarcus Overhagen 212083a11a3SMarcus Overhagen if (mstat & TS_INT_STAT_TS_RISC1) { 213083a11a3SMarcus Overhagen int32 count; 214083a11a3SMarcus Overhagen // dprintf("cx23882_mpegts_int buffer 1 at %Ld\n", system_time()); 215083a11a3SMarcus Overhagen device->capture_data = device->dma_buf1_virt; 216083a11a3SMarcus Overhagen device->capture_end_time = system_time(); 217083a11a3SMarcus Overhagen get_sem_count(device->capture_sem, &count); 218083a11a3SMarcus Overhagen if (count <= 0) 219083a11a3SMarcus Overhagen release_sem_etc(device->capture_sem, 1, B_DO_NOT_RESCHEDULE); 220083a11a3SMarcus Overhagen } 221083a11a3SMarcus Overhagen 222083a11a3SMarcus Overhagen if (mstat & TS_INT_STAT_TS_RISC2) { 223083a11a3SMarcus Overhagen int32 count; 224083a11a3SMarcus Overhagen // dprintf("cx23882_mpegts_int buffer 2 at %Ld\n", system_time()); 225083a11a3SMarcus Overhagen device->capture_data = device->dma_buf2_virt; 226083a11a3SMarcus Overhagen device->capture_end_time = system_time(); 227083a11a3SMarcus Overhagen get_sem_count(device->capture_sem, &count); 228083a11a3SMarcus Overhagen if (count <= 0) 229083a11a3SMarcus Overhagen release_sem_etc(device->capture_sem, 1, B_DO_NOT_RESCHEDULE); 230083a11a3SMarcus Overhagen } 231083a11a3SMarcus Overhagen } 232083a11a3SMarcus Overhagen 233083a11a3SMarcus Overhagen 234083a11a3SMarcus Overhagen int32 235083a11a3SMarcus Overhagen cx23882_int(void *data) 236083a11a3SMarcus Overhagen { 237083a11a3SMarcus Overhagen cx23882_device *device = data; 238083a11a3SMarcus Overhagen uint32 mstat; 239083a11a3SMarcus Overhagen uint32 wmstat; 240083a11a3SMarcus Overhagen 241083a11a3SMarcus Overhagen mstat = reg_read32(REG_PCI_INT_MSTAT); 242083a11a3SMarcus Overhagen if (!mstat) 243083a11a3SMarcus Overhagen return B_UNHANDLED_INTERRUPT; 244083a11a3SMarcus Overhagen 245083a11a3SMarcus Overhagen if (mstat & (PCI_INT_STAT_HST_INT | PCI_INT_STAT_VIP_INT | PCI_INT_STAT_AUD_INT | PCI_INT_STAT_VID_INT)) { 246083a11a3SMarcus Overhagen // serious error, these bits should not be set 247*6849e7ccSJérôme Duval dprintf("cx23882_int error: msk 0x%08" B_PRIx32 ", stat 0x%08" B_PRIx32 248*6849e7ccSJérôme Duval ", mstat 0x%08" B_PRIx32 "\n", reg_read32(REG_PCI_INT_MSK), 249*6849e7ccSJérôme Duval reg_read32(REG_PCI_INT_STAT), mstat); 250083a11a3SMarcus Overhagen reg_write32(REG_PCI_INT_MSK, 0); 251083a11a3SMarcus Overhagen return B_HANDLED_INTERRUPT; 252083a11a3SMarcus Overhagen } 253083a11a3SMarcus Overhagen 254083a11a3SMarcus 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); 255083a11a3SMarcus Overhagen if (wmstat) 256083a11a3SMarcus Overhagen reg_write32(REG_PCI_INT_STAT, wmstat); 257083a11a3SMarcus Overhagen 258083a11a3SMarcus Overhagen if (wmstat) 259*6849e7ccSJérôme Duval dprintf("cx23882_int got 0x%08" B_PRIx32 "\n", wmstat); 260083a11a3SMarcus Overhagen 261083a11a3SMarcus Overhagen if (mstat & PCI_INT_STAT_TS_INT) { 262083a11a3SMarcus Overhagen cx23882_mpegts_int(device); 263083a11a3SMarcus Overhagen return B_INVOKE_SCHEDULER; 264083a11a3SMarcus Overhagen } else { 265083a11a3SMarcus Overhagen return B_HANDLED_INTERRUPT; 266083a11a3SMarcus Overhagen } 267083a11a3SMarcus Overhagen } 268083a11a3SMarcus Overhagen 269083a11a3SMarcus Overhagen 270083a11a3SMarcus Overhagen static status_t 271083a11a3SMarcus Overhagen cx23882_buffers_alloc(cx23882_device *device) 272083a11a3SMarcus Overhagen { 273083a11a3SMarcus 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"); 274083a11a3SMarcus 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"); 275083a11a3SMarcus Overhagen if (device->dma_buf1_area < B_OK || device->dma_buf2_area < B_OK) { 276083a11a3SMarcus Overhagen cx23882_buffers_free(device); 277083a11a3SMarcus Overhagen return B_NO_MEMORY; 278083a11a3SMarcus Overhagen } 279083a11a3SMarcus Overhagen return B_OK; 280083a11a3SMarcus Overhagen } 281083a11a3SMarcus Overhagen 282083a11a3SMarcus Overhagen 283083a11a3SMarcus Overhagen static void 284083a11a3SMarcus Overhagen cx23882_buffers_free(cx23882_device *device) 285083a11a3SMarcus Overhagen { 286083a11a3SMarcus Overhagen if (device->dma_buf1_area >= 0) 287083a11a3SMarcus Overhagen delete_area(device->dma_buf1_area); 288083a11a3SMarcus Overhagen if (device->dma_buf2_area >= 0) 289083a11a3SMarcus Overhagen delete_area(device->dma_buf2_area); 290083a11a3SMarcus Overhagen device->dma_buf1_area = -1; 291083a11a3SMarcus Overhagen device->dma_buf2_area = -1; 292083a11a3SMarcus Overhagen } 293083a11a3SMarcus Overhagen 294083a11a3SMarcus Overhagen 295083a11a3SMarcus Overhagen static void 296083a11a3SMarcus Overhagen cx23882_sram_setup(cx23882_device *device) 297083a11a3SMarcus Overhagen { 298083a11a3SMarcus Overhagen dprintf("cx23882_sram_setup enter\n"); 299083a11a3SMarcus Overhagen 300083a11a3SMarcus Overhagen // setup CDT entries for both FIFOs 301083a11a3SMarcus Overhagen reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CDT, SRAM_START_ADDRESS + SRAM_BASE_FIFO_0); 302083a11a3SMarcus Overhagen reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CDT + 16, SRAM_START_ADDRESS + SRAM_BASE_FIFO_1); 303083a11a3SMarcus Overhagen 304083a11a3SMarcus Overhagen // setup CDMS 305083a11a3SMarcus Overhagen reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x00, SRAM_START_ADDRESS + SRAM_BASE_RISC_PROG); 306083a11a3SMarcus Overhagen reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x04, SRAM_START_ADDRESS + SRAM_BASE_CDT); 307083a11a3SMarcus Overhagen reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x08, (2 * 16) / 8); // FIFO count = 2 308083a11a3SMarcus Overhagen reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x0c, SRAM_START_ADDRESS + SRAM_BASE_RISC_QUEUE); 309083a11a3SMarcus Overhagen reg_write32(SRAM_START_ADDRESS + SRAM_BASE_CMDS_TS + 0x10, 0x80000000 | (0x100 / 4)); 310083a11a3SMarcus Overhagen 311083a11a3SMarcus Overhagen // setup DMA registers 312083a11a3SMarcus Overhagen reg_write32(REG_DMA28_PTR1, SRAM_START_ADDRESS + SRAM_BASE_FIFO_0); 313083a11a3SMarcus Overhagen reg_write32(REG_DMA28_PTR2, SRAM_START_ADDRESS + SRAM_BASE_CDT); 314083a11a3SMarcus Overhagen reg_write32(REG_DMA28_CNT1, BYTES_PER_LINE / 8); 315083a11a3SMarcus Overhagen reg_write32(REG_DMA28_CNT2, (2 * 16) / 8); // FIFO count = 2 316083a11a3SMarcus Overhagen 317083a11a3SMarcus Overhagen dprintf("cx23882_sram_setup leave\n"); 318083a11a3SMarcus Overhagen } 319083a11a3SMarcus Overhagen 320083a11a3SMarcus Overhagen 321083a11a3SMarcus Overhagen static void 322083a11a3SMarcus Overhagen cx23882_risc_ram_setup(cx23882_device *device) 323083a11a3SMarcus Overhagen { 324083a11a3SMarcus Overhagen char *start = (char *)(device->regs) + SRAM_START_ADDRESS + SRAM_BASE_RISC_PROG; 325083a11a3SMarcus Overhagen volatile uint32 *rp = (volatile uint32 *)start; 326083a11a3SMarcus Overhagen int i; 327083a11a3SMarcus Overhagen 328083a11a3SMarcus Overhagen #define set_opcode(a) (*rp++) = B_HOST_TO_LENDIAN_INT32((a)) 329083a11a3SMarcus Overhagen 330083a11a3SMarcus Overhagen dprintf("cx23882_risc_ram_setup enter\n"); 331083a11a3SMarcus Overhagen 332083a11a3SMarcus Overhagen // sync 333083a11a3SMarcus Overhagen set_opcode(RISC_RESYNC | 0); 334083a11a3SMarcus Overhagen 335083a11a3SMarcus Overhagen // copy buffer 1 336083a11a3SMarcus Overhagen for (i = 0; i < LINES_PER_BUFFER; i++) { 337083a11a3SMarcus Overhagen set_opcode(RISC_WRITE | RISC_SOL | RISC_EOL | BYTES_PER_LINE); 338083a11a3SMarcus Overhagen set_opcode((unsigned long)device->dma_buf1_phys + i * BYTES_PER_LINE); 339083a11a3SMarcus Overhagen } 340083a11a3SMarcus Overhagen 341083a11a3SMarcus Overhagen // execute IRQ 1 342083a11a3SMarcus Overhagen set_opcode(RISC_SKIP | RISC_IRQ1 | RISC_SOL | 0); 343083a11a3SMarcus Overhagen 344083a11a3SMarcus Overhagen // copy buffer 2 345083a11a3SMarcus Overhagen for (i = 0; i < LINES_PER_BUFFER; i++) { 346083a11a3SMarcus Overhagen set_opcode(RISC_WRITE | RISC_SOL | RISC_EOL | BYTES_PER_LINE); 347083a11a3SMarcus Overhagen set_opcode((unsigned long)device->dma_buf2_phys + i * BYTES_PER_LINE); 348083a11a3SMarcus Overhagen } 349083a11a3SMarcus Overhagen 350083a11a3SMarcus Overhagen // execute IRQ 2 351083a11a3SMarcus Overhagen set_opcode(RISC_SKIP | RISC_IRQ2 | RISC_SOL | 0); 352083a11a3SMarcus Overhagen 353083a11a3SMarcus Overhagen // jmp to start, but skip sync instruction 354083a11a3SMarcus Overhagen set_opcode(RISC_JUMP | RISC_SRP); 355083a11a3SMarcus Overhagen set_opcode(SRAM_START_ADDRESS + SRAM_BASE_RISC_PROG + 4); 356083a11a3SMarcus Overhagen 357083a11a3SMarcus Overhagen #undef set_opcode 358083a11a3SMarcus Overhagen 359083a11a3SMarcus Overhagen dprintf("cx23882_risc_ram_setup leave\n"); 360083a11a3SMarcus Overhagen } 361083a11a3SMarcus Overhagen 362083a11a3SMarcus Overhagen 363083a11a3SMarcus Overhagen static void 364083a11a3SMarcus Overhagen cx23882_via_sis_fixup(cx23882_device *device) 365083a11a3SMarcus Overhagen { 366083a11a3SMarcus Overhagen uint16 host_vendor; 367083a11a3SMarcus Overhagen uint32 dev_cntrl1; 368083a11a3SMarcus Overhagen 369083a11a3SMarcus Overhagen host_vendor = gPci->read_pci_config(0, 0, 0, PCI_vendor_id, 2); 370083a11a3SMarcus Overhagen dev_cntrl1 = reg_read32(REG_F2_DEV_CNTRL1); 371083a11a3SMarcus Overhagen 372083a11a3SMarcus Overhagen if (host_vendor == PCI_VENDOR_VIA || host_vendor == PCI_VENDOR_SIS) { 373083a11a3SMarcus Overhagen dprintf("cx23882: enabling VIA/SIS compatibility mode\n"); 374083a11a3SMarcus Overhagen reg_write32(REG_F2_DEV_CNTRL1, dev_cntrl1 | F2_DEV_CNTRL1_EN_VSFX); 375083a11a3SMarcus Overhagen } else { 376083a11a3SMarcus Overhagen dprintf("cx23882: disabling VIA/SIS compatibility mode\n"); 377083a11a3SMarcus Overhagen reg_write32(REG_F2_DEV_CNTRL1, dev_cntrl1 & ~F2_DEV_CNTRL1_EN_VSFX); 378083a11a3SMarcus Overhagen } 379083a11a3SMarcus Overhagen } 380