예제 #1
0
static int solo_disp_s_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:
		if (ctrl->value) {
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER,
					SOLO_VI_MOTION_Y_ADD |
					SOLO_VI_MOTION_Y_VALUE(0x20) |
					SOLO_VI_MOTION_CB_VALUE(0x10) |
					SOLO_VI_MOTION_CR_VALUE(0x10));
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR,
					SOLO_VI_MOTION_CR_ADD |
					SOLO_VI_MOTION_Y_VALUE(0x10) |
					SOLO_VI_MOTION_CB_VALUE(0x80) |
					SOLO_VI_MOTION_CR_VALUE(0x10));
		} else {
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
		}
		return 0;
	}
	return -EINVAL;
}
예제 #2
0
int solo_p2m_init(struct solo6010_dev *solo_dev)
{
    struct solo_p2m_dev *p2m_dev;
    int i;

    for (i = 0; i < SOLO_NR_P2M; i++) {
        p2m_dev = &solo_dev->p2m_dev[i];

        sema_init(&p2m_dev->sem, 1);
        init_completion(&p2m_dev->completion);

        solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(i),
                       __pa(p2m_dev->desc));

        solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
        solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
                       SOLO_P2M_CSC_16BIT_565 |
                       SOLO_P2M_DMA_INTERVAL(0) |
                       SOLO_P2M_PCI_MASTER_MODE);
        solo6010_irq_on(solo_dev, SOLO_IRQ_P2M(i));
    }

    run_p2m_test(solo_dev);

    return 0;
}
예제 #3
0
static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct solo_dev *solo_dev =
		container_of(ctrl->handler, struct solo_dev, disp_hdl);

	switch (ctrl->id) {
	case V4L2_CID_MOTION_TRACE:
		if (ctrl->val) {
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER,
					SOLO_VI_MOTION_Y_ADD |
					SOLO_VI_MOTION_Y_VALUE(0x20) |
					SOLO_VI_MOTION_CB_VALUE(0x10) |
					SOLO_VI_MOTION_CR_VALUE(0x10));
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR,
					SOLO_VI_MOTION_CR_ADD |
					SOLO_VI_MOTION_Y_VALUE(0x10) |
					SOLO_VI_MOTION_CB_VALUE(0x80) |
					SOLO_VI_MOTION_CR_VALUE(0x10));
		} else {
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
			solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
		}
		return 0;
	default:
		break;
	}
	return -EINVAL;
}
예제 #4
0
파일: gpio.c 프로젝트: CSCLOG/beaglebone
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);
}
예제 #5
0
static void solo_set_time(struct solo6010_dev *solo_dev)
{
	struct timeval tv;

	do_gettimeofday(&tv);
	solo_reg_write(solo_dev, SOLO_TIMER_SEC, tv.tv_sec);
	solo_reg_write(solo_dev, SOLO_TIMER_USEC, tv.tv_usec);
}
예제 #6
0
static void solo_set_time(struct solo6010_dev *solo_dev)
{
	struct timespec ts;

	ktime_get_ts(&ts);

	solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
	solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
}
예제 #7
0
static void set_qp(struct solo_enc_dev *solo_enc, int qp)
{
  u8 ch = solo_enc->ch;
  struct solo6010_dev *solo_dev = solo_enc->solo_dev;

  solo_enc->qp = qp;

  solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);

  /* Extended encoding only */
  solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
}
예제 #8
0
/* 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;
}
예제 #9
0
파일: solo6x10-i2c.c 프로젝트: 7799/linux
static void solo_i2c_stop(struct solo_dev *solo_dev)
{
	solo_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);
}
예제 #10
0
파일: solo6x10-i2c.c 프로젝트: 7799/linux
static int solo_i2c_handle_write(struct solo_dev *solo_dev)
{
retry_write:
	if (solo_dev->i2c_msg_ptr != solo_dev->i2c_msg->len) {
		solo_reg_write(solo_dev, SOLO_IIC_TXD,
			       solo_dev->i2c_msg->buf[solo_dev->i2c_msg_ptr]);
		solo_dev->i2c_msg_ptr++;
		solo_i2c_flush(solo_dev, 1);
		return 0;
	}

	solo_dev->i2c_msg_ptr = 0;
	solo_dev->i2c_msg++;
	solo_dev->i2c_msg_num--;

	if (solo_dev->i2c_msg_num == 0) {
		solo_i2c_stop(solo_dev);
		return 0;
	}

	if (!(solo_dev->i2c_msg->flags & I2C_M_NOSTART)) {
		solo_i2c_start(solo_dev);
	} else {
		if (solo_dev->i2c_msg->flags & I2C_M_RD)
			solo_i2c_stop(solo_dev);
		else
			goto retry_write;
	}

	return 0;
}
예제 #11
0
static void solo_win_setup(struct solo6010_dev *solo_dev, u8 ch,
			   int sx, int sy, int ex, int ey, int scale)
{
	if (ch >= solo_dev->nr_chans)
		return;

	/* Here, we just keep window/channel the same */
	solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL0(ch),
		       SOLO_VI_WIN_CHANNEL(ch) |
		       SOLO_VI_WIN_SX(sx) |
		       SOLO_VI_WIN_EX(ex) |
		       SOLO_VI_WIN_SCALE(scale));

        solo_reg_write(solo_dev, SOLO_VI_WIN_CTRL1(ch),
		       SOLO_VI_WIN_SY(sy) |
		       SOLO_VI_WIN_EY(ey));
}
예제 #12
0
/* 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;
}
예제 #13
0
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;
}
예제 #14
0
파일: solo6x10-i2c.c 프로젝트: 7799/linux
static void solo_i2c_start(struct solo_dev *solo_dev)
{
	u32 addr = solo_dev->i2c_msg->addr << 1;

	if (solo_dev->i2c_msg->flags & I2C_M_RD)
		addr |= 1;

	solo_dev->i2c_state = IIC_STATE_START;
	solo_reg_write(solo_dev, SOLO_IIC_TXD, addr);
	solo_i2c_flush(solo_dev, 1);
}
예제 #15
0
파일: solo6x10-i2c.c 프로젝트: 7799/linux
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;
}
예제 #16
0
int solo_p2m_dma_t(struct solo6010_dev *solo_dev, u8 id, int wr,
                   dma_addr_t dma_addr, u32 ext_addr, u32 size)
{
    struct solo_p2m_dev *p2m_dev;
    unsigned int timeout = 0;

    WARN_ON(!size);
    WARN_ON(id >= SOLO_NR_P2M);
    if (!size || id >= SOLO_NR_P2M)
        return -EINVAL;

    p2m_dev = &solo_dev->p2m_dev[id];

    down(&p2m_dev->sem);

start_dma:
    INIT_COMPLETION(p2m_dev->completion);
    p2m_dev->error = 0;
    solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), dma_addr);
    solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), ext_addr);
    solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id),
                   SOLO_P2M_COPY_SIZE(size >> 2));
    solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id),
                   SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
                   (wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON);

    timeout = wait_for_completion_timeout(&p2m_dev->completion, HZ);

    solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);

    /* XXX Really looks to me like we will get stuck here if a
     * real PCI P2M error occurs */
    if (p2m_dev->error)
        goto start_dma;

    up(&p2m_dev->sem);

    return (timeout == 0) ? -EAGAIN : 0;
}
예제 #17
0
static int erase_off(struct solo6010_dev *solo_dev)
{
	if (!solo_dev->erasing)
		return 0;

	/* First time around, assert erase off */
	if (!solo_dev->frame_blank)
		solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, 0);
	/* Keep the erasing flag on for 8 frames minimum */
	if (solo_dev->frame_blank++ >= 8)
		solo_dev->erasing = 0;

	return 1;
}
예제 #18
0
void solo_p2m_error_isr(struct solo6010_dev *solo_dev, u32 status)
{
    struct solo_p2m_dev *p2m_dev;
    int i;

    if (!(status & SOLO_PCI_ERR_P2M))
        return;

    for (i = 0; i < SOLO_NR_P2M; i++) {
        p2m_dev = &solo_dev->p2m_dev[i];
        p2m_dev->error = 1;
        solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
        complete(&p2m_dev->completion);
    }
}
예제 #19
0
int solo_i2c_init(struct solo6010_dev *solo_dev)
{
	int i;
	int ret;

	solo_reg_write(solo_dev, SOLO_IIC_CFG,
		       SOLO_IIC_PRESCALE(8) | SOLO_IIC_ENABLE);

	solo_dev->i2c_id = -1;
	solo_dev->i2c_state = IIC_STATE_IDLE;
	init_waitqueue_head(&solo_dev->i2c_wait);
	init_MUTEX(&solo_dev->i2c_sem);

	for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
		struct i2c_adapter *adap = &solo_dev->i2c_adap[i];

		snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d",
			 SOLO6010_NAME, i);
		adap->algo = &solo_i2c_algo;
		adap->algo_data = solo_dev;
		adap->retries = 1;
		adap->dev.parent = &solo_dev->pdev->dev;

		if ((ret = i2c_add_adapter(adap))) {
			adap->algo_data = NULL;
			break;
		}
	}

	if (ret) {
		for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
			if (!solo_dev->i2c_adap[i].algo_data)
				break;
			i2c_del_adapter(&solo_dev->i2c_adap[i]);
			solo_dev->i2c_adap[i].algo_data = NULL;
		}
		return ret;
	}

	dev_info(&solo_dev->pdev->dev, "Enabled %d i2c adapters\n",
		 SOLO_I2C_ADAPTERS);

	return 0;
}
예제 #20
0
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;
}
예제 #21
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);
	}
}
예제 #22
0
파일: solo6x10-i2c.c 프로젝트: 7799/linux
static void solo_i2c_flush(struct solo_dev *solo_dev, int wr)
{
	u32 ctrl;

	ctrl = SOLO_IIC_CH_SET(solo_dev->i2c_id);

	if (solo_dev->i2c_state == IIC_STATE_START)
		ctrl |= SOLO_IIC_START;

	if (wr) {
		ctrl |= SOLO_IIC_WRITE;
	} else {
		ctrl |= SOLO_IIC_READ;
		if (!(solo_dev->i2c_msg->flags & I2C_M_NO_RD_ACK))
			ctrl |= SOLO_IIC_ACK_EN;
	}

	if (solo_dev->i2c_msg_ptr == solo_dev->i2c_msg->len)
		ctrl |= SOLO_IIC_STOP;

	solo_reg_write(solo_dev, SOLO_IIC_CTRL, ctrl);
}
예제 #23
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);
	}
}
예제 #24
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;
}
예제 #25
0
void solo_video_in_isr(struct solo6010_dev *solo_dev)
{
	solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_VIDEO_IN);
	wake_up_interruptible(&solo_dev->disp_thread_wait);
}
예제 #26
0
static void erase_on(struct solo6010_dev *solo_dev)
{
	solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
	solo_dev->erasing = 1;
	solo_dev->frame_blank = 0;
}
예제 #27
0
void solo_irq_on(struct solo_dev *solo_dev, u32 mask)
{
	solo_dev->irq_mask |= mask;
	solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask);
}
예제 #28
0
void solo6010_irq_off(struct solo6010_dev *solo_dev, u32 mask)
{
	solo_dev->irq_mask &= ~mask;
	solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask);
}
예제 #29
0
void solo_p2m_isr(struct solo6010_dev *solo_dev, int id)
{
    solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_P2M(id));
    complete(&solo_dev->p2m_dev[id].completion);
}
예제 #30
0
static void solo_eeprom_reg_write(struct solo6010_dev *solo_dev, u32 data)
{
	solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
	eeprom_delay();
}