Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Maxim MAX9286 Quad GMSL2 Deserializer Driver
0004  *
0005  * Copyright (C) 2021 Renesas Electronics Corporation
0006  * Copyright (C) 2021 Niklas Söderlund
0007  */
0008 
0009 #include <linux/delay.h>
0010 #include <linux/i2c.h>
0011 #include <linux/module.h>
0012 #include <linux/of_graph.h>
0013 #include <linux/regmap.h>
0014 
0015 #include <media/v4l2-ctrls.h>
0016 #include <media/v4l2-fwnode.h>
0017 #include <media/v4l2-subdev.h>
0018 
0019 #define MAX96712_ID 0x20
0020 
0021 #define MAX96712_DPLL_FREQ 1000
0022 
0023 enum max96712_pattern {
0024     MAX96712_PATTERN_CHECKERBOARD = 0,
0025     MAX96712_PATTERN_GRADIENT,
0026 };
0027 
0028 struct max96712_priv {
0029     struct i2c_client *client;
0030     struct regmap *regmap;
0031     struct gpio_desc *gpiod_pwdn;
0032 
0033     struct v4l2_mbus_config_mipi_csi2 mipi;
0034 
0035     struct v4l2_subdev sd;
0036     struct v4l2_ctrl_handler ctrl_handler;
0037     struct media_pad pads[1];
0038 
0039     enum max96712_pattern pattern;
0040 };
0041 
0042 static int max96712_read(struct max96712_priv *priv, int reg)
0043 {
0044     int ret, val;
0045 
0046     ret = regmap_read(priv->regmap, reg, &val);
0047     if (ret) {
0048         dev_err(&priv->client->dev, "read 0x%04x failed\n", reg);
0049         return ret;
0050     }
0051 
0052     return val;
0053 }
0054 
0055 static int max96712_write(struct max96712_priv *priv, unsigned int reg, u8 val)
0056 {
0057     int ret;
0058 
0059     ret = regmap_write(priv->regmap, reg, val);
0060     if (ret)
0061         dev_err(&priv->client->dev, "write 0x%04x failed\n", reg);
0062 
0063     return ret;
0064 }
0065 
0066 static int max96712_update_bits(struct max96712_priv *priv, unsigned int reg,
0067                 u8 mask, u8 val)
0068 {
0069     int ret;
0070 
0071     ret = regmap_update_bits(priv->regmap, reg, mask, val);
0072     if (ret)
0073         dev_err(&priv->client->dev, "update 0x%04x failed\n", reg);
0074 
0075     return ret;
0076 }
0077 
0078 static int max96712_write_bulk(struct max96712_priv *priv, unsigned int reg,
0079                    const void *val, size_t val_count)
0080 {
0081     int ret;
0082 
0083     ret = regmap_bulk_write(priv->regmap, reg, val, val_count);
0084     if (ret)
0085         dev_err(&priv->client->dev, "bulk write 0x%04x failed\n", reg);
0086 
0087     return ret;
0088 }
0089 
0090 static int max96712_write_bulk_value(struct max96712_priv *priv,
0091                      unsigned int reg, unsigned int val,
0092                      size_t val_count)
0093 {
0094     unsigned int i;
0095     u8 values[4];
0096 
0097     for (i = 1; i <= val_count; i++)
0098         values[i - 1] = (val >> ((val_count - i) * 8)) & 0xff;
0099 
0100     return max96712_write_bulk(priv, reg, &values, val_count);
0101 }
0102 
0103 static void max96712_reset(struct max96712_priv *priv)
0104 {
0105     max96712_update_bits(priv, 0x13, 0x40, 0x40);
0106     msleep(20);
0107 }
0108 
0109 static void max96712_mipi_enable(struct max96712_priv *priv, bool enable)
0110 {
0111     if (enable) {
0112         max96712_update_bits(priv, 0x40b, 0x02, 0x02);
0113         max96712_update_bits(priv, 0x8a0, 0x80, 0x80);
0114     } else {
0115         max96712_update_bits(priv, 0x8a0, 0x80, 0x00);
0116         max96712_update_bits(priv, 0x40b, 0x02, 0x00);
0117     }
0118 }
0119 
0120 static void max96712_mipi_configure(struct max96712_priv *priv)
0121 {
0122     unsigned int i;
0123     u8 phy5 = 0;
0124 
0125     max96712_mipi_enable(priv, false);
0126 
0127     /* Select 2x4 mode. */
0128     max96712_write(priv, 0x8a0, 0x04);
0129 
0130     /* Configure a 4-lane DPHY using PHY0 and PHY1. */
0131     /* TODO: Add support for 2-lane and 1-lane configurations. */
0132     /* TODO: Add support CPHY mode. */
0133     max96712_write(priv, 0x94a, 0xc0);
0134 
0135     /* Configure lane mapping for PHY0 and PHY1. */
0136     /* TODO: Add support for lane swapping. */
0137     max96712_write(priv, 0x8a3, 0xe4);
0138 
0139     /* Configure lane polarity for PHY0 and PHY1. */
0140     for (i = 0; i < priv->mipi.num_data_lanes + 1; i++)
0141         if (priv->mipi.lane_polarities[i])
0142             phy5 |= BIT(i == 0 ? 5 : i < 3 ? i - 1 : i);
0143     max96712_write(priv, 0x8a5, phy5);
0144 
0145     /* Set link frequency for PHY0 and PHY1. */
0146     max96712_update_bits(priv, 0x415, 0x3f,
0147                  ((MAX96712_DPLL_FREQ / 100) & 0x1f) | BIT(5));
0148     max96712_update_bits(priv, 0x418, 0x3f,
0149                  ((MAX96712_DPLL_FREQ / 100) & 0x1f) | BIT(5));
0150 
0151     /* Enable PHY0 and PHY1 */
0152     max96712_update_bits(priv, 0x8a2, 0xf0, 0x30);
0153 }
0154 
0155 static void max96712_pattern_enable(struct max96712_priv *priv, bool enable)
0156 {
0157     const u32 h_active = 1920;
0158     const u32 h_fp = 88;
0159     const u32 h_sw = 44;
0160     const u32 h_bp = 148;
0161     const u32 h_tot = h_active + h_fp + h_sw + h_bp;
0162 
0163     const u32 v_active = 1080;
0164     const u32 v_fp = 4;
0165     const u32 v_sw = 5;
0166     const u32 v_bp = 36;
0167     const u32 v_tot = v_active + v_fp + v_sw + v_bp;
0168 
0169     if (!enable) {
0170         max96712_write(priv, 0x1051, 0x00);
0171         return;
0172     }
0173 
0174     /* PCLK 75MHz. */
0175     max96712_write(priv, 0x0009, 0x01);
0176 
0177     /* Configure Video Timing Generator for 1920x1080 @ 30 fps. */
0178     max96712_write_bulk_value(priv, 0x1052, 0, 3);
0179     max96712_write_bulk_value(priv, 0x1055, v_sw * h_tot, 3);
0180     max96712_write_bulk_value(priv, 0x1058,
0181                   (v_active + v_fp + + v_bp) * h_tot, 3);
0182     max96712_write_bulk_value(priv, 0x105b, 0, 3);
0183     max96712_write_bulk_value(priv, 0x105e, h_sw, 2);
0184     max96712_write_bulk_value(priv, 0x1060, h_active + h_fp + h_bp, 2);
0185     max96712_write_bulk_value(priv, 0x1062, v_tot, 2);
0186     max96712_write_bulk_value(priv, 0x1064,
0187                   h_tot * (v_sw + v_bp) + (h_sw + h_bp), 3);
0188     max96712_write_bulk_value(priv, 0x1067, h_active, 2);
0189     max96712_write_bulk_value(priv, 0x1069, h_fp + h_sw + h_bp, 2);
0190     max96712_write_bulk_value(priv, 0x106b, v_active, 2);
0191 
0192     /* Generate VS, HS and DE in free-running mode. */
0193     max96712_write(priv, 0x1050, 0xfb);
0194 
0195     /* Configure Video Pattern Generator. */
0196     if (priv->pattern == MAX96712_PATTERN_CHECKERBOARD) {
0197         /* Set checkerboard pattern size. */
0198         max96712_write(priv, 0x1074, 0x3c);
0199         max96712_write(priv, 0x1075, 0x3c);
0200         max96712_write(priv, 0x1076, 0x3c);
0201 
0202         /* Set checkerboard pattern colors. */
0203         max96712_write_bulk_value(priv, 0x106e, 0xfecc00, 3);
0204         max96712_write_bulk_value(priv, 0x1071, 0x006aa7, 3);
0205 
0206         /* Generate checkerboard pattern. */
0207         max96712_write(priv, 0x1051, 0x10);
0208     } else {
0209         /* Set gradient increment. */
0210         max96712_write(priv, 0x106d, 0x10);
0211 
0212         /* Generate gradient pattern. */
0213         max96712_write(priv, 0x1051, 0x20);
0214     }
0215 }
0216 
0217 static int max96712_s_stream(struct v4l2_subdev *sd, int enable)
0218 {
0219     struct max96712_priv *priv = v4l2_get_subdevdata(sd);
0220 
0221     if (enable) {
0222         max96712_pattern_enable(priv, true);
0223         max96712_mipi_enable(priv, true);
0224     } else {
0225         max96712_mipi_enable(priv, false);
0226         max96712_pattern_enable(priv, false);
0227     }
0228 
0229     return 0;
0230 }
0231 
0232 static const struct v4l2_subdev_video_ops max96712_video_ops = {
0233     .s_stream = max96712_s_stream,
0234 };
0235 
0236 static int max96712_get_pad_format(struct v4l2_subdev *sd,
0237                    struct v4l2_subdev_state *sd_state,
0238                    struct v4l2_subdev_format *format)
0239 {
0240     format->format.width = 1920;
0241     format->format.height = 1080;
0242     format->format.code = MEDIA_BUS_FMT_RGB888_1X24;
0243     format->format.field = V4L2_FIELD_NONE;
0244 
0245     return 0;
0246 }
0247 
0248 static const struct v4l2_subdev_pad_ops max96712_pad_ops = {
0249     .get_fmt = max96712_get_pad_format,
0250     .set_fmt = max96712_get_pad_format,
0251 };
0252 
0253 static const struct v4l2_subdev_ops max96712_subdev_ops = {
0254     .video = &max96712_video_ops,
0255     .pad = &max96712_pad_ops,
0256 };
0257 
0258 static const char * const max96712_test_pattern[] = {
0259     "Checkerboard",
0260     "Gradient",
0261 };
0262 
0263 static int max96712_s_ctrl(struct v4l2_ctrl *ctrl)
0264 {
0265     struct max96712_priv *priv =
0266         container_of(ctrl->handler, struct max96712_priv, ctrl_handler);
0267 
0268     switch (ctrl->id) {
0269     case V4L2_CID_TEST_PATTERN:
0270         priv->pattern = ctrl->val ?
0271             MAX96712_PATTERN_GRADIENT :
0272             MAX96712_PATTERN_CHECKERBOARD;
0273         break;
0274     }
0275     return 0;
0276 }
0277 
0278 static const struct v4l2_ctrl_ops max96712_ctrl_ops = {
0279     .s_ctrl = max96712_s_ctrl,
0280 };
0281 
0282 static int max96712_v4l2_register(struct max96712_priv *priv)
0283 {
0284     long pixel_rate;
0285     int ret;
0286 
0287     v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96712_subdev_ops);
0288     priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
0289     priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
0290 
0291     v4l2_ctrl_handler_init(&priv->ctrl_handler, 2);
0292 
0293     /*
0294      * TODO: Once V4L2_CID_LINK_FREQ is changed from a menu control to an
0295      * INT64 control it should be used here instead of V4L2_CID_PIXEL_RATE.
0296      */
0297     pixel_rate = MAX96712_DPLL_FREQ / priv->mipi.num_data_lanes * 1000000;
0298     v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE,
0299               pixel_rate, pixel_rate, 1, pixel_rate);
0300 
0301     v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, &max96712_ctrl_ops,
0302                      V4L2_CID_TEST_PATTERN,
0303                      ARRAY_SIZE(max96712_test_pattern) - 1,
0304                      0, 0, max96712_test_pattern);
0305 
0306     priv->sd.ctrl_handler = &priv->ctrl_handler;
0307     ret = priv->ctrl_handler.error;
0308     if (ret)
0309         goto error;
0310 
0311     priv->pads[0].flags = MEDIA_PAD_FL_SOURCE;
0312     ret = media_entity_pads_init(&priv->sd.entity, 1, priv->pads);
0313     if (ret)
0314         goto error;
0315 
0316     v4l2_set_subdevdata(&priv->sd, priv);
0317 
0318     ret = v4l2_async_register_subdev(&priv->sd);
0319     if (ret < 0) {
0320         dev_err(&priv->client->dev, "Unable to register subdevice\n");
0321         goto error;
0322     }
0323 
0324     return 0;
0325 error:
0326     v4l2_ctrl_handler_free(&priv->ctrl_handler);
0327 
0328     return ret;
0329 }
0330 
0331 static int max96712_parse_dt(struct max96712_priv *priv)
0332 {
0333     struct fwnode_handle *ep;
0334     struct v4l2_fwnode_endpoint v4l2_ep = {
0335         .bus_type = V4L2_MBUS_CSI2_DPHY
0336     };
0337     int ret;
0338 
0339     ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4,
0340                          0, 0);
0341     if (!ep) {
0342         dev_err(&priv->client->dev, "Not connected to subdevice\n");
0343         return -EINVAL;
0344     }
0345 
0346     ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep);
0347     fwnode_handle_put(ep);
0348     if (ret) {
0349         dev_err(&priv->client->dev, "Could not parse v4l2 endpoint\n");
0350         return -EINVAL;
0351     }
0352 
0353     if (v4l2_ep.bus.mipi_csi2.num_data_lanes != 4) {
0354         dev_err(&priv->client->dev, "Only 4 data lanes supported\n");
0355         return -EINVAL;
0356     }
0357 
0358     priv->mipi = v4l2_ep.bus.mipi_csi2;
0359 
0360     return 0;
0361 }
0362 
0363 static const struct regmap_config max96712_i2c_regmap = {
0364     .reg_bits = 16,
0365     .val_bits = 8,
0366     .max_register = 0x1f00,
0367 };
0368 
0369 static int max96712_probe(struct i2c_client *client)
0370 {
0371     struct max96712_priv *priv;
0372     int ret;
0373 
0374     priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
0375     if (!priv)
0376         return -ENOMEM;
0377 
0378     priv->client = client;
0379     i2c_set_clientdata(client, priv);
0380 
0381     priv->regmap = devm_regmap_init_i2c(client, &max96712_i2c_regmap);
0382     if (IS_ERR(priv->regmap))
0383         return PTR_ERR(priv->regmap);
0384 
0385     priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable",
0386                            GPIOD_OUT_HIGH);
0387     if (IS_ERR(priv->gpiod_pwdn))
0388         return PTR_ERR(priv->gpiod_pwdn);
0389 
0390     gpiod_set_consumer_name(priv->gpiod_pwdn, "max96712-pwdn");
0391     gpiod_set_value_cansleep(priv->gpiod_pwdn, 1);
0392 
0393     if (priv->gpiod_pwdn)
0394         usleep_range(4000, 5000);
0395 
0396     if (max96712_read(priv, 0x4a) != MAX96712_ID)
0397         return -ENODEV;
0398 
0399     max96712_reset(priv);
0400 
0401     ret = max96712_parse_dt(priv);
0402     if (ret)
0403         return ret;
0404 
0405     max96712_mipi_configure(priv);
0406 
0407     return max96712_v4l2_register(priv);
0408 }
0409 
0410 static int max96712_remove(struct i2c_client *client)
0411 {
0412     struct max96712_priv *priv = i2c_get_clientdata(client);
0413 
0414     v4l2_async_unregister_subdev(&priv->sd);
0415 
0416     gpiod_set_value_cansleep(priv->gpiod_pwdn, 0);
0417 
0418     return 0;
0419 }
0420 
0421 static const struct of_device_id max96712_of_table[] = {
0422     { .compatible = "maxim,max96712" },
0423     { /* sentinel */ },
0424 };
0425 MODULE_DEVICE_TABLE(of, max96712_of_table);
0426 
0427 static struct i2c_driver max96712_i2c_driver = {
0428     .driver = {
0429         .name = "max96712",
0430         .of_match_table = of_match_ptr(max96712_of_table),
0431     },
0432     .probe_new = max96712_probe,
0433     .remove = max96712_remove,
0434 };
0435 
0436 module_i2c_driver(max96712_i2c_driver);
0437 
0438 MODULE_DESCRIPTION("Maxim MAX96712 Quad GMSL2 Deserializer Driver");
0439 MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>");
0440 MODULE_LICENSE("GPL");