Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
saa7110.c
Go to the documentation of this file.
1 /*
2  * saa7110 - Philips SAA7110(A) video decoder driver
3  *
4  * Copyright (C) 1998 Pauline Middelink <[email protected]>
5  *
6  * Copyright (C) 1999 Wolfgang Scherr <[email protected]>
7  * Copyright (C) 2000 Serguei Miridonov <[email protected]>
8  * - some corrections for Pinnacle Systems Inc. DC10plus card.
9  *
10  * Changes by Ronald Bultje <[email protected]>
11  * - moved over to linux>=2.4.x i2c protocol (1/1/2003)
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27 
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/types.h>
31 #include <linux/delay.h>
32 #include <linux/slab.h>
33 #include <linux/wait.h>
34 #include <asm/uaccess.h>
35 #include <linux/i2c.h>
36 #include <linux/videodev2.h>
37 #include <media/v4l2-device.h>
38 #include <media/v4l2-chip-ident.h>
39 #include <media/v4l2-ctrls.h>
40 
41 MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
42 MODULE_AUTHOR("Pauline Middelink");
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 #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */
51 #define SAA7110_MAX_OUTPUT 1 /* 1 YUV */
52 
53 #define SAA7110_NR_REG 0x35
54 
55 struct saa7110 {
56  struct v4l2_subdev sd;
59 
61  int input;
62  int enable;
63 
65 };
66 
67 static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd)
68 {
69  return container_of(sd, struct saa7110, sd);
70 }
71 
72 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
73 {
74  return &container_of(ctrl->handler, struct saa7110, hdl)->sd;
75 }
76 
77 /* ----------------------------------------------------------------------- */
78 /* I2C support functions */
79 /* ----------------------------------------------------------------------- */
80 
81 static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value)
82 {
83  struct i2c_client *client = v4l2_get_subdevdata(sd);
84  struct saa7110 *decoder = to_saa7110(sd);
85 
86  decoder->reg[reg] = value;
87  return i2c_smbus_write_byte_data(client, reg, value);
88 }
89 
90 static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
91 {
92  struct i2c_client *client = v4l2_get_subdevdata(sd);
93  struct saa7110 *decoder = to_saa7110(sd);
94  int ret = -1;
95  u8 reg = *data; /* first register to write to */
96 
97  /* Sanity check */
98  if (reg + (len - 1) > SAA7110_NR_REG)
99  return ret;
100 
101  /* the saa7110 has an autoincrement function, use it if
102  * the adapter understands raw I2C */
103  if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
104  ret = i2c_master_send(client, data, len);
105 
106  /* Cache the written data */
107  memcpy(decoder->reg + reg, data + 1, len - 1);
108  } else {
109  for (++data, --len; len; len--) {
110  ret = saa7110_write(sd, reg++, *data++);
111  if (ret < 0)
112  break;
113  }
114  }
115 
116  return ret;
117 }
118 
119 static inline int saa7110_read(struct v4l2_subdev *sd)
120 {
121  struct i2c_client *client = v4l2_get_subdevdata(sd);
122 
123  return i2c_smbus_read_byte(client);
124 }
125 
126 /* ----------------------------------------------------------------------- */
127 /* SAA7110 functions */
128 /* ----------------------------------------------------------------------- */
129 
130 #define FRESP_06H_COMPST 0x03 /*0x13*/
131 #define FRESP_06H_SVIDEO 0x83 /*0xC0*/
132 
133 
134 static int saa7110_selmux(struct v4l2_subdev *sd, int chan)
135 {
136  static const unsigned char modes[9][8] = {
137  /* mode 0 */
138  {FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03,
139  0x44, 0x75, 0x16},
140  /* mode 1 */
141  {FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03,
142  0x44, 0x75, 0x16},
143  /* mode 2 */
144  {FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03,
145  0x60, 0xB5, 0x05},
146  /* mode 3 */
147  {FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03,
148  0x60, 0xB5, 0x05},
149  /* mode 4 */
150  {FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83,
151  0x60, 0xB5, 0x03},
152  /* mode 5 */
153  {FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83,
154  0x60, 0xB5, 0x03},
155  /* mode 6 */
156  {FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3,
157  0x44, 0x75, 0x12},
158  /* mode 7 */
159  {FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13,
160  0x60, 0xB5, 0x14},
161  /* mode 8 */
162  {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,
163  0x44, 0x75, 0x21}
164  };
165  struct saa7110 *decoder = to_saa7110(sd);
166  const unsigned char *ptr = modes[chan];
167 
168  saa7110_write(sd, 0x06, ptr[0]); /* Luminance control */
169  saa7110_write(sd, 0x20, ptr[1]); /* Analog Control #1 */
170  saa7110_write(sd, 0x21, ptr[2]); /* Analog Control #2 */
171  saa7110_write(sd, 0x22, ptr[3]); /* Mixer Control #1 */
172  saa7110_write(sd, 0x2C, ptr[4]); /* Mixer Control #2 */
173  saa7110_write(sd, 0x30, ptr[5]); /* ADCs gain control */
174  saa7110_write(sd, 0x31, ptr[6]); /* Mixer Control #3 */
175  saa7110_write(sd, 0x21, ptr[7]); /* Analog Control #2 */
176  decoder->input = chan;
177 
178  return 0;
179 }
180 
181 static const unsigned char initseq[1 + SAA7110_NR_REG] = {
182  0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00,
183  /* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90,
184  /* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
185  /* 0x18 */ 0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186  /* 0x20 */ 0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
187  /* 0x28 */ 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C,
188  /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
189 };
190 
191 static v4l2_std_id determine_norm(struct v4l2_subdev *sd)
192 {
193  DEFINE_WAIT(wait);
194  struct saa7110 *decoder = to_saa7110(sd);
195  int status;
196 
197  /* mode changed, start automatic detection */
198  saa7110_write_block(sd, initseq, sizeof(initseq));
199  saa7110_selmux(sd, decoder->input);
202  finish_wait(&decoder->wq, &wait);
203  status = saa7110_read(sd);
204  if (status & 0x40) {
205  v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status);
206  return decoder->norm; /* no change*/
207  }
208  if ((status & 3) == 0) {
209  saa7110_write(sd, 0x06, 0x83);
210  if (status & 0x20) {
211  v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status);
212  /*saa7110_write(sd,0x2E,0x81);*/
213  return V4L2_STD_NTSC;
214  }
215  v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status);
216  /*saa7110_write(sd,0x2E,0x9A);*/
217  return V4L2_STD_PAL;
218  }
219  /*saa7110_write(sd,0x06,0x03);*/
220  if (status & 0x20) { /* 60Hz */
221  v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status);
222  saa7110_write(sd, 0x0D, 0x86);
223  saa7110_write(sd, 0x0F, 0x50);
224  saa7110_write(sd, 0x11, 0x2C);
225  /*saa7110_write(sd,0x2E,0x81);*/
226  return V4L2_STD_NTSC;
227  }
228 
229  /* 50Hz -> PAL/SECAM */
230  saa7110_write(sd, 0x0D, 0x86);
231  saa7110_write(sd, 0x0F, 0x10);
232  saa7110_write(sd, 0x11, 0x59);
233  /*saa7110_write(sd,0x2E,0x9A);*/
234 
237  finish_wait(&decoder->wq, &wait);
238 
239  status = saa7110_read(sd);
240  if ((status & 0x03) == 0x01) {
241  v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status);
242  saa7110_write(sd, 0x0D, 0x87);
243  return V4L2_STD_SECAM;
244  }
245  v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status);
246  return V4L2_STD_PAL;
247 }
248 
249 static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus)
250 {
251  struct saa7110 *decoder = to_saa7110(sd);
253  int status = saa7110_read(sd);
254 
255  v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n",
256  status, (unsigned long long)decoder->norm);
257  if (!(status & 0x40))
258  res = 0;
259  if (!(status & 0x03))
260  res |= V4L2_IN_ST_NO_COLOR;
261 
262  *pstatus = res;
263  return 0;
264 }
265 
266 static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
267 {
268  *(v4l2_std_id *)std = determine_norm(sd);
269  return 0;
270 }
271 
272 static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
273 {
274  struct saa7110 *decoder = to_saa7110(sd);
275 
276  if (decoder->norm != std) {
277  decoder->norm = std;
278  /*saa7110_write(sd, 0x06, 0x03);*/
279  if (std & V4L2_STD_NTSC) {
280  saa7110_write(sd, 0x0D, 0x86);
281  saa7110_write(sd, 0x0F, 0x50);
282  saa7110_write(sd, 0x11, 0x2C);
283  /*saa7110_write(sd, 0x2E, 0x81);*/
284  v4l2_dbg(1, debug, sd, "switched to NTSC\n");
285  } else if (std & V4L2_STD_PAL) {
286  saa7110_write(sd, 0x0D, 0x86);
287  saa7110_write(sd, 0x0F, 0x10);
288  saa7110_write(sd, 0x11, 0x59);
289  /*saa7110_write(sd, 0x2E, 0x9A);*/
290  v4l2_dbg(1, debug, sd, "switched to PAL\n");
291  } else if (std & V4L2_STD_SECAM) {
292  saa7110_write(sd, 0x0D, 0x87);
293  saa7110_write(sd, 0x0F, 0x10);
294  saa7110_write(sd, 0x11, 0x59);
295  /*saa7110_write(sd, 0x2E, 0x9A);*/
296  v4l2_dbg(1, debug, sd, "switched to SECAM\n");
297  } else {
298  return -EINVAL;
299  }
300  }
301  return 0;
302 }
303 
304 static int saa7110_s_routing(struct v4l2_subdev *sd,
305  u32 input, u32 output, u32 config)
306 {
307  struct saa7110 *decoder = to_saa7110(sd);
308 
309  if (input >= SAA7110_MAX_INPUT) {
310  v4l2_dbg(1, debug, sd, "input=%d not available\n", input);
311  return -EINVAL;
312  }
313  if (decoder->input != input) {
314  saa7110_selmux(sd, input);
315  v4l2_dbg(1, debug, sd, "switched to input=%d\n", input);
316  }
317  return 0;
318 }
319 
320 static int saa7110_s_stream(struct v4l2_subdev *sd, int enable)
321 {
322  struct saa7110 *decoder = to_saa7110(sd);
323 
324  if (decoder->enable != enable) {
325  decoder->enable = enable;
326  saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80);
327  v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off");
328  }
329  return 0;
330 }
331 
332 static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl)
333 {
334  struct v4l2_subdev *sd = to_sd(ctrl);
335 
336  switch (ctrl->id) {
337  case V4L2_CID_BRIGHTNESS:
338  saa7110_write(sd, 0x19, ctrl->val);
339  break;
340  case V4L2_CID_CONTRAST:
341  saa7110_write(sd, 0x13, ctrl->val);
342  break;
343  case V4L2_CID_SATURATION:
344  saa7110_write(sd, 0x12, ctrl->val);
345  break;
346  case V4L2_CID_HUE:
347  saa7110_write(sd, 0x07, ctrl->val);
348  break;
349  default:
350  return -EINVAL;
351  }
352  return 0;
353 }
354 
355 static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
356 {
357  struct i2c_client *client = v4l2_get_subdevdata(sd);
358 
359  return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0);
360 }
361 
362 /* ----------------------------------------------------------------------- */
363 
364 static const struct v4l2_ctrl_ops saa7110_ctrl_ops = {
365  .s_ctrl = saa7110_s_ctrl,
366 };
367 
368 static const struct v4l2_subdev_core_ops saa7110_core_ops = {
369  .g_chip_ident = saa7110_g_chip_ident,
370  .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
371  .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
372  .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
373  .g_ctrl = v4l2_subdev_g_ctrl,
374  .s_ctrl = v4l2_subdev_s_ctrl,
375  .queryctrl = v4l2_subdev_queryctrl,
376  .querymenu = v4l2_subdev_querymenu,
377  .s_std = saa7110_s_std,
378 };
379 
380 static const struct v4l2_subdev_video_ops saa7110_video_ops = {
381  .s_routing = saa7110_s_routing,
382  .s_stream = saa7110_s_stream,
383  .querystd = saa7110_querystd,
384  .g_input_status = saa7110_g_input_status,
385 };
386 
387 static const struct v4l2_subdev_ops saa7110_ops = {
388  .core = &saa7110_core_ops,
389  .video = &saa7110_video_ops,
390 };
391 
392 /* ----------------------------------------------------------------------- */
393 
394 static int saa7110_probe(struct i2c_client *client,
395  const struct i2c_device_id *id)
396 {
397  struct saa7110 *decoder;
398  struct v4l2_subdev *sd;
399  int rv;
400 
401  /* Check if the adapter supports the needed features */
402  if (!i2c_check_functionality(client->adapter,
404  return -ENODEV;
405 
406  v4l_info(client, "chip found @ 0x%x (%s)\n",
407  client->addr << 1, client->adapter->name);
408 
409  decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
410  if (!decoder)
411  return -ENOMEM;
412  sd = &decoder->sd;
413  v4l2_i2c_subdev_init(sd, client, &saa7110_ops);
414  decoder->norm = V4L2_STD_PAL;
415  decoder->input = 0;
416  decoder->enable = 1;
417  v4l2_ctrl_handler_init(&decoder->hdl, 2);
418  v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
419  V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
420  v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
421  V4L2_CID_CONTRAST, 0, 127, 1, 64);
422  v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
423  V4L2_CID_SATURATION, 0, 127, 1, 64);
424  v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
425  V4L2_CID_HUE, -128, 127, 1, 0);
426  sd->ctrl_handler = &decoder->hdl;
427  if (decoder->hdl.error) {
428  int err = decoder->hdl.error;
429 
430  v4l2_ctrl_handler_free(&decoder->hdl);
431  kfree(decoder);
432  return err;
433  }
434  v4l2_ctrl_handler_setup(&decoder->hdl);
435 
436  init_waitqueue_head(&decoder->wq);
437 
438  rv = saa7110_write_block(sd, initseq, sizeof(initseq));
439  if (rv < 0) {
440  v4l2_dbg(1, debug, sd, "init status %d\n", rv);
441  } else {
442  int ver, status;
443  saa7110_write(sd, 0x21, 0x10);
444  saa7110_write(sd, 0x0e, 0x18);
445  saa7110_write(sd, 0x0D, 0x04);
446  ver = saa7110_read(sd);
447  saa7110_write(sd, 0x0D, 0x06);
448  /*mdelay(150);*/
449  status = saa7110_read(sd);
450  v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n",
451  ver, status);
452  saa7110_write(sd, 0x0D, 0x86);
453  saa7110_write(sd, 0x0F, 0x10);
454  saa7110_write(sd, 0x11, 0x59);
455  /*saa7110_write(sd, 0x2E, 0x9A);*/
456  }
457 
458  /*saa7110_selmux(sd,0);*/
459  /*determine_norm(sd);*/
460  /* setup and implicit mode 0 select has been performed */
461 
462  return 0;
463 }
464 
465 static int saa7110_remove(struct i2c_client *client)
466 {
467  struct v4l2_subdev *sd = i2c_get_clientdata(client);
468  struct saa7110 *decoder = to_saa7110(sd);
469 
471  v4l2_ctrl_handler_free(&decoder->hdl);
472  kfree(decoder);
473  return 0;
474 }
475 
476 /* ----------------------------------------------------------------------- */
477 
478 static const struct i2c_device_id saa7110_id[] = {
479  { "saa7110", 0 },
480  { }
481 };
482 MODULE_DEVICE_TABLE(i2c, saa7110_id);
483 
484 static struct i2c_driver saa7110_driver = {
485  .driver = {
486  .owner = THIS_MODULE,
487  .name = "saa7110",
488  },
489  .probe = saa7110_probe,
490  .remove = saa7110_remove,
491  .id_table = saa7110_id,
492 };
493 
494 module_i2c_driver(saa7110_driver);