Esempio n. 1
0
/* process ir data stored in driver buffer */
static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
{
	DEFINE_IR_RAW_EVENT(rawir);
	u8 sample;
	bool event = false;
	int i;

	for (i = 0; i < fintek->pkts; i++) {
		sample = fintek->buf[i];
		switch (fintek->parser_state) {
		case CMD_HEADER:
			fintek->cmd = sample;
			if ((fintek->cmd == BUF_COMMAND_HEADER) ||
			    ((fintek->cmd & BUF_COMMAND_MASK) !=
			     BUF_PULSE_BIT)) {
				fintek->parser_state = SUBCMD;
				continue;
			}
			fintek->rem = (fintek->cmd & BUF_LEN_MASK);
			fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem);
			if (fintek->rem)
				fintek->parser_state = PARSE_IRDATA;
			else
				ir_raw_event_reset(fintek->rdev);
			break;
		case SUBCMD:
			fintek->rem = fintek_cmdsize(fintek->cmd, sample);
			fintek->parser_state = CMD_DATA;
			break;
		case CMD_DATA:
			fintek->rem--;
			break;
		case PARSE_IRDATA:
			fintek->rem--;
			init_ir_raw_event(&rawir);
			rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
			rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK)
					  * CIR_SAMPLE_PERIOD);

			fit_dbg("Storing %s with duration %d",
				rawir.pulse ? "pulse" : "space",
				rawir.duration);
			if (ir_raw_event_store_with_filter(fintek->rdev,
									&rawir))
				event = true;
			break;
		}

		if ((fintek->parser_state != CMD_HEADER) && !fintek->rem)
			fintek->parser_state = CMD_HEADER;
	}

	fintek->pkts = 0;

	if (event) {
		fit_dbg("Calling ir_raw_event_handle");
		ir_raw_event_handle(fintek->rdev);
	}
}
Esempio n. 2
0
/* detect hardware features */
static int fintek_hw_detect(struct fintek_dev *fintek)
{
	unsigned long flags;
	u8 chip_major, chip_minor;
	u8 vendor_major, vendor_minor;
	u8 portsel, ir_class;
	u16 vendor;
	int ret = 0;

	fintek_config_mode_enable(fintek);

	/* Check if we're using config port 0x4e or 0x2e */
	portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
	if (portsel == 0xff) {
		fit_pr(KERN_INFO, "first portsel read was bunk, trying alt");
		fintek_config_mode_disable(fintek);
		fintek->cr_ip = CR_INDEX_PORT2;
		fintek->cr_dp = CR_DATA_PORT2;
		fintek_config_mode_enable(fintek);
		portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
	}
	fit_dbg("portsel reg: 0x%02x", portsel);

	ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS);
	fit_dbg("ir_class reg: 0x%02x", ir_class);

	switch (ir_class) {
	case CLASS_RX_2TX:
	case CLASS_RX_1TX:
		fintek->hw_tx_capable = true;
		break;
	case CLASS_RX_ONLY:
	default:
		fintek->hw_tx_capable = false;
		break;
	}

	chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI);
	chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO);

	vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI);
	vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO);
	vendor = vendor_major << 8 | vendor_minor;

	if (vendor != VENDOR_ID_FINTEK)
		fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor);
	else
		fit_dbg("Read Fintek vendor ID from chip");

	fintek_config_mode_disable(fintek);

	spin_lock_irqsave(&fintek->fintek_lock, flags);
	fintek->chip_major  = chip_major;
	fintek->chip_minor  = chip_minor;
	fintek->chip_vendor = vendor;
	spin_unlock_irqrestore(&fintek->fintek_lock, flags);

	return ret;
}
Esempio n. 3
0
static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)
{
	struct fintek_dev *fintek = pnp_get_drvdata(pdev);
	unsigned long flags;

	fit_dbg("%s called", __func__);

	spin_lock_irqsave(&fintek->fintek_lock, flags);

	/* disable all CIR interrupts */
	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);

	spin_unlock_irqrestore(&fintek->fintek_lock, flags);

	fintek_config_mode_enable(fintek);

	/* disable cir logical dev */
	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
	fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);

	fintek_config_mode_disable(fintek);

	/* make sure wake is enabled */
	fintek_enable_wake(fintek);

	return 0;
}
Esempio n. 4
0
/* write val to config reg */
static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg)
{
	fit_dbg("%s: reg 0x%02x, val 0x%02x  (ip/dp: %02x/%02x)",
		__func__, reg, val, fintek->cr_ip, fintek->cr_dp);
	outb(reg, fintek->cr_ip);
	outb(val, fintek->cr_dp);
}
Esempio n. 5
0
/* copy data from hardware rx register into driver buffer */
static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs)
{
	unsigned long flags;
	u8 sample, status;

	spin_lock_irqsave(&fintek->fintek_lock, flags);

	/*
	 * We must read data from CIR_RX_DATA until the hardware IR buffer
	 * is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in
	 * the CIR_STATUS register
	 */
	do {
		sample = fintek_cir_reg_read(fintek, CIR_RX_DATA);
		fit_dbg("%s: sample: 0x%02x", __func__, sample);

		fintek->buf[fintek->pkts] = sample;
		fintek->pkts++;

		status = fintek_cir_reg_read(fintek, CIR_STATUS);
		if (!(status & CIR_STATUS_IRQ_EN))
			break;
	} while (status & rx_irqs);

	fintek_process_rx_ir_data(fintek);

	spin_unlock_irqrestore(&fintek->fintek_lock, flags);
}
Esempio n. 6
0
/* read val from config reg */
static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg)
{
	u8 val;

	outb(reg, fintek->cr_ip);
	val = inb(fintek->cr_dp);

	fit_dbg("%s: reg 0x%02x, val 0x%02x  (ip/dp: %02x/%02x)",
		__func__, reg, val, fintek->cr_ip, fintek->cr_dp);
	return val;
}
Esempio n. 7
0
static void fintek_cir_ldev_init(struct fintek_dev *fintek)
{
	/* Select CIR logical device and enable */
	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
	fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);

	/* Write allocated CIR address and IRQ information to hardware */
	fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI);
	fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO);

	fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL);

	fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)",
		fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len);
}
Esempio n. 8
0
static int fintek_resume(struct pnp_dev *pdev)
{
	struct fintek_dev *fintek = pnp_get_drvdata(pdev);

	fit_dbg("%s called", __func__);

	/* open interrupt */
	fintek_enable_cir_irq(fintek);

	/* Enable CIR logical device */
	fintek_config_mode_enable(fintek);
	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
	fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);

	fintek_config_mode_disable(fintek);

	fintek_cir_regs_init(fintek);

	return 0;
}