static int solo_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct solo_dev *solo_dev = adap->algo_data; unsigned long timeout; int ret; int i; DEFINE_WAIT(wait); for (i = 0; i < SOLO_I2C_ADAPTERS; i++) { if (&solo_dev->i2c_adap[i] == adap) break; } if (i == SOLO_I2C_ADAPTERS) return num; /* XXX Right return value for failure? */ mutex_lock(&solo_dev->i2c_mutex); solo_dev->i2c_id = i; solo_dev->i2c_msg = msgs; solo_dev->i2c_msg_num = num; solo_dev->i2c_msg_ptr = 0; solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0); solo_irq_on(solo_dev, SOLO_IRQ_IIC); solo_i2c_start(solo_dev); timeout = HZ / 2; for (;;) { prepare_to_wait(&solo_dev->i2c_wait, &wait, TASK_INTERRUPTIBLE); if (solo_dev->i2c_state == IIC_STATE_STOP) break; timeout = schedule_timeout(timeout); if (!timeout) break; if (signal_pending(current)) break; } finish_wait(&solo_dev->i2c_wait, &wait); ret = num - solo_dev->i2c_msg_num; solo_dev->i2c_state = IIC_STATE_IDLE; solo_dev->i2c_id = -1; mutex_unlock(&solo_dev->i2c_mutex); return ret; }
static int solo_start_thread(struct solo_dev *solo_dev) { int ret = 0; solo_dev->kthread = kthread_run(solo_thread, solo_dev, SOLO6X10_NAME "_disp"); if (IS_ERR(solo_dev->kthread)) { ret = PTR_ERR(solo_dev->kthread); solo_dev->kthread = NULL; return ret; } solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN); return ret; }
static int solo_start_thread(struct solo_filehandle *fh) { int ret = 0; if (atomic_inc_return(&fh->solo_dev->disp_users) == 1) solo_irq_on(fh->solo_dev, SOLO_IRQ_VIDEO_IN); fh->kthread = kthread_run(solo_thread, fh, SOLO6X10_NAME "_disp"); if (IS_ERR(fh->kthread)) { ret = PTR_ERR(fh->kthread); fh->kthread = NULL; } 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); /* Only for during init */ solo_dev->p2m_jiffies = msecs_to_jiffies(100); 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 */ solo_irq_off(solo_dev, ~0); /* Initial global settings */ if (solo_dev->type == SOLO_DEV_6010) { solo_dev->clock_mhz = 108; solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT | SOLO_SYS_CFG_INPUTDIV(25) | SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2) | SOLO_SYS_CFG_OUTDIV(3); solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); } 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_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT; } solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); 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 */ solo_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 */ solo_reg_write(solo_dev, SOLO_DMA_CTRL1, solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300); if (solo_dev->type != SOLO_DEV_6010) { solo_dev->usec_lsb = 0x3f; solo_set_time(solo_dev); } /* Disable watchdog */ solo_reg_write(solo_dev, SOLO_WATCHDOG, 0); /* 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, video_nr))) goto fail_probe; if ((ret = solo_enc_init(solo_dev))) goto fail_probe; if ((ret = solo_enc_v4l2_init(solo_dev, video_nr))) 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(20); 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; }