Path: blob/master/drivers/media/video/cx88/cx88-input.c
17633 views
/*1*2* Device driver for GPIO attached remote control interfaces3* on Conexant 2388x based TV/DVB cards.4*5* Copyright (c) 2003 Pavel Machek6* Copyright (c) 2004 Gerd Knorr7* Copyright (c) 2004, 2005 Chris Pascoe8*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License as published by11* the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*14* This program is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the17* GNU General Public License for more details.18*19* You should have received a copy of the GNU General Public License20* along with this program; if not, write to the Free Software21* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA22*/2324#include <linux/init.h>25#include <linux/hrtimer.h>26#include <linux/pci.h>27#include <linux/slab.h>28#include <linux/module.h>2930#include "cx88.h"31#include <media/rc-core.h>3233#define MODULE_NAME "cx88xx"3435/* ---------------------------------------------------------------------- */3637struct cx88_IR {38struct cx88_core *core;39struct rc_dev *dev;4041int users;4243char name[32];44char phys[32];4546/* sample from gpio pin 16 */47u32 sampling;4849/* poll external decoder */50int polling;51struct hrtimer timer;52u32 gpio_addr;53u32 last_gpio;54u32 mask_keycode;55u32 mask_keydown;56u32 mask_keyup;57};5859static unsigned ir_samplerate = 4;60module_param(ir_samplerate, uint, 0444);61MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");6263static int ir_debug;64module_param(ir_debug, int, 0644); /* debug level [IR] */65MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");6667#define ir_dprintk(fmt, arg...) if (ir_debug) \68printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)6970#define dprintk(fmt, arg...) if (ir_debug) \71printk(KERN_DEBUG "cx88 IR: " fmt , ##arg)7273/* ---------------------------------------------------------------------- */7475static void cx88_ir_handle_key(struct cx88_IR *ir)76{77struct cx88_core *core = ir->core;78u32 gpio, data, auxgpio;7980/* read gpio value */81gpio = cx_read(ir->gpio_addr);82switch (core->boardnr) {83case CX88_BOARD_NPGTECH_REALTV_TOP10FM:84/* This board apparently uses a combination of 2 GPIO85to represent the keys. Additionally, the second GPIO86can be used for parity.8788Example:8990for key "5"91gpio = 0x758, auxgpio = 0xe5 or 0xf592for key "Power"93gpio = 0x758, auxgpio = 0xed or 0xfd94*/9596auxgpio = cx_read(MO_GP1_IO);97/* Take out the parity part */98gpio=(gpio & 0x7fd) + (auxgpio & 0xef);99break;100case CX88_BOARD_WINFAST_DTV1000:101case CX88_BOARD_WINFAST_DTV1800H:102case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:103gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);104auxgpio = gpio;105break;106default:107auxgpio = gpio;108}109if (ir->polling) {110if (ir->last_gpio == auxgpio)111return;112ir->last_gpio = auxgpio;113}114115/* extract data */116data = ir_extract_bits(gpio, ir->mask_keycode);117ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",118gpio, data,119ir->polling ? "poll" : "irq",120(gpio & ir->mask_keydown) ? " down" : "",121(gpio & ir->mask_keyup) ? " up" : "");122123if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {124u32 gpio_key = cx_read(MO_GP0_IO);125126data = (data << 4) | ((gpio_key & 0xf0) >> 4);127128rc_keydown(ir->dev, data, 0);129130} else if (ir->mask_keydown) {131/* bit set on keydown */132if (gpio & ir->mask_keydown)133rc_keydown_notimeout(ir->dev, data, 0);134else135rc_keyup(ir->dev);136137} else if (ir->mask_keyup) {138/* bit cleared on keydown */139if (0 == (gpio & ir->mask_keyup))140rc_keydown_notimeout(ir->dev, data, 0);141else142rc_keyup(ir->dev);143144} else {145/* can't distinguish keydown/up :-/ */146rc_keydown_notimeout(ir->dev, data, 0);147rc_keyup(ir->dev);148}149}150151static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)152{153unsigned long missed;154struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);155156cx88_ir_handle_key(ir);157missed = hrtimer_forward_now(&ir->timer,158ktime_set(0, ir->polling * 1000000));159if (missed > 1)160ir_dprintk("Missed ticks %ld\n", missed - 1);161162return HRTIMER_RESTART;163}164165static int __cx88_ir_start(void *priv)166{167struct cx88_core *core = priv;168struct cx88_IR *ir;169170if (!core || !core->ir)171return -EINVAL;172173ir = core->ir;174175if (ir->polling) {176hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);177ir->timer.function = cx88_ir_work;178hrtimer_start(&ir->timer,179ktime_set(0, ir->polling * 1000000),180HRTIMER_MODE_REL);181}182if (ir->sampling) {183core->pci_irqmask |= PCI_INT_IR_SMPINT;184cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */185cx_write(MO_DDSCFG_IO, 0x5); /* enable */186}187return 0;188}189190static void __cx88_ir_stop(void *priv)191{192struct cx88_core *core = priv;193struct cx88_IR *ir;194195if (!core || !core->ir)196return;197198ir = core->ir;199if (ir->sampling) {200cx_write(MO_DDSCFG_IO, 0x0);201core->pci_irqmask &= ~PCI_INT_IR_SMPINT;202}203204if (ir->polling)205hrtimer_cancel(&ir->timer);206}207208int cx88_ir_start(struct cx88_core *core)209{210if (core->ir->users)211return __cx88_ir_start(core);212213return 0;214}215216void cx88_ir_stop(struct cx88_core *core)217{218if (core->ir->users)219__cx88_ir_stop(core);220}221222static int cx88_ir_open(struct rc_dev *rc)223{224struct cx88_core *core = rc->priv;225226core->ir->users++;227return __cx88_ir_start(core);228}229230static void cx88_ir_close(struct rc_dev *rc)231{232struct cx88_core *core = rc->priv;233234core->ir->users--;235if (!core->ir->users)236__cx88_ir_stop(core);237}238239/* ---------------------------------------------------------------------- */240241int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)242{243struct cx88_IR *ir;244struct rc_dev *dev;245char *ir_codes = NULL;246u64 rc_type = RC_TYPE_OTHER;247int err = -ENOMEM;248u32 hardware_mask = 0; /* For devices with a hardware mask, when249* used with a full-code IR table250*/251252ir = kzalloc(sizeof(*ir), GFP_KERNEL);253dev = rc_allocate_device();254if (!ir || !dev)255goto err_out_free;256257ir->dev = dev;258259/* detect & configure */260switch (core->boardnr) {261case CX88_BOARD_DNTV_LIVE_DVB_T:262case CX88_BOARD_KWORLD_DVB_T:263case CX88_BOARD_KWORLD_DVB_T_CX22702:264ir_codes = RC_MAP_DNTV_LIVE_DVB_T;265ir->gpio_addr = MO_GP1_IO;266ir->mask_keycode = 0x1f;267ir->mask_keyup = 0x60;268ir->polling = 50; /* ms */269break;270case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:271ir_codes = RC_MAP_CINERGY_1400;272ir->sampling = 0xeb04; /* address */273break;274case CX88_BOARD_HAUPPAUGE:275case CX88_BOARD_HAUPPAUGE_DVB_T1:276case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:277case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:278case CX88_BOARD_HAUPPAUGE_HVR1100:279case CX88_BOARD_HAUPPAUGE_HVR3000:280case CX88_BOARD_HAUPPAUGE_HVR4000:281case CX88_BOARD_HAUPPAUGE_HVR4000LITE:282case CX88_BOARD_PCHDTV_HD3000:283case CX88_BOARD_PCHDTV_HD5500:284case CX88_BOARD_HAUPPAUGE_IRONLY:285ir_codes = RC_MAP_HAUPPAUGE;286ir->sampling = 1;287break;288case CX88_BOARD_WINFAST_DTV2000H:289case CX88_BOARD_WINFAST_DTV2000H_J:290case CX88_BOARD_WINFAST_DTV1800H:291ir_codes = RC_MAP_WINFAST;292ir->gpio_addr = MO_GP0_IO;293ir->mask_keycode = 0x8f8;294ir->mask_keyup = 0x100;295ir->polling = 50; /* ms */296break;297case CX88_BOARD_WINFAST2000XP_EXPERT:298case CX88_BOARD_WINFAST_DTV1000:299case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:300ir_codes = RC_MAP_WINFAST;301ir->gpio_addr = MO_GP0_IO;302ir->mask_keycode = 0x8f8;303ir->mask_keyup = 0x100;304ir->polling = 1; /* ms */305break;306case CX88_BOARD_IODATA_GVBCTV7E:307ir_codes = RC_MAP_IODATA_BCTV7E;308ir->gpio_addr = MO_GP0_IO;309ir->mask_keycode = 0xfd;310ir->mask_keydown = 0x02;311ir->polling = 5; /* ms */312break;313case CX88_BOARD_PROLINK_PLAYTVPVR:314case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:315/*316* It seems that this hardware is paired with NEC extended317* address 0x866b. So, unfortunately, its usage with other318* IR's with different address won't work. Still, there are319* other IR's from the same manufacturer that works, like the320* 002-T mini RC, provided with newer PV hardware321*/322ir_codes = RC_MAP_PIXELVIEW_MK12;323ir->gpio_addr = MO_GP1_IO;324ir->mask_keyup = 0x80;325ir->polling = 10; /* ms */326hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */327break;328case CX88_BOARD_PROLINK_PV_8000GT:329case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:330ir_codes = RC_MAP_PIXELVIEW_NEW;331ir->gpio_addr = MO_GP1_IO;332ir->mask_keycode = 0x3f;333ir->mask_keyup = 0x80;334ir->polling = 1; /* ms */335break;336case CX88_BOARD_KWORLD_LTV883:337ir_codes = RC_MAP_PIXELVIEW;338ir->gpio_addr = MO_GP1_IO;339ir->mask_keycode = 0x1f;340ir->mask_keyup = 0x60;341ir->polling = 1; /* ms */342break;343case CX88_BOARD_ADSTECH_DVB_T_PCI:344ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;345ir->gpio_addr = MO_GP1_IO;346ir->mask_keycode = 0xbf;347ir->mask_keyup = 0x40;348ir->polling = 50; /* ms */349break;350case CX88_BOARD_MSI_TVANYWHERE_MASTER:351ir_codes = RC_MAP_MSI_TVANYWHERE;352ir->gpio_addr = MO_GP1_IO;353ir->mask_keycode = 0x1f;354ir->mask_keyup = 0x40;355ir->polling = 1; /* ms */356break;357case CX88_BOARD_AVERTV_303:358case CX88_BOARD_AVERTV_STUDIO_303:359ir_codes = RC_MAP_AVERTV_303;360ir->gpio_addr = MO_GP2_IO;361ir->mask_keycode = 0xfb;362ir->mask_keydown = 0x02;363ir->polling = 50; /* ms */364break;365case CX88_BOARD_OMICOM_SS4_PCI:366case CX88_BOARD_SATTRADE_ST4200:367case CX88_BOARD_TBS_8920:368case CX88_BOARD_TBS_8910:369case CX88_BOARD_PROF_7300:370case CX88_BOARD_PROF_7301:371case CX88_BOARD_PROF_6200:372ir_codes = RC_MAP_TBS_NEC;373ir->sampling = 0xff00; /* address */374break;375case CX88_BOARD_TEVII_S464:376case CX88_BOARD_TEVII_S460:377case CX88_BOARD_TEVII_S420:378ir_codes = RC_MAP_TEVII_NEC;379ir->sampling = 0xff00; /* address */380break;381case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:382ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO;383ir->sampling = 0xff00; /* address */384break;385case CX88_BOARD_NORWOOD_MICRO:386ir_codes = RC_MAP_NORWOOD;387ir->gpio_addr = MO_GP1_IO;388ir->mask_keycode = 0x0e;389ir->mask_keyup = 0x80;390ir->polling = 50; /* ms */391break;392case CX88_BOARD_NPGTECH_REALTV_TOP10FM:393ir_codes = RC_MAP_NPGTECH;394ir->gpio_addr = MO_GP0_IO;395ir->mask_keycode = 0xfa;396ir->polling = 50; /* ms */397break;398case CX88_BOARD_PINNACLE_PCTV_HD_800i:399ir_codes = RC_MAP_PINNACLE_PCTV_HD;400ir->sampling = 1;401break;402case CX88_BOARD_POWERCOLOR_REAL_ANGEL:403ir_codes = RC_MAP_POWERCOLOR_REAL_ANGEL;404ir->gpio_addr = MO_GP2_IO;405ir->mask_keycode = 0x7e;406ir->polling = 100; /* ms */407break;408case CX88_BOARD_TWINHAN_VP1027_DVBS:409ir_codes = RC_MAP_TWINHAN_VP1027_DVBS;410rc_type = RC_TYPE_NEC;411ir->sampling = 0xff00; /* address */412break;413}414415if (!ir_codes) {416err = -ENODEV;417goto err_out_free;418}419420/*421* The usage of mask_keycode were very convenient, due to several422* reasons. Among others, the scancode tables were using the scancode423* as the index elements. So, the less bits it was used, the smaller424* the table were stored. After the input changes, the better is to use425* the full scancodes, since it allows replacing the IR remote by426* another one. Unfortunately, there are still some hardware, like427* Pixelview Ultra Pro, where only part of the scancode is sent via428* GPIO. So, there's no way to get the full scancode. Due to that,429* hardware_mask were introduced here: it represents those hardware430* that has such limits.431*/432if (hardware_mask && !ir->mask_keycode)433ir->mask_keycode = hardware_mask;434435/* init input device */436snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);437snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));438439dev->input_name = ir->name;440dev->input_phys = ir->phys;441dev->input_id.bustype = BUS_PCI;442dev->input_id.version = 1;443if (pci->subsystem_vendor) {444dev->input_id.vendor = pci->subsystem_vendor;445dev->input_id.product = pci->subsystem_device;446} else {447dev->input_id.vendor = pci->vendor;448dev->input_id.product = pci->device;449}450dev->dev.parent = &pci->dev;451dev->map_name = ir_codes;452dev->driver_name = MODULE_NAME;453dev->priv = core;454dev->open = cx88_ir_open;455dev->close = cx88_ir_close;456dev->scanmask = hardware_mask;457458if (ir->sampling) {459dev->driver_type = RC_DRIVER_IR_RAW;460dev->timeout = 10 * 1000 * 1000; /* 10 ms */461} else {462dev->driver_type = RC_DRIVER_SCANCODE;463dev->allowed_protos = rc_type;464}465466ir->core = core;467core->ir = ir;468469/* all done */470err = rc_register_device(dev);471if (err)472goto err_out_free;473474return 0;475476err_out_free:477rc_free_device(dev);478core->ir = NULL;479kfree(ir);480return err;481}482483int cx88_ir_fini(struct cx88_core *core)484{485struct cx88_IR *ir = core->ir;486487/* skip detach on non attached boards */488if (NULL == ir)489return 0;490491cx88_ir_stop(core);492rc_unregister_device(ir->dev);493kfree(ir);494495/* done */496core->ir = NULL;497return 0;498}499500/* ---------------------------------------------------------------------- */501502void cx88_ir_irq(struct cx88_core *core)503{504struct cx88_IR *ir = core->ir;505u32 samples;506unsigned todo, bits;507struct ir_raw_event ev;508509if (!ir || !ir->sampling)510return;511512/*513* Samples are stored in a 32 bit register, oldest sample in514* the msb. A set bit represents space and an unset bit515* represents a pulse.516*/517samples = cx_read(MO_SAMPLE_IO);518519if (samples == 0xff && ir->dev->idle)520return;521522init_ir_raw_event(&ev);523for (todo = 32; todo > 0; todo -= bits) {524ev.pulse = samples & 0x80000000 ? false : true;525bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));526ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;527ir_raw_event_store_with_filter(ir->dev, &ev);528samples <<= bits;529}530ir_raw_event_handle(ir->dev);531}532533static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)534{535int flags, code;536537/* poll IR chip */538flags = i2c_smbus_read_byte_data(ir->c, 0x10);539if (flags < 0) {540dprintk("read error\n");541return 0;542}543/* key pressed ? */544if (0 == (flags & 0x80))545return 0;546547/* read actual key code */548code = i2c_smbus_read_byte_data(ir->c, 0x00);549if (code < 0) {550dprintk("read error\n");551return 0;552}553554dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",555code & 0xff, flags & 0xff);556557*ir_key = code & 0xff;558*ir_raw = code;559return 1;560}561562void cx88_i2c_init_ir(struct cx88_core *core)563{564struct i2c_board_info info;565const unsigned short default_addr_list[] = {5660x18, 0x6b, 0x71,567I2C_CLIENT_END568};569const unsigned short pvr2000_addr_list[] = {5700x18, 0x1a,571I2C_CLIENT_END572};573const unsigned short *addr_list = default_addr_list;574const unsigned short *addrp;575/* Instantiate the IR receiver device, if present */576if (0 != core->i2c_rc)577return;578579memset(&info, 0, sizeof(struct i2c_board_info));580strlcpy(info.type, "ir_video", I2C_NAME_SIZE);581582switch (core->boardnr) {583case CX88_BOARD_LEADTEK_PVR2000:584addr_list = pvr2000_addr_list;585core->init_data.name = "cx88 Leadtek PVR 2000 remote";586core->init_data.type = RC_TYPE_UNKNOWN;587core->init_data.get_key = get_key_pvr2000;588core->init_data.ir_codes = RC_MAP_EMPTY;589break;590}591592/*593* We can't call i2c_new_probed_device() because it uses594* quick writes for probing and at least some RC receiver595* devices only reply to reads.596* Also, Hauppauge XVR needs to be specified, as address 0x71597* conflicts with another remote type used with saa7134598*/599for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {600info.platform_data = NULL;601memset(&core->init_data, 0, sizeof(core->init_data));602603if (*addrp == 0x71) {604/* Hauppauge XVR */605core->init_data.name = "cx88 Hauppauge XVR remote";606core->init_data.ir_codes = RC_MAP_HAUPPAUGE;607core->init_data.type = RC_TYPE_RC5;608core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;609610info.platform_data = &core->init_data;611}612if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,613I2C_SMBUS_READ, 0,614I2C_SMBUS_QUICK, NULL) >= 0) {615info.addr = *addrp;616i2c_new_device(&core->i2c_adap, &info);617break;618}619}620}621622/* ---------------------------------------------------------------------- */623624MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");625MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");626MODULE_LICENSE("GPL");627628629