Beispiel #1
0
static void solo_i2c_stop(struct solo6010_dev *solo_dev)
{
	solo6010_irq_off(solo_dev, SOLO_IRQ_IIC);
	solo_reg_write(solo_dev, SOLO_IIC_CTRL, 0);
	solo_dev->i2c_state = IIC_STATE_STOP;
	wake_up(&solo_dev->i2c_wait);
}
void solo_p2m_exit(struct solo6010_dev *solo_dev)
{
    int i;

    for (i = 0; i < SOLO_NR_P2M; i++)
        solo6010_irq_off(solo_dev, SOLO_IRQ_P2M(i));
}
void solo_v4l2_exit(struct solo6010_dev *solo_dev)
{
	solo6010_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN);
	if (solo_dev->vfd) {
		video_unregister_device(solo_dev->vfd);
		solo_dev->vfd = NULL;
	}
}
Beispiel #4
0
static void free_solo_dev(struct solo6010_dev *solo_dev)
{
	struct pci_dev *pdev;

	if (!solo_dev)
		return;

	if (solo_dev->dev.parent)
		device_unregister(&solo_dev->dev);

	pdev = solo_dev->pdev;

	/* If we never initialized the PCI device, then nothing else
	 * below here needs cleanup */
	if (!pdev) {
		kfree(solo_dev);
		return;
	}

	/* Bring down the sub-devices first */
	solo_g723_exit(solo_dev);
	solo_enc_v4l2_exit(solo_dev);
	solo_enc_exit(solo_dev);
	solo_v4l2_exit(solo_dev);
	solo_disp_exit(solo_dev);
	solo_gpio_exit(solo_dev);
	solo_p2m_exit(solo_dev);
	solo_i2c_exit(solo_dev);

	/* Now cleanup the PCI device */
	if (solo_dev->reg_base) {
		solo6010_irq_off(solo_dev, ~0);
		pci_iounmap(pdev, solo_dev->reg_base);
		if (pdev->irq)
			free_irq(pdev->irq, solo_dev);
	}

	pci_release_regions(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);

	kfree(solo_dev);
}
Beispiel #5
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;
}
Beispiel #6
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;
}