diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-08-25 10:44:15 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 23:18:39 -0400 |
commit | 2840d2497b912f25d2957477faa1c922ddd733e0 (patch) | |
tree | 0cb0fe8ced5e55236c448ab001c4c50faeaa3411 | |
parent | a813d01f823259d1b27668c2149785515843a7eb (diff) |
V4L/DVB (12513): soc-camera: add support for camera-host controls
Until now soc-camera only supported client (sensor) controls. This patch
enables camera-host drivers to implement their own controls too.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/soc_camera.c | 24 | ||||
-rw-r--r-- | include/media/soc_camera.h | 4 |
2 files changed, 28 insertions, 0 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 0a1cb40bfbf6..b3fb8f290ad5 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -633,6 +633,7 @@ static int soc_camera_queryctrl(struct file *file, void *priv, | |||
633 | { | 633 | { |
634 | struct soc_camera_file *icf = file->private_data; | 634 | struct soc_camera_file *icf = file->private_data; |
635 | struct soc_camera_device *icd = icf->icd; | 635 | struct soc_camera_device *icd = icf->icd; |
636 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
636 | int i; | 637 | int i; |
637 | 638 | ||
638 | WARN_ON(priv != file->private_data); | 639 | WARN_ON(priv != file->private_data); |
@@ -640,6 +641,15 @@ static int soc_camera_queryctrl(struct file *file, void *priv, | |||
640 | if (!qc->id) | 641 | if (!qc->id) |
641 | return -EINVAL; | 642 | return -EINVAL; |
642 | 643 | ||
644 | /* First check host controls */ | ||
645 | for (i = 0; i < ici->ops->num_controls; i++) | ||
646 | if (qc->id == ici->ops->controls[i].id) { | ||
647 | memcpy(qc, &(ici->ops->controls[i]), | ||
648 | sizeof(*qc)); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | /* Then device controls */ | ||
643 | for (i = 0; i < icd->ops->num_controls; i++) | 653 | for (i = 0; i < icd->ops->num_controls; i++) |
644 | if (qc->id == icd->ops->controls[i].id) { | 654 | if (qc->id == icd->ops->controls[i].id) { |
645 | memcpy(qc, &(icd->ops->controls[i]), | 655 | memcpy(qc, &(icd->ops->controls[i]), |
@@ -656,6 +666,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, | |||
656 | struct soc_camera_file *icf = file->private_data; | 666 | struct soc_camera_file *icf = file->private_data; |
657 | struct soc_camera_device *icd = icf->icd; | 667 | struct soc_camera_device *icd = icf->icd; |
658 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 668 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
669 | int ret; | ||
659 | 670 | ||
660 | WARN_ON(priv != file->private_data); | 671 | WARN_ON(priv != file->private_data); |
661 | 672 | ||
@@ -672,6 +683,12 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, | |||
672 | return 0; | 683 | return 0; |
673 | } | 684 | } |
674 | 685 | ||
686 | if (ici->ops->get_ctrl) { | ||
687 | ret = ici->ops->get_ctrl(icd, ctrl); | ||
688 | if (ret != -ENOIOCTLCMD) | ||
689 | return ret; | ||
690 | } | ||
691 | |||
675 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); | 692 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); |
676 | } | 693 | } |
677 | 694 | ||
@@ -681,9 +698,16 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, | |||
681 | struct soc_camera_file *icf = file->private_data; | 698 | struct soc_camera_file *icf = file->private_data; |
682 | struct soc_camera_device *icd = icf->icd; | 699 | struct soc_camera_device *icd = icf->icd; |
683 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 700 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
701 | int ret; | ||
684 | 702 | ||
685 | WARN_ON(priv != file->private_data); | 703 | WARN_ON(priv != file->private_data); |
686 | 704 | ||
705 | if (ici->ops->set_ctrl) { | ||
706 | ret = ici->ops->set_ctrl(icd, ctrl); | ||
707 | if (ret != -ENOIOCTLCMD) | ||
708 | return ret; | ||
709 | } | ||
710 | |||
687 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); | 711 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); |
688 | } | 712 | } |
689 | 713 | ||
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 3bc5b6b20f64..2d116bbbcce1 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -83,7 +83,11 @@ struct soc_camera_host_ops { | |||
83 | int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); | 83 | int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); |
84 | int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); | 84 | int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); |
85 | int (*set_bus_param)(struct soc_camera_device *, __u32); | 85 | int (*set_bus_param)(struct soc_camera_device *, __u32); |
86 | int (*get_ctrl)(struct soc_camera_device *, struct v4l2_control *); | ||
87 | int (*set_ctrl)(struct soc_camera_device *, struct v4l2_control *); | ||
86 | unsigned int (*poll)(struct file *, poll_table *); | 88 | unsigned int (*poll)(struct file *, poll_table *); |
89 | const struct v4l2_queryctrl *controls; | ||
90 | int num_controls; | ||
87 | }; | 91 | }; |
88 | 92 | ||
89 | #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) | 93 | #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) |