1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * CEC driver for ChromeOS Embedded Controller 4 * 5 * Copyright (c) 2018 BayLibre, SAS 6 * Author: Neil Armstrong <narmstrong@baylibre.com> 7 */ 8 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/dmi.h> 13 #include <linux/pci.h> 14 #include <linux/cec.h> 15 #include <linux/slab.h> 16 #include <linux/interrupt.h> 17 #include <linux/platform_data/cros_ec_commands.h> 18 #include <linux/platform_data/cros_ec_proto.h> 19 #include <media/cec.h> 20 #include <media/cec-notifier.h> 21 22 #define DRV_NAME "cros-ec-cec" 23 24 /* Only one port is supported for now */ 25 #define CEC_NUM_PORTS 1 26 #define CEC_PORT 0 27 28 /** 29 * struct cros_ec_cec_port - Driver data for a single EC CEC port 30 * 31 * @port_num: port number 32 * @adap: CEC adapter 33 * @notify: CEC notifier pointer 34 * @rx_msg: storage for a received message 35 * @cros_ec_cec: pointer to the parent struct 36 */ 37 struct cros_ec_cec_port { 38 int port_num; 39 struct cec_adapter *adap; 40 struct cec_notifier *notify; 41 struct cec_msg rx_msg; 42 struct cros_ec_cec *cros_ec_cec; 43 }; 44 45 /** 46 * struct cros_ec_cec - Driver data for EC CEC 47 * 48 * @cros_ec: Pointer to EC device 49 * @notifier: Notifier info for responding to EC events 50 * @write_cmd_version: Highest supported version of EC_CMD_CEC_WRITE_MSG. 51 * @num_ports: Number of CEC ports 52 * @ports: Array of ports 53 */ 54 struct cros_ec_cec { 55 struct cros_ec_device *cros_ec; 56 struct notifier_block notifier; 57 int write_cmd_version; 58 int num_ports; 59 struct cros_ec_cec_port *ports[EC_CEC_MAX_PORTS]; 60 }; 61 62 static void handle_cec_message(struct cros_ec_cec *cros_ec_cec) 63 { 64 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 65 uint8_t *cec_message = cros_ec->event_data.data.cec_message; 66 unsigned int len = cros_ec->event_size; 67 struct cros_ec_cec_port *port = cros_ec_cec->ports[CEC_PORT]; 68 69 if (len > CEC_MAX_MSG_SIZE) 70 len = CEC_MAX_MSG_SIZE; 71 port->rx_msg.len = len; 72 memcpy(port->rx_msg.msg, cec_message, len); 73 74 cec_received_msg(port->adap, &port->rx_msg); 75 } 76 77 static void handle_cec_event(struct cros_ec_cec *cros_ec_cec) 78 { 79 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 80 uint32_t cec_events = cros_ec->event_data.data.cec_events; 81 uint32_t port_num = EC_MKBP_EVENT_CEC_GET_PORT(cec_events); 82 uint32_t events = EC_MKBP_EVENT_CEC_GET_EVENTS(cec_events); 83 struct cros_ec_cec_port *port; 84 85 if (port_num >= cros_ec_cec->num_ports) { 86 dev_err(cros_ec->dev, 87 "received CEC event for invalid port %d\n", port_num); 88 return; 89 } 90 port = cros_ec_cec->ports[port_num]; 91 92 if (events & EC_MKBP_CEC_SEND_OK) 93 cec_transmit_attempt_done(port->adap, CEC_TX_STATUS_OK); 94 95 /* FW takes care of all retries, tell core to avoid more retries */ 96 if (events & EC_MKBP_CEC_SEND_FAILED) 97 cec_transmit_attempt_done(port->adap, 98 CEC_TX_STATUS_MAX_RETRIES | 99 CEC_TX_STATUS_NACK); 100 } 101 102 static int cros_ec_cec_event(struct notifier_block *nb, 103 unsigned long queued_during_suspend, 104 void *_notify) 105 { 106 struct cros_ec_cec *cros_ec_cec; 107 struct cros_ec_device *cros_ec; 108 109 cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier); 110 cros_ec = cros_ec_cec->cros_ec; 111 112 if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_EVENT) { 113 handle_cec_event(cros_ec_cec); 114 return NOTIFY_OK; 115 } 116 117 if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) { 118 handle_cec_message(cros_ec_cec); 119 return NOTIFY_OK; 120 } 121 122 return NOTIFY_DONE; 123 } 124 125 static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) 126 { 127 struct cros_ec_cec_port *port = adap->priv; 128 struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; 129 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 130 struct ec_params_cec_set params = { 131 .cmd = CEC_CMD_LOGICAL_ADDRESS, 132 .port = port->port_num, 133 .val = logical_addr, 134 }; 135 int ret; 136 137 ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), 138 NULL, 0); 139 if (ret < 0) { 140 dev_err(cros_ec->dev, 141 "error setting CEC logical address on EC: %d\n", ret); 142 return ret; 143 } 144 145 return 0; 146 } 147 148 static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, 149 u32 signal_free_time, struct cec_msg *cec_msg) 150 { 151 struct cros_ec_cec_port *port = adap->priv; 152 struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; 153 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 154 struct ec_params_cec_write params; 155 struct ec_params_cec_write_v1 params_v1; 156 int ret; 157 158 if (cros_ec_cec->write_cmd_version == 0) { 159 memcpy(params.msg, cec_msg->msg, cec_msg->len); 160 ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_WRITE_MSG, ¶ms, 161 cec_msg->len, NULL, 0); 162 } else { 163 params_v1.port = port->port_num; 164 params_v1.msg_len = cec_msg->len; 165 memcpy(params_v1.msg, cec_msg->msg, cec_msg->len); 166 ret = cros_ec_cmd(cros_ec, cros_ec_cec->write_cmd_version, 167 EC_CMD_CEC_WRITE_MSG, ¶ms_v1, 168 sizeof(params_v1), NULL, 0); 169 } 170 171 if (ret < 0) { 172 dev_err(cros_ec->dev, 173 "error writing CEC msg on EC: %d\n", ret); 174 return ret; 175 } 176 177 return 0; 178 } 179 180 static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) 181 { 182 struct cros_ec_cec_port *port = adap->priv; 183 struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; 184 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 185 struct ec_params_cec_set params = { 186 .cmd = CEC_CMD_ENABLE, 187 .port = port->port_num, 188 .val = enable, 189 }; 190 int ret; 191 192 ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), 193 NULL, 0); 194 if (ret < 0) { 195 dev_err(cros_ec->dev, 196 "error %sabling CEC on EC: %d\n", 197 (enable ? "en" : "dis"), ret); 198 return ret; 199 } 200 201 return 0; 202 } 203 204 static const struct cec_adap_ops cros_ec_cec_ops = { 205 .adap_enable = cros_ec_cec_adap_enable, 206 .adap_log_addr = cros_ec_cec_set_log_addr, 207 .adap_transmit = cros_ec_cec_transmit, 208 }; 209 210 #ifdef CONFIG_PM_SLEEP 211 static int cros_ec_cec_suspend(struct device *dev) 212 { 213 struct platform_device *pdev = to_platform_device(dev); 214 struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); 215 216 if (device_may_wakeup(dev)) 217 enable_irq_wake(cros_ec_cec->cros_ec->irq); 218 219 return 0; 220 } 221 222 static int cros_ec_cec_resume(struct device *dev) 223 { 224 struct platform_device *pdev = to_platform_device(dev); 225 struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); 226 227 if (device_may_wakeup(dev)) 228 disable_irq_wake(cros_ec_cec->cros_ec->irq); 229 230 return 0; 231 } 232 #endif 233 234 static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops, 235 cros_ec_cec_suspend, cros_ec_cec_resume); 236 237 #if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI) 238 239 /* 240 * The Firmware only handles a single CEC interface tied to a single HDMI 241 * connector we specify along with the DRM device name handling the HDMI output 242 */ 243 244 struct cec_dmi_match { 245 const char *sys_vendor; 246 const char *product_name; 247 const char *devname; 248 const char *conn; 249 }; 250 251 static const struct cec_dmi_match cec_dmi_match_table[] = { 252 /* Google Fizz */ 253 { "Google", "Fizz", "0000:00:02.0", "Port B" }, 254 /* Google Brask */ 255 { "Google", "Brask", "0000:00:02.0", "Port B" }, 256 /* Google Moli */ 257 { "Google", "Moli", "0000:00:02.0", "Port B" }, 258 /* Google Kinox */ 259 { "Google", "Kinox", "0000:00:02.0", "Port B" }, 260 /* Google Kuldax */ 261 { "Google", "Kuldax", "0000:00:02.0", "Port B" }, 262 /* Google Aurash */ 263 { "Google", "Aurash", "0000:00:02.0", "Port B" }, 264 /* Google Gladios */ 265 { "Google", "Gladios", "0000:00:02.0", "Port B" }, 266 /* Google Lisbon */ 267 { "Google", "Lisbon", "0000:00:02.0", "Port B" }, 268 }; 269 270 static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, 271 const char **conn) 272 { 273 int i; 274 275 for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) { 276 const struct cec_dmi_match *m = &cec_dmi_match_table[i]; 277 278 if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) && 279 dmi_match(DMI_PRODUCT_NAME, m->product_name)) { 280 struct device *d; 281 282 /* Find the device, bail out if not yet registered */ 283 d = bus_find_device_by_name(&pci_bus_type, NULL, 284 m->devname); 285 if (!d) 286 return ERR_PTR(-EPROBE_DEFER); 287 put_device(d); 288 *conn = m->conn; 289 return d; 290 } 291 } 292 293 /* Hardware support must be added in the cec_dmi_match_table */ 294 dev_warn(dev, "CEC notifier not configured for this hardware\n"); 295 296 return ERR_PTR(-ENODEV); 297 } 298 299 #else 300 301 static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, 302 const char **conn) 303 { 304 return ERR_PTR(-ENODEV); 305 } 306 307 #endif 308 309 static int cros_ec_cec_get_write_cmd_version(struct cros_ec_cec *cros_ec_cec) 310 { 311 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 312 struct ec_params_get_cmd_versions_v1 params = { 313 .cmd = EC_CMD_CEC_WRITE_MSG, 314 }; 315 struct ec_response_get_cmd_versions response; 316 int ret; 317 318 ret = cros_ec_cmd(cros_ec, 1, EC_CMD_GET_CMD_VERSIONS, ¶ms, 319 sizeof(params), &response, sizeof(response)); 320 if (ret < 0) { 321 dev_err(cros_ec->dev, 322 "error getting CEC write command version: %d\n", ret); 323 return ret; 324 } 325 326 if (response.version_mask & EC_VER_MASK(1)) { 327 cros_ec_cec->write_cmd_version = 1; 328 } else { 329 if (cros_ec_cec->num_ports != 1) { 330 dev_err(cros_ec->dev, 331 "v0 write command only supports 1 port, %d reported\n", 332 cros_ec_cec->num_ports); 333 return -EINVAL; 334 } 335 cros_ec_cec->write_cmd_version = 0; 336 } 337 338 return 0; 339 } 340 341 static int cros_ec_cec_init_port(struct device *dev, 342 struct cros_ec_cec *cros_ec_cec, 343 int port_num, struct device *hdmi_dev, 344 const char *conn) 345 { 346 struct cros_ec_cec_port *port; 347 int ret; 348 349 port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); 350 if (!port) 351 return -ENOMEM; 352 353 port->cros_ec_cec = cros_ec_cec; 354 port->port_num = port_num; 355 356 port->adap = cec_allocate_adapter(&cros_ec_cec_ops, port, DRV_NAME, 357 CEC_CAP_DEFAULTS | 358 CEC_CAP_CONNECTOR_INFO, 1); 359 if (IS_ERR(port->adap)) 360 return PTR_ERR(port->adap); 361 362 port->notify = cec_notifier_cec_adap_register(hdmi_dev, conn, 363 port->adap); 364 if (!port->notify) { 365 ret = -ENOMEM; 366 goto out_probe_adapter; 367 } 368 369 ret = cec_register_adapter(port->adap, dev); 370 if (ret < 0) 371 goto out_probe_notify; 372 373 cros_ec_cec->ports[port_num] = port; 374 375 return 0; 376 377 out_probe_notify: 378 cec_notifier_cec_adap_unregister(port->notify, port->adap); 379 out_probe_adapter: 380 cec_delete_adapter(port->adap); 381 return ret; 382 } 383 384 static int cros_ec_cec_probe(struct platform_device *pdev) 385 { 386 struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); 387 struct cros_ec_device *cros_ec = ec_dev->ec_dev; 388 struct cros_ec_cec *cros_ec_cec; 389 struct cros_ec_cec_port *port; 390 struct device *hdmi_dev; 391 const char *conn = NULL; 392 int ret; 393 394 hdmi_dev = cros_ec_cec_find_hdmi_dev(&pdev->dev, &conn); 395 if (IS_ERR(hdmi_dev)) 396 return PTR_ERR(hdmi_dev); 397 398 cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec), 399 GFP_KERNEL); 400 if (!cros_ec_cec) 401 return -ENOMEM; 402 403 platform_set_drvdata(pdev, cros_ec_cec); 404 cros_ec_cec->cros_ec = cros_ec; 405 406 device_init_wakeup(&pdev->dev, 1); 407 408 cros_ec_cec->num_ports = CEC_NUM_PORTS; 409 410 ret = cros_ec_cec_get_write_cmd_version(cros_ec_cec); 411 if (ret) 412 return ret; 413 414 for (int i = 0; i < cros_ec_cec->num_ports; i++) { 415 ret = cros_ec_cec_init_port(&pdev->dev, cros_ec_cec, i, 416 hdmi_dev, conn); 417 if (ret) 418 goto unregister_ports; 419 } 420 421 /* Get CEC events from the EC. */ 422 cros_ec_cec->notifier.notifier_call = cros_ec_cec_event; 423 ret = blocking_notifier_chain_register(&cros_ec->event_notifier, 424 &cros_ec_cec->notifier); 425 if (ret) { 426 dev_err(&pdev->dev, "failed to register notifier\n"); 427 goto unregister_ports; 428 } 429 430 return 0; 431 432 unregister_ports: 433 /* 434 * Unregister any adapters which have been registered. We don't add the 435 * port to the array until the adapter has been registered successfully, 436 * so any non-NULL ports must have been registered. 437 */ 438 for (int i = 0; i < cros_ec_cec->num_ports; i++) { 439 port = cros_ec_cec->ports[i]; 440 if (!port) 441 break; 442 cec_notifier_cec_adap_unregister(port->notify, port->adap); 443 cec_unregister_adapter(port->adap); 444 } 445 return ret; 446 } 447 448 static void cros_ec_cec_remove(struct platform_device *pdev) 449 { 450 struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); 451 struct device *dev = &pdev->dev; 452 struct cros_ec_cec_port *port; 453 int ret; 454 455 /* 456 * blocking_notifier_chain_unregister() only fails if the notifier isn't 457 * in the list. We know it was added to it by .probe(), so there should 458 * be no need for error checking. Be cautious and still check. 459 */ 460 ret = blocking_notifier_chain_unregister( 461 &cros_ec_cec->cros_ec->event_notifier, 462 &cros_ec_cec->notifier); 463 if (ret) 464 dev_err(dev, "failed to unregister notifier\n"); 465 466 for (int i = 0; i < cros_ec_cec->num_ports; i++) { 467 port = cros_ec_cec->ports[i]; 468 cec_notifier_cec_adap_unregister(port->notify, port->adap); 469 cec_unregister_adapter(port->adap); 470 } 471 } 472 473 static struct platform_driver cros_ec_cec_driver = { 474 .probe = cros_ec_cec_probe, 475 .remove_new = cros_ec_cec_remove, 476 .driver = { 477 .name = DRV_NAME, 478 .pm = &cros_ec_cec_pm_ops, 479 }, 480 }; 481 482 module_platform_driver(cros_ec_cec_driver); 483 484 MODULE_DESCRIPTION("CEC driver for ChromeOS ECs"); 485 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 486 MODULE_LICENSE("GPL"); 487 MODULE_ALIAS("platform:" DRV_NAME); 488