diff options
author | Andy Walls <awalls@radix.net> | 2009-11-20 23:47:45 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:41:55 -0500 |
commit | f412d36a8c9f8e40e057b71e80d534ac388e903e (patch) | |
tree | 36f5a0005efce82787a3dc99af8417dee79f0055 /drivers/media | |
parent | e45e8f5cee75b0559ce1ca7007b4963b91910fa8 (diff) |
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>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 19 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 4 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-i2c.c | 7 |
3 files changed, 28 insertions, 2 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 7cdbc1a8f218..8330fb5c7eb3 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -91,10 +91,15 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |||
91 | -1, -1, -1, -1, -1, -1, -1, -1, | 91 | -1, -1, -1, -1, -1, -1, -1, -1, |
92 | -1, -1, -1, -1, -1, -1, -1, -1, | 92 | -1, -1, -1, -1, -1, -1, -1, -1, |
93 | -1, -1, -1, -1, -1, -1, -1, -1 }; | 93 | -1, -1, -1, -1, -1, -1, -1, -1 }; |
94 | static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | ||
95 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
96 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
97 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
94 | 98 | ||
95 | static unsigned int cardtype_c = 1; | 99 | static unsigned int cardtype_c = 1; |
96 | static unsigned int tuner_c = 1; | 100 | static unsigned int tuner_c = 1; |
97 | static unsigned int radio_c = 1; | 101 | static unsigned int radio_c = 1; |
102 | static unsigned int i2c_clock_period_c = 1; | ||
98 | static char pal[] = "---"; | 103 | static char pal[] = "---"; |
99 | static char secam[] = "--"; | 104 | static char secam[] = "--"; |
100 | static char ntsc[] = "-"; | 105 | static char ntsc[] = "-"; |
@@ -151,6 +156,7 @@ module_param(dec_vbi_buffers, int, 0644); | |||
151 | 156 | ||
152 | module_param(tunertype, int, 0644); | 157 | module_param(tunertype, int, 0644); |
153 | module_param(newi2c, int, 0644); | 158 | module_param(newi2c, int, 0644); |
159 | module_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644); | ||
154 | 160 | ||
155 | MODULE_PARM_DESC(tuner, "Tuner type selection,\n" | 161 | MODULE_PARM_DESC(tuner, "Tuner type selection,\n" |
156 | "\t\t\tsee tuner.h for values"); | 162 | "\t\t\tsee tuner.h for values"); |
@@ -245,6 +251,10 @@ MODULE_PARM_DESC(newi2c, | |||
245 | "Use new I2C implementation\n" | 251 | "Use new I2C implementation\n" |
246 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" | 252 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" |
247 | "\t\t\tDefault is autodetect"); | 253 | "\t\t\tDefault is autodetect"); |
254 | MODULE_PARM_DESC(i2c_clock_period, | ||
255 | "Period of SCL for the I2C bus controlled by the CX23415/6\n" | ||
256 | "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n" | ||
257 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD)); | ||
248 | 258 | ||
249 | MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); | 259 | MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); |
250 | 260 | ||
@@ -600,6 +610,15 @@ static void ivtv_process_options(struct ivtv *itv) | |||
600 | itv->options.cardtype = cardtype[itv->instance]; | 610 | itv->options.cardtype = cardtype[itv->instance]; |
601 | itv->options.tuner = tuner[itv->instance]; | 611 | itv->options.tuner = tuner[itv->instance]; |
602 | itv->options.radio = radio[itv->instance]; | 612 | itv->options.radio = radio[itv->instance]; |
613 | |||
614 | itv->options.i2c_clock_period = i2c_clock_period[itv->instance]; | ||
615 | if (itv->options.i2c_clock_period == -1) | ||
616 | itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD; | ||
617 | else if (itv->options.i2c_clock_period < 10) | ||
618 | itv->options.i2c_clock_period = 10; | ||
619 | else if (itv->options.i2c_clock_period > 4500) | ||
620 | itv->options.i2c_clock_period = 4500; | ||
621 | |||
603 | itv->options.newi2c = newi2c; | 622 | itv->options.newi2c = newi2c; |
604 | if (tunertype < -1 || tunertype > 1) { | 623 | if (tunertype < -1 || tunertype > 1) { |
605 | IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); | 624 | IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 440f7328a7ed..2b3db90afb74 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -176,12 +176,16 @@ extern int ivtv_debug; | |||
176 | 176 | ||
177 | #define IVTV_MAX_PGM_INDEX (400) | 177 | #define IVTV_MAX_PGM_INDEX (400) |
178 | 178 | ||
179 | /* Default I2C SCL period in microseconds */ | ||
180 | #define IVTV_DEFAULT_I2C_CLOCK_PERIOD 20 | ||
181 | |||
179 | struct ivtv_options { | 182 | struct ivtv_options { |
180 | int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */ | 183 | int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */ |
181 | int cardtype; /* force card type on load */ | 184 | int cardtype; /* force card type on load */ |
182 | int tuner; /* set tuner on load */ | 185 | int tuner; /* set tuner on load */ |
183 | int radio; /* enable/disable radio */ | 186 | int radio; /* enable/disable radio */ |
184 | int newi2c; /* new I2C algorithm */ | 187 | int newi2c; /* new I2C algorithm */ |
188 | int i2c_clock_period; /* period of SCL for I2C bus */ | ||
185 | }; | 189 | }; |
186 | 190 | ||
187 | /* ivtv-specific mailbox template */ | 191 | /* ivtv-specific mailbox template */ |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index b9c71e61f7d6..d4cc3365038e 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -564,13 +564,15 @@ static struct i2c_adapter ivtv_i2c_adap_template = { | |||
564 | .owner = THIS_MODULE, | 564 | .owner = THIS_MODULE, |
565 | }; | 565 | }; |
566 | 566 | ||
567 | #define IVTV_ALGO_BIT_TIMEOUT (2) /* seconds */ | ||
568 | |||
567 | static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { | 569 | static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { |
568 | .setsda = ivtv_setsda_old, | 570 | .setsda = ivtv_setsda_old, |
569 | .setscl = ivtv_setscl_old, | 571 | .setscl = ivtv_setscl_old, |
570 | .getsda = ivtv_getsda_old, | 572 | .getsda = ivtv_getsda_old, |
571 | .getscl = ivtv_getscl_old, | 573 | .getscl = ivtv_getscl_old, |
572 | .udelay = 10, | 574 | .udelay = IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2, /* microseconds */ |
573 | .timeout = 200, | 575 | .timeout = IVTV_ALGO_BIT_TIMEOUT * HZ, /* jiffies */ |
574 | }; | 576 | }; |
575 | 577 | ||
576 | static struct i2c_client ivtv_i2c_client_template = { | 578 | static struct i2c_client ivtv_i2c_client_template = { |
@@ -602,6 +604,7 @@ int init_ivtv_i2c(struct ivtv *itv) | |||
602 | memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, | 604 | memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, |
603 | sizeof(struct i2c_algo_bit_data)); | 605 | sizeof(struct i2c_algo_bit_data)); |
604 | } | 606 | } |
607 | itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2; | ||
605 | itv->i2c_algo.data = itv; | 608 | itv->i2c_algo.data = itv; |
606 | itv->i2c_adap.algo_data = &itv->i2c_algo; | 609 | itv->i2c_adap.algo_data = &itv->i2c_algo; |
607 | 610 | ||