/* Assuming that the masks are a subset of the bits in gpio_dir */
/* Assert */
+ mutex_lock(&cx->gpio_lock);
cx->gpio_val =
(cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
gpio_write(cx);
(cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
gpio_write(cx);
schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
+ mutex_unlock(&cx->gpio_lock);
}
void cx18_gpio_init(struct cx18 *cx)
{
+ mutex_lock(&cx->gpio_lock);
cx->gpio_dir = cx->card->gpio_init.direction;
cx->gpio_val = cx->card->gpio_init.initial_value;
cx->gpio_val |= 1 << cx->card->xceive_pin;
}
- if (cx->gpio_dir == 0)
+ if (cx->gpio_dir == 0) {
+ mutex_unlock(&cx->gpio_lock);
return;
+ }
CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
gpio_write(cx);
+ mutex_unlock(&cx->gpio_lock);
}
/* Xceive tuner reset function */
return 0;
CX18_DEBUG_INFO("Resetting tuner\n");
+ mutex_lock(&cx->gpio_lock);
cx->gpio_val &= ~(1 << cx->card->xceive_pin);
-
gpio_write(cx);
+ mutex_unlock(&cx->gpio_lock);
schedule_timeout_interruptible(msecs_to_jiffies(1));
+ mutex_lock(&cx->gpio_lock);
cx->gpio_val |= 1 << cx->card->xceive_pin;
gpio_write(cx);
+ mutex_unlock(&cx->gpio_lock);
schedule_timeout_interruptible(msecs_to_jiffies(1));
return 0;
}
return -EINVAL;
}
if (mask) {
+ mutex_lock(&cx->gpio_lock);
cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
gpio_write(cx);
+ mutex_unlock(&cx->gpio_lock);
}
return 0;
}
cx18_get_audio_input(cx, cx->audio_input, &audin);
CX18_INFO("Video Input: %s\n", vidin.name);
CX18_INFO("Audio Input: %s\n", audin.name);
+ mutex_lock(&cx->gpio_lock);
CX18_INFO("GPIO: direction 0x%08x, value 0x%08x\n",
cx->gpio_dir, cx->gpio_val);
+ mutex_unlock(&cx->gpio_lock);
CX18_INFO("Tuner: %s\n",
test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ? "Radio" : "TV");
cx2341x_log_status(&cx->params, cx->name);