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

Configure Feed

Select the types of activity you want to include in your feed.

media: rcar-csi2: Add support for R-Car V4M

The V4M is the second Gen4 device that is enabled in the rcar-csi2
driver. There is much overlap with the already supported V4H device. The
registers that where new on Gen4 and where added with the V4H prefix are
retained and only new registers unique to the V4M are added with the new
V4M prefix. This follows the style for when V4H was added which had an
overlap with Gen3 registers.

The V4M CSI-2 receiver supports D-PHY mode only, either in 1-, 2- or
4-lane configuration. The datasheets do not document lane swapping and
is left out for now.

While the V4M only supports D-PHY the configuration for it is added in
such a way that it can be reused for V4H which supports both C-PHY and
D-PHY. No known SoC exists to test the D-PHY configuration on V4H so
it's not wired-up.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Niklas Söderlund and committed by
Mauro Carvalho Chehab
7e86c7a5 a59f7ffd

+294
+294
drivers/media/platform/renesas/rcar-csi2.c
··· 247 247 { /* sentinel */ }, 248 248 }; 249 249 250 + /* V4M registers */ 251 + #define V4M_OVR1_REG 0x0848 252 + #define V4M_OVR1_FORCERXMODE_3 BIT(12) 253 + #define V4M_OVR1_FORCERXMODE_2 BIT(11) 254 + #define V4M_OVR1_FORCERXMODE_1 BIT(10) 255 + #define V4M_OVR1_FORCERXMODE_0 BIT(9) 256 + 257 + #define V4M_FRXM_REG 0x2004 258 + #define V4M_FRXM_FORCERXMODE_3 BIT(3) 259 + #define V4M_FRXM_FORCERXMODE_2 BIT(2) 260 + #define V4M_FRXM_FORCERXMODE_1 BIT(1) 261 + #define V4M_FRXM_FORCERXMODE_0 BIT(0) 262 + 263 + #define V4M_PHYPLL_REG 0x02050 264 + #define V4M_CSI0CLKFCPR_REG 0x02054 265 + #define V4M_PHTW_REG 0x02060 266 + #define V4M_PHTR_REG 0x02064 267 + #define V4M_PHTC_REG 0x02068 268 + 250 269 struct phtw_value { 251 270 u8 data; 252 271 u8 code; ··· 274 255 struct rcsi2_mbps_info { 275 256 u16 mbps; 276 257 u8 reg; 258 + u16 osc_freq; /* V4M */ 277 259 }; 278 260 279 261 static const struct rcsi2_mbps_info phtw_mbps_v3u[] = { ··· 523 503 { .mbps = 1400, .reg = 0x1c }, 524 504 { .mbps = 1450, .reg = 0x2c }, 525 505 { .mbps = 1500, .reg = 0x3c }, 506 + { /* sentinel */ }, 507 + }; 508 + 509 + static const struct rcsi2_mbps_info hsfreqrange_v4m[] = { 510 + { .mbps = 80, .reg = 0x00, .osc_freq = 0x01a9 }, 511 + { .mbps = 90, .reg = 0x10, .osc_freq = 0x01a9 }, 512 + { .mbps = 100, .reg = 0x20, .osc_freq = 0x01a9 }, 513 + { .mbps = 110, .reg = 0x30, .osc_freq = 0x01a9 }, 514 + { .mbps = 120, .reg = 0x01, .osc_freq = 0x01a9 }, 515 + { .mbps = 130, .reg = 0x11, .osc_freq = 0x01a9 }, 516 + { .mbps = 140, .reg = 0x21, .osc_freq = 0x01a9 }, 517 + { .mbps = 150, .reg = 0x31, .osc_freq = 0x01a9 }, 518 + { .mbps = 160, .reg = 0x02, .osc_freq = 0x01a9 }, 519 + { .mbps = 170, .reg = 0x12, .osc_freq = 0x01a9 }, 520 + { .mbps = 180, .reg = 0x22, .osc_freq = 0x01a9 }, 521 + { .mbps = 190, .reg = 0x32, .osc_freq = 0x01a9 }, 522 + { .mbps = 205, .reg = 0x03, .osc_freq = 0x01a9 }, 523 + { .mbps = 220, .reg = 0x13, .osc_freq = 0x01a9 }, 524 + { .mbps = 235, .reg = 0x23, .osc_freq = 0x01a9 }, 525 + { .mbps = 250, .reg = 0x33, .osc_freq = 0x01a9 }, 526 + { .mbps = 275, .reg = 0x04, .osc_freq = 0x01a9 }, 527 + { .mbps = 300, .reg = 0x14, .osc_freq = 0x01a9 }, 528 + { .mbps = 325, .reg = 0x25, .osc_freq = 0x01a9 }, 529 + { .mbps = 350, .reg = 0x35, .osc_freq = 0x01a9 }, 530 + { .mbps = 400, .reg = 0x05, .osc_freq = 0x01a9 }, 531 + { .mbps = 450, .reg = 0x16, .osc_freq = 0x01a9 }, 532 + { .mbps = 500, .reg = 0x26, .osc_freq = 0x01a9 }, 533 + { .mbps = 550, .reg = 0x37, .osc_freq = 0x01a9 }, 534 + { .mbps = 600, .reg = 0x07, .osc_freq = 0x01a9 }, 535 + { .mbps = 650, .reg = 0x18, .osc_freq = 0x01a9 }, 536 + { .mbps = 700, .reg = 0x28, .osc_freq = 0x01a9 }, 537 + { .mbps = 750, .reg = 0x39, .osc_freq = 0x01a9 }, 538 + { .mbps = 800, .reg = 0x09, .osc_freq = 0x01a9 }, 539 + { .mbps = 850, .reg = 0x19, .osc_freq = 0x01a9 }, 540 + { .mbps = 900, .reg = 0x29, .osc_freq = 0x01a9 }, 541 + { .mbps = 950, .reg = 0x3a, .osc_freq = 0x01a9 }, 542 + { .mbps = 1000, .reg = 0x0a, .osc_freq = 0x01a9 }, 543 + { .mbps = 1050, .reg = 0x1a, .osc_freq = 0x01a9 }, 544 + { .mbps = 1100, .reg = 0x2a, .osc_freq = 0x01a9 }, 545 + { .mbps = 1150, .reg = 0x3b, .osc_freq = 0x01a9 }, 546 + { .mbps = 1200, .reg = 0x0b, .osc_freq = 0x01a9 }, 547 + { .mbps = 1250, .reg = 0x1b, .osc_freq = 0x01a9 }, 548 + { .mbps = 1300, .reg = 0x2b, .osc_freq = 0x01a9 }, 549 + { .mbps = 1350, .reg = 0x3c, .osc_freq = 0x01a9 }, 550 + { .mbps = 1400, .reg = 0x0c, .osc_freq = 0x01a9 }, 551 + { .mbps = 1450, .reg = 0x1c, .osc_freq = 0x01a9 }, 552 + { .mbps = 1500, .reg = 0x2c, .osc_freq = 0x01a9 }, 553 + { .mbps = 1550, .reg = 0x3d, .osc_freq = 0x0108 }, 554 + { .mbps = 1600, .reg = 0x0d, .osc_freq = 0x0110 }, 555 + { .mbps = 1650, .reg = 0x1d, .osc_freq = 0x0119 }, 556 + { .mbps = 1700, .reg = 0x2e, .osc_freq = 0x0121 }, 557 + { .mbps = 1750, .reg = 0x3e, .osc_freq = 0x012a }, 558 + { .mbps = 1800, .reg = 0x0e, .osc_freq = 0x0132 }, 559 + { .mbps = 1850, .reg = 0x1e, .osc_freq = 0x013b }, 560 + { .mbps = 1900, .reg = 0x2f, .osc_freq = 0x0143 }, 561 + { .mbps = 1950, .reg = 0x3f, .osc_freq = 0x014c }, 562 + { .mbps = 2000, .reg = 0x0f, .osc_freq = 0x0154 }, 563 + { .mbps = 2050, .reg = 0x40, .osc_freq = 0x015d }, 564 + { .mbps = 2100, .reg = 0x41, .osc_freq = 0x0165 }, 565 + { .mbps = 2150, .reg = 0x42, .osc_freq = 0x016e }, 566 + { .mbps = 2200, .reg = 0x43, .osc_freq = 0x0176 }, 567 + { .mbps = 2250, .reg = 0x44, .osc_freq = 0x017f }, 568 + { .mbps = 2300, .reg = 0x45, .osc_freq = 0x0187 }, 569 + { .mbps = 2350, .reg = 0x46, .osc_freq = 0x0190 }, 570 + { .mbps = 2400, .reg = 0x47, .osc_freq = 0x0198 }, 571 + { .mbps = 2450, .reg = 0x48, .osc_freq = 0x01a1 }, 572 + { .mbps = 2500, .reg = 0x49, .osc_freq = 0x01a9 }, 526 573 { /* sentinel */ }, 527 574 }; 528 575 ··· 1282 1195 return 0; 1283 1196 } 1284 1197 1198 + static int rcsi2_d_phy_setting_v4m(struct rcar_csi2 *priv, int data_rate) 1199 + { 1200 + unsigned int timeout; 1201 + int ret; 1202 + 1203 + static const struct phtw_value step1[] = { 1204 + { .data = 0x00, .code = 0x00 }, 1205 + { .data = 0x00, .code = 0x1e }, 1206 + }; 1207 + 1208 + /* Shutdown and reset PHY. */ 1209 + rcsi2_write(priv, V4H_DPHY_RSTZ_REG, BIT(0)); 1210 + rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, BIT(0)); 1211 + 1212 + /* Start internal calibration (POR). */ 1213 + ret = rcsi2_phtw_write_array(priv, step1, ARRAY_SIZE(step1)); 1214 + if (ret) 1215 + return ret; 1216 + 1217 + /* Wait for POR to complete. */ 1218 + for (timeout = 10; timeout > 0; timeout--) { 1219 + if ((rcsi2_read(priv, V4M_PHTR_REG) & 0xf0000) == 0x70000) 1220 + break; 1221 + usleep_range(1000, 2000); 1222 + } 1223 + 1224 + if (!timeout) { 1225 + dev_err(priv->dev, "D-PHY calibration failed\n"); 1226 + return -ETIMEDOUT; 1227 + } 1228 + 1229 + return 0; 1230 + } 1231 + 1232 + static int rcsi2_set_osc_freq(struct rcar_csi2 *priv, unsigned int mbps) 1233 + { 1234 + const struct rcsi2_mbps_info *info; 1235 + struct phtw_value steps[] = { 1236 + { .data = 0x00, .code = 0x00 }, 1237 + { .code = 0xe2 }, /* Data filled in below. */ 1238 + { .code = 0xe3 }, /* Data filled in below. */ 1239 + { .data = 0x01, .code = 0xe4 }, 1240 + }; 1241 + 1242 + info = rcsi2_mbps_to_info(priv, priv->info->hsfreqrange, mbps); 1243 + if (!info) 1244 + return -ERANGE; 1245 + 1246 + /* Fill in data for command. */ 1247 + steps[1].data = (info->osc_freq & 0x00ff) >> 0; 1248 + steps[2].data = (info->osc_freq & 0x0f00) >> 8; 1249 + 1250 + return rcsi2_phtw_write_array(priv, steps, ARRAY_SIZE(steps)); 1251 + } 1252 + 1253 + static int rcsi2_init_common_v4m(struct rcar_csi2 *priv, unsigned int mbps) 1254 + { 1255 + int ret; 1256 + 1257 + static const struct phtw_value step1[] = { 1258 + { .data = 0x00, .code = 0x00 }, 1259 + { .data = 0x3c, .code = 0x08 }, 1260 + }; 1261 + 1262 + static const struct phtw_value step2[] = { 1263 + { .data = 0x00, .code = 0x00 }, 1264 + { .data = 0x80, .code = 0xe0 }, 1265 + { .data = 0x01, .code = 0xe1 }, 1266 + { .data = 0x06, .code = 0x00 }, 1267 + { .data = 0x0f, .code = 0x11 }, 1268 + { .data = 0x08, .code = 0x00 }, 1269 + { .data = 0x0f, .code = 0x11 }, 1270 + { .data = 0x0a, .code = 0x00 }, 1271 + { .data = 0x0f, .code = 0x11 }, 1272 + { .data = 0x0c, .code = 0x00 }, 1273 + { .data = 0x0f, .code = 0x11 }, 1274 + { .data = 0x01, .code = 0x00 }, 1275 + { .data = 0x31, .code = 0xaa }, 1276 + { .data = 0x05, .code = 0x00 }, 1277 + { .data = 0x05, .code = 0x09 }, 1278 + { .data = 0x07, .code = 0x00 }, 1279 + { .data = 0x05, .code = 0x09 }, 1280 + { .data = 0x09, .code = 0x00 }, 1281 + { .data = 0x05, .code = 0x09 }, 1282 + { .data = 0x0b, .code = 0x00 }, 1283 + { .data = 0x05, .code = 0x09 }, 1284 + }; 1285 + 1286 + if (priv->info->hsfreqrange) { 1287 + ret = rcsi2_set_phypll(priv, mbps); 1288 + if (ret) 1289 + return ret; 1290 + 1291 + ret = rcsi2_set_osc_freq(priv, mbps); 1292 + if (ret) 1293 + return ret; 1294 + } 1295 + 1296 + if (mbps <= 1500) { 1297 + ret = rcsi2_phtw_write_array(priv, step1, ARRAY_SIZE(step1)); 1298 + if (ret) 1299 + return ret; 1300 + } 1301 + 1302 + if (priv->info->csi0clkfreqrange) 1303 + rcsi2_write(priv, V4M_CSI0CLKFCPR_REG, 1304 + CSI0CLKFREQRANGE(priv->info->csi0clkfreqrange)); 1305 + 1306 + rcsi2_write(priv, V4H_PHY_EN_REG, V4H_PHY_EN_ENABLE_CLK | 1307 + V4H_PHY_EN_ENABLE_0 | V4H_PHY_EN_ENABLE_1 | 1308 + V4H_PHY_EN_ENABLE_2 | V4H_PHY_EN_ENABLE_3); 1309 + 1310 + if (mbps > 1500) { 1311 + ret = rcsi2_phtw_write_array(priv, step2, ARRAY_SIZE(step2)); 1312 + if (ret) 1313 + return ret; 1314 + } 1315 + 1316 + return ret; 1317 + } 1318 + 1319 + static int rcsi2_start_receiver_v4m(struct rcar_csi2 *priv, 1320 + struct v4l2_subdev_state *state) 1321 + { 1322 + const struct rcar_csi2_format *format; 1323 + const struct v4l2_mbus_framefmt *fmt; 1324 + unsigned int lanes; 1325 + int mbps; 1326 + int ret; 1327 + 1328 + /* Calculate parameters */ 1329 + fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK); 1330 + format = rcsi2_code_to_fmt(fmt->code); 1331 + if (!format) 1332 + return -EINVAL; 1333 + 1334 + ret = rcsi2_get_active_lanes(priv, &lanes); 1335 + if (ret) 1336 + return ret; 1337 + 1338 + mbps = rcsi2_calc_mbps(priv, format->bpp, lanes); 1339 + if (mbps < 0) 1340 + return mbps; 1341 + 1342 + /* Reset LINK and PHY */ 1343 + rcsi2_write(priv, V4H_CSI2_RESETN_REG, 0); 1344 + rcsi2_write(priv, V4H_DPHY_RSTZ_REG, 0); 1345 + rcsi2_write(priv, V4H_PHY_SHUTDOWNZ_REG, 0); 1346 + rcsi2_write(priv, V4M_PHTC_REG, PHTC_TESTCLR); 1347 + 1348 + /* PHY static setting */ 1349 + rcsi2_write(priv, V4H_PHY_EN_REG, V4H_PHY_EN_ENABLE_CLK); 1350 + rcsi2_write(priv, V4H_FLDC_REG, 0); 1351 + rcsi2_write(priv, V4H_FLDD_REG, 0); 1352 + rcsi2_write(priv, V4H_IDIC_REG, 0); 1353 + rcsi2_write(priv, V4H_PHY_MODE_REG, V4H_PHY_MODE_DPHY); 1354 + rcsi2_write(priv, V4H_N_LANES_REG, lanes - 1); 1355 + 1356 + rcsi2_write(priv, V4M_FRXM_REG, 1357 + V4M_FRXM_FORCERXMODE_0 | V4M_FRXM_FORCERXMODE_1 | 1358 + V4M_FRXM_FORCERXMODE_2 | V4M_FRXM_FORCERXMODE_3); 1359 + rcsi2_write(priv, V4M_OVR1_REG, 1360 + V4M_OVR1_FORCERXMODE_0 | V4M_OVR1_FORCERXMODE_1 | 1361 + V4M_OVR1_FORCERXMODE_2 | V4M_OVR1_FORCERXMODE_3); 1362 + 1363 + /* Reset CSI2 */ 1364 + rcsi2_write(priv, V4M_PHTC_REG, 0); 1365 + rcsi2_write(priv, V4H_CSI2_RESETN_REG, BIT(0)); 1366 + 1367 + /* Common settings */ 1368 + ret = rcsi2_init_common_v4m(priv, mbps); 1369 + if (ret) 1370 + return ret; 1371 + 1372 + /* D-PHY settings */ 1373 + ret = rcsi2_d_phy_setting_v4m(priv, mbps); 1374 + if (ret) 1375 + return ret; 1376 + 1377 + rcsi2_wait_phy_start_v4h(priv, V4H_ST_PHYST_ST_STOPSTATE_0 | 1378 + V4H_ST_PHYST_ST_STOPSTATE_1 | 1379 + V4H_ST_PHYST_ST_STOPSTATE_2 | 1380 + V4H_ST_PHYST_ST_STOPSTATE_3); 1381 + 1382 + rcsi2_write(priv, V4M_FRXM_REG, 0); 1383 + 1384 + return 0; 1385 + } 1386 + 1285 1387 static int rcsi2_start(struct rcar_csi2 *priv, struct v4l2_subdev_state *state) 1286 1388 { 1287 1389 int ret; ··· 2108 1832 .support_cphy = true, 2109 1833 }; 2110 1834 1835 + static const struct rcsi2_register_layout rcsi2_registers_v4m = { 1836 + .phtw = V4M_PHTW_REG, 1837 + .phypll = V4M_PHYPLL_REG, 1838 + }; 1839 + 1840 + static const struct rcar_csi2_info rcar_csi2_info_r8a779h0 = { 1841 + .regs = &rcsi2_registers_v4m, 1842 + .start_receiver = rcsi2_start_receiver_v4m, 1843 + .hsfreqrange = hsfreqrange_v4m, 1844 + .csi0clkfreqrange = 0x0c, 1845 + .use_isp = true, 1846 + .support_dphy = true, 1847 + }; 1848 + 2111 1849 static const struct of_device_id rcar_csi2_of_table[] = { 2112 1850 { 2113 1851 .compatible = "renesas,r8a774a1-csi2", ··· 2174 1884 { 2175 1885 .compatible = "renesas,r8a779g0-csi2", 2176 1886 .data = &rcar_csi2_info_r8a779g0, 1887 + }, 1888 + { 1889 + .compatible = "renesas,r8a779h0-csi2", 1890 + .data = &rcar_csi2_info_r8a779h0, 2177 1891 }, 2178 1892 { /* sentinel */ }, 2179 1893 };