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

Configure Feed

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

media: i2c: ov9282: implement try_ctrl for strobe_duration

As the granularity of the hardware supported values is lower than the
control value, implement a try_ctrl() function for
V4L2_CID_FLASH_DURATION. This function calculates the nearest possible
µs strobe duration for the given value and returns it back to the
caller.

Signed-off-by: Richard Leitner <richard.leitner@linux.dev>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Richard Leitner and committed by
Hans Verkuil
b95d8058 84ec7597

+51 -2
+51 -2
drivers/media/i2c/ov9282.c
··· 9 9 #include <linux/clk.h> 10 10 #include <linux/delay.h> 11 11 #include <linux/i2c.h> 12 + #include <linux/math.h> 12 13 #include <linux/module.h> 13 14 #include <linux/pm_runtime.h> 14 15 #include <linux/regulator/consumer.h> ··· 128 127 129 128 #define OV9282_REG_MIN 0x00 130 129 #define OV9282_REG_MAX 0xfffff 130 + 131 + #define OV9282_STROBE_SPAN_FACTOR 192 131 132 132 133 static const char * const ov9282_supply_names[] = { 133 134 "avdd", /* Analog power */ ··· 694 691 return ov9282_write_reg(ov9282, OV9282_REG_OUTPUT_ENABLE6, 1, current_val); 695 692 } 696 693 697 - static int ov9282_set_ctrl_flash_duration(struct ov9282 *ov9282, u32 value) 694 + static u32 ov9282_us_to_flash_duration(struct ov9282 *ov9282, u32 value) 698 695 { 699 696 /* 700 697 * Calculate "strobe_frame_span" increments from a given value (µs). ··· 705 702 * The formula below is interpolated from different modes/framerates 706 703 * and should work quite well for most settings. 707 704 */ 708 - u32 val = value * 192 / (ov9282->cur_mode->width + ov9282->hblank_ctrl->val); 705 + u32 frame_width = ov9282->cur_mode->width + ov9282->hblank_ctrl->val; 706 + 707 + return value * OV9282_STROBE_SPAN_FACTOR / frame_width; 708 + } 709 + 710 + static u32 ov9282_flash_duration_to_us(struct ov9282 *ov9282, u32 value) 711 + { 712 + /* 713 + * Calculate back to microseconds from "strobe_frame_span" increments. 714 + * As the calculation in ov9282_us_to_flash_duration uses an integer 715 + * divison round up here. 716 + */ 717 + u32 frame_width = ov9282->cur_mode->width + ov9282->hblank_ctrl->val; 718 + 719 + return DIV_ROUND_UP(value * frame_width, OV9282_STROBE_SPAN_FACTOR); 720 + } 721 + 722 + static int ov9282_set_ctrl_flash_duration(struct ov9282 *ov9282, u32 value) 723 + { 724 + u32 val = ov9282_us_to_flash_duration(ov9282, value); 709 725 int ret; 710 726 711 727 ret = ov9282_write_reg(ov9282, OV9282_REG_STROBE_FRAME_SPAN, 1, ··· 828 806 return ret; 829 807 } 830 808 809 + static int ov9282_try_ctrl(struct v4l2_ctrl *ctrl) 810 + { 811 + struct ov9282 *ov9282 = 812 + container_of_const(ctrl->handler, struct ov9282, ctrl_handler); 813 + 814 + if (ctrl->id == V4L2_CID_FLASH_DURATION) { 815 + u32 us = ctrl->val; 816 + u32 fd = ov9282_us_to_flash_duration(ov9282, us); 817 + 818 + /* get nearest strobe_duration value */ 819 + u32 us0 = ov9282_flash_duration_to_us(ov9282, fd); 820 + u32 us1 = ov9282_flash_duration_to_us(ov9282, fd + 1); 821 + 822 + if (abs(us1 - us) < abs(us - us0)) 823 + ctrl->val = us1; 824 + else 825 + ctrl->val = us0; 826 + 827 + if (us != ctrl->val) 828 + dev_dbg(ov9282->dev, "using next valid strobe_duration %u instead of %u\n", 829 + ctrl->val, us); 830 + } 831 + 832 + return 0; 833 + } 834 + 831 835 /* V4l2 subdevice control ops*/ 832 836 static const struct v4l2_ctrl_ops ov9282_ctrl_ops = { 833 837 .s_ctrl = ov9282_set_ctrl, 838 + .try_ctrl = ov9282_try_ctrl, 834 839 }; 835 840 836 841 /**