media: go7007: s2250: propagate control I/O failures

The brightness and contrast paths use oldvalue after read_reg_fp()
without checking whether the read succeeded.  A failed read leaves
oldvalue uninitialized and can write arbitrary reserved register bits.

Return read and write errors from every control path so failed hardware
access cannot be reported as a successful control update.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
Yousef Alhouseen
2026-06-30 12:50:15 +02:00
committed by Hans Verkuil
parent e260d1d771
commit 59dc14a6cb

View File

@@ -365,36 +365,48 @@ static int s2250_s_ctrl(struct v4l2_ctrl *ctrl)
struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl);
struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
u16 oldvalue;
int ret;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
ctrl->val | (oldvalue & ~0xff));
read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
ctrl->val | (oldvalue & ~0xff));
write_reg_fp(client, 0x140, 0x60);
break;
ret = read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
if (ret)
return ret;
ret = write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
ctrl->val | (oldvalue & ~0xff));
if (ret)
return ret;
ret = read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
if (ret)
return ret;
ret = write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
ctrl->val | (oldvalue & ~0xff));
if (ret)
return ret;
return write_reg_fp(client, 0x140, 0x60);
case V4L2_CID_CONTRAST:
read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
write_reg_fp(client, VPX322_ADDR_CONTRAST0,
ctrl->val | (oldvalue & ~0x3f));
read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
write_reg_fp(client, VPX322_ADDR_CONTRAST1,
ctrl->val | (oldvalue & ~0x3f));
write_reg_fp(client, 0x140, 0x60);
break;
ret = read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
if (ret)
return ret;
ret = write_reg_fp(client, VPX322_ADDR_CONTRAST0,
ctrl->val | (oldvalue & ~0x3f));
if (ret)
return ret;
ret = read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
if (ret)
return ret;
ret = write_reg_fp(client, VPX322_ADDR_CONTRAST1,
ctrl->val | (oldvalue & ~0x3f));
if (ret)
return ret;
return write_reg_fp(client, 0x140, 0x60);
case V4L2_CID_SATURATION:
write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
break;
return write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val);
case V4L2_CID_HUE:
write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
break;
return write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val);
default:
return -EINVAL;
}
return 0;
}
static int s2250_set_fmt(struct v4l2_subdev *sd,