brintos

brintos / linux-shallow public Read only

0
0
Text · 17.4 KiB · 3fb0968 Raw
669 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR4 *5 * Copyright (C) 2011 Jarod Wilson <jarod@redhat.com>6 *7 * Special thanks to Fintek for providing hardware and spec sheets.8 * This driver is based upon the nuvoton, ite and ene drivers for9 * similar hardware.10 */11 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt13 14#include <linux/kernel.h>15#include <linux/module.h>16#include <linux/pnp.h>17#include <linux/io.h>18#include <linux/interrupt.h>19#include <linux/sched.h>20#include <linux/slab.h>21#include <media/rc-core.h>22 23#include "fintek-cir.h"24 25/* write val to config reg */26static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg)27{28	fit_dbg("%s: reg 0x%02x, val 0x%02x  (ip/dp: %02x/%02x)",29		__func__, reg, val, fintek->cr_ip, fintek->cr_dp);30	outb(reg, fintek->cr_ip);31	outb(val, fintek->cr_dp);32}33 34/* read val from config reg */35static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg)36{37	u8 val;38 39	outb(reg, fintek->cr_ip);40	val = inb(fintek->cr_dp);41 42	fit_dbg("%s: reg 0x%02x, val 0x%02x  (ip/dp: %02x/%02x)",43		__func__, reg, val, fintek->cr_ip, fintek->cr_dp);44	return val;45}46 47/* update config register bit without changing other bits */48static inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg)49{50	u8 tmp = fintek_cr_read(fintek, reg) | val;51	fintek_cr_write(fintek, tmp, reg);52}53 54/* enter config mode */55static inline void fintek_config_mode_enable(struct fintek_dev *fintek)56{57	/* Enabling Config Mode explicitly requires writing 2x */58	outb(CONFIG_REG_ENABLE, fintek->cr_ip);59	outb(CONFIG_REG_ENABLE, fintek->cr_ip);60}61 62/* exit config mode */63static inline void fintek_config_mode_disable(struct fintek_dev *fintek)64{65	outb(CONFIG_REG_DISABLE, fintek->cr_ip);66}67 68/*69 * When you want to address a specific logical device, write its logical70 * device number to GCR_LOGICAL_DEV_NO71 */72static inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev)73{74	fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO);75}76 77/* write val to cir config register */78static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset)79{80	outb(val, fintek->cir_addr + offset);81}82 83/* read val from cir config register */84static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)85{86	return inb(fintek->cir_addr + offset);87}88 89/* dump current cir register contents */90static void cir_dump_regs(struct fintek_dev *fintek)91{92	fintek_config_mode_enable(fintek);93	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);94 95	pr_info("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);96	pr_info(" * CR CIR BASE ADDR: 0x%x\n",97		(fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |98		fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO));99	pr_info(" * CR CIR IRQ NUM:   0x%x\n",100		fintek_cr_read(fintek, CIR_CR_IRQ_SEL));101 102	fintek_config_mode_disable(fintek);103 104	pr_info("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);105	pr_info(" * STATUS:     0x%x\n",106		fintek_cir_reg_read(fintek, CIR_STATUS));107	pr_info(" * CONTROL:    0x%x\n",108		fintek_cir_reg_read(fintek, CIR_CONTROL));109	pr_info(" * RX_DATA:    0x%x\n",110		fintek_cir_reg_read(fintek, CIR_RX_DATA));111	pr_info(" * TX_CONTROL: 0x%x\n",112		fintek_cir_reg_read(fintek, CIR_TX_CONTROL));113	pr_info(" * TX_DATA:    0x%x\n",114		fintek_cir_reg_read(fintek, CIR_TX_DATA));115}116 117/* detect hardware features */118static int fintek_hw_detect(struct fintek_dev *fintek)119{120	unsigned long flags;121	u8 chip_major, chip_minor;122	u8 vendor_major, vendor_minor;123	u8 portsel, ir_class;124	u16 vendor, chip;125 126	fintek_config_mode_enable(fintek);127 128	/* Check if we're using config port 0x4e or 0x2e */129	portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);130	if (portsel == 0xff) {131		fit_pr(KERN_INFO, "first portsel read was bunk, trying alt");132		fintek_config_mode_disable(fintek);133		fintek->cr_ip = CR_INDEX_PORT2;134		fintek->cr_dp = CR_DATA_PORT2;135		fintek_config_mode_enable(fintek);136		portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);137	}138	fit_dbg("portsel reg: 0x%02x", portsel);139 140	ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS);141	fit_dbg("ir_class reg: 0x%02x", ir_class);142 143	switch (ir_class) {144	case CLASS_RX_2TX:145	case CLASS_RX_1TX:146		fintek->hw_tx_capable = true;147		break;148	case CLASS_RX_ONLY:149	default:150		fintek->hw_tx_capable = false;151		break;152	}153 154	chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI);155	chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO);156	chip  = chip_major << 8 | chip_minor;157 158	vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI);159	vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO);160	vendor = vendor_major << 8 | vendor_minor;161 162	if (vendor != VENDOR_ID_FINTEK)163		fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor);164	else165		fit_dbg("Read Fintek vendor ID from chip");166 167	fintek_config_mode_disable(fintek);168 169	spin_lock_irqsave(&fintek->fintek_lock, flags);170	fintek->chip_major  = chip_major;171	fintek->chip_minor  = chip_minor;172	fintek->chip_vendor = vendor;173 174	/*175	 * Newer reviews of this chipset uses port 8 instead of 5176	 */177	if ((chip != 0x0408) && (chip != 0x0804))178		fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV2;179	else180		fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV1;181 182	spin_unlock_irqrestore(&fintek->fintek_lock, flags);183 184	return 0;185}186 187static void fintek_cir_ldev_init(struct fintek_dev *fintek)188{189	/* Select CIR logical device and enable */190	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);191	fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);192 193	/* Write allocated CIR address and IRQ information to hardware */194	fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI);195	fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO);196 197	fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL);198 199	fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)",200		fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len);201}202 203/* enable CIR interrupts */204static void fintek_enable_cir_irq(struct fintek_dev *fintek)205{206	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);207}208 209static void fintek_cir_regs_init(struct fintek_dev *fintek)210{211	/* clear any and all stray interrupts */212	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);213 214	/* and finally, enable interrupts */215	fintek_enable_cir_irq(fintek);216}217 218static void fintek_enable_wake(struct fintek_dev *fintek)219{220	fintek_config_mode_enable(fintek);221	fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI);222 223	/* Allow CIR PME's to wake system */224	fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG);225	/* Enable CIR PME's */226	fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG);227	/* Clear CIR PME status register */228	fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG);229	/* Save state */230	fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG);231 232	fintek_config_mode_disable(fintek);233}234 235static int fintek_cmdsize(u8 cmd, u8 subcmd)236{237	int datasize = 0;238 239	switch (cmd) {240	case BUF_COMMAND_NULL:241		if (subcmd == BUF_HW_CMD_HEADER)242			datasize = 1;243		break;244	case BUF_HW_CMD_HEADER:245		if (subcmd == BUF_CMD_G_REVISION)246			datasize = 2;247		break;248	case BUF_COMMAND_HEADER:249		switch (subcmd) {250		case BUF_CMD_S_CARRIER:251		case BUF_CMD_S_TIMEOUT:252		case BUF_RSP_PULSE_COUNT:253			datasize = 2;254			break;255		case BUF_CMD_SIG_END:256		case BUF_CMD_S_TXMASK:257		case BUF_CMD_S_RXSENSOR:258			datasize = 1;259			break;260		}261	}262 263	return datasize;264}265 266/* process ir data stored in driver buffer */267static void fintek_process_rx_ir_data(struct fintek_dev *fintek)268{269	struct ir_raw_event rawir = {};270	u8 sample;271	bool event = false;272	int i;273 274	for (i = 0; i < fintek->pkts; i++) {275		sample = fintek->buf[i];276		switch (fintek->parser_state) {277		case CMD_HEADER:278			fintek->cmd = sample;279			if ((fintek->cmd == BUF_COMMAND_HEADER) ||280			    ((fintek->cmd & BUF_COMMAND_MASK) !=281			     BUF_PULSE_BIT)) {282				fintek->parser_state = SUBCMD;283				continue;284			}285			fintek->rem = (fintek->cmd & BUF_LEN_MASK);286			fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem);287			if (fintek->rem)288				fintek->parser_state = PARSE_IRDATA;289			else290				ir_raw_event_overflow(fintek->rdev);291			break;292		case SUBCMD:293			fintek->rem = fintek_cmdsize(fintek->cmd, sample);294			fintek->parser_state = CMD_DATA;295			break;296		case CMD_DATA:297			fintek->rem--;298			break;299		case PARSE_IRDATA:300			fintek->rem--;301			rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);302			rawir.duration = (sample & BUF_SAMPLE_MASK)303					  * CIR_SAMPLE_PERIOD;304 305			fit_dbg("Storing %s with duration %d",306				rawir.pulse ? "pulse" : "space",307				rawir.duration);308			if (ir_raw_event_store_with_filter(fintek->rdev,309									&rawir))310				event = true;311			break;312		}313 314		if ((fintek->parser_state != CMD_HEADER) && !fintek->rem)315			fintek->parser_state = CMD_HEADER;316	}317 318	fintek->pkts = 0;319 320	if (event) {321		fit_dbg("Calling ir_raw_event_handle");322		ir_raw_event_handle(fintek->rdev);323	}324}325 326/* copy data from hardware rx register into driver buffer */327static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs)328{329	unsigned long flags;330	u8 sample, status;331 332	spin_lock_irqsave(&fintek->fintek_lock, flags);333 334	/*335	 * We must read data from CIR_RX_DATA until the hardware IR buffer336	 * is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in337	 * the CIR_STATUS register338	 */339	do {340		sample = fintek_cir_reg_read(fintek, CIR_RX_DATA);341		fit_dbg("%s: sample: 0x%02x", __func__, sample);342 343		fintek->buf[fintek->pkts] = sample;344		fintek->pkts++;345 346		status = fintek_cir_reg_read(fintek, CIR_STATUS);347		if (!(status & CIR_STATUS_IRQ_EN))348			break;349	} while (status & rx_irqs);350 351	fintek_process_rx_ir_data(fintek);352 353	spin_unlock_irqrestore(&fintek->fintek_lock, flags);354}355 356static void fintek_cir_log_irqs(u8 status)357{358	fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status,359		status & CIR_STATUS_IRQ_EN	? " IRQEN"	: "",360		status & CIR_STATUS_TX_FINISH	? " TXF"	: "",361		status & CIR_STATUS_TX_UNDERRUN	? " TXU"	: "",362		status & CIR_STATUS_RX_TIMEOUT	? " RXTO"	: "",363		status & CIR_STATUS_RX_RECEIVE	? " RXOK"	: "");364}365 366/* interrupt service routine for incoming and outgoing CIR data */367static irqreturn_t fintek_cir_isr(int irq, void *data)368{369	struct fintek_dev *fintek = data;370	u8 status, rx_irqs;371 372	fit_dbg_verbose("%s firing", __func__);373 374	fintek_config_mode_enable(fintek);375	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);376	fintek_config_mode_disable(fintek);377 378	/*379	 * Get IR Status register contents. Write 1 to ack/clear380	 *381	 * bit: reg name    - description382	 *   3: TX_FINISH   - TX is finished383	 *   2: TX_UNDERRUN - TX underrun384	 *   1: RX_TIMEOUT  - RX data timeout385	 *   0: RX_RECEIVE  - RX data received386	 */387	status = fintek_cir_reg_read(fintek, CIR_STATUS);388	if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) {389		fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status);390		fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);391		return IRQ_RETVAL(IRQ_NONE);392	}393 394	if (debug)395		fintek_cir_log_irqs(status);396 397	rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT);398	if (rx_irqs)399		fintek_get_rx_ir_data(fintek, rx_irqs);400 401	/* ack/clear all irq flags we've got */402	fintek_cir_reg_write(fintek, status, CIR_STATUS);403 404	fit_dbg_verbose("%s done", __func__);405	return IRQ_RETVAL(IRQ_HANDLED);406}407 408static void fintek_enable_cir(struct fintek_dev *fintek)409{410	/* set IRQ enabled */411	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);412 413	fintek_config_mode_enable(fintek);414 415	/* enable the CIR logical device */416	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);417	fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);418 419	fintek_config_mode_disable(fintek);420 421	/* clear all pending interrupts */422	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);423 424	/* enable interrupts */425	fintek_enable_cir_irq(fintek);426}427 428static void fintek_disable_cir(struct fintek_dev *fintek)429{430	fintek_config_mode_enable(fintek);431 432	/* disable the CIR logical device */433	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);434	fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);435 436	fintek_config_mode_disable(fintek);437}438 439static int fintek_open(struct rc_dev *dev)440{441	struct fintek_dev *fintek = dev->priv;442	unsigned long flags;443 444	spin_lock_irqsave(&fintek->fintek_lock, flags);445	fintek_enable_cir(fintek);446	spin_unlock_irqrestore(&fintek->fintek_lock, flags);447 448	return 0;449}450 451static void fintek_close(struct rc_dev *dev)452{453	struct fintek_dev *fintek = dev->priv;454	unsigned long flags;455 456	spin_lock_irqsave(&fintek->fintek_lock, flags);457	fintek_disable_cir(fintek);458	spin_unlock_irqrestore(&fintek->fintek_lock, flags);459}460 461/* Allocate memory, probe hardware, and initialize everything */462static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)463{464	struct fintek_dev *fintek;465	struct rc_dev *rdev;466	int ret = -ENOMEM;467 468	fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL);469	if (!fintek)470		return ret;471 472	/* input device for IR remote (and tx) */473	rdev = rc_allocate_device(RC_DRIVER_IR_RAW);474	if (!rdev)475		goto exit_free_dev_rdev;476 477	ret = -ENODEV;478	/* validate pnp resources */479	if (!pnp_port_valid(pdev, 0)) {480		dev_err(&pdev->dev, "IR PNP Port not valid!\n");481		goto exit_free_dev_rdev;482	}483 484	if (!pnp_irq_valid(pdev, 0)) {485		dev_err(&pdev->dev, "IR PNP IRQ not valid!\n");486		goto exit_free_dev_rdev;487	}488 489	fintek->cir_addr = pnp_port_start(pdev, 0);490	fintek->cir_irq  = pnp_irq(pdev, 0);491	fintek->cir_port_len = pnp_port_len(pdev, 0);492 493	fintek->cr_ip = CR_INDEX_PORT;494	fintek->cr_dp = CR_DATA_PORT;495 496	spin_lock_init(&fintek->fintek_lock);497 498	pnp_set_drvdata(pdev, fintek);499	fintek->pdev = pdev;500 501	ret = fintek_hw_detect(fintek);502	if (ret)503		goto exit_free_dev_rdev;504 505	/* Initialize CIR & CIR Wake Logical Devices */506	fintek_config_mode_enable(fintek);507	fintek_cir_ldev_init(fintek);508	fintek_config_mode_disable(fintek);509 510	/* Initialize CIR & CIR Wake Config Registers */511	fintek_cir_regs_init(fintek);512 513	/* Set up the rc device */514	rdev->priv = fintek;515	rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;516	rdev->open = fintek_open;517	rdev->close = fintek_close;518	rdev->device_name = FINTEK_DESCRIPTION;519	rdev->input_phys = "fintek/cir0";520	rdev->input_id.bustype = BUS_HOST;521	rdev->input_id.vendor = VENDOR_ID_FINTEK;522	rdev->input_id.product = fintek->chip_major;523	rdev->input_id.version = fintek->chip_minor;524	rdev->dev.parent = &pdev->dev;525	rdev->driver_name = FINTEK_DRIVER_NAME;526	rdev->map_name = RC_MAP_RC6_MCE;527	rdev->timeout = 1000;528	/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */529	rdev->rx_resolution = CIR_SAMPLE_PERIOD;530 531	fintek->rdev = rdev;532 533	ret = -EBUSY;534	/* now claim resources */535	if (!request_region(fintek->cir_addr,536			    fintek->cir_port_len, FINTEK_DRIVER_NAME))537		goto exit_free_dev_rdev;538 539	if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,540			FINTEK_DRIVER_NAME, (void *)fintek))541		goto exit_free_cir_addr;542 543	ret = rc_register_device(rdev);544	if (ret)545		goto exit_free_irq;546 547	device_init_wakeup(&pdev->dev, true);548 549	fit_pr(KERN_NOTICE, "driver has been successfully loaded\n");550	if (debug)551		cir_dump_regs(fintek);552 553	return 0;554 555exit_free_irq:556	free_irq(fintek->cir_irq, fintek);557exit_free_cir_addr:558	release_region(fintek->cir_addr, fintek->cir_port_len);559exit_free_dev_rdev:560	rc_free_device(rdev);561	kfree(fintek);562 563	return ret;564}565 566static void fintek_remove(struct pnp_dev *pdev)567{568	struct fintek_dev *fintek = pnp_get_drvdata(pdev);569	unsigned long flags;570 571	spin_lock_irqsave(&fintek->fintek_lock, flags);572	/* disable CIR */573	fintek_disable_cir(fintek);574	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);575	/* enable CIR Wake (for IR power-on) */576	fintek_enable_wake(fintek);577	spin_unlock_irqrestore(&fintek->fintek_lock, flags);578 579	/* free resources */580	free_irq(fintek->cir_irq, fintek);581	release_region(fintek->cir_addr, fintek->cir_port_len);582 583	rc_unregister_device(fintek->rdev);584 585	kfree(fintek);586}587 588static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)589{590	struct fintek_dev *fintek = pnp_get_drvdata(pdev);591	unsigned long flags;592 593	fit_dbg("%s called", __func__);594 595	spin_lock_irqsave(&fintek->fintek_lock, flags);596 597	/* disable all CIR interrupts */598	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);599 600	spin_unlock_irqrestore(&fintek->fintek_lock, flags);601 602	fintek_config_mode_enable(fintek);603 604	/* disable cir logical dev */605	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);606	fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);607 608	fintek_config_mode_disable(fintek);609 610	/* make sure wake is enabled */611	fintek_enable_wake(fintek);612 613	return 0;614}615 616static int fintek_resume(struct pnp_dev *pdev)617{618	struct fintek_dev *fintek = pnp_get_drvdata(pdev);619 620	fit_dbg("%s called", __func__);621 622	/* open interrupt */623	fintek_enable_cir_irq(fintek);624 625	/* Enable CIR logical device */626	fintek_config_mode_enable(fintek);627	fintek_select_logical_dev(fintek, fintek->logical_dev_cir);628	fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);629 630	fintek_config_mode_disable(fintek);631 632	fintek_cir_regs_init(fintek);633 634	return 0;635}636 637static void fintek_shutdown(struct pnp_dev *pdev)638{639	struct fintek_dev *fintek = pnp_get_drvdata(pdev);640	fintek_enable_wake(fintek);641}642 643static const struct pnp_device_id fintek_ids[] = {644	{ "FIT0002", 0 },   /* CIR */645	{ "", 0 },646};647 648static struct pnp_driver fintek_driver = {649	.name		= FINTEK_DRIVER_NAME,650	.id_table	= fintek_ids,651	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,652	.probe		= fintek_probe,653	.remove		= fintek_remove,654	.suspend	= fintek_suspend,655	.resume		= fintek_resume,656	.shutdown	= fintek_shutdown,657};658 659module_param(debug, int, S_IRUGO | S_IWUSR);660MODULE_PARM_DESC(debug, "Enable debugging output");661 662MODULE_DEVICE_TABLE(pnp, fintek_ids);663MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver");664 665MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");666MODULE_LICENSE("GPL");667 668module_pnp_driver(fintek_driver);669