Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp4620597imm; Fri, 18 May 2018 08:03:09 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqRml/N0RgBO3tNh+KsnmV/P75Y7pDXBMXNQylD+p5w4/ihHFAaGYAmH/91g/JUxRLuOcmg X-Received: by 2002:a65:5183:: with SMTP id h3-v6mr7689704pgq.58.1526655789851; Fri, 18 May 2018 08:03:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526655789; cv=none; d=google.com; s=arc-20160816; b=msCmg4BCNSpUkjJSEDvD30+GthR5bi7HzYWAJNkx+K3DCQPaUPhKxXtgYmsGNHlo6Y h/jpMjT8UkZecqK1wl3tIyt8S4+UcA7QvkoRLsoY2aAwVzzqx3o8vMdXbcNg2J4DwZwO fBJ3/iTugF3mmiSugVJz4SaL41wplZ6dUr5/UDj3sbTE5LEp95mmoUvkNCL2em1QxyPB L0UNlcyiGPFu3BmxjxDf2eapvAqT0qha2GWcixzFdXtv9+wrMpehgm2JgP89M88aTaxN BczYRrB5j3Vf/n4IU/R9cQxQSk/K7UK6Ojfzvx4g84GjzZbE6xBrYYGMiZMALy4zVuu3 uOQg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=oyVk6P3CVc2m6IvpG3OK0lMZ/D1zc351d5BaCgSVzAE=; b=F8S5ODFJoW/DbPx7cDZ5B3j5j8nMNPFJfeSX4O0hbjDiogiCL+ZVVsAgVSyWmJepzK pxZNfkFY5CKXT2LIO2QAUJHwQU+rErQ5wgtgbL9wtIHR824A2XbzM8pa94txoLjR6BJr ZxFVWvZuQUJkF0t4dbH8oQ0LAMLjxuL5b1xoQ1soHtmCxj+lziHBw94tGNiCbBnbqgei BhurwRt+km4UnPRGovlxxG3w7BtQzFNzwX+QwmzC03N3tontk4M6Ke17hg3+/GAFZKmj Wp7Mv0atrJ0vUgoschxytg72RUmEgbypYRxNbU86ZS2LTVr+A8gsCdUACCrxC9m8NqLm sznA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Eghzr/RH; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p3-v6si7427781pff.356.2018.05.18.08.02.55; Fri, 18 May 2018 08:03:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Eghzr/RH; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752022AbeERPCU (ORCPT + 99 others); Fri, 18 May 2018 11:02:20 -0400 Received: from mail-qk0-f194.google.com ([209.85.220.194]:33160 "EHLO mail-qk0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751571AbeERPCQ (ORCPT ); Fri, 18 May 2018 11:02:16 -0400 Received: by mail-qk0-f194.google.com with SMTP id c11-v6so6669480qkm.0; Fri, 18 May 2018 08:02:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=oyVk6P3CVc2m6IvpG3OK0lMZ/D1zc351d5BaCgSVzAE=; b=Eghzr/RHlSbofk44Ro7GeUyu8OA0KYgO3kwoxTsmd87i6g7TxjANpCGjTd0rKulVTU KsdfRYUoscOC/YKpd6Z2qwXLRKSonWi4EvV9BN+j8ClJ0jedDGiwACwc8MQ8nr8n+AZz ijfDmuIFdMTZGjtaDQCoSRAneph59UMpoMooWsXwWGCcJVQol0tn3FSVslPxEZHsEOBw tvOfZkie/m0snaGZhTq6jdg8Vl1j9ETKP9/fgK8miLQwYcj4CVNhez6+mnbtqQUl8fXm NrEmPs6qi1a6jqI+zcSBbcsY0puoCSvyWJQ890dtqN6hfOY/SLJg1+U8CBUQH8nyL7/h 2jIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=oyVk6P3CVc2m6IvpG3OK0lMZ/D1zc351d5BaCgSVzAE=; b=Gz5D/m9gi29U1rXRdg+RCW1R4I3UchhYRa14GcJQkM4WqB5JxQfkR/zAR0C1EnN5MJ 8qYgggOSm3U+BccfTPDAFb7Rb12GuHtD4gJZgpK5i5nvZSlMpiWMOItPtcZXTQkrhLhx 4Xz5eHB7SXoqbWBJT0tH9/90bm6U6fEvTO3P4CL2IHaB4C24yw24pdwXIKQ3mH7jfdUB zkzijIFV66K3MOCk5j3h/0dO/UElAMzj3EpBpFefIAYh3P7iiqKwQy1xjVXYA6l7jwDd TSA+7zxQ5YDRB/AI6AFocruDvSLy2UOw4VzzLoQr/5AliQRE8VWtEkDsfXGaeUx2pZBA 1Rbg== X-Gm-Message-State: ALKqPwczen4XfM1dGPj9CgXaoI5hUdR2ruMtGKqCiFv6yvdi45vs6kPJ XPZjxp5ZXV/cByGRRfsukrF5cCpTtcli9la3/Ms= X-Received: by 2002:a37:4d56:: with SMTP id a83-v6mr9145089qkb.105.1526655734963; Fri, 18 May 2018 08:02:14 -0700 (PDT) MIME-Version: 1.0 Received: by 10.200.13.68 with HTTP; Fri, 18 May 2018 08:02:14 -0700 (PDT) In-Reply-To: <1526648704-16873-6-git-send-email-narmstrong@baylibre.com> References: <1526648704-16873-1-git-send-email-narmstrong@baylibre.com> <1526648704-16873-6-git-send-email-narmstrong@baylibre.com> From: Enric Balletbo Serra Date: Fri, 18 May 2018 17:02:14 +0200 Message-ID: Subject: Re: [PATCH v2 5/5] media: platform: Add Chrome OS EC CEC driver To: Neil Armstrong Cc: David Airlie , Hans Verkuil , Lee Jones , Olof Johansson , Sean Paul , sadolfsson@google.com, intel-gfx@lists.freedesktop.org, linux-kernel , dri-devel , Fabien Parent , Felix Ekblom , =?UTF-8?Q?St=C3=A9phane_Marchesin?= , Benson Leung , darekm@google.com, linux-media@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Neil, 2018-05-18 15:05 GMT+02:00 Neil Armstrong : > The Chrome OS Embedded Controller can expose a CEC bus, this patch add the A minor nit, there is a "consensus" on tell cros-ec as "ChromeOS Embedded Controller" or "ChromeOS EC". Yes, I know that you can see in the kernel many other ways to refer to the ChromeOS EC, but to standardize a little bit, could you replace all occurrences s/Chrome OS/ChromeOS/. Thanks. > driver for such feature of the Embedded Controller. > > This driver is part of the cros-ec MFD and will be add as a sub-device when > the feature bit is exposed by the EC. > > The controller will only handle a single logical address and handles > all the messages retries and will only expose Success or Error. > > The controller will be tied to the HDMI CEC notifier by using the platform > DMI Data and the i915 device name and connector name. > > Signed-off-by: Neil Armstrong > --- > drivers/media/platform/Kconfig | 11 + > drivers/media/platform/Makefile | 2 + > drivers/media/platform/cros-ec-cec/Makefile | 1 + > drivers/media/platform/cros-ec-cec/cros-ec-cec.c | 347 +++++++++++++++++++++++ > 4 files changed, 361 insertions(+) > create mode 100644 drivers/media/platform/cros-ec-cec/Makefile > create mode 100644 drivers/media/platform/cros-ec-cec/cros-ec-cec.c > > diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig > index c7a1cf8..e55a8ed2 100644 > --- a/drivers/media/platform/Kconfig > +++ b/drivers/media/platform/Kconfig > @@ -546,6 +546,17 @@ menuconfig CEC_PLATFORM_DRIVERS > > if CEC_PLATFORM_DRIVERS > > +config VIDEO_CROS_EC_CEC > + tristate "Chrome OS EC CEC driver" here > + depends on MFD_CROS_EC || COMPILE_TEST > + select CEC_CORE > + select CEC_NOTIFIER > + ---help--- > + If you say yes here you will get support for the > + Chrome OS Embedded Controller's CEC. here > + The CEC bus is present in the HDMI connector and enables communication > + between compatible devices. > + > config VIDEO_MESON_AO_CEC > tristate "Amlogic Meson AO CEC driver" > depends on ARCH_MESON || COMPILE_TEST > diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile > index 932515d..830696f 100644 > --- a/drivers/media/platform/Makefile > +++ b/drivers/media/platform/Makefile > @@ -92,3 +92,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss-8x16/ > obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/ > > obj-y += meson/ > + > +obj-y += cros-ec-cec/ > diff --git a/drivers/media/platform/cros-ec-cec/Makefile b/drivers/media/platform/cros-ec-cec/Makefile > new file mode 100644 > index 0000000..9ce97f9 > --- /dev/null > +++ b/drivers/media/platform/cros-ec-cec/Makefile > @@ -0,0 +1 @@ > +obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o > diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c > new file mode 100644 > index 0000000..7e1e275 > --- /dev/null > +++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c > @@ -0,0 +1,347 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * CEC driver for Chrome OS Embedded Controller and here > + * > + * Copyright (c) 2018 BayLibre, SAS > + * Author: Neil Armstrong > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define DRV_NAME "cros-ec-cec" > + > +/** > + * struct cros_ec_cec - Driver data for EC CEC > + * > + * @cros_ec: Pointer to EC device > + * @notifier: Notifier info for responding to EC events > + * @adap: CEC adapter > + * @notify: CEC notifier pointer > + * @rx_msg: storage for a received message > + */ > +struct cros_ec_cec { > + struct cros_ec_device *cros_ec; > + struct notifier_block notifier; > + struct cec_adapter *adap; > + struct cec_notifier *notify; > + struct cec_msg rx_msg; > +}; > + > +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 handle_cec_event(struct cros_ec_cec *cros_ec_cec) > +{ > + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; > + uint32_t events = cros_ec->event_data.data.cec_events; > + > + if (events & EC_MKBP_CEC_SEND_OK) > + cec_transmit_attempt_done(cros_ec_cec->adap, > + CEC_TX_STATUS_OK); > + > + /* FW takes care of all retries, tell core to avoid more retries */ > + if (events & EC_MKBP_CEC_SEND_FAILED) > + cec_transmit_attempt_done(cros_ec_cec->adap, > + CEC_TX_STATUS_MAX_RETRIES | > + CEC_TX_STATUS_NACK); > +} > + > +static int cros_ec_cec_event(struct notifier_block *nb, > + unsigned long queued_during_suspend, > + void *_notify) > +{ > + struct cros_ec_cec *cros_ec_cec; > + struct cros_ec_device *cros_ec; > + > + cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier); > + cros_ec = cros_ec_cec->cros_ec; > + > + if (cros_ec->event_data.event_type == EC_MKBP_CEC_EVENT) { > + handle_cec_event(cros_ec_cec); > + return NOTIFY_OK; > + } > + > + if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) { > + handle_cec_message(cros_ec_cec); > + return NOTIFY_OK; > + } > + > + return NOTIFY_DONE; > +} > + > +static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) > +{ > + struct cros_ec_cec *cros_ec_cec = adap->priv; > + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; > + struct { > + struct cros_ec_command msg; > + struct ec_params_cec_set data; > + } __packed msg = {}; > + int ret; > + > + msg.msg.command = EC_CMD_CEC_SET; > + msg.msg.outsize = sizeof(msg.data); > + msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS; > + msg.data.address = logical_addr; > + > + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); > + if (ret < 0) { > + dev_err(cros_ec->dev, > + "error setting CEC logical address on EC: %d\n", ret); > + return ret; > + } > + > + return 0; > +} > + > +static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, > + u32 signal_free_time, struct cec_msg *cec_msg) > +{ > + struct cros_ec_cec *cros_ec_cec = adap->priv; > + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; > + struct { > + struct cros_ec_command msg; > + struct ec_params_cec_write data; > + } __packed msg = {}; > + int ret; > + > + msg.msg.command = EC_CMD_CEC_WRITE_MSG; > + msg.msg.outsize = cec_msg->len; > + memcpy(msg.data.msg, cec_msg->msg, cec_msg->len); > + > + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); > + if (ret < 0) { > + dev_err(cros_ec->dev, > + "error writing CEC msg on EC: %d\n", ret); > + return ret; > + } > + > + return 0; > +} > + > +static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) > +{ > + struct cros_ec_cec *cros_ec_cec = adap->priv; > + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; > + struct { > + struct cros_ec_command msg; > + struct ec_params_cec_set data; > + } __packed msg = {}; > + int ret; > + > + msg.msg.command = EC_CMD_CEC_SET; > + msg.msg.outsize = sizeof(msg.data); > + msg.data.cmd = CEC_CMD_ENABLE; > + msg.data.enable = enable; > + > + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); > + if (ret < 0) { > + dev_err(cros_ec->dev, > + "error %sabling CEC on EC: %d\n", > + (enable ? "en" : "dis"), ret); > + return ret; > + } > + > + return 0; > +} > + > +static const struct cec_adap_ops cros_ec_cec_ops = { > + .adap_enable = cros_ec_cec_adap_enable, > + .adap_log_addr = cros_ec_cec_set_log_addr, > + .adap_transmit = cros_ec_cec_transmit, > +}; > + > +#ifdef CONFIG_PM_SLEEP > +static int cros_ec_cec_suspend(struct device *dev) > +{ > + struct platform_device *pdev = to_platform_device(dev); > + struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); > + > + if (device_may_wakeup(dev)) > + enable_irq_wake(cros_ec_cec->cros_ec->irq); > + > + return 0; > +} > + > +static int cros_ec_cec_resume(struct device *dev) > +{ > + struct platform_device *pdev = to_platform_device(dev); > + struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); > + > + if (device_may_wakeup(dev)) > + disable_irq_wake(cros_ec_cec->cros_ec->irq); > + > + return 0; > +} > +#endif > + > +static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops, > + cros_ec_cec_suspend, cros_ec_cec_resume); > + > +#if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI) > + > +/* > + * The Firmware only handles a single CEC interface tied to a single HDMI > + * connector we specify along with the DRM device name handling the HDMI output > + */ > + > +struct cec_dmi_match { > + char *sys_vendor; > + char *product_name; > + char *devname; > + char *conn; > +}; > + > +static const struct cec_dmi_match cec_dmi_match_table[] = { > + /* Google Fizz */ > + { "Google", "Fizz", "0000:00:02.0", "Port B" }, > +}; > + > +static int cros_ec_cec_get_notifier(struct device *dev, > + struct cec_notifier **notify) > +{ > + int i; > + > + for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) { > + const struct cec_dmi_match *m = &cec_dmi_match_table[i]; > + > + if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) && > + dmi_match(DMI_PRODUCT_NAME, m->product_name)) { > + struct device *d; > + > + /* Find the device, bail out if not yet registered */ > + d = bus_find_device_by_name(&pci_bus_type, NULL, > + m->devname); > + if (!d) > + return -EPROBE_DEFER; > + > + *notify = cec_notifier_get_conn(d, m->conn); > + return 0; > + } > + } > + > + /* Hardware support must be added in the cec_dmi_match_table */ > + dev_warn(dev, "CEC notifier not configured for this hardware\n"); > + > + return -ENODEV; > +} > + > +#else > + > +static int cros_ec_cec_get_notifier(struct device *dev, > + struct cec_notifier **notify) > +{ > + return -ENODEV; > +} > + > +#endif > + > +static int cros_ec_cec_probe(struct platform_device *pdev) > +{ > + struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); > + struct cros_ec_device *cros_ec = ec_dev->ec_dev; > + struct cros_ec_cec *cros_ec_cec; > + int ret; > + > + cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec), > + GFP_KERNEL); > + if (!cros_ec_cec) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, cros_ec_cec); > + cros_ec_cec->cros_ec = cros_ec; > + > + ret = cros_ec_cec_get_notifier(&pdev->dev, &cros_ec_cec->notify); > + if (ret) > + return ret; > + > + ret = device_init_wakeup(&pdev->dev, 1); > + if (ret) { > + dev_err(&pdev->dev, "failed to initialize wakeup\n"); > + return ret; > + } > + > + cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec, > + DRV_NAME, CEC_CAP_DEFAULTS, 1); > + if (IS_ERR(cros_ec_cec->adap)) > + return PTR_ERR(cros_ec_cec->adap); > + > + /* Get CEC events from the EC. */ > + cros_ec_cec->notifier.notifier_call = cros_ec_cec_event; > + ret = blocking_notifier_chain_register(&cros_ec->event_notifier, > + &cros_ec_cec->notifier); > + if (ret) { > + dev_err(&pdev->dev, "failed to register notifier\n"); > + cec_delete_adapter(cros_ec_cec->adap); > + return ret; > + } > + > + ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev); > + if (ret < 0) { > + cec_delete_adapter(cros_ec_cec->adap); > + return ret; > + } > + > + cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify); > + > + return 0; > +} > + > +static int cros_ec_cec_remove(struct platform_device *pdev) > +{ > + struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); > + struct device *dev = &pdev->dev; > + int ret; > + > + ret = blocking_notifier_chain_unregister( > + &cros_ec_cec->cros_ec->event_notifier, > + &cros_ec_cec->notifier); > + > + if (ret) { > + dev_err(dev, "failed to unregister notifier\n"); > + return ret; > + } > + > + cec_unregister_adapter(cros_ec_cec->adap); > + > + if (cros_ec_cec->notify) > + cec_notifier_put(cros_ec_cec->notify); > + > + return 0; > +} > + > +static struct platform_driver cros_ec_cec_driver = { > + .probe = cros_ec_cec_probe, > + .remove = cros_ec_cec_remove, > + .driver = { > + .name = DRV_NAME, > + .pm = &cros_ec_cec_pm_ops, > + }, > +}; > + > +module_platform_driver(cros_ec_cec_driver); > + > +MODULE_DESCRIPTION("CEC driver for Chrome OS ECs"); > +MODULE_AUTHOR("Neil Armstrong "); > +MODULE_LICENSE("GPL"); > +MODULE_ALIAS("platform:" DRV_NAME); > -- > 2.7.4 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel The patch looks good to me, so Reviewed-by: Enric Balletbo i Serra