static ssize_t input_map_show(struct device *dev, struct device_attribute *attr, char *buf) { struct solo6010_dev *solo_dev = container_of(dev, struct solo6010_dev, dev); unsigned int val; char *out = buf; val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0); out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f); out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f); out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f); out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f); out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f); out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f); val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1); out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f); out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f); out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f); out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f); out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f); out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f); val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2); out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f); out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f); out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f); out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f); out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f); return out - buf; }
static void solo_gpio_mode(struct solo_dev *solo_dev, unsigned int port_mask, unsigned int mode) { int port; unsigned int ret; ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0); /* To set gpio */ for (port = 0; port < 16; port++) { if (!((1 << port) & port_mask)) continue; ret &= (~(3 << (port << 1))); ret |= ((mode & 3) << (port << 1)); } solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret); /* To set extended gpio - sensor */ ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1); for (port = 0; port < 16; port++) { if (!((1 << (port + 16)) & port_mask)) continue; if (!mode) ret &= ~(1 << port); else ret |= 1 << port; } solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret); }
static void solo_thread_try(struct solo_dev *solo_dev) { struct solo_vb2_buf *vb; /* Only "break" from this loop if slock is held, otherwise * just return. */ for (;;) { unsigned int cur_write; cur_write = SOLO_VI_STATUS0_PAGE( solo_reg_read(solo_dev, SOLO_VI_STATUS0)); if (cur_write == solo_dev->old_write) return; spin_lock(&solo_dev->slock); if (list_empty(&solo_dev->vidq_active)) break; vb = list_first_entry(&solo_dev->vidq_active, struct solo_vb2_buf, list); solo_dev->old_write = cur_write; list_del(&vb->list); spin_unlock(&solo_dev->slock); solo_fillbuf(solo_dev, &vb->vb); } assert_spin_locked(&solo_dev->slock); spin_unlock(&solo_dev->slock); }
static void solo_thread_try(struct solo_filehandle *fh) { struct videobuf_buffer *vb; unsigned int cur_write; for (;;) { spin_lock(&fh->slock); if (list_empty(&fh->vidq_active)) break; vb = list_first_entry(&fh->vidq_active, struct videobuf_buffer, queue); if (!waitqueue_active(&vb->done)) break; cur_write = SOLO_VI_STATUS0_PAGE(solo_reg_read(fh->solo_dev, SOLO_VI_STATUS0)); if (cur_write == fh->old_write) break; fh->old_write = cur_write; list_del(&vb->queue); spin_unlock(&fh->slock); solo_fillbuf(fh, vb); } assert_spin_locked(&fh->slock); spin_unlock(&fh->slock); }
/* XXX We should check the return value of the sub-device ISR's */ static irqreturn_t solo_isr(int irq, void *data) { struct solo_dev *solo_dev = data; u32 status; int i; status = solo_reg_read(solo_dev, SOLO_IRQ_STAT); if (!status) return IRQ_NONE; if (status & ~solo_dev->irq_mask) { solo_reg_write(solo_dev, SOLO_IRQ_STAT, status & ~solo_dev->irq_mask); status &= solo_dev->irq_mask; } if (status & SOLO_IRQ_PCI_ERR) { u32 err = solo_reg_read(solo_dev, SOLO_PCI_ERR); solo_p2m_error_isr(solo_dev, err); solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_PCI_ERR); } for (i = 0; i < SOLO_NR_P2M; i++) if (status & SOLO_IRQ_P2M(i)) solo_p2m_isr(solo_dev, i); if (status & SOLO_IRQ_IIC) solo_i2c_isr(solo_dev); if (status & SOLO_IRQ_VIDEO_IN) solo_video_in_isr(solo_dev); /* Call this first so enc gets detected flag set */ if (status & SOLO_IRQ_MOTION) solo_motion_isr(solo_dev); if (status & SOLO_IRQ_ENCODER) solo_enc_v4l2_isr(solo_dev); if (status & SOLO_IRQ_G723) solo_g723_isr(solo_dev); return IRQ_HANDLED; }
/* Mutex must be held for p2m_id before calling this!! */ int solo_p2m_dma_desc(struct solo6010_dev *solo_dev, struct solo_p2m_desc *desc, dma_addr_t desc_dma, int desc_cnt) { struct solo_p2m_dev *p2m_dev; unsigned int timeout = 0; unsigned int config = 0; int ret = 0; int p2m_id; /* Get next ID */ p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M; if (p2m_id < 0) p2m_id = 0 - p2m_id; p2m_dev = &solo_dev->p2m_dev[p2m_id]; if (mutex_lock_interruptible(&p2m_dev->mutex)) return -EINTR; INIT_COMPLETION(p2m_dev->completion); p2m_dev->error = 0; if (desc_cnt > 1) { /* We only need to do this when we have more than one * descriptor. */ config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id)); solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma); solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt); solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config | SOLO_P2M_DESC_MODE); } else { solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id), desc[1].dma_addr); solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id), desc[1].ext_addr); solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id), desc[1].cfg); solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), desc[1].ctrl); } timeout = wait_for_completion_timeout(&p2m_dev->completion, msecs_to_jiffies(solo_dev->p2m_msecs)); solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0); if (desc_cnt > 1) solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config); if (WARN_ON_ONCE(p2m_dev->error)) ret = -EIO; else if (timeout == 0) ret = -EAGAIN; mutex_unlock(&p2m_dev->mutex); return ret; }
int solo_i2c_isr(struct solo6010_dev *solo_dev) { u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL); int ret = -EINVAL; solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_IIC); if (status & (SOLO_IIC_STATE_TRNS & SOLO_IIC_STATE_SIG_ERR) || solo_dev->i2c_id < 0) { solo_i2c_stop(solo_dev); return -ENXIO; } switch (solo_dev->i2c_state) { case IIC_STATE_START: if (solo_dev->i2c_msg->flags & I2C_M_RD) { solo_dev->i2c_state = IIC_STATE_READ; ret = solo_i2c_handle_read(solo_dev); break; } solo_dev->i2c_state = IIC_STATE_WRITE; case IIC_STATE_WRITE: ret = solo_i2c_handle_write(solo_dev); break; case IIC_STATE_READ: solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr] = solo_reg_read(solo_dev, SOLO_IIC_RXD); solo_dev->i2c_msg_ptr++; ret = solo_i2c_handle_read(solo_dev); break; default: solo_i2c_stop(solo_dev); } return ret; }
static void solo_timer_sync(struct solo6010_dev *solo_dev) { u32 sec, usec; struct timespec ts; long diff; if (solo_dev->type != SOLO_DEV_6110) return; if (++solo_dev->time_sync < 60) return; solo_dev->time_sync = 0; sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC); usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC); ktime_get_ts(&ts); diff = (long)ts.tv_sec - (long)sec; diff = (diff * 1000000) + ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec); if (diff > 1000 || diff < -1000) { solo_set_time(solo_dev); } else if (diff) { long usec_lsb = solo_dev->usec_lsb; usec_lsb -= diff / 4; if (usec_lsb < 0) usec_lsb = 0; else if (usec_lsb > 255) usec_lsb = 255; solo_dev->usec_lsb = usec_lsb; solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB, solo_dev->usec_lsb); } }
static int solo_disp_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct solo_filehandle *fh = priv; struct solo6010_dev *solo_dev = fh->solo_dev; switch (ctrl->id) { case V4L2_CID_MOTION_TRACE: ctrl->value = solo_reg_read(solo_dev, SOLO_VI_MOTION_BAR) ? 1 : 0; return 0; } return -EINVAL; }
static void solo_timer_sync(struct solo6010_dev *solo_dev) { u32 sec, usec; struct timeval tv; long diff; if (solo_dev->type != SOLO_DEV_6110) return; solo_dev->time_sync++; if (solo_dev->time_sync % 60) return; sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC); usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC); do_gettimeofday(&tv); diff = (long)tv.tv_sec - (long)sec; diff = (diff * 1000000) + ((long)tv.tv_usec - (long)usec); if (diff > 1000 || diff < -1000) { solo_set_time(solo_dev); } else if (diff) { long usec_lsb = solo_dev->usec_lsb; usec_lsb -= diff / 4; if (usec_lsb < 0) usec_lsb = 0; else if (usec_lsb > 255) usec_lsb = 255; solo_dev->usec_lsb = usec_lsb; solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB, solo_dev->usec_lsb); } }
static ssize_t intervals_show(struct device *dev, struct device_attribute *attr, char *buf) { struct solo6010_dev *solo_dev = container_of(dev, struct solo6010_dev, dev); char *out = buf; int fps = solo_dev->fps; int i; for (i = 0; i < solo_dev->nr_chans; i++) { out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n", i, solo_dev->v4l2_enc[i]->interval, fps, solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i))); } return out - buf; }
static irqreturn_t solo6010_isr(int irq, void *data) { struct solo6010_dev *solo_dev = data; u32 status; int i; status = solo_reg_read(solo_dev, SOLO_IRQ_STAT); if (!status) return IRQ_NONE; if (status & ~solo_dev->irq_mask) { solo_reg_write(solo_dev, SOLO_IRQ_STAT, status & ~solo_dev->irq_mask); status &= solo_dev->irq_mask; } if (status & SOLO_IRQ_PCI_ERR) solo_p2m_error_isr(solo_dev); for (i = 0; i < SOLO_NR_P2M; i++) if (status & SOLO_IRQ_P2M(i)) solo_p2m_isr(solo_dev, i); if (status & SOLO_IRQ_IIC) solo_i2c_isr(solo_dev); if (status & SOLO_IRQ_VIDEO_IN) { solo_video_in_isr(solo_dev); solo_timer_sync(solo_dev); } if (status & SOLO_IRQ_ENCODER) solo_enc_v4l2_isr(solo_dev); if (status & SOLO_IRQ_G723) solo_g723_isr(solo_dev); /* Clear all interrupts handled */ solo_reg_write(solo_dev, SOLO_IRQ_STAT, status); return IRQ_HANDLED; }
static void solo_thread_try(struct solo_filehandle *fh) { struct videobuf_buffer *vb; /* Only "break" from this loop if slock is held, otherwise * just return. */ for (;;) { unsigned int cur_write; cur_write = SOLO_VI_STATUS0_PAGE( solo_reg_read(fh->solo_dev, SOLO_VI_STATUS0)); if (cur_write == fh->old_write) return; spin_lock(&fh->slock); if (list_empty(&fh->vidq_active)) break; vb = list_first_entry(&fh->vidq_active, struct videobuf_buffer, queue); if (!waitqueue_active(&vb->done)) break; fh->old_write = cur_write; list_del(&vb->queue); vb->state = VIDEOBUF_ACTIVE; spin_unlock(&fh->slock); solo_fillbuf(fh, vb); } assert_spin_locked(&fh->slock); spin_unlock(&fh->slock); }
static unsigned int solo_eeprom_reg_read(struct solo6010_dev *solo_dev) { return ((solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ) ? 1 : 0); }
static int __devinit solo6010_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct solo6010_dev *solo_dev; int ret; int sdram; u8 chip_id; if ((solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL)) == NULL) return -ENOMEM; solo_dev->pdev = pdev; spin_lock_init(&solo_dev->reg_io_lock); pci_set_drvdata(pdev, solo_dev); if ((ret = pci_enable_device(pdev))) goto fail_probe; pci_set_master(pdev); if ((ret = pci_request_regions(pdev, SOLO6010_NAME))) goto fail_probe; if ((solo_dev->reg_base = pci_ioremap_bar(pdev, 0)) == NULL) { ret = -ENOMEM; goto fail_probe; } chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & SOLO_CHIP_ID_MASK; switch (chip_id) { case 7: solo_dev->nr_chans = 16; solo_dev->nr_ext = 5; break; case 6: solo_dev->nr_chans = 8; solo_dev->nr_ext = 2; break; default: dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, " "defaulting to 4 channels\n", chip_id); case 5: solo_dev->nr_chans = 4; solo_dev->nr_ext = 1; } /* Disable all interrupts to start */ solo6010_irq_off(solo_dev, ~0); /* Initial global settings */ solo_reg_write(solo_dev, SOLO_SYS_CFG, SOLO_SYS_CFG_SDRAM64BIT | SOLO_SYS_CFG_INPUTDIV(25) | SOLO_SYS_CFG_FEEDBACKDIV((SOLO_CLOCK_MHZ * 2) - 2) | SOLO_SYS_CFG_OUTDIV(3)); solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, SOLO_CLOCK_MHZ - 1); /* PLL locking time of 1ms */ mdelay(1); ret = request_irq(pdev->irq, solo6010_isr, IRQF_SHARED, SOLO6010_NAME, solo_dev); if (ret) goto fail_probe; /* Handle this from the start */ solo6010_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); if ((ret = solo_i2c_init(solo_dev))) goto fail_probe; /* Setup the DMA engine */ sdram = (solo_dev->nr_chans >= 8) ? 2 : 1; solo_reg_write(solo_dev, SOLO_DMA_CTRL, SOLO_DMA_CTRL_REFRESH_CYCLE(1) | SOLO_DMA_CTRL_SDRAM_SIZE(sdram) | SOLO_DMA_CTRL_SDRAM_CLK_INVERT | SOLO_DMA_CTRL_READ_CLK_SELECT | SOLO_DMA_CTRL_LATENCY(1)); if ((ret = solo_p2m_init(solo_dev))) goto fail_probe; if ((ret = solo_disp_init(solo_dev))) goto fail_probe; if ((ret = solo_gpio_init(solo_dev))) goto fail_probe; if ((ret = solo_tw28_init(solo_dev))) goto fail_probe; if ((ret = solo_v4l2_init(solo_dev))) goto fail_probe; if ((ret = solo_enc_init(solo_dev))) goto fail_probe; if ((ret = solo_enc_v4l2_init(solo_dev))) goto fail_probe; if ((ret = solo_g723_init(solo_dev))) goto fail_probe; return 0; fail_probe: free_solo_dev(solo_dev); return ret; }
static int __devinit solo6010_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct solo6010_dev *solo_dev; int ret; u8 chip_id; solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); if (solo_dev == NULL) return -ENOMEM; if (id->driver_data == SOLO_DEV_6010) dev_info(&pdev->dev, "Probing Softlogic 6010\n"); else dev_info(&pdev->dev, "Probing Softlogic 6110\n"); solo_dev->type = id->driver_data; solo_dev->pdev = pdev; spin_lock_init(&solo_dev->reg_io_lock); pci_set_drvdata(pdev, solo_dev); solo_dev->p2m_jiffies = msecs_to_jiffies(100); /* Only for during init */ if ((ret = pci_enable_device(pdev))) goto fail_probe; pci_set_master(pdev); /* RETRY/TRDY Timeout disabled */ pci_write_config_byte(pdev, 0x40, 0x00); pci_write_config_byte(pdev, 0x41, 0x00); if ((ret = pci_request_regions(pdev, SOLO6010_NAME))) goto fail_probe; if ((solo_dev->reg_base = pci_ioremap_bar(pdev, 0)) == NULL) { ret = -ENOMEM; goto fail_probe; } chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & SOLO_CHIP_ID_MASK; switch (chip_id) { case 7: solo_dev->nr_chans = 16; solo_dev->nr_ext = 5; break; case 6: solo_dev->nr_chans = 8; solo_dev->nr_ext = 2; break; default: dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, " "defaulting to 4 channels\n", chip_id); case 5: solo_dev->nr_chans = 4; solo_dev->nr_ext = 1; } /* Disable all interrupts to start */ solo6010_irq_off(solo_dev, ~0); /* Initial global settings */ if (solo_dev->type == SOLO_DEV_6010) { solo_dev->clock_mhz = 108; solo_reg_write(solo_dev, SOLO_SYS_CFG, SOLO_SYS_CFG_SDRAM64BIT | SOLO_SYS_CFG_INPUTDIV(25) | SOLO_SYS_CFG_FEEDBACKDIV((solo_dev->clock_mhz * 2) - 2) | SOLO_SYS_CFG_OUTDIV(3)); } else { u32 divq, divf; solo_dev->clock_mhz = 135; if (solo_dev->clock_mhz < 125) { divq = 3; divf = (solo_dev->clock_mhz * 4) / 3 - 1; } else { divq = 2; divf = (solo_dev->clock_mhz * 2) / 3 - 1; } solo_reg_write(solo_dev, SOLO_PLL_CONFIG, (1 << 20) | /* PLL_RANGE */ (8 << 15) | /* PLL_DIVR */ (divq << 12 ) | (divf << 4 ) | (1 << 1) /* PLL_FSEN */ ); solo_reg_write(solo_dev, SOLO_SYS_CFG, SOLO_SYS_CFG_SDRAM64BIT); } solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, solo_dev->clock_mhz - 1); /* PLL locking time of 1ms */ mdelay(1); ret = request_irq(pdev->irq, solo6010_isr, IRQF_SHARED, SOLO6010_NAME, solo_dev); if (ret) goto fail_probe; /* Handle this from the start */ solo6010_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); if ((ret = solo_i2c_init(solo_dev))) goto fail_probe; /* Setup the DMA engine */ solo_reg_write(solo_dev, SOLO_DMA_CTRL, SOLO_DMA_CTRL_REFRESH_CYCLE(1) | SOLO_DMA_CTRL_SDRAM_SIZE(2) | SOLO_DMA_CTRL_SDRAM_CLK_INVERT | SOLO_DMA_CTRL_READ_CLK_SELECT | SOLO_DMA_CTRL_LATENCY(1)); /* Undocumented crap */ if (solo_dev->type == SOLO_DEV_6010) { solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 1 << 8); } else { solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 3 << 8); solo_dev->usec_lsb = 0x3f; solo_set_time(solo_dev); } /* Disable watchdog */ solo_reg_write(solo_dev, SOLO_TIMER_WATCHDOG, 0xff); /* Initialize sub components */ if ((ret = solo_p2m_init(solo_dev))) goto fail_probe; if ((ret = solo_disp_init(solo_dev))) goto fail_probe; if ((ret = solo_gpio_init(solo_dev))) goto fail_probe; if ((ret = solo_tw28_init(solo_dev))) goto fail_probe; if ((ret = solo_v4l2_init(solo_dev))) goto fail_probe; if ((ret = solo_enc_init(solo_dev))) goto fail_probe; if ((ret = solo_enc_v4l2_init(solo_dev))) goto fail_probe; if ((ret = solo_g723_init(solo_dev))) goto fail_probe; if ((ret = solo_sysfs_init(solo_dev))) goto fail_probe; /* Now that init is over, set this lower */ solo_dev->p2m_jiffies = msecs_to_jiffies(50); return 0; fail_probe: free_solo_dev(solo_dev); return ret; }
static int __devinit solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct solo_dev *solo_dev; int ret; int sdram; u8 chip_id; u32 reg; solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); if (solo_dev == NULL) return -ENOMEM; solo_dev->pdev = pdev; spin_lock_init(&solo_dev->reg_io_lock); pci_set_drvdata(pdev, solo_dev); ret = pci_enable_device(pdev); if (ret) goto fail_probe; pci_set_master(pdev); ret = pci_request_regions(pdev, SOLO6X10_NAME); if (ret) goto fail_probe; solo_dev->reg_base = pci_ioremap_bar(pdev, 0); if (solo_dev->reg_base == NULL) { ret = -ENOMEM; goto fail_probe; } chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & SOLO_CHIP_ID_MASK; switch (chip_id) { case 7: solo_dev->nr_chans = 16; solo_dev->nr_ext = 5; break; case 6: solo_dev->nr_chans = 8; solo_dev->nr_ext = 2; break; default: dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, " "defaulting to 4 channels\n", chip_id); case 5: solo_dev->nr_chans = 4; solo_dev->nr_ext = 1; } solo_dev->flags = id->driver_data; /* Disable all interrupts to start */ solo_irq_off(solo_dev, ~0); reg = SOLO_SYS_CFG_SDRAM64BIT; /* Initial global settings */ if (!(solo_dev->flags & FLAGS_6110)) reg |= SOLO6010_SYS_CFG_INPUTDIV(25) | SOLO6010_SYS_CFG_FEEDBACKDIV((SOLO_CLOCK_MHZ * 2) - 2) | SOLO6010_SYS_CFG_OUTDIV(3); solo_reg_write(solo_dev, SOLO_SYS_CFG, reg); if (solo_dev->flags & FLAGS_6110) { u32 sys_clock_MHz = SOLO_CLOCK_MHZ; u32 pll_DIVQ; u32 pll_DIVF; if (sys_clock_MHz < 125) { pll_DIVQ = 3; pll_DIVF = (sys_clock_MHz * 4) / 3; } else { pll_DIVQ = 2; pll_DIVF = (sys_clock_MHz * 2) / 3; } solo_reg_write(solo_dev, SOLO6110_PLL_CONFIG, SOLO6110_PLL_RANGE_5_10MHZ | SOLO6110_PLL_DIVR(9) | SOLO6110_PLL_DIVQ_EXP(pll_DIVQ) | SOLO6110_PLL_DIVF(pll_DIVF) | SOLO6110_PLL_FSEN); mdelay(1); /* PLL Locking time (1ms) */ solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 3 << 8); /* ? */ } else solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 1 << 8); /* ? */ solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, SOLO_CLOCK_MHZ - 1); /* PLL locking time of 1ms */ mdelay(1); ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME, solo_dev); if (ret) goto fail_probe; /* Handle this from the start */ solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); ret = solo_i2c_init(solo_dev); if (ret) goto fail_probe; /* Setup the DMA engine */ sdram = (solo_dev->nr_chans >= 8) ? 2 : 1; solo_reg_write(solo_dev, SOLO_DMA_CTRL, SOLO_DMA_CTRL_REFRESH_CYCLE(1) | SOLO_DMA_CTRL_SDRAM_SIZE(sdram) | SOLO_DMA_CTRL_SDRAM_CLK_INVERT | SOLO_DMA_CTRL_READ_CLK_SELECT | SOLO_DMA_CTRL_LATENCY(1)); ret = solo_p2m_init(solo_dev); if (ret) goto fail_probe; ret = solo_disp_init(solo_dev); if (ret) goto fail_probe; ret = solo_gpio_init(solo_dev); if (ret) goto fail_probe; ret = solo_tw28_init(solo_dev); if (ret) goto fail_probe; ret = solo_v4l2_init(solo_dev); if (ret) goto fail_probe; ret = solo_enc_init(solo_dev); if (ret) goto fail_probe; ret = solo_enc_v4l2_init(solo_dev); if (ret) goto fail_probe; ret = solo_g723_init(solo_dev); if (ret) goto fail_probe; return 0; fail_probe: free_solo_dev(solo_dev); return ret; }
static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value) { solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT, solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value); }