aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2008-06-22 00:27:00 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-06-26 14:58:54 -0400
commit1f09e8a25c9aaa4066b4593c1bf99a4cbcc38120 (patch)
tree4b204cb090b2b1be58d0aebc53291afd62e12321
parent08cf7b2ed172cc83f3d2f44b712b3d54e6cc4ae6 (diff)
V4L/DVB (8068): cx18: Add I2C slave reset via GPIO upon initialization
cx18: Add I2C slave reset via GPIO upon initialization. One user, Michael <msd4824@yahoo.com>, has reported this allows his HVR-1600 EEPROM to be consistently recognized when using (long,) 100 msec delays. The delays in this commit are nominal (10 & 40 msec) and need testing/tuning on boards with I2C problems to find the right values. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/cx18/cx18-cards.c10
-rw-r--r--drivers/media/video/cx18/cx18-cards.h10
-rw-r--r--drivers/media/video/cx18/cx18-gpio.c26
-rw-r--r--drivers/media/video/cx18/cx18-gpio.h1
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c2
5 files changed, 47 insertions, 2 deletions
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index c18865b0d6cc..bbf23fa459d6 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -82,6 +82,11 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
82 }, 82 },
83 .gpio_init.initial_value = 0x3001, 83 .gpio_init.initial_value = 0x3001,
84 .gpio_init.direction = 0x3001, 84 .gpio_init.direction = 0x3001,
85 .gpio_i2c_slave_reset = {
86 .active_lo_mask = 0x3001,
87 .msecs_asserted = 10,
88 .msecs_recovery = 40,
89 },
85 .i2c = &cx18_i2c_std, 90 .i2c = &cx18_i2c_std,
86}; 91};
87 92
@@ -122,6 +127,11 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
122 }, 127 },
123 .gpio_init.initial_value = 0x3001, 128 .gpio_init.initial_value = 0x3001,
124 .gpio_init.direction = 0x3001, 129 .gpio_init.direction = 0x3001,
130 .gpio_i2c_slave_reset = {
131 .active_lo_mask = 0x3001,
132 .msecs_asserted = 10,
133 .msecs_recovery = 40,
134 },
125 .i2c = &cx18_i2c_std, 135 .i2c = &cx18_i2c_std,
126}; 136};
127 137
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index 3c2c0b92956c..dc2dd945d4c3 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -78,6 +78,13 @@ struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
78 u32 initial_value; 78 u32 initial_value;
79}; 79};
80 80
81struct cx18_gpio_i2c_slave_reset {
82 u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */
83 u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
84 int msecs_asserted; /* time period reset must remain asserted */
85 int msecs_recovery; /* time after deassert for chips to be ready */
86};
87
81struct cx18_card_tuner { 88struct cx18_card_tuner {
82 v4l2_std_id std; /* standard for which the tuner is suitable */ 89 v4l2_std_id std; /* standard for which the tuner is suitable */
83 int tuner; /* tuner ID (from tuner.h) */ 90 int tuner; /* tuner ID (from tuner.h) */
@@ -114,7 +121,8 @@ struct cx18_card {
114 121
115 /* GPIO card-specific settings */ 122 /* GPIO card-specific settings */
116 u8 xceive_pin; /* XCeive tuner GPIO reset pin */ 123 u8 xceive_pin; /* XCeive tuner GPIO reset pin */
117 struct cx18_gpio_init gpio_init; 124 struct cx18_gpio_init gpio_init;
125 struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
118 126
119 struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; 127 struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
120 struct cx18_card_tuner_i2c *i2c; 128 struct cx18_card_tuner_i2c *i2c;
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index ceb63653c926..b302833f6f9d 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -53,10 +53,34 @@ static void gpio_write(struct cx18 *cx)
53 write_reg(((dir & 0xffff) << 16) | (val & 0xffff), 53 write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
54 CX18_REG_GPIO_OUT1); 54 CX18_REG_GPIO_OUT1);
55 write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); 55 write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
56 write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), 56 write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
57 CX18_REG_GPIO_OUT2); 57 CX18_REG_GPIO_OUT2);
58} 58}
59 59
60void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
61{
62 const struct cx18_gpio_i2c_slave_reset *p;
63
64 p = &cx->card->gpio_i2c_slave_reset;
65
66 if ((p->active_lo_mask | p->active_hi_mask) == 0)
67 return;
68
69 /* Assuming that the masks are a subset of the bits in gpio_dir */
70
71 /* Assert */
72 cx->gpio_val =
73 (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
74 gpio_write(cx);
75 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
76
77 /* Deassert */
78 cx->gpio_val =
79 (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
80 gpio_write(cx);
81 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
82}
83
60void cx18_gpio_init(struct cx18 *cx) 84void cx18_gpio_init(struct cx18 *cx)
61{ 85{
62 cx->gpio_dir = cx->card->gpio_init.direction; 86 cx->gpio_dir = cx->card->gpio_init.direction;
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
index 41bac8856b50..525c328f748a 100644
--- a/drivers/media/video/cx18/cx18-gpio.h
+++ b/drivers/media/video/cx18/cx18-gpio.h
@@ -21,4 +21,5 @@
21 */ 21 */
22 22
23void cx18_gpio_init(struct cx18 *cx); 23void cx18_gpio_init(struct cx18 *cx);
24void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
24int cx18_reset_tuner_gpio(void *dev, int cmd, int value); 25int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 1d6c51a75313..680bc4e35b79 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -405,6 +405,8 @@ int init_cx18_i2c(struct cx18 *cx)
405 cx18_setscl(&cx->i2c_algo_cb_data[1], 1); 405 cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
406 cx18_setsda(&cx->i2c_algo_cb_data[1], 1); 406 cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
407 407
408 cx18_reset_i2c_slaves_gpio(cx);
409
408 return i2c_bit_add_bus(&cx->i2c_adap[0]) || 410 return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
409 i2c_bit_add_bus(&cx->i2c_adap[1]); 411 i2c_bit_add_bus(&cx->i2c_adap[1]);
410} 412}