Пример #1
0
static void vivid_cec_xfer_done_worker(struct work_struct *work)
{
	struct vivid_cec_work *cw =
		container_of(work, struct vivid_cec_work, work.work);
	struct vivid_dev *dev = cw->dev;
	struct cec_adapter *adap = cw->adap;
	u8 dest = cec_msg_destination(&cw->msg);
	bool valid_dest;
	unsigned int i;

	valid_dest = cec_msg_is_broadcast(&cw->msg);
	if (!valid_dest)
		valid_dest = vivid_cec_find_dest_adap(dev, adap, dest);

	cw->tx_status = valid_dest ? CEC_TX_STATUS_OK : CEC_TX_STATUS_NACK;
	spin_lock(&dev->cec_slock);
	dev->cec_xfer_time_jiffies = 0;
	dev->cec_xfer_start_jiffies = 0;
	list_del(&cw->list);
	spin_unlock(&dev->cec_slock);
	cec_transmit_done(cw->adap, cw->tx_status, 0, valid_dest ? 0 : 1, 0, 0);

	/* Broadcast message */
	if (adap != dev->cec_rx_adap)
		cec_received_msg(dev->cec_rx_adap, &cw->msg);
	for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
		if (adap != dev->cec_tx_adap[i])
			cec_received_msg(dev->cec_tx_adap[i], &cw->msg);
	kfree(cw);
}
Пример #2
0
static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv)
{
	struct s5p_cec_dev *cec = priv;

	dev_dbg(cec->dev, "irq processing thread\n");
	switch (cec->tx) {
	case STATE_DONE:
		cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
		cec->tx = STATE_IDLE;
		break;
	case STATE_ERROR:
		cec_transmit_done(cec->adap,
			CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR,
			0, 0, 0, 1);
		cec->tx = STATE_IDLE;
		break;
	case STATE_BUSY:
		dev_err(cec->dev, "state set to busy, this should not occur here\n");
		break;
	default:
		break;
	}

	switch (cec->rx) {
	case STATE_DONE:
		cec_received_msg(cec->adap, &cec->msg);
		cec->rx = STATE_IDLE;
		break;
	default:
		break;
	}

	return IRQ_HANDLED;
}
Пример #3
0
static void vivid_cec_xfer_done_worker(struct work_struct *work)
{
	struct vivid_cec_work *cw =
		container_of(work, struct vivid_cec_work, work.work);
	struct vivid_dev *dev = cw->dev;
	struct cec_adapter *adap = cw->adap;
	bool is_poll = cw->msg.len == 1;
	u8 dest = cec_msg_destination(&cw->msg);
	struct cec_adapter *dest_adap = NULL;
	bool valid_dest;
	unsigned int i;

	valid_dest = cec_msg_is_broadcast(&cw->msg);
	if (!valid_dest) {
		dest_adap = vivid_cec_find_dest_adap(dev, adap, dest);
		if (dest_adap)
			valid_dest = true;
	}
	cw->tx_status = valid_dest ? CEC_TX_STATUS_OK : CEC_TX_STATUS_NACK;
	spin_lock(&dev->cec_slock);
	dev->cec_xfer_time_jiffies = 0;
	dev->cec_xfer_start_jiffies = 0;
	list_del(&cw->list);
	spin_unlock(&dev->cec_slock);
	cec_transmit_done(cw->adap, cw->tx_status, 0, valid_dest ? 0 : 1, 0, 0);

	if (!is_poll && dest_adap) {
		/* Directed message */
		cec_received_msg(dest_adap, &cw->msg);
	} else if (!is_poll && valid_dest) {
		/* Broadcast message */
		if (adap != dev->cec_rx_adap &&
		    dev->cec_rx_adap->log_addrs.log_addr_mask)
			cec_received_msg(dev->cec_rx_adap, &cw->msg);
		for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++) {
			if (adap == dev->cec_tx_adap[i] ||
			    !dev->cec_tx_adap[i]->log_addrs.log_addr_mask)
				continue;
			cec_received_msg(dev->cec_tx_adap[i], &cw->msg);
		}
	}
	kfree(cw);
}
Пример #4
0
static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
{
	struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
	uint8_t *cec_message = cros_ec->event_data.data.cec_message;
	unsigned int len = cros_ec->event_size;

	cros_ec_cec->rx_msg.len = len;
	memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);

	cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg);
}
Пример #5
0
static void meson_ao_cec_irq_rx(struct meson_ao_cec_device *ao_cec)
{
	int i, ret = 0;
	u8 reg;

	meson_ao_cec_read(ao_cec, CEC_RX_MSG_STATUS, &reg, &ret);
	if (reg != RX_DONE)
		goto rx_out;

	meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG, &reg, &ret);
	if (reg != 1)
		goto rx_out;

	meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH, &reg, &ret);

	ao_cec->rx_msg.len = reg + 1;
	if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE)
		ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE;

	for (i = 0; i < ao_cec->rx_msg.len; i++) {
		u8 byte;

		meson_ao_cec_read(ao_cec, CEC_RX_MSG_0_HEADER + i, &byte, &ret);

		ao_cec->rx_msg.msg[i] = byte;
	}

	if (ret)
		goto rx_out;

	cec_received_msg(ao_cec->adap, &ao_cec->rx_msg);

