diff --git a/drivers/media/platform/apple/isp/isp-v4l2-test.c b/drivers/media/platform/apple/isp/isp-v4l2-test.c index 88f428b3b0c27..ee38dc9ce7d21 100644 --- a/drivers/media/platform/apple/isp/isp-v4l2-test.c +++ b/drivers/media/platform/apple/isp/isp-v4l2-test.c @@ -371,6 +371,14 @@ static void isp_test_meta_exposure(struct kunit *test) KUNIT_EXPECT_EQ(test, isp->frame_exposure_us, 32475); KUNIT_EXPECT_EQ(test, isp->frame_gain, 3253); + /* A short header cannot supply the section-table entry. */ + put_unaligned_le16(700, virt + 0x1876); + meta.size = 0x1f; + isp_meta_read_exposure(isp, &meta); + KUNIT_EXPECT_EQ(test, isp->frame_gain, 3253); + meta.size = 0x2000; + put_unaligned_le16(3253, virt + 0x1876); + /* a section that would end past the buffer is ignored */ put_unaligned_le32(meta.size - 4, virt + 0x1c); put_unaligned_le32(1000, virt + meta.size - 4); @@ -393,8 +401,32 @@ static void isp_test_meta_exposure(struct kunit *test) KUNIT_EXPECT_EQ(test, isp->frame_gain, 600); } +static void isp_test_exposure_control_gate(struct kunit *test) +{ + static const struct apple_isp_hw hw_none = { }; + static const struct apple_isp_hw hw = { .meta_exposure = true }; + struct apple_isp *isp = isp_test_alloc(test); + + v4l2_ctrl_handler_init(&isp->ctrl_handler, 3); + isp->hw = &hw_none; + isp_init_exposure_ctrls(isp); + KUNIT_EXPECT_PTR_EQ(test, isp->gain, NULL); + KUNIT_EXPECT_PTR_EQ(test, isp->exposure, NULL); + isp->hw = &hw; + isp_init_exposure_ctrls(isp); + KUNIT_EXPECT_EQ(test, isp->ctrl_handler.error, 0); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, isp->gain); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, isp->exposure); + if (isp->gain) + KUNIT_EXPECT_EQ(test, isp->gain->flags & + (V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE), + (u32)(V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE)); + v4l2_ctrl_handler_free(&isp->ctrl_handler); +} + static struct kunit_case isp_v4l2_test_cases[] = { KUNIT_CASE(isp_test_meta_exposure), + KUNIT_CASE(isp_test_exposure_control_gate), KUNIT_CASE(isp_test_imx958_last_lease_requeue), KUNIT_CASE(isp_test_p010_report_defers_completion), KUNIT_CASE(isp_test_p010_mode_selection), diff --git a/drivers/media/platform/apple/isp/isp-v4l2.c b/drivers/media/platform/apple/isp/isp-v4l2.c index 24506ed526a34..26408e3c669d7 100644 --- a/drivers/media/platform/apple/isp/isp-v4l2.c +++ b/drivers/media/platform/apple/isp/isp-v4l2.c @@ -89,7 +89,8 @@ static void isp_meta_read_exposure(struct apple_isp *isp, u32 offset, time; u16 gain; - if (!isp->hw->meta_exposure || !virt) + if (!isp->hw->meta_exposure || !virt || + meta->size < ISP_META_SECTIONS + 4 * (ISP_META_SECTION_EXPOSURE + 1)) return; offset = get_unaligned_le32(virt + ISP_META_SECTIONS + @@ -1151,6 +1152,9 @@ static const struct v4l2_ctrl_ops isp_exposure_ctrl_ops = { */ static void isp_init_exposure_ctrls(struct apple_isp *isp) { + if (!isp->hw->meta_exposure) + return; + isp->frame_gain = 256; isp->gain = v4l2_ctrl_new_std(&isp->ctrl_handler, &isp_exposure_ctrl_ops, V4L2_CID_GAIN,