-
Notifications
You must be signed in to change notification settings - Fork 5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IRS1125 sensor driver updates #3544
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of comments for you to consider. You are the only users of this driver, therefore I'm not going to fuss over them excessively. Should you ever try to upstream this then you will get the same sort of queries there, and breaking backwards compatibility would be a big no-no.
drivers/media/i2c/irs1125.h
Outdated
#define IRS1125_CID_SEQ_CONFIG (IRS1125_CID_CUSTOM_BASE + 46) | ||
#define IRS1125_CID_IDENT0 (IRS1125_CID_CUSTOM_BASE + 47) | ||
#define IRS1125_CID_IDENT1 (IRS1125_CID_CUSTOM_BASE + 48) | ||
#define IRS1125_CID_IDENT2 (IRS1125_CID_CUSTOM_BASE + 49) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are the only user of this driver at present, but rewriting all the control CIDs like this means you have totally destroyed any backwards compatibility.
Generally speaking you should retain the same CID where possible, deprectate (and not reuse) those which are obsolete, and add new controls to the end. A user app can then know that the control matches the headers that it has.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, you are right, of course.
drivers/media/i2c/irs1125.c
Outdated
@@ -29,6 +29,7 @@ | |||
#include <media/v4l2-image-sizes.h> | |||
#include <media/v4l2-mediabus.h> | |||
#include <media/v4l2-ctrls.h> | |||
#include <asm/unaligned.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Includes should normally be in alhpabetical order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I didn't know that
drivers/media/i2c/irs1125.c
Outdated
|
||
*val = rdval[1] | (rdval[0] << 8); | ||
*val = get_unaligned_be16(data_buf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I prefer the explicit assignment rather than the use of the be16 functions here as the reassembly isn't down to CPU endianness. Others seem to use them in drivers/media/i2c though, so I'm not going to fuss.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, I'll use the previous version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few concerns/comments.
The commit texts could be more descriptive too.
drivers/media/i2c/irs1125.c
Outdated
dev_err(&client->dev, "%s: i2c read error, reg: %x\n", | ||
__func__, reg); | ||
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
if (ret != ARRAY_SIZE(msgs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://elixir.bootlin.com/linux/latest/source/drivers/i2c/i2c-core-base.c#L1987
"Returns negative errno, else the number of messages executed."
So this masks any error number and will always return -EIO on failure.
if (ret != ARRAY_SIZE(msgs)) {
if (ret >= 0)
ret = -EIO;
return ret;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. This should be fixed now
drivers/media/i2c/irs1125.c
Outdated
} | ||
addr = 0xC3A0 + i * 3; | ||
val = mod_new[i].pllcfg1; | ||
err = irs1125_write(&dev->sd, addr, val); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing as addr is only used the once, the calculation may as well be in the call to irs1125_write
Likewise you only use val once.
err = irs1125_write(&dev->sd, 0xC3A0 + i * 3, mod_new[i].pllcfg1);
Same all through this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There could be a minor optimisation in computing i3 (and i5) once per loop, and then using that as a pll_offset value to be added in each call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, done!
drivers/media/i2c/irs1125.c
Outdated
|
||
snprintf(name, sizeof(name), | ||
"Safe reconfiguration of framerate of sequence %d", i); | ||
ctrl_cfg.id += 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ctrl_cfg.id++;
would be more normal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed that now
drivers/media/i2c/irs1125.c
Outdated
dev_err(dev, "Failed to init custom control %s\n", | ||
ctrl_cfg.name); | ||
|
||
snprintf(name, sizeof(name), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has me worried.
struct v4l2_ctrl
only has a const char *name
you're passing in a stack allocated pointer, and I don't believe anything in the framework is going to take a persistent copy of that. That means that name
is pointer into random stuff, and is the same for all of your controls.
Does v4l2-ctl --list-ctrls
actually list out the right thing?
I suspect not, and you really need two arrays of const char* names, with IRS1125_NUM_SEQ_ENTRIES entries in each.
Doing that would also mean that it'd be neater to have two loops, one for adding the exposure ctrls, and one for the framerate ones. Initialise the struct v4l2_ctrl_config
outside the loop, and then insert id and pointer to the name. i+=2 in the loop increment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, the ctrl did not show up as expected. I changed this to use const char* arrays now.
I tested it again with v4l2-ctl --lsit-ctrls
and it shows the expected results now.
drivers/media/i2c/irs1125.c
Outdated
@@ -748,33 +759,22 @@ static const struct v4l2_ctrl_config irs1125_custom_ctrls[] = { | |||
.id = IRS1125_CID_MOD_PLL, | |||
.name = "Reconfigure modulation PLLs", | |||
.type = V4L2_CTRL_TYPE_U16, | |||
.flags = V4L2_CTRL_FLAG_HAS_PAYLOAD, | |||
.flags = V4L2_CTRL_FLAG_HAS_PAYLOAD | | |||
V4L2_CTRL_FLAG_EXECUTE_ON_WRITE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really need to write it every time, even if it hasn't changed? I'm willing to believe it, but it's slightly unusual.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No this is not needed, you are right.
drivers/media/i2c/irs1125.c
Outdated
int s; | ||
|
||
s = sizeof(struct irs1125_mod_pll) * IRS1125_NUM_MOD_PLLS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be done as the one line
int s = sizeof(struct irs1125_mod_pll) * IRS1125_NUM_MOD_PLLS;
(line wrap at the * if it's over 80 chars)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, this is changed now
} | ||
} | ||
if (!valid) | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we not want to return an error if invalid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I now skip only writing this control in case of internal sync.
drivers/media/i2c/irs1125.c
Outdated
for (pval = (u8 *)mod_new; pval < (u8 *)mod_new + s; pval++) { | ||
if (*pval != 0) { | ||
valid = true; | ||
break; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused by the validity test.
If any one 8bit value within an array of 8 16bit values is non-zero, then the whole thing is valid?
So all of these are all equally valid
0x0000 0x0000 0x0000 0x0001 0x0000 0x0000 0x0000 0x0000
0xdead 0xbeef 0xdead 0xbeef 0xdead 0xbeef 0xdead 0xbeef
0x0000 0x0000 0x0000 0x000 0x0000 0x0000 0x0000 0x8000
0x8000 0x0000 0x0000 0x000 0x0000 0x0000 0x0000 0x0000
I'll believe you. Do you really need to constrain this because the device dies if all 0's are set, or can you just let userspace worry about setting something sane?
And why test as 8bit values? The same comparison can be done on the u16 values, again treated as an array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a conceptual problem here. I would also like userspace to worry about setting something sane, but IRS1125_CID_MOD_PLL is a compound control. I want to keep controls and hardware in sync which I guess is a key concept of V4L2 (I'll remove all unnecessary V4L2_CTRL_FLAG_EXECUTE_ON_WRITE).
Now the problem is, that when userspace calls a "close" on the video device, the imager goes into deep sleep, which I guess is a good idea to safe power. But in this state, it also looses all its register contents and the V4L2 controls need to be synced with the HW again after the wakeup.
I do that inside __sensor_init with v4l2_ctrl_handler_setup(...). Here the IRS1125_CID_MOD_PLL contains a default value of "all zeros" which kills the imager. I'll look deeper into that problem, I think that the pre-devider value of 0 might be the problem, which would make the code much clearer here.
Anyway I did not find any other solution to that problem. Maybe you have one...? I think a p_def member to v4l2_ctrl_config is added to more recent kernel versions (https://lore.kernel.org/patchwork/patch/1147819/) which would give me the possibility to add a senseful default value for IRS1125_CID_MOD_PLL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, so you need IRS1125_CID_MOD_PLL initialised to something, or skip it if it hasn't been set.
Do you also need to guard against userspace setting all 0's? This will show up as a standard V4L2 device, so if all zeros is really fatal (hardware damage fatal?) then the driver ought to guard against it.
Minor nitpick - if (*pval) {
is neater than if (*pval != 0) {
It would also be nice if the sensor would just stream with default values, but I realise that this may not be terribly useful.
If you rebase against 5.4, then I'm happy for those patches from 5.5 to be cherry-picked back (probably ignore the vivid ones). We do insert a line
Commit <hash> upstream
into the commit text when cherry-picking back, just to make maintenance easier.
You can then set a default :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can look at the current change. I think it is a good idea, that the userspace is responsible for writing senseful data in this control. I skip writing this control only in case of the internal sync after HW power up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Down to the minor nit picks now.
drivers/media/i2c/irs1125.c
Outdated
@@ -1019,6 +1108,7 @@ static int irs1125_probe(struct i2c_client *client, | |||
} | |||
|
|||
sensor->num_seq = 5; | |||
sensor->ctrl_init = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically redudnant as you did a kzalloc of sensor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, removed
drivers/media/i2c/irs1125.c
Outdated
@@ -552,133 +612,147 @@ static int irs1125_s_ctrl(struct v4l2_ctrl *ctrl) | |||
struct irs1125, ctrl_handler); | |||
struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); | |||
int err, i; | |||
struct irs1125_mod_pll *mod_cur, *mod_new; | |||
struct irs1125_seq_cfg *cfg_cur, *cfg_new; | |||
u16 addr, val; | |||
|
|||
err = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Observation in passing, it's more normal to declare an initialise something like this in one step, ie
int err = 0, i;
at line 614.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I changed that. Actually I always separate declarations and initializations. A former colleague told me to do so. If I remember correctly, he was a freeBSD developer and they are very strict there, an excerpt of their coding styles:
Be careful to not obfuscate the code by initializing variables in the
declarations. Use this feature only thoughtfully.
drivers/media/i2c/irs1125.c
Outdated
struct irs1125_mod_pll *mod_new; | ||
|
||
if (dev->ctrl_init) | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing as err is already 0, you could just break;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
drivers/media/i2c/irs1125.c
Outdated
@@ -82,6 +82,7 @@ struct irs1125 { | |||
struct v4l2_ctrl *ctrl_numseq; | |||
|
|||
int power_count; | |||
bool ctrl_init; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't comment on the commit text directly, but the line
Thus, this ctrl is not written inside the driver into after power up. The userspace has to take care to write senseful data here.
is a little oddly phrased.
Thus, this ctrl is not written to the hardware until it has been initialised by userspace. Userspace must take care to write meaningful data to the control - it is not validated.
Secondly ctrl_init
is rather generic. It's specifically pll_ctrl_init, or pll_ctrl_set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope, the comment is better now.
I renamed ctrl_init
to mod_pll_init
Reading data over i2c is done by using i2c_transfer to ensure that this operation can't be interrupted. Signed-off-by: Markus Proeller <[email protected]>
Changed some variable names to comply with checkpatch --strict mode. Debug messages added. Signed-off-by: Markus Proeller <[email protected]>
Instead of changing the exposure and framerate settings for all sequences, they can be changed for every sequence individually now. Therefore the IRS1125_CID_SAFE_RECONFIG ctrl has been removed and replaced by IRS1125_CID_SAFE_RECONFIG_S<seq_num>_EXPO and *_FRAME ctrls. The consistency check in the sequence ctrl IRS1125_CID_SEQ_CONFIG is removed. Signed-off-by: Markus Proeller <[email protected]>
When closing the video device, the irs1125 is put in power down state. To keep V4L2 ctrls and the HW in sync, v4l2_ctrl_handler_setup is called after power up. The compound ctrl IRS1125_CID_MOD_PLL however has a default value of all zeros, which puts the imager into a non responding state. Thus, this ctrl is not written by the driver into HW after power up. The userspace has to take care to write senseful data. Signed-off-by: Markus Proeller <[email protected]>
@6by9 I think I have reworked everything according to your comments. |
Thanks. As long as this still works with the hardware then I think I'm happy. |
@Coimbra1984 @6by9 I have tested it and it works just fine. |
Based on @6by9's review, the fact that it looks sensible, and the limited scope for collateral damage, I'm happy to merge. |
kernel: brcmfmac: Prefer a ccode from OTP over nvram file kernel: staging: bcm2835-audio: Add missing MODULE_ALIAS See: raspberrypi/linux#3681 kernel: IRS1125 sensor driver updates See: raspberrypi/linux#3544 kernel: Revert downstream SPI patches See: raspberrypi/linux#3687 kernel: PCI: brcmstb: Add DT property to control L1SS firmware: hdmi: Set HD_CTL_WHOLSMP and HD_CTL_CHALIGN_SET See: https://forum.kodi.tv/showthread.php?tid=354589 firmware: arm_ldconfig: Honour the kernel8 text offset See: #1415 firmware: jpeghw: Skip repeated 0xFF padding bytes between markers See: RPi-Distro/vlc#8 filesystem: Add support for SD cards with GPT partition table
kernel: brcmfmac: Prefer a ccode from OTP over nvram file kernel: staging: bcm2835-audio: Add missing MODULE_ALIAS See: raspberrypi/linux#3681 kernel: IRS1125 sensor driver updates See: raspberrypi/linux#3544 kernel: Revert downstream SPI patches See: raspberrypi/linux#3687 kernel: PCI: brcmstb: Add DT property to control L1SS firmware: hdmi: Set HD_CTL_WHOLSMP and HD_CTL_CHALIGN_SET See: https://forum.kodi.tv/showthread.php?tid=354589 firmware: arm_ldconfig: Honour the kernel8 text offset See: raspberrypi/firmware#1415 firmware: jpeghw: Skip repeated 0xFF padding bytes between markers See: RPi-Distro/vlc#8 filesystem: Add support for SD cards with GPT partition table
Changed a few functions: