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); }
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; }
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); }
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); }
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, ®, &ret); if (reg != RX_DONE) goto rx_out; meson_ao_cec_read(ao_cec, CEC_RX_NUM_MSG, ®, &ret); if (reg != 1) goto rx_out; meson_ao_cec_read(ao_cec, CEC_RX_MSG_LENGTH, ®, &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); }
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; }
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; } }
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; }
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); }