linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Add SECO CEC driver for MEC Based boards
@ 2022-02-01 18:37 ektor5
  2022-02-01 18:37 ` [PATCH 1/2] media: cec: add SECO MEC-based cec driver ektor5
  2022-02-01 18:37 ` [PATCH 2/2] media: cec: seco: add newlines in debug messages ektor5
  0 siblings, 2 replies; 4+ messages in thread
From: ektor5 @ 2022-02-01 18:37 UTC (permalink / raw)
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Ettore Chimenti,
	linux-kernel, linux-media, linuxfancy

From: Ettore Chimenti <ek5.chimenti@gmail.com>

Hi all,

This series adds the SECO CEC driver for MAC-based Boards. The
boards have a Microchip MEC microcontroller as a general-purpose
Embedded Controller, and they communicate through a mailbox interface.

The EC used is more powerful and enables management of several CEC lines
at once (up to 4). The focus is on Intel-based SBC-D61 board and UDOO
Vision (SBC-D02) in this version, as the UDOO BOLT firmware
implementation is still ongoing. Moreover, there is no CEC Notifier
functionality inside amdgpu yet.

Similarly to the previous implementation, there are several commands
that can be issued, like WRITE and READ commands for sending and
receiving CEC messages. The retrieval and send confirmation are
triggered by a single GPIO interrupt connected directly to the SoC.

After every STATUS command, the MEC returns a data struct with all the
channels status, and it automatically clears the interrupt state afterwards.

In this implementation, the driver sends also the physical address to
the EC. This way it is possible to wake up the board upon receiving an
SET_STREAM_PATH with the matching physical address when the CPU is in S3
or S5 (depending on BIOS settings). The only time that it seems to be
already set is in the LA assignment (in the .enable callback it is not
set yet).

The last patch adds missing newlines to debug prints in the previous
driver seco-cec.

Best Regards,
	Ettore

Ettore Chimenti (2):
  media: cec: add SECO MEC-based cec driver
  media: cec: seco: add newlines in debug messages

 MAINTAINERS                                   |   2 +
 drivers/media/cec/platform/Kconfig            |  22 +-
 drivers/media/cec/platform/seco/Makefile      |   3 +-
 drivers/media/cec/platform/seco/seco-cec.c    |  54 +-
 drivers/media/cec/platform/seco/seco-meccec.c | 821 ++++++++++++++++++
 drivers/media/cec/platform/seco/seco-meccec.h | 130 +++
 6 files changed, 1002 insertions(+), 30 deletions(-)
 create mode 100644 drivers/media/cec/platform/seco/seco-meccec.c
 create mode 100644 drivers/media/cec/platform/seco/seco-meccec.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] media: cec: add SECO MEC-based cec driver
  2022-02-01 18:37 [PATCH 0/2] Add SECO CEC driver for MEC Based boards ektor5
