* [PATCH v3 0/5] Add the cat24c208 EDID EEPROM driver + new EDID capability
@ 2022-09-28 11:21 Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 1/5] media: videodev2.h: add V4L2_CAP_EDID Erling Ljunggren
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Erling Ljunggren @ 2022-09-28 11:21 UTC (permalink / raw)
To: linux-media; +Cc: Erling Ljunggren
This series adds support for the standalone cat24c208 EDID EEPROM i2c device.
Usually EDID support is part of an HDMI receiver, but this is a standalone EEPROM.
Note that EEPROMs for EDIDs are not regular EEPROM devices, these are dual port
devices that follow the VESA E-DDC standard.
Since this is a standalone device that does not capture any video a new
V4L2_CAP_EDID capability is introduced to represent such devices.
Note that such a device doesn't have to be an EEPROM, it can also be
implemented using a microcontroller, for example.
v3:
- use old V4L2_CAP_ASYNCIO (0x02000000) capability bit
- validate physical address of edid in driver
- handle empty edid in driver
- add cec notifier support to driver
- update driver and bindings with hpd gpio support
- removed references to "memory" in capability and docs
- associate ioctls based on device direction
v2:
- fix dt binding example
- rename i2c client variables in data struct
- fix include: of_device.h -> mod_devicetable.h
- Sorted makefile
- used define EDID_OFFSET_EXT_FLAG instead of magic number
- removed of_match_ptr
- added bus_info
- remove unneeded headers
- add depends on OF to Kconfig
Erling Ljunggren (4):
media: videodev2.h: add V4L2_CAP_EDID
media: docs: Add V4L2_CAP_EDID
dt-bindings: media: add cat24c208 bindings
media: v4l2-dev: handle V4L2_CAP_EDID
Jonathan Selnes (1):
media: i2c: cat24c208: driver for the cat24c208 EDID EEPROM
.../bindings/media/i2c/onnn,cat24c208.yaml | 48 ++
.../userspace-api/media/v4l/biblio.rst | 11 +
.../media/v4l/vidioc-querycap.rst | 11 +
.../media/videodev2.h.rst.exceptions | 1 +
MAINTAINERS | 7 +
drivers/media/i2c/Kconfig | 9 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/cat24c208.c | 480 ++++++++++++++++++
drivers/media/v4l2-core/v4l2-dev.c | 15 +
include/uapi/linux/videodev2.h | 1 +
10 files changed, 584 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
create mode 100644 drivers/media/i2c/cat24c208.c
--
2.37.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 1/5] media: videodev2.h: add V4L2_CAP_EDID
2022-09-28 11:21 [PATCH v3 0/5] Add the cat24c208 EDID EEPROM driver + new EDID capability Erling Ljunggren
@ 2022-09-28 11:21 ` Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 2/5] media: docs: Add V4L2_CAP_EDID Erling Ljunggren
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Erling Ljunggren @ 2022-09-28 11:21 UTC (permalink / raw)
To: linux-media; +Cc: Erling Ljunggren
Add capability flag to indicate that the device is an EDID-only device.
Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
---
include/uapi/linux/videodev2.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 054fc8bbdb22..2ea95639f441 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -480,6 +480,7 @@ struct v4l2_capability {
#define V4L2_CAP_META_CAPTURE 0x00800000 /* Is a metadata capture device */
#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
+#define V4L2_CAP_EDID 0x02000000 /* Is an EDID-only device */
#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
#define V4L2_CAP_META_OUTPUT 0x08000000 /* Is a metadata output device */
--
2.37.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 2/5] media: docs: Add V4L2_CAP_EDID
2022-09-28 11:21 [PATCH v3 0/5] Add the cat24c208 EDID EEPROM driver + new EDID capability Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 1/5] media: videodev2.h: add V4L2_CAP_EDID Erling Ljunggren
@ 2022-09-28 11:21 ` Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings Erling Ljunggren
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Erling Ljunggren @ 2022-09-28 11:21 UTC (permalink / raw)
To: linux-media; +Cc: Erling Ljunggren
Add documentation for the new edid capability.
Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
---
Documentation/userspace-api/media/v4l/biblio.rst | 11 +++++++++++
.../userspace-api/media/v4l/vidioc-querycap.rst | 11 +++++++++++
.../userspace-api/media/videodev2.h.rst.exceptions | 1 +
3 files changed, 23 insertions(+)
diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst
index 9cd18c153d19..5cbe41877a63 100644
--- a/Documentation/userspace-api/media/v4l/biblio.rst
+++ b/Documentation/userspace-api/media/v4l/biblio.rst
@@ -334,6 +334,17 @@ VESA DMT
:author: Video Electronics Standards Association (http://www.vesa.org)
+.. _vesaeddc:
+
+E-DDC
+====
+
+
+:title: VESA Enhanced Display Data Channel (E-DDC) Standard
+:subtitle: Version 1.3
+
+:author: Video Electronics Standards Association (http://www.vesa.org)
+
.. _vesaedid:
EDID
diff --git a/Documentation/userspace-api/media/v4l/vidioc-querycap.rst b/Documentation/userspace-api/media/v4l/vidioc-querycap.rst
index 6c57b8428356..3d11d86d9cbf 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-querycap.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-querycap.rst
@@ -244,6 +244,17 @@ specification the ioctl returns an ``EINVAL`` error code.
- 0x01000000
- The device supports the :c:func:`read()` and/or
:c:func:`write()` I/O methods.
+ * - ``V4L2_CAP_EDID``
+ - 0x02000000
+ - The device stores the EDID for a video input, or retrieves the EDID for a video
+ output. It is a standalone EDID device, so no video streaming etc. will take place.
+
+ For a video input this is typically an eeprom that supports the
+ :ref:`VESA Enhanced Display Data Channel Standard <vesaeddc>`. It can be something
+ else as well, for example a micro controller.
+
+ For a video output this is typically read from an external device such as an
+ HDMI splitter accessed by a serial port.
* - ``V4L2_CAP_STREAMING``
- 0x04000000
- The device supports the :ref:`streaming <mmap>` I/O method.
diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
index 9cbb7a0c354a..b1b1127d278c 100644
--- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions
+++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions
@@ -185,6 +185,7 @@ replace define V4L2_CAP_META_OUTPUT device-capabilities
replace define V4L2_CAP_DEVICE_CAPS device-capabilities
replace define V4L2_CAP_TOUCH device-capabilities
replace define V4L2_CAP_IO_MC device-capabilities
+replace define V4L2_CAP_EDID device-capabilities
# V4L2 pix flags
replace define V4L2_PIX_FMT_PRIV_MAGIC :c:type:`v4l2_pix_format`
--
2.37.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings
2022-09-28 11:21 [PATCH v3 0/5] Add the cat24c208 EDID EEPROM driver + new EDID capability Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 1/5] media: videodev2.h: add V4L2_CAP_EDID Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 2/5] media: docs: Add V4L2_CAP_EDID Erling Ljunggren
@ 2022-09-28 11:21 ` Erling Ljunggren
2022-09-28 22:37 ` Rob Herring
2022-09-29 13:26 ` Rob Herring
2022-09-28 11:21 ` [PATCH v3 4/5] media: i2c: cat24c208: driver for the cat24c208 EDID EEPROM Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 5/5] media: v4l2-dev: handle V4L2_CAP_EDID Erling Ljunggren
4 siblings, 2 replies; 9+ messages in thread
From: Erling Ljunggren @ 2022-09-28 11:21 UTC (permalink / raw)
To: linux-media; +Cc: Erling Ljunggren, devicetree
Add devicetree bindings for new cat24c208 EDID EEPROM driver.
Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
---
.../bindings/media/i2c/onnn,cat24c208.yaml | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
diff --git a/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml b/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
new file mode 100644
index 000000000000..fcfaccb5e39f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/onnn,cat24c208.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ON Semiconductor CAT24C208 EDID EEPROM driver
+
+maintainers:
+ - Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+description: |
+ CAT24C208 is a dual port i2c EEPROM designed for EDID storage.
+
+
+properties:
+ compatible:
+ const: onnn,cat24c208
+
+ reg:
+ maxItems: 1
+
+ hpd-gpios:
+ maxItems: 1
+ description:
+ References to the GPIO that controls the HDMI hot-plug detection pin.
+ The active flag indicates the GPIO level that enables hot-plug detection.
+
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cat24c208@31 {
+ compatible = "onnn,cat24c208";
+ reg = <0x31>;
+ hpd-gpios = <&ioexp 0 GPIO_ACTIVE_HIGH>;
+ };
+ };
+...
--
2.37.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 4/5] media: i2c: cat24c208: driver for the cat24c208 EDID EEPROM
2022-09-28 11:21 [PATCH v3 0/5] Add the cat24c208 EDID EEPROM driver + new EDID capability Erling Ljunggren
` (2 preceding siblings ...)
2022-09-28 11:21 ` [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings Erling Ljunggren
@ 2022-09-28 11:21 ` Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 5/5] media: v4l2-dev: handle V4L2_CAP_EDID Erling Ljunggren
4 siblings, 0 replies; 9+ messages in thread
From: Erling Ljunggren @ 2022-09-28 11:21 UTC (permalink / raw)
To: linux-media; +Cc: Jonathan Selnes, Hans Verkuil, Erling Ljunggren
From: Jonathan Selnes <jonathansb1@gmail.com>
Support reading and writing the EDID EEPROM through the
v4l2 API.
Signed-off-by: Jonathan Selnes <jonathansb1@gmail.com>
Co-developed-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Co-developed-by: Erling Ljunggren <hljunggr@cisco.com>
Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
---
MAINTAINERS | 7 +
drivers/media/i2c/Kconfig | 9 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/cat24c208.c | 480 ++++++++++++++++++++++++++++++++++
4 files changed, 497 insertions(+)
create mode 100644 drivers/media/i2c/cat24c208.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 7d9490a5c15a..407d76c42bab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14912,6 +14912,13 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov9734.c
+ON SEMICONDUCTOR CAT24C208 EDID EEPROM DRIVER
+M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
+F: drivers/media/i2c/cat24c208*
+
ONENAND FLASH DRIVER
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-mtd@lists.infradead.org
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 2b20aa6c37b1..2f5f9f058b48 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1530,6 +1530,15 @@ endmenu
menu "Miscellaneous helper chips"
visible if !MEDIA_HIDE_ANCILLARY_SUBDRV
+config VIDEO_CAT24C208
+ tristate "ON Semiconductor cat24c208 EDID EEPROM"
+ depends on VIDEO_DEV && I2C && OF
+ help
+ Support for the ON Semiconductor CAT24C208 Dual Port EDID EEPROM.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cat24c208.
+
config VIDEO_I2C
tristate "I2C transport video support"
depends on VIDEO_DEV && I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 3e1696963e7f..70e4360a21ba 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
obj-$(CONFIG_VIDEO_BT819) += bt819.o
obj-$(CONFIG_VIDEO_BT856) += bt856.o
obj-$(CONFIG_VIDEO_BT866) += bt866.o
+obj-$(CONFIG_VIDEO_CAT24C208) += cat24c208.o
obj-$(CONFIG_VIDEO_CCS) += ccs/
obj-$(CONFIG_VIDEO_CCS_PLL) += ccs-pll.o
obj-$(CONFIG_VIDEO_CS3308) += cs3308.o
diff --git a/drivers/media/i2c/cat24c208.c b/drivers/media/i2c/cat24c208.c
new file mode 100644
index 000000000000..63b496f62c19
--- /dev/null
+++ b/drivers/media/i2c/cat24c208.c
@@ -0,0 +1,480 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HDMI i2c controlled EEPROM from ON Semiconductor or Catalyst Semiconductor
+ *
+ * Support for i2c based DDC EEPROM
+ *
+ * Copyright (C) 2021-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * REF_01 - ON Semiconductor, cat24c208, Datasheet, URL : https://www.onsemi.com/pdf/datasheet/cat24c208-d.pdf
+ * Revision 7, May 2018
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mod_devicetable.h>
+#include <linux/gpio/consumer.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+
+#include <media/cec-notifier.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dv-timings.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+
+MODULE_DESCRIPTION("cat24c208 EDID EEPROM driver");
+MODULE_AUTHOR("Jonathan Selnes Bognaes <jonathansb1@gmail.com>");
+MODULE_LICENSE("GPL");
+
+/*
+ * CAT24C208 setup
+ */
+#define BYTES_PER_BLOCK 128
+#define EDID_OFFSET_EXT_FLAG 126
+#define MAX_WRITE_BYTES 16
+#define NUM_BLOCKS 4
+#define NUM_CLIENTS 3
+#define CONFIG_NB_BIT BIT(0)
+#define CONFIG_AB0_BIT BIT(1)
+#define CONFIG_AB1_BIT BIT(2)
+#define CONFIG_WE_BIT BIT(3)
+
+/*
+ * From the datasheet: REF_01
+ *
+ * The write cycle time is the time from a valid stop condition of a write
+ * sequence to the end of the internal program/erase cycle. During the write
+ * cycle, the bus interface circuits are disabled, SDA is allowed to remain
+ * high, and the device does not respond to its slave address.
+ */
+#define WRITE_CYCLE_TIME_US 5000
+
+/*
+ * CAT24C208 addresses
+ */
+#define CONFIG_I2C_ADDR 0x31
+#define EEPROM_I2C_ADDR 0x50
+#define SEGMENT_I2C_ADDR 0x30
+
+struct cat24c208_state {
+ struct i2c_client *dev_client;
+ struct i2c_client *data_client;
+ struct i2c_client *seg_client;
+ // V4L2 ioctl serialization
+ struct mutex lock;
+ struct cec_notifier *notifier;
+ struct delayed_work dwork_enable_hpd;
+
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct gpio_desc *hpd_gpio;
+
+ u8 edid_blocks; // edid length can vary, one block = 128 bytes
+ u8 edid[BYTES_PER_BLOCK * NUM_BLOCKS]; // actual active edid data
+};
+
+static const struct v4l2_file_operations cat24c208_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = v4l2_fh_release,
+ .unlocked_ioctl = video_ioctl2,
+};
+
+static int cat24c208_seg_write(struct cat24c208_state *state, u8 *data, u16 len, u8 seg)
+{
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->seg_client->addr, // Segment
+ .buf = &seg,
+ .len = 1,
+ .flags = 0,
+ },
+ {
+ .addr = state->data_client->addr, // write data
+ .buf = data,
+ .len = len,
+ .flags = 0,
+ },
+ };
+ int err;
+
+ if (seg)
+ err = i2c_transfer(state->dev_client->adapter, msg, ARRAY_SIZE(msg));
+ else
+ err = i2c_transfer(state->dev_client->adapter, &msg[1], 1);
+
+ if (err < 0)
+ dev_err(&state->dev_client->dev, "Writing to 0x%x failed (segment %d)\n",
+ state->data_client->addr, seg);
+
+ usleep_range(WRITE_CYCLE_TIME_US, 2 * WRITE_CYCLE_TIME_US);
+ return err < 0 ? err : 0;
+}
+
+static int cat24c208_edid_read(struct cat24c208_state *state, u8 *data, u8 seg, u8 offset, u16 len)
+{
+ int err;
+
+ len *= BYTES_PER_BLOCK;
+ if (seg) {
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->seg_client->addr, // Segment
+ .buf = &seg,
+ .len = 1,
+ .flags = 0,
+ },
+ {
+ .addr = state->data_client->addr, // read data
+ .buf = data,
+ .len = len,
+ .flags = I2C_M_RD,
+ },
+ };
+ err = i2c_transfer(state->dev_client->adapter, msg, ARRAY_SIZE(msg));
+ } else {
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->data_client->addr, // set offset
+ .buf = &offset,
+ .len = 1,
+ .flags = 0,
+ },
+ {
+ .addr = state->data_client->addr, // read data
+ .buf = data,
+ .len = len,
+ .flags = I2C_M_RD,
+ },
+ };
+ err = i2c_transfer(state->dev_client->adapter, msg, ARRAY_SIZE(msg));
+ }
+
+ if (err < 0)
+ dev_err(&state->dev_client->dev, "Reading of EDID failed\n");
+ return err < 0 ? err : 0;
+}
+
+static int cat24c208_set_config(struct i2c_client *client)
+{
+ u8 buf[2] = { 0, CONFIG_NB_BIT };
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .buf = buf,
+ .len = sizeof(buf),
+ .flags = 0,
+ };
+ int err;
+
+ err = i2c_transfer(client->adapter, &msg, 1);
+ if (err < 0)
+ dev_err(&client->dev, "Could not set config register\n");
+
+ usleep_range(WRITE_CYCLE_TIME_US, 2 * WRITE_CYCLE_TIME_US);
+ return err < 0 ? err : 0;
+}
+
+static bool cat24c208_is_valid_edid(const u8 *block)
+{
+ static const u8 header_pattern[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
+ };
+
+ return !memcmp(block, header_pattern, sizeof(header_pattern));
+}
+
+static void cat24c208_delayed_work_release_hpd(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct cat24c208_state *state = container_of(dwork, struct cat24c208_state,
+ dwork_enable_hpd);
+
+ gpiod_set_value(state->hpd_gpio, 1);
+}
+
+static int cat24c208_set_edid(struct file *file, void *fh, struct v4l2_edid *edid)
+{
+ struct cat24c208_state *state = video_drvdata(file);
+ u8 buf[MAX_WRITE_BYTES + 1];
+ u16 pa;
+ int err;
+ int seg;
+ int i;
+
+ memset(edid->reserved, 0, sizeof(edid->reserved));
+
+ if (edid->pad)
+ return -EINVAL;
+
+ if (edid->blocks > NUM_BLOCKS) {
+ edid->blocks = NUM_BLOCKS;
+ return -E2BIG;
+ }
+
+ if (edid->start_block)
+ return -EINVAL;
+
+ pa = v4l2_get_edid_phys_addr(edid->edid, edid->blocks * BYTES_PER_BLOCK, NULL);
+
+ err = v4l2_phys_addr_validate(pa, NULL, NULL);
+ if (err)
+ return err;
+
+ if (state->hpd_gpio) {
+ cancel_delayed_work_sync(&state->dwork_enable_hpd);
+ gpiod_set_value(state->hpd_gpio, 0);
+ }
+
+ if (edid->blocks == 0) {
+ cec_notifier_set_phys_addr(state->notifier, pa);
+ return 0;
+ }
+
+ state->edid_blocks = edid->blocks;
+ memcpy(state->edid, edid->edid, state->edid_blocks * BYTES_PER_BLOCK);
+
+ /* Write EDID to EEPROM */
+ for (i = 0; i < edid->blocks * BYTES_PER_BLOCK; i = i + MAX_WRITE_BYTES) {
+ if (i >= 2 * BYTES_PER_BLOCK) {
+ seg = 1;
+ buf[0] = i - BYTES_PER_BLOCK * 2;
+ } else {
+ seg = 0;
+ buf[0] = i;
+ }
+
+ memcpy(buf + 1, &edid->edid[i], MAX_WRITE_BYTES);
+ err = cat24c208_seg_write(state, buf, MAX_WRITE_BYTES + 1, seg);
+ if (err) {
+ dev_err(&state->dev_client->dev,
+ "Could not write EDID to EEPROM, i: %d\n", i);
+ return err;
+ }
+ }
+
+ cec_notifier_set_phys_addr(state->notifier, pa);
+
+ if (state->hpd_gpio)
+ schedule_delayed_work(&state->dwork_enable_hpd, 110 * HZ / 1000);
+
+ return 0;
+}
+
+static int cat24c208_get_edid(struct file *file, void *fh, struct v4l2_edid *edid)
+{
+ struct cat24c208_state *state = video_drvdata(file);
+
+ memset(edid->reserved, 0, sizeof(edid->reserved));
+
+ if (edid->pad != 0)
+ return -EINVAL;
+
+ if (edid->start_block == 0 && edid->blocks == 0) {
+ edid->blocks = state->edid_blocks;
+ return 0;
+ }
+
+ if (state->edid_blocks == 0)
+ return -ENODATA;
+
+ if (edid->start_block >= state->edid_blocks)
+ return -EINVAL;
+
+ if (edid->start_block + edid->blocks > state->edid_blocks)
+ edid->blocks = state->edid_blocks - edid->start_block;
+
+ memcpy(edid->edid, state->edid + edid->start_block * BYTES_PER_BLOCK,
+ edid->blocks * BYTES_PER_BLOCK);
+
+ return 0;
+}
+
+static int cat24c208_get_input(struct file *file, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int cat24c208_set_input(struct file *file, void *priv, unsigned int i)
+{
+ return i > 0 ? -EINVAL : 0;
+}
+
+static int cat24c208_enum_input(struct file *file, void *priv,
+ struct v4l2_input *inp)
+{
+ if (inp->index)
+ return -EINVAL;
+ strscpy(inp->name, "HDMI", sizeof(inp->name));
+ inp->capabilities = 0;
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ return 0;
+}
+
+static int cat24c208_querycap(struct file *file,
+ void *priv, struct v4l2_capability *cap)
+{
+ struct cat24c208_state *state = video_drvdata(file);
+ struct i2c_client *client = state->dev_client;
+
+ strscpy(cap->driver, "cat24c208", sizeof(cap->driver));
+ strscpy(cap->card, "cat24c208 EDID EEPROM", sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info),
+ "I2C:%d-%04x", client->adapter->nr, client->addr);
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops cat24c208_ioctl_ops = {
+ .vidioc_querycap = cat24c208_querycap,
+ .vidioc_g_edid = cat24c208_get_edid,
+ .vidioc_s_edid = cat24c208_set_edid,
+ .vidioc_g_input = cat24c208_get_input,
+ .vidioc_s_input = cat24c208_set_input,
+ .vidioc_enum_input = cat24c208_enum_input,
+};
+
+static void cat24c208_release(struct video_device *vdev)
+{
+ struct cat24c208_state *state = video_get_drvdata(vdev);
+
+ v4l2_device_unregister(&state->v4l2_dev);
+ mutex_destroy(&state->lock);
+ kfree(state);
+}
+
+static int cat24c208_probe(struct i2c_client *client)
+{
+ struct cat24c208_state *state;
+ struct v4l2_device *v4l2_dev;
+ int blocks;
+ int ret;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->dev_client = client;
+ state->data_client = i2c_new_ancillary_device(client, "eeprom", EEPROM_I2C_ADDR);
+ if (IS_ERR(state->data_client)) {
+ ret = PTR_ERR(state->data_client);
+ goto free_state;
+ }
+ state->seg_client = i2c_new_ancillary_device(client, "segment", SEGMENT_I2C_ADDR);
+ if (IS_ERR(state->seg_client)) {
+ ret = PTR_ERR(state->seg_client);
+ goto unreg_i2c_first;
+ }
+
+ ret = cat24c208_set_config(client);
+ if (ret)
+ goto unreg_i2c_all;
+
+ if (cat24c208_edid_read(state, state->edid, 0, 0, 2) >= 0 &&
+ cat24c208_is_valid_edid(state->edid)) {
+ unsigned int i;
+
+ blocks = 1 + state->edid[EDID_OFFSET_EXT_FLAG];
+ state->edid_blocks = blocks;
+ for (i = 2; i < blocks; i += 2) {
+ if (cat24c208_edid_read(state, state->edid + i * BYTES_PER_BLOCK,
+ i / 2, 0, (i + 1 >= blocks ? 1 : 2))) {
+ state->edid_blocks = i;
+ break;
+ }
+ }
+ }
+
+ v4l2_dev = &state->v4l2_dev;
+ strscpy(v4l2_dev->name, "cat24c208", sizeof(v4l2_dev->name));
+ ret = v4l2_device_register(&client->dev, v4l2_dev);
+ if (ret) {
+ dev_err(&client->dev, "v4l2_device_register failed: %d\n", ret);
+ goto unreg_i2c_all;
+ }
+
+ mutex_init(&state->lock);
+
+ state->notifier = cec_notifier_conn_register(&client->dev, NULL, NULL);
+ if (!state->notifier) {
+ dev_err(&client->dev, "Failed to get CEC notifier\n");
+ ret = -ENOMEM;
+ goto unreg_i2c_all;
+ }
+
+ state->hpd_gpio = devm_gpiod_get_optional(&client->dev,
+ "hpd", GPIOD_OUT_LOW);
+ if (IS_ERR(state->hpd_gpio)) {
+ ret = PTR_ERR(state->hpd_gpio);
+ dev_err(&client->dev, "Failed to get hpd-gpio err:%d\n", ret);
+ goto unreg_i2c_all;
+ }
+
+ INIT_DELAYED_WORK(&state->dwork_enable_hpd, cat24c208_delayed_work_release_hpd);
+
+ snprintf(state->vdev.name, sizeof(state->vdev.name),
+ "cat24c208 %d-%d", client->adapter->nr, client->addr);
+
+ state->vdev.v4l2_dev = v4l2_dev;
+ state->vdev.fops = &cat24c208_fops;
+ state->vdev.ioctl_ops = &cat24c208_ioctl_ops;
+ state->vdev.lock = &state->lock;
+ state->vdev.release = cat24c208_release;
+ state->vdev.device_caps = V4L2_CAP_EDID;
+
+ video_set_drvdata(&state->vdev, state);
+ i2c_set_clientdata(client, state);
+ ret = video_register_device(&state->vdev, VFL_TYPE_VIDEO, -1);
+ if (ret != 0) {
+ dev_err(&client->dev, "Video registering failed: %d\n", ret);
+ goto unreg_v4l2_dev;
+ }
+ return 0;
+
+unreg_v4l2_dev:
+ v4l2_device_unregister(&state->v4l2_dev);
+ cec_notifier_conn_unregister(state->notifier);
+ cancel_delayed_work_sync(&state->dwork_enable_hpd);
+unreg_i2c_all:
+ i2c_unregister_device(state->seg_client);
+unreg_i2c_first:
+ i2c_unregister_device(state->data_client);
+free_state:
+ kfree(state);
+ return ret;
+}
+
+static int cat24c208_remove(struct i2c_client *client)
+{
+ struct cat24c208_state *state = i2c_get_clientdata(client);
+
+ cancel_delayed_work_sync(&state->dwork_enable_hpd);
+ cec_notifier_conn_unregister(state->notifier);
+ i2c_unregister_device(state->data_client);
+ i2c_unregister_device(state->seg_client);
+ video_unregister_device(&state->vdev);
+
+ return 0;
+}
+
+static const struct of_device_id cat24c208_of_match[] = {
+ { .compatible = "onnn,cat24c208"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, cat24c208_of_match);
+
+static struct i2c_driver cat24c208_driver = {
+ .driver = {
+ .name = "cat24c208",
+ .of_match_table = cat24c208_of_match,
+ },
+ .probe_new = cat24c208_probe,
+ .remove = cat24c208_remove,
+};
+module_i2c_driver(cat24c208_driver);
--
2.37.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 5/5] media: v4l2-dev: handle V4L2_CAP_EDID
2022-09-28 11:21 [PATCH v3 0/5] Add the cat24c208 EDID EEPROM driver + new EDID capability Erling Ljunggren
` (3 preceding siblings ...)
2022-09-28 11:21 ` [PATCH v3 4/5] media: i2c: cat24c208: driver for the cat24c208 EDID EEPROM Erling Ljunggren
@ 2022-09-28 11:21 ` Erling Ljunggren
4 siblings, 0 replies; 9+ messages in thread
From: Erling Ljunggren @ 2022-09-28 11:21 UTC (permalink / raw)
To: linux-media; +Cc: Erling Ljunggren
When the V4L2_CAP_EDID capability flag is set,
ioctls for enum inputs/outputs and get/set edid are automatically set.
Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
---
drivers/media/v4l2-core/v4l2-dev.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index d00237ee4cae..e8222b9835e6 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -556,6 +556,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
bool is_io_mc = vdev->device_caps & V4L2_CAP_IO_MC;
+ bool is_edid = vdev->device_caps & V4L2_CAP_EDID;
bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);
@@ -778,6 +779,20 @@ static void determine_valid_ioctls(struct video_device *vdev)
SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner);
SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek);
}
+ if (is_edid) {
+ SET_VALID_IOCTL(ops, VIDIOC_G_EDID, vidioc_g_edid);
+ if (is_tx) {
+ SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output);
+ SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output);
+ }
+ if (is_rx) {
+ SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
+ SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
+ SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
+ SET_VALID_IOCTL(ops, VIDIOC_S_EDID, vidioc_s_edid);
+ }
+ }
bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls,
BASE_VIDIOC_PRIVATE);
--
2.37.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings
2022-09-28 11:21 ` [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings Erling Ljunggren
@ 2022-09-28 22:37 ` Rob Herring
2022-09-29 13:26 ` Rob Herring
1 sibling, 0 replies; 9+ messages in thread
From: Rob Herring @ 2022-09-28 22:37 UTC (permalink / raw)
To: Erling Ljunggren; +Cc: devicetree, linux-media
On Wed, 28 Sep 2022 13:21:45 +0200, Erling Ljunggren wrote:
> Add devicetree bindings for new cat24c208 EDID EEPROM driver.
>
> Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
> ---
> .../bindings/media/i2c/onnn,cat24c208.yaml | 48 +++++++++++++++++++
> 1 file changed, 48 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors:
Error: Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.example.dts:25.39-40 syntax error
FATAL ERROR: Unable to parse input tree
make[1]: *** [scripts/Makefile.lib:384: Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.example.dtb] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1420: dt_binding_check] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/patch/
This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings
2022-09-28 11:21 ` [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings Erling Ljunggren
2022-09-28 22:37 ` Rob Herring
@ 2022-09-29 13:26 ` Rob Herring
2022-10-04 8:02 ` Erling Ljunggren (hljunggr)
1 sibling, 1 reply; 9+ messages in thread
From: Rob Herring @ 2022-09-29 13:26 UTC (permalink / raw)
To: Erling Ljunggren; +Cc: linux-media, devicetree
On Wed, Sep 28, 2022 at 01:21:45PM +0200, Erling Ljunggren wrote:
> Add devicetree bindings for new cat24c208 EDID EEPROM driver.
>
> Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
> ---
> .../bindings/media/i2c/onnn,cat24c208.yaml | 48 +++++++++++++++++++
> 1 file changed, 48 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
>
> diff --git a/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml b/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
> new file mode 100644
> index 000000000000..fcfaccb5e39f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
> @@ -0,0 +1,48 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/i2c/onnn,cat24c208.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ON Semiconductor CAT24C208 EDID EEPROM driver
> +
> +maintainers:
> + - Hans Verkuil <hverkuil-cisco@xs4all.nl>
> +
> +description: |
> + CAT24C208 is a dual port i2c EEPROM designed for EDID storage.
> +
> +
> +properties:
> + compatible:
> + const: onnn,cat24c208
> +
> + reg:
> + maxItems: 1
> +
> + hpd-gpios:
> + maxItems: 1
> + description:
> + References to the GPIO that controls the HDMI hot-plug detection pin.
> + The active flag indicates the GPIO level that enables hot-plug detection.
This node is supposed to represent a device, cat24c208, but that device
I'm guessing knows nothing about HPD. That's a property of the connector
and belongs in a connector node much like we have for the other side of
display connections. It may seem like overkill, but it frequently
evolves such that not having a connector node becomes a problem. See
'hdmi-connector' binding for example.
Rob
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings
2022-09-29 13:26 ` Rob Herring
@ 2022-10-04 8:02 ` Erling Ljunggren (hljunggr)
0 siblings, 0 replies; 9+ messages in thread
From: Erling Ljunggren (hljunggr) @ 2022-10-04 8:02 UTC (permalink / raw)
To: robh; +Cc: linux-media, devicetree
On Thu, 2022-09-29 at 08:26 -0500, Rob Herring wrote:
> On Wed, Sep 28, 2022 at 01:21:45PM +0200, Erling Ljunggren wrote:
> > Add devicetree bindings for new cat24c208 EDID EEPROM driver.
> >
> > Signed-off-by: Erling Ljunggren <hljunggr@cisco.com>
> > ---
> > .../bindings/media/i2c/onnn,cat24c208.yaml | 48
> > +++++++++++++++++++
> > 1 file changed, 48 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
> >
> > diff --git
> > a/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
> > b/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
> > new file mode 100644
> > index 000000000000..fcfaccb5e39f
> > --- /dev/null
> > +++
> > b/Documentation/devicetree/bindings/media/i2c/onnn,cat24c208.yaml
> > @@ -0,0 +1,48 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/media/i2c/onnn,cat24c208.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: ON Semiconductor CAT24C208 EDID EEPROM driver
> > +
> > +maintainers:
> > + - Hans Verkuil <hverkuil-cisco@xs4all.nl>
> > +
> > +description: |
> > + CAT24C208 is a dual port i2c EEPROM designed for EDID storage.
> > +
> > +
> > +properties:
> > + compatible:
> > + const: onnn,cat24c208
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + hpd-gpios:
> > + maxItems: 1
> > + description:
> > + References to the GPIO that controls the HDMI hot-plug
> > detection pin.
> > + The active flag indicates the GPIO level that enables hot-
> > plug detection.
>
> This node is supposed to represent a device, cat24c208, but that
> device
> I'm guessing knows nothing about HPD. That's a property of the
> connector
> and belongs in a connector node much like we have for the other side
> of
> display connections. It may seem like overkill, but it frequently
> evolves such that not having a connector node becomes a problem. See
> 'hdmi-connector' binding for example.
>
> Rob
Is this what you had in mind?
cat24c208: cat24c208@31 {
compatible = "onnn,cat24c208";
reg = <0x31>;
status = "okay";
connector-phandle = <&hdmi_in_node>;
};
hdmi_in_node: hdmi-in {
compatible = "hdmi-connector";
label = "HDMI IN";
type = "a";
hpd-gpios = <&pca9554 4 GPIO_ACTIVE_HIGH>;
port {
hdmi_in: endpoint {
remote-endpoint = <&hdmi_out>;
};
};
};
- Erling
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-10-04 8:03 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-28 11:21 [PATCH v3 0/5] Add the cat24c208 EDID EEPROM driver + new EDID capability Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 1/5] media: videodev2.h: add V4L2_CAP_EDID Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 2/5] media: docs: Add V4L2_CAP_EDID Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 3/5] dt-bindings: media: add cat24c208 bindings Erling Ljunggren
2022-09-28 22:37 ` Rob Herring
2022-09-29 13:26 ` Rob Herring
2022-10-04 8:02 ` Erling Ljunggren (hljunggr)
2022-09-28 11:21 ` [PATCH v3 4/5] media: i2c: cat24c208: driver for the cat24c208 EDID EEPROM Erling Ljunggren
2022-09-28 11:21 ` [PATCH v3 5/5] media: v4l2-dev: handle V4L2_CAP_EDID Erling Ljunggren
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).