On Friday 12 February 2010 23:36:20 Pete Eberlein wrote:
> On Fri, 2010-02-12 at 22:03 +0100, Hans Verkuil wrote:
> > > > > +#include <media/v4l2-i2c-drv.h>
> > > > 
> > > > The v4l2-i2c-drv.h is to be used only for drivers that also need to be 
> > > > compiled
> > > > for kernels < 2.6.26. If I am not mistaken that is the case for this 
> > > > driver,
> > > > right? I remember you mentioning that customers of yours use this on 
> > > > such old
> > > > kernels. Just making sure.
> > > 
> > > My company, Sensoray, doesn't have any products that use this tuner.
> > > This driver was orignally written by Micronas to support their go7007
> > > chip in the Plextor TV402U models.  I don't have the datasheet or know
> > > much about tuners anyway.  I used the v4l2-i2c-drv.h since it seems like
> > > a good idea at the time.  What should I use instead?
> > 
> > We way i2c devices are handled changed massively in kernel 2.6.26. In order 
> > to
> > stay backwards compatible with older kernels the v4l2-i2c-drv.h header was
> > introduced. However, this is a bit of a hack and any i2c driver that does 
> > not
> > need it shouldn't use it.
> > 
> > So only if an i2c driver is *never* used by parent drivers that have to 
> > support
> > kernels < 2.6.26, then can it drop the v4l2-i2c-drv.h. An example of such an
> > i2c driver is tvp514x.c.
> > 
> > Eventually support for such old kernels will be dropped and the 
> > v4l2-i2c-drv.h
> > header will disappear altogether, but that's not going to happen anytime 
> > soon.
> > 
> > What this means for go7007 is that you have to decide whether you want this
> > go7007 driver to work only for kernels >= 2.6.26, or whether it should also
> > work for older kernels. My understanding is that Sensoray wants to be able 
> > to
> > compile go7007 for older kernels. In that case the use of v4l2-i2c-drv.h is
> > correct. Note that this is not about whether any of *Sensoray's* products 
> > use
> > a particular i2c device, but whether the *go7007* driver uses it.
> > 
> > I hope this clarifies this.
> 
> Yes it does, thank you.  We do want to allow our customers to use the
> go7007 driver with our products on older kernels, so I would like to
> keep the v4l2-i2c-drv.h for now.  I've addressed your other comments in
> the revised patch:

I've two small comments. See below.

I also realized that this is really two drivers in one: one driver for the
actual tuner device and one for the mpx device which seems similar in
functionality to the vp27smpx.c driver.

I will look at it again tomorrow, but I might decide that it is better to
split it up into two drivers: one for the tuner and one for the mpx.

Regards,

        Hans

