* [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
* 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
* [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
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).