[PATCH 4/9] media: cros-ec-cec: Support multiple ports in write command

From: Reka Norman
Date: Mon Aug 14 2023 - 00:36:44 EST


Add a v1 of the CEC write command which contains a port parameter. Check
which versions of the write command the EC supports and use the highest
supported version. If it only supports v0, check that there is only one
port. With v0, the EC will assume all write commands are for port 0.

Signed-off-by: Reka Norman <rekanorman@xxxxxxxxxxxx>
---

.../media/cec/platform/cros-ec/cros-ec-cec.c | 54 +++++++++++++++++--
.../linux/platform_data/cros_ec_commands.h | 12 +++++
2 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/drivers/media/cec/platform/cros-ec/cros-ec-cec.c b/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
index e969031e1e0e..d674a432dfdd 100644
--- a/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
+++ b/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
@@ -47,12 +47,14 @@ struct cros_ec_cec_port {
*
* @cros_ec: Pointer to EC device
* @notifier: Notifier info for responding to EC events
+ * @write_cmd_version: Highest supported version of EC_CMD_CEC_WRITE_MSG.
* @num_ports: Number of CEC ports
* @ports: Array of ports
*/
struct cros_ec_cec {
struct cros_ec_device *cros_ec;
struct notifier_block notifier;
+ int write_cmd_version;
int num_ports;
struct cros_ec_cec_port *ports[EC_CEC_MAX_PORTS];
};
@@ -141,12 +143,22 @@ static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts,
struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec;
struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
struct ec_params_cec_write params;
+ struct ec_params_cec_write_v1 params_v1;
int ret;

- memcpy(params.msg, cec_msg->msg, cec_msg->len);
+ if (cros_ec_cec->write_cmd_version == 0) {
+ memcpy(params.msg, cec_msg->msg, cec_msg->len);
+ ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_WRITE_MSG, &params,
+ cec_msg->len, NULL, 0);
+ } else {
+ params_v1.port = port->port_num;
+ params_v1.msg_len = cec_msg->len;
+ memcpy(params_v1.msg, cec_msg->msg, cec_msg->len);
+ ret = cros_ec_cmd(cros_ec, cros_ec_cec->write_cmd_version,
+ EC_CMD_CEC_WRITE_MSG, &params_v1,
+ sizeof(params_v1), NULL, 0);
+ }

- ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_WRITE_MSG, &params,
- cec_msg->len, NULL, 0);
if (ret < 0) {
dev_err(cros_ec->dev,
"error writing CEC msg on EC: %d\n", ret);
@@ -285,6 +297,38 @@ static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,

#endif

+static int cros_ec_cec_get_write_cmd_version(struct cros_ec_cec *cros_ec_cec)
+{
+ struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+ struct ec_params_get_cmd_versions_v1 params = {
+ .cmd = EC_CMD_CEC_WRITE_MSG,
+ };
+ struct ec_response_get_cmd_versions response;
+ int ret;
+
+ ret = cros_ec_cmd(cros_ec, 1, EC_CMD_GET_CMD_VERSIONS, &params,
+ sizeof(params), &response, sizeof(response));
+ if (ret < 0) {
+ dev_err(cros_ec->dev,
+ "error getting CEC write command version: %d\n", ret);
+ return ret;
+ }
+
+ if (response.version_mask & EC_VER_MASK(1)) {
+ cros_ec_cec->write_cmd_version = 1;
+ } else {
+ if (cros_ec_cec->num_ports != 1) {
+ dev_err(cros_ec->dev,
+ "v0 write command only supports 1 port, %d reported\n",
+ cros_ec_cec->num_ports);
+ return -EINVAL;
+ }
+ cros_ec_cec->write_cmd_version = 0;
+ }
+
+ return 0;
+}
+
static int cros_ec_cec_init_port(struct device *dev,
struct cros_ec_cec *cros_ec_cec,
int port_num, struct device *hdmi_dev,
@@ -354,6 +398,10 @@ static int cros_ec_cec_probe(struct platform_device *pdev)

cros_ec_cec->num_ports = CEC_NUM_PORTS;

+ ret = cros_ec_cec_get_write_cmd_version(cros_ec_cec);
+ if (ret)
+ return ret;
+
for (int i = 0; i < cros_ec_cec->num_ports; i++) {
ret = cros_ec_cec_init_port(&pdev->dev, cros_ec_cec, i,
hdmi_dev, conn);
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index e8bb05db360f..9a0c6e28f370 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -4451,6 +4451,18 @@ struct ec_params_cec_write {
uint8_t msg[MAX_CEC_MSG_LEN];
} __ec_align1;

+/**
+ * struct ec_params_cec_write_v1 - Message to write to the CEC bus
+ * @port: CEC port to write the message on
+ * @msg_len: length of msg in bytes
+ * @msg: message content to write to the CEC bus
+ */
+struct ec_params_cec_write_v1 {
+ uint8_t port;
+ uint8_t msg_len;
+ uint8_t msg[MAX_CEC_MSG_LEN];
+} __ec_align1;
+
/* Set various CEC parameters */
#define EC_CMD_CEC_SET 0x00BA

--
2.41.0.640.ga95def55d0-goog