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 * @num_ports: Number of CEC ports 51 * @ports: Array of ports 52 */ 53 struct cros_ec_cec { 54 struct cros_ec_device *cros_ec; 55 struct notifier_block notifier; 56 int num_ports; 57 struct cros_ec_cec_port *ports[EC_CEC_MAX_PORTS]; 58 }; 59 60 static void handle_cec_message(struct cros_ec_cec *cros_ec_cec) 61 { 62 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 63 uint8_t *cec_message = cros_ec->event_data.data.cec_message; 64 unsigned int len = cros_ec->event_size; 65 struct cros_ec_cec_port *port = cros_ec_cec->ports[CEC_PORT]; 66 67 if (len > CEC_MAX_MSG_SIZE) 68 len = CEC_MAX_MSG_SIZE; 69 port->rx_msg.len = len; 70 memcpy(port->rx_msg.msg, cec_message, len); 71 72 cec_received_msg(port->adap, &port->rx_msg); 73 } 74 75 static void handle_cec_event(struct cros_ec_cec *cros_ec_cec) 76 { 77 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 78 uint32_t events = cros_ec->event_data.data.cec_events; 79 struct cros_ec_cec_port *port = cros_ec_cec->ports[CEC_PORT]; 80 81 if (events & EC_MKBP_CEC_SEND_OK) 82 cec_transmit_attempt_done(port->adap, CEC_TX_STATUS_OK); 83 84 /* FW takes care of all retries, tell core to avoid more retries */ 85 if (events & EC_MKBP_CEC_SEND_FAILED) 86 cec_transmit_attempt_done(port->adap, 87 CEC_TX_STATUS_MAX_RETRIES | 88 CEC_TX_STATUS_NACK); 89 } 90 91 static int cros_ec_cec_event(struct notifier_block *nb, 92 unsigned long queued_during_suspend, 93 void *_notify) 94 { 95 struct cros_ec_cec *cros_ec_cec; 96 struct cros_ec_device *cros_ec; 97 98 cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier); 99 cros_ec = cros_ec_cec->cros_ec; 100 101 if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_EVENT) { 102 handle_cec_event(cros_ec_cec); 103 return NOTIFY_OK; 104 } 105 106 if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) { 107 handle_cec_message(cros_ec_cec); 108 return NOTIFY_OK; 109 } 110 111 return NOTIFY_DONE; 112 } 113 114 static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) 115 { 116 struct cros_ec_cec_port *port = adap->priv; 117 struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; 118 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 119 struct ec_params_cec_set params = { 120 .cmd = CEC_CMD_LOGICAL_ADDRESS, 121 .val = logical_addr, 122 }; 123 int ret; 124 125 ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), 126 NULL, 0); 127 if (ret < 0) { 128 dev_err(cros_ec->dev, 129 "error setting CEC logical address on EC: %d\n", ret); 130 return ret; 131 } 132 133 return 0; 134 } 135 136 static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, 137 u32 signal_free_time, struct cec_msg *cec_msg) 138 { 139 struct cros_ec_cec_port *port = adap->priv; 140 struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; 141 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 142 struct ec_params_cec_write params; 143 int ret; 144 145 memcpy(params.msg, cec_msg->msg, cec_msg->len); 146 147 ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_WRITE_MSG, ¶ms, 148 cec_msg->len, NULL, 0); 149 if (ret < 0) { 150 dev_err(cros_ec->dev, 151 "error writing CEC msg on EC: %d\n", ret); 152 return ret; 153 } 154 155 return 0; 156 } 157 158 static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) 159 { 160 struct cros_ec_cec_port *port = adap->priv; 161 struct cros_ec_cec *cros_ec_cec = port->cros_ec_cec; 162 struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; 163 struct ec_params_cec_set params = { 164 .cmd = CEC_CMD_ENABLE, 165 .val = enable, 166 }; 167 int ret; 168 169 ret = cros_ec_cmd(cros_ec, 0, EC_CMD_CEC_SET, ¶ms, sizeof(params), 170 NULL, 0); 171 if (ret < 0) { 172 dev_err(cros_ec->dev, 173 "error %sabling CEC on EC: %d\n", 174 (enable ? "en" : "dis"), ret); 175 return ret; 176 } 177 178 return 0; 179 } 180 181 static const struct cec_adap_ops cros_ec_cec_ops = { 182 .adap_enable = cros_ec_cec_adap_enable, 183 .adap_log_addr = cros_ec_cec_set_log_addr, 184 .adap_transmit = cros_ec_cec_transmit, 185 }; 186 187 #ifdef CONFIG_PM_SLEEP 188 static int cros_ec_cec_suspend(struct device *dev) 189 { 190 struct platform_device *pdev = to_platform_device(dev); 191 struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); 192 193 if (device_may_wakeup(dev)) 194 enable_irq_wake(cros_ec_cec->cros_ec->irq); 195 196 return 0; 197 } 198 199 static int cros_ec_cec_resume(struct device *dev) 200 { 201 struct platform_device *pdev = to_platform_device(dev); 202 struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); 203 204 if (device_may_wakeup(dev)) 205 disable_irq_wake(cros_ec_cec->cros_ec->irq); 206 207 return 0; 208 } 209 #endif 210 211 static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops, 212 cros_ec_cec_suspend, cros_ec_cec_resume); 213 214 #if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI) 215 216 /* 217 * The Firmware only handles a single CEC interface tied to a single HDMI 218 * connector we specify along with the DRM device name handling the HDMI output 219 */ 220 221 struct cec_dmi_match { 222 const char *sys_vendor; 223 const char *product_name; 224 const char *devname; 225 const char *conn; 226 }; 227 228 static const struct cec_dmi_match cec_dmi_match_table[] = { 229 /* Google Fizz */ 230 { "Google", "Fizz", "0000:00:02.0", "Port B" }, 231 /* Google Brask */ 232 { "Google", "Brask", "0000:00:02.0", "Port B" }, 233 /* Google Moli */ 234 { "Google", "Moli", "0000:00:02.0", "Port B" }, 235 /* Google Kinox */ 236 { "Google", "Kinox", "0000:00:02.0", "Port B" }, 237 /* Google Kuldax */ 238 { "Google", "Kuldax", "0000:00:02.0", "Port B" }, 239 /* Google Aurash */ 240 { "Google", "Aurash", "0000:00:02.0", "Port B" }, 241 /* Google Gladios */ 242 { "Google", "Gladios", "0000:00:02.0", "Port B" }, 243 /* Google Lisbon */ 244 { "Google", "Lisbon", "0000:00:02.0", "Port B" }, 245 }; 246 247 static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, 248 const char **conn) 249 { 250 int i; 251 252 for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) { 253 const struct cec_dmi_match *m = &cec_dmi_match_table[i]; 254 255 if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) && 256 dmi_match(DMI_PRODUCT_NAME, m->product_name)) { 257 struct device *d; 258 259 /* Find the device, bail out if not yet registered */ 260 d = bus_find_device_by_name(&pci_bus_type, NULL, 261 m->devname); 262 if (!d) 263 return ERR_PTR(-EPROBE_DEFER); 264 put_device(d); 265 *conn = m->conn; 266 return d; 267 } 268 } 269 270 /* Hardware support must be added in the cec_dmi_match_table */ 271 dev_warn(dev, "CEC notifier not configured for this hardware\n"); 272 273 return ERR_PTR(-ENODEV); 274 } 275 276 #else 277 278 static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev, 279 const char **conn) 280 { 281 return ERR_PTR(-ENODEV); 282 } 283 284 #endif 285 286 static int cros_ec_cec_init_port(struct device *dev, 287 struct cros_ec_cec *cros_ec_cec, 288 int port_num, struct device *hdmi_dev, 289 const char *conn) 290 { 291 struct cros_ec_cec_port *port; 292 int ret; 293 294 port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); 295 if (!port) 296 return -ENOMEM; 297 298 port->cros_ec_cec = cros_ec_cec; 299 port->port_num = port_num; 300 301 port->adap = cec_allocate_adapter(&cros_ec_cec_ops, port, DRV_NAME, 302 CEC_CAP_DEFAULTS | 303 CEC_CAP_CONNECTOR_INFO, 1); 304 if (IS_ERR(port->adap)) 305 return PTR_ERR(port->adap); 306 307 port->notify = cec_notifier_cec_adap_register(hdmi_dev, conn, 308 port->adap); 309 if (!port->notify) { 310 ret = -ENOMEM; 311 goto out_probe_adapter; 312 } 313 314 ret = cec_register_adapter(port->adap, dev); 315 if (ret < 0) 316 goto out_probe_notify; 317 318 cros_ec_cec->ports[port_num] = port; 319 320 return 0; 321 322 out_probe_notify: 323 cec_notifier_cec_adap_unregister(port->notify, port->adap); 324 out_probe_adapter: 325 cec_delete_adapter(port->adap); 326 return ret; 327 } 328 329 static int cros_ec_cec_probe(struct platform_device *pdev) 330 { 331 struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); 332 struct cros_ec_device *cros_ec = ec_dev->ec_dev; 333 struct cros_ec_cec *cros_ec_cec; 334 struct cros_ec_cec_port *port; 335 struct device *hdmi_dev; 336 const char *conn = NULL; 337 int ret; 338 339 hdmi_dev = cros_ec_cec_find_hdmi_dev(&pdev->dev, &conn); 340 if (IS_ERR(hdmi_dev)) 341 return PTR_ERR(hdmi_dev); 342 343 cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec), 344 GFP_KERNEL); 345 if (!cros_ec_cec) 346 return -ENOMEM; 347 348 platform_set_drvdata(pdev, cros_ec_cec); 349 cros_ec_cec->cros_ec = cros_ec; 350 351 device_init_wakeup(&pdev->dev, 1); 352 353 cros_ec_cec->num_ports = CEC_NUM_PORTS; 354 355 for (int i = 0; i < cros_ec_cec->num_ports; i++) { 356 ret = cros_ec_cec_init_port(&pdev->dev, cros_ec_cec, i, 357 hdmi_dev, conn); 358 if (ret) 359 goto unregister_ports; 360 } 361 362 /* Get CEC events from the EC. */ 363 cros_ec_cec->notifier.notifier_call = cros_ec_cec_event; 364 ret = blocking_notifier_chain_register(&cros_ec->event_notifier, 365 &cros_ec_cec->notifier); 366 if (ret) { 367 dev_err(&pdev->dev, "failed to register notifier\n"); 368 goto unregister_ports; 369 } 370 371 return 0; 372 373 unregister_ports: 374 /* 375 * Unregister any adapters which have been registered. We don't add the 376 * port to the array until the adapter has been registered successfully, 377 * so any non-NULL ports must have been registered. 378 */ 379 for (int i = 0; i < cros_ec_cec->num_ports; i++) { 380 port = cros_ec_cec->ports[i]; 381 if (!port) 382 break; 383 cec_notifier_cec_adap_unregister(port->notify, port->adap); 384 cec_unregister_adapter(port->adap); 385 } 386 return ret; 387 } 388 389 static void cros_ec_cec_remove(struct platform_device *pdev) 390 { 391 struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); 392 struct device *dev = &pdev->dev; 393 struct cros_ec_cec_port *port; 394 int ret; 395 396 /* 397 * blocking_notifier_chain_unregister() only fails if the notifier isn't 398 * in the list. We know it was added to it by .probe(), so there should 399 * be no need for error checking. Be cautious and still check. 400 */ 401 ret = blocking_notifier_chain_unregister( 402 &cros_ec_cec->cros_ec->event_notifier, 403 &cros_ec_cec->notifier); 404 if (ret) 405 dev_err(dev, "failed to unregister notifier\n"); 406 407 for (int i = 0; i < cros_ec_cec->num_ports; i++) { 408 port = cros_ec_cec->ports[i]; 409 cec_notifier_cec_adap_unregister(port->notify, port->adap); 410 cec_unregister_adapter(port->adap); 411 } 412 } 413 414 static struct platform_driver cros_ec_cec_driver = { 415 .probe = cros_ec_cec_probe, 416 .remove_new = cros_ec_cec_remove, 417 .driver = { 418 .name = DRV_NAME, 419 .pm = &cros_ec_cec_pm_ops, 420 }, 421 }; 422 423 module_platform_driver(cros_ec_cec_driver); 424 425 MODULE_DESCRIPTION("CEC driver for ChromeOS ECs"); 426 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 427 MODULE_LICENSE("GPL"); 428 MODULE_ALIAS("platform:" DRV_NAME); 429