> 
> 
> From: Pete Eberlein <[email protected]>
> 
> This is a subdev conversion of the go7007 wis-sony-tuner i2c driver,
> and places it with the other tuner drivers.  This obsoletes the
> wis-sony-tuner driver in the go7007 staging directory.
> 
> Priority: normal
> 
> Signed-off-by: Pete Eberlein <[email protected]>
> 
> diff -r 27ee8e515b18 -r 1cf1bf4e616f 
> linux/Documentation/video4linux/CARDLIST.tuner
> --- a/linux/Documentation/video4linux/CARDLIST.tuner  Wed Feb 10 11:25:59 
> 2010 -0800
> +++ b/linux/Documentation/video4linux/CARDLIST.tuner  Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -81,3 +81,6 @@
>  tuner=81 - Partsnic (Daewoo) PTI-5NF05
>  tuner=82 - Philips CU1216L
>  tuner=83 - NXP TDA18271
> +tuner=84 - Sony PAL+SECAM (BTF-PG472Z)
> +tuner=85 - Sony NTSC_JP (BTF-PK467Z)
> +tuner=86 - Sony NTSC (BTF-PB463Z)
> diff -r 27ee8e515b18 -r 1cf1bf4e616f linux/drivers/media/common/tuners/Kconfig
> --- a/linux/drivers/media/common/tuners/Kconfig       Wed Feb 10 11:25:59 
> 2010 -0800
> +++ b/linux/drivers/media/common/tuners/Kconfig       Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -179,4 +179,12 @@
>       help
>         A driver for the silicon tuner MAX2165 from Maxim.
>  
> +config MEDIA_TUNER_SONY
> +     tristate "Sony TV tuner"
> +     depends on VIDEO_MEDIA && I2C
> +     default m if MEDIA_TUNER_CUSTOMISE
> +     help
> +       A driver for the Sony tuners BTF-PG472Z, BTF-PK467Z, BTF-PB463Z.
> +
> +
>  endif # MEDIA_TUNER_CUSTOMISE
> diff -r 27ee8e515b18 -r 1cf1bf4e616f 
> linux/drivers/media/common/tuners/Makefile
> --- a/linux/drivers/media/common/tuners/Makefile      Wed Feb 10 11:25:59 
> 2010 -0800
> +++ b/linux/drivers/media/common/tuners/Makefile      Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -24,6 +24,7 @@
>  obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
>  obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
>  obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
> +obj-$(CONFIG_MEDIA_TUNER_SONY) += sony-tuner.o
>  
>  EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
>  EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
> diff -r 27ee8e515b18 -r 1cf1bf4e616f 
> linux/drivers/media/common/tuners/sony-tuner.c
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux/drivers/media/common/tuners/sony-tuner.c  Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -0,0 +1,677 @@
> +/*
> + * Copyright (C) 2005-2006 Micronas USA Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License (Version 2) as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software Foundation,
> + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/i2c.h>
> +#include <linux/videodev2.h>
> +#include <media/tuner.h>
> +#include <media/v4l2-common.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-i2c-drv.h>
> +
> +MODULE_DESCRIPTION("Sony TV Tuner driver");
> +MODULE_LICENSE("GPL v2");
> +
> +static int debug;
> +module_param(debug, int, 0644);
> +MODULE_PARM_DESC(debug, "debug level 0=off(default) 1=on\n");
> +
> +/* #define MPX_DEBUG */
> +
> +/* AS(IF/MPX) pin:      LOW      HIGH/OPEN
> + * IF/MPX address:   0x42/0x40   0x43/0x44
> + */
> +#define IF_I2C_ADDR  0x43
> +#define MPX_I2C_ADDR 0x44
> +
> +static v4l2_std_id force_band;
> +static char force_band_str[] = "-";
> +module_param_string(force_band, force_band_str, sizeof(force_band_str), 
> 0644);
> +static int force_mpx_mode = -1;
> +module_param(force_mpx_mode, int, 0644);
> +
> +/* Store tuner info in the same format as tuner.c, so maybe we can put the
> + * Sony tuner support in there. */
> +struct sony_tunertype {
> +     const char *name;
> +     unsigned char Vendor; /* unused here */
> +     unsigned char Type; /* unused here */
> +
> +     unsigned short thresh1; /*  band switch VHF_LO <=> VHF_HI */
> +     unsigned short thresh2; /*  band switch VHF_HI <=> UHF */
> +     unsigned char VHF_L;
> +     unsigned char VHF_H;
> +     unsigned char UHF;
> +     unsigned char config;
> +     unsigned short IFPCoff;
> +};
> +
> +/* This array is indexed by (tuner_type - TUNER_SONY_BTF_PG472Z) */
> +static const struct sony_tunertype sony_tuners[] = {
> +     { "Sony PAL+SECAM (BTF-PG472Z)", 0, 0,
> +       16*144.25, 16*427.25, 0x01, 0x02, 0x04, 0xc6, 623},
> +     { "Sony NTSC_JP (BTF-PK467Z)", 0, 0,
> +       16*220.25, 16*467.25, 0x01, 0x02, 0x04, 0xc6, 940},
> +     { "Sony NTSC (BTF-PB463Z)", 0, 0,
> +       16*130.25, 16*364.25, 0x01, 0x02, 0x04, 0xc6, 732},
> +};
> +
> +struct sony_tuner {
> +     struct v4l2_subdev sd;
> +     int type;
> +     v4l2_std_id std;
> +     unsigned int freq;
> +     int mpxmode;
> +     u32 audmode;
> +};
> +
> +static inline struct sony_tuner *to_state(struct v4l2_subdev *sd)
> +{
> +     return container_of(sd, struct sony_tuner, sd);
> +}
> +
> +/* Basically the same as default_set_tv_freq() in tuner.c */
> +static int set_freq(struct i2c_client *client, int freq)
> +{
> +     struct sony_tuner *t = to_state(i2c_get_clientdata(client));
> +     const char *band_name;
> +     int n;
> +     int band_select;
> +     const struct sony_tunertype *tun;
> +     u8 buffer[4];
> +
> +     tun = &sony_tuners[t->type - TUNER_SONY_BTF_PG472Z];
> +     if (freq < tun->thresh1) {
> +             band_name = "VHF_L";
> +             band_select = tun->VHF_L;
> +     } else if (freq < tun->thresh2) {
> +             band_name = "VHF_H";
> +             band_select = tun->VHF_H;
> +     } else {
> +             band_name = "UHF";
> +             band_select = tun->UHF;
> +     }
> +     v4l2_dbg(1, debug, client, "tuning to frequency %d.%04d (%s)\n",
> +                     freq / 16, (freq % 16) * 625, band_name);
> +     n = freq + tun->IFPCoff;
> +
> +     buffer[0] = n >> 8;
> +     buffer[1] = n & 0xff;
> +     buffer[2] = tun->config;
> +     buffer[3] = band_select;
> +     i2c_master_send(client, buffer, 4);
> +
> +     return 0;
> +}
> +
> +static int mpx_write(struct i2c_client *client, int dev, int addr, int val)
> +{
> +     u8 buffer[5];
> +     struct i2c_msg msg;
> +
> +     buffer[0] = dev;
> +     buffer[1] = addr >> 8;
> +     buffer[2] = addr & 0xff;
> +     buffer[3] = val >> 8;
> +     buffer[4] = val & 0xff;
> +     msg.addr = MPX_I2C_ADDR;
> +     msg.flags = 0;
> +     msg.len = 5;
> +     msg.buf = buffer;
> +     i2c_transfer(client->adapter, &msg, 1);
> +     return 0;
> +}
> +
> +/*
> + * MPX register values for the BTF-PG472Z:
> + *
> + *                                 FM_     NICAM_  SCART_
> + *          MODUS  SOURCE    ACB   PRESCAL PRESCAL PRESCAL SYSTEM  VOLUME
> + *         10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000
> + *         ---------------------------------------------------------------
> + * Auto     1003    0020    0100    2603    5000    XXXX    0001    7500
> + *
> + * B/G
> + *  Mono    1003    0020    0100    2603    5000    XXXX    0003    7500
> + *  A2      1003    0020    0100    2601    5000    XXXX    0003    7500
> + *  NICAM   1003    0120    0100    2603    5000    XXXX    0008    7500
> + *
> + * I
> + *  Mono    1003    0020    0100    2603    7900    XXXX    000A    7500
> + *  NICAM   1003    0120    0100    2603    7900    XXXX    000A    7500
> + *
> + * D/K
> + *  Mono    1003    0020    0100    2603    5000    XXXX    0004    7500
> + *  A2-1    1003    0020    0100    2601    5000    XXXX    0004    7500
> + *  A2-2    1003    0020    0100    2601    5000    XXXX    0005    7500
> + *  A2-3    1003    0020    0100    2601    5000    XXXX    0007    7500
> + *  NICAM   1003    0120    0100    2603    5000    XXXX    000B    7500
> + *
> + * L/L'
> + *  Mono    0003    0200    0100    7C03    5000    2200    0009    7500
> + *  NICAM   0003    0120    0100    7C03    5000    XXXX    0009    7500
> + *
> + * M
> + *  Mono    1003    0200    0100    2B03    5000    2B00    0002    7500
> + *
> + * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX.
> + *
> + * Bilingual selection in A2/NICAM:
> + *
> + *         High byte of SOURCE     Left chan   Right chan
> + *                 0x01              MAIN         SUB
> + *                 0x03              MAIN         MAIN
> + *                 0x04              SUB          SUB
> + *
> + * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or
> + * 0x00 (all other bands).  Force mono in A2 with FMONO_A2:
> + *
> + *                      FMONO_A2
> + *                      10/0022
> + *                      --------
> + *     Forced mono ON     07F0
> + *     Forced mono OFF    0190
> + */
> +
> +static struct {
> +     enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode;
> +     u16 modus;
> +     u16 source;
> +     u16 acb;
> +     u16 fm_prescale;
> +     u16 nicam_prescale;
> +     u16 scart_prescale;
> +     u16 system;
> +     u16 volume;
> +} mpx_audio_modes[] = {
> +     /* Auto */      { AUD_MONO,     0x1003, 0x0020, 0x0100, 0x2603,
> +                                     0x5000, 0x0000, 0x0001, 0x7500 },
> +     /* B/G Mono */  { AUD_MONO,     0x1003, 0x0020, 0x0100, 0x2603,
> +                                     0x5000, 0x0000, 0x0003, 0x7500 },
> +     /* B/G A2 */    { AUD_A2,       0x1003, 0x0020, 0x0100, 0x2601,
> +                                     0x5000, 0x0000, 0x0003, 0x7500 },
> +     /* B/G NICAM */ { AUD_NICAM,    0x1003, 0x0120, 0x0100, 0x2603,
> +                                     0x5000, 0x0000, 0x0008, 0x7500 },
> +     /* I Mono */    { AUD_MONO,     0x1003, 0x0020, 0x0100, 0x2603,
> +                                     0x7900, 0x0000, 0x000A, 0x7500 },
> +     /* I NICAM */   { AUD_NICAM,    0x1003, 0x0120, 0x0100, 0x2603,
> +                                     0x7900, 0x0000, 0x000A, 0x7500 },
> +     /* D/K Mono */  { AUD_MONO,     0x1003, 0x0020, 0x0100, 0x2603,
> +                                     0x5000, 0x0000, 0x0004, 0x7500 },
> +     /* D/K A2-1 */  { AUD_A2,       0x1003, 0x0020, 0x0100, 0x2601,
> +                                     0x5000, 0x0000, 0x0004, 0x7500 },
> +     /* D/K A2-2 */  { AUD_A2,       0x1003, 0x0020, 0x0100, 0x2601,
> +                                     0x5000, 0x0000, 0x0005, 0x7500 },
> +     /* D/K A2-3 */  { AUD_A2,       0x1003, 0x0020, 0x0100, 0x2601,
> +                                     0x5000, 0x0000, 0x0007, 0x7500 },
> +     /* D/K NICAM */ { AUD_NICAM,    0x1003, 0x0120, 0x0100, 0x2603,
> +                                     0x5000, 0x0000, 0x000B, 0x7500 },
> +     /* L/L' Mono */ { AUD_MONO,     0x0003, 0x0200, 0x0100, 0x7C03,
> +                                     0x5000, 0x2200, 0x0009, 0x7500 },
> +     /* L/L' NICAM */{ AUD_NICAM_L,  0x0003, 0x0120, 0x0100, 0x7C03,
> +                                     0x5000, 0x0000, 0x0009, 0x7500 },
> +};
> +
> +#define MPX_NUM_MODES        ARRAY_SIZE(mpx_audio_modes)
> +
> +static int mpx_setup(struct i2c_client *client)
> +{
> +     struct sony_tuner *t = i2c_get_clientdata(client);
> +     u16 source = 0;
> +     u8 buffer[3];
> +     struct i2c_msg msg;
> +
> +     /* reset MPX */
> +     buffer[0] = 0x00;
> +     buffer[1] = 0x80;
> +     buffer[2] = 0x00;
> +     msg.addr = MPX_I2C_ADDR;
> +     msg.flags = 0;
> +     msg.len = 3;
> +     msg.buf = buffer;
> +     i2c_transfer(client->adapter, &msg, 1);
> +     buffer[1] = 0x00;
> +     i2c_transfer(client->adapter, &msg, 1);
> +
> +     if (mpx_audio_modes[t->mpxmode].audio_mode != AUD_MONO) {
> +             switch (t->audmode) {
> +             case V4L2_TUNER_MODE_MONO:
> +                     switch (mpx_audio_modes[t->mpxmode].audio_mode) {
> +                     case AUD_A2:
> +                             source = mpx_audio_modes[t->mpxmode].source;
> +                             break;
> +                     case AUD_NICAM:
> +                             source = 0x0000;
> +                             break;
> +                     case AUD_NICAM_L:
> +                             source = 0x0200;
> +                             break;
> +                     default:
> +                             break;
> +                     }
> +                     break;
> +             case V4L2_TUNER_MODE_STEREO:
> +                     source = mpx_audio_modes[t->mpxmode].source;
> +                     break;
> +             case V4L2_TUNER_MODE_LANG1:
> +                     source = 0x0300;
> +                     break;
> +             case V4L2_TUNER_MODE_LANG2:
> +                     source = 0x0400;
> +                     break;
> +             }
> +             source |= mpx_audio_modes[t->mpxmode].source & 0x00ff;
> +     } else
> +             source = mpx_audio_modes[t->mpxmode].source;
> +
> +     mpx_write(client, 0x10, 0x0030, mpx_audio_modes[t->mpxmode].modus);
> +     mpx_write(client, 0x12, 0x0008, source);
> +     mpx_write(client, 0x12, 0x0013, mpx_audio_modes[t->mpxmode].acb);
> +     mpx_write(client, 0x12, 0x000e,
> +                     mpx_audio_modes[t->mpxmode].fm_prescale);
> +     mpx_write(client, 0x12, 0x0010,
> +                     mpx_audio_modes[t->mpxmode].nicam_prescale);
> +     mpx_write(client, 0x12, 0x000d,
> +                     mpx_audio_modes[t->mpxmode].scart_prescale);
> +     mpx_write(client, 0x10, 0x0020, mpx_audio_modes[t->mpxmode].system);
> +     mpx_write(client, 0x12, 0x0000, mpx_audio_modes[t->mpxmode].volume);
> +     if (mpx_audio_modes[t->mpxmode].audio_mode == AUD_A2)
> +             mpx_write(client, 0x10, 0x0022,
> +                     t->audmode == V4L2_TUNER_MODE_MONO ?  0x07f0 : 0x0190);
> +
> +#ifdef MPX_DEBUG
> +     {
> +             u8 buf1[3], buf2[2];
> +             struct i2c_msg msgs[2];
> +
> +             v4l2_info(client, "MPX registers: %04x %04x "
> +                             "%04x %04x %04x %04x %04x %04x\n",
> +                             mpx_audio_modes[t->mpxmode].modus,
> +                             source,
> +                             mpx_audio_modes[t->mpxmode].acb,
> +                             mpx_audio_modes[t->mpxmode].fm_prescale,
> +                             mpx_audio_modes[t->mpxmode].nicam_prescale,
> +                             mpx_audio_modes[t->mpxmode].scart_prescale,
> +                             mpx_audio_modes[t->mpxmode].system,
> +                             mpx_audio_modes[t->mpxmode].volume);
> +             buf1[0] = 0x11;
> +             buf1[1] = 0x00;
> +             buf1[2] = 0x7e;
> +             msgs[0].addr = MPX_I2C_ADDR;
> +             msgs[0].flags = 0;
> +             msgs[0].len = 3;
> +             msgs[0].buf = buf1;
> +             msgs[1].addr = MPX_I2C_ADDR;
> +             msgs[1].flags = I2C_M_RD;
> +             msgs[1].len = 2;
> +             msgs[1].buf = buf2;
> +             i2c_transfer(client->adapter, msgs, 2);
> +             v4l2_info(client, "MPX system: %02x%02x\n",
> +                             buf2[0], buf2[1]);
> +             buf1[0] = 0x11;
> +             buf1[1] = 0x02;
> +             buf1[2] = 0x00;
> +             i2c_transfer(client->adapter, msgs, 2);
> +             v4l2_info(client, "MPX status: %02x%02x\n",
> +                             buf2[0], buf2[1]);
> +     }
> +#endif
> +     return 0;
> +}
> +
> +/*
> + * IF configuration values for the BTF-PG472Z:
> + *
> + *   B/G: 0x94 0x70 0x49
> + *   I:   0x14 0x70 0x4a
> + *   D/K: 0x14 0x70 0x4b
> + *   L:   0x04 0x70 0x4b
> + *   L':  0x44 0x70 0x53
> + *   M:   0x50 0x30 0x4c
> + */
> +
> +static int set_if(struct i2c_client *client)
> +{
> +     struct sony_tuner *t = i2c_get_clientdata(client);
> +     u8 buffer[4];
> +     struct i2c_msg msg;
> +     int default_mpx_mode = 0;
> +
> +     /* configure IF */
> +     buffer[0] = 0;
> +     if (t->std & V4L2_STD_PAL_BG) {
> +             buffer[1] = 0x94;
> +             buffer[2] = 0x70;
> +             buffer[3] = 0x49;
> +             default_mpx_mode = 1;
> +     } else if (t->std & V4L2_STD_PAL_I) {
> +             buffer[1] = 0x14;
> +             buffer[2] = 0x70;
> +             buffer[3] = 0x4a;
> +             default_mpx_mode = 4;
> +     } else if (t->std & V4L2_STD_PAL_DK) {
> +             buffer[1] = 0x14;
> +             buffer[2] = 0x70;
> +             buffer[3] = 0x4b;
> +             default_mpx_mode = 6;
> +     } else if (t->std & V4L2_STD_SECAM_L) {
> +             buffer[1] = 0x04;
> +             buffer[2] = 0x70;
> +             buffer[3] = 0x4b;
> +             default_mpx_mode = 11;
> +     }
> +     msg.addr = IF_I2C_ADDR;
> +     msg.flags = 0;
> +     msg.len = 4;
> +     msg.buf = buffer;
> +     i2c_transfer(client->adapter, &msg, 1);
> +
> +     /* Select MPX mode if not forced by the user */
> +     if (force_mpx_mode >= 0 && force_mpx_mode < MPX_NUM_MODES)
> +             t->mpxmode = force_mpx_mode;
> +     else
> +             t->mpxmode = default_mpx_mode;
> +     v4l2_dbg(1, debug, client, "setting MPX to mode %d\n", t->mpxmode);
> +     mpx_setup(client);
> +
> +     return 0;
> +}
> +
> +static int sony_tuner_s_type_addr(struct v4l2_subdev *sd,
> +                                   struct tuner_setup *setup)
> +{
> +     struct sony_tuner *t = to_state(sd);
> +
> +     if (!(setup->mode_mask & T_ANALOG_TV))
> +             return 0;
> +
> +     if (t->type >= 0) {
> +             if (t->type != setup->type)
> +                     v4l2_dbg(1, debug, sd, "type already set to %d, "
> +                             "ignoring request for %d\n",
> +                             t->type, setup->type);
> +             return 0;
> +     }
> +     switch (setup->type) {
> +     case TUNER_SONY_BTF_PG472Z:
> +             switch (force_band_str[0]) {
> +             case 'b':
> +             case 'B':
> +             case 'g':
> +             case 'G':
> +                     v4l2_dbg(1, debug, sd, "forcing tuner to PAL-B/G 
> bands\n");
> +                     force_band = V4L2_STD_PAL_BG;
> +                     break;
> +             case 'i':
> +             case 'I':
> +                     v4l2_dbg(1, debug, sd, "forcing tuner to PAL-I band\n");
> +                     force_band = V4L2_STD_PAL_I;
> +                     break;
> +             case 'd':
> +             case 'D':
> +             case 'k':
> +             case 'K':
> +                     v4l2_dbg(1, debug, sd, "forcing tuner to PAL-D/K 
> bands\n");
> +                     force_band = V4L2_STD_PAL_I;
> +                     break;
> +             case 'l':
> +             case 'L':
> +                     v4l2_dbg(1, debug, sd, "forcing tuner to SECAM-L 
> band\n");
> +                     force_band = V4L2_STD_SECAM_L;
> +                     break;
> +             default:
> +                     force_band = 0;
> +                     break;
> +             }
> +             if (force_band)
> +                     t->std = force_band;
> +             else
> +                     t->std = V4L2_STD_PAL_BG;
> +             set_if(v4l2_get_subdevdata(sd));
> +             break;
> +     case TUNER_SONY_BTF_PK467Z:
> +             t->std = V4L2_STD_NTSC_M_JP;
> +             break;
> +     case TUNER_SONY_BTF_PB463Z:
> +             t->std = V4L2_STD_NTSC_M;
> +             break;
> +     default:
> +             v4l2_dbg(1, debug, sd,
> +                     "tuner type %d is not supported by this module\n",
> +                     setup->type);
> +             return -EINVAL;
> +     }
> +     t->type = setup->type;
> +     if (t->type >= 0)
> +             v4l2_dbg(1, debug, sd, "type set to %d (%s)\n",
> +                     t->type,
> +                     sony_tuners[t->type - TUNER_SONY_BTF_PG472Z].name);
> +     return 0;
> +}
> +
> +static int sony_tuner_g_frequency(struct v4l2_subdev *sd,
> +                                   struct v4l2_frequency *freq)
> +{
> +     struct sony_tuner *t = to_state(sd);
> +
> +     if (freq->type != V4L2_TUNER_ANALOG_TV)
> +             return -EINVAL;
> +
> +     freq->frequency = t->freq;
> +     return 0;
> +}
> +
> +static int sony_tuner_s_frequency(struct v4l2_subdev *sd,
> +                                   struct v4l2_frequency *freq)
> +{
> +     struct sony_tuner *t = to_state(sd);
> +
> +     if (freq->type != V4L2_TUNER_ANALOG_TV)
> +             return -EINVAL;
> +
> +     t->freq = freq->frequency;
> +     set_freq(v4l2_get_subdevdata(sd), t->freq);
> +     return 0;
> +}
> +
> +
> +
> +static int sony_tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
> +{
> +     struct sony_tuner *t = to_state(sd);
> +     v4l2_std_id old = t->std;
> +
> +     switch (t->type) {
> +     case TUNER_SONY_BTF_PG472Z:
> +             if (force_band && (norm & force_band) != norm &&
> +                             norm != V4L2_STD_PAL &&
> +                             norm != V4L2_STD_SECAM) {
> +                     v4l2_dbg(1, debug, sd, "ignoring requested TV standard 
> in "
> +                                     "favor of force_band value\n");
> +                     t->std = force_band;
> +             } else if (norm & V4L2_STD_PAL_BG) { /* default */
> +                     t->std = V4L2_STD_PAL_BG;
> +             } else if (norm & V4L2_STD_PAL_I) {
> +                     t->std = V4L2_STD_PAL_I;
> +             } else if (norm & V4L2_STD_PAL_DK) {
> +                     t->std = V4L2_STD_PAL_DK;
> +             } else if (norm & V4L2_STD_SECAM_L) {
> +                     t->std = V4L2_STD_SECAM_L;
> +             } else {
> +                     v4l2_dbg(1, debug, sd, "TV standard not supported\n");
> +                     return -EINVAL;
> +             }
> +             if (old != t->std)
> +                     set_if(v4l2_get_subdevdata(sd));
> +             break;
> +     case TUNER_SONY_BTF_PK467Z:
> +             if (!(norm & V4L2_STD_NTSC_M_JP)) {
> +                     v4l2_dbg(1, debug, sd, "TV standard not supported\n");
> +                     return -EINVAL;
> +             }
> +             break;
> +     case TUNER_SONY_BTF_PB463Z:
> +             if (!(norm & V4L2_STD_NTSC_M)) {
> +                     v4l2_dbg(1, debug, sd, "TV standard not supported\n");
> +                     return -EINVAL;
> +             }
> +             break;
> +     }
> +     return 0;
> +}
> +
> +static int sony_tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
> +{
> +     struct sony_tuner *t = to_state(sd);
> +
> +     strlcpy(vt->name, "Television", sizeof(vt->name));
> +     vt->type = V4L2_TUNER_ANALOG_TV;
> +     vt->rangelow = 16;              /* FIXME */
> +     vt->rangehigh = 16 * 999.99;    /* FIXME */

Instead of just saying 'FIXME' add a comment saying something like this:

'Since we do not have a datasheet for this tuner we just put in
artificial low and high frequency values.'

> +     switch (t->type) {
> +     case TUNER_SONY_BTF_PG472Z:
> +             vt->capability = V4L2_TUNER_CAP_NORM |
> +                     V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
> +                     V4L2_TUNER_CAP_LANG2;
> +             vt->rxsubchans = V4L2_TUNER_SUB_MONO |
> +                     V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_LANG1 |
> +                     V4L2_TUNER_SUB_LANG2;
> +             break;
> +     case TUNER_SONY_BTF_PK467Z:
> +     case TUNER_SONY_BTF_PB463Z:
> +             vt->capability = V4L2_TUNER_CAP_STEREO;
> +             vt->rxsubchans = V4L2_TUNER_SUB_MONO |
> +                                     V4L2_TUNER_SUB_STEREO;
> +             break;
> +     }
> +     vt->audmode = t->audmode;
> +     return 0;
> +}
> +
> +static int sony_tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
> +{
> +     struct sony_tuner *t = to_state(sd);
> +
> +     if (vt->type != V4L2_TUNER_ANALOG_TV)
> +             return -EINVAL;
> +
> +     switch (t->type) {
> +     case TUNER_SONY_BTF_PG472Z:
> +             if (vt->audmode != t->audmode) {
> +                     t->audmode = vt->audmode;
> +                     mpx_setup(v4l2_get_subdevdata(sd));
> +             }
> +             break;
> +     case TUNER_SONY_BTF_PK467Z:
> +     case TUNER_SONY_BTF_PB463Z:
> +             break;
> +     }
> +     return 0;
> +}
> +
> +static int sony_tuner_log_status(struct v4l2_subdev *sd)
> +{
> +     struct sony_tuner *t = to_state(sd);
> +
> +     v4l2_info(sd, "Standard: %s\n", t->std == V4L2_STD_NTSC ? "NTSC" :
> +                                     t->std == V4L2_STD_PAL ? "PAL" :
> +                                     t->std == V4L2_STD_SECAM ? "SECAM" :
> +                                     "unknown");
> +     v4l2_info(sd, "Frequency: %ud\n", t->freq);
> +     return 0;
> +}
> +
> +/* 
> --------------------------------------------------------------------------*/
> +
> +static const struct v4l2_subdev_core_ops sony_tuner_core_ops = {
> +     .log_status = sony_tuner_log_status,
> +     .s_std = sony_tuner_s_std,
> +};
> +
> +static const struct v4l2_subdev_tuner_ops sony_tuner_tuner_ops = {
> +     .s_frequency = sony_tuner_s_frequency,
> +     .g_frequency = sony_tuner_g_frequency,
> +     .s_tuner = sony_tuner_s_tuner,
> +     .g_tuner = sony_tuner_g_tuner,
> +     .s_type_addr = sony_tuner_s_type_addr,
> +};
> +
> +static const struct v4l2_subdev_ops sony_tuner_ops = {
> +     .core = &sony_tuner_core_ops,
> +     .tuner = &sony_tuner_tuner_ops,
> +};
> +
> +/* 
> --------------------------------------------------------------------------*/
> +
> +static int sony_tuner_probe(struct i2c_client *client,
> +                             const struct i2c_device_id *id)
> +{
> +     struct sony_tuner *t;
> +     struct v4l2_subdev *sd;
> +
> +     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
> +             return -ENODEV;
> +
> +     v4l2_info(client, "initializing Sony TV Tuner at address 0x%x on %s\n",
> +             client->addr << 1, client->adapter->name);

Please use this for consistency with the other i2c drivers:

        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);

> +
> +     t = kzalloc(sizeof(struct sony_tuner), GFP_KERNEL);
> +     if (t == NULL)
> +             return -ENOMEM;
> +
> +     sd = &t->sd;
> +     v4l2_i2c_subdev_init(sd, client, &sony_tuner_ops);
> +
> +     /* Initialize sony_tuner */
> +     t->type = -1;
> +     t->freq = 0;
> +     t->mpxmode = 0;
> +     t->audmode = V4L2_TUNER_MODE_STEREO;
> +
> +     return 0;
> +}
> +
> +static int sony_tuner_remove(struct i2c_client *client)
> +{
> +     struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +
> +     v4l2_device_unregister_subdev(sd);
> +     kfree(to_state(sd));
> +
> +     return 0;
> +}
> +
> +/* ----------------------------------------------------------------------- */
> +
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> +static const struct i2c_device_id sony_tuner_id[] = {
> +     { "sony_tuner", 0 },
> +     { }
> +};
> +MODULE_DEVICE_TABLE(i2c, sony_tuner_id);
> +#endif
> +
> +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
> +     .name = "sony_tuner",
> +     .probe = sony_tuner_probe,
> +     .remove = sony_tuner_remove,
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> +     .id_table = sony_tuner_id,
> +#endif
> +};
> diff -r 27ee8e515b18 -r 1cf1bf4e616f 
> linux/drivers/media/common/tuners/tuner-types.c
> --- a/linux/drivers/media/common/tuners/tuner-types.c Wed Feb 10 11:25:59 
> 2010 -0800
> +++ b/linux/drivers/media/common/tuners/tuner-types.c Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -1806,6 +1806,18 @@
>               .name   = "NXP TDA18271",
>               /* see tda18271-fe.c for details */
>       },
> +     [TUNER_SONY_BTF_PG472Z] = {
> +             .name   = "Sony PAL+SECAM (BTF-PG472Z)",
> +             /* see sony-tuner.c for details */
> +     },
> +     [TUNER_SONY_BTF_PK467Z] = {
> +             .name   = "Sony NTSC_JP (BTF-PK467Z)",
> +             /* see sony-tuner.c for details */
> +     },
> +     [TUNER_SONY_BTF_PB463Z] = {
> +             .name   = "Sony NTSC (BTF-PB463Z)",
> +             /* see sony-tuner.c for details */
> +     },
>  };
>  EXPORT_SYMBOL(tuners);
>  
> diff -r 27ee8e515b18 -r 1cf1bf4e616f 
> linux/drivers/staging/go7007/go7007-driver.c
> --- a/linux/drivers/staging/go7007/go7007-driver.c    Wed Feb 10 11:25:59 
> 2010 -0800
> +++ b/linux/drivers/staging/go7007/go7007-driver.c    Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -243,6 +243,16 @@
>                       init_i2c_module(&go->i2c_adapter,
>                                       go->board_info->i2c_devs[i].type,
>                                       go->board_info->i2c_devs[i].addr);
> +
> +             if (go->tuner_type >= 0) {
> +                     struct tuner_setup setup = {
> +                             .addr = ADDR_UNSET,
> +                             .type = go->tuner_type,
> +                             .mode_mask = T_ANALOG_TV,
> +                     };
> +                     v4l2_device_call_all(&go->v4l2_dev, 0, tuner,
> +                             s_type_addr, &setup);
> +             }
>               if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) {
>                       int channel = go->channel_number;
>                       struct v4l2_priv_tun_config config = {
> diff -r 27ee8e515b18 -r 1cf1bf4e616f 
> linux/drivers/staging/go7007/go7007-priv.h
> --- a/linux/drivers/staging/go7007/go7007-priv.h      Wed Feb 10 11:25:59 
> 2010 -0800
> +++ b/linux/drivers/staging/go7007/go7007-priv.h      Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -292,9 +292,3 @@
>  /* We re-use the I2C_M_TEN value so the flag passes through the masks in the
>   * core I2C code.  Major kludge, but the I2C layer ain't exactly flexible. */
>  #define      I2C_CLIENT_SCCB                 0x10
> -
> -/* Sony tuner types */
> -
> -#define TUNER_SONY_BTF_PG472Z                200
> -#define TUNER_SONY_BTF_PK467Z                201
> -#define TUNER_SONY_BTF_PB463Z                202
> diff -r 27ee8e515b18 -r 1cf1bf4e616f linux/drivers/staging/go7007/go7007-usb.c
> --- a/linux/drivers/staging/go7007/go7007-usb.c       Wed Feb 10 11:25:59 
> 2010 -0800
> +++ b/linux/drivers/staging/go7007/go7007-usb.c       Fri Feb 12 14:27:39 
> 2010 -0800
> @@ -27,6 +27,7 @@
>  #include <linux/i2c.h>
>  #include <asm/byteorder.h>
>  #include <media/tvaudio.h>
> +#include <media/tuner.h>
>  
>  #include "go7007-priv.h"
>  
> @@ -217,7 +218,7 @@
>                               .addr   = 0x1a,
>                       },
>                       {
> -                             .type   = "wis_sony_tuner",
> +                             .type   = "sony_tuner",
>                               .addr   = 0x60,
>                       },
>               },
> diff -r 27ee8e515b18 -r 1cf1bf4e616f linux/include/media/tuner.h
> --- a/linux/include/media/tuner.h     Wed Feb 10 11:25:59 2010 -0800
> +++ b/linux/include/media/tuner.h     Fri Feb 12 14:27:39 2010 -0800
> @@ -130,6 +130,10 @@
>  #define TUNER_PHILIPS_CU1216L           82
>  #define TUNER_NXP_TDA18271           83
>  
> +#define TUNER_SONY_BTF_PG472Z                84      /* PAL+SECAM */
> +#define TUNER_SONY_BTF_PK467Z                85      /* NTSC_JP */
> +#define TUNER_SONY_BTF_PB463Z                86      /* NTSC */
> +
>  /* tv card specific */
>  #define TDA9887_PRESENT              (1<<0)
>  #define TDA9887_PORT1_INACTIVE               (1<<1)
> 
> 

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to