예제 #1
0
파일: cros-ec-cec.c 프로젝트: avagin/linux
static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
{
	struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
	uint32_t events = cros_ec->event_data.data.cec_events;

	if (events & EC_MKBP_CEC_SEND_OK)
		cec_transmit_attempt_done(cros_ec_cec->adap,
					  CEC_TX_STATUS_OK);

	/* FW takes care of all retries, tell core to avoid more retries */
	if (events & EC_MKBP_CEC_SEND_FAILED)
		cec_transmit_attempt_done(cros_ec_cec->adap,
					  CEC_TX_STATUS_MAX_RETRIES |
					  CEC_TX_STATUS_NACK);
}
예제 #2
0
파일: ao-cec.c 프로젝트: avagin/linux
static void meson_ao_cec_irq_tx(struct meson_ao_cec_device *ao_cec)
{
	unsigned long tx_status = 0;
	u8 stat;
	int ret = 0;

	meson_ao_cec_read(ao_cec, CEC_TX_MSG_STATUS, &stat, &ret);
	if (ret)
		goto tx_reg_err;

	switch (stat) {
	case TX_DONE:
		tx_status = CEC_TX_STATUS_OK;
		break;

	case TX_BUSY:
		tx_status = CEC_TX_STATUS_ARB_LOST;
		break;

	case TX_IDLE:
		tx_status = CEC_TX_STATUS_LOW_DRIVE;
		break;

	case TX_ERROR:
	default:
		tx_status = CEC_TX_STATUS_NACK;
		break;
	}

	/* Clear Interruption */
	writel_relaxed(CEC_INTR_TX, ao_cec->base + CEC_INTR_CLR_REG);

	/* Stop TX */
	meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_NO_OP, &ret);
	if (ret)
		goto tx_reg_err;

	cec_transmit_attempt_done(ao_cec->adap, tx_status);
	return;

tx_reg_err:
	cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR);
}
예제 #3
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;
	}
}
예제 #4
0
static void drm_dp_cec_handle_irq(struct drm_dp_aux *aux)
{
	struct cec_adapter *adap = aux->cec.adap;
	u8 flags;

	if (drm_dp_dpcd_readb(aux, DP_CEC_TUNNELING_IRQ_FLAGS, &flags) < 0)
		return;

	if (flags & DP_CEC_RX_MESSAGE_INFO_VALID)
		drm_dp_cec_received(aux);

	if (flags & DP_CEC_TX_MESSAGE_SENT)
		cec_transmit_attempt_done(adap, CEC_TX_STATUS_OK);
	else if (flags & DP_CEC_TX_LINE_ERROR)
		cec_transmit_attempt_done(adap, CEC_TX_STATUS_ERROR |
						CEC_TX_STATUS_MAX_RETRIES);
	else if (flags &
		 (DP_CEC_TX_ADDRESS_NACK_ERROR | DP_CEC_TX_DATA_NACK_ERROR))
		cec_transmit_attempt_done(adap, CEC_TX_STATUS_NACK |
						CEC_TX_STATUS_MAX_RETRIES);
	drm_dp_dpcd_writeb(aux, DP_CEC_TUNNELING_IRQ_FLAGS, flags);
}
예제 #5
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;
}