aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-11-20 23:47:45 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:41:55 -0500
commitf412d36a8c9f8e40e057b71e80d534ac388e903e (patch)
tree36f5a0005efce82787a3dc99af8417dee79f0055 /drivers/media/video/ivtv
parente45e8f5cee75b0559ce1ca7007b4963b91910fa8 (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/video/ivtv')
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c19
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h4
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c7
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 };
94static 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
95static unsigned int cardtype_c = 1; 99static unsigned int cardtype_c = 1;
96static unsigned int tuner_c = 1; 100static unsigned int tuner_c = 1;
97static unsigned int radio_c = 1; 101static unsigned int radio_c = 1;
102static unsigned int i2c_clock_period_c = 1;
98static char pal[] = "---"; 103static char pal[] = "---";
99static char secam[] = "--"; 104static char secam[] = "--";
100static char ntsc[] = "-"; 105static char ntsc[] = "-";
@@ -151,6 +156,7 @@ module_param(dec_vbi_buffers, int, 0644);
151 156
152module_param(tunertype, int, 0644); 157module_param(tunertype, int, 0644);
153module_param(newi2c, int, 0644); 158module_param(newi2c, int, 0644);
159module_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644);
154 160
155MODULE_PARM_DESC(tuner, "Tuner type selection,\n" 161MODULE_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");
254MODULE_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
249MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); 259MODULE_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
179struct ivtv_options { 182struct 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
567static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { 569static 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
576static struct i2c_client ivtv_i2c_client_template = { 578static 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