1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * drivers/media/i2c/tvp514x.c |
4 | * |
5 | * TI TVP5146/47 decoder driver |
6 | * |
7 | * Copyright (C) 2008 Texas Instruments Inc |
8 | * Author: Vaibhav Hiremath <hvaibhav@ti.com> |
9 | * |
10 | * Contributors: |
11 | * Sivaraj R <sivaraj@ti.com> |
12 | * Brijesh R Jadav <brijesh.j@ti.com> |
13 | * Hardik Shah <hardik.shah@ti.com> |
14 | * Manjunath Hadli <mrh@ti.com> |
15 | * Karicheri Muralidharan <m-karicheri2@ti.com> |
16 | * Prabhakar Lad <prabhakar.lad@ti.com> |
17 | */ |
18 | |
19 | #include <linux/delay.h> |
20 | #include <linux/i2c.h> |
21 | #include <linux/mod_devicetable.h> |
22 | #include <linux/module.h> |
23 | #include <linux/of.h> |
24 | #include <linux/of_graph.h> |
25 | #include <linux/slab.h> |
26 | #include <linux/v4l2-mediabus.h> |
27 | #include <linux/videodev2.h> |
28 | |
29 | #include <media/i2c/tvp514x.h> |
30 | #include <media/media-entity.h> |
31 | #include <media/v4l2-async.h> |
32 | #include <media/v4l2-common.h> |
33 | #include <media/v4l2-ctrls.h> |
34 | #include <media/v4l2-device.h> |
35 | #include <media/v4l2-fwnode.h> |
36 | #include <media/v4l2-mediabus.h> |
37 | |
38 | #include "tvp514x_regs.h" |
39 | |
40 | /* Private macros for TVP */ |
41 | #define I2C_RETRY_COUNT (5) |
42 | #define LOCK_RETRY_COUNT (5) |
43 | #define LOCK_RETRY_DELAY (200) |
44 | |
45 | /* Debug functions */ |
46 | static bool debug; |
47 | module_param(debug, bool, 0644); |
48 | MODULE_PARM_DESC(debug, "Debug level (0-1)" ); |
49 | |
50 | MODULE_AUTHOR("Texas Instruments" ); |
51 | MODULE_DESCRIPTION("TVP514X linux decoder driver" ); |
52 | MODULE_LICENSE("GPL" ); |
53 | |
54 | /* enum tvp514x_std - enum for supported standards */ |
55 | enum tvp514x_std { |
56 | STD_NTSC_MJ = 0, |
57 | STD_PAL_BDGHIN, |
58 | STD_INVALID |
59 | }; |
60 | |
61 | /** |
62 | * struct tvp514x_std_info - Structure to store standard information |
63 | * @width: Line width in pixels |
64 | * @height:Number of active lines |
65 | * @video_std: Value to write in REG_VIDEO_STD register |
66 | * @standard: v4l2 standard structure information |
67 | */ |
68 | struct tvp514x_std_info { |
69 | unsigned long width; |
70 | unsigned long height; |
71 | u8 video_std; |
72 | struct v4l2_standard standard; |
73 | }; |
74 | |
75 | static struct tvp514x_reg tvp514x_reg_list_default[0x40]; |
76 | |
77 | static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); |
78 | /** |
79 | * struct tvp514x_decoder - TVP5146/47 decoder object |
80 | * @sd: Subdevice Slave handle |
81 | * @hdl: embedded &struct v4l2_ctrl_handler |
82 | * @tvp514x_regs: copy of hw's regs with preset values. |
83 | * @pdata: Board specific |
84 | * @ver: Chip version |
85 | * @streaming: TVP5146/47 decoder streaming - enabled or disabled. |
86 | * @pix: Current pixel format |
87 | * @num_fmts: Number of formats |
88 | * @fmt_list: Format list |
89 | * @current_std: Current standard |
90 | * @num_stds: Number of standards |
91 | * @std_list: Standards list |
92 | * @input: Input routing at chip level |
93 | * @output: Output routing at chip level |
94 | * @pad: subdev media pad associated with the decoder |
95 | * @format: media bus frame format |
96 | * @int_seq: driver's register init sequence |
97 | */ |
98 | struct tvp514x_decoder { |
99 | struct v4l2_subdev sd; |
100 | struct v4l2_ctrl_handler hdl; |
101 | struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; |
102 | const struct tvp514x_platform_data *pdata; |
103 | |
104 | int ver; |
105 | int streaming; |
106 | |
107 | struct v4l2_pix_format pix; |
108 | int num_fmts; |
109 | const struct v4l2_fmtdesc *fmt_list; |
110 | |
111 | enum tvp514x_std current_std; |
112 | int num_stds; |
113 | const struct tvp514x_std_info *std_list; |
114 | /* Input and Output Routing parameters */ |
115 | u32 input; |
116 | u32 output; |
117 | |
118 | /* mc related members */ |
119 | struct media_pad pad; |
120 | struct v4l2_mbus_framefmt format; |
121 | |
122 | const struct tvp514x_reg *int_seq; |
123 | }; |
124 | |
125 | /* TVP514x default register values */ |
126 | static struct tvp514x_reg tvp514x_reg_list_default[] = { |
127 | /* Composite selected */ |
128 | {TOK_WRITE, REG_INPUT_SEL, 0x05}, |
129 | {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F}, |
130 | /* Auto mode */ |
131 | {TOK_WRITE, REG_VIDEO_STD, 0x00}, |
132 | {TOK_WRITE, REG_OPERATION_MODE, 0x00}, |
133 | {TOK_SKIP, REG_AUTOSWITCH_MASK, 0x3F}, |
134 | {TOK_WRITE, REG_COLOR_KILLER, 0x10}, |
135 | {TOK_WRITE, REG_LUMA_CONTROL1, 0x00}, |
136 | {TOK_WRITE, REG_LUMA_CONTROL2, 0x00}, |
137 | {TOK_WRITE, REG_LUMA_CONTROL3, 0x02}, |
138 | {TOK_WRITE, REG_BRIGHTNESS, 0x80}, |
139 | {TOK_WRITE, REG_CONTRAST, 0x80}, |
140 | {TOK_WRITE, REG_SATURATION, 0x80}, |
141 | {TOK_WRITE, REG_HUE, 0x00}, |
142 | {TOK_WRITE, REG_CHROMA_CONTROL1, 0x00}, |
143 | {TOK_WRITE, REG_CHROMA_CONTROL2, 0x0E}, |
144 | /* Reserved */ |
145 | {TOK_SKIP, 0x0F, 0x00}, |
146 | {TOK_WRITE, REG_COMP_PR_SATURATION, 0x80}, |
147 | {TOK_WRITE, REG_COMP_Y_CONTRAST, 0x80}, |
148 | {TOK_WRITE, REG_COMP_PB_SATURATION, 0x80}, |
149 | /* Reserved */ |
150 | {TOK_SKIP, 0x13, 0x00}, |
151 | {TOK_WRITE, REG_COMP_Y_BRIGHTNESS, 0x80}, |
152 | /* Reserved */ |
153 | {TOK_SKIP, 0x15, 0x00}, |
154 | /* NTSC timing */ |
155 | {TOK_SKIP, REG_AVID_START_PIXEL_LSB, 0x55}, |
156 | {TOK_SKIP, REG_AVID_START_PIXEL_MSB, 0x00}, |
157 | {TOK_SKIP, REG_AVID_STOP_PIXEL_LSB, 0x25}, |
158 | {TOK_SKIP, REG_AVID_STOP_PIXEL_MSB, 0x03}, |
159 | /* NTSC timing */ |
160 | {TOK_SKIP, REG_HSYNC_START_PIXEL_LSB, 0x00}, |
161 | {TOK_SKIP, REG_HSYNC_START_PIXEL_MSB, 0x00}, |
162 | {TOK_SKIP, REG_HSYNC_STOP_PIXEL_LSB, 0x40}, |
163 | {TOK_SKIP, REG_HSYNC_STOP_PIXEL_MSB, 0x00}, |
164 | /* NTSC timing */ |
165 | {TOK_SKIP, REG_VSYNC_START_LINE_LSB, 0x04}, |
166 | {TOK_SKIP, REG_VSYNC_START_LINE_MSB, 0x00}, |
167 | {TOK_SKIP, REG_VSYNC_STOP_LINE_LSB, 0x07}, |
168 | {TOK_SKIP, REG_VSYNC_STOP_LINE_MSB, 0x00}, |
169 | /* NTSC timing */ |
170 | {TOK_SKIP, REG_VBLK_START_LINE_LSB, 0x01}, |
171 | {TOK_SKIP, REG_VBLK_START_LINE_MSB, 0x00}, |
172 | {TOK_SKIP, REG_VBLK_STOP_LINE_LSB, 0x15}, |
173 | {TOK_SKIP, REG_VBLK_STOP_LINE_MSB, 0x00}, |
174 | /* Reserved */ |
175 | {TOK_SKIP, 0x26, 0x00}, |
176 | /* Reserved */ |
177 | {TOK_SKIP, 0x27, 0x00}, |
178 | {TOK_SKIP, REG_FAST_SWTICH_CONTROL, 0xCC}, |
179 | /* Reserved */ |
180 | {TOK_SKIP, 0x29, 0x00}, |
181 | {TOK_SKIP, REG_FAST_SWTICH_SCART_DELAY, 0x00}, |
182 | /* Reserved */ |
183 | {TOK_SKIP, 0x2B, 0x00}, |
184 | {TOK_SKIP, REG_SCART_DELAY, 0x00}, |
185 | {TOK_SKIP, REG_CTI_DELAY, 0x00}, |
186 | {TOK_SKIP, REG_CTI_CONTROL, 0x00}, |
187 | /* Reserved */ |
188 | {TOK_SKIP, 0x2F, 0x00}, |
189 | /* Reserved */ |
190 | {TOK_SKIP, 0x30, 0x00}, |
191 | /* Reserved */ |
192 | {TOK_SKIP, 0x31, 0x00}, |
193 | /* HS, VS active high */ |
194 | {TOK_WRITE, REG_SYNC_CONTROL, 0x00}, |
195 | /* 10-bit BT.656 */ |
196 | {TOK_WRITE, REG_OUTPUT_FORMATTER1, 0x00}, |
197 | /* Enable clk & data */ |
198 | {TOK_WRITE, REG_OUTPUT_FORMATTER2, 0x11}, |
199 | /* Enable AVID & FLD */ |
200 | {TOK_WRITE, REG_OUTPUT_FORMATTER3, 0xEE}, |
201 | /* Enable VS & HS */ |
202 | {TOK_WRITE, REG_OUTPUT_FORMATTER4, 0xAF}, |
203 | {TOK_WRITE, REG_OUTPUT_FORMATTER5, 0xFF}, |
204 | {TOK_WRITE, REG_OUTPUT_FORMATTER6, 0xFF}, |
205 | /* Clear status */ |
206 | {TOK_WRITE, REG_CLEAR_LOST_LOCK, 0x01}, |
207 | {TOK_TERM, 0, 0}, |
208 | }; |
209 | |
210 | /* |
211 | * List of image formats supported by TVP5146/47 decoder |
212 | * Currently we are using 8 bit mode only, but can be |
213 | * extended to 10/20 bit mode. |
214 | */ |
215 | static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { |
216 | { |
217 | .index = 0, |
218 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, |
219 | .flags = 0, |
220 | .description = "8-bit UYVY 4:2:2 Format" , |
221 | .pixelformat = V4L2_PIX_FMT_UYVY, |
222 | }, |
223 | }; |
224 | |
225 | /* |
226 | * Supported standards - |
227 | * |
228 | * Currently supports two standards only, need to add support for rest of the |
229 | * modes, like SECAM, etc... |
230 | */ |
231 | static const struct tvp514x_std_info tvp514x_std_list[] = { |
232 | /* Standard: STD_NTSC_MJ */ |
233 | [STD_NTSC_MJ] = { |
234 | .width = NTSC_NUM_ACTIVE_PIXELS, |
235 | .height = NTSC_NUM_ACTIVE_LINES, |
236 | .video_std = VIDEO_STD_NTSC_MJ_BIT, |
237 | .standard = { |
238 | .index = 0, |
239 | .id = V4L2_STD_NTSC, |
240 | .name = "NTSC" , |
241 | .frameperiod = {1001, 30000}, |
242 | .framelines = 525 |
243 | }, |
244 | /* Standard: STD_PAL_BDGHIN */ |
245 | }, |
246 | [STD_PAL_BDGHIN] = { |
247 | .width = PAL_NUM_ACTIVE_PIXELS, |
248 | .height = PAL_NUM_ACTIVE_LINES, |
249 | .video_std = VIDEO_STD_PAL_BDGHIN_BIT, |
250 | .standard = { |
251 | .index = 1, |
252 | .id = V4L2_STD_PAL, |
253 | .name = "PAL" , |
254 | .frameperiod = {1, 25}, |
255 | .framelines = 625 |
256 | }, |
257 | }, |
258 | /* Standard: need to add for additional standard */ |
259 | }; |
260 | |
261 | |
262 | static inline struct tvp514x_decoder *to_decoder(struct v4l2_subdev *sd) |
263 | { |
264 | return container_of(sd, struct tvp514x_decoder, sd); |
265 | } |
266 | |
267 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) |
268 | { |
269 | return &container_of(ctrl->handler, struct tvp514x_decoder, hdl)->sd; |
270 | } |
271 | |
272 | |
273 | /** |
274 | * tvp514x_read_reg() - Read a value from a register in an TVP5146/47. |
275 | * @sd: ptr to v4l2_subdev struct |
276 | * @reg: TVP5146/47 register address |
277 | * |
278 | * Returns value read if successful, or non-zero (-1) otherwise. |
279 | */ |
280 | static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg) |
281 | { |
282 | int err, retry = 0; |
283 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
284 | |
285 | read_again: |
286 | |
287 | err = i2c_smbus_read_byte_data(client, command: reg); |
288 | if (err < 0) { |
289 | if (retry <= I2C_RETRY_COUNT) { |
290 | v4l2_warn(sd, "Read: retry ... %d\n" , retry); |
291 | retry++; |
292 | msleep_interruptible(msecs: 10); |
293 | goto read_again; |
294 | } |
295 | } |
296 | |
297 | return err; |
298 | } |
299 | |
300 | /** |
301 | * dump_reg() - dump the register content of TVP5146/47. |
302 | * @sd: ptr to v4l2_subdev struct |
303 | * @reg: TVP5146/47 register address |
304 | */ |
305 | static void dump_reg(struct v4l2_subdev *sd, u8 reg) |
306 | { |
307 | u32 val; |
308 | |
309 | val = tvp514x_read_reg(sd, reg); |
310 | v4l2_info(sd, "Reg(0x%.2X): 0x%.2X\n" , reg, val); |
311 | } |
312 | |
313 | /** |
314 | * tvp514x_write_reg() - Write a value to a register in TVP5146/47 |
315 | * @sd: ptr to v4l2_subdev struct |
316 | * @reg: TVP5146/47 register address |
317 | * @val: value to be written to the register |
318 | * |
319 | * Write a value to a register in an TVP5146/47 decoder device. |
320 | * Returns zero if successful, or non-zero otherwise. |
321 | */ |
322 | static int tvp514x_write_reg(struct v4l2_subdev *sd, u8 reg, u8 val) |
323 | { |
324 | int err, retry = 0; |
325 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
326 | |
327 | write_again: |
328 | |
329 | err = i2c_smbus_write_byte_data(client, command: reg, value: val); |
330 | if (err) { |
331 | if (retry <= I2C_RETRY_COUNT) { |
332 | v4l2_warn(sd, "Write: retry ... %d\n" , retry); |
333 | retry++; |
334 | msleep_interruptible(msecs: 10); |
335 | goto write_again; |
336 | } |
337 | } |
338 | |
339 | return err; |
340 | } |
341 | |
342 | /** |
343 | * tvp514x_write_regs() : Initializes a list of TVP5146/47 registers |
344 | * @sd: ptr to v4l2_subdev struct |
345 | * @reglist: list of TVP5146/47 registers and values |
346 | * |
347 | * Initializes a list of TVP5146/47 registers:- |
348 | * if token is TOK_TERM, then entire write operation terminates |
349 | * if token is TOK_DELAY, then a delay of 'val' msec is introduced |
350 | * if token is TOK_SKIP, then the register write is skipped |
351 | * if token is TOK_WRITE, then the register write is performed |
352 | * Returns zero if successful, or non-zero otherwise. |
353 | */ |
354 | static int tvp514x_write_regs(struct v4l2_subdev *sd, |
355 | const struct tvp514x_reg reglist[]) |
356 | { |
357 | int err; |
358 | const struct tvp514x_reg *next = reglist; |
359 | |
360 | for (; next->token != TOK_TERM; next++) { |
361 | if (next->token == TOK_DELAY) { |
362 | msleep(msecs: next->val); |
363 | continue; |
364 | } |
365 | |
366 | if (next->token == TOK_SKIP) |
367 | continue; |
368 | |
369 | err = tvp514x_write_reg(sd, reg: next->reg, val: (u8) next->val); |
370 | if (err) { |
371 | v4l2_err(sd, "Write failed. Err[%d]\n" , err); |
372 | return err; |
373 | } |
374 | } |
375 | return 0; |
376 | } |
377 | |
378 | /** |
379 | * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47 |
380 | * @sd: ptr to v4l2_subdev struct |
381 | * |
382 | * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no |
383 | * standard detected. |
384 | */ |
385 | static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd) |
386 | { |
387 | u8 std, std_status; |
388 | |
389 | std = tvp514x_read_reg(sd, REG_VIDEO_STD); |
390 | if ((std & VIDEO_STD_MASK) == VIDEO_STD_AUTO_SWITCH_BIT) |
391 | /* use the standard status register */ |
392 | std_status = tvp514x_read_reg(sd, REG_VIDEO_STD_STATUS); |
393 | else |
394 | /* use the standard register itself */ |
395 | std_status = std; |
396 | |
397 | switch (std_status & VIDEO_STD_MASK) { |
398 | case VIDEO_STD_NTSC_MJ_BIT: |
399 | return STD_NTSC_MJ; |
400 | |
401 | case VIDEO_STD_PAL_BDGHIN_BIT: |
402 | return STD_PAL_BDGHIN; |
403 | |
404 | default: |
405 | return STD_INVALID; |
406 | } |
407 | |
408 | return STD_INVALID; |
409 | } |
410 | |
411 | /* TVP5146/47 register dump function */ |
412 | static void tvp514x_reg_dump(struct v4l2_subdev *sd) |
413 | { |
414 | dump_reg(sd, REG_INPUT_SEL); |
415 | dump_reg(sd, REG_AFE_GAIN_CTRL); |
416 | dump_reg(sd, REG_VIDEO_STD); |
417 | dump_reg(sd, REG_OPERATION_MODE); |
418 | dump_reg(sd, REG_COLOR_KILLER); |
419 | dump_reg(sd, REG_LUMA_CONTROL1); |
420 | dump_reg(sd, REG_LUMA_CONTROL2); |
421 | dump_reg(sd, REG_LUMA_CONTROL3); |
422 | dump_reg(sd, REG_BRIGHTNESS); |
423 | dump_reg(sd, REG_CONTRAST); |
424 | dump_reg(sd, REG_SATURATION); |
425 | dump_reg(sd, REG_HUE); |
426 | dump_reg(sd, REG_CHROMA_CONTROL1); |
427 | dump_reg(sd, REG_CHROMA_CONTROL2); |
428 | dump_reg(sd, REG_COMP_PR_SATURATION); |
429 | dump_reg(sd, REG_COMP_Y_CONTRAST); |
430 | dump_reg(sd, REG_COMP_PB_SATURATION); |
431 | dump_reg(sd, REG_COMP_Y_BRIGHTNESS); |
432 | dump_reg(sd, REG_AVID_START_PIXEL_LSB); |
433 | dump_reg(sd, REG_AVID_START_PIXEL_MSB); |
434 | dump_reg(sd, REG_AVID_STOP_PIXEL_LSB); |
435 | dump_reg(sd, REG_AVID_STOP_PIXEL_MSB); |
436 | dump_reg(sd, REG_HSYNC_START_PIXEL_LSB); |
437 | dump_reg(sd, REG_HSYNC_START_PIXEL_MSB); |
438 | dump_reg(sd, REG_HSYNC_STOP_PIXEL_LSB); |
439 | dump_reg(sd, REG_HSYNC_STOP_PIXEL_MSB); |
440 | dump_reg(sd, REG_VSYNC_START_LINE_LSB); |
441 | dump_reg(sd, REG_VSYNC_START_LINE_MSB); |
442 | dump_reg(sd, REG_VSYNC_STOP_LINE_LSB); |
443 | dump_reg(sd, REG_VSYNC_STOP_LINE_MSB); |
444 | dump_reg(sd, REG_VBLK_START_LINE_LSB); |
445 | dump_reg(sd, REG_VBLK_START_LINE_MSB); |
446 | dump_reg(sd, REG_VBLK_STOP_LINE_LSB); |
447 | dump_reg(sd, REG_VBLK_STOP_LINE_MSB); |
448 | dump_reg(sd, REG_SYNC_CONTROL); |
449 | dump_reg(sd, REG_OUTPUT_FORMATTER1); |
450 | dump_reg(sd, REG_OUTPUT_FORMATTER2); |
451 | dump_reg(sd, REG_OUTPUT_FORMATTER3); |
452 | dump_reg(sd, REG_OUTPUT_FORMATTER4); |
453 | dump_reg(sd, REG_OUTPUT_FORMATTER5); |
454 | dump_reg(sd, REG_OUTPUT_FORMATTER6); |
455 | dump_reg(sd, REG_CLEAR_LOST_LOCK); |
456 | } |
457 | |
458 | /** |
459 | * tvp514x_configure() - Configure the TVP5146/47 registers |
460 | * @sd: ptr to v4l2_subdev struct |
461 | * @decoder: ptr to tvp514x_decoder structure |
462 | * |
463 | * Returns zero if successful, or non-zero otherwise. |
464 | */ |
465 | static int tvp514x_configure(struct v4l2_subdev *sd, |
466 | struct tvp514x_decoder *decoder) |
467 | { |
468 | int err; |
469 | |
470 | /* common register initialization */ |
471 | err = |
472 | tvp514x_write_regs(sd, reglist: decoder->tvp514x_regs); |
473 | if (err) |
474 | return err; |
475 | |
476 | if (debug) |
477 | tvp514x_reg_dump(sd); |
478 | |
479 | return 0; |
480 | } |
481 | |
482 | /** |
483 | * tvp514x_detect() - Detect if an tvp514x is present, and if so which revision. |
484 | * @sd: pointer to standard V4L2 sub-device structure |
485 | * @decoder: pointer to tvp514x_decoder structure |
486 | * |
487 | * A device is considered to be detected if the chip ID (LSB and MSB) |
488 | * registers match the expected values. |
489 | * Any value of the rom version register is accepted. |
490 | * Returns ENODEV error number if no device is detected, or zero |
491 | * if a device is detected. |
492 | */ |
493 | static int tvp514x_detect(struct v4l2_subdev *sd, |
494 | struct tvp514x_decoder *decoder) |
495 | { |
496 | u8 chip_id_msb, chip_id_lsb, rom_ver; |
497 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
498 | |
499 | chip_id_msb = tvp514x_read_reg(sd, REG_CHIP_ID_MSB); |
500 | chip_id_lsb = tvp514x_read_reg(sd, REG_CHIP_ID_LSB); |
501 | rom_ver = tvp514x_read_reg(sd, REG_ROM_VERSION); |
502 | |
503 | v4l2_dbg(1, debug, sd, |
504 | "chip id detected msb:0x%x lsb:0x%x rom version:0x%x\n" , |
505 | chip_id_msb, chip_id_lsb, rom_ver); |
506 | if ((chip_id_msb != TVP514X_CHIP_ID_MSB) |
507 | || ((chip_id_lsb != TVP5146_CHIP_ID_LSB) |
508 | && (chip_id_lsb != TVP5147_CHIP_ID_LSB))) { |
509 | /* We didn't read the values we expected, so this must not be |
510 | * an TVP5146/47. |
511 | */ |
512 | v4l2_err(sd, "chip id mismatch msb:0x%x lsb:0x%x\n" , |
513 | chip_id_msb, chip_id_lsb); |
514 | return -ENODEV; |
515 | } |
516 | |
517 | decoder->ver = rom_ver; |
518 | |
519 | v4l2_info(sd, "%s (Version - 0x%.2x) found at 0x%x (%s)\n" , |
520 | client->name, decoder->ver, |
521 | client->addr << 1, client->adapter->name); |
522 | return 0; |
523 | } |
524 | |
525 | /** |
526 | * tvp514x_querystd() - V4L2 decoder interface handler for querystd |
527 | * @sd: pointer to standard V4L2 sub-device structure |
528 | * @std_id: standard V4L2 std_id ioctl enum |
529 | * |
530 | * Returns the current standard detected by TVP5146/47. If no active input is |
531 | * detected then *std_id is set to 0 and the function returns 0. |
532 | */ |
533 | static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) |
534 | { |
535 | struct tvp514x_decoder *decoder = to_decoder(sd); |
536 | enum tvp514x_std current_std; |
537 | enum tvp514x_input input_sel; |
538 | u8 sync_lock_status, lock_mask; |
539 | |
540 | if (std_id == NULL) |
541 | return -EINVAL; |
542 | |
543 | /* To query the standard the TVP514x must power on the ADCs. */ |
544 | if (!decoder->streaming) { |
545 | tvp514x_s_stream(sd, enable: 1); |
546 | msleep(LOCK_RETRY_DELAY); |
547 | } |
548 | |
549 | /* query the current standard */ |
550 | current_std = tvp514x_query_current_std(sd); |
551 | if (current_std == STD_INVALID) { |
552 | *std_id = V4L2_STD_UNKNOWN; |
553 | return 0; |
554 | } |
555 | |
556 | input_sel = decoder->input; |
557 | |
558 | switch (input_sel) { |
559 | case INPUT_CVBS_VI1A: |
560 | case INPUT_CVBS_VI1B: |
561 | case INPUT_CVBS_VI1C: |
562 | case INPUT_CVBS_VI2A: |
563 | case INPUT_CVBS_VI2B: |
564 | case INPUT_CVBS_VI2C: |
565 | case INPUT_CVBS_VI3A: |
566 | case INPUT_CVBS_VI3B: |
567 | case INPUT_CVBS_VI3C: |
568 | case INPUT_CVBS_VI4A: |
569 | lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT | |
570 | STATUS_HORZ_SYNC_LOCK_BIT | |
571 | STATUS_VIRT_SYNC_LOCK_BIT; |
572 | break; |
573 | |
574 | case INPUT_SVIDEO_VI2A_VI1A: |
575 | case INPUT_SVIDEO_VI2B_VI1B: |
576 | case INPUT_SVIDEO_VI2C_VI1C: |
577 | case INPUT_SVIDEO_VI2A_VI3A: |
578 | case INPUT_SVIDEO_VI2B_VI3B: |
579 | case INPUT_SVIDEO_VI2C_VI3C: |
580 | case INPUT_SVIDEO_VI4A_VI1A: |
581 | case INPUT_SVIDEO_VI4A_VI1B: |
582 | case INPUT_SVIDEO_VI4A_VI1C: |
583 | case INPUT_SVIDEO_VI4A_VI3A: |
584 | case INPUT_SVIDEO_VI4A_VI3B: |
585 | case INPUT_SVIDEO_VI4A_VI3C: |
586 | lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | |
587 | STATUS_VIRT_SYNC_LOCK_BIT; |
588 | break; |
589 | /*Need to add other interfaces*/ |
590 | default: |
591 | return -EINVAL; |
592 | } |
593 | /* check whether signal is locked */ |
594 | sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); |
595 | if (lock_mask != (sync_lock_status & lock_mask)) { |
596 | *std_id = V4L2_STD_UNKNOWN; |
597 | return 0; /* No input detected */ |
598 | } |
599 | |
600 | *std_id &= decoder->std_list[current_std].standard.id; |
601 | |
602 | v4l2_dbg(1, debug, sd, "Current STD: %s\n" , |
603 | decoder->std_list[current_std].standard.name); |
604 | return 0; |
605 | } |
606 | |
607 | /** |
608 | * tvp514x_s_std() - V4L2 decoder interface handler for s_std |
609 | * @sd: pointer to standard V4L2 sub-device structure |
610 | * @std_id: standard V4L2 v4l2_std_id ioctl enum |
611 | * |
612 | * If std_id is supported, sets the requested standard. Otherwise, returns |
613 | * -EINVAL |
614 | */ |
615 | static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id) |
616 | { |
617 | struct tvp514x_decoder *decoder = to_decoder(sd); |
618 | int err, i; |
619 | |
620 | for (i = 0; i < decoder->num_stds; i++) |
621 | if (std_id & decoder->std_list[i].standard.id) |
622 | break; |
623 | |
624 | if ((i == decoder->num_stds) || (i == STD_INVALID)) |
625 | return -EINVAL; |
626 | |
627 | err = tvp514x_write_reg(sd, REG_VIDEO_STD, |
628 | val: decoder->std_list[i].video_std); |
629 | if (err) |
630 | return err; |
631 | |
632 | decoder->current_std = i; |
633 | decoder->tvp514x_regs[REG_VIDEO_STD].val = |
634 | decoder->std_list[i].video_std; |
635 | |
636 | v4l2_dbg(1, debug, sd, "Standard set to: %s\n" , |
637 | decoder->std_list[i].standard.name); |
638 | return 0; |
639 | } |
640 | |
641 | /** |
642 | * tvp514x_s_routing() - V4L2 decoder interface handler for s_routing |
643 | * @sd: pointer to standard V4L2 sub-device structure |
644 | * @input: input selector for routing the signal |
645 | * @output: output selector for routing the signal |
646 | * @config: config value. Not used |
647 | * |
648 | * If index is valid, selects the requested input. Otherwise, returns -EINVAL if |
649 | * the input is not supported or there is no active signal present in the |
650 | * selected input. |
651 | */ |
652 | static int tvp514x_s_routing(struct v4l2_subdev *sd, |
653 | u32 input, u32 output, u32 config) |
654 | { |
655 | struct tvp514x_decoder *decoder = to_decoder(sd); |
656 | int err; |
657 | enum tvp514x_input input_sel; |
658 | enum tvp514x_output output_sel; |
659 | |
660 | if ((input >= INPUT_INVALID) || |
661 | (output >= OUTPUT_INVALID)) |
662 | /* Index out of bound */ |
663 | return -EINVAL; |
664 | |
665 | input_sel = input; |
666 | output_sel = output; |
667 | |
668 | err = tvp514x_write_reg(sd, REG_INPUT_SEL, val: input_sel); |
669 | if (err) |
670 | return err; |
671 | |
672 | output_sel |= tvp514x_read_reg(sd, |
673 | REG_OUTPUT_FORMATTER1) & 0x7; |
674 | err = tvp514x_write_reg(sd, REG_OUTPUT_FORMATTER1, |
675 | val: output_sel); |
676 | if (err) |
677 | return err; |
678 | |
679 | decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel; |
680 | decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel; |
681 | decoder->input = input; |
682 | decoder->output = output; |
683 | |
684 | v4l2_dbg(1, debug, sd, "Input set to: %d\n" , input_sel); |
685 | |
686 | return 0; |
687 | } |
688 | |
689 | /** |
690 | * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl |
691 | * @ctrl: pointer to v4l2_ctrl structure |
692 | * |
693 | * If the requested control is supported, sets the control's current |
694 | * value in HW. Otherwise, returns -EINVAL if the control is not supported. |
695 | */ |
696 | static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl) |
697 | { |
698 | struct v4l2_subdev *sd = to_sd(ctrl); |
699 | struct tvp514x_decoder *decoder = to_decoder(sd); |
700 | int err = -EINVAL, value; |
701 | |
702 | value = ctrl->val; |
703 | |
704 | switch (ctrl->id) { |
705 | case V4L2_CID_BRIGHTNESS: |
706 | err = tvp514x_write_reg(sd, REG_BRIGHTNESS, val: value); |
707 | if (!err) |
708 | decoder->tvp514x_regs[REG_BRIGHTNESS].val = value; |
709 | break; |
710 | case V4L2_CID_CONTRAST: |
711 | err = tvp514x_write_reg(sd, REG_CONTRAST, val: value); |
712 | if (!err) |
713 | decoder->tvp514x_regs[REG_CONTRAST].val = value; |
714 | break; |
715 | case V4L2_CID_SATURATION: |
716 | err = tvp514x_write_reg(sd, REG_SATURATION, val: value); |
717 | if (!err) |
718 | decoder->tvp514x_regs[REG_SATURATION].val = value; |
719 | break; |
720 | case V4L2_CID_HUE: |
721 | if (value == 180) |
722 | value = 0x7F; |
723 | else if (value == -180) |
724 | value = 0x80; |
725 | err = tvp514x_write_reg(sd, REG_HUE, val: value); |
726 | if (!err) |
727 | decoder->tvp514x_regs[REG_HUE].val = value; |
728 | break; |
729 | case V4L2_CID_AUTOGAIN: |
730 | err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, val: value ? 0x0f : 0x0c); |
731 | if (!err) |
732 | decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value; |
733 | break; |
734 | } |
735 | |
736 | v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n" , |
737 | ctrl->id, ctrl->val); |
738 | return err; |
739 | } |
740 | |
741 | static int |
742 | tvp514x_get_frame_interval(struct v4l2_subdev *sd, |
743 | struct v4l2_subdev_state *sd_state, |
744 | struct v4l2_subdev_frame_interval *ival) |
745 | { |
746 | struct tvp514x_decoder *decoder = to_decoder(sd); |
747 | enum tvp514x_std current_std; |
748 | |
749 | /* |
750 | * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 |
751 | * subdev active state API. |
752 | */ |
753 | if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) |
754 | return -EINVAL; |
755 | |
756 | /* get the current standard */ |
757 | current_std = decoder->current_std; |
758 | |
759 | ival->interval = |
760 | decoder->std_list[current_std].standard.frameperiod; |
761 | |
762 | return 0; |
763 | } |
764 | |
765 | static int |
766 | tvp514x_set_frame_interval(struct v4l2_subdev *sd, |
767 | struct v4l2_subdev_state *sd_state, |
768 | struct v4l2_subdev_frame_interval *ival) |
769 | { |
770 | struct tvp514x_decoder *decoder = to_decoder(sd); |
771 | struct v4l2_fract *timeperframe; |
772 | enum tvp514x_std current_std; |
773 | |
774 | /* |
775 | * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 |
776 | * subdev active state API. |
777 | */ |
778 | if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) |
779 | return -EINVAL; |
780 | |
781 | timeperframe = &ival->interval; |
782 | |
783 | /* get the current standard */ |
784 | current_std = decoder->current_std; |
785 | |
786 | *timeperframe = |
787 | decoder->std_list[current_std].standard.frameperiod; |
788 | |
789 | return 0; |
790 | } |
791 | |
792 | /** |
793 | * tvp514x_s_stream() - V4L2 decoder i/f handler for s_stream |
794 | * @sd: pointer to standard V4L2 sub-device structure |
795 | * @enable: streaming enable or disable |
796 | * |
797 | * Sets streaming to enable or disable, if possible. |
798 | */ |
799 | static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) |
800 | { |
801 | int err = 0; |
802 | struct tvp514x_decoder *decoder = to_decoder(sd); |
803 | |
804 | if (decoder->streaming == enable) |
805 | return 0; |
806 | |
807 | switch (enable) { |
808 | case 0: |
809 | { |
810 | /* Power Down Sequence */ |
811 | err = tvp514x_write_reg(sd, REG_OPERATION_MODE, val: 0x01); |
812 | if (err) { |
813 | v4l2_err(sd, "Unable to turn off decoder\n" ); |
814 | return err; |
815 | } |
816 | decoder->streaming = enable; |
817 | break; |
818 | } |
819 | case 1: |
820 | { |
821 | /* Power Up Sequence */ |
822 | err = tvp514x_write_regs(sd, reglist: decoder->int_seq); |
823 | if (err) { |
824 | v4l2_err(sd, "Unable to turn on decoder\n" ); |
825 | return err; |
826 | } |
827 | /* Detect if not already detected */ |
828 | err = tvp514x_detect(sd, decoder); |
829 | if (err) { |
830 | v4l2_err(sd, "Unable to detect decoder\n" ); |
831 | return err; |
832 | } |
833 | err = tvp514x_configure(sd, decoder); |
834 | if (err) { |
835 | v4l2_err(sd, "Unable to configure decoder\n" ); |
836 | return err; |
837 | } |
838 | decoder->streaming = enable; |
839 | break; |
840 | } |
841 | default: |
842 | err = -ENODEV; |
843 | break; |
844 | } |
845 | |
846 | return err; |
847 | } |
848 | |
849 | static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = { |
850 | .s_ctrl = tvp514x_s_ctrl, |
851 | }; |
852 | |
853 | /** |
854 | * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code |
855 | * @sd: pointer to standard V4L2 sub-device structure |
856 | * @sd_state: subdev state |
857 | * @code: pointer to v4l2_subdev_mbus_code_enum structure |
858 | * |
859 | * Enumertaes mbus codes supported |
860 | */ |
861 | static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd, |
862 | struct v4l2_subdev_state *sd_state, |
863 | struct v4l2_subdev_mbus_code_enum *code) |
864 | { |
865 | u32 pad = code->pad; |
866 | u32 index = code->index; |
867 | |
868 | memset(code, 0, sizeof(*code)); |
869 | code->index = index; |
870 | code->pad = pad; |
871 | |
872 | if (index != 0) |
873 | return -EINVAL; |
874 | |
875 | code->code = MEDIA_BUS_FMT_UYVY8_2X8; |
876 | |
877 | return 0; |
878 | } |
879 | |
880 | /** |
881 | * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format |
882 | * @sd: pointer to standard V4L2 sub-device structure |
883 | * @sd_state: subdev state |
884 | * @format: pointer to v4l2_subdev_format structure |
885 | * |
886 | * Retrieves pad format which is active or tried based on requirement |
887 | */ |
888 | static int tvp514x_get_pad_format(struct v4l2_subdev *sd, |
889 | struct v4l2_subdev_state *sd_state, |
890 | struct v4l2_subdev_format *format) |
891 | { |
892 | struct tvp514x_decoder *decoder = to_decoder(sd); |
893 | __u32 which = format->which; |
894 | |
895 | if (format->pad) |
896 | return -EINVAL; |
897 | |
898 | if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { |
899 | format->format = decoder->format; |
900 | return 0; |
901 | } |
902 | |
903 | format->format.code = MEDIA_BUS_FMT_UYVY8_2X8; |
904 | format->format.width = tvp514x_std_list[decoder->current_std].width; |
905 | format->format.height = tvp514x_std_list[decoder->current_std].height; |
906 | format->format.colorspace = V4L2_COLORSPACE_SMPTE170M; |
907 | format->format.field = V4L2_FIELD_INTERLACED; |
908 | |
909 | return 0; |
910 | } |
911 | |
912 | /** |
913 | * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format |
914 | * @sd: pointer to standard V4L2 sub-device structure |
915 | * @sd_state: subdev state |
916 | * @fmt: pointer to v4l2_subdev_format structure |
917 | * |
918 | * Set pad format for the output pad |
919 | */ |
920 | static int tvp514x_set_pad_format(struct v4l2_subdev *sd, |
921 | struct v4l2_subdev_state *sd_state, |
922 | struct v4l2_subdev_format *fmt) |
923 | { |
924 | struct tvp514x_decoder *decoder = to_decoder(sd); |
925 | |
926 | if (fmt->format.field != V4L2_FIELD_INTERLACED || |
927 | fmt->format.code != MEDIA_BUS_FMT_UYVY8_2X8 || |
928 | fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M || |
929 | fmt->format.width != tvp514x_std_list[decoder->current_std].width || |
930 | fmt->format.height != tvp514x_std_list[decoder->current_std].height) |
931 | return -EINVAL; |
932 | |
933 | decoder->format = fmt->format; |
934 | |
935 | return 0; |
936 | } |
937 | |
938 | static const struct v4l2_subdev_video_ops tvp514x_video_ops = { |
939 | .s_std = tvp514x_s_std, |
940 | .s_routing = tvp514x_s_routing, |
941 | .querystd = tvp514x_querystd, |
942 | .s_stream = tvp514x_s_stream, |
943 | }; |
944 | |
945 | static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = { |
946 | .enum_mbus_code = tvp514x_enum_mbus_code, |
947 | .get_fmt = tvp514x_get_pad_format, |
948 | .set_fmt = tvp514x_set_pad_format, |
949 | .get_frame_interval = tvp514x_get_frame_interval, |
950 | .set_frame_interval = tvp514x_set_frame_interval, |
951 | }; |
952 | |
953 | static const struct v4l2_subdev_ops tvp514x_ops = { |
954 | .video = &tvp514x_video_ops, |
955 | .pad = &tvp514x_pad_ops, |
956 | }; |
957 | |
958 | static const struct tvp514x_decoder tvp514x_dev = { |
959 | .streaming = 0, |
960 | .fmt_list = tvp514x_fmt_list, |
961 | .num_fmts = ARRAY_SIZE(tvp514x_fmt_list), |
962 | .pix = { |
963 | /* Default to NTSC 8-bit YUV 422 */ |
964 | .width = NTSC_NUM_ACTIVE_PIXELS, |
965 | .height = NTSC_NUM_ACTIVE_LINES, |
966 | .pixelformat = V4L2_PIX_FMT_UYVY, |
967 | .field = V4L2_FIELD_INTERLACED, |
968 | .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2, |
969 | .sizeimage = NTSC_NUM_ACTIVE_PIXELS * 2 * |
970 | NTSC_NUM_ACTIVE_LINES, |
971 | .colorspace = V4L2_COLORSPACE_SMPTE170M, |
972 | }, |
973 | .current_std = STD_NTSC_MJ, |
974 | .std_list = tvp514x_std_list, |
975 | .num_stds = ARRAY_SIZE(tvp514x_std_list), |
976 | |
977 | }; |
978 | |
979 | static struct tvp514x_platform_data * |
980 | tvp514x_get_pdata(struct i2c_client *client) |
981 | { |
982 | struct tvp514x_platform_data *pdata = NULL; |
983 | struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; |
984 | struct device_node *endpoint; |
985 | unsigned int flags; |
986 | |
987 | if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) |
988 | return client->dev.platform_data; |
989 | |
990 | endpoint = of_graph_get_endpoint_by_regs(parent: client->dev.of_node, port_reg: 0, reg: -1); |
991 | if (!endpoint) |
992 | return NULL; |
993 | |
994 | if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), vep: &bus_cfg)) |
995 | goto done; |
996 | |
997 | pdata = devm_kzalloc(dev: &client->dev, size: sizeof(*pdata), GFP_KERNEL); |
998 | if (!pdata) |
999 | goto done; |
1000 | |
1001 | flags = bus_cfg.bus.parallel.flags; |
1002 | |
1003 | if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) |
1004 | pdata->hs_polarity = 1; |
1005 | |
1006 | if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) |
1007 | pdata->vs_polarity = 1; |
1008 | |
1009 | if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) |
1010 | pdata->clk_polarity = 1; |
1011 | |
1012 | done: |
1013 | of_node_put(node: endpoint); |
1014 | return pdata; |
1015 | } |
1016 | |
1017 | /** |
1018 | * tvp514x_probe() - decoder driver i2c probe handler |
1019 | * @client: i2c driver client device structure |
1020 | * |
1021 | * Register decoder as an i2c client device and V4L2 |
1022 | * device. |
1023 | */ |
1024 | static int |
1025 | tvp514x_probe(struct i2c_client *client) |
1026 | { |
1027 | struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); |
1028 | struct tvp514x_decoder *decoder; |
1029 | struct v4l2_subdev *sd; |
1030 | int ret; |
1031 | |
1032 | if (pdata == NULL) { |
1033 | dev_err(&client->dev, "No platform data\n" ); |
1034 | return -EINVAL; |
1035 | } |
1036 | |
1037 | /* Check if the adapter supports the needed features */ |
1038 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1039 | return -EIO; |
1040 | |
1041 | decoder = devm_kzalloc(dev: &client->dev, size: sizeof(*decoder), GFP_KERNEL); |
1042 | if (!decoder) |
1043 | return -ENOMEM; |
1044 | |
1045 | /* Initialize the tvp514x_decoder with default configuration */ |
1046 | *decoder = tvp514x_dev; |
1047 | /* Copy default register configuration */ |
1048 | memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, |
1049 | sizeof(tvp514x_reg_list_default)); |
1050 | |
1051 | decoder->int_seq = i2c_get_match_data(client); |
1052 | |
1053 | /* Copy board specific information here */ |
1054 | decoder->pdata = pdata; |
1055 | |
1056 | /** |
1057 | * Fetch platform specific data, and configure the |
1058 | * tvp514x_reg_list[] accordingly. Since this is one |
1059 | * time configuration, no need to preserve. |
1060 | */ |
1061 | decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |= |
1062 | (decoder->pdata->clk_polarity << 1); |
1063 | decoder->tvp514x_regs[REG_SYNC_CONTROL].val |= |
1064 | ((decoder->pdata->hs_polarity << 2) | |
1065 | (decoder->pdata->vs_polarity << 3)); |
1066 | /* Set default standard to auto */ |
1067 | decoder->tvp514x_regs[REG_VIDEO_STD].val = |
1068 | VIDEO_STD_AUTO_SWITCH_BIT; |
1069 | |
1070 | /* Register with V4L2 layer as slave device */ |
1071 | sd = &decoder->sd; |
1072 | v4l2_i2c_subdev_init(sd, client, ops: &tvp514x_ops); |
1073 | |
1074 | #if defined(CONFIG_MEDIA_CONTROLLER) |
1075 | decoder->pad.flags = MEDIA_PAD_FL_SOURCE; |
1076 | decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1077 | decoder->sd.entity.function = MEDIA_ENT_F_ATV_DECODER; |
1078 | |
1079 | ret = media_entity_pads_init(entity: &decoder->sd.entity, num_pads: 1, pads: &decoder->pad); |
1080 | if (ret < 0) { |
1081 | v4l2_err(sd, "%s decoder driver failed to register !!\n" , |
1082 | sd->name); |
1083 | return ret; |
1084 | } |
1085 | #endif |
1086 | v4l2_ctrl_handler_init(&decoder->hdl, 5); |
1087 | v4l2_ctrl_new_std(hdl: &decoder->hdl, ops: &tvp514x_ctrl_ops, |
1088 | V4L2_CID_BRIGHTNESS, min: 0, max: 255, step: 1, def: 128); |
1089 | v4l2_ctrl_new_std(hdl: &decoder->hdl, ops: &tvp514x_ctrl_ops, |
1090 | V4L2_CID_CONTRAST, min: 0, max: 255, step: 1, def: 128); |
1091 | v4l2_ctrl_new_std(hdl: &decoder->hdl, ops: &tvp514x_ctrl_ops, |
1092 | V4L2_CID_SATURATION, min: 0, max: 255, step: 1, def: 128); |
1093 | v4l2_ctrl_new_std(hdl: &decoder->hdl, ops: &tvp514x_ctrl_ops, |
1094 | V4L2_CID_HUE, min: -180, max: 180, step: 180, def: 0); |
1095 | v4l2_ctrl_new_std(hdl: &decoder->hdl, ops: &tvp514x_ctrl_ops, |
1096 | V4L2_CID_AUTOGAIN, min: 0, max: 1, step: 1, def: 1); |
1097 | sd->ctrl_handler = &decoder->hdl; |
1098 | if (decoder->hdl.error) { |
1099 | ret = decoder->hdl.error; |
1100 | goto done; |
1101 | } |
1102 | v4l2_ctrl_handler_setup(hdl: &decoder->hdl); |
1103 | |
1104 | ret = v4l2_async_register_subdev(sd: &decoder->sd); |
1105 | if (!ret) |
1106 | v4l2_info(sd, "%s decoder driver registered !!\n" , sd->name); |
1107 | |
1108 | done: |
1109 | if (ret < 0) { |
1110 | v4l2_ctrl_handler_free(hdl: &decoder->hdl); |
1111 | media_entity_cleanup(entity: &decoder->sd.entity); |
1112 | } |
1113 | return ret; |
1114 | } |
1115 | |
1116 | /** |
1117 | * tvp514x_remove() - decoder driver i2c remove handler |
1118 | * @client: i2c driver client device structure |
1119 | * |
1120 | * Unregister decoder as an i2c client device and V4L2 |
1121 | * device. Complement of tvp514x_probe(). |
1122 | */ |
1123 | static void tvp514x_remove(struct i2c_client *client) |
1124 | { |
1125 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1126 | struct tvp514x_decoder *decoder = to_decoder(sd); |
1127 | |
1128 | v4l2_async_unregister_subdev(sd: &decoder->sd); |
1129 | media_entity_cleanup(entity: &decoder->sd.entity); |
1130 | v4l2_ctrl_handler_free(hdl: &decoder->hdl); |
1131 | } |
1132 | /* TVP5146 Init/Power on Sequence */ |
1133 | static const struct tvp514x_reg tvp5146_init_reg_seq[] = { |
1134 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, |
1135 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, |
1136 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, |
1137 | {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, |
1138 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, |
1139 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, |
1140 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, |
1141 | {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, |
1142 | {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, |
1143 | {TOK_WRITE, REG_OPERATION_MODE, 0x01}, |
1144 | {TOK_WRITE, REG_OPERATION_MODE, 0x00}, |
1145 | {TOK_TERM, 0, 0}, |
1146 | }; |
1147 | |
1148 | /* TVP5147 Init/Power on Sequence */ |
1149 | static const struct tvp514x_reg tvp5147_init_reg_seq[] = { |
1150 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, |
1151 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, |
1152 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80}, |
1153 | {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, |
1154 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, |
1155 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, |
1156 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, |
1157 | {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01}, |
1158 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x16}, |
1159 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, |
1160 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xA0}, |
1161 | {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x16}, |
1162 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60}, |
1163 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, |
1164 | {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0}, |
1165 | {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, |
1166 | {TOK_WRITE, REG_OPERATION_MODE, 0x01}, |
1167 | {TOK_WRITE, REG_OPERATION_MODE, 0x00}, |
1168 | {TOK_TERM, 0, 0}, |
1169 | }; |
1170 | |
1171 | /* TVP5146M2/TVP5147M1 Init/Power on Sequence */ |
1172 | static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { |
1173 | {TOK_WRITE, REG_OPERATION_MODE, 0x01}, |
1174 | {TOK_WRITE, REG_OPERATION_MODE, 0x00}, |
1175 | {TOK_TERM, 0, 0}, |
1176 | }; |
1177 | |
1178 | /* |
1179 | * I2C Device Table - |
1180 | * |
1181 | * name - Name of the actual device/chip. |
1182 | * driver_data - Driver data |
1183 | */ |
1184 | static const struct i2c_device_id tvp514x_id[] = { |
1185 | {"tvp5146" , (kernel_ulong_t)tvp5146_init_reg_seq }, |
1186 | {"tvp5146m2" , (kernel_ulong_t)tvp514xm_init_reg_seq }, |
1187 | {"tvp5147" , (kernel_ulong_t)tvp5147_init_reg_seq }, |
1188 | {"tvp5147m1" , (kernel_ulong_t)tvp514xm_init_reg_seq }, |
1189 | { /* sentinel */ } |
1190 | }; |
1191 | MODULE_DEVICE_TABLE(i2c, tvp514x_id); |
1192 | |
1193 | static const struct of_device_id tvp514x_of_match[] = { |
1194 | { .compatible = "ti,tvp5146" , .data = tvp5146_init_reg_seq }, |
1195 | { .compatible = "ti,tvp5146m2" , .data = tvp514xm_init_reg_seq }, |
1196 | { .compatible = "ti,tvp5147" , .data = tvp5147_init_reg_seq }, |
1197 | { .compatible = "ti,tvp5147m1" , .data = tvp514xm_init_reg_seq }, |
1198 | { /* sentinel */ } |
1199 | }; |
1200 | MODULE_DEVICE_TABLE(of, tvp514x_of_match); |
1201 | |
1202 | static struct i2c_driver tvp514x_driver = { |
1203 | .driver = { |
1204 | .of_match_table = tvp514x_of_match, |
1205 | .name = TVP514X_MODULE_NAME, |
1206 | }, |
1207 | .probe = tvp514x_probe, |
1208 | .remove = tvp514x_remove, |
1209 | .id_table = tvp514x_id, |
1210 | }; |
1211 | |
1212 | module_i2c_driver(tvp514x_driver); |
1213 | |