diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2012-09-20 07:16:45 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-01 19:59:36 -0400 |
commit | 5565a2ad47cdd8e697a28137bd8379455667bc1c (patch) | |
tree | d4d7f322962faa8edd99f3f18f135cd7ebf4efe2 | |
parent | 05fb4da441c9197a59d537cf7f88522716287c61 (diff) |
[media] m5mols: Protect driver data with a mutex
Without the locking the driver's data could get corrupted when the subdev
is accessed from user space and from host driver by multiple processes.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols.h | 18 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_core.c | 77 |
2 files changed, 62 insertions, 33 deletions
diff --git a/drivers/media/i2c/m5mols/m5mols.h b/drivers/media/i2c/m5mols/m5mols.h index 527e7b2965df..86c815be348c 100644 --- a/drivers/media/i2c/m5mols/m5mols.h +++ b/drivers/media/i2c/m5mols/m5mols.h | |||
@@ -155,8 +155,6 @@ struct m5mols_version { | |||
155 | * @pdata: platform data | 155 | * @pdata: platform data |
156 | * @sd: v4l-subdev instance | 156 | * @sd: v4l-subdev instance |
157 | * @pad: media pad | 157 | * @pad: media pad |
158 | * @ffmt: current fmt according to resolution type | ||
159 | * @res_type: current resolution type | ||
160 | * @irq_waitq: waitqueue for the capture | 158 | * @irq_waitq: waitqueue for the capture |
161 | * @irq_done: set to 1 in the interrupt handler | 159 | * @irq_done: set to 1 in the interrupt handler |
162 | * @handle: control handler | 160 | * @handle: control handler |
@@ -174,6 +172,10 @@ struct m5mols_version { | |||
174 | * @wdr: wide dynamic range control | 172 | * @wdr: wide dynamic range control |
175 | * @stabilization: image stabilization control | 173 | * @stabilization: image stabilization control |
176 | * @jpeg_quality: JPEG compression quality control | 174 | * @jpeg_quality: JPEG compression quality control |
175 | * @set_power: optional power callback to the board code | ||
176 | * @lock: mutex protecting the structure fields below | ||
177 | * @ffmt: current fmt according to resolution type | ||
178 | * @res_type: current resolution type | ||
177 | * @ver: information of the version | 179 | * @ver: information of the version |
178 | * @cap: the capture mode attributes | 180 | * @cap: the capture mode attributes |
179 | * @isp_ready: 1 when the ISP controller has completed booting | 181 | * @isp_ready: 1 when the ISP controller has completed booting |
@@ -181,14 +183,11 @@ struct m5mols_version { | |||
181 | * @ctrl_sync: 1 when the control handler state is restored in H/W | 183 | * @ctrl_sync: 1 when the control handler state is restored in H/W |
182 | * @resolution: register value for current resolution | 184 | * @resolution: register value for current resolution |
183 | * @mode: register value for current operation mode | 185 | * @mode: register value for current operation mode |
184 | * @set_power: optional power callback to the board code | ||
185 | */ | 186 | */ |
186 | struct m5mols_info { | 187 | struct m5mols_info { |
187 | const struct m5mols_platform_data *pdata; | 188 | const struct m5mols_platform_data *pdata; |
188 | struct v4l2_subdev sd; | 189 | struct v4l2_subdev sd; |
189 | struct media_pad pad; | 190 | struct media_pad pad; |
190 | struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; | ||
191 | int res_type; | ||
192 | 191 | ||
193 | wait_queue_head_t irq_waitq; | 192 | wait_queue_head_t irq_waitq; |
194 | atomic_t irq_done; | 193 | atomic_t irq_done; |
@@ -216,6 +215,13 @@ struct m5mols_info { | |||
216 | struct v4l2_ctrl *stabilization; | 215 | struct v4l2_ctrl *stabilization; |
217 | struct v4l2_ctrl *jpeg_quality; | 216 | struct v4l2_ctrl *jpeg_quality; |
218 | 217 | ||
218 | int (*set_power)(struct device *dev, int on); | ||
219 | |||
220 | struct mutex lock; | ||
221 | |||
222 | struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; | ||
223 | int res_type; | ||
224 | |||
219 | struct m5mols_version ver; | 225 | struct m5mols_version ver; |
220 | struct m5mols_capture cap; | 226 | struct m5mols_capture cap; |
221 | 227 | ||
@@ -225,8 +231,6 @@ struct m5mols_info { | |||
225 | 231 | ||
226 | u8 resolution; | 232 | u8 resolution; |
227 | u8 mode; | 233 | u8 mode; |
228 | |||
229 | int (*set_power)(struct device *dev, int on); | ||
230 | }; | 234 | }; |
231 | 235 | ||
232 | #define is_available_af(__info) (__info->ver.af) | 236 | #define is_available_af(__info) (__info->ver.af) |
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 57293aa7512b..2f490ef26c38 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c | |||
@@ -551,13 +551,18 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
551 | { | 551 | { |
552 | struct m5mols_info *info = to_m5mols(sd); | 552 | struct m5mols_info *info = to_m5mols(sd); |
553 | struct v4l2_mbus_framefmt *format; | 553 | struct v4l2_mbus_framefmt *format; |
554 | int ret = 0; | ||
555 | |||
556 | mutex_lock(&info->lock); | ||
554 | 557 | ||
555 | format = __find_format(info, fh, fmt->which, info->res_type); | 558 | format = __find_format(info, fh, fmt->which, info->res_type); |
556 | if (!format) | 559 | if (!format) |
557 | return -EINVAL; | 560 | fmt->format = *format; |
561 | else | ||
562 | ret = -EINVAL; | ||
558 | 563 | ||
559 | fmt->format = *format; | 564 | mutex_unlock(&info->lock); |
560 | return 0; | 565 | return ret; |
561 | } | 566 | } |
562 | 567 | ||
563 | static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | 568 | static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, |
@@ -578,6 +583,7 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
578 | if (!sfmt) | 583 | if (!sfmt) |
579 | return 0; | 584 | return 0; |
580 | 585 | ||
586 | mutex_lock(&info->lock); | ||
581 | 587 | ||
582 | format->code = m5mols_default_ffmt[type].code; | 588 | format->code = m5mols_default_ffmt[type].code; |
583 | format->colorspace = V4L2_COLORSPACE_JPEG; | 589 | format->colorspace = V4L2_COLORSPACE_JPEG; |
@@ -589,7 +595,8 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
589 | info->res_type = type; | 595 | info->res_type = type; |
590 | } | 596 | } |
591 | 597 | ||
592 | return 0; | 598 | mutex_unlock(&info->lock); |
599 | return ret; | ||
593 | } | 600 | } |
594 | 601 | ||
595 | static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, | 602 | static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, |
@@ -661,20 +668,25 @@ static int m5mols_start_monitor(struct m5mols_info *info) | |||
661 | static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) | 668 | static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) |
662 | { | 669 | { |
663 | struct m5mols_info *info = to_m5mols(sd); | 670 | struct m5mols_info *info = to_m5mols(sd); |
664 | u32 code = info->ffmt[info->res_type].code; | 671 | u32 code; |
672 | int ret; | ||
665 | 673 | ||
666 | if (enable) { | 674 | mutex_lock(&info->lock); |
667 | int ret = -EINVAL; | 675 | code = info->ffmt[info->res_type].code; |
668 | 676 | ||
677 | if (enable) { | ||
669 | if (is_code(code, M5MOLS_RESTYPE_MONITOR)) | 678 | if (is_code(code, M5MOLS_RESTYPE_MONITOR)) |
670 | ret = m5mols_start_monitor(info); | 679 | ret = m5mols_start_monitor(info); |
671 | if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) | 680 | if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) |
672 | ret = m5mols_start_capture(info); | 681 | ret = m5mols_start_capture(info); |
673 | 682 | else | |
674 | return ret; | 683 | ret = -EINVAL; |
684 | } else { | ||
685 | ret = m5mols_set_mode(info, REG_PARAMETER); | ||
675 | } | 686 | } |
676 | 687 | ||
677 | return m5mols_set_mode(info, REG_PARAMETER); | 688 | mutex_unlock(&info->lock); |
689 | return ret; | ||
678 | } | 690 | } |
679 | 691 | ||
680 | static const struct v4l2_subdev_video_ops m5mols_video_ops = { | 692 | static const struct v4l2_subdev_video_ops m5mols_video_ops = { |
@@ -773,6 +785,20 @@ static int m5mols_fw_start(struct v4l2_subdev *sd) | |||
773 | return ret; | 785 | return ret; |
774 | } | 786 | } |
775 | 787 | ||
788 | /* Execute the lens soft-landing algorithm */ | ||
789 | static int m5mols_auto_focus_stop(struct m5mols_info *info) | ||
790 | { | ||
791 | int ret; | ||
792 | |||
793 | ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); | ||
794 | if (!ret) | ||
795 | ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF); | ||
796 | if (!ret) | ||
797 | ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE, | ||
798 | 0xff, -1); | ||
799 | return ret; | ||
800 | } | ||
801 | |||
776 | /** | 802 | /** |
777 | * m5mols_s_power - Main sensor power control function | 803 | * m5mols_s_power - Main sensor power control function |
778 | * | 804 | * |
@@ -785,29 +811,26 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on) | |||
785 | struct m5mols_info *info = to_m5mols(sd); | 811 | struct m5mols_info *info = to_m5mols(sd); |
786 | int ret; | 812 | int ret; |
787 | 813 | ||
814 | mutex_lock(&info->lock); | ||
815 | |||
788 | if (on) { | 816 | if (on) { |
789 | ret = m5mols_sensor_power(info, true); | 817 | ret = m5mols_sensor_power(info, true); |
790 | if (!ret) | 818 | if (!ret) |
791 | ret = m5mols_fw_start(sd); | 819 | ret = m5mols_fw_start(sd); |
792 | return ret; | 820 | } else { |
793 | } | 821 | if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { |
822 | ret = m5mols_set_mode(info, REG_MONITOR); | ||
823 | if (!ret) | ||
824 | ret = m5mols_auto_focus_stop(info); | ||
825 | if (ret < 0) | ||
826 | v4l2_warn(sd, "Soft landing lens failed\n"); | ||
827 | } | ||
828 | ret = m5mols_sensor_power(info, false); | ||
794 | 829 | ||
795 | if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { | 830 | info->ctrl_sync = 0; |
796 | ret = m5mols_set_mode(info, REG_MONITOR); | ||
797 | if (!ret) | ||
798 | ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); | ||
799 | if (!ret) | ||
800 | ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); | ||
801 | if (!ret) | ||
802 | ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE, | ||
803 | 0xff, -1); | ||
804 | if (ret < 0) | ||
805 | v4l2_warn(sd, "Soft landing lens failed\n"); | ||
806 | } | 831 | } |
807 | 832 | ||
808 | ret = m5mols_sensor_power(info, false); | 833 | mutex_unlock(&info->lock); |
809 | info->ctrl_sync = 0; | ||
810 | |||
811 | return ret; | 834 | return ret; |
812 | } | 835 | } |
813 | 836 | ||
@@ -912,6 +935,8 @@ static int __devinit m5mols_probe(struct i2c_client *client, | |||
912 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 935 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; |
913 | 936 | ||
914 | init_waitqueue_head(&info->irq_waitq); | 937 | init_waitqueue_head(&info->irq_waitq); |
938 | mutex_init(&info->lock); | ||
939 | |||
915 | ret = request_irq(client->irq, m5mols_irq_handler, | 940 | ret = request_irq(client->irq, m5mols_irq_handler, |
916 | IRQF_TRIGGER_RISING, MODULE_NAME, sd); | 941 | IRQF_TRIGGER_RISING, MODULE_NAME, sd); |
917 | if (ret) { | 942 | if (ret) { |