]>
Commit | Line | Data |
---|---|---|
d5048c9a | 1 | |
bc125106 HK |
2 | /* |
3 | * The Capture code for Fujitsu M-5MOLS ISP | |
4 | * | |
5 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | |
c3070113 | 6 | * Author: HeungJun Kim <riverful.kim@samsung.com> |
bc125106 HK |
7 | * |
8 | * Copyright (C) 2009 Samsung Electronics Co., Ltd. | |
c3070113 | 9 | * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com> |
bc125106 HK |
10 | * |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation; either version 2 of the License, or | |
14 | * (at your option) any later version. | |
15 | */ | |
16 | ||
17 | #include <linux/i2c.h> | |
18 | #include <linux/slab.h> | |
19 | #include <linux/irq.h> | |
20 | #include <linux/interrupt.h> | |
21 | #include <linux/delay.h> | |
bc125106 HK |
22 | #include <linux/gpio.h> |
23 | #include <linux/regulator/consumer.h> | |
24 | #include <linux/videodev2.h> | |
bc125106 HK |
25 | #include <media/v4l2-ctrls.h> |
26 | #include <media/v4l2-device.h> | |
27 | #include <media/v4l2-subdev.h> | |
b5dcee22 | 28 | #include <media/i2c/m5mols.h> |
d647f0b7 | 29 | #include <media/drv-intf/exynos-fimc.h> |
bc125106 HK |
30 | |
31 | #include "m5mols.h" | |
32 | #include "m5mols_reg.h" | |
33 | ||
bc125106 HK |
34 | /** |
35 | * m5mols_read_rational - I2C read of a rational number | |
897aa67a MCC |
36 | * @sd: sub-device, as pointed by struct v4l2_subdev |
37 | * @addr_num: numerator register | |
38 | * @addr_den: denominator register | |
39 | * @val: place to store the division result | |
bc125106 HK |
40 | * |
41 | * Read numerator and denominator from registers @addr_num and @addr_den | |
42 | * respectively and return the division result in @val. | |
43 | */ | |
44 | static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, | |
45 | u32 addr_den, u32 *val) | |
46 | { | |
47 | u32 num, den; | |
48 | ||
57644f56 | 49 | int ret = m5mols_read_u32(sd, addr_num, &num); |
bc125106 | 50 | if (!ret) |
57644f56 | 51 | ret = m5mols_read_u32(sd, addr_den, &den); |
bc125106 HK |
52 | if (ret) |
53 | return ret; | |
54 | *val = den == 0 ? 0 : num / den; | |
55 | return ret; | |
56 | } | |
57 | ||
58 | /** | |
59 | * m5mols_capture_info - Gather captured image information | |
897aa67a | 60 | * @info: M-5MOLS driver data structure |
bc125106 HK |
61 | * |
62 | * For now it gathers only EXIF information and file size. | |
63 | */ | |
64 | static int m5mols_capture_info(struct m5mols_info *info) | |
65 | { | |
66 | struct m5mols_exif *exif = &info->cap.exif; | |
67 | struct v4l2_subdev *sd = &info->sd; | |
68 | int ret; | |
69 | ||
70 | ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU, | |
71 | EXIF_INFO_EXPTIME_DE, &exif->exposure_time); | |
72 | if (ret) | |
73 | return ret; | |
74 | ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE, | |
75 | &exif->shutter_speed); | |
76 | if (ret) | |
77 | return ret; | |
78 | ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE, | |
79 | &exif->aperture); | |
80 | if (ret) | |
81 | return ret; | |
82 | ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE, | |
83 | &exif->brightness); | |
84 | if (ret) | |
85 | return ret; | |
86 | ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE, | |
87 | &exif->exposure_bias); | |
88 | if (ret) | |
89 | return ret; | |
90 | ||
57644f56 | 91 | ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed); |
bc125106 | 92 | if (!ret) |
57644f56 | 93 | ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash); |
bc125106 | 94 | if (!ret) |
57644f56 | 95 | ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr); |
bc125106 | 96 | if (!ret) |
57644f56 | 97 | ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval); |
bc125106 HK |
98 | if (ret) |
99 | return ret; | |
100 | ||
101 | if (!ret) | |
57644f56 | 102 | ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main); |
bc125106 | 103 | if (!ret) |
57644f56 | 104 | ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb); |
bc125106 HK |
105 | if (!ret) |
106 | info->cap.total = info->cap.main + info->cap.thumb; | |
107 | ||
108 | return ret; | |
109 | } | |
110 | ||
111 | int m5mols_start_capture(struct m5mols_info *info) | |
112 | { | |
ab7ef224 | 113 | unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE; |
bc125106 | 114 | struct v4l2_subdev *sd = &info->sd; |
bc125106 HK |
115 | int ret; |
116 | ||
117 | /* | |
92e93a1f HK |
118 | * Synchronize the controls, set the capture frame resolution and color |
119 | * format. The frame capture is initiated during switching from Monitor | |
120 | * to Capture mode. | |
bc125106 | 121 | */ |
3c5da0ba | 122 | ret = m5mols_set_mode(info, REG_MONITOR); |
bc125106 | 123 | if (!ret) |
5d4294b8 | 124 | ret = m5mols_restore_controls(info); |
bc125106 | 125 | if (!ret) |
92e93a1f HK |
126 | ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); |
127 | if (!ret) | |
9346459a | 128 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution); |
ab7ef224 SN |
129 | if (!ret) |
130 | ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize); | |
bc125106 | 131 | if (!ret) |
3c5da0ba | 132 | ret = m5mols_set_mode(info, REG_CAPTURE); |
ce808a47 | 133 | if (!ret) |
92e93a1f | 134 | /* Wait until a frame is captured to ISP internal memory */ |
ce808a47 | 135 | ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); |
bc125106 HK |
136 | if (ret) |
137 | return ret; | |
92e93a1f | 138 | |
bc125106 | 139 | /* |
92e93a1f | 140 | * Initiate the captured data transfer to a MIPI-CSI receiver. |
bc125106 HK |
141 | */ |
142 | ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); | |
bc125106 HK |
143 | if (!ret) |
144 | ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); | |
145 | if (!ret) { | |
d5048c9a SN |
146 | bool captured = false; |
147 | unsigned int size; | |
148 | ||
bc125106 | 149 | /* Wait for the capture completion interrupt */ |
ce808a47 HK |
150 | ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); |
151 | if (!ret) { | |
d5048c9a | 152 | captured = true; |
bc125106 | 153 | ret = m5mols_capture_info(info); |
bc125106 | 154 | } |
d5048c9a SN |
155 | size = captured ? info->cap.main : 0; |
156 | v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n", | |
157 | __func__, size, info->cap.thumb); | |
158 | ||
159 | v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size); | |
bc125106 HK |
160 | } |
161 | ||
ce808a47 | 162 | return ret; |
bc125106 | 163 | } |