diff options
author | Oliver Brown <oliver.brown@freescale.com> | 2013-09-08 16:05:28 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:05:37 -0400 |
commit | 16afcaab006ca76784cf64e67678f4b754f84500 (patch) | |
tree | a7159b266bb3cd3abb8d6d34eacddca5b3b4cd70 | |
parent | 9ec0aa2f9c10c1ca6724511b75c3e5bd48dc4fa2 (diff) |
ENGR00278667-1 [mxc_v4l2_capture]: Add adv7180 driver in 3.10.9 Kernel
Copied file from 3.5.7 Kernel
commit de6459732a23402cbe520812bf4202299330fd68
Author: Oliver Brown <oliver.brown@freescale.com>
Date: Mon Jun 24 16:41:17 2013 -0500
Added missing call to clk_disable_unprepare() in adv7180_probe.
Signed-off-by: Oliver Brown <oliver.brown@freescale.com>
-rw-r--r-- | drivers/media/platform/mxc/capture/Kconfig | 6 | ||||
-rw-r--r-- | drivers/media/platform/mxc/capture/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/platform/mxc/capture/adv7180.c | 1344 |
3 files changed, 1353 insertions, 0 deletions
diff --git a/drivers/media/platform/mxc/capture/Kconfig b/drivers/media/platform/mxc/capture/Kconfig index 6f253c1e45f5..cee7aa31f2d1 100644 --- a/drivers/media/platform/mxc/capture/Kconfig +++ b/drivers/media/platform/mxc/capture/Kconfig | |||
@@ -30,6 +30,12 @@ config MXC_CAMERA_OV5640_MIPI | |||
30 | ---help--- | 30 | ---help--- |
31 | If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here. | 31 | If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here. |
32 | 32 | ||
33 | config MXC_TVIN_ADV7180 | ||
34 | tristate "Analog Device adv7180 TV Decoder Input support" | ||
35 | depends on !VIDEO_MXC_EMMA_CAMERA && I2C | ||
36 | ---help--- | ||
37 | If you plan to use the adv7180 video decoder with your MXC system, say Y here. | ||
38 | |||
33 | choice | 39 | choice |
34 | prompt "Select Overlay Rounting" | 40 | prompt "Select Overlay Rounting" |
35 | default MXC_IPU_DEVICE_QUEUE_SDC | 41 | default MXC_IPU_DEVICE_QUEUE_SDC |
diff --git a/drivers/media/platform/mxc/capture/Makefile b/drivers/media/platform/mxc/capture/Makefile index 0f5eb3d10192..4303c0a2ccdf 100644 --- a/drivers/media/platform/mxc/capture/Makefile +++ b/drivers/media/platform/mxc/capture/Makefile | |||
@@ -16,3 +16,6 @@ obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o | |||
16 | 16 | ||
17 | ov5640_camera_mipi-objs := ov5640_mipi.o | 17 | ov5640_camera_mipi-objs := ov5640_mipi.o |
18 | obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o | 18 | obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o |
19 | |||
20 | adv7180_tvin-objs := adv7180.o | ||
21 | obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o | ||
diff --git a/drivers/media/platform/mxc/capture/adv7180.c b/drivers/media/platform/mxc/capture/adv7180.c new file mode 100644 index 000000000000..ae17d7f25ff6 --- /dev/null +++ b/drivers/media/platform/mxc/capture/adv7180.c | |||
@@ -0,0 +1,1344 @@ | |||
1 | /* | ||
2 | * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * The code contained herein is licensed under the GNU General Public | ||
7 | * License. You may obtain a copy of the GNU General Public License | ||
8 | * Version 2 or later at the following locations: | ||
9 | * | ||
10 | * http://www.opensource.org/licenses/gpl-license.html | ||
11 | * http://www.gnu.org/copyleft/gpl.html | ||
12 | */ | ||
13 | |||
14 | /*! | ||
15 | * @file adv7180.c | ||
16 | * | ||
17 | * @brief Analog Device ADV7180 video decoder functions | ||
18 | * | ||
19 | * @ingroup Camera | ||
20 | */ | ||
21 | |||
22 | #include <linux/clk.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/of_device.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <linux/pinctrl/consumer.h> | ||
31 | #include <linux/regulator/consumer.h> | ||
32 | #include <media/v4l2-chip-ident.h> | ||
33 | #include <media/v4l2-int-device.h> | ||
34 | #include "mxc_v4l2_capture.h" | ||
35 | |||
36 | #define ADV7180_VOLTAGE_ANALOG 1800000 | ||
37 | #define ADV7180_VOLTAGE_DIGITAL_CORE 1800000 | ||
38 | #define ADV7180_VOLTAGE_DIGITAL_IO 3300000 | ||
39 | #define ADV7180_VOLTAGE_PLL 1800000 | ||
40 | |||
41 | static struct regulator *dvddio_regulator; | ||
42 | static struct regulator *dvdd_regulator; | ||
43 | static struct regulator *avdd_regulator; | ||
44 | static struct regulator *pvdd_regulator; | ||
45 | static int pwn_gpio; | ||
46 | |||
47 | static int adv7180_probe(struct i2c_client *adapter, | ||
48 | const struct i2c_device_id *id); | ||
49 | static int adv7180_detach(struct i2c_client *client); | ||
50 | |||
51 | static const struct i2c_device_id adv7180_id[] = { | ||
52 | {"adv7180", 0}, | ||
53 | {}, | ||
54 | }; | ||
55 | |||
56 | MODULE_DEVICE_TABLE(i2c, adv7180_id); | ||
57 | |||
58 | static struct i2c_driver adv7180_i2c_driver = { | ||
59 | .driver = { | ||
60 | .owner = THIS_MODULE, | ||
61 | .name = "adv7180", | ||
62 | }, | ||
63 | .probe = adv7180_probe, | ||
64 | .remove = adv7180_detach, | ||
65 | .id_table = adv7180_id, | ||
66 | }; | ||
67 | |||
68 | /*! | ||
69 | * Maintains the information on the current state of the sensor. | ||
70 | */ | ||
71 | struct sensor { | ||
72 | struct sensor_data sen; | ||
73 | v4l2_std_id std_id; | ||
74 | } adv7180_data; | ||
75 | |||
76 | |||
77 | /*! List of input video formats supported. The video formats is corresponding | ||
78 | * with v4l2 id in video_fmt_t | ||
79 | */ | ||
80 | typedef enum { | ||
81 | ADV7180_NTSC = 0, /*!< Locked on (M) NTSC video signal. */ | ||
82 | ADV7180_PAL, /*!< (B, G, H, I, N)PAL video signal. */ | ||
83 | ADV7180_NOT_LOCKED, /*!< Not locked on a signal. */ | ||
84 | } video_fmt_idx; | ||
85 | |||
86 | /*! Number of video standards supported (including 'not locked' signal). */ | ||
87 | #define ADV7180_STD_MAX (ADV7180_PAL + 1) | ||
88 | |||
89 | /*! Video format structure. */ | ||
90 | typedef struct { | ||
91 | int v4l2_id; /*!< Video for linux ID. */ | ||
92 | char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */ | ||
93 | u16 raw_width; /*!< Raw width. */ | ||
94 | u16 raw_height; /*!< Raw height. */ | ||
95 | u16 active_width; /*!< Active width. */ | ||
96 | u16 active_height; /*!< Active height. */ | ||
97 | } video_fmt_t; | ||
98 | |||
99 | /*! Description of video formats supported. | ||
100 | * | ||
101 | * PAL: raw=720x625, active=720x576. | ||
102 | * NTSC: raw=720x525, active=720x480. | ||
103 | */ | ||
104 | static video_fmt_t video_fmts[] = { | ||
105 | { /*! NTSC */ | ||
106 | .v4l2_id = V4L2_STD_NTSC, | ||
107 | .name = "NTSC", | ||
108 | .raw_width = 720, /* SENS_FRM_WIDTH */ | ||
109 | .raw_height = 525, /* SENS_FRM_HEIGHT */ | ||
110 | .active_width = 720, /* ACT_FRM_WIDTH plus 1 */ | ||
111 | .active_height = 480, /* ACT_FRM_WIDTH plus 1 */ | ||
112 | }, | ||
113 | { /*! (B, G, H, I, N) PAL */ | ||
114 | .v4l2_id = V4L2_STD_PAL, | ||
115 | .name = "PAL", | ||
116 | .raw_width = 720, | ||
117 | .raw_height = 625, | ||
118 | .active_width = 720, | ||
119 | .active_height = 576, | ||
120 | }, | ||
121 | { /*! Unlocked standard */ | ||
122 | .v4l2_id = V4L2_STD_ALL, | ||
123 | .name = "Autodetect", | ||
124 | .raw_width = 720, | ||
125 | .raw_height = 625, | ||
126 | .active_width = 720, | ||
127 | .active_height = 576, | ||
128 | }, | ||
129 | }; | ||
130 | |||
131 | /*!* Standard index of ADV7180. */ | ||
132 | static video_fmt_idx video_idx = ADV7180_PAL; | ||
133 | |||
134 | /*! @brief This mutex is used to provide mutual exclusion. | ||
135 | * | ||
136 | * Create a mutex that can be used to provide mutually exclusive | ||
137 | * read/write access to the globally accessible data structures | ||
138 | * and variables that were defined above. | ||
139 | */ | ||
140 | static DEFINE_MUTEX(mutex); | ||
141 | |||
142 | #define IF_NAME "adv7180" | ||
143 | #define ADV7180_INPUT_CTL 0x00 /* Input Control */ | ||
144 | #define ADV7180_STATUS_1 0x10 /* Status #1 */ | ||
145 | #define ADV7180_BRIGHTNESS 0x0a /* Brightness */ | ||
146 | #define ADV7180_IDENT 0x11 /* IDENT */ | ||
147 | #define ADV7180_VSYNC_FIELD_CTL_1 0x31 /* VSYNC Field Control #1 */ | ||
148 | #define ADV7180_MANUAL_WIN_CTL 0x3d /* Manual Window Control */ | ||
149 | #define ADV7180_SD_SATURATION_CB 0xe3 /* SD Saturation Cb */ | ||
150 | #define ADV7180_SD_SATURATION_CR 0xe4 /* SD Saturation Cr */ | ||
151 | #define ADV7180_PWR_MNG 0x0f /* Power Management */ | ||
152 | |||
153 | /* supported controls */ | ||
154 | /* This hasn't been fully implemented yet. | ||
155 | * This is how it should work, though. */ | ||
156 | static struct v4l2_queryctrl adv7180_qctrl[] = { | ||
157 | { | ||
158 | .id = V4L2_CID_BRIGHTNESS, | ||
159 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
160 | .name = "Brightness", | ||
161 | .minimum = 0, /* check this value */ | ||
162 | .maximum = 255, /* check this value */ | ||
163 | .step = 1, /* check this value */ | ||
164 | .default_value = 127, /* check this value */ | ||
165 | .flags = 0, | ||
166 | }, { | ||
167 | .id = V4L2_CID_SATURATION, | ||
168 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
169 | .name = "Saturation", | ||
170 | .minimum = 0, /* check this value */ | ||
171 | .maximum = 255, /* check this value */ | ||
172 | .step = 0x1, /* check this value */ | ||
173 | .default_value = 127, /* check this value */ | ||
174 | .flags = 0, | ||
175 | } | ||
176 | }; | ||
177 | |||
178 | static inline void adv7180_power_down(int enable) | ||
179 | { | ||
180 | gpio_set_value_cansleep(pwn_gpio, !enable); | ||
181 | msleep(2); | ||
182 | } | ||
183 | |||
184 | static int adv7180_regulator_enable(struct device *dev) | ||
185 | { | ||
186 | int ret = 0; | ||
187 | |||
188 | dvddio_regulator = devm_regulator_get(dev, "DOVDD"); | ||
189 | |||
190 | if (!IS_ERR(dvddio_regulator)) { | ||
191 | regulator_set_voltage(dvddio_regulator, | ||
192 | ADV7180_VOLTAGE_DIGITAL_IO, | ||
193 | ADV7180_VOLTAGE_DIGITAL_IO); | ||
194 | ret = regulator_enable(dvddio_regulator); | ||
195 | if (ret) { | ||
196 | dev_err(dev, "set io voltage failed\n"); | ||
197 | return ret; | ||
198 | } else { | ||
199 | dev_dbg(dev, "set io voltage ok\n"); | ||
200 | } | ||
201 | } else { | ||
202 | dev_warn(dev, "cannot get io voltage\n"); | ||
203 | } | ||
204 | |||
205 | dvdd_regulator = devm_regulator_get(dev, "DVDD"); | ||
206 | if (!IS_ERR(dvdd_regulator)) { | ||
207 | regulator_set_voltage(dvdd_regulator, | ||
208 | ADV7180_VOLTAGE_DIGITAL_CORE, | ||
209 | ADV7180_VOLTAGE_DIGITAL_CORE); | ||
210 | ret = regulator_enable(dvdd_regulator); | ||
211 | if (ret) { | ||
212 | dev_err(dev, "set core voltage failed\n"); | ||
213 | return ret; | ||
214 | } else { | ||
215 | dev_dbg(dev, "set core voltage ok\n"); | ||
216 | } | ||
217 | } else { | ||
218 | dev_warn(dev, "cannot get core voltage\n"); | ||
219 | } | ||
220 | |||
221 | avdd_regulator = devm_regulator_get(dev, "AVDD"); | ||
222 | if (!IS_ERR(avdd_regulator)) { | ||
223 | regulator_set_voltage(avdd_regulator, | ||
224 | ADV7180_VOLTAGE_ANALOG, | ||
225 | ADV7180_VOLTAGE_ANALOG); | ||
226 | ret = regulator_enable(avdd_regulator); | ||
227 | if (ret) { | ||
228 | dev_err(dev, "set analog voltage failed\n"); | ||
229 | return ret; | ||
230 | } else { | ||
231 | dev_dbg(dev, "set analog voltage ok\n"); | ||
232 | } | ||
233 | } else { | ||
234 | dev_warn(dev, "cannot get analog voltage\n"); | ||
235 | } | ||
236 | |||
237 | pvdd_regulator = devm_regulator_get(dev, "PVDD"); | ||
238 | if (!IS_ERR(pvdd_regulator)) { | ||
239 | regulator_set_voltage(pvdd_regulator, | ||
240 | ADV7180_VOLTAGE_PLL, | ||
241 | ADV7180_VOLTAGE_PLL); | ||
242 | ret = regulator_enable(pvdd_regulator); | ||
243 | if (ret) { | ||
244 | dev_err(dev, "set pll voltage failed\n"); | ||
245 | return ret; | ||
246 | } else { | ||
247 | dev_dbg(dev, "set pll voltage ok\n"); | ||
248 | } | ||
249 | } else { | ||
250 | dev_warn(dev, "cannot get pll voltage\n"); | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | |||
257 | /*********************************************************************** | ||
258 | * I2C transfert. | ||
259 | ***********************************************************************/ | ||
260 | |||
261 | /*! Read one register from a ADV7180 i2c slave device. | ||
262 | * | ||
263 | * @param *reg register in the device we wish to access. | ||
264 | * | ||
265 | * @return 0 if success, an error code otherwise. | ||
266 | */ | ||
267 | static inline int adv7180_read(u8 reg) | ||
268 | { | ||
269 | int val; | ||
270 | |||
271 | val = i2c_smbus_read_byte_data(adv7180_data.sen.i2c_client, reg); | ||
272 | if (val < 0) { | ||
273 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
274 | "%s:read reg error: reg=%2x\n", __func__, reg); | ||
275 | return -1; | ||
276 | } | ||
277 | return val; | ||
278 | } | ||
279 | |||
280 | /*! Write one register of a ADV7180 i2c slave device. | ||
281 | * | ||
282 | * @param *reg register in the device we wish to access. | ||
283 | * | ||
284 | * @return 0 if success, an error code otherwise. | ||
285 | */ | ||
286 | static int adv7180_write_reg(u8 reg, u8 val) | ||
287 | { | ||
288 | s32 ret; | ||
289 | |||
290 | ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val); | ||
291 | if (ret < 0) { | ||
292 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
293 | "%s:write reg error:reg=%2x,val=%2x\n", __func__, | ||
294 | reg, val); | ||
295 | return -1; | ||
296 | } | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | /*********************************************************************** | ||
301 | * mxc_v4l2_capture interface. | ||
302 | ***********************************************************************/ | ||
303 | |||
304 | /*! | ||
305 | * Return attributes of current video standard. | ||
306 | * Since this device autodetects the current standard, this function also | ||
307 | * sets the values that need to be changed if the standard changes. | ||
308 | * There is no set std equivalent function. | ||
309 | * | ||
310 | * @return None. | ||
311 | */ | ||
312 | static void adv7180_get_std(v4l2_std_id *std) | ||
313 | { | ||
314 | int tmp; | ||
315 | int idx; | ||
316 | |||
317 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_get_std\n"); | ||
318 | |||
319 | /* Read the AD_RESULT to get the detect output video standard */ | ||
320 | tmp = adv7180_read(ADV7180_STATUS_1) & 0x70; | ||
321 | |||
322 | mutex_lock(&mutex); | ||
323 | if (tmp == 0x40) { | ||
324 | /* PAL */ | ||
325 | *std = V4L2_STD_PAL; | ||
326 | idx = ADV7180_PAL; | ||
327 | } else if (tmp == 0) { | ||
328 | /*NTSC*/ | ||
329 | *std = V4L2_STD_NTSC; | ||
330 | idx = ADV7180_NTSC; | ||
331 | } else { | ||
332 | *std = V4L2_STD_ALL; | ||
333 | idx = ADV7180_NOT_LOCKED; | ||
334 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
335 | "Got invalid video standard!\n"); | ||
336 | } | ||
337 | mutex_unlock(&mutex); | ||
338 | |||
339 | /* This assumes autodetect which this device uses. */ | ||
340 | if (*std != adv7180_data.std_id) { | ||
341 | video_idx = idx; | ||
342 | adv7180_data.std_id = *std; | ||
343 | adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width; | ||
344 | adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | /*********************************************************************** | ||
349 | * IOCTL Functions from v4l2_int_ioctl_desc. | ||
350 | ***********************************************************************/ | ||
351 | |||
352 | /*! | ||
353 | * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num | ||
354 | * s: pointer to standard V4L2 device structure | ||
355 | * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure | ||
356 | * | ||
357 | * Gets slave interface parameters. | ||
358 | * Calculates the required xclk value to support the requested | ||
359 | * clock parameters in p. This value is returned in the p | ||
360 | * parameter. | ||
361 | * | ||
362 | * vidioc_int_g_ifparm returns platform-specific information about the | ||
363 | * interface settings used by the sensor. | ||
364 | * | ||
365 | * Called on open. | ||
366 | */ | ||
367 | static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) | ||
368 | { | ||
369 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_ifparm\n"); | ||
370 | |||
371 | if (s == NULL) { | ||
372 | pr_err(" ERROR!! no slave device set!\n"); | ||
373 | return -1; | ||
374 | } | ||
375 | |||
376 | /* Initialize structure to 0s then set any non-0 values. */ | ||
377 | memset(p, 0, sizeof(*p)); | ||
378 | p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */ | ||
379 | p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; | ||
380 | p->u.bt656.nobt_hs_inv = 1; | ||
381 | p->u.bt656.bt_sync_correct = 1; | ||
382 | |||
383 | /* ADV7180 has a dedicated clock so no clock settings needed. */ | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | /*! | ||
389 | * Sets the camera power. | ||
390 | * | ||
391 | * s pointer to the camera device | ||
392 | * on if 1, power is to be turned on. 0 means power is to be turned off | ||
393 | * | ||
394 | * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num | ||
395 | * @s: pointer to standard V4L2 device structure | ||
396 | * @on: power state to which device is to be set | ||
397 | * | ||
398 | * Sets devices power state to requrested state, if possible. | ||
399 | * This is called on open, close, suspend and resume. | ||
400 | */ | ||
401 | static int ioctl_s_power(struct v4l2_int_device *s, int on) | ||
402 | { | ||
403 | struct sensor *sensor = s->priv; | ||
404 | |||
405 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_s_power\n"); | ||
406 | |||
407 | if (on && !sensor->sen.on) { | ||
408 | if (adv7180_write_reg(ADV7180_PWR_MNG, 0x04) != 0) | ||
409 | return -EIO; | ||
410 | |||
411 | /* | ||
412 | * FIXME:Additional 400ms to wait the chip to be stable? | ||
413 | * This is a workaround for preview scrolling issue. | ||
414 | */ | ||
415 | msleep(400); | ||
416 | } else if (!on && sensor->sen.on) { | ||
417 | if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0) | ||
418 | return -EIO; | ||
419 | } | ||
420 | |||
421 | sensor->sen.on = on; | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | /*! | ||
427 | * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl | ||
428 | * @s: pointer to standard V4L2 device structure | ||
429 | * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure | ||
430 | * | ||
431 | * Returns the sensor's video CAPTURE parameters. | ||
432 | */ | ||
433 | static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) | ||
434 | { | ||
435 | struct sensor *sensor = s->priv; | ||
436 | struct v4l2_captureparm *cparm = &a->parm.capture; | ||
437 | |||
438 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_parm\n"); | ||
439 | |||
440 | switch (a->type) { | ||
441 | /* These are all the possible cases. */ | ||
442 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
443 | pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); | ||
444 | memset(a, 0, sizeof(*a)); | ||
445 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
446 | cparm->capability = sensor->sen.streamcap.capability; | ||
447 | cparm->timeperframe = sensor->sen.streamcap.timeperframe; | ||
448 | cparm->capturemode = sensor->sen.streamcap.capturemode; | ||
449 | break; | ||
450 | |||
451 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
452 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
453 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
454 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
455 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
456 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
457 | break; | ||
458 | |||
459 | default: | ||
460 | pr_debug("ioctl_g_parm:type is unknown %d\n", a->type); | ||
461 | break; | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | /*! | ||
468 | * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl | ||
469 | * @s: pointer to standard V4L2 device structure | ||
470 | * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure | ||
471 | * | ||
472 | * Configures the sensor to use the input parameters, if possible. If | ||
473 | * not possible, reverts to the old parameters and returns the | ||
474 | * appropriate error code. | ||
475 | * | ||
476 | * This driver cannot change these settings. | ||
477 | */ | ||
478 | static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) | ||
479 | { | ||
480 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_parm\n"); | ||
481 | |||
482 | switch (a->type) { | ||
483 | /* These are all the possible cases. */ | ||
484 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
485 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
486 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
487 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
488 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
489 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
490 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
491 | break; | ||
492 | |||
493 | default: | ||
494 | pr_debug(" type is unknown - %d\n", a->type); | ||
495 | break; | ||
496 | } | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | /*! | ||
502 | * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap | ||
503 | * @s: pointer to standard V4L2 device structure | ||
504 | * @f: pointer to standard V4L2 v4l2_format structure | ||
505 | * | ||
506 | * Returns the sensor's current pixel format in the v4l2_format | ||
507 | * parameter. | ||
508 | */ | ||
509 | static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) | ||
510 | { | ||
511 | struct sensor *sensor = s->priv; | ||
512 | |||
513 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_fmt_cap\n"); | ||
514 | |||
515 | switch (f->type) { | ||
516 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
517 | pr_debug(" Returning size of %dx%d\n", | ||
518 | sensor->sen.pix.width, sensor->sen.pix.height); | ||
519 | f->fmt.pix = sensor->sen.pix; | ||
520 | break; | ||
521 | |||
522 | case V4L2_BUF_TYPE_PRIVATE: { | ||
523 | v4l2_std_id std; | ||
524 | adv7180_get_std(&std); | ||
525 | f->fmt.pix.pixelformat = (u32)std; | ||
526 | } | ||
527 | break; | ||
528 | |||
529 | default: | ||
530 | f->fmt.pix = sensor->sen.pix; | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | /*! | ||
538 | * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl | ||
539 | * @s: pointer to standard V4L2 device structure | ||
540 | * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure | ||
541 | * | ||
542 | * If the requested control is supported, returns the control information | ||
543 | * from the video_control[] array. Otherwise, returns -EINVAL if the | ||
544 | * control is not supported. | ||
545 | */ | ||
546 | static int ioctl_queryctrl(struct v4l2_int_device *s, | ||
547 | struct v4l2_queryctrl *qc) | ||
548 | { | ||
549 | int i; | ||
550 | |||
551 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_queryctrl\n"); | ||
552 | |||
553 | for (i = 0; i < ARRAY_SIZE(adv7180_qctrl); i++) | ||
554 | if (qc->id && qc->id == adv7180_qctrl[i].id) { | ||
555 | memcpy(qc, &(adv7180_qctrl[i]), | ||
556 | sizeof(*qc)); | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | return -EINVAL; | ||
561 | } | ||
562 | |||
563 | /*! | ||
564 | * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl | ||
565 | * @s: pointer to standard V4L2 device structure | ||
566 | * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure | ||
567 | * | ||
568 | * If the requested control is supported, returns the control's current | ||
569 | * value from the video_control[] array. Otherwise, returns -EINVAL | ||
570 | * if the control is not supported. | ||
571 | */ | ||
572 | static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) | ||
573 | { | ||
574 | int ret = 0; | ||
575 | int sat = 0; | ||
576 | |||
577 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n"); | ||
578 | |||
579 | switch (vc->id) { | ||
580 | case V4L2_CID_BRIGHTNESS: | ||
581 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
582 | " V4L2_CID_BRIGHTNESS\n"); | ||
583 | adv7180_data.sen.brightness = adv7180_read(ADV7180_BRIGHTNESS); | ||
584 | vc->value = adv7180_data.sen.brightness; | ||
585 | break; | ||
586 | case V4L2_CID_CONTRAST: | ||
587 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
588 | " V4L2_CID_CONTRAST\n"); | ||
589 | vc->value = adv7180_data.sen.contrast; | ||
590 | break; | ||
591 | case V4L2_CID_SATURATION: | ||
592 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
593 | " V4L2_CID_SATURATION\n"); | ||
594 | sat = adv7180_read(ADV7180_SD_SATURATION_CB); | ||
595 | adv7180_data.sen.saturation = sat; | ||
596 | vc->value = adv7180_data.sen.saturation; | ||
597 | break; | ||
598 | case V4L2_CID_HUE: | ||
599 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
600 | " V4L2_CID_HUE\n"); | ||
601 | vc->value = adv7180_data.sen.hue; | ||
602 | break; | ||
603 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
604 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
605 | " V4L2_CID_AUTO_WHITE_BALANCE\n"); | ||
606 | break; | ||
607 | case V4L2_CID_DO_WHITE_BALANCE: | ||
608 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
609 | " V4L2_CID_DO_WHITE_BALANCE\n"); | ||
610 | break; | ||
611 | case V4L2_CID_RED_BALANCE: | ||
612 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
613 | " V4L2_CID_RED_BALANCE\n"); | ||
614 | vc->value = adv7180_data.sen.red; | ||
615 | break; | ||
616 | case V4L2_CID_BLUE_BALANCE: | ||
617 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
618 | " V4L2_CID_BLUE_BALANCE\n"); | ||
619 | vc->value = adv7180_data.sen.blue; | ||
620 | break; | ||
621 | case V4L2_CID_GAMMA: | ||
622 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
623 | " V4L2_CID_GAMMA\n"); | ||
624 | break; | ||
625 | case V4L2_CID_EXPOSURE: | ||
626 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
627 | " V4L2_CID_EXPOSURE\n"); | ||
628 | vc->value = adv7180_data.sen.ae_mode; | ||
629 | break; | ||
630 | case V4L2_CID_AUTOGAIN: | ||
631 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
632 | " V4L2_CID_AUTOGAIN\n"); | ||
633 | break; | ||
634 | case V4L2_CID_GAIN: | ||
635 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
636 | " V4L2_CID_GAIN\n"); | ||
637 | break; | ||
638 | case V4L2_CID_HFLIP: | ||
639 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
640 | " V4L2_CID_HFLIP\n"); | ||
641 | break; | ||
642 | case V4L2_CID_VFLIP: | ||
643 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
644 | " V4L2_CID_VFLIP\n"); | ||
645 | break; | ||
646 | default: | ||
647 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
648 | " Default case\n"); | ||
649 | vc->value = 0; | ||
650 | ret = -EPERM; | ||
651 | break; | ||
652 | } | ||
653 | |||
654 | return ret; | ||
655 | } | ||
656 | |||
657 | /*! | ||
658 | * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl | ||
659 | * @s: pointer to standard V4L2 device structure | ||
660 | * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure | ||
661 | * | ||
662 | * If the requested control is supported, sets the control's current | ||
663 | * value in HW (and updates the video_control[] array). Otherwise, | ||
664 | * returns -EINVAL if the control is not supported. | ||
665 | */ | ||
666 | static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) | ||
667 | { | ||
668 | int retval = 0; | ||
669 | u8 tmp; | ||
670 | |||
671 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n"); | ||
672 | |||
673 | switch (vc->id) { | ||
674 | case V4L2_CID_BRIGHTNESS: | ||
675 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
676 | " V4L2_CID_BRIGHTNESS\n"); | ||
677 | tmp = vc->value; | ||
678 | adv7180_write_reg(ADV7180_BRIGHTNESS, tmp); | ||
679 | adv7180_data.sen.brightness = vc->value; | ||
680 | break; | ||
681 | case V4L2_CID_CONTRAST: | ||
682 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
683 | " V4L2_CID_CONTRAST\n"); | ||
684 | break; | ||
685 | case V4L2_CID_SATURATION: | ||
686 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
687 | " V4L2_CID_SATURATION\n"); | ||
688 | tmp = vc->value; | ||
689 | adv7180_write_reg(ADV7180_SD_SATURATION_CB, tmp); | ||
690 | adv7180_write_reg(ADV7180_SD_SATURATION_CR, tmp); | ||
691 | adv7180_data.sen.saturation = vc->value; | ||
692 | break; | ||
693 | case V4L2_CID_HUE: | ||
694 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
695 | " V4L2_CID_HUE\n"); | ||
696 | break; | ||
697 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
698 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
699 | " V4L2_CID_AUTO_WHITE_BALANCE\n"); | ||
700 | break; | ||
701 | case V4L2_CID_DO_WHITE_BALANCE: | ||
702 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
703 | " V4L2_CID_DO_WHITE_BALANCE\n"); | ||
704 | break; | ||
705 | case V4L2_CID_RED_BALANCE: | ||
706 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
707 | " V4L2_CID_RED_BALANCE\n"); | ||
708 | break; | ||
709 | case V4L2_CID_BLUE_BALANCE: | ||
710 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
711 | " V4L2_CID_BLUE_BALANCE\n"); | ||
712 | break; | ||
713 | case V4L2_CID_GAMMA: | ||
714 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
715 | " V4L2_CID_GAMMA\n"); | ||
716 | break; | ||
717 | case V4L2_CID_EXPOSURE: | ||
718 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
719 | " V4L2_CID_EXPOSURE\n"); | ||
720 | break; | ||
721 | case V4L2_CID_AUTOGAIN: | ||
722 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
723 | " V4L2_CID_AUTOGAIN\n"); | ||
724 | break; | ||
725 | case V4L2_CID_GAIN: | ||
726 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
727 | " V4L2_CID_GAIN\n"); | ||
728 | break; | ||
729 | case V4L2_CID_HFLIP: | ||
730 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
731 | " V4L2_CID_HFLIP\n"); | ||
732 | break; | ||
733 | case V4L2_CID_VFLIP: | ||
734 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
735 | " V4L2_CID_VFLIP\n"); | ||
736 | break; | ||
737 | default: | ||
738 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
739 | " Default case\n"); | ||
740 | retval = -EPERM; | ||
741 | break; | ||
742 | } | ||
743 | |||
744 | return retval; | ||
745 | } | ||
746 | |||
747 | /*! | ||
748 | * ioctl_enum_framesizes - V4L2 sensor interface handler for | ||
749 | * VIDIOC_ENUM_FRAMESIZES ioctl | ||
750 | * @s: pointer to standard V4L2 device structure | ||
751 | * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure | ||
752 | * | ||
753 | * Return 0 if successful, otherwise -EINVAL. | ||
754 | */ | ||
755 | static int ioctl_enum_framesizes(struct v4l2_int_device *s, | ||
756 | struct v4l2_frmsizeenum *fsize) | ||
757 | { | ||
758 | if (fsize->index >= 1) | ||
759 | return -EINVAL; | ||
760 | |||
761 | fsize->discrete.width = video_fmts[video_idx].active_width; | ||
762 | fsize->discrete.height = video_fmts[video_idx].active_height; | ||
763 | |||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | /*! | ||
768 | * ioctl_g_chip_ident - V4L2 sensor interface handler for | ||
769 | * VIDIOC_DBG_G_CHIP_IDENT ioctl | ||
770 | * @s: pointer to standard V4L2 device structure | ||
771 | * @id: pointer to int | ||
772 | * | ||
773 | * Return 0. | ||
774 | */ | ||
775 | static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) | ||
776 | { | ||
777 | ((struct v4l2_dbg_chip_ident *)id)->match.type = | ||
778 | V4L2_CHIP_MATCH_I2C_DRIVER; | ||
779 | strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, | ||
780 | "adv7180_decoder"); | ||
781 | ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_ADV7180; | ||
782 | |||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /*! | ||
787 | * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT | ||
788 | * @s: pointer to standard V4L2 device structure | ||
789 | */ | ||
790 | static int ioctl_init(struct v4l2_int_device *s) | ||
791 | { | ||
792 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_init\n"); | ||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | /*! | ||
797 | * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num | ||
798 | * @s: pointer to standard V4L2 device structure | ||
799 | * | ||
800 | * Initialise the device when slave attaches to the master. | ||
801 | */ | ||
802 | static int ioctl_dev_init(struct v4l2_int_device *s) | ||
803 | { | ||
804 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_dev_init\n"); | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | /*! | ||
809 | * This structure defines all the ioctls for this module. | ||
810 | */ | ||
811 | static struct v4l2_int_ioctl_desc adv7180_ioctl_desc[] = { | ||
812 | |||
813 | {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init}, | ||
814 | |||
815 | /*! | ||
816 | * Delinitialise the dev. at slave detach. | ||
817 | * The complement of ioctl_dev_init. | ||
818 | */ | ||
819 | /* {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *)ioctl_dev_exit}, */ | ||
820 | |||
821 | {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power}, | ||
822 | {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm}, | ||
823 | /* {vidioc_int_g_needs_reset_num, | ||
824 | (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */ | ||
825 | /* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */ | ||
826 | {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init}, | ||
827 | |||
828 | /*! | ||
829 | * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type. | ||
830 | */ | ||
831 | /* {vidioc_int_enum_fmt_cap_num, | ||
832 | (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */ | ||
833 | |||
834 | /*! | ||
835 | * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. | ||
836 | * This ioctl is used to negotiate the image capture size and | ||
837 | * pixel format without actually making it take effect. | ||
838 | */ | ||
839 | /* {vidioc_int_try_fmt_cap_num, | ||
840 | (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */ | ||
841 | |||
842 | {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap}, | ||
843 | |||
844 | /*! | ||
845 | * If the requested format is supported, configures the HW to use that | ||
846 | * format, returns error code if format not supported or HW can't be | ||
847 | * correctly configured. | ||
848 | */ | ||
849 | /* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */ | ||
850 | |||
851 | {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm}, | ||
852 | {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm}, | ||
853 | {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl}, | ||
854 | {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl}, | ||
855 | {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl}, | ||
856 | {vidioc_int_enum_framesizes_num, | ||
857 | (v4l2_int_ioctl_func *) ioctl_enum_framesizes}, | ||
858 | {vidioc_int_g_chip_ident_num, | ||
859 | (v4l2_int_ioctl_func *)ioctl_g_chip_ident}, | ||
860 | }; | ||
861 | |||
862 | static struct v4l2_int_slave adv7180_slave = { | ||
863 | .ioctls = adv7180_ioctl_desc, | ||
864 | .num_ioctls = ARRAY_SIZE(adv7180_ioctl_desc), | ||
865 | }; | ||
866 | |||
867 | static struct v4l2_int_device adv7180_int_device = { | ||
868 | .module = THIS_MODULE, | ||
869 | .name = "adv7180", | ||
870 | .type = v4l2_int_type_slave, | ||
871 | .u = { | ||
872 | .slave = &adv7180_slave, | ||
873 | }, | ||
874 | }; | ||
875 | |||
876 | |||
877 | /*********************************************************************** | ||
878 | * I2C client and driver. | ||
879 | ***********************************************************************/ | ||
880 | |||
881 | /*! ADV7180 Reset function. | ||
882 | * | ||
883 | * @return None. | ||
884 | */ | ||
885 | static void adv7180_hard_reset(bool cvbs) | ||
886 | { | ||
887 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
888 | "In adv7180:adv7180_hard_reset\n"); | ||
889 | |||
890 | if (cvbs) { | ||
891 | /* Set CVBS input on AIN1 */ | ||
892 | adv7180_write_reg(ADV7180_INPUT_CTL, 0x00); | ||
893 | } else { | ||
894 | /* | ||
895 | * Set YPbPr input on AIN1,4,5 and normal | ||
896 | * operations(autodection of all stds). | ||
897 | */ | ||
898 | adv7180_write_reg(ADV7180_INPUT_CTL, 0x09); | ||
899 | } | ||
900 | |||
901 | /* Datasheet recommends */ | ||
902 | adv7180_write_reg(0x01, 0xc8); | ||
903 | adv7180_write_reg(0x02, 0x04); | ||
904 | adv7180_write_reg(0x03, 0x00); | ||
905 | adv7180_write_reg(0x04, 0x45); | ||
906 | adv7180_write_reg(0x05, 0x00); | ||
907 | adv7180_write_reg(0x06, 0x02); | ||
908 | adv7180_write_reg(0x07, 0x7F); | ||
909 | adv7180_write_reg(0x08, 0x80); | ||
910 | adv7180_write_reg(0x0A, 0x00); | ||
911 | adv7180_write_reg(0x0B, 0x00); | ||
912 | adv7180_write_reg(0x0C, 0x36); | ||
913 | adv7180_write_reg(0x0D, 0x7C); | ||
914 | adv7180_write_reg(0x0E, 0x00); | ||
915 | adv7180_write_reg(0x0F, 0x00); | ||
916 | adv7180_write_reg(0x13, 0x00); | ||
917 | adv7180_write_reg(0x14, 0x12); | ||
918 | adv7180_write_reg(0x15, 0x00); | ||
919 | adv7180_write_reg(0x16, 0x00); | ||
920 | adv7180_write_reg(0x17, 0x01); | ||
921 | adv7180_write_reg(0x18, 0x93); | ||
922 | adv7180_write_reg(0xF1, 0x19); | ||
923 | adv7180_write_reg(0x1A, 0x00); | ||
924 | adv7180_write_reg(0x1B, 0x00); | ||
925 | adv7180_write_reg(0x1C, 0x00); | ||
926 | adv7180_write_reg(0x1D, 0x40); | ||
927 | adv7180_write_reg(0x1E, 0x00); | ||
928 | adv7180_write_reg(0x1F, 0x00); | ||
929 | adv7180_write_reg(0x20, 0x00); | ||
930 | adv7180_write_reg(0x21, 0x00); | ||
931 | adv7180_write_reg(0x22, 0x00); | ||
932 | adv7180_write_reg(0x23, 0xC0); | ||
933 | adv7180_write_reg(0x24, 0x00); | ||
934 | adv7180_write_reg(0x25, 0x00); | ||
935 | adv7180_write_reg(0x26, 0x00); | ||
936 | adv7180_write_reg(0x27, 0x58); | ||
937 | adv7180_write_reg(0x28, 0x00); | ||
938 | adv7180_write_reg(0x29, 0x00); | ||
939 | adv7180_write_reg(0x2A, 0x00); | ||
940 | adv7180_write_reg(0x2B, 0xE1); | ||
941 | adv7180_write_reg(0x2C, 0xAE); | ||
942 | adv7180_write_reg(0x2D, 0xF4); | ||
943 | adv7180_write_reg(0x2E, 0x00); | ||
944 | adv7180_write_reg(0x2F, 0xF0); | ||
945 | adv7180_write_reg(0x30, 0x00); | ||
946 | adv7180_write_reg(0x31, 0x12); | ||
947 | adv7180_write_reg(0x32, 0x41); | ||
948 | adv7180_write_reg(0x33, 0x84); | ||
949 | adv7180_write_reg(0x34, 0x00); | ||
950 | adv7180_write_reg(0x35, 0x02); | ||
951 | adv7180_write_reg(0x36, 0x00); | ||
952 | adv7180_write_reg(0x37, 0x01); | ||
953 | adv7180_write_reg(0x38, 0x80); | ||
954 | adv7180_write_reg(0x39, 0xC0); | ||
955 | adv7180_write_reg(0x3A, 0x10); | ||
956 | adv7180_write_reg(0x3B, 0x05); | ||
957 | adv7180_write_reg(0x3C, 0x58); | ||
958 | adv7180_write_reg(0x3D, 0xB2); | ||
959 | adv7180_write_reg(0x3E, 0x64); | ||
960 | adv7180_write_reg(0x3F, 0xE4); | ||
961 | adv7180_write_reg(0x40, 0x90); | ||
962 | adv7180_write_reg(0x41, 0x01); | ||
963 | adv7180_write_reg(0x42, 0x7E); | ||
964 | adv7180_write_reg(0x43, 0xA4); | ||
965 | adv7180_write_reg(0x44, 0xFF); | ||
966 | adv7180_write_reg(0x45, 0xB6); | ||
967 | adv7180_write_reg(0x46, 0x12); | ||
968 | adv7180_write_reg(0x48, 0x00); | ||
969 | adv7180_write_reg(0x49, 0x00); | ||
970 | adv7180_write_reg(0x4A, 0x00); | ||
971 | adv7180_write_reg(0x4B, 0x00); | ||
972 | adv7180_write_reg(0x4C, 0x00); | ||
973 | adv7180_write_reg(0x4D, 0xEF); | ||
974 | adv7180_write_reg(0x4E, 0x08); | ||
975 | adv7180_write_reg(0x4F, 0x08); | ||
976 | adv7180_write_reg(0x50, 0x08); | ||
977 | adv7180_write_reg(0x51, 0x24); | ||
978 | adv7180_write_reg(0x52, 0x0B); | ||
979 | adv7180_write_reg(0x53, 0x4E); | ||
980 | adv7180_write_reg(0x54, 0x80); | ||
981 | adv7180_write_reg(0x55, 0x00); | ||
982 | adv7180_write_reg(0x56, 0x10); | ||
983 | adv7180_write_reg(0x57, 0x00); | ||
984 | adv7180_write_reg(0x58, 0x00); | ||
985 | adv7180_write_reg(0x59, 0x00); | ||
986 | adv7180_write_reg(0x5A, 0x00); | ||
987 | adv7180_write_reg(0x5B, 0x00); | ||
988 | adv7180_write_reg(0x5C, 0x00); | ||
989 | adv7180_write_reg(0x5D, 0x00); | ||
990 | adv7180_write_reg(0x5E, 0x00); | ||
991 | adv7180_write_reg(0x5F, 0x00); | ||
992 | adv7180_write_reg(0x60, 0x00); | ||
993 | adv7180_write_reg(0x61, 0x00); | ||
994 | adv7180_write_reg(0x62, 0x20); | ||
995 | adv7180_write_reg(0x63, 0x00); | ||
996 | adv7180_write_reg(0x64, 0x00); | ||
997 | adv7180_write_reg(0x65, 0x00); | ||
998 | adv7180_write_reg(0x66, 0x00); | ||
999 | adv7180_write_reg(0x67, 0x03); | ||
1000 | adv7180_write_reg(0x68, 0x01); | ||
1001 | adv7180_write_reg(0x69, 0x00); | ||
1002 | adv7180_write_reg(0x6A, 0x00); | ||
1003 | adv7180_write_reg(0x6B, 0xC0); | ||
1004 | adv7180_write_reg(0x6C, 0x00); | ||
1005 | adv7180_write_reg(0x6D, 0x00); | ||
1006 | adv7180_write_reg(0x6E, 0x00); | ||
1007 | adv7180_write_reg(0x6F, 0x00); | ||
1008 | adv7180_write_reg(0x70, 0x00); | ||
1009 | adv7180_write_reg(0x71, 0x00); | ||
1010 | adv7180_write_reg(0x72, 0x00); | ||
1011 | adv7180_write_reg(0x73, 0x10); | ||
1012 | adv7180_write_reg(0x74, 0x04); | ||
1013 | adv7180_write_reg(0x75, 0x01); | ||
1014 | adv7180_write_reg(0x76, 0x00); | ||
1015 | adv7180_write_reg(0x77, 0x3F); | ||
1016 | adv7180_write_reg(0x78, 0xFF); | ||
1017 | adv7180_write_reg(0x79, 0xFF); | ||
1018 | adv7180_write_reg(0x7A, 0xFF); | ||
1019 | adv7180_write_reg(0x7B, 0x1E); | ||
1020 | adv7180_write_reg(0x7C, 0xC0); | ||
1021 | adv7180_write_reg(0x7D, 0x00); | ||
1022 | adv7180_write_reg(0x7E, 0x00); | ||
1023 | adv7180_write_reg(0x7F, 0x00); | ||
1024 | adv7180_write_reg(0x80, 0x00); | ||
1025 | adv7180_write_reg(0x81, 0xC0); | ||
1026 | adv7180_write_reg(0x82, 0x04); | ||
1027 | adv7180_write_reg(0x83, 0x00); | ||
1028 | adv7180_write_reg(0x84, 0x0C); | ||
1029 | adv7180_write_reg(0x85, 0x02); | ||
1030 | adv7180_write_reg(0x86, 0x03); | ||
1031 | adv7180_write_reg(0x87, 0x63); | ||
1032 | adv7180_write_reg(0x88, 0x5A); | ||
1033 | adv7180_write_reg(0x89, 0x08); | ||
1034 | adv7180_write_reg(0x8A, 0x10); | ||
1035 | adv7180_write_reg(0x8B, 0x00); | ||
1036 | adv7180_write_reg(0x8C, 0x40); | ||
1037 | adv7180_write_reg(0x8D, 0x00); | ||
1038 | adv7180_write_reg(0x8E, 0x40); | ||
1039 | adv7180_write_reg(0x8F, 0x00); | ||
1040 | adv7180_write_reg(0x90, 0x00); | ||
1041 | adv7180_write_reg(0x91, 0x50); | ||
1042 | adv7180_write_reg(0x92, 0x00); | ||
1043 | adv7180_write_reg(0x93, 0x00); | ||
1044 | adv7180_write_reg(0x94, 0x00); | ||
1045 | adv7180_write_reg(0x95, 0x00); | ||
1046 | adv7180_write_reg(0x96, 0x00); | ||
1047 | adv7180_write_reg(0x97, 0xF0); | ||
1048 | adv7180_write_reg(0x98, 0x00); | ||
1049 | adv7180_write_reg(0x99, 0x00); | ||
1050 | adv7180_write_reg(0x9A, 0x00); | ||
1051 | adv7180_write_reg(0x9B, 0x00); | ||
1052 | adv7180_write_reg(0x9C, 0x00); | ||
1053 | adv7180_write_reg(0x9D, 0x00); | ||
1054 | adv7180_write_reg(0x9E, 0x00); | ||
1055 | adv7180_write_reg(0x9F, 0x00); | ||
1056 | adv7180_write_reg(0xA0, 0x00); | ||
1057 | adv7180_write_reg(0xA1, 0x00); | ||
1058 | adv7180_write_reg(0xA2, 0x00); | ||
1059 | adv7180_write_reg(0xA3, 0x00); | ||
1060 | adv7180_write_reg(0xA4, 0x00); | ||
1061 | adv7180_write_reg(0xA5, 0x00); | ||
1062 | adv7180_write_reg(0xA6, 0x00); | ||
1063 | adv7180_write_reg(0xA7, 0x00); | ||
1064 | adv7180_write_reg(0xA8, 0x00); | ||
1065 | adv7180_write_reg(0xA9, 0x00); | ||
1066 | adv7180_write_reg(0xAA, 0x00); | ||
1067 | adv7180_write_reg(0xAB, 0x00); | ||
1068 | adv7180_write_reg(0xAC, 0x00); | ||
1069 | adv7180_write_reg(0xAD, 0x00); | ||
1070 | adv7180_write_reg(0xAE, 0x60); | ||
1071 | adv7180_write_reg(0xAF, 0x00); | ||
1072 | adv7180_write_reg(0xB0, 0x00); | ||
1073 | adv7180_write_reg(0xB1, 0x60); | ||
1074 | adv7180_write_reg(0xB2, 0x1C); | ||
1075 | adv7180_write_reg(0xB3, 0x54); | ||
1076 | adv7180_write_reg(0xB4, 0x00); | ||
1077 | adv7180_write_reg(0xB5, 0x00); | ||
1078 | adv7180_write_reg(0xB6, 0x00); | ||
1079 | adv7180_write_reg(0xB7, 0x13); | ||
1080 | adv7180_write_reg(0xB8, 0x03); | ||
1081 | adv7180_write_reg(0xB9, 0x33); | ||
1082 | adv7180_write_reg(0xBF, 0x02); | ||
1083 | adv7180_write_reg(0xC0, 0x00); | ||
1084 | adv7180_write_reg(0xC1, 0x00); | ||
1085 | adv7180_write_reg(0xC2, 0x00); | ||
1086 | adv7180_write_reg(0xC3, 0x00); | ||
1087 | adv7180_write_reg(0xC4, 0x00); | ||
1088 | adv7180_write_reg(0xC5, 0x81); | ||
1089 | adv7180_write_reg(0xC6, 0x00); | ||
1090 | adv7180_write_reg(0xC7, 0x00); | ||
1091 | adv7180_write_reg(0xC8, 0x00); | ||
1092 | adv7180_write_reg(0xC9, 0x04); | ||
1093 | adv7180_write_reg(0xCC, 0x69); | ||
1094 | adv7180_write_reg(0xCD, 0x00); | ||
1095 | adv7180_write_reg(0xCE, 0x01); | ||
1096 | adv7180_write_reg(0xCF, 0xB4); | ||
1097 | adv7180_write_reg(0xD0, 0x00); | ||
1098 | adv7180_write_reg(0xD1, 0x10); | ||
1099 | adv7180_write_reg(0xD2, 0xFF); | ||
1100 | adv7180_write_reg(0xD3, 0xFF); | ||
1101 | adv7180_write_reg(0xD4, 0x7F); | ||
1102 | adv7180_write_reg(0xD5, 0x7F); | ||
1103 | adv7180_write_reg(0xD6, 0x3E); | ||
1104 | adv7180_write_reg(0xD7, 0x08); | ||
1105 | adv7180_write_reg(0xD8, 0x3C); | ||
1106 | adv7180_write_reg(0xD9, 0x08); | ||
1107 | adv7180_write_reg(0xDA, 0x3C); | ||
1108 | adv7180_write_reg(0xDB, 0x9B); | ||
1109 | adv7180_write_reg(0xDC, 0xAC); | ||
1110 | adv7180_write_reg(0xDD, 0x4C); | ||
1111 | adv7180_write_reg(0xDE, 0x00); | ||
1112 | adv7180_write_reg(0xDF, 0x00); | ||
1113 | adv7180_write_reg(0xE0, 0x14); | ||
1114 | adv7180_write_reg(0xE1, 0x80); | ||
1115 | adv7180_write_reg(0xE2, 0x80); | ||
1116 | adv7180_write_reg(0xE3, 0x80); | ||
1117 | adv7180_write_reg(0xE4, 0x80); | ||
1118 | adv7180_write_reg(0xE5, 0x25); | ||
1119 | adv7180_write_reg(0xE6, 0x44); | ||
1120 | adv7180_write_reg(0xE7, 0x63); | ||
1121 | adv7180_write_reg(0xE8, 0x65); | ||
1122 | adv7180_write_reg(0xE9, 0x14); | ||
1123 | adv7180_write_reg(0xEA, 0x63); | ||
1124 | adv7180_write_reg(0xEB, 0x55); | ||
1125 | adv7180_write_reg(0xEC, 0x55); | ||
1126 | adv7180_write_reg(0xEE, 0x00); | ||
1127 | adv7180_write_reg(0xEF, 0x4A); | ||
1128 | adv7180_write_reg(0xF0, 0x44); | ||
1129 | adv7180_write_reg(0xF1, 0x0C); | ||
1130 | adv7180_write_reg(0xF2, 0x32); | ||
1131 | adv7180_write_reg(0xF3, 0x00); | ||
1132 | adv7180_write_reg(0xF4, 0x3F); | ||
1133 | adv7180_write_reg(0xF5, 0xE0); | ||
1134 | adv7180_write_reg(0xF6, 0x69); | ||
1135 | adv7180_write_reg(0xF7, 0x10); | ||
1136 | adv7180_write_reg(0xF8, 0x00); | ||
1137 | adv7180_write_reg(0xF9, 0x03); | ||
1138 | adv7180_write_reg(0xFA, 0xFA); | ||
1139 | adv7180_write_reg(0xFB, 0x40); | ||
1140 | } | ||
1141 | |||
1142 | /*! ADV7180 I2C attach function. | ||
1143 | * | ||
1144 | * @param *adapter struct i2c_adapter *. | ||
1145 | * | ||
1146 | * @return Error code indicating success or failure. | ||
1147 | */ | ||
1148 | |||
1149 | /*! | ||
1150 | * ADV7180 I2C probe function. | ||
1151 | * Function set in i2c_driver struct. | ||
1152 | * Called by insmod. | ||
1153 | * | ||
1154 | * @param *adapter I2C adapter descriptor. | ||
1155 | * | ||
1156 | * @return Error code indicating success or failure. | ||
1157 | */ | ||
1158 | static int adv7180_probe(struct i2c_client *client, | ||
1159 | const struct i2c_device_id *id) | ||
1160 | { | ||
1161 | int rev_id; | ||
1162 | int ret = 0; | ||
1163 | u32 cvbs = true; | ||
1164 | struct pinctrl *pinctrl; | ||
1165 | struct device *dev = &client->dev; | ||
1166 | |||
1167 | printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data); | ||
1168 | |||
1169 | /* ov5640 pinctrl */ | ||
1170 | pinctrl = devm_pinctrl_get_select_default(dev); | ||
1171 | if (IS_ERR(pinctrl)) { | ||
1172 | dev_err(dev, "setup pinctrl failed\n"); | ||
1173 | return PTR_ERR(pinctrl); | ||
1174 | } | ||
1175 | |||
1176 | /* request power down pin */ | ||
1177 | pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); | ||
1178 | if (!gpio_is_valid(pwn_gpio)) { | ||
1179 | dev_err(dev, "no sensor pwdn pin available\n"); | ||
1180 | return -ENODEV; | ||
1181 | } | ||
1182 | ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, | ||
1183 | "adv7180_pwdn"); | ||
1184 | if (ret < 0) { | ||
1185 | dev_err(dev, "no power pin available!\n"); | ||
1186 | return ret; | ||
1187 | } | ||
1188 | |||
1189 | adv7180_regulator_enable(dev); | ||
1190 | |||
1191 | adv7180_power_down(0); | ||
1192 | |||
1193 | msleep(1); | ||
1194 | |||
1195 | /* Set initial values for the sensor struct. */ | ||
1196 | memset(&adv7180_data, 0, sizeof(adv7180_data)); | ||
1197 | adv7180_data.sen.i2c_client = client; | ||
1198 | adv7180_data.sen.streamcap.timeperframe.denominator = 30; | ||
1199 | adv7180_data.sen.streamcap.timeperframe.numerator = 1; | ||
1200 | adv7180_data.std_id = V4L2_STD_ALL; | ||
1201 | video_idx = ADV7180_NOT_LOCKED; | ||
1202 | adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width; | ||
1203 | adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height; | ||
1204 | adv7180_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */ | ||
1205 | adv7180_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */ | ||
1206 | adv7180_data.sen.on = true; | ||
1207 | |||
1208 | adv7180_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk"); | ||
1209 | if (IS_ERR(adv7180_data.sen.sensor_clk)) { | ||
1210 | dev_err(dev, "get mclk failed\n"); | ||
1211 | return PTR_ERR(adv7180_data.sen.sensor_clk); | ||
1212 | } | ||
1213 | |||
1214 | ret = of_property_read_u32(dev->of_node, "mclk", | ||
1215 | &adv7180_data.sen.mclk); | ||
1216 | if (ret) { | ||
1217 | dev_err(dev, "mclk frequency is invalid\n"); | ||
1218 | return ret; | ||
1219 | } | ||
1220 | |||
1221 | ret = of_property_read_u32( | ||
1222 | dev->of_node, "mclk_source", | ||
1223 | (u32 *) &(adv7180_data.sen.mclk_source)); | ||
1224 | if (ret) { | ||
1225 | dev_err(dev, "mclk_source invalid\n"); | ||
1226 | return ret; | ||
1227 | } | ||
1228 | |||
1229 | ret = of_property_read_u32(dev->of_node, "csi_id", | ||
1230 | &(adv7180_data.sen.csi)); | ||
1231 | if (ret) { | ||
1232 | dev_err(dev, "csi_id invalid\n"); | ||
1233 | return ret; | ||
1234 | } | ||
1235 | |||
1236 | clk_prepare_enable(adv7180_data.sen.sensor_clk); | ||
1237 | |||
1238 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
1239 | "%s:adv7180 probe i2c address is 0x%02X\n", | ||
1240 | __func__, adv7180_data.sen.i2c_client->addr); | ||
1241 | |||
1242 | /*! Read the revision ID of the tvin chip */ | ||
1243 | rev_id = adv7180_read(ADV7180_IDENT); | ||
1244 | dev_dbg(dev, | ||
1245 | "%s:Analog Device adv7%2X0 detected!\n", __func__, | ||
1246 | rev_id); | ||
1247 | |||
1248 | ret = of_property_read_u32(dev->of_node, "cvbs", &(cvbs)); | ||
1249 | if (ret) { | ||
1250 | dev_err(dev, "cvbs setting is not found\n"); | ||
1251 | cvbs = true; | ||
1252 | } | ||
1253 | |||
1254 | /*! ADV7180 initialization. */ | ||
1255 | adv7180_hard_reset(cvbs); | ||
1256 | |||
1257 | pr_debug(" type is %d (expect %d)\n", | ||
1258 | adv7180_int_device.type, v4l2_int_type_slave); | ||
1259 | pr_debug(" num ioctls is %d\n", | ||
1260 | adv7180_int_device.u.slave->num_ioctls); | ||
1261 | |||
1262 | /* This function attaches this structure to the /dev/video0 device. | ||
1263 | * The pointer in priv points to the adv7180_data structure here.*/ | ||
1264 | adv7180_int_device.priv = &adv7180_data; | ||
1265 | ret = v4l2_int_device_register(&adv7180_int_device); | ||
1266 | |||
1267 | clk_disable_unprepare(adv7180_data.sen.sensor_clk); | ||
1268 | |||
1269 | return ret; | ||
1270 | } | ||
1271 | |||
1272 | /*! | ||
1273 | * ADV7180 I2C detach function. | ||
1274 | * Called on rmmod. | ||
1275 | * | ||
1276 | * @param *client struct i2c_client*. | ||
1277 | * | ||
1278 | * @return Error code indicating success or failure. | ||
1279 | */ | ||
1280 | static int adv7180_detach(struct i2c_client *client) | ||
1281 | { | ||
1282 | dev_dbg(&adv7180_data.sen.i2c_client->dev, | ||
1283 | "%s:Removing %s video decoder @ 0x%02X from adapter %s\n", | ||
1284 | __func__, IF_NAME, client->addr << 1, client->adapter->name); | ||
1285 | |||
1286 | /* Power down via i2c */ | ||
1287 | adv7180_write_reg(ADV7180_PWR_MNG, 0x24); | ||
1288 | |||
1289 | if (dvddio_regulator) | ||
1290 | regulator_disable(dvddio_regulator); | ||
1291 | |||
1292 | if (dvdd_regulator) | ||
1293 | regulator_disable(dvdd_regulator); | ||
1294 | |||
1295 | if (avdd_regulator) | ||
1296 | regulator_disable(avdd_regulator); | ||
1297 | |||
1298 | if (pvdd_regulator) | ||
1299 | regulator_disable(pvdd_regulator); | ||
1300 | |||
1301 | v4l2_int_device_unregister(&adv7180_int_device); | ||
1302 | |||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | /*! | ||
1307 | * ADV7180 init function. | ||
1308 | * Called on insmod. | ||
1309 | * | ||
1310 | * @return Error code indicating success or failure. | ||
1311 | */ | ||
1312 | static __init int adv7180_init(void) | ||
1313 | { | ||
1314 | u8 err = 0; | ||
1315 | |||
1316 | pr_debug("In adv7180_init\n"); | ||
1317 | |||
1318 | /* Tells the i2c driver what functions to call for this driver. */ | ||
1319 | err = i2c_add_driver(&adv7180_i2c_driver); | ||
1320 | if (err != 0) | ||
1321 | pr_err("%s:driver registration failed, error=%d\n", | ||
1322 | __func__, err); | ||
1323 | |||
1324 | return err; | ||
1325 | } | ||
1326 | |||
1327 | /*! | ||
1328 | * ADV7180 cleanup function. | ||
1329 | * Called on rmmod. | ||
1330 | * | ||
1331 | * @return Error code indicating success or failure. | ||
1332 | */ | ||
1333 | static void __exit adv7180_clean(void) | ||
1334 | { | ||
1335 | dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_clean\n"); | ||
1336 | i2c_del_driver(&adv7180_i2c_driver); | ||
1337 | } | ||
1338 | |||
1339 | module_init(adv7180_init); | ||
1340 | module_exit(adv7180_clean); | ||
1341 | |||
1342 | MODULE_AUTHOR("Freescale Semiconductor"); | ||
1343 | MODULE_DESCRIPTION("Anolog Device ADV7180 video decoder driver"); | ||
1344 | MODULE_LICENSE("GPL"); | ||