Hi Hans, On 2017-11-06 08:19 AM, Hans Verkuil wrote: > Hi Helen, > > On 09/27/2017 08:30 PM, Helen Koike wrote: >> Hi Hans, >> >> Thanks for your patch and sorry for my late reply. > > Sorry for my late reply to your reply :-) > >> Please see my comments and questions below >> >> On 2017-07-28 07:23 AM, Hans Verkuil wrote: >>> Add support for the test_pattern control and the h/vflip controls. >>> >>> This makes it possible to switch to more interesting test patterns and to >>> test control handling in v4l-subdevs. >>> >>> There are more tpg-related controls that can be added, but this is a good >>> start. >>> >>> Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx> >>> --- >>> diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h >>> index dca528a316e7..2e9981b18166 100644 >>> --- a/drivers/media/platform/vimc/vimc-common.h >>> +++ b/drivers/media/platform/vimc/vimc-common.h >>> @@ -22,6 +22,11 @@ >>> #include <media/media-device.h> >>> #include <media/v4l2-device.h> >>> >>> +/* VIMC-specific controls */ >>> +#define VIMC_CID_VIMC_BASE (0x00f00000 | 0xf000) >>> +#define VIMC_CID_VIMC_CLASS (0x00f00000 | 1) >> >> Why this values, shouldn't we use a derivative from >> V4L2_CID_PRIVATE_BASE for custom controls? Or can we use random values? > > The values are taken from vivid which uses the same scheme. These controls > deal with how the virtual driver emulates things, and I prefer not to make > these control IDs part of the public API so we can be a bit more flexible in > the future. It's a design choice which worked well for vivid. > >> >>> +#define VIMC_CID_TEST_PATTERN (VIMC_CID_VIMC_BASE + 0) >>> + >>> #define VIMC_FRAME_MAX_WIDTH 4096 >>> #define VIMC_FRAME_MAX_HEIGHT 2160 >>> #define VIMC_FRAME_MIN_WIDTH 16 >>> diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c >>> index 615c2b18dcfc..532097566b27 100644 >>> --- a/drivers/media/platform/vimc/vimc-sensor.c >>> +++ b/drivers/media/platform/vimc/vimc-sensor.c >>> @@ -22,6 +22,7 @@ >>> #include <linux/platform_device.h> >>> #include <linux/v4l2-mediabus.h> >>> #include <linux/vmalloc.h> >>> +#include <media/v4l2-ctrls.h> >>> #include <media/v4l2-subdev.h> >>> #include <media/v4l2-tpg.h> >>> >>> @@ -38,6 +39,7 @@ struct vimc_sen_device { >>> u8 *frame; >>> /* The active format */ >>> struct v4l2_mbus_framefmt mbus_format; >>> + struct v4l2_ctrl_handler hdl; >>> }; >>> >>> static const struct v4l2_mbus_framefmt fmt_default = { >>> @@ -291,6 +293,31 @@ static const struct v4l2_subdev_ops vimc_sen_ops = { >>> .video = &vimc_sen_video_ops, >>> }; >>> >>> +static int vimc_sen_s_ctrl(struct v4l2_ctrl *ctrl) >>> +{ >>> + struct vimc_sen_device *vsen = >>> + container_of(ctrl->handler, struct vimc_sen_device, hdl); >>> + >>> + switch (ctrl->id) { >>> + case VIMC_CID_TEST_PATTERN: >>> + tpg_s_pattern(&vsen->tpg, ctrl->val); >>> + break; >>> + case V4L2_CID_HFLIP: >>> + tpg_s_hflip(&vsen->tpg, ctrl->val); >>> + break; >>> + case V4L2_CID_VFLIP: >>> + tpg_s_vflip(&vsen->tpg, ctrl->val); >>> + break; >>> + default: >>> + return -EINVAL; >>> + } >>> + return 0; >>> +} >>> + >>> +static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = { >>> + .s_ctrl = vimc_sen_s_ctrl, >>> +}; >>> + >>> static void vimc_sen_comp_unbind(struct device *comp, struct device *master, >>> void *master_data) >>> { >>> @@ -299,10 +326,29 @@ static void vimc_sen_comp_unbind(struct device *comp, struct device *master, >>> container_of(ved, struct vimc_sen_device, ved); >>> >>> vimc_ent_sd_unregister(ved, &vsen->sd); >>> + v4l2_ctrl_handler_free(&vsen->hdl); >>> tpg_free(&vsen->tpg); >>> kfree(vsen); >>> } >>> >>> +/* Image Processing Controls */ >>> +static const struct v4l2_ctrl_config vimc_sen_ctrl_class = { >>> + .ops = &vimc_sen_ctrl_ops, >>> + .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY, >> >> I was wondering if it is really necessary to specify the ops and flags >> in the class, as this is seems to me a meta control for the other >> controls to be grouped in a class. > > ops can be dropped, but flags needs to be there. > >> >>> + .id = VIMC_CID_VIMC_CLASS, >>> + .name = "VIMC Controls", >>> + .type = V4L2_CTRL_TYPE_CTRL_CLASS, >>> +}; >>> + >>> +static const struct v4l2_ctrl_config vimc_sen_ctrl_test_pattern = { >>> + .ops = &vimc_sen_ctrl_ops, >>> + .id = VIMC_CID_TEST_PATTERN, >>> + .name = "Test Pattern", >>> + .type = V4L2_CTRL_TYPE_MENU, >>> + .max = TPG_PAT_NOISE, >>> + .qmenu = tpg_pattern_strings, >>> +}; >>> + >>> static int vimc_sen_comp_bind(struct device *comp, struct device *master, >>> void *master_data) >>> { >>> @@ -316,6 +362,20 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, >>> if (!vsen) >>> return -ENOMEM; >>> >>> + v4l2_ctrl_handler_init(&vsen->hdl, 4); >>> + >>> + v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_class, NULL); >>> + v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_test_pattern, NULL); >>> + v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, >>> + V4L2_CID_VFLIP, 0, 1, 1, 0); >>> + v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, >>> + V4L2_CID_HFLIP, 0, 1, 1, 0); >> >> Shouldn't we test the return values of the above functions? Or maybe not >> because we should know what we are doing and this doesn't depend on the >> user space. >> >>> + vsen->sd.ctrl_handler = &vsen->hdl; >>> + if (vsen->hdl.error) { > > The error check happens here. These control functions do nothing if vsen->hdl.error > is non-0, and set it if an error occurs. > > This simplifies the code since you have to check for an error only once at the end. > >>> + ret = vsen->hdl.error; >>> + goto err_free_vsen; >>> + } >>> + >>> /* Initialize ved and sd */ >>> ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev, >>> pdata->entity_name, >>> @@ -323,7 +383,7 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, >>> (const unsigned long[1]) {MEDIA_PAD_FL_SOURCE}, >>> &vimc_sen_ops); >>> if (ret) >>> - goto err_free_vsen; >>> + goto err_free_hdl; >>> >>> dev_set_drvdata(comp, &vsen->ved); >>> vsen->dev = comp; >>> @@ -342,6 +402,8 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, >>> >>> err_unregister_ent_sd: >>> vimc_ent_sd_unregister(&vsen->ved, &vsen->sd); >>> +err_free_hdl: >>> + v4l2_ctrl_handler_free(&vsen->hdl); >>> err_free_vsen: >>> kfree(vsen); >>> >> >> >> This conflicts a bit in the way I was preparing the optimization to >> generate the pattern directly from the capture device as it will need to >> propagate the changes from the controls in the sensor as well, but it >> shouldn't be a problem to let the sensor to configure the tpg used in >> the capture, I'll re-work my patch to include this. > > OK. I'll post a v2 dropping the ops field for the 'control class' control. with this change, Acked-by: Helen Koike <helen.koike@xxxxxxxxxxxxx> > > Regards, > > Hans >