| .. | .. |
|---|
| 13 | 13 | * 1. add 2lane support. |
|---|
| 14 | 14 | * 2. add some debug info. |
|---|
| 15 | 15 | * 3. adjust gc8034_g_mbus_config function. |
|---|
| 16 | + * V0.0X01.0X07 support get channel info |
|---|
| 17 | + * V0.0X01.0X08 |
|---|
| 18 | + * 1. default support 2lane full 30fps. |
|---|
| 19 | + * 2. default support rk otp spec. |
|---|
| 20 | + * V0.0X01.0X09 adjust supply sequence to suit spec |
|---|
| 16 | 21 | */ |
|---|
| 17 | | - |
|---|
| 22 | +//#define DEBUG |
|---|
| 18 | 23 | #include <linux/clk.h> |
|---|
| 19 | 24 | #include <linux/device.h> |
|---|
| 20 | 25 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 39 | 44 | #include <media/v4l2-subdev.h> |
|---|
| 40 | 45 | #include <linux/pinctrl/consumer.h> |
|---|
| 41 | 46 | #include <linux/slab.h> |
|---|
| 47 | +#include <linux/of_graph.h> |
|---|
| 48 | +#include "otp_eeprom.h" |
|---|
| 42 | 49 | |
|---|
| 43 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x06) |
|---|
| 50 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x09) |
|---|
| 44 | 51 | |
|---|
| 45 | 52 | #ifndef V4L2_CID_DIGITAL_GAIN |
|---|
| 46 | 53 | #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN |
|---|
| .. | .. |
|---|
| 49 | 56 | #define GC8034_LANES 4 |
|---|
| 50 | 57 | #define GC8034_BITS_PER_SAMPLE 10 |
|---|
| 51 | 58 | #define GC8034_MIPI_FREQ_336MHZ 336000000U |
|---|
| 59 | +#define GC8034_MIPI_FREQ_634MHZ 634000000U |
|---|
| 52 | 60 | |
|---|
| 53 | 61 | /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ |
|---|
| 54 | 62 | #define GC8034_PIXEL_RATE 288000000 |
|---|
| .. | .. |
|---|
| 92 | 100 | #define GC8034_NAME "gc8034" |
|---|
| 93 | 101 | #define GC8034_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB10_1X10 |
|---|
| 94 | 102 | |
|---|
| 103 | +/* use RK_OTP or old mode */ |
|---|
| 104 | +#define RK_OTP |
|---|
| 105 | +/* choose 2lane support full 30fps or 15fps */ |
|---|
| 106 | +#define GC8034_2LANE_30FPS |
|---|
| 107 | + |
|---|
| 95 | 108 | static const char * const gc8034_supply_names[] = { |
|---|
| 96 | | - "avdd", /* Analog power */ |
|---|
| 97 | 109 | "dovdd", /* Digital I/O power */ |
|---|
| 98 | 110 | "dvdd", /* Digital core power */ |
|---|
| 111 | + "avdd", /* Analog power */ |
|---|
| 99 | 112 | }; |
|---|
| 100 | 113 | |
|---|
| 101 | | -static const struct regval *gc8034_global_regs; |
|---|
| 102 | 114 | #define GC8034_NUM_SUPPLIES ARRAY_SIZE(gc8034_supply_names) |
|---|
| 103 | 115 | |
|---|
| 116 | +#ifndef RK_OTP |
|---|
| 104 | 117 | struct gc8034_dd { |
|---|
| 105 | 118 | u16 x; |
|---|
| 106 | 119 | u16 y; |
|---|
| .. | .. |
|---|
| 145 | 158 | {0xd0, "CK8401"}, |
|---|
| 146 | 159 | {0x00, "Unknown"} |
|---|
| 147 | 160 | }; |
|---|
| 161 | +#endif |
|---|
| 148 | 162 | |
|---|
| 149 | 163 | struct regval { |
|---|
| 150 | 164 | u8 addr; |
|---|
| .. | .. |
|---|
| 158 | 172 | u32 hts_def; |
|---|
| 159 | 173 | u32 vts_def; |
|---|
| 160 | 174 | u32 exp_def; |
|---|
| 175 | + u32 mipi_freq_idx; |
|---|
| 176 | + const struct regval *global_reg_list; |
|---|
| 161 | 177 | const struct regval *reg_list; |
|---|
| 178 | + u32 vc[PAD_MAX]; |
|---|
| 162 | 179 | }; |
|---|
| 163 | 180 | |
|---|
| 164 | 181 | struct gc8034 { |
|---|
| .. | .. |
|---|
| 192 | 209 | const char *module_name; |
|---|
| 193 | 210 | const char *len_name; |
|---|
| 194 | 211 | u32 Dgain_ratio; |
|---|
| 212 | +#ifdef RK_OTP |
|---|
| 213 | + struct otp_info *otp; |
|---|
| 214 | +#else |
|---|
| 195 | 215 | struct gc8034_otp_info *otp; |
|---|
| 216 | +#endif |
|---|
| 196 | 217 | struct rkmodule_inf module_inf; |
|---|
| 197 | 218 | struct rkmodule_awb_cfg awb_cfg; |
|---|
| 198 | 219 | }; |
|---|
| .. | .. |
|---|
| 244 | 265 | * Xclk 24Mhz |
|---|
| 245 | 266 | */ |
|---|
| 246 | 267 | static const struct regval gc8034_global_regs_2lane[] = { |
|---|
| 268 | +#ifdef GC8034_2LANE_30FPS |
|---|
| 269 | + /* SYS */ |
|---|
| 270 | + {0xf2, 0x00}, |
|---|
| 271 | + {0xf4, 0x90}, |
|---|
| 272 | + {0xf5, 0x3d}, |
|---|
| 273 | + {0xf6, 0x44}, |
|---|
| 274 | + {0xf8, 0x63}, |
|---|
| 275 | + {0xfa, 0x42}, |
|---|
| 276 | + {0xf9, 0x00}, |
|---|
| 277 | + {0xf7, 0x95}, |
|---|
| 278 | + {0xfc, 0x00}, |
|---|
| 279 | + {0xfc, 0x00}, |
|---|
| 280 | + {0xfc, 0xea}, |
|---|
| 281 | + {0xfe, 0x03}, |
|---|
| 282 | + {0x03, 0x9a}, |
|---|
| 283 | + {0xfc, 0xee}, |
|---|
| 284 | + {0xfe, 0x00}, |
|---|
| 285 | + {0x88, 0x03}, |
|---|
| 286 | + |
|---|
| 287 | + /*Cisctl&Analog*/ |
|---|
| 288 | + {0xfe, 0x00}, |
|---|
| 289 | + {0x03, 0x08}, |
|---|
| 290 | + {0x04, 0xc6}, |
|---|
| 291 | + {0x05, 0x02}, |
|---|
| 292 | + {0x06, 0x16}, |
|---|
| 293 | + {0x07, 0x00}, |
|---|
| 294 | + {0x08, 0x10}, |
|---|
| 295 | + {0x0a, 0x3a}, //row start |
|---|
| 296 | + {0x0b, 0x00}, |
|---|
| 297 | + {0x0c, 0x04}, //col start |
|---|
| 298 | + {0x0d, 0x09}, |
|---|
| 299 | + {0x0e, 0xa0}, //win_height 2464 |
|---|
| 300 | + {0x0f, 0x0c}, |
|---|
| 301 | + {0x10, 0xd4}, //win_width 3284 |
|---|
| 302 | + {0x17, GC8034_MIRROR}, |
|---|
| 303 | + {0x18, 0x02}, |
|---|
| 304 | + {0x19, 0x17}, |
|---|
| 305 | + {0x1e, 0x50}, |
|---|
| 306 | + {0x1f, 0x80}, |
|---|
| 307 | + {0x21, 0x4c}, |
|---|
| 308 | + {0x25, 0x00}, |
|---|
| 309 | + {0x28, 0x4a}, |
|---|
| 310 | + {0x2d, 0x89}, |
|---|
| 311 | + {0xca, 0x02}, |
|---|
| 312 | + {0xcb, 0x00}, |
|---|
| 313 | + {0xcc, 0x39}, |
|---|
| 314 | + {0xce, 0xd0}, |
|---|
| 315 | + {0xcf, 0x93}, |
|---|
| 316 | + {0xd0, 0x1b}, |
|---|
| 317 | + {0xd1, 0xaa}, |
|---|
| 318 | + {0xd2, 0xcb}, |
|---|
| 319 | + {0xd8, 0x40}, |
|---|
| 320 | + {0xd9, 0xff}, |
|---|
| 321 | + {0xda, 0x0e}, |
|---|
| 322 | + {0xdb, 0xb0}, |
|---|
| 323 | + {0xdc, 0x0e}, |
|---|
| 324 | + {0xde, 0x08}, |
|---|
| 325 | + {0xe4, 0xc6}, |
|---|
| 326 | + {0xe5, 0x08}, |
|---|
| 327 | + {0xe6, 0x10}, |
|---|
| 328 | + {0xed, 0x2a}, |
|---|
| 329 | + {0xfe, 0x02}, |
|---|
| 330 | + {0x59, 0x02}, |
|---|
| 331 | + {0x5a, 0x04}, |
|---|
| 332 | + {0x5b, 0x08}, |
|---|
| 333 | + {0x5c, 0x20}, |
|---|
| 334 | + {0xfe, 0x00}, |
|---|
| 335 | + {0x1a, 0x09}, |
|---|
| 336 | + {0x1d, 0x13}, |
|---|
| 337 | + {0xfe, 0x10}, |
|---|
| 338 | + {0xfe, 0x00}, |
|---|
| 339 | + {0xfe, 0x10}, |
|---|
| 340 | + {0xfe, 0x00}, |
|---|
| 341 | + |
|---|
| 342 | + /* Gamma */ |
|---|
| 343 | + {0xfe, 0x00}, |
|---|
| 344 | + {0x20, 0x54}, |
|---|
| 345 | + {0x33, 0x82}, |
|---|
| 346 | + {0xfe, 0x01}, |
|---|
| 347 | + {0xdf, 0x06}, |
|---|
| 348 | + {0xe7, 0x18}, |
|---|
| 349 | + {0xe8, 0x20}, |
|---|
| 350 | + {0xe9, 0x16}, |
|---|
| 351 | + {0xea, 0x17}, |
|---|
| 352 | + {0xeb, 0x50}, |
|---|
| 353 | + {0xec, 0x6c}, |
|---|
| 354 | + {0xed, 0x9b}, |
|---|
| 355 | + {0xee, 0xd8}, |
|---|
| 356 | + |
|---|
| 357 | + /*ISP*/ |
|---|
| 358 | + {0xfe, 0x00}, |
|---|
| 359 | + {0x80, 0x13}, |
|---|
| 360 | + {0x84, 0x01}, |
|---|
| 361 | + {0x89, 0x03}, |
|---|
| 362 | + {0x8d, 0x03}, |
|---|
| 363 | + {0x8f, 0x14}, |
|---|
| 364 | + {0xad, 0x00}, |
|---|
| 365 | + {0x66, 0x0c}, |
|---|
| 366 | + {0xbc, 0x09}, |
|---|
| 367 | + {0xc2, 0x7f}, |
|---|
| 368 | + {0xc3, 0xff}, |
|---|
| 369 | + |
|---|
| 370 | + /*Crop window*/ |
|---|
| 371 | + {0x90, 0x01}, |
|---|
| 372 | + {0x92, FULL_STARTY}, |
|---|
| 373 | + {0x94, FULL_STARTX}, |
|---|
| 374 | + {0x95, 0x09}, |
|---|
| 375 | + {0x96, 0x90}, |
|---|
| 376 | + {0x97, 0x0c}, |
|---|
| 377 | + {0x98, 0xc0}, |
|---|
| 378 | + |
|---|
| 379 | + /*Gain*/ |
|---|
| 380 | + {0xb0, 0x90}, |
|---|
| 381 | + {0xb1, 0x01}, |
|---|
| 382 | + {0xb2, 0x00}, |
|---|
| 383 | + {0xb6, 0x00}, |
|---|
| 384 | + |
|---|
| 385 | + /*BLK*/ |
|---|
| 386 | + {0xfe, 0x00}, |
|---|
| 387 | + {0x40, 0x22}, |
|---|
| 388 | + {0x41, 0x20}, |
|---|
| 389 | + {0x42, 0x02}, |
|---|
| 390 | + {0x43, 0x08}, |
|---|
| 391 | + {0x4e, 0x0f}, |
|---|
| 392 | + {0x4f, 0xf0}, |
|---|
| 393 | + {0x58, 0x80}, |
|---|
| 394 | + {0x59, 0x80}, |
|---|
| 395 | + {0x5a, 0x80}, |
|---|
| 396 | + {0x5b, 0x80}, |
|---|
| 397 | + {0x5c, 0x00}, |
|---|
| 398 | + {0x5d, 0x00}, |
|---|
| 399 | + {0x5e, 0x00}, |
|---|
| 400 | + {0x5f, 0x00}, |
|---|
| 401 | + {0x6b, 0x01}, |
|---|
| 402 | + {0x6c, 0x00}, |
|---|
| 403 | + {0x6d, 0x0c}, |
|---|
| 404 | + |
|---|
| 405 | + /*WB offset*/ |
|---|
| 406 | + {0xfe, 0x01}, |
|---|
| 407 | + {0xbf, 0x40}, |
|---|
| 408 | + |
|---|
| 409 | + /*Dark Sun*/ |
|---|
| 410 | + {0xfe, 0x01}, |
|---|
| 411 | + {0x68, 0x77}, |
|---|
| 412 | + |
|---|
| 413 | + /*DPC*/ |
|---|
| 414 | + {0xfe, 0x01}, |
|---|
| 415 | + {0x60, 0x00}, |
|---|
| 416 | + {0x61, 0x10}, |
|---|
| 417 | + {0x62, 0x60}, |
|---|
| 418 | + {0x63, 0x30}, |
|---|
| 419 | + {0x64, 0x00}, |
|---|
| 420 | + |
|---|
| 421 | + /* LSC */ |
|---|
| 422 | + {0xfe, 0x01}, |
|---|
| 423 | + {0xa8, 0x60}, |
|---|
| 424 | + {0xa2, 0xd1}, |
|---|
| 425 | + {0xc8, 0x57}, |
|---|
| 426 | + {0xa1, 0xb8}, |
|---|
| 427 | + {0xa3, 0x91}, |
|---|
| 428 | + {0xc0, 0x50}, |
|---|
| 429 | + {0xd0, 0x05}, |
|---|
| 430 | + {0xd1, 0xb2}, |
|---|
| 431 | + {0xd2, 0x1f}, |
|---|
| 432 | + {0xd3, 0x00}, |
|---|
| 433 | + {0xd4, 0x00}, |
|---|
| 434 | + {0xd5, 0x00}, |
|---|
| 435 | + {0xd6, 0x00}, |
|---|
| 436 | + {0xd7, 0x00}, |
|---|
| 437 | + {0xd8, 0x00}, |
|---|
| 438 | + {0xd9, 0x00}, |
|---|
| 439 | + {0xa4, 0x10}, |
|---|
| 440 | + {0xa5, 0x20}, |
|---|
| 441 | + {0xa6, 0x60}, |
|---|
| 442 | + {0xa7, 0x80}, |
|---|
| 443 | + {0xab, 0x18}, |
|---|
| 444 | + {0xc7, 0xc0}, |
|---|
| 445 | + |
|---|
| 446 | + /*ABB*/ |
|---|
| 447 | + {0xfe, 0x01}, |
|---|
| 448 | + {0x20, 0x02}, |
|---|
| 449 | + {0x21, 0x02}, |
|---|
| 450 | + {0x23, 0x42}, |
|---|
| 451 | + |
|---|
| 452 | + /*MIPI*/ |
|---|
| 453 | + {0xfe, 0x03}, |
|---|
| 454 | + {0x01, 0x07}, |
|---|
| 455 | + {0x02, 0x04}, |
|---|
| 456 | + {0x04, 0x80}, |
|---|
| 457 | + {0x11, 0x2b}, |
|---|
| 458 | + {0x12, 0xf0}, //lwc 3264*5/4 |
|---|
| 459 | + {0x13, 0x0f}, |
|---|
| 460 | + {0x15, 0x10}, //LP |
|---|
| 461 | + {0x16, 0x29}, |
|---|
| 462 | + {0x17, 0xff}, |
|---|
| 463 | + {0x18, 0x01}, |
|---|
| 464 | + {0x19, 0xaa}, |
|---|
| 465 | + {0x1a, 0x02}, |
|---|
| 466 | + {0x21, 0x0c}, |
|---|
| 467 | + {0x22, 0x0e}, |
|---|
| 468 | + {0x23, 0x45}, |
|---|
| 469 | + {0x24, 0x01}, |
|---|
| 470 | + {0x25, 0x1c}, |
|---|
| 471 | + {0x26, 0x0b}, |
|---|
| 472 | + {0x29, 0x0e}, |
|---|
| 473 | + {0x2a, 0x1d}, |
|---|
| 474 | + {0x2b, 0x0b}, |
|---|
| 475 | + {0xfe, 0x00}, |
|---|
| 476 | + //{0x3f, 0x91}, |
|---|
| 477 | + {0x3f, 0x00}, |
|---|
| 478 | +#else |
|---|
| 247 | 479 | /*SYS*/ |
|---|
| 248 | 480 | {0xf2, 0x00}, |
|---|
| 249 | 481 | {0xf4, 0x80}, |
|---|
| .. | .. |
|---|
| 433 | 665 | {0xfe, 0x00}, |
|---|
| 434 | 666 | //{0x3f, 0x91}, |
|---|
| 435 | 667 | {0x3f, 0x00}, |
|---|
| 436 | | - |
|---|
| 668 | +#endif |
|---|
| 437 | 669 | {REG_NULL, 0x00}, |
|---|
| 438 | 670 | }; |
|---|
| 439 | 671 | |
|---|
| 672 | +#ifndef GC8034_2LANE_30FPS |
|---|
| 440 | 673 | /* |
|---|
| 441 | 674 | * Xclk 24Mhz |
|---|
| 442 | 675 | * max_framerate 30fps |
|---|
| .. | .. |
|---|
| 507 | 740 | |
|---|
| 508 | 741 | {REG_NULL, 0x00}, |
|---|
| 509 | 742 | }; |
|---|
| 743 | +#endif |
|---|
| 510 | 744 | |
|---|
| 511 | 745 | /* |
|---|
| 512 | 746 | * Xclk 24Mhz |
|---|
| .. | .. |
|---|
| 514 | 748 | * mipi_datarate per lane 672Mbps |
|---|
| 515 | 749 | */ |
|---|
| 516 | 750 | static const struct regval gc8034_3264x2448_regs_2lane[] = { |
|---|
| 751 | +#ifdef GC8034_2LANE_30FPS |
|---|
| 752 | + /* SYS */ |
|---|
| 753 | + {0xf2, 0x00}, |
|---|
| 754 | + {0xf4, 0x90}, |
|---|
| 755 | + {0xf5, 0x3d}, |
|---|
| 756 | + {0xf6, 0x44}, |
|---|
| 757 | + {0xf8, 0x63}, |
|---|
| 758 | + {0xfa, 0x42}, |
|---|
| 759 | + {0xf9, 0x00}, |
|---|
| 760 | + {0xf7, 0x95}, |
|---|
| 761 | + {0xfc, 0x00}, |
|---|
| 762 | + {0xfc, 0x00}, |
|---|
| 763 | + {0xfc, 0xea}, |
|---|
| 764 | + {0xfe, 0x03}, |
|---|
| 765 | + {0x03, 0x9a}, |
|---|
| 766 | + {0xfc, 0xee}, |
|---|
| 767 | + {0xfe, 0x00}, |
|---|
| 768 | + {0x3f, 0x00}, |
|---|
| 769 | + {0xfe, 0x10}, |
|---|
| 770 | + {0xfe, 0x00}, |
|---|
| 771 | + {0xfe, 0x10}, |
|---|
| 772 | + {0xfe, 0x00}, |
|---|
| 773 | + |
|---|
| 774 | + /* ISP */ |
|---|
| 775 | + {0xfe, 0x00}, |
|---|
| 776 | + {0x80, 0x13}, |
|---|
| 777 | + {0xad, 0x00}, |
|---|
| 778 | + {0x66, 0x0c}, |
|---|
| 779 | + {0xbc, 0x06}, |
|---|
| 780 | + |
|---|
| 781 | + /* Crop window */ |
|---|
| 782 | + {0x90, 0x01}, |
|---|
| 783 | + {0x92, FULL_STARTY}, |
|---|
| 784 | + {0x94, FULL_STARTX}, |
|---|
| 785 | + {0x95, 0x09}, |
|---|
| 786 | + {0x96, 0x90}, |
|---|
| 787 | + {0x97, 0x0c}, |
|---|
| 788 | + {0x98, 0xc0}, |
|---|
| 789 | + |
|---|
| 790 | + /* MIPI */ |
|---|
| 791 | + {0xfe, 0x03}, |
|---|
| 792 | + {0x01, 0x07}, |
|---|
| 793 | + {0x02, 0x04}, |
|---|
| 794 | + {0x04, 0x80}, |
|---|
| 795 | + {0x11, 0x2b}, |
|---|
| 796 | + {0x12, 0xf0}, //lwc 3264*5/4 |
|---|
| 797 | + {0x13, 0x0f}, |
|---|
| 798 | + {0x15, 0x10}, //LP |
|---|
| 799 | + {0x16, 0x29}, |
|---|
| 800 | + {0x17, 0xff}, |
|---|
| 801 | + {0x18, 0x01}, |
|---|
| 802 | + {0x19, 0xaa}, |
|---|
| 803 | + {0x1a, 0x02}, |
|---|
| 804 | + {0x21, 0x0c}, |
|---|
| 805 | + {0x22, 0x0c}, |
|---|
| 806 | + {0x23, 0x56}, |
|---|
| 807 | + {0x24, 0x00}, |
|---|
| 808 | + {0x25, 0x1c}, |
|---|
| 809 | + {0x26, 0x0b}, |
|---|
| 810 | + {0x29, 0x0e}, |
|---|
| 811 | + {0x2a, 0x1d}, |
|---|
| 812 | + {0x2b, 0x0b}, |
|---|
| 813 | + {0xfe, 0x00}, |
|---|
| 814 | + //{0x3f, 0x91}, |
|---|
| 815 | + {0x3f, 0x00}, |
|---|
| 816 | +#else |
|---|
| 517 | 817 | /*SYS*/ |
|---|
| 518 | 818 | {0xf2, 0x00}, |
|---|
| 519 | 819 | {0xf4, 0x80}, |
|---|
| .. | .. |
|---|
| 570 | 870 | {0xfe, 0x00}, |
|---|
| 571 | 871 | //{0x3f, 0x91}, |
|---|
| 572 | 872 | {0x3f, 0x00}, |
|---|
| 873 | +#endif |
|---|
| 573 | 874 | {REG_NULL, 0x00}, |
|---|
| 574 | 875 | }; |
|---|
| 575 | 876 | |
|---|
| .. | .. |
|---|
| 843 | 1144 | }; |
|---|
| 844 | 1145 | |
|---|
| 845 | 1146 | static const struct gc8034_mode supported_modes_2lane[] = { |
|---|
| 1147 | +#ifdef GC8034_2LANE_30FPS |
|---|
| 1148 | + { |
|---|
| 1149 | + .width = 3264, |
|---|
| 1150 | + .height = 2448, |
|---|
| 1151 | + .max_fps = { |
|---|
| 1152 | + .numerator = 10000, |
|---|
| 1153 | + .denominator = 300000, |
|---|
| 1154 | + }, |
|---|
| 1155 | + .exp_def = 0x0900, |
|---|
| 1156 | + .hts_def = 0x0858 * 2, |
|---|
| 1157 | + .vts_def = 0x09c0, |
|---|
| 1158 | + .mipi_freq_idx = 1, |
|---|
| 1159 | + .global_reg_list = gc8034_global_regs_2lane, |
|---|
| 1160 | + .reg_list = gc8034_3264x2448_regs_2lane, |
|---|
| 1161 | + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
|---|
| 1162 | + }, |
|---|
| 1163 | +#else |
|---|
| 846 | 1164 | { |
|---|
| 847 | 1165 | .width = 3264, |
|---|
| 848 | 1166 | .height = 2448, |
|---|
| .. | .. |
|---|
| 853 | 1171 | .exp_def = 0x09a0, |
|---|
| 854 | 1172 | .hts_def = 0x0858 * 2, |
|---|
| 855 | 1173 | .vts_def = 0x09c4, |
|---|
| 1174 | + .mipi_freq_idx = 0, |
|---|
| 1175 | + .global_reg_list = gc8034_global_regs_2lane, |
|---|
| 856 | 1176 | .reg_list = gc8034_3264x2448_regs_2lane, |
|---|
| 1177 | + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
|---|
| 857 | 1178 | }, |
|---|
| 858 | 1179 | { |
|---|
| 859 | 1180 | .width = 1632, |
|---|
| .. | .. |
|---|
| 865 | 1186 | .exp_def = 0x09a0, |
|---|
| 866 | 1187 | .hts_def = 0x0858 * 2, |
|---|
| 867 | 1188 | .vts_def = 0x09c4, |
|---|
| 1189 | + .mipi_freq_idx = 0, |
|---|
| 1190 | + .global_reg_list = gc8034_global_regs_2lane, |
|---|
| 868 | 1191 | .reg_list = gc8034_1632x1224_regs_2lane, |
|---|
| 1192 | + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
|---|
| 869 | 1193 | }, |
|---|
| 1194 | +#endif |
|---|
| 870 | 1195 | }; |
|---|
| 871 | 1196 | |
|---|
| 872 | 1197 | static const struct gc8034_mode supported_modes_4lane[] = { |
|---|
| .. | .. |
|---|
| 880 | 1205 | .exp_def = 0x08c6, |
|---|
| 881 | 1206 | .hts_def = 0x10b0, |
|---|
| 882 | 1207 | .vts_def = 0x09c0, |
|---|
| 1208 | + .mipi_freq_idx = 0, |
|---|
| 1209 | + .global_reg_list = gc8034_global_regs_4lane, |
|---|
| 883 | 1210 | .reg_list = gc8034_3264x2448_regs_4lane, |
|---|
| 1211 | + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, |
|---|
| 884 | 1212 | }, |
|---|
| 885 | 1213 | }; |
|---|
| 886 | 1214 | |
|---|
| .. | .. |
|---|
| 888 | 1216 | |
|---|
| 889 | 1217 | static const s64 link_freq_menu_items[] = { |
|---|
| 890 | 1218 | GC8034_MIPI_FREQ_336MHZ, |
|---|
| 1219 | + GC8034_MIPI_FREQ_634MHZ |
|---|
| 891 | 1220 | }; |
|---|
| 892 | 1221 | |
|---|
| 893 | 1222 | /* Write registers up to 4 at a time */ |
|---|
| .. | .. |
|---|
| 1017 | 1346 | __v4l2_ctrl_modify_range(gc8034->vblank, vblank_def, |
|---|
| 1018 | 1347 | GC8034_VTS_MAX - mode->height, |
|---|
| 1019 | 1348 | 1, vblank_def); |
|---|
| 1020 | | - __v4l2_ctrl_s_ctrl(gc8034->link_freq, |
|---|
| 1021 | | - link_freq_menu_items[0]); |
|---|
| 1349 | + __v4l2_ctrl_s_ctrl(gc8034->vblank, vblank_def); |
|---|
| 1350 | + __v4l2_ctrl_s_ctrl(gc8034->link_freq, mode->mipi_freq_idx); |
|---|
| 1022 | 1351 | } |
|---|
| 1023 | 1352 | |
|---|
| 1024 | 1353 | mutex_unlock(&gc8034->mutex); |
|---|
| .. | .. |
|---|
| 1089 | 1418 | struct gc8034 *gc8034 = to_gc8034(sd); |
|---|
| 1090 | 1419 | const struct gc8034_mode *mode = gc8034->cur_mode; |
|---|
| 1091 | 1420 | |
|---|
| 1092 | | - mutex_lock(&gc8034->mutex); |
|---|
| 1093 | 1421 | fi->interval = mode->max_fps; |
|---|
| 1094 | | - mutex_unlock(&gc8034->mutex); |
|---|
| 1095 | 1422 | |
|---|
| 1096 | 1423 | return 0; |
|---|
| 1097 | 1424 | } |
|---|
| 1098 | 1425 | |
|---|
| 1426 | +#ifdef RK_OTP |
|---|
| 1427 | +static void gc8034_get_otp(struct otp_info *otp, |
|---|
| 1428 | + struct rkmodule_inf *inf) |
|---|
| 1429 | +{ |
|---|
| 1430 | + u32 i, j; |
|---|
| 1431 | + u32 w, h; |
|---|
| 1432 | + |
|---|
| 1433 | + /* awb */ |
|---|
| 1434 | + if (otp->awb_data.flag) { |
|---|
| 1435 | + inf->awb.flag = 1; |
|---|
| 1436 | + inf->awb.r_value = otp->awb_data.r_ratio; |
|---|
| 1437 | + inf->awb.b_value = otp->awb_data.b_ratio; |
|---|
| 1438 | + inf->awb.gr_value = otp->awb_data.g_ratio; |
|---|
| 1439 | + inf->awb.gb_value = 0x0; |
|---|
| 1440 | + |
|---|
| 1441 | + inf->awb.golden_r_value = otp->awb_data.r_golden; |
|---|
| 1442 | + inf->awb.golden_b_value = otp->awb_data.b_golden; |
|---|
| 1443 | + inf->awb.golden_gr_value = otp->awb_data.g_golden; |
|---|
| 1444 | + inf->awb.golden_gb_value = 0x0; |
|---|
| 1445 | + } |
|---|
| 1446 | + |
|---|
| 1447 | + /* lsc */ |
|---|
| 1448 | + if (otp->lsc_data.flag) { |
|---|
| 1449 | + inf->lsc.flag = 1; |
|---|
| 1450 | + inf->lsc.width = otp->basic_data.size.width; |
|---|
| 1451 | + inf->lsc.height = otp->basic_data.size.height; |
|---|
| 1452 | + inf->lsc.table_size = otp->lsc_data.table_size; |
|---|
| 1453 | + |
|---|
| 1454 | + for (i = 0; i < 289; i++) { |
|---|
| 1455 | + inf->lsc.lsc_r[i] = (otp->lsc_data.data[i * 2] << 8) | |
|---|
| 1456 | + otp->lsc_data.data[i * 2 + 1]; |
|---|
| 1457 | + inf->lsc.lsc_gr[i] = (otp->lsc_data.data[i * 2 + 578] << 8) | |
|---|
| 1458 | + otp->lsc_data.data[i * 2 + 579]; |
|---|
| 1459 | + inf->lsc.lsc_gb[i] = (otp->lsc_data.data[i * 2 + 1156] << 8) | |
|---|
| 1460 | + otp->lsc_data.data[i * 2 + 1157]; |
|---|
| 1461 | + inf->lsc.lsc_b[i] = (otp->lsc_data.data[i * 2 + 1734] << 8) | |
|---|
| 1462 | + otp->lsc_data.data[i * 2 + 1735]; |
|---|
| 1463 | + } |
|---|
| 1464 | + } |
|---|
| 1465 | + |
|---|
| 1466 | + /* pdaf */ |
|---|
| 1467 | + if (otp->pdaf_data.flag) { |
|---|
| 1468 | + inf->pdaf.flag = 1; |
|---|
| 1469 | + inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width; |
|---|
| 1470 | + inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height; |
|---|
| 1471 | + inf->pdaf.pd_offset = otp->pdaf_data.pd_offset; |
|---|
| 1472 | + inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode; |
|---|
| 1473 | + inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir; |
|---|
| 1474 | + inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width; |
|---|
| 1475 | + inf->pdaf.dccmap_height = otp->pdaf_data.dccmap_height; |
|---|
| 1476 | + w = otp->pdaf_data.gainmap_width; |
|---|
| 1477 | + h = otp->pdaf_data.gainmap_height; |
|---|
| 1478 | + for (i = 0; i < h; i++) { |
|---|
| 1479 | + for (j = 0; j < w; j++) { |
|---|
| 1480 | + inf->pdaf.gainmap[i * w + j] = |
|---|
| 1481 | + (otp->pdaf_data.gainmap[(i * w + j) * 2] << 8) | |
|---|
| 1482 | + otp->pdaf_data.gainmap[(i * w + j) * 2 + 1]; |
|---|
| 1483 | + } |
|---|
| 1484 | + } |
|---|
| 1485 | + w = otp->pdaf_data.dccmap_width; |
|---|
| 1486 | + h = otp->pdaf_data.dccmap_height; |
|---|
| 1487 | + for (i = 0; i < h; i++) { |
|---|
| 1488 | + for (j = 0; j < w; j++) { |
|---|
| 1489 | + inf->pdaf.dccmap[i * w + j] = |
|---|
| 1490 | + (otp->pdaf_data.dccmap[(i * w + j) * 2] << 8) | |
|---|
| 1491 | + otp->pdaf_data.dccmap[(i * w + j) * 2 + 1]; |
|---|
| 1492 | + } |
|---|
| 1493 | + } |
|---|
| 1494 | + } |
|---|
| 1495 | + |
|---|
| 1496 | + /* af */ |
|---|
| 1497 | + if (otp->af_data.flag) { |
|---|
| 1498 | + inf->af.flag = 1; |
|---|
| 1499 | + inf->af.dir_cnt = 1; |
|---|
| 1500 | + inf->af.af_otp[0].vcm_start = otp->af_data.af_inf; |
|---|
| 1501 | + inf->af.af_otp[0].vcm_end = otp->af_data.af_macro; |
|---|
| 1502 | + inf->af.af_otp[0].vcm_dir = 0; |
|---|
| 1503 | + } |
|---|
| 1504 | + |
|---|
| 1505 | +} |
|---|
| 1506 | +#else |
|---|
| 1099 | 1507 | #define DD_WIDTH 3284 |
|---|
| 1100 | 1508 | #define DD_HEIGHT 2464 |
|---|
| 1101 | 1509 | |
|---|
| .. | .. |
|---|
| 1605 | 2013 | inf->af.af_otp[0].vcm_dir = otp->vcm_dir; |
|---|
| 1606 | 2014 | } |
|---|
| 1607 | 2015 | } |
|---|
| 2016 | +#endif |
|---|
| 1608 | 2017 | |
|---|
| 1609 | 2018 | static void gc8034_get_module_inf(struct gc8034 *gc8034, |
|---|
| 1610 | 2019 | struct rkmodule_inf *inf) |
|---|
| 1611 | 2020 | { |
|---|
| 2021 | +#ifdef RK_OTP |
|---|
| 2022 | + struct otp_info *otp = gc8034->otp; |
|---|
| 2023 | +#else |
|---|
| 1612 | 2024 | struct gc8034_otp_info *otp = gc8034->otp; |
|---|
| 2025 | +#endif |
|---|
| 1613 | 2026 | |
|---|
| 1614 | 2027 | strlcpy(inf->base.sensor, |
|---|
| 1615 | 2028 | GC8034_NAME, |
|---|
| .. | .. |
|---|
| 1632 | 2045 | mutex_unlock(&gc8034->mutex); |
|---|
| 1633 | 2046 | } |
|---|
| 1634 | 2047 | |
|---|
| 2048 | +static int gc8034_get_channel_info(struct gc8034 *gc8034, struct rkmodule_channel_info *ch_info) |
|---|
| 2049 | +{ |
|---|
| 2050 | + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) |
|---|
| 2051 | + return -EINVAL; |
|---|
| 2052 | + ch_info->vc = gc8034->cur_mode->vc[ch_info->index]; |
|---|
| 2053 | + ch_info->width = gc8034->cur_mode->width; |
|---|
| 2054 | + ch_info->height = gc8034->cur_mode->height; |
|---|
| 2055 | + ch_info->bus_fmt = GC8034_MEDIA_BUS_FMT; |
|---|
| 2056 | + return 0; |
|---|
| 2057 | +} |
|---|
| 2058 | + |
|---|
| 1635 | 2059 | static long gc8034_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
|---|
| 1636 | 2060 | { |
|---|
| 1637 | 2061 | struct gc8034 *gc8034 = to_gc8034(sd); |
|---|
| 1638 | 2062 | long ret = 0; |
|---|
| 1639 | 2063 | u32 stream = 0; |
|---|
| 2064 | + struct rkmodule_channel_info *ch_info; |
|---|
| 1640 | 2065 | |
|---|
| 1641 | 2066 | switch (cmd) { |
|---|
| 1642 | 2067 | case RKMODULE_GET_MODULE_INFO: |
|---|
| .. | .. |
|---|
| 1671 | 2096 | GC8034_MODE_SW_STANDBY); |
|---|
| 1672 | 2097 | } |
|---|
| 1673 | 2098 | break; |
|---|
| 2099 | + case RKMODULE_GET_CHANNEL_INFO: |
|---|
| 2100 | + ch_info = (struct rkmodule_channel_info *)arg; |
|---|
| 2101 | + ret = gc8034_get_channel_info(gc8034, ch_info); |
|---|
| 2102 | + break; |
|---|
| 1674 | 2103 | default: |
|---|
| 1675 | 2104 | ret = -ENOTTY; |
|---|
| 1676 | 2105 | break; |
|---|
| .. | .. |
|---|
| 1688 | 2117 | struct rkmodule_awb_cfg *cfg; |
|---|
| 1689 | 2118 | long ret = 0; |
|---|
| 1690 | 2119 | u32 stream = 0; |
|---|
| 2120 | + struct rkmodule_channel_info *ch_info; |
|---|
| 1691 | 2121 | |
|---|
| 1692 | 2122 | switch (cmd) { |
|---|
| 1693 | 2123 | case RKMODULE_GET_MODULE_INFO: |
|---|
| .. | .. |
|---|
| 1698 | 2128 | } |
|---|
| 1699 | 2129 | |
|---|
| 1700 | 2130 | ret = gc8034_ioctl(sd, cmd, inf); |
|---|
| 1701 | | - if (!ret) |
|---|
| 2131 | + if (!ret) { |
|---|
| 1702 | 2132 | ret = copy_to_user(up, inf, sizeof(*inf)); |
|---|
| 2133 | + if (ret) |
|---|
| 2134 | + ret = -EFAULT; |
|---|
| 2135 | + } |
|---|
| 1703 | 2136 | kfree(inf); |
|---|
| 1704 | 2137 | break; |
|---|
| 1705 | 2138 | case RKMODULE_AWB_CFG: |
|---|
| .. | .. |
|---|
| 1712 | 2145 | ret = copy_from_user(cfg, up, sizeof(*cfg)); |
|---|
| 1713 | 2146 | if (!ret) |
|---|
| 1714 | 2147 | ret = gc8034_ioctl(sd, cmd, cfg); |
|---|
| 2148 | + else |
|---|
| 2149 | + ret = -EFAULT; |
|---|
| 1715 | 2150 | kfree(cfg); |
|---|
| 1716 | 2151 | break; |
|---|
| 1717 | 2152 | case RKMODULE_SET_QUICK_STREAM: |
|---|
| 1718 | 2153 | ret = copy_from_user(&stream, up, sizeof(u32)); |
|---|
| 1719 | 2154 | if (!ret) |
|---|
| 1720 | 2155 | ret = gc8034_ioctl(sd, cmd, &stream); |
|---|
| 2156 | + else |
|---|
| 2157 | + ret = -EFAULT; |
|---|
| 2158 | + break; |
|---|
| 2159 | + case RKMODULE_GET_CHANNEL_INFO: |
|---|
| 2160 | + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); |
|---|
| 2161 | + if (!ch_info) { |
|---|
| 2162 | + ret = -ENOMEM; |
|---|
| 2163 | + return ret; |
|---|
| 2164 | + } |
|---|
| 2165 | + |
|---|
| 2166 | + ret = gc8034_ioctl(sd, cmd, ch_info); |
|---|
| 2167 | + if (!ret) { |
|---|
| 2168 | + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); |
|---|
| 2169 | + if (ret) |
|---|
| 2170 | + ret = -EFAULT; |
|---|
| 2171 | + } |
|---|
| 2172 | + kfree(ch_info); |
|---|
| 1721 | 2173 | break; |
|---|
| 1722 | 2174 | default: |
|---|
| 1723 | 2175 | ret = -ENOTTY; |
|---|
| .. | .. |
|---|
| 1728 | 2180 | } |
|---|
| 1729 | 2181 | #endif |
|---|
| 1730 | 2182 | |
|---|
| 2183 | +#ifndef RK_OTP |
|---|
| 1731 | 2184 | /*--------------------------------------------------------------------------*/ |
|---|
| 1732 | 2185 | static int gc8034_apply_otp(struct gc8034 *gc8034) |
|---|
| 1733 | 2186 | { |
|---|
| .. | .. |
|---|
| 1908 | 2361 | } |
|---|
| 1909 | 2362 | return 0; |
|---|
| 1910 | 2363 | } |
|---|
| 2364 | +#endif |
|---|
| 1911 | 2365 | |
|---|
| 1912 | 2366 | static int __gc8034_start_stream(struct gc8034 *gc8034) |
|---|
| 1913 | 2367 | { |
|---|
| 1914 | 2368 | int ret; |
|---|
| 1915 | | - |
|---|
| 2369 | +#ifndef RK_OTP |
|---|
| 1916 | 2370 | if (gc8034->otp) { |
|---|
| 1917 | 2371 | ret = gc8034_otp_enable(gc8034); |
|---|
| 1918 | 2372 | gc8034_check_prsel(gc8034); |
|---|
| .. | .. |
|---|
| 1922 | 2376 | if (ret) |
|---|
| 1923 | 2377 | return ret; |
|---|
| 1924 | 2378 | } |
|---|
| 2379 | +#endif |
|---|
| 1925 | 2380 | ret = gc8034_write_array(gc8034->client, gc8034->cur_mode->reg_list); |
|---|
| 1926 | 2381 | if (ret) |
|---|
| 1927 | 2382 | return ret; |
|---|
| .. | .. |
|---|
| 2006 | 2461 | { |
|---|
| 2007 | 2462 | struct gc8034 *gc8034 = to_gc8034(sd); |
|---|
| 2008 | 2463 | struct i2c_client *client = gc8034->client; |
|---|
| 2464 | + const struct gc8034_mode *mode = gc8034->cur_mode; |
|---|
| 2009 | 2465 | int ret = 0; |
|---|
| 2010 | 2466 | |
|---|
| 2011 | 2467 | dev_info(&client->dev, "%s(%d) on(%d)\n", __func__, __LINE__, on); |
|---|
| .. | .. |
|---|
| 2022 | 2478 | goto unlock_and_return; |
|---|
| 2023 | 2479 | } |
|---|
| 2024 | 2480 | |
|---|
| 2025 | | - ret = gc8034_write_array(gc8034->client, gc8034_global_regs); |
|---|
| 2481 | + ret = gc8034_write_array(gc8034->client, mode->global_reg_list); |
|---|
| 2026 | 2482 | if (ret) { |
|---|
| 2027 | 2483 | v4l2_err(sd, "could not set init registers\n"); |
|---|
| 2028 | 2484 | pm_runtime_put_noidle(&client->dev); |
|---|
| .. | .. |
|---|
| 2047 | 2503 | return DIV_ROUND_UP(cycles, GC8034_XVCLK_FREQ / 1000 / 1000); |
|---|
| 2048 | 2504 | } |
|---|
| 2049 | 2505 | |
|---|
| 2506 | +static int gc8034_enable_regulators(struct gc8034 *gc8034, |
|---|
| 2507 | + struct regulator_bulk_data *consumers) |
|---|
| 2508 | +{ |
|---|
| 2509 | + int i, j; |
|---|
| 2510 | + int ret = 0; |
|---|
| 2511 | + struct device *dev = &gc8034->client->dev; |
|---|
| 2512 | + int num_consumers = GC8034_NUM_SUPPLIES; |
|---|
| 2513 | + |
|---|
| 2514 | + for (i = 0; i < num_consumers; i++) { |
|---|
| 2515 | + |
|---|
| 2516 | + ret = regulator_enable(consumers[i].consumer); |
|---|
| 2517 | + if (ret < 0) { |
|---|
| 2518 | + dev_err(dev, "Failed to enable regulator: %s\n", |
|---|
| 2519 | + consumers[i].supply); |
|---|
| 2520 | + goto err; |
|---|
| 2521 | + } |
|---|
| 2522 | + } |
|---|
| 2523 | + return 0; |
|---|
| 2524 | +err: |
|---|
| 2525 | + for (j = 0; j < i; j++) |
|---|
| 2526 | + regulator_disable(consumers[j].consumer); |
|---|
| 2527 | + |
|---|
| 2528 | + return ret; |
|---|
| 2529 | +} |
|---|
| 2530 | + |
|---|
| 2050 | 2531 | static int __gc8034_power_on(struct gc8034 *gc8034) |
|---|
| 2051 | 2532 | { |
|---|
| 2052 | 2533 | int ret; |
|---|
| .. | .. |
|---|
| 2069 | 2550 | dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); |
|---|
| 2070 | 2551 | if (clk_get_rate(gc8034->xvclk) != GC8034_XVCLK_FREQ) |
|---|
| 2071 | 2552 | dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); |
|---|
| 2072 | | - ret = clk_prepare_enable(gc8034->xvclk); |
|---|
| 2073 | | - if (ret < 0) { |
|---|
| 2074 | | - dev_err(dev, "Failed to enable xvclk\n"); |
|---|
| 2075 | | - return ret; |
|---|
| 2076 | | - } |
|---|
| 2553 | + |
|---|
| 2077 | 2554 | if (!IS_ERR(gc8034->reset_gpio)) |
|---|
| 2078 | 2555 | gpiod_set_value_cansleep(gc8034->reset_gpio, 1); |
|---|
| 2079 | 2556 | |
|---|
| 2080 | | - ret = regulator_bulk_enable(GC8034_NUM_SUPPLIES, gc8034->supplies); |
|---|
| 2557 | + ret = gc8034_enable_regulators(gc8034, gc8034->supplies); |
|---|
| 2081 | 2558 | if (ret < 0) { |
|---|
| 2082 | 2559 | dev_err(dev, "Failed to enable regulators\n"); |
|---|
| 2083 | 2560 | goto disable_clk; |
|---|
| 2084 | 2561 | } |
|---|
| 2085 | 2562 | |
|---|
| 2563 | + usleep_range(100, 200); |
|---|
| 2564 | + ret = clk_prepare_enable(gc8034->xvclk); |
|---|
| 2565 | + if (ret < 0) { |
|---|
| 2566 | + dev_err(dev, "Failed to enable xvclk\n"); |
|---|
| 2567 | + return ret; |
|---|
| 2568 | + } |
|---|
| 2569 | + |
|---|
| 2086 | 2570 | usleep_range(1000, 1100); |
|---|
| 2571 | + if (!IS_ERR(gc8034->pwdn_gpio)) |
|---|
| 2572 | + gpiod_set_value_cansleep(gc8034->pwdn_gpio, 0); |
|---|
| 2573 | + |
|---|
| 2574 | + usleep_range(500, 1000); |
|---|
| 2087 | 2575 | if (!IS_ERR(gc8034->reset_gpio)) |
|---|
| 2088 | 2576 | gpiod_set_value_cansleep(gc8034->reset_gpio, 0); |
|---|
| 2089 | 2577 | |
|---|
| 2090 | | - usleep_range(500, 1000); |
|---|
| 2091 | | - if (!IS_ERR(gc8034->pwdn_gpio)) |
|---|
| 2092 | | - gpiod_set_value_cansleep(gc8034->pwdn_gpio, 0); |
|---|
| 2578 | + usleep_range(6000, 7000); |
|---|
| 2093 | 2579 | |
|---|
| 2094 | 2580 | /* 8192 cycles prior to first SCCB transaction */ |
|---|
| 2095 | 2581 | delay_us = gc8034_cal_delay(8192); |
|---|
| .. | .. |
|---|
| 2109 | 2595 | |
|---|
| 2110 | 2596 | if (!IS_ERR(gc8034->pwdn_gpio)) |
|---|
| 2111 | 2597 | gpiod_set_value_cansleep(gc8034->pwdn_gpio, 1); |
|---|
| 2112 | | - clk_disable_unprepare(gc8034->xvclk); |
|---|
| 2598 | + |
|---|
| 2113 | 2599 | if (!IS_ERR(gc8034->reset_gpio)) |
|---|
| 2114 | 2600 | gpiod_set_value_cansleep(gc8034->reset_gpio, 1); |
|---|
| 2601 | + |
|---|
| 2602 | + clk_disable_unprepare(gc8034->xvclk); |
|---|
| 2115 | 2603 | if (!IS_ERR_OR_NULL(gc8034->pins_sleep)) { |
|---|
| 2116 | 2604 | ret = pinctrl_select_state(gc8034->pinctrl, |
|---|
| 2117 | 2605 | gc8034->pins_sleep); |
|---|
| .. | .. |
|---|
| 2124 | 2612 | regulator_bulk_disable(GC8034_NUM_SUPPLIES, gc8034->supplies); |
|---|
| 2125 | 2613 | } |
|---|
| 2126 | 2614 | |
|---|
| 2127 | | -static int gc8034_runtime_resume(struct device *dev) |
|---|
| 2615 | +static int __maybe_unused gc8034_runtime_resume(struct device *dev) |
|---|
| 2128 | 2616 | { |
|---|
| 2129 | 2617 | struct i2c_client *client = to_i2c_client(dev); |
|---|
| 2130 | 2618 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
|---|
| .. | .. |
|---|
| 2133 | 2621 | return __gc8034_power_on(gc8034); |
|---|
| 2134 | 2622 | } |
|---|
| 2135 | 2623 | |
|---|
| 2136 | | -static int gc8034_runtime_suspend(struct device *dev) |
|---|
| 2624 | +static int __maybe_unused gc8034_runtime_suspend(struct device *dev) |
|---|
| 2137 | 2625 | { |
|---|
| 2138 | 2626 | struct i2c_client *client = to_i2c_client(dev); |
|---|
| 2139 | 2627 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
|---|
| .. | .. |
|---|
| 2175 | 2663 | if (fie->index >= gc8034->cfg_num) |
|---|
| 2176 | 2664 | return -EINVAL; |
|---|
| 2177 | 2665 | |
|---|
| 2178 | | - if (fie->code != GC8034_MEDIA_BUS_FMT) |
|---|
| 2179 | | - return -EINVAL; |
|---|
| 2180 | | - |
|---|
| 2666 | + fie->code = GC8034_MEDIA_BUS_FMT; |
|---|
| 2181 | 2667 | fie->width = supported_modes[fie->index].width; |
|---|
| 2182 | 2668 | fie->height = supported_modes[fie->index].height; |
|---|
| 2183 | 2669 | fie->interval = supported_modes[fie->index].max_fps; |
|---|
| 2184 | 2670 | return 0; |
|---|
| 2185 | 2671 | } |
|---|
| 2186 | 2672 | |
|---|
| 2187 | | -static int gc8034_g_mbus_config(struct v4l2_subdev *sd, |
|---|
| 2673 | +static int gc8034_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
|---|
| 2188 | 2674 | struct v4l2_mbus_config *config) |
|---|
| 2189 | 2675 | { |
|---|
| 2190 | 2676 | struct gc8034 *sensor = to_gc8034(sd); |
|---|
| .. | .. |
|---|
| 2193 | 2679 | dev_info(dev, "%s(%d) enter!\n", __func__, __LINE__); |
|---|
| 2194 | 2680 | |
|---|
| 2195 | 2681 | if (2 == sensor->lane_num) { |
|---|
| 2196 | | - config->type = V4L2_MBUS_CSI2; |
|---|
| 2682 | + config->type = V4L2_MBUS_CSI2_DPHY; |
|---|
| 2197 | 2683 | config->flags = V4L2_MBUS_CSI2_2_LANE | |
|---|
| 2198 | 2684 | V4L2_MBUS_CSI2_CHANNEL_0 | |
|---|
| 2199 | 2685 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
|---|
| 2200 | 2686 | } else if (4 == sensor->lane_num) { |
|---|
| 2201 | | - config->type = V4L2_MBUS_CSI2; |
|---|
| 2687 | + config->type = V4L2_MBUS_CSI2_DPHY; |
|---|
| 2202 | 2688 | config->flags = V4L2_MBUS_CSI2_4_LANE | |
|---|
| 2203 | 2689 | V4L2_MBUS_CSI2_CHANNEL_0 | |
|---|
| 2204 | 2690 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
|---|
| .. | .. |
|---|
| 2231 | 2717 | static const struct v4l2_subdev_video_ops gc8034_video_ops = { |
|---|
| 2232 | 2718 | .s_stream = gc8034_s_stream, |
|---|
| 2233 | 2719 | .g_frame_interval = gc8034_g_frame_interval, |
|---|
| 2234 | | - .g_mbus_config = gc8034_g_mbus_config, |
|---|
| 2235 | 2720 | }; |
|---|
| 2236 | 2721 | |
|---|
| 2237 | 2722 | static const struct v4l2_subdev_pad_ops gc8034_pad_ops = { |
|---|
| .. | .. |
|---|
| 2240 | 2725 | .enum_frame_interval = gc8034_enum_frame_interval, |
|---|
| 2241 | 2726 | .get_fmt = gc8034_get_fmt, |
|---|
| 2242 | 2727 | .set_fmt = gc8034_set_fmt, |
|---|
| 2728 | + .get_mbus_config = gc8034_g_mbus_config, |
|---|
| 2243 | 2729 | }; |
|---|
| 2244 | 2730 | |
|---|
| 2245 | 2731 | static const struct v4l2_subdev_ops gc8034_subdev_ops = { |
|---|
| .. | .. |
|---|
| 2388 | 2874 | switch (ctrl->id) { |
|---|
| 2389 | 2875 | case V4L2_CID_EXPOSURE: |
|---|
| 2390 | 2876 | /* 4 least significant bits of expsoure are fractional part */ |
|---|
| 2391 | | - dev_info(&client->dev, "set exposure value 0x%x\n", ctrl->val); |
|---|
| 2877 | + dev_dbg(&client->dev, "set exposure value 0x%x\n", ctrl->val); |
|---|
| 2392 | 2878 | ret = gc8034_set_exposure_reg(gc8034, ctrl->val); |
|---|
| 2393 | 2879 | break; |
|---|
| 2394 | 2880 | case V4L2_CID_ANALOGUE_GAIN: |
|---|
| 2395 | | - dev_info(&client->dev, "set analog gain value 0x%x\n", ctrl->val); |
|---|
| 2881 | + dev_dbg(&client->dev, "set analog gain value 0x%x\n", ctrl->val); |
|---|
| 2396 | 2882 | ret = gc8034_set_gain_reg(gc8034, ctrl->val); |
|---|
| 2397 | 2883 | break; |
|---|
| 2398 | 2884 | case V4L2_CID_VBLANK: |
|---|
| 2399 | | - dev_info(&client->dev, "set vb value 0x%x\n", ctrl->val); |
|---|
| 2885 | + dev_dbg(&client->dev, "set vb value 0x%x\n", ctrl->val); |
|---|
| 2400 | 2886 | /* VB = VTS - 2448 -36, according android8.1 driver */ |
|---|
| 2401 | 2887 | temp = ctrl->val + gc8034->cur_mode->height - 2448 - 36; |
|---|
| 2402 | 2888 | ret = gc8034_write_reg(gc8034->client, |
|---|
| .. | .. |
|---|
| 2440 | 2926 | handler->lock = &gc8034->mutex; |
|---|
| 2441 | 2927 | |
|---|
| 2442 | 2928 | gc8034->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, |
|---|
| 2443 | | - V4L2_CID_LINK_FREQ, 0, 0, |
|---|
| 2929 | + V4L2_CID_LINK_FREQ, |
|---|
| 2930 | + ARRAY_SIZE(link_freq_menu_items) - 1, 0, |
|---|
| 2444 | 2931 | link_freq_menu_items); |
|---|
| 2932 | + v4l2_ctrl_s_ctrl(gc8034->link_freq, mode->mipi_freq_idx); |
|---|
| 2445 | 2933 | |
|---|
| 2446 | 2934 | v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, |
|---|
| 2447 | 2935 | 0, gc8034->pixel_rate, 1, gc8034->pixel_rate); |
|---|
| .. | .. |
|---|
| 2542 | 3030 | gc8034->cur_mode = &supported_modes_4lane[0]; |
|---|
| 2543 | 3031 | supported_modes = supported_modes_4lane; |
|---|
| 2544 | 3032 | gc8034->cfg_num = ARRAY_SIZE(supported_modes_4lane); |
|---|
| 2545 | | - gc8034_global_regs = gc8034_global_regs_4lane; |
|---|
| 2546 | 3033 | /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ |
|---|
| 2547 | 3034 | fps = DIV_ROUND_CLOSEST(gc8034->cur_mode->max_fps.denominator, |
|---|
| 2548 | 3035 | gc8034->cur_mode->max_fps.numerator); |
|---|
| .. | .. |
|---|
| 2555 | 3042 | gc8034->cur_mode = &supported_modes_2lane[0]; |
|---|
| 2556 | 3043 | supported_modes = supported_modes_2lane; |
|---|
| 2557 | 3044 | gc8034->cfg_num = ARRAY_SIZE(supported_modes_2lane); |
|---|
| 2558 | | - gc8034_global_regs = gc8034_global_regs_2lane; |
|---|
| 2559 | 3045 | /*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ |
|---|
| 2560 | 3046 | fps = DIV_ROUND_CLOSEST(gc8034->cur_mode->max_fps.denominator, |
|---|
| 2561 | 3047 | gc8034->cur_mode->max_fps.numerator); |
|---|
| .. | .. |
|---|
| 2580 | 3066 | struct v4l2_subdev *sd; |
|---|
| 2581 | 3067 | char facing[2]; |
|---|
| 2582 | 3068 | int ret; |
|---|
| 3069 | + struct device_node *eeprom_ctrl_node; |
|---|
| 3070 | + struct i2c_client *eeprom_ctrl_client; |
|---|
| 3071 | + struct v4l2_subdev *eeprom_ctrl; |
|---|
| 3072 | + struct otp_info *otp_ptr; |
|---|
| 2583 | 3073 | |
|---|
| 2584 | 3074 | dev_info(dev, "driver version: %02x.%02x.%02x", |
|---|
| 2585 | 3075 | DRIVER_VERSION >> 16, |
|---|
| .. | .. |
|---|
| 2661 | 3151 | ret = gc8034_check_sensor_id(gc8034, client); |
|---|
| 2662 | 3152 | if (ret) |
|---|
| 2663 | 3153 | goto err_power_off; |
|---|
| 2664 | | - |
|---|
| 3154 | +#ifdef RK_OTP |
|---|
| 3155 | + eeprom_ctrl_node = of_parse_phandle(node, "eeprom-ctrl", 0); |
|---|
| 3156 | + if (eeprom_ctrl_node) { |
|---|
| 3157 | + eeprom_ctrl_client = |
|---|
| 3158 | + of_find_i2c_device_by_node(eeprom_ctrl_node); |
|---|
| 3159 | + of_node_put(eeprom_ctrl_node); |
|---|
| 3160 | + if (IS_ERR_OR_NULL(eeprom_ctrl_client)) { |
|---|
| 3161 | + dev_err(dev, "can not get node\n"); |
|---|
| 3162 | + goto continue_probe; |
|---|
| 3163 | + } |
|---|
| 3164 | + eeprom_ctrl = i2c_get_clientdata(eeprom_ctrl_client); |
|---|
| 3165 | + if (IS_ERR_OR_NULL(eeprom_ctrl)) { |
|---|
| 3166 | + dev_err(dev, "can not get eeprom i2c client\n"); |
|---|
| 3167 | + } else { |
|---|
| 3168 | + otp_ptr = devm_kzalloc(dev, sizeof(*otp_ptr), GFP_KERNEL); |
|---|
| 3169 | + if (!otp_ptr) |
|---|
| 3170 | + return -ENOMEM; |
|---|
| 3171 | + ret = v4l2_subdev_call(eeprom_ctrl, |
|---|
| 3172 | + core, ioctl, 0, otp_ptr); |
|---|
| 3173 | + if (!ret) { |
|---|
| 3174 | + gc8034->otp = otp_ptr; |
|---|
| 3175 | + } else { |
|---|
| 3176 | + gc8034->otp = NULL; |
|---|
| 3177 | + devm_kfree(dev, otp_ptr); |
|---|
| 3178 | + dev_warn(dev, "can not get otp info, skip!\n"); |
|---|
| 3179 | + } |
|---|
| 3180 | + } |
|---|
| 3181 | + } |
|---|
| 3182 | +continue_probe: |
|---|
| 3183 | +#else |
|---|
| 2665 | 3184 | gc8034_otp_enable(gc8034); |
|---|
| 2666 | 3185 | gc8034_otp_read(gc8034); |
|---|
| 2667 | 3186 | gc8034_otp_disable(gc8034); |
|---|
| 3187 | +#endif |
|---|
| 2668 | 3188 | |
|---|
| 2669 | 3189 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API |
|---|
| 2670 | 3190 | sd->internal_ops = &gc8034_internal_ops; |
|---|