From 0e1165e8d05ef4a530001ea4ac5ff0df78129dd2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Oct 2007 20:10:07 -0300 Subject: V4L/DVB (6385): Adds the capability of configuring tea5767 support tea5767 has several possible configurations. Before the patch, the driver were assuming the more common configuration. However, some newer cards, like MSI @nyware Master requires other configurations, like de-activating a gpio port and changing chip Xtal. This patch adds the capability of altering device configuration at runtime. This may also be used later to activate some features like auto-mute when signal is weak. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tea5767.c | 89 ++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 27 deletions(-) (limited to 'drivers/media/video/tea5767.c') diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 71df419df7b..2d2acbdd24a 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -22,10 +22,12 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages"); #define PREFIX "tea5767 " -struct tea5767_priv { - struct tuner_i2c_props i2c_props; +/*****************************************************************************/ - u32 frequency; +struct tea5767_priv { + struct tuner_i2c_props i2c_props; + u32 frequency; + struct tea5767_ctrl ctrl; }; /*****************************************************************************/ @@ -127,17 +129,10 @@ struct tea5767_priv { /* Reserved for future extensions */ #define TEA5767_RESERVED_MASK 0xff -enum tea5767_xtal_freq { - TEA5767_LOW_LO_32768 = 0, - TEA5767_HIGH_LO_32768 = 1, - TEA5767_LOW_LO_13MHz = 2, - TEA5767_HIGH_LO_13MHz = 3, -}; - - /*****************************************************************************/ -static void tea5767_status_dump(unsigned char *buffer) +static void tea5767_status_dump(struct tea5767_priv *priv, + unsigned char *buffer) { unsigned int div, frq; @@ -153,7 +148,7 @@ static void tea5767_status_dump(unsigned char *buffer) div = ((buffer[0] & 0x3f) << 8) | buffer[1]; - switch (TEA5767_HIGH_LO_32768) { + switch (priv->ctrl.xtal_freq) { case TEA5767_HIGH_LO_13MHz: frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */ break; @@ -202,13 +197,10 @@ static int set_radio_freq(struct dvb_frontend *fe, tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000); - /* Rounds freq to next decimal value - for 62.5 KHz step */ - /* frq = 20*(frq/16)+radio_frq[frq%16]; */ + buffer[2] = 0; - buffer[2] = TEA5767_PORT1_HIGH; - buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL | - TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND; - buffer[4] = 0; + if (priv->ctrl.port1) + buffer[2] |= TEA5767_PORT1_HIGH; if (params->audmode == V4L2_TUNER_MODE_MONO) { tuner_dbg("TEA5767 set to mono\n"); @@ -217,18 +209,45 @@ static int set_radio_freq(struct dvb_frontend *fe, tuner_dbg("TEA5767 set to stereo\n"); } - /* Should be replaced */ - switch (TEA5767_HIGH_LO_32768) { + + buffer[3] = 0; + + if (priv->ctrl.port2) + buffer[3] |= TEA5767_PORT2_HIGH; + + if (priv->ctrl.high_cut) + buffer[3] |= TEA5767_HIGH_CUT_CTRL; + + if (priv->ctrl.st_noise) + buffer[3] |= TEA5767_ST_NOISE_CTL; + + if (priv->ctrl.soft_mute) + buffer[3] |= TEA5767_SOFT_MUTE; + + if (priv->ctrl.japan_band) + buffer[3] |= TEA5767_JAPAN_BAND; + + buffer[4] = 0; + + if (priv->ctrl.deemph_75) + buffer[4] |= TEA5767_DEEMPH_75; + + if (priv->ctrl.pllref) + buffer[4] |= TEA5767_PLLREF_ENABLE; + + + /* Rounds freq to next decimal value - for 62.5 KHz step */ + /* frq = 20*(frq/16)+radio_frq[frq%16]; */ + + switch (priv->ctrl.xtal_freq) { case TEA5767_HIGH_LO_13MHz: tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n"); buffer[2] |= TEA5767_HIGH_LO_INJECT; - buffer[4] |= TEA5767_PLLREF_ENABLE; div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000; break; case TEA5767_LOW_LO_13MHz: tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n"); - buffer[4] |= TEA5767_PLLREF_ENABLE; div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000; break; case TEA5767_LOW_LO_32768: @@ -256,7 +275,7 @@ static int set_radio_freq(struct dvb_frontend *fe, if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); else - tea5767_status_dump(buffer); + tea5767_status_dump(priv, buffer); } priv->frequency = frq * 125 / 2; @@ -398,6 +417,16 @@ static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct tea5767_priv *priv = fe->tuner_priv; *frequency = priv->frequency; + + return 0; +} + +static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg) +{ + struct tea5767_priv *priv = fe->tuner_priv; + + memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl)); + return 0; } @@ -407,6 +436,7 @@ static struct dvb_tuner_ops tea5767_tuner_ops = { }, .set_analog_params = set_radio_freq, + .set_config = tea5767_set_config, .sleep = tea5767_standby, .release = tea5767_release, .get_frequency = tea5767_get_frequency, @@ -425,8 +455,14 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, return NULL; fe->tuner_priv = priv; - priv->i2c_props.addr = i2c_addr; - priv->i2c_props.adap = i2c_adap; + priv->i2c_props.addr = i2c_addr; + priv->i2c_props.adap = i2c_adap; + priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768; + priv->ctrl.port1 = 1; + priv->ctrl.port2 = 1; + priv->ctrl.high_cut = 1; + priv->ctrl.st_noise = 1; + priv->ctrl.japan_band = 1; memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops, sizeof(struct dvb_tuner_ops)); @@ -436,7 +472,6 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, return fe; } - EXPORT_SYMBOL_GPL(tea5767_attach); EXPORT_SYMBOL_GPL(tea5767_autodetection); -- cgit v1.2.3-70-g09d2 From 9dd659de9fbd1687c6175053c6453db5b932f152 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 4 Nov 2007 11:03:36 -0300 Subject: V4L/DVB (6556): tuner: convert to bus-based I2C API Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt20xx.c | 2 +- drivers/media/video/tda8290.c | 2 +- drivers/media/video/tea5761.c | 2 +- drivers/media/video/tea5767.c | 2 +- drivers/media/video/tuner-core.c | 99 ++++++++++++-------------------------- drivers/media/video/tuner-driver.h | 6 +-- drivers/media/video/tuner-i2c.h | 6 +-- drivers/media/video/tuner-simple.c | 2 +- drivers/media/video/tuner-xc2028.c | 2 +- 9 files changed, 44 insertions(+), 79 deletions(-) (limited to 'drivers/media/video/tea5767.c') diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index f49d1f4c40d..b630c26cfe8 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -14,7 +14,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "mt20xx " +#define PREFIX "mt20xx" /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index f0191babe40..a849ded0000 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -31,7 +31,7 @@ static int tuner_debug; module_param_named(debug, tuner_debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda8290 " +#define PREFIX "tda8290" /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index 2150222a386..5326eeceaac 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c @@ -18,7 +18,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5761 " +#define PREFIX "tea5761" struct tea5761_priv { struct tuner_i2c_props i2c_props; diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 2d2acbdd24a..2f5a99de185 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -20,7 +20,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5767 " +#define PREFIX "tea5767" /*****************************************************************************/ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 48b2d46048a..1b0d28a0ca7 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "tuner-driver.h" #include "mt20xx.h" #include "tda8290.h" @@ -30,7 +31,7 @@ #define UNSET (-1U) -#define PREFIX "tuner " +#define PREFIX t->i2c->driver->driver.name /* standard i2c insmod options */ static unsigned short normal_i2c[] = { @@ -75,9 +76,6 @@ MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); MODULE_LICENSE("GPL"); -static struct i2c_driver driver; -static struct i2c_client client_template; - /* ---------------------------------------------------------------------- */ static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq) @@ -919,18 +917,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) static int tuner_suspend(struct i2c_client *c, pm_message_t state) { - struct tuner *t = i2c_get_clientdata (c); + struct tuner *t = i2c_get_clientdata(c); - tuner_dbg ("suspend\n"); + tuner_dbg("suspend\n"); /* FIXME: power down ??? */ return 0; } static int tuner_resume(struct i2c_client *c) { - struct tuner *t = i2c_get_clientdata (c); + struct tuner *t = i2c_get_clientdata(c); - tuner_dbg ("resume\n"); + tuner_dbg("resume\n"); if (V4L2_TUNER_RADIO == t->mode) { if (t->radio_freq) set_freq(c, t->radio_freq); @@ -946,7 +944,7 @@ static int tuner_resume(struct i2c_client *c) LIST_HEAD(tuner_list); /* Search for existing radio and/or TV tuners on the given I2C adapter. - Note that when this function is called from tuner_attach you can be + Note that when this function is called from tuner_probe you can be certain no other devices will be added/deleted at the same time, I2C core protects against that. */ static void tuner_lookup(struct i2c_adapter *adap, @@ -977,28 +975,19 @@ static void tuner_lookup(struct i2c_adapter *adap, } /* During client attach, set_type is called by adapter's attach_inform callback. - set_type must then be completed by tuner_attach. + set_type must then be completed by tuner_probe. */ -static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) +static int tuner_probe(struct i2c_client *client) { - struct i2c_client *client; struct tuner *t; struct tuner *radio; struct tuner *tv; - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (NULL == client) - return -ENOMEM; - t = kzalloc(sizeof(struct tuner), GFP_KERNEL); - if (NULL == t) { - kfree(client); + if (NULL == t) return -ENOMEM; - } t->i2c = client; - client_template.adapter = adap; - client_template.addr = addr; - memcpy(client, &client_template, sizeof(struct i2c_client)); + strlcpy(client->name, "(tuner unset)", sizeof(client->name)); i2c_set_clientdata(client, t); t->type = UNSET; t->audmode = V4L2_TUNER_MODE_STEREO; @@ -1015,14 +1004,16 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) printk(KERN_CONT "%02x ", buffer[i]); printk("\n"); } - /* HACK: This test were added to avoid tuner to probe tda9840 and + /* HACK: This test was added to avoid tuner to probe tda9840 and tea6415c on the MXB card */ - if (adap->id == I2C_HW_SAA7146 && addr < 0x4a) + if (client->adapter->id == I2C_HW_SAA7146 && client->addr < 0x4a) { + kfree(t); return -ENODEV; + } /* autodetection code based on the i2c addr */ if (!no_autodetect) { - switch (addr) { + switch (client->addr) { case 0x10: if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr) != EINVAL) { @@ -1092,7 +1083,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* Should be just before return */ register_client: - tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1, + client->adapter->name); /* Sets a default mode */ if (t->mode_mask & T_ANALOG_TV) { @@ -1102,19 +1094,21 @@ register_client: } else { t->mode = T_DIGITAL_TV; } - - i2c_attach_client(client); set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); + list_add_tail(&t->list, &tuner_list); return 0; } -static int tuner_probe(struct i2c_adapter *adap) +static int tuner_legacy_probe(struct i2c_adapter *adap) { if (0 != addr) { normal_i2c[0] = addr; normal_i2c[1] = I2C_CLIENT_END; } + if ((adap->class & I2C_CLASS_TV_ANALOG) == 0) + return 0; + /* HACK: Ignore 0x6b and 0x6f on cx88 boards. * FusionHDTV5 RT Gold has an ir receiver at 0x6b * and an RTC at 0x6f which can get corrupted if probed. @@ -1136,64 +1130,35 @@ static int tuner_probe(struct i2c_adapter *adap) "too many options specified " "in i2c probe ignore list!\n"); } - - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, tuner_attach); - return 0; + return 1; } -static int tuner_detach(struct i2c_client *client) +static int tuner_remove(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; - int err; - - err = i2c_detach_client(t->i2c); - if (err) { - tuner_warn - ("Client deregistration failed, client not detached.\n"); - return err; - } if (ops && ops->release) ops->release(&t->fe); list_del(&t->list); kfree(t); - kfree(client); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .id = I2C_DRIVERID_TUNER, - .attach_adapter = tuner_probe, - .detach_client = tuner_detach, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tuner", + .driverid = I2C_DRIVERID_TUNER, .command = tuner_command, + .probe = tuner_probe, + .remove = tuner_remove, .suspend = tuner_suspend, - .resume = tuner_resume, - .driver = { - .name = "tuner", - }, + .resume = tuner_resume, + .legacy_probe = tuner_legacy_probe, }; -static struct i2c_client client_template = { - .name = "(tuner unset)", - .driver = &driver, -}; - -static int __init tuner_init_module(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit tuner_cleanup_module(void) -{ - i2c_del_driver(&driver); -} -module_init(tuner_init_module); -module_exit(tuner_cleanup_module); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index 3ff2943ecc1..d6e5afdaa82 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -72,15 +72,15 @@ struct tuner { /* ------------------------------------------------------------------------ */ #define tuner_warn(fmt, arg...) do {\ - printk(KERN_WARNING PREFIX "%d-%04x: " fmt, \ + printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ - printk(KERN_INFO PREFIX "%d-%04x: " fmt, \ + printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ extern int tuner_debug; \ if (tuner_debug) \ - printk(KERN_DEBUG PREFIX "%d-%04x: " fmt, \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #endif /* __TUNER_DRIVER_H__ */ diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index 159019ec337..cfba3d10906 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -48,14 +48,14 @@ static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, #ifndef __TUNER_DRIVER_H__ #define tuner_warn(fmt, arg...) do {\ - printk(KERN_WARNING PREFIX "%d-%04x: " fmt, \ + printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ - printk(KERN_INFO PREFIX "%d-%04x: " fmt, \ + printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ if ((debug)) \ - printk(KERN_DEBUG PREFIX "%d-%04x: " fmt, \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) #endif /* __TUNER_DRIVER_H__ */ diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index eec13cb6cd6..c1db576696c 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -17,7 +17,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tuner-simple " +#define PREFIX "tuner-simple" static int offset = 0; module_param(offset, int, 0664); diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 473fa73b181..80d14020c78 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -22,7 +22,7 @@ #include #include "dvb_frontend.h" -#define PREFIX "xc2028 " +#define PREFIX "xc2028" static LIST_HEAD(xc2028_list); /* struct for storing firmware table */ -- cgit v1.2.3-70-g09d2 From e7a2bc8a756e5c0adc6804dd7702442a06174b74 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 1 Nov 2007 06:19:39 -0300 Subject: V4L/DVB (6557): tea5767: remove unnecessary warning Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tea5767.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video/tea5767.c') diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 2f5a99de185..e1b48d87e7b 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -401,7 +401,6 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) return EINVAL; } - printk(KERN_WARNING "TEA5767 detected.\n"); return 0; } -- cgit v1.2.3-70-g09d2