* Re: [PATCH 07/11] ASoC: mmp-sspa: Prepare/unprepare the clocks
From: Mark Brown @ 2020-05-12 16:29 UTC (permalink / raw)
To: Lubomir Rintel
Cc: Liam Girdwood, Michael Turquette, Stephen Boyd, Rob Herring,
linux-clk, devicetree, linux-kernel, linux-media
In-Reply-To: <20200512153654.GB604838@furthur.local>
[-- Attachment #1: Type: text/plain, Size: 587 bytes --]
On Tue, May 12, 2020 at 05:36:54PM +0200, Lubomir Rintel wrote:
> On Tue, May 12, 2020 at 01:45:20PM +0100, Mark Brown wrote:
> > This fix should've been earlier in the series so it could be sent as a
> > fix.
> I'll order it earlier on v2.
> However, there's not much of a point in picking this patch alone,
> because the driver is certainly not used anywhere and very likely
> doesn't even work to any sensible extent without the rest of the
> series.
Well, I've already applied everything except the DT patches for that
reason - it's just worth pointing out for future reference.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v3 0/6] allow ramoops to collect all kmesg_dump events
From: Steven Rostedt @ 2020-05-12 16:03 UTC (permalink / raw)
To: Petr Mladek
Cc: Pavel Tatashin, Kees Cook, Anton Vorontsov, Colin Cross,
Tony Luck, Jonathan Corbet, Rob Herring, Benson Leung,
Enric Balletbo i Serra, Sergey Senozhatsky, James Morris,
Sasha Levin, Linux Doc Mailing List, LKML, devicetree
In-Reply-To: <20200512155207.GF17734@linux-b0ei>
On Tue, 12 May 2020 17:52:07 +0200
Petr Mladek <pmladek@suse.com> wrote:
> I know that there is the "do not break existing userspace" rule. The
> question is if there is any user and if it is worth it.
If you break user space, and nobody is around to notice it, did you really
break it?
The answer is "No" ;-)
-- Steve
^ permalink raw reply
* Re: [PATCH v3 0/6] allow ramoops to collect all kmesg_dump events
From: Petr Mladek @ 2020-05-12 15:52 UTC (permalink / raw)
To: Pavel Tatashin
Cc: Kees Cook, Anton Vorontsov, Colin Cross, Tony Luck,
Jonathan Corbet, Rob Herring, Benson Leung,
Enric Balletbo i Serra, Sergey Senozhatsky, Steven Rostedt,
James Morris, Sasha Levin, Linux Doc Mailing List, LKML,
devicetree
In-Reply-To: <CA+CK2bBMUxxuTBicQ7ihKpN3jK94mMjcNCXhnAXUaODce09Wmw@mail.gmail.com>
On Tue 2020-05-12 10:03:44, Pavel Tatashin wrote:
> > OK, I personally see this as two separate problems:
> >
> > 1. Missing support to set loglevel per console.
> > 2. Missing support to dump messages for other reasons.
> >
> > I would remove the paragraph about console log levels completely.
>
> OK, I see your point, this paragraph can be removed, however, I think
> it makes it clear to understand the rationale for this change. As I
> understand, the per console loglevel has been proposed but were never
> accepted.
The proposal was not accepted because there were more requirements:
+ add console device into sysfs so that it can be modified there
+ make a reasonable backward compatible behavior
I guess that the sysfs interface discouraged the author to continue
on it.
Note that console loglevel handling is very complicated. There are
already four variables, see console_printk array in
kernel/printk/printk.c. Per console loglevel would make it even
more complicated.
It is a nighmare. And introducing max_reason parameter goes the same way.
> > Now, the max_reason logic makes sense only when all the values
> > have some ordering. Is this the case?
> >
> > I see it as two distinct sets:
> >
> > + panic, oops, emerg: describe how critical is an error situation
> > + restart, halt, poweroff: describe behavior when the system goes down
> >
> > Let's say that panic is more critical than oops. Is restart more
> > critical than halt?
> >
> > If you want the dump during restart. Does it mean that you want it
> > also during emergency situation?
> >
> > My fear is that this patchset is going to introduce user interface
> > (max_reason) with a weird logic. IMHO, max_reason is confusing even
> > in the code and we should not spread this to users.
> >
> > Is there any reason why the existing printk.always_kmsg_dump option
> > is not enough for you?
>
> printk.always_kmsg_dump is not working for me because ramoops has its
> own filtering based on dump_oops boolean, and ignores everything but
> panics and conditionally oops.
> max_reason makes the ramoops internal logic cleaner compared to using dump_oops.
I see. Just to be sure. Is the main reason to add max_reason parameter
to keep complatibility of the deprecated dump_oops parameter? Or is
there any real use case for this granularity?
I made some arecheology. ramoops.dump_oops parameter was added in 2010 by the
initial commit 56d611a04fb2db77334e ("char drivers: RAM oops/panic
logger."
Note that the initial implementation printed Oops reason only when
dump_oops was set. It printed all other reasons otherwise. It seems
that there were only the two reasons at that time.
Now, printk.always_kmsg_dump parameter was added later in 2012 by
the commit c22ab332902333f8376601 ("kmsg_dump: don't run on non-error
paths by default").
IMHO, the later commit actually fixed the default behavior of ramoops.
I wonder if anyone is actually using the ramoops.dump_oops parameter
in reality. I would personally make it deprecated and change the
default behavior to work according to printk.always_kmsg_dump parameter.
IMHO, ramoops.dump_oops just increases complexity and should not have
been introduced at all. I would try hard to avoid introducing even bigger
complecity and mess.
I know that there is the "do not break existing userspace" rule. The
question is if there is any user and if it is worth it.
> I agree, the reasons in kmsg_dump_reason do not order well (I
> actually want to add another reason for kexec type reboots, and where
> do I put it?), so how about if we change the ordering list to
> bitfield/flags, and instead of max_reason provide: "reasons" bitset?
It looks too complicated. I would really try hard to avoid the
parameter at all.
Best Regards,
Petr
^ permalink raw reply
* [PATCH v9 1/4] dt-bindings: media: i2c: Add bindings for Maxim Integrated MAX9286
From: Kieran Bingham @ 2020-05-12 15:51 UTC (permalink / raw)
To: linux-renesas-soc, linux-media, devicetree, linux-kernel,
Mauro Carvalho Chehab
Cc: Kieran Bingham, Laurent Pinchart, Jacopo Mondi,
Niklas Söderlund, sakari.ailus, Hans Verkuil, Hyun Kwon,
Manivannan Sadhasivam, Rob Herring, Laurent Pinchart,
Jacopo Mondi, Kieran Bingham, Niklas Söderlund, Rob Herring
In-Reply-To: <20200512155105.1068064-1-kieran.bingham+renesas@ideasonboard.com>
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
The MAX9286 deserializes video data received on up to 4 Gigabit
Multimedia Serial Links (GMSL) and outputs them on a CSI-2 port using up
to 4 data lanes.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v7:
- Collect Rob's RB tag
- Remove redundant maxItems from remote-endpoints
- Fix SPDX licence tag
.../bindings/media/i2c/maxim,max9286.yaml | 287 ++++++++++++++++++
1 file changed, 287 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
new file mode 100644
index 000000000000..f9d3e5712c59
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
@@ -0,0 +1,287 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2019 Renesas Electronics Corp.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/maxim,max9286.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim Integrated Quad GMSL Deserializer
+
+maintainers:
+ - Jacopo Mondi <jacopo+renesas@jmondi.org>
+ - Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+ - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+ - Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+description: |
+ The MAX9286 deserializer receives video data on up to 4 Gigabit Multimedia
+ Serial Links (GMSL) and outputs them on a CSI-2 D-PHY port using up to 4 data
+ lanes.
+
+ In addition to video data, the GMSL links carry a bidirectional control
+ channel that encapsulates I2C messages. The MAX9286 forwards all I2C traffic
+ not addressed to itself to the other side of the links, where a GMSL
+ serializer will output it on a local I2C bus. In the other direction all I2C
+ traffic received over GMSL by the MAX9286 is output on the local I2C bus.
+
+properties:
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ compatible:
+ const: maxim,max9286
+
+ reg:
+ description: I2C device address
+ maxItems: 1
+
+ poc-supply:
+ description: Regulator providing Power over Coax to the cameras
+ maxItems: 1
+
+ enable-gpios:
+ description: GPIO connected to the \#PWDN pin with inverted polarity
+ maxItems: 1
+
+ ports:
+ type: object
+ description: |
+ The connections to the MAX9286 GMSL and its endpoint nodes are modelled
+ using the OF graph bindings in accordance with the video interface
+ bindings defined in
+ Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+ The following table lists the port number corresponding to each device
+ port.
+
+ Port Description
+ ----------------------------------------
+ Port 0 GMSL Input 0
+ Port 1 GMSL Input 1
+ Port 2 GMSL Input 2
+ Port 3 GMSL Input 3
+ Port 4 CSI-2 Output
+
+ properties:
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ port@[0-3]:
+ type: object
+ properties:
+ reg:
+ enum: [ 0, 1, 2, 3 ]
+
+ endpoint:
+ type: object
+
+ properties:
+ remote-endpoint:
+ description: |
+ phandle to the remote GMSL source endpoint subnode in the
+ remote node port.
+
+ required:
+ - remote-endpoint
+
+ required:
+ - reg
+ - endpoint
+
+ additionalProperties: false
+
+ port@4:
+ type: object
+ properties:
+ reg:
+ const: 4
+
+ endpoint:
+ type: object
+
+ properties:
+ remote-endpoint:
+ description: phandle to the remote CSI-2 sink endpoint.
+
+ data-lanes:
+ description: array of physical CSI-2 data lane indexes.
+
+ required:
+ - remote-endpoint
+ - data-lanes
+
+ required:
+ - reg
+ - endpoint
+
+ additionalProperties: false
+
+ required:
+ - port@4
+
+ i2c-mux:
+ type: object
+ description: |
+ Each GMSL link is modelled as a child bus of an i2c bus
+ multiplexer/switch, in accordance with bindings described in
+ Documentation/devicetree/bindings/i2c/i2c-mux.txt. The serializer
+ device on the remote end of the GMSL link shall be modelled as a child
+ node of the corresponding I2C bus.
+
+ properties:
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - ports
+ - i2c-mux
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c@e66d8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <0 0xe66d8000 0 0x40>;
+
+ gmsl-deserializer@2c {
+ compatible = "maxim,max9286";
+ reg = <0x2c>;
+ poc-supply = <&camera_poc_12v>;
+ enable-gpios = <&gpio 13 GPIO_ACTIVE_HIGH>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ max9286_in0: endpoint {
+ remote-endpoint = <&rdacm20_out0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ max9286_in1: endpoint {
+ remote-endpoint = <&rdacm20_out1>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ max9286_in2: endpoint {
+ remote-endpoint = <&rdacm20_out2>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+
+ max9286_in3: endpoint {
+ remote-endpoint = <&rdacm20_out3>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+
+ max9286_out: endpoint {
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&csi40_in>;
+ };
+ };
+ };
+
+ i2c-mux {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <0>;
+
+ camera@51 {
+ reg = <0x51>;
+
+ port {
+ rdacm20_out0: endpoint {
+ remote-endpoint = <&max9286_in0>;
+ };
+ };
+
+ };
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ camera@52 {
+ reg = <0x52>;
+
+ port {
+ rdacm20_out1: endpoint {
+ remote-endpoint = <&max9286_in1>;
+ };
+ };
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ camera@53 {
+ reg = <0x53>;
+
+ port {
+ rdacm20_out2: endpoint {
+ remote-endpoint = <&max9286_in2>;
+ };
+ };
+ };
+ };
+
+ i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ camera@54 {
+ reg = <0x54>;
+
+ port {
+ rdacm20_out3: endpoint {
+ remote-endpoint = <&max9286_in3>;
+ };
+ };
+ };
+ };
+ };
+ };
+ };
--
2.25.1
^ permalink raw reply related
* [PATCH v9 2/4] media: i2c: Add MAX9286 driver
From: Kieran Bingham @ 2020-05-12 15:51 UTC (permalink / raw)
To: linux-renesas-soc, linux-media, devicetree, linux-kernel,
Mauro Carvalho Chehab
Cc: Kieran Bingham, Laurent Pinchart, Jacopo Mondi,
Niklas Söderlund, sakari.ailus, Hans Verkuil, Hyun Kwon,
Manivannan Sadhasivam, Rob Herring, Kieran Bingham, Jacopo Mondi,
Laurent Pinchart, Niklas Söderlund
In-Reply-To: <20200512155105.1068064-1-kieran.bingham+renesas@ideasonboard.com>
The MAX9286 is a 4-channel GMSL deserializer with coax or STP input and
CSI-2 output. The device supports multicamera streaming applications,
and features the ability to synchronise the attached cameras.
CSI-2 output can be configured with 1 to 4 lanes, and a control channel
is supported over I2C, which implements an I2C mux to facilitate
communications with connected cameras across the reverse control
channel.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
--
v2:
- Fix MAINTAINERS entry
This posting is released with the following modifications to work
without Sakari's VC developments:
- max9286_g_mbus_config() re-instated
- max9286_get_frame_desc() is not bus/csi aware
- max9286_{get,set}_routing() removed
v3:
- Initialise notifier with v4l2_async_notifier_init
- Update for new mbus csi2 format V4L2_MBUS_CSI2_DPHY
v4: - Re-introduce required code to function with the VC series.
- Implement max9286_get_routing, max9286_set_routing
- Remove max9286_g_mbus_config
v5: (internal release)
- Fix printk formatting for hex value
- max9286->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE (add |)
- MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER -> MEDIA_ENT_F_VID_IF_BRIDGE
- Remove 'device is bound' workaround
v6:
- v4l2_subdev_krouting instead of v4l2_subdev_routing separated
to allow integration without the VC/V4L2-Mux series.
- convert sd_to_max9286 to inline function
- rename max9286_device to max9286_priv
- Cleanup the v4l2_async_notifier
- Extend MODULE_AUTHOR
- Replace of_graph_get_endpoint_by_regs with fwnode_graph_get_endpoint_by_id
- Pass default bus type when parsing fwnode endpoint (Manivannan Sadhasivam)
- Use new YAML file reference in MAINTAINERS
- Parse new i2c-mux node in max9286_get_i2c_by_id
(This could/should be refactored to parse these separately first)
- Spelling and calculation fixes in the FSYNC_LOCKED check comments
- Identify each enabled i2c-mux channel in a single pass
- max9286: Improve mux-state readbility [v2]
- Fix frame sync lock durations
- Add comment to describe /why/ we must open the mux in s_stream
- use -EXDEV as return code for failed link synchronisation.
- Fix reference counting of the dt nodeS
- Convert to probe_new for I2C
- Remove redundant max9286_i2c_mux_state
- Provide optional enable-gpio (max9286-pwdn)
v7:
[Kieran]
- Ensure powerdown lines are optional
- Add a 4ms power-up delay
- Add max9286_check_config_link() to core
- Add GPIO chip controller for GPIO0OUT and GPIO1OUT
- Fix GPIO registration
- max9286: Split out async registration
(fixes regulator -EPROBE_DEFERs failures)
- Collect all V4L2 registrations
- balance v4l2_async refcnting
- Rename max9286_v4l2_async_ => max9286_v4l2_notifier_
[Jacopo]
- Remove redundanct MAXIM_I2C_SPEED macros
- Move notifiers operations
- Add delay after reverse channel reconfiguration
- Move link setup to completion
- Fix up max9286_check_config_link() implementation
- Remove redundant dual configuration of reverse channel
v8:
[Kieran]
- Update the bound_sources mask on unbind
- Convert probe kzalloc usage to devm_ variant
- Fix up cleanup path from GPIO PowerDown registration
- cleanup GPIO device registration fail path
- Convert to use devm_regulator_get()
- Fit max9286_parse_dt print on one line
- Move multi-device workarounds out of upstream driver
- Remove I2C mod-table
- Lock format changes
- Describe pad index usage
- Remove poc_enabled workaround
- Rename the max9286_gpio to be more explicit on it's actions.
- Move max9286_init_format call
- Rework probe sequence and simplify error paths.
- Simplify i2c comments
- Implement Pixelrate control
- Disable overlap window
[Jacopo]
- Adapt Kconfig to latest upstream changes
- Put of node on error
- Calculate pixel rate
- Simplify overlap window disablement
v9:
[Kieran]
- Kconfig: Depend on OF
- Re-sort addition to Makefile
---
MAINTAINERS | 10 +
drivers/media/i2c/Kconfig | 13 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/max9286.c | 1332 +++++++++++++++++++++++++++++++++++
4 files changed, 1356 insertions(+)
create mode 100644 drivers/media/i2c/max9286.c
diff --git a/MAINTAINERS b/MAINTAINERS
index a7bb6e22d5da..99e3bf7760fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10274,6 +10274,16 @@ F: Documentation/hwmon/max6697.rst
F: drivers/hwmon/max6697.c
F: include/linux/platform_data/max6697.h
+MAX9286 QUAD GMSL DESERIALIZER DRIVER
+M: Jacopo Mondi <jacopo+renesas@jmondi.org>
+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+M: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+M: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
+F: drivers/media/i2c/max9286.c
+
MAX9860 MONO AUDIO VOICE CODEC DRIVER
M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 3abc80373ec0..2e390f41f6da 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -464,6 +464,19 @@ config VIDEO_VPX3220
To compile this driver as a module, choose M here: the
module will be called vpx3220.
+config VIDEO_MAX9286
+ tristate "Maxim MAX9286 GMSL deserializer support"
+ depends on I2C && I2C_MUX
+ depends on OF
+ select V4L2_FWNODE
+ select VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ help
+ This driver supports the Maxim MAX9286 GMSL deserializer.
+
+ To compile this driver as a module, choose M here: the
+ module will be called max9286.
+
comment "Video and audio decoders"
config VIDEO_SAA717X
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 77bf7d0b691f..f0b001ee4b05 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -117,6 +117,7 @@ obj-$(CONFIG_VIDEO_IMX274) += imx274.o
obj-$(CONFIG_VIDEO_IMX290) += imx290.o
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
obj-$(CONFIG_VIDEO_IMX355) += imx355.o
+obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
obj-$(CONFIG_SDR_MAX2175) += max2175.o
diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
new file mode 100644
index 000000000000..481d65f2b51d
--- /dev/null
+++ b/drivers/media/i2c/max9286.c
@@ -0,0 +1,1332 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Maxim MAX9286 GMSL Deserializer Driver
+ *
+ * Copyright (C) 2017-2019 Jacopo Mondi
+ * Copyright (C) 2017-2019 Kieran Bingham
+ * Copyright (C) 2017-2019 Laurent Pinchart
+ * Copyright (C) 2017-2019 Niklas Söderlund
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fwnode.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+/* Register 0x00 */
+#define MAX9286_MSTLINKSEL_AUTO (7 << 5)
+#define MAX9286_MSTLINKSEL(n) ((n) << 5)
+#define MAX9286_EN_VS_GEN BIT(4)
+#define MAX9286_LINKEN(n) (1 << (n))
+/* Register 0x01 */
+#define MAX9286_FSYNCMODE_ECU (3 << 6)
+#define MAX9286_FSYNCMODE_EXT (2 << 6)
+#define MAX9286_FSYNCMODE_INT_OUT (1 << 6)
+#define MAX9286_FSYNCMODE_INT_HIZ (0 << 6)
+#define MAX9286_GPIEN BIT(5)
+#define MAX9286_ENLMO_RSTFSYNC BIT(2)
+#define MAX9286_FSYNCMETH_AUTO (2 << 0)
+#define MAX9286_FSYNCMETH_SEMI_AUTO (1 << 0)
+#define MAX9286_FSYNCMETH_MANUAL (0 << 0)
+#define MAX9286_REG_FSYNC_PERIOD_L 0x06
+#define MAX9286_REG_FSYNC_PERIOD_M 0x07
+#define MAX9286_REG_FSYNC_PERIOD_H 0x08
+/* Register 0x0a */
+#define MAX9286_FWDCCEN(n) (1 << ((n) + 4))
+#define MAX9286_REVCCEN(n) (1 << (n))
+/* Register 0x0c */
+#define MAX9286_HVEN BIT(7)
+#define MAX9286_EDC_6BIT_HAMMING (2 << 5)
+#define MAX9286_EDC_6BIT_CRC (1 << 5)
+#define MAX9286_EDC_1BIT_PARITY (0 << 5)
+#define MAX9286_DESEL BIT(4)
+#define MAX9286_INVVS BIT(3)
+#define MAX9286_INVHS BIT(2)
+#define MAX9286_HVSRC_D0 (2 << 0)
+#define MAX9286_HVSRC_D14 (1 << 0)
+#define MAX9286_HVSRC_D18 (0 << 0)
+/* Register 0x0f */
+#define MAX9286_0X0F_RESERVED BIT(3)
+/* Register 0x12 */
+#define MAX9286_CSILANECNT(n) (((n) - 1) << 6)
+#define MAX9286_CSIDBL BIT(5)
+#define MAX9286_DBL BIT(4)
+#define MAX9286_DATATYPE_USER_8BIT (11 << 0)
+#define MAX9286_DATATYPE_USER_YUV_12BIT (10 << 0)
+#define MAX9286_DATATYPE_USER_24BIT (9 << 0)
+#define MAX9286_DATATYPE_RAW14 (8 << 0)
+#define MAX9286_DATATYPE_RAW11 (7 << 0)
+#define MAX9286_DATATYPE_RAW10 (6 << 0)
+#define MAX9286_DATATYPE_RAW8 (5 << 0)
+#define MAX9286_DATATYPE_YUV422_10BIT (4 << 0)
+#define MAX9286_DATATYPE_YUV422_8BIT (3 << 0)
+#define MAX9286_DATATYPE_RGB555 (2 << 0)
+#define MAX9286_DATATYPE_RGB565 (1 << 0)
+#define MAX9286_DATATYPE_RGB888 (0 << 0)
+/* Register 0x15 */
+#define MAX9286_VC(n) ((n) << 5)
+#define MAX9286_VCTYPE BIT(4)
+#define MAX9286_CSIOUTEN BIT(3)
+#define MAX9286_0X15_RESV (3 << 0)
+/* Register 0x1b */
+#define MAX9286_SWITCHIN(n) (1 << ((n) + 4))
+#define MAX9286_ENEQ(n) (1 << (n))
+/* Register 0x27 */
+#define MAX9286_LOCKED BIT(7)
+/* Register 0x31 */
+#define MAX9286_FSYNC_LOCKED BIT(6)
+/* Register 0x34 */
+#define MAX9286_I2CLOCACK BIT(7)
+#define MAX9286_I2CSLVSH_1046NS_469NS (3 << 5)
+#define MAX9286_I2CSLVSH_938NS_352NS (2 << 5)
+#define MAX9286_I2CSLVSH_469NS_234NS (1 << 5)
+#define MAX9286_I2CSLVSH_352NS_117NS (0 << 5)
+#define MAX9286_I2CMSTBT_837KBPS (7 << 2)
+#define MAX9286_I2CMSTBT_533KBPS (6 << 2)
+#define MAX9286_I2CMSTBT_339KBPS (5 << 2)
+#define MAX9286_I2CMSTBT_173KBPS (4 << 2)
+#define MAX9286_I2CMSTBT_105KBPS (3 << 2)
+#define MAX9286_I2CMSTBT_84KBPS (2 << 2)
+#define MAX9286_I2CMSTBT_28KBPS (1 << 2)
+#define MAX9286_I2CMSTBT_8KBPS (0 << 2)
+#define MAX9286_I2CSLVTO_NONE (3 << 0)
+#define MAX9286_I2CSLVTO_1024US (2 << 0)
+#define MAX9286_I2CSLVTO_256US (1 << 0)
+#define MAX9286_I2CSLVTO_64US (0 << 0)
+/* Register 0x3b */
+#define MAX9286_REV_TRF(n) ((n) << 4)
+#define MAX9286_REV_AMP(n) ((((n) - 30) / 10) << 1) /* in mV */
+#define MAX9286_REV_AMP_X BIT(0)
+/* Register 0x3f */
+#define MAX9286_EN_REV_CFG BIT(6)
+#define MAX9286_REV_FLEN(n) ((n) - 20)
+/* Register 0x49 */
+#define MAX9286_VIDEO_DETECT_MASK 0x0f
+/* Register 0x69 */
+#define MAX9286_LFLTBMONMASKED BIT(7)
+#define MAX9286_LOCKMONMASKED BIT(6)
+#define MAX9286_AUTOCOMBACKEN BIT(5)
+#define MAX9286_AUTOMASKEN BIT(4)
+#define MAX9286_MASKLINK(n) ((n) << 0)
+
+/*
+ * The sink and source pads are created to match the OF graph port numbers so
+ * that their indexes can be used interchangeably.
+ */
+#define MAX9286_NUM_GMSL 4
+#define MAX9286_N_SINKS 4
+#define MAX9286_N_PADS 5
+#define MAX9286_SRC_PAD 4
+
+struct max9286_source {
+ struct v4l2_async_subdev asd;
+ struct v4l2_subdev *sd;
+ struct fwnode_handle *fwnode;
+};
+
+#define asd_to_max9286_source(_asd) \
+ container_of(_asd, struct max9286_source, asd)
+
+struct max9286_priv {
+ struct i2c_client *client;
+ struct gpio_desc *gpiod_pwdn;
+ struct v4l2_subdev sd;
+ struct media_pad pads[MAX9286_N_PADS];
+ struct regulator *regulator;
+
+ struct gpio_chip gpio;
+ u8 gpio_state;
+
+ struct i2c_mux_core *mux;
+ unsigned int mux_channel;
+ bool mux_open;
+
+ struct v4l2_ctrl_handler ctrls;
+ struct v4l2_ctrl *pixelrate;
+
+ struct v4l2_mbus_framefmt fmt[MAX9286_N_SINKS];
+
+ /* Protects controls and fmt structures */
+ struct mutex mutex;
+
+ unsigned int nsources;
+ unsigned int source_mask;
+ unsigned int route_mask;
+ unsigned int bound_sources;
+ unsigned int csi2_data_lanes;
+ struct max9286_source sources[MAX9286_NUM_GMSL];
+ struct v4l2_async_notifier notifier;
+};
+
+static struct max9286_source *next_source(struct max9286_priv *priv,
+ struct max9286_source *source)
+{
+ if (!source)
+ source = &priv->sources[0];
+ else
+ source++;
+
+ for (; source < &priv->sources[MAX9286_NUM_GMSL]; source++) {
+ if (source->fwnode)
+ return source;
+ }
+
+ return NULL;
+}
+
+#define for_each_source(priv, source) \
+ for ((source) = NULL; ((source) = next_source((priv), (source))); )
+
+#define to_index(priv, source) ((source) - &(priv)->sources[0])
+
+static inline struct max9286_priv *sd_to_max9286(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct max9286_priv, sd);
+}
+
+/* -----------------------------------------------------------------------------
+ * I2C IO
+ */
+
+static int max9286_read(struct max9286_priv *priv, u8 reg)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(priv->client, reg);
+ if (ret < 0)
+ dev_err(&priv->client->dev,
+ "%s: register 0x%02x read failed (%d)\n",
+ __func__, reg, ret);
+
+ return ret;
+}
+
+static int max9286_write(struct max9286_priv *priv, u8 reg, u8 val)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(priv->client, reg, val);
+ if (ret < 0)
+ dev_err(&priv->client->dev,
+ "%s: register 0x%02x write failed (%d)\n",
+ __func__, reg, ret);
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * I2C Multiplexer
+ */
+
+static void max9286_i2c_mux_configure(struct max9286_priv *priv, u8 conf)
+{
+ max9286_write(priv, 0x0a, conf);
+
+ /*
+ * We must sleep after any change to the forward or reverse channel
+ * configuration.
+ */
+ usleep_range(3000, 5000);
+}
+
+static void max9286_i2c_mux_open(struct max9286_priv *priv)
+{
+ /* Open all channels on the MAX9286 */
+ max9286_i2c_mux_configure(priv, 0xff);
+
+ priv->mux_open = true;
+}
+
+static void max9286_i2c_mux_close(struct max9286_priv *priv)
+{
+ /*
+ * Ensure that both the forward and reverse channel are disabled on the
+ * mux, and that the channel ID is invalidated to ensure we reconfigure
+ * on the next max9286_i2c_mux_select() call.
+ */
+ max9286_i2c_mux_configure(priv, 0x00);
+
+ priv->mux_open = false;
+ priv->mux_channel = -1;
+}
+
+static int max9286_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct max9286_priv *priv = i2c_mux_priv(muxc);
+
+ /* Channel select is disabled when configured in the opened state. */
+ if (priv->mux_open)
+ return 0;
+
+ if (priv->mux_channel == chan)
+ return 0;
+
+ priv->mux_channel = chan;
+
+ max9286_i2c_mux_configure(priv,
+ MAX9286_FWDCCEN(chan) |
+ MAX9286_REVCCEN(chan));
+
+ return 0;
+}
+
+static int max9286_i2c_mux_init(struct max9286_priv *priv)
+{
+ struct max9286_source *source;
+ int ret;
+
+ if (!i2c_check_functionality(priv->client->adapter,
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ return -ENODEV;
+
+ priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
+ priv->nsources, 0, I2C_MUX_LOCKED,
+ max9286_i2c_mux_select, NULL);
+ if (!priv->mux)
+ return -ENOMEM;
+
+ priv->mux->priv = priv;
+
+ for_each_source(priv, source) {
+ unsigned int index = to_index(priv, source);
+
+ ret = i2c_mux_add_adapter(priv->mux, 0, index, 0);
+ if (ret < 0)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ i2c_mux_del_adapters(priv->mux);
+ return ret;
+}
+
+static void max9286_configure_i2c(struct max9286_priv *priv, bool localack)
+{
+ u8 config = MAX9286_I2CSLVSH_469NS_234NS | MAX9286_I2CSLVTO_1024US |
+ MAX9286_I2CMSTBT_105KBPS;
+
+ if (localack)
+ config |= MAX9286_I2CLOCACK;
+
+ max9286_write(priv, 0x34, config);
+ usleep_range(3000, 5000);
+}
+
+/*
+ * max9286_check_video_links() - Make sure video links are detected and locked
+ *
+ * Performs safety checks on video link status. Make sure they are detected
+ * and all enabled links are locked.
+ *
+ * Returns 0 for success, -EIO for errors.
+ */
+static int max9286_check_video_links(struct max9286_priv *priv)
+{
+ unsigned int i;
+ int ret;
+
+ /*
+ * Make sure valid video links are detected.
+ * The delay is not characterized in de-serializer manual, wait up
+ * to 5 ms.
+ */
+ for (i = 0; i < 10; i++) {
+ ret = max9286_read(priv, 0x49);
+ if (ret < 0)
+ return -EIO;
+
+ if ((ret & MAX9286_VIDEO_DETECT_MASK) == priv->source_mask)
+ break;
+
+ usleep_range(350, 500);
+ }
+
+ if (i == 10) {
+ dev_err(&priv->client->dev,
+ "Unable to detect video links: 0x%02x\n", ret);
+ return -EIO;
+ }
+
+ /* Make sure all enabled links are locked (4ms max). */
+ for (i = 0; i < 10; i++) {
+ ret = max9286_read(priv, 0x27);
+ if (ret < 0)
+ return -EIO;
+
+ if (ret & MAX9286_LOCKED)
+ break;
+
+ usleep_range(350, 450);
+ }
+
+ if (i == 10) {
+ dev_err(&priv->client->dev, "Not all enabled links locked\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/*
+ * max9286_check_config_link() - Detect and wait for configuration links
+ *
+ * Determine if the configuration channel is up and settled for a link.
+ *
+ * Returns 0 for success, -EIO for errors.
+ */
+static int max9286_check_config_link(struct max9286_priv *priv,
+ unsigned int source_mask)
+{
+ unsigned int conflink_mask = (source_mask & 0x0f) << 4;
+ unsigned int i;
+ int ret;
+
+ /*
+ * Make sure requested configuration links are detected.
+ * The delay is not characterized in the chip manual: wait up
+ * to 5 milliseconds.
+ */
+ for (i = 0; i < 10; i++) {
+ ret = max9286_read(priv, 0x49) & 0xf0;
+ if (ret < 0)
+ return -EIO;
+
+ if (ret == conflink_mask)
+ break;
+
+ usleep_range(350, 500);
+ }
+
+ if (ret != conflink_mask) {
+ dev_err(&priv->client->dev,
+ "Unable to detect configuration links: 0x%02x expected 0x%02x\n",
+ ret, conflink_mask);
+ return -EIO;
+ }
+
+ dev_info(&priv->client->dev,
+ "Successfully detected configuration links after %u loops: 0x%02x\n",
+ i, conflink_mask);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdev
+ */
+
+static int max9286_set_pixelrate(struct max9286_priv *priv)
+{
+ struct max9286_source *source = NULL;
+ u64 pixelrate = 0;
+
+ for_each_source(priv, source) {
+ struct v4l2_ctrl *ctrl;
+ u64 source_rate = 0;
+
+ /* Pixel rate is mandatory to be reported by sources. */
+ ctrl = v4l2_ctrl_find(source->sd->ctrl_handler,
+ V4L2_CID_PIXEL_RATE);
+ if (!ctrl) {
+ pixelrate = 0;
+ break;
+ }
+
+ /* All source must report the same pixel rate. */
+ source_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+ if (!pixelrate) {
+ pixelrate = source_rate;
+ } else if (pixelrate != source_rate) {
+ dev_err(&priv->client->dev,
+ "Unable to calculate pixel rate\n");
+ return -EINVAL;
+ }
+ }
+
+ if (!pixelrate) {
+ dev_err(&priv->client->dev,
+ "No pixel rate control available in sources\n");
+ return -EINVAL;
+ }
+
+ /*
+ * The CSI-2 transmitter pixel rate is the single source rate multiplied
+ * by the number of available sources.
+ */
+ return v4l2_ctrl_s_ctrl_int64(priv->pixelrate,
+ pixelrate * priv->nsources);
+}
+
+static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *subdev,
+ struct v4l2_async_subdev *asd)
+{
+ struct max9286_priv *priv = sd_to_max9286(notifier->sd);
+ struct max9286_source *source = asd_to_max9286_source(asd);
+ unsigned int index = to_index(priv, source);
+ unsigned int src_pad;
+ int ret;
+
+ ret = media_entity_get_fwnode_pad(&subdev->entity,
+ source->fwnode,
+ MEDIA_PAD_FL_SOURCE);
+ if (ret < 0) {
+ dev_err(&priv->client->dev,
+ "Failed to find pad for %s\n", subdev->name);
+ return ret;
+ }
+
+ priv->bound_sources |= BIT(index);
+ source->sd = subdev;
+ src_pad = ret;
+
+ ret = media_create_pad_link(&source->sd->entity, src_pad,
+ &priv->sd.entity, index,
+ MEDIA_LNK_FL_ENABLED |
+ MEDIA_LNK_FL_IMMUTABLE);
+ if (ret) {
+ dev_err(&priv->client->dev,
+ "Unable to link %s:%u -> %s:%u\n",
+ source->sd->name, src_pad, priv->sd.name, index);
+ return ret;
+ }
+
+ dev_dbg(&priv->client->dev, "Bound %s pad: %u on index %u\n",
+ subdev->name, src_pad, index);
+
+ /*
+ * We can only register v4l2_async_notifiers, which do not provide a
+ * means to register a complete callback. bound_sources allows us to
+ * identify when all remote serializers have completed their probe.
+ */
+ if (priv->bound_sources != priv->source_mask)
+ return 0;
+
+ /*
+ * All enabled sources have probed and enabled their reverse control
+ * channels:
+ *
+ * - Verify all configuration links are properly detected
+ * - Disable auto-ack as communication on the control channel are now
+ * stable.
+ */
+ max9286_check_config_link(priv, priv->source_mask);
+
+ /*
+ * Re-configure I2C with local acknowledge disabled after cameras have
+ * probed.
+ */
+ max9286_configure_i2c(priv, false);
+
+ return max9286_set_pixelrate(priv);
+}
+
+static void max9286_notify_unbind(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *subdev,
+ struct v4l2_async_subdev *asd)
+{
+ struct max9286_priv *priv = sd_to_max9286(notifier->sd);
+ struct max9286_source *source = asd_to_max9286_source(asd);
+ unsigned int index = to_index(priv, source);
+
+ source->sd = NULL;
+ priv->bound_sources &= ~BIT(index);
+}
+
+static const struct v4l2_async_notifier_operations max9286_notify_ops = {
+ .bound = max9286_notify_bound,
+ .unbind = max9286_notify_unbind,
+};
+
+static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
+{
+ struct device *dev = &priv->client->dev;
+ struct max9286_source *source = NULL;
+ int ret;
+
+ if (!priv->nsources)
+ return 0;
+
+ v4l2_async_notifier_init(&priv->notifier);
+
+ for_each_source(priv, source) {
+ unsigned int i = to_index(priv, source);
+
+ source->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
+ source->asd.match.fwnode = source->fwnode;
+
+ ret = v4l2_async_notifier_add_subdev(&priv->notifier,
+ &source->asd);
+ if (ret) {
+ dev_err(dev, "Failed to add subdev for source %d", i);
+ v4l2_async_notifier_cleanup(&priv->notifier);
+ return ret;
+ }
+
+ /*
+ * Balance the reference counting handled through
+ * v4l2_async_notifier_cleanup()
+ */
+ fwnode_handle_get(source->fwnode);
+ }
+
+ priv->notifier.ops = &max9286_notify_ops;
+
+ ret = v4l2_async_subdev_notifier_register(&priv->sd, &priv->notifier);
+ if (ret) {
+ dev_err(dev, "Failed to register subdev_notifier");
+ v4l2_async_notifier_cleanup(&priv->notifier);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void max9286_v4l2_notifier_unregister(struct max9286_priv *priv)
+{
+ if (!priv->nsources)
+ return;
+
+ v4l2_async_notifier_unregister(&priv->notifier);
+ v4l2_async_notifier_cleanup(&priv->notifier);
+}
+
+static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct max9286_priv *priv = sd_to_max9286(sd);
+ struct max9286_source *source;
+ unsigned int i;
+ bool sync = false;
+ int ret;
+
+ if (enable) {
+ /*
+ * The frame sync between cameras is transmitted across the
+ * reverse channel as GPIO. We must open all channels while
+ * streaming to allow this synchronisation signal to be shared.
+ */
+ max9286_i2c_mux_open(priv);
+
+ /* Start all cameras. */
+ for_each_source(priv, source) {
+ ret = v4l2_subdev_call(source->sd, video, s_stream, 1);
+ if (ret)
+ return ret;
+ }
+
+ ret = max9286_check_video_links(priv);
+ if (ret)
+ return ret;
+
+ /*
+ * Wait until frame synchronization is locked.
+ *
+ * Manual says frame sync locking should take ~6 VTS.
+ * From practical experience at least 8 are required. Give
+ * 12 complete frames time (~400ms at 30 fps) to achieve frame
+ * locking before returning error.
+ */
+ for (i = 0; i < 40; i++) {
+ if (max9286_read(priv, 0x31) & MAX9286_FSYNC_LOCKED) {
+ sync = true;
+ break;
+ }
+ usleep_range(9000, 11000);
+ }
+
+ if (!sync) {
+ dev_err(&priv->client->dev,
+ "Failed to get frame synchronization\n");
+ return -EXDEV; /* Invalid cross-device link */
+ }
+
+ /*
+ * Enable CSI output, VC set according to link number.
+ * Bit 7 must be set (chip manual says it's 0 and reserved).
+ */
+ max9286_write(priv, 0x15, 0x80 | MAX9286_VCTYPE |
+ MAX9286_CSIOUTEN | MAX9286_0X15_RESV);
+ } else {
+ max9286_write(priv, 0x15, MAX9286_VCTYPE | MAX9286_0X15_RESV);
+
+ /* Stop all cameras. */
+ for_each_source(priv, source)
+ v4l2_subdev_call(source->sd, video, s_stream, 0);
+
+ max9286_i2c_mux_close(priv);
+ }
+
+ return 0;
+}
+
+static int max9286_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad || code->index > 0)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
+
+ return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+max9286_get_pad_format(struct max9286_priv *priv,
+ struct v4l2_subdev_pad_config *cfg,
+ unsigned int pad, u32 which)
+{
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_format(&priv->sd, cfg, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &priv->fmt[pad];
+ default:
+ return NULL;
+ }
+}
+
+static int max9286_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct max9286_priv *priv = sd_to_max9286(sd);
+ struct v4l2_mbus_framefmt *cfg_fmt;
+
+ if (format->pad >= MAX9286_SRC_PAD)
+ return -EINVAL;
+
+ /* Refuse non YUV422 formats as we hardcode DT to 8 bit YUV422 */
+ switch (format->format.code) {
+ case MEDIA_BUS_FMT_UYVY8_2X8:
+ case MEDIA_BUS_FMT_VYUY8_2X8:
+ case MEDIA_BUS_FMT_YUYV8_2X8:
+ case MEDIA_BUS_FMT_YVYU8_2X8:
+ break;
+ default:
+ format->format.code = MEDIA_BUS_FMT_YUYV8_2X8;
+ break;
+ }
+
+ cfg_fmt = max9286_get_pad_format(priv, cfg, format->pad, format->which);
+ if (!cfg_fmt)
+ return -EINVAL;
+
+ mutex_lock(&priv->mutex);
+ *cfg_fmt = format->format;
+ mutex_unlock(&priv->mutex);
+
+ return 0;
+}
+
+static int max9286_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct max9286_priv *priv = sd_to_max9286(sd);
+ struct v4l2_mbus_framefmt *cfg_fmt;
+
+ if (format->pad >= MAX9286_SRC_PAD)
+ return -EINVAL;
+
+ cfg_fmt = max9286_get_pad_format(priv, cfg, format->pad, format->which);
+ if (!cfg_fmt)
+ return -EINVAL;
+
+ mutex_lock(&priv->mutex);
+ format->format = *cfg_fmt;
+ mutex_unlock(&priv->mutex);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops max9286_video_ops = {
+ .s_stream = max9286_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops max9286_pad_ops = {
+ .enum_mbus_code = max9286_enum_mbus_code,
+ .get_fmt = max9286_get_fmt,
+ .set_fmt = max9286_set_fmt,
+};
+
+static const struct v4l2_subdev_ops max9286_subdev_ops = {
+ .video = &max9286_video_ops,
+ .pad = &max9286_pad_ops,
+};
+
+static void max9286_init_format(struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->width = 1280;
+ fmt->height = 800;
+ fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
+ fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+}
+
+static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+ struct v4l2_mbus_framefmt *format;
+ unsigned int i;
+
+ for (i = 0; i < MAX9286_N_SINKS; i++) {
+ format = v4l2_subdev_get_try_format(subdev, fh->pad, i);
+ max9286_init_format(format);
+ }
+
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops max9286_subdev_internal_ops = {
+ .open = max9286_open,
+};
+
+static int max9286_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_PIXEL_RATE:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct v4l2_ctrl_ops max9286_ctrl_ops = {
+ .s_ctrl = max9286_s_ctrl,
+};
+
+static int max9286_v4l2_register(struct max9286_priv *priv)
+{
+ struct device *dev = &priv->client->dev;
+ struct fwnode_handle *ep;
+ int ret;
+ int i;
+
+ /* Register v4l2 async notifiers for connected Camera subdevices */
+ ret = max9286_v4l2_notifier_register(priv);
+ if (ret) {
+ dev_err(dev, "Unable to register V4L2 async notifiers\n");
+ return ret;
+ }
+
+ /* Configure V4L2 for the MAX9286 itself */
+
+ for (i = 0; i < MAX9286_N_SINKS; i++)
+ max9286_init_format(&priv->fmt[i]);
+
+ v4l2_i2c_subdev_init(&priv->sd, priv->client, &max9286_subdev_ops);
+ priv->sd.internal_ops = &max9286_subdev_internal_ops;
+ priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ v4l2_ctrl_handler_init(&priv->ctrls, 1);
+ priv->pixelrate = v4l2_ctrl_new_std(&priv->ctrls,
+ &max9286_ctrl_ops,
+ V4L2_CID_PIXEL_RATE,
+ 1, INT_MAX, 1, 50000000);
+
+ priv->sd.ctrl_handler = &priv->ctrls;
+ ret = priv->ctrls.error;
+ if (ret)
+ goto err_async;
+
+ priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+
+ priv->pads[MAX9286_SRC_PAD].flags = MEDIA_PAD_FL_SOURCE;
+ for (i = 0; i < MAX9286_SRC_PAD; i++)
+ priv->pads[i].flags = MEDIA_PAD_FL_SINK;
+ ret = media_entity_pads_init(&priv->sd.entity, MAX9286_N_PADS,
+ priv->pads);
+ if (ret)
+ goto err_async;
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), MAX9286_SRC_PAD,
+ 0, 0);
+ if (!ep) {
+ dev_err(dev, "Unable to retrieve endpoint on \"port@4\"\n");
+ ret = -ENOENT;
+ goto err_async;
+ }
+ priv->sd.fwnode = ep;
+
+ ret = v4l2_async_register_subdev(&priv->sd);
+ if (ret < 0) {
+ dev_err(dev, "Unable to register subdevice\n");
+ goto err_put_node;
+ }
+
+ return 0;
+
+err_put_node:
+ fwnode_handle_put(ep);
+err_async:
+ max9286_v4l2_notifier_unregister(priv);
+
+ return ret;
+}
+
+static void max9286_v4l2_unregister(struct max9286_priv *priv)
+{
+ fwnode_handle_put(priv->sd.fwnode);
+ v4l2_async_unregister_subdev(&priv->sd);
+ max9286_v4l2_notifier_unregister(priv);
+}
+
+/* -----------------------------------------------------------------------------
+ * Probe/Remove
+ */
+
+static int max9286_setup(struct max9286_priv *priv)
+{
+ /*
+ * Link ordering values for all enabled links combinations. Orders must
+ * be assigned sequentially from 0 to the number of enabled links
+ * without leaving any hole for disabled links. We thus assign orders to
+ * enabled links first, and use the remaining order values for disabled
+ * links are all links must have a different order value;
+ */
+ static const u8 link_order[] = {
+ (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* xxxx */
+ (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* xxx0 */
+ (3 << 6) | (2 << 4) | (0 << 2) | (1 << 0), /* xx0x */
+ (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* xx10 */
+ (3 << 6) | (0 << 4) | (2 << 2) | (1 << 0), /* x0xx */
+ (3 << 6) | (1 << 4) | (2 << 2) | (0 << 0), /* x1x0 */
+ (3 << 6) | (1 << 4) | (0 << 2) | (2 << 0), /* x10x */
+ (3 << 6) | (1 << 4) | (1 << 2) | (0 << 0), /* x210 */
+ (0 << 6) | (3 << 4) | (2 << 2) | (1 << 0), /* 0xxx */
+ (1 << 6) | (3 << 4) | (2 << 2) | (0 << 0), /* 1xx0 */
+ (1 << 6) | (3 << 4) | (0 << 2) | (2 << 0), /* 1x0x */
+ (2 << 6) | (3 << 4) | (1 << 2) | (0 << 0), /* 2x10 */
+ (1 << 6) | (0 << 4) | (3 << 2) | (2 << 0), /* 10xx */
+ (2 << 6) | (1 << 4) | (3 << 2) | (0 << 0), /* 21x0 */
+ (2 << 6) | (1 << 4) | (0 << 2) | (3 << 0), /* 210x */
+ (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* 3210 */
+ };
+
+ /*
+ * Set the I2C bus speed.
+ *
+ * Enable I2C Local Acknowledge during the probe sequences of the camera
+ * only. This should be disabled after the mux is initialised.
+ */
+ max9286_configure_i2c(priv, true);
+
+ /*
+ * Reverse channel setup.
+ *
+ * - Enable custom reverse channel configuration (through register 0x3f)
+ * and set the first pulse length to 35 clock cycles.
+ * - Increase the reverse channel amplitude to 170mV to accommodate the
+ * high threshold enabled by the serializer driver.
+ */
+ max9286_write(priv, 0x3f, MAX9286_EN_REV_CFG | MAX9286_REV_FLEN(35));
+ max9286_write(priv, 0x3b, MAX9286_REV_TRF(1) | MAX9286_REV_AMP(70) |
+ MAX9286_REV_AMP_X);
+ usleep_range(2000, 2500);
+
+ /*
+ * Enable GMSL links, mask unused ones and autodetect link
+ * used as CSI clock source.
+ */
+ max9286_write(priv, 0x00, MAX9286_MSTLINKSEL_AUTO | priv->route_mask);
+ max9286_write(priv, 0x0b, link_order[priv->route_mask]);
+ max9286_write(priv, 0x69, (0xf & ~priv->route_mask));
+
+ /*
+ * Video format setup:
+ * Disable CSI output, VC is set according to Link number.
+ */
+ max9286_write(priv, 0x15, MAX9286_VCTYPE | MAX9286_0X15_RESV);
+
+ /* Enable CSI-2 Lane D0-D3 only, DBL mode, YUV422 8-bit. */
+ max9286_write(priv, 0x12, MAX9286_CSIDBL | MAX9286_DBL |
+ MAX9286_CSILANECNT(priv->csi2_data_lanes) |
+ MAX9286_DATATYPE_YUV422_8BIT);
+
+ /* Automatic: FRAMESYNC taken from the slowest Link. */
+ max9286_write(priv, 0x01, MAX9286_FSYNCMODE_INT_HIZ |
+ MAX9286_FSYNCMETH_AUTO);
+
+ /* Enable HS/VS encoding, use D14/15 for HS/VS, invert VS. */
+ max9286_write(priv, 0x0c, MAX9286_HVEN | MAX9286_INVVS |
+ MAX9286_HVSRC_D14);
+
+ /*
+ * The overlap window seems to provide additional validation by tracking
+ * the delay between vsync and frame sync, generating an error if the
+ * delay is bigger than the programmed window, though it's not yet clear
+ * what value should be set.
+ *
+ * As it's an optional value and can be disabled, we do so by setting
+ * a 0 overlap value.
+ */
+ max9286_write(priv, 0x63, 0);
+ max9286_write(priv, 0x64, 0);
+
+ /*
+ * Wait for 2ms to allow the link to resynchronize after the
+ * configuration change.
+ */
+ usleep_range(2000, 5000);
+
+ return 0;
+}
+
+static void max9286_gpio_set(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct max9286_priv *priv = gpiochip_get_data(chip);
+
+ if (value)
+ priv->gpio_state |= BIT(offset);
+ else
+ priv->gpio_state &= ~BIT(offset);
+
+ max9286_write(priv, 0x0f, MAX9286_0X0F_RESERVED | priv->gpio_state);
+}
+
+static int max9286_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct max9286_priv *priv = gpiochip_get_data(chip);
+
+ return priv->gpio_state & BIT(offset);
+}
+
+static int max9286_register_gpio(struct max9286_priv *priv)
+{
+ struct device *dev = &priv->client->dev;
+ struct gpio_chip *gpio = &priv->gpio;
+ int ret;
+
+ static const char * const names[] = {
+ "GPIO0OUT",
+ "GPIO1OUT",
+ };
+
+ /* Configure the GPIO */
+ gpio->label = dev_name(dev);
+ gpio->parent = dev;
+ gpio->owner = THIS_MODULE;
+ gpio->of_node = dev->of_node;
+ gpio->ngpio = 2;
+ gpio->base = -1;
+ gpio->set = max9286_gpio_set;
+ gpio->get = max9286_gpio_get;
+ gpio->can_sleep = true;
+ gpio->names = names;
+
+ /* GPIO values default to high */
+ priv->gpio_state = BIT(0) | BIT(1);
+
+ ret = devm_gpiochip_add_data(dev, gpio, priv);
+ if (ret)
+ dev_err(dev, "Unable to create gpio_chip\n");
+
+ return ret;
+}
+
+static int max9286_init(struct device *dev)
+{
+ struct max9286_priv *priv;
+ struct i2c_client *client;
+ int ret;
+
+ client = to_i2c_client(dev);
+ priv = i2c_get_clientdata(client);
+
+ /* Enable the bus power. */
+ ret = regulator_enable(priv->regulator);
+ if (ret < 0) {
+ dev_err(&client->dev, "Unable to turn PoC on\n");
+ return ret;
+ }
+
+ ret = max9286_setup(priv);
+ if (ret) {
+ dev_err(dev, "Unable to setup max9286\n");
+ goto err_regulator;
+ }
+
+ /*
+ * Register all V4L2 interactions for the MAX9286 and notifiers for
+ * any subdevices connected.
+ */
+ ret = max9286_v4l2_register(priv);
+ if (ret) {
+ dev_err(dev, "Failed to register with V4L2\n");
+ goto err_regulator;
+ }
+
+ ret = max9286_i2c_mux_init(priv);
+ if (ret) {
+ dev_err(dev, "Unable to initialize I2C multiplexer\n");
+ goto err_v4l2_register;
+ }
+
+ /* Leave the mux channels disabled until they are selected. */
+ max9286_i2c_mux_close(priv);
+
+ return 0;
+
+err_v4l2_register:
+ max9286_v4l2_unregister(priv);
+err_regulator:
+ regulator_disable(priv->regulator);
+
+ return ret;
+}
+
+static void max9286_cleanup_dt(struct max9286_priv *priv)
+{
+ struct max9286_source *source;
+
+ for_each_source(priv, source) {
+ fwnode_handle_put(source->fwnode);
+ source->fwnode = NULL;
+ }
+}
+
+static int max9286_parse_dt(struct max9286_priv *priv)
+{
+ struct device *dev = &priv->client->dev;
+ struct device_node *i2c_mux;
+ struct device_node *node = NULL;
+ unsigned int i2c_mux_mask = 0;
+
+ of_node_get(dev->of_node);
+ i2c_mux = of_find_node_by_name(dev->of_node, "i2c-mux");
+ if (!i2c_mux) {
+ dev_err(dev, "Failed to find i2c-mux node\n");
+ of_node_put(dev->of_node);
+ return -EINVAL;
+ }
+
+ /* Identify which i2c-mux channels are enabled */
+ for_each_child_of_node(i2c_mux, node) {
+ u32 id = 0;
+
+ of_property_read_u32(node, "reg", &id);
+ if (id >= MAX9286_NUM_GMSL)
+ continue;
+
+ if (!of_device_is_available(node)) {
+ dev_dbg(dev, "Skipping disabled I2C bus port %u\n", id);
+ continue;
+ }
+
+ i2c_mux_mask |= BIT(id);
+ }
+ of_node_put(node);
+ of_node_put(i2c_mux);
+
+ /* Parse the endpoints */
+ for_each_endpoint_of_node(dev->of_node, node) {
+ struct max9286_source *source;
+ struct of_endpoint ep;
+
+ of_graph_parse_endpoint(node, &ep);
+ dev_dbg(dev, "Endpoint %pOF on port %d",
+ ep.local_node, ep.port);
+
+ if (ep.port > MAX9286_NUM_GMSL) {
+ dev_err(dev, "Invalid endpoint %s on port %d",
+ of_node_full_name(ep.local_node), ep.port);
+ continue;
+ }
+
+ /* For the source endpoint just parse the bus configuration. */
+ if (ep.port == MAX9286_SRC_PAD) {
+ struct v4l2_fwnode_endpoint vep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ int ret;
+
+ ret = v4l2_fwnode_endpoint_parse(
+ of_fwnode_handle(node), &vep);
+ if (ret) {
+ of_node_put(node);
+ of_node_put(dev->of_node);
+ return ret;
+ }
+
+ if (vep.bus_type != V4L2_MBUS_CSI2_DPHY) {
+ dev_err(dev,
+ "Media bus %u type not supported\n",
+ vep.bus_type);
+ v4l2_fwnode_endpoint_free(&vep);
+ of_node_put(node);
+ of_node_put(dev->of_node);
+ return -EINVAL;
+ }
+
+ priv->csi2_data_lanes =
+ vep.bus.mipi_csi2.num_data_lanes;
+ v4l2_fwnode_endpoint_free(&vep);
+
+ continue;
+ }
+
+ /* Skip if the corresponding GMSL link is unavailable. */
+ if (!(i2c_mux_mask & BIT(ep.port)))
+ continue;
+
+ if (priv->sources[ep.port].fwnode) {
+ dev_err(dev,
+ "Multiple port endpoints are not supported: %d",
+ ep.port);
+
+ continue;
+ }
+
+ source = &priv->sources[ep.port];
+ source->fwnode = fwnode_graph_get_remote_endpoint(
+ of_fwnode_handle(node));
+ if (!source->fwnode) {
+ dev_err(dev,
+ "Endpoint %pOF has no remote endpoint connection\n",
+ ep.local_node);
+
+ continue;
+ }
+
+ priv->source_mask |= BIT(ep.port);
+ priv->nsources++;
+ }
+ of_node_put(node);
+ of_node_put(dev->of_node);
+
+ priv->route_mask = priv->source_mask;
+
+ return 0;
+}
+
+static int max9286_probe(struct i2c_client *client)
+{
+ struct max9286_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ mutex_init(&priv->mutex);
+
+ priv->client = client;
+ i2c_set_clientdata(client, priv);
+
+ priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->gpiod_pwdn))
+ return PTR_ERR(priv->gpiod_pwdn);
+
+ gpiod_set_consumer_name(priv->gpiod_pwdn, "max9286-pwdn");
+ gpiod_set_value_cansleep(priv->gpiod_pwdn, 1);
+
+ /* Wait at least 4ms before the I2C lines latch to the address */
+ if (priv->gpiod_pwdn)
+ usleep_range(4000, 5000);
+
+ /*
+ * The MAX9286 starts by default with all ports enabled, we disable all
+ * ports early to ensure that all channels are disabled if we error out
+ * and keep the bus consistent.
+ */
+ max9286_i2c_mux_close(priv);
+
+ /*
+ * The MAX9286 initialises with auto-acknowledge enabled by default.
+ * This can be invasive to other transactions on the same bus, so
+ * disable it early. It will be enabled only as and when needed.
+ */
+ max9286_configure_i2c(priv, false);
+
+ ret = max9286_register_gpio(priv);
+ if (ret)
+ goto err_powerdown;
+
+ priv->regulator = devm_regulator_get(&client->dev, "poc");
+ if (IS_ERR(priv->regulator)) {
+ if (PTR_ERR(priv->regulator) != -EPROBE_DEFER)
+ dev_err(&client->dev,
+ "Unable to get PoC regulator (%ld)\n",
+ PTR_ERR(priv->regulator));
+ ret = PTR_ERR(priv->regulator);
+ goto err_powerdown;
+ }
+
+ ret = max9286_parse_dt(priv);
+ if (ret)
+ goto err_powerdown;
+
+ ret = max9286_init(&client->dev);
+ if (ret < 0)
+ goto err_cleanup_dt;
+
+ return 0;
+
+err_cleanup_dt:
+ max9286_cleanup_dt(priv);
+err_powerdown:
+ gpiod_set_value_cansleep(priv->gpiod_pwdn, 0);
+
+ return ret;
+}
+
+static int max9286_remove(struct i2c_client *client)
+{
+ struct max9286_priv *priv = i2c_get_clientdata(client);
+
+ i2c_mux_del_adapters(priv->mux);
+
+ max9286_v4l2_unregister(priv);
+
+ regulator_disable(priv->regulator);
+
+ gpiod_set_value_cansleep(priv->gpiod_pwdn, 0);
+
+ max9286_cleanup_dt(priv);
+
+ return 0;
+}
+
+static const struct of_device_id max9286_dt_ids[] = {
+ { .compatible = "maxim,max9286" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, max9286_dt_ids);
+
+static struct i2c_driver max9286_i2c_driver = {
+ .driver = {
+ .name = "max9286",
+ .of_match_table = of_match_ptr(max9286_dt_ids),
+ },
+ .probe_new = max9286_probe,
+ .remove = max9286_remove,
+};
+
+module_i2c_driver(max9286_i2c_driver);
+
+MODULE_DESCRIPTION("Maxim MAX9286 GMSL Deserializer Driver");
+MODULE_AUTHOR("Jacopo Mondi, Kieran Bingham, Laurent Pinchart, Niklas Söderlund, Vladimir Barinov");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related
* [PATCH v9 3/4] dt-bindings: media: i2c: Add bindings for IMI RDACM2x
From: Kieran Bingham @ 2020-05-12 15:51 UTC (permalink / raw)
To: linux-renesas-soc, linux-media, devicetree, linux-kernel,
Mauro Carvalho Chehab
Cc: Kieran Bingham, Laurent Pinchart, Jacopo Mondi,
Niklas Söderlund, sakari.ailus, Hans Verkuil, Hyun Kwon,
Manivannan Sadhasivam, Rob Herring, Jacopo Mondi, Kieran Bingham,
Rob Herring
In-Reply-To: <20200512155105.1068064-1-kieran.bingham+renesas@ideasonboard.com>
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
The IMI RDACM20 and IMI RDACM21 are Gigabit Multimedia Serial Link (GMSL) camera
capable of transmitting video and I2C control messages on a coax cable
physical link for automotive applications.
Document their device tree bindings.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v2:
- Provide imi vendor prefix
- Fix minor spelling
v3:
- update binding descriptions
v4:
- No change
v5:
- Specify optional third reg address for the MCU
v7:
[Jacopo]
- Rename to imi,rdacm2x-gmsl.yaml
- Exand bindings to describe RDACM21
v9:
[Jacopo]
- Rework 'compatible' property as suggested by Rob
- Re-order vendor prefixes ('g' comes before 'i' ... )
- Add Rob's tag
.../bindings/media/i2c/imi,rdacm2x-gmsl.yaml | 159 ++++++++++++++++++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
2 files changed, 161 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml
diff --git a/Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml b/Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml
new file mode 100644
index 000000000000..fe524490e6a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml
@@ -0,0 +1,159 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+# Copyright (C) 2019 Renesas Electronics Corp.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/imi,rdacm2x-gmsl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IMI D&D RDACM20 and RDACM21 Automotive Camera Platforms
+
+maintainers:
+ - Jacopo Mondi <jacopo+renesas@jmondi.org>
+ - Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+ - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+ - Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+description: -|
+ The IMI D&D RDACM20 and RDACM21 are GMSL-compatible camera designed for
+ automotive applications.
+
+ The RDACM20 camera module encloses a Maxim Integrated MAX9271 GMSL serializer,
+ coupled with an OV10635 image sensor and an embedded MCU. Both the MCU and
+ the image sensor are connected to the serializer local I2C bus and are
+ accessible by the host SoC by direct addressing.
+
+ The RDACM21 camera module encloses the same serializer, coupled with an
+ OV10640 image sensor and an OV490 ISP. Only the OV490 ISP is interfaced to
+ the serializer local I2C bus while the image sensor is not accessible from
+ the host SoC.
+
+ They both connect to a remote GMSL endpoint through a coaxial cable.
+
+ IMI RDACM20
+ +---------------+ +--------------------------------+
+ | GMSL | <- Video Stream | <- Video--------\ |
+ | |< === GMSL Link ====== >|MAX9271<- I2C bus-> <-->OV10635 |
+ | de-serializer | <- I2C messages -> | \<-->MCU |
+ +---------------+ +--------------------------------+
+
+ IMI RDACM21
+ +---------------+ +--------------------------------+
+ | GMSL | <- Video Stream | <- Video--------\ |
+ | |< === GMSL Link ====== >|MAX9271<- I2C bus-> <-->OV490 |
+ | | <- I2C messages -> | | |
+ | de-serializer | | OV10640 <-------| |
+ +---------------+ +--------------------------------+
+
+ Both camera modules serialize video data generated by the embedded camera
+ sensor on the GMSL serial channel to a remote GMSL de-serializer. They also
+ receive and transmit I2C messages encapsulated and transmitted on the GMSL
+ bidirectional control channel.
+
+ All I2C traffic received on the GMSL link not directed to the serializer is
+ propagated on the local I2C bus to the remote device there connected. All the
+ I2C traffic generated on the local I2C bus not directed to the serializer is
+ propagated to the remote de-serializer encapsulated in the GMSL control
+ channel.
+
+ The RDACM20 and RDACM21 DT node should be a direct child of the GMSL
+ deserializer's I2C bus corresponding to the GMSL link that the camera is
+ attached to.
+
+properties:
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ compatible:
+ enum:
+ - imi,rdacm20
+ - imi,rdacm21
+
+ reg:
+ description: -|
+ I2C device addresses, the first to be assigned to the serializer, the
+ following ones to be assigned to the remote devices.
+
+ For RDACM20 the second entry of the property is assigned to the
+ OV10635 image sensor and the optional third one to the embedded MCU.
+
+ For RDACM21 the second entry is assigned to the OV490 ISP and the optional
+ third one ignored.
+
+ minItems: 2
+ maxItems: 3
+
+ port:
+ type: object
+ additionalProperties: false
+ description: -|
+ Connection to the remote GMSL endpoint are modelled using the OF graph
+ bindings in accordance with the video interface bindings defined in
+ Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+ The device node contains a single "port" child node with a single
+ "endpoint" sub-device.
+
+ properties:
+ endpoint:
+ type: object
+ additionalProperties: false
+
+ properties:
+ remote-endpoint:
+ description: -|
+ phandle to the remote GMSL endpoint sub-node in the remote node
+ port.
+ maxItems: 1
+
+ required:
+ - remote-endpoint
+
+ required:
+ - endpoint
+
+required:
+ - compatible
+ - reg
+ - port
+
+examples:
+ - |
+ i2c@e66d8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <0 0xe66d8000 0 0x40>;
+
+ camera@31 {
+ compatible = "imi,rdacm20";
+ reg = <0x31>, <0x41>, <0x51>;
+
+ port {
+ rdacm20_out0: endpoint {
+ remote-endpoint = <&max9286_in0>;
+ };
+ };
+ };
+ };
+
+ - |
+ i2c@e66d8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <0 0xe66d8000 0 0x40>;
+
+ camera@31 {
+ compatible = "imi,rdacm21";
+ reg = <0x31>, <0x41>;
+
+ port {
+ rdacm21_out0: endpoint {
+ remote-endpoint = <&max9286_in0>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index d3891386d671..f0f09a4c23ad 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -455,6 +455,8 @@ patternProperties:
description: ILI Technology Corporation (ILITEK)
"^img,.*":
description: Imagination Technologies Ltd.
+ "^imi,.*":
+ description: Integrated Micro-Electronics Inc.
"^incircuit,.*":
description: In-Circuit GmbH
"^inet-tek,.*":
--
2.25.1
^ permalink raw reply related
* [PATCH v9 4/4] media: i2c: Add RDACM20 driver
From: Kieran Bingham @ 2020-05-12 15:51 UTC (permalink / raw)
To: linux-renesas-soc, linux-media, devicetree, linux-kernel,
Mauro Carvalho Chehab
Cc: Kieran Bingham, Laurent Pinchart, Jacopo Mondi,
Niklas Söderlund, sakari.ailus, Hans Verkuil, Hyun Kwon,
Manivannan Sadhasivam, Rob Herring, Jacopo Mondi,
Laurent Pinchart, Niklas Söderlund, Kieran Bingham,
Rob Herring
In-Reply-To: <20200512155105.1068064-1-kieran.bingham+renesas@ideasonboard.com>
From: Jacopo Mondi <jacopo+renesas@jmondi.org>
The RDACM20 is a GMSL camera supporting 1280x800 resolution images
developed by IMI based on an Omnivision 10635 sensor and a Maxim MAX9271
GMSL serializer.
The GMSL link carries power, control (I2C) and video data over a
single coax cable.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v2:
- Fix MAINTAINERS entry
v3:
- Use new V4L2_MBUS_CSI2_DPHY bus type
- Remove 'always zero' error print
- Fix module description
v5:
- use sleep rather than busy loops for 10 ms delays
- Return ov10635_set_regs directly
- Use devm_kzalloc instead of kzalloc in probe()
- Or in the flags: dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE
- Ensure v4l2_ctrl_handler_free() is called
- rdacm20_probe converted to use .probe_new and drop i2c device id
tables
- Remove rdacm20_g_mbus_config
v7:
- Use new i2c_new_dummy_device API
v8:
- Almost a new version, main changes are:
- Split max9271 out
- Rework bindings to yaml format and include forthcoming RDACM21
- Remove unecessary header file
- Add pixel rate calculation
- Drop unused fields and dead code
- Rebase on media-master v5.7-rc1
- A detailed list of changes provided as fixup patches is avilable at
git://jmondi.org/linux #gmsl/jmondi/media-master/max9286-v8+old-rdacm20+split
which includes the following list of patches:
squash!: rdacm20: Report pixel rate
squash!: rdacm20: Force sensor ID re-read
squash!: rdamc20: Check register programming result
squash!: rdacm20: Update to use the new max9271 APIs
squash!: rdacm20: Start with serial link disabled
squash!: rdacm20: Hard reset the sensor
squash!: rdacm20: Cache i2c addresses
squash!: rdacm20: Adjust to use new max9271 API
squash!: rdacm20: Drop unused format definition
squash!: rdacm20: Refresh file header
squash!: max9271: Add two functions to control addresses
squash!: max9271: Do not rewrite i2c address
squash!: max9271: Improve gpio handling
squash!: max9271: Rework core functions
squash!: max9271 refresh
squash!: rdacm20: Update maintainers file
squash!: rdacm20: Remove unsued/duplicated defines
squash!: rdacm20: Remove header file
squash!: rdacm20: Move content of header into C file
squash!: rdacm20: Reorganize register table
squash!: rdacm20: Fix subdevice flag creation
squash!: rdacm20: Drop i2c id table
squash!: rdacm20: Release control handler
squash!: rdacm20: Better handle i2c dummy error
squash!: rdacm20: Use devm_kzalloc
squash!: rdacm20: Use probe_new()
squash!: rdacm20: Drop deprecated g_mbus_config
media: i2c: rdacm20: Break max9271 out from rdacm20
squash!: rdacm20: Rebase on latest media/maste
media: i2c: Add RDACM20 driver
dt-bindings: media: i2c: Add bindings for IMI RDACM2x
v9:
- Drop OV10635_FORMAT and use MEDIA_BUS_FMT_UYVY8_2X8 as suggested by
Hans
MAINTAINERS | 12 +
drivers/media/i2c/Kconfig | 13 +
drivers/media/i2c/Makefile | 2 +
drivers/media/i2c/max9271.c | 341 ++++++++++++++++++
drivers/media/i2c/max9271.h | 224 ++++++++++++
drivers/media/i2c/rdacm20.c | 667 ++++++++++++++++++++++++++++++++++++
6 files changed, 1259 insertions(+)
create mode 100644 drivers/media/i2c/max9271.c
create mode 100644 drivers/media/i2c/max9271.h
create mode 100644 drivers/media/i2c/rdacm20.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 99e3bf7760fd..713b56652181 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14206,6 +14206,18 @@ S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git dev
F: tools/testing/selftests/rcutorture
+RDACM20 Camera Sensor
+M: Jacopo Mondi <jacopo+renesas@jmondi.org>
+M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+M: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+M: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml
+F: drivers/media/i2c/rdacm20.c
+F: drivers/media/i2c/max9271.c
+F: drivers/media/i2c/max9271.h
+
RDC R-321X SoC
M: Florian Fainelli <florian@openwrt.org>
S: Maintained
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 2e390f41f6da..6e3300760c7f 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1157,6 +1157,19 @@ config VIDEO_NOON010PC30
source "drivers/media/i2c/m5mols/Kconfig"
+config VIDEO_RDACM20
+ tristate "IMI RDACM20 camera support"
+ depends on I2C
+ select V4L2_FWNODE
+ select VIDEO_V4L2_SUBDEV_API
+ select MEDIA_CONTROLLER
+ help
+ This driver supports the IMI RDACM20 GMSL camera, used in
+ ADAS systems.
+
+ This camera should be used in conjunction with a GMSL
+ deserialiser such as the MAX9286.
+
config VIDEO_RJ54N1
tristate "Sharp RJ54N1CB0C sensor support"
depends on I2C && VIDEO_V4L2
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index f0b001ee4b05..64e6df50f68c 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -118,6 +118,8 @@ obj-$(CONFIG_VIDEO_IMX290) += imx290.o
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
obj-$(CONFIG_VIDEO_IMX355) += imx355.o
obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
+rdacm20-camera_module-objs := rdacm20.o max9271.o
+obj-$(CONFIG_VIDEO_RDACM20) += rdacm20-camera_module.o
obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
obj-$(CONFIG_SDR_MAX2175) += max2175.o
diff --git a/drivers/media/i2c/max9271.c b/drivers/media/i2c/max9271.c
new file mode 100644
index 000000000000..0f6f7a092a46
--- /dev/null
+++ b/drivers/media/i2c/max9271.c
@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017-2020 Jacopo Mondi
+ * Copyright (C) 2017-2020 Kieran Bingham
+ * Copyright (C) 2017-2020 Laurent Pinchart
+ * Copyright (C) 2017-2020 Niklas Söderlund
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * This file exports functions to control the Maxim MAX9271 GMSL serializer
+ * chip. This is not a self-contained driver, as MAX9271 is usually embedded in
+ * camera modules with at least one image sensor and optional additional
+ * components, such as uController units or ISPs/DSPs.
+ *
+ * Drivers for the camera modules (i.e. rdacm20/21) are expected to use
+ * functions exported from this library driver to maximize code re-use.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+
+#include "max9271.h"
+
+static int max9271_read(struct max9271_device *dev, u8 reg)
+{
+ int ret;
+
+ dev_dbg(&dev->client->dev, "%s(0x%02x)\n", __func__, reg);
+
+ ret = i2c_smbus_read_byte_data(dev->client, reg);
+ if (ret < 0)
+ dev_dbg(&dev->client->dev,
+ "%s: register 0x%02x read failed (%d)\n",
+ __func__, reg, ret);
+
+ return ret;
+}
+
+static int max9271_write(struct max9271_device *dev, u8 reg, u8 val)
+{
+ int ret;
+
+ dev_dbg(&dev->client->dev, "%s(0x%02x, 0x%02x)\n", __func__, reg, val);
+
+ ret = i2c_smbus_write_byte_data(dev->client, reg, val);
+ if (ret < 0)
+ dev_err(&dev->client->dev,
+ "%s: register 0x%02x write failed (%d)\n",
+ __func__, reg, ret);
+
+ return ret;
+}
+
+/*
+ * max9271_pclk_detect() - Detect valid pixel clock from image sensor
+ *
+ * Wait up to 10ms for a valid pixel clock.
+ *
+ * Returns 0 for success, < 0 for pixel clock not properly detected
+ */
+static int max9271_pclk_detect(struct max9271_device *dev)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < 100; i++) {
+ ret = max9271_read(dev, 0x15);
+ if (ret < 0)
+ return ret;
+
+ if (ret & MAX9271_PCLKDET)
+ return 0;
+
+ usleep_range(50, 100);
+ }
+
+ dev_err(&dev->client->dev, "Unable to detect valid pixel clock\n");
+
+ return -EIO;
+}
+
+int max9271_set_serial_link(struct max9271_device *dev, bool enable)
+{
+ int ret;
+ u8 val = MAX9271_REVCCEN | MAX9271_FWDCCEN;
+
+ if (enable) {
+ ret = max9271_pclk_detect(dev);
+ if (ret)
+ return ret;
+
+ val |= MAX9271_SEREN;
+ } else {
+ val |= MAX9271_CLINKEN;
+ }
+
+ /*
+ * The serializer temporarily disables the reverse control channel for
+ * 350µs after starting/stopping the forward serial link, but the
+ * deserializer synchronization time isn't clearly documented.
+ *
+ * According to the serializer datasheet we should wait 3ms, while
+ * according to the deserializer datasheet we should wait 5ms.
+ *
+ * Short delays here appear to show bit-errors in the writes following.
+ * Therefore a conservative delay seems best here.
+ */
+ max9271_write(dev, 0x04, val);
+ usleep_range(5000, 8000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_set_serial_link);
+
+int max9271_configure_i2c(struct max9271_device *dev, u8 i2c_config)
+{
+ int ret;
+
+ ret = max9271_write(dev, 0x0d, i2c_config);
+ if (ret)
+ return ret;
+
+ /* The delay required after an I2C bus configuration change is not
+ * characterized in the serializer manual. Sleep up to 5msec to
+ * stay safe.
+ */
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_configure_i2c);
+
+int max9271_set_high_threshold(struct max9271_device *dev, bool enable)
+{
+ int ret;
+
+ ret = max9271_read(dev, 0x08);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Enable or disable reverse channel high threshold to increase
+ * immunity to power supply noise.
+ */
+ max9271_write(dev, 0x08, enable ? ret | BIT(0) : ret & ~BIT(0));
+ usleep_range(2000, 2500);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_set_high_threshold);
+
+int max9271_configure_gmsl_link(struct max9271_device *dev)
+{
+ /*
+ * Configure the GMSL link:
+ *
+ * - Double input mode, high data rate, 24-bit mode
+ * - Latch input data on PCLKIN rising edge
+ * - Enable HS/VS encoding
+ * - 1-bit parity error detection
+ *
+ * TODO: Make the GMSL link configuration parametric.
+ */
+ max9271_write(dev, 0x07, MAX9271_DBL | MAX9271_HVEN |
+ MAX9271_EDC_1BIT_PARITY);
+ usleep_range(5000, 8000);
+
+ /*
+ * Adjust spread spectrum to +4% and auto-detect pixel clock
+ * and serial link rate.
+ */
+ max9271_write(dev, 0x02, MAX9271_SPREAD_SPECT_4 | MAX9271_R02_RES |
+ MAX9271_PCLK_AUTODETECT | MAX9271_SERIAL_AUTODETECT);
+ usleep_range(5000, 8000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_configure_gmsl_link);
+
+int max9271_set_gpios(struct max9271_device *dev, u8 gpio_mask)
+{
+ int ret;
+
+ ret = max9271_read(dev, 0x0f);
+ if (ret < 0)
+ return 0;
+
+ ret |= gpio_mask;
+ ret = max9271_write(dev, 0x0f, ret);
+ if (ret < 0) {
+ dev_err(&dev->client->dev, "Failed to set gpio (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_set_gpios);
+
+int max9271_clear_gpios(struct max9271_device *dev, u8 gpio_mask)
+{
+ int ret;
+
+ ret = max9271_read(dev, 0x0f);
+ if (ret < 0)
+ return 0;
+
+ ret &= ~gpio_mask;
+ ret = max9271_write(dev, 0x0f, ret);
+ if (ret < 0) {
+ dev_err(&dev->client->dev, "Failed to clear gpio (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_clear_gpios);
+
+int max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask)
+{
+ int ret;
+
+ ret = max9271_read(dev, 0x0f);
+ if (ret < 0)
+ return 0;
+
+ /* BIT(0) reserved: GPO is always enabled. */
+ ret |= gpio_mask | BIT(0);
+ ret = max9271_write(dev, 0x0e, ret);
+ if (ret < 0) {
+ dev_err(&dev->client->dev, "Failed to enable gpio (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_enable_gpios);
+
+int max9271_disable_gpios(struct max9271_device *dev, u8 gpio_mask)
+{
+ int ret;
+
+ ret = max9271_read(dev, 0x0f);
+ if (ret < 0)
+ return 0;
+
+ /* BIT(0) reserved: GPO cannot be disabled */
+ ret &= (~gpio_mask | BIT(0));
+ ret = max9271_write(dev, 0x0e, ret);
+ if (ret < 0) {
+ dev_err(&dev->client->dev, "Failed to disable gpio (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_disable_gpios);
+
+int max9271_verify_id(struct max9271_device *dev)
+{
+ int ret;
+
+ ret = max9271_read(dev, 0x1e);
+ if (ret < 0) {
+ dev_err(&dev->client->dev, "MAX9271 ID read failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ if (ret != MAX9271_ID) {
+ dev_err(&dev->client->dev, "MAX9271 ID mismatch (0x%02x)\n",
+ ret);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_verify_id);
+
+int max9271_set_address(struct max9271_device *dev, u8 addr)
+{
+ int ret;
+
+ ret = max9271_write(dev, 0x00, addr << 1);
+ if (ret < 0) {
+ dev_err(&dev->client->dev,
+ "MAX9271 I2C address change failed (%d)\n", ret);
+ return ret;
+ }
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_set_address);
+
+int max9271_set_deserializer_address(struct max9271_device *dev, u8 addr)
+{
+ int ret;
+
+ ret = max9271_write(dev, 0x01, addr << 1);
+ if (ret < 0) {
+ dev_err(&dev->client->dev,
+ "MAX9271 deserializer address set failed (%d)\n", ret);
+ return ret;
+ }
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_set_deserializer_address);
+
+int max9271_set_translation(struct max9271_device *dev, u8 source, u8 dest)
+{
+ int ret;
+
+ ret = max9271_write(dev, 0x09, source << 1);
+ if (ret < 0) {
+ dev_err(&dev->client->dev,
+ "MAX9271 I2C translation setup failed (%d)\n", ret);
+ return ret;
+ }
+ usleep_range(3500, 5000);
+
+ ret = max9271_write(dev, 0x0a, dest << 1);
+ if (ret < 0) {
+ dev_err(&dev->client->dev,
+ "MAX9271 I2C translation setup failed (%d)\n", ret);
+ return ret;
+ }
+ usleep_range(3500, 5000);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(max9271_set_translation);
diff --git a/drivers/media/i2c/max9271.h b/drivers/media/i2c/max9271.h
new file mode 100644
index 000000000000..d78fb21441e9
--- /dev/null
+++ b/drivers/media/i2c/max9271.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017-2020 Jacopo Mondi
+ * Copyright (C) 2017-2020 Kieran Bingham
+ * Copyright (C) 2017-2020 Laurent Pinchart
+ * Copyright (C) 2017-2020 Niklas Söderlund
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ */
+
+#include <linux/i2c.h>
+
+#define MAX9271_DEFAULT_ADDR 0x40
+
+/* Register 0x02 */
+#define MAX9271_SPREAD_SPECT_0 (0 << 5)
+#define MAX9271_SPREAD_SPECT_05 (1 << 5)
+#define MAX9271_SPREAD_SPECT_15 (2 << 5)
+#define MAX9271_SPREAD_SPECT_1 (5 << 5)
+#define MAX9271_SPREAD_SPECT_2 (3 << 5)
+#define MAX9271_SPREAD_SPECT_3 (6 << 5)
+#define MAX9271_SPREAD_SPECT_4 (7 << 5)
+#define MAX9271_R02_RES BIT(4)
+#define MAX9271_PCLK_AUTODETECT (3 << 2)
+#define MAX9271_SERIAL_AUTODETECT (0x03)
+/* Register 0x04 */
+#define MAX9271_SEREN BIT(7)
+#define MAX9271_CLINKEN BIT(6)
+#define MAX9271_PRBSEN BIT(5)
+#define MAX9271_SLEEP BIT(4)
+#define MAX9271_INTTYPE_I2C (0 << 2)
+#define MAX9271_INTTYPE_UART (1 << 2)
+#define MAX9271_INTTYPE_NONE (2 << 2)
+#define MAX9271_REVCCEN BIT(1)
+#define MAX9271_FWDCCEN BIT(0)
+/* Register 0x07 */
+#define MAX9271_DBL BIT(7)
+#define MAX9271_DRS BIT(6)
+#define MAX9271_BWS BIT(5)
+#define MAX9271_ES BIT(4)
+#define MAX9271_HVEN BIT(2)
+#define MAX9271_EDC_1BIT_PARITY (0 << 0)
+#define MAX9271_EDC_6BIT_CRC (1 << 0)
+#define MAX9271_EDC_6BIT_HAMMING (2 << 0)
+/* Register 0x08 */
+#define MAX9271_INVVS BIT(7)
+#define MAX9271_INVHS BIT(6)
+#define MAX9271_REV_LOGAIN BIT(3)
+#define MAX9271_REV_HIVTH BIT(0)
+/* Register 0x09 */
+#define MAX9271_ID 0x09
+/* Register 0x0d */
+#define MAX9271_I2CLOCACK BIT(7)
+#define MAX9271_I2CSLVSH_1046NS_469NS (3 << 5)
+#define MAX9271_I2CSLVSH_938NS_352NS (2 << 5)
+#define MAX9271_I2CSLVSH_469NS_234NS (1 << 5)
+#define MAX9271_I2CSLVSH_352NS_117NS (0 << 5)
+#define MAX9271_I2CMSTBT_837KBPS (7 << 2)
+#define MAX9271_I2CMSTBT_533KBPS (6 << 2)
+#define MAX9271_I2CMSTBT_339KBPS (5 << 2)
+#define MAX9271_I2CMSTBT_173KBPS (4 << 2)
+#define MAX9271_I2CMSTBT_105KBPS (3 << 2)
+#define MAX9271_I2CMSTBT_84KBPS (2 << 2)
+#define MAX9271_I2CMSTBT_28KBPS (1 << 2)
+#define MAX9271_I2CMSTBT_8KBPS (0 << 2)
+#define MAX9271_I2CSLVTO_NONE (3 << 0)
+#define MAX9271_I2CSLVTO_1024US (2 << 0)
+#define MAX9271_I2CSLVTO_256US (1 << 0)
+#define MAX9271_I2CSLVTO_64US (0 << 0)
+/* Register 0x0f */
+#define MAX9271_GPIO5OUT BIT(5)
+#define MAX9271_GPIO4OUT BIT(4)
+#define MAX9271_GPIO3OUT BIT(3)
+#define MAX9271_GPIO2OUT BIT(2)
+#define MAX9271_GPIO1OUT BIT(1)
+#define MAX9271_GPO BIT(0)
+/* Register 0x15 */
+#define MAX9271_PCLKDET BIT(0)
+
+/**
+ * struct max9271_device - max9271 device
+ * @client: The i2c client for the max9271 instance
+ */
+struct max9271_device {
+ struct i2c_client *client;
+};
+
+/**
+ * max9271_set_serial_link() - Enable/disable serial link
+ * @dev: The max9271 device
+ * @enable: Serial link enable/disable flag
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_set_serial_link(struct max9271_device *dev, bool enable);
+
+/**
+ * max9271_configure_i2c() - Configure I2C bus parameters
+ * @dev: The max9271 device
+ * @i2c_config: The I2C bus configuration bit mask
+ *
+ * Configure MAX9271 I2C interface. The bus configuration provided in the
+ * @i2c_config parameter shall be assembled using bit values defined by the
+ * MAX9271_I2C* macros.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_configure_i2c(struct max9271_device *dev, u8 i2c_config);
+
+/**
+ * max9271_set_high_threshold() - Enable or disable reverse channel high
+ * threshold
+ * @dev: The max9271 device
+ * @enable: High threshold enable/disable flag
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_set_high_threshold(struct max9271_device *dev, bool enable);
+
+/**
+ * max9271_configure_gmsl_link() - Configure the GMSL link
+ * @dev: The max9271 device
+ *
+ * FIXME: the GMSL link configuration is currently hardcoded and performed
+ * by programming registers 0x04, 0x07 and 0x02.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_configure_gmsl_link(struct max9271_device *dev);
+
+/**
+ * max9271_set_gpios() - Set gpio lines to physical high value
+ * @dev: The max9271 device
+ * @gpio_mask: The mask of gpio lines to set to high value
+ *
+ * The @gpio_mask parameter shall be assembled using the MAX9271_GP[IO|O]*
+ * bit values.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_set_gpios(struct max9271_device *dev, u8 gpio_mask);
+
+/**
+ * max9271_clear_gpios() - Set gpio lines to physical low value
+ * @dev: The max9271 device
+ * @gpio_mask: The mask of gpio lines to set to low value
+ *
+ * The @gpio_mask parameter shall be assembled using the MAX9271_GP[IO|O]*
+ * bit values.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_clear_gpios(struct max9271_device *dev, u8 gpio_mask);
+
+/**
+ * max9271_enable_gpios() - Enable gpio lines
+ * @dev: The max9271 device
+ * @gpio_mask: The mask of gpio lines to enable
+ *
+ * The @gpio_mask parameter shall be assembled using the MAX9271_GPIO*
+ * bit values. GPO line is always enabled by default.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask);
+
+/**
+ * max9271_disable_gpios() - Disable gpio lines
+ * @dev: The max9271 device
+ * @gpio_mask: The mask of gpio lines to disable
+ *
+ * The @gpio_mask parameter shall be assembled using the MAX9271_GPIO*
+ * bit values. GPO line is always enabled by default and cannot be disabled.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_disable_gpios(struct max9271_device *dev, u8 gpio_mask);
+
+/**
+ * max9271_verify_id() - Read and verify MAX9271 id
+ * @dev: The max9271 device
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_verify_id(struct max9271_device *dev);
+
+/**
+ * max9271_set_address() - Program a new I2C address
+ * @dev: The max9271 device
+ * @addr: The new I2C address in 7-bit format
+ *
+ * This function only takes care of programming the new I2C address @addr to
+ * in the MAX9271 chip registers, it is responsiblity of the caller to set
+ * the i2c address client to the @addr value to be able to communicate with
+ * the MAX9271 chip using the I2C framework APIs after this function returns.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_set_address(struct max9271_device *dev, u8 addr);
+
+/**
+ * max9271_set_deserializer_address() - Program the remote deserializer address
+ * @dev: The max9271 device
+ * @addr: The deserializer I2C address in 7-bit format
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_set_deserializer_address(struct max9271_device *dev, u8 addr);
+
+/**
+ * max9271_set_translation() - Program I2C address translation
+ * @dev: The max9271 device
+ * @source: The I2C source address
+ * @dest: The I2C destination address
+ *
+ * Program address translation from @source to @dest. This is required to
+ * communicate with local devices that do not support address reprogramming.
+ *
+ * TODO: The device supports translation of two address, this function currently
+ * supports a single one.
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+int max9271_set_translation(struct max9271_device *dev, u8 source, u8 dest);
diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
new file mode 100644
index 000000000000..cda3e6372ea9
--- /dev/null
+++ b/drivers/media/i2c/rdacm20.c
@@ -0,0 +1,667 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * IMI RDACM20 GMSL Camera Driver
+ *
+ * Copyright (C) 2017-2020 Jacopo Mondi
+ * Copyright (C) 2017-2020 Kieran Bingham
+ * Copyright (C) 2017-2019 Laurent Pinchart
+ * Copyright (C) 2017-2019 Niklas Söderlund
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ */
+
+/*
+ * The camera is made of an Omnivision OV10635 sensor connected to a Maxim
+ * MAX9271 GMSL serializer.
+ */
+
+#include <linux/delay.h>
+#include <linux/fwnode.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "max9271.h"
+
+#define OV10635_I2C_ADDRESS 0x30
+
+#define OV10635_SOFTWARE_RESET 0x0103
+#define OV10635_PID 0x300a
+#define OV10635_VER 0x300b
+#define OV10635_SC_CMMN_SCCB_ID 0x300c
+#define OV10635_SC_CMMN_SCCB_ID_SELECT BIT(0)
+#define OV10635_VERSION 0xa635
+
+#define OV10635_WIDTH 1280
+#define OV10635_HEIGHT 800
+
+/* VTS = PCLK / FPS / HTS / 2 (= 88MHz / 1572 / 30 / 2) */
+#define OV10635_HTS 1572
+/* FPS = 29,9998 */
+#define OV10635_VTS 933
+
+/*
+ * As the drivers supports a single MEDIA_BUS_FMT_UYVY8_2X8 format we
+ * can harcode the pixel rate.
+ *
+ * PCLK is fed through the system clock, programmed @88MHz.
+ * MEDIA_BUS_FMT_UYVY8_2X8 format = 2 samples per pixel.
+ *
+ * Pixelrate = PCLK / 2
+ * FPS = (OV10635_VTS * OV10635_HTS) / PixelRate
+ * = 29,9998
+ */
+#define OV10635_PIXEL_RATE (44000000)
+
+static const struct ov10635_reg {
+ u16 reg;
+ u8 val;
+} ov10635_regs_wizard[] = {
+ { 0x301b, 0xff }, { 0x301c, 0xff }, { 0x301a, 0xff }, { 0x3011, 0x42 },
+ { 0x6900, 0x0c }, { 0x6901, 0x19 }, { 0x3503, 0x10 }, { 0x3025, 0x03 },
+ { 0x3003, 0x16 }, { 0x3004, 0x30 }, { 0x3005, 0x40 }, { 0x3006, 0x91 },
+ { 0x3600, 0x74 }, { 0x3601, 0x2b }, { 0x3612, 0x00 }, { 0x3611, 0x67 },
+ { 0x3633, 0xca }, { 0x3602, 0xaf }, { 0x3603, 0x04 }, { 0x3630, 0x28 },
+ { 0x3631, 0x16 }, { 0x3714, 0x10 }, { 0x371d, 0x01 }, { 0x4300, 0x3a },
+ { 0x3007, 0x01 }, { 0x3024, 0x03 }, { 0x3020, 0x0a }, { 0x3702, 0x0d },
+ { 0x3703, 0x20 }, { 0x3704, 0x15 }, { 0x3709, 0xa8 }, { 0x370c, 0xc7 },
+ { 0x370d, 0x80 }, { 0x3712, 0x00 }, { 0x3713, 0x20 }, { 0x3715, 0x04 },
+ { 0x381d, 0x40 }, { 0x381c, 0x00 }, { 0x3822, 0x50 }, { 0x3824, 0x10 },
+ { 0x3815, 0x8c }, { 0x3804, 0x05 }, { 0x3805, 0x1f }, { 0x3800, 0x00 },
+ { 0x3801, 0x00 }, { 0x3806, 0x03 }, { 0x3807, 0x28 }, { 0x3802, 0x00 },
+ { 0x3803, 0x07 }, { 0x3808, 0x05 }, { 0x3809, 0x00 }, { 0x380a, 0x03 },
+ { 0x380b, 0x20 }, { 0x380c, OV10635_HTS >> 8 },
+ { 0x380d, OV10635_HTS & 0xff }, { 0x380e, OV10635_VTS >> 8 },
+ { 0x380f, OV10635_VTS & 0xff }, { 0x3813, 0x02 }, { 0x3811, 0x08 },
+ { 0x381f, 0x0c }, { 0x3819, 0x04 }, { 0x3804, 0x01 }, { 0x3805, 0x00 },
+ { 0x3828, 0x03 }, { 0x3829, 0x10 }, { 0x382a, 0x10 }, { 0x3621, 0x63 },
+ { 0x5005, 0x08 }, { 0x56d5, 0x00 }, { 0x56d6, 0x80 }, { 0x56d7, 0x00 },
+ { 0x56d8, 0x00 }, { 0x56d9, 0x00 }, { 0x56da, 0x80 }, { 0x56db, 0x00 },
+ { 0x56dc, 0x00 }, { 0x56e8, 0x00 }, { 0x56e9, 0x7f }, { 0x56ea, 0x00 },
+ { 0x56eb, 0x7f }, { 0x5100, 0x00 }, { 0x5101, 0x80 }, { 0x5102, 0x00 },
+ { 0x5103, 0x80 }, { 0x5104, 0x00 }, { 0x5105, 0x80 }, { 0x5106, 0x00 },
+ { 0x5107, 0x80 }, { 0x5108, 0x00 }, { 0x5109, 0x00 }, { 0x510a, 0x00 },
+ { 0x510b, 0x00 }, { 0x510c, 0x00 }, { 0x510d, 0x00 }, { 0x510e, 0x00 },
+ { 0x510f, 0x00 }, { 0x5110, 0x00 }, { 0x5111, 0x80 }, { 0x5112, 0x00 },
+ { 0x5113, 0x80 }, { 0x5114, 0x00 }, { 0x5115, 0x80 }, { 0x5116, 0x00 },
+ { 0x5117, 0x80 }, { 0x5118, 0x00 }, { 0x5119, 0x00 }, { 0x511a, 0x00 },
+ { 0x511b, 0x00 }, { 0x511c, 0x00 }, { 0x511d, 0x00 }, { 0x511e, 0x00 },
+ { 0x511f, 0x00 }, { 0x56d0, 0x00 }, { 0x5006, 0x04 }, { 0x5608, 0x05 },
+ { 0x52d7, 0x06 }, { 0x528d, 0x08 }, { 0x5293, 0x12 }, { 0x52d3, 0x12 },
+ { 0x5288, 0x06 }, { 0x5289, 0x20 }, { 0x52c8, 0x06 }, { 0x52c9, 0x20 },
+ { 0x52cd, 0x04 }, { 0x5381, 0x00 }, { 0x5382, 0xff }, { 0x5589, 0x76 },
+ { 0x558a, 0x47 }, { 0x558b, 0xef }, { 0x558c, 0xc9 }, { 0x558d, 0x49 },
+ { 0x558e, 0x30 }, { 0x558f, 0x67 }, { 0x5590, 0x3f }, { 0x5591, 0xf0 },
+ { 0x5592, 0x10 }, { 0x55a2, 0x6d }, { 0x55a3, 0x55 }, { 0x55a4, 0xc3 },
+ { 0x55a5, 0xb5 }, { 0x55a6, 0x43 }, { 0x55a7, 0x38 }, { 0x55a8, 0x5f },
+ { 0x55a9, 0x4b }, { 0x55aa, 0xf0 }, { 0x55ab, 0x10 }, { 0x5581, 0x52 },
+ { 0x5300, 0x01 }, { 0x5301, 0x00 }, { 0x5302, 0x00 }, { 0x5303, 0x0e },
+ { 0x5304, 0x00 }, { 0x5305, 0x0e }, { 0x5306, 0x00 }, { 0x5307, 0x36 },
+ { 0x5308, 0x00 }, { 0x5309, 0xd9 }, { 0x530a, 0x00 }, { 0x530b, 0x0f },
+ { 0x530c, 0x00 }, { 0x530d, 0x2c }, { 0x530e, 0x00 }, { 0x530f, 0x59 },
+ { 0x5310, 0x00 }, { 0x5311, 0x7b }, { 0x5312, 0x00 }, { 0x5313, 0x22 },
+ { 0x5314, 0x00 }, { 0x5315, 0xd5 }, { 0x5316, 0x00 }, { 0x5317, 0x13 },
+ { 0x5318, 0x00 }, { 0x5319, 0x18 }, { 0x531a, 0x00 }, { 0x531b, 0x26 },
+ { 0x531c, 0x00 }, { 0x531d, 0xdc }, { 0x531e, 0x00 }, { 0x531f, 0x02 },
+ { 0x5320, 0x00 }, { 0x5321, 0x24 }, { 0x5322, 0x00 }, { 0x5323, 0x56 },
+ { 0x5324, 0x00 }, { 0x5325, 0x85 }, { 0x5326, 0x00 }, { 0x5327, 0x20 },
+ { 0x5609, 0x01 }, { 0x560a, 0x40 }, { 0x560b, 0x01 }, { 0x560c, 0x40 },
+ { 0x560d, 0x00 }, { 0x560e, 0xfa }, { 0x560f, 0x00 }, { 0x5610, 0xfa },
+ { 0x5611, 0x02 }, { 0x5612, 0x80 }, { 0x5613, 0x02 }, { 0x5614, 0x80 },
+ { 0x5615, 0x01 }, { 0x5616, 0x2c }, { 0x5617, 0x01 }, { 0x5618, 0x2c },
+ { 0x563b, 0x01 }, { 0x563c, 0x01 }, { 0x563d, 0x01 }, { 0x563e, 0x01 },
+ { 0x563f, 0x03 }, { 0x5640, 0x03 }, { 0x5641, 0x03 }, { 0x5642, 0x05 },
+ { 0x5643, 0x09 }, { 0x5644, 0x05 }, { 0x5645, 0x05 }, { 0x5646, 0x05 },
+ { 0x5647, 0x05 }, { 0x5651, 0x00 }, { 0x5652, 0x80 }, { 0x521a, 0x01 },
+ { 0x521b, 0x03 }, { 0x521c, 0x06 }, { 0x521d, 0x0a }, { 0x521e, 0x0e },
+ { 0x521f, 0x12 }, { 0x5220, 0x16 }, { 0x5223, 0x02 }, { 0x5225, 0x04 },
+ { 0x5227, 0x08 }, { 0x5229, 0x0c }, { 0x522b, 0x12 }, { 0x522d, 0x18 },
+ { 0x522f, 0x1e }, { 0x5241, 0x04 }, { 0x5242, 0x01 }, { 0x5243, 0x03 },
+ { 0x5244, 0x06 }, { 0x5245, 0x0a }, { 0x5246, 0x0e }, { 0x5247, 0x12 },
+ { 0x5248, 0x16 }, { 0x524a, 0x03 }, { 0x524c, 0x04 }, { 0x524e, 0x08 },
+ { 0x5250, 0x0c }, { 0x5252, 0x12 }, { 0x5254, 0x18 }, { 0x5256, 0x1e },
+ /* fifo_line_length = 2*hts */
+ { 0x4606, (2 * OV10635_HTS) >> 8 }, { 0x4607, (2 * OV10635_HTS) & 0xff },
+ /* fifo_hsync_start = 2*(hts - xres) */
+ { 0x460a, (2 * (OV10635_HTS - OV10635_WIDTH)) >> 8 },
+ { 0x460b, (2 * (OV10635_HTS - OV10635_WIDTH)) & 0xff },
+ { 0x460c, 0x00 }, { 0x4620, 0x0e },
+ /* BT601: 0x08 is also acceptable as HS/VS mode */
+ { 0x4700, 0x04 }, { 0x4701, 0x00 }, { 0x4702, 0x01 }, { 0x4004, 0x04 },
+ { 0x4005, 0x18 }, { 0x4001, 0x06 }, { 0x4050, 0x22 }, { 0x4051, 0x24 },
+ { 0x4052, 0x02 }, { 0x4057, 0x9c }, { 0x405a, 0x00 }, { 0x4202, 0x02 },
+ { 0x3023, 0x10 }, { 0x0100, 0x01 }, { 0x0100, 0x01 }, { 0x6f10, 0x07 },
+ { 0x6f11, 0x82 }, { 0x6f12, 0x04 }, { 0x6f13, 0x00 }, { 0xd000, 0x19 },
+ { 0xd001, 0xa0 }, { 0xd002, 0x00 }, { 0xd003, 0x01 }, { 0xd004, 0xa9 },
+ { 0xd005, 0xad }, { 0xd006, 0x10 }, { 0xd007, 0x40 }, { 0xd008, 0x44 },
+ { 0xd009, 0x00 }, { 0xd00a, 0x68 }, { 0xd00b, 0x00 }, { 0xd00c, 0x15 },
+ { 0xd00d, 0x00 }, { 0xd00e, 0x00 }, { 0xd00f, 0x00 }, { 0xd040, 0x9c },
+ { 0xd041, 0x21 }, { 0xd042, 0xff }, { 0xd043, 0xf8 }, { 0xd044, 0xd4 },
+ { 0xd045, 0x01 }, { 0xd046, 0x48 }, { 0xd047, 0x00 }, { 0xd048, 0xd4 },
+ { 0xd049, 0x01 }, { 0xd04a, 0x50 }, { 0xd04b, 0x04 }, { 0xd04c, 0x18 },
+ { 0xd04d, 0x60 }, { 0xd04e, 0x00 }, { 0xd04f, 0x01 }, { 0xd050, 0xa8 },
+ { 0xd051, 0x63 }, { 0xd052, 0x02 }, { 0xd053, 0xa4 }, { 0xd054, 0x85 },
+ { 0xd055, 0x43 }, { 0xd056, 0x00 }, { 0xd057, 0x00 }, { 0xd058, 0x18 },
+ { 0xd059, 0x60 }, { 0xd05a, 0x00 }, { 0xd05b, 0x01 }, { 0xd05c, 0xa8 },
+ { 0xd05d, 0x63 }, { 0xd05e, 0x03 }, { 0xd05f, 0xf0 }, { 0xd060, 0x98 },
+ { 0xd061, 0xa3 }, { 0xd062, 0x00 }, { 0xd063, 0x00 }, { 0xd064, 0x8c },
+ { 0xd065, 0x6a }, { 0xd066, 0x00 }, { 0xd067, 0x6e }, { 0xd068, 0xe5 },
+ { 0xd069, 0x85 }, { 0xd06a, 0x18 }, { 0xd06b, 0x00 }, { 0xd06c, 0x10 },
+ { 0xd06d, 0x00 }, { 0xd06e, 0x00 }, { 0xd06f, 0x10 }, { 0xd070, 0x9c },
+ { 0xd071, 0x80 }, { 0xd072, 0x00 }, { 0xd073, 0x03 }, { 0xd074, 0x18 },
+ { 0xd075, 0x60 }, { 0xd076, 0x00 }, { 0xd077, 0x01 }, { 0xd078, 0xa8 },
+ { 0xd079, 0x63 }, { 0xd07a, 0x07 }, { 0xd07b, 0x80 }, { 0xd07c, 0x07 },
+ { 0xd07d, 0xff }, { 0xd07e, 0xf9 }, { 0xd07f, 0x03 }, { 0xd080, 0x8c },
+ { 0xd081, 0x63 }, { 0xd082, 0x00 }, { 0xd083, 0x00 }, { 0xd084, 0xa5 },
+ { 0xd085, 0x6b }, { 0xd086, 0x00 }, { 0xd087, 0xff }, { 0xd088, 0x18 },
+ { 0xd089, 0x80 }, { 0xd08a, 0x00 }, { 0xd08b, 0x01 }, { 0xd08c, 0xa8 },
+ { 0xd08d, 0x84 }, { 0xd08e, 0x01 }, { 0xd08f, 0x04 }, { 0xd090, 0xe1 },
+ { 0xd091, 0x6b }, { 0xd092, 0x58 }, { 0xd093, 0x00 }, { 0xd094, 0x94 },
+ { 0xd095, 0x6a }, { 0xd096, 0x00 }, { 0xd097, 0x70 }, { 0xd098, 0xe1 },
+ { 0xd099, 0x6b }, { 0xd09a, 0x20 }, { 0xd09b, 0x00 }, { 0xd09c, 0x95 },
+ { 0xd09d, 0x6b }, { 0xd09e, 0x00 }, { 0xd09f, 0x00 }, { 0xd0a0, 0xe4 },
+ { 0xd0a1, 0x8b }, { 0xd0a2, 0x18 }, { 0xd0a3, 0x00 }, { 0xd0a4, 0x0c },
+ { 0xd0a5, 0x00 }, { 0xd0a6, 0x00 }, { 0xd0a7, 0x23 }, { 0xd0a8, 0x15 },
+ { 0xd0a9, 0x00 }, { 0xd0aa, 0x00 }, { 0xd0ab, 0x00 }, { 0xd0ac, 0x18 },
+ { 0xd0ad, 0x60 }, { 0xd0ae, 0x80 }, { 0xd0af, 0x06 }, { 0xd0b0, 0xa8 },
+ { 0xd0b1, 0x83 }, { 0xd0b2, 0x40 }, { 0xd0b3, 0x08 }, { 0xd0b4, 0xa8 },
+ { 0xd0b5, 0xe3 }, { 0xd0b6, 0x38 }, { 0xd0b7, 0x2a }, { 0xd0b8, 0xa8 },
+ { 0xd0b9, 0xc3 }, { 0xd0ba, 0x40 }, { 0xd0bb, 0x09 }, { 0xd0bc, 0xa8 },
+ { 0xd0bd, 0xa3 }, { 0xd0be, 0x38 }, { 0xd0bf, 0x29 }, { 0xd0c0, 0x8c },
+ { 0xd0c1, 0x65 }, { 0xd0c2, 0x00 }, { 0xd0c3, 0x00 }, { 0xd0c4, 0xd8 },
+ { 0xd0c5, 0x04 }, { 0xd0c6, 0x18 }, { 0xd0c7, 0x00 }, { 0xd0c8, 0x8c },
+ { 0xd0c9, 0x67 }, { 0xd0ca, 0x00 }, { 0xd0cb, 0x00 }, { 0xd0cc, 0xd8 },
+ { 0xd0cd, 0x06 }, { 0xd0ce, 0x18 }, { 0xd0cf, 0x00 }, { 0xd0d0, 0x18 },
+ { 0xd0d1, 0x60 }, { 0xd0d2, 0x80 }, { 0xd0d3, 0x06 }, { 0xd0d4, 0xa8 },
+ { 0xd0d5, 0xe3 }, { 0xd0d6, 0x67 }, { 0xd0d7, 0x02 }, { 0xd0d8, 0xa9 },
+ { 0xd0d9, 0x03 }, { 0xd0da, 0x67 }, { 0xd0db, 0x03 }, { 0xd0dc, 0xa8 },
+ { 0xd0dd, 0xc3 }, { 0xd0de, 0x3d }, { 0xd0df, 0x05 }, { 0xd0e0, 0x8c },
+ { 0xd0e1, 0x66 }, { 0xd0e2, 0x00 }, { 0xd0e3, 0x00 }, { 0xd0e4, 0xb8 },
+ { 0xd0e5, 0x63 }, { 0xd0e6, 0x00 }, { 0xd0e7, 0x18 }, { 0xd0e8, 0xb8 },
+ { 0xd0e9, 0x63 }, { 0xd0ea, 0x00 }, { 0xd0eb, 0x98 }, { 0xd0ec, 0xbc },
+ { 0xd0ed, 0x03 }, { 0xd0ee, 0x00 }, { 0xd0ef, 0x00 }, { 0xd0f0, 0x10 },
+ { 0xd0f1, 0x00 }, { 0xd0f2, 0x00 }, { 0xd0f3, 0x16 }, { 0xd0f4, 0xb8 },
+ { 0xd0f5, 0x83 }, { 0xd0f6, 0x00 }, { 0xd0f7, 0x19 }, { 0xd0f8, 0x8c },
+ { 0xd0f9, 0x67 }, { 0xd0fa, 0x00 }, { 0xd0fb, 0x00 }, { 0xd0fc, 0xb8 },
+ { 0xd0fd, 0xa4 }, { 0xd0fe, 0x00 }, { 0xd0ff, 0x98 }, { 0xd100, 0xb8 },
+ { 0xd101, 0x83 }, { 0xd102, 0x00 }, { 0xd103, 0x08 }, { 0xd104, 0x8c },
+ { 0xd105, 0x68 }, { 0xd106, 0x00 }, { 0xd107, 0x00 }, { 0xd108, 0xe0 },
+ { 0xd109, 0x63 }, { 0xd10a, 0x20 }, { 0xd10b, 0x04 }, { 0xd10c, 0xe0 },
+ { 0xd10d, 0x65 }, { 0xd10e, 0x18 }, { 0xd10f, 0x00 }, { 0xd110, 0xa4 },
+ { 0xd111, 0x83 }, { 0xd112, 0xff }, { 0xd113, 0xff }, { 0xd114, 0xb8 },
+ { 0xd115, 0x64 }, { 0xd116, 0x00 }, { 0xd117, 0x48 }, { 0xd118, 0xd8 },
+ { 0xd119, 0x07 }, { 0xd11a, 0x18 }, { 0xd11b, 0x00 }, { 0xd11c, 0xd8 },
+ { 0xd11d, 0x08 }, { 0xd11e, 0x20 }, { 0xd11f, 0x00 }, { 0xd120, 0x9c },
+ { 0xd121, 0x60 }, { 0xd122, 0x00 }, { 0xd123, 0x00 }, { 0xd124, 0xd8 },
+ { 0xd125, 0x06 }, { 0xd126, 0x18 }, { 0xd127, 0x00 }, { 0xd128, 0x00 },
+ { 0xd129, 0x00 }, { 0xd12a, 0x00 }, { 0xd12b, 0x08 }, { 0xd12c, 0x15 },
+ { 0xd12d, 0x00 }, { 0xd12e, 0x00 }, { 0xd12f, 0x00 }, { 0xd130, 0x8c },
+ { 0xd131, 0x6a }, { 0xd132, 0x00 }, { 0xd133, 0x76 }, { 0xd134, 0xbc },
+ { 0xd135, 0x23 }, { 0xd136, 0x00 }, { 0xd137, 0x00 }, { 0xd138, 0x13 },
+ { 0xd139, 0xff }, { 0xd13a, 0xff }, { 0xd13b, 0xe6 }, { 0xd13c, 0x18 },
+ { 0xd13d, 0x60 }, { 0xd13e, 0x80 }, { 0xd13f, 0x06 }, { 0xd140, 0x03 },
+ { 0xd141, 0xff }, { 0xd142, 0xff }, { 0xd143, 0xdd }, { 0xd144, 0xa8 },
+ { 0xd145, 0x83 }, { 0xd146, 0x40 }, { 0xd147, 0x08 }, { 0xd148, 0x85 },
+ { 0xd149, 0x21 }, { 0xd14a, 0x00 }, { 0xd14b, 0x00 }, { 0xd14c, 0x85 },
+ { 0xd14d, 0x41 }, { 0xd14e, 0x00 }, { 0xd14f, 0x04 }, { 0xd150, 0x44 },
+ { 0xd151, 0x00 }, { 0xd152, 0x48 }, { 0xd153, 0x00 }, { 0xd154, 0x9c },
+ { 0xd155, 0x21 }, { 0xd156, 0x00 }, { 0xd157, 0x08 }, { 0x6f0e, 0x03 },
+ { 0x6f0f, 0x00 }, { 0x460e, 0x08 }, { 0x460f, 0x01 }, { 0x4610, 0x00 },
+ { 0x4611, 0x01 }, { 0x4612, 0x00 }, { 0x4613, 0x01 },
+ /* 8 bits */
+ { 0x4605, 0x08 },
+ /* Swap data bits order [9:0] -> [0:9] */
+ { 0x4709, 0x10 }, { 0x4608, 0x00 }, { 0x4609, 0x08 }, { 0x6804, 0x00 },
+ { 0x6805, 0x06 }, { 0x6806, 0x00 }, { 0x5120, 0x00 }, { 0x3510, 0x00 },
+ { 0x3504, 0x00 }, { 0x6800, 0x00 }, { 0x6f0d, 0x01 },
+ /* PCLK falling edge */
+ { 0x4708, 0x01 }, { 0x5000, 0xff }, { 0x5001, 0xbf }, { 0x5002, 0x7e },
+ { 0x503d, 0x00 }, { 0xc450, 0x01 }, { 0xc452, 0x04 }, { 0xc453, 0x00 },
+ { 0xc454, 0x00 }, { 0xc455, 0x01 }, { 0xc456, 0x01 }, { 0xc457, 0x00 },
+ { 0xc458, 0x00 }, { 0xc459, 0x00 }, { 0xc45b, 0x00 }, { 0xc45c, 0x01 },
+ { 0xc45d, 0x00 }, { 0xc45e, 0x00 }, { 0xc45f, 0x00 }, { 0xc460, 0x00 },
+ { 0xc461, 0x01 }, { 0xc462, 0x01 }, { 0xc464, 0x03 }, { 0xc465, 0x00 },
+ { 0xc466, 0x8a }, { 0xc467, 0x00 }, { 0xc468, 0x86 }, { 0xc469, 0x00 },
+ { 0xc46a, 0x40 }, { 0xc46b, 0x50 }, { 0xc46c, 0x30 }, { 0xc46d, 0x28 },
+ { 0xc46e, 0x60 }, { 0xc46f, 0x40 }, { 0xc47c, 0x01 }, { 0xc47d, 0x38 },
+ { 0xc47e, 0x00 }, { 0xc47f, 0x00 }, { 0xc480, 0x00 }, { 0xc481, 0xff },
+ { 0xc482, 0x00 }, { 0xc483, 0x40 }, { 0xc484, 0x00 }, { 0xc485, 0x18 },
+ { 0xc486, 0x00 }, { 0xc487, 0x18 },
+ { 0xc488, (OV10635_VTS - 8) * 16 >> 8},
+ { 0xc489, (OV10635_VTS - 8) * 16 & 0xff},
+ { 0xc48a, (OV10635_VTS - 8) * 16 >> 8},
+ { 0xc48b, (OV10635_VTS - 8) * 16 & 0xff}, { 0xc48c, 0x00 },
+ { 0xc48d, 0x04 }, { 0xc48e, 0x00 }, { 0xc48f, 0x04 }, { 0xc490, 0x03 },
+ { 0xc492, 0x20 }, { 0xc493, 0x08 }, { 0xc498, 0x02 }, { 0xc499, 0x00 },
+ { 0xc49a, 0x02 }, { 0xc49b, 0x00 }, { 0xc49c, 0x02 }, { 0xc49d, 0x00 },
+ { 0xc49e, 0x02 }, { 0xc49f, 0x60 }, { 0xc4a0, 0x03 }, { 0xc4a1, 0x00 },
+ { 0xc4a2, 0x04 }, { 0xc4a3, 0x00 }, { 0xc4a4, 0x00 }, { 0xc4a5, 0x10 },
+ { 0xc4a6, 0x00 }, { 0xc4a7, 0x40 }, { 0xc4a8, 0x00 }, { 0xc4a9, 0x80 },
+ { 0xc4aa, 0x0d }, { 0xc4ab, 0x00 }, { 0xc4ac, 0x0f }, { 0xc4ad, 0xc0 },
+ { 0xc4b4, 0x01 }, { 0xc4b5, 0x01 }, { 0xc4b6, 0x00 }, { 0xc4b7, 0x01 },
+ { 0xc4b8, 0x00 }, { 0xc4b9, 0x01 }, { 0xc4ba, 0x01 }, { 0xc4bb, 0x00 },
+ { 0xc4bc, 0x01 }, { 0xc4bd, 0x60 }, { 0xc4be, 0x02 }, { 0xc4bf, 0x33 },
+ { 0xc4c8, 0x03 }, { 0xc4c9, 0xd0 }, { 0xc4ca, 0x0e }, { 0xc4cb, 0x00 },
+ { 0xc4cc, 0x0e }, { 0xc4cd, 0x51 }, { 0xc4ce, 0x0e }, { 0xc4cf, 0x51 },
+ { 0xc4d0, 0x04 }, { 0xc4d1, 0x80 }, { 0xc4e0, 0x04 }, { 0xc4e1, 0x02 },
+ { 0xc4e2, 0x01 }, { 0xc4e4, 0x10 }, { 0xc4e5, 0x20 }, { 0xc4e6, 0x30 },
+ { 0xc4e7, 0x40 }, { 0xc4e8, 0x50 }, { 0xc4e9, 0x60 }, { 0xc4ea, 0x70 },
+ { 0xc4eb, 0x80 }, { 0xc4ec, 0x90 }, { 0xc4ed, 0xa0 }, { 0xc4ee, 0xb0 },
+ { 0xc4ef, 0xc0 }, { 0xc4f0, 0xd0 }, { 0xc4f1, 0xe0 }, { 0xc4f2, 0xf0 },
+ { 0xc4f3, 0x80 }, { 0xc4f4, 0x00 }, { 0xc4f5, 0x20 }, { 0xc4f6, 0x02 },
+ { 0xc4f7, 0x00 }, { 0xc4f8, 0x00 }, { 0xc4f9, 0x00 }, { 0xc4fa, 0x00 },
+ { 0xc4fb, 0x01 }, { 0xc4fc, 0x01 }, { 0xc4fd, 0x00 }, { 0xc4fe, 0x04 },
+ { 0xc4ff, 0x02 }, { 0xc500, 0x48 }, { 0xc501, 0x74 }, { 0xc502, 0x58 },
+ { 0xc503, 0x80 }, { 0xc504, 0x05 }, { 0xc505, 0x80 }, { 0xc506, 0x03 },
+ { 0xc507, 0x80 }, { 0xc508, 0x01 }, { 0xc509, 0xc0 }, { 0xc50a, 0x01 },
+ { 0xc50b, 0xa0 }, { 0xc50c, 0x01 }, { 0xc50d, 0x2c }, { 0xc50e, 0x01 },
+ { 0xc50f, 0x0a }, { 0xc510, 0x00 }, { 0xc511, 0x00 }, { 0xc512, 0xe5 },
+ { 0xc513, 0x14 }, { 0xc514, 0x04 }, { 0xc515, 0x00 }, { 0xc518, OV10635_VTS >> 8},
+ { 0xc519, OV10635_VTS & 0xff}, { 0xc51a, OV10635_HTS >> 8},
+ { 0xc51b, OV10635_HTS & 0xff}, { 0xc2e0, 0x00 }, { 0xc2e1, 0x51 },
+ { 0xc2e2, 0x00 }, { 0xc2e3, 0xd6 }, { 0xc2e4, 0x01 }, { 0xc2e5, 0x5e },
+ { 0xc2e9, 0x01 }, { 0xc2ea, 0x7a }, { 0xc2eb, 0x90 }, { 0xc2ed, 0x00 },
+ { 0xc2ee, 0x7a }, { 0xc2ef, 0x64 }, { 0xc308, 0x00 }, { 0xc309, 0x00 },
+ { 0xc30a, 0x00 }, { 0xc30c, 0x00 }, { 0xc30d, 0x01 }, { 0xc30e, 0x00 },
+ { 0xc30f, 0x00 }, { 0xc310, 0x01 }, { 0xc311, 0x60 }, { 0xc312, 0xff },
+ { 0xc313, 0x08 }, { 0xc314, 0x01 }, { 0xc315, 0x00 }, { 0xc316, 0xff },
+ { 0xc317, 0x0b }, { 0xc318, 0x00 }, { 0xc319, 0x0c }, { 0xc31a, 0x00 },
+ { 0xc31b, 0xe0 }, { 0xc31c, 0x00 }, { 0xc31d, 0x14 }, { 0xc31e, 0x00 },
+ { 0xc31f, 0xc5 }, { 0xc320, 0xff }, { 0xc321, 0x4b }, { 0xc322, 0xff },
+ { 0xc323, 0xf0 }, { 0xc324, 0xff }, { 0xc325, 0xe8 }, { 0xc326, 0x00 },
+ { 0xc327, 0x46 }, { 0xc328, 0xff }, { 0xc329, 0xd2 }, { 0xc32a, 0xff },
+ { 0xc32b, 0xe4 }, { 0xc32c, 0xff }, { 0xc32d, 0xbb }, { 0xc32e, 0x00 },
+ { 0xc32f, 0x61 }, { 0xc330, 0xff }, { 0xc331, 0xf9 }, { 0xc332, 0x00 },
+ { 0xc333, 0xd9 }, { 0xc334, 0x00 }, { 0xc335, 0x2e }, { 0xc336, 0x00 },
+ { 0xc337, 0xb1 }, { 0xc338, 0xff }, { 0xc339, 0x64 }, { 0xc33a, 0xff },
+ { 0xc33b, 0xeb }, { 0xc33c, 0xff }, { 0xc33d, 0xe8 }, { 0xc33e, 0x00 },
+ { 0xc33f, 0x48 }, { 0xc340, 0xff }, { 0xc341, 0xd0 }, { 0xc342, 0xff },
+ { 0xc343, 0xed }, { 0xc344, 0xff }, { 0xc345, 0xad }, { 0xc346, 0x00 },
+ { 0xc347, 0x66 }, { 0xc348, 0x01 }, { 0xc349, 0x00 }, { 0x6700, 0x04 },
+ { 0x6701, 0x7b }, { 0x6702, 0xfd }, { 0x6703, 0xf9 }, { 0x6704, 0x3d },
+ { 0x6705, 0x71 }, { 0x6706, 0x78 }, { 0x6708, 0x05 }, { 0x6f06, 0x6f },
+ { 0x6f07, 0x00 }, { 0x6f0a, 0x6f }, { 0x6f0b, 0x00 }, { 0x6f00, 0x03 },
+ { 0xc34c, 0x01 }, { 0xc34d, 0x00 }, { 0xc34e, 0x46 }, { 0xc34f, 0x55 },
+ { 0xc350, 0x00 }, { 0xc351, 0x40 }, { 0xc352, 0x00 }, { 0xc353, 0xff },
+ { 0xc354, 0x04 }, { 0xc355, 0x08 }, { 0xc356, 0x01 }, { 0xc357, 0xef },
+ { 0xc358, 0x30 }, { 0xc359, 0x01 }, { 0xc35a, 0x64 }, { 0xc35b, 0x46 },
+ { 0xc35c, 0x00 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 },
+ { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 },
+ { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 },
+ { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 },
+ { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 },
+ { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 },
+ { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0x3042, 0xf0 }, { 0xc261, 0x01 },
+ { 0x301b, 0xf0 }, { 0x301c, 0xf0 }, { 0x301a, 0xf0 }, { 0x6f00, 0xc3 },
+ { 0xc46a, 0x30 }, { 0xc46d, 0x20 }, { 0xc464, 0x84 }, { 0xc465, 0x00 },
+ { 0x6f00, 0x03 }, { 0x6f00, 0x43 }, { 0x381c, 0x00 }, { 0x381d, 0x40 },
+ { 0xc454, 0x01 }, { 0x6f00, 0xc3 }, { 0xc454, 0x00 }, { 0xc4b1, 0x02 },
+ { 0xc4b2, 0x01 }, { 0xc4b3, 0x03 }, { 0x6f00, 0x03 }, { 0x6f00, 0x43 },
+ /* enable FSIN (FRAMESYNC input) functionality */
+ { 0x3832, (0x0d + 2 * 0x20 + 0x15 + 38) >> 8 },
+ { 0x3833, (0x0d + 2 * 0x20 + 0x15 + 38) & 0xff },
+ { 0x3834, OV10635_VTS >> 8 }, { 0x3835, OV10635_VTS & 0xff },
+ { 0x302e, 0x01 },
+};
+
+struct rdacm20_device {
+ struct device *dev;
+ struct max9271_device *serializer;
+ struct i2c_client *sensor;
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct v4l2_ctrl_handler ctrls;
+ u32 addrs[2];
+};
+
+static inline struct rdacm20_device *sd_to_rdacm20(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct rdacm20_device, sd);
+}
+
+static inline struct rdacm20_device *i2c_to_rdacm20(struct i2c_client *client)
+{
+ return sd_to_rdacm20(i2c_get_clientdata(client));
+}
+
+static int ov10635_read16(struct rdacm20_device *dev, u16 reg)
+{
+ u8 buf[2] = { reg >> 8, reg & 0xff };
+ int ret;
+
+ ret = i2c_master_send(dev->sensor, buf, 2);
+ if (ret != 2) {
+ dev_dbg(dev->dev, "%s: register 0x%04x write failed (%d)\n",
+ __func__, reg, ret);
+ return ret;
+ }
+
+ ret = i2c_master_recv(dev->sensor, buf, 2);
+ if (ret < 0) {
+ dev_dbg(dev->dev, "%s: register 0x%04x read failed (%d)\n",
+ __func__, reg, ret);
+ return ret;
+ }
+
+ return (buf[0] << 8) | buf[1];
+}
+
+static int __ov10635_write(struct rdacm20_device *dev, u16 reg, u8 val)
+{
+ u8 buf[3] = { reg >> 8, reg & 0xff, val };
+ int ret;
+
+ dev_dbg(dev->dev, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
+
+ ret = i2c_master_send(dev->sensor, buf, 3);
+ return ret < 0 ? ret : 0;
+}
+
+static int ov10635_write(struct rdacm20_device *dev, u16 reg, u8 val)
+{
+ int ret;
+
+ ret = __ov10635_write(dev, reg, val);
+ if (ret < 0)
+ dev_err(dev->dev, "%s: register 0x%04x write failed (%d)\n",
+ __func__, reg, ret);
+
+ return ret;
+}
+
+static int ov10635_set_regs(struct rdacm20_device *dev,
+ const struct ov10635_reg *regs,
+ unsigned int nr_regs)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < nr_regs; i++) {
+ ret = __ov10635_write(dev, regs[i].reg, regs[i].val);
+ if (ret) {
+ dev_err(dev->dev,
+ "%s: register %u (0x%04x) write failed (%d)\n",
+ __func__, i, regs[i].reg, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct rdacm20_device *dev = sd_to_rdacm20(sd);
+
+ return max9271_set_serial_link(dev->serializer, enable);
+}
+
+static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad || code->index > 0)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
+
+ return 0;
+}
+
+static int rdacm20_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
+{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
+
+ mf->width = OV10635_WIDTH;
+ mf->height = OV10635_HEIGHT;
+ mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->colorspace = V4L2_COLORSPACE_RAW;
+ mf->field = V4L2_FIELD_NONE;
+ mf->ycbcr_enc = V4L2_YCBCR_ENC_601;
+ mf->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ mf->xfer_func = V4L2_XFER_FUNC_NONE;
+
+ return 0;
+}
+
+static struct v4l2_subdev_video_ops rdacm20_video_ops = {
+ .s_stream = rdacm20_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops rdacm20_subdev_pad_ops = {
+ .enum_mbus_code = rdacm20_enum_mbus_code,
+ .get_fmt = rdacm20_get_fmt,
+ .set_fmt = rdacm20_get_fmt,
+};
+
+static struct v4l2_subdev_ops rdacm20_subdev_ops = {
+ .video = &rdacm20_video_ops,
+ .pad = &rdacm20_subdev_pad_ops,
+};
+
+static int rdacm20_initialize(struct rdacm20_device *dev)
+{
+ unsigned int retry = 3;
+ int ret;
+
+ /* Verify communication with the MAX9271: ping to wakeup. */
+ dev->serializer->client->addr = MAX9271_DEFAULT_ADDR;
+ i2c_smbus_read_byte(dev->serializer->client);
+
+ /* Serial link disabled during config as it needs a valid pixel clock. */
+ ret = max9271_set_serial_link(dev->serializer, false);
+ if (ret)
+ return ret;
+
+ /*
+ * Ensure that we have a good link configuration before attempting to
+ * identify the device.
+ */
+ max9271_configure_i2c(dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
+ MAX9271_I2CSLVTO_1024US |
+ MAX9271_I2CMSTBT_105KBPS);
+
+ max9271_configure_gmsl_link(dev->serializer);
+
+ ret = max9271_verify_id(dev->serializer);
+ if (ret < 0)
+ return ret;
+
+ ret = max9271_set_address(dev->serializer, dev->addrs[0]);
+ if (ret < 0)
+ return ret;
+ dev->serializer->client->addr = dev->addrs[0];
+
+ /*
+ * Reset the sensor by cycling the OV10635 reset signal connected to the
+ * MAX9271 GPIO1 and verify communication with the OV10635.
+ */
+ max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ mdelay(10);
+ max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ mdelay(10);
+
+again:
+ ret = ov10635_read16(dev, OV10635_PID);
+ if (ret < 0) {
+ if (retry--)
+ goto again;
+
+ dev_err(dev->dev, "OV10635 ID read failed (%d)\n",
+ ret);
+ return -ENXIO;
+ }
+
+ if (ret != OV10635_VERSION) {
+ if (retry--)
+ goto again;
+
+ dev_err(dev->dev, "OV10635 ID mismatch (0x%04x)\n",
+ ret);
+ return -ENXIO;
+ }
+
+ /* Change the sensor I2C address. */
+ ret = ov10635_write(dev, OV10635_SC_CMMN_SCCB_ID,
+ (dev->addrs[1] << 1) |
+ OV10635_SC_CMMN_SCCB_ID_SELECT);
+ if (ret < 0) {
+ dev_err(dev->dev,
+ "OV10635 I2C address change failed (%d)\n", ret);
+ return ret;
+ }
+ dev->sensor->addr = dev->addrs[1];
+ usleep_range(3500, 5000);
+
+ /* Program the 0V10635 initial configuration. */
+ ret = ov10635_set_regs(dev, ov10635_regs_wizard,
+ ARRAY_SIZE(ov10635_regs_wizard));
+ if (ret)
+ return ret;
+
+ dev_info(dev->dev, "Identified MAX9271 + OV10635 device\n");
+
+ return 0;
+}
+
+static int rdacm20_probe(struct i2c_client *client)
+{
+ struct rdacm20_device *dev;
+ struct fwnode_handle *ep;
+ int ret;
+
+ dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+ dev->dev = &client->dev;
+
+ dev->serializer = devm_kzalloc(&client->dev, sizeof(*dev->serializer),
+ GFP_KERNEL);
+ if (!dev->serializer)
+ return -ENOMEM;
+
+ dev->serializer->client = client;
+
+ ret = of_property_read_u32_array(client->dev.of_node, "reg",
+ dev->addrs, 2);
+ if (ret < 0) {
+ dev_err(dev->dev, "Invalid DT reg property: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* Create the dummy I2C client for the sensor. */
+ dev->sensor = i2c_new_dummy_device(client->adapter,
+ OV10635_I2C_ADDRESS);
+ if (IS_ERR(dev->sensor)) {
+ ret = PTR_ERR(dev->sensor);
+ goto error;
+ }
+
+ /* Initialize the hardware. */
+ ret = rdacm20_initialize(dev);
+ if (ret < 0)
+ goto error;
+
+ /* Initialize and register the subdevice. */
+ v4l2_i2c_subdev_init(&dev->sd, client, &rdacm20_subdev_ops);
+ dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ v4l2_ctrl_handler_init(&dev->ctrls, 1);
+ v4l2_ctrl_new_std(&dev->ctrls, NULL, V4L2_CID_PIXEL_RATE,
+ OV10635_PIXEL_RATE, OV10635_PIXEL_RATE, 1,
+ OV10635_PIXEL_RATE);
+ dev->sd.ctrl_handler = &dev->ctrls;
+
+ ret = dev->ctrls.error;
+ if (ret)
+ goto error_free_ctrls;
+
+ dev->pad.flags = MEDIA_PAD_FL_SOURCE;
+ dev->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
+ ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
+ if (ret < 0)
+ goto error_free_ctrls;
+
+ ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
+ if (!ep) {
+ dev_err(&client->dev,
+ "Unable to get endpoint in node %pOF\n",
+ client->dev.of_node);
+ ret = -ENOENT;
+ goto error_free_ctrls;
+ }
+ dev->sd.fwnode = ep;
+
+ ret = v4l2_async_register_subdev(&dev->sd);
+ if (ret)
+ goto error_put_node;
+
+ return 0;
+
+error_put_node:
+ fwnode_handle_put(ep);
+error_free_ctrls:
+ v4l2_ctrl_handler_free(&dev->ctrls);
+error:
+ media_entity_cleanup(&dev->sd.entity);
+ if (dev->sensor)
+ i2c_unregister_device(dev->sensor);
+
+ dev_err(&client->dev, "probe failed\n");
+
+ return ret;
+}
+
+static int rdacm20_remove(struct i2c_client *client)
+{
+ struct rdacm20_device *dev = i2c_to_rdacm20(client);
+
+ fwnode_handle_put(dev->sd.fwnode);
+ v4l2_async_unregister_subdev(&dev->sd);
+ v4l2_ctrl_handler_free(&dev->ctrls);
+ media_entity_cleanup(&dev->sd.entity);
+ i2c_unregister_device(dev->sensor);
+
+ return 0;
+}
+
+static void rdacm20_shutdown(struct i2c_client *client)
+{
+ struct rdacm20_device *dev = i2c_to_rdacm20(client);
+
+ /* make sure stream off during shutdown (reset/reboot) */
+ rdacm20_s_stream(&dev->sd, 0);
+}
+
+static const struct of_device_id rdacm20_of_ids[] = {
+ { .compatible = "imi,rdacm20", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rdacm20_of_ids);
+
+static struct i2c_driver rdacm20_i2c_driver = {
+ .driver = {
+ .name = "rdacm20",
+ .of_match_table = rdacm20_of_ids,
+ },
+ .probe_new = rdacm20_probe,
+ .remove = rdacm20_remove,
+ .shutdown = rdacm20_shutdown,
+};
+
+module_i2c_driver(rdacm20_i2c_driver);
+
+MODULE_DESCRIPTION("GMSL Camera driver for RDACM20");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related
* [PATCH v9 0/4] MAX9286 GMSL Support (+RDACM20)
From: Kieran Bingham @ 2020-05-12 15:51 UTC (permalink / raw)
To: linux-renesas-soc, linux-media, devicetree, linux-kernel,
Mauro Carvalho Chehab
Cc: Kieran Bingham, Laurent Pinchart, Jacopo Mondi,
Niklas Söderlund, sakari.ailus, Hans Verkuil, Hyun Kwon,
Manivannan Sadhasivam, Rob Herring, Kieran Bingham
This series provides a pair of drivers for the GMSL cameras on the R-Car ADAS
platforms.
These drivers originate from Cogent Embedded, and have been refactored to split
the MAX9286 away from the RDACM20 drivers which were once very tightly coupled.
The MAX9286 is capable of capturing up to 4 streams simultaneously, and while
the V4L2-Multiplexed streams series is not available, this works purely on the
assumption that the receiver will correctly map each of the 4 VCs to separate
video nodes, as the RCar-VIN does.
This driver along with a camera driver for the RDACM20 and the
associated platform support for the Renesas R-Car Salvator-X, and the Eagle-V3M
can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/kbingham/rcar.git gmsl/v9
This latest v9 brings in a few minor comments from v8, and has been
successfully tested to capture from all 4 inputs simultaneously.
We're very much hoping that we can aim to get the max9286 into the next
merge-window. Please let us know if there are any issues blocking this.
Jacopo Mondi (2):
dt-bindings: media: i2c: Add bindings for IMI RDACM2x
media: i2c: Add RDACM20 driver
Kieran Bingham (1):
media: i2c: Add MAX9286 driver
Laurent Pinchart (1):
dt-bindings: media: i2c: Add bindings for Maxim Integrated MAX9286
.../bindings/media/i2c/imi,rdacm2x-gmsl.yaml | 159 ++
.../bindings/media/i2c/maxim,max9286.yaml | 287 ++++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
MAINTAINERS | 22 +
drivers/media/i2c/Kconfig | 26 +
drivers/media/i2c/Makefile | 3 +
drivers/media/i2c/max9271.c | 341 +++++
drivers/media/i2c/max9271.h | 224 +++
drivers/media/i2c/max9286.c | 1332 +++++++++++++++++
drivers/media/i2c/rdacm20.c | 667 +++++++++
10 files changed, 3063 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/imi,rdacm2x-gmsl.yaml
create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
create mode 100644 drivers/media/i2c/max9271.c
create mode 100644 drivers/media/i2c/max9271.h
create mode 100644 drivers/media/i2c/max9286.c
create mode 100644 drivers/media/i2c/rdacm20.c
--
2.25.1
^ permalink raw reply
* [PATCH] of/fdt: Remove redundant kbasename function call
From: Qi Zheng @ 2020-05-12 15:49 UTC (permalink / raw)
To: robh+dt, frowand.list; +Cc: devicetree, linux-kernel, Qi Zheng
For version 1 to 3 of the device tree, this is the node full
path as a zero terminated string, starting with "/". The
following equation will not hold, since the node name has
been processed in the fdt_get_name().
*pathp == '/'
For version 16 and later, this is the node unit name only
(or an empty string for the root node). So the above
equation will still not hold.
So the kbasename() is redundant, just remove it.
Signed-off-by: Qi Zheng <arch0.zheng@gmail.com>
---
drivers/of/fdt.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 8a8e07a8f03d..ea31b2ae8474 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -643,8 +643,6 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
offset = fdt_next_node(blob, offset, &depth)) {
pathp = fdt_get_name(blob, offset, NULL);
- if (*pathp == '/')
- pathp = kbasename(pathp);
rc = it(offset, pathp, depth, data);
}
return rc;
--
2.25.1
^ permalink raw reply related
* Re: R: [PATCH v3 08/11] devicetree: bindings: pci: document PARF params bindings
From: Rob Herring @ 2020-05-12 15:45 UTC (permalink / raw)
To: ansuelsmth
Cc: 'Bjorn Andersson', 'Andy Gross',
'Bjorn Helgaas', 'Mark Rutland',
'Stanimir Varbanov', 'Lorenzo Pieralisi',
'Andrew Murray', 'Philipp Zabel', linux-arm-msm,
linux-pci, devicetree, linux-kernel
In-Reply-To: <062301d624a6$8be610d0$a3b23270$@gmail.com>
On Thu, May 07, 2020 at 09:34:35PM +0200, ansuelsmth@gmail.com wrote:
> > On Fri, May 01, 2020 at 12:06:15AM +0200, Ansuel Smith wrote:
> > > It is now supported the editing of Tx De-Emphasis, Tx Swing and
> > > Rx equalization params on ipq8064. Document this new optional params.
> > >
> > > Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
> > > ---
> > > .../devicetree/bindings/pci/qcom,pcie.txt | 36 +++++++++++++++++++
> > > 1 file changed, 36 insertions(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> > b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> > > index 6efcef040741..8cc5aea8a1da 100644
> > > --- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> > > +++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> > > @@ -254,6 +254,42 @@
> > > - "perst-gpios" PCIe endpoint reset signal line
> > > - "wake-gpios" PCIe endpoint wake signal line
> > >
> > > +- qcom,tx-deemph-gen1:
> > > + Usage: optional (available for ipq/apq8064)
> > > + Value type: <u32>
> > > + Definition: Gen1 De-emphasis value.
> > > + For ipq806x should be set to 24.
> >
> > Unless these need to be tuned per board, then the compatible string for
> > ipq806x should imply all these settings.
> >
>
> It was requested by v2 to make this settings tunable. These don't change are
> all the same for every ipq806x SoC. The original implementation had this
> value hardcoded for ipq806x. Should I restore this and drop this patch?
Yes, please.
Rob
^ permalink raw reply
* Re: [PATCH v2 1/2] dt-bindings: remoteproc: qcom: pas: Add SM8250 remoteprocs
From: Rob Herring @ 2020-05-12 15:37 UTC (permalink / raw)
To: Bjorn Andersson
Cc: linux-kernel, Rob Herring, linux-arm-msm, Sibi Sankar,
linux-remoteproc, Ohad Ben-Cohen, devicetree
In-Reply-To: <20200430180051.3795305-1-bjorn.andersson@linaro.org>
On Thu, 30 Apr 2020 11:00:50 -0700, Bjorn Andersson wrote:
> Add the SM8250 audio, compute and sensor remoteprocs to the PAS DT
> binding.
>
> Reviewed-by: Sibi Sankar <sibis@codeaurora.org>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>
> Changes since v1:
> - Changed adsp power-domains to lcx and added missing lmx
>
> .../devicetree/bindings/remoteproc/qcom,adsp.txt | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH 2/6] dt-bindings: serdev: ngsm: Add binding for serdev-ngsm
From: Rob Herring @ 2020-05-12 15:37 UTC (permalink / raw)
To: Tony Lindgren
Cc: Pavel Machek, Peter Hurley, Alan Cox, Jiri Slaby, Merlijn Wajer,
linux-serial, Greg Kroah-Hartman, devicetree, linux-omap,
Lee Jones, Johan Hovold, Sebastian Reichel, linux-kernel
In-Reply-To: <20200430174615.41185-3-tony@atomide.com>
On Thu, 30 Apr 2020 10:46:11 -0700, Tony Lindgren wrote:
> Add a binding document for a generic serdev-ngsm driver that can be
> used to bring up TS 27.010 line discipline with Linux n_gsm support
> on a serial port.
>
> As the Motorola Mapphone modems require some custom handling, they
> are handled with a separate compatible.
>
> Let's also add vendor string for ETSI as we're using a ETSI 3GPP
> TS 27.010 standard.
>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
> .../bindings/serdev/serdev-ngsm.yaml | 64 +++++++++++++++++++
> .../devicetree/bindings/vendor-prefixes.yaml | 2 +
> 2 files changed, 66 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/serdev/serdev-ngsm.yaml
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH 07/11] ASoC: mmp-sspa: Prepare/unprepare the clocks
From: Lubomir Rintel @ 2020-05-12 15:36 UTC (permalink / raw)
To: Mark Brown
Cc: Liam Girdwood, Michael Turquette, Stephen Boyd, Rob Herring,
linux-clk, devicetree, linux-kernel, linux-media
In-Reply-To: <20200512124520.GH5110@sirena.org.uk>
On Tue, May 12, 2020 at 01:45:20PM +0100, Mark Brown wrote:
> On Mon, May 11, 2020 at 11:01:30PM +0200, Lubomir Rintel wrote:
> > The driver enables the clocks without preparing them and disables
> > without unpreparing afterwards. Fix that.
>
> This fix should've been earlier in the series so it could be sent as a
> fix.
I'll order it earlier on v2.
However, there's not much of a point in picking this patch alone,
because the driver is certainly not used anywhere and very likely
doesn't even work to any sensible extent without the rest of the
series.
Lubo
^ permalink raw reply
* Re: [PATCH v2 1/7] regulator: arizona-regulator: Move binding over to dtschema
From: Charles Keepax @ 2020-05-12 15:29 UTC (permalink / raw)
To: cw00.choi, robh+dt, lee.jones, linus.walleij, broonie
Cc: myungjoo.ham, lgirdwood, linux-kernel, devicetree, patches
In-Reply-To: <20200506155758.14643-1-ckeepax@opensource.cirrus.com>
On Wed, May 06, 2020 at 04:57:52PM +0100, Charles Keepax wrote:
> Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> ---
Will update this series to match comments on my Lochnagar series
as well.
Thanks,
Charles
^ permalink raw reply
* [PATCH v3 3/5] pinctrl: lochnagar: Move binding over to dtschema
From: Charles Keepax @ 2020-05-12 15:23 UTC (permalink / raw)
To: robh+dt, lee.jones, broonie, mturquette, sboyd, jdelvare, linux,
linus.walleij
Cc: lgirdwood, linux-kernel, devicetree, patches
In-Reply-To: <20200512152359.11839-1-ckeepax@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
Changes since v2:
- Removed description for gpio-controller
- Force pin node to be called pin-settings
- Simplify -pins pattern
- Add additional blank line
Thanks,
Charles
.../bindings/pinctrl/cirrus,lochnagar.txt | 141 ---------------
.../bindings/pinctrl/cirrus,lochnagar.yaml | 190 +++++++++++++++++++++
2 files changed, 190 insertions(+), 141 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
create mode 100644 Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.yaml
diff --git a/Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
deleted file mode 100644
index a87447180e838..0000000000000
--- a/Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
+++ /dev/null
@@ -1,141 +0,0 @@
-Cirrus Logic Lochnagar Audio Development Board
-
-Lochnagar is an evaluation and development board for Cirrus Logic
-Smart CODEC and Amp devices. It allows the connection of most Cirrus
-Logic devices on mini-cards, as well as allowing connection of
-various application processor systems to provide a full evaluation
-platform. Audio system topology, clocking and power can all be
-controlled through the Lochnagar, allowing the device under test
-to be used in a variety of possible use cases.
-
-This binding document describes the binding for the pinctrl portion
-of the driver.
-
-Also see these documents for generic binding information:
- [1] GPIO : ../gpio/gpio.txt
- [2] Pinctrl: ../pinctrl/pinctrl-bindings.txt
-
-And these for relevant defines:
- [3] include/dt-bindings/pinctrl/lochnagar.h
-
-This binding must be part of the Lochnagar MFD binding:
- [4] ../mfd/cirrus,lochnagar.txt
-
-Required properties:
-
- - compatible : One of the following strings:
- "cirrus,lochnagar-pinctrl"
-
- - gpio-controller : Indicates this device is a GPIO controller.
- - #gpio-cells : Must be 2. The first cell is the pin number, see
- [3] for available pins and the second cell is used to specify
- optional parameters, see [1].
- - gpio-ranges : Range of pins managed by the GPIO controller, see
- [1]. Both the GPIO and Pinctrl base should be set to zero and the
- count to the appropriate of the LOCHNAGARx_PIN_NUM_GPIOS define,
- see [3].
-
- - pinctrl-names : A pinctrl state named "default" must be defined.
- - pinctrl-0 : A phandle to the default pinctrl state.
-
-Required sub-nodes:
-
-The pin configurations are defined as a child of the pinctrl states
-node, see [2]. Each sub-node can have the following properties:
- - groups : A list of groups to select (either this or "pins" must be
- specified), available groups:
- codec-aif1, codec-aif2, codec-aif3, dsp-aif1, dsp-aif2, psia1,
- psia2, gf-aif1, gf-aif2, gf-aif3, gf-aif4, spdif-aif, usb-aif1,
- usb-aif2, adat-aif, soundcard-aif
- - pins : A list of pin names to select (either this or "groups" must
- be specified), available pins:
- fpga-gpio1, fpga-gpio2, fpga-gpio3, fpga-gpio4, fpga-gpio5,
- fpga-gpio6, codec-gpio1, codec-gpio2, codec-gpio3, codec-gpio4,
- codec-gpio5, codec-gpio6, codec-gpio7, codec-gpio8, dsp-gpio1,
- dsp-gpio2, dsp-gpio3, dsp-gpio4, dsp-gpio5, dsp-gpio6, gf-gpio2,
- gf-gpio3, gf-gpio7, codec-aif1-bclk, codec-aif1-rxdat,
- codec-aif1-lrclk, codec-aif1-txdat, codec-aif2-bclk,
- codec-aif2-rxdat, codec-aif2-lrclk, codec-aif2-txdat,
- codec-aif3-bclk, codec-aif3-rxdat, codec-aif3-lrclk,
- codec-aif3-txdat, dsp-aif1-bclk, dsp-aif1-rxdat, dsp-aif1-lrclk,
- dsp-aif1-txdat, dsp-aif2-bclk, dsp-aif2-rxdat,
- dsp-aif2-lrclk, dsp-aif2-txdat, psia1-bclk, psia1-rxdat,
- psia1-lrclk, psia1-txdat, psia2-bclk, psia2-rxdat, psia2-lrclk,
- psia2-txdat, gf-aif3-bclk, gf-aif3-rxdat, gf-aif3-lrclk,
- gf-aif3-txdat, gf-aif4-bclk, gf-aif4-rxdat, gf-aif4-lrclk,
- gf-aif4-txdat, gf-aif1-bclk, gf-aif1-rxdat, gf-aif1-lrclk,
- gf-aif1-txdat, gf-aif2-bclk, gf-aif2-rxdat, gf-aif2-lrclk,
- gf-aif2-txdat, dsp-uart1-rx, dsp-uart1-tx, dsp-uart2-rx,
- dsp-uart2-tx, gf-uart2-rx, gf-uart2-tx, usb-uart-rx,
- codec-pdmclk1, codec-pdmdat1, codec-pdmclk2, codec-pdmdat2,
- codec-dmicclk1, codec-dmicdat1, codec-dmicclk2, codec-dmicdat2,
- codec-dmicclk3, codec-dmicdat3, codec-dmicclk4, codec-dmicdat4,
- dsp-dmicclk1, dsp-dmicdat1, dsp-dmicclk2, dsp-dmicdat2, i2c2-scl,
- i2c2-sda, i2c3-scl, i2c3-sda, i2c4-scl, i2c4-sda, dsp-standby,
- codec-mclk1, codec-mclk2, dsp-clkin, psia1-mclk, psia2-mclk,
- gf-gpio1, gf-gpio5, dsp-gpio20, led1, led2
- - function : The mux function to select, available functions:
- aif, fpga-gpio1, fpga-gpio2, fpga-gpio3, fpga-gpio4, fpga-gpio5,
- fpga-gpio6, codec-gpio1, codec-gpio2, codec-gpio3, codec-gpio4,
- codec-gpio5, codec-gpio6, codec-gpio7, codec-gpio8, dsp-gpio1,
- dsp-gpio2, dsp-gpio3, dsp-gpio4, dsp-gpio5, dsp-gpio6, gf-gpio2,
- gf-gpio3, gf-gpio7, gf-gpio1, gf-gpio5, dsp-gpio20, codec-clkout,
- dsp-clkout, pmic-32k, spdif-clkout, clk-12m288, clk-11m2986,
- clk-24m576, clk-22m5792, xmos-mclk, gf-clkout1, gf-mclk1,
- gf-mclk3, gf-mclk2, gf-clkout2, codec-mclk1, codec-mclk2,
- dsp-clkin, psia1-mclk, psia2-mclk, spdif-mclk, codec-irq,
- codec-reset, dsp-reset, dsp-irq, dsp-standby, codec-pdmclk1,
- codec-pdmdat1, codec-pdmclk2, codec-pdmdat2, codec-dmicclk1,
- codec-dmicdat1, codec-dmicclk2, codec-dmicdat2, codec-dmicclk3,
- codec-dmicdat3, codec-dmicclk4, codec-dmicdat4, dsp-dmicclk1,
- dsp-dmicdat1, dsp-dmicclk2, dsp-dmicdat2, dsp-uart1-rx,
- dsp-uart1-tx, dsp-uart2-rx, dsp-uart2-tx, gf-uart2-rx,
- gf-uart2-tx, usb-uart-rx, usb-uart-tx, i2c2-scl, i2c2-sda,
- i2c3-scl, i2c3-sda, i2c4-scl, i2c4-sda, spdif-aif, psia1,
- psia1-bclk, psia1-lrclk, psia1-rxdat, psia1-txdat, psia2,
- psia2-bclk, psia2-lrclk, psia2-rxdat, psia2-txdat, codec-aif1,
- codec-aif1-bclk, codec-aif1-lrclk, codec-aif1-rxdat,
- codec-aif1-txdat, codec-aif2, codec-aif2-bclk, codec-aif2-lrclk,
- codec-aif2-rxdat, codec-aif2-txdat, codec-aif3, codec-aif3-bclk,
- codec-aif3-lrclk, codec-aif3-rxdat, codec-aif3-txdat, dsp-aif1,
- dsp-aif1-bclk, dsp-aif1-lrclk, dsp-aif1-rxdat, dsp-aif1-txdat,
- dsp-aif2, dsp-aif2-bclk, dsp-aif2-lrclk, dsp-aif2-rxdat,
- dsp-aif2-txdat, gf-aif3, gf-aif3-bclk, gf-aif3-lrclk,
- gf-aif3-rxdat, gf-aif3-txdat, gf-aif4, gf-aif4-bclk,
- gf-aif4-lrclk, gf-aif4-rxdat, gf-aif4-txdat, gf-aif1,
- gf-aif1-bclk, gf-aif1-lrclk, gf-aif1-rxdat, gf-aif1-txdat,
- gf-aif2, gf-aif2-bclk, gf-aif2-lrclk, gf-aif2-rxdat,
- gf-aif2-txdat, usb-aif1, usb-aif2, adat-aif, soundcard-aif,
-
- - output-enable : Specifies that an AIF group will be used as a master
- interface (either this or input-enable is required if a group is
- being muxed to an AIF)
- - input-enable : Specifies that an AIF group will be used as a slave
- interface (either this or output-enable is required if a group is
- being muxed to an AIF)
-
-Example:
-
-lochnagar-pinctrl {
- compatible = "cirrus,lochnagar-pinctrl";
-
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&lochnagar 0 0 LOCHNAGAR2_PIN_NUM_GPIOS>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pin-settings>;
-
- pin-settings: pin-settings {
- ap-aif {
- input-enable;
- groups = "gf-aif1";
- function = "codec-aif3";
- };
- codec-aif {
- output-enable;
- groups = "codec-aif3";
- function = "gf-aif1";
- };
- };
-};
diff --git a/Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.yaml
new file mode 100644
index 0000000000000..420d74856032f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.yaml
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/cirrus,lochnagar.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic Lochnagar Audio Development Board
+
+maintainers:
+ - patches@opensource.cirrus.com
+
+description: |
+ Lochnagar is an evaluation and development board for Cirrus Logic
+ Smart CODEC and Amp devices. It allows the connection of most Cirrus
+ Logic devices on mini-cards, as well as allowing connection of various
+ application processor systems to provide a full evaluation platform.
+ Audio system topology, clocking and power can all be controlled through
+ the Lochnagar, allowing the device under test to be used in a variety of
+ possible use cases.
+
+ This binding document describes the binding for the pinctrl portion of
+ the driver.
+
+ Also see these documents for generic binding information:
+ [1] GPIO : ../gpio/gpio.txt
+ [2] Pinctrl: ../pinctrl/pinctrl-bindings.txt
+
+ And these for relevant defines:
+ [3] include/dt-bindings/pinctrl/lochnagar.h
+
+ This binding must be part of the Lochnagar MFD binding:
+ [4] ../mfd/cirrus,lochnagar.yaml
+
+properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar-pinctrl
+
+ gpio-controller: true
+
+ '#gpio-cells':
+ description:
+ The first cell is the pin number and the second cell is used
+ to specify optional parameters.
+ const: 2
+
+ gpio-ranges:
+ description:
+ Range of pins managed by the GPIO controller, see [1]. Both the
+ GPIO and Pinctrl base should be set to zero and the count to the
+ appropriate of the LOCHNAGARx_PIN_NUM_GPIOS define, see [3].
+ maxItems: 1
+
+ pinctrl-0:
+ description:
+ A phandle to the default pinctrl state.
+
+ pinctrl-names:
+ description:
+ A pinctrl state named "default" must be defined.
+ const: default
+
+ pin-settings:
+ type: object
+ patternProperties:
+ '-pins$':
+ description:
+ The pin configurations are defined as a child of the pinctrl
+ states node, see [2]. Each sub-node can have the following
+ properties.
+ type: object
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: pinmux-node.yaml#
+
+ properties:
+ groups:
+ description:
+ A list of groups to select (either this or "pins" must be
+ specified), available groups.
+ enum: [ codec-aif1, codec-aif2, codec-aif3, dsp-aif1,
+ dsp-aif2, psia1, psia2, gf-aif1, gf-aif2, gf-aif3,
+ gf-aif4, spdif-aif, usb-aif1, usb-aif2, adat-aif,
+ soundcard-aif ]
+
+ pins:
+ description:
+ A list of pin names to select (either this or "groups" must
+ be specified), available pins.
+ enum: [ fpga-gpio1, fpga-gpio2, fpga-gpio3, fpga-gpio4,
+ fpga-gpio5, fpga-gpio6, codec-gpio1, codec-gpio2,
+ codec-gpio3, codec-gpio4, codec-gpio5, codec-gpio6,
+ codec-gpio7, codec-gpio8, dsp-gpio1, dsp-gpio2,
+ dsp-gpio3, dsp-gpio4, dsp-gpio5, dsp-gpio6,
+ gf-gpio2, gf-gpio3, gf-gpio7, codec-aif1-bclk,
+ codec-aif1-rxdat, codec-aif1-lrclk, codec-aif1-txdat,
+ codec-aif2-bclk, codec-aif2-rxdat, codec-aif2-lrclk,
+ codec-aif2-txdat, codec-aif3-bclk, codec-aif3-rxdat,
+ codec-aif3-lrclk, codec-aif3-txdat, dsp-aif1-bclk,
+ dsp-aif1-rxdat, dsp-aif1-lrclk, dsp-aif1-txdat,
+ dsp-aif2-bclk, dsp-aif2-rxdat, dsp-aif2-lrclk,
+ dsp-aif2-txdat, psia1-bclk, psia1-rxdat, psia1-lrclk,
+ psia1-txdat, psia2-bclk, psia2-rxdat, psia2-lrclk,
+ psia2-txdat, gf-aif3-bclk, gf-aif3-rxdat,
+ gf-aif3-lrclk, gf-aif3-txdat, gf-aif4-bclk,
+ gf-aif4-rxdat, gf-aif4-lrclk, gf-aif4-txdat,
+ gf-aif1-bclk, gf-aif1-rxdat, gf-aif1-lrclk,
+ gf-aif1-txdat, gf-aif2-bclk, gf-aif2-rxdat,
+ gf-aif2-lrclk, gf-aif2-txdat, dsp-uart1-rx,
+ dsp-uart1-tx, dsp-uart2-rx, dsp-uart2-tx,
+ gf-uart2-rx, gf-uart2-tx, usb-uart-rx, codec-pdmclk1,
+ codec-pdmdat1, codec-pdmclk2, codec-pdmdat2,
+ codec-dmicclk1, codec-dmicdat1, codec-dmicclk2,
+ codec-dmicdat2, codec-dmicclk3, codec-dmicdat3,
+ codec-dmicclk4, codec-dmicdat4, dsp-dmicclk1,
+ dsp-dmicdat1, dsp-dmicclk2, dsp-dmicdat2, i2c2-scl,
+ i2c2-sda, i2c3-scl, i2c3-sda, i2c4-scl, i2c4-sda,
+ dsp-standby, codec-mclk1, codec-mclk2, dsp-clkin,
+ psia1-mclk, psia2-mclk, gf-gpio1, gf-gpio5,
+ dsp-gpio20, led1, led2 ]
+
+ function:
+ description:
+ The mux function to select, available functions.
+ enum: [ aif, fpga-gpio1, fpga-gpio2, fpga-gpio3, fpga-gpio4,
+ fpga-gpio5, fpga-gpio6, codec-gpio1, codec-gpio2,
+ codec-gpio3, codec-gpio4, codec-gpio5, codec-gpio6,
+ codec-gpio7, codec-gpio8, dsp-gpio1, dsp-gpio2,
+ dsp-gpio3, dsp-gpio4, dsp-gpio5, dsp-gpio6,
+ gf-gpio2, gf-gpio3, gf-gpio7, gf-gpio1, gf-gpio5,
+ dsp-gpio20, codec-clkout, dsp-clkout, pmic-32k,
+ spdif-clkout, clk-12m288, clk-11m2986, clk-24m576,
+ clk-22m5792, xmos-mclk, gf-clkout1, gf-mclk1,
+ gf-mclk3, gf-mclk2, gf-clkout2, codec-mclk1,
+ codec-mclk2, dsp-clkin, psia1-mclk, psia2-mclk,
+ spdif-mclk, codec-irq, codec-reset, dsp-reset,
+ dsp-irq, dsp-standby, codec-pdmclk1, codec-pdmdat1,
+ codec-pdmclk2, codec-pdmdat2, codec-dmicclk1,
+ codec-dmicdat1, codec-dmicclk2, codec-dmicdat2,
+ codec-dmicclk3, codec-dmicdat3, codec-dmicclk4,
+ codec-dmicdat4, dsp-dmicclk1, dsp-dmicdat1,
+ dsp-dmicclk2, dsp-dmicdat2, dsp-uart1-rx,
+ dsp-uart1-tx, dsp-uart2-rx, dsp-uart2-tx,
+ gf-uart2-rx, gf-uart2-tx, usb-uart-rx, usb-uart-tx,
+ i2c2-scl, i2c2-sda, i2c3-scl, i2c3-sda, i2c4-scl,
+ i2c4-sda, spdif-aif, psia1, psia1-bclk, psia1-lrclk,
+ psia1-rxdat, psia1-txdat, psia2, psia2-bclk,
+ psia2-lrclk, psia2-rxdat, psia2-txdat, codec-aif1,
+ codec-aif1-bclk, codec-aif1-lrclk, codec-aif1-rxdat,
+ codec-aif1-txdat, codec-aif2, codec-aif2-bclk,
+ codec-aif2-lrclk, codec-aif2-rxdat, codec-aif2-txdat,
+ codec-aif3, codec-aif3-bclk, codec-aif3-lrclk,
+ codec-aif3-rxdat, codec-aif3-txdat, dsp-aif1,
+ dsp-aif1-bclk, dsp-aif1-lrclk, dsp-aif1-rxdat,
+ dsp-aif1-txdat, dsp-aif2, dsp-aif2-bclk,
+ dsp-aif2-lrclk, dsp-aif2-rxdat, dsp-aif2-txdat,
+ gf-aif3, gf-aif3-bclk, gf-aif3-lrclk, gf-aif3-rxdat,
+ gf-aif3-txdat, gf-aif4, gf-aif4-bclk, gf-aif4-lrclk,
+ gf-aif4-rxdat, gf-aif4-txdat, gf-aif1, gf-aif1-bclk,
+ gf-aif1-lrclk, gf-aif1-rxdat, gf-aif1-txdat, gf-aif2,
+ gf-aif2-bclk, gf-aif2-lrclk, gf-aif2-rxdat,
+ gf-aif2-txdat, usb-aif1, usb-aif2, adat-aif,
+ soundcard-aif ]
+
+ output-enable:
+ description:
+ Specifies that an AIF group will be used as a master
+ interface (either this or input-enable is required if a
+ group is being muxed to an AIF)
+
+ input-enable:
+ description:
+ Specifies that an AIF group will be used as a slave
+ interface (either this or output-enable is required if a
+ group is being muxed to an AIF)
+
+ additionalProperties: false
+
+ required:
+ - function
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - gpio-controller
+ - '#gpio-cells'
+ - gpio-ranges
+ - pinctrl-0
+ - pinctrl-names
--
2.11.0
^ permalink raw reply related
* [PATCH v3 5/5] mfd: lochnagar: Move binding over to dtschema
From: Charles Keepax @ 2020-05-12 15:23 UTC (permalink / raw)
To: robh+dt, lee.jones, broonie, mturquette, sboyd, jdelvare, linux,
linus.walleij
Cc: lgirdwood, linux-kernel, devicetree, patches
In-Reply-To: <20200512152359.11839-1-ckeepax@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v2.
Thanks,
Charles
.../devicetree/bindings/mfd/cirrus,lochnagar.txt | 85 -----
.../devicetree/bindings/mfd/cirrus,lochnagar.yaml | 352 +++++++++++++++++++++
.../bindings/regulator/cirrus,lochnagar.txt | 82 -----
MAINTAINERS | 11 +-
4 files changed, 357 insertions(+), 173 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
create mode 100644 Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
delete mode 100644 Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
diff --git a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
deleted file mode 100644
index 3bf92ad37fa1b..0000000000000
--- a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-Cirrus Logic Lochnagar Audio Development Board
-
-Lochnagar is an evaluation and development board for Cirrus Logic
-Smart CODEC and Amp devices. It allows the connection of most Cirrus
-Logic devices on mini-cards, as well as allowing connection of
-various application processor systems to provide a full evaluation
-platform. Audio system topology, clocking and power can all be
-controlled through the Lochnagar, allowing the device under test
-to be used in a variety of possible use cases.
-
-Also see these documents for generic binding information:
- [1] GPIO : ../gpio/gpio.txt
-
-And these for relevant defines:
- [2] include/dt-bindings/pinctrl/lochnagar.h
- [3] include/dt-bindings/clock/lochnagar.h
-
-And these documents for the required sub-node binding details:
- [4] Clock: ../clock/cirrus,lochnagar.txt
- [5] Pinctrl: ../pinctrl/cirrus,lochnagar.txt
- [6] Regulator: ../regulator/cirrus,lochnagar.txt
- [7] Sound: ../sound/cirrus,lochnagar.txt
- [8] Hardware Monitor: ../hwmon/cirrus,lochnagar.txt
-
-Required properties:
-
- - compatible : One of the following strings:
- "cirrus,lochnagar1"
- "cirrus,lochnagar2"
-
- - reg : I2C slave address
-
- - reset-gpios : Reset line to the Lochnagar, see [1].
-
-Required sub-nodes:
-
- - lochnagar-clk : Binding for the clocking components, see [4].
-
- - lochnagar-pinctrl : Binding for the pin control components, see [5].
-
-Optional sub-nodes:
-
- - Bindings for the regulator components, see [6]. Only available on
- Lochnagar 2.
-
- - lochnagar-sc : Binding for the sound card components, see [7].
- Only available on Lochnagar 2.
- - lochnagar-hwmon : Binding for the hardware monitor components, see [8].
- Only available on Lochnagar 2.
-
-Optional properties:
-
- - present-gpios : Host present line, indicating the presence of a
- host system, see [1]. This can be omitted if the present line is
- tied in hardware.
-
-Example:
-
-lochnagar: lochnagar@22 {
- compatible = "cirrus,lochnagar2";
- reg = <0x22>;
-
- reset-gpios = <&gpio0 55 0>;
- present-gpios = <&gpio0 60 0>;
-
- lochnagar-clk {
- compatible = "cirrus,lochnagar2-clk";
- ...
- };
-
- lochnagar-pinctrl {
- compatible = "cirrus,lochnagar-pinctrl";
- ...
- };
-
- lochnagar-sc {
- compatible = "cirrus,lochnagar2-soundcard";
- ...
- };
-
- lochnagar-hwmon {
- compatible = "cirrus,lochnagar2-hwmon";
- ...
- };
-};
diff --git a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
new file mode 100644
index 0000000000000..7a616577ac634
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
@@ -0,0 +1,352 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/cirrus,lochnagar.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic Lochnagar Audio Development Board
+
+maintainers:
+ - patches@opensource.cirrus.com
+
+description: |
+ Lochnagar is an evaluation and development board for Cirrus Logic
+ Smart CODEC and Amp devices. It allows the connection of most Cirrus
+ Logic devices on mini-cards, as well as allowing connection of
+ various application processor systems to provide a full evaluation
+ platform. Audio system topology, clocking and power can all be
+ controlled through the Lochnagar, allowing the device under test
+ to be used in a variety of possible use cases.
+
+ Also see these documents for generic binding information:
+ [1] GPIO : ../gpio/gpio.txt
+
+ And these for relevant defines:
+ [2] include/dt-bindings/pinctrl/lochnagar.h
+ [3] include/dt-bindings/clock/lochnagar.h
+
+ And these documents for the required sub-node binding details:
+ [4] Clock: ../clock/cirrus,lochnagar.yaml
+ [5] Pinctrl: ../pinctrl/cirrus,lochnagar.yaml
+ [6] Sound: ../sound/cirrus,lochnagar.yaml
+ [7] Hardware Monitor: ../hwmon/cirrus,lochnagar.yaml
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar2
+ then:
+ properties:
+ lochnagar-hwmon:
+ type: object
+ $ref: /schemas/hwmon/cirrus,lochnagar.yaml#
+
+ lochnagar-sc:
+ type: object
+ $ref: /schemas/sound/cirrus,lochnagar.yaml#
+
+properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar1
+ - cirrus,lochnagar2
+
+ reg:
+ const: 0x22
+
+ reset-gpios:
+ maxItems: 1
+
+ present-gpios:
+ description: |
+ Host present line, indicating the presence of a
+ host system, see [1]. This can be omitted if the present line is
+ tied in hardware.
+ maxItems: 1
+
+ lochnagar-clk:
+ type: object
+ $ref: /schemas/clock/cirrus,lochnagar.yaml#
+
+ lochnagar-pmic32k:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 32768
+
+ lochnagar-clk12m:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 12288000
+
+ lochnagar-clk11m:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 11298600
+
+ lochnagar-clk24m:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 24576000
+
+ lochnagar-clk22m:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 22579200
+
+ lochnagar-clk8m:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 8192000
+
+ lochnagar-usb24m:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 24576000
+
+ lochnagar-usb12m:
+ type: object
+ $ref: /schemas/clock/fixed-clock.yaml#
+ properties:
+ clock-frequency:
+ const: 12288000
+
+ lochnagar-pinctrl:
+ type: object
+ $ref: /schemas/pinctrl/cirrus,lochnagar.yaml#
+
+ VDDCORE:
+ description:
+ Initialisation data for the VDDCORE regulator, which supplies the
+ CODECs digital core if not being provided by an internal regulator.
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar2-vddcore
+
+ SYSVDD-supply:
+ description:
+ Primary power supply for the Lochnagar.
+ required:
+ - compatible
+
+ MICVDD:
+ description:
+ Initialisation data for the MICVDD regulator, which supplies the
+ CODECs MICVDD.
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar2-micvdd
+
+ SYSVDD-supply:
+ description:
+ Primary power supply for the Lochnagar.
+ required:
+ - compatible
+
+ MIC1VDD:
+ description:
+ Initialisation data for the MIC1VDD supplies.
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar2-mic1vdd
+
+ cirrus,micbias-input:
+ description:
+ A property selecting which of the CODEC minicard micbias outputs
+ should be used.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+ maximum: 4
+
+ MICBIAS1-supply:
+ description:
+ Regulator supplies for the MIC1VDD outputs, supplying the digital
+ microphones, normally supplied from the attached CODEC.
+ required:
+ - compatible
+
+ MIC2VDD:
+ description:
+ Initialisation data for the MIC2VDD supplies.
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar2-mic2vdd
+
+ cirrus,micbias-input:
+ description:
+ A property selecting which of the CODEC minicard micbias outputs
+ should be used.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+ maximum: 4
+
+ MICBIAS2-supply:
+ description:
+ Regulator supplies for the MIC2VDD outputs, supplying the digital
+ microphones, normally supplied from the attached CODEC.
+ required:
+ - compatible
+
+ VDD1V8:
+ description:
+ Recommended fixed regulator for the VDD1V8 regulator, which supplies
+ the CODECs analog and 1.8V digital supplies.
+ type: object
+ $ref: /schemas/regulator/regulator.yaml#
+ properties:
+ compatible:
+ enum:
+ - regulator-fixed
+
+ regulator-min-microvolt:
+ const: 1800000
+
+ regulator-max-microvolt:
+ const: 1800000
+
+ vin-supply:
+ description:
+ Should be set to same supply as SYSVDD
+ required:
+ - compatible
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+ - regulator-boot-on
+ - regulator-always-on
+ - vin-supply
+
+required:
+ - compatible
+ - reg
+ - reset-gpios
+ - lochnagar-clk
+ - lochnagar-pinctrl
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clk/lochnagar.h>
+ #include <dt-bindings/pinctrl/lochnagar.h>
+ i2c@e0004000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xe0004000 0x1000>;
+
+ lochnagar: lochnagar@22 {
+ compatible = "cirrus,lochnagar2";
+ reg = <0x22>;
+
+ reset-gpios = <&gpio0 55 0>;
+ present-gpios = <&gpio0 60 0>;
+
+ lochnagarclk: lochnagar-clk {
+ compatible = "cirrus,lochnagar2-clk";
+
+ #clock-cells = <1>;
+ clocks = <&clkaudio>, <&clkpmic>;
+ clock-names = "ln-gf-mclk2", "ln-pmic-32k";
+
+ assigned-clocks = <&lochnagarclk LOCHNAGAR_CDC_MCLK1>,
+ <&lochnagarclk LOCHNAGAR_CDC_MCLK2>;
+ assigned-clock-parents = <&clkaudio>, <&clkpmic>;
+ };
+
+ clkpmic: lochnagar-pmic32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ lochnagar-pinctrl {
+ compatible = "cirrus,lochnagar-pinctrl";
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&lochnagar 0 0 LOCHNAGAR2_PIN_NUM_GPIOS>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinsettings>;
+
+ pinsettings: pin-settings {
+ ap2aif-pins {
+ input-enable;
+ groups = "gf-aif1";
+ function = "codec-aif3";
+ };
+ codec2aif-pins {
+ output-enable;
+ groups = "codec-aif3";
+ function = "gf-aif1";
+ };
+ };
+ };
+
+ lochnagar-sc {
+ compatible = "cirrus,lochnagar2-soundcard";
+
+ #sound-dai-cells = <1>;
+
+ clocks = <&lochnagarclk LOCHNAGAR_SOUNDCARD_MCLK>;
+ clock-names = "mclk";
+ };
+
+ lochnagar-hwmon {
+ compatible = "cirrus,lochnagar2-hwmon";
+ };
+
+ MIC1VDD {
+ compatible = "cirrus,lochnagar2-mic1vdd";
+
+ cirrus,micbias-input = <3>;
+ };
+
+ MICVDD {
+ compatible = "cirrus,lochnagar2-micvdd";
+
+ SYSVDD-supply = <&wallvdd>;
+
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ VDD1V8 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VDD1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+
+ vin-supply = <&wallvdd>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
deleted file mode 100644
index 91974e6ee251b..0000000000000
--- a/Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-Cirrus Logic Lochnagar Audio Development Board
-
-Lochnagar is an evaluation and development board for Cirrus Logic
-Smart CODEC and Amp devices. It allows the connection of most Cirrus
-Logic devices on mini-cards, as well as allowing connection of
-various application processor systems to provide a full evaluation
-platform. Audio system topology, clocking and power can all be
-controlled through the Lochnagar, allowing the device under test
-to be used in a variety of possible use cases.
-
-This binding document describes the binding for the regulator portion
-of the driver.
-
-Also see these documents for generic binding information:
- [1] Regulator: ../regulator/regulator.txt
-
-This binding must be part of the Lochnagar MFD binding:
- [2] ../mfd/cirrus,lochnagar.txt
-
-Optional sub-nodes:
-
- - VDDCORE : Initialisation data for the VDDCORE regulator, which
- supplies the CODECs digital core if it has no build regulator for that
- purpose.
- Required Properties:
- - compatible : One of the following strings:
- "cirrus,lochnagar2-vddcore"
- - SYSVDD-supply: Primary power supply for the Lochnagar.
-
- - MICVDD : Initialisation data for the MICVDD regulator, which
- supplies the CODECs MICVDD.
- Required Properties:
- - compatible : One of the following strings:
- "cirrus,lochnagar2-micvdd"
- - SYSVDD-supply: Primary power supply for the Lochnagar.
-
- - MIC1VDD, MIC2VDD : Initialisation data for the MICxVDD supplies.
- Required Properties:
- - compatible : One of the following strings:
- "cirrus,lochnagar2-mic1vdd", "cirrus,lochnagar2-mic2vdd"
- Optional Properties:
- - cirrus,micbias-input : A property selecting which of the CODEC
- minicard micbias outputs should be used, valid values are 1 - 4.
- - MICBIAS1-supply, MICBIAS2-supply: Regulator supplies for the
- MICxVDD outputs, supplying the digital microphones, normally
- supplied from the attached CODEC.
-
- - VDD1V8 : Recommended fixed regulator for the VDD1V8 regulator, which supplies the
- CODECs analog and 1.8V digital supplies.
- Required Properties:
- - compatible : Should be set to "regulator-fixed"
- - regulator-min-microvolt : Should be set to 1.8V
- - regulator-max-microvolt : Should be set to 1.8V
- - regulator-boot-on
- - regulator-always-on
- - vin-supply : Should be set to same supply as SYSVDD
-
-Example:
-
-lochnagar {
- lochnagar-micvdd: MICVDD {
- compatible = "cirrus,lochnagar2-micvdd";
-
- SYSVDD-supply = <&wallvdd>;
-
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
-
- lochnagar-vdd1v8: VDD1V8 {
- compatible = "regulator-fixed";
-
- regulator-name = "VDD1V8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-boot-on;
- regulator-always-on;
-
- vin-supply = <&wallvdd>;
- };
-};
-
diff --git a/MAINTAINERS b/MAINTAINERS
index e64e5db314976..91bf1fbe98c8e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4062,12 +4062,11 @@ M: Charles Keepax <ckeepax@opensource.cirrus.com>
M: Richard Fitzgerald <rf@opensource.cirrus.com>
L: patches@opensource.cirrus.com
S: Supported
-F: Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
-F: Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.txt
-F: Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
-F: Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
-F: Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
-F: Documentation/devicetree/bindings/sound/cirrus,lochnagar.txt
+F: Documentation/devicetree/bindings/clock/cirrus,lochnagar.yaml
+F: Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.yaml
+F: Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml
+F: Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.yaml
+F: Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
F: Documentation/hwmon/lochnagar.rst
F: drivers/clk/clk-lochnagar.c
F: drivers/hwmon/lochnagar-hwmon.c
--
2.11.0
^ permalink raw reply related
* [PATCH v3 4/5] clk: lochnagar: Move binding over to dtschema
From: Charles Keepax @ 2020-05-12 15:23 UTC (permalink / raw)
To: robh+dt, lee.jones, broonie, mturquette, sboyd, jdelvare, linux,
linus.walleij
Cc: lgirdwood, linux-kernel, devicetree, patches
In-Reply-To: <20200512152359.11839-1-ckeepax@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v2.
Thanks,
Charles
.../devicetree/bindings/clock/cirrus,lochnagar.txt | 94 ----------------------
.../bindings/clock/cirrus,lochnagar.yaml | 78 ++++++++++++++++++
2 files changed, 78 insertions(+), 94 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
create mode 100644 Documentation/devicetree/bindings/clock/cirrus,lochnagar.yaml
diff --git a/Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
deleted file mode 100644
index 52a064c789eec..0000000000000
--- a/Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
+++ /dev/null
@@ -1,94 +0,0 @@
-Cirrus Logic Lochnagar Audio Development Board
-
-Lochnagar is an evaluation and development board for Cirrus Logic
-Smart CODEC and Amp devices. It allows the connection of most Cirrus
-Logic devices on mini-cards, as well as allowing connection of
-various application processor systems to provide a full evaluation
-platform. Audio system topology, clocking and power can all be
-controlled through the Lochnagar, allowing the device under test
-to be used in a variety of possible use cases.
-
-This binding document describes the binding for the clock portion of
-the driver.
-
-Also see these documents for generic binding information:
- [1] Clock : ../clock/clock-bindings.txt
-
-And these for relevant defines:
- [2] include/dt-bindings/clock/lochnagar.h
-
-This binding must be part of the Lochnagar MFD binding:
- [3] ../mfd/cirrus,lochnagar.txt
-
-Required properties:
-
- - compatible : One of the following strings:
- "cirrus,lochnagar1-clk"
- "cirrus,lochnagar2-clk"
-
- - #clock-cells : Must be 1. The first cell indicates the clock
- number, see [2] for available clocks and [1].
-
-Optional properties:
-
- - clocks : Must contain an entry for each clock in clock-names.
- - clock-names : May contain entries for each of the following
- clocks:
- - ln-cdc-clkout : Output clock from CODEC card.
- - ln-dsp-clkout : Output clock from DSP card.
- - ln-gf-mclk1,ln-gf-mclk2,ln-gf-mclk3,ln-gf-mclk4 : Optional
- input audio clocks from host system.
- - ln-psia1-mclk, ln-psia2-mclk : Optional input audio clocks from
- external connector.
- - ln-spdif-mclk : Optional input audio clock from SPDIF.
- - ln-spdif-clkout : Optional input audio clock from SPDIF.
- - ln-adat-mclk : Optional input audio clock from ADAT.
- - ln-pmic-32k : On board fixed clock.
- - ln-clk-12m : On board fixed clock.
- - ln-clk-11m : On board fixed clock.
- - ln-clk-24m : On board fixed clock.
- - ln-clk-22m : On board fixed clock.
- - ln-clk-8m : On board fixed clock.
- - ln-usb-clk-24m : On board fixed clock.
- - ln-usb-clk-12m : On board fixed clock.
-
- - assigned-clocks : A list of Lochnagar clocks to be reparented, see
- [2] for available clocks.
- - assigned-clock-parents : Parents to be assigned to the clocks
- listed in "assigned-clocks".
-
-Optional nodes:
-
- - fixed-clock nodes may be registered for the following on board clocks:
- - ln-pmic-32k : 32768 Hz
- - ln-clk-12m : 12288000 Hz
- - ln-clk-11m : 11298600 Hz
- - ln-clk-24m : 24576000 Hz
- - ln-clk-22m : 22579200 Hz
- - ln-clk-8m : 8192000 Hz
- - ln-usb-clk-24m : 24576000 Hz
- - ln-usb-clk-12m : 12288000 Hz
-
-Example:
-
-lochnagar {
- lochnagar-clk {
- compatible = "cirrus,lochnagar2-clk";
-
- #clock-cells = <1>;
-
- clocks = <&clk-audio>, <&clk_pmic>;
- clock-names = "ln-gf-mclk2", "ln-pmic-32k";
-
- assigned-clocks = <&lochnagar-clk LOCHNAGAR_CDC_MCLK1>,
- <&lochnagar-clk LOCHNAGAR_CDC_MCLK2>;
- assigned-clock-parents = <&clk-audio>,
- <&clk-pmic>;
- };
-
- clk-pmic: clk-pmic {
- compatible = "fixed-clock";
- clock-cells = <0>;
- clock-frequency = <32768>;
- };
-};
diff --git a/Documentation/devicetree/bindings/clock/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/clock/cirrus,lochnagar.yaml
new file mode 100644
index 0000000000000..59de125647ecb
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/cirrus,lochnagar.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/cirrus,lochnagar.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic Lochnagar Audio Development Board
+
+maintainers:
+ - patches@opensource.cirrus.com
+
+description: |
+ Lochnagar is an evaluation and development board for Cirrus Logic
+ Smart CODEC and Amp devices. It allows the connection of most Cirrus
+ Logic devices on mini-cards, as well as allowing connection of various
+ application processor systems to provide a full evaluation platform.
+ Audio system topology, clocking and power can all be controlled through
+ the Lochnagar, allowing the device under test to be used in a variety of
+ possible use cases.
+
+ This binding document describes the binding for the clock portion of the
+ driver.
+
+ Also see these documents for generic binding information:
+ [1] Clock : ../clock/clock-bindings.txt
+
+ And these for relevant defines:
+ [2] include/dt-bindings/clock/lochnagar.h
+
+ This binding must be part of the Lochnagar MFD binding:
+ [3] ../mfd/cirrus,lochnagar.yaml
+
+properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar1-clk
+ - cirrus,lochnagar2-clk
+
+ '#clock-cells':
+ description:
+ The first cell indicates the clock number, see [2] for available
+ clocks and [1].
+ const: 1
+
+ clock-names:
+ items:
+ enum:
+ - ln-cdc-clkout # Output clock from CODEC card.
+ - ln-dsp-clkout # Output clock from DSP card.
+ - ln-gf-mclk1 # Optional input clock from host system.
+ - ln-gf-mclk2 # Optional input clock from host system.
+ - ln-gf-mclk3 # Optional input clock from host system.
+ - ln-gf-mclk4 # Optional input clock from host system.
+ - ln-psia1-mclk # Optional input clock from external connector.
+ - ln-psia2-mclk # Optional input clock from external connector.
+ - ln-spdif-mclk # Optional input clock from SPDIF.
+ - ln-spdif-clkout # Optional input clock from SPDIF.
+ - ln-adat-mclk # Optional input clock from ADAT.
+ - ln-pmic-32k # On board fixed clock.
+ - ln-clk-12m # On board fixed clock.
+ - ln-clk-11m # On board fixed clock.
+ - ln-clk-24m # On board fixed clock.
+ - ln-clk-22m # On board fixed clock.
+ - ln-clk-8m # On board fixed clock.
+ - ln-usb-clk-24m # On board fixed clock.
+ - ln-usb-clk-12m # On board fixed clock.
+ minItems: 1
+ maxItems: 19
+
+ clocks: true
+ assigned-clocks: true
+ assigned-clock-parents: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - '#clock-cells'
--
2.11.0
^ permalink raw reply related
* [PATCH v3 1/5] hwmon: lochnagar: Move binding over to dtschema
From: Charles Keepax @ 2020-05-12 15:23 UTC (permalink / raw)
To: robh+dt, lee.jones, broonie, mturquette, sboyd, jdelvare, linux,
linus.walleij
Cc: lgirdwood, linux-kernel, devicetree, patches
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v2.
Thanks,
Charles
.../devicetree/bindings/hwmon/cirrus,lochnagar.txt | 26 ----------------
.../bindings/hwmon/cirrus,lochnagar.yaml | 35 ++++++++++++++++++++++
2 files changed, 35 insertions(+), 26 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.txt
create mode 100644 Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.yaml
diff --git a/Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.txt
deleted file mode 100644
index ffb79ccf51ee3..0000000000000
--- a/Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Cirrus Logic Lochnagar Audio Development Board
-
-Lochnagar is an evaluation and development board for Cirrus Logic
-Smart CODEC and Amp devices. It allows the connection of most Cirrus
-Logic devices on mini-cards, as well as allowing connection of
-various application processor systems to provide a full evaluation
-platform. Audio system topology, clocking and power can all be
-controlled through the Lochnagar, allowing the device under test
-to be used in a variety of possible use cases.
-
-This binding document describes the binding for the hardware monitor
-portion of the driver.
-
-This binding must be part of the Lochnagar MFD binding:
- [4] ../mfd/cirrus,lochnagar.txt
-
-Required properties:
-
- - compatible : One of the following strings:
- "cirrus,lochnagar2-hwmon"
-
-Example:
-
-lochnagar-hwmon {
- compatible = "cirrus,lochnagar2-hwmon";
-};
diff --git a/Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.yaml
new file mode 100644
index 0000000000000..cc00b97a7dace
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/cirrus,lochnagar.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/cirrus,lochnagar.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic Lochnagar Audio Development Board
+
+maintainers:
+ - patches@opensource.cirrus.com
+
+description: |
+ Lochnagar is an evaluation and development board for Cirrus Logic
+ Smart CODEC and Amp devices. It allows the connection of most Cirrus
+ Logic devices on mini-cards, as well as allowing connection of various
+ application processor systems to provide a full evaluation platform.
+ Audio system topology, clocking and power can all be controlled through
+ the Lochnagar, allowing the device under test to be used in a variety of
+ possible use cases.
+
+ This binding document describes the binding for the hardware monitor
+ portion of the driver.
+
+ This binding must be part of the Lochnagar MFD binding:
+ [1] ../mfd/cirrus,lochnagar.yaml
+
+properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar2-hwmon
+
+required:
+ - compatible
+
+additionalProperties: false
--
2.11.0
^ permalink raw reply related
* [PATCH 2/5] ASoC: lochnagar: Move binding over to dtschema
From: Charles Keepax @ 2020-05-12 15:23 UTC (permalink / raw)
To: robh+dt, lee.jones, broonie, mturquette, sboyd, jdelvare, linux,
linus.walleij
Cc: lgirdwood, linux-kernel, devicetree, patches
In-Reply-To: <20200512152359.11839-1-ckeepax@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v2.
Thanks,
Charles
.../devicetree/bindings/sound/cirrus,lochnagar.txt | 39 ----------------
.../bindings/sound/cirrus,lochnagar.yaml | 52 ++++++++++++++++++++++
2 files changed, 52 insertions(+), 39 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/sound/cirrus,lochnagar.txt
create mode 100644 Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
diff --git a/Documentation/devicetree/bindings/sound/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/sound/cirrus,lochnagar.txt
deleted file mode 100644
index 41ae2699f07a9..0000000000000
--- a/Documentation/devicetree/bindings/sound/cirrus,lochnagar.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-Cirrus Logic Lochnagar Audio Development Board
-
-Lochnagar is an evaluation and development board for Cirrus Logic
-Smart CODEC and Amp devices. It allows the connection of most Cirrus
-Logic devices on mini-cards, as well as allowing connection of
-various application processor systems to provide a full evaluation
-platform. Audio system topology, clocking and power can all be
-controlled through the Lochnagar, allowing the device under test
-to be used in a variety of possible use cases.
-
-This binding document describes the binding for the audio portion
-of the driver.
-
-This binding must be part of the Lochnagar MFD binding:
- [4] ../mfd/cirrus,lochnagar.txt
-
-Required properties:
-
- - compatible : One of the following strings:
- "cirrus,lochnagar2-soundcard"
-
- - #sound-dai-cells : Must be set to 1.
-
- - clocks : Contains an entry for each entry in clock-names.
- - clock-names : Must include the following clocks:
- "mclk" Master clock source for the sound card, should normally
- be set to LOCHNAGAR_SOUNDCARD_MCLK provided by the Lochnagar
- clock driver.
-
-Example:
-
-lochnagar-sc {
- compatible = "cirrus,lochnagar2-soundcard";
-
- #sound-dai-cells = <1>;
-
- clocks = <&lochnagar_clk LOCHNAGAR_SOUNDCARD_MCLK>;
- clock-names = "mclk";
-};
diff --git a/Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
new file mode 100644
index 0000000000000..cea612d3d4a7d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/cirrus,lochnagar.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cirrus Logic Lochnagar Audio Development Board
+
+maintainers:
+ - patches@opensource.cirrus.com
+
+description: |
+ Lochnagar is an evaluation and development board for Cirrus Logic
+ Smart CODEC and Amp devices. It allows the connection of most Cirrus
+ Logic devices on mini-cards, as well as allowing connection of various
+ application processor systems to provide a full evaluation platform.
+ Audio system topology, clocking and power can all be controlled through
+ the Lochnagar, allowing the device under test to be used in a variety of
+ possible use cases.
+
+ This binding document describes the binding for the audio portion of the
+ driver.
+
+ This binding must be part of the Lochnagar MFD binding:
+ [1] ../mfd/cirrus,lochnagar.yaml
+
+properties:
+ compatible:
+ enum:
+ - cirrus,lochnagar2-soundcard
+
+ '#sound-dai-cells':
+ description:
+ The first cell indicating the audio interface.
+ const: 1
+
+ clocks:
+ description:
+ Master clock source for the sound card, should normally be set to
+ LOCHNAGAR_SOUNDCARD_MCLK provided by the Lochnagar clock driver.
+ maxItems: 1
+
+ clock-names:
+ const: mclk
+
+required:
+ - compatible
+ - '#sound-dai-cells'
+ - clocks
+ - clock-names
+
+additionalProperties: false
--
2.11.0
^ permalink raw reply related
* Re: [PATCH] dt-bindings: vendor-prefixes: Add U-Boot bootloader prefix
From: Rob Herring @ 2020-05-12 15:22 UTC (permalink / raw)
To: Michal Simek
Cc: Stephan Gerhold, Heiko Stuebner, git, devicetree, Sam Ravnborg,
linux-kernel, Linus Walleij, u-boot, monstr, Rob Herring,
Mark Brown, Maxime Ripard, Tom Rini
In-Reply-To: <85b8dc9e6288270bbfdf55f1c156dba160293f01.1588239081.git.michal.simek@xilinx.com>
On Thu, 30 Apr 2020 11:31:27 +0200, Michal Simek wrote:
> List U-Boot project in vendor prefixes.
>
> For more information take a look at:
> https://en.wikipedia.org/wiki/Das_U-Boot
> Source code is available here:
> https://gitlab.denx.de/u-boot/u-boot
>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> ---
>
> The patch was created based on discussion with Rob
> https://lore.kernel.org/linux-devicetree/CAL_Jsq+ehJSK7sjqmKtWOVjr-QZ3LDB+ywCO85uF8WJ+cB=AAw@mail.gmail.com/
> ---
> Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
> 1 file changed, 2 insertions(+)
>
Applied, thanks!
^ permalink raw reply
* [PATCH v13 2/2] media: v4l: xilinx: Add Xilinx MIPI CSI-2 Rx Subsystem driver
From: Vishal Sagar @ 2020-05-12 15:19 UTC (permalink / raw)
To: Hyun Kwon, laurent.pinchart, mchehab, robh+dt, mark.rutland,
Michal Simek, linux-media, devicetree, hans.verkuil,
linux-arm-kernel, linux-kernel, Dinesh Kumar, Sandip Kothari,
Luca Ceresoli, Jacopo Mondi
Cc: Vishal Sagar, Hyun Kwon
In-Reply-To: <20200512151947.120348-1-vishal.sagar@xilinx.com>
The Xilinx MIPI CSI-2 Rx Subsystem soft IP is used to capture images
from MIPI CSI-2 camera sensors and output AXI4-Stream video data ready
for image processing. Please refer to PG232 for details.
The CSI2 Rx controller filters out all packets except for the packets
with data type fixed in hardware. RAW8 packets are always allowed to
pass through.
It is also used to setup and handle interrupts and enable the core. It
logs all the events in respective counters between streaming on and off.
The driver supports only the video format bridge enabled configuration.
Some data types like YUV 422 10bpc, RAW16, RAW20 are supported when the
CSI v2.0 feature is enabled in design. When the VCX feature is enabled,
the maximum number of virtual channels becomes 16 from 4.
Signed-off-by: Vishal Sagar <vishal.sagar@xilinx.com>
Reviewed-by: Hyun Kwon <hyun.kwon@xilinx.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v13
- Based on Laurent's suggestions
- Removed unnecessary debug statement for vep
- Added TODO for clock to enable disable at streamon/off
- Fix for index to start from 0 for get_nth_mbus_format
- Removed macro XCSI_TIMEOUT_VAL
- Remove ndelay from hard reset
- Remove hard reset from irq handler
- Fix short packet fifo clear
- Add TODO for v4l2_subdev_notify for SLBF error
- Fix the enable condition in s_stream
- Fix condition in xcsi2rxss_set_format
- Fix enum_mbus_code for double enumeration of RAW8 Data type
- Removed core struct
- Added reviewed by Laurent
v12
- Changes done as suggested by Laurent Pinchart and Luca Ceresoli
- Removed unused macros
- No local storage of supported formats
- Dropped init mbus fmts and removed xcsi2rxss_init_mbus_fmts()
- XCSI_GET_BITSET_STR removed
- Add data type and mbus LUT
- Added xcsi2rxss_get_nth_mbus() and xcsi2rxss_get_dt()
- Replaced all core->dev with dev in dev_dbg() and related debug prints
- Replaced xcsi2rxss_log_ipconfig() with single line
- Removed small functions to enable/disable interrupts and core
- Now save remote subdev in state struct before streaming on
- Made xcsi2rxss_reset as soft_reset()
- Added hard reset using video-reset gpio
- 2 modes one with delay and another sleep
- Instead of reset-gpios it is not video-reset-gpios
- In irq handler
- Moved clearing of ISR up
- Dump / empty short packet fifo
- Irq handler is now threaded
- Added init_cfg pad ops and removed open()
- Updated xcsi2rxss_set_format(), xcsi2rxss_enum_mbus_code() to use the dt mbus lut
- xcsi2rxss_set_default_format() updated
- Moved mutex_init()
- Updated graph handling
- Removed unnecessary prints
- Use devm_platform_ioremap_resource() and platform_get_irq()
- Update KConfig description
v11
- Fixed changes as suggested by Sakari Ailus
- Removed VIDEO_XILINX from KConfig
- Minor formatting
- Start / Stop upstream sub-device in xcsi2rxss_start_stream()
and xcsi2rxss_stop_stream()
- Added v4l2_subdev_link_validate_default() in v4l2_subdev_pad_ops()
- Use fwnode_graph_get_endpoint_by_id() instead of parsing by self
- Set bus type as V4L2_MBUS_CSI2_DPHY in struct v4l2_fwnode_endpoint
- Remove num_clks from core. Instead use ARRAY_SIZE()
- Fixed SPDX header to GPL-2.0
- Update copyright year to 2020
v10
- Removed all V4L2 controls and events based on Sakari's comments.
- Now stop_stream() before toggling rst_gpio
- Updated init_mbus() to throw error on array out of bound access
- Make events and vcx_events as counters instead of structures
- Minor fixes in set_format() enum_mbus_code() as suggested by Sakari
v9
- Moved all controls and events to xilinx-csi2rxss.h
- Updated name and description of controls and events
- Get control base address from v4l2-controls.h (0x10c0)
- Fix KConfig for dependency on VIDEO_XILINX
- Added enum_mbus_code() support
- Added default format to be returned on open()
- Mark variables are const
- Remove references to short packet in comments
- Add check for streaming before setting active lanes control
- strlcpy -> strscpy
- Fix xcsi2rxss_set_format()
v8
- Use clk_bulk* APIs
- Add gpio reset for asserting video_aresetn when stream line buffer occurs
- Removed short packet related events and irq handling
- V4L2_EVENT_XLNXCSIRX_SPKT and V4L2_EVENT_XLNXCSIRX_SPKT_OVF removed
- Removed frame counter control V4L2_CID_XILINX_MIPICSISS_FRAME_COUNTER
and xcsi2rxss_g_volatile_ctrl()
- Minor formatting fixes
v7
- No change
v6
- No change
v5
- Removed bayer and updated related parts like set default format based
on Luca Cersoli's comments.
- Added correct YUV422 10bpc media bus format
v4
- Removed irq member from core structure
- Consolidated IP config prints in xcsi2rxss_log_ipconfig()
- Return -EINVAL in case of invalid ioctl
- Code formatting
- Added reviewed by Hyun Kwon
v3
- Fixed comments given by Hyun.
- Removed DPHY 200 MHz clock. This will be controlled by DPHY driver
- Minor code formatting
- en_csi_v20 and vfb members removed from struct and made local to dt parsing
- lock description updated
- changed to ratelimited type for all dev prints in irq handler
- Removed YUV 422 10bpc media format
v2
- Fixed comments given by Hyun and Sakari.
- Made all bitmask using BIT() and GENMASK()
- Removed unused definitions
- Removed DPHY access. This will be done by separate DPHY PHY driver.
- Added support for CSI v2.0 for YUV 422 10bpc, RAW16, RAW20 and extra
virtual channels
- Fixed the ports as sink and source
- Now use the v4l2fwnode API to get number of data-lanes
- Added clock framework support
- Removed the close() function
- updated the set format function
- support only VFB enabled configuration
drivers/media/platform/xilinx/Kconfig | 7 +
drivers/media/platform/xilinx/Makefile | 1 +
.../media/platform/xilinx/xilinx-csi2rxss.c | 1114 +++++++++++++++++
3 files changed, 1122 insertions(+)
create mode 100644 drivers/media/platform/xilinx/xilinx-csi2rxss.c
diff --git a/drivers/media/platform/xilinx/Kconfig b/drivers/media/platform/xilinx/Kconfig
index 01c96fb66414..44587dccacf1 100644
--- a/drivers/media/platform/xilinx/Kconfig
+++ b/drivers/media/platform/xilinx/Kconfig
@@ -12,6 +12,13 @@ config VIDEO_XILINX
if VIDEO_XILINX
+config VIDEO_XILINX_CSI2RXSS
+ tristate "Xilinx CSI-2 Rx Subsystem"
+ help
+ Driver for Xilinx MIPI CSI-2 Rx Subsystem. This is a V4L sub-device
+ based driver that takes input from CSI-2 Tx source and converts
+ it into an AXI4-Stream.
+
config VIDEO_XILINX_TPG
tristate "Xilinx Video Test Pattern Generator"
depends on VIDEO_XILINX
diff --git a/drivers/media/platform/xilinx/Makefile b/drivers/media/platform/xilinx/Makefile
index 4cdc0b1ec7a5..6119a34f3043 100644
--- a/drivers/media/platform/xilinx/Makefile
+++ b/drivers/media/platform/xilinx/Makefile
@@ -3,5 +3,6 @@
xilinx-video-objs += xilinx-dma.o xilinx-vip.o xilinx-vipp.o
obj-$(CONFIG_VIDEO_XILINX) += xilinx-video.o
+obj-$(CONFIG_VIDEO_XILINX_CSI2RXSS) += xilinx-csi2rxss.o
obj-$(CONFIG_VIDEO_XILINX_TPG) += xilinx-tpg.o
obj-$(CONFIG_VIDEO_XILINX_VTC) += xilinx-vtc.o
diff --git a/drivers/media/platform/xilinx/xilinx-csi2rxss.c b/drivers/media/platform/xilinx/xilinx-csi2rxss.c
new file mode 100644
index 000000000000..cac08149ae7a
--- /dev/null
+++ b/drivers/media/platform/xilinx/xilinx-csi2rxss.c
@@ -0,0 +1,1114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Xilinx MIPI CSI-2 Rx Subsystem
+ *
+ * Copyright (C) 2016 - 2020 Xilinx, Inc.
+ *
+ * Contacts: Vishal Sagar <vishal.sagar@xilinx.com>
+ *
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/v4l2-subdev.h>
+#include <media/media-entity.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+#include "xilinx-vip.h"
+
+/* Register register map */
+#define XCSI_CCR_OFFSET 0x00
+#define XCSI_CCR_SOFTRESET BIT(1)
+#define XCSI_CCR_ENABLE BIT(0)
+
+#define XCSI_PCR_OFFSET 0x04
+#define XCSI_PCR_MAXLANES_MASK GENMASK(4, 3)
+#define XCSI_PCR_ACTLANES_MASK GENMASK(1, 0)
+
+#define XCSI_CSR_OFFSET 0x10
+#define XCSI_CSR_PKTCNT GENMASK(31, 16)
+#define XCSI_CSR_SPFIFOFULL BIT(3)
+#define XCSI_CSR_SPFIFONE BIT(2)
+#define XCSI_CSR_SLBF BIT(1)
+#define XCSI_CSR_RIPCD BIT(0)
+
+#define XCSI_GIER_OFFSET 0x20
+#define XCSI_GIER_GIE BIT(0)
+
+#define XCSI_ISR_OFFSET 0x24
+#define XCSI_IER_OFFSET 0x28
+
+#define XCSI_ISR_FR BIT(31)
+#define XCSI_ISR_VCXFE BIT(30)
+#define XCSI_ISR_WCC BIT(22)
+#define XCSI_ISR_ILC BIT(21)
+#define XCSI_ISR_SPFIFOF BIT(20)
+#define XCSI_ISR_SPFIFONE BIT(19)
+#define XCSI_ISR_SLBF BIT(18)
+#define XCSI_ISR_STOP BIT(17)
+#define XCSI_ISR_SOTERR BIT(13)
+#define XCSI_ISR_SOTSYNCERR BIT(12)
+#define XCSI_ISR_ECC2BERR BIT(11)
+#define XCSI_ISR_ECC1BERR BIT(10)
+#define XCSI_ISR_CRCERR BIT(9)
+#define XCSI_ISR_DATAIDERR BIT(8)
+#define XCSI_ISR_VC3FSYNCERR BIT(7)
+#define XCSI_ISR_VC3FLVLERR BIT(6)
+#define XCSI_ISR_VC2FSYNCERR BIT(5)
+#define XCSI_ISR_VC2FLVLERR BIT(4)
+#define XCSI_ISR_VC1FSYNCERR BIT(3)
+#define XCSI_ISR_VC1FLVLERR BIT(2)
+#define XCSI_ISR_VC0FSYNCERR BIT(1)
+#define XCSI_ISR_VC0FLVLERR BIT(0)
+
+#define XCSI_ISR_ALLINTR_MASK (0xc07e3fff)
+
+/*
+ * Removed VCXFE mask as it doesn't exist in IER
+ * Removed STOP state irq as this will keep driver in irq handler only
+ */
+#define XCSI_IER_INTR_MASK (XCSI_ISR_ALLINTR_MASK &\
+ ~(XCSI_ISR_STOP | XCSI_ISR_VCXFE))
+
+#define XCSI_SPKTR_OFFSET 0x30
+#define XCSI_SPKTR_DATA GENMASK(23, 8)
+#define XCSI_SPKTR_VC GENMASK(7, 6)
+#define XCSI_SPKTR_DT GENMASK(5, 0)
+#define XCSI_SPKT_FIFO_DEPTH 31
+
+#define XCSI_VCXR_OFFSET 0x34
+#define XCSI_VCXR_VCERR GENMASK(23, 0)
+#define XCSI_VCXR_FSYNCERR BIT(1)
+#define XCSI_VCXR_FLVLERR BIT(0)
+
+#define XCSI_CLKINFR_OFFSET 0x3C
+#define XCSI_CLKINFR_STOP BIT(1)
+
+#define XCSI_DLXINFR_OFFSET 0x40
+#define XCSI_DLXINFR_STOP BIT(5)
+#define XCSI_DLXINFR_SOTERR BIT(1)
+#define XCSI_DLXINFR_SOTSYNCERR BIT(0)
+#define XCSI_MAXDL_COUNT 0x4
+
+#define XCSI_VCXINF1R_OFFSET 0x60
+#define XCSI_VCXINF1R_LINECOUNT GENMASK(31, 16)
+#define XCSI_VCXINF1R_LINECOUNT_SHIFT 16
+#define XCSI_VCXINF1R_BYTECOUNT GENMASK(15, 0)
+
+#define XCSI_VCXINF2R_OFFSET 0x64
+#define XCSI_VCXINF2R_DT GENMASK(5, 0)
+#define XCSI_MAXVCX_COUNT 16
+
+/*
+ * Sink pad connected to sensor source pad.
+ * Source pad connected to next module like demosaic.
+ */
+#define XCSI_MEDIA_PADS 2
+#define XCSI_DEFAULT_WIDTH 1920
+#define XCSI_DEFAULT_HEIGHT 1080
+
+/* MIPI CSI-2 Data Types from spec */
+#define XCSI_DT_YUV4228B 0x1e
+#define XCSI_DT_YUV42210B 0x1f
+#define XCSI_DT_RGB444 0x20
+#define XCSI_DT_RGB555 0x21
+#define XCSI_DT_RGB565 0x22
+#define XCSI_DT_RGB666 0x23
+#define XCSI_DT_RGB888 0x24
+#define XCSI_DT_RAW6 0x28
+#define XCSI_DT_RAW7 0x29
+#define XCSI_DT_RAW8 0x2a
+#define XCSI_DT_RAW10 0x2b
+#define XCSI_DT_RAW12 0x2c
+#define XCSI_DT_RAW14 0x2d
+#define XCSI_DT_RAW16 0x2e
+#define XCSI_DT_RAW20 0x2f
+
+#define XCSI_VCX_START 4
+#define XCSI_MAX_VC 4
+#define XCSI_MAX_VCX 16
+
+#define XCSI_NEXTREG_OFFSET 4
+
+/* There are 2 events frame sync and frame level error per VC */
+#define XCSI_VCX_NUM_EVENTS ((XCSI_MAX_VCX - XCSI_MAX_VC) * 2)
+
+/**
+ * struct xcsi2rxss_event - Event log structure
+ * @mask: Event mask
+ * @name: Name of the event
+ */
+struct xcsi2rxss_event {
+ u32 mask;
+ const char *name;
+};
+
+static const struct xcsi2rxss_event xcsi2rxss_events[] = {
+ { XCSI_ISR_FR, "Frame Received" },
+ { XCSI_ISR_VCXFE, "VCX Frame Errors" },
+ { XCSI_ISR_WCC, "Word Count Errors" },
+ { XCSI_ISR_ILC, "Invalid Lane Count Error" },
+ { XCSI_ISR_SPFIFOF, "Short Packet FIFO OverFlow Error" },
+ { XCSI_ISR_SPFIFONE, "Short Packet FIFO Not Empty" },
+ { XCSI_ISR_SLBF, "Streamline Buffer Full Error" },
+ { XCSI_ISR_STOP, "Lane Stop State" },
+ { XCSI_ISR_SOTERR, "SOT Error" },
+ { XCSI_ISR_SOTSYNCERR, "SOT Sync Error" },
+ { XCSI_ISR_ECC2BERR, "2 Bit ECC Unrecoverable Error" },
+ { XCSI_ISR_ECC1BERR, "1 Bit ECC Recoverable Error" },
+ { XCSI_ISR_CRCERR, "CRC Error" },
+ { XCSI_ISR_DATAIDERR, "Data Id Error" },
+ { XCSI_ISR_VC3FSYNCERR, "Virtual Channel 3 Frame Sync Error" },
+ { XCSI_ISR_VC3FLVLERR, "Virtual Channel 3 Frame Level Error" },
+ { XCSI_ISR_VC2FSYNCERR, "Virtual Channel 2 Frame Sync Error" },
+ { XCSI_ISR_VC2FLVLERR, "Virtual Channel 2 Frame Level Error" },
+ { XCSI_ISR_VC1FSYNCERR, "Virtual Channel 1 Frame Sync Error" },
+ { XCSI_ISR_VC1FLVLERR, "Virtual Channel 1 Frame Level Error" },
+ { XCSI_ISR_VC0FSYNCERR, "Virtual Channel 0 Frame Sync Error" },
+ { XCSI_ISR_VC0FLVLERR, "Virtual Channel 0 Frame Level Error" }
+};
+
+#define XCSI_NUM_EVENTS ARRAY_SIZE(xcsi2rxss_events)
+
+/*
+ * This table provides a mapping between CSI-2 Data type
+ * and media bus formats
+ */
+static const u32 xcsi2dt_mbus_lut[][2] = {
+ { XCSI_DT_YUV4228B, MEDIA_BUS_FMT_UYVY8_1X16 },
+ { XCSI_DT_YUV42210B, MEDIA_BUS_FMT_UYVY10_1X20 },
+ { XCSI_DT_RGB444, 0 },
+ { XCSI_DT_RGB555, 0 },
+ { XCSI_DT_RGB565, 0 },
+ { XCSI_DT_RGB666, 0 },
+ { XCSI_DT_RGB888, MEDIA_BUS_FMT_RBG888_1X24 },
+ { XCSI_DT_RAW6, 0 },
+ { XCSI_DT_RAW7, 0 },
+ { XCSI_DT_RAW8, MEDIA_BUS_FMT_SRGGB8_1X8 },
+ { XCSI_DT_RAW8, MEDIA_BUS_FMT_SBGGR8_1X8 },
+ { XCSI_DT_RAW8, MEDIA_BUS_FMT_SGBRG8_1X8 },
+ { XCSI_DT_RAW8, MEDIA_BUS_FMT_SGRBG8_1X8 },
+ { XCSI_DT_RAW10, MEDIA_BUS_FMT_SRGGB10_1X10 },
+ { XCSI_DT_RAW10, MEDIA_BUS_FMT_SBGGR10_1X10 },
+ { XCSI_DT_RAW10, MEDIA_BUS_FMT_SGBRG10_1X10 },
+ { XCSI_DT_RAW10, MEDIA_BUS_FMT_SGRBG10_1X10 },
+ { XCSI_DT_RAW12, MEDIA_BUS_FMT_SRGGB12_1X12 },
+ { XCSI_DT_RAW12, MEDIA_BUS_FMT_SBGGR12_1X12 },
+ { XCSI_DT_RAW12, MEDIA_BUS_FMT_SGBRG12_1X12 },
+ { XCSI_DT_RAW12, MEDIA_BUS_FMT_SGRBG12_1X12 },
+ { XCSI_DT_RAW16, MEDIA_BUS_FMT_SRGGB16_1X16 },
+ { XCSI_DT_RAW16, MEDIA_BUS_FMT_SBGGR16_1X16 },
+ { XCSI_DT_RAW16, MEDIA_BUS_FMT_SGBRG16_1X16 },
+ { XCSI_DT_RAW16, MEDIA_BUS_FMT_SGRBG16_1X16 },
+ { XCSI_DT_RAW20, 0 },
+};
+
+/**
+ * struct xcsi2rxss_state - CSI-2 Rx Subsystem device structure
+ * @subdev: The v4l2 subdev structure
+ * @format: Active V4L2 formats on each pad
+ * @default_format: Default V4L2 format
+ * @events: counter for events
+ * @vcx_events: counter for vcx_events
+ * @dev: Platform structure
+ * @rsubdev: Remote subdev connected to sink pad
+ * @rst_gpio: reset to video_aresetn
+ * @clks: array of clocks
+ * @iomem: Base address of subsystem
+ * @max_num_lanes: Maximum number of lanes present
+ * @datatype: Data type filter
+ * @lock: mutex for accessing this structure
+ * @pads: media pads
+ * @streaming: Flag for storing streaming state
+ * @enable_active_lanes: If number of active lanes can be modified
+ * @en_vcx: If more than 4 VC are enabled
+ *
+ * This structure contains the device driver related parameters
+ */
+struct xcsi2rxss_state {
+ struct v4l2_subdev subdev;
+ struct v4l2_mbus_framefmt format;
+ struct v4l2_mbus_framefmt default_format;
+ u32 events[XCSI_NUM_EVENTS];
+ u32 vcx_events[XCSI_VCX_NUM_EVENTS];
+ struct device *dev;
+ struct v4l2_subdev *rsubdev;
+ struct gpio_desc *rst_gpio;
+ struct clk_bulk_data *clks;
+ void __iomem *iomem;
+ u32 max_num_lanes;
+ u32 datatype;
+ /* used to protect access to this struct */
+ struct mutex lock;
+ struct media_pad pads[XCSI_MEDIA_PADS];
+ bool streaming;
+ bool enable_active_lanes;
+ bool en_vcx;
+};
+
+static const struct clk_bulk_data xcsi2rxss_clks[] = {
+ { .id = "lite_aclk" },
+ { .id = "video_aclk" },
+};
+
+static inline struct xcsi2rxss_state *
+to_xcsi2rxssstate(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct xcsi2rxss_state, subdev);
+}
+
+/*
+ * Register related operations
+ */
+static inline u32 xcsi2rxss_read(struct xcsi2rxss_state *xcsi2rxss, u32 addr)
+{
+ return ioread32(xcsi2rxss->iomem + addr);
+}
+
+static inline void xcsi2rxss_write(struct xcsi2rxss_state *xcsi2rxss, u32 addr,
+ u32 value)
+{
+ iowrite32(value, xcsi2rxss->iomem + addr);
+}
+
+static inline void xcsi2rxss_clr(struct xcsi2rxss_state *xcsi2rxss, u32 addr,
+ u32 clr)
+{
+ xcsi2rxss_write(xcsi2rxss, addr,
+ xcsi2rxss_read(xcsi2rxss, addr) & ~clr);
+}
+
+static inline void xcsi2rxss_set(struct xcsi2rxss_state *xcsi2rxss, u32 addr,
+ u32 set)
+{
+ xcsi2rxss_write(xcsi2rxss, addr, xcsi2rxss_read(xcsi2rxss, addr) | set);
+}
+
+/*
+ * This function returns the nth mbus for a data type.
+ * In case of error, mbus code returned is 0.
+ */
+static u32 xcsi2rxss_get_nth_mbus(u32 dt, u32 n)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(xcsi2dt_mbus_lut); i++) {
+ if (xcsi2dt_mbus_lut[i][0] == dt) {
+ if (n-- == 0)
+ return xcsi2dt_mbus_lut[i][1];
+ }
+ }
+
+ return 0;
+}
+
+/* This returns the data type for a media bus format else 0 */
+static u32 xcsi2rxss_get_dt(u32 mbus)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(xcsi2dt_mbus_lut); i++) {
+ if (xcsi2dt_mbus_lut[i][1] == mbus)
+ return xcsi2dt_mbus_lut[i][0];
+ }
+
+ return 0;
+}
+
+/**
+ * xcsi2rxss_soft_reset - Does a soft reset of the MIPI CSI-2 Rx Subsystem
+ * @state: Xilinx CSI-2 Rx Subsystem structure pointer
+ *
+ * Core takes less than 100 video clock cycles to reset.
+ * So a larger timeout value is chosen for margin.
+ *
+ * Return: 0 - on success OR -ETIME if reset times out
+ */
+static int xcsi2rxss_soft_reset(struct xcsi2rxss_state *state)
+{
+ u32 timeout = 1000; /* us */
+
+ xcsi2rxss_set(state, XCSI_CCR_OFFSET, XCSI_CCR_SOFTRESET);
+
+ while (xcsi2rxss_read(state, XCSI_CSR_OFFSET) & XCSI_CSR_RIPCD) {
+ if (timeout == 0) {
+ dev_err(state->dev, "soft reset timed out!\n");
+ return -ETIME;
+ }
+
+ timeout--;
+ udelay(1);
+ }
+
+ xcsi2rxss_clr(state, XCSI_CCR_OFFSET, XCSI_CCR_SOFTRESET);
+ return 0;
+}
+
+static void xcsi2rxss_hard_reset(struct xcsi2rxss_state *state)
+{
+ if (!state->rst_gpio)
+ return;
+
+ /* minimum of 40 dphy_clk_200M cycles */
+ gpiod_set_value_cansleep(state->rst_gpio, 1);
+ usleep_range(1, 2);
+ gpiod_set_value_cansleep(state->rst_gpio, 0);
+}
+
+static void xcsi2rxss_reset_event_counters(struct xcsi2rxss_state *state)
+{
+ unsigned int i;
+
+ for (i = 0; i < XCSI_NUM_EVENTS; i++)
+ state->events[i] = 0;
+
+ for (i = 0; i < XCSI_VCX_NUM_EVENTS; i++)
+ state->vcx_events[i] = 0;
+}
+
+/* Print event counters */
+static void xcsi2rxss_log_counters(struct xcsi2rxss_state *state)
+{
+ struct device *dev = state->dev;
+ unsigned int i;
+
+ for (i = 0; i < XCSI_NUM_EVENTS; i++) {
+ if (state->events[i] > 0) {
+ dev_info(dev, "%s events: %d\n",
+ xcsi2rxss_events[i].name,
+ state->events[i]);
+ }
+ }
+
+ if (state->en_vcx) {
+ for (i = 0; i < XCSI_VCX_NUM_EVENTS; i++) {
+ if (state->vcx_events[i] > 0) {
+ dev_info(dev,
+ "VC %d Frame %s err vcx events: %d\n",
+ (i / 2) + XCSI_VCX_START,
+ i & 1 ? "Sync" : "Level",
+ state->vcx_events[i]);
+ }
+ }
+ }
+}
+
+/**
+ * xcsi2rxss_log_status - Logs the status of the CSI-2 Receiver
+ * @sd: Pointer to V4L2 subdevice structure
+ *
+ * This function prints the current status of Xilinx MIPI CSI-2
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_log_status(struct v4l2_subdev *sd)
+{
+ struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+ struct device *dev = xcsi2rxss->dev;
+ const char *tr = "true";
+ const char *fa = "false";
+ u32 reg, data;
+ unsigned int i, max_vc;
+
+ mutex_lock(&xcsi2rxss->lock);
+
+ xcsi2rxss_log_counters(xcsi2rxss);
+
+ dev_info(dev, "***** Core Status *****\n");
+ data = xcsi2rxss_read(xcsi2rxss, XCSI_CSR_OFFSET);
+ dev_info(dev, "Short Packet FIFO Full = %s\n",
+ data & XCSI_CSR_SPFIFOFULL ? tr : fa);
+ dev_info(dev, "Short Packet FIFO Not Empty = %s\n",
+ data & XCSI_CSR_SPFIFONE ? tr : fa);
+ dev_info(dev, "Stream line buffer full = %s\n",
+ data & XCSI_CSR_SLBF ? tr : fa);
+ dev_info(dev, "Soft reset/Core disable in progress = %s\n",
+ data & XCSI_CSR_RIPCD ? tr : fa);
+
+ /* Clk & Lane Info */
+ dev_info(dev, "******** Clock Lane Info *********\n");
+ data = xcsi2rxss_read(xcsi2rxss, XCSI_CLKINFR_OFFSET);
+ dev_info(dev, "Clock Lane in Stop State = %s\n",
+ data & XCSI_CLKINFR_STOP ? tr : fa);
+
+ dev_info(dev, "******** Data Lane Info *********\n");
+ dev_info(dev, "Lane\tSoT Error\tSoT Sync Error\tStop State\n");
+ reg = XCSI_DLXINFR_OFFSET;
+ for (i = 0; i < XCSI_MAXDL_COUNT; i++) {
+ data = xcsi2rxss_read(xcsi2rxss, reg);
+
+ dev_info(dev, "%d\t%s\t\t%s\t\t%s\n", i,
+ data & XCSI_DLXINFR_SOTERR ? tr : fa,
+ data & XCSI_DLXINFR_SOTSYNCERR ? tr : fa,
+ data & XCSI_DLXINFR_STOP ? tr : fa);
+
+ reg += XCSI_NEXTREG_OFFSET;
+ }
+
+ /* Virtual Channel Image Information */
+ dev_info(dev, "********** Virtual Channel Info ************\n");
+ dev_info(dev, "VC\tLine Count\tByte Count\tData Type\n");
+ if (xcsi2rxss->en_vcx)
+ max_vc = XCSI_MAX_VCX;
+ else
+ max_vc = XCSI_MAX_VC;
+
+ reg = XCSI_VCXINF1R_OFFSET;
+ for (i = 0; i < max_vc; i++) {
+ u32 line_count, byte_count, data_type;
+
+ /* Get line and byte count from VCXINFR1 Register */
+ data = xcsi2rxss_read(xcsi2rxss, reg);
+ byte_count = data & XCSI_VCXINF1R_BYTECOUNT;
+ line_count = data & XCSI_VCXINF1R_LINECOUNT;
+ line_count >>= XCSI_VCXINF1R_LINECOUNT_SHIFT;
+
+ /* Get data type from VCXINFR2 Register */
+ reg += XCSI_NEXTREG_OFFSET;
+ data = xcsi2rxss_read(xcsi2rxss, reg);
+ data_type = data & XCSI_VCXINF2R_DT;
+
+ dev_info(dev, "%d\t%d\t\t%d\t\t0x%x\n", i, line_count,
+ byte_count, data_type);
+
+ /* Move to next pair of VC Info registers */
+ reg += XCSI_NEXTREG_OFFSET;
+ }
+
+ mutex_unlock(&xcsi2rxss->lock);
+
+ return 0;
+}
+
+static struct v4l2_subdev *xcsi2rxss_get_remote_subdev(struct media_pad *local)
+{
+ struct media_pad *remote;
+
+ remote = media_entity_remote_pad(local);
+ if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
+ return NULL;
+
+ return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+static int xcsi2rxss_start_stream(struct xcsi2rxss_state *state)
+{
+ int ret = 0;
+
+ /* enable core */
+ xcsi2rxss_set(state, XCSI_CCR_OFFSET, XCSI_CCR_ENABLE);
+
+ ret = xcsi2rxss_soft_reset(state);
+ if (ret < 0) {
+ state->streaming = false;
+ return ret;
+ }
+
+ /* enable interrupts */
+ xcsi2rxss_clr(state, XCSI_GIER_OFFSET, XCSI_GIER_GIE);
+ xcsi2rxss_write(state, XCSI_IER_OFFSET, XCSI_IER_INTR_MASK);
+ xcsi2rxss_set(state, XCSI_GIER_OFFSET, XCSI_GIER_GIE);
+
+ state->streaming = true;
+
+ state->rsubdev =
+ xcsi2rxss_get_remote_subdev(&state->pads[XVIP_PAD_SINK]);
+
+ ret = v4l2_subdev_call(state->rsubdev, video, s_stream, 1);
+ if (ret) {
+ /* disable interrupts */
+ xcsi2rxss_clr(state, XCSI_IER_OFFSET, XCSI_IER_INTR_MASK);
+ xcsi2rxss_clr(state, XCSI_GIER_OFFSET, XCSI_GIER_GIE);
+
+ /* disable core */
+ xcsi2rxss_clr(state, XCSI_CCR_OFFSET, XCSI_CCR_ENABLE);
+ state->streaming = false;
+ }
+
+ return ret;
+}
+
+static void xcsi2rxss_stop_stream(struct xcsi2rxss_state *state)
+{
+ v4l2_subdev_call(state->rsubdev, video, s_stream, 0);
+
+ /* disable interrupts */
+ xcsi2rxss_clr(state, XCSI_IER_OFFSET, XCSI_IER_INTR_MASK);
+ xcsi2rxss_clr(state, XCSI_GIER_OFFSET, XCSI_GIER_GIE);
+
+ /* disable core */
+ xcsi2rxss_clr(state, XCSI_CCR_OFFSET, XCSI_CCR_ENABLE);
+ state->streaming = false;
+}
+
+/**
+ * xcsi2rxss_irq_handler - Interrupt handler for CSI-2
+ * @irq: IRQ number
+ * @data: Pointer to device state
+ *
+ * In the interrupt handler, a list of event counters are updated for
+ * corresponding interrupts. This is useful to get status / debug.
+ *
+ * Return: IRQ_HANDLED after handling interrupts
+ */
+static irqreturn_t xcsi2rxss_irq_handler(int irq, void *data)
+{
+ struct xcsi2rxss_state *state = (struct xcsi2rxss_state *)data;
+ struct device *dev = state->dev;
+ u32 status;
+
+ status = xcsi2rxss_read(state, XCSI_ISR_OFFSET) & XCSI_ISR_ALLINTR_MASK;
+ xcsi2rxss_write(state, XCSI_ISR_OFFSET, status);
+
+ /* Received a short packet */
+ if (status & XCSI_ISR_SPFIFONE) {
+ u32 count = 0;
+
+ /*
+ * Drain generic short packet FIFO by reading max 31
+ * (fifo depth) short packets from fifo or till fifo is empty.
+ */
+ for (count = 0; count < XCSI_SPKT_FIFO_DEPTH; ++count) {
+ u32 spfifostat, spkt;
+
+ spkt = xcsi2rxss_read(state, XCSI_SPKTR_OFFSET);
+ dev_dbg(dev, "Short packet = 0x%08x\n", spkt);
+ spfifostat = xcsi2rxss_read(state, XCSI_ISR_OFFSET);
+ spfifostat &= XCSI_ISR_SPFIFONE;
+ if (!spfifostat)
+ break;
+ xcsi2rxss_write(state, XCSI_ISR_OFFSET, spfifostat);
+ }
+ }
+
+ /* Short packet FIFO overflow */
+ if (status & XCSI_ISR_SPFIFOF)
+ dev_dbg_ratelimited(dev, "Short packet FIFO overflowed\n");
+
+ /*
+ * Stream line buffer full
+ * This means there is a backpressure from downstream IP
+ */
+ if (status & XCSI_ISR_SLBF) {
+ dev_alert_ratelimited(dev, "Stream Line Buffer Full!\n");
+
+ /* disable interrupts */
+ xcsi2rxss_clr(state, XCSI_IER_OFFSET, XCSI_IER_INTR_MASK);
+ xcsi2rxss_clr(state, XCSI_GIER_OFFSET, XCSI_GIER_GIE);
+
+ /* disable core */
+ xcsi2rxss_clr(state, XCSI_CCR_OFFSET, XCSI_CCR_ENABLE);
+ state->streaming = false;
+
+ /*
+ * The IP needs to be hard reset before it can be used now.
+ * This will be done in streamoff.
+ */
+
+ /*
+ * TODO: Notify the whole pipeline with v4l2_subdev_notify() to
+ * inform userspace.
+ */
+ }
+
+ /* Increment event counters */
+ if (status & XCSI_ISR_ALLINTR_MASK) {
+ unsigned int i;
+
+ for (i = 0; i < XCSI_NUM_EVENTS; i++) {
+ if (!(status & xcsi2rxss_events[i].mask))
+ continue;
+ state->events[i]++;
+ dev_dbg_ratelimited(dev, "%s: %u\n",
+ xcsi2rxss_events[i].name,
+ state->events[i]);
+ }
+
+ if (status & XCSI_ISR_VCXFE && state->en_vcx) {
+ u32 vcxstatus;
+
+ vcxstatus = xcsi2rxss_read(state, XCSI_VCXR_OFFSET);
+ vcxstatus &= XCSI_VCXR_VCERR;
+ for (i = 0; i < XCSI_VCX_NUM_EVENTS; i++) {
+ if (!(vcxstatus & (1 << i)))
+ continue;
+ state->vcx_events[i]++;
+ }
+ xcsi2rxss_write(state, XCSI_VCXR_OFFSET, vcxstatus);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * xcsi2rxss_s_stream - It is used to start/stop the streaming.
+ * @sd: V4L2 Sub device
+ * @enable: Flag (True / False)
+ *
+ * This function controls the start or stop of streaming for the
+ * Xilinx MIPI CSI-2 Rx Subsystem.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xcsi2rxss_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+ int ret = 0;
+
+ mutex_lock(&xcsi2rxss->lock);
+
+ if (enable == xcsi2rxss->streaming)
+ goto stream_done;
+
+ if (enable) {
+ xcsi2rxss_reset_event_counters(xcsi2rxss);
+ ret = xcsi2rxss_start_stream(xcsi2rxss);
+ } else {
+ xcsi2rxss_stop_stream(xcsi2rxss);
+ xcsi2rxss_hard_reset(xcsi2rxss);
+ }
+
+stream_done:
+ mutex_unlock(&xcsi2rxss->lock);
+ return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__xcsi2rxss_get_pad_format(struct xcsi2rxss_state *xcsi2rxss,
+ struct v4l2_subdev_pad_config *cfg,
+ unsigned int pad, u32 which)
+{
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_format(&xcsi2rxss->subdev, cfg, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &xcsi2rxss->format;
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * xcsi2rxss_init_cfg - Initialise the pad format config to default
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ *
+ * This function is used to initialize the pad format with the default
+ * values.
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg)
+{
+ struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+ struct v4l2_mbus_framefmt *format;
+ unsigned int i;
+
+ mutex_lock(&xcsi2rxss->lock);
+ for (i = 0; i < XCSI_MEDIA_PADS; i++) {
+ format = v4l2_subdev_get_try_format(sd, cfg, i);
+ *format = xcsi2rxss->default_format;
+ }
+ mutex_unlock(&xcsi2rxss->lock);
+
+ return 0;
+}
+
+/**
+ * xcsi2rxss_get_format - Get the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to get the pad format information.
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_get_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+
+ mutex_lock(&xcsi2rxss->lock);
+ fmt->format = *__xcsi2rxss_get_pad_format(xcsi2rxss, cfg, fmt->pad,
+ fmt->which);
+ mutex_unlock(&xcsi2rxss->lock);
+
+ return 0;
+}
+
+/**
+ * xcsi2rxss_set_format - This is used to set the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to set the pad format. Since the pad format is fixed
+ * in hardware, it can't be modified on run time. So when a format set is
+ * requested by application, all parameters except the format type is saved
+ * for the pad and the original pad format is sent back to the application.
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+ struct v4l2_mbus_framefmt *__format;
+ u32 dt;
+
+ /* only sink pad format can be updated */
+ mutex_lock(&xcsi2rxss->lock);
+
+ /*
+ * Only the format->code parameter matters for CSI as the
+ * CSI format cannot be changed at runtime.
+ * Ensure that format to set is copied to over to CSI pad format
+ */
+ __format = __xcsi2rxss_get_pad_format(xcsi2rxss, cfg,
+ fmt->pad, fmt->which);
+
+ if (fmt->pad == XVIP_PAD_SOURCE) {
+ fmt->format = *__format;
+ mutex_unlock(&xcsi2rxss->lock);
+ return 0;
+ }
+
+ /*
+ * RAW8 is supported in all datatypes. So if requested media bus format
+ * is of RAW8 type, then allow to be set. In case core is configured to
+ * other RAW, YUV422 8/10 or RGB888, set appropriate media bus format.
+ */
+ dt = xcsi2rxss_get_dt(fmt->format.code);
+ if (dt != xcsi2rxss->datatype && dt != XCSI_DT_RAW8) {
+ dev_dbg(xcsi2rxss->dev, "Unsupported media bus format");
+ /* set the default format for the data type */
+ fmt->format.code = xcsi2rxss_get_nth_mbus(xcsi2rxss->datatype,
+ 0);
+ }
+
+ *__format = fmt->format;
+ mutex_unlock(&xcsi2rxss->lock);
+
+ return 0;
+}
+
+/*
+ * xcsi2rxss_enum_mbus_code - Handle pixel format enumeration
+ * @sd : pointer to v4l2 subdev structure
+ * @cfg: V4L2 subdev pad configuration
+ * @code : pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Return: -EINVAL or zero on success
+ */
+int xcsi2rxss_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct xcsi2rxss_state *state = to_xcsi2rxssstate(sd);
+ u32 dt, n;
+ int ret = 0;
+
+ /* RAW8 dt packets are available in all DT configurations */
+ if (code->index < 4) {
+ n = code->index;
+ dt = XCSI_DT_RAW8;
+ } else if (state->datatype != XCSI_DT_RAW8) {
+ n = code->index - 4;
+ dt = state->datatype;
+ } else {
+ return -EINVAL;
+ }
+
+ code->code = xcsi2rxss_get_nth_mbus(dt, n);
+ if (!code->code)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xcsi2rxss_media_ops = {
+ .link_validate = v4l2_subdev_link_validate
+};
+
+static const struct v4l2_subdev_core_ops xcsi2rxss_core_ops = {
+ .log_status = xcsi2rxss_log_status,
+};
+
+static const struct v4l2_subdev_video_ops xcsi2rxss_video_ops = {
+ .s_stream = xcsi2rxss_s_stream
+};
+
+static const struct v4l2_subdev_pad_ops xcsi2rxss_pad_ops = {
+ .init_cfg = xcsi2rxss_init_cfg,
+ .get_fmt = xcsi2rxss_get_format,
+ .set_fmt = xcsi2rxss_set_format,
+ .enum_mbus_code = xcsi2rxss_enum_mbus_code,
+ .link_validate = v4l2_subdev_link_validate_default,
+};
+
+static const struct v4l2_subdev_ops xcsi2rxss_ops = {
+ .core = &xcsi2rxss_core_ops,
+ .video = &xcsi2rxss_video_ops,
+ .pad = &xcsi2rxss_pad_ops
+};
+
+static int xcsi2rxss_parse_of(struct xcsi2rxss_state *xcsi2rxss)
+{
+ struct device *dev = xcsi2rxss->dev;
+ struct device_node *node = dev->of_node;
+
+ struct fwnode_handle *ep;
+ struct v4l2_fwnode_endpoint vep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ bool en_csi_v20, vfb;
+ int ret;
+
+ en_csi_v20 = of_property_read_bool(node, "xlnx,en-csi-v2-0");
+ if (en_csi_v20)
+ xcsi2rxss->en_vcx = of_property_read_bool(node, "xlnx,en-vcx");
+
+ xcsi2rxss->enable_active_lanes =
+ of_property_read_bool(node, "xlnx,en-active-lanes");
+
+ ret = of_property_read_u32(node, "xlnx,csi-pxl-format",
+ &xcsi2rxss->datatype);
+ if (ret < 0) {
+ dev_err(dev, "missing xlnx,csi-pxl-format property\n");
+ return ret;
+ }
+
+ switch (xcsi2rxss->datatype) {
+ case XCSI_DT_YUV4228B:
+ case XCSI_DT_RGB444:
+ case XCSI_DT_RGB555:
+ case XCSI_DT_RGB565:
+ case XCSI_DT_RGB666:
+ case XCSI_DT_RGB888:
+ case XCSI_DT_RAW6:
+ case XCSI_DT_RAW7:
+ case XCSI_DT_RAW8:
+ case XCSI_DT_RAW10:
+ case XCSI_DT_RAW12:
+ case XCSI_DT_RAW14:
+ break;
+ case XCSI_DT_YUV42210B:
+ case XCSI_DT_RAW16:
+ case XCSI_DT_RAW20:
+ if (!en_csi_v20) {
+ ret = -EINVAL;
+ dev_dbg(dev, "enable csi v2 for this pixel format");
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ if (ret < 0) {
+ dev_err(dev, "invalid csi-pxl-format property!\n");
+ return ret;
+ }
+
+ vfb = of_property_read_bool(node, "xlnx,vfb");
+ if (!vfb) {
+ dev_err(dev, "operation without VFB is not supported\n");
+ return -EINVAL;
+ }
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+ XVIP_PAD_SINK, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (!ep) {
+ dev_err(dev, "no sink port found");
+ return -EINVAL;
+ }
+
+ ret = v4l2_fwnode_endpoint_parse(ep, &vep);
+ fwnode_handle_put(ep);
+ if (ret) {
+ dev_err(dev, "error parsing sink port");
+ return ret;
+ }
+
+ dev_dbg(dev, "mipi number lanes = %d\n",
+ vep.bus.mipi_csi2.num_data_lanes);
+
+ xcsi2rxss->max_num_lanes = vep.bus.mipi_csi2.num_data_lanes;
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+ XVIP_PAD_SOURCE, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (!ep) {
+ dev_err(dev, "no source port found");
+ return -EINVAL;
+ }
+
+ fwnode_handle_put(ep);
+
+ dev_dbg(dev, "vcx %s, %u data lanes (%s), data type 0x%02x\n",
+ xcsi2rxss->en_vcx ? "enabled" : "disabled",
+ xcsi2rxss->max_num_lanes,
+ xcsi2rxss->enable_active_lanes ? "dynamic" : "static",
+ xcsi2rxss->datatype);
+
+ return 0;
+}
+
+static int xcsi2rxss_probe(struct platform_device *pdev)
+{
+ struct v4l2_subdev *subdev;
+ struct xcsi2rxss_state *xcsi2rxss;
+ int num_clks = ARRAY_SIZE(xcsi2rxss_clks);
+ struct device *dev = &pdev->dev;
+ int irq, ret;
+
+ xcsi2rxss = devm_kzalloc(dev, sizeof(*xcsi2rxss), GFP_KERNEL);
+ if (!xcsi2rxss)
+ return -ENOMEM;
+
+ xcsi2rxss->dev = dev;
+
+ xcsi2rxss->clks = devm_kmemdup(dev, xcsi2rxss_clks,
+ sizeof(xcsi2rxss_clks), GFP_KERNEL);
+ if (!xcsi2rxss->clks)
+ return -ENOMEM;
+
+ /* Reset GPIO */
+ xcsi2rxss->rst_gpio = devm_gpiod_get_optional(dev, "video-reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(xcsi2rxss->rst_gpio)) {
+ if (PTR_ERR(xcsi2rxss->rst_gpio) != -EPROBE_DEFER)
+ dev_err(dev, "Video Reset GPIO not setup in DT");
+ return PTR_ERR(xcsi2rxss->rst_gpio);
+ }
+
+ ret = xcsi2rxss_parse_of(xcsi2rxss);
+ if (ret < 0)
+ return ret;
+
+ xcsi2rxss->iomem = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(xcsi2rxss->iomem))
+ return PTR_ERR(xcsi2rxss->iomem);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ xcsi2rxss_irq_handler, IRQF_ONESHOT,
+ dev_name(dev), xcsi2rxss);
+ if (ret) {
+ dev_err(dev, "Err = %d Interrupt handler reg failed!\n", ret);
+ return ret;
+ }
+
+ ret = clk_bulk_get(dev, num_clks, xcsi2rxss->clks);
+ if (ret)
+ return ret;
+
+ /* TODO: Enable/disable clocks at stream on/off time. */
+ ret = clk_bulk_prepare_enable(num_clks, xcsi2rxss->clks);
+ if (ret)
+ goto err_clk_put;
+
+ mutex_init(&xcsi2rxss->lock);
+
+ xcsi2rxss_hard_reset(xcsi2rxss);
+ xcsi2rxss_soft_reset(xcsi2rxss);
+
+ /* Initialize V4L2 subdevice and media entity */
+ xcsi2rxss->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+ xcsi2rxss->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+ /* Initialize the default format */
+ xcsi2rxss->default_format.code =
+ xcsi2rxss_get_nth_mbus(xcsi2rxss->datatype, 0);
+ xcsi2rxss->default_format.field = V4L2_FIELD_NONE;
+ xcsi2rxss->default_format.colorspace = V4L2_COLORSPACE_SRGB;
+ xcsi2rxss->default_format.width = XCSI_DEFAULT_WIDTH;
+ xcsi2rxss->default_format.height = XCSI_DEFAULT_HEIGHT;
+ xcsi2rxss->format = xcsi2rxss->default_format;
+
+ /* Initialize V4L2 subdevice and media entity */
+ subdev = &xcsi2rxss->subdev;
+ v4l2_subdev_init(subdev, &xcsi2rxss_ops);
+ subdev->dev = dev;
+ strscpy(subdev->name, dev_name(dev), sizeof(subdev->name));
+ subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+ subdev->entity.ops = &xcsi2rxss_media_ops;
+ v4l2_set_subdevdata(subdev, xcsi2rxss);
+
+ ret = media_entity_pads_init(&subdev->entity, XCSI_MEDIA_PADS,
+ xcsi2rxss->pads);
+ if (ret < 0)
+ goto error;
+
+ platform_set_drvdata(pdev, xcsi2rxss);
+
+ ret = v4l2_async_register_subdev(subdev);
+ if (ret < 0) {
+ dev_err(dev, "failed to register subdev\n");
+ goto error;
+ }
+
+ return 0;
+error:
+ media_entity_cleanup(&subdev->entity);
+ mutex_destroy(&xcsi2rxss->lock);
+ clk_bulk_disable_unprepare(num_clks, xcsi2rxss->clks);
+err_clk_put:
+ clk_bulk_put(num_clks, xcsi2rxss->clks);
+ return ret;
+}
+
+static int xcsi2rxss_remove(struct platform_device *pdev)
+{
+ struct xcsi2rxss_state *xcsi2rxss = platform_get_drvdata(pdev);
+ struct v4l2_subdev *subdev = &xcsi2rxss->subdev;
+ int num_clks = ARRAY_SIZE(xcsi2rxss_clks);
+
+ v4l2_async_unregister_subdev(subdev);
+ media_entity_cleanup(&subdev->entity);
+ mutex_destroy(&xcsi2rxss->lock);
+ clk_bulk_disable_unprepare(num_clks, xcsi2rxss->clks);
+ clk_bulk_put(num_clks, xcsi2rxss->clks);
+
+ return 0;
+}
+
+static const struct of_device_id xcsi2rxss_of_id_table[] = {
+ { .compatible = "xlnx,mipi-csi2-rx-subsystem-5.0", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, xcsi2rxss_of_id_table);
+
+static struct platform_driver xcsi2rxss_driver = {
+ .driver = {
+ .name = "xilinx-csi2rxss",
+ .of_match_table = xcsi2rxss_of_id_table,
+ },
+ .probe = xcsi2rxss_probe,
+ .remove = xcsi2rxss_remove,
+};
+
+module_platform_driver(xcsi2rxss_driver);
+
+MODULE_AUTHOR("Vishal Sagar <vsagar@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx MIPI CSI-2 Rx Subsystem Driver");
+MODULE_LICENSE("GPL v2");
--
2.21.0
^ permalink raw reply related
* [PATCH v13 1/2] media: dt-bindings: media: xilinx: Add Xilinx MIPI CSI-2 Rx Subsystem
From: Vishal Sagar @ 2020-05-12 15:19 UTC (permalink / raw)
To: Hyun Kwon, laurent.pinchart, mchehab, robh+dt, mark.rutland,
Michal Simek, linux-media, devicetree, hans.verkuil,
linux-arm-kernel, linux-kernel, Dinesh Kumar, Sandip Kothari,
Luca Ceresoli, Jacopo Mondi
Cc: Vishal Sagar, Hyun Kwon, Rob Herring
In-Reply-To: <20200512151947.120348-1-vishal.sagar@xilinx.com>
Add bindings documentation for Xilinx MIPI CSI-2 Rx Subsystem.
The Xilinx MIPI CSI-2 Rx Subsystem consists of a CSI-2 Rx controller, a
D-PHY in Rx mode and a Video Format Bridge.
Signed-off-by: Vishal Sagar <vishal.sagar@xilinx.com>
Reviewed-by: Hyun Kwon <hyun.kwon@xilinx.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Luca Ceresoli <luca@lucaceresoli.net>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v13
- Based on Laurent's suggestions
- Fixed the datatypes values as minimum and maximum
- condition added for en-vcx property
v12
- Moved to yaml format
- Update CSI-2 and D-PHY
- Mention that bindings for D-PHY not here
- reset -> video-reset
v11
- Modify compatible string from 4.0 to 5.0
v10
- No changes
v9
- Fix xlnx,vfb description.
- s/Optional/Required endpoint property.
- Move data-lanes description from Ports to endpoint property section.
v8
- Added reset-gpios optional property to assert video_aresetn
v7
- Removed the control name from dt bindings
- Updated the example dt node name to csi2rx
v6
- Added "control" after V4L2_CID_XILINX_MIPICSISS_ACT_LANES as suggested by Luca
- Added reviewed by Rob Herring
v5
- Incorporated comments by Luca Cersoli
- Removed DPHY clock from description and example
- Removed bayer pattern from device tree MIPI CSI IP
doesn't deal with bayer pattern.
v4
- Added reviewed by Hyun Kwon
v3
- removed interrupt parent as suggested by Rob
- removed dphy clock
- moved vfb to optional properties
- Added required and optional port properties section
- Added endpoint property section
v2
- updated the compatible string to latest version supported
- removed DPHY related parameters
- added CSI v2.0 related property (including VCX for supporting upto 16
virtual channels).
- modified csi-pxl-format from string to unsigned int type where the value
is as per the CSI specification
- Defined port 0 and port 1 as sink and source ports.
- Removed max-lanes property as suggested by Rob and Sakari
.../bindings/media/xilinx/xlnx,csi2rxss.yaml | 226 ++++++++++++++++++
1 file changed, 226 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml
diff --git a/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml b/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml
new file mode 100644
index 000000000000..b0885f461785
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml
@@ -0,0 +1,226 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/xilinx/xlnx,csi2rxss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx MIPI CSI-2 Receiver Subsystem
+
+maintainers:
+ - Vishal Sagar <vishal.sagar@xilinx.com>
+
+description: |
+ The Xilinx MIPI CSI-2 Receiver Subsystem is used to capture MIPI CSI-2
+ traffic from compliant camera sensors and send the output as AXI4 Stream
+ video data for image processing.
+ The subsystem consists of a MIPI D-PHY in slave mode which captures the
+ data packets. This is passed along the MIPI CSI-2 Rx IP which extracts the
+ packet data. The optional Video Format Bridge (VFB) converts this data to
+ AXI4 Stream video data.
+ For more details, please refer to PG232 Xilinx MIPI CSI-2 Receiver Subsystem.
+ Please note that this bindings includes only the MIPI CSI-2 Rx controller
+ and Video Format Bridge and not D-PHY.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - xlnx,mipi-csi2-rx-subsystem-5.0
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ description: List of clock specifiers
+ items:
+ - description: AXI Lite clock
+ - description: Video clock
+
+ clock-names:
+ items:
+ - const: lite_aclk
+ - const: video_aclk
+
+ xlnx,csi-pxl-format:
+ description: |
+ This denotes the CSI Data type selected in hw design.
+ Packets other than this data type (except for RAW8 and
+ User defined data types) will be filtered out.
+ Possible values are as below -
+ 0x1e - YUV4228B
+ 0x1f - YUV42210B
+ 0x20 - RGB444
+ 0x21 - RGB555
+ 0x22 - RGB565
+ 0x23 - RGB666
+ 0x24 - RGB888
+ 0x28 - RAW6
+ 0x29 - RAW7
+ 0x2a - RAW8
+ 0x2b - RAW10
+ 0x2c - RAW12
+ 0x2d - RAW14
+ 0x2e - RAW16
+ 0x2f - RAW20
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32
+ - anyOf:
+ - minimum: 0x1e
+ - maximum: 0x24
+ - minimum: 0x28
+ - maximum: 0x2f
+
+ xlnx,vfb:
+ type: boolean
+ description: Present when Video Format Bridge is enabled in IP configuration
+
+ xlnx,en-csi-v2-0:
+ type: boolean
+ description: Present if CSI v2 is enabled in IP configuration.
+
+ xlnx,en-vcx:
+ type: boolean
+ description: |
+ When present, there are maximum 16 virtual channels, else only 4.
+
+ xlnx,en-active-lanes:
+ type: boolean
+ description: |
+ Present if the number of active lanes can be re-configured at
+ runtime in the Protocol Configuration Register. Otherwise all lanes,
+ as set in IP configuration, are always active.
+
+ video-reset-gpios:
+ description: Optional specifier for a GPIO that asserts video_aresetn.
+ maxItems: 1
+
+ ports:
+ type: object
+
+ properties:
+ port@0:
+ type: object
+ description: |
+ Input / sink port node, single endpoint describing the
+ CSI-2 transmitter.
+
+ properties:
+ reg:
+ const: 0
+
+ endpoint:
+ type: object
+
+ properties:
+
+ data-lanes:
+ description: |
+ This is required only in the sink port 0 endpoint which
+ connects to MIPI CSI-2 source like sensor.
+ The possible values are -
+ 1 - For 1 lane enabled in IP.
+ 1 2 - For 2 lanes enabled in IP.
+ 1 2 3 - For 3 lanes enabled in IP.
+ 1 2 3 4 - For 4 lanes enabled in IP.
+ items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+
+ remote-endpoint: true
+
+ required:
+ - data-lanes
+ - remote-endpoint
+
+ additionalProperties: false
+
+ additionalProperties: false
+
+ port@1:
+ type: object
+ description: |
+ Output / source port node, endpoint describing modules
+ connected the CSI-2 receiver.
+
+ properties:
+
+ reg:
+ const: 1
+
+ endpoint:
+ type: object
+
+ properties:
+
+ remote-endpoint: true
+
+ required:
+ - remote-endpoint
+
+ additionalProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - xlnx,csi-pxl-format
+ - ports
+
+if:
+ not:
+ required:
+ - xlnx,en-csi-v2-0
+then:
+ properties:
+ xlnx,en-vcx: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ xcsi2rxss_1: csi2rx@a0020000 {
+ compatible = "xlnx,mipi-csi2-rx-subsystem-5.0";
+ reg = <0x0 0xa0020000 0x0 0x10000>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 95 4>;
+ xlnx,csi-pxl-format = <0x2a>;
+ xlnx,vfb;
+ xlnx,en-active-lanes;
+ xlnx,en-csi-v2-0;
+ xlnx,en-vcx;
+ clock-names = "lite_aclk", "video_aclk";
+ clocks = <&misc_clk_0>, <&misc_clk_1>;
+ video-reset-gpios = <&gpio 86 GPIO_ACTIVE_LOW>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ /* Sink port */
+ reg = <0>;
+ csiss_in: endpoint {
+ data-lanes = <1 2 3 4>;
+ /* MIPI CSI-2 Camera handle */
+ remote-endpoint = <&camera_out>;
+ };
+ };
+ port@1 {
+ /* Source port */
+ reg = <1>;
+ csiss_out: endpoint {
+ remote-endpoint = <&vproc_in>;
+ };
+ };
+ };
+ };
--
2.21.0
^ permalink raw reply related
* [PATCH v13 0/2] Add support for Xilinx CSI2 Receiver Subsystem
From: Vishal Sagar @ 2020-05-12 15:19 UTC (permalink / raw)
To: Hyun Kwon, laurent.pinchart, mchehab, robh+dt, mark.rutland,
Michal Simek, linux-media, devicetree, hans.verkuil,
linux-arm-kernel, linux-kernel, Dinesh Kumar, Sandip Kothari,
Luca Ceresoli, Jacopo Mondi
Cc: Vishal Sagar
Xilinx MIPI CSI-2 Receiver Subsystem
------------------------------------
The Xilinx MIPI CSI-2 Receiver Subsystem Soft IP consists of a D-PHY which
gets the data, a CSI-2 Receiver controller which parses the data and
converts it into AXIS data.
This stream output maybe connected to a Xilinx Video Format Bridge.
The maximum number of lanes supported is fixed in the design.
The pixel format set in design acts as a filter allowing only the selected
data type or RAW8 data packets. The D-PHY register access can be gated in
the design.
The device driver registers the MIPI CSI-2 Rx Subsystem as a V4L2 sub device
having 2 pads. The sink pad is connected to the MIPI camera sensor and
output pad is connected to the video node.
Refer to xlnx,csi2rxss.yaml for device tree node details.
This driver helps enable the core, setting and handling interrupts.
It logs the number of events occurring according to their type between
streaming ON and OFF.
The Xilinx CSI-2 Rx Subsystem outputs an AXI4 Stream data which can be
used for image processing. This data follows the video formats mentioned
in Xilinx UG934 when the Video Format Bridge is enabled.
v13
- 1/2
- Based on Laurent's suggestions
- Fixed the datatypes values as minimum and maximum
- condition added for en-vcx property
- 2/2
- Based on Laurent's suggestions
- Removed unnecessary debug statement for vep
- Added TODO for clock to enable disable at streamon/off
- Fix for index to start from 0 for get_nth_mbus_format
- Removed macro XCSI_TIMEOUT_VAL
- Remove ndelay from hard reset
- Remove hard reset from irq handler
- Fix short packet fifo clear
- Add TODO for v4l2_subdev_notify for SLBF error
- Fix the enable condition in s_stream
- Fix condition in xcsi2rxss_set_format
- Fix enum_mbus_code for double enumeration of RAW8 Data type
- Removed core struct
- Added reviewed by Laurent
v12
- 1/2
- Moved to yaml format
- 2/2
- Changes done as suggested by Laurent Pinchart and Luca Ceresoli
- Removed unused macros
- No local storage of supported formats
- Dropped init mbus fmts and removed xcsi2rxss_init_mbus_fmts()
- XCSI_GET_BITSET_STR removed
- Add data type and mbus LUT
- Added xcsi2rxss_get_nth_mbus() and xcsi2rxss_get_dt()
- Replaced all core->dev with dev in dev_dbg() and related debug prints
- Replaced xcsi2rxss_log_ipconfig() with single line
- Removed small functions to enable/disable interrupts and core
- Now save remote subdev in state struct before streaming on
- Made xcsi2rxss_reset as soft_reset()
- Added hard reset using video-reset gpio
- 2 modes one with delay and another sleep
- Instead of reset-gpios it is not video-reset-gpios
- In irq handler
- Moved clearing of ISR up
- Dump / empty short packet fifo
- Irq handler is now threaded
- Added init_cfg pad ops and removed open()
- Updated xcsi2rxss_set_format(), xcsi2rxss_enum_mbus_code() to use the dt mbus lut
- xcsi2rxss_set_default_format() updated
- Moved mutex_init()
- Updated graph handling
- Removed unnecessary prints
- devm_platform_ioremap_resource() and platform_get_irq()
v11
- 1/2
- Modified the compatible string to 5.0 from 4.0
- 2/2
- Fixed changes as suggested by Sakari Ailus
- Removed VIDEO_XILINX from KConfig
- Minor formatting
- Start / Stop upstream sub-device in xcsi2rxss_start_stream()
and xcsi2rxss_stop_stream()
- Added v4l2_subdev_link_validate_default() in v4l2_subdev_pad_ops()
- Use fwnode_graph_get_endpoint_by_id() instead of parsing by self
- Set bus type as V4L2_MBUS_CSI2_DPHY in struct v4l2_fwnode_endpoint
- Remove num_clks from core. Instead use ARRAY_SIZE()
- Fixed SPDX header to GPL-2.0
- Update copyright year to 2020
v10
- 1/2
- No changes
- 2/2
- Removed all V4L2 controls and events.
- Now stop_stream() before toggling rst_gpio
- Updated init_mbus() to throw error on array out of bound access
- Added XADD_MBUS macro
- Make events and vcx_events as counters instead of structures
- Minor fixes in set_format() enum_mbus_code() as suggested by Sakari
v9
- 1/2
- Fix xlnx,vfb description.
- s/Optional/Required endpoint property.
- Move data-lanes description from Ports to endpoint property section.
- 2/2
- Moved all controls and events to xilinx-csi2rxss.h
- Updated name and description of controls and events
- Get control base address from v4l2-controls.h (0x10c0)
- Fix KConfig for dependency on VIDEO_XILINX
- Added enum_mbus_code() support
- Added default format to be returned on open()
- Mark variables are const
- Remove references to short packet in comments
- Add check for streaming before setting active lanes control
- strlcpy -> strscpy
- Fix xcsi2rxss_set_format()
v8
- 1/2
- Added reset-gpios optional property
- 2/2
- Use clk_bulk* APIs
- Add gpio reset for asserting video_aresetn when stream line buffer occurs
- Removed short packet related events and irq handling
- V4L2_EVENT_XLNXCSIRX_SPKT and V4L2_EVENT_XLNXCSIRX_SPKT_OVF removed
- Removed frame counter control V4L2_CID_XILINX_MIPICSISS_FRAME_COUNTER
and xcsi2rxss_g_volatile_ctrl()
- Minor formatting fixes
v7
- 1/2
- Removed the name of control from en-active-lanes as suggested by Sakari
- Updated the dt node name to csi2rx
- 2/2
- No change
v6
- 1/2
- Added minor comment by Luca
- Added Reviewed by Rob Herring
- 2/2
- No change
v5
- 1/2
- Removed the DPHY clock description and dt node.
- removed bayer pattern as CSI doesn't deal with it.
- 2/2
- removed bayer pattern as CSI doesn't deal with it.
- add YUV422 10bpc media bus format.
v4
- 1/2
- Added reviewed by Hyun Kwon
- 2/2
- Removed irq member from core structure
- Consolidated IP config prints in xcsi2rxss_log_ipconfig()
- Return -EINVAL in case of invalid ioctl
- Code formatting
- Added reviewed by Hyun Kwon
v3
- 1/2
- removed interrupt parent as suggested by Rob
- removed dphy clock
- moved vfb to optional properties
- Added required and optional port properties section
- Added endpoint property section
- 2/2
- Fixed comments given by Hyun.
- Removed DPHY 200 MHz clock. This will be controlled by DPHY driver
- Minor code formatting
- en_csi_v20 and vfb members removed from struct and made local to dt parsing
- lock description updated
- changed to ratelimited type for all dev prints in irq handler
- Removed YUV 422 10bpc media format
v2
- 1/2
- updated the compatible string to latest version supported
- removed DPHY related parameters
- added CSI v2.0 related property (including VCX for supporting upto 16
virtual channels).
- modified csi-pxl-format from string to unsigned int type where the value
is as per the CSI specification
- Defined port 0 and port 1 as sink and source ports.
- Removed max-lanes property as suggested by Rob and Sakari
- 2/2
- Fixed comments given by Hyun and Sakari.
- Made all bitmask using BIT() and GENMASK()
- Removed unused definitions
- Removed DPHY access. This will be done by separate DPHY PHY driver.
- Added support for CSI v2.0 for YUV 422 10bpc, RAW16, RAW20 and extra
virtual channels
- Fixed the ports as sink and source
- Now use the v4l2fwnode API to get number of data-lanes
- Added clock framework support
- Removed the close() function
- updated the set format function
- Support only VFB enabled config
Vishal Sagar (2):
media: dt-bindings: media: xilinx: Add Xilinx MIPI CSI-2 Rx Subsystem
media: v4l: xilinx: Add Xilinx MIPI CSI-2 Rx Subsystem driver
.../bindings/media/xilinx/xlnx,csi2rxss.yaml | 226 ++++
drivers/media/platform/xilinx/Kconfig | 7 +
drivers/media/platform/xilinx/Makefile | 1 +
.../media/platform/xilinx/xilinx-csi2rxss.c | 1114 +++++++++++++++++
4 files changed, 1348 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.yaml
create mode 100644 drivers/media/platform/xilinx/xilinx-csi2rxss.c
--
2.21.0
^ permalink raw reply
* Re: [PATCH] dt-bindings: clock: renesas: div6: Convert to json-schema
From: Niklas Söderlund @ 2020-05-12 15:16 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Rob Herring, Michael Turquette, Stephen Boyd, devicetree,
linux-clk, linux-renesas-soc
In-Reply-To: <20200507075026.31941-1-geert+renesas@glider.be>
Hi Geert,
Thanks for your work.
On 2020-05-07 09:50:26 +0200, Geert Uytterhoeven wrote:
> Convert the Renesas CPG DIV6 Clock Device Tree binding documentation to
> json-schema.
>
> Drop R-Car Gen2 compatible values, which were obsoleted by the unified
> "Renesas Clock Pulse Generator / Module Standby and Software Reset" DT
> bindings.
> Update the example to match reality.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
> To be queued in clk-renesas-for-v5.8.
>
> .../clock/renesas,cpg-div6-clock.yaml | 60 +++++++++++++++++++
> .../clock/renesas,cpg-div6-clocks.txt | 40 -------------
> 2 files changed, 60 insertions(+), 40 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml
> delete mode 100644 Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml
> new file mode 100644
> index 0000000000000000..c55a7c494e013da5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml
> @@ -0,0 +1,60 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/renesas,cpg-div6-clock.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Renesas CPG DIV6 Clock
> +
> +maintainers:
> + - Geert Uytterhoeven <geert+renesas@glider.be>
> +
> +description:
> + The CPG DIV6 clocks are variable factor clocks provided by the Clock Pulse
> + Generator (CPG). Their clock input is divided by a configurable factor from 1
> + to 64.
> +
> +properties:
> + compatible:
> + items:
> + - enum:
> + - renesas,r8a73a4-div6-clock # R-Mobile APE6
> + - renesas,r8a7740-div6-clock # R-Mobile A1
> + - renesas,sh73a0-div6-clock # SH-Mobile AG5
> + - const: renesas,cpg-div6-clock
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + oneOf:
> + - maxItems: 1
> + - maxItems: 4
> + - maxItems: 8
> + description:
> + For clocks with multiple parents, invalid settings must be specified as
> + "<0>".
> +
> + '#clock-cells':
> + const: 0
> +
> + clock-output-names: true
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - '#clock-cells'
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/r8a73a4-clock.h>
> + sdhi2_clk: sdhi2_clk@e615007c {
> + compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
> + reg = <0xe615007c 4>;
> + clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>,
> + <&extal2_clk>;
> + #clock-cells = <0>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
> deleted file mode 100644
> index ae36ab84291988b7..0000000000000000
> --- a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
> +++ /dev/null
> @@ -1,40 +0,0 @@
> -* Renesas CPG DIV6 Clock
> -
> -The CPG DIV6 clocks are variable factor clocks provided by the Clock Pulse
> -Generator (CPG). Their clock input is divided by a configurable factor from 1
> -to 64.
> -
> -Required Properties:
> -
> - - compatible: Must be one of the following
> - - "renesas,r8a73a4-div6-clock" for R8A73A4 (R-Mobile APE6) DIV6 clocks
> - - "renesas,r8a7740-div6-clock" for R8A7740 (R-Mobile A1) DIV6 clocks
> - - "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks
> - - "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2-W) DIV6 clocks
> - - "renesas,r8a7793-div6-clock" for R8A7793 (R-Car M2-N) DIV6 clocks
> - - "renesas,r8a7794-div6-clock" for R8A7794 (R-Car E2) DIV6 clocks
> - - "renesas,sh73a0-div6-clock" for SH73A0 (SH-Mobile AG5) DIV6 clocks
> - and "renesas,cpg-div6-clock" as a fallback.
> - - reg: Base address and length of the memory resource used by the DIV6 clock
> - - clocks: Reference to the parent clock(s); either one, four, or eight
> - clocks must be specified. For clocks with multiple parents, invalid
> - settings must be specified as "<0>".
> - - #clock-cells: Must be 0
> -
> -
> -Optional Properties:
> -
> - - clock-output-names: The name of the clock as a free-form string
> -
> -
> -Example
> --------
> -
> - sdhi2_clk: sdhi2_clk@e615007c {
> - compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
> - reg = <0 0xe615007c 0 4>;
> - clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
> - <0>, <&extal2_clk>;
> - #clock-cells = <0>;
> - clock-output-names = "sdhi2ck";
> - };
> --
> 2.17.1
>
--
Regards,
Niklas Söderlund
^ permalink raw reply
* Re: [PATCH v2 5/5] mfd: lochnagar: Move binding over to dtschema
From: Charles Keepax @ 2020-05-12 15:06 UTC (permalink / raw)
To: Rob Herring
Cc: lee.jones, broonie, mturquette, sboyd, jdelvare, linux,
linus.walleij, lgirdwood, linux-kernel, devicetree, patches
In-Reply-To: <20200512134949.GA14057@bogus>
On Tue, May 12, 2020 at 08:49:49AM -0500, Rob Herring wrote:
> On Mon, May 04, 2020 at 04:47:57PM +0100, Charles Keepax wrote:
> > Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> > ---
> >
> > Changes since v1:
> > - Removed contains on the compatible
> > - Moved all sub-nodes into here directly only using $ref for properties
> > - As the regulator binding only contained subnodes that file is now deleted
> > - Removed some pointless descriptions
> >
> > A little nervous about the amount of clock and regulator stuff this
> > pulls into the MFD file, any comments on that welcome? Would it be worth
> > looking into something along the lines of the definitions stuff to keep
> > some of that out in the clock and regulator bindings?
>
> It's fine like this. Other than my comments on patch 3, looks fine.
> Respin and I'll apply.
>
Groovy thanks for the reviews.
Thanks,
Charles
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox