diff options
author | Sathishkumar S | 2014-02-25 01:12:56 -0600 |
---|---|---|
committer | Arthur Philpott | 2014-03-11 18:24:49 -0500 |
commit | bfcfdedba5ae7fda55ac631571a45a5ed877f3e8 (patch) | |
tree | 835efdfab5e67f4cf7183701ce5b4168bfb9269b | |
parent | 50ddb384a2672c25e5c219509b7bc9da25cbcf1e (diff) | |
download | kernel-video-bfcfdedba5ae7fda55ac631571a45a5ed877f3e8.tar.gz kernel-video-bfcfdedba5ae7fda55ac631571a45a5ed877f3e8.tar.xz kernel-video-bfcfdedba5ae7fda55ac631571a45a5ed877f3e8.zip |
i2c: tvp5158: Analog camera Driver Support
Add support for TVP5158 video decoder. This driver
does the default initialization for single channel
NTSC decode. It is tested with NTSC camera source.
Change-Id: Ida5a9b45414a917bd6f515882fe72a4b4b8e0947
Signed-off-by: Sathishkumar S <sathish.omap@gmail.com>
-rw-r--r-- | drivers/media/i2c/Kconfig | 11 | ||||
-rw-r--r-- | drivers/media/i2c/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/i2c/tvp5158.c | 672 |
3 files changed, 684 insertions, 0 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index c9ea9eb1ff4..ff9845c8eff 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig | |||
@@ -433,6 +433,17 @@ config VIDEO_OV1063X | |||
433 | This is a Video4Linux2 sensor-level driver for the OmniVision | 433 | This is a Video4Linux2 sensor-level driver for the OmniVision |
434 | OV1063X Sensor. | 434 | OV1063X Sensor. |
435 | 435 | ||
436 | config VIDEO_TVP5158 | ||
437 | tristate "Analog video decoder TVP5158 support NTSC/PAL" | ||
438 | depends on I2C && VIDEO_V4L2 | ||
439 | depends on MEDIA_CAMERA_SUPPORT | ||
440 | ---help--- | ||
441 | This is a Video4Linux2 sensor-level driver for the TVP5158 | ||
442 | NTSC/PAL video decoder. | ||
443 | |||
444 | To compile this driver as a module, choose M here: the | ||
445 | module will be called tvp5158. | ||
446 | |||
436 | config VIDEO_VS6624 | 447 | config VIDEO_VS6624 |
437 | tristate "ST VS6624 sensor support" | 448 | tristate "ST VS6624 sensor support" |
438 | depends on VIDEO_V4L2 && I2C | 449 | depends on VIDEO_V4L2 && I2C |
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index c081c244db4..90d46063124 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile | |||
@@ -48,6 +48,7 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o | |||
48 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | 48 | obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o |
49 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | 49 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o |
50 | obj-$(CONFIG_VIDEO_OV1063X) += ov1063x.o | 50 | obj-$(CONFIG_VIDEO_OV1063X) += ov1063x.o |
51 | obj-$(CONFIG_VIDEO_TVP5158) += tvp5158.o | ||
51 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | 52 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o |
52 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | 53 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
53 | obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o | 54 | obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o |
diff --git a/drivers/media/i2c/tvp5158.c b/drivers/media/i2c/tvp5158.c new file mode 100644 index 00000000000..674fefa367c --- /dev/null +++ b/drivers/media/i2c/tvp5158.c | |||
@@ -0,0 +1,672 @@ | |||
1 | #include <linux/delay.h> | ||
2 | #include <linux/i2c.h> | ||
3 | #include <linux/gpio.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/regulator/consumer.h> | ||
7 | #include <linux/regmap.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/v4l2-mediabus.h> | ||
10 | #include <linux/videodev2.h> | ||
11 | |||
12 | #include <media/soc_camera.h> | ||
13 | #include <media/v4l2-async.h> | ||
14 | #include <media/v4l2-chip-ident.h> | ||
15 | #include <media/v4l2-common.h> | ||
16 | #include <media/v4l2-ctrls.h> | ||
17 | |||
18 | #include <linux/pm_runtime.h> | ||
19 | |||
20 | #include <linux/of_gpio.h> | ||
21 | #include <linux/of_i2c.h> | ||
22 | #include <linux/of_device.h> | ||
23 | |||
24 | /* Debug functions */ | ||
25 | static bool debug; | ||
26 | module_param(debug, bool, 0644); | ||
27 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); | ||
28 | |||
29 | /* VBUS Register Address (24-bit), VBUS Register value (8-bit) */ | ||
30 | struct vbus_addr_value { | ||
31 | unsigned int addr; | ||
32 | unsigned char val; | ||
33 | }; | ||
34 | |||
35 | struct vbus_addr_value vbus_addr_value_set[] = { | ||
36 | {0x00403E50, 0x40}, | ||
37 | {0x00403E51, 0x00}, | ||
38 | {0x00403E52, 0x40}, | ||
39 | {0x00403E53, 0x00}, | ||
40 | {0x00403E54, 0x44}, | ||
41 | {0x00403E55, 0x23}, | ||
42 | {0x00403E56, 0x38}, | ||
43 | {0x00403E57, 0x10}, | ||
44 | {0x00403E58, 0x53}, | ||
45 | {0x00403E59, 0x23}, | ||
46 | {0x00403E5A, 0x02}, | ||
47 | {0x00403E5B, 0x00}, | ||
48 | {0x00403E5C, 0x20}, | ||
49 | {0x00403E5D, 0x00}, | ||
50 | {0x00403E5E, 0x04}, | ||
51 | {0x00403E5F, 0x04}, | ||
52 | {0x00403E60, 0x04}, | ||
53 | {0x00403E61, 0x04}, | ||
54 | {0x00403E62, 0x10}, | ||
55 | {0x00403E63, 0xF8}, | ||
56 | {0x00403E64, 0x30}, | ||
57 | {0x00403E65, 0x20}, | ||
58 | {0x00403E66, 0x30}, | ||
59 | {0x00403E67, 0x3F}, | ||
60 | {0x00403E68, 0x3F}, | ||
61 | {0x00403E69, 0x3F}, | ||
62 | {0x00403E6A, 0x0C}, | ||
63 | {0x00403E6B, 0x0C}, | ||
64 | {0x00403E6C, 0x80}, | ||
65 | {0x00403E6D, 0x80}, | ||
66 | {0x00403E6E, 0x08}, | ||
67 | {0x00403E6F, 0x08}, | ||
68 | {0x00403E70, 0x08}, | ||
69 | {0x00403E71, 0x30}, | ||
70 | {0x00403E72, 0x08}, | ||
71 | {0x00403E73, 0x04}, | ||
72 | {0x00403E74, 0x00}, | ||
73 | {0x00403E75, 0x10}, | ||
74 | {0x00403E76, 0x00}, | ||
75 | {0x00403E77, 0x00}, | ||
76 | {0x00403E78, 0x38}, | ||
77 | {0x00403E79, 0x00}, | ||
78 | {0x00403E7A, 0x55}, | ||
79 | {0x00403E7B, 0x03}, | ||
80 | {0x00403E7C, 0x03}, | ||
81 | {0x00403E7D, 0x00}, | ||
82 | {0x00403E7E, 0x03}, | ||
83 | {0x00403E7F, 0x00}, | ||
84 | {0x00403E80, 0x30}, | ||
85 | {0x00403E81, 0x30}, | ||
86 | {0x00403E82, 0x18}, | ||
87 | {0x00403E83, 0x0C}, | ||
88 | {0x00403E95, 0x00}, | ||
89 | {0x00403E96, 0x00}, | ||
90 | {0x00403E9B, 0x3F}, | ||
91 | {0x00403EA2, 0x0C}, | ||
92 | {0x00403EA3, 0x10}, | ||
93 | {0x00403EA6, 0x0C}, | ||
94 | {0x00403EA7, 0x10}, | ||
95 | {0x00403EA8, 0x44}, | ||
96 | {0x00403EA9, 0x00}, | ||
97 | }; | ||
98 | static bool vbus_prog = 1; | ||
99 | static int | ||
100 | tvp5158_get_gpios(struct device_node *node, struct i2c_client *client); | ||
101 | static int tvp5158_set_gpios(struct i2c_client *client); | ||
102 | static int | ||
103 | tvp5158_set_default(struct i2c_client *client, unsigned char core); | ||
104 | static enum tvp5158_std | ||
105 | tvp5158_get_video_std(struct i2c_client *client, unsigned char core); | ||
106 | static void | ||
107 | tvp5158_start_streaming(struct i2c_client *client, unsigned char core); | ||
108 | static int | ||
109 | tvp5158_set_int_regs(struct i2c_client *client, struct vbus_addr_value *reg, | ||
110 | int cnt); | ||
111 | |||
112 | #define REG_STAUS_1 0x00 | ||
113 | #define REG_STAUS_2 0x01 | ||
114 | #define REG_VID_STAND 0x0C | ||
115 | #define REG_CHIPID_MSB 0x08 | ||
116 | #define REG_CHIPID_LSB 0x09 | ||
117 | #define REG_AVD_CTRL_1 0xB0 | ||
118 | #define REG_AVD_CTRL_2 0xB1 | ||
119 | #define REG_OFM_CTRL 0xB2 | ||
120 | #define REG_DEC_RD_EN 0xFF | ||
121 | #define REG_DEC_WR_EN 0xFE | ||
122 | #define REG_VBUS_1 0xE8 | ||
123 | #define REG_VBUS_2 0xE9 | ||
124 | #define REG_VBUS_3 0xEA | ||
125 | #define REG_VBUS_DATA 0xE0 | ||
126 | |||
127 | #define TVP_CORE_ALL 0x0F | ||
128 | #define TVP_DECODER_1 (1<<0) | ||
129 | /* Non interleaved */ | ||
130 | #define TVP_INTERLEAVE_MODE_NON (0<<6) | ||
131 | /* Number of time multiplexed channels = 0 */ | ||
132 | #define TVP_CH_MUX_NUMBER (2<<4) | ||
133 | /* ITU BT 656 8 bit */ | ||
134 | #define TVP_OUTPUT_TYPE (0<<3) | ||
135 | /* Single stage */ | ||
136 | #define TVP_VCS_ID (0<<2) | ||
137 | /* D1 */ | ||
138 | #define TVP_VID_RES (0<<0) | ||
139 | |||
140 | #define TVP_ENABLE_DITHERING (1<<4) | ||
141 | #define TVP_VID_DET_SAVEAV_EN (1<<0) | ||
142 | |||
143 | #define TVP_VIDEO_PORT_ENABLE (1<<0) | ||
144 | #define TVP_OUT_CLK_P_EN (1<<2) | ||
145 | #define TVP_FIELD_RATE (1<<5) | ||
146 | #define TVP_SIGNAL_PRESENT (1<<7) | ||
147 | #define TVP_VIDEO_STANDARD_MASK (0x07) | ||
148 | |||
149 | /* Number of pixels and number of lines per frame for different standards */ | ||
150 | #define NTSC_NUM_ACTIVE_PIXELS (720) | ||
151 | #define NTSC_NUM_ACTIVE_LINES (480) | ||
152 | |||
153 | struct tvp5158_color_format { | ||
154 | enum v4l2_mbus_pixelcode code; | ||
155 | enum v4l2_colorspace colorspace; | ||
156 | }; | ||
157 | |||
158 | static const struct tvp5158_color_format tvp5158_cfmts[] = { | ||
159 | { | ||
160 | .code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
161 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
162 | }, | ||
163 | { | ||
164 | .code = V4L2_MBUS_FMT_YUYV10_2X10, | ||
165 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
166 | }, | ||
167 | }; | ||
168 | |||
169 | /* enum tvp5158_std - enum for supported standards */ | ||
170 | enum tvp5158_std { | ||
171 | STD_NTSC_MJ = 0, | ||
172 | STD_PAL_BDGHIN, | ||
173 | STD_INVALID | ||
174 | }; | ||
175 | |||
176 | /** | ||
177 | * struct tvp5158_std_info - Structure to store standard informations | ||
178 | * @width: Line width in pixels | ||
179 | * @height:Number of active lines | ||
180 | * @standard: v4l2 standard structure information | ||
181 | */ | ||
182 | struct tvp5158_std_info { | ||
183 | unsigned long width; | ||
184 | unsigned long height; | ||
185 | struct v4l2_standard standard; | ||
186 | }; | ||
187 | |||
188 | enum tvp5158_signal_present { | ||
189 | TVP5158_SIGNAL_DEAD = 0, | ||
190 | TVP5158_SIGNAL_PRESENT | ||
191 | }; | ||
192 | struct tvp5158_priv { | ||
193 | struct v4l2_subdev subdev; | ||
194 | struct v4l2_async_subdev asd; | ||
195 | struct v4l2_async_subdev_list asdl; | ||
196 | struct v4l2_ctrl_handler hdl; | ||
197 | int power; | ||
198 | int model; | ||
199 | int revision; | ||
200 | int width; | ||
201 | int height; | ||
202 | const char *sensor_name; | ||
203 | int cam_fpd_mux_s0_gpio; | ||
204 | int sel_tvp_fpd_s0; | ||
205 | enum tvp5158_std current_std; | ||
206 | enum tvp5158_signal_present signal_present; | ||
207 | const struct tvp5158_std_info *std_list; | ||
208 | const struct tvp5158_color_format *cfmt; | ||
209 | }; | ||
210 | |||
211 | static const struct tvp5158_std_info tvp5158_std_list[] = { | ||
212 | /* Standard: STD_NTSC_MJ */ | ||
213 | [STD_NTSC_MJ] = { | ||
214 | .width = NTSC_NUM_ACTIVE_PIXELS, | ||
215 | .height = NTSC_NUM_ACTIVE_LINES, | ||
216 | .standard = { | ||
217 | .index = 0, | ||
218 | .id = V4L2_STD_NTSC, | ||
219 | .name = "NTSC", | ||
220 | .frameperiod = {1001, 30000}, | ||
221 | .framelines = 525 | ||
222 | }, | ||
223 | }, | ||
224 | /* Standard: need to add for additional standard */ | ||
225 | }; | ||
226 | |||
227 | static struct tvp5158_priv *to_tvp5158(const struct i2c_client *client) | ||
228 | { | ||
229 | return container_of(i2c_get_clientdata(client), struct tvp5158_priv, | ||
230 | subdev); | ||
231 | } | ||
232 | |||
233 | |||
234 | static int tvp5158_read(struct i2c_client *client, unsigned char addr) | ||
235 | { | ||
236 | unsigned char buffer[1]; | ||
237 | int rc; | ||
238 | |||
239 | buffer[0] = addr; | ||
240 | |||
241 | rc = i2c_master_send(client, buffer, 1); | ||
242 | if (rc < 0) { | ||
243 | dev_err(&client->dev, "i2c i/o error: rc == %d (should be 1)\n" | ||
244 | , rc); | ||
245 | return rc; | ||
246 | } | ||
247 | |||
248 | rc = i2c_master_recv(client, buffer, 1); | ||
249 | if (rc < 0) { | ||
250 | dev_err(&client->dev, "i2c i/o error: rc == %d (should be 1)\n" | ||
251 | , rc); | ||
252 | return rc; | ||
253 | } | ||
254 | |||
255 | return buffer[0]; | ||
256 | } | ||
257 | static inline void tvp5158_write(struct i2c_client *client, unsigned char addr, | ||
258 | unsigned char value) | ||
259 | { | ||
260 | unsigned char buffer[2]; | ||
261 | int rc; | ||
262 | |||
263 | buffer[0] = addr; | ||
264 | buffer[1] = value; | ||
265 | rc = i2c_master_send(client, buffer, 2); | ||
266 | if (rc != 2) | ||
267 | dev_err(&client->dev, "i2c i/o error: rc == %d (should be 2)\n" | ||
268 | , rc); | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * tvp5158_s_stream() - V4L2 decoder i/f handler for s_stream | ||
273 | * @sd: pointer to standard V4L2 sub-device structure | ||
274 | * @enable: streaming enable or disable | ||
275 | * | ||
276 | * Sets streaming to enable or disable. | ||
277 | */ | ||
278 | static int tvp5158_s_stream(struct v4l2_subdev *sd, int enable) | ||
279 | { | ||
280 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
281 | if (enable) { | ||
282 | if (vbus_prog == 1) | ||
283 | /* VBUS address value setting */ | ||
284 | tvp5158_set_int_regs(client, vbus_addr_value_set, | ||
285 | ARRAY_SIZE(vbus_addr_value_set)); | ||
286 | tvp5158_start_streaming(client, TVP_DECODER_1); | ||
287 | } else { | ||
288 | tvp5158_write(client, REG_OFM_CTRL, 0x0); | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * tvp5158_querystd() - V4L2 decoder interface handler for querystd | ||
296 | * @sd: pointer to standard V4L2 sub-device structure | ||
297 | * @std_id: standard V4L2 std_id ioctl enum | ||
298 | * | ||
299 | * Returns the current standard detected by TVP5146/47. If no active input is | ||
300 | * detected then *std_id is set to 0 and the function returns 0. | ||
301 | */ | ||
302 | static int tvp5158_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) | ||
303 | { | ||
304 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
305 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
306 | |||
307 | if (std_id == NULL) | ||
308 | return -EINVAL; | ||
309 | *std_id = V4L2_STD_UNKNOWN; | ||
310 | |||
311 | tvp5158_get_video_std(client, TVP_DECODER_1); | ||
312 | if (priv->current_std == STD_INVALID) | ||
313 | return -EINVAL; | ||
314 | *std_id = priv->std_list[0].standard.id; | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * tvp5158_g_parm() - V4L2 decoder interface handler for g_parm | ||
321 | * @sd: pointer to standard V4L2 sub-device structure | ||
322 | * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure | ||
323 | * | ||
324 | * Returns the decoder's video CAPTURE parameters. | ||
325 | */ | ||
326 | static int tvp5158_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | ||
327 | { | ||
328 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
329 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
330 | struct v4l2_captureparm *cparm; | ||
331 | enum tvp5158_std current_std; | ||
332 | |||
333 | if (parms == NULL) | ||
334 | return -EINVAL; | ||
335 | |||
336 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
337 | /* only capture is supported */ | ||
338 | return -EINVAL; | ||
339 | tvp5158_set_default(client, TVP_DECODER_1); | ||
340 | tvp5158_get_video_std(client, TVP_DECODER_1); | ||
341 | if (priv->current_std == STD_INVALID) | ||
342 | return -EINVAL; | ||
343 | /* get the current standard */ | ||
344 | current_std = priv->current_std; | ||
345 | cparm = &parms->parm.capture; | ||
346 | cparm->capability = V4L2_CAP_TIMEPERFRAME; | ||
347 | cparm->timeperframe = | ||
348 | priv->std_list[current_std].standard.frameperiod; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * tvp5158_s_parm() - V4L2 decoder interface handler for s_parm | ||
355 | * @sd: pointer to standard V4L2 sub-device structure | ||
356 | * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure | ||
357 | * | ||
358 | * Configures the decoder to use the input parameters, if possible. If | ||
359 | * not possible, returns the appropriate error code. | ||
360 | */ | ||
361 | static int tvp5158_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | ||
362 | { | ||
363 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
364 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
365 | struct v4l2_fract *timeperframe; | ||
366 | enum tvp5158_std current_std; | ||
367 | |||
368 | if (parms == NULL) | ||
369 | return -EINVAL; | ||
370 | |||
371 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
372 | /* only capture is supported */ | ||
373 | return -EINVAL; | ||
374 | |||
375 | timeperframe = &parms->parm.capture.timeperframe; | ||
376 | |||
377 | /* get the current standard */ | ||
378 | current_std = priv->current_std; | ||
379 | |||
380 | *timeperframe = | ||
381 | priv->std_list[current_std].standard.frameperiod; | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | /* set the format we will capture in */ | ||
387 | static int tvp5158_s_fmt(struct v4l2_subdev *sd, | ||
388 | struct v4l2_mbus_framefmt *mf) | ||
389 | { | ||
390 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
391 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
392 | |||
393 | tvp5158_set_gpios(client); | ||
394 | v4l2_info(&priv->subdev, "Currently only D1 resolution is supported\n"); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int tvp5158_g_fmt(struct v4l2_subdev *sd, | ||
400 | struct v4l2_mbus_framefmt *mf) | ||
401 | { | ||
402 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
403 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
404 | enum tvp5158_std current_std; | ||
405 | |||
406 | tvp5158_set_default(client, TVP_DECODER_1); | ||
407 | tvp5158_get_video_std(client, TVP_DECODER_1); | ||
408 | |||
409 | if (priv->current_std == STD_INVALID) | ||
410 | return -EINVAL; | ||
411 | /* Calculate height and width based on current standard */ | ||
412 | current_std = priv->current_std; | ||
413 | /* both fields alternating into separate buffers */ | ||
414 | mf->field = V4L2_FIELD_ALTERNATE; | ||
415 | mf->code = tvp5158_cfmts[0].code; | ||
416 | mf->width = priv->std_list[current_std].width; | ||
417 | mf->height = priv->std_list[current_std].height; | ||
418 | mf->colorspace = tvp5158_cfmts[0].colorspace; | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int tvp5158_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | ||
424 | enum v4l2_mbus_pixelcode *code) | ||
425 | { | ||
426 | if (index >= ARRAY_SIZE(tvp5158_cfmts)) | ||
427 | return -EINVAL; | ||
428 | |||
429 | *code = tvp5158_cfmts[0].code; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int tvp5158_get_gpios(struct device_node *node, | ||
435 | struct i2c_client *client) | ||
436 | { | ||
437 | |||
438 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
439 | int gpio; | ||
440 | |||
441 | gpio = of_get_gpio(node, 0); | ||
442 | if (gpio_is_valid(gpio)) { | ||
443 | priv->cam_fpd_mux_s0_gpio = gpio; | ||
444 | } else { | ||
445 | dev_err(&client->dev, "failed to parse CAM_FPD_MUX_S0 gpio\n"); | ||
446 | return -EINVAL; | ||
447 | } | ||
448 | gpio = of_get_gpio(node, 1); | ||
449 | if (gpio_is_valid(gpio)) { | ||
450 | priv->sel_tvp_fpd_s0 = gpio; | ||
451 | } else { | ||
452 | dev_err(&client->dev, "failed to parse TVP_FPD_MUX_S0 gpio\n"); | ||
453 | return -EINVAL; | ||
454 | } | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static int tvp5158_set_gpios(struct i2c_client *client) | ||
460 | { | ||
461 | |||
462 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
463 | struct gpio gpios[] = { | ||
464 | { priv->sel_tvp_fpd_s0, GPIOF_OUT_INIT_LOW, | ||
465 | "tvp_fpd_mux_s0" }, | ||
466 | { priv->cam_fpd_mux_s0_gpio, GPIOF_OUT_INIT_HIGH, | ||
467 | "cam_fpd_mux_s0" }, | ||
468 | }; | ||
469 | int ret = -1; | ||
470 | |||
471 | ret = gpio_request_array(gpios, ARRAY_SIZE(gpios)); | ||
472 | if (ret) | ||
473 | return ret; | ||
474 | |||
475 | gpio_free_array(gpios, ARRAY_SIZE(gpios)); | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static struct v4l2_subdev_video_ops tvp5158_video_ops = { | ||
481 | .querystd = tvp5158_querystd, | ||
482 | .enum_mbus_fmt = tvp5158_enum_fmt, | ||
483 | .g_parm = tvp5158_g_parm, | ||
484 | .s_parm = tvp5158_s_parm, | ||
485 | .s_stream = tvp5158_s_stream, | ||
486 | .g_mbus_fmt = tvp5158_g_fmt, | ||
487 | .s_mbus_fmt = tvp5158_s_fmt, | ||
488 | .try_mbus_fmt = tvp5158_g_fmt, | ||
489 | }; | ||
490 | |||
491 | static struct v4l2_subdev_ops tvp5158_subdev_ops = { | ||
492 | .video = &tvp5158_video_ops, | ||
493 | }; | ||
494 | |||
495 | static const struct i2c_device_id tvp5158_id[] = { | ||
496 | { "ti,tvp5158", 0 }, | ||
497 | { } | ||
498 | }; | ||
499 | MODULE_DEVICE_TABLE(i2c, tvp5158_id); | ||
500 | |||
501 | static const struct of_device_id tvp5158_dt_id[] = { | ||
502 | { | ||
503 | .compatible = "ti,tvp5158", .data = "tvp5158" | ||
504 | }, | ||
505 | { | ||
506 | } | ||
507 | }; | ||
508 | |||
509 | static int tvp5158_set_int_regs(struct i2c_client *client, | ||
510 | struct vbus_addr_value *reg, int cnt) | ||
511 | { | ||
512 | int i = 0; | ||
513 | /* Core Write enable*/ | ||
514 | tvp5158_write(client, REG_DEC_WR_EN, TVP_DECODER_1); | ||
515 | for (i = 0; i < cnt; i++) { | ||
516 | tvp5158_write(client, REG_VBUS_1, ((reg[i].addr >> 0) & 0xFF)); | ||
517 | tvp5158_write(client, REG_VBUS_2, ((reg[i].addr >> 8) & 0xFF)); | ||
518 | tvp5158_write(client, REG_VBUS_3, ((reg[i].addr >> 16) & 0xFF)); | ||
519 | tvp5158_write(client, REG_VBUS_DATA, reg[i].val); | ||
520 | } | ||
521 | vbus_prog = 0; | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int | ||
526 | tvp5158_set_default(struct i2c_client *client, unsigned char core) | ||
527 | { | ||
528 | unsigned char tvp_reg_val = 0; | ||
529 | /* Core Write enable*/ | ||
530 | tvp5158_write(client, REG_DEC_WR_EN, core); | ||
531 | /* Set Video format */ | ||
532 | tvp_reg_val = TVP_INTERLEAVE_MODE_NON | TVP_CH_MUX_NUMBER | ||
533 | | TVP_OUTPUT_TYPE | TVP_VCS_ID | TVP_VID_RES; | ||
534 | tvp5158_write(client, REG_AVD_CTRL_1, tvp_reg_val); | ||
535 | tvp_reg_val = 0; | ||
536 | tvp_reg_val = TVP_ENABLE_DITHERING | TVP_VID_DET_SAVEAV_EN; | ||
537 | tvp5158_write(client, REG_AVD_CTRL_2, tvp_reg_val); | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static enum tvp5158_std | ||
543 | tvp5158_get_video_std(struct i2c_client *client, unsigned char core) | ||
544 | { | ||
545 | struct tvp5158_priv *priv = to_tvp5158(client); | ||
546 | int i2c_read = 0, ret = 0; | ||
547 | |||
548 | /* Core Read Enable */ | ||
549 | tvp5158_write(client, REG_DEC_RD_EN, core); | ||
550 | /* Get Video Status */ | ||
551 | i2c_read = tvp5158_read(client, REG_STAUS_2); | ||
552 | v4l2_dbg(1, debug, &priv->subdev, "%s\n", | ||
553 | (i2c_read & TVP_SIGNAL_PRESENT) ? | ||
554 | "Signal Present" : "Signal not present"); | ||
555 | if (i2c_read & TVP_SIGNAL_PRESENT) | ||
556 | priv->signal_present = TVP5158_SIGNAL_PRESENT; | ||
557 | else { | ||
558 | priv->current_std = STD_INVALID; | ||
559 | return priv->current_std; | ||
560 | } | ||
561 | /* Get Video Standard */ | ||
562 | ret = tvp5158_read(client, REG_VID_STAND); | ||
563 | i2c_read = tvp5158_read(client, REG_STAUS_1); | ||
564 | v4l2_dbg(1, debug, &priv->subdev, "Video Standard : %s %dHz\n", | ||
565 | (ret & TVP_VIDEO_STANDARD_MASK) == 1 ? | ||
566 | "NTSC 720x240 @" : "Unknown", | ||
567 | (i2c_read & TVP_FIELD_RATE) ? 50 : 60); | ||
568 | if (ret & TVP_VIDEO_STANDARD_MASK) { | ||
569 | priv->std_list = tvp5158_std_list; | ||
570 | priv->current_std = STD_NTSC_MJ; | ||
571 | } else | ||
572 | priv->current_std = STD_INVALID; | ||
573 | |||
574 | return priv->current_std; | ||
575 | } | ||
576 | |||
577 | static void | ||
578 | tvp5158_start_streaming(struct i2c_client *client, unsigned char core) | ||
579 | { | ||
580 | unsigned char tvp_reg_val = 0; | ||
581 | |||
582 | /* Decoder Write Enable */ | ||
583 | tvp5158_write(client, REG_DEC_WR_EN, core); | ||
584 | /* Enable output stream on */ | ||
585 | tvp_reg_val = TVP_VIDEO_PORT_ENABLE | TVP_OUT_CLK_P_EN ; | ||
586 | tvp5158_write(client, REG_OFM_CTRL, tvp_reg_val); | ||
587 | |||
588 | } | ||
589 | |||
590 | static int tvp5158_probe(struct i2c_client *client, | ||
591 | const struct i2c_device_id *did) | ||
592 | { | ||
593 | struct tvp5158_priv *priv; | ||
594 | struct v4l2_subdev *sd; | ||
595 | struct device_node *node = client->dev.of_node; | ||
596 | int ret = -1; | ||
597 | int i2c_read; | ||
598 | union { | ||
599 | char buff[4]; | ||
600 | int buffer; | ||
601 | } u_i2cbuf; | ||
602 | |||
603 | priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); | ||
604 | if (!priv) | ||
605 | return -ENOMEM; | ||
606 | i2c_set_clientdata(client, priv); | ||
607 | |||
608 | priv->cfmt = &tvp5158_cfmts[0]; | ||
609 | |||
610 | sd = &priv->subdev; | ||
611 | |||
612 | v4l2_i2c_subdev_init(sd, client, &tvp5158_subdev_ops); | ||
613 | |||
614 | ret = tvp5158_get_gpios(node, client); | ||
615 | if (ret) { | ||
616 | dev_err(&client->dev, "Unable to get gpios\n"); | ||
617 | return ret; | ||
618 | } | ||
619 | |||
620 | ret = tvp5158_set_gpios(client); | ||
621 | if (ret) { | ||
622 | dev_err(&client->dev, "failed to set gpios ERR %d\n", ret); | ||
623 | return ret; | ||
624 | } | ||
625 | |||
626 | priv->signal_present = TVP5158_SIGNAL_DEAD; | ||
627 | priv->current_std = STD_INVALID; | ||
628 | /* Get Chip ID and register with v4l2*/ | ||
629 | i2c_read = tvp5158_read(client, REG_CHIPID_MSB); | ||
630 | u_i2cbuf.buffer = i2c_read << 8; | ||
631 | i2c_read = tvp5158_read(client, REG_CHIPID_LSB); | ||
632 | u_i2cbuf.buffer |= i2c_read; | ||
633 | if (u_i2cbuf.buffer == 0x5158) { | ||
634 | v4l2_dbg(1, debug, sd, "Chip id : %x\n", u_i2cbuf.buffer); | ||
635 | tvp5158_write(client, REG_DEC_WR_EN, TVP_DECODER_1); | ||
636 | tvp5158_write(client, REG_OFM_CTRL, | ||
637 | (TVP_VIDEO_PORT_ENABLE | TVP_OUT_CLK_P_EN)); | ||
638 | /* V4l2 asyn subdev register */ | ||
639 | sd->dev = &client->dev; | ||
640 | ret = v4l2_async_register_subdev(sd); | ||
641 | if (!ret) | ||
642 | v4l2_info(&priv->subdev, "Camera sensor driver registered\n"); | ||
643 | pm_runtime_enable(&client->dev); | ||
644 | } | ||
645 | |||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | static int tvp5158_remove(struct i2c_client *client) | ||
650 | { | ||
651 | struct tvp5158_priv *priv = i2c_get_clientdata(client); | ||
652 | |||
653 | v4l2_device_unregister_subdev(&priv->subdev); | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | static struct i2c_driver tvp5158_i2c_driver = { | ||
658 | .driver = { | ||
659 | .owner = THIS_MODULE, | ||
660 | .name = "tvp5158", | ||
661 | .of_match_table = tvp5158_dt_id, | ||
662 | }, | ||
663 | .probe = tvp5158_probe, | ||
664 | .remove = tvp5158_remove, | ||
665 | .id_table = tvp5158_id, | ||
666 | }; | ||
667 | |||
668 | module_i2c_driver(tvp5158_i2c_driver); | ||
669 | |||
670 | MODULE_DESCRIPTION("Video Decoder driver"); | ||
671 | MODULE_AUTHOR("Sathishkumar S"); | ||
672 | MODULE_LICENSE("GPL v2"); | ||