blob: 3d495dba4983d1662b2c2973ca97a1bb87b0ec54 [file] [log] [blame]
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03001/*
2 * cx18 gpio functions
3 *
4 * Derived from ivtv-gpio.c
5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 * 02111-1307 USA
22 */
23
24#include "cx18-driver.h"
25#include "cx18-cards.h"
26#include "cx18-gpio.h"
27#include "tuner-xc2028.h"
28
29/********************* GPIO stuffs *********************/
30
31/* GPIO registers */
32#define CX18_REG_GPIO_IN 0xc72010
33#define CX18_REG_GPIO_OUT1 0xc78100
34#define CX18_REG_GPIO_DIR1 0xc78108
35#define CX18_REG_GPIO_OUT2 0xc78104
36#define CX18_REG_GPIO_DIR2 0xc7810c
37
38/*
39 * HVR-1600 GPIO pins, courtesy of Hauppauge:
40 *
41 * gpio0: zilog ir process reset pin
42 * gpio1: zilog programming pin (you should never use this)
43 * gpio12: cx24227 reset pin
44 * gpio13: cs5345 reset pin
45*/
46
Hans Verkuil9dcbf352008-05-12 13:57:18 -030047static void gpio_write(struct cx18 *cx)
48{
Hans Verkuilba60bc62008-05-25 14:34:36 -030049 u32 dir = cx->gpio_dir;
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),
Hans Verkuil9dcbf352008-05-12 13:57:18 -030054 CX18_REG_GPIO_OUT1);
Hans Verkuilba60bc62008-05-25 14:34:36 -030055 write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
Andy Walls1f09e8a2008-06-22 01:27:00 -030056 write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
Hans Verkuil9dcbf352008-05-12 13:57:18 -030057 CX18_REG_GPIO_OUT2);
58}
59
Andy Walls1f09e8a2008-06-22 01:27:00 -030060void 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 */
Andy Walls8abdd002008-07-13 19:05:25 -030072 mutex_lock(&cx->gpio_lock);
Andy Walls1f09e8a2008-06-22 01:27:00 -030073 cx->gpio_val =
74 (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
75 gpio_write(cx);
76 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
77
78 /* Deassert */
79 cx->gpio_val =
80 (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
81 gpio_write(cx);
82 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
Andy Walls8abdd002008-07-13 19:05:25 -030083 mutex_unlock(&cx->gpio_lock);
Andy Walls1f09e8a2008-06-22 01:27:00 -030084}
85
Andy Walls02fa2722008-07-13 19:30:15 -030086void cx18_reset_ir_gpio(void *data)
87{
88 struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
89 const struct cx18_gpio_i2c_slave_reset *p;
90
91 p = &cx->card->gpio_i2c_slave_reset;
92
93 if (p->ir_reset_mask == 0)
94 return;
95
96 CX18_DEBUG_INFO("Resetting IR microcontroller\n");
97
98 /*
99 Assert timing for the Z8F0811 on HVR-1600 boards:
100 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to initiate
101 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock cycles
102 (6,601,085 nanoseconds ~= 7 milliseconds)
103 3. DBG pin must be high before chip exits reset for normal operation.
104 DBG is open drain and hopefully pulled high since we don't
105 normally drive it (GPIO 1?) for the HVR-1600
106 4. Z8F0811 won't exit reset until RESET is deasserted
107 */
108 mutex_lock(&cx->gpio_lock);
109 cx->gpio_val = cx->gpio_val & ~p->ir_reset_mask;
110 gpio_write(cx);
111 mutex_unlock(&cx->gpio_lock);
112 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
113
114 /*
115 Zilog comes out of reset, loads reset vector address and executes
116 from there. Required recovery delay unknown.
117 */
118 mutex_lock(&cx->gpio_lock);
119 cx->gpio_val = cx->gpio_val | p->ir_reset_mask;
120 gpio_write(cx);
121 mutex_unlock(&cx->gpio_lock);
122 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
123}
124EXPORT_SYMBOL(cx18_reset_ir_gpio);
125/* This symbol is exported for use by an infrared module for the IR-blaster */
126
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300127void cx18_gpio_init(struct cx18 *cx)
128{
Andy Walls8abdd002008-07-13 19:05:25 -0300129 mutex_lock(&cx->gpio_lock);
Hans Verkuilba60bc62008-05-25 14:34:36 -0300130 cx->gpio_dir = cx->card->gpio_init.direction;
131 cx->gpio_val = cx->card->gpio_init.initial_value;
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300132
Hans Verkuil4ecc2472008-05-30 11:03:12 -0300133 if (cx->card->tuners[0].tuner == TUNER_XC2028) {
Hans Verkuilba60bc62008-05-25 14:34:36 -0300134 cx->gpio_dir |= 1 << cx->card->xceive_pin;
135 cx->gpio_val |= 1 << cx->card->xceive_pin;
Hans Verkuil7f3917f2008-05-19 22:13:02 -0300136 }
137
Andy Walls8abdd002008-07-13 19:05:25 -0300138 if (cx->gpio_dir == 0) {
139 mutex_unlock(&cx->gpio_lock);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300140 return;
Andy Walls8abdd002008-07-13 19:05:25 -0300141 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300142
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300143 CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
144 read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
145 read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
146
147 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300148 mutex_unlock(&cx->gpio_lock);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300149}
150
151/* Xceive tuner reset function */
152int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
153{
154 struct i2c_algo_bit_data *algo = dev;
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300155 struct cx18_i2c_algo_callback_data *cb_data = algo->data;
156 struct cx18 *cx = cb_data->cx;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300157
158 if (cmd != XC2028_TUNER_RESET)
159 return 0;
160 CX18_DEBUG_INFO("Resetting tuner\n");
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300161
Andy Walls8abdd002008-07-13 19:05:25 -0300162 mutex_lock(&cx->gpio_lock);
Hans Verkuilba60bc62008-05-25 14:34:36 -0300163 cx->gpio_val &= ~(1 << cx->card->xceive_pin);
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300164 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300165 mutex_unlock(&cx->gpio_lock);
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300166 schedule_timeout_interruptible(msecs_to_jiffies(1));
167
Andy Walls8abdd002008-07-13 19:05:25 -0300168 mutex_lock(&cx->gpio_lock);
Hans Verkuilba60bc62008-05-25 14:34:36 -0300169 cx->gpio_val |= 1 << cx->card->xceive_pin;
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300170 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300171 mutex_unlock(&cx->gpio_lock);
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300172 schedule_timeout_interruptible(msecs_to_jiffies(1));
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300173 return 0;
174}
Sri Deevi03c28082008-06-21 11:06:44 -0300175
176int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg)
177{
178 struct v4l2_routing *route = arg;
179 u32 mask, data;
180
181 switch (command) {
182 case VIDIOC_INT_S_AUDIO_ROUTING:
183 if (route->input > 2)
184 return -EINVAL;
185 mask = cx->card->gpio_audio_input.mask;
186 switch (route->input) {
187 case 0:
188 data = cx->card->gpio_audio_input.tuner;
189 break;
190 case 1:
191 data = cx->card->gpio_audio_input.linein;
192 break;
193 case 2:
194 default:
195 data = cx->card->gpio_audio_input.radio;
196 break;
197 }
198 break;
199
200 default:
201 return -EINVAL;
202 }
203 if (mask) {
Andy Walls8abdd002008-07-13 19:05:25 -0300204 mutex_lock(&cx->gpio_lock);
Sri Deevi03c28082008-06-21 11:06:44 -0300205 cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
206 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300207 mutex_unlock(&cx->gpio_lock);
Sri Deevi03c28082008-06-21 11:06:44 -0300208 }
209 return 0;
210}