Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: rcar-csi2: add Renesas R-Car MIPI CSI-2 receiver driver

A V4L2 driver for Renesas R-Car MIPI CSI-2 receiver. The driver
supports the R-Car Gen3 SoCs where separate CSI-2 hardware blocks are
connected between the video sources and the video grabbers (VIN).

Driver is based on a prototype by Koji Matsuoka in the Renesas BSP.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>

authored by

Niklas Söderlund and committed by
Mauro Carvalho Chehab
769afd21 385c83eb

+1097
+12
drivers/media/platform/rcar-vin/Kconfig
··· 1 + config VIDEO_RCAR_CSI2 2 + tristate "R-Car MIPI CSI-2 Receiver" 3 + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF 4 + depends on ARCH_RENESAS || COMPILE_TEST 5 + select V4L2_FWNODE 6 + help 7 + Support for Renesas R-Car MIPI CSI-2 receiver. 8 + Supports R-Car Gen3 SoCs. 9 + 10 + To compile this driver as a module, choose M here: the 11 + module will be called rcar-csi2. 12 + 1 13 config VIDEO_RCAR_VIN 2 14 tristate "R-Car Video Input (VIN) Driver" 3 15 depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && HAS_DMA && MEDIA_CONTROLLER
+1
drivers/media/platform/rcar-vin/Makefile
··· 1 1 rcar-vin-objs = rcar-core.o rcar-dma.o rcar-v4l2.o 2 2 3 + obj-$(CONFIG_VIDEO_RCAR_CSI2) += rcar-csi2.o 3 4 obj-$(CONFIG_VIDEO_RCAR_VIN) += rcar-vin.o
+1084
drivers/media/platform/rcar-vin/rcar-csi2.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Driver for Renesas R-Car MIPI CSI-2 Receiver 4 + * 5 + * Copyright (C) 2018 Renesas Electronics Corp. 6 + */ 7 + 8 + #include <linux/delay.h> 9 + #include <linux/interrupt.h> 10 + #include <linux/io.h> 11 + #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/of_device.h> 14 + #include <linux/of_graph.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/pm_runtime.h> 17 + #include <linux/sys_soc.h> 18 + 19 + #include <media/v4l2-ctrls.h> 20 + #include <media/v4l2-device.h> 21 + #include <media/v4l2-fwnode.h> 22 + #include <media/v4l2-mc.h> 23 + #include <media/v4l2-subdev.h> 24 + 25 + struct rcar_csi2; 26 + 27 + /* Register offsets and bits */ 28 + 29 + /* Control Timing Select */ 30 + #define TREF_REG 0x00 31 + #define TREF_TREF BIT(0) 32 + 33 + /* Software Reset */ 34 + #define SRST_REG 0x04 35 + #define SRST_SRST BIT(0) 36 + 37 + /* PHY Operation Control */ 38 + #define PHYCNT_REG 0x08 39 + #define PHYCNT_SHUTDOWNZ BIT(17) 40 + #define PHYCNT_RSTZ BIT(16) 41 + #define PHYCNT_ENABLECLK BIT(4) 42 + #define PHYCNT_ENABLE_3 BIT(3) 43 + #define PHYCNT_ENABLE_2 BIT(2) 44 + #define PHYCNT_ENABLE_1 BIT(1) 45 + #define PHYCNT_ENABLE_0 BIT(0) 46 + 47 + /* Checksum Control */ 48 + #define CHKSUM_REG 0x0c 49 + #define CHKSUM_ECC_EN BIT(1) 50 + #define CHKSUM_CRC_EN BIT(0) 51 + 52 + /* 53 + * Channel Data Type Select 54 + * VCDT[0-15]: Channel 1 VCDT[16-31]: Channel 2 55 + * VCDT2[0-15]: Channel 3 VCDT2[16-31]: Channel 4 56 + */ 57 + #define VCDT_REG 0x10 58 + #define VCDT2_REG 0x14 59 + #define VCDT_VCDTN_EN BIT(15) 60 + #define VCDT_SEL_VC(n) (((n) & 0x3) << 8) 61 + #define VCDT_SEL_DTN_ON BIT(6) 62 + #define VCDT_SEL_DT(n) (((n) & 0x3f) << 0) 63 + 64 + /* Frame Data Type Select */ 65 + #define FRDT_REG 0x18 66 + 67 + /* Field Detection Control */ 68 + #define FLD_REG 0x1c 69 + #define FLD_FLD_NUM(n) (((n) & 0xff) << 16) 70 + #define FLD_FLD_EN4 BIT(3) 71 + #define FLD_FLD_EN3 BIT(2) 72 + #define FLD_FLD_EN2 BIT(1) 73 + #define FLD_FLD_EN BIT(0) 74 + 75 + /* Automatic Standby Control */ 76 + #define ASTBY_REG 0x20 77 + 78 + /* Long Data Type Setting 0 */ 79 + #define LNGDT0_REG 0x28 80 + 81 + /* Long Data Type Setting 1 */ 82 + #define LNGDT1_REG 0x2c 83 + 84 + /* Interrupt Enable */ 85 + #define INTEN_REG 0x30 86 + 87 + /* Interrupt Source Mask */ 88 + #define INTCLOSE_REG 0x34 89 + 90 + /* Interrupt Status Monitor */ 91 + #define INTSTATE_REG 0x38 92 + #define INTSTATE_INT_ULPS_START BIT(7) 93 + #define INTSTATE_INT_ULPS_END BIT(6) 94 + 95 + /* Interrupt Error Status Monitor */ 96 + #define INTERRSTATE_REG 0x3c 97 + 98 + /* Short Packet Data */ 99 + #define SHPDAT_REG 0x40 100 + 101 + /* Short Packet Count */ 102 + #define SHPCNT_REG 0x44 103 + 104 + /* LINK Operation Control */ 105 + #define LINKCNT_REG 0x48 106 + #define LINKCNT_MONITOR_EN BIT(31) 107 + #define LINKCNT_REG_MONI_PACT_EN BIT(25) 108 + #define LINKCNT_ICLK_NONSTOP BIT(24) 109 + 110 + /* Lane Swap */ 111 + #define LSWAP_REG 0x4c 112 + #define LSWAP_L3SEL(n) (((n) & 0x3) << 6) 113 + #define LSWAP_L2SEL(n) (((n) & 0x3) << 4) 114 + #define LSWAP_L1SEL(n) (((n) & 0x3) << 2) 115 + #define LSWAP_L0SEL(n) (((n) & 0x3) << 0) 116 + 117 + /* PHY Test Interface Write Register */ 118 + #define PHTW_REG 0x50 119 + #define PHTW_DWEN BIT(24) 120 + #define PHTW_TESTDIN_DATA(n) (((n & 0xff)) << 16) 121 + #define PHTW_CWEN BIT(8) 122 + #define PHTW_TESTDIN_CODE(n) ((n & 0xff)) 123 + 124 + struct phtw_value { 125 + u16 data; 126 + u16 code; 127 + }; 128 + 129 + struct rcsi2_mbps_reg { 130 + u16 mbps; 131 + u16 reg; 132 + }; 133 + 134 + static const struct rcsi2_mbps_reg phtw_mbps_h3_v3h_m3n[] = { 135 + { .mbps = 80, .reg = 0x86 }, 136 + { .mbps = 90, .reg = 0x86 }, 137 + { .mbps = 100, .reg = 0x87 }, 138 + { .mbps = 110, .reg = 0x87 }, 139 + { .mbps = 120, .reg = 0x88 }, 140 + { .mbps = 130, .reg = 0x88 }, 141 + { .mbps = 140, .reg = 0x89 }, 142 + { .mbps = 150, .reg = 0x89 }, 143 + { .mbps = 160, .reg = 0x8a }, 144 + { .mbps = 170, .reg = 0x8a }, 145 + { .mbps = 180, .reg = 0x8b }, 146 + { .mbps = 190, .reg = 0x8b }, 147 + { .mbps = 205, .reg = 0x8c }, 148 + { .mbps = 220, .reg = 0x8d }, 149 + { .mbps = 235, .reg = 0x8e }, 150 + { .mbps = 250, .reg = 0x8e }, 151 + { /* sentinel */ }, 152 + }; 153 + 154 + static const struct rcsi2_mbps_reg phtw_mbps_v3m_e3[] = { 155 + { .mbps = 80, .reg = 0x00 }, 156 + { .mbps = 90, .reg = 0x20 }, 157 + { .mbps = 100, .reg = 0x40 }, 158 + { .mbps = 110, .reg = 0x02 }, 159 + { .mbps = 130, .reg = 0x22 }, 160 + { .mbps = 140, .reg = 0x42 }, 161 + { .mbps = 150, .reg = 0x04 }, 162 + { .mbps = 170, .reg = 0x24 }, 163 + { .mbps = 180, .reg = 0x44 }, 164 + { .mbps = 200, .reg = 0x06 }, 165 + { .mbps = 220, .reg = 0x26 }, 166 + { .mbps = 240, .reg = 0x46 }, 167 + { .mbps = 250, .reg = 0x08 }, 168 + { .mbps = 270, .reg = 0x28 }, 169 + { .mbps = 300, .reg = 0x0a }, 170 + { .mbps = 330, .reg = 0x2a }, 171 + { .mbps = 360, .reg = 0x4a }, 172 + { .mbps = 400, .reg = 0x0c }, 173 + { .mbps = 450, .reg = 0x2c }, 174 + { .mbps = 500, .reg = 0x0e }, 175 + { .mbps = 550, .reg = 0x2e }, 176 + { .mbps = 600, .reg = 0x10 }, 177 + { .mbps = 650, .reg = 0x30 }, 178 + { .mbps = 700, .reg = 0x12 }, 179 + { .mbps = 750, .reg = 0x32 }, 180 + { .mbps = 800, .reg = 0x52 }, 181 + { .mbps = 850, .reg = 0x72 }, 182 + { .mbps = 900, .reg = 0x14 }, 183 + { .mbps = 950, .reg = 0x34 }, 184 + { .mbps = 1000, .reg = 0x54 }, 185 + { .mbps = 1050, .reg = 0x74 }, 186 + { .mbps = 1125, .reg = 0x16 }, 187 + { /* sentinel */ }, 188 + }; 189 + 190 + /* PHY Test Interface Clear */ 191 + #define PHTC_REG 0x58 192 + #define PHTC_TESTCLR BIT(0) 193 + 194 + /* PHY Frequency Control */ 195 + #define PHYPLL_REG 0x68 196 + #define PHYPLL_HSFREQRANGE(n) ((n) << 16) 197 + 198 + static const struct rcsi2_mbps_reg hsfreqrange_h3_v3h_m3n[] = { 199 + { .mbps = 80, .reg = 0x00 }, 200 + { .mbps = 90, .reg = 0x10 }, 201 + { .mbps = 100, .reg = 0x20 }, 202 + { .mbps = 110, .reg = 0x30 }, 203 + { .mbps = 120, .reg = 0x01 }, 204 + { .mbps = 130, .reg = 0x11 }, 205 + { .mbps = 140, .reg = 0x21 }, 206 + { .mbps = 150, .reg = 0x31 }, 207 + { .mbps = 160, .reg = 0x02 }, 208 + { .mbps = 170, .reg = 0x12 }, 209 + { .mbps = 180, .reg = 0x22 }, 210 + { .mbps = 190, .reg = 0x32 }, 211 + { .mbps = 205, .reg = 0x03 }, 212 + { .mbps = 220, .reg = 0x13 }, 213 + { .mbps = 235, .reg = 0x23 }, 214 + { .mbps = 250, .reg = 0x33 }, 215 + { .mbps = 275, .reg = 0x04 }, 216 + { .mbps = 300, .reg = 0x14 }, 217 + { .mbps = 325, .reg = 0x25 }, 218 + { .mbps = 350, .reg = 0x35 }, 219 + { .mbps = 400, .reg = 0x05 }, 220 + { .mbps = 450, .reg = 0x16 }, 221 + { .mbps = 500, .reg = 0x26 }, 222 + { .mbps = 550, .reg = 0x37 }, 223 + { .mbps = 600, .reg = 0x07 }, 224 + { .mbps = 650, .reg = 0x18 }, 225 + { .mbps = 700, .reg = 0x28 }, 226 + { .mbps = 750, .reg = 0x39 }, 227 + { .mbps = 800, .reg = 0x09 }, 228 + { .mbps = 850, .reg = 0x19 }, 229 + { .mbps = 900, .reg = 0x29 }, 230 + { .mbps = 950, .reg = 0x3a }, 231 + { .mbps = 1000, .reg = 0x0a }, 232 + { .mbps = 1050, .reg = 0x1a }, 233 + { .mbps = 1100, .reg = 0x2a }, 234 + { .mbps = 1150, .reg = 0x3b }, 235 + { .mbps = 1200, .reg = 0x0b }, 236 + { .mbps = 1250, .reg = 0x1b }, 237 + { .mbps = 1300, .reg = 0x2b }, 238 + { .mbps = 1350, .reg = 0x3c }, 239 + { .mbps = 1400, .reg = 0x0c }, 240 + { .mbps = 1450, .reg = 0x1c }, 241 + { .mbps = 1500, .reg = 0x2c }, 242 + { /* sentinel */ }, 243 + }; 244 + 245 + static const struct rcsi2_mbps_reg hsfreqrange_m3w_h3es1[] = { 246 + { .mbps = 80, .reg = 0x00 }, 247 + { .mbps = 90, .reg = 0x10 }, 248 + { .mbps = 100, .reg = 0x20 }, 249 + { .mbps = 110, .reg = 0x30 }, 250 + { .mbps = 120, .reg = 0x01 }, 251 + { .mbps = 130, .reg = 0x11 }, 252 + { .mbps = 140, .reg = 0x21 }, 253 + { .mbps = 150, .reg = 0x31 }, 254 + { .mbps = 160, .reg = 0x02 }, 255 + { .mbps = 170, .reg = 0x12 }, 256 + { .mbps = 180, .reg = 0x22 }, 257 + { .mbps = 190, .reg = 0x32 }, 258 + { .mbps = 205, .reg = 0x03 }, 259 + { .mbps = 220, .reg = 0x13 }, 260 + { .mbps = 235, .reg = 0x23 }, 261 + { .mbps = 250, .reg = 0x33 }, 262 + { .mbps = 275, .reg = 0x04 }, 263 + { .mbps = 300, .reg = 0x14 }, 264 + { .mbps = 325, .reg = 0x05 }, 265 + { .mbps = 350, .reg = 0x15 }, 266 + { .mbps = 400, .reg = 0x25 }, 267 + { .mbps = 450, .reg = 0x06 }, 268 + { .mbps = 500, .reg = 0x16 }, 269 + { .mbps = 550, .reg = 0x07 }, 270 + { .mbps = 600, .reg = 0x17 }, 271 + { .mbps = 650, .reg = 0x08 }, 272 + { .mbps = 700, .reg = 0x18 }, 273 + { .mbps = 750, .reg = 0x09 }, 274 + { .mbps = 800, .reg = 0x19 }, 275 + { .mbps = 850, .reg = 0x29 }, 276 + { .mbps = 900, .reg = 0x39 }, 277 + { .mbps = 950, .reg = 0x0a }, 278 + { .mbps = 1000, .reg = 0x1a }, 279 + { .mbps = 1050, .reg = 0x2a }, 280 + { .mbps = 1100, .reg = 0x3a }, 281 + { .mbps = 1150, .reg = 0x0b }, 282 + { .mbps = 1200, .reg = 0x1b }, 283 + { .mbps = 1250, .reg = 0x2b }, 284 + { .mbps = 1300, .reg = 0x3b }, 285 + { .mbps = 1350, .reg = 0x0c }, 286 + { .mbps = 1400, .reg = 0x1c }, 287 + { .mbps = 1450, .reg = 0x2c }, 288 + { .mbps = 1500, .reg = 0x3c }, 289 + { /* sentinel */ }, 290 + }; 291 + 292 + /* PHY ESC Error Monitor */ 293 + #define PHEERM_REG 0x74 294 + 295 + /* PHY Clock Lane Monitor */ 296 + #define PHCLM_REG 0x78 297 + #define PHCLM_STOPSTATECKL BIT(0) 298 + 299 + /* PHY Data Lane Monitor */ 300 + #define PHDLM_REG 0x7c 301 + 302 + /* CSI0CLK Frequency Configuration Preset Register */ 303 + #define CSI0CLKFCPR_REG 0x260 304 + #define CSI0CLKFREQRANGE(n) ((n & 0x3f) << 16) 305 + 306 + struct rcar_csi2_format { 307 + u32 code; 308 + unsigned int datatype; 309 + unsigned int bpp; 310 + }; 311 + 312 + static const struct rcar_csi2_format rcar_csi2_formats[] = { 313 + { .code = MEDIA_BUS_FMT_RGB888_1X24, .datatype = 0x24, .bpp = 24 }, 314 + { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, .bpp = 16 }, 315 + { .code = MEDIA_BUS_FMT_YUYV8_1X16, .datatype = 0x1e, .bpp = 16 }, 316 + { .code = MEDIA_BUS_FMT_UYVY8_2X8, .datatype = 0x1e, .bpp = 16 }, 317 + { .code = MEDIA_BUS_FMT_YUYV10_2X10, .datatype = 0x1e, .bpp = 20 }, 318 + }; 319 + 320 + static const struct rcar_csi2_format *rcsi2_code_to_fmt(unsigned int code) 321 + { 322 + unsigned int i; 323 + 324 + for (i = 0; i < ARRAY_SIZE(rcar_csi2_formats); i++) 325 + if (rcar_csi2_formats[i].code == code) 326 + return &rcar_csi2_formats[i]; 327 + 328 + return NULL; 329 + } 330 + 331 + enum rcar_csi2_pads { 332 + RCAR_CSI2_SINK, 333 + RCAR_CSI2_SOURCE_VC0, 334 + RCAR_CSI2_SOURCE_VC1, 335 + RCAR_CSI2_SOURCE_VC2, 336 + RCAR_CSI2_SOURCE_VC3, 337 + NR_OF_RCAR_CSI2_PAD, 338 + }; 339 + 340 + struct rcar_csi2_info { 341 + int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps); 342 + const struct rcsi2_mbps_reg *hsfreqrange; 343 + unsigned int csi0clkfreqrange; 344 + bool clear_ulps; 345 + }; 346 + 347 + struct rcar_csi2 { 348 + struct device *dev; 349 + void __iomem *base; 350 + const struct rcar_csi2_info *info; 351 + 352 + struct v4l2_subdev subdev; 353 + struct media_pad pads[NR_OF_RCAR_CSI2_PAD]; 354 + 355 + struct v4l2_async_notifier notifier; 356 + struct v4l2_async_subdev asd; 357 + struct v4l2_subdev *remote; 358 + 359 + struct v4l2_mbus_framefmt mf; 360 + 361 + struct mutex lock; 362 + int stream_count; 363 + 364 + unsigned short lanes; 365 + unsigned char lane_swap[4]; 366 + }; 367 + 368 + static inline struct rcar_csi2 *sd_to_csi2(struct v4l2_subdev *sd) 369 + { 370 + return container_of(sd, struct rcar_csi2, subdev); 371 + } 372 + 373 + static inline struct rcar_csi2 *notifier_to_csi2(struct v4l2_async_notifier *n) 374 + { 375 + return container_of(n, struct rcar_csi2, notifier); 376 + } 377 + 378 + static u32 rcsi2_read(struct rcar_csi2 *priv, unsigned int reg) 379 + { 380 + return ioread32(priv->base + reg); 381 + } 382 + 383 + static void rcsi2_write(struct rcar_csi2 *priv, unsigned int reg, u32 data) 384 + { 385 + iowrite32(data, priv->base + reg); 386 + } 387 + 388 + static void rcsi2_reset(struct rcar_csi2 *priv) 389 + { 390 + rcsi2_write(priv, SRST_REG, SRST_SRST); 391 + usleep_range(100, 150); 392 + rcsi2_write(priv, SRST_REG, 0); 393 + } 394 + 395 + static int rcsi2_wait_phy_start(struct rcar_csi2 *priv) 396 + { 397 + unsigned int timeout; 398 + 399 + /* Wait for the clock and data lanes to enter LP-11 state. */ 400 + for (timeout = 0; timeout <= 20; timeout++) { 401 + const u32 lane_mask = (1 << priv->lanes) - 1; 402 + 403 + if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL) && 404 + (rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask) 405 + return 0; 406 + 407 + usleep_range(1000, 2000); 408 + } 409 + 410 + dev_err(priv->dev, "Timeout waiting for LP-11 state\n"); 411 + 412 + return -ETIMEDOUT; 413 + } 414 + 415 + static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps) 416 + { 417 + const struct rcsi2_mbps_reg *hsfreq; 418 + 419 + for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) 420 + if (hsfreq->mbps >= mbps) 421 + break; 422 + 423 + if (!hsfreq->mbps) { 424 + dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps); 425 + return -ERANGE; 426 + } 427 + 428 + rcsi2_write(priv, PHYPLL_REG, PHYPLL_HSFREQRANGE(hsfreq->reg)); 429 + 430 + return 0; 431 + } 432 + 433 + static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) 434 + { 435 + struct v4l2_subdev *source; 436 + struct v4l2_ctrl *ctrl; 437 + u64 mbps; 438 + 439 + if (!priv->remote) 440 + return -ENODEV; 441 + 442 + source = priv->remote; 443 + 444 + /* Read the pixel rate control from remote. */ 445 + ctrl = v4l2_ctrl_find(source->ctrl_handler, V4L2_CID_PIXEL_RATE); 446 + if (!ctrl) { 447 + dev_err(priv->dev, "no pixel rate control in subdev %s\n", 448 + source->name); 449 + return -EINVAL; 450 + } 451 + 452 + /* 453 + * Calculate the phypll in mbps. 454 + * link_freq = (pixel_rate * bits_per_sample) / (2 * nr_of_lanes) 455 + * bps = link_freq * 2 456 + */ 457 + mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp; 458 + do_div(mbps, priv->lanes * 1000000); 459 + 460 + return mbps; 461 + } 462 + 463 + static int rcsi2_start(struct rcar_csi2 *priv) 464 + { 465 + const struct rcar_csi2_format *format; 466 + u32 phycnt, vcdt = 0, vcdt2 = 0; 467 + unsigned int i; 468 + int mbps, ret; 469 + 470 + dev_dbg(priv->dev, "Input size (%ux%u%c)\n", 471 + priv->mf.width, priv->mf.height, 472 + priv->mf.field == V4L2_FIELD_NONE ? 'p' : 'i'); 473 + 474 + /* Code is validated in set_fmt. */ 475 + format = rcsi2_code_to_fmt(priv->mf.code); 476 + 477 + /* 478 + * Enable all Virtual Channels. 479 + * 480 + * NOTE: It's not possible to get individual datatype for each 481 + * source virtual channel. Once this is possible in V4L2 482 + * it should be used here. 483 + */ 484 + for (i = 0; i < 4; i++) { 485 + u32 vcdt_part; 486 + 487 + vcdt_part = VCDT_SEL_VC(i) | VCDT_VCDTN_EN | VCDT_SEL_DTN_ON | 488 + VCDT_SEL_DT(format->datatype); 489 + 490 + /* Store in correct reg and offset. */ 491 + if (i < 2) 492 + vcdt |= vcdt_part << ((i % 2) * 16); 493 + else 494 + vcdt2 |= vcdt_part << ((i % 2) * 16); 495 + } 496 + 497 + phycnt = PHYCNT_ENABLECLK; 498 + phycnt |= (1 << priv->lanes) - 1; 499 + 500 + mbps = rcsi2_calc_mbps(priv, format->bpp); 501 + if (mbps < 0) 502 + return mbps; 503 + 504 + /* Init */ 505 + rcsi2_write(priv, TREF_REG, TREF_TREF); 506 + rcsi2_reset(priv); 507 + rcsi2_write(priv, PHTC_REG, 0); 508 + 509 + /* Configure */ 510 + rcsi2_write(priv, FLD_REG, FLD_FLD_NUM(2) | FLD_FLD_EN4 | 511 + FLD_FLD_EN3 | FLD_FLD_EN2 | FLD_FLD_EN); 512 + rcsi2_write(priv, VCDT_REG, vcdt); 513 + rcsi2_write(priv, VCDT2_REG, vcdt2); 514 + /* Lanes are zero indexed. */ 515 + rcsi2_write(priv, LSWAP_REG, 516 + LSWAP_L0SEL(priv->lane_swap[0] - 1) | 517 + LSWAP_L1SEL(priv->lane_swap[1] - 1) | 518 + LSWAP_L2SEL(priv->lane_swap[2] - 1) | 519 + LSWAP_L3SEL(priv->lane_swap[3] - 1)); 520 + 521 + /* Start */ 522 + if (priv->info->init_phtw) { 523 + ret = priv->info->init_phtw(priv, mbps); 524 + if (ret) 525 + return ret; 526 + } 527 + 528 + if (priv->info->hsfreqrange) { 529 + ret = rcsi2_set_phypll(priv, mbps); 530 + if (ret) 531 + return ret; 532 + } 533 + 534 + if (priv->info->csi0clkfreqrange) 535 + rcsi2_write(priv, CSI0CLKFCPR_REG, 536 + CSI0CLKFREQRANGE(priv->info->csi0clkfreqrange)); 537 + 538 + rcsi2_write(priv, PHYCNT_REG, phycnt); 539 + rcsi2_write(priv, LINKCNT_REG, LINKCNT_MONITOR_EN | 540 + LINKCNT_REG_MONI_PACT_EN | LINKCNT_ICLK_NONSTOP); 541 + rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ); 542 + rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ); 543 + 544 + ret = rcsi2_wait_phy_start(priv); 545 + if (ret) 546 + return ret; 547 + 548 + /* Clear Ultra Low Power interrupt. */ 549 + if (priv->info->clear_ulps) 550 + rcsi2_write(priv, INTSTATE_REG, 551 + INTSTATE_INT_ULPS_START | 552 + INTSTATE_INT_ULPS_END); 553 + return 0; 554 + } 555 + 556 + static void rcsi2_stop(struct rcar_csi2 *priv) 557 + { 558 + rcsi2_write(priv, PHYCNT_REG, 0); 559 + 560 + rcsi2_reset(priv); 561 + 562 + rcsi2_write(priv, PHTC_REG, PHTC_TESTCLR); 563 + } 564 + 565 + static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable) 566 + { 567 + struct rcar_csi2 *priv = sd_to_csi2(sd); 568 + struct v4l2_subdev *nextsd; 569 + int ret = 0; 570 + 571 + mutex_lock(&priv->lock); 572 + 573 + if (!priv->remote) { 574 + ret = -ENODEV; 575 + goto out; 576 + } 577 + 578 + nextsd = priv->remote; 579 + 580 + if (enable && priv->stream_count == 0) { 581 + pm_runtime_get_sync(priv->dev); 582 + 583 + ret = rcsi2_start(priv); 584 + if (ret) { 585 + pm_runtime_put(priv->dev); 586 + goto out; 587 + } 588 + 589 + ret = v4l2_subdev_call(nextsd, video, s_stream, 1); 590 + if (ret) { 591 + rcsi2_stop(priv); 592 + pm_runtime_put(priv->dev); 593 + goto out; 594 + } 595 + } else if (!enable && priv->stream_count == 1) { 596 + rcsi2_stop(priv); 597 + v4l2_subdev_call(nextsd, video, s_stream, 0); 598 + pm_runtime_put(priv->dev); 599 + } 600 + 601 + priv->stream_count += enable ? 1 : -1; 602 + out: 603 + mutex_unlock(&priv->lock); 604 + 605 + return ret; 606 + } 607 + 608 + static int rcsi2_set_pad_format(struct v4l2_subdev *sd, 609 + struct v4l2_subdev_pad_config *cfg, 610 + struct v4l2_subdev_format *format) 611 + { 612 + struct rcar_csi2 *priv = sd_to_csi2(sd); 613 + struct v4l2_mbus_framefmt *framefmt; 614 + 615 + if (!rcsi2_code_to_fmt(format->format.code)) 616 + return -EINVAL; 617 + 618 + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 619 + priv->mf = format->format; 620 + } else { 621 + framefmt = v4l2_subdev_get_try_format(sd, cfg, 0); 622 + *framefmt = format->format; 623 + } 624 + 625 + return 0; 626 + } 627 + 628 + static int rcsi2_get_pad_format(struct v4l2_subdev *sd, 629 + struct v4l2_subdev_pad_config *cfg, 630 + struct v4l2_subdev_format *format) 631 + { 632 + struct rcar_csi2 *priv = sd_to_csi2(sd); 633 + 634 + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) 635 + format->format = priv->mf; 636 + else 637 + format->format = *v4l2_subdev_get_try_format(sd, cfg, 0); 638 + 639 + return 0; 640 + } 641 + 642 + static const struct v4l2_subdev_video_ops rcar_csi2_video_ops = { 643 + .s_stream = rcsi2_s_stream, 644 + }; 645 + 646 + static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = { 647 + .set_fmt = rcsi2_set_pad_format, 648 + .get_fmt = rcsi2_get_pad_format, 649 + }; 650 + 651 + static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = { 652 + .video = &rcar_csi2_video_ops, 653 + .pad = &rcar_csi2_pad_ops, 654 + }; 655 + 656 + /* ----------------------------------------------------------------------------- 657 + * Async handling and registration of subdevices and links. 658 + */ 659 + 660 + static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier, 661 + struct v4l2_subdev *subdev, 662 + struct v4l2_async_subdev *asd) 663 + { 664 + struct rcar_csi2 *priv = notifier_to_csi2(notifier); 665 + int pad; 666 + 667 + pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, 668 + MEDIA_PAD_FL_SOURCE); 669 + if (pad < 0) { 670 + dev_err(priv->dev, "Failed to find pad for %s\n", subdev->name); 671 + return pad; 672 + } 673 + 674 + priv->remote = subdev; 675 + 676 + dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad); 677 + 678 + return media_create_pad_link(&subdev->entity, pad, 679 + &priv->subdev.entity, 0, 680 + MEDIA_LNK_FL_ENABLED | 681 + MEDIA_LNK_FL_IMMUTABLE); 682 + } 683 + 684 + static void rcsi2_notify_unbind(struct v4l2_async_notifier *notifier, 685 + struct v4l2_subdev *subdev, 686 + struct v4l2_async_subdev *asd) 687 + { 688 + struct rcar_csi2 *priv = notifier_to_csi2(notifier); 689 + 690 + priv->remote = NULL; 691 + 692 + dev_dbg(priv->dev, "Unbind %s\n", subdev->name); 693 + } 694 + 695 + static const struct v4l2_async_notifier_operations rcar_csi2_notify_ops = { 696 + .bound = rcsi2_notify_bound, 697 + .unbind = rcsi2_notify_unbind, 698 + }; 699 + 700 + static int rcsi2_parse_v4l2(struct rcar_csi2 *priv, 701 + struct v4l2_fwnode_endpoint *vep) 702 + { 703 + unsigned int i; 704 + 705 + /* Only port 0 endpoint 0 is valid. */ 706 + if (vep->base.port || vep->base.id) 707 + return -ENOTCONN; 708 + 709 + if (vep->bus_type != V4L2_MBUS_CSI2) { 710 + dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type); 711 + return -EINVAL; 712 + } 713 + 714 + priv->lanes = vep->bus.mipi_csi2.num_data_lanes; 715 + if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) { 716 + dev_err(priv->dev, "Unsupported number of data-lanes: %u\n", 717 + priv->lanes); 718 + return -EINVAL; 719 + } 720 + 721 + for (i = 0; i < ARRAY_SIZE(priv->lane_swap); i++) { 722 + priv->lane_swap[i] = i < priv->lanes ? 723 + vep->bus.mipi_csi2.data_lanes[i] : i; 724 + 725 + /* Check for valid lane number. */ 726 + if (priv->lane_swap[i] < 1 || priv->lane_swap[i] > 4) { 727 + dev_err(priv->dev, "data-lanes must be in 1-4 range\n"); 728 + return -EINVAL; 729 + } 730 + } 731 + 732 + return 0; 733 + } 734 + 735 + static int rcsi2_parse_dt(struct rcar_csi2 *priv) 736 + { 737 + struct device_node *ep; 738 + struct v4l2_fwnode_endpoint v4l2_ep; 739 + int ret; 740 + 741 + ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0); 742 + if (!ep) { 743 + dev_err(priv->dev, "Not connected to subdevice\n"); 744 + return -EINVAL; 745 + } 746 + 747 + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &v4l2_ep); 748 + if (ret) { 749 + dev_err(priv->dev, "Could not parse v4l2 endpoint\n"); 750 + of_node_put(ep); 751 + return -EINVAL; 752 + } 753 + 754 + ret = rcsi2_parse_v4l2(priv, &v4l2_ep); 755 + if (ret) { 756 + of_node_put(ep); 757 + return ret; 758 + } 759 + 760 + priv->asd.match.fwnode = 761 + fwnode_graph_get_remote_endpoint(of_fwnode_handle(ep)); 762 + priv->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 763 + 764 + of_node_put(ep); 765 + 766 + priv->notifier.subdevs = devm_kzalloc(priv->dev, 767 + sizeof(*priv->notifier.subdevs), 768 + GFP_KERNEL); 769 + if (!priv->notifier.subdevs) 770 + return -ENOMEM; 771 + 772 + priv->notifier.num_subdevs = 1; 773 + priv->notifier.subdevs[0] = &priv->asd; 774 + priv->notifier.ops = &rcar_csi2_notify_ops; 775 + 776 + dev_dbg(priv->dev, "Found '%pOF'\n", 777 + to_of_node(priv->asd.match.fwnode)); 778 + 779 + return v4l2_async_subdev_notifier_register(&priv->subdev, 780 + &priv->notifier); 781 + } 782 + 783 + /* ----------------------------------------------------------------------------- 784 + * PHTW initialization sequences. 785 + * 786 + * NOTE: Magic values are from the datasheet and lack documentation. 787 + */ 788 + 789 + static int rcsi2_phtw_write(struct rcar_csi2 *priv, u16 data, u16 code) 790 + { 791 + unsigned int timeout; 792 + 793 + rcsi2_write(priv, PHTW_REG, 794 + PHTW_DWEN | PHTW_TESTDIN_DATA(data) | 795 + PHTW_CWEN | PHTW_TESTDIN_CODE(code)); 796 + 797 + /* Wait for DWEN and CWEN to be cleared by hardware. */ 798 + for (timeout = 0; timeout <= 20; timeout++) { 799 + if (!(rcsi2_read(priv, PHTW_REG) & (PHTW_DWEN | PHTW_CWEN))) 800 + return 0; 801 + 802 + usleep_range(1000, 2000); 803 + } 804 + 805 + dev_err(priv->dev, "Timeout waiting for PHTW_DWEN and/or PHTW_CWEN\n"); 806 + 807 + return -ETIMEDOUT; 808 + } 809 + 810 + static int rcsi2_phtw_write_array(struct rcar_csi2 *priv, 811 + const struct phtw_value *values) 812 + { 813 + const struct phtw_value *value; 814 + int ret; 815 + 816 + for (value = values; value->data || value->code; value++) { 817 + ret = rcsi2_phtw_write(priv, value->data, value->code); 818 + if (ret) 819 + return ret; 820 + } 821 + 822 + return 0; 823 + } 824 + 825 + static int rcsi2_phtw_write_mbps(struct rcar_csi2 *priv, unsigned int mbps, 826 + const struct rcsi2_mbps_reg *values, u16 code) 827 + { 828 + const struct rcsi2_mbps_reg *value; 829 + 830 + for (value = values; value->mbps; value++) 831 + if (value->mbps >= mbps) 832 + break; 833 + 834 + if (!value->mbps) { 835 + dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps); 836 + return -ERANGE; 837 + } 838 + 839 + return rcsi2_phtw_write(priv, value->reg, code); 840 + } 841 + 842 + static int rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, unsigned int mbps) 843 + { 844 + static const struct phtw_value step1[] = { 845 + { .data = 0xcc, .code = 0xe2 }, 846 + { .data = 0x01, .code = 0xe3 }, 847 + { .data = 0x11, .code = 0xe4 }, 848 + { .data = 0x01, .code = 0xe5 }, 849 + { .data = 0x10, .code = 0x04 }, 850 + { /* sentinel */ }, 851 + }; 852 + 853 + static const struct phtw_value step2[] = { 854 + { .data = 0x38, .code = 0x08 }, 855 + { .data = 0x01, .code = 0x00 }, 856 + { .data = 0x4b, .code = 0xac }, 857 + { .data = 0x03, .code = 0x00 }, 858 + { .data = 0x80, .code = 0x07 }, 859 + { /* sentinel */ }, 860 + }; 861 + 862 + int ret; 863 + 864 + ret = rcsi2_phtw_write_array(priv, step1); 865 + if (ret) 866 + return ret; 867 + 868 + if (mbps <= 250) { 869 + ret = rcsi2_phtw_write(priv, 0x39, 0x05); 870 + if (ret) 871 + return ret; 872 + 873 + ret = rcsi2_phtw_write_mbps(priv, mbps, phtw_mbps_h3_v3h_m3n, 874 + 0xf1); 875 + if (ret) 876 + return ret; 877 + } 878 + 879 + return rcsi2_phtw_write_array(priv, step2); 880 + } 881 + 882 + static int rcsi2_init_phtw_v3m_e3(struct rcar_csi2 *priv, unsigned int mbps) 883 + { 884 + static const struct phtw_value step1[] = { 885 + { .data = 0xed, .code = 0x34 }, 886 + { .data = 0xed, .code = 0x44 }, 887 + { .data = 0xed, .code = 0x54 }, 888 + { .data = 0xed, .code = 0x84 }, 889 + { .data = 0xed, .code = 0x94 }, 890 + { /* sentinel */ }, 891 + }; 892 + 893 + int ret; 894 + 895 + ret = rcsi2_phtw_write_mbps(priv, mbps, phtw_mbps_v3m_e3, 0x44); 896 + if (ret) 897 + return ret; 898 + 899 + return rcsi2_phtw_write_array(priv, step1); 900 + } 901 + 902 + /* ----------------------------------------------------------------------------- 903 + * Platform Device Driver. 904 + */ 905 + 906 + static const struct media_entity_operations rcar_csi2_entity_ops = { 907 + .link_validate = v4l2_subdev_link_validate, 908 + }; 909 + 910 + static int rcsi2_probe_resources(struct rcar_csi2 *priv, 911 + struct platform_device *pdev) 912 + { 913 + struct resource *res; 914 + int irq; 915 + 916 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 917 + priv->base = devm_ioremap_resource(&pdev->dev, res); 918 + if (IS_ERR(priv->base)) 919 + return PTR_ERR(priv->base); 920 + 921 + irq = platform_get_irq(pdev, 0); 922 + if (irq < 0) 923 + return irq; 924 + 925 + return 0; 926 + } 927 + 928 + static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = { 929 + .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, 930 + .hsfreqrange = hsfreqrange_h3_v3h_m3n, 931 + .csi0clkfreqrange = 0x20, 932 + .clear_ulps = true, 933 + }; 934 + 935 + static const struct rcar_csi2_info rcar_csi2_info_r8a7795es1 = { 936 + .hsfreqrange = hsfreqrange_m3w_h3es1, 937 + }; 938 + 939 + static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = { 940 + .hsfreqrange = hsfreqrange_m3w_h3es1, 941 + }; 942 + 943 + static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = { 944 + .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, 945 + .hsfreqrange = hsfreqrange_h3_v3h_m3n, 946 + .csi0clkfreqrange = 0x20, 947 + .clear_ulps = true, 948 + }; 949 + 950 + static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = { 951 + .init_phtw = rcsi2_init_phtw_v3m_e3, 952 + }; 953 + 954 + static const struct of_device_id rcar_csi2_of_table[] = { 955 + { 956 + .compatible = "renesas,r8a7795-csi2", 957 + .data = &rcar_csi2_info_r8a7795, 958 + }, 959 + { 960 + .compatible = "renesas,r8a7796-csi2", 961 + .data = &rcar_csi2_info_r8a7796, 962 + }, 963 + { 964 + .compatible = "renesas,r8a77965-csi2", 965 + .data = &rcar_csi2_info_r8a77965, 966 + }, 967 + { 968 + .compatible = "renesas,r8a77970-csi2", 969 + .data = &rcar_csi2_info_r8a77970, 970 + }, 971 + { /* sentinel */ }, 972 + }; 973 + MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); 974 + 975 + static const struct soc_device_attribute r8a7795es1[] = { 976 + { 977 + .soc_id = "r8a7795", .revision = "ES1.*", 978 + .data = &rcar_csi2_info_r8a7795es1, 979 + }, 980 + { /* sentinel */ }, 981 + }; 982 + 983 + static int rcsi2_probe(struct platform_device *pdev) 984 + { 985 + const struct soc_device_attribute *attr; 986 + struct rcar_csi2 *priv; 987 + unsigned int i; 988 + int ret; 989 + 990 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 991 + if (!priv) 992 + return -ENOMEM; 993 + 994 + priv->info = of_device_get_match_data(&pdev->dev); 995 + 996 + /* 997 + * r8a7795 ES1.x behaves differently than the ES2.0+ but doesn't 998 + * have it's own compatible string. 999 + */ 1000 + attr = soc_device_match(r8a7795es1); 1001 + if (attr) 1002 + priv->info = attr->data; 1003 + 1004 + priv->dev = &pdev->dev; 1005 + 1006 + mutex_init(&priv->lock); 1007 + priv->stream_count = 0; 1008 + 1009 + ret = rcsi2_probe_resources(priv, pdev); 1010 + if (ret) { 1011 + dev_err(priv->dev, "Failed to get resources\n"); 1012 + return ret; 1013 + } 1014 + 1015 + platform_set_drvdata(pdev, priv); 1016 + 1017 + ret = rcsi2_parse_dt(priv); 1018 + if (ret) 1019 + return ret; 1020 + 1021 + priv->subdev.owner = THIS_MODULE; 1022 + priv->subdev.dev = &pdev->dev; 1023 + v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops); 1024 + v4l2_set_subdevdata(&priv->subdev, &pdev->dev); 1025 + snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s %s", 1026 + KBUILD_MODNAME, dev_name(&pdev->dev)); 1027 + priv->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 1028 + 1029 + priv->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; 1030 + priv->subdev.entity.ops = &rcar_csi2_entity_ops; 1031 + 1032 + priv->pads[RCAR_CSI2_SINK].flags = MEDIA_PAD_FL_SINK; 1033 + for (i = RCAR_CSI2_SOURCE_VC0; i < NR_OF_RCAR_CSI2_PAD; i++) 1034 + priv->pads[i].flags = MEDIA_PAD_FL_SOURCE; 1035 + 1036 + ret = media_entity_pads_init(&priv->subdev.entity, NR_OF_RCAR_CSI2_PAD, 1037 + priv->pads); 1038 + if (ret) 1039 + goto error; 1040 + 1041 + pm_runtime_enable(&pdev->dev); 1042 + 1043 + ret = v4l2_async_register_subdev(&priv->subdev); 1044 + if (ret < 0) 1045 + goto error; 1046 + 1047 + dev_info(priv->dev, "%d lanes found\n", priv->lanes); 1048 + 1049 + return 0; 1050 + 1051 + error: 1052 + v4l2_async_notifier_unregister(&priv->notifier); 1053 + v4l2_async_notifier_cleanup(&priv->notifier); 1054 + 1055 + return ret; 1056 + } 1057 + 1058 + static int rcsi2_remove(struct platform_device *pdev) 1059 + { 1060 + struct rcar_csi2 *priv = platform_get_drvdata(pdev); 1061 + 1062 + v4l2_async_notifier_unregister(&priv->notifier); 1063 + v4l2_async_notifier_cleanup(&priv->notifier); 1064 + v4l2_async_unregister_subdev(&priv->subdev); 1065 + 1066 + pm_runtime_disable(&pdev->dev); 1067 + 1068 + return 0; 1069 + } 1070 + 1071 + static struct platform_driver rcar_csi2_pdrv = { 1072 + .remove = rcsi2_remove, 1073 + .probe = rcsi2_probe, 1074 + .driver = { 1075 + .name = "rcar-csi2", 1076 + .of_match_table = rcar_csi2_of_table, 1077 + }, 1078 + }; 1079 + 1080 + module_platform_driver(rcar_csi2_pdrv); 1081 + 1082 + MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>"); 1083 + MODULE_DESCRIPTION("Renesas R-Car MIPI CSI-2 receiver driver"); 1084 + MODULE_LICENSE("GPL");