diff options
author | Mauro Carvalho Chehab <devnull@localhost> | 2005-05-30 02:02:47 +0000 |
---|---|---|
committer | Mauro Carvalho Chehab <devnull@localhost> | 2005-05-30 02:02:47 +0000 |
commit | 3a08c98d6b0d71c97886f1caf24203a378ea3563 (patch) | |
tree | e7d469f67b212639ddf1028b1025218f0f665b46 | |
parent | cf677744e728b271c15c5e7bee421925b6b1452f (diff) | |
download | mediapointer-dvb-s2-3a08c98d6b0d71c97886f1caf24203a378ea3563.tar.gz mediapointer-dvb-s2-3a08c98d6b0d71c97886f1caf24203a378ea3563.tar.bz2 |
Some relevant changes on tuner for supporting cards with different tunners for TV and FM (Like Pixelview cards with TVision tuners). This code is experimental.
Summary of changes:
- tuner-core changed to support multiple I2C devices
- created a new define option (CONFIG_TUNER_MULTI_I2C) to allow new behavor. It is commented on tuner-core.c
- By default, it uses first scanned I2C device for FM and TV
- New client control command TUNER_SET_ADDR allows changing I2C address for FM or TV tuner.
- TVision 5533 MF now uses I2C on 0xC2 for TV and on 0xC0 for radio
- TVision 5533 MF div now uses only integer arithmetics
- tuner I2C dettach now generates warn log if failed
-rw-r--r-- | linux/drivers/media/video/tuner-core.c | 80 | ||||
-rw-r--r-- | linux/drivers/media/video/tuner-simple.c | 28 | ||||
-rw-r--r-- | linux/include/media/tuner.h | 7 | ||||
-rw-r--r-- | v4l/ChangeLog | 15 |
4 files changed, 115 insertions, 15 deletions
diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 4633c0d6a..b330eba5a 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-core.c,v 1.6 2005/05/22 19:23:39 nsh Exp $ + * $Id: tuner-core.c,v 1.7 2005/05/30 02:02:47 mchehab Exp $ * * i2c tv tuner chip device driver * core core, i.e. kernel interfaces, registering and so on @@ -24,6 +24,11 @@ #include <media/audiochip.h> #include "compat.h" +/* + * comment line bellow to return to old behavor, where only one I2C device is supported + */ +/* #define CONFIG_TUNER_MULTI_I2C */ + #define UNSET (-1U) /* standard i2c insmod options */ @@ -62,6 +67,9 @@ MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); MODULE_LICENSE("GPL"); static int this_adap; +#ifdef CONFIG_TUNER_MULTI_I2C +static unsigned short tv_tuner, radio_tuner; +#endif static struct i2c_driver driver; static struct i2c_client client_template; @@ -134,6 +142,27 @@ static void set_freq(struct i2c_client *c, unsigned long freq) t->freq = freq; } +#ifdef CONFIG_TUNER_MULTI_I2C +static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr) +{ + struct tuner *t = i2c_get_clientdata(c); + + switch (tun_addr->type) { + case V4L2_TUNER_RADIO: + radio_tuner=tun_addr->addr; + tuner_dbg("radio tuner set to I2C address 0x%02x\n",radio_tuner<<1); + + break; + default: + tv_tuner=tun_addr->addr; + tuner_dbg("TV tuner set to I2C address 0x%02x\n",tv_tuner<<1); + break; + } +} +#else +#define set_addr(c,tun_addr) +#endif + static void set_type(struct i2c_client *c, unsigned int type) { struct tuner *t = i2c_get_clientdata(c); @@ -206,8 +235,16 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) { struct tuner *t; +#ifndef CONFIG_TUNER_MULTI_I2C if (this_adap > 0) return -1; +#else + /* by default, first I2C card is both tv and radio tuner */ + if (this_adap == 0) { + tv_tuner = addr; + radio_tuner = addr; + } +#endif this_adap++; client_template.adapter = adap; @@ -238,6 +275,11 @@ static int tuner_probe(struct i2c_adapter *adap) } this_adap = 0; +#ifdef CONFIG_TUNER_MULTI_I2C + tv_tuner = 0; + radio_tuner = 0; +#endif + if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tuner_attach); return 0; @@ -246,8 +288,14 @@ static int tuner_probe(struct i2c_adapter *adap) static int tuner_detach(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); + int err; - i2c_detach_client(&t->i2c); + err=i2c_detach_client(&t->i2c); + if (err) { + tuner_warn ("Client deregistration failed, client not detached.\n"); + return err; + } + kfree(t); return 0; } @@ -258,7 +306,18 @@ static int tuner_detach(struct i2c_client *client) #define CHECK_V4L2 if (t->using_v4l2) { if (tuner_debug) \ tuner_info("ignore v4l1 call\n"); \ return 0; } - + +#ifdef CONFIG_TUNER_MULTI_I2C +#define CHECK_ADDR(tp,cmd) if (client->addr!=tp) { \ + tuner_info ("Cmd %s to addr 0x%02x rejected.\n",cmd,client->addr<<1); \ + return 0; } +#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \ + CHECK_ADDR(radio_tuner,cmd) } else { CHECK_ADDR(tv_tuner,cmd); } +#else +#define CHECK_ADDR(tp,cmd) +#define CHECK_MODE(cmd) +#endif + static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -266,18 +325,23 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) unsigned int *iarg = (int*)arg; switch (cmd) { - /* --- configuration --- */ case TUNER_SET_TYPE: set_type(client,*iarg); break; + case TUNER_SET_ADDR: + set_addr(client,(struct tuner_addr *)arg); + break; case AUDC_SET_RADIO: + CHECK_ADDR(radio_tuner,"AUDC_SET_RADIO"); + if (V4L2_TUNER_RADIO != t->mode) { set_tv_freq(client,400 * 16); t->mode = V4L2_TUNER_RADIO; } break; case AUDC_CONFIG_PINNACLE: + CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE"); switch (*iarg) { case 2: tuner_dbg("pinnacle pal\n"); @@ -305,6 +369,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) }; struct video_channel *vc = arg; + CHECK_ADDR(tv_tuner,"VIDIOCSCHAN"); CHECK_V4L2; t->mode = V4L2_TUNER_ANALOG_TV; if (vc->norm < ARRAY_SIZE(map)) @@ -318,6 +383,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { unsigned long *v = arg; + CHECK_MODE("VIDIOCSFREQ"); CHECK_V4L2; set_freq(client,*v); return 0; @@ -326,6 +392,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_tuner *vt = arg; + CHECK_ADDR(radio_tuner,"VIDIOCGTUNER:"); CHECK_V4L2; if (V4L2_TUNER_RADIO == t->mode && t->has_signal) vt->signal = t->has_signal(client); @@ -335,6 +402,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_audio *va = arg; + CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO"); CHECK_V4L2; if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) va->mode = t->is_stereo(client) @@ -347,6 +415,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { v4l2_std_id *id = arg; + CHECK_ADDR(tv_tuner,"VIDIOC_S_STD"); SWITCH_V4L2; t->mode = V4L2_TUNER_ANALOG_TV; t->std = *id; @@ -359,6 +428,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_frequency *f = arg; + CHECK_MODE("VIDIOC_S_FREQUENCY"); SWITCH_V4L2; if (V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) @@ -371,6 +441,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_frequency *f = arg; + CHECK_MODE("VIDIOC_G_FREQUENCY"); SWITCH_V4L2; f->type = t->mode; f->frequency = t->freq; @@ -380,6 +451,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct v4l2_tuner *tuner = arg; + CHECK_MODE("VIDIOC_G_TUNER"); SWITCH_V4L2; if (V4L2_TUNER_RADIO == t->mode && t->has_signal) tuner->signal = t->has_signal(client); diff --git a/linux/drivers/media/video/tuner-simple.c b/linux/drivers/media/video/tuner-simple.c index d100901e0..4998fcc6f 100644 --- a/linux/drivers/media/video/tuner-simple.c +++ b/linux/drivers/media/video/tuner-simple.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-simple.c,v 1.13 2005/05/29 10:22:08 nsh Exp $ + * $Id: tuner-simple.c,v 1.14 2005/05/30 02:02:47 mchehab Exp $ * * i2c tv tuner chip device driver * controls all those simple 4-control-bytes style tuners. @@ -426,7 +426,6 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) unsigned char buffer[4]; unsigned div; int rc; - int old_addr=c->addr; tun=&tuners[t->type]; div = freq + (int)(16*10.7); @@ -434,12 +433,11 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) switch (t->type) { case TUNER_YMEC_TVF_5533MF: - c->addr=0x60; /* Forces usage of I2C FM Tuner which is different from TV */ /*These values are empirically determinated */ - div = (int)(freq*7.625)- 20; - buffer[2] = 0x80; /* could be also 0x88 */ - buffer[3] = 0x10; /* could be also 0x18 or 0x19 */ + div = (freq*122)/16 - 20; + buffer[2] = 0x88; /* could be also 0x80 */ + buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */ break; case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: @@ -465,8 +463,6 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); - - c->addr=old_addr; } int default_tuner_init(struct i2c_client *c) @@ -476,7 +472,21 @@ int default_tuner_init(struct i2c_client *c) tuner_info("type set to %d (%s)\n", t->type, tuners[t->type].name); strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); - + + switch (t->type) { + case TUNER_YMEC_TVF_5533MF: + { + struct tuner_addr tun_addr = { V4L2_TUNER_ANALOG_TV, 0xc2>>1 }; + + if (c->driver->command) { + c->driver->command(c, TUNER_SET_ADDR, &tun_addr); + } else { + tuner_warn("Couldn't set TV tuner I2C address to 0x%02x\n",tun_addr.addr<<1); + } + break; + } + } + t->tv_freq = default_set_tv_freq; t->radio_freq = default_set_radio_freq; t->has_signal = tuner_signal; diff --git a/linux/include/media/tuner.h b/linux/include/media/tuner.h index 9a7584e10..f9dd563ec 100644 --- a/linux/include/media/tuner.h +++ b/linux/include/media/tuner.h @@ -125,8 +125,10 @@ #define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ #define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ +#define TUNER_SET_ADDR _IOW('T',3,int) /* Chooses tuner I2C address */ #define TDA9887_SET_CONFIG _IOW('t',5,int) + /* tv card specific */ # define TDA9887_PRESENT (1<<0) # define TDA9887_PORT1_INACTIVE (1<<1) @@ -147,6 +149,11 @@ #define I2C_ADDR_TDA8290 0x4b #define I2C_ADDR_TDA8275 0x61 +struct tuner_addr { + enum v4l2_tuner_type type; + unsigned short addr; +}; + struct tuner { /* device */ struct i2c_client i2c; diff --git a/v4l/ChangeLog b/v4l/ChangeLog index 229a13606..698eb093f 100644 --- a/v4l/ChangeLog +++ b/v4l/ChangeLog @@ -1,3 +1,14 @@ +2005-05-30 02:42 mchehab + * tuner-core.c, tuner-simple.c, tuner.h: + + - tuner-core changed to support multiple I2C devices + - has to define CONFIG_TUNER_MULTI_I2C to allow new behavor + - By default, it uses first I2C device for FM and TV + - New client control TUNER_SET_ADDR changes I2C addr for FM or TV + - TVision 5533 MF now uses I2C on 0xC2 for TV and on 0xC0 for radio + - TVision 5533 MF div now uses only integer arithmetics + - tuner I2C dettach now generates warn log if failed + 2005-05-29 13:38 nshmyrev * cx88-cards.c, cx88.h: @@ -11,7 +22,7 @@ - Added initial support for Radio tuner for Ymec TVF xxx3 MF - Buffer values determinated empirically. - - There's a hack for selecting I2C bus for Radio (0xC0>>2) + - There's a hack for selecting I2C bus for Radio (0xC0>>1) 2005-05-25 04:00 nshmyrev @@ -1066,7 +1077,7 @@ saa7134-reg.h, saa7134-ts.c, saa7134-tvaudio.c, saa7134-vbi.c, saa7134-video.c, saa7134.h, video-buf.c, video-buf.h: - - added a bunch of $Id: ChangeLog,v 1.9 2005/05/29 17:34:51 mchehab Exp $ tags. + - added a bunch of $Id: ChangeLog,v 1.10 2005/05/30 02:02:47 mchehab Exp $ tags. 2004-09-15 17:35 kraxel |