📄 cx23885-417.c
字号:
regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; cx_write(MC417_RWD, regval); /* Read data byte 3 */ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3; cx_write(MC417_RWD, regval); regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3; cx_write(MC417_RWD, regval); tempval = cx_read(MC417_RWD); dataval |= ((tempval & 0x000000FF) << 24); regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; cx_write(MC417_RWD, regval); *value = dataval; return retval;}int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value){ u32 regval; /* Enable MC417 GPIO outputs except for MC417_MIRDY, * which is an input. */ cx_write(MC417_OEN, MC417_MIRDY); /* Write data byte 0 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 | (value & 0x000000FF); cx_write(MC417_RWD, regval); /* Transition CS/WR to effect write transaction across bus. */ regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write data byte 1 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 | ((value >> 8) & 0x000000FF); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write data byte 2 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 | ((value >> 16) & 0x000000FF); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write data byte 3 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 | ((value >> 24) & 0x000000FF); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write address byte 2 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write address byte 1 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 | ((address >> 8) & 0xFF); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write address byte 0 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 | (address & 0xFF); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Wait for the trans to complete (MC417_MIRDY asserted). */ return mc417_wait_ready(dev);}int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value){ int retval; u32 regval; u32 tempval; u32 dataval; /* Enable MC417 GPIO outputs except for MC417_MIRDY, * which is an input. */ cx_write(MC417_OEN, MC417_MIRDY); /* Write address byte 2 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write address byte 1 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 | ((address >> 8) & 0xFF); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Write address byte 0 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 | (address & 0xFF); cx_write(MC417_RWD, regval); regval |= MC417_MICS | MC417_MIWR; cx_write(MC417_RWD, regval); /* Wait for the trans to complete (MC417_MIRDY asserted). */ retval = mc417_wait_ready(dev); /* switch the DAT0-7 GPIO[10:3] to input mode */ cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA); /* Read data byte 3 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3; cx_write(MC417_RWD, regval); /* Transition RD to effect read transaction across bus. */ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3; cx_write(MC417_RWD, regval); /* Collect byte */ tempval = cx_read(MC417_RWD); dataval = ((tempval & 0x000000FF) << 24); /* Bring CS and RD high. */ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; cx_write(MC417_RWD, regval); /* Read data byte 2 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2; cx_write(MC417_RWD, regval); regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2; cx_write(MC417_RWD, regval); tempval = cx_read(MC417_RWD); dataval |= ((tempval & 0x000000FF) << 16); regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; cx_write(MC417_RWD, regval); /* Read data byte 1 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1; cx_write(MC417_RWD, regval); regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1; cx_write(MC417_RWD, regval); tempval = cx_read(MC417_RWD); dataval |= ((tempval & 0x000000FF) << 8); regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; cx_write(MC417_RWD, regval); /* Read data byte 0 */ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0; cx_write(MC417_RWD, regval); regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0; cx_write(MC417_RWD, regval); tempval = cx_read(MC417_RWD); dataval |= (tempval & 0x000000FF); regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY; cx_write(MC417_RWD, regval); *value = dataval; return retval;}/* ------------------------------------------------------------------ *//* MPEG encoder API */static char *cmd_to_str(int cmd){ switch (cmd) { case CX2341X_ENC_PING_FW: return "PING_FW"; case CX2341X_ENC_START_CAPTURE: return "START_CAPTURE"; case CX2341X_ENC_STOP_CAPTURE: return "STOP_CAPTURE"; case CX2341X_ENC_SET_AUDIO_ID: return "SET_AUDIO_ID"; case CX2341X_ENC_SET_VIDEO_ID: return "SET_VIDEO_ID"; case CX2341X_ENC_SET_PCR_ID: return "SET_PCR_PID"; case CX2341X_ENC_SET_FRAME_RATE: return "SET_FRAME_RATE"; case CX2341X_ENC_SET_FRAME_SIZE: return "SET_FRAME_SIZE"; case CX2341X_ENC_SET_BIT_RATE: return "SET_BIT_RATE"; case CX2341X_ENC_SET_GOP_PROPERTIES: return "SET_GOP_PROPERTIES"; case CX2341X_ENC_SET_ASPECT_RATIO: return "SET_ASPECT_RATIO"; case CX2341X_ENC_SET_DNR_FILTER_MODE: return "SET_DNR_FILTER_PROPS"; case CX2341X_ENC_SET_DNR_FILTER_PROPS: return "SET_DNR_FILTER_PROPS"; case CX2341X_ENC_SET_CORING_LEVELS: return "SET_CORING_LEVELS"; case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE: return "SET_SPATIAL_FILTER_TYPE"; case CX2341X_ENC_SET_VBI_LINE: return "SET_VBI_LINE"; case CX2341X_ENC_SET_STREAM_TYPE: return "SET_STREAM_TYPE"; case CX2341X_ENC_SET_OUTPUT_PORT: return "SET_OUTPUT_PORT"; case CX2341X_ENC_SET_AUDIO_PROPERTIES: return "SET_AUDIO_PROPERTIES"; case CX2341X_ENC_HALT_FW: return "HALT_FW"; case CX2341X_ENC_GET_VERSION: return "GET_VERSION"; case CX2341X_ENC_SET_GOP_CLOSURE: return "SET_GOP_CLOSURE"; case CX2341X_ENC_GET_SEQ_END: return "GET_SEQ_END"; case CX2341X_ENC_SET_PGM_INDEX_INFO: return "SET_PGM_INDEX_INFO"; case CX2341X_ENC_SET_VBI_CONFIG: return "SET_VBI_CONFIG"; case CX2341X_ENC_SET_DMA_BLOCK_SIZE: return "SET_DMA_BLOCK_SIZE"; case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10: return "GET_PREV_DMA_INFO_MB_10"; case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9: return "GET_PREV_DMA_INFO_MB_9"; case CX2341X_ENC_SCHED_DMA_TO_HOST: return "SCHED_DMA_TO_HOST"; case CX2341X_ENC_INITIALIZE_INPUT: return "INITIALIZE_INPUT"; case CX2341X_ENC_SET_FRAME_DROP_RATE: return "SET_FRAME_DROP_RATE"; case CX2341X_ENC_PAUSE_ENCODER: return "PAUSE_ENCODER"; case CX2341X_ENC_REFRESH_INPUT: return "REFRESH_INPUT"; case CX2341X_ENC_SET_COPYRIGHT: return "SET_COPYRIGHT"; case CX2341X_ENC_SET_EVENT_NOTIFICATION: return "SET_EVENT_NOTIFICATION"; case CX2341X_ENC_SET_NUM_VSYNC_LINES: return "SET_NUM_VSYNC_LINES"; case CX2341X_ENC_SET_PLACEHOLDER: return "SET_PLACEHOLDER"; case CX2341X_ENC_MUTE_VIDEO: return "MUTE_VIDEO"; case CX2341X_ENC_MUTE_AUDIO: return "MUTE_AUDIO"; case CX2341X_ENC_MISC: return "MISC"; default: return "UNKNOWN"; }}static int cx23885_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]){ struct cx23885_dev *dev = priv; unsigned long timeout; u32 value, flag, retval = 0; int i; dprintk(3, "%s: command(0x%X) = %s\n", __func__, command, cmd_to_str(command)); /* this may not be 100% safe if we can't read any memory location without side effects */ mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value); if (value != 0x12345678) { printk(KERN_ERR "Firmware and/or mailbox pointer not initialized " "or corrupted, signature = 0x%x, cmd = %s\n", value, cmd_to_str(command)); return -1; } /* This read looks at 32 bits, but flag is only 8 bits. * Seems we also bail if CMD or TIMEOUT bytes are set??? */ mc417_memory_read(dev, dev->cx23417_mailbox, &flag); if (flag) { printk(KERN_ERR "ERROR: Mailbox appears to be in use " "(%x), cmd = %s\n", flag, cmd_to_str(command)); return -1; } flag |= 1; /* tell 'em we're working on it */ mc417_memory_write(dev, dev->cx23417_mailbox, flag); /* write command + args + fill remaining with zeros */ /* command code */ mc417_memory_write(dev, dev->cx23417_mailbox + 1, command); mc417_memory_write(dev, dev->cx23417_mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ for (i = 0; i < in; i++) { mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]); dprintk(3, "API Input %d = %d\n", i, data[i]); } for (; i < CX2341X_MBOX_MAX_DATA; i++) mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0); flag |= 3; /* tell 'em we're done writing */ mc417_memory_write(dev, dev->cx23417_mailbox, flag); /* wait for firmware to handle the API command */ timeout = jiffies + msecs_to_jiffies(10); for (;;) { mc417_memory_read(dev, dev->cx23417_mailbox, &flag); if (0 != (flag & 4)) break; if (time_after(jiffies, timeout)) { printk(KERN_ERR "ERROR: API Mailbox timeout\n"); return -1; } udelay(10); } /* read output values */ for (i = 0; i < out; i++) { mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i); dprintk(3, "API Output %d = %d\n", i, data[i]); } mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval); dprintk(3, "API result = %d\n", retval); flag = 0; mc417_memory_write(dev, dev->cx23417_mailbox, flag); return retval;}/* We don't need to call the API often, so using just one * mailbox will probably suffice */static int cx23885_api_cmd(struct cx23885_dev *dev, u32 command, u32 inputcnt, u32 outputcnt, ...){ u32 data[CX2341X_MBOX_MAX_DATA]; va_list vargs; int i, err; dprintk(3, "%s() cmds = 0x%08x\n", __func__, command); va_start(vargs, outputcnt); for (i = 0; i < inputcnt; i++) data[i] = va_arg(vargs, int); err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data); for (i = 0; i < outputcnt; i++) { int *vptr = va_arg(vargs, int *); *vptr = data[i]; } va_end(vargs); return err;}static int cx23885_find_mailbox(struct cx23885_dev *dev){ u32 signature[4] = { 0x12345678, 0x34567812, 0x56781234, 0x78123456 }; int signaturecnt = 0; u32 value; int i; dprintk(2, "%s()\n", __func__); for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) { mc417_memory_read(dev, i, &value); if (value == signature[signaturecnt]) signaturecnt++; else signaturecnt = 0; if (4 == signaturecnt) { dprintk(1, "Mailbox signature found at 0x%x\n", i+1); return i+1; } } printk(KERN_ERR "Mailbox signature values not found!\n"); return -1;}static int cx23885_load_firmware(struct cx23885_dev *dev){ static const unsigned char magic[8] = { 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa }; const struct firmware *firmware; int i, retval = 0; u32 value = 0; u32 gpio_output = 0; u32 checksum = 0; u32 *dataptr; dprintk(2, "%s()\n", __func__); /* Save GPIO settings before reset of APU */ retval |= mc417_memory_read(dev, 0x9020, &gpio_output); retval |= mc417_memory_read(dev, 0x900C, &value); retval = mc417_register_write(dev, IVTV_REG_VPU, 0xFFFFFFED); retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); retval |= mc417_register_write(dev, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800); retval |= mc417_register_write(dev, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); retval |= mc417_register_write(dev, IVTV_REG_APU, 0); if (retval != 0) { printk(KERN_ERR "%s: Error with mc417_register_write\n", __func__); return -1; } retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME, &dev->pci->dev); if (retval != 0) { printk(KERN_ERR "ERROR: Hotplug firmware request failed (%s).\n", CX2341X_FIRM_ENC_FILENAME); printk(KERN_ERR "Please fix your hotplug setup, the board will " "not work without firmware loaded!\n"); return -1; } if (firmware->size != CX23885_FIRM_IMAGE_SIZE) { printk(KERN_ERR "ERROR: Firmware size mismatch " "(have %zd, expected %d)\n", firmware->size, CX23885_FIRM_IMAGE_SIZE); release_firmware(firmware); return -1; } if (0 != memcmp(firmware->data, magic, 8)) { printk(KERN_ERR "ERROR: Firmware magic mismatch, wrong file?\n"); release_firmware(firmware);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -