| .. | .. |
|---|
| 20 | 20 | #include <media/videobuf2-dma-contig.h> |
|---|
| 21 | 21 | #include <media/v4l2-fwnode.h> |
|---|
| 22 | 22 | #include <linux/iommu.h> |
|---|
| 23 | | -#include <dt-bindings/soc/rockchip-system-status.h> |
|---|
| 24 | 23 | #include <soc/rockchip/rockchip-system-status.h> |
|---|
| 25 | 24 | #include <linux/io.h> |
|---|
| 26 | 25 | #include <linux/mfd/syscon.h> |
|---|
| 27 | 26 | #include "dev.h" |
|---|
| 28 | 27 | #include "procfs.h" |
|---|
| 28 | +#include <linux/kthread.h> |
|---|
| 29 | +#include "../../../../phy/rockchip/phy-rockchip-csi2-dphy-common.h" |
|---|
| 30 | +#include <linux/of_reserved_mem.h> |
|---|
| 31 | +#include <linux/of_address.h> |
|---|
| 29 | 32 | |
|---|
| 30 | 33 | #define RKCIF_VERNO_LEN 10 |
|---|
| 31 | 34 | |
|---|
| .. | .. |
|---|
| 92 | 95 | return len; |
|---|
| 93 | 96 | } |
|---|
| 94 | 97 | |
|---|
| 98 | +static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR, |
|---|
| 99 | + rkcif_show_compact_mode, rkcif_store_compact_mode); |
|---|
| 100 | + |
|---|
| 95 | 101 | static ssize_t rkcif_show_line_int_num(struct device *dev, |
|---|
| 96 | 102 | struct device_attribute *attr, |
|---|
| 97 | 103 | char *buf) |
|---|
| .. | .. |
|---|
| 109 | 115 | const char *buf, size_t len) |
|---|
| 110 | 116 | { |
|---|
| 111 | 117 | struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 118 | + struct sditf_priv *priv = cif_dev->sditf[0]; |
|---|
| 112 | 119 | int val = 0; |
|---|
| 113 | 120 | int ret = 0; |
|---|
| 114 | 121 | |
|---|
| 122 | + if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { |
|---|
| 123 | + dev_info(cif_dev->dev, |
|---|
| 124 | + "current mode is on the fly, wake up mode wouldn't used\n"); |
|---|
| 125 | + return len; |
|---|
| 126 | + } |
|---|
| 115 | 127 | ret = kstrtoint(buf, 0, &val); |
|---|
| 116 | 128 | if (!ret && val >= 0 && val <= 0x3fff) |
|---|
| 117 | 129 | cif_dev->wait_line_cache = val; |
|---|
| .. | .. |
|---|
| 119 | 131 | dev_info(cif_dev->dev, "set line int num failed\n"); |
|---|
| 120 | 132 | return len; |
|---|
| 121 | 133 | } |
|---|
| 134 | + |
|---|
| 135 | +static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR, |
|---|
| 136 | + rkcif_show_line_int_num, rkcif_store_line_int_num); |
|---|
| 122 | 137 | |
|---|
| 123 | 138 | static ssize_t rkcif_show_dummybuf_mode(struct device *dev, |
|---|
| 124 | 139 | struct device_attribute *attr, |
|---|
| .. | .. |
|---|
| 152 | 167 | return len; |
|---|
| 153 | 168 | } |
|---|
| 154 | 169 | |
|---|
| 155 | | -/* show the compact mode of each stream in stream index order, |
|---|
| 156 | | - * 1 for compact, 0 for 16bit |
|---|
| 170 | +static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR, |
|---|
| 171 | + rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode); |
|---|
| 172 | + |
|---|
| 173 | +/* show the memory mode of each stream in stream index order, |
|---|
| 174 | + * 1 for high align, 0 for low align |
|---|
| 157 | 175 | */ |
|---|
| 158 | 176 | static ssize_t rkcif_show_memory_mode(struct device *dev, |
|---|
| 159 | 177 | struct device_attribute *attr, |
|---|
| .. | .. |
|---|
| 210 | 228 | return len; |
|---|
| 211 | 229 | } |
|---|
| 212 | 230 | |
|---|
| 213 | | -static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR, |
|---|
| 214 | | - rkcif_show_compact_mode, rkcif_store_compact_mode); |
|---|
| 215 | | - |
|---|
| 216 | | -static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR, |
|---|
| 217 | | - rkcif_show_line_int_num, rkcif_store_line_int_num); |
|---|
| 218 | | - |
|---|
| 219 | | -static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR, |
|---|
| 220 | | - rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode); |
|---|
| 221 | | - |
|---|
| 222 | 231 | static DEVICE_ATTR(is_high_align, S_IWUSR | S_IRUSR, |
|---|
| 223 | 232 | rkcif_show_memory_mode, rkcif_store_memory_mode); |
|---|
| 224 | 233 | |
|---|
| 234 | +static ssize_t rkcif_show_scale_ch0_blc(struct device *dev, |
|---|
| 235 | + struct device_attribute *attr, |
|---|
| 236 | + char *buf) |
|---|
| 237 | +{ |
|---|
| 238 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 239 | + int ret; |
|---|
| 240 | + |
|---|
| 241 | + ret = snprintf(buf, PAGE_SIZE, "ch0 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 242 | + cif_dev->scale_vdev[0].blc.pattern00, |
|---|
| 243 | + cif_dev->scale_vdev[0].blc.pattern01, |
|---|
| 244 | + cif_dev->scale_vdev[0].blc.pattern02, |
|---|
| 245 | + cif_dev->scale_vdev[0].blc.pattern03); |
|---|
| 246 | + return ret; |
|---|
| 247 | +} |
|---|
| 248 | + |
|---|
| 249 | +static ssize_t rkcif_store_scale_ch0_blc(struct device *dev, |
|---|
| 250 | + struct device_attribute *attr, |
|---|
| 251 | + const char *buf, size_t len) |
|---|
| 252 | +{ |
|---|
| 253 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 254 | + int i = 0, index = 0; |
|---|
| 255 | + unsigned int val[4] = {0}; |
|---|
| 256 | + unsigned int temp = 0; |
|---|
| 257 | + int ret = 0; |
|---|
| 258 | + int j = 0; |
|---|
| 259 | + char cha[2] = {0}; |
|---|
| 260 | + |
|---|
| 261 | + if (buf) { |
|---|
| 262 | + index = 0; |
|---|
| 263 | + for (i = 0; i < len; i++) { |
|---|
| 264 | + if (((buf[i] == ' ') || (buf[i] == '\n')) && j) { |
|---|
| 265 | + index++; |
|---|
| 266 | + j = 0; |
|---|
| 267 | + if (index == 4) |
|---|
| 268 | + break; |
|---|
| 269 | + continue; |
|---|
| 270 | + } else { |
|---|
| 271 | + if (buf[i] < '0' || buf[i] > '9') |
|---|
| 272 | + continue; |
|---|
| 273 | + cha[0] = buf[i]; |
|---|
| 274 | + cha[1] = '\0'; |
|---|
| 275 | + ret = kstrtoint(cha, 0, &temp); |
|---|
| 276 | + if (!ret) { |
|---|
| 277 | + if (j) |
|---|
| 278 | + val[index] *= 10; |
|---|
| 279 | + val[index] += temp; |
|---|
| 280 | + j++; |
|---|
| 281 | + } |
|---|
| 282 | + } |
|---|
| 283 | + } |
|---|
| 284 | + if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255) |
|---|
| 285 | + return -EINVAL; |
|---|
| 286 | + cif_dev->scale_vdev[0].blc.pattern00 = val[0]; |
|---|
| 287 | + cif_dev->scale_vdev[0].blc.pattern01 = val[1]; |
|---|
| 288 | + cif_dev->scale_vdev[0].blc.pattern02 = val[2]; |
|---|
| 289 | + cif_dev->scale_vdev[0].blc.pattern03 = val[3]; |
|---|
| 290 | + dev_info(cif_dev->dev, |
|---|
| 291 | + "set ch0 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 292 | + cif_dev->scale_vdev[0].blc.pattern00, |
|---|
| 293 | + cif_dev->scale_vdev[0].blc.pattern01, |
|---|
| 294 | + cif_dev->scale_vdev[0].blc.pattern02, |
|---|
| 295 | + cif_dev->scale_vdev[0].blc.pattern03); |
|---|
| 296 | + } |
|---|
| 297 | + |
|---|
| 298 | + return len; |
|---|
| 299 | +} |
|---|
| 300 | + |
|---|
| 301 | +static DEVICE_ATTR(scale_ch0_blc, S_IWUSR | S_IRUSR, |
|---|
| 302 | + rkcif_show_scale_ch0_blc, rkcif_store_scale_ch0_blc); |
|---|
| 303 | + |
|---|
| 304 | +static ssize_t rkcif_show_scale_ch1_blc(struct device *dev, |
|---|
| 305 | + struct device_attribute *attr, |
|---|
| 306 | + char *buf) |
|---|
| 307 | +{ |
|---|
| 308 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 309 | + int ret; |
|---|
| 310 | + |
|---|
| 311 | + ret = snprintf(buf, PAGE_SIZE, "ch1 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 312 | + cif_dev->scale_vdev[1].blc.pattern00, |
|---|
| 313 | + cif_dev->scale_vdev[1].blc.pattern01, |
|---|
| 314 | + cif_dev->scale_vdev[1].blc.pattern02, |
|---|
| 315 | + cif_dev->scale_vdev[1].blc.pattern03); |
|---|
| 316 | + return ret; |
|---|
| 317 | +} |
|---|
| 318 | + |
|---|
| 319 | +static ssize_t rkcif_store_scale_ch1_blc(struct device *dev, |
|---|
| 320 | + struct device_attribute *attr, |
|---|
| 321 | + const char *buf, size_t len) |
|---|
| 322 | +{ |
|---|
| 323 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 324 | + int i = 0, index = 0; |
|---|
| 325 | + unsigned int val[4] = {0}; |
|---|
| 326 | + unsigned int temp = 0; |
|---|
| 327 | + int ret = 0; |
|---|
| 328 | + int j = 0; |
|---|
| 329 | + char cha[2] = {0}; |
|---|
| 330 | + |
|---|
| 331 | + if (buf) { |
|---|
| 332 | + index = 0; |
|---|
| 333 | + for (i = 0; i < len; i++) { |
|---|
| 334 | + if (((buf[i] == ' ') || (buf[i] == '\n')) && j) { |
|---|
| 335 | + index++; |
|---|
| 336 | + j = 0; |
|---|
| 337 | + if (index == 4) |
|---|
| 338 | + break; |
|---|
| 339 | + continue; |
|---|
| 340 | + } else { |
|---|
| 341 | + if (buf[i] < '0' || buf[i] > '9') |
|---|
| 342 | + continue; |
|---|
| 343 | + cha[0] = buf[i]; |
|---|
| 344 | + cha[1] = '\0'; |
|---|
| 345 | + ret = kstrtoint(cha, 0, &temp); |
|---|
| 346 | + if (!ret) { |
|---|
| 347 | + if (j) |
|---|
| 348 | + val[index] *= 10; |
|---|
| 349 | + val[index] += temp; |
|---|
| 350 | + j++; |
|---|
| 351 | + } |
|---|
| 352 | + } |
|---|
| 353 | + } |
|---|
| 354 | + if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255) |
|---|
| 355 | + return -EINVAL; |
|---|
| 356 | + |
|---|
| 357 | + cif_dev->scale_vdev[1].blc.pattern00 = val[0]; |
|---|
| 358 | + cif_dev->scale_vdev[1].blc.pattern01 = val[1]; |
|---|
| 359 | + cif_dev->scale_vdev[1].blc.pattern02 = val[2]; |
|---|
| 360 | + cif_dev->scale_vdev[1].blc.pattern03 = val[3]; |
|---|
| 361 | + |
|---|
| 362 | + dev_info(cif_dev->dev, |
|---|
| 363 | + "set ch1 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 364 | + cif_dev->scale_vdev[1].blc.pattern00, |
|---|
| 365 | + cif_dev->scale_vdev[1].blc.pattern01, |
|---|
| 366 | + cif_dev->scale_vdev[1].blc.pattern02, |
|---|
| 367 | + cif_dev->scale_vdev[1].blc.pattern03); |
|---|
| 368 | + } |
|---|
| 369 | + |
|---|
| 370 | + return len; |
|---|
| 371 | +} |
|---|
| 372 | + |
|---|
| 373 | +static DEVICE_ATTR(scale_ch1_blc, S_IWUSR | S_IRUSR, |
|---|
| 374 | + rkcif_show_scale_ch1_blc, rkcif_store_scale_ch1_blc); |
|---|
| 375 | + |
|---|
| 376 | +static ssize_t rkcif_show_scale_ch2_blc(struct device *dev, |
|---|
| 377 | + struct device_attribute *attr, |
|---|
| 378 | + char *buf) |
|---|
| 379 | +{ |
|---|
| 380 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 381 | + int ret; |
|---|
| 382 | + |
|---|
| 383 | + ret = snprintf(buf, PAGE_SIZE, "ch2 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 384 | + cif_dev->scale_vdev[2].blc.pattern00, |
|---|
| 385 | + cif_dev->scale_vdev[2].blc.pattern01, |
|---|
| 386 | + cif_dev->scale_vdev[2].blc.pattern02, |
|---|
| 387 | + cif_dev->scale_vdev[2].blc.pattern03); |
|---|
| 388 | + return ret; |
|---|
| 389 | +} |
|---|
| 390 | + |
|---|
| 391 | +static ssize_t rkcif_store_scale_ch2_blc(struct device *dev, |
|---|
| 392 | + struct device_attribute *attr, |
|---|
| 393 | + const char *buf, size_t len) |
|---|
| 394 | +{ |
|---|
| 395 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 396 | + int i = 0, index = 0; |
|---|
| 397 | + unsigned int val[4] = {0}; |
|---|
| 398 | + unsigned int temp = 0; |
|---|
| 399 | + int ret = 0; |
|---|
| 400 | + int j = 0; |
|---|
| 401 | + char cha[2] = {0}; |
|---|
| 402 | + |
|---|
| 403 | + if (buf) { |
|---|
| 404 | + index = 0; |
|---|
| 405 | + for (i = 0; i < len; i++) { |
|---|
| 406 | + if (((buf[i] == ' ') || (buf[i] == '\n')) && j) { |
|---|
| 407 | + index++; |
|---|
| 408 | + j = 0; |
|---|
| 409 | + if (index == 4) |
|---|
| 410 | + break; |
|---|
| 411 | + continue; |
|---|
| 412 | + } else { |
|---|
| 413 | + if (buf[i] < '0' || buf[i] > '9') |
|---|
| 414 | + continue; |
|---|
| 415 | + cha[0] = buf[i]; |
|---|
| 416 | + cha[1] = '\0'; |
|---|
| 417 | + ret = kstrtoint(cha, 0, &temp); |
|---|
| 418 | + if (!ret) { |
|---|
| 419 | + if (j) |
|---|
| 420 | + val[index] *= 10; |
|---|
| 421 | + val[index] += temp; |
|---|
| 422 | + j++; |
|---|
| 423 | + } |
|---|
| 424 | + } |
|---|
| 425 | + } |
|---|
| 426 | + if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255) |
|---|
| 427 | + return -EINVAL; |
|---|
| 428 | + |
|---|
| 429 | + cif_dev->scale_vdev[2].blc.pattern00 = val[0]; |
|---|
| 430 | + cif_dev->scale_vdev[2].blc.pattern01 = val[1]; |
|---|
| 431 | + cif_dev->scale_vdev[2].blc.pattern02 = val[2]; |
|---|
| 432 | + cif_dev->scale_vdev[2].blc.pattern03 = val[3]; |
|---|
| 433 | + |
|---|
| 434 | + dev_info(cif_dev->dev, |
|---|
| 435 | + "set ch2 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 436 | + cif_dev->scale_vdev[2].blc.pattern00, |
|---|
| 437 | + cif_dev->scale_vdev[2].blc.pattern01, |
|---|
| 438 | + cif_dev->scale_vdev[2].blc.pattern02, |
|---|
| 439 | + cif_dev->scale_vdev[2].blc.pattern03); |
|---|
| 440 | + } |
|---|
| 441 | + |
|---|
| 442 | + return len; |
|---|
| 443 | +} |
|---|
| 444 | +static DEVICE_ATTR(scale_ch2_blc, S_IWUSR | S_IRUSR, |
|---|
| 445 | + rkcif_show_scale_ch2_blc, rkcif_store_scale_ch2_blc); |
|---|
| 446 | + |
|---|
| 447 | +static ssize_t rkcif_show_scale_ch3_blc(struct device *dev, |
|---|
| 448 | + struct device_attribute *attr, |
|---|
| 449 | + char *buf) |
|---|
| 450 | +{ |
|---|
| 451 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 452 | + int ret; |
|---|
| 453 | + |
|---|
| 454 | + ret = snprintf(buf, PAGE_SIZE, "ch3 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 455 | + cif_dev->scale_vdev[3].blc.pattern00, |
|---|
| 456 | + cif_dev->scale_vdev[3].blc.pattern01, |
|---|
| 457 | + cif_dev->scale_vdev[3].blc.pattern02, |
|---|
| 458 | + cif_dev->scale_vdev[3].blc.pattern03); |
|---|
| 459 | + return ret; |
|---|
| 460 | +} |
|---|
| 461 | + |
|---|
| 462 | +static ssize_t rkcif_store_scale_ch3_blc(struct device *dev, |
|---|
| 463 | + struct device_attribute *attr, |
|---|
| 464 | + const char *buf, size_t len) |
|---|
| 465 | +{ |
|---|
| 466 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 467 | + int i = 0, index = 0; |
|---|
| 468 | + unsigned int val[4] = {0}; |
|---|
| 469 | + unsigned int temp = 0; |
|---|
| 470 | + int ret = 0; |
|---|
| 471 | + int j = 0; |
|---|
| 472 | + char cha[2] = {0}; |
|---|
| 473 | + |
|---|
| 474 | + if (buf) { |
|---|
| 475 | + index = 0; |
|---|
| 476 | + for (i = 0; i < len; i++) { |
|---|
| 477 | + if (((buf[i] == ' ') || (buf[i] == '\n')) && j) { |
|---|
| 478 | + index++; |
|---|
| 479 | + j = 0; |
|---|
| 480 | + if (index == 4) |
|---|
| 481 | + break; |
|---|
| 482 | + continue; |
|---|
| 483 | + } else { |
|---|
| 484 | + if (buf[i] < '0' || buf[i] > '9') |
|---|
| 485 | + continue; |
|---|
| 486 | + cha[0] = buf[i]; |
|---|
| 487 | + cha[1] = '\0'; |
|---|
| 488 | + ret = kstrtoint(cha, 0, &temp); |
|---|
| 489 | + if (!ret) { |
|---|
| 490 | + if (j) |
|---|
| 491 | + val[index] *= 10; |
|---|
| 492 | + val[index] += temp; |
|---|
| 493 | + j++; |
|---|
| 494 | + } |
|---|
| 495 | + } |
|---|
| 496 | + } |
|---|
| 497 | + if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255) |
|---|
| 498 | + return -EINVAL; |
|---|
| 499 | + |
|---|
| 500 | + cif_dev->scale_vdev[3].blc.pattern00 = val[0]; |
|---|
| 501 | + cif_dev->scale_vdev[3].blc.pattern01 = val[1]; |
|---|
| 502 | + cif_dev->scale_vdev[3].blc.pattern02 = val[2]; |
|---|
| 503 | + cif_dev->scale_vdev[3].blc.pattern03 = val[3]; |
|---|
| 504 | + |
|---|
| 505 | + dev_info(cif_dev->dev, |
|---|
| 506 | + "set ch3 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n", |
|---|
| 507 | + cif_dev->scale_vdev[3].blc.pattern00, |
|---|
| 508 | + cif_dev->scale_vdev[3].blc.pattern01, |
|---|
| 509 | + cif_dev->scale_vdev[3].blc.pattern02, |
|---|
| 510 | + cif_dev->scale_vdev[3].blc.pattern03); |
|---|
| 511 | + } |
|---|
| 512 | + |
|---|
| 513 | + return len; |
|---|
| 514 | +} |
|---|
| 515 | + |
|---|
| 516 | +static DEVICE_ATTR(scale_ch3_blc, S_IWUSR | S_IRUSR, |
|---|
| 517 | + rkcif_show_scale_ch3_blc, rkcif_store_scale_ch3_blc); |
|---|
| 518 | + |
|---|
| 519 | +static ssize_t rkcif_store_capture_fps(struct device *dev, |
|---|
| 520 | + struct device_attribute *attr, |
|---|
| 521 | + const char *buf, size_t len) |
|---|
| 522 | +{ |
|---|
| 523 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 524 | + struct rkcif_stream *stream = NULL; |
|---|
| 525 | + int i = 0, index = 0; |
|---|
| 526 | + unsigned int val[4] = {0}; |
|---|
| 527 | + unsigned int temp = 0; |
|---|
| 528 | + int ret = 0; |
|---|
| 529 | + int j = 0; |
|---|
| 530 | + char cha[2] = {0}; |
|---|
| 531 | + struct rkcif_fps fps = {0}; |
|---|
| 532 | + |
|---|
| 533 | + if (buf) { |
|---|
| 534 | + index = 0; |
|---|
| 535 | + for (i = 0; i < len; i++) { |
|---|
| 536 | + if (((buf[i] == ' ') || (buf[i] == '\n')) && j) { |
|---|
| 537 | + index++; |
|---|
| 538 | + j = 0; |
|---|
| 539 | + if (index == 4) |
|---|
| 540 | + break; |
|---|
| 541 | + continue; |
|---|
| 542 | + } else { |
|---|
| 543 | + if (buf[i] < '0' || buf[i] > '9') |
|---|
| 544 | + continue; |
|---|
| 545 | + cha[0] = buf[i]; |
|---|
| 546 | + cha[1] = '\0'; |
|---|
| 547 | + ret = kstrtoint(cha, 0, &temp); |
|---|
| 548 | + if (!ret) { |
|---|
| 549 | + if (j) |
|---|
| 550 | + val[index] *= 10; |
|---|
| 551 | + val[index] += temp; |
|---|
| 552 | + j++; |
|---|
| 553 | + } |
|---|
| 554 | + } |
|---|
| 555 | + } |
|---|
| 556 | + |
|---|
| 557 | + for (i = 0; i < index; i++) { |
|---|
| 558 | + if ((val[i] - '0' != 0) && cif_dev->chip_id >= CHIP_RV1106_CIF) { |
|---|
| 559 | + stream = &cif_dev->stream[i]; |
|---|
| 560 | + fps.fps = val[i]; |
|---|
| 561 | + rkcif_set_fps(stream, &fps); |
|---|
| 562 | + } |
|---|
| 563 | + } |
|---|
| 564 | + dev_info(cif_dev->dev, |
|---|
| 565 | + "set fps id0: %d, id1: %d, id2: %d, id3: %d\n", |
|---|
| 566 | + val[0], val[1], val[2], val[3]); |
|---|
| 567 | + } |
|---|
| 568 | + |
|---|
| 569 | + return len; |
|---|
| 570 | +} |
|---|
| 571 | +static DEVICE_ATTR(fps, 0200, NULL, rkcif_store_capture_fps); |
|---|
| 572 | + |
|---|
| 573 | +static ssize_t rkcif_show_rdbk_debug(struct device *dev, |
|---|
| 574 | + struct device_attribute *attr, |
|---|
| 575 | + char *buf) |
|---|
| 576 | +{ |
|---|
| 577 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 578 | + int ret; |
|---|
| 579 | + |
|---|
| 580 | + ret = snprintf(buf, PAGE_SIZE, "%d\n", |
|---|
| 581 | + cif_dev->rdbk_debug); |
|---|
| 582 | + return ret; |
|---|
| 583 | +} |
|---|
| 584 | + |
|---|
| 585 | +static ssize_t rkcif_store_rdbk_debug(struct device *dev, |
|---|
| 586 | + struct device_attribute *attr, |
|---|
| 587 | + const char *buf, size_t len) |
|---|
| 588 | +{ |
|---|
| 589 | + struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev); |
|---|
| 590 | + int val = 0; |
|---|
| 591 | + int ret = 0; |
|---|
| 592 | + |
|---|
| 593 | + ret = kstrtoint(buf, 0, &val); |
|---|
| 594 | + if (!ret) |
|---|
| 595 | + cif_dev->rdbk_debug = val; |
|---|
| 596 | + else |
|---|
| 597 | + dev_info(cif_dev->dev, "set rdbk debug failed\n"); |
|---|
| 598 | + return len; |
|---|
| 599 | +} |
|---|
| 600 | +static DEVICE_ATTR(rdbk_debug, 0200, rkcif_show_rdbk_debug, rkcif_store_rdbk_debug); |
|---|
| 225 | 601 | |
|---|
| 226 | 602 | static struct attribute *dev_attrs[] = { |
|---|
| 227 | 603 | &dev_attr_compact_test.attr, |
|---|
| 228 | 604 | &dev_attr_wait_line.attr, |
|---|
| 229 | 605 | &dev_attr_is_use_dummybuf.attr, |
|---|
| 230 | 606 | &dev_attr_is_high_align.attr, |
|---|
| 607 | + &dev_attr_scale_ch0_blc.attr, |
|---|
| 608 | + &dev_attr_scale_ch1_blc.attr, |
|---|
| 609 | + &dev_attr_scale_ch2_blc.attr, |
|---|
| 610 | + &dev_attr_scale_ch3_blc.attr, |
|---|
| 611 | + &dev_attr_fps.attr, |
|---|
| 612 | + &dev_attr_rdbk_debug.attr, |
|---|
| 231 | 613 | NULL, |
|---|
| 232 | 614 | }; |
|---|
| 233 | 615 | |
|---|
| .. | .. |
|---|
| 244 | 626 | { |
|---|
| 245 | 627 | void __iomem *base = dev->hw_dev->base_addr; |
|---|
| 246 | 628 | const struct cif_reg *reg = &dev->hw_dev->cif_regs[index]; |
|---|
| 629 | + int csi_offset = 0; |
|---|
| 247 | 630 | |
|---|
| 631 | + if (dev->inf_id == RKCIF_MIPI_LVDS && |
|---|
| 632 | + index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 && |
|---|
| 633 | + index <= CIF_REG_MIPI_ON_PAD) { |
|---|
| 634 | + if (dev->chip_id == CHIP_RK3588_CIF) { |
|---|
| 635 | + csi_offset = dev->csi_host_idx * 0x100; |
|---|
| 636 | + } else if (dev->chip_id == CHIP_RV1106_CIF) { |
|---|
| 637 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 638 | + } else if (dev->chip_id == CHIP_RK3562_CIF) { |
|---|
| 639 | + if (dev->csi_host_idx < 3) |
|---|
| 640 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 641 | + else |
|---|
| 642 | + csi_offset = 0x500; |
|---|
| 643 | + } |
|---|
| 644 | + } |
|---|
| 248 | 645 | if (index < CIF_REG_INDEX_MAX) { |
|---|
| 249 | | - if (index == CIF_REG_DVP_CTRL || |
|---|
| 250 | | - (index != CIF_REG_DVP_CTRL && reg->offset != 0x0)) |
|---|
| 251 | | - write_cif_reg(base, reg->offset, val); |
|---|
| 252 | | - else |
|---|
| 646 | + if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) { |
|---|
| 647 | + write_cif_reg(base, reg->offset + csi_offset, val); |
|---|
| 648 | + v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, |
|---|
| 649 | + "write reg[0x%x]:0x%x!!!\n", |
|---|
| 650 | + reg->offset + csi_offset, val); |
|---|
| 651 | + } else { |
|---|
| 253 | 652 | v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, |
|---|
| 254 | 653 | "write reg[%d]:0x%x failed, maybe useless!!!\n", |
|---|
| 255 | 654 | index, val); |
|---|
| 655 | + } |
|---|
| 256 | 656 | } |
|---|
| 257 | 657 | } |
|---|
| 258 | 658 | |
|---|
| .. | .. |
|---|
| 262 | 662 | unsigned int reg_val = 0x0; |
|---|
| 263 | 663 | void __iomem *base = dev->hw_dev->base_addr; |
|---|
| 264 | 664 | const struct cif_reg *reg = &dev->hw_dev->cif_regs[index]; |
|---|
| 665 | + int csi_offset = 0; |
|---|
| 666 | + |
|---|
| 667 | + if (dev->inf_id == RKCIF_MIPI_LVDS && |
|---|
| 668 | + index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 && |
|---|
| 669 | + index <= CIF_REG_MIPI_ON_PAD) { |
|---|
| 670 | + if (dev->chip_id == CHIP_RK3588_CIF) { |
|---|
| 671 | + csi_offset = dev->csi_host_idx * 0x100; |
|---|
| 672 | + } else if (dev->chip_id == CHIP_RV1106_CIF) { |
|---|
| 673 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 674 | + } else if (dev->chip_id == CHIP_RK3562_CIF) { |
|---|
| 675 | + if (dev->csi_host_idx < 3) |
|---|
| 676 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 677 | + else |
|---|
| 678 | + csi_offset = 0x500; |
|---|
| 679 | + } |
|---|
| 680 | + } |
|---|
| 265 | 681 | |
|---|
| 266 | 682 | if (index < CIF_REG_INDEX_MAX) { |
|---|
| 267 | | - if (index == CIF_REG_DVP_CTRL || |
|---|
| 268 | | - (index != CIF_REG_DVP_CTRL && reg->offset != 0x0)) { |
|---|
| 269 | | - reg_val = read_cif_reg(base, reg->offset); |
|---|
| 683 | + if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) { |
|---|
| 684 | + reg_val = read_cif_reg(base, reg->offset + csi_offset); |
|---|
| 270 | 685 | reg_val |= val; |
|---|
| 271 | | - write_cif_reg(base, reg->offset, reg_val); |
|---|
| 686 | + write_cif_reg(base, reg->offset + csi_offset, reg_val); |
|---|
| 687 | + v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, |
|---|
| 688 | + "write or reg[0x%x]:0x%x!!!\n", |
|---|
| 689 | + reg->offset + csi_offset, val); |
|---|
| 272 | 690 | } else { |
|---|
| 273 | 691 | v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, |
|---|
| 274 | 692 | "write reg[%d]:0x%x with OR failed, maybe useless!!!\n", |
|---|
| .. | .. |
|---|
| 283 | 701 | unsigned int reg_val = 0x0; |
|---|
| 284 | 702 | void __iomem *base = dev->hw_dev->base_addr; |
|---|
| 285 | 703 | const struct cif_reg *reg = &dev->hw_dev->cif_regs[index]; |
|---|
| 704 | + int csi_offset = 0; |
|---|
| 705 | + |
|---|
| 706 | + if (dev->inf_id == RKCIF_MIPI_LVDS && |
|---|
| 707 | + index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 && |
|---|
| 708 | + index <= CIF_REG_MIPI_ON_PAD) { |
|---|
| 709 | + if (dev->chip_id == CHIP_RK3588_CIF) { |
|---|
| 710 | + csi_offset = dev->csi_host_idx * 0x100; |
|---|
| 711 | + } else if (dev->chip_id == CHIP_RV1106_CIF) { |
|---|
| 712 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 713 | + } else if (dev->chip_id == CHIP_RK3562_CIF) { |
|---|
| 714 | + if (dev->csi_host_idx < 3) |
|---|
| 715 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 716 | + else |
|---|
| 717 | + csi_offset = 0x500; |
|---|
| 718 | + } |
|---|
| 719 | + } |
|---|
| 286 | 720 | |
|---|
| 287 | 721 | if (index < CIF_REG_INDEX_MAX) { |
|---|
| 288 | | - if (index == CIF_REG_DVP_CTRL || |
|---|
| 289 | | - (index != CIF_REG_DVP_CTRL && reg->offset != 0x0)) { |
|---|
| 290 | | - reg_val = read_cif_reg(base, reg->offset); |
|---|
| 722 | + if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) { |
|---|
| 723 | + reg_val = read_cif_reg(base, reg->offset + csi_offset); |
|---|
| 291 | 724 | reg_val &= val; |
|---|
| 292 | | - write_cif_reg(base, reg->offset, reg_val); |
|---|
| 725 | + write_cif_reg(base, reg->offset + csi_offset, reg_val); |
|---|
| 726 | + v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, |
|---|
| 727 | + "write and reg[0x%x]:0x%x!!!\n", |
|---|
| 728 | + reg->offset + csi_offset, val); |
|---|
| 293 | 729 | } else { |
|---|
| 294 | 730 | v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, |
|---|
| 295 | 731 | "write reg[%d]:0x%x with OR failed, maybe useless!!!\n", |
|---|
| .. | .. |
|---|
| 304 | 740 | unsigned int val = 0x0; |
|---|
| 305 | 741 | void __iomem *base = dev->hw_dev->base_addr; |
|---|
| 306 | 742 | const struct cif_reg *reg = &dev->hw_dev->cif_regs[index]; |
|---|
| 743 | + int csi_offset = 0; |
|---|
| 744 | + |
|---|
| 745 | + if (dev->inf_id == RKCIF_MIPI_LVDS && |
|---|
| 746 | + index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 && |
|---|
| 747 | + index <= CIF_REG_MIPI_ON_PAD) { |
|---|
| 748 | + if (dev->chip_id == CHIP_RK3588_CIF) { |
|---|
| 749 | + csi_offset = dev->csi_host_idx * 0x100; |
|---|
| 750 | + } else if (dev->chip_id == CHIP_RV1106_CIF) { |
|---|
| 751 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 752 | + } else if (dev->chip_id == CHIP_RK3562_CIF) { |
|---|
| 753 | + if (dev->csi_host_idx < 3) |
|---|
| 754 | + csi_offset = dev->csi_host_idx * 0x200; |
|---|
| 755 | + else |
|---|
| 756 | + csi_offset = 0x500; |
|---|
| 757 | + } |
|---|
| 758 | + } |
|---|
| 307 | 759 | |
|---|
| 308 | 760 | if (index < CIF_REG_INDEX_MAX) { |
|---|
| 309 | | - if (index == CIF_REG_DVP_CTRL || |
|---|
| 310 | | - (index != CIF_REG_DVP_CTRL && reg->offset != 0x0)) |
|---|
| 311 | | - val = read_cif_reg(base, reg->offset); |
|---|
| 761 | + if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) |
|---|
| 762 | + val = read_cif_reg(base, reg->offset + csi_offset); |
|---|
| 312 | 763 | else |
|---|
| 313 | 764 | v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, |
|---|
| 314 | 765 | "read reg[%d] failed, maybe useless!!!\n", |
|---|
| .. | .. |
|---|
| 375 | 826 | else |
|---|
| 376 | 827 | val = CIF_SAMPLING_EDGE_SINGLE; |
|---|
| 377 | 828 | rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val); |
|---|
| 829 | + } else if (dev->chip_id == CHIP_RK3588_CIF) { |
|---|
| 830 | + if (on) |
|---|
| 831 | + val = RK3588_CIF_PCLK_DUAL_EDGE; |
|---|
| 832 | + else |
|---|
| 833 | + val = RK3588_CIF_PCLK_SINGLE_EDGE; |
|---|
| 834 | + rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val); |
|---|
| 835 | + } else if (dev->chip_id == CHIP_RV1106_CIF) { |
|---|
| 836 | + if (on) |
|---|
| 837 | + val = RV1106_CIF_PCLK_DUAL_EDGE; |
|---|
| 838 | + else |
|---|
| 839 | + val = RV1106_CIF_PCLK_SINGLE_EDGE; |
|---|
| 840 | + rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val); |
|---|
| 378 | 841 | } |
|---|
| 379 | 842 | } |
|---|
| 380 | 843 | |
|---|
| .. | .. |
|---|
| 402 | 865 | else |
|---|
| 403 | 866 | val = RK3568_CIF_PCLK_SAMPLING_EDGE_FALLING; |
|---|
| 404 | 867 | } |
|---|
| 868 | + |
|---|
| 869 | + if (dev->chip_id == CHIP_RK3588_CIF) { |
|---|
| 870 | + if (edge == RKCIF_CLK_RISING) |
|---|
| 871 | + val = RK3588_CIF_PCLK_SAMPLING_EDGE_RISING; |
|---|
| 872 | + else |
|---|
| 873 | + val = RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING; |
|---|
| 874 | + } |
|---|
| 875 | + if (dev->chip_id == CHIP_RV1106_CIF) { |
|---|
| 876 | + if (dev->dphy_hw) { |
|---|
| 877 | + if (edge == RKCIF_CLK_RISING) |
|---|
| 878 | + val = RV1106_CIF_PCLK_EDGE_RISING_M0; |
|---|
| 879 | + else |
|---|
| 880 | + val = RV1106_CIF_PCLK_EDGE_FALLING_M0; |
|---|
| 881 | + } else { |
|---|
| 882 | + if (edge == RKCIF_CLK_RISING) |
|---|
| 883 | + val = RV1106_CIF_PCLK_EDGE_RISING_M1; |
|---|
| 884 | + else |
|---|
| 885 | + val = RV1106_CIF_PCLK_EDGE_FALLING_M1; |
|---|
| 886 | + rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_VENC, val); |
|---|
| 887 | + return; |
|---|
| 888 | + } |
|---|
| 889 | + } |
|---|
| 405 | 890 | rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val); |
|---|
| 891 | + } |
|---|
| 892 | +} |
|---|
| 893 | + |
|---|
| 894 | +void rkcif_config_dvp_pin(struct rkcif_device *dev, bool on) |
|---|
| 895 | +{ |
|---|
| 896 | + if (dev->dphy_hw && dev->dphy_hw->ttl_mode_enable && dev->dphy_hw->ttl_mode_disable) { |
|---|
| 897 | + rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, RV1106_CIF_GRF_SEL_M0); |
|---|
| 898 | + if (on) |
|---|
| 899 | + dev->dphy_hw->ttl_mode_enable(dev->dphy_hw); |
|---|
| 900 | + else |
|---|
| 901 | + dev->dphy_hw->ttl_mode_disable(dev->dphy_hw); |
|---|
| 902 | + } else { |
|---|
| 903 | + rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, RV1106_CIF_GRF_SEL_M1); |
|---|
| 406 | 904 | } |
|---|
| 407 | 905 | } |
|---|
| 408 | 906 | |
|---|
| .. | .. |
|---|
| 480 | 978 | return 0; |
|---|
| 481 | 979 | } |
|---|
| 482 | 980 | |
|---|
| 981 | +static void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev) |
|---|
| 982 | +{ |
|---|
| 983 | + struct rkcif_hw *hw = cif_dev->hw_dev; |
|---|
| 984 | + struct rkcif_device *dev = NULL; |
|---|
| 985 | + int i = 0, j = 0; |
|---|
| 986 | + int on = 1; |
|---|
| 987 | + int ret = 0; |
|---|
| 988 | + bool is_streaming = false; |
|---|
| 989 | + struct rkcif_multi_sync_config *sync_config; |
|---|
| 990 | + |
|---|
| 991 | + if (!cif_dev->sync_cfg.type) |
|---|
| 992 | + return; |
|---|
| 993 | + |
|---|
| 994 | + mutex_lock(&hw->dev_lock); |
|---|
| 995 | + sync_config = &hw->sync_config[cif_dev->sync_cfg.group]; |
|---|
| 996 | + sync_config->streaming_cnt++; |
|---|
| 997 | + if (sync_config->streaming_cnt < sync_config->dev_cnt) { |
|---|
| 998 | + mutex_unlock(&hw->dev_lock); |
|---|
| 999 | + return; |
|---|
| 1000 | + } |
|---|
| 1001 | + |
|---|
| 1002 | + if (sync_config->mode == RKCIF_MASTER_MASTER || |
|---|
| 1003 | + sync_config->mode == RKCIF_MASTER_SLAVE) { |
|---|
| 1004 | + for (i = 0; i < sync_config->slave.count; i++) { |
|---|
| 1005 | + dev = sync_config->slave.cif_dev[i]; |
|---|
| 1006 | + is_streaming = sync_config->slave.is_streaming[i]; |
|---|
| 1007 | + if (!is_streaming) { |
|---|
| 1008 | + if (dev->sditf_cnt == 1) { |
|---|
| 1009 | + ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, |
|---|
| 1010 | + RKMODULE_SET_QUICK_STREAM, &on); |
|---|
| 1011 | + if (ret) |
|---|
| 1012 | + dev_info(dev->dev, |
|---|
| 1013 | + "set RKMODULE_SET_QUICK_STREAM failed\n"); |
|---|
| 1014 | + } else { |
|---|
| 1015 | + for (j = 0; j < dev->sditf_cnt; j++) |
|---|
| 1016 | + ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd, |
|---|
| 1017 | + core, |
|---|
| 1018 | + ioctl, |
|---|
| 1019 | + RKMODULE_SET_QUICK_STREAM, |
|---|
| 1020 | + &on); |
|---|
| 1021 | + if (ret) |
|---|
| 1022 | + dev_info(dev->dev, |
|---|
| 1023 | + "set RKMODULE_SET_QUICK_STREAM failed\n"); |
|---|
| 1024 | + } |
|---|
| 1025 | + sync_config->slave.is_streaming[i] = true; |
|---|
| 1026 | + } |
|---|
| 1027 | + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, |
|---|
| 1028 | + "quick stream in sync mode, slave_dev[%d]\n", i); |
|---|
| 1029 | + |
|---|
| 1030 | + } |
|---|
| 1031 | + for (i = 0; i < sync_config->ext_master.count; i++) { |
|---|
| 1032 | + dev = sync_config->ext_master.cif_dev[i]; |
|---|
| 1033 | + is_streaming = sync_config->ext_master.is_streaming[i]; |
|---|
| 1034 | + if (!is_streaming) { |
|---|
| 1035 | + if (dev->sditf_cnt == 1) { |
|---|
| 1036 | + ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, |
|---|
| 1037 | + RKMODULE_SET_QUICK_STREAM, &on); |
|---|
| 1038 | + if (ret) |
|---|
| 1039 | + dev_info(dev->dev, |
|---|
| 1040 | + "set RKMODULE_SET_QUICK_STREAM failed\n"); |
|---|
| 1041 | + } else { |
|---|
| 1042 | + for (j = 0; j < dev->sditf_cnt; j++) |
|---|
| 1043 | + ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd, |
|---|
| 1044 | + core, |
|---|
| 1045 | + ioctl, |
|---|
| 1046 | + RKMODULE_SET_QUICK_STREAM, |
|---|
| 1047 | + &on); |
|---|
| 1048 | + if (ret) |
|---|
| 1049 | + dev_info(dev->dev, |
|---|
| 1050 | + "set RKMODULE_SET_QUICK_STREAM failed\n"); |
|---|
| 1051 | + } |
|---|
| 1052 | + sync_config->ext_master.is_streaming[i] = true; |
|---|
| 1053 | + } |
|---|
| 1054 | + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, |
|---|
| 1055 | + "quick stream in sync mode, ext_master_dev[%d]\n", i); |
|---|
| 1056 | + } |
|---|
| 1057 | + for (i = 0; i < sync_config->int_master.count; i++) { |
|---|
| 1058 | + dev = sync_config->int_master.cif_dev[i]; |
|---|
| 1059 | + is_streaming = sync_config->int_master.is_streaming[i]; |
|---|
| 1060 | + if (!is_streaming) { |
|---|
| 1061 | + if (dev->sditf_cnt == 1) { |
|---|
| 1062 | + ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, |
|---|
| 1063 | + RKMODULE_SET_QUICK_STREAM, &on); |
|---|
| 1064 | + if (ret) |
|---|
| 1065 | + dev_info(hw->dev, |
|---|
| 1066 | + "set RKMODULE_SET_QUICK_STREAM failed\n"); |
|---|
| 1067 | + } else { |
|---|
| 1068 | + for (j = 0; j < dev->sditf_cnt; j++) |
|---|
| 1069 | + ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd, |
|---|
| 1070 | + core, |
|---|
| 1071 | + ioctl, |
|---|
| 1072 | + RKMODULE_SET_QUICK_STREAM, |
|---|
| 1073 | + &on); |
|---|
| 1074 | + if (ret) |
|---|
| 1075 | + dev_info(dev->dev, |
|---|
| 1076 | + "set RKMODULE_SET_QUICK_STREAM failed\n"); |
|---|
| 1077 | + } |
|---|
| 1078 | + sync_config->int_master.is_streaming[i] = true; |
|---|
| 1079 | + } |
|---|
| 1080 | + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, |
|---|
| 1081 | + "quick stream in sync mode, int_master_dev[%d]\n", i); |
|---|
| 1082 | + } |
|---|
| 1083 | + } |
|---|
| 1084 | + mutex_unlock(&hw->dev_lock); |
|---|
| 1085 | +} |
|---|
| 1086 | + |
|---|
| 1087 | +static void rkcif_sensor_streaming_cb(void *data) |
|---|
| 1088 | +{ |
|---|
| 1089 | + struct v4l2_subdev *subdevs = (struct v4l2_subdev *)data; |
|---|
| 1090 | + |
|---|
| 1091 | + v4l2_subdev_call(subdevs, video, s_stream, 1); |
|---|
| 1092 | +} |
|---|
| 1093 | + |
|---|
| 483 | 1094 | /* |
|---|
| 484 | 1095 | * stream-on order: isp_subdev, mipi dphy, sensor |
|---|
| 485 | 1096 | * stream-off order: mipi dphy, sensor, isp_subdev |
|---|
| .. | .. |
|---|
| 487 | 1098 | static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on) |
|---|
| 488 | 1099 | { |
|---|
| 489 | 1100 | struct rkcif_device *cif_dev = container_of(p, struct rkcif_device, pipe); |
|---|
| 490 | | - struct rkcif_stream *stream = NULL; |
|---|
| 491 | 1101 | bool can_be_set = false; |
|---|
| 492 | | - int i, ret; |
|---|
| 1102 | + int i, ret = 0; |
|---|
| 493 | 1103 | |
|---|
| 494 | | - if (cif_dev->hdr.mode == NO_HDR) { |
|---|
| 1104 | + if (cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) { |
|---|
| 495 | 1105 | if ((on && atomic_inc_return(&p->stream_cnt) > 1) || |
|---|
| 496 | 1106 | (!on && atomic_dec_return(&p->stream_cnt) > 0)) |
|---|
| 497 | 1107 | return 0; |
|---|
| .. | .. |
|---|
| 505 | 1115 | cif_dev->irq_stats.dvp_overflow_cnt = 0; |
|---|
| 506 | 1116 | cif_dev->irq_stats.dvp_pix_err_cnt = 0; |
|---|
| 507 | 1117 | cif_dev->irq_stats.all_err_cnt = 0; |
|---|
| 508 | | - cif_dev->irq_stats.all_frm_end_cnt = 0; |
|---|
| 1118 | + cif_dev->irq_stats.csi_size_err_cnt = 0; |
|---|
| 1119 | + cif_dev->irq_stats.dvp_size_err_cnt = 0; |
|---|
| 1120 | + cif_dev->irq_stats.dvp_bwidth_lack_cnt = 0; |
|---|
| 1121 | + cif_dev->irq_stats.frm_end_cnt[0] = 0; |
|---|
| 1122 | + cif_dev->irq_stats.frm_end_cnt[1] = 0; |
|---|
| 1123 | + cif_dev->irq_stats.frm_end_cnt[2] = 0; |
|---|
| 1124 | + cif_dev->irq_stats.frm_end_cnt[3] = 0; |
|---|
| 1125 | + cif_dev->irq_stats.not_active_buf_cnt[0] = 0; |
|---|
| 1126 | + cif_dev->irq_stats.not_active_buf_cnt[1] = 0; |
|---|
| 1127 | + cif_dev->irq_stats.not_active_buf_cnt[2] = 0; |
|---|
| 1128 | + cif_dev->irq_stats.not_active_buf_cnt[3] = 0; |
|---|
| 1129 | + cif_dev->irq_stats.trig_simult_cnt[0] = 0; |
|---|
| 1130 | + cif_dev->irq_stats.trig_simult_cnt[1] = 0; |
|---|
| 1131 | + cif_dev->irq_stats.trig_simult_cnt[2] = 0; |
|---|
| 1132 | + cif_dev->irq_stats.trig_simult_cnt[3] = 0; |
|---|
| 509 | 1133 | cif_dev->reset_watchdog_timer.is_triggered = false; |
|---|
| 1134 | + cif_dev->reset_watchdog_timer.is_running = false; |
|---|
| 1135 | + cif_dev->err_state_work.last_timestamp = 0; |
|---|
| 1136 | + cif_dev->is_toisp_reset = false; |
|---|
| 510 | 1137 | for (i = 0; i < cif_dev->num_channels; i++) |
|---|
| 511 | 1138 | cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0; |
|---|
| 1139 | + cif_dev->reset_watchdog_timer.run_cnt = 0; |
|---|
| 512 | 1140 | } |
|---|
| 513 | 1141 | |
|---|
| 514 | 1142 | /* phy -> sensor */ |
|---|
| 515 | 1143 | for (i = 0; i < p->num_subdevs; i++) { |
|---|
| 516 | | - ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on); |
|---|
| 1144 | + if (p->subdevs[i] == cif_dev->terminal_sensor.sd && |
|---|
| 1145 | + on && |
|---|
| 1146 | + cif_dev->is_thunderboot && |
|---|
| 1147 | + !rk_tb_mcu_is_done()) { |
|---|
| 1148 | + cif_dev->tb_client.data = p->subdevs[i]; |
|---|
| 1149 | + cif_dev->tb_client.cb = rkcif_sensor_streaming_cb; |
|---|
| 1150 | + rk_tb_client_register_cb(&cif_dev->tb_client); |
|---|
| 1151 | + } else { |
|---|
| 1152 | + ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on); |
|---|
| 1153 | + } |
|---|
| 517 | 1154 | if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) |
|---|
| 518 | 1155 | goto err_stream_off; |
|---|
| 519 | 1156 | } |
|---|
| 1157 | + |
|---|
| 1158 | + if (cif_dev->sditf_cnt > 1) { |
|---|
| 1159 | + for (i = 0; i < cif_dev->sditf_cnt; i++) { |
|---|
| 1160 | + ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, |
|---|
| 1161 | + video, |
|---|
| 1162 | + s_stream, |
|---|
| 1163 | + on); |
|---|
| 1164 | + if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) |
|---|
| 1165 | + goto err_stream_off; |
|---|
| 1166 | + } |
|---|
| 1167 | + } |
|---|
| 1168 | + |
|---|
| 520 | 1169 | if (on) |
|---|
| 521 | | - rkcif_monitor_reset_event(cif_dev->hw_dev); |
|---|
| 1170 | + rkcif_set_sensor_streamon_in_sync_mode(cif_dev); |
|---|
| 522 | 1171 | } else { |
|---|
| 523 | 1172 | if (!on && atomic_dec_return(&p->stream_cnt) > 0) |
|---|
| 524 | 1173 | return 0; |
|---|
| 525 | 1174 | |
|---|
| 526 | 1175 | if (on) { |
|---|
| 527 | 1176 | atomic_inc(&p->stream_cnt); |
|---|
| 528 | | - if (cif_dev->hdr.mode == HDR_X2) { |
|---|
| 1177 | + if (cif_dev->hdr.hdr_mode == HDR_X2) { |
|---|
| 529 | 1178 | if (atomic_read(&p->stream_cnt) == 1) { |
|---|
| 530 | 1179 | rockchip_set_system_status(SYS_STATUS_CIF0); |
|---|
| 531 | 1180 | can_be_set = false; |
|---|
| 532 | 1181 | } else if (atomic_read(&p->stream_cnt) == 2) { |
|---|
| 533 | 1182 | can_be_set = true; |
|---|
| 534 | 1183 | } |
|---|
| 535 | | - } else if (cif_dev->hdr.mode == HDR_X3) { |
|---|
| 1184 | + } else if (cif_dev->hdr.hdr_mode == HDR_X3) { |
|---|
| 536 | 1185 | if (atomic_read(&p->stream_cnt) == 1) { |
|---|
| 537 | 1186 | rockchip_set_system_status(SYS_STATUS_CIF0); |
|---|
| 538 | 1187 | can_be_set = false; |
|---|
| .. | .. |
|---|
| 550 | 1199 | cif_dev->irq_stats.dvp_line_err_cnt = 0; |
|---|
| 551 | 1200 | cif_dev->irq_stats.dvp_overflow_cnt = 0; |
|---|
| 552 | 1201 | cif_dev->irq_stats.dvp_pix_err_cnt = 0; |
|---|
| 1202 | + cif_dev->irq_stats.dvp_bwidth_lack_cnt = 0; |
|---|
| 553 | 1203 | cif_dev->irq_stats.all_err_cnt = 0; |
|---|
| 554 | | - cif_dev->irq_stats.all_frm_end_cnt = 0; |
|---|
| 1204 | + cif_dev->irq_stats.csi_size_err_cnt = 0; |
|---|
| 1205 | + cif_dev->irq_stats.dvp_size_err_cnt = 0; |
|---|
| 1206 | + cif_dev->irq_stats.frm_end_cnt[0] = 0; |
|---|
| 1207 | + cif_dev->irq_stats.frm_end_cnt[1] = 0; |
|---|
| 1208 | + cif_dev->irq_stats.frm_end_cnt[2] = 0; |
|---|
| 1209 | + cif_dev->irq_stats.frm_end_cnt[3] = 0; |
|---|
| 1210 | + cif_dev->irq_stats.not_active_buf_cnt[0] = 0; |
|---|
| 1211 | + cif_dev->irq_stats.not_active_buf_cnt[1] = 0; |
|---|
| 1212 | + cif_dev->irq_stats.not_active_buf_cnt[2] = 0; |
|---|
| 1213 | + cif_dev->irq_stats.not_active_buf_cnt[3] = 0; |
|---|
| 1214 | + cif_dev->irq_stats.trig_simult_cnt[0] = 0; |
|---|
| 1215 | + cif_dev->irq_stats.trig_simult_cnt[1] = 0; |
|---|
| 1216 | + cif_dev->irq_stats.trig_simult_cnt[2] = 0; |
|---|
| 1217 | + cif_dev->irq_stats.trig_simult_cnt[3] = 0; |
|---|
| 555 | 1218 | cif_dev->is_start_hdr = true; |
|---|
| 556 | 1219 | cif_dev->reset_watchdog_timer.is_triggered = false; |
|---|
| 1220 | + cif_dev->reset_watchdog_timer.is_running = false; |
|---|
| 1221 | + cif_dev->is_toisp_reset = false; |
|---|
| 557 | 1222 | for (i = 0; i < cif_dev->num_channels; i++) |
|---|
| 558 | 1223 | cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0; |
|---|
| 1224 | + cif_dev->reset_watchdog_timer.run_cnt = 0; |
|---|
| 559 | 1225 | } |
|---|
| 560 | 1226 | |
|---|
| 561 | 1227 | /* phy -> sensor */ |
|---|
| 562 | 1228 | for (i = 0; i < p->num_subdevs; i++) { |
|---|
| 563 | | - ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on); |
|---|
| 564 | | - |
|---|
| 1229 | + if (p->subdevs[i] == cif_dev->terminal_sensor.sd && |
|---|
| 1230 | + on && |
|---|
| 1231 | + cif_dev->is_thunderboot && |
|---|
| 1232 | + !rk_tb_mcu_is_done()) { |
|---|
| 1233 | + cif_dev->tb_client.data = p->subdevs[i]; |
|---|
| 1234 | + cif_dev->tb_client.cb = rkcif_sensor_streaming_cb; |
|---|
| 1235 | + rk_tb_client_register_cb(&cif_dev->tb_client); |
|---|
| 1236 | + } else { |
|---|
| 1237 | + ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on); |
|---|
| 1238 | + } |
|---|
| 565 | 1239 | if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) |
|---|
| 566 | 1240 | goto err_stream_off; |
|---|
| 567 | 1241 | } |
|---|
| 568 | | - if (on) { |
|---|
| 569 | | - rkcif_monitor_reset_event(cif_dev->hw_dev); |
|---|
| 570 | | - for (i = 0; i < atomic_read(&p->stream_cnt); i++) { |
|---|
| 571 | | - stream = &cif_dev->stream[i]; |
|---|
| 572 | | - stream->streamon_timestamp = ktime_get_ns(); |
|---|
| 1242 | + if (cif_dev->sditf_cnt > 1) { |
|---|
| 1243 | + for (i = 0; i < cif_dev->sditf_cnt; i++) { |
|---|
| 1244 | + ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, |
|---|
| 1245 | + video, |
|---|
| 1246 | + s_stream, |
|---|
| 1247 | + on); |
|---|
| 1248 | + if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) |
|---|
| 1249 | + goto err_stream_off; |
|---|
| 573 | 1250 | } |
|---|
| 574 | 1251 | } |
|---|
| 1252 | + |
|---|
| 1253 | + if (on) |
|---|
| 1254 | + rkcif_set_sensor_streamon_in_sync_mode(cif_dev); |
|---|
| 575 | 1255 | } |
|---|
| 576 | 1256 | } |
|---|
| 577 | 1257 | |
|---|
| .. | .. |
|---|
| 587 | 1267 | return ret; |
|---|
| 588 | 1268 | } |
|---|
| 589 | 1269 | |
|---|
| 590 | | -/***************************** media controller *******************************/ |
|---|
| 591 | | -static int rkcif_create_links(struct rkcif_device *dev) |
|---|
| 1270 | +static int rkcif_create_link(struct rkcif_device *dev, |
|---|
| 1271 | + struct rkcif_sensor_info *sensor, |
|---|
| 1272 | + u32 stream_num, |
|---|
| 1273 | + bool *mipi_lvds_linked) |
|---|
| 592 | 1274 | { |
|---|
| 593 | | - int ret; |
|---|
| 594 | | - u32 flags; |
|---|
| 595 | | - unsigned int s, pad, id, stream_num = 0; |
|---|
| 596 | | - bool mipi_lvds_linked = false; |
|---|
| 1275 | + struct rkcif_sensor_info linked_sensor; |
|---|
| 1276 | + struct media_entity *source_entity, *sink_entity; |
|---|
| 1277 | + int ret = 0; |
|---|
| 1278 | + u32 flags, pad, id; |
|---|
| 1279 | + int pad_offset = 0; |
|---|
| 597 | 1280 | |
|---|
| 598 | | - if (dev->chip_id < CHIP_RV1126_CIF) { |
|---|
| 599 | | - if (dev->inf_id == RKCIF_MIPI_LVDS) |
|---|
| 600 | | - stream_num = RKCIF_MAX_STREAM_MIPI; |
|---|
| 601 | | - else |
|---|
| 602 | | - stream_num = RKCIF_SINGLE_STREAM; |
|---|
| 1281 | + if (dev->chip_id >= CHIP_RK3588_CIF) |
|---|
| 1282 | + pad_offset = 4; |
|---|
| 1283 | + |
|---|
| 1284 | + linked_sensor.lanes = sensor->lanes; |
|---|
| 1285 | + |
|---|
| 1286 | + if (sensor->mbus.type == V4L2_MBUS_CCP2) { |
|---|
| 1287 | + linked_sensor.sd = &dev->lvds_subdev.sd; |
|---|
| 1288 | + dev->lvds_subdev.sensor_self.sd = &dev->lvds_subdev.sd; |
|---|
| 1289 | + dev->lvds_subdev.sensor_self.lanes = sensor->lanes; |
|---|
| 1290 | + memcpy(&dev->lvds_subdev.sensor_self.mbus, &sensor->mbus, |
|---|
| 1291 | + sizeof(struct v4l2_mbus_config)); |
|---|
| 603 | 1292 | } else { |
|---|
| 604 | | - stream_num = RKCIF_MAX_STREAM_MIPI; |
|---|
| 1293 | + linked_sensor.sd = sensor->sd; |
|---|
| 605 | 1294 | } |
|---|
| 606 | 1295 | |
|---|
| 607 | | - /* sensor links(or mipi-phy) */ |
|---|
| 608 | | - for (s = 0; s < dev->num_sensors; ++s) { |
|---|
| 609 | | - struct rkcif_sensor_info *sensor = &dev->sensors[s]; |
|---|
| 610 | | - struct rkcif_sensor_info linked_sensor; |
|---|
| 611 | | - struct media_entity *source_entity, *sink_entity; |
|---|
| 1296 | + memcpy(&linked_sensor.mbus, &sensor->mbus, |
|---|
| 1297 | + sizeof(struct v4l2_mbus_config)); |
|---|
| 612 | 1298 | |
|---|
| 613 | | - linked_sensor.lanes = sensor->lanes; |
|---|
| 1299 | + for (pad = 0; pad < linked_sensor.sd->entity.num_pads; pad++) { |
|---|
| 1300 | + if (linked_sensor.sd->entity.pads[pad].flags & |
|---|
| 1301 | + MEDIA_PAD_FL_SOURCE) { |
|---|
| 1302 | + if (pad == linked_sensor.sd->entity.num_pads) { |
|---|
| 1303 | + dev_err(dev->dev, |
|---|
| 1304 | + "failed to find src pad for %s\n", |
|---|
| 1305 | + linked_sensor.sd->name); |
|---|
| 614 | 1306 | |
|---|
| 615 | | - if (sensor->mbus.type == V4L2_MBUS_CCP2) { |
|---|
| 616 | | - linked_sensor.sd = &dev->lvds_subdev.sd; |
|---|
| 617 | | - dev->lvds_subdev.sensor_self.sd = &dev->lvds_subdev.sd; |
|---|
| 618 | | - dev->lvds_subdev.sensor_self.lanes = sensor->lanes; |
|---|
| 619 | | - memcpy(&dev->lvds_subdev.sensor_self.mbus, &sensor->mbus, |
|---|
| 620 | | - sizeof(struct v4l2_mbus_config)); |
|---|
| 621 | | - } else { |
|---|
| 622 | | - linked_sensor.sd = sensor->sd; |
|---|
| 623 | | - } |
|---|
| 1307 | + break; |
|---|
| 1308 | + } |
|---|
| 624 | 1309 | |
|---|
| 625 | | - memcpy(&linked_sensor.mbus, &sensor->mbus, |
|---|
| 626 | | - sizeof(struct v4l2_mbus_config)); |
|---|
| 1310 | + if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 || |
|---|
| 1311 | + linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) && |
|---|
| 1312 | + (dev->chip_id == CHIP_RK1808_CIF)) { |
|---|
| 1313 | + source_entity = &linked_sensor.sd->entity; |
|---|
| 1314 | + sink_entity = &dev->stream[RKCIF_STREAM_CIF].vnode.vdev.entity; |
|---|
| 627 | 1315 | |
|---|
| 628 | | - for (pad = 0; pad < linked_sensor.sd->entity.num_pads; pad++) { |
|---|
| 629 | | - if (linked_sensor.sd->entity.pads[pad].flags & |
|---|
| 630 | | - MEDIA_PAD_FL_SOURCE) { |
|---|
| 631 | | - if (pad == linked_sensor.sd->entity.num_pads) { |
|---|
| 632 | | - dev_err(dev->dev, |
|---|
| 633 | | - "failed to find src pad for %s\n", |
|---|
| 1316 | + ret = media_create_pad_link(source_entity, |
|---|
| 1317 | + pad, |
|---|
| 1318 | + sink_entity, |
|---|
| 1319 | + 0, |
|---|
| 1320 | + MEDIA_LNK_FL_ENABLED); |
|---|
| 1321 | + if (ret) |
|---|
| 1322 | + dev_err(dev->dev, "failed to create link for %s\n", |
|---|
| 634 | 1323 | linked_sensor.sd->name); |
|---|
| 1324 | + break; |
|---|
| 1325 | + } |
|---|
| 635 | 1326 | |
|---|
| 1327 | + if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 || |
|---|
| 1328 | + linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) && |
|---|
| 1329 | + (dev->chip_id >= CHIP_RV1126_CIF)) { |
|---|
| 1330 | + source_entity = &linked_sensor.sd->entity; |
|---|
| 1331 | + sink_entity = &dev->stream[pad].vnode.vdev.entity; |
|---|
| 1332 | + |
|---|
| 1333 | + ret = media_create_pad_link(source_entity, |
|---|
| 1334 | + pad, |
|---|
| 1335 | + sink_entity, |
|---|
| 1336 | + 0, |
|---|
| 1337 | + MEDIA_LNK_FL_ENABLED); |
|---|
| 1338 | + if (ret) |
|---|
| 1339 | + dev_err(dev->dev, "failed to create link for %s pad[%d]\n", |
|---|
| 1340 | + linked_sensor.sd->name, pad); |
|---|
| 1341 | + continue; |
|---|
| 1342 | + } |
|---|
| 1343 | + |
|---|
| 1344 | + for (id = 0; id < stream_num; id++) { |
|---|
| 1345 | + source_entity = &linked_sensor.sd->entity; |
|---|
| 1346 | + sink_entity = &dev->stream[id].vnode.vdev.entity; |
|---|
| 1347 | + |
|---|
| 1348 | + if ((dev->chip_id < CHIP_RK1808_CIF) || |
|---|
| 1349 | + (id == pad - 1 && !(*mipi_lvds_linked))) |
|---|
| 1350 | + flags = MEDIA_LNK_FL_ENABLED; |
|---|
| 1351 | + else |
|---|
| 1352 | + flags = 0; |
|---|
| 1353 | + |
|---|
| 1354 | + ret = media_create_pad_link(source_entity, |
|---|
| 1355 | + pad, |
|---|
| 1356 | + sink_entity, |
|---|
| 1357 | + 0, |
|---|
| 1358 | + flags); |
|---|
| 1359 | + if (ret) { |
|---|
| 1360 | + dev_err(dev->dev, |
|---|
| 1361 | + "failed to create link for %s\n", |
|---|
| 1362 | + linked_sensor.sd->name); |
|---|
| 636 | 1363 | break; |
|---|
| 637 | 1364 | } |
|---|
| 638 | | - |
|---|
| 639 | | - if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 || |
|---|
| 640 | | - linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) && |
|---|
| 641 | | - (dev->chip_id == CHIP_RK1808_CIF)) { |
|---|
| 642 | | - source_entity = &linked_sensor.sd->entity; |
|---|
| 643 | | - sink_entity = &dev->stream[RKCIF_STREAM_CIF].vnode.vdev.entity; |
|---|
| 644 | | - |
|---|
| 645 | | - ret = media_create_pad_link(source_entity, |
|---|
| 646 | | - pad, |
|---|
| 647 | | - sink_entity, |
|---|
| 648 | | - 0, |
|---|
| 649 | | - MEDIA_LNK_FL_ENABLED); |
|---|
| 650 | | - if (ret) |
|---|
| 651 | | - dev_err(dev->dev, "failed to create link for %s\n", |
|---|
| 652 | | - linked_sensor.sd->name); |
|---|
| 653 | | - break; |
|---|
| 654 | | - } |
|---|
| 655 | | - |
|---|
| 656 | | - if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 || |
|---|
| 657 | | - linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) && |
|---|
| 658 | | - (dev->chip_id >= CHIP_RV1126_CIF)) { |
|---|
| 659 | | - source_entity = &linked_sensor.sd->entity; |
|---|
| 660 | | - sink_entity = &dev->stream[pad].vnode.vdev.entity; |
|---|
| 661 | | - |
|---|
| 662 | | - ret = media_create_pad_link(source_entity, |
|---|
| 663 | | - pad, |
|---|
| 664 | | - sink_entity, |
|---|
| 665 | | - 0, |
|---|
| 666 | | - MEDIA_LNK_FL_ENABLED); |
|---|
| 667 | | - if (ret) |
|---|
| 668 | | - dev_err(dev->dev, "failed to create link for %s pad[%d]\n", |
|---|
| 669 | | - linked_sensor.sd->name, pad); |
|---|
| 670 | | - continue; |
|---|
| 671 | | - } |
|---|
| 672 | | - |
|---|
| 1365 | + } |
|---|
| 1366 | + if (dev->chip_id >= CHIP_RK3588_CIF) { |
|---|
| 673 | 1367 | for (id = 0; id < stream_num; id++) { |
|---|
| 674 | 1368 | source_entity = &linked_sensor.sd->entity; |
|---|
| 675 | | - sink_entity = &dev->stream[id].vnode.vdev.entity; |
|---|
| 1369 | + sink_entity = &dev->scale_vdev[id].vnode.vdev.entity; |
|---|
| 676 | 1370 | |
|---|
| 677 | | - if ((dev->chip_id != CHIP_RK1808_CIF && |
|---|
| 678 | | - dev->chip_id != CHIP_RV1126_CIF && |
|---|
| 679 | | - dev->chip_id != CHIP_RV1126_CIF_LITE && |
|---|
| 680 | | - dev->chip_id != CHIP_RK3568_CIF) || |
|---|
| 681 | | - (id == pad - 1 && !mipi_lvds_linked)) |
|---|
| 1371 | + if ((id + stream_num) == pad - 1 && !(*mipi_lvds_linked)) |
|---|
| 1372 | + flags = MEDIA_LNK_FL_ENABLED; |
|---|
| 1373 | + else |
|---|
| 1374 | + flags = 0; |
|---|
| 1375 | + |
|---|
| 1376 | + ret = media_create_pad_link(source_entity, |
|---|
| 1377 | + pad, |
|---|
| 1378 | + sink_entity, |
|---|
| 1379 | + 0, |
|---|
| 1380 | + flags); |
|---|
| 1381 | + if (ret) { |
|---|
| 1382 | + dev_err(dev->dev, |
|---|
| 1383 | + "failed to create link for %s\n", |
|---|
| 1384 | + linked_sensor.sd->name); |
|---|
| 1385 | + break; |
|---|
| 1386 | + } |
|---|
| 1387 | + } |
|---|
| 1388 | + } |
|---|
| 1389 | + if (dev->chip_id > CHIP_RK1808_CIF) { |
|---|
| 1390 | + for (id = 0; id < RKCIF_MAX_TOOLS_CH; id++) { |
|---|
| 1391 | + source_entity = &linked_sensor.sd->entity; |
|---|
| 1392 | + sink_entity = &dev->tools_vdev[id].vnode.vdev.entity; |
|---|
| 1393 | + |
|---|
| 1394 | + if ((id + stream_num + pad_offset) == pad - 1 && !(*mipi_lvds_linked)) |
|---|
| 682 | 1395 | flags = MEDIA_LNK_FL_ENABLED; |
|---|
| 683 | 1396 | else |
|---|
| 684 | 1397 | flags = 0; |
|---|
| .. | .. |
|---|
| 697 | 1410 | } |
|---|
| 698 | 1411 | } |
|---|
| 699 | 1412 | } |
|---|
| 1413 | + } |
|---|
| 700 | 1414 | |
|---|
| 701 | | - if (sensor->mbus.type == V4L2_MBUS_CCP2) { |
|---|
| 702 | | - source_entity = &sensor->sd->entity; |
|---|
| 703 | | - sink_entity = &linked_sensor.sd->entity; |
|---|
| 704 | | - ret = media_create_pad_link(source_entity, |
|---|
| 705 | | - 1, |
|---|
| 706 | | - sink_entity, |
|---|
| 707 | | - 0, |
|---|
| 708 | | - MEDIA_LNK_FL_ENABLED); |
|---|
| 709 | | - if (ret) |
|---|
| 710 | | - dev_err(dev->dev, "failed to create link between %s and %s\n", |
|---|
| 711 | | - linked_sensor.sd->name, |
|---|
| 712 | | - sensor->sd->name); |
|---|
| 713 | | - } |
|---|
| 1415 | + if (sensor->mbus.type == V4L2_MBUS_CCP2) { |
|---|
| 1416 | + source_entity = &sensor->sd->entity; |
|---|
| 1417 | + sink_entity = &linked_sensor.sd->entity; |
|---|
| 1418 | + ret = media_create_pad_link(source_entity, |
|---|
| 1419 | + 1, |
|---|
| 1420 | + sink_entity, |
|---|
| 1421 | + 0, |
|---|
| 1422 | + MEDIA_LNK_FL_ENABLED); |
|---|
| 1423 | + if (ret) |
|---|
| 1424 | + dev_err(dev->dev, "failed to create link between %s and %s\n", |
|---|
| 1425 | + linked_sensor.sd->name, |
|---|
| 1426 | + sensor->sd->name); |
|---|
| 1427 | + } |
|---|
| 714 | 1428 | |
|---|
| 715 | | - if (linked_sensor.mbus.type != V4L2_MBUS_BT656 && |
|---|
| 716 | | - linked_sensor.mbus.type != V4L2_MBUS_PARALLEL) |
|---|
| 717 | | - mipi_lvds_linked = true; |
|---|
| 1429 | + if (linked_sensor.mbus.type != V4L2_MBUS_BT656 && |
|---|
| 1430 | + linked_sensor.mbus.type != V4L2_MBUS_PARALLEL) |
|---|
| 1431 | + *mipi_lvds_linked = true; |
|---|
| 1432 | + return ret; |
|---|
| 1433 | +} |
|---|
| 1434 | + |
|---|
| 1435 | +/***************************** media controller *******************************/ |
|---|
| 1436 | +static int rkcif_create_links(struct rkcif_device *dev) |
|---|
| 1437 | +{ |
|---|
| 1438 | + u32 s = 0; |
|---|
| 1439 | + u32 stream_num = 0; |
|---|
| 1440 | + bool mipi_lvds_linked = false; |
|---|
| 1441 | + |
|---|
| 1442 | + if (dev->chip_id < CHIP_RV1126_CIF) { |
|---|
| 1443 | + if (dev->inf_id == RKCIF_MIPI_LVDS) |
|---|
| 1444 | + stream_num = RKCIF_MAX_STREAM_MIPI; |
|---|
| 1445 | + else |
|---|
| 1446 | + stream_num = RKCIF_SINGLE_STREAM; |
|---|
| 1447 | + } else { |
|---|
| 1448 | + stream_num = RKCIF_MAX_STREAM_MIPI; |
|---|
| 1449 | + } |
|---|
| 1450 | + |
|---|
| 1451 | + /* sensor links(or mipi-phy) */ |
|---|
| 1452 | + for (s = 0; s < dev->num_sensors; ++s) { |
|---|
| 1453 | + struct rkcif_sensor_info *sensor = &dev->sensors[s]; |
|---|
| 1454 | + |
|---|
| 1455 | + rkcif_create_link(dev, sensor, stream_num, &mipi_lvds_linked); |
|---|
| 718 | 1456 | } |
|---|
| 719 | 1457 | |
|---|
| 720 | 1458 | return 0; |
|---|
| .. | .. |
|---|
| 728 | 1466 | |
|---|
| 729 | 1467 | static int subdev_asyn_register_itf(struct rkcif_device *dev) |
|---|
| 730 | 1468 | { |
|---|
| 731 | | - struct sditf_priv *sditf = dev->sditf; |
|---|
| 1469 | + struct sditf_priv *sditf = NULL; |
|---|
| 732 | 1470 | int ret = 0; |
|---|
| 733 | 1471 | |
|---|
| 734 | | - if (sditf) |
|---|
| 1472 | + ret = rkcif_update_sensor_info(&dev->stream[0]); |
|---|
| 1473 | + if (ret) { |
|---|
| 1474 | + v4l2_err(&dev->v4l2_dev, |
|---|
| 1475 | + "There is not terminal subdev, not synchronized with ISP\n"); |
|---|
| 1476 | + return 0; |
|---|
| 1477 | + } |
|---|
| 1478 | + sditf = dev->sditf[0]; |
|---|
| 1479 | + if (sditf && (!sditf->is_combine_mode) && (!dev->is_notifier_isp)) { |
|---|
| 735 | 1480 | ret = v4l2_async_register_subdev_sensor_common(&sditf->sd); |
|---|
| 1481 | + dev->is_notifier_isp = true; |
|---|
| 1482 | + } |
|---|
| 736 | 1483 | |
|---|
| 737 | 1484 | return ret; |
|---|
| 738 | 1485 | } |
|---|
| .. | .. |
|---|
| 756 | 1503 | if (sd->ops) { |
|---|
| 757 | 1504 | if (sd == sensor->sd) { |
|---|
| 758 | 1505 | ret = v4l2_subdev_call(sd, |
|---|
| 759 | | - video, |
|---|
| 760 | | - g_mbus_config, |
|---|
| 1506 | + pad, |
|---|
| 1507 | + get_mbus_config, |
|---|
| 1508 | + 0, |
|---|
| 761 | 1509 | &sensor->mbus); |
|---|
| 762 | 1510 | if (ret) |
|---|
| 763 | 1511 | v4l2_err(v4l2_dev, |
|---|
| .. | .. |
|---|
| 767 | 1515 | } |
|---|
| 768 | 1516 | |
|---|
| 769 | 1517 | if (sensor->mbus.type == V4L2_MBUS_CCP2 || |
|---|
| 770 | | - sensor->mbus.type == V4L2_MBUS_CSI2) { |
|---|
| 1518 | + sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || |
|---|
| 1519 | + sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) { |
|---|
| 771 | 1520 | |
|---|
| 772 | 1521 | switch (sensor->mbus.flags & V4L2_MBUS_CSI2_LANES) { |
|---|
| 773 | 1522 | case V4L2_MBUS_CSI2_1_LANE: |
|---|
| .. | .. |
|---|
| 821 | 1570 | if (ret < 0) |
|---|
| 822 | 1571 | goto unregister_lvds; |
|---|
| 823 | 1572 | |
|---|
| 1573 | + if (!completion_done(&dev->cmpl_ntf)) |
|---|
| 1574 | + complete(&dev->cmpl_ntf); |
|---|
| 824 | 1575 | v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n"); |
|---|
| 825 | 1576 | |
|---|
| 826 | 1577 | return ret; |
|---|
| .. | .. |
|---|
| 874 | 1625 | |
|---|
| 875 | 1626 | if (vep->bus_type != V4L2_MBUS_BT656 && |
|---|
| 876 | 1627 | vep->bus_type != V4L2_MBUS_PARALLEL && |
|---|
| 877 | | - vep->bus_type != V4L2_MBUS_CSI2 && |
|---|
| 1628 | + vep->bus_type != V4L2_MBUS_CSI2_DPHY && |
|---|
| 1629 | + vep->bus_type != V4L2_MBUS_CSI2_CPHY && |
|---|
| 878 | 1630 | vep->bus_type != V4L2_MBUS_CCP2) |
|---|
| 879 | 1631 | return 0; |
|---|
| 880 | 1632 | |
|---|
| 881 | 1633 | rk_asd->mbus.type = vep->bus_type; |
|---|
| 882 | 1634 | |
|---|
| 883 | | - if (vep->bus_type == V4L2_MBUS_CSI2) { |
|---|
| 1635 | + if (vep->bus_type == V4L2_MBUS_CSI2_DPHY || |
|---|
| 1636 | + vep->bus_type == V4L2_MBUS_CSI2_CPHY) { |
|---|
| 884 | 1637 | rk_asd->mbus.flags = vep->bus.mipi_csi2.flags; |
|---|
| 885 | 1638 | rk_asd->lanes = vep->bus.mipi_csi2.num_data_lanes; |
|---|
| 886 | 1639 | } else if (vep->bus_type == V4L2_MBUS_CCP2) { |
|---|
| .. | .. |
|---|
| 903 | 1656 | struct device *dev = cif_dev->dev; |
|---|
| 904 | 1657 | int ret; |
|---|
| 905 | 1658 | |
|---|
| 1659 | + v4l2_async_notifier_init(ntf); |
|---|
| 1660 | + |
|---|
| 906 | 1661 | ret = v4l2_async_notifier_parse_fwnode_endpoints( |
|---|
| 907 | 1662 | dev, ntf, sizeof(struct rkcif_async_subdev), rkcif_fwnode_parse); |
|---|
| 908 | 1663 | |
|---|
| .. | .. |
|---|
| 912 | 1667 | return ret; |
|---|
| 913 | 1668 | } |
|---|
| 914 | 1669 | |
|---|
| 915 | | - if (!ntf->num_subdevs) { |
|---|
| 916 | | - v4l2_warn(&cif_dev->v4l2_dev, |
|---|
| 917 | | - "%s: no subdev be found!\n", __func__); |
|---|
| 918 | | - return -ENODEV; /* no endpoint */ |
|---|
| 919 | | - } |
|---|
| 920 | | - |
|---|
| 921 | 1670 | ntf->ops = &subdev_notifier_ops; |
|---|
| 922 | 1671 | |
|---|
| 923 | 1672 | ret = v4l2_async_notifier_register(&cif_dev->v4l2_dev, ntf); |
|---|
| 924 | 1673 | |
|---|
| 925 | 1674 | return ret; |
|---|
| 1675 | +} |
|---|
| 1676 | + |
|---|
| 1677 | +static int notifier_isp_thread(void *data) |
|---|
| 1678 | +{ |
|---|
| 1679 | + struct rkcif_device *dev = data; |
|---|
| 1680 | + int ret = 0; |
|---|
| 1681 | + |
|---|
| 1682 | + ret = wait_for_completion_timeout(&dev->cmpl_ntf, msecs_to_jiffies(5000)); |
|---|
| 1683 | + if (ret) { |
|---|
| 1684 | + mutex_lock(&rkcif_dev_mutex); |
|---|
| 1685 | + subdev_asyn_register_itf(dev); |
|---|
| 1686 | + mutex_unlock(&rkcif_dev_mutex); |
|---|
| 1687 | + } |
|---|
| 1688 | + return 0; |
|---|
| 926 | 1689 | } |
|---|
| 927 | 1690 | |
|---|
| 928 | 1691 | /***************************** platform deive *******************************/ |
|---|
| .. | .. |
|---|
| 945 | 1708 | stream_num = RKCIF_MAX_STREAM_MIPI; |
|---|
| 946 | 1709 | ret = rkcif_register_stream_vdevs(cif_dev, stream_num, true); |
|---|
| 947 | 1710 | } |
|---|
| 948 | | - cif_dev->num_channels = stream_num; |
|---|
| 1711 | + |
|---|
| 949 | 1712 | if (ret < 0) { |
|---|
| 950 | 1713 | dev_err(cif_dev->dev, "cif register stream[%d] failed!\n", stream_num); |
|---|
| 951 | 1714 | return -EINVAL; |
|---|
| 952 | 1715 | } |
|---|
| 953 | 1716 | |
|---|
| 1717 | + if (cif_dev->chip_id == CHIP_RK3588_CIF || |
|---|
| 1718 | + cif_dev->chip_id == CHIP_RV1106_CIF || |
|---|
| 1719 | + cif_dev->chip_id == CHIP_RK3562_CIF) { |
|---|
| 1720 | + ret = rkcif_register_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH, true); |
|---|
| 1721 | + |
|---|
| 1722 | + if (ret < 0) { |
|---|
| 1723 | + dev_err(cif_dev->dev, "cif register scale_vdev[%d] failed!\n", stream_num); |
|---|
| 1724 | + goto err_unreg_stream_vdev; |
|---|
| 1725 | + } |
|---|
| 1726 | + } |
|---|
| 1727 | + if (cif_dev->chip_id > CHIP_RK1808_CIF) { |
|---|
| 1728 | + ret = rkcif_register_tools_vdevs(cif_dev, RKCIF_MAX_TOOLS_CH, true); |
|---|
| 1729 | + |
|---|
| 1730 | + if (ret < 0) { |
|---|
| 1731 | + dev_err(cif_dev->dev, "cif register tools_vdev[%d] failed!\n", RKCIF_MAX_TOOLS_CH); |
|---|
| 1732 | + goto err_unreg_stream_vdev; |
|---|
| 1733 | + } |
|---|
| 1734 | + cif_dev->is_support_tools = true; |
|---|
| 1735 | + } else { |
|---|
| 1736 | + cif_dev->is_support_tools = false; |
|---|
| 1737 | + } |
|---|
| 1738 | + init_completion(&cif_dev->cmpl_ntf); |
|---|
| 1739 | + kthread_run(notifier_isp_thread, cif_dev, "notifier isp"); |
|---|
| 954 | 1740 | ret = cif_subdev_notifier(cif_dev); |
|---|
| 955 | 1741 | if (ret < 0) { |
|---|
| 956 | 1742 | v4l2_err(&cif_dev->v4l2_dev, |
|---|
| .. | .. |
|---|
| 961 | 1747 | return 0; |
|---|
| 962 | 1748 | err_unreg_stream_vdev: |
|---|
| 963 | 1749 | rkcif_unregister_stream_vdevs(cif_dev, stream_num); |
|---|
| 1750 | + if (cif_dev->chip_id == CHIP_RK3588_CIF || |
|---|
| 1751 | + cif_dev->chip_id == CHIP_RV1106_CIF || |
|---|
| 1752 | + cif_dev->chip_id == CHIP_RK3562_CIF) |
|---|
| 1753 | + rkcif_unregister_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH); |
|---|
| 1754 | + |
|---|
| 1755 | + if (cif_dev->chip_id > CHIP_RK1808_CIF) |
|---|
| 1756 | + rkcif_unregister_tools_vdevs(cif_dev, RKCIF_MAX_TOOLS_CH); |
|---|
| 964 | 1757 | |
|---|
| 965 | 1758 | return ret; |
|---|
| 966 | 1759 | } |
|---|
| 967 | 1760 | |
|---|
| 968 | 1761 | static irqreturn_t rkcif_irq_handler(int irq, struct rkcif_device *cif_dev) |
|---|
| 969 | 1762 | { |
|---|
| 970 | | - if (cif_dev->workmode == RKCIF_WORKMODE_PINGPONG) |
|---|
| 971 | | - rkcif_irq_pingpong(cif_dev); |
|---|
| 972 | | - else |
|---|
| 1763 | + if (cif_dev->workmode == RKCIF_WORKMODE_PINGPONG) { |
|---|
| 1764 | + if (cif_dev->chip_id < CHIP_RK3588_CIF) |
|---|
| 1765 | + rkcif_irq_pingpong(cif_dev); |
|---|
| 1766 | + else |
|---|
| 1767 | + rkcif_irq_pingpong_v1(cif_dev); |
|---|
| 1768 | + } else { |
|---|
| 973 | 1769 | rkcif_irq_oneframe(cif_dev); |
|---|
| 974 | | - |
|---|
| 1770 | + } |
|---|
| 975 | 1771 | return IRQ_HANDLED; |
|---|
| 976 | 1772 | } |
|---|
| 977 | 1773 | |
|---|
| .. | .. |
|---|
| 982 | 1778 | return IRQ_HANDLED; |
|---|
| 983 | 1779 | } |
|---|
| 984 | 1780 | |
|---|
| 985 | | -void rkcif_soft_reset(struct rkcif_device *cif_dev, bool is_rst_iommu) |
|---|
| 1781 | +static void rkcif_attach_dphy_hw(struct rkcif_device *cif_dev) |
|---|
| 986 | 1782 | { |
|---|
| 987 | | - struct rkcif_hw *hw_dev = cif_dev->hw_dev; |
|---|
| 988 | | - bool can_reset = true; |
|---|
| 989 | | - int i; |
|---|
| 1783 | + struct platform_device *plat_dev; |
|---|
| 1784 | + struct device *dev = cif_dev->dev; |
|---|
| 1785 | + struct device_node *np; |
|---|
| 1786 | + struct csi2_dphy_hw *dphy_hw; |
|---|
| 990 | 1787 | |
|---|
| 991 | | - if (!cif_dev->hw_dev) |
|---|
| 1788 | + np = of_parse_phandle(dev->of_node, "rockchip,dphy_hw", 0); |
|---|
| 1789 | + if (!np || !of_device_is_available(np)) { |
|---|
| 1790 | + dev_err(dev, |
|---|
| 1791 | + "failed to get dphy hw node\n"); |
|---|
| 992 | 1792 | return; |
|---|
| 1793 | + } |
|---|
| 993 | 1794 | |
|---|
| 994 | | - for (i = 0; i < hw_dev->dev_num; i++) |
|---|
| 995 | | - if (atomic_read(&hw_dev->cif_dev[i]->pipe.stream_cnt) != 0) { |
|---|
| 996 | | - can_reset = false; |
|---|
| 997 | | - break; |
|---|
| 998 | | - } |
|---|
| 1795 | + plat_dev = of_find_device_by_node(np); |
|---|
| 1796 | + of_node_put(np); |
|---|
| 1797 | + if (!plat_dev) { |
|---|
| 1798 | + dev_err(dev, |
|---|
| 1799 | + "failed to get dphy hw from node\n"); |
|---|
| 1800 | + return; |
|---|
| 1801 | + } |
|---|
| 999 | 1802 | |
|---|
| 1000 | | - if (can_reset) |
|---|
| 1001 | | - rkcif_hw_soft_reset(cif_dev->hw_dev, is_rst_iommu); |
|---|
| 1803 | + dphy_hw = platform_get_drvdata(plat_dev); |
|---|
| 1804 | + if (!dphy_hw) { |
|---|
| 1805 | + dev_err(dev, |
|---|
| 1806 | + "failed attach dphy hw\n"); |
|---|
| 1807 | + return; |
|---|
| 1808 | + } |
|---|
| 1809 | + cif_dev->dphy_hw = dphy_hw; |
|---|
| 1002 | 1810 | } |
|---|
| 1003 | 1811 | |
|---|
| 1004 | 1812 | int rkcif_attach_hw(struct rkcif_device *cif_dev) |
|---|
| .. | .. |
|---|
| 1035 | 1843 | cif_dev->hw_dev = hw; |
|---|
| 1036 | 1844 | cif_dev->chip_id = hw->chip_id; |
|---|
| 1037 | 1845 | dev_info(cif_dev->dev, "attach to cif hw node\n"); |
|---|
| 1846 | + if (IS_ENABLED(CONFIG_CPU_RV1106)) |
|---|
| 1847 | + rkcif_attach_dphy_hw(cif_dev); |
|---|
| 1038 | 1848 | |
|---|
| 1039 | 1849 | return 0; |
|---|
| 1040 | 1850 | } |
|---|
| .. | .. |
|---|
| 1065 | 1875 | static void rkcif_init_reset_monitor(struct rkcif_device *dev) |
|---|
| 1066 | 1876 | { |
|---|
| 1067 | 1877 | struct rkcif_timer *timer = &dev->reset_watchdog_timer; |
|---|
| 1068 | | - struct notifier_block *notifier = &dev->reset_notifier; |
|---|
| 1069 | 1878 | |
|---|
| 1879 | +#if defined(CONFIG_ROCKCHIP_CIF_USE_MONITOR) |
|---|
| 1880 | + timer->monitor_mode = CONFIG_ROCKCHIP_CIF_MONITOR_MODE; |
|---|
| 1881 | + timer->err_time_interval = CONFIG_ROCKCHIP_CIF_MONITOR_KEEP_TIME; |
|---|
| 1882 | + timer->frm_num_of_monitor_cycle = CONFIG_ROCKCHIP_CIF_MONITOR_CYCLE; |
|---|
| 1883 | + timer->triggered_frame_num = CONFIG_ROCKCHIP_CIF_MONITOR_START_FRAME; |
|---|
| 1884 | + timer->csi2_err_ref_cnt = CONFIG_ROCKCHIP_CIF_MONITOR_ERR_CNT; |
|---|
| 1885 | + #if defined(CONFIG_ROCKCHIP_CIF_RESET_BY_USER) |
|---|
| 1886 | + timer->is_ctrl_by_user = true; |
|---|
| 1887 | + #else |
|---|
| 1888 | + timer->is_ctrl_by_user = false; |
|---|
| 1889 | + #endif |
|---|
| 1890 | +#else |
|---|
| 1891 | + timer->monitor_mode = RKCIF_MONITOR_MODE_IDLE; |
|---|
| 1892 | + timer->err_time_interval = 0xffffffff; |
|---|
| 1893 | + timer->frm_num_of_monitor_cycle = 0xffffffff; |
|---|
| 1894 | + timer->triggered_frame_num = 0xffffffff; |
|---|
| 1895 | + timer->csi2_err_ref_cnt = 0xffffffff; |
|---|
| 1896 | +#endif |
|---|
| 1897 | + timer->is_running = false; |
|---|
| 1070 | 1898 | timer->is_triggered = false; |
|---|
| 1071 | 1899 | timer->is_buf_stop_update = false; |
|---|
| 1072 | 1900 | timer->csi2_err_cnt_even = 0; |
|---|
| .. | .. |
|---|
| 1076 | 1904 | timer->csi2_err_triggered_cnt = 0; |
|---|
| 1077 | 1905 | timer->csi2_first_err_timestamp = 0; |
|---|
| 1078 | 1906 | |
|---|
| 1079 | | - if (dev->inf_id == RKCIF_MIPI_LVDS) { |
|---|
| 1080 | | - notifier->priority = 1; |
|---|
| 1081 | | - notifier->notifier_call = rkcif_reset_notifier; |
|---|
| 1082 | | - rkcif_csi2_register_notifier(notifier); |
|---|
| 1083 | | - } |
|---|
| 1907 | + timer_setup(&timer->timer, rkcif_reset_watchdog_timer_handler, 0); |
|---|
| 1908 | + |
|---|
| 1084 | 1909 | INIT_WORK(&dev->reset_work.work, rkcif_reset_work); |
|---|
| 1910 | +} |
|---|
| 1911 | + |
|---|
| 1912 | +void rkcif_set_sensor_stream(struct work_struct *work) |
|---|
| 1913 | +{ |
|---|
| 1914 | + struct rkcif_sensor_work *sensor_work = container_of(work, |
|---|
| 1915 | + struct rkcif_sensor_work, |
|---|
| 1916 | + work); |
|---|
| 1917 | + struct rkcif_device *cif_dev = container_of(sensor_work, |
|---|
| 1918 | + struct rkcif_device, |
|---|
| 1919 | + sensor_work); |
|---|
| 1920 | + |
|---|
| 1921 | + v4l2_subdev_call(cif_dev->terminal_sensor.sd, |
|---|
| 1922 | + core, ioctl, |
|---|
| 1923 | + RKMODULE_SET_QUICK_STREAM, |
|---|
| 1924 | + &sensor_work->on); |
|---|
| 1925 | +} |
|---|
| 1926 | + |
|---|
| 1927 | +static void rkcif_deal_err_intr(struct work_struct *work) |
|---|
| 1928 | +{ |
|---|
| 1929 | + struct delayed_work *dwork = to_delayed_work(work); |
|---|
| 1930 | + struct rkcif_device *cif_dev = container_of(dwork, |
|---|
| 1931 | + struct rkcif_device, |
|---|
| 1932 | + work_deal_err); |
|---|
| 1933 | + |
|---|
| 1934 | + cif_dev->intr_mask |= CSI_BANDWIDTH_LACK_V1; |
|---|
| 1935 | + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTEN, CSI_BANDWIDTH_LACK_V1); |
|---|
| 1085 | 1936 | } |
|---|
| 1086 | 1937 | |
|---|
| 1087 | 1938 | int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id) |
|---|
| .. | .. |
|---|
| 1090 | 1941 | struct v4l2_device *v4l2_dev; |
|---|
| 1091 | 1942 | int ret; |
|---|
| 1092 | 1943 | |
|---|
| 1093 | | - cif_dev->hdr.mode = NO_HDR; |
|---|
| 1944 | + cif_dev->hdr.hdr_mode = NO_HDR; |
|---|
| 1094 | 1945 | cif_dev->inf_id = inf_id; |
|---|
| 1095 | 1946 | |
|---|
| 1096 | 1947 | mutex_init(&cif_dev->stream_lock); |
|---|
| 1948 | + mutex_init(&cif_dev->scale_lock); |
|---|
| 1949 | + mutex_init(&cif_dev->tools_lock); |
|---|
| 1097 | 1950 | spin_lock_init(&cif_dev->hdr_lock); |
|---|
| 1951 | + spin_lock_init(&cif_dev->buffree_lock); |
|---|
| 1952 | + spin_lock_init(&cif_dev->reset_watchdog_timer.timer_lock); |
|---|
| 1098 | 1953 | spin_lock_init(&cif_dev->reset_watchdog_timer.csi2_err_lock); |
|---|
| 1099 | 1954 | atomic_set(&cif_dev->pipe.power_cnt, 0); |
|---|
| 1100 | 1955 | atomic_set(&cif_dev->pipe.stream_cnt, 0); |
|---|
| 1101 | | - atomic_set(&cif_dev->fh_cnt, 0); |
|---|
| 1956 | + atomic_set(&cif_dev->power_cnt, 0); |
|---|
| 1957 | + atomic_set(&cif_dev->streamoff_cnt, 0); |
|---|
| 1102 | 1958 | cif_dev->is_start_hdr = false; |
|---|
| 1103 | 1959 | cif_dev->pipe.open = rkcif_pipeline_open; |
|---|
| 1104 | 1960 | cif_dev->pipe.close = rkcif_pipeline_close; |
|---|
| 1105 | 1961 | cif_dev->pipe.set_stream = rkcif_pipeline_set_stream; |
|---|
| 1106 | 1962 | cif_dev->isr_hdl = rkcif_irq_handler; |
|---|
| 1963 | + cif_dev->id_use_cnt = 0; |
|---|
| 1964 | + memset(&cif_dev->sync_cfg, 0, sizeof(cif_dev->sync_cfg)); |
|---|
| 1965 | + cif_dev->sditf_cnt = 0; |
|---|
| 1966 | + cif_dev->is_notifier_isp = false; |
|---|
| 1967 | + cif_dev->sensor_linetime = 0; |
|---|
| 1968 | + cif_dev->early_line = 0; |
|---|
| 1969 | + cif_dev->is_thunderboot = false; |
|---|
| 1970 | + cif_dev->rdbk_debug = 0; |
|---|
| 1971 | + |
|---|
| 1972 | + cif_dev->resume_mode = 0; |
|---|
| 1973 | + memset(&cif_dev->channels[0].capture_info, 0, sizeof(cif_dev->channels[0].capture_info)); |
|---|
| 1107 | 1974 | if (cif_dev->chip_id == CHIP_RV1126_CIF_LITE) |
|---|
| 1108 | 1975 | cif_dev->isr_hdl = rkcif_irq_lite_handler; |
|---|
| 1976 | + |
|---|
| 1977 | + INIT_WORK(&cif_dev->err_state_work.work, rkcif_err_print_work); |
|---|
| 1978 | + INIT_WORK(&cif_dev->sensor_work.work, rkcif_set_sensor_stream); |
|---|
| 1979 | + INIT_DELAYED_WORK(&cif_dev->work_deal_err, rkcif_deal_err_intr); |
|---|
| 1109 | 1980 | |
|---|
| 1110 | 1981 | if (cif_dev->chip_id < CHIP_RV1126_CIF) { |
|---|
| 1111 | 1982 | if (cif_dev->inf_id == RKCIF_MIPI_LVDS) { |
|---|
| .. | .. |
|---|
| 1124 | 1995 | rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID3); |
|---|
| 1125 | 1996 | } |
|---|
| 1126 | 1997 | |
|---|
| 1998 | + if (cif_dev->chip_id == CHIP_RK3588_CIF || |
|---|
| 1999 | + cif_dev->chip_id == CHIP_RV1106_CIF || |
|---|
| 2000 | + cif_dev->chip_id == CHIP_RK3562_CIF) { |
|---|
| 2001 | + rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH0); |
|---|
| 2002 | + rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH1); |
|---|
| 2003 | + rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH2); |
|---|
| 2004 | + rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH3); |
|---|
| 2005 | + } |
|---|
| 2006 | + |
|---|
| 2007 | + if (cif_dev->chip_id > CHIP_RK1808_CIF) { |
|---|
| 2008 | + rkcif_init_tools_vdev(cif_dev, RKCIF_TOOLS_CH0); |
|---|
| 2009 | + rkcif_init_tools_vdev(cif_dev, RKCIF_TOOLS_CH1); |
|---|
| 2010 | + rkcif_init_tools_vdev(cif_dev, RKCIF_TOOLS_CH2); |
|---|
| 2011 | + } |
|---|
| 1127 | 2012 | #if defined(CONFIG_ROCKCHIP_CIF_WORKMODE_PINGPONG) |
|---|
| 1128 | 2013 | cif_dev->workmode = RKCIF_WORKMODE_PINGPONG; |
|---|
| 1129 | 2014 | #elif defined(CONFIG_ROCKCHIP_CIF_WORKMODE_ONEFRAME) |
|---|
| .. | .. |
|---|
| 1137 | 2022 | #else |
|---|
| 1138 | 2023 | cif_dev->is_use_dummybuf = false; |
|---|
| 1139 | 2024 | #endif |
|---|
| 2025 | + if (cif_dev->chip_id == CHIP_RV1106_CIF) |
|---|
| 2026 | + cif_dev->is_use_dummybuf = false; |
|---|
| 1140 | 2027 | |
|---|
| 1141 | 2028 | strlcpy(cif_dev->media_dev.model, dev_name(dev), |
|---|
| 1142 | 2029 | sizeof(cif_dev->media_dev.model)); |
|---|
| 2030 | + cif_dev->csi_host_idx = of_alias_get_id(node, "rkcif_mipi_lvds"); |
|---|
| 2031 | + if (cif_dev->csi_host_idx < 0 || cif_dev->csi_host_idx > 5) |
|---|
| 2032 | + cif_dev->csi_host_idx = 0; |
|---|
| 2033 | + if (cif_dev->hw_dev->is_rk3588s2) { |
|---|
| 2034 | + if (cif_dev->csi_host_idx == 0) |
|---|
| 2035 | + cif_dev->csi_host_idx = 2; |
|---|
| 2036 | + else if (cif_dev->csi_host_idx == 2) |
|---|
| 2037 | + cif_dev->csi_host_idx = 4; |
|---|
| 2038 | + else if (cif_dev->csi_host_idx == 3) |
|---|
| 2039 | + cif_dev->csi_host_idx = 5; |
|---|
| 2040 | + v4l2_info(&cif_dev->v4l2_dev, "rk3588s2 attach to mipi%d\n", |
|---|
| 2041 | + cif_dev->csi_host_idx); |
|---|
| 2042 | + } |
|---|
| 2043 | + cif_dev->csi_host_idx_def = cif_dev->csi_host_idx; |
|---|
| 1143 | 2044 | cif_dev->media_dev.dev = dev; |
|---|
| 1144 | 2045 | v4l2_dev = &cif_dev->v4l2_dev; |
|---|
| 1145 | 2046 | v4l2_dev->mdev = &cif_dev->media_dev; |
|---|
| .. | .. |
|---|
| 1204 | 2105 | } |
|---|
| 1205 | 2106 | rkcif_unregister_stream_vdevs(cif_dev, stream_num); |
|---|
| 1206 | 2107 | |
|---|
| 2108 | + if (cif_dev->chip_id == CHIP_RV1106_CIF) |
|---|
| 2109 | + rkcif_rockit_dev_deinit(); |
|---|
| 1207 | 2110 | return 0; |
|---|
| 1208 | 2111 | } |
|---|
| 1209 | 2112 | |
|---|
| .. | .. |
|---|
| 1240 | 2143 | dev_info(cif_dev->dev, "rkcif wait line %d\n", cif_dev->wait_line); |
|---|
| 1241 | 2144 | } |
|---|
| 1242 | 2145 | |
|---|
| 2146 | +static int rkcif_get_reserved_mem(struct rkcif_device *cif_dev) |
|---|
| 2147 | +{ |
|---|
| 2148 | + struct device *dev = cif_dev->dev; |
|---|
| 2149 | + struct device_node *np; |
|---|
| 2150 | + struct resource r; |
|---|
| 2151 | + int ret; |
|---|
| 2152 | + |
|---|
| 2153 | + cif_dev->is_thunderboot = false; |
|---|
| 2154 | + cif_dev->is_rtt_suspend = false; |
|---|
| 2155 | + /* Get reserved memory region from Device-tree */ |
|---|
| 2156 | + np = of_parse_phandle(dev->of_node, "memory-region-thunderboot", 0); |
|---|
| 2157 | + if (!np) { |
|---|
| 2158 | + dev_info(dev, "No memory-region-thunderboot specified\n"); |
|---|
| 2159 | + return 0; |
|---|
| 2160 | + } |
|---|
| 2161 | + |
|---|
| 2162 | + ret = of_address_to_resource(np, 0, &r); |
|---|
| 2163 | + if (ret) { |
|---|
| 2164 | + dev_err(dev, "No memory address assigned to the region\n"); |
|---|
| 2165 | + return ret; |
|---|
| 2166 | + } |
|---|
| 2167 | + |
|---|
| 2168 | + cif_dev->resmem_pa = r.start; |
|---|
| 2169 | + cif_dev->resmem_size = resource_size(&r); |
|---|
| 2170 | + cif_dev->resmem_addr = dma_map_single(dev, phys_to_virt(r.start), |
|---|
| 2171 | + sizeof(struct rkisp_thunderboot_resmem_head), |
|---|
| 2172 | + DMA_BIDIRECTIONAL); |
|---|
| 2173 | + |
|---|
| 2174 | + if (device_property_read_bool(dev, "rtt-suspend")) |
|---|
| 2175 | + cif_dev->is_rtt_suspend = true; |
|---|
| 2176 | + if (IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) |
|---|
| 2177 | + cif_dev->is_thunderboot = true; |
|---|
| 2178 | + dev_info(dev, "Allocated reserved memory, paddr: 0x%x, size 0x%x\n", |
|---|
| 2179 | + (u32)cif_dev->resmem_pa, |
|---|
| 2180 | + (u32)cif_dev->resmem_size); |
|---|
| 2181 | + return ret; |
|---|
| 2182 | +} |
|---|
| 2183 | + |
|---|
| 1243 | 2184 | static int rkcif_plat_probe(struct platform_device *pdev) |
|---|
| 1244 | 2185 | { |
|---|
| 1245 | 2186 | const struct of_device_id *match; |
|---|
| .. | .. |
|---|
| 1268 | 2209 | dev_set_drvdata(dev, cif_dev); |
|---|
| 1269 | 2210 | cif_dev->dev = dev; |
|---|
| 1270 | 2211 | |
|---|
| 1271 | | - rkcif_attach_hw(cif_dev); |
|---|
| 2212 | + if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp)) |
|---|
| 2213 | + return -ENODEV; |
|---|
| 2214 | + |
|---|
| 2215 | + ret = rkcif_attach_hw(cif_dev); |
|---|
| 2216 | + if (ret) |
|---|
| 2217 | + return ret; |
|---|
| 1272 | 2218 | |
|---|
| 1273 | 2219 | rkcif_parse_dts(cif_dev); |
|---|
| 1274 | 2220 | |
|---|
| .. | .. |
|---|
| 1278 | 2224 | return ret; |
|---|
| 1279 | 2225 | } |
|---|
| 1280 | 2226 | |
|---|
| 1281 | | - if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp)) |
|---|
| 1282 | | - return -ENODEV; |
|---|
| 2227 | + ret = rkcif_get_reserved_mem(cif_dev); |
|---|
| 2228 | + if (ret) |
|---|
| 2229 | + return ret; |
|---|
| 1283 | 2230 | |
|---|
| 1284 | 2231 | if (rkcif_proc_init(cif_dev)) |
|---|
| 1285 | 2232 | dev_warn(dev, "dev:%s create proc failed\n", dev_name(dev)); |
|---|
| 1286 | 2233 | |
|---|
| 1287 | 2234 | rkcif_init_reset_monitor(cif_dev); |
|---|
| 1288 | | - rkcif_soft_reset(cif_dev, false); |
|---|
| 2235 | + if (cif_dev->chip_id == CHIP_RV1106_CIF) |
|---|
| 2236 | + rkcif_rockit_dev_init(cif_dev); |
|---|
| 1289 | 2237 | pm_runtime_enable(&pdev->dev); |
|---|
| 1290 | 2238 | |
|---|
| 1291 | 2239 | return 0; |
|---|
| .. | .. |
|---|
| 1298 | 2246 | rkcif_plat_uninit(cif_dev); |
|---|
| 1299 | 2247 | rkcif_detach_hw(cif_dev); |
|---|
| 1300 | 2248 | rkcif_proc_cleanup(cif_dev); |
|---|
| 1301 | | - rkcif_csi2_unregister_notifier(&cif_dev->reset_notifier); |
|---|
| 1302 | 2249 | sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp); |
|---|
| 2250 | + del_timer_sync(&cif_dev->reset_watchdog_timer.timer); |
|---|
| 1303 | 2251 | |
|---|
| 2252 | + return 0; |
|---|
| 2253 | +} |
|---|
| 2254 | + |
|---|
| 2255 | +static int __maybe_unused rkcif_sleep_suspend(struct device *dev) |
|---|
| 2256 | +{ |
|---|
| 2257 | + struct rkcif_device *cif_dev = dev_get_drvdata(dev); |
|---|
| 2258 | + |
|---|
| 2259 | + rkcif_stream_suspend(cif_dev, RKCIF_RESUME_CIF); |
|---|
| 2260 | + return 0; |
|---|
| 2261 | +} |
|---|
| 2262 | + |
|---|
| 2263 | +static int __maybe_unused rkcif_sleep_resume(struct device *dev) |
|---|
| 2264 | +{ |
|---|
| 2265 | + struct rkcif_device *cif_dev = dev_get_drvdata(dev); |
|---|
| 2266 | + |
|---|
| 2267 | + rkcif_stream_resume(cif_dev, RKCIF_RESUME_CIF); |
|---|
| 1304 | 2268 | return 0; |
|---|
| 1305 | 2269 | } |
|---|
| 1306 | 2270 | |
|---|
| .. | .. |
|---|
| 1309 | 2273 | struct rkcif_device *cif_dev = dev_get_drvdata(dev); |
|---|
| 1310 | 2274 | int ret = 0; |
|---|
| 1311 | 2275 | |
|---|
| 1312 | | - if (atomic_dec_return(&cif_dev->hw_dev->power_cnt)) |
|---|
| 2276 | + if (atomic_dec_return(&cif_dev->power_cnt)) |
|---|
| 1313 | 2277 | return 0; |
|---|
| 1314 | 2278 | |
|---|
| 1315 | 2279 | mutex_lock(&cif_dev->hw_dev->dev_lock); |
|---|
| .. | .. |
|---|
| 1323 | 2287 | struct rkcif_device *cif_dev = dev_get_drvdata(dev); |
|---|
| 1324 | 2288 | int ret = 0; |
|---|
| 1325 | 2289 | |
|---|
| 1326 | | - if (atomic_inc_return(&cif_dev->hw_dev->power_cnt) > 1) |
|---|
| 2290 | + if (atomic_inc_return(&cif_dev->power_cnt) > 1) |
|---|
| 1327 | 2291 | return 0; |
|---|
| 2292 | + |
|---|
| 1328 | 2293 | mutex_lock(&cif_dev->hw_dev->dev_lock); |
|---|
| 1329 | | - ret = pm_runtime_get_sync(cif_dev->hw_dev->dev); |
|---|
| 2294 | + ret = pm_runtime_resume_and_get(cif_dev->hw_dev->dev); |
|---|
| 1330 | 2295 | mutex_unlock(&cif_dev->hw_dev->dev_lock); |
|---|
| 2296 | + rkcif_do_soft_reset(cif_dev); |
|---|
| 1331 | 2297 | return (ret > 0) ? 0 : ret; |
|---|
| 1332 | 2298 | } |
|---|
| 1333 | 2299 | |
|---|
| .. | .. |
|---|
| 1360 | 2326 | MODULE_PARM_DESC(clr_unready_dev, "clear unready devices"); |
|---|
| 1361 | 2327 | |
|---|
| 1362 | 2328 | #ifndef MODULE |
|---|
| 1363 | | -static int __init rkcif_clr_unready_dev(void) |
|---|
| 2329 | +int rkcif_clr_unready_dev(void) |
|---|
| 1364 | 2330 | { |
|---|
| 1365 | 2331 | __rkcif_clr_unready_dev(); |
|---|
| 1366 | 2332 | |
|---|
| 1367 | 2333 | return 0; |
|---|
| 1368 | 2334 | } |
|---|
| 2335 | +#ifndef CONFIG_VIDEO_REVERSE_IMAGE |
|---|
| 1369 | 2336 | late_initcall(rkcif_clr_unready_dev); |
|---|
| 2337 | +#endif |
|---|
| 1370 | 2338 | #endif |
|---|
| 1371 | 2339 | |
|---|
| 1372 | 2340 | static const struct dev_pm_ops rkcif_plat_pm_ops = { |
|---|
| 1373 | | - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
|---|
| 1374 | | - pm_runtime_force_resume) |
|---|
| 2341 | + SET_SYSTEM_SLEEP_PM_OPS(rkcif_sleep_suspend, rkcif_sleep_resume) |
|---|
| 1375 | 2342 | SET_RUNTIME_PM_OPS(rkcif_runtime_suspend, rkcif_runtime_resume, NULL) |
|---|
| 1376 | 2343 | }; |
|---|
| 1377 | 2344 | |
|---|