aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-gpio.c')
-rw-r--r--drivers/media/video/cx18/cx18-gpio.c57
1 files changed, 41 insertions, 16 deletions
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index bb8bc86086d0..b302833f6f9d 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -35,9 +35,6 @@
35#define CX18_REG_GPIO_OUT2 0xc78104 35#define CX18_REG_GPIO_OUT2 0xc78104
36#define CX18_REG_GPIO_DIR2 0xc7810c 36#define CX18_REG_GPIO_DIR2 0xc7810c
37 37
38static u32 gpio_dir;
39static u32 gpio_val;
40
41/* 38/*
42 * HVR-1600 GPIO pins, courtesy of Hauppauge: 39 * HVR-1600 GPIO pins, courtesy of Hauppauge:
43 * 40 *
@@ -49,24 +46,53 @@ static u32 gpio_val;
49 46
50static void gpio_write(struct cx18 *cx) 47static void gpio_write(struct cx18 *cx)
51{ 48{
52 write_reg((gpio_dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); 49 u32 dir = cx->gpio_dir;
53 write_reg(((gpio_dir & 0xffff) << 16) | (gpio_val & 0xffff), 50 u32 val = cx->gpio_val;
51
52 write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
53 write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
54 CX18_REG_GPIO_OUT1); 54 CX18_REG_GPIO_OUT1);
55 write_reg(gpio_dir & 0xffff0000, CX18_REG_GPIO_DIR2); 55 write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
56 write_reg((gpio_dir & 0xffff0000) | ((gpio_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_gpio_init(struct cx18 *cx) 60void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
61{ 61{
62 gpio_dir = cx->card->gpio_init.direction; 62 const struct cx18_gpio_i2c_slave_reset *p;
63 gpio_val = cx->card->gpio_init.initial_value; 63
64 p = &cx->card->gpio_i2c_slave_reset;
64 65
65 if (gpio_dir == 0) 66 if ((p->active_lo_mask | p->active_hi_mask) == 0)
66 return; 67 return;
67 68
68 gpio_dir |= 1 << cx->card->xceive_pin; 69 /* Assuming that the masks are a subset of the bits in gpio_dir */
69 gpio_val |= 1 << cx->card->xceive_pin; 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
84void cx18_gpio_init(struct cx18 *cx)
85{
86 cx->gpio_dir = cx->card->gpio_init.direction;
87 cx->gpio_val = cx->card->gpio_init.initial_value;
88
89 if (cx->card->tuners[0].tuner == TUNER_XC2028) {
90 cx->gpio_dir |= 1 << cx->card->xceive_pin;
91 cx->gpio_val |= 1 << cx->card->xceive_pin;
92 }
93
94 if (cx->gpio_dir == 0)
95 return;
70 96
71 CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", 97 CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
72 read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), 98 read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
@@ -86,13 +112,12 @@ int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
86 return 0; 112 return 0;
87 CX18_DEBUG_INFO("Resetting tuner\n"); 113 CX18_DEBUG_INFO("Resetting tuner\n");
88 114
89 gpio_dir |= 1 << cx->card->xceive_pin; 115 cx->gpio_val &= ~(1 << cx->card->xceive_pin);
90 gpio_val &= ~(1 << cx->card->xceive_pin);
91 116
92 gpio_write(cx); 117 gpio_write(cx);
93 schedule_timeout_interruptible(msecs_to_jiffies(1)); 118 schedule_timeout_interruptible(msecs_to_jiffies(1));
94 119
95 gpio_val |= 1 << cx->card->xceive_pin; 120 cx->gpio_val |= 1 << cx->card->xceive_pin;
96 gpio_write(cx); 121 gpio_write(cx);
97 schedule_timeout_interruptible(msecs_to_jiffies(1)); 122 schedule_timeout_interruptible(msecs_to_jiffies(1));
98 return 0; 123 return 0;