Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}