Tyler Trafford wrote:
I'm guessing that the I2C defined parameters are done in the 'obsolete
style' in Morten's kernel version, causing it to ignore all
non-obsoletely-defined ones.
Ah yes, I didn't even think about that (even though he clearly
posted it in his log).
Actually, there's probably no reason why he can't use the tda9887 that
came with his kernel..
This is true. However, not being one to not submit like a patch a
day... this adds those params as well as syncs with the latest v4l
version, which has a parameter fix and support for mono radio (woohoo!).
Why don't you give this a try Morten? (against the 0.3.6s release)
You'll need the options:
options ivtv tda9887=0
options tda9887 port1=0 port2=0
Index: driver/tda9887.c
===================================================================
--- driver/tda9887.c (revision 325)
+++ driver/tda9887.c (working copy)
@@ -9,9 +9,17 @@
#include <linux/slab.h>
#include <linux/delay.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include "audiochip.h"
+#include "tuner.h"
+#include "id.h"
+#include "i2c-compat.h"
+#else
#include <media/audiochip.h>
-#include "tuner.h"
+#include <media/tuner.h>
#include <media/id.h>
+#endif
+#include "compat.h"
/* Chips:
TDA9885 (PAL, NTSC)
@@ -33,17 +41,43 @@
0x96 >>1,
I2C_CLIENT_END,
};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+#endif
I2C_CLIENT_INSMOD;
/* insmod options */
+#define UNSET (-1U)
static unsigned int debug = 0;
+static unsigned int port1 = UNSET;
+static unsigned int port2 = UNSET;
+static unsigned int qss = UNSET;
+static unsigned int adjust = 0x10;
+static char pal[] = "-";
+static char secam[] = "-";
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
module_param(debug, int, 0644);
+module_param(port1, int, 0644);
+module_param(port2, int, 0644);
+module_param(qss, int, 0644);
+module_param(adjust, int, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+#else
+MODULE_PARM(debug, "i");
+MODULE_PARM(port1, "i");
+MODULE_PARM(port2, "i");
+MODULE_PARM(qss, "i" );
+MODULE_PARM(adjust, "i");
+MODULE_PARM(pal, "s");
+MODULE_PARM(secam, "s");
+#endif
+
MODULE_LICENSE("GPL");
/* ---------------------------------------------------------------------- */
-#define UNSET (-1U)
#define PREFIX "tda9885/6/7: "
#define dprintk if (debug) printk
@@ -54,6 +88,7 @@
unsigned int config;
unsigned int pinnacle_id;
unsigned int using_v4l2;
+ unsigned int radio_mode;
};
struct tvnorm {
@@ -213,20 +248,26 @@
}
};
-static struct tvnorm radio = {
- .name = "radio",
+static struct tvnorm radio_stereo = {
+ .name = "Radio Stereo",
.b = ( cFmRadio |
- cQSS |
- cAutoMuteFmActive |
- cOutputPort1Inactive ),
- .c = ( cAudioGain6 |
- 0x10 ),
- .e = ( cAudioIF_6_5 |
- cRadioIF_38_90 |
- cGating_36 |
- cTunerGainLow ),
+ cQSS ),
+ .c = ( cDeemphasisOFF |
+ cAudioGain6 ),
+ .e = ( cAudioIF_5_5 |
+ cRadioIF_38_90 ),
};
+static struct tvnorm radio_mono = {
+ .name = "Radio Mono",
+ .b = ( cFmRadio |
+ cQSS ),
+ .c = ( cDeemphasisON |
+ cDeemphasis50),
+ .e = ( cAudioIF_5_5 |
+ cRadioIF_38_90 ),
+};
+
/* ---------------------------------------------------------------------- */
static void dump_read_message(unsigned char *buf)
@@ -359,7 +400,10 @@
int i;
if (t->radio) {
- norm = &radio;
+ if (t->radio_mode == V4L2_TUNER_MODE_MONO)
+ norm = &radio_mono;
+ else
+ norm = &radio_stereo;
} else {
for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
if (tvnorms[i].std & t->std) {
@@ -380,15 +424,6 @@
return 0;
}
-static unsigned int port1 = UNSET;
-static unsigned int port2 = UNSET;
-static unsigned int qss = UNSET;
-static unsigned int adjust = 0x10;
-module_param(port1, int, 0644);
-module_param(port2, int, 0644);
-module_param(qss, int, 0644);
-module_param(adjust, int, 0644);
-
static int tda9887_set_insmod(struct tda9887 *t, char *buf)
{
if (UNSET != port1) {
@@ -418,6 +453,12 @@
static int tda9887_set_config(struct tda9887 *t, char *buf)
{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+ if (t->config & TDA9887_PORT1)
+ buf[1] |= cOutputPort1Inactive;
+ if (t->config & TDA9887_PORT2)
+ buf[1] |= cOutputPort2Inactive;
+#else
if (t->config & TDA9887_PORT1_ACTIVE)
buf[1] &= ~cOutputPort1Inactive;
if (t->config & TDA9887_PORT1_INACTIVE)
@@ -426,6 +467,7 @@
buf[1] &= ~cOutputPort2Inactive;
if (t->config & TDA9887_PORT2_INACTIVE)
buf[1] |= cOutputPort2Inactive;
+#endif
if (t->config & TDA9887_QSS)
buf[1] |= cQSS;
@@ -448,8 +490,6 @@
break;
}
}
- if(t->config & TDA9887_LOW_GAIN)
- buf[2] |= cTunerGainLow;
return 0;
}
@@ -483,10 +523,6 @@
/* ---------------------------------------------------------------------- */
-static char pal[] = "-";
-module_param_string(pal, pal, 0644, sizeof(pal));
-static char secam[] = "-";
-module_param_string(secam, secam, 0644, sizeof(secam));
static int tda9887_fixup_std(struct tda9887 *t)
{
@@ -545,19 +581,6 @@
return 0;
}
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 8)
-static unsigned int msleep_interruptible(unsigned int msecs)
-{
- unsigned long timeout = msecs_to_jiffies(msecs);
-
- while (timeout && !signal_pending(current)) {
- set_current_state(TASK_INTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- }
- return jiffies_to_msecs(timeout);
-}
-#endif
-
static int tda9887_configure(struct tda9887 *t)
{
unsigned char buf[4];
@@ -565,8 +588,10 @@
memset(buf,0,sizeof(buf));
tda9887_set_tvnorm(t,buf);
+
buf[1] |= cOutputPort1Inactive;
buf[1] |= cOutputPort2Inactive;
+
if (UNSET != t->pinnacle_id) {
tda9887_set_pinnacle(t,buf);
}
@@ -576,7 +601,7 @@
#if 0
/* This as-is breaks some cards, must be fixed in a
* card-specific way, probably using TDA9887_SET_CONFIG to
- * turn on/off port2 */
+ * turn on/off port2 */
if (t->std & V4L2_STD_SECAM_L) {
/* secam fixup (FIXME: move this to tvnorms array?) */
buf[1] &= ~cOutputPort2Inactive;
@@ -591,16 +616,23 @@
if (4 != (rc = i2c_master_send(&t->client,buf,4)))
printk(PREFIX "i2c i/o error: rc == %d (should be 4)\n",rc);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
if (debug > 2) {
msleep_interruptible(1000);
tda9887_status(t);
}
+#endif
return 0;
}
/* ---------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
+#else
+static int tda9887_attach(struct i2c_adapter *adap, int addr,
+ unsigned short flags, int kind)
+#endif
{
struct tda9887 *t;
@@ -612,12 +644,18 @@
if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
return -ENOMEM;
memset(t,0,sizeof(*t));
+
t->client = client_template;
t->std = 0;
t->pinnacle_id = UNSET;
- i2c_set_clientdata(&t->client, t);
- i2c_attach_client(&t->client);
+ t->radio_mode = V4L2_TUNER_MODE_STEREO;
+ i2c_set_clientdata(&t->client, t);
+ i2c_attach_client(&t->client);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ MOD_INC_USE_COUNT;
+#endif
return 0;
}
@@ -644,6 +682,9 @@
i2c_detach_client(client);
kfree(t);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ MOD_DEC_USE_COUNT;
+#endif
return 0;
}
@@ -753,6 +794,16 @@
}
break;
}
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner* tuner = arg;
+
+ if (t->radio) {
+ t->radio_mode = tuner->audmode;
+ tda9887_configure (t);
+ }
+ break;
+ }
default:
/* nothing */
break;
@@ -779,7 +830,9 @@
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,54)
.owner = THIS_MODULE,
+#endif
.name = "i2c tda9887 driver",
.id = -1, /* FIXME */
.flags = I2C_DF_NOTIFY,