@ 2022-02-01 18:37 ` ektor5
  2022-02-02 14:31   ` kernel test robot
  2022-02-01 18:37 ` [PATCH 2/2] media: cec: seco: add newlines in debug messages ektor5
  1 sibling, 1 reply; 4+ messages in thread
From: ektor5 @ 2022-02-01 18:37 UTC (permalink / raw)
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Ettore Chimenti,
	linux-kernel, linux-media, linuxfancy

From: Ettore Chimenti <ek5.chimenti@gmail.com>

This patch adds support to the CEC device implemented with a Microchip
MEC microcontroller in SECO Boards, including UDOO BOLT and UDOO Vision.

The communication is achieved via Mailbox protocol.
The driver use direct access to the PCI addresses.
The firmware implementation also supports resuming from suspend by
sending physical address to EC and waiting for a SET_STREAM_PATH command
that matches the provided physical address.

The basic functionalities are tested with success with cec-ctl and
cec-compliance.

Inspired by previous seco-cec implementation, attaches to i915 driver
cec-notifier.

Signed-off-by: Ettore Chimenti <ek5.chimenti@gmail.com>
---
 MAINTAINERS                                   |   2 +
 drivers/media/cec/platform/Kconfig            |  22 +-
 drivers/media/cec/platform/seco/Makefile      |   3 +-
 drivers/media/cec/platform/seco/seco-meccec.c | 821 ++++++++++++++++++
 drivers/media/cec/platform/seco/seco-meccec.h | 130 +++
 5 files changed, 975 insertions(+), 3 deletions(-)
 create mode 100644 drivers/media/cec/platform/seco/seco-meccec.c
 create mode 100644 drivers/media/cec/platform/seco/seco-meccec.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f41088418aae..0e330c1dfe49 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17273,6 +17273,8 @@ M:	Ettore Chimenti <ek5.chimenti@gmail.com>
 S:	Maintained
 F:	drivers/media/cec/platform/seco/seco-cec.c
 F:	drivers/media/cec/platform/seco/seco-cec.h
+F:	drivers/media/cec/platform/seco/seco-meccec.c
+F:	drivers/media/cec/platform/seco/seco-meccec.h
 
 SECURE COMPUTING
 M:	Kees Cook <keescook@chromium.org>
diff --git a/drivers/media/cec/platform/Kconfig b/drivers/media/cec/platform/Kconfig
index b672d3142eb7..da92b22d0775 100644
--- a/drivers/media/cec/platform/Kconfig
+++ b/drivers/media/cec/platform/Kconfig
@@ -98,7 +98,11 @@ config CEC_TEGRA
 	  between compatible devices.
 
 config CEC_SECO
-	tristate "SECO Boards HDMI CEC driver"
+	bool "SECO Boards HDMI CEC drivers"
+
+config CEC_SECO_LEGACY
+	tristate "SECO Legacy Boards HDMI CEC driver"
+	depends on CEC_SECO
 	depends on (X86 || IA64) || COMPILE_TEST
 	depends on PCI && DMI
 	select CEC_CORE
@@ -109,9 +113,23 @@ config CEC_SECO
 	  CEC bus is present in the HDMI connector and enables communication
 	  between compatible devices.
 
+config CEC_SECO_MEC
+	tristate "SECO MEC-Based Boards HDMI CEC driver"
+	depends on CEC_SECO
+	depends on (X86 || IA64) || COMPILE_TEST
+	depends on PCI && DMI
+	select CEC_CORE
+	select CEC_NOTIFIER
+	help
+	  This is a driver for SECO MEC-Based Boards integrated CEC interface.
+	  Selecting it will enable support for this device.
+	  CEC bus is present in the HDMI connectors and enables communication
+	  between compatible devices.
+
+
 config CEC_SECO_RC
 	bool "SECO Boards IR RC5 support"
-	depends on CEC_SECO
+	depends on CEC_SECO_LEGACY
 	depends on RC_CORE=y || RC_CORE = CEC_SECO
 	help
 	  If you say yes here you will get support for the
diff --git a/drivers/media/cec/platform/seco/Makefile b/drivers/media/cec/platform/seco/Makefile
index aa1ca8ccdb8b..ccd51dc4c5ac 100644
--- a/drivers/media/cec/platform/seco/Makefile
+++ b/drivers/media/cec/platform/seco/Makefile
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_CEC_SECO) += seco-cec.o
+obj-$(CONFIG_CEC_SECO_LEGACY) += seco-cec.o
+obj-$(CONFIG_CEC_SECO_MEC) += seco-meccec.o
diff --git a/drivers/media/cec/platform/seco/seco-meccec.c b/drivers/media/cec/platform/seco/seco-meccec.c
new file mode 100644
index 000000000000..5e761427c413
--- /dev/null
+++ b/drivers/media/cec/platform/seco/seco-meccec.c
@@ -0,0 +1,821 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * CEC driver for SECO MEC-based Boards
+ *
+ * Author:  Ettore Chimenti <ek5.chimenti@gmail.com>
+ * Copyright (C) 2022, SECO SpA.
+ */
+
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+
+/* CEC Framework */
+#include <media/cec-notifier.h>
+
+#include "seco-meccec.h"
+
+#define SECO_MECCEC_DEV_NAME "seco_meccec"
+#define MECCEC_MAX_CEC_ADAP 4
+#define MECCEC_MAX_ADDRS 1
+#define MECCEC_MAX_STATUS_RETRIES 10
+
+static DEFINE_MUTEX(ec_mutex);
+
+struct seco_meccec_data {
+	struct device *dev;
+	struct platform_device *pdev;
+	struct cec_adapter *cec_adap[MECCEC_MAX_CEC_ADAP];
+	struct cec_notifier *notifier[MECCEC_MAX_CEC_ADAP];
+	u8 channels;	/* bitmask */
+	int irq;
+};
+
+struct seco_meccec_adap_data {
+	struct seco_meccec_data *cec;
+	int idx;
+};
+
+static int ec_reg_byte_op(u8 reg, u8 operation, u8 data, u8 *result)
+{
+	int res;
+
+	/* Check still active */
+	res = inb(MBX_RESOURCE_REGISTER) & AGENT_ACTIVE(AGENT_USER);
+	if (!res)
+		return -EBUSY;
+
+	/* Set the register index */
+	outb(reg, EC_REGISTER_INDEX);
+
+	/* Check still active */
+	res = inb(MBX_RESOURCE_REGISTER) & AGENT_ACTIVE(AGENT_USER);
+	if (!res)
+		return -EBUSY;
+
+	if (operation == READ) {
+		if (!result)
+			return -EINVAL;
+
+		/* Read the data value */
+		*result = inb(EC_REGISTER_DATA);
+
+	} else if (operation == WRITE) {
+		/* Write the data value */
+		outb(data, EC_REGISTER_DATA);
+	}
+
+	/* Check still active */
+	res = inb(MBX_RESOURCE_REGISTER) & AGENT_ACTIVE(AGENT_USER);
+	if (!res)
+		return -EBUSY;
+
+	return 0;
+}
+
+#define ec_reg_byte_rd(reg, res) ec_reg_byte_op(reg, READ, 0, res)
+#define ec_reg_byte_wr(reg, val) ec_reg_byte_op(reg, WRITE, val, NULL)
+
+static int ec_waitstatus(u8 status, u8 cmd)
+{
+	int idx;
+
+	/* Loop until time-out or Status */
+	for (idx = 0; idx < EC_CMD_TIMEOUT; idx++) {
+		u8 res = inb(MBX_RESOURCE_REGISTER);
+
+		/* If status, done */
+		if ((res & AGENT_MASK(AGENT_USER)) == status)
+			return 0;
+
+		/* Send command if needed */
+		if (!cmd)
+			continue;
+
+		/* Retry sending command when mailbox is free */
+		for ( ; idx < EC_CMD_TIMEOUT; idx++) {
+			/* Check busy bit */
+			res = inb(MBX_BUSY_REGISTER) & EC_STATUS_REGISTER;
+
+			if (!res) {
+				/* Send command */
+				outb_p(cmd, MBX_BUSY_REGISTER);
+				break;
+			}
+		}
+	}
+
+	/* Time-out expired */
+	return -EAGAIN;
+}
+
+static int ec_send_command(const struct platform_device *pdev, u8 cmd,
+			   void *tx_buf, u8 tx_size,
+			   void *rx_buf, u8 rx_size)
+{
+	struct seco_meccec_data *meccec = platform_get_drvdata(pdev);
+	const struct device *dev = meccec->dev;
+
+	int status;
+	u8 *buf;
+	u8 idx;
+	u8 res;
+
+	mutex_lock(&ec_mutex);
+
+	/* Wait for BIOS agent idle */
+	status = ec_waitstatus(AGENT_IDLE(AGENT_USER), 0);
+	if (status) {
+		dev_err(dev, "Mailbox agent not available\n");
+		goto err;
+	}
+
+	/* BIOS agent is idle: we can request access */
+	status = ec_waitstatus(AGENT_ACTIVE(AGENT_USER),
+			       REQUEST_MBX_ACCESS(AGENT_USER));
+	if (status) {
+		dev_err(dev, "Request mailbox agent failed\n");
+		goto err;
+	}
+
+	/* Prepare MBX data */
+	for (buf = (uint8_t *)tx_buf, idx = 0; (!status) && idx < tx_size; idx++)
+		status = ec_reg_byte_wr(EC_MBX_REGISTER + idx, buf[idx]);
+
+	if (status) {
+		dev_err(dev, "Mailbox buffer write failed\n");
+		goto err;
+	}
+
+	/* Send command */
+	status = ec_reg_byte_wr(EC_COMMAND_REGISTER, cmd);
+	if (status) {
+		dev_err(dev, "Command write failed\n");
+		goto err;
+	}
+
+	/* Wait for completion */
+	status = ec_waitstatus(AGENT_DONE(AGENT_USER), 0);
+	if (status) {
+		dev_err(dev, "Mailbox did not complete after command write\n");
+		goto err;
+	}
+
+	/* Get result code */
+	status = ec_reg_byte_rd(EC_RESULT_REGISTER, &res);
+	if (status) {
+		dev_err(dev, "Result read failed\n");
+		goto err;
+	}
+
+	/* Get result code and translate it */
+	switch (res) {
+	case EC_NO_ERROR:
+		status = 0;
+		break;
+
+	case EC_UNKNOWN_COMMAND_ERROR:
+		status = -EPERM;
+		break;
+
+	case EC_INVALID_ARGUMENT_ERROR:
+		status = -EINVAL;
+		break;
+
+	case EC_TIMEOUT_ERROR:
+		status = -EAGAIN;
+		break;
+
+	default:
+		status = -EIO;
+		break;
+	}
+	if (status) {
+		dev_err(dev, "Command failed\n");
+		goto err;
+	}
+
+	/* Read return data */
+	for (buf = (uint8_t *)rx_buf, idx = 0; !status && idx < rx_size; idx++)
+		status = ec_reg_byte_rd(EC_MBX_REGISTER + idx, &buf[idx]);
+
+	if (status) {
+		dev_err(dev, "Mailbox read failed\n");
+		goto err;
+	}
+
+err:
+	/* Release access, ignoring eventual time-out */
+	ec_waitstatus(AGENT_IDLE(AGENT_USER), RELEASE_MBX_ACCESS(AGENT_USER));
+
+	mutex_unlock(&ec_mutex);
+	return status;
+}
+
+static int ec_get_version(struct seco_meccec_data *cec)
+{
+	const struct device *dev = cec->dev;
+	const struct platform_device *pdev = cec->pdev;
+	struct version_msg_t version;
+	int status;
+
+	status = ec_send_command(pdev, GET_FIRMWARE_VERSION_CMD,
+				 NULL, 0,
+				 &version, sizeof(struct version_msg_t));
+
+	if (status)
+		return status;
+
+	dev_dbg(dev, "Firmware version %X.%02X / %X.%02X\n",
+		version.fw.major,
+		version.fw.minor,
+		version.lib.major,
+		version.lib.minor);
+
+	return 0;
+}
+
+static int ec_cec_status(struct seco_meccec_data *cec,
+			 struct seco_meccec_status_t *result)
+{
+	const struct device *dev = cec->dev;
+	const struct platform_device *pdev = cec->pdev;
+	struct seco_meccec_status_t buf = { 0 };
+	int ret, i;
+
+	/* retry until get status or interrupt will not reset */
+	for (i = 0; i < MECCEC_MAX_STATUS_RETRIES; i++) {
+		ret = ec_send_command(pdev, GET_CEC_STATUS_CMD,
+				      &buf, sizeof(struct seco_meccec_status_t),
+				      &buf, sizeof(struct seco_meccec_status_t));
+		if (ret) {
+			dev_dbg(dev, "Status: Mailbox is busy. Retrying.\n");
+			continue;
+		}
+		break;
+	}
+
+	if (ret)
+		return ret;
+
+	dev_dbg(dev, "CEC Status:\n");
+	dev_dbg(dev, "ch0: 0x%02x\n", buf.status_ch0);
+	dev_dbg(dev, "ch1: 0x%02x\n", buf.status_ch1);
+	dev_dbg(dev, "ch2: 0x%02x\n", buf.status_ch2);
+	dev_dbg(dev, "ch3: 0x%02x\n", buf.status_ch3);
+
+	if (result)
+		*result = buf;
+
+	return 0;
+}
+
+static int meccec_adap_phys_addr(struct cec_adapter *adap, u16 phys_addr)
+{
+	struct seco_meccec_adap_data *adap_data = cec_get_drvdata(adap);
+	struct seco_meccec_data *cec = adap_data->cec;
+	const struct platform_device *pdev = cec->pdev;
+	const struct device *dev = cec->dev;
+	struct seco_meccec_phyaddr_t buf = { };
+	int status;
+
+	buf.bus = adap_data->idx;
+	buf.addr = phys_addr;
+
+	/* Need to tell physical address to wake up while standby */
+	status = ec_send_command(pdev, SET_CEC_PHYADDR_CMD,
+				 &buf, sizeof(struct seco_meccec_phyaddr_t),
+				 NULL, 0);
+	dev_dbg(dev, "Physical address 0x%04x\n", phys_addr);
+
+	return status;
+}
+
+static int meccec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
+{
+	struct seco_meccec_adap_data *adap_data = cec_get_drvdata(adap);
+	struct seco_meccec_data *cec = adap_data->cec;
+	struct platform_device *pdev = cec->pdev;
+	const struct device *dev = cec->dev;
+	struct seco_meccec_logaddr_t buf = { };
+	int status;
+
+	buf.bus = adap_data->idx;
+	buf.addr = logical_addr & 0x0f;
+
+	status = ec_send_command(pdev, SET_CEC_LOGADDR_CMD,
+				 &buf, sizeof(struct seco_meccec_logaddr_t),
+				 NULL, 0);
+	dev_dbg(dev, "Logical address 0x%02x\n", logical_addr);
+
+	/* Physical address is sent to MEC to be stored for replying
+	 * autonomously to GIVE_PHYSICAL_ADDR and matching SET_STREAM_PATH when
+	 * the CPU is sleeping. If PA match with a SET_STREAM_PATH message, it
+	 * will resume the CPU.
+	 *
+	 * When setting LA, adap has valid physical address
+	 */
+	status = meccec_adap_phys_addr(adap, adap->phys_addr);
+	if (status)
+		dev_err(dev, "Set physical address failed %d\n", status);
+
+	return status;
+}
+
+static int meccec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+	struct seco_meccec_adap_data *adap_data = cec_get_drvdata(adap);
+	struct seco_meccec_data *cec = adap_data->cec;
+	const struct device *dev = cec->dev;
+	int ret;
+
+	/* reset status register */
+	ret = ec_cec_status(cec, NULL);
+	if (ret)
+		dev_err(dev, "enable: status operation failed %d\n", ret);
+
+	if (enable) {
+		dev_dbg(dev, "Device enabled\n");
+	} else {
+		dev_dbg(dev, "Device disabled\n");
+
+		/* When the adapter is disabled, setting the physical address to
+		 * invalid prevents the MEC firmware to wake up the CPU.
+		 */
+		ret = meccec_adap_phys_addr(adap, CEC_PHYS_ADDR_INVALID);
+		if (ret) {
+			dev_err(dev, "enable: set physical address failed %d\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int meccec_adap_transmit(struct cec_adapter *adap, u8 attempts,
+				u32 signal_free_time, struct cec_msg *msg)
+{
+	struct seco_meccec_adap_data *adap_data = cec_get_drvdata(adap);
+	struct seco_meccec_data *cec = adap_data->cec;
+	struct platform_device *pdev = cec->pdev;
+	const struct device *dev = cec->dev;
+	struct seco_meccec_msg_t buf = { };
+	int status;
+
+	dev_dbg(dev, "Device transmitting\n");
+
+	buf.bus = adap_data->idx;
+	buf.send = (msg->msg[0] & 0xf0) >> 4;
+	buf.dest = msg->msg[0] & 0x0f;
+	buf.size = msg->len - 1;
+	memcpy(buf.data, msg->msg + 1, buf.size);
+
+	status = ec_send_command(pdev, CEC_WRITE_CMD,
+				 &buf, sizeof(struct seco_meccec_msg_t),
+				 NULL, 0);
+
+	return status;
+}
+
+static void meccec_tx_done(struct seco_meccec_data *cec, int adap_idx, u8 status_val)
+{
+	struct cec_adapter *adap = cec->cec_adap[adap_idx];
+
+	if (status_val & SECOCEC_STATUS_TX_ERROR_MASK) {
+		if (status_val & SECOCEC_STATUS_TX_NACK_ERROR)
+			cec_transmit_attempt_done(adap, CEC_TX_STATUS_NACK);
+		else
+			cec_transmit_attempt_done(adap, CEC_TX_STATUS_ERROR);
+	} else {
+		cec_transmit_attempt_done(adap, CEC_TX_STATUS_OK);
+	}
+}
+
+static void meccec_rx_done(struct seco_meccec_data *cec, int adap_idx, u8 status_val)
+{
+	struct device *dev = cec->dev;
+	struct platform_device *pdev = cec->pdev;
+	struct cec_adapter *adap = cec->cec_adap[adap_idx];
+	struct seco_meccec_msg_t buf = { .bus = adap_idx };
+	struct cec_msg msg = { };
+	int status;
+
+	if (status_val & SECOCEC_STATUS_RX_OVERFLOW_MASK)
+		dev_warn(dev, "Received more than 16 bytes. Discarding\n");
+
+	if (status_val & SECOCEC_STATUS_RX_ERROR_MASK) {
+		dev_warn(dev, "Message received with errors. Discarding\n");
+		status = -EIO;
+		goto rxerr;
+	}
+	/* Read message buffer */
+	status = ec_send_command(pdev, CEC_READ_CMD,
+				 &buf, sizeof(struct seco_meccec_msg_t),
+				 &buf, sizeof(struct seco_meccec_msg_t));
+	if (status)
+		return;
+
+	/* Device msg len already accounts for the header */
+	msg.len = min(buf.size + 1, CEC_MAX_MSG_SIZE);
+
+	/* Read logical address */
+	msg.msg[0]  = buf.dest & 0x0f;
+	msg.msg[0] |= (buf.send & 0x0f) << 4;
+
+	memcpy(msg.msg + 1, buf.data, buf.size);
+
+	cec_received_msg(adap, &msg);
+	dev_dbg(dev, "Message received successfully\n");
+
+rxerr:
+	return;
+}
+
+static int get_status_ch(struct seco_meccec_status_t *s,
+			 int ch)
+{
+	if (!s)
+		return -1;
+
+	switch (ch) {
+	case 0: return s->status_ch0;
+	case 1: return s->status_ch1;
+	case 2: return s->status_ch2;
+	case 3: return s->status_ch3;
+	default: return -1;
+	}
+}
+
+static irqreturn_t seco_meccec_irq_handler(int irq, void *priv)
+{
+	struct seco_meccec_data *cec = priv;
+	struct device *dev = cec->dev;
+	struct seco_meccec_status_t status;
+	bool interrupt_served = false;
+	int ret, idx;
+
+	dev_dbg(dev, "Interrupt Called!\n");
+
+	ret = ec_cec_status(cec, &status);
+	if (ret) {
+		dev_warn(dev, "IRQ: status cmd failed %d\n", ret);
+		goto err;
+	}
+
+	for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
+		if (cec->channels & BIT_MASK(idx)) {
+			int cec_val = get_status_ch(&status, idx);
+
+			if (cec_val < 0)
+				continue;
+
+			if (cec_val & SECOCEC_STATUS_MSG_RECEIVED_MASK)
+				meccec_rx_done(cec, idx, cec_val);
+			if (cec_val & SECOCEC_STATUS_MSG_SENT_MASK)
+				meccec_tx_done(cec, idx, cec_val);
+
+			if (cec_val & (SECOCEC_STATUS_MSG_SENT_MASK |
+				       SECOCEC_STATUS_MSG_RECEIVED_MASK))
+				interrupt_served = true;
+		}
+	}
+	if (!interrupt_served)
+		dev_warn(dev, "Message not received or sent, but interrupt fired\n");
+
+	return IRQ_HANDLED;
+err:
+	/* reset status register */
+	ret = ec_cec_status(cec, NULL);
+	if (ret)
+		dev_err(dev, "IRQ: status cmd failed twice %d\n", ret);
+
+	return IRQ_HANDLED;
+}
+
+struct cec_dmi_match {
+	const char *sys_vendor;
+	const char *product_name;
+	const char *devname;
+	const char *conn[MECCEC_MAX_CEC_ADAP];
+};
+
+static const struct cec_dmi_match secocec_dmi_match_table[] = {
+	/* UDOO BOLT */
+	{ "Seco", "0C60", "0000:05:00.0", {"Port B", "Port C"} },
+	/* UDOO Vision */
+	{ "Seco", "0D02", "0000:00:02.0", {"Port B"} },
+	/* SECO SBC-D61 */
+	{ "Seco", "0D61", "0000:00:02.0", {"Port B", "Port C"} },
+};
+
+static struct device *seco_meccec_find_hdmi_dev(struct device *dev,
+						const char * const **conn_ptr)
+{
+	int i;
+
+	for (i = 0 ; i < ARRAY_SIZE(secocec_dmi_match_table) ; ++i) {
+		const struct cec_dmi_match *m = &secocec_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 ERR_PTR(-EPROBE_DEFER);
+
+			put_device(d);
+
+			if (!conn_ptr)
+				return ERR_PTR(-EFAULT);
+
+			*conn_ptr = m->conn;
+
+			return d;
+		}
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int seco_meccec_acpi_probe(struct seco_meccec_data *sdev)
+{
+	struct device *dev = sdev->dev;
+	const struct acpi_device *adev = ACPI_COMPANION(dev);
+	const union acpi_object *obj;
+	struct gpio_desc *gpio;
+	int irq = 0;
+	int ret;
+
+	gpio = devm_gpiod_get(dev, "notify", GPIOF_IN);
+	if (IS_ERR(gpio)) {
+		dev_err(dev, "Cannot request interrupt gpio\n");
+		return PTR_ERR(gpio);
+	}
+
+	irq = gpiod_to_irq(gpio);
+	if (irq < 0) {
+		dev_err(dev, "Cannot find valid irq\n");
+		return -ENODEV;
+	}
+	dev_dbg(dev, "irq-gpio is bound to IRQ %d\n", irq);
+	sdev->irq = irq;
+
+	/* Get info from ACPI about channels capabilities */
+	ret = acpi_dev_get_property(adev, "av-channels",  ACPI_TYPE_INTEGER, &obj);
+	if (ret < 0) {
+		dev_err(dev, "Cannot retrieve channel properties\n");
+		return ret;
+	}
+	dev_dbg(dev, "ACPI property: av-channels -> %x\n", (int)obj->integer.value);
+	sdev->channels = (int)obj->integer.value;
+
+	return 0;
+}
+
+static const struct cec_adap_ops meccec_cec_adap_ops = {
+	/* Low-level callbacks */
+	.adap_enable = meccec_adap_enable,
+	.adap_log_addr = meccec_adap_log_addr,
+	.adap_transmit = meccec_adap_transmit,
+};
+
+static int meccec_create_adapter(struct seco_meccec_data *cec, int idx)
+{
+	struct seco_meccec_adap_data *adap_data;
+	struct device *dev = cec->dev;
+	struct cec_adapter *acec;
+	char adap_name[32];
+
+	if (!cec)
+		return -EINVAL;
+
+	adap_data = devm_kzalloc(dev, sizeof(*adap_data), GFP_KERNEL);
+	if (!adap_data)
+		return -ENOMEM;
+
+	adap_data->cec = cec;
+	adap_data->idx = idx;
+
+	sprintf(adap_name, "%s-%d", dev_name(dev), idx);
+
+	/* Allocate CEC adapter */
+	acec = cec_allocate_adapter(&meccec_cec_adap_ops,
+				    adap_data,
+				    adap_name,
+				    CEC_CAP_DEFAULTS |
+				    CEC_CAP_CONNECTOR_INFO,
+				    MECCEC_MAX_ADDRS);
+
+	if (IS_ERR(acec))
+		return PTR_ERR(acec);
+
+	/* Assign to data */
+	cec->cec_adap[idx] = acec;
+
+	return 0;
+}
+
+static int seco_meccec_probe(struct platform_device *pdev)
+{
+	struct seco_meccec_data *meccec;
+	struct device *dev = &pdev->dev;
+	struct device *hdmi_dev;
+	const char * const *conn;
+	int ret, idx;
+	int adaps, notifs = 0;
+
+	meccec = devm_kzalloc(dev, sizeof(*meccec), GFP_KERNEL);
+	if (!meccec)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, meccec);
+
+	meccec->pdev = pdev;
+	meccec->dev = dev;
+
+	ret = ec_get_version(meccec);
+	if (ret) {
+		dev_err(dev, "Get version failed\n");
+		goto err;
+	}
+
+	if (!has_acpi_companion(dev)) {
+		dev_err(dev, "Cannot find any ACPI companion\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = seco_meccec_acpi_probe(meccec);
+	if (ret) {
+		dev_err(dev, "ACPI probe failed\n");
+		goto err;
+	}
+
+	ret = devm_request_threaded_irq(dev,
+					meccec->irq,
+					NULL,
+					seco_meccec_irq_handler,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					dev_name(&pdev->dev), meccec);
+
+	if (ret) {
+		dev_err(dev, "Cannot request IRQ %d\n", meccec->irq);
+		ret = -EIO;
+		goto err;
+	}
+
+	hdmi_dev = seco_meccec_find_hdmi_dev(&pdev->dev, &conn);
+	if (IS_ERR(hdmi_dev)) {
+		dev_err(dev, "Cannot find HDMI Device\n");
+		return PTR_ERR(hdmi_dev);
+	}
+	dev_dbg(dev, "HDMI device found\n");
+
+	for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
+		if (meccec->channels & BIT_MASK(idx)) {
+			ret = meccec_create_adapter(meccec, idx);
+			if (ret)
+				goto err_delete_adapter;
+			dev_dbg(dev, "CEC adapter #%d allocated\n", idx);
+		}
+	}
+
+	for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
+		if (meccec->channels & BIT_MASK(idx)) {
+			struct cec_adapter *acec = meccec->cec_adap[idx];
+			struct cec_notifier *ncec;
+
+			if (!acec) {
+				ret = -EINVAL;
+				goto err_notifier;
+			}
+
+			ncec = cec_notifier_cec_adap_register(hdmi_dev,
+							      conn[idx], acec);
+
+			dev_dbg(dev, "CEC notifier #%d allocated %s\n", idx, conn[idx]);
+
+			if (IS_ERR(ncec)) {
+				ret = PTR_ERR(ncec);
+				goto err_notifier;
+			}
+
+			meccec->notifier[idx] = ncec;
+			notifs++;
+		}
+	}
+
+	for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
+		if (meccec->channels & BIT_MASK(idx)) {
+			ret = cec_register_adapter(meccec->cec_adap[idx], dev);
+			if (ret)
+				goto err_notifier;
+
+			dev_dbg(dev, "CEC adapter #%d registered\n", idx);
+		}
+	}
+
+	platform_set_drvdata(pdev, meccec);
+	dev_dbg(dev, "Device registered\n");
+
+	return ret;
+
+err_notifier:
+	for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
+		if (meccec->channels & BIT_MASK(idx)) {
+			if (adaps--)
+				return ret;
+
+			cec_notifier_cec_adap_unregister(meccec->notifier[idx],
+							 meccec->cec_adap[idx]);
+		}
+	}
+err_delete_adapter:
+	for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
+		if (meccec->channels & BIT_MASK(idx)) {
+			if (notifs--)
+				return ret;
+
+			cec_delete_adapter(meccec->cec_adap[idx]);
+		}
+	}
+err:
+	dev_err(dev, "%s device probe failed: %d\n", dev_name(dev), ret);
+
+	return ret;
+}
+
+static int seco_meccec_remove(struct platform_device *pdev)
+{
+	struct seco_meccec_data *meccec = platform_get_drvdata(pdev);
+	int idx;
+
+	for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
+		if (meccec->channels && BIT_MASK(idx)) {
+			cec_notifier_cec_adap_unregister(meccec->notifier[idx],
+							 meccec->cec_adap[idx]);
+
+			cec_unregister_adapter(meccec->cec_adap[idx]);
+		}
+	}
+
+	dev_dbg(&pdev->dev, "CEC device removed\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int seco_meccec_resume(struct device *dev)
+{
+	struct seco_meccec_data *cec = dev_get_drvdata(dev);
+	int ret;
+
+	dev_dbg(dev, "Device resumed from suspend\n");
+
+	/* reset status register */
+	ret = ec_cec_status(cec, NULL);
+	if (ret)
+		dev_err(dev, "resume: status operation failed %d\n", ret);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(seco_meccec_pm_ops, NULL, seco_meccec_resume);
+#define SECO_MECCEC_PM_OPS (&seco_meccec_pm_ops)
+#else
+#define SECO_MECCEC_PM_OPS NULL
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id seco_meccec_acpi_match[] = {
+	{"CEC00002", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(acpi, seco_meccec_acpi_match);
+#endif
+
+static struct platform_driver seco_meccec_driver = {
+	.driver = {
+		.name = SECO_MECCEC_DEV_NAME,
+		.acpi_match_table = ACPI_PTR(seco_meccec_acpi_match),
+		.pm = SECO_MECCEC_PM_OPS,
+	},
+	.probe = seco_meccec_probe,
+	.remove = seco_meccec_remove,
+};
+
+module_platform_driver(seco_meccec_driver);
+
+MODULE_DESCRIPTION("SECO MEC CEC Driver");
+MODULE_AUTHOR("Ettore Chimenti <ek5.chimenti@gmail.com>");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/media/cec/platform/seco/seco-meccec.h b/drivers/media/cec/platform/seco/seco-meccec.h
new file mode 100644
index 000000000000..6f7fc9e13e30
--- /dev/null
+++ b/drivers/media/cec/platform/seco/seco-meccec.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ * CEC driver for SECO MEC-based Boards
+ *
+ * Author:  Ettore Chimenti <ek5.chimenti@gmail.com>
+ * Copyright (C) 2022, SECO SpA.
+ */
+
+/* MailBox definitions */
+#define MBX_RESERVED_SIZE	0x10
+#define MBX_RESERVED_BASE	0x2b0
+
+#define BAR_FROM_MBX_BASE(x)	(x + MBX_RESERVED_BASE)
+
+#define RES_BAR_OFFSET		0
+#define BSY_BAR_OFFSET		4
+#define MBX_BAR_OFFSET		0xc
+
+#define MBX_RESOURCE_REGISTER	BAR_FROM_MBX_BASE(RES_BAR_OFFSET)
+#define MBX_BUSY_REGISTER	BAR_FROM_MBX_BASE(BSY_BAR_OFFSET)
+#define MBX_ACCESS_BAR		BAR_FROM_MBX_BASE(MBX_BAR_OFFSET)
+
+#define EC_REGISTER_INDEX	MBX_ACCESS_BAR
+#define EC_REGISTER_DATA	(EC_REGISTER_INDEX + 1)
+#define EC_MBX_SIZE		0x20
+
+#define EC_COMMAND_REGISTER	0
+#define EC_RESULT_REGISTER	1
+#define EC_STATUS_REGISTER	2
+#define EC_MBX_REGISTER		0x10
+
+#define EC_CMD_TIMEOUT		0x30000 /* Maximum wait loop */
+
+/* Firmware version data struct and definitions */
+#define FIRMWARE_TIME_STAMP_SIZE (EC_MBX_SIZE - sizeof(u32))
+
+struct version_t {
+	u8 minor;
+	u8 major;
+};
+
+struct version_msg_t {
+	struct version_t fw;
+	struct version_t lib;
+	u8 firmware_ts[FIRMWARE_TIME_STAMP_SIZE];
+};
+
+/* CEC data structs and constant definitions */
+#define MECCEC_MAX_MSG_SIZE 16
+
+struct seco_meccec_msg_t {
+	u8 bus;
+	u8 send;
+	u8 dest;
+	u8 data[MECCEC_MAX_MSG_SIZE];
+	u8 size;
+};
+
+struct seco_meccec_logaddr_t {
+	u8 bus;
+	u8 addr;
+};
+
+struct seco_meccec_phyaddr_t {
+	u16 bus;
+	u16 addr;
+};
+
+struct seco_meccec_status_t {
+	u8 status_ch0;
+	u8 status_ch1;
+	u8 status_ch2;
+	u8 status_ch3;
+};
+
+/* Status data */
+#define SECOCEC_STATUS_MSG_RECEIVED_MASK	BIT(0)
+#define SECOCEC_STATUS_RX_ERROR_MASK		BIT(1)
+#define SECOCEC_STATUS_MSG_SENT_MASK		BIT(2)
+#define SECOCEC_STATUS_TX_ERROR_MASK		BIT(3)
+
+#define SECOCEC_STATUS_TX_NACK_ERROR		BIT(4)
+#define SECOCEC_STATUS_RX_OVERFLOW_MASK		BIT(5)
+
+/* MBX Status bitmap values from EC to Host */
+enum MBX_STATUS {
+	MBX_OFF     = 0,	/* Disable MBX Interface */
+	MBX_ON      = 1,	/* Enable MBX Interface  */
+	MBX_ACTIVE0 = (1 << 6),	/* MBX AGENT 0 active    */
+	MBX_QUEUED0 = (1 << 7),	/* MBX AGENT 0 idle      */
+};
+
+#define AGENT_IDLE(x)      0
+#define AGENT_QUEUED(x)    (MBX_QUEUED0 >> (2 * x))
+#define AGENT_ACTIVE(x)    (MBX_ACTIVE0 >> (2 * x))
+#define AGENT_MASK(x)      (AGENT_QUEUED(x) + AGENT_ACTIVE(x))
+#define AGENT_DONE(x)      AGENT_MASK(x)
+#define MBX_STATUS_DEFAULT 0
+
+/* MBX user IDs */
+enum AGENT_IDS {
+	AGENT_BIOS, /* BIOS AGENT */
+	AGENT_ACPI, /* ACPI AGENT */
+	AGENT_EAPI, /* EAPI AGENT */
+	AGENT_USER, /* USER AGENT */
+	AGENT_NONE, /* No AGENT   */
+};
+
+/* MBX command results */
+enum CMD_RESULT {
+	EC_NO_ERROR = 0,		/* Success	    */
+	EC_UNKNOWN_COMMAND_ERROR,	/* Unknown command  */
+	EC_INVALID_ARGUMENT_ERROR,	/* Invalid argument */
+	EC_TIMEOUT_ERROR,		/* Waiting Time-out */
+	EC_DEVICE_ERROR,		/* Device error     */
+};
+
+/* MBX commands */
+enum MBX_CMDS {
+	GET_FIRMWARE_VERSION_CMD = 0,    /* Get firmware version record		*/
+	CEC_WRITE_CMD		 = 0x80, /* Write CEC command			*/
+	CEC_READ_CMD		 = 0x81, /* Read CEC command			*/
+	GET_CEC_STATUS_CMD	 = 0x82, /* Get CEC status regisers		*/
+	SET_CEC_LOGADDR_CMD	 = 0x83, /* Set CEC Logical Address		*/
+	SET_CEC_PHYADDR_CMD	 = 0x84, /* Set CEC Physical Address		*/
+	REQUEST_MBX_ACCESS_CMD   = 0xf0, /* First request access command	*/
+	RELEASE_MBX_ACCESS_CMD   = 0xf8, /* First release access command	*/
+};
+
+#define REQUEST_MBX_ACCESS(x) (REQUEST_MBX_ACCESS_CMD + x)
+#define RELEASE_MBX_ACCESS(x) (RELEASE_MBX_ACCESS_CMD + x)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] media: cec: seco: add newlines in debug messages
  2022-02-01 18:37 [PATCH 0/2] Add SECO CEC driver for MEC Based boards ektor5
  2022-02-01 18:37 ` [PATCH 1/2] media: cec: add SECO MEC-based cec driver ektor5
