ret = regmap_write(ch7322->regmap, CH7322_WRITE, len - 1); if (ret) return ret;
for (i = 0; i < len; i++) {
ret = regmap_write(ch7322->regmap,
CH7322_WRBUF + i, msg->msg[i]); if (ret) return ret;
}
return 0;
}
staticint ch7322_receive_message(struct ch7322 *ch7322, struct cec_msg *msg)
{ unsignedint val; int ret = 0; int i;
WARN_ON(!mutex_is_locked(&ch7322->mutex));
ret = regmap_read(ch7322->regmap, CH7322_READ, &val); if (ret) return ret;
/* Message not ready */ if (!(val & CH7322_READ_NRDT)) return -EIO;
msg->len = (val & CH7322_READ_NMASK) + 1;
/* Read entire RDBUF to clear state */ for (i = 0; i < CH7322_RDBUF_LEN; i++) {
ret = regmap_read(ch7322->regmap, CH7322_RDBUF + i, &val); if (ret) return ret;
msg->msg[i] = (u8)val;
}
mutex_lock(&ch7322->mutex);
ret = regmap_read(ch7322->regmap, CH7322_WRITE, &val);
flags = ch7322->tx_flags;
mutex_unlock(&ch7322->mutex);
/* * The device returns a one-bit OK status which usually means ACK but * actually means NACK when sending a logical address query or a * broadcast.
*/ if (ret)
status = CEC_TX_STATUS_ERROR; elseif ((val & CH7322_WRITE_BOK) && (flags & CH7322_TX_FLAG_NACK))
status = CEC_TX_STATUS_NACK; elseif (val & CH7322_WRITE_BOK)
status = CEC_TX_STATUS_OK; elseif (flags & CH7322_TX_FLAG_NACK)
status = CEC_TX_STATUS_OK; else
status = CEC_TX_STATUS_NACK;
if (status == CEC_TX_STATUS_NACK && (flags & CH7322_TX_FLAG_RETRY))
status |= CEC_TX_STATUS_MAX_RETRIES;
cec_transmit_attempt_done(ch7322->cec, status);
}
staticvoid ch7322_rx_done(struct ch7322 *ch7322)
{ struct cec_msg msg; int ret;
mutex_lock(&ch7322->mutex);
ret = ch7322_receive_message(ch7322, &msg);
mutex_unlock(&ch7322->mutex);
/* * This device can either monitor the DDC lines to obtain the physical address * or it can allow the host to program it. This driver lets the device obtain * it.
*/ staticvoid ch7322_phys_addr(struct ch7322 *ch7322)
{ unsignedint pah, pal; int ret = 0;
mutex_lock(&ch7322->mutex);
ret |= regmap_read(ch7322->regmap, CH7322_PARH, &pah);
ret |= regmap_read(ch7322->regmap, CH7322_PARL, &pal);
mutex_unlock(&ch7322->mutex);
if (ret)
dev_err(&ch7322->i2c->dev, "phys addr error\n"); else
cec_s_phys_addr(ch7322->cec, pal | (pah << 8), false);
}
if (IS_ERR(ch7322->cec)) {
ret = PTR_ERR(ch7322->cec); goto err_mutex;
}
ch7322->cec->adap_controls_phys_addr = true;
if (hdmi_dev) {
notifier = cec_notifier_cec_adap_register(hdmi_dev,
port_name,
ch7322->cec); if (!notifier) {
ret = -ENOMEM; goto err_cec;
}
}
/* Configure, mask, and clear interrupt */
ret = regmap_write(ch7322->regmap, CH7322_CFG1, 0); if (ret) goto err_notifier;
ret = regmap_write(ch7322->regmap, CH7322_INTCTL, CH7322_INTCTL_INTPB); if (ret) goto err_notifier;
ret = regmap_write(ch7322->regmap, CH7322_INTDATA, 0xff); if (ret) goto err_notifier;
/* If HPD is up read physical address */
ret = regmap_read(ch7322->regmap, CH7322_ADDLR, &val); if (ret) goto err_notifier; if (val & CH7322_ADDLR_HPD)
ch7322_phys_addr(ch7322);
ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
ch7322_irq,
IRQF_ONESHOT | IRQF_TRIGGER_RISING,
client->name, ch7322); if (ret) goto err_notifier;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.