Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wis-sony-tuner.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2006 Micronas USA Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License (Version 2) as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software Foundation,
15  * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16  */
17 
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/i2c.h>
21 #include <linux/videodev2.h>
22 #include <linux/slab.h>
23 #include <media/tuner.h>
24 #include <media/v4l2-common.h>
25 #include <media/v4l2-ioctl.h>
26 
27 #include "wis-i2c.h"
28 
29 /* #define MPX_DEBUG */
30 
31 /* AS(IF/MPX) pin: LOW HIGH/OPEN
32  * IF/MPX address: 0x42/0x40 0x43/0x44
33  */
34 #define IF_I2C_ADDR 0x43
35 #define MPX_I2C_ADDR 0x44
36 
37 static v4l2_std_id force_band;
38 static char force_band_str[] = "-";
39 module_param_string(force_band, force_band_str, sizeof(force_band_str), 0644);
40 static int force_mpx_mode = -1;
41 module_param(force_mpx_mode, int, 0644);
42 
43 /* Store tuner info in the same format as tuner.c, so maybe we can put the
44  * Sony tuner support in there. */
46  char *name;
47  unsigned char Vendor; /* unused here */
48  unsigned char Type; /* unused here */
49 
50  unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */
51  unsigned short thresh2; /* band switch VHF_HI <=> UHF */
52  unsigned char VHF_L;
53  unsigned char VHF_H;
54  unsigned char UHF;
55  unsigned char config;
56  unsigned short IFPCoff;
57 };
58 
59 /* This array is indexed by (tuner_type - 200) */
60 static struct sony_tunertype sony_tuners[] = {
61  { "Sony PAL+SECAM (BTF-PG472Z)", 0, 0,
62  16*144.25, 16*427.25, 0x01, 0x02, 0x04, 0xc6, 623},
63  { "Sony NTSC_JP (BTF-PK467Z)", 0, 0,
64  16*220.25, 16*467.25, 0x01, 0x02, 0x04, 0xc6, 940},
65  { "Sony NTSC (BTF-PB463Z)", 0, 0,
66  16*130.25, 16*364.25, 0x01, 0x02, 0x04, 0xc6, 732},
67 };
68 
70  int type;
72  unsigned int freq;
73  int mpxmode;
75 };
76 
77 /* Basically the same as default_set_tv_freq() in tuner.c */
78 static int set_freq(struct i2c_client *client, int freq)
79 {
80  struct wis_sony_tuner *t = i2c_get_clientdata(client);
81  char *band_name;
82  int n;
83  int band_select;
84  struct sony_tunertype *tun;
85  u8 buffer[4];
86 
87  tun = &sony_tuners[t->type - 200];
88  if (freq < tun->thresh1) {
89  band_name = "VHF_L";
90  band_select = tun->VHF_L;
91  } else if (freq < tun->thresh2) {
92  band_name = "VHF_H";
93  band_select = tun->VHF_H;
94  } else {
95  band_name = "UHF";
96  band_select = tun->UHF;
97  }
98  printk(KERN_DEBUG "wis-sony-tuner: tuning to frequency %d.%04d (%s)\n",
99  freq / 16, (freq % 16) * 625, band_name);
100  n = freq + tun->IFPCoff;
101 
102  buffer[0] = n >> 8;
103  buffer[1] = n & 0xff;
104  buffer[2] = tun->config;
105  buffer[3] = band_select;
106  i2c_master_send(client, buffer, 4);
107 
108  return 0;
109 }
110 
111 static int mpx_write(struct i2c_client *client, int dev, int addr, int val)
112 {
113  u8 buffer[5];
114  struct i2c_msg msg;
115 
116  buffer[0] = dev;
117  buffer[1] = addr >> 8;
118  buffer[2] = addr & 0xff;
119  buffer[3] = val >> 8;
120  buffer[4] = val & 0xff;
121  msg.addr = MPX_I2C_ADDR;
122  msg.flags = 0;
123  msg.len = 5;
124  msg.buf = buffer;
125  i2c_transfer(client->adapter, &msg, 1);
126  return 0;
127 }
128 
129 /*
130  * MPX register values for the BTF-PG472Z:
131  *
132  * FM_ NICAM_ SCART_
133  * MODUS SOURCE ACB PRESCAL PRESCAL PRESCAL SYSTEM VOLUME
134  * 10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000
135  * ---------------------------------------------------------------
136  * Auto 1003 0020 0100 2603 5000 XXXX 0001 7500
137  *
138  * B/G
139  * Mono 1003 0020 0100 2603 5000 XXXX 0003 7500
140  * A2 1003 0020 0100 2601 5000 XXXX 0003 7500
141  * NICAM 1003 0120 0100 2603 5000 XXXX 0008 7500
142  *
143  * I
144  * Mono 1003 0020 0100 2603 7900 XXXX 000A 7500
145  * NICAM 1003 0120 0100 2603 7900 XXXX 000A 7500
146  *
147  * D/K
148  * Mono 1003 0020 0100 2603 5000 XXXX 0004 7500
149  * A2-1 1003 0020 0100 2601 5000 XXXX 0004 7500
150  * A2-2 1003 0020 0100 2601 5000 XXXX 0005 7500
151  * A2-3 1003 0020 0100 2601 5000 XXXX 0007 7500
152  * NICAM 1003 0120 0100 2603 5000 XXXX 000B 7500
153  *
154  * L/L'
155  * Mono 0003 0200 0100 7C03 5000 2200 0009 7500
156  * NICAM 0003 0120 0100 7C03 5000 XXXX 0009 7500
157  *
158  * M
159  * Mono 1003 0200 0100 2B03 5000 2B00 0002 7500
160  *
161  * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX.
162  *
163  * Bilingual selection in A2/NICAM:
164  *
165  * High byte of SOURCE Left chan Right chan
166  * 0x01 MAIN SUB
167  * 0x03 MAIN MAIN
168  * 0x04 SUB SUB
169  *
170  * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or
171  * 0x00 (all other bands). Force mono in A2 with FMONO_A2:
172  *
173  * FMONO_A2
174  * 10/0022
175  * --------
176  * Forced mono ON 07F0
177  * Forced mono OFF 0190
178  */
179 
180 static struct {
181  enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode;
190 } mpx_audio_modes[] = {
191  /* Auto */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
192  0x5000, 0x0000, 0x0001, 0x7500 },
193  /* B/G Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
194  0x5000, 0x0000, 0x0003, 0x7500 },
195  /* B/G A2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
196  0x5000, 0x0000, 0x0003, 0x7500 },
197  /* B/G NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
198  0x5000, 0x0000, 0x0008, 0x7500 },
199  /* I Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
200  0x7900, 0x0000, 0x000A, 0x7500 },
201  /* I NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
202  0x7900, 0x0000, 0x000A, 0x7500 },
203  /* D/K Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603,
204  0x5000, 0x0000, 0x0004, 0x7500 },
205  /* D/K A2-1 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
206  0x5000, 0x0000, 0x0004, 0x7500 },
207  /* D/K A2-2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
208  0x5000, 0x0000, 0x0005, 0x7500 },
209  /* D/K A2-3 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601,
210  0x5000, 0x0000, 0x0007, 0x7500 },
211  /* D/K NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603,
212  0x5000, 0x0000, 0x000B, 0x7500 },
213  /* L/L' Mono */ { AUD_MONO, 0x0003, 0x0200, 0x0100, 0x7C03,
214  0x5000, 0x2200, 0x0009, 0x7500 },
215  /* L/L' NICAM */{ AUD_NICAM_L, 0x0003, 0x0120, 0x0100, 0x7C03,
216  0x5000, 0x0000, 0x0009, 0x7500 },
217 };
218 
219 #define MPX_NUM_MODES ARRAY_SIZE(mpx_audio_modes)
220 
221 static int mpx_setup(struct i2c_client *client)
222 {
223  struct wis_sony_tuner *t = i2c_get_clientdata(client);
224  u16 source = 0;
225  u8 buffer[3];
226  struct i2c_msg msg;
227 
228  /* reset MPX */
229  buffer[0] = 0x00;
230  buffer[1] = 0x80;
231  buffer[2] = 0x00;
232  msg.addr = MPX_I2C_ADDR;
233  msg.flags = 0;
234  msg.len = 3;
235  msg.buf = buffer;
236  i2c_transfer(client->adapter, &msg, 1);
237  buffer[1] = 0x00;
238  i2c_transfer(client->adapter, &msg, 1);
239 
240  if (mpx_audio_modes[t->mpxmode].audio_mode != AUD_MONO) {
241  switch (t->audmode) {
243  switch (mpx_audio_modes[t->mpxmode].audio_mode) {
244  case AUD_A2:
245  source = mpx_audio_modes[t->mpxmode].source;
246  break;
247  case AUD_NICAM:
248  source = 0x0000;
249  break;
250  case AUD_NICAM_L:
251  source = 0x0200;
252  break;
253  default:
254  break;
255  }
256  break;
258  source = mpx_audio_modes[t->mpxmode].source;
259  break;
261  source = 0x0300;
262  break;
264  source = 0x0400;
265  break;
266  }
267  source |= mpx_audio_modes[t->mpxmode].source & 0x00ff;
268  } else
269  source = mpx_audio_modes[t->mpxmode].source;
270 
271  mpx_write(client, 0x10, 0x0030, mpx_audio_modes[t->mpxmode].modus);
272  mpx_write(client, 0x12, 0x0008, source);
273  mpx_write(client, 0x12, 0x0013, mpx_audio_modes[t->mpxmode].acb);
274  mpx_write(client, 0x12, 0x000e,
275  mpx_audio_modes[t->mpxmode].fm_prescale);
276  mpx_write(client, 0x12, 0x0010,
277  mpx_audio_modes[t->mpxmode].nicam_prescale);
278  mpx_write(client, 0x12, 0x000d,
279  mpx_audio_modes[t->mpxmode].scart_prescale);
280  mpx_write(client, 0x10, 0x0020, mpx_audio_modes[t->mpxmode].system);
281  mpx_write(client, 0x12, 0x0000, mpx_audio_modes[t->mpxmode].volume);
282  if (mpx_audio_modes[t->mpxmode].audio_mode == AUD_A2)
283  mpx_write(client, 0x10, 0x0022,
284  t->audmode == V4L2_TUNER_MODE_MONO ? 0x07f0 : 0x0190);
285 
286 #ifdef MPX_DEBUG
287  {
288  u8 buf1[3], buf2[2];
289  struct i2c_msg msgs[2];
290 
291  printk(KERN_DEBUG "wis-sony-tuner: MPX registers: %04x %04x "
292  "%04x %04x %04x %04x %04x %04x\n",
293  mpx_audio_modes[t->mpxmode].modus,
294  source,
295  mpx_audio_modes[t->mpxmode].acb,
296  mpx_audio_modes[t->mpxmode].fm_prescale,
297  mpx_audio_modes[t->mpxmode].nicam_prescale,
298  mpx_audio_modes[t->mpxmode].scart_prescale,
299  mpx_audio_modes[t->mpxmode].system,
300  mpx_audio_modes[t->mpxmode].volume);
301  buf1[0] = 0x11;
302  buf1[1] = 0x00;
303  buf1[2] = 0x7e;
304  msgs[0].addr = MPX_I2C_ADDR;
305  msgs[0].flags = 0;
306  msgs[0].len = 3;
307  msgs[0].buf = buf1;
308  msgs[1].addr = MPX_I2C_ADDR;
309  msgs[1].flags = I2C_M_RD;
310  msgs[1].len = 2;
311  msgs[1].buf = buf2;
312  i2c_transfer(client->adapter, msgs, 2);
313  printk(KERN_DEBUG "wis-sony-tuner: MPX system: %02x%02x\n",
314  buf2[0], buf2[1]);
315  buf1[0] = 0x11;
316  buf1[1] = 0x02;
317  buf1[2] = 0x00;
318  i2c_transfer(client->adapter, msgs, 2);
319  printk(KERN_DEBUG "wis-sony-tuner: MPX status: %02x%02x\n",
320  buf2[0], buf2[1]);
321  }
322 #endif
323  return 0;
324 }
325 
326 /*
327  * IF configuration values for the BTF-PG472Z:
328  *
329  * B/G: 0x94 0x70 0x49
330  * I: 0x14 0x70 0x4a
331  * D/K: 0x14 0x70 0x4b
332  * L: 0x04 0x70 0x4b
333  * L': 0x44 0x70 0x53
334  * M: 0x50 0x30 0x4c
335  */
336 
337 static int set_if(struct i2c_client *client)
338 {
339  struct wis_sony_tuner *t = i2c_get_clientdata(client);
340  u8 buffer[4];
341  struct i2c_msg msg;
342  int default_mpx_mode = 0;
343 
344  /* configure IF */
345  buffer[0] = 0;
346  if (t->std & V4L2_STD_PAL_BG) {
347  buffer[1] = 0x94;
348  buffer[2] = 0x70;
349  buffer[3] = 0x49;
350  default_mpx_mode = 1;
351  } else if (t->std & V4L2_STD_PAL_I) {
352  buffer[1] = 0x14;
353  buffer[2] = 0x70;
354  buffer[3] = 0x4a;
355  default_mpx_mode = 4;
356  } else if (t->std & V4L2_STD_PAL_DK) {
357  buffer[1] = 0x14;
358  buffer[2] = 0x70;
359  buffer[3] = 0x4b;
360  default_mpx_mode = 6;
361  } else if (t->std & V4L2_STD_SECAM_L) {
362  buffer[1] = 0x04;
363  buffer[2] = 0x70;
364  buffer[3] = 0x4b;
365  default_mpx_mode = 11;
366  }
367  msg.addr = IF_I2C_ADDR;
368  msg.flags = 0;
369  msg.len = 4;
370  msg.buf = buffer;
371  i2c_transfer(client->adapter, &msg, 1);
372 
373  /* Select MPX mode if not forced by the user */
374  if (force_mpx_mode >= 0 && force_mpx_mode < MPX_NUM_MODES)
375  t->mpxmode = force_mpx_mode;
376  else
377  t->mpxmode = default_mpx_mode;
378  printk(KERN_DEBUG "wis-sony-tuner: setting MPX to mode %d\n",
379  t->mpxmode);
380  mpx_setup(client);
381 
382  return 0;
383 }
384 
385 static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
386 {
387  struct wis_sony_tuner *t = i2c_get_clientdata(client);
388 
389  switch (cmd) {
390 #if 0
391 #ifdef TUNER_SET_TYPE_ADDR
392  case TUNER_SET_TYPE_ADDR:
393  {
394  struct tuner_setup *tun_setup = arg;
395  int *type = &tun_setup->type;
396 #else
397  case TUNER_SET_TYPE:
398  {
399  int *type = arg;
400 #endif
401 
402  if (t->type >= 0) {
403  if (t->type != *type)
404  printk(KERN_ERR "wis-sony-tuner: type already "
405  "set to %d, ignoring request for %d\n",
406  t->type, *type);
407  break;
408  }
409  t->type = *type;
410  switch (t->type) {
412  switch (force_band_str[0]) {
413  case 'b':
414  case 'B':
415  case 'g':
416  case 'G':
417  printk(KERN_INFO "wis-sony-tuner: forcing "
418  "tuner to PAL-B/G bands\n");
419  force_band = V4L2_STD_PAL_BG;
420  break;
421  case 'i':
422  case 'I':
423  printk(KERN_INFO "wis-sony-tuner: forcing "
424  "tuner to PAL-I band\n");
425  force_band = V4L2_STD_PAL_I;
426  break;
427  case 'd':
428  case 'D':
429  case 'k':
430  case 'K':
431  printk(KERN_INFO "wis-sony-tuner: forcing "
432  "tuner to PAL-D/K bands\n");
433  force_band = V4L2_STD_PAL_I;
434  break;
435  case 'l':
436  case 'L':
437  printk(KERN_INFO "wis-sony-tuner: forcing "
438  "tuner to SECAM-L band\n");
439  force_band = V4L2_STD_SECAM_L;
440  break;
441  default:
442  force_band = 0;
443  break;
444  }
445  if (force_band)
446  t->std = force_band;
447  else
448  t->std = V4L2_STD_PAL_BG;
449  set_if(client);
450  break;
452  t->std = V4L2_STD_NTSC_M_JP;
453  break;
455  t->std = V4L2_STD_NTSC_M;
456  break;
457  default:
458  printk(KERN_ERR "wis-sony-tuner: tuner type %d is not "
459  "supported by this module\n", *type);
460  break;
461  }
462  if (type >= 0)
464  "wis-sony-tuner: type set to %d (%s)\n",
465  t->type, sony_tuners[t->type - 200].name);
466  break;
467  }
468 #endif
469  case VIDIOC_G_FREQUENCY:
470  {
471  struct v4l2_frequency *f = arg;
472 
473  f->frequency = t->freq;
474  break;
475  }
476  case VIDIOC_S_FREQUENCY:
477  {
478  struct v4l2_frequency *f = arg;
479 
480  t->freq = f->frequency;
481  set_freq(client, t->freq);
482  break;
483  }
484  case VIDIOC_ENUMSTD:
485  {
486  struct v4l2_standard *std = arg;
487 
488  switch (t->type) {
490  switch (std->index) {
491  case 0:
493  V4L2_STD_PAL_BG, "PAL-B/G");
494  break;
495  case 1:
497  V4L2_STD_PAL_I, "PAL-I");
498  break;
499  case 2:
501  V4L2_STD_PAL_DK, "PAL-D/K");
502  break;
503  case 3:
505  V4L2_STD_SECAM_L, "SECAM-L");
506  break;
507  default:
508  std->id = 0; /* hack to indicate EINVAL */
509  break;
510  }
511  break;
513  if (std->index != 0) {
514  std->id = 0; /* hack to indicate EINVAL */
515  break;
516  }
518  V4L2_STD_NTSC_M_JP, "NTSC-J");
519  break;
521  if (std->index != 0) {
522  std->id = 0; /* hack to indicate EINVAL */
523  break;
524  }
526  break;
527  }
528  break;
529  }
530  case VIDIOC_G_STD:
531  {
532  v4l2_std_id *std = arg;
533 
534  *std = t->std;
535  break;
536  }
537  case VIDIOC_S_STD:
538  {
539  v4l2_std_id *std = arg;
540  v4l2_std_id old = t->std;
541 
542  switch (t->type) {
544  if (force_band && (*std & force_band) != *std &&
545  *std != V4L2_STD_PAL &&
546  *std != V4L2_STD_SECAM) {
547  printk(KERN_DEBUG "wis-sony-tuner: ignoring "
548  "requested TV standard in "
549  "favor of force_band value\n");
550  t->std = force_band;
551  } else if (*std & V4L2_STD_PAL_BG) { /* default */
552  t->std = V4L2_STD_PAL_BG;
553  } else if (*std & V4L2_STD_PAL_I) {
554  t->std = V4L2_STD_PAL_I;
555  } else if (*std & V4L2_STD_PAL_DK) {
556  t->std = V4L2_STD_PAL_DK;
557  } else if (*std & V4L2_STD_SECAM_L) {
558  t->std = V4L2_STD_SECAM_L;
559  } else {
560  printk(KERN_ERR "wis-sony-tuner: TV standard "
561  "not supported\n");
562  *std = 0; /* hack to indicate EINVAL */
563  break;
564  }
565  if (old != t->std)
566  set_if(client);
567  break;
569  if (!(*std & V4L2_STD_NTSC_M_JP)) {
570  printk(KERN_ERR "wis-sony-tuner: TV standard "
571  "not supported\n");
572  *std = 0; /* hack to indicate EINVAL */
573  }
574  break;
576  if (!(*std & V4L2_STD_NTSC_M)) {
577  printk(KERN_ERR "wis-sony-tuner: TV standard "
578  "not supported\n");
579  *std = 0; /* hack to indicate EINVAL */
580  }
581  break;
582  }
583  break;
584  }
585  case VIDIOC_QUERYSTD:
586  {
587  v4l2_std_id *std = arg;
588 
589  switch (t->type) {
591  if (force_band)
592  *std = force_band;
593  else
594  *std = V4L2_STD_PAL_BG | V4L2_STD_PAL_I |
595  V4L2_STD_PAL_DK | V4L2_STD_SECAM_L;
596  break;
598  *std = V4L2_STD_NTSC_M_JP;
599  break;
601  *std = V4L2_STD_NTSC_M;
602  break;
603  }
604  break;
605  }
606  case VIDIOC_G_TUNER:
607  {
608  struct v4l2_tuner *tun = arg;
609 
610  memset(tun, 0, sizeof(*tun));
611  strcpy(tun->name, "Television");
612  tun->type = V4L2_TUNER_ANALOG_TV;
613  tun->rangelow = 0UL; /* does anything use these? */
614  tun->rangehigh = 0xffffffffUL;
615  switch (t->type) {
623  break;
629  break;
630  }
631  tun->audmode = t->audmode;
632  return 0;
633  }
634  case VIDIOC_S_TUNER:
635  {
636  struct v4l2_tuner *tun = arg;
637 
638  switch (t->type) {
640  if (tun->audmode != t->audmode) {
641  t->audmode = tun->audmode;
642  mpx_setup(client);
643  }
644  break;
647  break;
648  }
649  return 0;
650  }
651  default:
652  break;
653  }
654  return 0;
655 }
656 
657 static int wis_sony_tuner_probe(struct i2c_client *client,
658  const struct i2c_device_id *id)
659 {
660  struct i2c_adapter *adapter = client->adapter;
661  struct wis_sony_tuner *t;
662 
663  if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
664  return -ENODEV;
665 
666  t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL);
667  if (t == NULL)
668  return -ENOMEM;
669 
670  t->type = -1;
671  t->freq = 0;
672  t->mpxmode = 0;
674  i2c_set_clientdata(client, t);
675 
677  "wis-sony-tuner: initializing tuner at address %d on %s\n",
678  client->addr, adapter->name);
679 
680  return 0;
681 }
682 
683 static int wis_sony_tuner_remove(struct i2c_client *client)
684 {
685  struct wis_sony_tuner *t = i2c_get_clientdata(client);
686 
687  kfree(t);
688  return 0;
689 }
690 
691 static const struct i2c_device_id wis_sony_tuner_id[] = {
692  { "wis_sony_tuner", 0 },
693  { }
694 };
695 MODULE_DEVICE_TABLE(i2c, wis_sony_tuner_id);
696 
697 static struct i2c_driver wis_sony_tuner_driver = {
698  .driver = {
699  .name = "WIS Sony TV Tuner I2C driver",
700  },
701  .probe = wis_sony_tuner_probe,
702  .remove = wis_sony_tuner_remove,
703  .command = tuner_command,
704  .id_table = wis_sony_tuner_id,
705 };
706 
707 static int __init wis_sony_tuner_init(void)
708 {
709  return i2c_add_driver(&wis_sony_tuner_driver);
710 }
711 
712 static void __exit wis_sony_tuner_cleanup(void)
713 {
714  i2c_del_driver(&wis_sony_tuner_driver);
715 }
716 
717 module_init(wis_sony_tuner_init);
718 module_exit(wis_sony_tuner_cleanup);
719 
720 MODULE_LICENSE("GPL v2");