aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-09-20 07:16:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-10-01 19:59:36 -0400
commit5565a2ad47cdd8e697a28137bd8379455667bc1c (patch)
treed4d7f322962faa8edd99f3f18f135cd7ebf4efe2
parent05fb4da441c9197a59d537cf7f88522716287c61 (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.h18
-rw-r--r--drivers/media/i2c/m5mols/m5mols_core.c77
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 */
186struct m5mols_info { 187struct 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
563static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, 568static 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
595static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, 602static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
@@ -661,20 +668,25 @@ static int m5mols_start_monitor(struct m5mols_info *info)
661static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) 668static 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
680static const struct v4l2_subdev_video_ops m5mols_video_ops = { 692static 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 */
789static 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) {