diff options
Diffstat (limited to 'drivers/media/platform/vimc/vimc-sensor.c')
-rw-r--r-- | drivers/media/platform/vimc/vimc-sensor.c | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index 02e68c8fc02b..ca1c52232d1e 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/v4l2-mediabus.h> | 23 | #include <linux/v4l2-mediabus.h> |
24 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
25 | #include <media/v4l2-ctrls.h> | ||
25 | #include <media/v4l2-subdev.h> | 26 | #include <media/v4l2-subdev.h> |
26 | #include <media/v4l2-tpg.h> | 27 | #include <media/v4l2-tpg.h> |
27 | 28 | ||
@@ -38,6 +39,7 @@ struct vimc_sen_device { | |||
38 | u8 *frame; | 39 | u8 *frame; |
39 | /* The active format */ | 40 | /* The active format */ |
40 | struct v4l2_mbus_framefmt mbus_format; | 41 | struct v4l2_mbus_framefmt mbus_format; |
42 | struct v4l2_ctrl_handler hdl; | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | static const struct v4l2_mbus_framefmt fmt_default = { | 45 | static const struct v4l2_mbus_framefmt fmt_default = { |
@@ -291,6 +293,31 @@ static const struct v4l2_subdev_ops vimc_sen_ops = { | |||
291 | .video = &vimc_sen_video_ops, | 293 | .video = &vimc_sen_video_ops, |
292 | }; | 294 | }; |
293 | 295 | ||
296 | static int vimc_sen_s_ctrl(struct v4l2_ctrl *ctrl) | ||
297 | { | ||
298 | struct vimc_sen_device *vsen = | ||
299 | container_of(ctrl->handler, struct vimc_sen_device, hdl); | ||
300 | |||
301 | switch (ctrl->id) { | ||
302 | case VIMC_CID_TEST_PATTERN: | ||
303 | tpg_s_pattern(&vsen->tpg, ctrl->val); | ||
304 | break; | ||
305 | case V4L2_CID_HFLIP: | ||
306 | tpg_s_hflip(&vsen->tpg, ctrl->val); | ||
307 | break; | ||
308 | case V4L2_CID_VFLIP: | ||
309 | tpg_s_vflip(&vsen->tpg, ctrl->val); | ||
310 | break; | ||
311 | default: | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = { | ||
318 | .s_ctrl = vimc_sen_s_ctrl, | ||
319 | }; | ||
320 | |||
294 | static void vimc_sen_comp_unbind(struct device *comp, struct device *master, | 321 | static void vimc_sen_comp_unbind(struct device *comp, struct device *master, |
295 | void *master_data) | 322 | void *master_data) |
296 | { | 323 | { |
@@ -299,10 +326,28 @@ static void vimc_sen_comp_unbind(struct device *comp, struct device *master, | |||
299 | container_of(ved, struct vimc_sen_device, ved); | 326 | container_of(ved, struct vimc_sen_device, ved); |
300 | 327 | ||
301 | vimc_ent_sd_unregister(ved, &vsen->sd); | 328 | vimc_ent_sd_unregister(ved, &vsen->sd); |
329 | v4l2_ctrl_handler_free(&vsen->hdl); | ||
302 | tpg_free(&vsen->tpg); | 330 | tpg_free(&vsen->tpg); |
303 | kfree(vsen); | 331 | kfree(vsen); |
304 | } | 332 | } |
305 | 333 | ||
334 | /* Image Processing Controls */ | ||
335 | static const struct v4l2_ctrl_config vimc_sen_ctrl_class = { | ||
336 | .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY, | ||
337 | .id = VIMC_CID_VIMC_CLASS, | ||
338 | .name = "VIMC Controls", | ||
339 | .type = V4L2_CTRL_TYPE_CTRL_CLASS, | ||
340 | }; | ||
341 | |||
342 | static const struct v4l2_ctrl_config vimc_sen_ctrl_test_pattern = { | ||
343 | .ops = &vimc_sen_ctrl_ops, | ||
344 | .id = VIMC_CID_TEST_PATTERN, | ||
345 | .name = "Test Pattern", | ||
346 | .type = V4L2_CTRL_TYPE_MENU, | ||
347 | .max = TPG_PAT_NOISE, | ||
348 | .qmenu = tpg_pattern_strings, | ||
349 | }; | ||
350 | |||
306 | static int vimc_sen_comp_bind(struct device *comp, struct device *master, | 351 | static int vimc_sen_comp_bind(struct device *comp, struct device *master, |
307 | void *master_data) | 352 | void *master_data) |
308 | { | 353 | { |
@@ -316,6 +361,20 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, | |||
316 | if (!vsen) | 361 | if (!vsen) |
317 | return -ENOMEM; | 362 | return -ENOMEM; |
318 | 363 | ||
364 | v4l2_ctrl_handler_init(&vsen->hdl, 4); | ||
365 | |||
366 | v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_class, NULL); | ||
367 | v4l2_ctrl_new_custom(&vsen->hdl, &vimc_sen_ctrl_test_pattern, NULL); | ||
368 | v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, | ||
369 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
370 | v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, | ||
371 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
372 | vsen->sd.ctrl_handler = &vsen->hdl; | ||
373 | if (vsen->hdl.error) { | ||
374 | ret = vsen->hdl.error; | ||
375 | goto err_free_vsen; | ||
376 | } | ||
377 | |||
319 | /* Initialize ved and sd */ | 378 | /* Initialize ved and sd */ |
320 | ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev, | 379 | ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev, |
321 | pdata->entity_name, | 380 | pdata->entity_name, |
@@ -323,7 +382,7 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, | |||
323 | (const unsigned long[1]) {MEDIA_PAD_FL_SOURCE}, | 382 | (const unsigned long[1]) {MEDIA_PAD_FL_SOURCE}, |
324 | &vimc_sen_ops); | 383 | &vimc_sen_ops); |
325 | if (ret) | 384 | if (ret) |
326 | goto err_free_vsen; | 385 | goto err_free_hdl; |
327 | 386 | ||
328 | dev_set_drvdata(comp, &vsen->ved); | 387 | dev_set_drvdata(comp, &vsen->ved); |
329 | vsen->dev = comp; | 388 | vsen->dev = comp; |
@@ -342,6 +401,8 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, | |||
342 | 401 | ||
343 | err_unregister_ent_sd: | 402 | err_unregister_ent_sd: |
344 | vimc_ent_sd_unregister(&vsen->ved, &vsen->sd); | 403 | vimc_ent_sd_unregister(&vsen->ved, &vsen->sd); |
404 | err_free_hdl: | ||
405 | v4l2_ctrl_handler_free(&vsen->hdl); | ||
345 | err_free_vsen: | 406 | err_free_vsen: |
346 | kfree(vsen); | 407 | kfree(vsen); |
347 | 408 | ||