Ejemplo n.º 1
0
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);
	}
}
Ejemplo n.º 2
0
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);
	}
}
Ejemplo n.º 3
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);
	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;
}