@ 2022-02-01 18:37 ` ektor5
  1 sibling, 0 replies; 4+ messages in thread
From: ektor5 @ 2022-02-01 18:37 UTC (permalink / raw)
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Ettore Chimenti,
	linux-kernel, linux-media, linuxfancy

From: Ettore Chimenti <ek5.chimenti@gmail.com>

Newlines were missing in almost all regular and debug printk.

Signed-off-by: Ettore Chimenti <ek5.chimenti@gmail.com>
---
 drivers/media/cec/platform/seco/seco-cec.c | 54 +++++++++++-----------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/media/cec/platform/seco/seco-cec.c b/drivers/media/cec/platform/seco/seco-cec.c
index ae138cc253fd..78856a55e637 100644
--- a/drivers/media/cec/platform/seco/seco-cec.c
+++ b/drivers/media/cec/platform/seco/seco-cec.c
@@ -129,7 +129,7 @@ static int secocec_adap_enable(struct cec_adapter *adap, bool enable)
 		if (status)
 			goto err;
 
-		dev_dbg(dev, "Device enabled");
+		dev_dbg(dev, "Device enabled\n");
 	} else {
 		/* Clear the status register */
 		status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
@@ -141,7 +141,7 @@ static int secocec_adap_enable(struct cec_adapter *adap, bool enable)
 				  ~SECOCEC_ENABLE_REG_1_CEC &
 				  ~SECOCEC_ENABLE_REG_1_IR);
 
-		dev_dbg(dev, "Device disabled");
+		dev_dbg(dev, "Device disabled\n");
 	}
 
 	return 0;
@@ -264,12 +264,12 @@ static void secocec_rx_done(struct cec_adapter *adap, u16 status_val)
 
 	if (status_val & SECOCEC_STATUS_RX_OVERFLOW_MASK) {
 		/* NOTE: Untested, it also might not be necessary */
-		dev_warn(dev, "Received more than 16 bytes. Discarding");
+		dev_warn(dev, "Received more than 16 bytes. Discarding\n");
 		flag_overflow = true;
 	}
 
 	if (status_val & SECOCEC_STATUS_RX_ERROR_MASK) {
-		dev_warn(dev, "Message received with errors. Discarding");
+		dev_warn(dev, "Message received with errors. Discarding\n");
 		status = -EIO;
 		goto rxerr;
 	}
@@ -390,12 +390,12 @@ static int secocec_ir_probe(void *priv)
 	if (status != 0)
 		goto err;
 
-	dev_dbg(dev, "IR enabled");
+	dev_dbg(dev, "IR enabled\n");
 
 	status = devm_rc_register_device(dev, cec->ir);
 
 	if (status) {
-		dev_err(dev, "Failed to prepare input device");
+		dev_err(dev, "Failed to prepare input device\n");
 		cec->ir = NULL;
 		goto err;
 	}
@@ -408,7 +408,7 @@ static int secocec_ir_probe(void *priv)
 	smb_wr16(SECOCEC_ENABLE_REG_1,
 		 val & ~SECOCEC_ENABLE_REG_1_IR);
 
-	dev_dbg(dev, "IR disabled");
+	dev_dbg(dev, "IR disabled\n");
 	return status;
 }
 
@@ -431,13 +431,13 @@ static int secocec_ir_rx(struct secocec_data *priv)
 
 	rc_keydown(cec->ir, RC_PROTO_RC5, RC_SCANCODE_RC5(addr, key), toggle);
 
-	dev_dbg(dev, "IR key pressed: 0x%02x addr 0x%02x toggle 0x%02x", key,
+	dev_dbg(dev, "IR key pressed: 0x%02x addr 0x%02x toggle 0x%02x\n", key,
 		addr, toggle);
 
 	return 0;
 
 err:
-	dev_err(dev, "IR Receive message failed (%d)", status);
+	dev_err(dev, "IR Receive message failed (%d)\n", status);
 	return -EIO;
 }
 #else
@@ -497,7 +497,7 @@ static irqreturn_t secocec_irq_handler(int irq, void *priv)
 	return IRQ_HANDLED;
 
 err:
-	dev_err_once(dev, "IRQ: R/W SMBus operation failed (%d)", status);
+	dev_err_once(dev, "IRQ: R/W SMBus operation failed %d\n", status);
 
 	/*  Reset status register */
 	val = SECOCEC_STATUS_REG_1_CEC | SECOCEC_STATUS_REG_1_IR;
@@ -553,16 +553,16 @@ static int secocec_acpi_probe(struct secocec_data *sdev)
 
 	gpio = devm_gpiod_get(dev, NULL, GPIOF_IN);
 	if (IS_ERR(gpio)) {
-		dev_err(dev, "Cannot request interrupt gpio");
+		dev_err(dev, "Cannot request interrupt gpio\n");
 		return PTR_ERR(gpio);
 	}
 
 	irq = gpiod_to_irq(gpio);
 	if (irq < 0) {
-		dev_err(dev, "Cannot find valid irq");
+		dev_err(dev, "Cannot find valid irq\n");
 		return -ENODEV;
 	}
-	dev_dbg(dev, "irq-gpio is bound to IRQ %d", irq);
+	dev_dbg(dev, "irq-gpio is bound to IRQ %d\n", irq);
 
 	sdev->irq = irq;
 
@@ -590,7 +590,7 @@ static int secocec_probe(struct platform_device *pdev)
 
 	/* Request SMBus regions */
 	if (!request_muxed_region(BRA_SMB_BASE_ADDR, 7, "CEC00001")) {
-		dev_err(dev, "Request memory region failed");
+		dev_err(dev, "Request memory region failed\n");
 		return -ENXIO;
 	}
 
@@ -598,14 +598,14 @@ static int secocec_probe(struct platform_device *pdev)
 	secocec->dev = dev;
 
 	if (!has_acpi_companion(dev)) {
-		dev_dbg(dev, "Cannot find any ACPI companion");
+		dev_dbg(dev, "Cannot find any ACPI companion\n");
 		ret = -ENODEV;
 		goto err;
 	}
 
 	ret = secocec_acpi_probe(secocec);
 	if (ret) {
-		dev_err(dev, "Cannot assign gpio to IRQ");
+		dev_err(dev, "Cannot assign gpio to IRQ\n");
 		ret = -ENODEV;
 		goto err;
 	}
@@ -613,11 +613,11 @@ static int secocec_probe(struct platform_device *pdev)
 	/* Firmware version check */
 	ret = smb_rd16(SECOCEC_VERSION, &val);
 	if (ret) {
-		dev_err(dev, "Cannot check fw version");
+		dev_err(dev, "Cannot check fw version\n");
 		goto err;
 	}
 	if (val < SECOCEC_LATEST_FW) {
-		dev_err(dev, "CEC Firmware not supported (v.%04x). Use ver > v.%04x",
+		dev_err(dev, "CEC Firmware not supported (v.%04x). Use ver > v.%04x\n",
 			val, SECOCEC_LATEST_FW);
 		ret = -EINVAL;
 		goto err;
@@ -631,7 +631,7 @@ static int secocec_probe(struct platform_device *pdev)
 					dev_name(&pdev->dev), secocec);
 
 	if (ret) {
-		dev_err(dev, "Cannot request IRQ %d", secocec->irq);
+		dev_err(dev, "Cannot request IRQ %d\n", secocec->irq);
 		ret = -EIO;
 		goto err;
 	}
@@ -666,7 +666,7 @@ static int secocec_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, secocec);
 
-	dev_dbg(dev, "Device registered");
+	dev_dbg(dev, "Device registered\n");
 
 	return ret;
 
@@ -691,14 +691,14 @@ static int secocec_remove(struct platform_device *pdev)
 
 		smb_wr16(SECOCEC_ENABLE_REG_1, val & ~SECOCEC_ENABLE_REG_1_IR);
 
-		dev_dbg(&pdev->dev, "IR disabled");
+		dev_dbg(&pdev->dev, "IR disabled\n");
 	}
 	cec_notifier_cec_adap_unregister(secocec->notifier, secocec->cec_adap);
 	cec_unregister_adapter(secocec->cec_adap);
 
 	release_region(BRA_SMB_BASE_ADDR, 7);
 
-	dev_dbg(&pdev->dev, "CEC device removed");
+	dev_dbg(&pdev->dev, "CEC device removed\n");
 
 	return 0;
 }
@@ -709,7 +709,7 @@ static int secocec_suspend(struct device *dev)
 	int status;
 	u16 val;
 
-	dev_dbg(dev, "Device going to suspend, disabling");
+	dev_dbg(dev, "Device going to suspend, disabling\n");
 
 	/* Clear the status register */
 	status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
@@ -733,7 +733,7 @@ static int secocec_suspend(struct device *dev)
 	return 0;
 
 err:
-	dev_err(dev, "Suspend failed (err: %d)", status);
+	dev_err(dev, "Suspend failed: %d\n", status);
 	return status;
 }
 
@@ -742,7 +742,7 @@ static int secocec_resume(struct device *dev)
 	int status;
 	u16 val;
 
-	dev_dbg(dev, "Resuming device from suspend");
+	dev_dbg(dev, "Resuming device from suspend\n");
 
 	/* Clear the status register */
 	status = smb_rd16(SECOCEC_STATUS_REG_1, &val);
@@ -762,12 +762,12 @@ static int secocec_resume(struct device *dev)
 	if (status)
 		goto err;
 
-	dev_dbg(dev, "Device resumed from suspend");
+	dev_dbg(dev, "Device resumed from suspend\n");
 
 	return 0;
 
 err:
-	dev_err(dev, "Resume failed (err: %d)", status);
+	dev_err(dev, "Resume failed: %d\n", status);
 	return status;
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] media: cec: add SECO MEC-based cec driver
  2022-02-01 18:37 ` [PATCH 1/2] media: cec: add SECO MEC-based cec driver ektor5
