| .. | .. |
|---|
| 85 | 85 | |
|---|
| 86 | 86 | struct ov2680_ctrls { |
|---|
| 87 | 87 | struct v4l2_ctrl_handler handler; |
|---|
| 88 | | - struct { |
|---|
| 89 | | - struct v4l2_ctrl *auto_exp; |
|---|
| 90 | | - struct v4l2_ctrl *exposure; |
|---|
| 91 | | - }; |
|---|
| 92 | | - struct { |
|---|
| 93 | | - struct v4l2_ctrl *auto_gain; |
|---|
| 94 | | - struct v4l2_ctrl *gain; |
|---|
| 95 | | - }; |
|---|
| 96 | | - |
|---|
| 88 | + struct v4l2_ctrl *exposure; |
|---|
| 89 | + struct v4l2_ctrl *gain; |
|---|
| 97 | 90 | struct v4l2_ctrl *hflip; |
|---|
| 98 | 91 | struct v4l2_ctrl *vflip; |
|---|
| 99 | 92 | struct v4l2_ctrl *test_pattern; |
|---|
| .. | .. |
|---|
| 143 | 136 | {0x380e, 0x02}, {0x380f, 0x84}, {0x3811, 0x04}, {0x3813, 0x04}, |
|---|
| 144 | 137 | {0x3814, 0x31}, {0x3815, 0x31}, {0x3820, 0xc0}, {0x4008, 0x00}, |
|---|
| 145 | 138 | {0x4009, 0x03}, {0x4837, 0x1e}, {0x3501, 0x4e}, {0x3502, 0xe0}, |
|---|
| 139 | + {0x3503, 0x03}, |
|---|
| 146 | 140 | }; |
|---|
| 147 | 141 | |
|---|
| 148 | 142 | static const struct reg_value ov2680_setting_30fps_720P_1280_720[] = { |
|---|
| .. | .. |
|---|
| 321 | 315 | usleep_range(5000, 10000); |
|---|
| 322 | 316 | } |
|---|
| 323 | 317 | |
|---|
| 324 | | -static int ov2680_bayer_order(struct ov2680_dev *sensor) |
|---|
| 318 | +static void ov2680_set_bayer_order(struct ov2680_dev *sensor) |
|---|
| 325 | 319 | { |
|---|
| 326 | | - u32 format1; |
|---|
| 327 | | - u32 format2; |
|---|
| 328 | | - u32 hv_flip; |
|---|
| 329 | | - int ret; |
|---|
| 320 | + int hv_flip = 0; |
|---|
| 330 | 321 | |
|---|
| 331 | | - ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT1, &format1); |
|---|
| 332 | | - if (ret < 0) |
|---|
| 333 | | - return ret; |
|---|
| 322 | + if (sensor->ctrls.vflip && sensor->ctrls.vflip->val) |
|---|
| 323 | + hv_flip += 1; |
|---|
| 334 | 324 | |
|---|
| 335 | | - ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT2, &format2); |
|---|
| 336 | | - if (ret < 0) |
|---|
| 337 | | - return ret; |
|---|
| 338 | | - |
|---|
| 339 | | - hv_flip = (format2 & BIT(2) << 1) | (format1 & BIT(2)); |
|---|
| 325 | + if (sensor->ctrls.hflip && sensor->ctrls.hflip->val) |
|---|
| 326 | + hv_flip += 2; |
|---|
| 340 | 327 | |
|---|
| 341 | 328 | sensor->fmt.code = ov2680_hv_flip_bayer_order[hv_flip]; |
|---|
| 329 | +} |
|---|
| 342 | 330 | |
|---|
| 331 | +static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val) |
|---|
| 332 | +{ |
|---|
| 333 | + int ret; |
|---|
| 334 | + |
|---|
| 335 | + if (sensor->is_streaming) |
|---|
| 336 | + return -EBUSY; |
|---|
| 337 | + |
|---|
| 338 | + ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, |
|---|
| 339 | + BIT(2), val ? BIT(2) : 0); |
|---|
| 340 | + if (ret < 0) |
|---|
| 341 | + return ret; |
|---|
| 342 | + |
|---|
| 343 | + ov2680_set_bayer_order(sensor); |
|---|
| 343 | 344 | return 0; |
|---|
| 344 | 345 | } |
|---|
| 345 | 346 | |
|---|
| 346 | | -static int ov2680_vflip_enable(struct ov2680_dev *sensor) |
|---|
| 347 | +static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val) |
|---|
| 347 | 348 | { |
|---|
| 348 | 349 | int ret; |
|---|
| 349 | 350 | |
|---|
| 350 | | - ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(2)); |
|---|
| 351 | + if (sensor->is_streaming) |
|---|
| 352 | + return -EBUSY; |
|---|
| 353 | + |
|---|
| 354 | + ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, |
|---|
| 355 | + BIT(2), val ? BIT(2) : 0); |
|---|
| 351 | 356 | if (ret < 0) |
|---|
| 352 | 357 | return ret; |
|---|
| 353 | 358 | |
|---|
| 354 | | - return ov2680_bayer_order(sensor); |
|---|
| 355 | | -} |
|---|
| 356 | | - |
|---|
| 357 | | -static int ov2680_vflip_disable(struct ov2680_dev *sensor) |
|---|
| 358 | | -{ |
|---|
| 359 | | - int ret; |
|---|
| 360 | | - |
|---|
| 361 | | - ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(0)); |
|---|
| 362 | | - if (ret < 0) |
|---|
| 363 | | - return ret; |
|---|
| 364 | | - |
|---|
| 365 | | - return ov2680_bayer_order(sensor); |
|---|
| 366 | | -} |
|---|
| 367 | | - |
|---|
| 368 | | -static int ov2680_hflip_enable(struct ov2680_dev *sensor) |
|---|
| 369 | | -{ |
|---|
| 370 | | - int ret; |
|---|
| 371 | | - |
|---|
| 372 | | - ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(2)); |
|---|
| 373 | | - if (ret < 0) |
|---|
| 374 | | - return ret; |
|---|
| 375 | | - |
|---|
| 376 | | - return ov2680_bayer_order(sensor); |
|---|
| 377 | | -} |
|---|
| 378 | | - |
|---|
| 379 | | -static int ov2680_hflip_disable(struct ov2680_dev *sensor) |
|---|
| 380 | | -{ |
|---|
| 381 | | - int ret; |
|---|
| 382 | | - |
|---|
| 383 | | - ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(0)); |
|---|
| 384 | | - if (ret < 0) |
|---|
| 385 | | - return ret; |
|---|
| 386 | | - |
|---|
| 387 | | - return ov2680_bayer_order(sensor); |
|---|
| 359 | + ov2680_set_bayer_order(sensor); |
|---|
| 360 | + return 0; |
|---|
| 388 | 361 | } |
|---|
| 389 | 362 | |
|---|
| 390 | 363 | static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value) |
|---|
| .. | .. |
|---|
| 405 | 378 | return 0; |
|---|
| 406 | 379 | } |
|---|
| 407 | 380 | |
|---|
| 408 | | -static int ov2680_gain_set(struct ov2680_dev *sensor, bool auto_gain) |
|---|
| 381 | +static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain) |
|---|
| 409 | 382 | { |
|---|
| 410 | | - struct ov2680_ctrls *ctrls = &sensor->ctrls; |
|---|
| 411 | | - u32 gain; |
|---|
| 412 | | - int ret; |
|---|
| 413 | | - |
|---|
| 414 | | - ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(1), |
|---|
| 415 | | - auto_gain ? 0 : BIT(1)); |
|---|
| 416 | | - if (ret < 0) |
|---|
| 417 | | - return ret; |
|---|
| 418 | | - |
|---|
| 419 | | - if (auto_gain || !ctrls->gain->is_new) |
|---|
| 420 | | - return 0; |
|---|
| 421 | | - |
|---|
| 422 | | - gain = ctrls->gain->val; |
|---|
| 423 | | - |
|---|
| 424 | | - ret = ov2680_write_reg16(sensor, OV2680_REG_GAIN_PK, gain); |
|---|
| 425 | | - |
|---|
| 426 | | - return 0; |
|---|
| 383 | + return ov2680_write_reg16(sensor, OV2680_REG_GAIN_PK, gain); |
|---|
| 427 | 384 | } |
|---|
| 428 | 385 | |
|---|
| 429 | | -static int ov2680_gain_get(struct ov2680_dev *sensor) |
|---|
| 386 | +static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp) |
|---|
| 430 | 387 | { |
|---|
| 431 | | - u32 gain; |
|---|
| 432 | | - int ret; |
|---|
| 433 | | - |
|---|
| 434 | | - ret = ov2680_read_reg16(sensor, OV2680_REG_GAIN_PK, &gain); |
|---|
| 435 | | - if (ret) |
|---|
| 436 | | - return ret; |
|---|
| 437 | | - |
|---|
| 438 | | - return gain; |
|---|
| 439 | | -} |
|---|
| 440 | | - |
|---|
| 441 | | -static int ov2680_exposure_set(struct ov2680_dev *sensor, bool auto_exp) |
|---|
| 442 | | -{ |
|---|
| 443 | | - struct ov2680_ctrls *ctrls = &sensor->ctrls; |
|---|
| 444 | | - u32 exp; |
|---|
| 445 | | - int ret; |
|---|
| 446 | | - |
|---|
| 447 | | - ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(0), |
|---|
| 448 | | - auto_exp ? 0 : BIT(0)); |
|---|
| 449 | | - if (ret < 0) |
|---|
| 450 | | - return ret; |
|---|
| 451 | | - |
|---|
| 452 | | - if (auto_exp || !ctrls->exposure->is_new) |
|---|
| 453 | | - return 0; |
|---|
| 454 | | - |
|---|
| 455 | | - exp = (u32)ctrls->exposure->val; |
|---|
| 456 | | - exp <<= 4; |
|---|
| 457 | | - |
|---|
| 458 | | - return ov2680_write_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, exp); |
|---|
| 459 | | -} |
|---|
| 460 | | - |
|---|
| 461 | | -static int ov2680_exposure_get(struct ov2680_dev *sensor) |
|---|
| 462 | | -{ |
|---|
| 463 | | - int ret; |
|---|
| 464 | | - u32 exp; |
|---|
| 465 | | - |
|---|
| 466 | | - ret = ov2680_read_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, &exp); |
|---|
| 467 | | - if (ret) |
|---|
| 468 | | - return ret; |
|---|
| 469 | | - |
|---|
| 470 | | - return exp >> 4; |
|---|
| 388 | + return ov2680_write_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, |
|---|
| 389 | + exp << 4); |
|---|
| 471 | 390 | } |
|---|
| 472 | 391 | |
|---|
| 473 | 392 | static int ov2680_stream_enable(struct ov2680_dev *sensor) |
|---|
| .. | .. |
|---|
| 482 | 401 | |
|---|
| 483 | 402 | static int ov2680_mode_set(struct ov2680_dev *sensor) |
|---|
| 484 | 403 | { |
|---|
| 485 | | - struct ov2680_ctrls *ctrls = &sensor->ctrls; |
|---|
| 486 | 404 | int ret; |
|---|
| 487 | | - |
|---|
| 488 | | - ret = ov2680_gain_set(sensor, false); |
|---|
| 489 | | - if (ret < 0) |
|---|
| 490 | | - return ret; |
|---|
| 491 | | - |
|---|
| 492 | | - ret = ov2680_exposure_set(sensor, false); |
|---|
| 493 | | - if (ret < 0) |
|---|
| 494 | | - return ret; |
|---|
| 495 | 405 | |
|---|
| 496 | 406 | ret = ov2680_load_regs(sensor, sensor->current_mode); |
|---|
| 497 | 407 | if (ret < 0) |
|---|
| 498 | 408 | return ret; |
|---|
| 499 | 409 | |
|---|
| 500 | | - if (ctrls->auto_gain->val) { |
|---|
| 501 | | - ret = ov2680_gain_set(sensor, true); |
|---|
| 502 | | - if (ret < 0) |
|---|
| 503 | | - return ret; |
|---|
| 504 | | - } |
|---|
| 505 | | - |
|---|
| 506 | | - if (ctrls->auto_exp->val == V4L2_EXPOSURE_AUTO) { |
|---|
| 507 | | - ret = ov2680_exposure_set(sensor, true); |
|---|
| 508 | | - if (ret < 0) |
|---|
| 509 | | - return ret; |
|---|
| 510 | | - } |
|---|
| 410 | + /* Restore value of all ctrls */ |
|---|
| 411 | + ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler); |
|---|
| 412 | + if (ret < 0) |
|---|
| 413 | + return ret; |
|---|
| 511 | 414 | |
|---|
| 512 | 415 | sensor->mode_pending_changes = false; |
|---|
| 513 | 416 | |
|---|
| .. | .. |
|---|
| 556 | 459 | ret = ov2680_write_reg(sensor, OV2680_REG_SOFT_RESET, 0x01); |
|---|
| 557 | 460 | if (ret != 0) { |
|---|
| 558 | 461 | dev_err(dev, "sensor soft reset failed\n"); |
|---|
| 559 | | - return ret; |
|---|
| 462 | + goto err_disable_regulators; |
|---|
| 560 | 463 | } |
|---|
| 561 | 464 | usleep_range(1000, 2000); |
|---|
| 562 | 465 | } else { |
|---|
| .. | .. |
|---|
| 566 | 469 | |
|---|
| 567 | 470 | ret = clk_prepare_enable(sensor->xvclk); |
|---|
| 568 | 471 | if (ret < 0) |
|---|
| 569 | | - return ret; |
|---|
| 472 | + goto err_disable_regulators; |
|---|
| 570 | 473 | |
|---|
| 571 | 474 | sensor->is_enabled = true; |
|---|
| 572 | 475 | |
|---|
| .. | .. |
|---|
| 576 | 479 | ov2680_stream_disable(sensor); |
|---|
| 577 | 480 | |
|---|
| 578 | 481 | return 0; |
|---|
| 482 | + |
|---|
| 483 | +err_disable_regulators: |
|---|
| 484 | + regulator_bulk_disable(OV2680_NUM_SUPPLIES, sensor->supplies); |
|---|
| 485 | + return ret; |
|---|
| 579 | 486 | } |
|---|
| 580 | 487 | |
|---|
| 581 | 488 | static int ov2680_s_power(struct v4l2_subdev *sd, int on) |
|---|
| .. | .. |
|---|
| 590 | 497 | else |
|---|
| 591 | 498 | ret = ov2680_power_off(sensor); |
|---|
| 592 | 499 | |
|---|
| 593 | | - mutex_unlock(&sensor->lock); |
|---|
| 594 | | - |
|---|
| 595 | | - if (on && ret == 0) { |
|---|
| 596 | | - ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler); |
|---|
| 597 | | - if (ret < 0) |
|---|
| 598 | | - return ret; |
|---|
| 599 | | - |
|---|
| 500 | + if (on && ret == 0) |
|---|
| 600 | 501 | ret = ov2680_mode_restore(sensor); |
|---|
| 601 | | - } |
|---|
| 502 | + |
|---|
| 503 | + mutex_unlock(&sensor->lock); |
|---|
| 602 | 504 | |
|---|
| 603 | 505 | return ret; |
|---|
| 604 | 506 | } |
|---|
| .. | .. |
|---|
| 793 | 695 | return 0; |
|---|
| 794 | 696 | } |
|---|
| 795 | 697 | |
|---|
| 796 | | -static int ov2680_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
|---|
| 797 | | -{ |
|---|
| 798 | | - struct v4l2_subdev *sd = ctrl_to_sd(ctrl); |
|---|
| 799 | | - struct ov2680_dev *sensor = to_ov2680_dev(sd); |
|---|
| 800 | | - struct ov2680_ctrls *ctrls = &sensor->ctrls; |
|---|
| 801 | | - int val; |
|---|
| 802 | | - |
|---|
| 803 | | - if (!sensor->is_enabled) |
|---|
| 804 | | - return 0; |
|---|
| 805 | | - |
|---|
| 806 | | - switch (ctrl->id) { |
|---|
| 807 | | - case V4L2_CID_GAIN: |
|---|
| 808 | | - val = ov2680_gain_get(sensor); |
|---|
| 809 | | - if (val < 0) |
|---|
| 810 | | - return val; |
|---|
| 811 | | - ctrls->gain->val = val; |
|---|
| 812 | | - break; |
|---|
| 813 | | - case V4L2_CID_EXPOSURE: |
|---|
| 814 | | - val = ov2680_exposure_get(sensor); |
|---|
| 815 | | - if (val < 0) |
|---|
| 816 | | - return val; |
|---|
| 817 | | - ctrls->exposure->val = val; |
|---|
| 818 | | - break; |
|---|
| 819 | | - } |
|---|
| 820 | | - |
|---|
| 821 | | - return 0; |
|---|
| 822 | | -} |
|---|
| 823 | | - |
|---|
| 824 | 698 | static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl) |
|---|
| 825 | 699 | { |
|---|
| 826 | 700 | struct v4l2_subdev *sd = ctrl_to_sd(ctrl); |
|---|
| 827 | 701 | struct ov2680_dev *sensor = to_ov2680_dev(sd); |
|---|
| 828 | | - struct ov2680_ctrls *ctrls = &sensor->ctrls; |
|---|
| 829 | 702 | |
|---|
| 830 | 703 | if (!sensor->is_enabled) |
|---|
| 831 | 704 | return 0; |
|---|
| 832 | 705 | |
|---|
| 833 | 706 | switch (ctrl->id) { |
|---|
| 834 | | - case V4L2_CID_AUTOGAIN: |
|---|
| 835 | | - return ov2680_gain_set(sensor, !!ctrl->val); |
|---|
| 836 | 707 | case V4L2_CID_GAIN: |
|---|
| 837 | | - return ov2680_gain_set(sensor, !!ctrls->auto_gain->val); |
|---|
| 838 | | - case V4L2_CID_EXPOSURE_AUTO: |
|---|
| 839 | | - return ov2680_exposure_set(sensor, !!ctrl->val); |
|---|
| 708 | + return ov2680_gain_set(sensor, ctrl->val); |
|---|
| 840 | 709 | case V4L2_CID_EXPOSURE: |
|---|
| 841 | | - return ov2680_exposure_set(sensor, !!ctrls->auto_exp->val); |
|---|
| 710 | + return ov2680_exposure_set(sensor, ctrl->val); |
|---|
| 842 | 711 | case V4L2_CID_VFLIP: |
|---|
| 843 | | - if (sensor->is_streaming) |
|---|
| 844 | | - return -EBUSY; |
|---|
| 845 | | - if (ctrl->val) |
|---|
| 846 | | - return ov2680_vflip_enable(sensor); |
|---|
| 847 | | - else |
|---|
| 848 | | - return ov2680_vflip_disable(sensor); |
|---|
| 712 | + return ov2680_set_vflip(sensor, ctrl->val); |
|---|
| 849 | 713 | case V4L2_CID_HFLIP: |
|---|
| 850 | | - if (sensor->is_streaming) |
|---|
| 851 | | - return -EBUSY; |
|---|
| 852 | | - if (ctrl->val) |
|---|
| 853 | | - return ov2680_hflip_enable(sensor); |
|---|
| 854 | | - else |
|---|
| 855 | | - return ov2680_hflip_disable(sensor); |
|---|
| 714 | + return ov2680_set_hflip(sensor, ctrl->val); |
|---|
| 856 | 715 | case V4L2_CID_TEST_PATTERN: |
|---|
| 857 | 716 | return ov2680_test_pattern_set(sensor, ctrl->val); |
|---|
| 858 | 717 | default: |
|---|
| .. | .. |
|---|
| 863 | 722 | } |
|---|
| 864 | 723 | |
|---|
| 865 | 724 | static const struct v4l2_ctrl_ops ov2680_ctrl_ops = { |
|---|
| 866 | | - .g_volatile_ctrl = ov2680_g_volatile_ctrl, |
|---|
| 867 | 725 | .s_ctrl = ov2680_s_ctrl, |
|---|
| 868 | 726 | }; |
|---|
| 869 | 727 | |
|---|
| .. | .. |
|---|
| 935 | 793 | if (ret < 0) |
|---|
| 936 | 794 | return ret; |
|---|
| 937 | 795 | |
|---|
| 938 | | - v4l2_ctrl_handler_init(hdl, 7); |
|---|
| 796 | + v4l2_ctrl_handler_init(hdl, 5); |
|---|
| 939 | 797 | |
|---|
| 940 | 798 | hdl->lock = &sensor->lock; |
|---|
| 941 | 799 | |
|---|
| .. | .. |
|---|
| 947 | 805 | ARRAY_SIZE(test_pattern_menu) - 1, |
|---|
| 948 | 806 | 0, 0, test_pattern_menu); |
|---|
| 949 | 807 | |
|---|
| 950 | | - ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops, |
|---|
| 951 | | - V4L2_CID_EXPOSURE_AUTO, |
|---|
| 952 | | - V4L2_EXPOSURE_MANUAL, 0, |
|---|
| 953 | | - V4L2_EXPOSURE_AUTO); |
|---|
| 954 | | - |
|---|
| 955 | 808 | ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, |
|---|
| 956 | 809 | 0, 32767, 1, 0); |
|---|
| 957 | 810 | |
|---|
| 958 | | - ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN, |
|---|
| 959 | | - 0, 1, 1, 1); |
|---|
| 960 | 811 | ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, 0, 2047, 1, 0); |
|---|
| 961 | 812 | |
|---|
| 962 | 813 | if (hdl->error) { |
|---|
| .. | .. |
|---|
| 964 | 815 | goto cleanup_entity; |
|---|
| 965 | 816 | } |
|---|
| 966 | 817 | |
|---|
| 967 | | - ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE; |
|---|
| 968 | | - ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; |
|---|
| 969 | | - |
|---|
| 970 | | - v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true); |
|---|
| 971 | | - v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true); |
|---|
| 818 | + ctrls->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; |
|---|
| 819 | + ctrls->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; |
|---|
| 972 | 820 | |
|---|
| 973 | 821 | sensor->sd.ctrl_handler = hdl; |
|---|
| 974 | 822 | |
|---|