V4L/DVB (13442): ivtv: Add module parameter to adjust I2C SCL clock period per board
Add a module parameter to adjust I2C SCL clock period per board. This allows some experimental fine tuning by end users to overcome quirky I2C device problems. Reported-by: "Aleksandr V. Piskunov" <aleksandr.v.piskunov@gmail.com> Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
e45e8f5cee
commit
f412d36a8c
3 changed files with 28 additions and 2 deletions
|
@ -91,10 +91,15 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1 };
|
-1, -1, -1, -1, -1, -1, -1, -1 };
|
||||||
|
static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1 };
|
||||||
|
|
||||||
static unsigned int cardtype_c = 1;
|
static unsigned int cardtype_c = 1;
|
||||||
static unsigned int tuner_c = 1;
|
static unsigned int tuner_c = 1;
|
||||||
static unsigned int radio_c = 1;
|
static unsigned int radio_c = 1;
|
||||||
|
static unsigned int i2c_clock_period_c = 1;
|
||||||
static char pal[] = "---";
|
static char pal[] = "---";
|
||||||
static char secam[] = "--";
|
static char secam[] = "--";
|
||||||
static char ntsc[] = "-";
|
static char ntsc[] = "-";
|
||||||
|
@ -151,6 +156,7 @@ module_param(dec_vbi_buffers, int, 0644);
|
||||||
|
|
||||||
module_param(tunertype, int, 0644);
|
module_param(tunertype, int, 0644);
|
||||||
module_param(newi2c, int, 0644);
|
module_param(newi2c, int, 0644);
|
||||||
|
module_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644);
|
||||||
|
|
||||||
MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
|
MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
|
||||||
"\t\t\tsee tuner.h for values");
|
"\t\t\tsee tuner.h for values");
|
||||||
|
@ -245,6 +251,10 @@ MODULE_PARM_DESC(newi2c,
|
||||||
"Use new I2C implementation\n"
|
"Use new I2C implementation\n"
|
||||||
"\t\t\t-1 is autodetect, 0 is off, 1 is on\n"
|
"\t\t\t-1 is autodetect, 0 is off, 1 is on\n"
|
||||||
"\t\t\tDefault is autodetect");
|
"\t\t\tDefault is autodetect");
|
||||||
|
MODULE_PARM_DESC(i2c_clock_period,
|
||||||
|
"Period of SCL for the I2C bus controlled by the CX23415/6\n"
|
||||||
|
"\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n"
|
||||||
|
"\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD));
|
||||||
|
|
||||||
MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card");
|
MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card");
|
||||||
|
|
||||||
|
@ -600,6 +610,15 @@ static void ivtv_process_options(struct ivtv *itv)
|
||||||
itv->options.cardtype = cardtype[itv->instance];
|
itv->options.cardtype = cardtype[itv->instance];
|
||||||
itv->options.tuner = tuner[itv->instance];
|
itv->options.tuner = tuner[itv->instance];
|
||||||
itv->options.radio = radio[itv->instance];
|
itv->options.radio = radio[itv->instance];
|
||||||
|
|
||||||
|
itv->options.i2c_clock_period = i2c_clock_period[itv->instance];
|
||||||
|
if (itv->options.i2c_clock_period == -1)
|
||||||
|
itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD;
|
||||||
|
else if (itv->options.i2c_clock_period < 10)
|
||||||
|
itv->options.i2c_clock_period = 10;
|
||||||
|
else if (itv->options.i2c_clock_period > 4500)
|
||||||
|
itv->options.i2c_clock_period = 4500;
|
||||||
|
|
||||||
itv->options.newi2c = newi2c;
|
itv->options.newi2c = newi2c;
|
||||||
if (tunertype < -1 || tunertype > 1) {
|
if (tunertype < -1 || tunertype > 1) {
|
||||||
IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
|
IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
|
||||||
|
|
|
@ -176,12 +176,16 @@ extern int ivtv_debug;
|
||||||
|
|
||||||
#define IVTV_MAX_PGM_INDEX (400)
|
#define IVTV_MAX_PGM_INDEX (400)
|
||||||
|
|
||||||
|
/* Default I2C SCL period in microseconds */
|
||||||
|
#define IVTV_DEFAULT_I2C_CLOCK_PERIOD 20
|
||||||
|
|
||||||
struct ivtv_options {
|
struct ivtv_options {
|
||||||
int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */
|
int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */
|
||||||
int cardtype; /* force card type on load */
|
int cardtype; /* force card type on load */
|
||||||
int tuner; /* set tuner on load */
|
int tuner; /* set tuner on load */
|
||||||
int radio; /* enable/disable radio */
|
int radio; /* enable/disable radio */
|
||||||
int newi2c; /* new I2C algorithm */
|
int newi2c; /* new I2C algorithm */
|
||||||
|
int i2c_clock_period; /* period of SCL for I2C bus */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ivtv-specific mailbox template */
|
/* ivtv-specific mailbox template */
|
||||||
|
|
|
@ -564,13 +564,15 @@ static struct i2c_adapter ivtv_i2c_adap_template = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define IVTV_ALGO_BIT_TIMEOUT (2) /* seconds */
|
||||||
|
|
||||||
static const struct i2c_algo_bit_data ivtv_i2c_algo_template = {
|
static const struct i2c_algo_bit_data ivtv_i2c_algo_template = {
|
||||||
.setsda = ivtv_setsda_old,
|
.setsda = ivtv_setsda_old,
|
||||||
.setscl = ivtv_setscl_old,
|
.setscl = ivtv_setscl_old,
|
||||||
.getsda = ivtv_getsda_old,
|
.getsda = ivtv_getsda_old,
|
||||||
.getscl = ivtv_getscl_old,
|
.getscl = ivtv_getscl_old,
|
||||||
.udelay = 10,
|
.udelay = IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2, /* microseconds */
|
||||||
.timeout = 200,
|
.timeout = IVTV_ALGO_BIT_TIMEOUT * HZ, /* jiffies */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct i2c_client ivtv_i2c_client_template = {
|
static struct i2c_client ivtv_i2c_client_template = {
|
||||||
|
@ -602,6 +604,7 @@ int init_ivtv_i2c(struct ivtv *itv)
|
||||||
memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template,
|
memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template,
|
||||||
sizeof(struct i2c_algo_bit_data));
|
sizeof(struct i2c_algo_bit_data));
|
||||||
}
|
}
|
||||||
|
itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2;
|
||||||
itv->i2c_algo.data = itv;
|
itv->i2c_algo.data = itv;
|
||||||
itv->i2c_adap.algo_data = &itv->i2c_algo;
|
itv->i2c_adap.algo_data = &itv->i2c_algo;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue