Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver
0004  *
0005  * Copyright (C) 2021 Purism SPC
0006  */
0007 
0008 #include <linux/clk.h>
0009 #include <linux/clk-provider.h>
0010 #include <linux/delay.h>
0011 #include <linux/errno.h>
0012 #include <linux/interconnect.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/mfd/syscon.h>
0017 #include <linux/module.h>
0018 #include <linux/mutex.h>
0019 #include <linux/of.h>
0020 #include <linux/of_device.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/pm_runtime.h>
0023 #include <linux/regmap.h>
0024 #include <linux/regulator/consumer.h>
0025 #include <linux/reset.h>
0026 #include <linux/spinlock.h>
0027 
0028 #include <media/v4l2-common.h>
0029 #include <media/v4l2-device.h>
0030 #include <media/v4l2-fwnode.h>
0031 #include <media/v4l2-mc.h>
0032 #include <media/v4l2-subdev.h>
0033 
0034 #define MIPI_CSI2_DRIVER_NAME           "imx8mq-mipi-csi2"
0035 #define MIPI_CSI2_SUBDEV_NAME           MIPI_CSI2_DRIVER_NAME
0036 
0037 #define MIPI_CSI2_PAD_SINK          0
0038 #define MIPI_CSI2_PAD_SOURCE            1
0039 #define MIPI_CSI2_PADS_NUM          2
0040 
0041 #define MIPI_CSI2_DEF_PIX_WIDTH         640
0042 #define MIPI_CSI2_DEF_PIX_HEIGHT        480
0043 
0044 /* Register map definition */
0045 
0046 /* i.MX8MQ CSI-2 controller CSR */
0047 #define CSI2RX_CFG_NUM_LANES            0x100
0048 #define CSI2RX_CFG_DISABLE_DATA_LANES       0x104
0049 #define CSI2RX_BIT_ERR              0x108
0050 #define CSI2RX_IRQ_STATUS           0x10c
0051 #define CSI2RX_IRQ_MASK             0x110
0052 #define CSI2RX_IRQ_MASK_ALL         0x1ff
0053 #define CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE  0x8
0054 #define CSI2RX_ULPS_STATUS          0x114
0055 #define CSI2RX_PPI_ERRSOT_HS            0x118
0056 #define CSI2RX_PPI_ERRSOTSYNC_HS        0x11c
0057 #define CSI2RX_PPI_ERRESC           0x120
0058 #define CSI2RX_PPI_ERRSYNCESC           0x124
0059 #define CSI2RX_PPI_ERRCONTROL           0x128
0060 #define CSI2RX_CFG_DISABLE_PAYLOAD_0        0x12c
0061 #define CSI2RX_CFG_VID_VC_IGNORE        0x180
0062 #define CSI2RX_CFG_VID_VC           0x184
0063 #define CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL    0x188
0064 #define CSI2RX_CFG_DISABLE_PAYLOAD_1        0x130
0065 
0066 enum {
0067     ST_POWERED  = 1,
0068     ST_STREAMING    = 2,
0069     ST_SUSPENDED    = 4,
0070 };
0071 
0072 enum imx8mq_mipi_csi_clk {
0073     CSI2_CLK_CORE,
0074     CSI2_CLK_ESC,
0075     CSI2_CLK_UI,
0076     CSI2_NUM_CLKS,
0077 };
0078 
0079 static const char * const imx8mq_mipi_csi_clk_id[CSI2_NUM_CLKS] = {
0080     [CSI2_CLK_CORE] = "core",
0081     [CSI2_CLK_ESC] = "esc",
0082     [CSI2_CLK_UI] = "ui",
0083 };
0084 
0085 #define CSI2_NUM_CLKS   ARRAY_SIZE(imx8mq_mipi_csi_clk_id)
0086 
0087 #define GPR_CSI2_1_RX_ENABLE        BIT(13)
0088 #define GPR_CSI2_1_VID_INTFC_ENB    BIT(12)
0089 #define GPR_CSI2_1_HSEL         BIT(10)
0090 #define GPR_CSI2_1_CONT_CLK_MODE    BIT(8)
0091 #define GPR_CSI2_1_S_PRG_RXHS_SETTLE(x) (((x) & 0x3f) << 2)
0092 
0093 /*
0094  * The send level configures the number of entries that must accumulate in
0095  * the Pixel FIFO before the data will be transferred to the video output.
0096  * The exact value needed for this configuration is dependent on the rate at
0097  * which the sensor transfers data to the CSI-2 Controller and the user
0098  * video clock.
0099  *
0100  * The calculation is the classical rate-in rate-out type of problem: If the
0101  * video bandwidth is 10% faster than the incoming mipi data and the video
0102  * line length is 500 pixels, then the fifo should be allowed to fill
0103  * 10% of the line length or 50 pixels. If the gap data is ok, then the level
0104  * can be set to 16 and ignored.
0105  */
0106 #define CSI2RX_SEND_LEVEL           64
0107 
0108 struct csi_state {
0109     struct device *dev;
0110     void __iomem *regs;
0111     struct clk_bulk_data clks[CSI2_NUM_CLKS];
0112     struct reset_control *rst;
0113     struct regulator *mipi_phy_regulator;
0114 
0115     struct v4l2_subdev sd;
0116     struct media_pad pads[MIPI_CSI2_PADS_NUM];
0117     struct v4l2_async_notifier notifier;
0118     struct v4l2_subdev *src_sd;
0119 
0120     struct v4l2_mbus_config_mipi_csi2 bus;
0121 
0122     struct mutex lock; /* Protect csi2_fmt, format_mbus, state, hs_settle */
0123     const struct csi2_pix_format *csi2_fmt;
0124     struct v4l2_mbus_framefmt format_mbus[MIPI_CSI2_PADS_NUM];
0125     u32 state;
0126     u32 hs_settle;
0127 
0128     struct regmap *phy_gpr;
0129     u8 phy_gpr_reg;
0130 
0131     struct icc_path         *icc_path;
0132     s32             icc_path_bw;
0133 };
0134 
0135 /* -----------------------------------------------------------------------------
0136  * Format helpers
0137  */
0138 
0139 struct csi2_pix_format {
0140     u32 code;
0141     u8 width;
0142 };
0143 
0144 static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = {
0145     /* RAW (Bayer and greyscale) formats. */
0146     {
0147         .code = MEDIA_BUS_FMT_SBGGR8_1X8,
0148         .width = 8,
0149     }, {
0150         .code = MEDIA_BUS_FMT_SGBRG8_1X8,
0151         .width = 8,
0152     }, {
0153         .code = MEDIA_BUS_FMT_SGRBG8_1X8,
0154         .width = 8,
0155     }, {
0156         .code = MEDIA_BUS_FMT_SRGGB8_1X8,
0157         .width = 8,
0158     }, {
0159         .code = MEDIA_BUS_FMT_Y8_1X8,
0160         .width = 8,
0161     }, {
0162         .code = MEDIA_BUS_FMT_SBGGR10_1X10,
0163         .width = 10,
0164     }, {
0165         .code = MEDIA_BUS_FMT_SGBRG10_1X10,
0166         .width = 10,
0167     }, {
0168         .code = MEDIA_BUS_FMT_SGRBG10_1X10,
0169         .width = 10,
0170     }, {
0171         .code = MEDIA_BUS_FMT_SRGGB10_1X10,
0172         .width = 10,
0173     }, {
0174         .code = MEDIA_BUS_FMT_Y10_1X10,
0175         .width = 10,
0176     }, {
0177         .code = MEDIA_BUS_FMT_SBGGR12_1X12,
0178         .width = 12,
0179     }, {
0180         .code = MEDIA_BUS_FMT_SGBRG12_1X12,
0181         .width = 12,
0182     }, {
0183         .code = MEDIA_BUS_FMT_SGRBG12_1X12,
0184         .width = 12,
0185     }, {
0186         .code = MEDIA_BUS_FMT_SRGGB12_1X12,
0187         .width = 12,
0188     }, {
0189         .code = MEDIA_BUS_FMT_Y12_1X12,
0190         .width = 12,
0191     }, {
0192         .code = MEDIA_BUS_FMT_SBGGR14_1X14,
0193         .width = 14,
0194     }, {
0195         .code = MEDIA_BUS_FMT_SGBRG14_1X14,
0196         .width = 14,
0197     }, {
0198         .code = MEDIA_BUS_FMT_SGRBG14_1X14,
0199         .width = 14,
0200     }, {
0201         .code = MEDIA_BUS_FMT_SRGGB14_1X14,
0202         .width = 14,
0203     },
0204     /* YUV formats */
0205     {
0206         .code = MEDIA_BUS_FMT_YUYV8_1X16,
0207         .width = 16,
0208     }, {
0209         .code = MEDIA_BUS_FMT_UYVY8_1X16,
0210         .width = 16,
0211     }
0212 };
0213 
0214 static const struct csi2_pix_format *find_csi2_format(u32 code)
0215 {
0216     unsigned int i;
0217 
0218     for (i = 0; i < ARRAY_SIZE(imx8mq_mipi_csi_formats); i++)
0219         if (code == imx8mq_mipi_csi_formats[i].code)
0220             return &imx8mq_mipi_csi_formats[i];
0221     return NULL;
0222 }
0223 
0224 /* -----------------------------------------------------------------------------
0225  * Hardware configuration
0226  */
0227 
0228 static inline void imx8mq_mipi_csi_write(struct csi_state *state, u32 reg, u32 val)
0229 {
0230     writel(val, state->regs + reg);
0231 }
0232 
0233 static int imx8mq_mipi_csi_sw_reset(struct csi_state *state)
0234 {
0235     int ret;
0236 
0237     /*
0238      * these are most likely self-clearing reset bits. to make it
0239      * more clear, the reset-imx7 driver should implement the
0240      * .reset() operation.
0241      */
0242     ret = reset_control_assert(state->rst);
0243     if (ret < 0) {
0244         dev_err(state->dev, "Failed to assert resets: %d\n", ret);
0245         return ret;
0246     }
0247 
0248     return 0;
0249 }
0250 
0251 static void imx8mq_mipi_csi_system_enable(struct csi_state *state, int on)
0252 {
0253     if (!on) {
0254         imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf);
0255         return;
0256     }
0257 
0258     regmap_update_bits(state->phy_gpr,
0259                state->phy_gpr_reg,
0260                0x3fff,
0261                GPR_CSI2_1_RX_ENABLE |
0262                GPR_CSI2_1_VID_INTFC_ENB |
0263                GPR_CSI2_1_HSEL |
0264                GPR_CSI2_1_CONT_CLK_MODE |
0265                GPR_CSI2_1_S_PRG_RXHS_SETTLE(state->hs_settle));
0266 }
0267 
0268 static void imx8mq_mipi_csi_set_params(struct csi_state *state)
0269 {
0270     int lanes = state->bus.num_data_lanes;
0271 
0272     imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, lanes - 1);
0273     imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES,
0274                   (0xf << lanes) & 0xf);
0275     imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, CSI2RX_IRQ_MASK_ALL);
0276     /*
0277      * 0x180 bit 0 controls the Virtual Channel behaviour: when set the
0278      * interface ignores the Virtual Channel (VC) field in received packets;
0279      * when cleared it causes the interface to only accept packets whose VC
0280      * matches the value to which VC is set at offset 0x184.
0281      */
0282     imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_VC_IGNORE, 1);
0283     imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL,
0284                   CSI2RX_SEND_LEVEL);
0285 }
0286 
0287 static int imx8mq_mipi_csi_clk_enable(struct csi_state *state)
0288 {
0289     return clk_bulk_prepare_enable(CSI2_NUM_CLKS, state->clks);
0290 }
0291 
0292 static void imx8mq_mipi_csi_clk_disable(struct csi_state *state)
0293 {
0294     clk_bulk_disable_unprepare(CSI2_NUM_CLKS, state->clks);
0295 }
0296 
0297 static int imx8mq_mipi_csi_clk_get(struct csi_state *state)
0298 {
0299     unsigned int i;
0300 
0301     for (i = 0; i < CSI2_NUM_CLKS; i++)
0302         state->clks[i].id = imx8mq_mipi_csi_clk_id[i];
0303 
0304     return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks);
0305 }
0306 
0307 static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state)
0308 {
0309     s64 link_freq;
0310     u32 lane_rate;
0311     unsigned long esc_clk_rate;
0312     u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns;
0313 
0314     /* Calculate the line rate from the pixel rate. */
0315     link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler,
0316                        state->csi2_fmt->width,
0317                        state->bus.num_data_lanes * 2);
0318     if (link_freq < 0) {
0319         dev_err(state->dev, "Unable to obtain link frequency: %d\n",
0320             (int)link_freq);
0321         return link_freq;
0322     }
0323 
0324     lane_rate = link_freq * 2;
0325     if (lane_rate < 80000000 || lane_rate > 1500000000) {
0326         dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
0327         return -EINVAL;
0328     }
0329 
0330     /*
0331      * The D-PHY specification requires Ths-settle to be in the range
0332      * 85ns + 6*UI to 140ns + 10*UI, with the unit interval UI being half
0333      * the clock period.
0334      *
0335      * The Ths-settle value is expressed in the hardware as a multiple of
0336      * the Esc clock period:
0337      *
0338      * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc
0339      *
0340      * Due to the one cycle inaccuracy introduced by rounding, the
0341      * documentation recommends picking a value away from the boundaries.
0342      * Let's pick the average.
0343      */
0344     esc_clk_rate = clk_get_rate(state->clks[CSI2_CLK_ESC].clk);
0345     if (!esc_clk_rate) {
0346         dev_err(state->dev, "Could not get esc clock rate.\n");
0347         return -EINVAL;
0348     }
0349 
0350     dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate);
0351     esc_clk_period_ns = 1000000000 / esc_clk_rate;
0352 
0353     min_ths_settle = 85 + 6 * 1000000 / (lane_rate / 1000);
0354     max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000);
0355     ths_settle_ns = (min_ths_settle + max_ths_settle) / 2;
0356 
0357     state->hs_settle = ths_settle_ns / esc_clk_period_ns - 1;
0358 
0359     dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n",
0360         lane_rate, ths_settle_ns, state->hs_settle);
0361 
0362     return 0;
0363 }
0364 
0365 static int imx8mq_mipi_csi_start_stream(struct csi_state *state)
0366 {
0367     int ret;
0368 
0369     ret = imx8mq_mipi_csi_sw_reset(state);
0370     if (ret)
0371         return ret;
0372 
0373     imx8mq_mipi_csi_set_params(state);
0374     ret = imx8mq_mipi_csi_calc_hs_settle(state);
0375     if (ret)
0376         return ret;
0377 
0378     imx8mq_mipi_csi_system_enable(state, true);
0379 
0380     return 0;
0381 }
0382 
0383 static void imx8mq_mipi_csi_stop_stream(struct csi_state *state)
0384 {
0385     imx8mq_mipi_csi_system_enable(state, false);
0386 }
0387 
0388 /* -----------------------------------------------------------------------------
0389  * V4L2 subdev operations
0390  */
0391 
0392 static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev)
0393 {
0394     return container_of(sdev, struct csi_state, sd);
0395 }
0396 
0397 static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
0398 {
0399     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0400     int ret = 0;
0401 
0402     if (enable) {
0403         ret = pm_runtime_resume_and_get(state->dev);
0404         if (ret < 0)
0405             return ret;
0406     }
0407 
0408     mutex_lock(&state->lock);
0409 
0410     if (enable) {
0411         if (state->state & ST_SUSPENDED) {
0412             ret = -EBUSY;
0413             goto unlock;
0414         }
0415 
0416         ret = imx8mq_mipi_csi_start_stream(state);
0417         if (ret < 0)
0418             goto unlock;
0419 
0420         ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
0421         if (ret < 0)
0422             goto unlock;
0423 
0424         state->state |= ST_STREAMING;
0425     } else {
0426         v4l2_subdev_call(state->src_sd, video, s_stream, 0);
0427         imx8mq_mipi_csi_stop_stream(state);
0428         state->state &= ~ST_STREAMING;
0429     }
0430 
0431 unlock:
0432     mutex_unlock(&state->lock);
0433 
0434     if (!enable || ret < 0)
0435         pm_runtime_put(state->dev);
0436 
0437     return ret;
0438 }
0439 
0440 static struct v4l2_mbus_framefmt *
0441 imx8mq_mipi_csi_get_format(struct csi_state *state,
0442                struct v4l2_subdev_state *sd_state,
0443                enum v4l2_subdev_format_whence which,
0444                unsigned int pad)
0445 {
0446     if (which == V4L2_SUBDEV_FORMAT_TRY)
0447         return v4l2_subdev_get_try_format(&state->sd, sd_state, pad);
0448 
0449     return &state->format_mbus[pad];
0450 }
0451 
0452 static int imx8mq_mipi_csi_init_cfg(struct v4l2_subdev *sd,
0453                     struct v4l2_subdev_state *sd_state)
0454 {
0455     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0456     struct v4l2_mbus_framefmt *fmt_sink;
0457     struct v4l2_mbus_framefmt *fmt_source;
0458     enum v4l2_subdev_format_whence which;
0459 
0460     which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
0461     fmt_sink = imx8mq_mipi_csi_get_format(state, sd_state, which,
0462                           MIPI_CSI2_PAD_SINK);
0463 
0464     fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10;
0465     fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH;
0466     fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT;
0467     fmt_sink->field = V4L2_FIELD_NONE;
0468 
0469     fmt_sink->colorspace = V4L2_COLORSPACE_RAW;
0470     fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
0471     fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
0472     fmt_sink->quantization =
0473         V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
0474                           fmt_sink->ycbcr_enc);
0475 
0476     fmt_source = imx8mq_mipi_csi_get_format(state, sd_state, which,
0477                         MIPI_CSI2_PAD_SOURCE);
0478     *fmt_source = *fmt_sink;
0479 
0480     return 0;
0481 }
0482 
0483 static int imx8mq_mipi_csi_get_fmt(struct v4l2_subdev *sd,
0484                    struct v4l2_subdev_state *sd_state,
0485                    struct v4l2_subdev_format *sdformat)
0486 {
0487     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0488     struct v4l2_mbus_framefmt *fmt;
0489 
0490     fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
0491                      sdformat->pad);
0492 
0493     mutex_lock(&state->lock);
0494 
0495     sdformat->format = *fmt;
0496 
0497     mutex_unlock(&state->lock);
0498 
0499     return 0;
0500 }
0501 
0502 static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd,
0503                       struct v4l2_subdev_state *sd_state,
0504                       struct v4l2_subdev_mbus_code_enum *code)
0505 {
0506     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0507 
0508     /*
0509      * We can't transcode in any way, the source format is identical
0510      * to the sink format.
0511      */
0512     if (code->pad == MIPI_CSI2_PAD_SOURCE) {
0513         struct v4l2_mbus_framefmt *fmt;
0514 
0515         if (code->index > 0)
0516             return -EINVAL;
0517 
0518         fmt = imx8mq_mipi_csi_get_format(state, sd_state, code->which,
0519                          code->pad);
0520         code->code = fmt->code;
0521         return 0;
0522     }
0523 
0524     if (code->pad != MIPI_CSI2_PAD_SINK)
0525         return -EINVAL;
0526 
0527     if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats))
0528         return -EINVAL;
0529 
0530     code->code = imx8mq_mipi_csi_formats[code->index].code;
0531 
0532     return 0;
0533 }
0534 
0535 static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd,
0536                    struct v4l2_subdev_state *sd_state,
0537                    struct v4l2_subdev_format *sdformat)
0538 {
0539     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0540     struct csi2_pix_format const *csi2_fmt;
0541     struct v4l2_mbus_framefmt *fmt;
0542 
0543     /*
0544      * The device can't transcode in any way, the source format can't be
0545      * modified.
0546      */
0547     if (sdformat->pad == MIPI_CSI2_PAD_SOURCE)
0548         return imx8mq_mipi_csi_get_fmt(sd, sd_state, sdformat);
0549 
0550     if (sdformat->pad != MIPI_CSI2_PAD_SINK)
0551         return -EINVAL;
0552 
0553     csi2_fmt = find_csi2_format(sdformat->format.code);
0554     if (!csi2_fmt)
0555         csi2_fmt = &imx8mq_mipi_csi_formats[0];
0556 
0557     fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
0558                      sdformat->pad);
0559 
0560     mutex_lock(&state->lock);
0561 
0562     fmt->code = csi2_fmt->code;
0563     fmt->width = sdformat->format.width;
0564     fmt->height = sdformat->format.height;
0565 
0566     sdformat->format = *fmt;
0567 
0568     /* Propagate the format from sink to source. */
0569     fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which,
0570                      MIPI_CSI2_PAD_SOURCE);
0571     *fmt = sdformat->format;
0572 
0573     /* Store the CSI2 format descriptor for active formats. */
0574     if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
0575         state->csi2_fmt = csi2_fmt;
0576 
0577     mutex_unlock(&state->lock);
0578 
0579     return 0;
0580 }
0581 
0582 static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = {
0583     .s_stream   = imx8mq_mipi_csi_s_stream,
0584 };
0585 
0586 static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = {
0587     .init_cfg       = imx8mq_mipi_csi_init_cfg,
0588     .enum_mbus_code     = imx8mq_mipi_csi_enum_mbus_code,
0589     .get_fmt        = imx8mq_mipi_csi_get_fmt,
0590     .set_fmt        = imx8mq_mipi_csi_set_fmt,
0591 };
0592 
0593 static const struct v4l2_subdev_ops imx8mq_mipi_csi_subdev_ops = {
0594     .video  = &imx8mq_mipi_csi_video_ops,
0595     .pad    = &imx8mq_mipi_csi_pad_ops,
0596 };
0597 
0598 /* -----------------------------------------------------------------------------
0599  * Media entity operations
0600  */
0601 
0602 static const struct media_entity_operations imx8mq_mipi_csi_entity_ops = {
0603     .link_validate  = v4l2_subdev_link_validate,
0604     .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
0605 };
0606 
0607 /* -----------------------------------------------------------------------------
0608  * Async subdev notifier
0609  */
0610 
0611 static struct csi_state *
0612 mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n)
0613 {
0614     return container_of(n, struct csi_state, notifier);
0615 }
0616 
0617 static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier,
0618                     struct v4l2_subdev *sd,
0619                     struct v4l2_async_subdev *asd)
0620 {
0621     struct csi_state *state = mipi_notifier_to_csi2_state(notifier);
0622     struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK];
0623 
0624     state->src_sd = sd;
0625 
0626     return v4l2_create_fwnode_links_to_pad(sd, sink, MEDIA_LNK_FL_ENABLED |
0627                            MEDIA_LNK_FL_IMMUTABLE);
0628 }
0629 
0630 static const struct v4l2_async_notifier_operations imx8mq_mipi_csi_notify_ops = {
0631     .bound = imx8mq_mipi_csi_notify_bound,
0632 };
0633 
0634 static int imx8mq_mipi_csi_async_register(struct csi_state *state)
0635 {
0636     struct v4l2_fwnode_endpoint vep = {
0637         .bus_type = V4L2_MBUS_CSI2_DPHY,
0638     };
0639     struct v4l2_async_subdev *asd;
0640     struct fwnode_handle *ep;
0641     unsigned int i;
0642     int ret;
0643 
0644     v4l2_async_nf_init(&state->notifier);
0645 
0646     ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
0647                          FWNODE_GRAPH_ENDPOINT_NEXT);
0648     if (!ep)
0649         return -ENOTCONN;
0650 
0651     ret = v4l2_fwnode_endpoint_parse(ep, &vep);
0652     if (ret)
0653         goto err_parse;
0654 
0655     for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
0656         if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
0657             dev_err(state->dev,
0658                 "data lanes reordering is not supported");
0659             ret = -EINVAL;
0660             goto err_parse;
0661         }
0662     }
0663 
0664     state->bus = vep.bus.mipi_csi2;
0665 
0666     dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n",
0667         state->bus.num_data_lanes,
0668         state->bus.flags);
0669 
0670     asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
0671                           struct v4l2_async_subdev);
0672     if (IS_ERR(asd)) {
0673         ret = PTR_ERR(asd);
0674         goto err_parse;
0675     }
0676 
0677     fwnode_handle_put(ep);
0678 
0679     state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
0680 
0681     ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
0682     if (ret)
0683         return ret;
0684 
0685     return v4l2_async_register_subdev(&state->sd);
0686 
0687 err_parse:
0688     fwnode_handle_put(ep);
0689 
0690     return ret;
0691 }
0692 
0693 /* -----------------------------------------------------------------------------
0694  * Suspend/resume
0695  */
0696 
0697 static void imx8mq_mipi_csi_pm_suspend(struct device *dev)
0698 {
0699     struct v4l2_subdev *sd = dev_get_drvdata(dev);
0700     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0701 
0702     mutex_lock(&state->lock);
0703 
0704     if (state->state & ST_POWERED) {
0705         imx8mq_mipi_csi_stop_stream(state);
0706         imx8mq_mipi_csi_clk_disable(state);
0707         state->state &= ~ST_POWERED;
0708     }
0709 
0710     mutex_unlock(&state->lock);
0711 }
0712 
0713 static int imx8mq_mipi_csi_pm_resume(struct device *dev)
0714 {
0715     struct v4l2_subdev *sd = dev_get_drvdata(dev);
0716     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0717     int ret = 0;
0718 
0719     mutex_lock(&state->lock);
0720 
0721     if (!(state->state & ST_POWERED)) {
0722         state->state |= ST_POWERED;
0723         ret = imx8mq_mipi_csi_clk_enable(state);
0724     }
0725     if (state->state & ST_STREAMING) {
0726         ret = imx8mq_mipi_csi_start_stream(state);
0727         if (ret)
0728             goto unlock;
0729     }
0730 
0731     state->state &= ~ST_SUSPENDED;
0732 
0733 unlock:
0734     mutex_unlock(&state->lock);
0735 
0736     return ret ? -EAGAIN : 0;
0737 }
0738 
0739 static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev)
0740 {
0741     struct v4l2_subdev *sd = dev_get_drvdata(dev);
0742     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0743 
0744     imx8mq_mipi_csi_pm_suspend(dev);
0745 
0746     state->state |= ST_SUSPENDED;
0747 
0748     return 0;
0749 }
0750 
0751 static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev)
0752 {
0753     struct v4l2_subdev *sd = dev_get_drvdata(dev);
0754     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0755 
0756     if (!(state->state & ST_SUSPENDED))
0757         return 0;
0758 
0759     return imx8mq_mipi_csi_pm_resume(dev);
0760 }
0761 
0762 static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev)
0763 {
0764     struct v4l2_subdev *sd = dev_get_drvdata(dev);
0765     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0766     int ret;
0767 
0768     imx8mq_mipi_csi_pm_suspend(dev);
0769 
0770     ret = icc_set_bw(state->icc_path, 0, 0);
0771     if (ret)
0772         dev_err(dev, "icc_set_bw failed with %d\n", ret);
0773 
0774     return ret;
0775 }
0776 
0777 static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev)
0778 {
0779     struct v4l2_subdev *sd = dev_get_drvdata(dev);
0780     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0781     int ret;
0782 
0783     ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
0784     if (ret) {
0785         dev_err(dev, "icc_set_bw failed with %d\n", ret);
0786         return ret;
0787     }
0788 
0789     return imx8mq_mipi_csi_pm_resume(dev);
0790 }
0791 
0792 static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = {
0793     SET_RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend,
0794                imx8mq_mipi_csi_runtime_resume,
0795                NULL)
0796     SET_SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume)
0797 };
0798 
0799 /* -----------------------------------------------------------------------------
0800  * Probe/remove & platform driver
0801  */
0802 
0803 static int imx8mq_mipi_csi_subdev_init(struct csi_state *state)
0804 {
0805     struct v4l2_subdev *sd = &state->sd;
0806 
0807     v4l2_subdev_init(sd, &imx8mq_mipi_csi_subdev_ops);
0808     sd->owner = THIS_MODULE;
0809     snprintf(sd->name, sizeof(sd->name), "%s %s",
0810          MIPI_CSI2_SUBDEV_NAME, dev_name(state->dev));
0811 
0812     sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
0813 
0814     sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
0815     sd->entity.ops = &imx8mq_mipi_csi_entity_ops;
0816 
0817     sd->dev = state->dev;
0818 
0819     state->csi2_fmt = &imx8mq_mipi_csi_formats[0];
0820     imx8mq_mipi_csi_init_cfg(sd, NULL);
0821 
0822     state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
0823                      | MEDIA_PAD_FL_MUST_CONNECT;
0824     state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
0825                        | MEDIA_PAD_FL_MUST_CONNECT;
0826     return media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM,
0827                       state->pads);
0828 }
0829 
0830 static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev)
0831 {
0832     struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
0833     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0834 
0835     icc_put(state->icc_path);
0836 }
0837 
0838 static int imx8mq_mipi_csi_init_icc(struct platform_device *pdev)
0839 {
0840     struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev);
0841     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0842 
0843     /* Optional interconnect request */
0844     state->icc_path = of_icc_get(&pdev->dev, "dram");
0845     if (IS_ERR_OR_NULL(state->icc_path))
0846         return PTR_ERR_OR_ZERO(state->icc_path);
0847 
0848     state->icc_path_bw = MBps_to_icc(700);
0849 
0850     return 0;
0851 }
0852 
0853 static int imx8mq_mipi_csi_parse_dt(struct csi_state *state)
0854 {
0855     struct device *dev = state->dev;
0856     struct device_node *np = state->dev->of_node;
0857     struct device_node *node;
0858     phandle ph;
0859     u32 out_val[2];
0860     int ret = 0;
0861 
0862     state->rst = devm_reset_control_array_get_exclusive(dev);
0863     if (IS_ERR(state->rst)) {
0864         dev_err(dev, "Failed to get reset: %pe\n", state->rst);
0865         return PTR_ERR(state->rst);
0866     }
0867 
0868     ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val,
0869                      ARRAY_SIZE(out_val));
0870     if (ret) {
0871         dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret);
0872         return ret;
0873     }
0874 
0875     ph = *out_val;
0876 
0877     node = of_find_node_by_phandle(ph);
0878     if (!node) {
0879         dev_err(dev, "Error finding node by phandle\n");
0880         return -ENODEV;
0881     }
0882     state->phy_gpr = syscon_node_to_regmap(node);
0883     of_node_put(node);
0884     if (IS_ERR(state->phy_gpr)) {
0885         dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr);
0886         return PTR_ERR(state->phy_gpr);
0887     }
0888 
0889     state->phy_gpr_reg = out_val[1];
0890     dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg);
0891 
0892     return ret;
0893 }
0894 
0895 static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
0896 {
0897     struct device *dev = &pdev->dev;
0898     struct csi_state *state;
0899     int ret;
0900 
0901     state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
0902     if (!state)
0903         return -ENOMEM;
0904 
0905     state->dev = dev;
0906 
0907     ret = imx8mq_mipi_csi_parse_dt(state);
0908     if (ret < 0) {
0909         dev_err(dev, "Failed to parse device tree: %d\n", ret);
0910         return ret;
0911     }
0912 
0913     /* Acquire resources. */
0914     state->regs = devm_platform_ioremap_resource(pdev, 0);
0915     if (IS_ERR(state->regs))
0916         return PTR_ERR(state->regs);
0917 
0918     ret = imx8mq_mipi_csi_clk_get(state);
0919     if (ret < 0)
0920         return ret;
0921 
0922     platform_set_drvdata(pdev, &state->sd);
0923 
0924     mutex_init(&state->lock);
0925 
0926     ret = imx8mq_mipi_csi_subdev_init(state);
0927     if (ret < 0)
0928         goto mutex;
0929 
0930     ret = imx8mq_mipi_csi_init_icc(pdev);
0931     if (ret)
0932         goto mutex;
0933 
0934     /* Enable runtime PM. */
0935     pm_runtime_enable(dev);
0936     if (!pm_runtime_enabled(dev)) {
0937         ret = imx8mq_mipi_csi_runtime_resume(dev);
0938         if (ret < 0)
0939             goto icc;
0940     }
0941 
0942     ret = imx8mq_mipi_csi_async_register(state);
0943     if (ret < 0)
0944         goto cleanup;
0945 
0946     return 0;
0947 
0948 cleanup:
0949     pm_runtime_disable(&pdev->dev);
0950     imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
0951 
0952     media_entity_cleanup(&state->sd.entity);
0953     v4l2_async_nf_unregister(&state->notifier);
0954     v4l2_async_nf_cleanup(&state->notifier);
0955     v4l2_async_unregister_subdev(&state->sd);
0956 icc:
0957     imx8mq_mipi_csi_release_icc(pdev);
0958 mutex:
0959     mutex_destroy(&state->lock);
0960 
0961     return ret;
0962 }
0963 
0964 static int imx8mq_mipi_csi_remove(struct platform_device *pdev)
0965 {
0966     struct v4l2_subdev *sd = platform_get_drvdata(pdev);
0967     struct csi_state *state = mipi_sd_to_csi2_state(sd);
0968 
0969     v4l2_async_nf_unregister(&state->notifier);
0970     v4l2_async_nf_cleanup(&state->notifier);
0971     v4l2_async_unregister_subdev(&state->sd);
0972 
0973     pm_runtime_disable(&pdev->dev);
0974     imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
0975     media_entity_cleanup(&state->sd.entity);
0976     mutex_destroy(&state->lock);
0977     pm_runtime_set_suspended(&pdev->dev);
0978     imx8mq_mipi_csi_release_icc(pdev);
0979 
0980     return 0;
0981 }
0982 
0983 static const struct of_device_id imx8mq_mipi_csi_of_match[] = {
0984     { .compatible = "fsl,imx8mq-mipi-csi2", },
0985     { /* sentinel */ },
0986 };
0987 MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match);
0988 
0989 static struct platform_driver imx8mq_mipi_csi_driver = {
0990     .probe      = imx8mq_mipi_csi_probe,
0991     .remove     = imx8mq_mipi_csi_remove,
0992     .driver     = {
0993         .of_match_table = imx8mq_mipi_csi_of_match,
0994         .name       = MIPI_CSI2_DRIVER_NAME,
0995         .pm     = &imx8mq_mipi_csi_pm_ops,
0996     },
0997 };
0998 
0999 module_platform_driver(imx8mq_mipi_csi_driver);
1000 
1001 MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver");
1002 MODULE_AUTHOR("Martin Kepplinger <martin.kepplinger@puri.sm>");
1003 MODULE_LICENSE("GPL v2");
1004 MODULE_ALIAS("platform:imx8mq-mipi-csi2");