@ 2022-02-02 14:31   ` kernel test robot
  0 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2022-02-02 14:31 UTC (permalink / raw)
  To: ektor5
  Cc: llvm, kbuild-all, Hans Verkuil, Mauro Carvalho Chehab,
	linux-media, Ettore Chimenti, linux-kernel, linuxfancy

Hi ektor5,

I love your patch! Perhaps something to improve:

[auto build test WARNING on media-tree/master]
[also build test WARNING on linux/master linus/master v5.17-rc2 next-20220202]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/ektor5/Add-SECO-CEC-driver-for-MEC-Based-boards/20220202-023834
base:   git://linuxtv.org/media_tree.git master
config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20220202/202202022216.MCt6c52g-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 6b1e844b69f15bb7dffaf9365cd2b355d2eb7579)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/8960cb39808a004dee84a2f955ed949b1a4da7a8
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review ektor5/Add-SECO-CEC-driver-for-MEC-Based-boards/20220202-023834
        git checkout 8960cb39808a004dee84a2f955ed949b1a4da7a8
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/media/cec/platform/seco/ drivers/net/wireless/ath/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/media/cec/platform/seco/seco-meccec.c:735:8: warning: variable 'adaps' is uninitialized when used here [-Wuninitialized]
                           if (adaps--)
                               ^~~~~
   drivers/media/cec/platform/seco/seco-meccec.c:634:11: note: initialize the variable 'adaps' to silence this warning
           int adaps, notifs = 0;
                    ^
                     = 0
   1 warning generated.


vim +/adaps +735 drivers/media/cec/platform/seco/seco-meccec.c

   626	
   627	static int seco_meccec_probe(struct platform_device *pdev)
   628	{
   629		struct seco_meccec_data *meccec;
   630		struct device *dev = &pdev->dev;
   631		struct device *hdmi_dev;
   632		const char * const *conn;
   633		int ret, idx;
   634		int adaps, notifs = 0;
   635	
   636		meccec = devm_kzalloc(dev, sizeof(*meccec), GFP_KERNEL);
   637		if (!meccec)
   638			return -ENOMEM;
   639	
   640		dev_set_drvdata(dev, meccec);
   641	
   642		meccec->pdev = pdev;
   643		meccec->dev = dev;
   644	
   645		ret = ec_get_version(meccec);
   646		if (ret) {
   647			dev_err(dev, "Get version failed\n");
   648			goto err;
   649		}
   650	
   651		if (!has_acpi_companion(dev)) {
   652			dev_err(dev, "Cannot find any ACPI companion\n");
   653			ret = -ENODEV;
   654			goto err;
   655		}
   656	
   657		ret = seco_meccec_acpi_probe(meccec);
   658		if (ret) {
   659			dev_err(dev, "ACPI probe failed\n");
   660			goto err;
   661		}
   662	
   663		ret = devm_request_threaded_irq(dev,
   664						meccec->irq,
   665						NULL,
   666						seco_meccec_irq_handler,
   667						IRQF_TRIGGER_RISING | IRQF_ONESHOT,
   668						dev_name(&pdev->dev), meccec);
   669	
   670		if (ret) {
   671			dev_err(dev, "Cannot request IRQ %d\n", meccec->irq);
   672			ret = -EIO;
   673			goto err;
   674		}
   675	
   676		hdmi_dev = seco_meccec_find_hdmi_dev(&pdev->dev, &conn);
   677		if (IS_ERR(hdmi_dev)) {
   678			dev_err(dev, "Cannot find HDMI Device\n");
   679			return PTR_ERR(hdmi_dev);
   680		}
   681		dev_dbg(dev, "HDMI device found\n");
   682	
   683		for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
   684			if (meccec->channels & BIT_MASK(idx)) {
   685				ret = meccec_create_adapter(meccec, idx);
   686				if (ret)
   687					goto err_delete_adapter;
   688				dev_dbg(dev, "CEC adapter #%d allocated\n", idx);
   689			}
   690		}
   691	
   692		for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
   693			if (meccec->channels & BIT_MASK(idx)) {
   694				struct cec_adapter *acec = meccec->cec_adap[idx];
   695				struct cec_notifier *ncec;
   696	
   697				if (!acec) {
   698					ret = -EINVAL;
   699					goto err_notifier;
   700				}
   701	
   702				ncec = cec_notifier_cec_adap_register(hdmi_dev,
   703								      conn[idx], acec);
   704	
   705				dev_dbg(dev, "CEC notifier #%d allocated %s\n", idx, conn[idx]);
   706	
   707				if (IS_ERR(ncec)) {
   708					ret = PTR_ERR(ncec);
   709					goto err_notifier;
   710				}
   711	
   712				meccec->notifier[idx] = ncec;
   713				notifs++;
   714			}
   715		}
   716	
   717		for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
   718			if (meccec->channels & BIT_MASK(idx)) {
   719				ret = cec_register_adapter(meccec->cec_adap[idx], dev);
   720				if (ret)
   721					goto err_notifier;
   722	
   723				dev_dbg(dev, "CEC adapter #%d registered\n", idx);
   724			}
   725		}
   726	
   727		platform_set_drvdata(pdev, meccec);
   728		dev_dbg(dev, "Device registered\n");
   729	
   730		return ret;
   731	
   732	err_notifier:
   733		for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
   734			if (meccec->channels & BIT_MASK(idx)) {
 > 735				if (adaps--)
   736					return ret;
   737	
   738				cec_notifier_cec_adap_unregister(meccec->notifier[idx],
   739								 meccec->cec_adap[idx]);
   740			}
   741		}
   742	err_delete_adapter:
   743		for (idx = 0; idx < MECCEC_MAX_CEC_ADAP; idx++) {
   744			if (meccec->channels & BIT_MASK(idx)) {
   745				if (notifs--)
   746					return ret;
   747	
   748				cec_delete_adapter(meccec->cec_adap[idx]);
   749			}
   750		}
   751	err:
   752		dev_err(dev, "%s device probe failed: %d\n", dev_name(dev), ret);
   753	
   754		return ret;
   755	}
   756	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-02-02 14:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-01 18:37 [PATCH 0/2] Add SECO CEC driver for MEC Based boards ektor5
2022-02-01 18:37 ` [PATCH 1/2] media: cec: add SECO MEC-based cec driver ektor5
2022-02-02 14:31   ` kernel test robot
2022-02-01 18:37 ` [PATCH 2/2] media: cec: seco: add newlines in debug messages ektor5

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).