Exemplo n.º 1
0
int cx25840_ir_remove(struct v4l2_subdev *sd)
{
	struct cx25840_state *state = to_state(sd);
	struct cx25840_ir_state *ir_state = to_ir_state(sd);

	if (ir_state == NULL)
		return -ENODEV;

	cx25840_ir_rx_shutdown(sd);
	cx25840_ir_tx_shutdown(sd);

	kfifo_free(&ir_state->rx_kfifo);
	state->ir_state = NULL;
	return 0;
}
Exemplo n.º 2
0
static int cx25840_ir_rx_s_parameters(struct v4l2_subdev *sd,
				      struct v4l2_subdev_ir_parameters *p)
{
	struct cx25840_ir_state *ir_state = to_ir_state(sd);
	struct i2c_client *c;
	struct v4l2_subdev_ir_parameters *o;
	u16 rxclk_divider;

	if (ir_state == NULL)
		return -ENODEV;

	if (p->shutdown)
		return cx25840_ir_rx_shutdown(sd);

	if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
		return -ENOSYS;

	c = ir_state->c;
	o = &ir_state->rx_params;

	mutex_lock(&ir_state->rx_params_lock);

	o->shutdown = p->shutdown;

	p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
	o->mode = p->mode;

	p->bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec);
	o->bytes_per_data_element = p->bytes_per_data_element;

	/* Before we tweak the hardware, we have to disable the receiver */
	irqenable_rx(sd, 0);
	control_rx_enable(c, false);

	control_rx_demodulation_enable(c, p->modulation);
	o->modulation = p->modulation;

	if (p->modulation) {
		p->carrier_freq = rxclk_rx_s_carrier(c, p->carrier_freq,
						     &rxclk_divider);

		o->carrier_freq = p->carrier_freq;

		p->duty_cycle = 50;
		o->duty_cycle = p->duty_cycle;

		control_rx_s_carrier_window(c, p->carrier_freq,
					    &p->carrier_range_lower,
					    &p->carrier_range_upper);
		o->carrier_range_lower = p->carrier_range_lower;
		o->carrier_range_upper = p->carrier_range_upper;

		p->max_pulse_width =
			(u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
	} else {
		p->max_pulse_width =
			    rxclk_rx_s_max_pulse_width(c, p->max_pulse_width,
						       &rxclk_divider);
	}
	o->max_pulse_width = p->max_pulse_width;
	atomic_set(&ir_state->rxclk_divider, rxclk_divider);

	p->noise_filter_min_width =
			    filter_rx_s_min_width(c, p->noise_filter_min_width);
	o->noise_filter_min_width = p->noise_filter_min_width;

	p->resolution = clock_divider_to_resolution(rxclk_divider);
	o->resolution = p->resolution;

	/* FIXME - make this dependent on resolution for better performance */
	control_rx_irq_watermark(c, RX_FIFO_HALF_FULL);

	control_rx_s_edge_detection(c, CNTRL_EDG_BOTH);

	o->invert_level = p->invert_level;
	atomic_set(&ir_state->rx_invert, p->invert_level);

	o->interrupt_enable = p->interrupt_enable;
	o->enable = p->enable;
	if (p->enable) {
		unsigned long flags;

		spin_lock_irqsave(&ir_state->rx_kfifo_lock, flags);
		kfifo_reset(&ir_state->rx_kfifo);
		spin_unlock_irqrestore(&ir_state->rx_kfifo_lock, flags);
		if (p->interrupt_enable)
			irqenable_rx(sd, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
		control_rx_enable(c, p->enable);
	}

	mutex_unlock(&ir_state->rx_params_lock);
	return 0;
}