Commit 02fa272f authored by Andy Walls's avatar Andy Walls Committed by Mauro Carvalho Chehab

V4L/DVB (8332): cx18: Suport external reset of the Z8F0811 IR controller on HVR-1600 for lirc

cx18: added in cx18_ir_reset_gpio function for lirc_pvr150 like module.  Also
added the ability to reset the IR chip via ioctl like ivtv.  This needs the
mutex to protect gpio_dir and gpio_val in struct cx18 as gpio changes can
come from a few different asynchronous sources now.
Signed-off-by: default avatarAndy Walls <awalls@radix.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 8abdd00d
...@@ -88,6 +88,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { ...@@ -88,6 +88,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
.active_lo_mask = 0x3001, .active_lo_mask = 0x3001,
.msecs_asserted = 10, .msecs_asserted = 10,
.msecs_recovery = 40, .msecs_recovery = 40,
.ir_reset_mask = 0x0001,
}, },
.i2c = &cx18_i2c_std, .i2c = &cx18_i2c_std,
}; };
...@@ -133,6 +134,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { ...@@ -133,6 +134,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
.active_lo_mask = 0x3001, .active_lo_mask = 0x3001,
.msecs_asserted = 10, .msecs_asserted = 10,
.msecs_recovery = 40, .msecs_recovery = 40,
.ir_reset_mask = 0x0001,
}, },
.i2c = &cx18_i2c_std, .i2c = &cx18_i2c_std,
}; };
......
...@@ -83,6 +83,7 @@ struct cx18_gpio_i2c_slave_reset { ...@@ -83,6 +83,7 @@ struct cx18_gpio_i2c_slave_reset {
u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */ u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
int msecs_asserted; /* time period reset must remain asserted */ int msecs_asserted; /* time period reset must remain asserted */
int msecs_recovery; /* time after deassert for chips to be ready */ int msecs_recovery; /* time after deassert for chips to be ready */
u32 ir_reset_mask; /* GPIO to reset the Zilog Z8F0811 IR contoller */
}; };
struct cx18_gpio_audio_input { /* select tuner/line in input */ struct cx18_gpio_audio_input { /* select tuner/line in input */
......
...@@ -83,6 +83,47 @@ void cx18_reset_i2c_slaves_gpio(struct cx18 *cx) ...@@ -83,6 +83,47 @@ void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
mutex_unlock(&cx->gpio_lock); mutex_unlock(&cx->gpio_lock);
} }
void cx18_reset_ir_gpio(void *data)
{
struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
const struct cx18_gpio_i2c_slave_reset *p;
p = &cx->card->gpio_i2c_slave_reset;
if (p->ir_reset_mask == 0)
return;
CX18_DEBUG_INFO("Resetting IR microcontroller\n");
/*
Assert timing for the Z8F0811 on HVR-1600 boards:
1. Assert RESET for min of 4 clock cycles at 18.432 MHz to initiate
2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock cycles
(6,601,085 nanoseconds ~= 7 milliseconds)
3. DBG pin must be high before chip exits reset for normal operation.
DBG is open drain and hopefully pulled high since we don't
normally drive it (GPIO 1?) for the HVR-1600
4. Z8F0811 won't exit reset until RESET is deasserted
*/
mutex_lock(&cx->gpio_lock);
cx->gpio_val = cx->gpio_val & ~p->ir_reset_mask;
gpio_write(cx);
mutex_unlock(&cx->gpio_lock);
schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
/*
Zilog comes out of reset, loads reset vector address and executes
from there. Required recovery delay unknown.
*/
mutex_lock(&cx->gpio_lock);
cx->gpio_val = cx->gpio_val | p->ir_reset_mask;
gpio_write(cx);
mutex_unlock(&cx->gpio_lock);
schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
}
EXPORT_SYMBOL(cx18_reset_ir_gpio);
/* This symbol is exported for use by an infrared module for the IR-blaster */
void cx18_gpio_init(struct cx18 *cx) void cx18_gpio_init(struct cx18 *cx)
{ {
mutex_lock(&cx->gpio_lock); mutex_lock(&cx->gpio_lock);
......
...@@ -22,5 +22,6 @@ ...@@ -22,5 +22,6 @@
void cx18_gpio_init(struct cx18 *cx); void cx18_gpio_init(struct cx18 *cx);
void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
void cx18_reset_ir_gpio(void *data);
int cx18_reset_tuner_gpio(void *dev, int cmd, int value); int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
...@@ -754,6 +754,15 @@ static int cx18_default(struct file *file, void *fh, int cmd, void *arg) ...@@ -754,6 +754,15 @@ static int cx18_default(struct file *file, void *fh, int cmd, void *arg)
cx18_audio_set_route(cx, route); cx18_audio_set_route(cx, route);
break; break;
} }
case VIDIOC_INT_RESET: {
u32 val = *(u32 *)arg;
if ((val == 0) || (val & 0x01))
cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]);
break;
}
default: default:
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment