Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
adv7170.c
Go to the documentation of this file.
1 /*
2  * adv7170 - adv7170, adv7171 video encoder driver version 0.0.1
3  *
4  * Copyright (C) 2002 Maxim Yevtyushkin <[email protected]>
5  *
6  * Based on adv7176 driver by:
7  *
8  * Copyright (C) 1998 Dave Perks <[email protected]>
9  * Copyright (C) 1999 Wolfgang Scherr <[email protected]>
10  * Copyright (C) 2000 Serguei Miridonov <[email protected]>
11  * - some corrections for Pinnacle Systems Inc. DC10plus card.
12  *
13  * Changes by Ronald Bultje <[email protected]>
14  * - moved over to linux>=2.4.x i2c protocol (1/1/2003)
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29  */
30 
31 #include <linux/module.h>
32 #include <linux/types.h>
33 #include <linux/slab.h>
34 #include <linux/ioctl.h>
35 #include <asm/uaccess.h>
36 #include <linux/i2c.h>
37 #include <linux/videodev2.h>
38 #include <media/v4l2-device.h>
39 #include <media/v4l2-chip-ident.h>
40 
41 MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
42 MODULE_AUTHOR("Maxim Yevtyushkin");
43 MODULE_LICENSE("GPL");
44 
45 
46 static int debug;
47 module_param(debug, int, 0);
48 MODULE_PARM_DESC(debug, "Debug level (0-1)");
49 
50 /* ----------------------------------------------------------------------- */
51 
52 struct adv7170 {
53  struct v4l2_subdev sd;
54  unsigned char reg[128];
55 
57  int input;
58 };
59 
60 static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd)
61 {
62  return container_of(sd, struct adv7170, sd);
63 }
64 
65 static char *inputs[] = { "pass_through", "play_back" };
66 
67 static enum v4l2_mbus_pixelcode adv7170_codes[] = {
70 };
71 
72 /* ----------------------------------------------------------------------- */
73 
74 static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value)
75 {
76  struct i2c_client *client = v4l2_get_subdevdata(sd);
77  struct adv7170 *encoder = to_adv7170(sd);
78 
79  encoder->reg[reg] = value;
80  return i2c_smbus_write_byte_data(client, reg, value);
81 }
82 
83 static inline int adv7170_read(struct v4l2_subdev *sd, u8 reg)
84 {
85  struct i2c_client *client = v4l2_get_subdevdata(sd);
86 
87  return i2c_smbus_read_byte_data(client, reg);
88 }
89 
90 static int adv7170_write_block(struct v4l2_subdev *sd,
91  const u8 *data, unsigned int len)
92 {
93  struct i2c_client *client = v4l2_get_subdevdata(sd);
94  struct adv7170 *encoder = to_adv7170(sd);
95  int ret = -1;
96  u8 reg;
97 
98  /* the adv7170 has an autoincrement function, use it if
99  * the adapter understands raw I2C */
100  if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
101  /* do raw I2C, not smbus compatible */
102  u8 block_data[32];
103  int block_len;
104 
105  while (len >= 2) {
106  block_len = 0;
107  block_data[block_len++] = reg = data[0];
108  do {
109  block_data[block_len++] =
110  encoder->reg[reg++] = data[1];
111  len -= 2;
112  data += 2;
113  } while (len >= 2 && data[0] == reg && block_len < 32);
114  ret = i2c_master_send(client, block_data, block_len);
115  if (ret < 0)
116  break;
117  }
118  } else {
119  /* do some slow I2C emulation kind of thing */
120  while (len >= 2) {
121  reg = *data++;
122  ret = adv7170_write(sd, reg, *data++);
123  if (ret < 0)
124  break;
125  len -= 2;
126  }
127  }
128  return ret;
129 }
130 
131 /* ----------------------------------------------------------------------- */
132 
133 #define TR0MODE 0x4c
134 #define TR0RST 0x80
135 
136 #define TR1CAPT 0x00
137 #define TR1PLAY 0x00
138 
139 static const unsigned char init_NTSC[] = {
140  0x00, 0x10, /* MR0 */
141  0x01, 0x20, /* MR1 */
142  0x02, 0x0e, /* MR2 RTC control: bits 2 and 1 */
143  0x03, 0x80, /* MR3 */
144  0x04, 0x30, /* MR4 */
145  0x05, 0x00, /* Reserved */
146  0x06, 0x00, /* Reserved */
147  0x07, TR0MODE, /* TM0 */
148  0x08, TR1CAPT, /* TM1 */
149  0x09, 0x16, /* Fsc0 */
150  0x0a, 0x7c, /* Fsc1 */
151  0x0b, 0xf0, /* Fsc2 */
152  0x0c, 0x21, /* Fsc3 */
153  0x0d, 0x00, /* Subcarrier Phase */
154  0x0e, 0x00, /* Closed Capt. Ext 0 */
155  0x0f, 0x00, /* Closed Capt. Ext 1 */
156  0x10, 0x00, /* Closed Capt. 0 */
157  0x11, 0x00, /* Closed Capt. 1 */
158  0x12, 0x00, /* Pedestal Ctl 0 */
159  0x13, 0x00, /* Pedestal Ctl 1 */
160  0x14, 0x00, /* Pedestal Ctl 2 */
161  0x15, 0x00, /* Pedestal Ctl 3 */
162  0x16, 0x00, /* CGMS_WSS_0 */
163  0x17, 0x00, /* CGMS_WSS_1 */
164  0x18, 0x00, /* CGMS_WSS_2 */
165  0x19, 0x00, /* Teletext Ctl */
166 };
167 
168 static const unsigned char init_PAL[] = {
169  0x00, 0x71, /* MR0 */
170  0x01, 0x20, /* MR1 */
171  0x02, 0x0e, /* MR2 RTC control: bits 2 and 1 */
172  0x03, 0x80, /* MR3 */
173  0x04, 0x30, /* MR4 */
174  0x05, 0x00, /* Reserved */
175  0x06, 0x00, /* Reserved */
176  0x07, TR0MODE, /* TM0 */
177  0x08, TR1CAPT, /* TM1 */
178  0x09, 0xcb, /* Fsc0 */
179  0x0a, 0x8a, /* Fsc1 */
180  0x0b, 0x09, /* Fsc2 */
181  0x0c, 0x2a, /* Fsc3 */
182  0x0d, 0x00, /* Subcarrier Phase */
183  0x0e, 0x00, /* Closed Capt. Ext 0 */
184  0x0f, 0x00, /* Closed Capt. Ext 1 */
185  0x10, 0x00, /* Closed Capt. 0 */
186  0x11, 0x00, /* Closed Capt. 1 */
187  0x12, 0x00, /* Pedestal Ctl 0 */
188  0x13, 0x00, /* Pedestal Ctl 1 */
189  0x14, 0x00, /* Pedestal Ctl 2 */
190  0x15, 0x00, /* Pedestal Ctl 3 */
191  0x16, 0x00, /* CGMS_WSS_0 */
192  0x17, 0x00, /* CGMS_WSS_1 */
193  0x18, 0x00, /* CGMS_WSS_2 */
194  0x19, 0x00, /* Teletext Ctl */
195 };
196 
197 
198 static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
199 {
200  struct adv7170 *encoder = to_adv7170(sd);
201 
202  v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
203 
204  if (std & V4L2_STD_NTSC) {
205  adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC));
206  if (encoder->input == 0)
207  adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */
208  adv7170_write(sd, 0x07, TR0MODE | TR0RST);
209  adv7170_write(sd, 0x07, TR0MODE);
210  } else if (std & V4L2_STD_PAL) {
211  adv7170_write_block(sd, init_PAL, sizeof(init_PAL));
212  if (encoder->input == 0)
213  adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */
214  adv7170_write(sd, 0x07, TR0MODE | TR0RST);
215  adv7170_write(sd, 0x07, TR0MODE);
216  } else {
217  v4l2_dbg(1, debug, sd, "illegal norm: %llx\n",
218  (unsigned long long)std);
219  return -EINVAL;
220  }
221  v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std);
222  encoder->norm = std;
223  return 0;
224 }
225 
226 static int adv7170_s_routing(struct v4l2_subdev *sd,
227  u32 input, u32 output, u32 config)
228 {
229  struct adv7170 *encoder = to_adv7170(sd);
230 
231  /* RJ: input = 0: input is from decoder
232  input = 1: input is from ZR36060
233  input = 2: color bar */
234 
235  v4l2_dbg(1, debug, sd, "set input from %s\n",
236  input == 0 ? "decoder" : "ZR36060");
237 
238  switch (input) {
239  case 0:
240  adv7170_write(sd, 0x01, 0x20);
241  adv7170_write(sd, 0x08, TR1CAPT); /* TR1 */
242  adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */
243  adv7170_write(sd, 0x07, TR0MODE | TR0RST);
244  adv7170_write(sd, 0x07, TR0MODE);
245  /* udelay(10); */
246  break;
247 
248  case 1:
249  adv7170_write(sd, 0x01, 0x00);
250  adv7170_write(sd, 0x08, TR1PLAY); /* TR1 */
251  adv7170_write(sd, 0x02, 0x08);
252  adv7170_write(sd, 0x07, TR0MODE | TR0RST);
253  adv7170_write(sd, 0x07, TR0MODE);
254  /* udelay(10); */
255  break;
256 
257  default:
258  v4l2_dbg(1, debug, sd, "illegal input: %d\n", input);
259  return -EINVAL;
260  }
261  v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]);
262  encoder->input = input;
263  return 0;
264 }
265 
266 static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
268 {
269  if (index >= ARRAY_SIZE(adv7170_codes))
270  return -EINVAL;
271 
272  *code = adv7170_codes[index];
273  return 0;
274 }
275 
276 static int adv7170_g_fmt(struct v4l2_subdev *sd,
277  struct v4l2_mbus_framefmt *mf)
278 {
279  u8 val = adv7170_read(sd, 0x7);
280 
281  if ((val & 0x40) == (1 << 6))
282  mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
283  else
284  mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
285 
286  mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
287  mf->width = 0;
288  mf->height = 0;
289  mf->field = V4L2_FIELD_ANY;
290 
291  return 0;
292 }
293 
294 static int adv7170_s_fmt(struct v4l2_subdev *sd,
295  struct v4l2_mbus_framefmt *mf)
296 {
297  u8 val = adv7170_read(sd, 0x7);
298  int ret;
299 
300  switch (mf->code) {
302  val &= ~0x40;
303  break;
304 
306  val |= 0x40;
307  break;
308 
309  default:
310  v4l2_dbg(1, debug, sd,
311  "illegal v4l2_mbus_framefmt code: %d\n", mf->code);
312  return -EINVAL;
313  }
314 
315  ret = adv7170_write(sd, 0x7, val);
316 
317  return ret;
318 }
319 
320 static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
321 {
322  struct i2c_client *client = v4l2_get_subdevdata(sd);
323 
324  return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0);
325 }
326 
327 /* ----------------------------------------------------------------------- */
328 
329 static const struct v4l2_subdev_core_ops adv7170_core_ops = {
330  .g_chip_ident = adv7170_g_chip_ident,
331 };
332 
333 static const struct v4l2_subdev_video_ops adv7170_video_ops = {
334  .s_std_output = adv7170_s_std_output,
335  .s_routing = adv7170_s_routing,
336  .s_mbus_fmt = adv7170_s_fmt,
337  .g_mbus_fmt = adv7170_g_fmt,
338  .enum_mbus_fmt = adv7170_enum_fmt,
339 };
340 
341 static const struct v4l2_subdev_ops adv7170_ops = {
342  .core = &adv7170_core_ops,
343  .video = &adv7170_video_ops,
344 };
345 
346 /* ----------------------------------------------------------------------- */
347 
348 static int adv7170_probe(struct i2c_client *client,
349  const struct i2c_device_id *id)
350 {
351  struct adv7170 *encoder;
352  struct v4l2_subdev *sd;
353  int i;
354 
355  /* Check if the adapter supports the needed features */
356  if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
357  return -ENODEV;
358 
359  v4l_info(client, "chip found @ 0x%x (%s)\n",
360  client->addr << 1, client->adapter->name);
361 
362  encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
363  if (encoder == NULL)
364  return -ENOMEM;
365  sd = &encoder->sd;
366  v4l2_i2c_subdev_init(sd, client, &adv7170_ops);
367  encoder->norm = V4L2_STD_NTSC;
368  encoder->input = 0;
369 
370  i = adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC));
371  if (i >= 0) {
372  i = adv7170_write(sd, 0x07, TR0MODE | TR0RST);
373  i = adv7170_write(sd, 0x07, TR0MODE);
374  i = adv7170_read(sd, 0x12);
375  v4l2_dbg(1, debug, sd, "revision %d\n", i & 1);
376  }
377  if (i < 0)
378  v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
379  return 0;
380 }
381 
382 static int adv7170_remove(struct i2c_client *client)
383 {
384  struct v4l2_subdev *sd = i2c_get_clientdata(client);
385 
387  kfree(to_adv7170(sd));
388  return 0;
389 }
390 
391 /* ----------------------------------------------------------------------- */
392 
393 static const struct i2c_device_id adv7170_id[] = {
394  { "adv7170", 0 },
395  { "adv7171", 0 },
396  { }
397 };
398 MODULE_DEVICE_TABLE(i2c, adv7170_id);
399 
400 static struct i2c_driver adv7170_driver = {
401  .driver = {
402  .owner = THIS_MODULE,
403  .name = "adv7170",
404  },
405  .probe = adv7170_probe,
406  .remove = adv7170_remove,
407  .id_table = adv7170_id,
408 };
409 
410 module_i2c_driver(adv7170_driver);