rx_out:
	/* Clear Interruption */
	writel_relaxed(CEC_INTR_RX, ao_cec->base + CEC_INTR_CLR_REG);

	/* Ack RX message */
	meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_ACK_CURRENT, &ret);
	meson_ao_cec_write(ao_cec, CEC_RX_MSG_CMD, RX_NO_OP, &ret);

	/* Clear RX buffer */
	meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_START, &ret);
	meson_ao_cec_write(ao_cec, CEC_RX_CLEAR_BUF, CLEAR_STOP, &ret);
}
Пример #6
0
static irqreturn_t tegra_cec_irq_thread_handler(int irq, void *data)
{
	struct device *dev = data;
	struct tegra_cec *cec = dev_get_drvdata(dev);

	if (cec->tx_done) {
		cec_transmit_attempt_done(cec->adap, cec->tx_status);
		cec->tx_done = false;
	}
	if (cec->rx_done) {
		struct cec_msg msg = {};

		msg.len = cec->rx_buf_cnt;
		memcpy(msg.msg, cec->rx_buf, msg.len);
		cec_received_msg(cec->adap, &msg);
		cec->rx_done = false;
		cec->rx_buf_cnt = 0;
	}
	return IRQ_HANDLED;
}
Пример #7
0
static void rain_process_msg(struct rain *rain)
{
	struct cec_msg msg = {};
	const char *cmd = rain->cmd + 3;
	int stat = -1;

	for (; *cmd; cmd++) {
		if (!isxdigit(*cmd))
			continue;
		if (isxdigit(cmd[0]) && isxdigit(cmd[1])) {
			if (msg.len == CEC_MAX_MSG_SIZE)
				break;
			if (hex2bin(msg.msg + msg.len, cmd, 1))
				continue;
			msg.len++;
			cmd++;
			continue;
		}
		if (!cmd[1])
			stat = hex_to_bin(cmd[0]);
		break;
	}

	if (rain->cmd[0] == 'R') {
		if (stat == 1 || stat == 2)
			cec_received_msg(rain->adap, &msg);
		return;
	}

	switch (stat) {
	case 1:
		cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_OK);
		break;
	case 2:
		cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_NACK);
		break;
	default:
		cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_LOW_DRIVE);
		break;
	}
}
Пример #8
0
static int drm_dp_cec_received(struct drm_dp_aux *aux)
{
	struct cec_adapter *adap = aux->cec.adap;
	struct cec_msg msg;
	u8 rx_msg_info;
	ssize_t err;

	err = drm_dp_dpcd_readb(aux, DP_CEC_RX_MESSAGE_INFO, &rx_msg_info);
	if (err < 0)
		return err;

	if (!(rx_msg_info & DP_CEC_RX_MESSAGE_ENDED))
		return 0;

	msg.len = (rx_msg_info & DP_CEC_RX_MESSAGE_LEN_MASK) + 1;
	err = drm_dp_dpcd_read(aux, DP_CEC_RX_MESSAGE_BUFFER, msg.msg, msg.len);
	if (err < 0)
		return err;

	cec_received_msg(adap, &msg);
	return 0;
}
Пример #9
0
static void stih_rx_done(struct stih_cec *cec, u32 status)
{
	struct cec_msg msg = {};
	u8 i;

	if (status & CEC_RX_ERROR_MIN)
		return;

	if (status & CEC_RX_ERROR_MAX)
		return;

	msg.len = readl(cec->regs + CEC_DATA_ARRAY_STATUS) & 0x1f;

	if (!msg.len)
		return;

	if (msg.len > 16)
		msg.len = 16;

	for (i = 0; i < msg.len; i++)
		msg.msg[i] = readl(cec->regs + CEC_RX_DATA_BASE + i);

	cec_received_msg(cec->adap, &msg);
}