1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Maxim MAX9286 Quad GMSL2 Deserializer Driver 4 * 5 * Copyright (C) 2021 Renesas Electronics Corporation 6 * Copyright (C) 2021 Niklas S��derlund 7 */ 8 9#include <linux/delay.h> 10#include <linux/i2c.h> 11#include <linux/module.h> 12#include <linux/of_graph.h> 13#include <linux/regmap.h> 14 15#include <media/v4l2-ctrls.h> 16#include <media/v4l2-fwnode.h> 17#include <media/v4l2-subdev.h> 18 19#define MAX96712_ID 0x20 20 21#define MAX96712_DPLL_FREQ 1000 22 23enum max96712_pattern { 24 MAX96712_PATTERN_CHECKERBOARD = 0, 25 MAX96712_PATTERN_GRADIENT, 26}; 27 28struct max96712_priv { 29 struct i2c_client *client; 30 struct regmap *regmap; 31 struct gpio_desc *gpiod_pwdn; 32 33 bool cphy; 34 struct v4l2_mbus_config_mipi_csi2 mipi; 35 36 struct v4l2_subdev sd; 37 struct v4l2_ctrl_handler ctrl_handler; 38 struct media_pad pads[1]; 39 40 enum max96712_pattern pattern; 41}; 42 43static int max96712_read(struct max96712_priv *priv, int reg) 44{ 45 int ret, val; 46 47 ret = regmap_read(priv->regmap, reg, &val); 48 if (ret) { 49 dev_err(&priv->client->dev, "read 0x%04x failed\n", reg); 50 return ret; 51 } 52 53 return val; 54} 55 56static int max96712_write(struct max96712_priv *priv, unsigned int reg, u8 val) 57{ 58 int ret; 59 60 ret = regmap_write(priv->regmap, reg, val); 61 if (ret) 62 dev_err(&priv->client->dev, "write 0x%04x failed\n", reg); 63 64 return ret; 65} 66 67static int max96712_update_bits(struct max96712_priv *priv, unsigned int reg, 68 u8 mask, u8 val) 69{ 70 int ret; 71 72 ret = regmap_update_bits(priv->regmap, reg, mask, val); 73 if (ret) 74 dev_err(&priv->client->dev, "update 0x%04x failed\n", reg); 75 76 return ret; 77} 78 79static int max96712_write_bulk(struct max96712_priv *priv, unsigned int reg, 80 const void *val, size_t val_count) 81{ 82 int ret; 83 84 ret = regmap_bulk_write(priv->regmap, reg, val, val_count); 85 if (ret) 86 dev_err(&priv->client->dev, "bulk write 0x%04x failed\n", reg); 87 88 return ret; 89} 90 91static int max96712_write_bulk_value(struct max96712_priv *priv, 92 unsigned int reg, unsigned int val, 93 size_t val_count) 94{ 95 unsigned int i; 96 u8 values[4]; 97 98 for (i = 1; i <= val_count; i++) 99 values[i - 1] = (val >> ((val_count - i) * 8)) & 0xff; 100 101 return max96712_write_bulk(priv, reg, &values, val_count); 102} 103 104static void max96712_reset(struct max96712_priv *priv) 105{ 106 max96712_update_bits(priv, 0x13, 0x40, 0x40); 107 msleep(20); 108} 109 110static void max96712_mipi_enable(struct max96712_priv *priv, bool enable) 111{ 112 if (enable) { 113 max96712_update_bits(priv, 0x40b, 0x02, 0x02); 114 max96712_update_bits(priv, 0x8a0, 0x80, 0x80); 115 } else { 116 max96712_update_bits(priv, 0x8a0, 0x80, 0x00); 117 max96712_update_bits(priv, 0x40b, 0x02, 0x00); 118 } 119} 120 121static void max96712_mipi_configure(struct max96712_priv *priv) 122{ 123 unsigned int i; 124 u8 phy5 = 0; 125 126 max96712_mipi_enable(priv, false); 127 128 /* Select 2x4 mode. */ 129 max96712_write(priv, 0x8a0, 0x04); 130 131 /* TODO: Add support for 2-lane and 1-lane configurations. */ 132 if (priv->cphy) { 133 /* Configure a 3-lane C-PHY using PHY0 and PHY1. */ 134 max96712_write(priv, 0x94a, 0xa0); 135 136 /* Configure C-PHY timings. */ 137 max96712_write(priv, 0x8ad, 0x3f); 138 max96712_write(priv, 0x8ae, 0x7d); 139 } else { 140 /* Configure a 4-lane D-PHY using PHY0 and PHY1. */ 141 max96712_write(priv, 0x94a, 0xc0); 142 } 143 144 /* Configure lane mapping for PHY0 and PHY1. */ 145 /* TODO: Add support for lane swapping. */ 146 max96712_write(priv, 0x8a3, 0xe4); 147 148 /* Configure lane polarity for PHY0 and PHY1. */ 149 for (i = 0; i < priv->mipi.num_data_lanes + 1; i++) 150 if (priv->mipi.lane_polarities[i]) 151 phy5 |= BIT(i == 0 ? 5 : i < 3 ? i - 1 : i); 152 max96712_write(priv, 0x8a5, phy5); 153 154 /* Set link frequency for PHY0 and PHY1. */ 155 max96712_update_bits(priv, 0x415, 0x3f, 156 ((MAX96712_DPLL_FREQ / 100) & 0x1f) | BIT(5)); 157 max96712_update_bits(priv, 0x418, 0x3f, 158 ((MAX96712_DPLL_FREQ / 100) & 0x1f) | BIT(5)); 159 160 /* Enable PHY0 and PHY1 */ 161 max96712_update_bits(priv, 0x8a2, 0xf0, 0x30); 162} 163 164static void max96712_pattern_enable(struct max96712_priv *priv, bool enable) 165{ 166 const u32 h_active = 1920; 167 const u32 h_fp = 88; 168 const u32 h_sw = 44; 169 const u32 h_bp = 148; 170 const u32 h_tot = h_active + h_fp + h_sw + h_bp; 171 172 const u32 v_active = 1080; 173 const u32 v_fp = 4; 174 const u32 v_sw = 5; 175 const u32 v_bp = 36; 176 const u32 v_tot = v_active + v_fp + v_sw + v_bp; 177 178 if (!enable) { 179 max96712_write(priv, 0x1051, 0x00); 180 return; 181 } 182 183 /* PCLK 75MHz. */ 184 max96712_write(priv, 0x0009, 0x01); 185 186 /* Configure Video Timing Generator for 1920x1080 @ 30 fps. */ 187 max96712_write_bulk_value(priv, 0x1052, 0, 3); 188 max96712_write_bulk_value(priv, 0x1055, v_sw * h_tot, 3); 189 max96712_write_bulk_value(priv, 0x1058, 190 (v_active + v_fp + + v_bp) * h_tot, 3); 191 max96712_write_bulk_value(priv, 0x105b, 0, 3); 192 max96712_write_bulk_value(priv, 0x105e, h_sw, 2); 193 max96712_write_bulk_value(priv, 0x1060, h_active + h_fp + h_bp, 2); 194 max96712_write_bulk_value(priv, 0x1062, v_tot, 2); 195 max96712_write_bulk_value(priv, 0x1064, 196 h_tot * (v_sw + v_bp) + (h_sw + h_bp), 3); 197 max96712_write_bulk_value(priv, 0x1067, h_active, 2); 198 max96712_write_bulk_value(priv, 0x1069, h_fp + h_sw + h_bp, 2); 199 max96712_write_bulk_value(priv, 0x106b, v_active, 2); 200 201 /* Generate VS, HS and DE in free-running mode. */ 202 max96712_write(priv, 0x1050, 0xfb); 203 204 /* Configure Video Pattern Generator. */ 205 if (priv->pattern == MAX96712_PATTERN_CHECKERBOARD) { 206 /* Set checkerboard pattern size. */ 207 max96712_write(priv, 0x1074, 0x3c); 208 max96712_write(priv, 0x1075, 0x3c); 209 max96712_write(priv, 0x1076, 0x3c); 210 211 /* Set checkerboard pattern colors. */ 212 max96712_write_bulk_value(priv, 0x106e, 0xfecc00, 3); 213 max96712_write_bulk_value(priv, 0x1071, 0x006aa7, 3); 214 215 /* Generate checkerboard pattern. */ 216 max96712_write(priv, 0x1051, 0x10); 217 } else { 218 /* Set gradient increment. */ 219 max96712_write(priv, 0x106d, 0x10); 220 221 /* Generate gradient pattern. */ 222 max96712_write(priv, 0x1051, 0x20); 223 } 224} 225 226static int max96712_s_stream(struct v4l2_subdev *sd, int enable) 227{ 228 struct max96712_priv *priv = v4l2_get_subdevdata(sd); 229 230 if (enable) { 231 max96712_pattern_enable(priv, true); 232 max96712_mipi_enable(priv, true); 233 } else { 234 max96712_mipi_enable(priv, false); 235 max96712_pattern_enable(priv, false); 236 } 237 238 return 0; 239} 240 241static const struct v4l2_subdev_video_ops max96712_video_ops = { 242 .s_stream = max96712_s_stream, 243}; 244 245static int max96712_get_pad_format(struct v4l2_subdev *sd, 246 struct v4l2_subdev_state *sd_state, 247 struct v4l2_subdev_format *format) 248{ 249 format->format.width = 1920; 250 format->format.height = 1080; 251 format->format.code = MEDIA_BUS_FMT_RGB888_1X24; 252 format->format.field = V4L2_FIELD_NONE; 253 254 return 0; 255} 256 257static const struct v4l2_subdev_pad_ops max96712_pad_ops = { 258 .get_fmt = max96712_get_pad_format, 259 .set_fmt = max96712_get_pad_format, 260}; 261 262static const struct v4l2_subdev_ops max96712_subdev_ops = { 263 .video = &max96712_video_ops, 264 .pad = &max96712_pad_ops, 265}; 266 267static const char * const max96712_test_pattern[] = { 268 "Checkerboard", 269 "Gradient", 270}; 271 272static int max96712_s_ctrl(struct v4l2_ctrl *ctrl) 273{ 274 struct max96712_priv *priv = 275 container_of(ctrl->handler, struct max96712_priv, ctrl_handler); 276 277 switch (ctrl->id) { 278 case V4L2_CID_TEST_PATTERN: 279 priv->pattern = ctrl->val ? 280 MAX96712_PATTERN_GRADIENT : 281 MAX96712_PATTERN_CHECKERBOARD; 282 break; 283 } 284 return 0; 285} 286 287static const struct v4l2_ctrl_ops max96712_ctrl_ops = { 288 .s_ctrl = max96712_s_ctrl, 289}; 290 291static int max96712_v4l2_register(struct max96712_priv *priv) 292{ 293 long pixel_rate; 294 int ret; 295 296 v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96712_subdev_ops); 297 priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 298 priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; 299 300 v4l2_ctrl_handler_init(&priv->ctrl_handler, 2); 301 302 /* 303 * TODO: Once V4L2_CID_LINK_FREQ is changed from a menu control to an 304 * INT64 control it should be used here instead of V4L2_CID_PIXEL_RATE. 305 */ 306 pixel_rate = MAX96712_DPLL_FREQ / priv->mipi.num_data_lanes * 1000000; 307 v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE, 308 pixel_rate, pixel_rate, 1, pixel_rate); 309 310 v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, &max96712_ctrl_ops, 311 V4L2_CID_TEST_PATTERN, 312 ARRAY_SIZE(max96712_test_pattern) - 1, 313 0, 0, max96712_test_pattern); 314 315 priv->sd.ctrl_handler = &priv->ctrl_handler; 316 ret = priv->ctrl_handler.error; 317 if (ret) 318 goto error; 319 320 priv->pads[0].flags = MEDIA_PAD_FL_SOURCE; 321 ret = media_entity_pads_init(&priv->sd.entity, 1, priv->pads); 322 if (ret) 323 goto error; 324 325 v4l2_set_subdevdata(&priv->sd, priv); 326 327 ret = v4l2_async_register_subdev(&priv->sd); 328 if (ret < 0) { 329 dev_err(&priv->client->dev, "Unable to register subdevice\n"); 330 goto error; 331 } 332 333 return 0; 334error: 335 v4l2_ctrl_handler_free(&priv->ctrl_handler); 336 337 return ret; 338} 339 340static int max96712_parse_dt(struct max96712_priv *priv) 341{ 342 struct fwnode_handle *ep; 343 struct v4l2_fwnode_endpoint v4l2_ep = { 344 .bus_type = V4L2_MBUS_UNKNOWN, 345 }; 346 unsigned int supported_lanes; 347 int ret; 348 349 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4, 350 0, 0); 351 if (!ep) { 352 dev_err(&priv->client->dev, "Not connected to subdevice\n"); 353 return -EINVAL; 354 } 355 356 ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep); 357 fwnode_handle_put(ep); 358 if (ret) { 359 dev_err(&priv->client->dev, "Could not parse v4l2 endpoint\n"); 360 return -EINVAL; 361 } 362 363 switch (v4l2_ep.bus_type) { 364 case V4L2_MBUS_CSI2_DPHY: 365 supported_lanes = 4; 366 priv->cphy = false; 367 break; 368 case V4L2_MBUS_CSI2_CPHY: 369 supported_lanes = 3; 370 priv->cphy = true; 371 break; 372 default: 373 dev_err(&priv->client->dev, "Unsupported bus-type %u\n", 374 v4l2_ep.bus_type); 375 return -EINVAL; 376 } 377 378 if (v4l2_ep.bus.mipi_csi2.num_data_lanes != supported_lanes) { 379 dev_err(&priv->client->dev, "Only %u data lanes supported\n", 380 supported_lanes); 381 return -EINVAL; 382 } 383 384 priv->mipi = v4l2_ep.bus.mipi_csi2; 385 386 return 0; 387} 388 389static const struct regmap_config max96712_i2c_regmap = { 390 .reg_bits = 16, 391 .val_bits = 8, 392 .max_register = 0x1f00, 393}; 394 395static int max96712_probe(struct i2c_client *client) 396{ 397 struct max96712_priv *priv; 398 int ret; 399 400 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 401 if (!priv) 402 return -ENOMEM; 403 404 priv->client = client; 405 i2c_set_clientdata(client, priv); 406 407 priv->regmap = devm_regmap_init_i2c(client, &max96712_i2c_regmap); 408 if (IS_ERR(priv->regmap)) 409 return PTR_ERR(priv->regmap); 410 411 priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable", 412 GPIOD_OUT_HIGH); 413 if (IS_ERR(priv->gpiod_pwdn)) 414 return PTR_ERR(priv->gpiod_pwdn); 415 416 gpiod_set_consumer_name(priv->gpiod_pwdn, "max96712-pwdn"); 417 gpiod_set_value_cansleep(priv->gpiod_pwdn, 1); 418 419 if (priv->gpiod_pwdn) 420 usleep_range(4000, 5000); 421 422 if (max96712_read(priv, 0x4a) != MAX96712_ID) 423 return -ENODEV; 424 425 max96712_reset(priv); 426 427 ret = max96712_parse_dt(priv); 428 if (ret) 429 return ret; 430 431 max96712_mipi_configure(priv); 432 433 return max96712_v4l2_register(priv); 434} 435 436static void max96712_remove(struct i2c_client *client) 437{ 438 struct max96712_priv *priv = i2c_get_clientdata(client); 439 440 v4l2_async_unregister_subdev(&priv->sd); 441 442 gpiod_set_value_cansleep(priv->gpiod_pwdn, 0); 443} 444 445static const struct of_device_id max96712_of_table[] = { 446 { .compatible = "maxim,max96712" }, 447 { /* sentinel */ }, 448}; 449MODULE_DEVICE_TABLE(of, max96712_of_table); 450 451static struct i2c_driver max96712_i2c_driver = { 452 .driver = { 453 .name = "max96712", 454 .of_match_table = of_match_ptr(max96712_of_table), 455 }, 456 .probe = max96712_probe, 457 .remove = max96712_remove, 458}; 459 460module_i2c_driver(max96712_i2c_driver); 461 462MODULE_DESCRIPTION("Maxim MAX96712 Quad GMSL2 Deserializer Driver"); 463MODULE_AUTHOR("Niklas S��derlund <niklas.soderlund@ragnatech.se>"); 464MODULE_LICENSE("GPL"); 465