From: Andy Walls Date: Sun, 13 Jul 2008 22:30:15 +0000 (-0300) Subject: V4L/DVB (8332): cx18: Suport external reset of the Z8F0811 IR controller on HVR-1600... X-Git-Tag: v2.6.27-rc1~966^2~52 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=02fa272fcb6edda9059d6dbaab20dfe919f4f4d2;p=linux-2.6 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: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 0caae1a5ed..8fe5f38c4d 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -88,6 +88,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { .active_lo_mask = 0x3001, .msecs_asserted = 10, .msecs_recovery = 40, + .ir_reset_mask = 0x0001, }, .i2c = &cx18_i2c_std, }; @@ -133,6 +134,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { .active_lo_mask = 0x3001, .msecs_asserted = 10, .msecs_recovery = 40, + .ir_reset_mask = 0x0001, }, .i2c = &cx18_i2c_std, }; diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index dc283d7569..32155f6e6f 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -83,6 +83,7 @@ struct cx18_gpio_i2c_slave_reset { u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */ int msecs_asserted; /* time period reset must remain asserted */ 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 */ diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index d753a40973..3d495dba49 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -83,6 +83,47 @@ void cx18_reset_i2c_slaves_gpio(struct cx18 *cx) 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) { mutex_lock(&cx->gpio_lock); diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index 7447fed357..22cd7ddf85 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h @@ -22,5 +22,6 @@ void cx18_gpio_init(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_gpio(struct cx18 *cx, unsigned int command, void *arg); diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 146a4b8564..0d74e59e50 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -754,6 +754,15 @@ static int cx18_default(struct file *file, void *fh, int cmd, void *arg) cx18_audio_set_route(cx, route); 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: return -EINVAL; }