blob: 17b7a32fcc311f14b9b8153764463922af4c015d [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"
Andy Wallsb1526422008-08-30 16:03:44 -030025#include "cx18-io.h"
Hans Verkuil1c1e45d2008-04-28 20:24:33 -030026#include "cx18-cards.h"
27#include "cx18-gpio.h"
28#include "tuner-xc2028.h"
29
30/********************* GPIO stuffs *********************/
31
32/* GPIO registers */
33#define CX18_REG_GPIO_IN 0xc72010
34#define CX18_REG_GPIO_OUT1 0xc78100
35#define CX18_REG_GPIO_DIR1 0xc78108
36#define CX18_REG_GPIO_OUT2 0xc78104
37#define CX18_REG_GPIO_DIR2 0xc7810c
38
39/*
40 * HVR-1600 GPIO pins, courtesy of Hauppauge:
41 *
42 * gpio0: zilog ir process reset pin
43 * gpio1: zilog programming pin (you should never use this)
44 * gpio12: cx24227 reset pin
45 * gpio13: cs5345 reset pin
46*/
47
Hans Verkuil9dcbf352008-05-12 13:57:18 -030048static void gpio_write(struct cx18 *cx)
49{
Andy Wallsced07372008-11-02 10:59:04 -030050 u32 dir_lo = cx->gpio_dir & 0xffff;
51 u32 val_lo = cx->gpio_val & 0xffff;
52 u32 dir_hi = cx->gpio_dir >> 16;
53 u32 val_hi = cx->gpio_val >> 16;
Hans Verkuilba60bc62008-05-25 14:34:36 -030054
Andy Wallsced07372008-11-02 10:59:04 -030055 cx18_write_reg_expect(cx, dir_lo << 16,
56 CX18_REG_GPIO_DIR1, ~dir_lo, dir_lo);
57 cx18_write_reg_expect(cx, (dir_lo << 16) | val_lo,
58 CX18_REG_GPIO_OUT1, val_lo, dir_lo);
59 cx18_write_reg_expect(cx, dir_hi << 16,
60 CX18_REG_GPIO_DIR2, ~dir_hi, dir_hi);
61 cx18_write_reg_expect(cx, (dir_hi << 16) | val_hi,
62 CX18_REG_GPIO_OUT2, val_hi, dir_hi);
63 if (!cx18_retry_mmio)
64 (void) cx18_read_reg(cx, CX18_REG_GPIO_OUT2); /* sync */
Hans Verkuil9dcbf352008-05-12 13:57:18 -030065}
66
Andy Walls1f09e8a2008-06-22 01:27:00 -030067void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
68{
69 const struct cx18_gpio_i2c_slave_reset *p;
70
71 p = &cx->card->gpio_i2c_slave_reset;
72
73 if ((p->active_lo_mask | p->active_hi_mask) == 0)
74 return;
75
76 /* Assuming that the masks are a subset of the bits in gpio_dir */
77
78 /* Assert */
Andy Walls8abdd002008-07-13 19:05:25 -030079 mutex_lock(&cx->gpio_lock);
Andy Walls1f09e8a2008-06-22 01:27:00 -030080 cx->gpio_val =
81 (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
82 gpio_write(cx);
83 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
84
85 /* Deassert */
86 cx->gpio_val =
87 (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
88 gpio_write(cx);
89 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
Andy Walls8abdd002008-07-13 19:05:25 -030090 mutex_unlock(&cx->gpio_lock);
Andy Walls1f09e8a2008-06-22 01:27:00 -030091}
92
Andy Walls02fa2722008-07-13 19:30:15 -030093void cx18_reset_ir_gpio(void *data)
94{
95 struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
96 const struct cx18_gpio_i2c_slave_reset *p;
97
98 p = &cx->card->gpio_i2c_slave_reset;
99
100 if (p->ir_reset_mask == 0)
101 return;
102
103 CX18_DEBUG_INFO("Resetting IR microcontroller\n");
104
105 /*
106 Assert timing for the Z8F0811 on HVR-1600 boards:
107 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to initiate
108 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock cycles
109 (6,601,085 nanoseconds ~= 7 milliseconds)
110 3. DBG pin must be high before chip exits reset for normal operation.
111 DBG is open drain and hopefully pulled high since we don't
112 normally drive it (GPIO 1?) for the HVR-1600
113 4. Z8F0811 won't exit reset until RESET is deasserted
114 */
115 mutex_lock(&cx->gpio_lock);
116 cx->gpio_val = cx->gpio_val & ~p->ir_reset_mask;
117 gpio_write(cx);
118 mutex_unlock(&cx->gpio_lock);
119 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
120
121 /*
122 Zilog comes out of reset, loads reset vector address and executes
123 from there. Required recovery delay unknown.
124 */
125 mutex_lock(&cx->gpio_lock);
126 cx->gpio_val = cx->gpio_val | p->ir_reset_mask;
127 gpio_write(cx);
128 mutex_unlock(&cx->gpio_lock);
129 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
130}
131EXPORT_SYMBOL(cx18_reset_ir_gpio);
132/* This symbol is exported for use by an infrared module for the IR-blaster */
133
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300134void cx18_gpio_init(struct cx18 *cx)
135{
Andy Walls8abdd002008-07-13 19:05:25 -0300136 mutex_lock(&cx->gpio_lock);
Hans Verkuilba60bc62008-05-25 14:34:36 -0300137 cx->gpio_dir = cx->card->gpio_init.direction;
138 cx->gpio_val = cx->card->gpio_init.initial_value;
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300139
Hans Verkuil4ecc2472008-05-30 11:03:12 -0300140 if (cx->card->tuners[0].tuner == TUNER_XC2028) {
Hans Verkuilba60bc62008-05-25 14:34:36 -0300141 cx->gpio_dir |= 1 << cx->card->xceive_pin;
142 cx->gpio_val |= 1 << cx->card->xceive_pin;
Hans Verkuil7f3917f2008-05-19 22:13:02 -0300143 }
144
Andy Walls8abdd002008-07-13 19:05:25 -0300145 if (cx->gpio_dir == 0) {
146 mutex_unlock(&cx->gpio_lock);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300147 return;
Andy Walls8abdd002008-07-13 19:05:25 -0300148 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300149
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300150 CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
Andy Wallsb1526422008-08-30 16:03:44 -0300151 cx18_read_reg(cx, CX18_REG_GPIO_DIR1),
152 cx18_read_reg(cx, CX18_REG_GPIO_DIR2),
153 cx18_read_reg(cx, CX18_REG_GPIO_OUT1),
154 cx18_read_reg(cx, CX18_REG_GPIO_OUT2));
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300155
156 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300157 mutex_unlock(&cx->gpio_lock);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300158}
159
160/* Xceive tuner reset function */
Michael Krufkyd7cba042008-09-12 13:31:45 -0300161int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300162{
163 struct i2c_algo_bit_data *algo = dev;
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300164 struct cx18_i2c_algo_callback_data *cb_data = algo->data;
165 struct cx18 *cx = cb_data->cx;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300166
167 if (cmd != XC2028_TUNER_RESET)
168 return 0;
169 CX18_DEBUG_INFO("Resetting tuner\n");
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300170
Andy Walls8abdd002008-07-13 19:05:25 -0300171 mutex_lock(&cx->gpio_lock);
Hans Verkuilba60bc62008-05-25 14:34:36 -0300172 cx->gpio_val &= ~(1 << cx->card->xceive_pin);
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300173 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300174 mutex_unlock(&cx->gpio_lock);
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300175 schedule_timeout_interruptible(msecs_to_jiffies(1));
176
Andy Walls8abdd002008-07-13 19:05:25 -0300177 mutex_lock(&cx->gpio_lock);
Hans Verkuilba60bc62008-05-25 14:34:36 -0300178 cx->gpio_val |= 1 << cx->card->xceive_pin;
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300179 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300180 mutex_unlock(&cx->gpio_lock);
Hans Verkuil9dcbf352008-05-12 13:57:18 -0300181 schedule_timeout_interruptible(msecs_to_jiffies(1));
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300182 return 0;
183}
Sri Deevi03c28082008-06-21 11:06:44 -0300184
185int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg)
186{
187 struct v4l2_routing *route = arg;
188 u32 mask, data;
189
190 switch (command) {
191 case VIDIOC_INT_S_AUDIO_ROUTING:
192 if (route->input > 2)
193 return -EINVAL;
194 mask = cx->card->gpio_audio_input.mask;
195 switch (route->input) {
196 case 0:
197 data = cx->card->gpio_audio_input.tuner;
198 break;
199 case 1:
200 data = cx->card->gpio_audio_input.linein;
201 break;
202 case 2:
203 default:
204 data = cx->card->gpio_audio_input.radio;
205 break;
206 }
207 break;
208
209 default:
210 return -EINVAL;
211 }
212 if (mask) {
Andy Walls8abdd002008-07-13 19:05:25 -0300213 mutex_lock(&cx->gpio_lock);
Sri Deevi03c28082008-06-21 11:06:44 -0300214 cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
215 gpio_write(cx);
Andy Walls8abdd002008-07-13 19:05:25 -0300216 mutex_unlock(&cx->gpio_lock);
Sri Deevi03c28082008-06-21 11:06:44 -0300217 }
218 return 0;
219}