aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/adv7343.c
diff options
context:
space:
mode:
authorChaithrika U S <chaithrika@ti.com>2009-05-07 08:30:01 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-16 17:20:59 -0400
commit06e61f8d5f5df68104168ac20d0527ecee13638a (patch)
tree11a0a57bfd6120a79edb2a13d358732f72bbda99 /drivers/media/video/adv7343.c
parent40199c50b891d24d1a8f1d480f886680a3ac9b74 (diff)
V4L/DVB (11743): Analog Devices ADV7343 video encoder driver
Add ADV7343 I2C based video encoder driver. This follows the v4l2-subdev framework. This driver has been tested on TI DM646x EVM. It has been tested for Composite and Component outputs. Updates as per review by Mauro Chehab, added support for more standards supported by the encoder. Also adding the missed out signed-offs.Tested only NTSC and PAL standards. [hverkuil@xs4all.nl: s_routing API changed, updated driver to use new API] Signed-off-by: Manjunath Hadli <mrh@ti.com> Signed-off-by: Brijesh Jadav <brijesh.j@ti.com> Signed-off-by: Chaithrika U S <chaithrika@ti.com> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/adv7343.c')
-rw-r--r--drivers/media/video/adv7343.c534
1 files changed, 534 insertions, 0 deletions
diff --git a/drivers/media/video/adv7343.c b/drivers/media/video/adv7343.c
new file mode 100644
index 000000000000..30f5caf5dda5
--- /dev/null
+++ b/drivers/media/video/adv7343.c
@@ -0,0 +1,534 @@
1/*
2 * adv7343 - ADV7343 Video Encoder Driver
3 *
4 * The encoder hardware does not support SECAM.
5 *
6 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation version 2.
11 *
12 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/ctype.h>
21#include <linux/i2c.h>
22#include <linux/device.h>
23#include <linux/delay.h>
24#include <linux/module.h>
25#include <linux/videodev2.h>
26#include <linux/uaccess.h>
27#include <linux/version.h>
28
29#include <media/adv7343.h>
30#include <media/v4l2-device.h>
31#include <media/v4l2-chip-ident.h>
32
33#include "adv7343_regs.h"
34
35MODULE_DESCRIPTION("ADV7343 video encoder driver");
36MODULE_LICENSE("GPL");
37
38static int debug;
39module_param(debug, int, 0644);
40MODULE_PARM_DESC(debug, "Debug level 0-1");
41
42struct adv7343_state {
43 struct v4l2_subdev sd;
44 u8 reg00;
45 u8 reg01;
46 u8 reg02;
47 u8 reg35;
48 u8 reg80;
49 u8 reg82;
50 int bright;
51 int hue;
52 int gain;
53 u32 output;
54 v4l2_std_id std;
55};
56
57static inline struct adv7343_state *to_state(struct v4l2_subdev *sd)
58{
59 return container_of(sd, struct adv7343_state, sd);
60}
61
62static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value)
63{
64 struct i2c_client *client = v4l2_get_subdevdata(sd);
65
66 return i2c_smbus_write_byte_data(client, reg, value);
67}
68
69static const u8 adv7343_init_reg_val[] = {
70 ADV7343_SOFT_RESET, ADV7343_SOFT_RESET_DEFAULT,
71 ADV7343_POWER_MODE_REG, ADV7343_POWER_MODE_REG_DEFAULT,
72
73 ADV7343_HD_MODE_REG1, ADV7343_HD_MODE_REG1_DEFAULT,
74 ADV7343_HD_MODE_REG2, ADV7343_HD_MODE_REG2_DEFAULT,
75 ADV7343_HD_MODE_REG3, ADV7343_HD_MODE_REG3_DEFAULT,
76 ADV7343_HD_MODE_REG4, ADV7343_HD_MODE_REG4_DEFAULT,
77 ADV7343_HD_MODE_REG5, ADV7343_HD_MODE_REG5_DEFAULT,
78 ADV7343_HD_MODE_REG6, ADV7343_HD_MODE_REG6_DEFAULT,
79 ADV7343_HD_MODE_REG7, ADV7343_HD_MODE_REG7_DEFAULT,
80
81 ADV7343_SD_MODE_REG1, ADV7343_SD_MODE_REG1_DEFAULT,
82 ADV7343_SD_MODE_REG2, ADV7343_SD_MODE_REG2_DEFAULT,
83 ADV7343_SD_MODE_REG3, ADV7343_SD_MODE_REG3_DEFAULT,
84 ADV7343_SD_MODE_REG4, ADV7343_SD_MODE_REG4_DEFAULT,
85 ADV7343_SD_MODE_REG5, ADV7343_SD_MODE_REG5_DEFAULT,
86 ADV7343_SD_MODE_REG6, ADV7343_SD_MODE_REG6_DEFAULT,
87 ADV7343_SD_MODE_REG7, ADV7343_SD_MODE_REG7_DEFAULT,
88 ADV7343_SD_MODE_REG8, ADV7343_SD_MODE_REG8_DEFAULT,
89
90 ADV7343_SD_HUE_REG, ADV7343_SD_HUE_REG_DEFAULT,
91 ADV7343_SD_CGMS_WSS0, ADV7343_SD_CGMS_WSS0_DEFAULT,
92 ADV7343_SD_BRIGHTNESS_WSS, ADV7343_SD_BRIGHTNESS_WSS_DEFAULT,
93};
94
95/*
96 * 2^32
97 * FSC(reg) = FSC (HZ) * --------
98 * 27000000
99 */
100static const struct adv7343_std_info stdinfo[] = {
101 {
102 /* FSC(Hz) = 3,579,545.45 Hz */
103 SD_STD_NTSC, 569408542, V4L2_STD_NTSC,
104 }, {
105 /* FSC(Hz) = 3,575,611.00 Hz */
106 SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M,
107 }, {
108 /* FSC(Hz) = 3,582,056.00 */
109 SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc,
110 }, {
111 /* FSC(Hz) = 4,433,618.75 Hz */
112 SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N,
113 }, {
114 /* FSC(Hz) = 4,433,618.75 Hz */
115 SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL,
116 }, {
117 /* FSC(Hz) = 4,433,618.75 Hz */
118 SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443,
119 }, {
120 /* FSC(Hz) = 4,433,618.75 Hz */
121 SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60,
122 },
123};
124
125static int adv7343_setstd(struct v4l2_subdev *sd, v4l2_std_id std)
126{
127 struct adv7343_state *state = to_state(sd);
128 struct adv7343_std_info *std_info;
129 int output_idx, num_std;
130 char *fsc_ptr;
131 u8 reg, val;
132 int err = 0;
133 int i = 0;
134
135 output_idx = state->output;
136
137 std_info = (struct adv7343_std_info *)stdinfo;
138 num_std = ARRAY_SIZE(stdinfo);
139
140 for (i = 0; i < num_std; i++) {
141 if (std_info[i].stdid & std)
142 break;
143 }
144
145 if (i == num_std) {
146 v4l2_dbg(1, debug, sd,
147 "Invalid std or std is not supported: %llx\n",
148 (unsigned long long)std);
149 return -EINVAL;
150 }
151
152 /* Set the standard */
153 val = state->reg80 & (~(SD_STD_MASK));
154 val |= std_info[i].standard_val3;
155 err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
156 if (err < 0)
157 goto setstd_exit;
158
159 state->reg80 = val;
160
161 /* Configure the input mode register */
162 val = state->reg01 & (~((u8) INPUT_MODE_MASK));
163 val |= SD_INPUT_MODE;
164 err = adv7343_write(sd, ADV7343_MODE_SELECT_REG, val);
165 if (err < 0)
166 goto setstd_exit;
167
168 state->reg01 = val;
169
170 /* Program the sub carrier frequency registers */
171 fsc_ptr = (unsigned char *)&std_info[i].fsc_val;
172 reg = ADV7343_FSC_REG0;
173 for (i = 0; i < 4; i++, reg++, fsc_ptr++) {
174 err = adv7343_write(sd, reg, *fsc_ptr);
175 if (err < 0)
176 goto setstd_exit;
177 }
178
179 val = state->reg80;
180
181 /* Filter settings */
182 if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443))
183 val &= 0x03;
184 else if (std & ~V4L2_STD_SECAM)
185 val |= 0x04;
186
187 err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
188 if (err < 0)
189 goto setstd_exit;
190
191 state->reg80 = val;
192
193setstd_exit:
194 if (err != 0)
195 v4l2_err(sd, "Error setting std, write failed\n");
196
197 return err;
198}
199
200static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
201{
202 struct adv7343_state *state = to_state(sd);
203 unsigned char val;
204 int err = 0;
205
206 if (output_type > ADV7343_SVIDEO_ID) {
207 v4l2_dbg(1, debug, sd,
208 "Invalid output type or output type not supported:%d\n",
209 output_type);
210 return -EINVAL;
211 }
212
213 /* Enable Appropriate DAC */
214 val = state->reg00 & 0x03;
215
216 if (output_type == ADV7343_COMPOSITE_ID)
217 val |= ADV7343_COMPOSITE_POWER_VALUE;
218 else if (output_type == ADV7343_COMPONENT_ID)
219 val |= ADV7343_COMPONENT_POWER_VALUE;
220 else
221 val |= ADV7343_SVIDEO_POWER_VALUE;
222
223 err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val);
224 if (err < 0)
225 goto setoutput_exit;
226
227 state->reg00 = val;
228
229 /* Enable YUV output */
230 val = state->reg02 | YUV_OUTPUT_SELECT;
231 err = adv7343_write(sd, ADV7343_MODE_REG0, val);
232 if (err < 0)
233 goto setoutput_exit;
234
235 state->reg02 = val;
236
237 /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */
238 val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI);
239 err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val);
240 if (err < 0)
241 goto setoutput_exit;
242
243 state->reg82 = val;
244
245 /* configure ED/HD Color DAC Swap and ED/HD RGB Input Enable bit to
246 * zero */
247 val = state->reg35 & (HD_RGB_INPUT_DI & HD_DAC_SWAP_DI);
248 err = adv7343_write(sd, ADV7343_HD_MODE_REG6, val);
249 if (err < 0)
250 goto setoutput_exit;
251
252 state->reg35 = val;
253
254setoutput_exit:
255 if (err != 0)
256 v4l2_err(sd, "Error setting output, write failed\n");
257
258 return err;
259}
260
261static int adv7343_log_status(struct v4l2_subdev *sd)
262{
263 struct adv7343_state *state = to_state(sd);
264
265 v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std);
266 v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" :
267 ((state->output == 1) ? "Component" : "S-Video"));
268 return 0;
269}
270
271static int adv7343_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
272{
273 switch (qc->id) {
274 case V4L2_CID_BRIGHTNESS:
275 return v4l2_ctrl_query_fill(qc, ADV7343_BRIGHTNESS_MIN,
276 ADV7343_BRIGHTNESS_MAX, 1,
277 ADV7343_BRIGHTNESS_DEF);
278 case V4L2_CID_HUE:
279 return v4l2_ctrl_query_fill(qc, ADV7343_HUE_MIN,
280 ADV7343_HUE_MAX, 1 ,
281 ADV7343_HUE_DEF);
282 case V4L2_CID_GAIN:
283 return v4l2_ctrl_query_fill(qc, ADV7343_GAIN_MIN,
284 ADV7343_GAIN_MAX, 1,
285 ADV7343_GAIN_DEF);
286 default:
287 break;
288 }
289
290 return 0;
291}
292
293static int adv7343_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
294{
295 struct adv7343_state *state = to_state(sd);
296 int err = 0;
297
298 switch (ctrl->id) {
299 case V4L2_CID_BRIGHTNESS:
300 if (ctrl->value < ADV7343_BRIGHTNESS_MIN ||
301 ctrl->value > ADV7343_BRIGHTNESS_MAX) {
302 v4l2_dbg(1, debug, sd,
303 "invalid brightness settings %d\n",
304 ctrl->value);
305 return -ERANGE;
306 }
307
308 state->bright = ctrl->value;
309 err = adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS,
310 state->bright);
311 break;
312
313 case V4L2_CID_HUE:
314 if (ctrl->value < ADV7343_HUE_MIN ||
315 ctrl->value > ADV7343_HUE_MAX) {
316 v4l2_dbg(1, debug, sd, "invalid hue settings %d\n",
317 ctrl->value);
318 return -ERANGE;
319 }
320
321 state->hue = ctrl->value;
322 err = adv7343_write(sd, ADV7343_SD_HUE_REG, state->hue);
323 break;
324
325 case V4L2_CID_GAIN:
326 if (ctrl->value < ADV7343_GAIN_MIN ||
327 ctrl->value > ADV7343_GAIN_MAX) {
328 v4l2_dbg(1, debug, sd, "invalid gain settings %d\n",
329 ctrl->value);
330 return -ERANGE;
331 }
332
333 if ((ctrl->value > POSITIVE_GAIN_MAX) &&
334 (ctrl->value < NEGATIVE_GAIN_MIN)) {
335 v4l2_dbg(1, debug, sd,
336 "gain settings not within the specified range\n");
337 return -ERANGE;
338 }
339
340 state->gain = ctrl->value;
341 err = adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, state->gain);
342 break;
343
344 default:
345 return -EINVAL;
346 }
347
348 if (err < 0)
349 v4l2_err(sd, "Failed to set the encoder controls\n");
350
351 return err;
352}
353
354static int adv7343_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
355{
356 struct adv7343_state *state = to_state(sd);
357
358 switch (ctrl->id) {
359 case V4L2_CID_BRIGHTNESS:
360 ctrl->value = state->bright;
361 break;
362
363 case V4L2_CID_HUE:
364 ctrl->value = state->hue;
365 break;
366
367 case V4L2_CID_GAIN:
368 ctrl->value = state->gain;
369 break;
370
371 default:
372 return -EINVAL;
373 }
374
375 return 0;
376}
377
378static int adv7343_g_chip_ident(struct v4l2_subdev *sd,
379 struct v4l2_dbg_chip_ident *chip)
380{
381 struct i2c_client *client = v4l2_get_subdevdata(sd);
382
383 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0);
384}
385
386static const struct v4l2_subdev_core_ops adv7343_core_ops = {
387 .log_status = adv7343_log_status,
388 .g_chip_ident = adv7343_g_chip_ident,
389 .g_ctrl = adv7343_g_ctrl,
390 .s_ctrl = adv7343_s_ctrl,
391 .queryctrl = adv7343_queryctrl,
392};
393
394static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
395{
396 struct adv7343_state *state = to_state(sd);
397 int err = 0;
398
399 if (state->std == std)
400 return 0;
401
402 err = adv7343_setstd(sd, std);
403 if (!err)
404 state->std = std;
405
406 return err;
407}
408
409static int adv7343_s_routing(struct v4l2_subdev *sd,
410 u32 input, u32 output, u32 config)
411{
412 struct adv7343_state *state = to_state(sd);
413 int err = 0;
414
415 if (state->output == output)
416 return 0;
417
418 err = adv7343_setoutput(sd, output);
419 if (!err)
420 state->output = output;
421
422 return err;
423}
424
425static const struct v4l2_subdev_video_ops adv7343_video_ops = {
426 .s_std_output = adv7343_s_std_output,
427 .s_routing = adv7343_s_routing,
428};
429
430static const struct v4l2_subdev_ops adv7343_ops = {
431 .core = &adv7343_core_ops,
432 .video = &adv7343_video_ops,
433};
434
435static int adv7343_initialize(struct v4l2_subdev *sd)
436{
437 struct adv7343_state *state = to_state(sd);
438 int err = 0;
439 int i;
440
441 for (i = 0; i < ARRAY_SIZE(adv7343_init_reg_val); i += 2) {
442
443 err = adv7343_write(sd, adv7343_init_reg_val[i],
444 adv7343_init_reg_val[i+1]);
445 if (err) {
446 v4l2_err(sd, "Error initializing\n");
447 return err;
448 }
449 }
450
451 /* Configure for default video standard */
452 err = adv7343_setoutput(sd, state->output);
453 if (err < 0) {
454 v4l2_err(sd, "Error setting output during init\n");
455 return -EINVAL;
456 }
457
458 err = adv7343_setstd(sd, state->std);
459 if (err < 0) {
460 v4l2_err(sd, "Error setting std during init\n");
461 return -EINVAL;
462 }
463
464 return err;
465}
466
467static int adv7343_probe(struct i2c_client *client,
468 const struct i2c_device_id *id)
469{
470 struct adv7343_state *state;
471
472 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
473 return -ENODEV;
474
475 v4l_info(client, "chip found @ 0x%x (%s)\n",
476 client->addr << 1, client->adapter->name);
477
478 state = kzalloc(sizeof(struct adv7343_state), GFP_KERNEL);
479 if (state == NULL)
480 return -ENOMEM;
481
482 state->reg00 = 0x80;
483 state->reg01 = 0x00;
484 state->reg02 = 0x20;
485 state->reg35 = 0x00;
486 state->reg80 = ADV7343_SD_MODE_REG1_DEFAULT;
487 state->reg82 = ADV7343_SD_MODE_REG2_DEFAULT;
488
489 state->output = ADV7343_COMPOSITE_ID;
490 state->std = V4L2_STD_NTSC;
491
492 v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops);
493 return adv7343_initialize(&state->sd);
494}
495
496static int adv7343_remove(struct i2c_client *client)
497{
498 struct v4l2_subdev *sd = i2c_get_clientdata(client);
499
500 v4l2_device_unregister_subdev(sd);
501 kfree(to_state(sd));
502
503 return 0;
504}
505
506static const struct i2c_device_id adv7343_id[] = {
507 {"adv7343", 0},
508 {},
509};
510
511MODULE_DEVICE_TABLE(i2c, adv7343_id);
512
513static struct i2c_driver adv7343_driver = {
514 .driver = {
515 .owner = THIS_MODULE,
516 .name = "adv7343",
517 },
518 .probe = adv7343_probe,
519 .remove = adv7343_remove,
520 .id_table = adv7343_id,
521};
522
523static __init int init_adv7343(void)
524{
525 return i2c_add_driver(&adv7343_driver);
526}
527
528static __exit void exit_adv7343(void)
529{
530 i2c_del_driver(&adv7343_driver);
531}
532
533module_init(init_adv7343);
534module_exit(exit_adv7343);